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 | 
