summaryrefslogtreecommitdiffstats
path: root/matlab/mex
diff options
context:
space:
mode:
authorWillem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>2015-05-13 11:56:24 +0200
committerWillem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>2015-05-13 11:56:24 +0200
commitde30f7538a865a2ee7acb7dd8294fb6cdc4f98be (patch)
treeba11189e6e83e83e73167518b45641fc287c8eda /matlab/mex
parent6504cffdbe74d9b671222a7ec24b26fbb4f871f0 (diff)
parent86ad56f005d9d3871f654390739459d5634dd5d5 (diff)
downloadastra-de30f7538a865a2ee7acb7dd8294fb6cdc4f98be.tar.gz
astra-de30f7538a865a2ee7acb7dd8294fb6cdc4f98be.tar.bz2
astra-de30f7538a865a2ee7acb7dd8294fb6cdc4f98be.tar.xz
astra-de30f7538a865a2ee7acb7dd8294fb6cdc4f98be.zip
Merge branch 'master'
Diffstat (limited to 'matlab/mex')
-rw-r--r--matlab/mex/astra_mex_algorithm_c.cpp2
-rw-r--r--matlab/mex/astra_mex_data2d_c.cpp4
-rw-r--r--matlab/mex/astra_mex_data3d_c.cpp114
-rw-r--r--matlab/mex/mexCopyDataHelpFunctions.cpp2
-rw-r--r--matlab/mex/mexDataManagerHelpFunctions.cpp2
-rw-r--r--matlab/mex/mexHelpFunctions.cpp68
-rw-r--r--matlab/mex/mexHelpFunctions.h6
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);