diff options
author | Willem Jan Palenstijn <wjp@usecode.org> | 2015-02-27 11:46:29 +0100 |
---|---|---|
committer | Willem Jan Palenstijn <wjp@usecode.org> | 2015-02-27 11:46:29 +0100 |
commit | 03a9dd972ada50eedb83386910cecf02fe8d0e35 (patch) | |
tree | f764bff6a8109d42445bdd1db622fd739baf5d4a | |
parent | 9e2bb413a937aefe57f4fcf343413543ae57258a (diff) | |
parent | 169e912d2633cda7ffc234e78afba1b096e122ea (diff) | |
download | astra-03a9dd972ada50eedb83386910cecf02fe8d0e35.tar.gz astra-03a9dd972ada50eedb83386910cecf02fe8d0e35.tar.bz2 astra-03a9dd972ada50eedb83386910cecf02fe8d0e35.tar.xz astra-03a9dd972ada50eedb83386910cecf02fe8d0e35.zip |
Merge pull request #20 from wvaarle/matlab-get-geometry
'get_geometry' functions in the matlab layer
38 files changed, 724 insertions, 702 deletions
diff --git a/include/astra/ConeProjectionGeometry3D.h b/include/astra/ConeProjectionGeometry3D.h index 2a0474d..00e72ce 100644 --- a/include/astra/ConeProjectionGeometry3D.h +++ b/include/astra/ConeProjectionGeometry3D.h @@ -40,8 +40,8 @@ namespace astra * \par XML Configuration * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.} * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.} - * \astra_xml_item{DetectorWidth, float, Width of each detector.} - * \astra_xml_item{DetectorHeight, float, Width of each detector.} + * \astra_xml_item{DetectorSpacingX, float, Width of each detector.} + * \astra_xml_item{DetectorSpacingY, float, Width of each detector.} * \astra_xml_item{ProjectionAngles, vector of float, projection angles in radians.} * \astra_xml_item{DistanceOriginDetector, float, Distance between the center of rotation and the detectorarray.} * \astra_xml_item{DistanceOriginSource, float, Distance between the center of rotation the the x-ray source.} @@ -51,8 +51,8 @@ namespace astra * proj_geom = astra_struct('cone');\n * proj_geom.DetectorRowCount = 512;\n * proj_geom.DetectorColCount = 512;\n - * proj_geom.DetectorWidth = 1.0;\n - * proj_geom.DetectorHeight = 1.0;\n + * proj_geom.DetectorSpacingX = 1.0;\n + * proj_geom.DetectorSpacingY = 1.0;\n * proj_geom.ProjectionAngles = linspace(0,pi,100);\n * proj_geom.DistanceOriginDetector = 10000;\n * proj_geom.DistanceOriginSource = 10000;\n @@ -148,6 +148,12 @@ public: */ virtual bool isEqual(const CProjectionGeometry3D*) const; + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const; + /** Returns true if the type of geometry defined in this class is the one specified in _sType. * * @param _sType geometry type to compare to. @@ -155,12 +161,6 @@ public: */ virtual bool isOfType(const std::string& _sType) const; - /** Turn this object into an XML object. - * - * @param _sNode The XML object to fill. - */ - virtual void toXML(XMLNode* _sNode) const; - /** Returns the distance from the origin of the coordinate system to the source. * * @return Distance from the origin of the coordinate system to the source diff --git a/include/astra/ConeVecProjectionGeometry3D.h b/include/astra/ConeVecProjectionGeometry3D.h index 68a80ef..e82a411 100644 --- a/include/astra/ConeVecProjectionGeometry3D.h +++ b/include/astra/ConeVecProjectionGeometry3D.h @@ -56,7 +56,7 @@ namespace astra * to a single projection, and consists of: * ( srcX, srcY, srcZ, dX, dY, dZ, uX, uY, uZ, vX, vY, vZ ) * src: the ray source - * d : the corner of the detector + * d : the centre of the detector plane * u : the vector from detector pixel (0,0) to (0,1) * v : the vector from detector pixel (0,0) to (1,0) */ @@ -128,6 +128,12 @@ public: */ virtual bool isEqual(const CProjectionGeometry3D*) const; + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const; + /** Returns true if the type of geometry defined in this class is the one specified in _sType. * * @param _sType geometry type to compare to. @@ -135,12 +141,6 @@ public: */ virtual bool isOfType(const std::string& _sType) const; - /** Turn this object into an XML object. - * - * @param _sNode The XML object to fill. - */ - virtual void toXML(XMLNode* _sNode) const; - /** * Returns a vector giving the projection direction for a projection and detector index */ diff --git a/include/astra/Config.h b/include/astra/Config.h index 647462b..9893c90 100644 --- a/include/astra/Config.h +++ b/include/astra/Config.h @@ -31,6 +31,7 @@ $Id$ #include "Globals.h" #include "XMLNode.h" +#include "XMLDocument.h" #include <set> @@ -46,6 +47,8 @@ struct _AstraExport Config { Config(XMLNode* _self); ~Config(); + void initialize(std::string rootname); + XMLNode* self; XMLNode* global; }; diff --git a/include/astra/FanFlatProjectionGeometry2D.h b/include/astra/FanFlatProjectionGeometry2D.h index 8f22c35..180fe68 100644 --- a/include/astra/FanFlatProjectionGeometry2D.h +++ b/include/astra/FanFlatProjectionGeometry2D.h @@ -140,6 +140,12 @@ public: */ virtual bool isOfType(const std::string& _sType); + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const; + /** Return true if this geometry instance is the same as the one specified. * * @return true if this geometry instance is the same as the one specified. diff --git a/include/astra/FanFlatVecProjectionGeometry2D.h b/include/astra/FanFlatVecProjectionGeometry2D.h index 85c994f..ee85408 100644 --- a/include/astra/FanFlatVecProjectionGeometry2D.h +++ b/include/astra/FanFlatVecProjectionGeometry2D.h @@ -53,6 +53,14 @@ namespace astra * proj_geom.DetectorCount = 512;\n * proj_geom.Vectors = V;\n * } + * + * \par Vectors + * Vectors is a matrix containing the actual geometry. Each row corresponds + * to a single projection, and consists of: + * ( srcX, srcY, srcZ, dX, dY uX, uY) + * src: the ray source + * d : the centre of the detector array + * u : the vector from detector 0 to detector 1 */ class _AstraExport CFanFlatVecProjectionGeometry2D : public CProjectionGeometry2D { @@ -126,6 +134,13 @@ public: */ virtual bool isEqual(CProjectionGeometry2D*) const; + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const; + + /** Get the value for t and theta, based upon the row and column index. * * @param _iRow row index diff --git a/include/astra/ParallelProjectionGeometry2D.h b/include/astra/ParallelProjectionGeometry2D.h index ed9d228..2f7d36f 100644 --- a/include/astra/ParallelProjectionGeometry2D.h +++ b/include/astra/ParallelProjectionGeometry2D.h @@ -136,6 +136,12 @@ public: */ virtual bool isOfType(const std::string& _sType); + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const; + /** * Returns a vector describing the direction of a ray belonging to a certain detector, * the direction is the same for all detectors in one projection diff --git a/include/astra/ParallelProjectionGeometry3D.h b/include/astra/ParallelProjectionGeometry3D.h index da60617..72401e5 100644 --- a/include/astra/ParallelProjectionGeometry3D.h +++ b/include/astra/ParallelProjectionGeometry3D.h @@ -41,8 +41,8 @@ namespace astra * \par XML Configuration * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.} * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.} - * \astra_xml_item{DetectorWidth, float, Width of each detector.} - * \astra_xml_item{DetectorHeight, float, Width of each detector.} + * \astra_xml_item{DetectorSpacingX, float, Width of each detector.} + * \astra_xml_item{DetectorSpacingY, float, Width of each detector.} * \astra_xml_item{ProjectionAngles, vector of float, projection angles in radians.} * * \par MATLAB example @@ -50,8 +50,8 @@ namespace astra * proj_geom = astra_struct('parallel');\n * proj_geom.DetectorRowCount = 512;\n * proj_geom.DetectorColCount = 512;\n - * proj_geom.DetectorWidth = 1.0;\n - * proj_geom.DetectorHeight = 1.0;\n + * proj_geom.DetectorSpacingX = 1.0;\n + * proj_geom.DetectorSpacingY = 1.0;\n * proj_geom.ProjectionAngles = linspace(0,pi,100);\n * } */ @@ -129,6 +129,12 @@ public: */ virtual bool isEqual(const CProjectionGeometry3D*) const; + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const; + /** Returns true if the type of geometry defined in this class is the one specified in _sType. * * @param _sType geometry type to compare to. @@ -136,12 +142,6 @@ public: */ virtual bool isOfType(const std::string& _sType) const; - /** Turn this object into an XML object. - * - * @param _sNode The XML object to fill. - */ - virtual void toXML(XMLNode* _sNode) const; - /** * Returns a vector giving the projection direction for a projection and detector index */ diff --git a/include/astra/ParallelVecProjectionGeometry3D.h b/include/astra/ParallelVecProjectionGeometry3D.h index fbc2112..5a63249 100644 --- a/include/astra/ParallelVecProjectionGeometry3D.h +++ b/include/astra/ParallelVecProjectionGeometry3D.h @@ -55,7 +55,7 @@ namespace astra * to a single projection, and consists of: * ( rayX, rayY, rayZ, dX, dY, dZ, uX, uY, uZ, vX, vY, vZ ) * ray: the ray direction - * d : the corner of the detector + * d : the centre of the detector plane * u : the vector from detector pixel (0,0) to (0,1) * v : the vector from detector pixel (0,0) to (1,0) */ @@ -128,6 +128,12 @@ public: */ virtual bool isEqual(const CProjectionGeometry3D*) const; + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const; + /** Returns true if the type of geometry defined in this class is the one specified in _sType. * * @param _sType geometry type to compare to. @@ -135,12 +141,6 @@ public: */ virtual bool isOfType(const std::string& _sType) const; - /** Turn this object into an XML object. - * - * @param _sNode The XML object to fill. - */ - virtual void toXML(XMLNode* _sNode) const; - /** * Returns a vector giving the projection direction for a projection and detector index */ diff --git a/include/astra/ProjectionGeometry2D.h b/include/astra/ProjectionGeometry2D.h index 303ca0a..b8324e2 100644 --- a/include/astra/ProjectionGeometry2D.h +++ b/include/astra/ProjectionGeometry2D.h @@ -157,6 +157,12 @@ public: */ virtual bool isEqual(CProjectionGeometry2D*) const = 0; + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const = 0; + /** Get the number of projection angles. * * @return Number of projection angles diff --git a/include/astra/ProjectionGeometry3D.h b/include/astra/ProjectionGeometry3D.h index 41b1cb7..19ac3ab 100644 --- a/include/astra/ProjectionGeometry3D.h +++ b/include/astra/ProjectionGeometry3D.h @@ -187,6 +187,12 @@ public: */ virtual bool isEqual(const CProjectionGeometry3D *) const = 0; + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const = 0; + /** Get the number of projections. * * @return Number of projections @@ -322,12 +328,6 @@ public: */ virtual bool isOfType(const std::string& _sType) const = 0; - /** Turn this object into an XML object. - * - * @param _sNode The XML object to fill. - */ - virtual void toXML(XMLNode* _sNode) const = 0; - /** * Returns a vector giving the projection direction for a projection and detector index */ diff --git a/include/astra/SparseMatrixProjectionGeometry2D.h b/include/astra/SparseMatrixProjectionGeometry2D.h index 36964be..d56f95e 100644 --- a/include/astra/SparseMatrixProjectionGeometry2D.h +++ b/include/astra/SparseMatrixProjectionGeometry2D.h @@ -103,7 +103,6 @@ public: * @param _pMatrix Pointer to a CSparseMatrix. The caller is responsible for keeping this matrix valid until it is no longer required. * @return initialization successful? */ - bool setMatrix(CSparseMatrix* _pMatrix); /** Get a pointer to the associated sparse matrix. @@ -128,6 +127,13 @@ public: */ virtual bool isOfType(const std::string& _sType); + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const; + + /** * Returns a vector describing the direction of a ray belonging to a certain detector * diff --git a/include/astra/VolumeGeometry2D.h b/include/astra/VolumeGeometry2D.h index fa0528d..28703d5 100644 --- a/include/astra/VolumeGeometry2D.h +++ b/include/astra/VolumeGeometry2D.h @@ -205,6 +205,12 @@ public: */ virtual bool isEqual(CVolumeGeometry2D*) const; + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const; + /** Get the number of columns in the volume grid. * * @return Number of columns in the volume grid. diff --git a/include/astra/VolumeGeometry3D.h b/include/astra/VolumeGeometry3D.h index d5c8fff..ff94844 100644 --- a/include/astra/VolumeGeometry3D.h +++ b/include/astra/VolumeGeometry3D.h @@ -246,6 +246,12 @@ public: */ virtual bool isEqual(const CVolumeGeometry3D*) const; + /** Get all settings in a Config object. + * + * @return Configuration Object. + */ + virtual Config* getConfiguration() const; + /** Get the number of columns in the volume grid. * * @return Number of columns in the volume grid. diff --git a/include/astra/XMLDocument.h b/include/astra/XMLDocument.h index c6f1b9a..869e1a3 100644 --- a/include/astra/XMLDocument.h +++ b/include/astra/XMLDocument.h @@ -86,6 +86,9 @@ public: */ void saveToFile(string sFilename); + /** convert and XML DOM tree to a string + */ + std::string toString(); private: diff --git a/matlab/mex/astra_mex_algorithm_c.cpp b/matlab/mex/astra_mex_algorithm_c.cpp index be1c89f..669af8c 100644 --- a/matlab/mex/astra_mex_algorithm_c.cpp +++ b/matlab/mex/astra_mex_algorithm_c.cpp @@ -78,26 +78,23 @@ void astra_mex_algorithm_create(int nlhs, mxArray* plhs[], int nrhs, const mxArr } // turn MATLAB struct to an XML-based Config object - XMLDocument* xml = struct2XML("Algorithm", prhs[1]); - Config cfg; - cfg.self = xml->getRootNode(); + Config* cfg = structToConfig("Algorithm", prhs[1]); - CAlgorithm* pAlg = CAlgorithmFactory::getSingleton().create(cfg.self->getAttribute("type")); + CAlgorithm* pAlg = CAlgorithmFactory::getSingleton().create(cfg->self->getAttribute("type")); if (!pAlg) { - delete xml; + delete cfg; mexErrMsgTxt("Unknown algorithm. \n"); return; } // create algorithm - if (!pAlg->initialize(cfg)) { - delete xml; + if (!pAlg->initialize(*cfg)) { + delete cfg; delete pAlg; mexErrMsgTxt("Algorithm not initialized. \n"); return; } - - delete xml; + delete cfg; // store algorithm int iIndex = CAlgorithmManager::getSingleton().store(pAlg); @@ -322,7 +319,7 @@ void mexFunction(int nlhs, mxArray* plhs[], // INPUT: Mode string sMode = ""; if (1 <= nrhs) { - sMode = mex_util_get_string(prhs[0]); + sMode = mexToString(prhs[0]); } else { printHelp(); return; diff --git a/matlab/mex/astra_mex_c.cpp b/matlab/mex/astra_mex_c.cpp index 2989b7a..760bd51 100644 --- a/matlab/mex/astra_mex_c.cpp +++ b/matlab/mex/astra_mex_c.cpp @@ -122,7 +122,7 @@ void mexFunction(int nlhs, mxArray* plhs[], // INPUT0: Mode string sMode = ""; if (1 <= nrhs) { - sMode = mex_util_get_string(prhs[0]); + sMode = mexToString(prhs[0]); } else { printHelp(); return; diff --git a/matlab/mex/astra_mex_data2d_c.cpp b/matlab/mex/astra_mex_data2d_c.cpp index b219179..5f79e98 100644 --- a/matlab/mex/astra_mex_data2d_c.cpp +++ b/matlab/mex/astra_mex_data2d_c.cpp @@ -98,10 +98,10 @@ void astra_mex_data2d_create(int& nlhs, mxArray* plhs[], int& nrhs, const mxArra return; } - string sDataType = mex_util_get_string(prhs[1]); + string sDataType = mexToString(prhs[1]); CFloat32Data2D* pDataObject2D = NULL; - if (nrhs >= 4 && !(mex_is_scalar(prhs[3])|| mxIsDouble(prhs[3]) || mxIsLogical(prhs[3]) || mxIsSingle(prhs[3]) )) { + if (nrhs >= 4 && !(mexIsScalar(prhs[3])|| mxIsDouble(prhs[3]) || mxIsLogical(prhs[3]) || mxIsSingle(prhs[3]) )) { mexErrMsgTxt("Data must be single, double or logical."); return; } @@ -116,23 +116,20 @@ void astra_mex_data2d_create(int& nlhs, mxArray* plhs[], int& nrhs, const mxArra if (!mxIsStruct(prhs[2])) { mexErrMsgTxt("Argument 3 is not a valid MATLAB struct.\n"); } - XMLDocument* xml = struct2XML(string("VolumeGeometry"), prhs[2]); - if (!xml) - return; - Config cfg; - cfg.self = xml->getRootNode(); + + Config* cfg = structToConfig("VolumeGeometry", prhs[2]); CVolumeGeometry2D* pGeometry = new CVolumeGeometry2D(); - if (!pGeometry->initialize(cfg)) { + if (!pGeometry->initialize(*cfg)) { mexErrMsgTxt("Geometry class not initialized. \n"); - delete xml; + delete cfg; delete pGeometry; return; } // If data is specified, check dimensions - if (nrhs >= 4 && !mex_is_scalar(prhs[3])) { + if (nrhs >= 4 && !mexIsScalar(prhs[3])) { if (pGeometry->getGridColCount() != mxGetN(prhs[3]) || pGeometry->getGridRowCount() != mxGetM(prhs[3])) { mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry. \n"); - delete xml; + delete cfg; delete pGeometry; return; } @@ -140,21 +137,18 @@ void astra_mex_data2d_create(int& nlhs, mxArray* plhs[], int& nrhs, const mxArra // Initialize data object pDataObject2D = new CFloat32VolumeData2D(pGeometry); delete pGeometry; - delete xml; + delete cfg; } else if (sDataType == "-sino") { // Read geometry if (!mxIsStruct(prhs[2])) { mexErrMsgTxt("Argument 3 is not a valid MATLAB struct.\n"); } - XMLDocument* xml = struct2XML("ProjectionGeometry", prhs[2]); - if (!xml) - return; - Config cfg; - cfg.self = xml->getRootNode(); + + Config* cfg = structToConfig("ProjectionGeometry", prhs[2]); // FIXME: Change how the base class is created. (This is duplicated // in 'change_geometry' and Projector2D.cpp.) - std::string type = cfg.self->getAttribute("type"); + std::string type = cfg->self->getAttribute("type"); CProjectionGeometry2D* pGeometry; if (type == "sparse_matrix") { pGeometry = new CSparseMatrixProjectionGeometry2D(); @@ -168,25 +162,25 @@ void astra_mex_data2d_create(int& nlhs, mxArray* plhs[], int& nrhs, const mxArra } else { pGeometry = new CParallelProjectionGeometry2D(); } - if (!pGeometry->initialize(cfg)) { + if (!pGeometry->initialize(*cfg)) { mexErrMsgTxt("Geometry class not initialized. \n"); delete pGeometry; - delete xml; + delete cfg; return; } // If data is specified, check dimensions - if (nrhs >= 4 && !mex_is_scalar(prhs[3])) { + if (nrhs >= 4 && !mexIsScalar(prhs[3])) { if (pGeometry->getDetectorCount() != mxGetN(prhs[3]) || pGeometry->getProjectionAngleCount() != mxGetM(prhs[3])) { mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry. \n"); delete pGeometry; - delete xml; + delete cfg; return; } } // Initialize data object pDataObject2D = new CFloat32ProjectionData2D(pGeometry); delete pGeometry; - delete xml; + delete cfg; } else { mexErrMsgTxt("Invalid datatype. Please specify '-vol' or '-sino'. \n"); @@ -210,7 +204,7 @@ void astra_mex_data2d_create(int& nlhs, mxArray* plhs[], int& nrhs, const mxArra // Store data if (nrhs >= 4) { // fill with scalar value - if (mex_is_scalar(prhs[3])) { + if (mexIsScalar(prhs[3])) { float32 fValue = (float32)mxGetScalar(prhs[3]); for (int i = 0; i < pDataObject2D->getSize(); ++i) { pDataObject2D->getData()[i] = fValue; @@ -294,7 +288,7 @@ void astra_mex_data2d_store(int nlhs, mxArray* plhs[], int nrhs, const mxArray* } int iDataID = (int)(mxGetScalar(prhs[1])); - if (!(mex_is_scalar(prhs[2]) || mxIsDouble(prhs[2]) || mxIsLogical(prhs[2]) || mxIsSingle(prhs[2]))) { + if (!(mexIsScalar(prhs[2]) || mxIsDouble(prhs[2]) || mxIsLogical(prhs[2]) || mxIsSingle(prhs[2]))) { mexErrMsgTxt("Data must be single, double or logical."); return; } @@ -312,7 +306,7 @@ void astra_mex_data2d_store(int nlhs, mxArray* plhs[], int nrhs, const mxArray* // step3: insert data // fill with scalar value - if (mex_is_scalar(prhs[2])) { + if (mexIsScalar(prhs[2])) { float32 fValue = (float32)mxGetScalar(prhs[2]); for (int i = 0; i < pDataObject->getSize(); ++i) { pDataObject->getData()[i] = fValue; @@ -373,7 +367,7 @@ void astra_mex_data2d_store(int nlhs, mxArray* plhs[], int nrhs, const mxArray* */ void astra_mex_data2d_get_geometry(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { - // step1: input + // parse input if (nrhs < 2) { mexErrMsgTxt("Not enough arguments. See the help document for a detailed argument list. \n"); return; @@ -384,7 +378,7 @@ void astra_mex_data2d_get_geometry(int nlhs, mxArray* plhs[], int nrhs, const mx } int iDataID = (int)(mxGetScalar(prhs[1])); - // step2: get data object + // fetch data object CFloat32Data2D* pDataObject = astra::CData2DManager::getSingleton().get(iDataID); if (!pDataObject || !pDataObject->isInitialized()) { mexErrMsgTxt("Data object not found or not initialized properly.\n"); @@ -395,11 +389,11 @@ void astra_mex_data2d_get_geometry(int nlhs, mxArray* plhs[], int nrhs, const mx if (1 <= nlhs) { if (pDataObject->getType() == CFloat32Data2D::PROJECTION) { CFloat32ProjectionData2D* pDataObject2 = dynamic_cast<CFloat32ProjectionData2D*>(pDataObject); - plhs[0] = createProjectionGeometryStruct(pDataObject2->getGeometry()); + plhs[0] = configToStruct(pDataObject2->getGeometry()->getConfiguration()); } else if (pDataObject->getType() == CFloat32Data2D::VOLUME) { CFloat32VolumeData2D* pDataObject2 = dynamic_cast<CFloat32VolumeData2D*>(pDataObject); - plhs[0] = createVolumeGeometryStruct(pDataObject2->getGeometry()); + plhs[0] = configToStruct(pDataObject2->getGeometry()->getConfiguration()); } } } @@ -440,12 +434,10 @@ void astra_mex_data2d_change_geometry(int nlhs, mxArray* plhs[], int nrhs, const if (!mxIsStruct(prhs[2])) { mexErrMsgTxt("Argument 3 is not a valid MATLAB struct.\n"); } - XMLDocument* xml = struct2XML("ProjectionGeometry", prhs[2]); - Config cfg; - cfg.self = xml->getRootNode(); + Config* cfg = structToConfig("ProjectionGeometry2D", prhs[2]); // FIXME: Change how the base class is created. (This is duplicated // in 'create' and Projector2D.cpp.) - std::string type = cfg.self->getAttribute("type"); + std::string type = cfg->self->getAttribute("type"); CProjectionGeometry2D* pGeometry; if (type == "sparse_matrix") { pGeometry = new CSparseMatrixProjectionGeometry2D(); @@ -459,24 +451,24 @@ void astra_mex_data2d_change_geometry(int nlhs, mxArray* plhs[], int nrhs, const } else { pGeometry = new CParallelProjectionGeometry2D(); } - if (!pGeometry->initialize(cfg)) { + if (!pGeometry->initialize(*cfg)) { mexErrMsgTxt("Geometry class not initialized. \n"); delete pGeometry; - delete xml; + delete cfg; return; } // If data is specified, check dimensions if (pGeometry->getDetectorCount() != pSinogram->getDetectorCount() || pGeometry->getProjectionAngleCount() != pSinogram->getAngleCount()) { mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry. \n"); delete pGeometry; - delete xml; + delete cfg; return; } // If ok, change geometry pSinogram->changeGeometry(pGeometry); delete pGeometry; - delete xml; + delete cfg; return; } @@ -490,27 +482,25 @@ void astra_mex_data2d_change_geometry(int nlhs, mxArray* plhs[], int nrhs, const if (!mxIsStruct(prhs[2])) { mexErrMsgTxt("Argument 3 is not a valid MATLAB struct.\n"); } - XMLDocument* xml = struct2XML(string("VolumeGeometry"), prhs[2]); - Config cfg; - cfg.self = xml->getRootNode(); + Config* cfg = structToConfig("VolumeGeometry2D", prhs[2]); CVolumeGeometry2D* pGeometry = new CVolumeGeometry2D(); - if (!pGeometry->initialize(cfg)) { + if (!pGeometry->initialize(*cfg)) { mexErrMsgTxt("Geometry class not initialized. \n"); - delete xml; + delete cfg; delete pGeometry; return; } // If data is specified, check dimensions if (pGeometry->getGridColCount() != pVolume->getWidth() || pGeometry->getGridRowCount() != pVolume->getHeight()) { mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry. \n"); - delete xml; + delete cfg; delete pGeometry; return; } // If ok, change geometry pVolume->changeGeometry(pGeometry); - delete xml; + delete cfg; delete pGeometry; } @@ -639,7 +629,7 @@ void mexFunction(int nlhs, mxArray* plhs[], // INPUT0: Mode string sMode = ""; if (1 <= nrhs) { - sMode = mex_util_get_string(prhs[0]); + sMode = mexToString(prhs[0]); } else { printHelp(); return; diff --git a/matlab/mex/astra_mex_data3d_c.cpp b/matlab/mex/astra_mex_data3d_c.cpp index 35a7512..0a3f85d 100644 --- a/matlab/mex/astra_mex_data3d_c.cpp +++ b/matlab/mex/astra_mex_data3d_c.cpp @@ -83,7 +83,7 @@ void astra_mex_data3d_create(int& nlhs, mxArray* plhs[], int& nrhs, const mxArra return; } - const string sDataType = mex_util_get_string(prhs[1]); + const string sDataType = mexToString(prhs[1]); // step2: Allocate data CFloat32Data3DMemory* pDataObject3D = @@ -152,7 +152,7 @@ void astra_mex_data3d_link(int& nlhs, mxArray* plhs[], int& nrhs, const mxArray* return; } - string sDataType = mex_util_get_string(prhs[1]); + string sDataType = mexToString(prhs[1]); // step2: Allocate data CFloat32Data3DMemory* pDataObject3D = @@ -266,48 +266,46 @@ void astra_mex_data3d_dimensions(int nlhs, mxArray* plhs[], int nrhs, const mxAr } //----------------------------------------------------------------------------------------- -/** - * [geom] = astra_mex_data3d('geometry', id); +/** geom = astra_mex_data3d('get_geometry', id); + * + * Fetch the geometry of a 3d data object stored in the astra-library. + * id: identifier of the 3d data object as stored in the astra-library. + * geom: MATLAB-struct containing information about the used geometry. */ -void astra_mex_data3d_geometry(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +void astra_mex_data3d_get_geometry(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { - //// Get input - //if (nrhs < 2) { - // mexErrMsgTxt("Not enough arguments. See the help document for a detailed argument list. \n"); - // return; - //} - //int iDid = (int)(mxGetScalar(prhs[1])); - - //// Get data object - //CFloat32Data3D* pData = CData3DManager::getSingleton().get(iDid); - //if (!pData) { - // mexErrMsgTxt("DataObject not valid. \n"); - // return; - //} - - //// Projection Data - //if (pData->getType() == CFloat32Data3D::PROJECTION) { - // CFloat32ProjectionData3D* pData2 = dynamic_cast<CFloat32ProjectionData3D*>(pData); - // CProjectionGeometry3D* pProjGeom = pData2->getGeometry(); - // XMLDocument* config = pProjGeom->toXML(); - - // if (1 <= nlhs) { - // plhs[0] = XML2struct(config); - // } - //} - //// Volume Data - //else if (pData->getType() == CFloat32Data3D::VOLUME) { - //// CFloat32VolumeData3D* pData2 = dynamic_cast<CFloat32VolumeData3D*>(pData); - //// CVolumeGeometry2D* pVolGeom = pData2->getGeometry2D(iSliceNr); - //// if (1 <= nlhs) { - //// plhs[0] = createVolumeGeometryStruct(pVolGeom); - //// } - //} - //// Error - //else { - // mexErrMsgTxt("Type not valid. \n"); - // return; - //} + // parse input + if (nrhs < 2) { + mexErrMsgTxt("Not enough arguments. See the help document for a detailed argument list. \n"); + return; + } + if (!mxIsDouble(prhs[1])) { + mexErrMsgTxt("Identifier should be a scalar value. \n"); + return; + } + int iDataID = (int)(mxGetScalar(prhs[1])); + + // fetch data object + CFloat32Data3D* pDataObject = astra::CData3DManager::getSingleton().get(iDataID); + if (!pDataObject || !pDataObject->isInitialized()) { + mexErrMsgTxt("Data object not found or not initialized properly.\n"); + return; + } + + // create output + if (1 <= nlhs) { + if (pDataObject->getType() == CFloat32Data3D::PROJECTION) { + CFloat32ProjectionData3DMemory* pDataObject2 = dynamic_cast<CFloat32ProjectionData3DMemory*>(pDataObject); + plhs[0] = configToStruct(pDataObject2->getGeometry()->getConfiguration()); + + } + else if (pDataObject->getType() == CFloat32Data3D::VOLUME) { + CFloat32VolumeData3DMemory* pDataObject2 = dynamic_cast<CFloat32VolumeData3DMemory*>(pDataObject); + plhs[0] = configToStruct(pDataObject2->getGeometry()->getConfiguration()); + } + } + + } //----------------------------------------------------------------------------------------- @@ -367,7 +365,7 @@ void mexFunction(int nlhs, mxArray* plhs[], // INPUT: Mode string sMode = ""; if (1 <= nrhs) { - sMode = mex_util_get_string(prhs[0]); + sMode = mexToString(prhs[0]); } else { printHelp(); return; @@ -395,8 +393,8 @@ void mexFunction(int nlhs, mxArray* plhs[], astra_mex_data3d_info(nlhs, plhs, nrhs, prhs); } else if (sMode == std::string("dimensions")) { astra_mex_data3d_dimensions(nlhs, plhs, nrhs, prhs); - } else if (sMode == std::string("geometry")) { - astra_mex_data3d_geometry(nlhs, plhs, nrhs, prhs); + } else if (sMode == std::string("get_geometry")) { + astra_mex_data3d_get_geometry(nlhs, plhs, nrhs, prhs); } else { printHelp(); } diff --git a/matlab/mex/astra_mex_matrix_c.cpp b/matlab/mex/astra_mex_matrix_c.cpp index 016566a..01ad08b 100644 --- a/matlab/mex/astra_mex_matrix_c.cpp +++ b/matlab/mex/astra_mex_matrix_c.cpp @@ -406,7 +406,7 @@ void mexFunction(int nlhs, mxArray* plhs[], // INPUT0: Mode string sMode = ""; if (1 <= nrhs) { - sMode = mex_util_get_string(prhs[0]); + sMode = mexToString(prhs[0]); } else { printHelp(); return; diff --git a/matlab/mex/astra_mex_projector3d_c.cpp b/matlab/mex/astra_mex_projector3d_c.cpp index 25980f9..5381cf6 100644 --- a/matlab/mex/astra_mex_projector3d_c.cpp +++ b/matlab/mex/astra_mex_projector3d_c.cpp @@ -65,16 +65,16 @@ void astra_mex_projector3d_create(int nlhs, mxArray* plhs[], int nrhs, const mxA } // turn MATLAB struct to an XML-based Config object - XMLDocument* xml = struct2XML("Projector3D", prhs[1]); - Config cfg; - cfg.self = xml->getRootNode(); + Config* cfg = structToConfig("Projector3D", prhs[1]); // create algorithm - CProjector3D* pProj = CProjector3DFactory::getSingleton().create(cfg); + CProjector3D* pProj = CProjector3DFactory::getSingleton().create(*cfg); if (pProj == NULL) { + delete cfg; mexErrMsgTxt("Error creating Projector3D. \n"); return; } + delete cfg; // store projector int iIndex = CProjector3DManager::getSingleton().store(pProj); @@ -135,16 +135,16 @@ void astra_mex_projector3d_get_projection_geometry(int nlhs, mxArray* plhs[], in } // step3: get projection_geometry and turn it into a MATLAB struct - //if (1 <= nlhs) { - // plhs[0] = createProjectionGeometryStruct(pProjector->getProjectionGeometry()); - //} + if (1 <= nlhs) { + plhs[0] = configToStruct(pProjector->getProjectionGeometry()->getConfiguration()); + } } //----------------------------------------------------------------------------------------- /** * [recon_geom] = astra_mex_projector3d('get_volume_geometry', pid); */ -void astra_mex_projector3d_get_reconstruction_geometry(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +void astra_mex_projector3d_get_volume_geometry(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { // step1: read input if (nrhs < 2) { @@ -161,9 +161,9 @@ void astra_mex_projector3d_get_reconstruction_geometry(int nlhs, mxArray* plhs[] } // step3: get projection_geometry and turn it into a MATLAB struct - //if (1 <= nlhs) { - // plhs[0] = createVolumeGeometryStruct(pProjector->getVolumeGeometry()); - //} + if (1 <= nlhs) { + plhs[0] = configToStruct(pProjector->getVolumeGeometry()->getConfiguration()); + } } //----------------------------------------------------------------------------------------- @@ -397,7 +397,7 @@ void mexFunction(int nlhs, mxArray* plhs[], // INPUT: Mode string sMode = ""; if (1 <= nrhs) { - sMode = mex_util_get_string(prhs[0]); + sMode = mexToString(prhs[0]); } else { printHelp(); return; @@ -413,7 +413,7 @@ void mexFunction(int nlhs, mxArray* plhs[], } else if (sMode == "get_projection_geometry") { astra_mex_projector3d_get_projection_geometry(nlhs, plhs, nrhs, prhs); } else if (sMode == "get_volume_geometry") { - astra_mex_projector3d_get_reconstruction_geometry(nlhs, plhs, nrhs, prhs); + astra_mex_projector3d_get_volume_geometry(nlhs, plhs, nrhs, prhs); } else if (sMode == "weights_single_ray") { astra_mex_projector_weights_single_ray(nlhs, plhs, nrhs, prhs); //} else if (sMode == "weights_projection") { diff --git a/matlab/mex/astra_mex_projector_c.cpp b/matlab/mex/astra_mex_projector_c.cpp index de73f07..58cd953 100644 --- a/matlab/mex/astra_mex_projector_c.cpp +++ b/matlab/mex/astra_mex_projector_c.cpp @@ -74,19 +74,16 @@ void astra_mex_projector_create(int nlhs, mxArray* plhs[], int nrhs, const mxArr // turn MATLAB struct to an XML-based Config object - XMLDocument* xml = struct2XML("Projector2D", prhs[1]); - Config cfg; - cfg.self = xml->getRootNode(); + Config* cfg = structToConfig("Projector2D", prhs[1]); // create algorithm - CProjector2D* pProj = CProjector2DFactory::getSingleton().create(cfg); + CProjector2D* pProj = CProjector2DFactory::getSingleton().create(*cfg); if (pProj == NULL) { - delete xml; + delete cfg; mexErrMsgTxt("Error creating projector. \n"); return; } - - delete xml; + delete cfg; // store projector iIndex = CProjector2DManager::getSingleton().store(pProj); @@ -162,7 +159,7 @@ void astra_mex_projector_projection_geometry(int nlhs, mxArray* plhs[], int nrhs // step3: get projection_geometry and turn it into a MATLAB struct if (1 <= nlhs) { - plhs[0] = createProjectionGeometryStruct(pProjector->getProjectionGeometry()); + plhs[0] = configToStruct(pProjector->getProjectionGeometry()->getConfiguration()); } } @@ -191,7 +188,8 @@ void astra_mex_projector_volume_geometry(int nlhs, mxArray* plhs[], int nrhs, co // step3: get projection_geometry and turn it into a MATLAB struct if (1 <= nlhs) { - plhs[0] = createVolumeGeometryStruct(pProjector->getVolumeGeometry()); + plhs[0] = configToStruct(pProjector->getVolumeGeometry()->getConfiguration()); + } } @@ -472,7 +470,7 @@ void mexFunction(int nlhs, mxArray* plhs[], // INPUT: Mode string sMode = ""; if (1 <= nrhs) { - sMode = mex_util_get_string(prhs[0]); + sMode = mexToString(prhs[0]); } else { printHelp(); return; diff --git a/matlab/mex/mexCopyDataHelpFunctions.cpp b/matlab/mex/mexCopyDataHelpFunctions.cpp index 6dfd4a6..80fb834 100644 --- a/matlab/mex/mexCopyDataHelpFunctions.cpp +++ b/matlab/mex/mexCopyDataHelpFunctions.cpp @@ -263,7 +263,7 @@ copyMexToCFloat32Array(const mxArray * const in, #pragma omp parallel { // fill with scalar value - if (mex_is_scalar(in)) { + if (mexIsScalar(in)) { astra::float32 fValue = 0.f; if (!mxIsEmpty(in)) { fValue = (astra::float32)mxGetScalar(in); diff --git a/matlab/mex/mexDataManagerHelpFunctions.cpp b/matlab/mex/mexDataManagerHelpFunctions.cpp index f9d971c..d482428 100644 --- a/matlab/mex/mexDataManagerHelpFunctions.cpp +++ b/matlab/mex/mexDataManagerHelpFunctions.cpp @@ -105,7 +105,7 @@ checkID(const astra::int32 & id, astra::CFloat32Data3DMemory *& pDataObj) bool checkDataType(const mxArray * const in) { - return (mex_is_scalar(in) || mxIsDouble(in) || mxIsSingle(in) || mxIsLogical(in)); + return (mexIsScalar(in) || mxIsDouble(in) || mxIsSingle(in) || mxIsLogical(in)); } //----------------------------------------------------------------------------------------- @@ -213,7 +213,7 @@ allocateDataObject(const std::string & sDataType, bool bUnshare = true; if (unshare) { - if (!mex_is_scalar(unshare)) + if (!mexIsScalar(unshare)) { mexErrMsgTxt("Argument 5 (read-only) must be scalar"); return NULL; @@ -225,7 +225,7 @@ allocateDataObject(const std::string & sDataType, mwIndex iZ = 0; if (zIndex) { - if (!mex_is_scalar(zIndex)) + if (!mexIsScalar(zIndex)) { mexErrMsgTxt("Argument 6 (Z) must be scalar"); return NULL; @@ -237,25 +237,19 @@ allocateDataObject(const std::string & sDataType, if (sDataType == "-vol") { // Read geometry - astra::XMLDocument* xml = struct2XML("VolumeGeometry", geometry); - if (!xml) { - return NULL; - } - astra::Config cfg; - cfg.self = xml->getRootNode(); - + astra::Config* cfg = structToConfig("VolumeGeometry3D", geometry); astra::CVolumeGeometry3D* pGeometry = new astra::CVolumeGeometry3D(); - if (!pGeometry->initialize(cfg)) + if (!pGeometry->initialize(*cfg)) { mexErrMsgTxt("Geometry class not initialized. \n"); delete pGeometry; - delete xml; + delete cfg; return NULL; } - delete xml; + delete cfg; // If data is specified, check dimensions - if (data && !mex_is_scalar(data)) + if (data && !mexIsScalar(data)) { if (! (zIndex ? checkDataSize(data, pGeometry, iZ) @@ -288,16 +282,10 @@ allocateDataObject(const std::string & sDataType, else if (sDataType == "-sino" || sDataType == "-proj3d" || sDataType == "-sinocone") { // Read geometry - astra::XMLDocument* xml = struct2XML("ProjectionGeometry", geometry); - if (!xml) { - return NULL; - } - astra::Config cfg; - cfg.self = xml->getRootNode(); - + 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"); + std::string type = cfg->self->getAttribute("type"); astra::CProjectionGeometry3D* pGeometry = 0; if (type == "parallel3d") { pGeometry = new astra::CParallelProjectionGeometry3D(); @@ -312,16 +300,16 @@ allocateDataObject(const std::string & sDataType, return NULL; } - if (!pGeometry->initialize(cfg)) { + if (!pGeometry->initialize(*cfg)) { mexErrMsgTxt("Geometry class not initialized. \n"); delete pGeometry; - delete xml; + delete cfg; return NULL; } - delete xml; + delete cfg; // If data is specified, check dimensions - if (data && !mex_is_scalar(data)) + if (data && !mexIsScalar(data)) { if (! (zIndex ? checkDataSize(data, pGeometry, iZ) diff --git a/matlab/mex/mexHelpFunctions.cpp b/matlab/mex/mexHelpFunctions.cpp index e919dd9..c0ac711 100644 --- a/matlab/mex/mexHelpFunctions.cpp +++ b/matlab/mex/mexHelpFunctions.cpp @@ -32,9 +32,11 @@ $Id$ */ #include "mexHelpFunctions.h" -#include "astra/SparseMatrixProjectionGeometry2D.h" -#include "astra/FanFlatVecProjectionGeometry2D.h" -#include "astra/AstraObjectManager.h" +#include <algorithm> +#include <boost/lexical_cast.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/classification.hpp> using namespace std; using namespace astra; @@ -42,387 +44,148 @@ using namespace astra; //----------------------------------------------------------------------------------------- // get string from matlab -std::string mex_util_get_string(const mxArray* pInput) +string mexToString(const mxArray* pInput) { - if (!mxIsChar(pInput)) { - return ""; + // is string? + if (mxIsChar(pInput)) { + mwSize iLength = mxGetNumberOfElements(pInput) + 1; + char* buf = new char[iLength]; + mxGetString(pInput, buf, iLength); + std::string res = std::string(buf); + delete[] buf; + return res; } - mwSize iLength = mxGetNumberOfElements(pInput) + 1; - char* buf = new char[iLength]; - mxGetString(pInput, buf, iLength); - std::string res = std::string(buf); - delete[] buf; - return res; + + // is scalar? + if (mxIsNumeric(pInput) && mxGetM(pInput)*mxGetN(pInput) == 1) { + return boost::lexical_cast<string>(mxGetScalar(pInput)); + } + + return ""; } //----------------------------------------------------------------------------------------- -// is option -bool isOption(std::list<std::string> lOptions, std::string sOption) +// return true if the argument is a scalar +bool mexIsScalar(const mxArray* pInput) { - return std::find(lOptions.begin(), lOptions.end(), sOption) != lOptions.end(); + return (mxIsNumeric(pInput) && mxGetM(pInput)*mxGetN(pInput) == 1); } //----------------------------------------------------------------------------------------- -// turn a matlab struct into a c++ map -std::map<std::string, mxArray*> parseStruct(const mxArray* pInput) +void get3DMatrixDims(const mxArray* x, mwSize *dims) { - std::map<std::string, mxArray*> res; - - // check type - if (!mxIsStruct(pInput)) { - mexErrMsgTxt("Input must be a struct."); - return res; + const mwSize* mdims = mxGetDimensions(x); + mwSize dimCount = mxGetNumberOfDimensions(x); + if (dimCount == 1) { + dims[0] = mdims[0]; + dims[1] = 1; + dims[2] = 1; + } else if (dimCount == 2) { + dims[0] = mdims[0]; + dims[1] = mdims[1]; + dims[2] = 1; + } else if (dimCount == 3) { + dims[0] = mdims[0]; + dims[1] = mdims[1]; + dims[2] = mdims[2]; + } else { + dims[0] = 0; + dims[1] = 0; + dims[2] = 0; } +} + + + + - // get field names - int nfields = mxGetNumberOfFields(pInput); - for (int i = 0; i < nfields; i++) { - std::string sFieldName = std::string(mxGetFieldNameByNumber(pInput, i)); - res[sFieldName] = mxGetFieldByNumber(pInput,0,i); - } - return res; -} //----------------------------------------------------------------------------------------- -// turn a c++ map into a matlab struct -mxArray* buildStruct(std::map<std::string, mxArray*> mInput) +// turn an std vector<float32> object to an mxArray +mxArray* vectorToMxArray(std::vector<astra::float32> mInput) { - mwSize dims[2] = {1, 1}; - mxArray* res = mxCreateStructArray(2,dims,0,0); - - for (std::map<std::string, mxArray*>::iterator it = mInput.begin(); it != mInput.end(); it++) { - mxAddField(res, (*it).first.c_str()); - mxSetField(res, 0, (*it).first.c_str(), (*it).second); + mxArray* res = mxCreateDoubleMatrix(1, mInput.size(), mxREAL); + double* pdData = mxGetPr(res); + for (unsigned int i = 0; i < mInput.size(); i++) { + pdData[i] = mInput[i]; } return res; } //----------------------------------------------------------------------------------------- -// parse projection geometry data -astra::CProjectionGeometry2D* parseProjectionGeometryStruct(const mxArray* prhs) +// turn a vector<vector<float32>> object to an mxArray +mxArray* vector2DToMxArray(std::vector<std::vector<astra::float32> > mInput) { - // parse struct - std::map<string, mxArray*> mStruct = parseStruct(prhs); - - // create projection geometry object - string type = mex_util_get_string(mStruct["type"]); - if (type == "parallel") { - - // detector_width - float32 fDetWidth = 1.0f; - mxArray* tmp = mStruct["detector_width"]; - if (tmp != NULL) { - fDetWidth = (float32)(mxGetScalar(tmp)); - } - - // detector_count - int iDetCount = 100; - tmp = mStruct["detector_count"]; - if (tmp != NULL) { - iDetCount = (int)(mxGetScalar(tmp)); - } - - // angles - float32* pfAngles; - int iAngleCount; - tmp = mStruct["projection_angles"]; - if (tmp != NULL) { - double* angleValues = mxGetPr(tmp); - iAngleCount = mxGetN(tmp) * mxGetM(tmp); - pfAngles = new float32[iAngleCount]; - for (int i = 0; i < iAngleCount; i++) { - pfAngles[i] = angleValues[i]; - } - } else { - mexErrMsgTxt("'angles' not specified, error."); - return NULL; - } - - // create projection geometry - return new astra::CParallelProjectionGeometry2D(iAngleCount, // number of projections - iDetCount, // number of detectors - fDetWidth, // width of the detectors - pfAngles); // angles array - } - - else if (type == "fanflat") { - - // detector_width - float32 fDetWidth = 1.0f; - mxArray* tmp = mStruct["detector_width"]; - if (tmp != NULL) { - fDetWidth = (float32)(mxGetScalar(tmp)); - } - - // detector_count - int iDetCount = 100; - tmp = mStruct["detector_count"]; - if (tmp != NULL) { - iDetCount = (int)(mxGetScalar(tmp)); - } - - // angles - float32* pfAngles; - int iAngleCount; - tmp = mStruct["projection_angles"]; - if (tmp != NULL) { - double* angleValues = mxGetPr(tmp); - iAngleCount = mxGetN(tmp) * mxGetM(tmp); - pfAngles = new float32[iAngleCount]; - for (int i = 0; i < iAngleCount; i++) { - pfAngles[i] = angleValues[i]; - } - } else { - mexErrMsgTxt("'angles' not specified, error."); - return NULL; - } - - // origin_source_dist - int iDistOriginSource = 100; - tmp = mStruct["origin_source_dist"]; - if (tmp != NULL) { - iDistOriginSource = (int)(mxGetScalar(tmp)); - } + unsigned int sizex = mInput.size(); + if (sizex == 0) return mxCreateString("empty"); + unsigned int sizey = mInput[0].size(); - // origin_det_dist - int iDistOriginDet = 100; - tmp = mStruct["origin_det_dist"]; - if (tmp != NULL) { - iDistOriginDet = (int)(mxGetScalar(tmp)); + mxArray* res = mxCreateDoubleMatrix(sizex, sizey, mxREAL); + double* pdData = mxGetPr(res); + for (unsigned int i = 0; i < sizex; i++) { + for (unsigned int j = 0; j < sizey && j < mInput[i].size(); j++) { + pdData[j*sizex+i] = mInput[i][j]; } - - // create projection geometry - return new astra::CFanFlatProjectionGeometry2D(iAngleCount, // number of projections - iDetCount, // number of detectors - fDetWidth, // width of the detectors - pfAngles, // angles array - iDistOriginSource, // distance origin source - iDistOriginDet); // distance origin detector - } - - else { - mexPrintf("Only parallel and fanflat projection geometry implemented."); - return NULL; } + return res; } //----------------------------------------------------------------------------------------- -// create projection geometry data -mxArray* createProjectionGeometryStruct(astra::CProjectionGeometry2D* _pProjGeom) +// turn a boost::any object to an mxArray +mxArray* anyToMxArray(boost::any _any) { - // temporary map to store the data for the MATLAB struct - std::map<std::string, mxArray*> mGeometryInfo; - - // detectorCount - mGeometryInfo["DetectorCount"] = mxCreateDoubleScalar(_pProjGeom->getDetectorCount()); - - if (!_pProjGeom->isOfType("fanflat_vec")) { - // detectorWidth - mGeometryInfo["DetectorWidth"] = mxCreateDoubleScalar(_pProjGeom->getDetectorWidth()); - - // pfProjectionAngles - mxArray* pAngles = mxCreateDoubleMatrix(1, _pProjGeom->getProjectionAngleCount(), mxREAL); - double* out = mxGetPr(pAngles); - for (int i = 0; i < _pProjGeom->getProjectionAngleCount(); i++) { - out[i] = _pProjGeom->getProjectionAngle(i); - } - mGeometryInfo["ProjectionAngles"] = pAngles; - } - else { - astra::CFanFlatVecProjectionGeometry2D* pVecGeom = dynamic_cast<astra::CFanFlatVecProjectionGeometry2D*>(_pProjGeom); - mxArray* pVectors = mxCreateDoubleMatrix(1, pVecGeom->getProjectionAngleCount()*6, mxREAL); - double* out = mxGetPr(pVectors); - int iDetCount = pVecGeom->getDetectorCount(); - for (int i = 0; i < pVecGeom->getProjectionAngleCount(); i++) { - const SFanProjection* p = &pVecGeom->getProjectionVectors()[i]; - out[6*i + 0] = p->fSrcX; - out[6*i + 1] = p->fSrcY; - out[6*i + 2] = p->fDetSX + 0.5f*iDetCount*p->fDetUX; - out[6*i + 3] = p->fDetSY + 0.5f*iDetCount*p->fDetUY; - out[6*i + 4] = p->fDetUX; - out[6*i + 5] = p->fDetUY; - } - mGeometryInfo["Vectors"] = pVectors; + if (_any.type() == typeid(std::string)) { + std::string str = boost::any_cast<std::string>(_any); + return mxCreateString(str.c_str()); } - - // parallel specific options - if (_pProjGeom->isOfType("parallel")) { - // type - mGeometryInfo["type"] = mxCreateString("parallel"); + if (_any.type() == typeid(int)) { + return mxCreateDoubleScalar(boost::any_cast<int>(_any)); } - // fanflat specific options - else if (_pProjGeom->isOfType("fanflat")) { - astra::CFanFlatProjectionGeometry2D* pFanFlatGeom = dynamic_cast<astra::CFanFlatProjectionGeometry2D*>(_pProjGeom); - // detectorCount - mGeometryInfo["DistanceOriginSource"] = mxCreateDoubleScalar(pFanFlatGeom->getOriginSourceDistance()); - // detectorWidth - mGeometryInfo["DistanceOriginDetector"] = mxCreateDoubleScalar(pFanFlatGeom->getOriginDetectorDistance()); - // type - mGeometryInfo["type"] = mxCreateString("fanflat"); + if (_any.type() == typeid(float32)) { + return mxCreateDoubleScalar(boost::any_cast<float32>(_any)); } - else if (_pProjGeom->isOfType("sparse_matrix")) { - astra::CSparseMatrixProjectionGeometry2D* pSparseMatrixGeom = dynamic_cast<astra::CSparseMatrixProjectionGeometry2D*>(_pProjGeom); - mGeometryInfo["type"] = mxCreateString("sparse_matrix"); - mGeometryInfo["MatrixID"] = mxCreateDoubleScalar(CMatrixManager::getSingleton().getIndex(pSparseMatrixGeom->getMatrix())); + if (_any.type() == typeid(std::vector<astra::float32>)) { + return vectorToMxArray(boost::any_cast<std::vector<float32> >(_any)); } - else if(_pProjGeom->isOfType("fanflat_vec")) { - mGeometryInfo["type"] = mxCreateString("fanflat_vec"); + if (_any.type() == typeid(std::vector<std::vector<astra::float32> >)) { + return vector2DToMxArray(boost::any_cast<std::vector<std::vector<float32> > >(_any)); } - - // build and return the MATLAB struct - return buildStruct(mGeometryInfo); + return NULL; } -//----------------------------------------------------------------------------------------- -// parse reconstruction geometry data -astra::CVolumeGeometry2D* parseVolumeGeometryStruct(const mxArray* prhs) -{ - // parse struct - std::map<string, mxArray*> mStruct = parseStruct(prhs); - - std::map<string, mxArray*> mOptions = parseStruct(mStruct["option"]); - - // GridColCount - int iWindowColCount = 128; - mxArray* tmp = mStruct["GridColCount"]; - if (tmp != NULL) { - iWindowColCount = (int)(mxGetScalar(tmp)); - } - - // GridRowCount - int iWindowRowCount = 128; - tmp = mStruct["GridRowCount"]; - if (tmp != NULL) { - iWindowRowCount = (int)(mxGetScalar(tmp)); - } - // WindowMinX - float32 fWindowMinX = - iWindowColCount / 2; - tmp = mOptions["WindowMinX"]; - if (tmp != NULL) { - fWindowMinX = (float32)(mxGetScalar(tmp)); - } - - // WindowMaxX - float32 fWindowMaxX = iWindowColCount / 2; - tmp = mOptions["WindowMaxX"]; - if (tmp != NULL) { - fWindowMaxX = (float32)(mxGetScalar(tmp)); - } - - // WindowMinY - float32 fWindowMinY = - iWindowRowCount / 2; - tmp = mOptions["WindowMinY"]; - if (tmp != NULL) { - fWindowMinY = (float32)(mxGetScalar(tmp)); - } - - // WindowMaxX - float32 fWindowMaxY = iWindowRowCount / 2; - tmp = mOptions["WindowMaxY"]; - if (tmp != NULL) { - fWindowMaxY = (float32)(mxGetScalar(tmp)); - } - - // create and return reconstruction geometry - return new astra::CVolumeGeometry2D(iWindowColCount, iWindowRowCount, - fWindowMinX, fWindowMinY, - fWindowMaxX, fWindowMaxY); -} -//----------------------------------------------------------------------------------------- -// create reconstruction geometry data -mxArray* createVolumeGeometryStruct(astra::CVolumeGeometry2D* _pReconGeom) -{ - // temporary map to store the data for the MATLAB struct - std::map<std::string, mxArray*> mGeometryInfo; - // fill up map - mGeometryInfo["GridColCount"] = mxCreateDoubleScalar(_pReconGeom->getGridColCount()); - mGeometryInfo["GridRowCount"] = mxCreateDoubleScalar(_pReconGeom->getGridRowCount()); - std::map<std::string, mxArray*> mGeometryOptions; - mGeometryOptions["WindowMinX"] = mxCreateDoubleScalar(_pReconGeom->getWindowMinX()); - mGeometryOptions["WindowMaxX"] = mxCreateDoubleScalar(_pReconGeom->getWindowMaxX()); - mGeometryOptions["WindowMinY"] = mxCreateDoubleScalar(_pReconGeom->getWindowMinY()); - mGeometryOptions["WindowMaxY"] = mxCreateDoubleScalar(_pReconGeom->getWindowMaxY()); - mGeometryInfo["option"] = buildStruct(mGeometryOptions); - // build and return the MATLAB struct - return buildStruct(mGeometryInfo); -} //----------------------------------------------------------------------------------------- -string matlab2string(const mxArray* pField) +// turn a MATLAB struct into a Config object +Config* structToConfig(string rootname, const mxArray* pStruct) { - // is string? - if (mxIsChar(pField)) { - return mex_util_get_string(pField); - } - - // is scalar? - if (mxIsNumeric(pField) && mxGetM(pField)*mxGetN(pField) == 1) { - return boost::lexical_cast<string>(mxGetScalar(pField)); + if (!mxIsStruct(pStruct)) { + mexErrMsgTxt("Input must be a struct."); + return NULL; } - return ""; -} - -//----------------------------------------------------------------------------------------- -// Options struct to xml node -bool readOptions(XMLNode* node, const mxArray* pOptionStruct) -{ - // loop all fields - int nfields = mxGetNumberOfFields(pOptionStruct); - for (int i = 0; i < nfields; i++) { - std::string sFieldName = std::string(mxGetFieldNameByNumber(pOptionStruct, i)); - const mxArray* pField = mxGetFieldByNumber(pOptionStruct, 0, i); - - if (node->hasOption(sFieldName)) { - mexErrMsgTxt("Duplicate option"); - return false; - } - - // string or scalar - if (mxIsChar(pField) || mex_is_scalar(pField)) { - string sValue = matlab2string(pField); - node->addOption(sFieldName, sValue); - } else - // numerical array - if (mxIsNumeric(pField) && mxGetM(pField)*mxGetN(pField) > 1) { - if (!mxIsDouble(pField)) { - mexErrMsgTxt("Numeric input must be double."); - return false; - } + // create the document + Config* cfg = new Config(); + cfg->initialize(rootname); - XMLNode* listbase = node->addChildNode("Option"); - listbase->addAttribute("key", sFieldName); - listbase->addAttribute("listsize", mxGetM(pField)*mxGetN(pField)); - double* pdValues = mxGetPr(pField); - int index = 0; - for (unsigned int row = 0; row < mxGetM(pField); row++) { - for (unsigned int col = 0; col < mxGetN(pField); col++) { - XMLNode* item = listbase->addChildNode("ListItem"); - item->addAttribute("index", index); - item->addAttribute("value", pdValues[col*mxGetM(pField)+row]); - index++; - delete item; - } - } - delete listbase; - } else { - mexErrMsgTxt("Unsupported option type"); - return false; - } + // read the struct + bool ret = structToXMLNode(cfg->self, pStruct); + if (!ret) { + delete cfg; + mexErrMsgTxt("Error parsing struct."); + return NULL; } - return true; + return cfg; } //----------------------------------------------------------------------------------------- -// struct to xml node -bool readStruct(XMLNode* root, const mxArray* pStruct) +bool structToXMLNode(XMLNode* node, const mxArray* pStruct) { // loop all fields int nfields = mxGetNumberOfFields(pStruct); @@ -434,27 +197,27 @@ bool readStruct(XMLNode* root, const mxArray* pStruct) // string if (mxIsChar(pField)) { - string sValue = matlab2string(pField); + string sValue = mexToString(pField); if (sFieldName == "type") { - root->addAttribute("type", sValue); + node->addAttribute("type", sValue); } else { - delete root->addChildNode(sFieldName, sValue); + delete node->addChildNode(sFieldName, sValue); } } // scalar - if (mex_is_scalar(pField)) { - string sValue = matlab2string(pField); - delete root->addChildNode(sFieldName, sValue); + else if (mxIsNumeric(pField) && mxGetM(pField)*mxGetN(pField) == 1) { + string sValue = mexToString(pField); + delete node->addChildNode(sFieldName, sValue); } // numerical array - if (mxIsNumeric(pField) && mxGetM(pField)*mxGetN(pField) > 1) { + else if (mxIsNumeric(pField) && mxGetM(pField)*mxGetN(pField) > 1) { if (!mxIsDouble(pField)) { mexErrMsgTxt("Numeric input must be double."); return false; } - XMLNode* listbase = root->addChildNode(sFieldName); + XMLNode* listbase = node->addChildNode(sFieldName); listbase->addAttribute("listsize", mxGetM(pField)*mxGetN(pField)); double* pdValues = mxGetPr(pField); int index = 0; @@ -470,16 +233,15 @@ bool readStruct(XMLNode* root, const mxArray* pStruct) delete listbase; } - // not castable to a single string - if (mxIsStruct(pField)) { + else if (mxIsStruct(pField)) { if (sFieldName == "options" || sFieldName == "option" || sFieldName == "Options" || sFieldName == "Option") { - bool ret = readOptions(root, pField); + bool ret = optionsToXMLNode(node, pField); if (!ret) return false; } else { - XMLNode* newNode = root->addChildNode(sFieldName); - bool ret = readStruct(newNode, pField); + XMLNode* newNode = node->addChildNode(sFieldName); + bool ret = structToXMLNode(newNode, pField); delete newNode; if (!ret) return false; @@ -490,109 +252,101 @@ bool readStruct(XMLNode* root, const mxArray* pStruct) return true; } +//----------------------------------------------------------------------------------------- +// Options struct to xml node +bool optionsToXMLNode(XMLNode* node, const mxArray* pOptionStruct) +{ + // loop all fields + int nfields = mxGetNumberOfFields(pOptionStruct); + for (int i = 0; i < nfields; i++) { + std::string sFieldName = std::string(mxGetFieldNameByNumber(pOptionStruct, i)); + const mxArray* pField = mxGetFieldByNumber(pOptionStruct, 0, i); + if (node->hasOption(sFieldName)) { + mexErrMsgTxt("Duplicate option"); + return false; + } + + // string or scalar + if (mxIsChar(pField) || mexIsScalar(pField)) { + string sValue = mexToString(pField); + node->addOption(sFieldName, sValue); + } + // numerical array + else if (mxIsNumeric(pField) && mxGetM(pField)*mxGetN(pField) > 1) { + if (!mxIsDouble(pField)) { + mexErrMsgTxt("Numeric input must be double."); + return false; + } + + XMLNode* listbase = node->addChildNode("Option"); + listbase->addAttribute("key", sFieldName); + listbase->addAttribute("listsize", mxGetM(pField)*mxGetN(pField)); + double* pdValues = mxGetPr(pField); + int index = 0; + for (unsigned int row = 0; row < mxGetM(pField); row++) { + for (unsigned int col = 0; col < mxGetN(pField); col++) { + XMLNode* item = listbase->addChildNode("ListItem"); + item->addAttribute("index", index); + item->addAttribute("value", pdValues[col*mxGetM(pField)+row]); + index++; + delete item; + } + } + delete listbase; + } else { + mexErrMsgTxt("Unsupported option type"); + return false; + } + } + return true; +} //----------------------------------------------------------------------------------------- -// turn a MATLAB struct into an XML Document -XMLDocument* struct2XML(string rootname, const mxArray* pStruct) +// turn a matlab struct into a c++ map +std::map<std::string, mxArray*> parseStruct(const mxArray* pInput) { - if (!mxIsStruct(pStruct)) { + std::map<std::string, mxArray*> res; + + // check type + if (!mxIsStruct(pInput)) { mexErrMsgTxt("Input must be a struct."); - return NULL; + return res; } - // create the document - XMLDocument* doc = XMLDocument::createDocument(rootname); - XMLNode* rootnode = doc->getRootNode(); + // get field names + int nfields = mxGetNumberOfFields(pInput); + for (int i = 0; i < nfields; i++) { + std::string sFieldName = std::string(mxGetFieldNameByNumber(pInput, i)); + res[sFieldName] = mxGetFieldByNumber(pInput,0,i); + } + return res; +} + + - // read the struct - bool ret = readStruct(rootnode, pStruct); - //doc->getRootNode()->print(); - delete rootnode; - if (!ret) { - delete doc; - doc = 0; - } - return doc; -} -//----------------------------------------------------------------------------------------- -// turn an std vector<float32> object to an mxArray -mxArray* vectorToMxArray(std::vector<astra::float32> mInput) -{ - mxArray* res = mxCreateDoubleMatrix(1, mInput.size(), mxREAL); - double* pdData = mxGetPr(res); - for (unsigned int i = 0; i < mInput.size(); i++) { - pdData[i] = mInput[i]; - } - return res; -} -//----------------------------------------------------------------------------------------- -// turn a vector<vector<float32>> object to an mxArray -mxArray* vector2DToMxArray(std::vector<std::vector<astra::float32> > mInput) -{ - unsigned int sizex = mInput.size(); - if (sizex == 0) return mxCreateString("empty"); - unsigned int sizey = mInput[0].size(); - mxArray* res = mxCreateDoubleMatrix(sizex, sizey, mxREAL); - double* pdData = mxGetPr(res); - for (unsigned int i = 0; i < sizex; i++) { - for (unsigned int j = 0; j < sizey && j < mInput[i].size(); j++) { - pdData[j*sizex+i] = mInput[i][j]; - } - } - return res; -} -//----------------------------------------------------------------------------------------- -// turn a boost::any object to an mxArray -mxArray* anyToMxArray(boost::any _any) -{ - if (_any.type() == typeid(std::string)) { - std::string str = boost::any_cast<std::string>(_any); - return mxCreateString(str.c_str()); - } - if (_any.type() == typeid(int)) { - return mxCreateDoubleScalar(boost::any_cast<int>(_any)); - } - if (_any.type() == typeid(float32)) { - return mxCreateDoubleScalar(boost::any_cast<float32>(_any)); - } - if (_any.type() == typeid(std::vector<astra::float32>)) { - return vectorToMxArray(boost::any_cast<std::vector<float32> >(_any)); - } - if (_any.type() == typeid(std::vector<std::vector<astra::float32> >)) { - return vector2DToMxArray(boost::any_cast<std::vector<std::vector<float32> > >(_any)); - } - return NULL; -} -//----------------------------------------------------------------------------------------- -// return true ig the argument is a scalar -bool mex_is_scalar(const mxArray* pInput) -{ - return (mxIsNumeric(pInput) && mxGetM(pInput)*mxGetN(pInput) == 1); -} //----------------------------------------------------------------------------------------- -mxArray* XML2struct(astra::XMLDocument* xml) +// turn a Config object into a MATLAB struct +mxArray* configToStruct(astra::Config* cfg) { - XMLNode* node = xml->getRootNode(); - mxArray* str = XMLNode2struct(xml->getRootNode()); - delete node; - return str; + return XMLNodeToStruct(cfg->self); } //----------------------------------------------------------------------------------------- -mxArray* XMLNode2struct(astra::XMLNode* node) +mxArray* XMLNodeToStruct(astra::XMLNode* node) { - std::map<std::string, mxArray*> mList; + std::map<std::string, mxArray*> mList; + std::map<std::string, mxArray*> mOptions; // type_attribute if (node->hasAttribute("type")) { @@ -602,41 +356,103 @@ mxArray* XMLNode2struct(astra::XMLNode* node) list<XMLNode*> nodes = node->getNodes(); for (list<XMLNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) { XMLNode* subnode = (*it); - // list - if (subnode->hasAttribute("listsize")) { - cout << "lkmdsqldqsjkl" << endl; - cout << " " << node->getContentNumericalArray().size() << endl; - mList[subnode->getName()] = vectorToMxArray(node->getContentNumericalArray()); + + // option + if (subnode->getName() == "Option") { + mOptions[subnode->getAttribute("key")] = stringToMxArray(subnode->getAttribute("value")); } - // string + + // regular content else { - mList[subnode->getName()] = mxCreateString(subnode->getContent().c_str()); + mList[subnode->getName()] = stringToMxArray(subnode->getContent()); } delete subnode; } + if (mOptions.size() > 0) mList["options"] = buildStruct(mOptions); return buildStruct(mList); } -void get3DMatrixDims(const mxArray* x, mwSize *dims) +//----------------------------------------------------------------------------------------- +mxArray* stringToMxArray(std::string input) { - const mwSize* mdims = mxGetDimensions(x); - mwSize dimCount = mxGetNumberOfDimensions(x); - if (dimCount == 1) { - dims[0] = mdims[0]; - dims[1] = 1; - dims[2] = 1; - } else if (dimCount == 2) { - dims[0] = mdims[0]; - dims[1] = mdims[1]; - dims[2] = 1; - } else if (dimCount == 3) { - dims[0] = mdims[0]; - dims[1] = mdims[1]; - dims[2] = mdims[2]; - } else { - dims[0] = 0; - dims[1] = 0; - dims[2] = 0; + // matrix + if (input.find(';') != std::string::npos) { + + // split rows + std::vector<std::string> row_strings; + std::vector<std::string> col_strings; + boost::split(row_strings, input, boost::is_any_of(";")); + boost::split(col_strings, row_strings[0], boost::is_any_of(",")); + + // get dimensions + int rows = row_strings.size(); + int cols = col_strings.size(); + + // init matrix + mxArray* pMatrix = mxCreateDoubleMatrix(rows, cols, mxREAL); + double* out = mxGetPr(pMatrix); + + // loop elements + for (unsigned int row = 0; row < rows; row++) { + boost::split(col_strings, row_strings[row], boost::is_any_of(",")); + // check size + for (unsigned int col = 0; col < col_strings.size(); col++) { + out[col*rows + row] = boost::lexical_cast<float32>(col_strings[col]); + } + } + return pMatrix; } -} + + // vector + if (input.find(',') != std::string::npos) { + + // split + std::vector<std::string> items; + boost::split(items, input, boost::is_any_of(",")); + + // init matrix + mxArray* pVector = mxCreateDoubleMatrix(1, items.size(), mxREAL); + double* out = mxGetPr(pVector); + + // loop elements + for (unsigned int i = 0; i < items.size(); i++) { + out[i] = boost::lexical_cast<float32>(items[i]); + } + return pVector; + } + + // number + char* end; + double content = ::strtod(input.c_str(), &end); + bool isnumber = !*end; + if (isnumber) { + return mxCreateDoubleScalar(content); + } + + // string + return mxCreateString(input.c_str()); +} +//----------------------------------------------------------------------------------------- +// turn a c++ map into a matlab struct +mxArray* buildStruct(std::map<std::string, mxArray*> mInput) +{ + mwSize dims[2] = {1, 1}; + mxArray* res = mxCreateStructArray(2,dims,0,0); + + for (std::map<std::string, mxArray*>::iterator it = mInput.begin(); it != mInput.end(); it++) { + mxAddField(res, (*it).first.c_str()); + mxSetField(res, 0, (*it).first.c_str(), (*it).second); + } + return res; +} + + + + + + + + + + diff --git a/matlab/mex/mexHelpFunctions.h b/matlab/mex/mexHelpFunctions.h index 84372ba..f9ffcf2 100644 --- a/matlab/mex/mexHelpFunctions.h +++ b/matlab/mex/mexHelpFunctions.h @@ -43,34 +43,31 @@ $Id$ #include "astra/Globals.h" #include "astra/Utilities.h" -#include "astra/ParallelProjectionGeometry2D.h" -#include "astra/FanFlatProjectionGeometry2D.h" -#include "astra/VolumeGeometry2D.h" - +#include "astra/Config.h" #include "astra/XMLDocument.h" #include "astra/XMLNode.h" -std::string mex_util_get_string(const mxArray* pInput); -bool isOption(std::list<std::string> lOptions, std::string sOption); - -bool mex_is_scalar(const mxArray* pInput); +// utility functions +string mexToString(const mxArray* pInput); +bool mexIsScalar(const mxArray* pInput); +void get3DMatrixDims(const mxArray* x, mwSize *dims); -std::map<std::string, mxArray*> parseStruct(const mxArray* pInput); -mxArray* buildStruct(std::map<std::string, mxArray*> mInput); +// convert boost::any into a MALTAB object mxArray* vectorToMxArray(std::vector<astra::float32> mInput); - mxArray* anyToMxArray(boost::any _any); -astra::CProjectionGeometry2D* parseProjectionGeometryStruct(const mxArray*); -mxArray* createProjectionGeometryStruct(astra::CProjectionGeometry2D*); -astra::CVolumeGeometry2D* parseVolumeGeometryStruct(const mxArray*); -mxArray* createVolumeGeometryStruct(astra::CVolumeGeometry2D* _pReconGeom); +// turn a MATLAB struct into a Config object +astra::Config* structToConfig(string rootname, const mxArray* pStruct); +bool structToXMLNode(astra::XMLNode* node, const mxArray* pStruct); +bool optionsToXMLNode(astra::XMLNode* node, const mxArray* pOptionStruct); +std::map<std::string, mxArray*> parseStruct(const mxArray* pInput); -astra::XMLDocument* struct2XML(string rootname, const mxArray* pStruct); +// turn a Config object into a MATLAB struct +mxArray* configToStruct(astra::Config* cfg); +mxArray* XMLNodeToStruct(astra::XMLNode* xml); +mxArray* stringToMxArray(std::string input); +mxArray* buildStruct(std::map<std::string, mxArray*> mInput); -mxArray* XML2struct(astra::XMLDocument* xml); -mxArray* XMLNode2struct(astra::XMLNode* xml); -void get3DMatrixDims(const mxArray* x, mwSize *dims); #endif diff --git a/src/ConeProjectionGeometry3D.cpp b/src/ConeProjectionGeometry3D.cpp index e6999df..eb9adcf 100644 --- a/src/ConeProjectionGeometry3D.cpp +++ b/src/ConeProjectionGeometry3D.cpp @@ -186,17 +186,22 @@ bool CConeProjectionGeometry3D::isOfType(const std::string& _sType) const } //---------------------------------------------------------------------------------------- -void CConeProjectionGeometry3D::toXML(XMLNode* _sNode) const +// Get the configuration object +Config* CConeProjectionGeometry3D::getConfiguration() const { - _sNode->addAttribute("type", "cone"); - _sNode->addChildNode("DetectorSpacingX", m_fDetectorSpacingX); - _sNode->addChildNode("DetectorSpacingY", m_fDetectorSpacingY); - _sNode->addChildNode("DetectorRowCount", m_iDetectorRowCount); - _sNode->addChildNode("DetectorColCount", m_iDetectorColCount); - _sNode->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); - _sNode->addChildNode("DistanceOriginDetector", m_fOriginDetectorDistance); - _sNode->addChildNode("DistanceOriginSource", m_fOriginSourceDistance); + Config* cfg = new Config(); + cfg->initialize("ProjectionGeometry3D"); + cfg->self->addAttribute("type", "cone"); + cfg->self->addChildNode("DetectorSpacingX", m_fDetectorSpacingX); + cfg->self->addChildNode("DetectorSpacingY", m_fDetectorSpacingY); + cfg->self->addChildNode("DetectorRowCount", m_iDetectorRowCount); + cfg->self->addChildNode("DetectorColCount", m_iDetectorColCount); + cfg->self->addChildNode("DistanceOriginDetector", m_fOriginDetectorDistance); + cfg->self->addChildNode("DistanceOriginSource", m_fOriginSourceDistance); + cfg->self->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); + return cfg; } + //---------------------------------------------------------------------------------------- CVector3D CConeProjectionGeometry3D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const diff --git a/src/ConeVecProjectionGeometry3D.cpp b/src/ConeVecProjectionGeometry3D.cpp index cf8f76d..a4bd22d 100644 --- a/src/ConeVecProjectionGeometry3D.cpp +++ b/src/ConeVecProjectionGeometry3D.cpp @@ -198,18 +198,42 @@ bool CConeVecProjectionGeometry3D::isEqual(const CProjectionGeometry3D * _pGeom2 // is of type bool CConeVecProjectionGeometry3D::isOfType(const std::string& _sType) const { - return (_sType == "cone3d_vec"); + return (_sType == "cone_vec"); } //---------------------------------------------------------------------------------------- -void CConeVecProjectionGeometry3D::toXML(XMLNode* _sNode) const +// Get the configuration object +Config* CConeVecProjectionGeometry3D::getConfiguration() const { - _sNode->addAttribute("type","cone3d_vec"); - _sNode->addChildNode("DetectorRowCount", m_iDetectorRowCount); - _sNode->addChildNode("DetectorColCount", m_iDetectorColCount); - // TODO: - //_sNode->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); + Config* cfg = new Config(); + cfg->initialize("ProjectionGeometry3D"); + + cfg->self->addAttribute("type", "cone"); + cfg->self->addChildNode("DetectorRowCount", m_iDetectorRowCount); + cfg->self->addChildNode("DetectorColCount", m_iDetectorColCount); + + std::string vectors = ""; + for (int i = 0; i < m_iProjectionAngleCount; ++i) { + SConeProjection& p = m_pProjectionAngles[i]; + vectors += boost::lexical_cast<string>(p.fSrcX) + ","; + vectors += boost::lexical_cast<string>(p.fSrcY) + ","; + vectors += boost::lexical_cast<string>(p.fSrcZ) + ","; + vectors += boost::lexical_cast<string>(p.fDetSX + 0.5f*m_iDetectorRowCount*p.fDetUX + 0.5f*m_iDetectorColCount*p.fDetVX) + ","; + vectors += boost::lexical_cast<string>(p.fDetSY + 0.5f*m_iDetectorRowCount*p.fDetUY + 0.5f*m_iDetectorColCount*p.fDetVY) + ","; + vectors += boost::lexical_cast<string>(p.fDetSZ + 0.5f*m_iDetectorRowCount*p.fDetUZ + 0.5f*m_iDetectorColCount*p.fDetVZ) + ","; + vectors += boost::lexical_cast<string>(p.fDetUX) + ","; + vectors += boost::lexical_cast<string>(p.fDetUY) + ","; + vectors += boost::lexical_cast<string>(p.fDetUZ) + ","; + vectors += boost::lexical_cast<string>(p.fDetVX) + ","; + vectors += boost::lexical_cast<string>(p.fDetVY) + ","; + vectors += boost::lexical_cast<string>(p.fDetVZ); + if (i < m_iProjectionAngleCount-1) vectors += ';'; + } + cfg->self->addChildNode("Vectors", vectors); + + return cfg; } +//---------------------------------------------------------------------------------------- CVector3D CConeVecProjectionGeometry3D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const { diff --git a/src/Config.cpp b/src/Config.cpp index 3a3cb53..653935e 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -54,12 +54,24 @@ Config::Config(XMLNode* _self) self = _self; } +//----------------------------------------------------------------------------- Config::~Config() { delete self; self = 0; } +//----------------------------------------------------------------------------- +void Config::initialize(std::string rootname) +{ + if (self == 0) { + XMLDocument* doc = XMLDocument::createDocument(rootname); + self = doc->getRootNode(); + } +} + + +//----------------------------------------------------------------------------- template <class T> ConfigStackCheck<T>::ConfigStackCheck(const char *_name, T* _obj, const Config& _cfg) : object(_obj), cfg(&_cfg), name(_name) diff --git a/src/FanFlatProjectionGeometry2D.cpp b/src/FanFlatProjectionGeometry2D.cpp index bfc7fa9..d757f18 100644 --- a/src/FanFlatProjectionGeometry2D.cpp +++ b/src/FanFlatProjectionGeometry2D.cpp @@ -204,6 +204,20 @@ CVector3D CFanFlatProjectionGeometry2D::getProjectionDirection(int _iProjectionI } //---------------------------------------------------------------------------------------- +// Get the configuration object +Config* CFanFlatProjectionGeometry2D::getConfiguration() const +{ + Config* cfg = new Config(); + cfg->initialize("ProjectionGeometry2D"); + cfg->self->addAttribute("type", "fanflat"); + cfg->self->addChildNode("DetectorCount", getDetectorCount()); + cfg->self->addChildNode("DetectorWidth", getDetectorWidth()); + cfg->self->addChildNode("DistanceOriginSource", getOriginSourceDistance()); + cfg->self->addChildNode("DistanceOriginDetector", getOriginDetectorDistance()); + cfg->self->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); + return cfg; +} +//---------------------------------------------------------------------------------------- } // namespace astra diff --git a/src/FanFlatVecProjectionGeometry2D.cpp b/src/FanFlatVecProjectionGeometry2D.cpp index 77f9db7..9c7b596 100644 --- a/src/FanFlatVecProjectionGeometry2D.cpp +++ b/src/FanFlatVecProjectionGeometry2D.cpp @@ -194,7 +194,7 @@ bool CFanFlatVecProjectionGeometry2D::isEqual(CProjectionGeometry2D* _pGeom2) co // Is of type bool CFanFlatVecProjectionGeometry2D::isOfType(const std::string& _sType) { - return (_sType == "fanflat_vec"); + return (_sType == "fanflat_vec"); } //---------------------------------------------------------------------------------------- @@ -227,6 +227,28 @@ bool CFanFlatVecProjectionGeometry2D::_check() //---------------------------------------------------------------------------------------- +// Get the configuration object +Config* CFanFlatVecProjectionGeometry2D::getConfiguration() const +{ + Config* cfg = new Config(); + cfg->initialize("ProjectionGeometry2D"); + cfg->self->addAttribute("type", "fanflat_vec"); + cfg->self->addChildNode("DetectorCount", getDetectorCount()); + std::string vectors = ""; + for (int i = 0; i < m_iProjectionAngleCount; ++i) { + SFanProjection& p = m_pProjectionAngles[i]; + vectors += boost::lexical_cast<string>(p.fSrcX) + ","; + vectors += boost::lexical_cast<string>(p.fSrcY) + ","; + vectors += boost::lexical_cast<string>(p.fDetSX + 0.5f * m_iDetectorCount * p.fDetUX) + ","; + vectors += boost::lexical_cast<string>(p.fDetSY + 0.5f * m_iDetectorCount * p.fDetUY) + ","; + vectors += boost::lexical_cast<string>(p.fDetUX) + ","; + vectors += boost::lexical_cast<string>(p.fDetUY); + if (i < m_iProjectionAngleCount-1) vectors += ';'; + } + cfg->self->addChildNode("Vectors", vectors); + return cfg; +} +//---------------------------------------------------------------------------------------- } // namespace astra diff --git a/src/ParallelProjectionGeometry2D.cpp b/src/ParallelProjectionGeometry2D.cpp index 8f8faa4..cac8f30 100644 --- a/src/ParallelProjectionGeometry2D.cpp +++ b/src/ParallelProjectionGeometry2D.cpp @@ -27,6 +27,7 @@ $Id$ */ #include "astra/ParallelProjectionGeometry2D.h" +#include <boost/lexical_cast.hpp> #include <cstring> @@ -168,6 +169,19 @@ bool CParallelProjectionGeometry2D::isOfType(const std::string& _sType) { return (_sType == "parallel"); } + +//---------------------------------------------------------------------------------------- +// Get the configuration object +Config* CParallelProjectionGeometry2D::getConfiguration() const +{ + Config* cfg = new Config(); + cfg->initialize("ProjectionGeometry2D"); + cfg->self->addAttribute("type", "parallel"); + cfg->self->addChildNode("DetectorCount", getDetectorCount()); + cfg->self->addChildNode("DetectorWidth", getDetectorWidth()); + cfg->self->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); + return cfg; +} //---------------------------------------------------------------------------------------- CVector3D CParallelProjectionGeometry2D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex /* = 0 */) diff --git a/src/ParallelProjectionGeometry3D.cpp b/src/ParallelProjectionGeometry3D.cpp index 8a13f0f..eb200f9 100644 --- a/src/ParallelProjectionGeometry3D.cpp +++ b/src/ParallelProjectionGeometry3D.cpp @@ -27,6 +27,7 @@ $Id$ */ #include "astra/ParallelProjectionGeometry3D.h" +#include <boost/lexical_cast.hpp> #include <cstring> @@ -154,19 +155,24 @@ bool CParallelProjectionGeometry3D::isEqual(const CProjectionGeometry3D * _pGeom // is of type bool CParallelProjectionGeometry3D::isOfType(const std::string& _sType) const { - return (_sType == "parallel"); + return (_sType == "parallel3d"); } //---------------------------------------------------------------------------------------- -void CParallelProjectionGeometry3D::toXML(XMLNode* _sNode) const +// Get the configuration object +Config* CParallelProjectionGeometry3D::getConfiguration() const { - _sNode->addAttribute("type","parallel3d"); - _sNode->addChildNode("DetectorSpacingX", m_fDetectorSpacingX); - _sNode->addChildNode("DetectorSpacingY", m_fDetectorSpacingY); - _sNode->addChildNode("DetectorRowCount", m_iDetectorRowCount); - _sNode->addChildNode("DetectorColCount", m_iDetectorColCount); - _sNode->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); + Config* cfg = new Config(); + cfg->initialize("ProjectionGeometry3D"); + cfg->self->addAttribute("type", "parallel3d"); + cfg->self->addChildNode("DetectorRowCount", m_iDetectorRowCount); + cfg->self->addChildNode("DetectorColCount", m_iDetectorColCount); + cfg->self->addChildNode("DetectorSpacingX", m_fDetectorSpacingX); + cfg->self->addChildNode("DetectorSpacingY", m_fDetectorSpacingY); + cfg->self->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); + return cfg; } +//---------------------------------------------------------------------------------------- CVector3D CParallelProjectionGeometry3D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const { diff --git a/src/ParallelVecProjectionGeometry3D.cpp b/src/ParallelVecProjectionGeometry3D.cpp index 17f00a4..cfac485 100644 --- a/src/ParallelVecProjectionGeometry3D.cpp +++ b/src/ParallelVecProjectionGeometry3D.cpp @@ -202,14 +202,38 @@ bool CParallelVecProjectionGeometry3D::isOfType(const std::string& _sType) const } //---------------------------------------------------------------------------------------- -void CParallelVecProjectionGeometry3D::toXML(XMLNode* _sNode) const +// Get the configuration object +Config* CParallelVecProjectionGeometry3D::getConfiguration() const { - _sNode->addAttribute("type","parallel3d_vec"); - _sNode->addChildNode("DetectorRowCount", m_iDetectorRowCount); - _sNode->addChildNode("DetectorColCount", m_iDetectorColCount); - // TODO: - //_sNode->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); + Config* cfg = new Config(); + cfg->initialize("ProjectionGeometry3D"); + + cfg->self->addAttribute("type", "parallel3d"); + cfg->self->addChildNode("DetectorRowCount", m_iDetectorRowCount); + cfg->self->addChildNode("DetectorColCount", m_iDetectorColCount); + + std::string vectors = ""; + for (int i = 0; i < m_iProjectionAngleCount; ++i) { + SPar3DProjection& p = m_pProjectionAngles[i]; + vectors += boost::lexical_cast<string>(p.fRayX) + ","; + vectors += boost::lexical_cast<string>(p.fRayY) + ","; + vectors += boost::lexical_cast<string>(p.fRayZ) + ","; + vectors += boost::lexical_cast<string>(p.fDetSX + 0.5f*m_iDetectorRowCount*p.fDetUX + 0.5f*m_iDetectorColCount*p.fDetVX) + ","; + vectors += boost::lexical_cast<string>(p.fDetSY + 0.5f*m_iDetectorRowCount*p.fDetUY + 0.5f*m_iDetectorColCount*p.fDetVY) + ","; + vectors += boost::lexical_cast<string>(p.fDetSZ + 0.5f*m_iDetectorRowCount*p.fDetUZ + 0.5f*m_iDetectorColCount*p.fDetVZ) + ","; + vectors += boost::lexical_cast<string>(p.fDetUX) + ","; + vectors += boost::lexical_cast<string>(p.fDetUY) + ","; + vectors += boost::lexical_cast<string>(p.fDetUZ) + ","; + vectors += boost::lexical_cast<string>(p.fDetVX) + ","; + vectors += boost::lexical_cast<string>(p.fDetVY) + ","; + vectors += boost::lexical_cast<string>(p.fDetVZ); + if (i < m_iProjectionAngleCount-1) vectors += ';'; + } + cfg->self->addChildNode("Vectors", vectors); + + return cfg; } +//---------------------------------------------------------------------------------------- CVector3D CParallelVecProjectionGeometry3D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const { diff --git a/src/SparseMatrixProjectionGeometry2D.cpp b/src/SparseMatrixProjectionGeometry2D.cpp index 7f14d9d..86357d2 100644 --- a/src/SparseMatrixProjectionGeometry2D.cpp +++ b/src/SparseMatrixProjectionGeometry2D.cpp @@ -189,7 +189,20 @@ bool CSparseMatrixProjectionGeometry2D::isOfType(const std::string& _sType) return (_sType == "sparse_matrix"); } //---------------------------------------------------------------------------------------- +// Get the configuration object +Config* CSparseMatrixProjectionGeometry2D::getConfiguration() const +{ + Config* cfg = new Config(); + cfg->initialize("ProjectionGeometry2D"); + cfg->self->addAttribute("type", "sparse matrix"); + cfg->self->addChildNode("DetectorCount", getDetectorCount()); + cfg->self->addChildNode("DetectorWidth", getDetectorWidth()); + cfg->self->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); + cfg->self->addChildNode("MatrixID", CMatrixManager::getSingleton().getIndex(m_pMatrix)); + return cfg; +} +//---------------------------------------------------------------------------------------- CVector3D CSparseMatrixProjectionGeometry2D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) { CVector3D vOutput(0.0f, 0.0f, 0.0f); diff --git a/src/VolumeGeometry2D.cpp b/src/VolumeGeometry2D.cpp index 19aa905..d412914 100644 --- a/src/VolumeGeometry2D.cpp +++ b/src/VolumeGeometry2D.cpp @@ -152,7 +152,7 @@ CVolumeGeometry2D* CVolumeGeometry2D::clone() } //---------------------------------------------------------------------------------------- -// Initialization witha COnfig object +// Initialization witha Config object bool CVolumeGeometry2D::initialize(const Config& _cfg) { ASTRA_ASSERT(_cfg.self); @@ -277,6 +277,24 @@ bool CVolumeGeometry2D::isEqual(CVolumeGeometry2D* _pGeom2) const return true; } + +//---------------------------------------------------------------------------------------- +// Get the configuration object +Config* CVolumeGeometry2D::getConfiguration() const +{ + Config* cfg = new Config(); + cfg->initialize("VolumeGeometry2D"); + + cfg->self->addChildNode("GridColCount", m_iGridColCount); + cfg->self->addChildNode("GridRowCount", m_iGridRowCount); + + cfg->self->addOption("WindowMinX", m_fWindowMinX); + cfg->self->addOption("WindowMaxX", m_fWindowMaxX); + cfg->self->addOption("WindowMinY", m_fWindowMinY); + cfg->self->addOption("WindowMaxY", m_fWindowMaxY); + + return cfg; +} //---------------------------------------------------------------------------------------- } // namespace astra diff --git a/src/VolumeGeometry3D.cpp b/src/VolumeGeometry3D.cpp index d7a93a9..66e6f0c 100644 --- a/src/VolumeGeometry3D.cpp +++ b/src/VolumeGeometry3D.cpp @@ -380,5 +380,28 @@ CVolumeGeometry2D * CVolumeGeometry3D::createVolumeGeometry2D() const } //---------------------------------------------------------------------------------------- +// Get the configuration object +Config* CVolumeGeometry3D::getConfiguration() const +{ + Config* cfg = new Config(); + cfg->initialize("VolumeGeometry3D"); + + cfg->self->addChildNode("GridColCount", m_iGridColCount); + cfg->self->addChildNode("GridRowCount", m_iGridRowCount); + cfg->self->addChildNode("GridSliceCount", m_iGridSliceCount); + + cfg->self->addOption("WindowMinX", m_fWindowMinX); + cfg->self->addOption("WindowMaxX", m_fWindowMaxX); + cfg->self->addOption("WindowMinY", m_fWindowMinY); + cfg->self->addOption("WindowMaxY", m_fWindowMaxY); + cfg->self->addOption("WindowMinZ", m_fWindowMinZ); + cfg->self->addOption("WindowMaxZ", m_fWindowMaxZ); + + return cfg; +} +//---------------------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------------------- } // namespace astra diff --git a/src/XMLDocument.cpp b/src/XMLDocument.cpp index b39875b..406564f 100644 --- a/src/XMLDocument.cpp +++ b/src/XMLDocument.cpp @@ -109,4 +109,12 @@ void XMLDocument::saveToFile(string sFilename) } //----------------------------------------------------------------------------- +std::string XMLDocument::toString() +{ + std::stringstream ss; + ss << *fDOMDocument->first_node(); + return ss.str(); +} + +//----------------------------------------------------------------------------- diff --git a/src/XMLNode.cpp b/src/XMLNode.cpp index a5b6796..4b2bdf4 100644 --- a/src/XMLNode.cpp +++ b/src/XMLNode.cpp @@ -448,13 +448,11 @@ void XMLNode::setContent(float32 _fValue) // Set content - LIST void XMLNode::setContent(float32* pfList, int _iSize) { - addAttribute("listsize", _iSize); - for (int i = 0; i < _iSize; i++) { - XMLNode* item = addChildNode("ListItem"); - item->addAttribute("index", i); - item->addAttribute("value",pfList[i]); - delete item; + std::string str = (_iSize > 0) ? boost::lexical_cast<std::string>(pfList[0]) : ""; + for (int i = 1; i < _iSize; i++) { + str += "," + boost::lexical_cast<std::string>(pfList[i]); } + setContent(str); } //----------------------------------------------------------------------------- |