diff options
| -rw-r--r-- | build/linux/Makefile.in | 3 | ||||
| -rwxr-xr-x | matlab/mex/astra_mex_direct_c.cpp | 332 | ||||
| -rw-r--r-- | matlab/tools/astra_mex_direct.m | 24 | 
3 files changed, 358 insertions, 1 deletions
diff --git a/build/linux/Makefile.in b/build/linux/Makefile.in index 2d862f2..abbebe2 100644 --- a/build/linux/Makefile.in +++ b/build/linux/Makefile.in @@ -232,7 +232,8 @@ MATLAB_MEX=\  	matlab/mex/astra_mex_projector_c.$(MEXSUFFIX) \  	matlab/mex/astra_mex_projector3d_c.$(MEXSUFFIX) \  	matlab/mex/astra_mex_log_c.$(MEXSUFFIX) \ -	matlab/mex/astra_mex_data3d_c.$(MEXSUFFIX) +	matlab/mex/astra_mex_data3d_c.$(MEXSUFFIX) \ +	matlab/mex/astra_mex_direct_c.$(MEXSUFFIX)  OBJECT_DIRS = src/ tests/ cuda/2d/ cuda/3d/ matlab/mex/ ./ diff --git a/matlab/mex/astra_mex_direct_c.cpp b/matlab/mex/astra_mex_direct_c.cpp new file mode 100755 index 0000000..94eb1cd --- /dev/null +++ b/matlab/mex/astra_mex_direct_c.cpp @@ -0,0 +1,332 @@ +/* +----------------------------------------------------------------------- +Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp +           2014-2015, CWI, Amsterdam + +Contact: astra@uantwerpen.be +Website: http://sf.net/projects/astra-toolbox + +This file is part of the ASTRA Toolbox. + + +The ASTRA Toolbox is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The ASTRA Toolbox is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +$Id$ +*/ + +/** \file astra_mex_direct_c.cpp + * + *  \brief Utility functions for low-overhead FP and BP calls. + */ +#include <mex.h> +#include "mexHelpFunctions.h" +#include "mexCopyDataHelpFunctions.h" +#include "mexDataManagerHelpFunctions.h" + +#include <list> + +#include "astra/Globals.h" + +#include "astra/AstraObjectManager.h" + +#include "astra/Float32ProjectionData2D.h" +#include "astra/Float32VolumeData2D.h" +#include "astra/CudaProjector3D.h" +#include "astra/Projector3D.h" +#include "astra/Float32ProjectionData3DMemory.h" +#include "astra/Float32VolumeData3DMemory.h" + +#include "astra/CudaForwardProjectionAlgorithm3D.h" + +#include "astra/CudaBackProjectionAlgorithm3D.h" + +using namespace std; +using namespace astra; + +#define USE_MATLAB_UNDOCUMENTED + + +class CFloat32CustomMemory_simple : public astra::CFloat32CustomMemory { +public: +	CFloat32CustomMemory_simple(float *ptr) { m_fPtr = ptr; } +	~CFloat32CustomMemory_simple() { } +}; + +#ifdef ASTRA_CUDA + +//----------------------------------------------------------------------------------------- +/** + * projection = astra_mex_direct_c('FP3D', projector_id, volume); + * Both 'projection' and 'volume' are Matlab arrays. + */ +void astra_mex_direct_fp3d(int& nlhs, mxArray* plhs[], int& nrhs, const mxArray* prhs[]) +{ +	// TODO: Add an optional way of specifying extra options + +	if (nrhs < 3) { +		mexErrMsgTxt("Not enough arguments. Syntax: astra_mex_direct_c('FP3D', projector_id, data)"); +		return; +	} + +	int iPid = (int)(mxGetScalar(prhs[1])); +	astra::CProjector3D* pProjector; +	pProjector = astra::CProjector3DManager::getSingleton().get(iPid); +	if (!pProjector) { +		mexErrMsgTxt("Projector not found."); +		return; +	} +	if (!pProjector->isInitialized()) { +		mexErrMsgTxt("Projector not initialized."); +		return; +	} +	bool isCuda = false; +	if (dynamic_cast<CCudaProjector3D*>(pProjector)) +		isCuda = true; +	if (!isCuda) { +		mexErrMsgTxt("Only CUDA projectors are currently supported."); +		return; +	} + +	astra::CVolumeGeometry3D* pVolGeom = pProjector->getVolumeGeometry(); +	astra::CProjectionGeometry3D* pProjGeom = pProjector->getProjectionGeometry(); + +	const mxArray* const data = prhs[2]; +	if (!checkDataType(data)) { +		mexErrMsgTxt("Data must be single or double."); +		return; +	} + +	if (!checkDataSize(data, pVolGeom)) { +		mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry."); +		return; +	} + + +	// Allocate input data +	astra::CFloat32VolumeData3DMemory* pInput; +	if (mxIsSingle(data)) { +		astra::CFloat32CustomMemory* m = new CFloat32CustomMemory_simple((float *)mxGetData(data)); +		pInput = new astra::CFloat32VolumeData3DMemory(pVolGeom, m); +	} else { +		pInput = new astra::CFloat32VolumeData3DMemory(pVolGeom); +		copyMexToCFloat32Array(data, pInput->getData(), pInput->getSize()); +	} + + +	// Allocate output data +	// If the input is single, we also allocate single output. +	// Otherwise, double. +	astra::CFloat32ProjectionData3DMemory* pOutput; +	mxArray *pOutputMx; +	if (mxIsSingle(data)) { +		mwSize dims[3]; +		dims[0] = pProjGeom->getDetectorColCount(); +		dims[1] = pProjGeom->getProjectionCount(); +		dims[2] = pProjGeom->getDetectorRowCount(); +		pOutputMx = mxCreateNumericArray(3, dims, mxSINGLE_CLASS, mxREAL); + +		astra::CFloat32CustomMemory* m = new CFloat32CustomMemory_simple((float *)mxGetData(pOutputMx)); +		pOutput = new astra::CFloat32ProjectionData3DMemory(pProjGeom, m); +	} else { +		pOutput = new astra::CFloat32ProjectionData3DMemory(pProjGeom); +	} + +	// Perform FP + +	astra::CCudaForwardProjectionAlgorithm3D* pAlg; +	pAlg = new astra::CCudaForwardProjectionAlgorithm3D(); +	pAlg->initialize(pProjector, pOutput, pInput); + +	if (!pAlg->isInitialized()) { +		mexErrMsgTxt("Error initializing algorithm."); +		// TODO: Delete pOutputMx? +		delete pAlg; +		delete pInput; +		delete pOutput; +		return; +	} + +	pAlg->run(); + +	delete pAlg; + + +	if (mxIsSingle(data)) { + +	} else { +		pOutputMx = createEquivMexArray<mxDOUBLE_CLASS>(pOutput); +		copyCFloat32ArrayToMex(pOutput->getData(), pOutputMx); +	} +	plhs[0] = pOutputMx; + +	delete pOutput; +	delete pInput; +} +//----------------------------------------------------------------------------------------- +/** + * projection = astra_mex_direct_c('BP3D', projector_id, volume); + * Both 'projection' and 'volume' are Matlab arrays. + */ +void astra_mex_direct_bp3d(int& nlhs, mxArray* plhs[], int& nrhs, const mxArray* prhs[]) +{ +	// TODO: Add an optional way of specifying extra options + +	if (nrhs < 3) { +		mexErrMsgTxt("Not enough arguments. Syntax: astra_mex_direct_c('BP3D', projector_id, data)"); +		return; +	} + +	int iPid = (int)(mxGetScalar(prhs[1])); +	astra::CProjector3D* pProjector; +	pProjector = astra::CProjector3DManager::getSingleton().get(iPid); +	if (!pProjector) { +		mexErrMsgTxt("Projector not found."); +		return; +	} +	if (!pProjector->isInitialized()) { +		mexErrMsgTxt("Projector not initialized."); +		return; +	} +	bool isCuda = false; +	if (dynamic_cast<CCudaProjector3D*>(pProjector)) +		isCuda = true; +	if (!isCuda) { +		mexErrMsgTxt("Only CUDA projectors are currently supported."); +		return; +	} + +	astra::CVolumeGeometry3D* pVolGeom = pProjector->getVolumeGeometry(); +	astra::CProjectionGeometry3D* pProjGeom = pProjector->getProjectionGeometry(); + +	const mxArray* const data = prhs[2]; +	if (!checkDataType(data)) { +		mexErrMsgTxt("Data must be single or double."); +		return; +	} + +	if (!checkDataSize(data, pProjGeom)) { +		mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry."); +		return; +	} + + +	// Allocate input data +	astra::CFloat32ProjectionData3DMemory* pInput; +	if (mxIsSingle(data)) { +		astra::CFloat32CustomMemory* m = new CFloat32CustomMemory_simple((float *)mxGetData(data)); +		pInput = new astra::CFloat32ProjectionData3DMemory(pProjGeom, m); +	} else { +		pInput = new astra::CFloat32ProjectionData3DMemory(pProjGeom); +		copyMexToCFloat32Array(data, pInput->getData(), pInput->getSize()); +	} + + +	// Allocate output data +	// If the input is single, we also allocate single output. +	// Otherwise, double. +	astra::CFloat32VolumeData3DMemory* pOutput; +	mxArray *pOutputMx; +	if (mxIsSingle(data)) { +		mwSize dims[3]; +		dims[0] = pVolGeom->getGridColCount(); +		dims[1] = pVolGeom->getGridRowCount(); +		dims[2] = pVolGeom->getGridSliceCount(); +		pOutputMx = mxCreateNumericArray(3, dims, mxSINGLE_CLASS, mxREAL); + +		astra::CFloat32CustomMemory* m = new CFloat32CustomMemory_simple((float *)mxGetData(pOutputMx)); +		pOutput = new astra::CFloat32VolumeData3DMemory(pVolGeom, m); +	} else { +		pOutput = new astra::CFloat32VolumeData3DMemory(pVolGeom); +	} + +	// Perform BP + +	astra::CCudaBackProjectionAlgorithm3D* pAlg; +	pAlg = new astra::CCudaBackProjectionAlgorithm3D(); +	pAlg->initialize(pProjector, pInput, pOutput); + +	if (!pAlg->isInitialized()) { +		mexErrMsgTxt("Error initializing algorithm."); +		// TODO: Delete pOutputMx? +		delete pAlg; +		delete pInput; +		delete pOutput; +		return; +	} + +	pAlg->run(); + +	delete pAlg; + + +	if (mxIsSingle(data)) { + +	} else { +		pOutputMx = createEquivMexArray<mxDOUBLE_CLASS>(pOutput); +		copyCFloat32ArrayToMex(pOutput->getData(), pOutputMx); +	} +	plhs[0] = pOutputMx; + +	delete pOutput; +	delete pInput; +} + +#endif + +//----------------------------------------------------------------------------------------- + +static void printHelp() +{ +	mexPrintf("Please specify a mode of operation.\n"); +	mexPrintf("Valid modes: FP3D, BP3D\n"); +} + + +//----------------------------------------------------------------------------------------- +/** + * ... = astra_mex_direct_c(mode,...); + */ +void mexFunction(int nlhs, mxArray* plhs[], +				 int nrhs, const mxArray* prhs[]) +{ + +	// INPUT: Mode +	string sMode; +	if (1 <= nrhs) { +		sMode = mexToString(prhs[0]); +	} else { +		printHelp(); +		return; +	} + +#ifndef ASTRA_CUDA +	mexErrMsgTxt("Only CUDA projectors are currently supported."); +	return; +#else + +	// 3D data +	if (sMode == "FP3D") { +		astra_mex_direct_fp3d(nlhs, plhs, nrhs, prhs); +	} else if (sMode == "BP3D") { +		astra_mex_direct_bp3d(nlhs, plhs, nrhs, prhs); +	} else { +		printHelp(); +	} +#endif + +	return; +} + + diff --git a/matlab/tools/astra_mex_direct.m b/matlab/tools/astra_mex_direct.m new file mode 100644 index 0000000..58c4fd2 --- /dev/null +++ b/matlab/tools/astra_mex_direct.m @@ -0,0 +1,24 @@ +function [varargout] = astra_mex_direct(varargin) +%------------------------------------------------------------------------ +% Reference page in Help browser +%    <a href="matlab:docsearch('astra_mex_direct' )">astra_mex_data3d</a>. +%------------------------------------------------------------------------ +%------------------------------------------------------------------------ +% This file is part of the ASTRA Toolbox +%  +% Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp +%            2014-2015, CWI, Amsterdam +% License: Open Source under GPLv3 +% Contact: astra@uantwerpen.be +% Website: http://sf.net/projects/astra-toolbox +%------------------------------------------------------------------------ +% $Id$ +if nargout == 0 +    astra_mex_direct_c(varargin{:}); +    if exist('ans','var') +        varargout{1} = ans; +    end +else +    varargout = cell(1,nargout); +    [varargout{:}] = astra_mex_direct_c(varargin{:}); +end  | 
