diff options
-rw-r--r-- | include/astra/Float32ProjectionData3D.h | 5 | ||||
-rw-r--r-- | include/astra/Float32VolumeData3D.h | 5 | ||||
-rw-r--r-- | matlab/mex/astra_mex_data3d_c.cpp | 110 | ||||
-rw-r--r-- | python/astra/PyIncludes.pxd | 15 | ||||
-rw-r--r-- | python/astra/data3d.py | 11 | ||||
-rw-r--r-- | python/astra/data3d_c.pyx | 55 | ||||
-rw-r--r-- | src/Float32ProjectionData3D.cpp | 9 | ||||
-rw-r--r-- | src/Float32VolumeData3D.cpp | 9 |
8 files changed, 218 insertions, 1 deletions
diff --git a/include/astra/Float32ProjectionData3D.h b/include/astra/Float32ProjectionData3D.h index 79b762e..329c9a4 100644 --- a/include/astra/Float32ProjectionData3D.h +++ b/include/astra/Float32ProjectionData3D.h @@ -196,6 +196,11 @@ public: * @return pointer to projection geometry. */ virtual CProjectionGeometry3D* getGeometry() const; + + /** Change the projection geometry. + * Note that this can't change the dimensions of the data. + */ + virtual void changeGeometry(CProjectionGeometry3D* pGeometry); }; diff --git a/include/astra/Float32VolumeData3D.h b/include/astra/Float32VolumeData3D.h index d8f0ae9..07df78f 100644 --- a/include/astra/Float32VolumeData3D.h +++ b/include/astra/Float32VolumeData3D.h @@ -214,6 +214,11 @@ public: * @return The geometry describing the data stored in this volume */ virtual CVolumeGeometry3D* getGeometry() const; + + /** Change the projection geometry. + * Note that this can't change the dimensions of the data. + */ + virtual void changeGeometry(CVolumeGeometry3D* pGeometry); }; //---------------------------------------------------------------------------------------- diff --git a/matlab/mex/astra_mex_data3d_c.cpp b/matlab/mex/astra_mex_data3d_c.cpp index 7efbdab..6096adc 100644 --- a/matlab/mex/astra_mex_data3d_c.cpp +++ b/matlab/mex/astra_mex_data3d_c.cpp @@ -310,6 +310,112 @@ void astra_mex_data3d_get_geometry(int nlhs, mxArray* plhs[], int nrhs, const mx } //----------------------------------------------------------------------------------------- +/** astra_mex_data3d('change_geometry', id, geom); + * + * Change the geometry of a 3d data object. + * id: identifier of the 3d data object as stored in the astra-library. + * geom: the new geometry struct, as created by astra_create_vol/proj_geom + */ +void astra_mex_data3d_change_geometry(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + // parse input + if (nrhs < 3) { + mexErrMsgTxt("Not enough arguments. See the help document for a detailed argument list. \n"); + return; + } + + // get data object + CFloat32Data3DMemory* pDataObject = NULL; + if (!checkID(mxGetScalar(prhs[1]), pDataObject)) { + mexErrMsgTxt("Data object not found or not initialized properly.\n"); + return; + } + + const mxArray * const geometry = prhs[2]; + + if (!checkStructs(geometry)) { + mexErrMsgTxt("Argument 3 is not a valid MATLAB struct.\n"); + return; + } + + CFloat32ProjectionData3D* pProjData = dynamic_cast<CFloat32ProjectionData3D*>(pDataObject); + if (pProjData) { + // Projection data + + // Read geometry + astra::Config* cfg = structToConfig("ProjectionGeometry3D", geometry); + // FIXME: Change how the base class is created. (This is duplicated + // in Projector3D.cpp.) + std::string type = cfg->self->getAttribute("type"); + astra::CProjectionGeometry3D* pGeometry = 0; + if (type == "parallel3d") { + pGeometry = new astra::CParallelProjectionGeometry3D(); + } else if (type == "parallel3d_vec") { + pGeometry = new astra::CParallelVecProjectionGeometry3D(); + } else if (type == "cone") { + pGeometry = new astra::CConeProjectionGeometry3D(); + } else if (type == "cone_vec") { + pGeometry = new astra::CConeVecProjectionGeometry3D(); + } else { + mexErrMsgTxt("Invalid geometry type.\n"); + return; + } + + if (!pGeometry->initialize(*cfg)) { + mexErrMsgTxt("Geometry class not initialized. \n"); + delete pGeometry; + delete cfg; + return; + } + delete cfg; + + // Check dimensions + if (pGeometry->getDetectorColCount() != pProjData->getDetectorColCount() || + pGeometry->getProjectionCount() != pProjData->getAngleCount() || + pGeometry->getDetectorRowCount() != pProjData->getDetectorRowCount()) + { + mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry. \n"); + delete pGeometry; + return; + } + + // If ok, change geometry + pProjData->changeGeometry(pGeometry); + delete pGeometry; + } else { + // Volume data + CFloat32VolumeData3D* pVolData = dynamic_cast<CFloat32VolumeData3D*>(pDataObject); + assert(pVolData); + + // Read geometry + astra::Config* cfg = structToConfig("VolumeGeometry3D", geometry); + astra::CVolumeGeometry3D* pGeometry = new astra::CVolumeGeometry3D(); + if (!pGeometry->initialize(*cfg)) + { + mexErrMsgTxt("Geometry class not initialized. \n"); + delete pGeometry; + delete cfg; + return; + } + delete cfg; + + // Check dimensions + if (pGeometry->getGridColCount() != pVolData->getColCount() || + pGeometry->getGridRowCount() != pVolData->getRowCount() || + pGeometry->getGridSliceCount() != pVolData->getSliceCount()) + { + mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry. \n"); + delete pGeometry; + return; + } + + // If ok, change geometry + pVolData->changeGeometry(pGeometry); + delete pGeometry; + } +} + +//----------------------------------------------------------------------------------------- /** * astra_mex_data3d('delete', did1, did2, ...); */ @@ -351,7 +457,7 @@ static void printHelp() { mexPrintf("Please specify a mode of operation.\n"); mexPrintf("Valid modes: create, get, get_single, delete, clear, info\n"); - mexPrintf(" dimensions\n"); + mexPrintf(" dimensions, get_geometry, change_geometry\n"); } @@ -398,6 +504,8 @@ void mexFunction(int nlhs, mxArray* plhs[], astra_mex_data3d_dimensions(nlhs, plhs, nrhs, prhs); } else if (sMode == std::string("get_geometry")) { astra_mex_data3d_get_geometry(nlhs, plhs, nrhs, prhs); + } else if (sMode == std::string("change_geometry")) { + astra_mex_data3d_change_geometry(nlhs, plhs, nrhs, prhs); } else { printHelp(); } diff --git a/python/astra/PyIncludes.pxd b/python/astra/PyIncludes.pxd index 13329d1..1d8285b 100644 --- a/python/astra/PyIncludes.pxd +++ b/python/astra/PyIncludes.pxd @@ -201,12 +201,18 @@ cdef extern from "astra/VolumeGeometry3D.h" namespace "astra": CVolumeGeometry3D() bool initialize(Config) Config * getConfiguration() + int getGridColCount() + int getGridRowCount() + int getGridSliceCount() cdef extern from "astra/ProjectionGeometry3D.h" namespace "astra": cdef cppclass CProjectionGeometry3D: CProjectionGeometry3D() bool initialize(Config) Config * getConfiguration() + int getProjectionCount() + int getDetectorColCount() + int getDetectorRowCount() cdef extern from "astra/Float32VolumeData3DMemory.h" namespace "astra": @@ -214,6 +220,11 @@ cdef extern from "astra/Float32VolumeData3DMemory.h" namespace "astra": CFloat32VolumeData3DMemory(CVolumeGeometry3D*) CFloat32VolumeData3DMemory(CVolumeGeometry3D*, CFloat32CustomMemory*) CVolumeGeometry3D* getGeometry() + void changeGeometry(CVolumeGeometry3D*) + int getRowCount() + int getColCount() + int getSliceCount() + cdef extern from "astra/ParallelProjectionGeometry3D.h" namespace "astra": @@ -240,6 +251,10 @@ cdef extern from "astra/Float32ProjectionData3DMemory.h" namespace "astra": CFloat32ProjectionData3DMemory(CProjectionGeometry3D*, CFloat32CustomMemory*) CFloat32ProjectionData3DMemory(CConeProjectionGeometry3D*, CFloat32CustomMemory*) CProjectionGeometry3D* getGeometry() + void changeGeometry(CProjectionGeometry3D*) + int getDetectorColCount() + int getDetectorRowCount() + int getAngleCount() cdef extern from "astra/Float32Data3D.h" namespace "astra": cdef cppclass CFloat32Data3D: diff --git a/python/astra/data3d.py b/python/astra/data3d.py index 4fdf9d7..e5ef6b0 100644 --- a/python/astra/data3d.py +++ b/python/astra/data3d.py @@ -112,6 +112,17 @@ def get_geometry(i): """ return d.get_geometry(i) +def change_geometry(i, geometry): + """Change the geometry of a 3D object. + + :param i: ID of object. + :type i: :class:`int` + :param geometry: Volume or projection geometry. + :type geometry: :class:`dict` + + """ + return d.change_geometry(i, geometry) + def dimensions(i): """Get dimensions of a 3D object. diff --git a/python/astra/data3d_c.pyx b/python/astra/data3d_c.pyx index f2c6e26..84472c1 100644 --- a/python/astra/data3d_c.pyx +++ b/python/astra/data3d_c.pyx @@ -139,6 +139,61 @@ def get_geometry(i): raise Exception("Not a known data object") return geom +def change_geometry(i, geom): + cdef CFloat32Data3DMemory * pDataObject = dynamic_cast_mem(getObject(i)) + cdef CFloat32ProjectionData3DMemory * pDataObject2 + cdef CFloat32VolumeData3DMemory * pDataObject3 + if pDataObject.getType() == THREEPROJECTION: + pDataObject2 = <CFloat32ProjectionData3DMemory * >pDataObject + # TODO: Reduce code duplication here + cfg = utils.dictToConfig(six.b('ProjectionGeometry'), geom) + tpe = wrap_from_bytes(cfg.self.getAttribute(six.b('type'))) + if (tpe == "parallel3d"): + ppGeometry = <CProjectionGeometry3D*> new CParallelProjectionGeometry3D(); + elif (tpe == "parallel3d_vec"): + ppGeometry = <CProjectionGeometry3D*> new CParallelVecProjectionGeometry3D(); + elif (tpe == "cone"): + ppGeometry = <CProjectionGeometry3D*> new CConeProjectionGeometry3D(); + elif (tpe == "cone_vec"): + ppGeometry = <CProjectionGeometry3D*> new CConeVecProjectionGeometry3D(); + else: + raise Exception("Invalid geometry type.") + if not ppGeometry.initialize(cfg[0]): + del cfg + del ppGeometry + raise Exception('Geometry class not initialized.') + del cfg + if (ppGeometry.getDetectorColCount() != pDataObject2.getDetectorColCount() or \ + ppGeometry.getProjectionCount() != pDataObject2.getAngleCount() or \ + ppGeometry.getDetectorRowCount() != pDataObject2.getDetectorRowCount()): + del ppGeometry + raise Exception( + "The dimensions of the data do not match those specified in the geometry.") + pDataObject2.changeGeometry(ppGeometry) + del ppGeometry + + elif pDataObject.getType() == THREEVOLUME: + pDataObject3 = <CFloat32VolumeData3DMemory * >pDataObject + cfg = utils.dictToConfig(six.b('VolumeGeometry'), geom) + pGeometry = new CVolumeGeometry3D() + if not pGeometry.initialize(cfg[0]): + del cfg + del pGeometry + raise Exception('Geometry class not initialized.') + del cfg + if (pGeometry.getGridColCount() != pDataObject3.getColCount() or \ + pGeometry.getGridRowCount() != pDataObject3.getRowCount() or \ + pGeometry.getGridSliceCount() != pDataObject3.getSliceCount()): + del pGeometry + raise Exception( + "The dimensions of the data do not match those specified in the geometry.") + pDataObject3.changeGeometry(pGeometry) + del pGeometry + + else: + raise Exception("Not a known data object") + + cdef fillDataObject(CFloat32Data3DMemory * obj, data): if data is None: fillDataObjectScalar(obj, 0) diff --git a/src/Float32ProjectionData3D.cpp b/src/Float32ProjectionData3D.cpp index d039c83..2bd0447 100644 --- a/src/Float32ProjectionData3D.cpp +++ b/src/Float32ProjectionData3D.cpp @@ -270,4 +270,13 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator-=(const float32& _f return *this; } +void CFloat32ProjectionData3D::changeGeometry(CProjectionGeometry3D* _pGeometry) +{ + if (!m_bInitialized) return; + + delete m_pGeometry; + m_pGeometry = _pGeometry->clone(); +} + + } // end namespace astra diff --git a/src/Float32VolumeData3D.cpp b/src/Float32VolumeData3D.cpp index ce00a10..bd78001 100644 --- a/src/Float32VolumeData3D.cpp +++ b/src/Float32VolumeData3D.cpp @@ -266,4 +266,13 @@ CFloat32VolumeData3D& CFloat32VolumeData3D::operator-=(const float32& _fScalar) return *this; } +void CFloat32VolumeData3D::changeGeometry(CVolumeGeometry3D* _pGeometry) +{ + if (!m_bInitialized) return; + + delete m_pGeometry; + m_pGeometry = _pGeometry->clone(); +} + + } // end namespace astra |