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 /matlab | |
| 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
Diffstat (limited to 'matlab')
| -rw-r--r-- | matlab/mex/astra_mex_algorithm_c.cpp | 17 | ||||
| -rw-r--r-- | matlab/mex/astra_mex_c.cpp | 2 | ||||
| -rw-r--r-- | matlab/mex/astra_mex_data2d_c.cpp | 82 | ||||
| -rw-r--r-- | matlab/mex/astra_mex_data3d_c.cpp | 88 | ||||
| -rw-r--r-- | matlab/mex/astra_mex_matrix_c.cpp | 2 | ||||
| -rw-r--r-- | matlab/mex/astra_mex_projector3d_c.cpp | 26 | ||||
| -rw-r--r-- | matlab/mex/astra_mex_projector_c.cpp | 18 | ||||
| -rw-r--r-- | matlab/mex/mexCopyDataHelpFunctions.cpp | 2 | ||||
| -rw-r--r-- | matlab/mex/mexDataManagerHelpFunctions.cpp | 40 | ||||
| -rw-r--r-- | matlab/mex/mexHelpFunctions.cpp | 718 | ||||
| -rw-r--r-- | matlab/mex/mexHelpFunctions.h | 35 | 
11 files changed, 407 insertions, 623 deletions
| 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 | 
