diff options
| -rw-r--r-- | include/astra/Filters.h | 4 | ||||
| -rw-r--r-- | samples/matlab/s014_FBP.m | 2 | ||||
| -rw-r--r-- | samples/matlab/s023_FBP_filters.m | 10 | ||||
| -rw-r--r-- | samples/python/s014_FBP.py | 2 | ||||
| -rw-r--r-- | samples/python/s023_FBP_filters.py | 11 | ||||
| -rw-r--r-- | src/FilteredBackProjectionAlgorithm.cpp | 5 | ||||
| -rw-r--r-- | src/Filters.cpp | 114 | 
7 files changed, 98 insertions, 50 deletions
diff --git a/include/astra/Filters.h b/include/astra/Filters.h index a1dec97..2e229b9 100644 --- a/include/astra/Filters.h +++ b/include/astra/Filters.h @@ -28,6 +28,8 @@ along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.  #ifndef _INC_ASTRA_FILTERS_H  #define _INC_ASTRA_FILTERS_H +#include <string> +  namespace astra {  struct Config; @@ -82,7 +84,7 @@ float *genFilter(const SFilterConfig &_cfg,                   int _iFFTFourierDetectorCount);  // Convert string to filter type. Returns FILTER_ERROR if unrecognized. -E_FBPFILTER convertStringToFilter(const char * _filterType); +E_FBPFILTER convertStringToFilter(const std::string &_filterType);  SFilterConfig getFilterConfigForAlgorithm(const Config& _cfg, CAlgorithm *_alg); diff --git a/samples/matlab/s014_FBP.m b/samples/matlab/s014_FBP.m index 1fc6f90..038aa90 100644 --- a/samples/matlab/s014_FBP.m +++ b/samples/matlab/s014_FBP.m @@ -24,7 +24,7 @@ rec_id = astra_mex_data2d('create', '-vol', vol_geom);  cfg = astra_struct('FBP_CUDA');  cfg.ReconstructionDataId = rec_id;  cfg.ProjectionDataId = sinogram_id; -cfg.FilterType = 'Ram-Lak'; +cfg.option.FilterType = 'Ram-Lak';  % possible values for FilterType:  % none, ram-lak, shepp-logan, cosine, hamming, hann, tukey, lanczos, diff --git a/samples/matlab/s023_FBP_filters.m b/samples/matlab/s023_FBP_filters.m index 4abec7e..d01b0d0 100644 --- a/samples/matlab/s023_FBP_filters.m +++ b/samples/matlab/s023_FBP_filters.m @@ -32,7 +32,7 @@ cfg.ProjectorId = proj_id;  % 1. Use a standard Ram-Lak filter -cfg.FilterType = 'ram-lak'; +cfg.option.FilterType = 'ram-lak';  alg_id = astra_mex_algorithm('create', cfg);  astra_mex_algorithm('run', alg_id); @@ -53,8 +53,8 @@ filter = kernel(1:halfFilterSize);  filter_geom = astra_create_proj_geom('parallel', 1.0, halfFilterSize, [0]);  filter_id = astra_mex_data2d('create', '-sino', filter_geom, filter); -cfg.FilterType = 'projection'; -cfg.FilterSinogramId = filter_id; +cfg.option.FilterType = 'projection'; +cfg.option.FilterSinogramId = filter_id;  alg_id = astra_mex_algorithm('create', cfg);  astra_mex_algorithm('run', alg_id); @@ -77,8 +77,8 @@ kernel(floor(N/2)+1) = 0.5;  kernel_geom = astra_create_proj_geom('parallel', 1.0, N, [0]);  kernel_id = astra_mex_data2d('create', '-sino', kernel_geom, kernel); -cfg.FilterType = 'rprojection'; -cfg.FilterSinogramId = kernel_id; +cfg.option.FilterType = 'rprojection'; +cfg.option.FilterSinogramId = kernel_id;  alg_id = astra_mex_algorithm('create', cfg);  astra_mex_algorithm('run', alg_id); diff --git a/samples/python/s014_FBP.py b/samples/python/s014_FBP.py index f7cefd4..1c3a341 100644 --- a/samples/python/s014_FBP.py +++ b/samples/python/s014_FBP.py @@ -49,7 +49,7 @@ rec_id = astra.data2d.create('-vol', vol_geom)  cfg = astra.astra_dict('FBP_CUDA')  cfg['ReconstructionDataId'] = rec_id  cfg['ProjectionDataId'] = sinogram_id -cfg['FilterType'] = 'Ram-Lak' +cfg['option'] = { 'FilterType': 'Ram-Lak' }  # possible values for FilterType:  # none, ram-lak, shepp-logan, cosine, hamming, hann, tukey, lanczos, diff --git a/samples/python/s023_FBP_filters.py b/samples/python/s023_FBP_filters.py index 11518ac..a67c338 100644 --- a/samples/python/s023_FBP_filters.py +++ b/samples/python/s023_FBP_filters.py @@ -47,11 +47,12 @@ cfg = astra.astra_dict('FBP')  cfg['ReconstructionDataId'] = rec_id  cfg['ProjectionDataId'] = sinogram_id  cfg['ProjectorId'] = proj_id +cfg['option'] = {}  # 1. Use a standard Ram-Lak filter -cfg['FilterType'] = 'ram-lak' +cfg['option']['FilterType'] = 'ram-lak'  alg_id = astra.algorithm.create(cfg)  astra.algorithm.run(alg_id) @@ -71,8 +72,8 @@ filter = np.reshape(kernel[0:halfFilterSize], (1, halfFilterSize))  filter_geom = astra.create_proj_geom('parallel', 1.0, halfFilterSize, [0]);  filter_id = astra.data2d.create('-sino', filter_geom, filter); -cfg['FilterType'] = 'projection' -cfg['FilterSinogramId'] = filter_id +cfg['option']['FilterType'] = 'projection' +cfg['option']['FilterSinogramId'] = filter_id  alg_id = astra.algorithm.create(cfg)  astra.algorithm.run(alg_id)  rec_filter = astra.data2d.get(rec_id) @@ -92,8 +93,8 @@ kernel[0, N//2] = 0.5  kernel_geom = astra.create_proj_geom('parallel', 1.0, N, [0]);  kernel_id = astra.data2d.create('-sino', kernel_geom, kernel); -cfg['FilterType'] = 'rprojection' -cfg['FilterSinogramId'] = kernel_id +cfg['option']['FilterType'] = 'rprojection' +cfg['option']['FilterSinogramId'] = kernel_id  alg_id = astra.algorithm.create(cfg)  astra.algorithm.run(alg_id)  rec_kernel = astra.data2d.get(rec_id) diff --git a/src/FilteredBackProjectionAlgorithm.cpp b/src/FilteredBackProjectionAlgorithm.cpp index 67a12a2..ea606f7 100644 --- a/src/FilteredBackProjectionAlgorithm.cpp +++ b/src/FilteredBackProjectionAlgorithm.cpp @@ -92,24 +92,28 @@ void CFilteredBackProjectionAlgorithm::clear()  bool CFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)  {  	ASTRA_ASSERT(_cfg.self); +	ConfigStackCheck<CAlgorithm> CC("FilteredBackProjectionAlgorithm", this, _cfg);  	// projector  	XMLNode node = _cfg.self.getSingleNode("ProjectorId");  	ASTRA_CONFIG_CHECK(node, "FilteredBackProjection", "No ProjectorId tag specified.");  	int id = node.getContentInt();  	m_pProjector = CProjector2DManager::getSingleton().get(id); +	CC.markNodeParsed("ProjectorId");  	// sinogram data  	node = _cfg.self.getSingleNode("ProjectionDataId");  	ASTRA_CONFIG_CHECK(node, "FilteredBackProjection", "No ProjectionDataId tag specified.");  	id = node.getContentInt();  	m_pSinogram = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id)); +	CC.markNodeParsed("ProjectionDataId");  	// volume data  	node = _cfg.self.getSingleNode("ReconstructionDataId");  	ASTRA_CONFIG_CHECK(node, "FilteredBackProjection", "No ReconstructionDataId tag specified.");  	id = node.getContentInt();  	m_pReconstruction = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id)); +	CC.markNodeParsed("ReconstructionDataId");  	node = _cfg.self.getSingleNode("ProjectionIndex");  	if (node)  @@ -153,6 +157,7 @@ bool CFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)  		delete[] sinogramData2D;  		delete[] projectionAngles;  	} +	CC.markNodeParsed("ProjectionIndex");  	m_filterConfig = getFilterConfigForAlgorithm(_cfg, this); diff --git a/src/Filters.cpp b/src/Filters.cpp index e756052..8f68202 100644 --- a/src/Filters.cpp +++ b/src/Filters.cpp @@ -443,7 +443,7 @@ struct FilterNameMapEntry {  	E_FBPFILTER m_type;  }; -E_FBPFILTER convertStringToFilter(const char * _filterType) +E_FBPFILTER convertStringToFilter(const std::string &_filterType)  {  	static const FilterNameMapEntry map[] = { @@ -474,10 +474,10 @@ E_FBPFILTER convertStringToFilter(const char * _filterType)  	const FilterNameMapEntry *i;  	for (i = &map[0]; i->m_name; ++i) -		if (stringCompareLowerCase(_filterType, i->m_name)) +		if (stringCompareLowerCase(_filterType.c_str(), i->m_name))  			return i->m_type; -	ASTRA_ERROR("Failed to convert \"%s\" into a filter.",_filterType); +	ASTRA_ERROR("Failed to convert \"%s\" into a filter.",_filterType.c_str());  	return FILTER_ERROR;  } @@ -489,60 +489,100 @@ SFilterConfig getFilterConfigForAlgorithm(const Config& _cfg, CAlgorithm *_alg)  	SFilterConfig c; +	XMLNode node; +  	// filter type -	XMLNode node = _cfg.self.getSingleNode("FilterType"); -	if (node) -		c.m_eType = convertStringToFilter(node.getContent().c_str()); -	else +	const char *nodeName = "FilterType"; +	node = _cfg.self.getSingleNode(nodeName); +	if (_cfg.self.hasOption(nodeName)) { +		c.m_eType = convertStringToFilter(_cfg.self.getOption(nodeName)); +		CC.markOptionParsed(nodeName); +	} else if (node) { +		// Fallback: check cfg.FilterType (instead of cfg.option.FilterType) +		c.m_eType = convertStringToFilter(node.getContent()); +		CC.markNodeParsed(nodeName); +	} else {  		c.m_eType = FILTER_RAMLAK; -	CC.markNodeParsed("FilterType"); +	}  	// filter -	node = _cfg.self.getSingleNode("FilterSinogramId"); -	if (node) -	{ -		int id = node.getContentInt(); +	nodeName = "FilterSinogramId"; +	int id = -1; +	switch (c.m_eType) { +	case FILTER_PROJECTION: +	case FILTER_SINOGRAM: +	case FILTER_RPROJECTION: +	case FILTER_RSINOGRAM: +		node = _cfg.self.getSingleNode(nodeName); +		if (_cfg.self.hasOption(nodeName)) { +			id = _cfg.self.getOptionInt(nodeName); +			CC.markOptionParsed(nodeName); +		} else if (node) { +			id = node.getContentInt(); +			CC.markNodeParsed(nodeName); +		} +		break; +	default: +		break; +	} + +	if (id != -1) {  		const CFloat32ProjectionData2D * pFilterData = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));  		c.m_iCustomFilterWidth = pFilterData->getGeometry()->getDetectorCount();  		c.m_iCustomFilterHeight = pFilterData->getGeometry()->getProjectionAngleCount();  		c.m_pfCustomFilter = new float[c.m_iCustomFilterWidth * c.m_iCustomFilterHeight];  		memcpy(c.m_pfCustomFilter, pFilterData->getDataConst(), sizeof(float) * c.m_iCustomFilterWidth * c.m_iCustomFilterHeight); -	} -	else -	{ +	} else {  		c.m_iCustomFilterWidth = 0;  		c.m_iCustomFilterHeight = 0;  		c.m_pfCustomFilter = NULL;  	} -	CC.markNodeParsed("FilterSinogramId"); // TODO: Only for some types!  	// filter parameter -	node = _cfg.self.getSingleNode("FilterParameter"); -	if (node) -	{ -		float fParameter = node.getContentNumerical(); -		c.m_fParameter = fParameter; -	} -	else -	{ -		c.m_fParameter = -1.0f; +	nodeName = "FilterParameter"; +	c.m_fParameter = -1.0f; +	switch (c.m_eType) { +	case FILTER_TUKEY: +	case FILTER_GAUSSIAN: +	case FILTER_BLACKMAN: +	case FILTER_KAISER: +		node = _cfg.self.getSingleNode(nodeName); +		if (_cfg.self.hasOption(nodeName)) { +			c.m_fParameter = _cfg.self.getOptionNumerical(nodeName); +			CC.markOptionParsed(nodeName); +		} else if (node) { +			c.m_fParameter = node.getContentNumerical(); +			CC.markNodeParsed(nodeName); +		} +		break; +	default: +		break;  	} -	CC.markNodeParsed("FilterParameter"); // TODO: Only for some types!  	// D value -	node = _cfg.self.getSingleNode("FilterD"); -	if (node) -	{ -		float fD = node.getContentNumerical(); -		c.m_fD = fD; -	} -	else -	{ -		c.m_fD = 1.0f; +	nodeName = "FilterD"; +	c.m_fD = 1.0f; +	switch (c.m_eType) { +	case FILTER_PROJECTION: +	case FILTER_SINOGRAM: +	case FILTER_RPROJECTION: +	case FILTER_RSINOGRAM: +		break; +	case FILTER_NONE: +	case FILTER_ERROR: +		break; +	default: +		node = _cfg.self.getSingleNode(nodeName); +		if (_cfg.self.hasOption(nodeName)) { +			c.m_fD = _cfg.self.getOptionNumerical(nodeName); +			CC.markOptionParsed(nodeName); +		} else if (node) { +			c.m_fD = node.getContentNumerical(); +			CC.markNodeParsed(nodeName); +		} +		break;  	} -	CC.markNodeParsed("FilterD"); // TODO: Only for some types! -  	return c;  }  | 
