diff options
| -rw-r--r-- | include/astra/Float32ProjectionData2D.h | 25 | ||||
| -rw-r--r-- | include/astra/Float32VolumeData2D.h | 25 | ||||
| -rw-r--r-- | python/astra/CFloat32CustomPython.h | 17 | ||||
| -rw-r--r-- | python/astra/PyIncludes.pxd | 8 | ||||
| -rw-r--r-- | python/astra/data2d.py | 21 | ||||
| -rw-r--r-- | python/astra/data2d_c.pyx | 21 | ||||
| -rw-r--r-- | python/astra/data3d.py | 22 | ||||
| -rw-r--r-- | python/astra/data3d_c.pyx | 27 | ||||
| -rw-r--r-- | src/Float32ProjectionData2D.cpp | 19 | ||||
| -rw-r--r-- | src/Float32VolumeData2D.cpp | 20 | 
10 files changed, 196 insertions, 9 deletions
| diff --git a/include/astra/Float32ProjectionData2D.h b/include/astra/Float32ProjectionData2D.h index 7461491..bb99f4b 100644 --- a/include/astra/Float32ProjectionData2D.h +++ b/include/astra/Float32ProjectionData2D.h @@ -101,6 +101,19 @@ public:  	 * Copy constructor  	 */  	CFloat32ProjectionData2D(const CFloat32ProjectionData2D& _other); +	 +	/** Constructor. Create an instance of the CFloat32ProjectionData2D class with pre-allocated memory. +	 * +	 * Creates an instance of the CFloat32ProjectionData2D class. Memory  +	 * is pre-allocated and passed via the abstract CFloat32CustomMemory handle +	 * class. The handle will be deleted when the memory can be freed. +	 * You should override the destructor to provide custom behaviour on free. +	 * +	 * @param _pGeometry Projection Geometry object.  This object will be HARDCOPIED into this class. +	 * @param _pCustomMemory custom memory handle +	 * +	 */ +	CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry, CFloat32CustomMemory* _pCustomMemory);  	/**  	 * Assignment operator @@ -148,6 +161,18 @@ public:  	 * @param _fScalar scalar value to be put at each index.  	 */  	bool initialize(CProjectionGeometry2D* _pGeometry, float32 _fScalar); +	 +	/** Initialization. Initializes an instance of the CFloat32ProjectionData2D class with pre-allocated memory. +	 * +	 * Memory is pre-allocated and passed via the abstract CFloat32CustomMemory handle +	 * class. The handle will be deleted when the memory can be freed. +	 * You should override the destructor to provide custom behaviour on free. +	 * +	 * @param _pGeometry Projection Geometry object.  This object will be HARDCOPIED into this class. +	 * @param _pCustomMemory custom memory handle +	 * +	 */ +	bool initialize(CProjectionGeometry2D* _pGeometry, CFloat32CustomMemory* _pCustomMemory);  	/** Get the number of detectors.  	 * diff --git a/include/astra/Float32VolumeData2D.h b/include/astra/Float32VolumeData2D.h index 4f44a8c..abecebf 100644 --- a/include/astra/Float32VolumeData2D.h +++ b/include/astra/Float32VolumeData2D.h @@ -92,6 +92,19 @@ public:  	 * Copy constructor  	 */  	CFloat32VolumeData2D(const CFloat32VolumeData2D& _other); +	 +	/** Constructor. Create an instance of the CFloat32VolumeData2D class with pre-allocated memory. +	 * +	 * Creates an instance of the CFloat32VolumeData2D class. Memory  +	 * is pre-allocated and passed via the abstract CFloat32CustomMemory handle +	 * class. The handle will be deleted when the memory can be freed. +	 * You should override the destructor to provide custom behaviour on free. +	 * +	 * @param _pGeometry Volume Geometry object.  This object will be HARDCOPIED into this class. +	 * @param _pCustomMemory custom memory handle +	 * +	 */ +	CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry, CFloat32CustomMemory* _pCustomMemory);  	/**  	 * Assignment operator @@ -132,6 +145,18 @@ public:  	 * @param _fScalar scalar value to be put at each index.  	 */  	bool initialize(CVolumeGeometry2D* _pGeometry, float32 _fScalar); +	 +	/** Initialization. Initializes an instance of the CFloat32VolumeData2D class with pre-allocated memory. +	 * +	 * Memory is pre-allocated and passed via the abstract CFloat32CustomMemory handle +	 * class. The handle will be deleted when the memory can be freed. +	 * You should override the destructor to provide custom behaviour on free. +	 * +	 * @param _pGeometry Volume Geometry object.  This object will be HARDCOPIED into this class. +	 * @param _pCustomMemory custom memory handle +	 * +	 */ +	bool initialize(CVolumeGeometry2D* _pGeometry, CFloat32CustomMemory* _pCustomMemory);  	/** Destructor.  	 */ diff --git a/python/astra/CFloat32CustomPython.h b/python/astra/CFloat32CustomPython.h new file mode 100644 index 0000000..d8593fc --- /dev/null +++ b/python/astra/CFloat32CustomPython.h @@ -0,0 +1,17 @@ +class CFloat32CustomPython : public astra::CFloat32CustomMemory { +public: +    CFloat32CustomPython(PyObject * arrIn) +    { +        arr = arrIn; +        // Set pointer to numpy data pointer +        m_fPtr = (float *)PyArray_DATA(arr); +        // Increase reference count since ASTRA has a reference +        Py_INCREF(arr); +    } +    virtual ~CFloat32CustomPython() { +        // Decrease reference count since ASTRA object is destroyed +        Py_DECREF(arr); +    } +private: +    PyObject* arr; +};
\ No newline at end of file diff --git a/python/astra/PyIncludes.pxd b/python/astra/PyIncludes.pxd index a581f88..1d8285b 100644 --- a/python/astra/PyIncludes.pxd +++ b/python/astra/PyIncludes.pxd @@ -63,10 +63,14 @@ cdef extern from "astra/VolumeGeometry2D.h" namespace "astra":  		float32 getWindowMaxY()  		Config* getConfiguration() +cdef extern from "astra/Float32Data2D.h" namespace "astra": +	cdef cppclass CFloat32CustomMemory: +		pass  cdef extern from "astra/Float32VolumeData2D.h" namespace "astra":  	cdef cppclass CFloat32VolumeData2D:  		CFloat32VolumeData2D(CVolumeGeometry2D*) +		CFloat32VolumeData2D(CVolumeGeometry2D*, CFloat32CustomMemory*)  		CVolumeGeometry2D * getGeometry()  		int getWidth()  		int getHeight() @@ -130,6 +134,7 @@ cdef extern from "astra/ParallelProjectionGeometry2D.h" namespace "astra":  cdef extern from "astra/Float32ProjectionData2D.h" namespace "astra":  	cdef cppclass CFloat32ProjectionData2D:  		CFloat32ProjectionData2D(CProjectionGeometry2D*) +		CFloat32ProjectionData2D(CProjectionGeometry2D*, CFloat32CustomMemory*)  		CProjectionGeometry2D * getGeometry()  		void changeGeometry(CProjectionGeometry2D*)  		int getDetectorCount() @@ -213,6 +218,7 @@ cdef extern from "astra/ProjectionGeometry3D.h" namespace "astra":  cdef extern from "astra/Float32VolumeData3DMemory.h" namespace "astra":  	cdef cppclass CFloat32VolumeData3DMemory:  		CFloat32VolumeData3DMemory(CVolumeGeometry3D*) +		CFloat32VolumeData3DMemory(CVolumeGeometry3D*, CFloat32CustomMemory*)  		CVolumeGeometry3D* getGeometry()  		void changeGeometry(CVolumeGeometry3D*)  		int getRowCount() @@ -242,6 +248,8 @@ cdef extern from "astra/Float32ProjectionData3DMemory.h" namespace "astra":  	cdef cppclass CFloat32ProjectionData3DMemory:  		CFloat32ProjectionData3DMemory(CProjectionGeometry3D*)  		CFloat32ProjectionData3DMemory(CConeProjectionGeometry3D*) +		CFloat32ProjectionData3DMemory(CProjectionGeometry3D*, CFloat32CustomMemory*) +		CFloat32ProjectionData3DMemory(CConeProjectionGeometry3D*, CFloat32CustomMemory*)  		CProjectionGeometry3D* getGeometry()  		void changeGeometry(CProjectionGeometry3D*)  		int getDetectorColCount() diff --git a/python/astra/data2d.py b/python/astra/data2d.py index 8c4be03..f119f05 100644 --- a/python/astra/data2d.py +++ b/python/astra/data2d.py @@ -24,6 +24,7 @@  #  #-----------------------------------------------------------------------  from . import data2d_c as d +import numpy as np  def clear():      """Clear all 2D data objects.""" @@ -52,6 +53,26 @@ def create(datatype, geometry, data=None):      """      return d.create(datatype,geometry,data) +def link(datatype, geometry, data): +    """Link a 2D numpy array with the toolbox. +         +    :param datatype: Data object type, '-vol' or '-sino'. +    :type datatype: :class:`string` +    :param geometry: Volume or projection geometry. +    :type geometry: :class:`dict` +    :param data: Numpy array to link +    :type data: :class:`numpy.ndarray` +    :returns: :class:`int` -- the ID of the constructed object. +     +    """ +    if not isinstance(data,np.ndarray): +        raise ValueError("Input should be a numpy array") +    if not data.dtype==np.float32: +        raise ValueError("Numpy array should be float32") +    if not (data.flags['C_CONTIGUOUS'] and data.flags['ALIGNED']): +        raise ValueError("Numpy array should be C_CONTIGUOUS and ALIGNED") +    return d.create(datatype,geometry,data,True) +  def store(i, data):      """Fill existing 2D object with data. diff --git a/python/astra/data2d_c.pyx b/python/astra/data2d_c.pyx index b9c105e..ac54898 100644 --- a/python/astra/data2d_c.pyx +++ b/python/astra/data2d_c.pyx @@ -49,6 +49,10 @@ from .utils import wrap_from_bytes  cdef CData2DManager * man2d = <CData2DManager * >PyData2DManager.getSingletonPtr() +cdef extern from "CFloat32CustomPython.h": +    cdef cppclass CFloat32CustomPython: +        CFloat32CustomPython(arrIn) +  def clear():      man2d.clear() @@ -61,11 +65,12 @@ def delete(ids):          man2d.remove(ids) -def create(datatype, geometry, data=None): +def create(datatype, geometry, data=None, link=False):      cdef Config *cfg      cdef CVolumeGeometry2D * pGeometry      cdef CProjectionGeometry2D * ppGeometry      cdef CFloat32Data2D * pDataObject2D +    cdef CFloat32CustomMemory * pCustom      if datatype == '-vol':          cfg = utils.dictToConfig(six.b('VolumeGeometry'), geometry)          pGeometry = new CVolumeGeometry2D() @@ -73,7 +78,11 @@ def create(datatype, geometry, data=None):              del cfg              del pGeometry              raise Exception('Geometry class not initialized.') -        pDataObject2D = <CFloat32Data2D * > new CFloat32VolumeData2D(pGeometry) +        if link: +            pCustom = <CFloat32CustomMemory*> new CFloat32CustomPython(data) +            pDataObject2D = <CFloat32Data2D * > new CFloat32VolumeData2D(pGeometry, pCustom) +        else: +            pDataObject2D = <CFloat32Data2D * > new CFloat32VolumeData2D(pGeometry)          del cfg          del pGeometry      elif datatype == '-sino': @@ -91,7 +100,11 @@ def create(datatype, geometry, data=None):              del cfg              del ppGeometry              raise Exception('Geometry class not initialized.') -        pDataObject2D = <CFloat32Data2D * > new CFloat32ProjectionData2D(ppGeometry) +        if link: +            pCustom = <CFloat32CustomMemory*> new CFloat32CustomPython(data) +            pDataObject2D = <CFloat32Data2D * > new CFloat32ProjectionData2D(ppGeometry, pCustom) +        else: +            pDataObject2D = <CFloat32Data2D * > new CFloat32ProjectionData2D(ppGeometry)          del ppGeometry          del cfg      else: @@ -101,7 +114,7 @@ def create(datatype, geometry, data=None):          del pDataObject2D          raise Exception("Couldn't initialize data object.") -    fillDataObject(pDataObject2D, data) +    if not link: fillDataObject(pDataObject2D, data)      return man2d.store(pDataObject2D) diff --git a/python/astra/data3d.py b/python/astra/data3d.py index 4679489..e5ef6b0 100644 --- a/python/astra/data3d.py +++ b/python/astra/data3d.py @@ -24,6 +24,7 @@  #  #-----------------------------------------------------------------------  from . import data3d_c as d +import numpy as np  def create(datatype,geometry,data=None):      """Create a 3D object. @@ -39,6 +40,27 @@ def create(datatype,geometry,data=None):      """      return d.create(datatype,geometry,data) +def link(datatype, geometry, data): +    """Link a 3D numpy array with the toolbox. +         +    :param datatype: Data object type, '-vol' or '-sino'. +    :type datatype: :class:`string` +    :param geometry: Volume or projection geometry. +    :type geometry: :class:`dict` +    :param data: Numpy array to link +    :type data: :class:`numpy.ndarray` +    :returns: :class:`int` -- the ID of the constructed object. +     +    """ +    if not isinstance(data,np.ndarray): +        raise ValueError("Input should be a numpy array") +    if not data.dtype==np.float32: +        raise ValueError("Numpy array should be float32") +    if not (data.flags['C_CONTIGUOUS'] and data.flags['ALIGNED']): +        raise ValueError("Numpy array should be C_CONTIGUOUS and ALIGNED") +    return d.create(datatype,geometry,data,True) + +  def get(i):      """Get a 3D object. diff --git a/python/astra/data3d_c.pyx b/python/astra/data3d_c.pyx index 48af032..84472c1 100644 --- a/python/astra/data3d_c.pyx +++ b/python/astra/data3d_c.pyx @@ -50,12 +50,17 @@ cdef CData3DManager * man3d = <CData3DManager * >PyData3DManager.getSingletonPtr  cdef extern from *:      CFloat32Data3DMemory * dynamic_cast_mem "dynamic_cast<astra::CFloat32Data3DMemory*>" (CFloat32Data3D * ) except NULL -def create(datatype,geometry,data=None): +cdef extern from "CFloat32CustomPython.h": +    cdef cppclass CFloat32CustomPython: +        CFloat32CustomPython(arrIn) + +def create(datatype,geometry,data=None, link=False):      cdef Config *cfg      cdef CVolumeGeometry3D * pGeometry      cdef CProjectionGeometry3D * ppGeometry      cdef CFloat32Data3DMemory * pDataObject3D      cdef CConeProjectionGeometry3D* pppGeometry +    cdef CFloat32CustomMemory * pCustom      if datatype == '-vol':          cfg = utils.dictToConfig(six.b('VolumeGeometry'), geometry)          pGeometry = new CVolumeGeometry3D() @@ -63,7 +68,11 @@ def create(datatype,geometry,data=None):              del cfg              del pGeometry              raise Exception('Geometry class not initialized.') -        pDataObject3D = <CFloat32Data3DMemory * > new CFloat32VolumeData3DMemory(pGeometry) +        if link: +            pCustom = <CFloat32CustomMemory*> new CFloat32CustomPython(data) +            pDataObject3D = <CFloat32Data3DMemory * > new CFloat32VolumeData3DMemory(pGeometry, pCustom) +        else: +            pDataObject3D = <CFloat32Data3DMemory * > new CFloat32VolumeData3DMemory(pGeometry)          del cfg          del pGeometry      elif datatype == '-sino' or datatype == '-proj3d': @@ -84,7 +93,11 @@ def create(datatype,geometry,data=None):              del cfg              del ppGeometry              raise Exception('Geometry class not initialized.') -        pDataObject3D = <CFloat32Data3DMemory * > new CFloat32ProjectionData3DMemory(ppGeometry) +        if link: +            pCustom = <CFloat32CustomMemory*> new CFloat32CustomPython(data) +            pDataObject3D = <CFloat32Data3DMemory * > new CFloat32ProjectionData3DMemory(ppGeometry, pCustom) +        else: +            pDataObject3D = <CFloat32Data3DMemory * > new CFloat32ProjectionData3DMemory(ppGeometry)          del ppGeometry          del cfg      elif datatype == "-sinocone": @@ -94,7 +107,11 @@ def create(datatype,geometry,data=None):              del cfg              del pppGeometry              raise Exception('Geometry class not initialized.') -        pDataObject3D = <CFloat32Data3DMemory * > new CFloat32ProjectionData3DMemory(pppGeometry) +        if link: +            pCustom = <CFloat32CustomMemory*> new CFloat32CustomPython(data) +            pDataObject3D = <CFloat32Data3DMemory * > new CFloat32ProjectionData3DMemory(pppGeometry, pCustom) +        else: +            pDataObject3D = <CFloat32Data3DMemory * > new CFloat32ProjectionData3DMemory(pppGeometry)      else:          raise Exception("Invalid datatype.  Please specify '-vol' or '-proj3d'.") @@ -102,7 +119,7 @@ def create(datatype,geometry,data=None):          del pDataObject3D          raise Exception("Couldn't initialize data object.") -    fillDataObject(pDataObject3D, data) +    if not link: fillDataObject(pDataObject3D, data)      pDataObject3D.updateStatistics() diff --git a/src/Float32ProjectionData2D.cpp b/src/Float32ProjectionData2D.cpp index 85e0cdd..f7f83e3 100644 --- a/src/Float32ProjectionData2D.cpp +++ b/src/Float32ProjectionData2D.cpp @@ -75,6 +75,16 @@ CFloat32ProjectionData2D::CFloat32ProjectionData2D(const CFloat32ProjectionData2  	m_bInitialized = true;  } +//---------------------------------------------------------------------------------------- +// Create an instance of the CFloat32ProjectionData2D class with pre-allocated data +CFloat32ProjectionData2D::CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry, CFloat32CustomMemory* _pCustomMemory) +{ +	m_bInitialized = false; +	m_bInitialized = initialize(_pGeometry, _pCustomMemory); +} +  + +  // Assignment operator  CFloat32ProjectionData2D& CFloat32ProjectionData2D::operator=(const CFloat32ProjectionData2D& _other) @@ -119,6 +129,15 @@ bool CFloat32ProjectionData2D::initialize(CProjectionGeometry2D* _pGeometry, flo  }  //---------------------------------------------------------------------------------------- +// Initialization +bool CFloat32ProjectionData2D::initialize(CProjectionGeometry2D* _pGeometry, CFloat32CustomMemory* _pCustomMemory)  +{ +	m_pGeometry = _pGeometry->clone(); +	m_bInitialized = _initialize(m_pGeometry->getDetectorCount(), m_pGeometry->getProjectionAngleCount(), _pCustomMemory); +	return m_bInitialized; +} + +//----------------------------------------------------------------------------------------  // Destructor  CFloat32ProjectionData2D::~CFloat32ProjectionData2D()   { diff --git a/src/Float32VolumeData2D.cpp b/src/Float32VolumeData2D.cpp index e11c4e4..c903c66 100644 --- a/src/Float32VolumeData2D.cpp +++ b/src/Float32VolumeData2D.cpp @@ -72,6 +72,15 @@ CFloat32VolumeData2D::CFloat32VolumeData2D(const CFloat32VolumeData2D& _other) :  	m_bInitialized = true;  } +//---------------------------------------------------------------------------------------- +// Create an instance of the CFloat32VolumeData2D class with pre-allocated data +CFloat32VolumeData2D::CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry, CFloat32CustomMemory* _pCustomMemory) +{ +	m_bInitialized = false; +	m_bInitialized = initialize(_pGeometry, _pCustomMemory); +} + +  // Assignment operator  CFloat32VolumeData2D& CFloat32VolumeData2D::operator=(const CFloat32VolumeData2D& _other) @@ -122,6 +131,17 @@ bool CFloat32VolumeData2D::initialize(CVolumeGeometry2D* _pGeometry, float32 _fS  	m_bInitialized = _initialize(m_pGeometry->getGridColCount(), m_pGeometry->getGridRowCount(), _fScalar);  	return m_bInitialized;  } + +//---------------------------------------------------------------------------------------- +// Initialization +bool CFloat32VolumeData2D::initialize(CVolumeGeometry2D* _pGeometry, CFloat32CustomMemory* _pCustomMemory)  +{ +	m_pGeometry = _pGeometry->clone(); +	m_bInitialized = _initialize(m_pGeometry->getGridColCount(), m_pGeometry->getGridRowCount(), _pCustomMemory); +	return m_bInitialized; +} + +  //----------------------------------------------------------------------------------------  void CFloat32VolumeData2D::changeGeometry(CVolumeGeometry2D* _pGeometry)  { | 
