diff options
Diffstat (limited to 'matlab')
-rw-r--r-- | matlab/mex/astra_mex_algorithm_c.cpp | 2 | ||||
-rw-r--r-- | matlab/mex/astra_mex_data2d_c.cpp | 4 | ||||
-rw-r--r-- | matlab/mex/astra_mex_data3d_c.cpp | 114 | ||||
-rw-r--r-- | matlab/mex/mexCopyDataHelpFunctions.cpp | 2 | ||||
-rw-r--r-- | matlab/mex/mexDataManagerHelpFunctions.cpp | 2 | ||||
-rw-r--r-- | matlab/mex/mexHelpFunctions.cpp | 68 | ||||
-rw-r--r-- | matlab/mex/mexHelpFunctions.h | 6 |
7 files changed, 141 insertions, 57 deletions
diff --git a/matlab/mex/astra_mex_algorithm_c.cpp b/matlab/mex/astra_mex_algorithm_c.cpp index e4afa63..ec7aa72 100644 --- a/matlab/mex/astra_mex_algorithm_c.cpp +++ b/matlab/mex/astra_mex_algorithm_c.cpp @@ -81,7 +81,7 @@ void astra_mex_algorithm_create(int nlhs, mxArray* plhs[], int nrhs, const mxArr // turn MATLAB struct to an XML-based Config object 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 cfg; mexErrMsgTxt("Unknown algorithm. \n"); diff --git a/matlab/mex/astra_mex_data2d_c.cpp b/matlab/mex/astra_mex_data2d_c.cpp index 9576896..909d229 100644 --- a/matlab/mex/astra_mex_data2d_c.cpp +++ b/matlab/mex/astra_mex_data2d_c.cpp @@ -149,7 +149,7 @@ void astra_mex_data2d_create(int& nlhs, mxArray* plhs[], int& nrhs, const mxArra 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(); @@ -438,7 +438,7 @@ void astra_mex_data2d_change_geometry(int nlhs, mxArray* plhs[], int nrhs, const 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(); diff --git a/matlab/mex/astra_mex_data3d_c.cpp b/matlab/mex/astra_mex_data3d_c.cpp index 32b0ba7..fe4ce37 100644 --- a/matlab/mex/astra_mex_data3d_c.cpp +++ b/matlab/mex/astra_mex_data3d_c.cpp @@ -148,8 +148,8 @@ void astra_mex_data3d_link(int& nlhs, mxArray* plhs[], int& nrhs, const mxArray* return; } - if (data && !checkDataType(data)) { - mexErrMsgTxt("Data must be single or double."); + if (data && !mxIsSingle(data)) { + mexErrMsgTxt("Data must be single."); return; } @@ -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/matlab/mex/mexCopyDataHelpFunctions.cpp b/matlab/mex/mexCopyDataHelpFunctions.cpp index 80fb834..4db6abd 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 (mexIsScalar(in)) { + if (mexIsScalar(in) || mxIsEmpty(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 d482428..1794abb 100644 --- a/matlab/mex/mexDataManagerHelpFunctions.cpp +++ b/matlab/mex/mexDataManagerHelpFunctions.cpp @@ -285,7 +285,7 @@ allocateDataObject(const std::string & sDataType, 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(); diff --git a/matlab/mex/mexHelpFunctions.cpp b/matlab/mex/mexHelpFunctions.cpp index c0ac711..87a9672 100644 --- a/matlab/mex/mexHelpFunctions.cpp +++ b/matlab/mex/mexHelpFunctions.cpp @@ -185,7 +185,7 @@ Config* structToConfig(string rootname, const mxArray* pStruct) } //----------------------------------------------------------------------------------------- -bool structToXMLNode(XMLNode* node, const mxArray* pStruct) +bool structToXMLNode(XMLNode node, const mxArray* pStruct) { // loop all fields int nfields = mxGetNumberOfFields(pStruct); @@ -199,16 +199,16 @@ bool structToXMLNode(XMLNode* node, const mxArray* pStruct) if (mxIsChar(pField)) { string sValue = mexToString(pField); if (sFieldName == "type") { - node->addAttribute("type", sValue); + node.addAttribute("type", sValue); } else { - delete node->addChildNode(sFieldName, sValue); + node.addChildNode(sFieldName, sValue); } } // scalar else if (mxIsNumeric(pField) && mxGetM(pField)*mxGetN(pField) == 1) { string sValue = mexToString(pField); - delete node->addChildNode(sFieldName, sValue); + node.addChildNode(sFieldName, sValue); } // numerical array @@ -217,20 +217,9 @@ bool structToXMLNode(XMLNode* node, const mxArray* pStruct) mexErrMsgTxt("Numeric input must be double."); return false; } - XMLNode* listbase = node->addChildNode(sFieldName); - listbase->addAttribute("listsize", mxGetM(pField)*mxGetN(pField)); + XMLNode listbase = node.addChildNode(sFieldName); 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; + listbase.setContent(pdValues, mxGetN(pField), mxGetM(pField), true); } // not castable to a single string @@ -240,9 +229,8 @@ bool structToXMLNode(XMLNode* node, const mxArray* pStruct) if (!ret) return false; } else { - XMLNode* newNode = node->addChildNode(sFieldName); + XMLNode newNode = node.addChildNode(sFieldName); bool ret = structToXMLNode(newNode, pField); - delete newNode; if (!ret) return false; } @@ -254,7 +242,7 @@ bool structToXMLNode(XMLNode* node, const mxArray* pStruct) } //----------------------------------------------------------------------------------------- // Options struct to xml node -bool optionsToXMLNode(XMLNode* node, const mxArray* pOptionStruct) +bool optionsToXMLNode(XMLNode node, const mxArray* pOptionStruct) { // loop all fields int nfields = mxGetNumberOfFields(pOptionStruct); @@ -262,7 +250,7 @@ bool optionsToXMLNode(XMLNode* node, const mxArray* pOptionStruct) std::string sFieldName = std::string(mxGetFieldNameByNumber(pOptionStruct, i)); const mxArray* pField = mxGetFieldByNumber(pOptionStruct, 0, i); - if (node->hasOption(sFieldName)) { + if (node.hasOption(sFieldName)) { mexErrMsgTxt("Duplicate option"); return false; } @@ -270,7 +258,7 @@ bool optionsToXMLNode(XMLNode* node, const mxArray* pOptionStruct) // string or scalar if (mxIsChar(pField) || mexIsScalar(pField)) { string sValue = mexToString(pField); - node->addOption(sFieldName, sValue); + node.addOption(sFieldName, sValue); } // numerical array else if (mxIsNumeric(pField) && mxGetM(pField)*mxGetN(pField) > 1) { @@ -279,21 +267,10 @@ bool optionsToXMLNode(XMLNode* node, const mxArray* pOptionStruct) return false; } - XMLNode* listbase = node->addChildNode("Option"); - listbase->addAttribute("key", sFieldName); - listbase->addAttribute("listsize", mxGetM(pField)*mxGetN(pField)); + XMLNode listbase = node.addChildNode("Option"); + listbase.addAttribute("key", sFieldName); 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; + listbase.setContent(pdValues, mxGetN(pField), mxGetM(pField), true); } else { mexErrMsgTxt("Unsupported option type"); return false; @@ -343,30 +320,29 @@ mxArray* configToStruct(astra::Config* cfg) } //----------------------------------------------------------------------------------------- -mxArray* XMLNodeToStruct(astra::XMLNode* node) +mxArray* XMLNodeToStruct(astra::XMLNode node) { std::map<std::string, mxArray*> mList; std::map<std::string, mxArray*> mOptions; // type_attribute - if (node->hasAttribute("type")) { - mList["type"] = mxCreateString(node->getAttribute("type").c_str()); + if (node.hasAttribute("type")) { + mList["type"] = mxCreateString(node.getAttribute("type").c_str()); } - list<XMLNode*> nodes = node->getNodes(); - for (list<XMLNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) { - XMLNode* subnode = (*it); + list<XMLNode> nodes = node.getNodes(); + for (list<XMLNode>::iterator it = nodes.begin(); it != nodes.end(); it++) { + XMLNode subnode = (*it); // option - if (subnode->getName() == "Option") { - mOptions[subnode->getAttribute("key")] = stringToMxArray(subnode->getAttribute("value")); + if (subnode.getName() == "Option") { + mOptions[subnode.getAttribute("key")] = stringToMxArray(subnode.getAttribute("value")); } // regular content else { - mList[subnode->getName()] = stringToMxArray(subnode->getContent()); + mList[subnode.getName()] = stringToMxArray(subnode.getContent()); } - delete subnode; } if (mOptions.size() > 0) mList["options"] = buildStruct(mOptions); diff --git a/matlab/mex/mexHelpFunctions.h b/matlab/mex/mexHelpFunctions.h index f9ffcf2..3ac5bd8 100644 --- a/matlab/mex/mexHelpFunctions.h +++ b/matlab/mex/mexHelpFunctions.h @@ -58,13 +58,13 @@ mxArray* anyToMxArray(boost::any _any); // 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); +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); // turn a Config object into a MATLAB struct mxArray* configToStruct(astra::Config* cfg); -mxArray* XMLNodeToStruct(astra::XMLNode* xml); +mxArray* XMLNodeToStruct(astra::XMLNode xml); mxArray* stringToMxArray(std::string input); mxArray* buildStruct(std::map<std::string, mxArray*> mInput); |