From b2fc6c70434674d74551c3a6c01ffb3233499312 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Mon, 1 Jul 2013 22:34:11 +0000 Subject: Update version to 1.3 --- include/astra/Algorithm.h | 135 +++ include/astra/AlgorithmTypelist.h | 108 +++ include/astra/ArtAlgorithm.h | 196 +++++ include/astra/AstraObjectFactory.h | 149 ++++ include/astra/AstraObjectManager.h | 290 +++++++ include/astra/AsyncAlgorithm.h | 128 +++ include/astra/BackProjectionAlgorithm.h | 155 ++++ include/astra/CglsAlgorithm.h | 182 ++++ include/astra/ConeProjectionGeometry3D.h | 213 +++++ include/astra/ConeVecProjectionGeometry3D.h | 154 ++++ include/astra/Config.h | 80 ++ include/astra/CudaBackProjectionAlgorithm.h | 110 +++ include/astra/CudaBackProjectionAlgorithm3D.h | 152 ++++ include/astra/CudaCglsAlgorithm.h | 122 +++ include/astra/CudaCglsAlgorithm3D.h | 173 ++++ include/astra/CudaDartMaskAlgorithm.h | 126 +++ include/astra/CudaDartMaskAlgorithm3D.h | 122 +++ include/astra/CudaDartSmoothingAlgorithm.h | 125 +++ include/astra/CudaDartSmoothingAlgorithm3D.h | 122 +++ include/astra/CudaDataOperationAlgorithm.h | 128 +++ include/astra/CudaEMAlgorithm.h | 92 ++ include/astra/CudaFDKAlgorithm3D.h | 164 ++++ .../astra/CudaFilteredBackProjectionAlgorithm.h | 94 ++ include/astra/CudaForwardProjectionAlgorithm.h | 169 ++++ include/astra/CudaForwardProjectionAlgorithm3D.h | 135 +++ include/astra/CudaProjector2D.h | 122 +++ include/astra/CudaProjector3D.h | 131 +++ include/astra/CudaReconstructionAlgorithm2D.h | 176 ++++ include/astra/CudaRoiSelectAlgorithm.h | 123 +++ include/astra/CudaSartAlgorithm.h | 112 +++ include/astra/CudaSirtAlgorithm.h | 131 +++ include/astra/CudaSirtAlgorithm3D.h | 187 ++++ include/astra/DataProjector.h | 327 +++++++ include/astra/DataProjectorPolicies.h | 382 ++++++++ include/astra/DataProjectorPolicies.inl | 855 ++++++++++++++++++ include/astra/FanFlatBeamLineKernelProjector2D.h | 194 +++++ include/astra/FanFlatBeamLineKernelProjector2D.inl | 740 ++++++++++++++++ include/astra/FanFlatBeamStripKernelProjector2D.h | 191 ++++ .../astra/FanFlatBeamStripKernelProjector2D.inl | 961 +++++++++++++++++++++ include/astra/FanFlatProjectionGeometry2D.h | 244 ++++++ include/astra/FanFlatVecProjectionGeometry2D.h | 155 ++++ include/astra/FilteredBackProjectionAlgorithm.h | 155 ++++ include/astra/Float32Data.h | 88 ++ include/astra/Float32Data2D.h | 544 ++++++++++++ include/astra/Float32Data3D.h | 199 +++++ include/astra/Float32Data3DMemory.h | 338 ++++++++ include/astra/Float32ProjectionData2D.h | 247 ++++++ include/astra/Float32ProjectionData3D.h | 257 ++++++ include/astra/Float32ProjectionData3DMemory.h | 218 +++++ include/astra/Float32VolumeData2D.h | 183 ++++ include/astra/Float32VolumeData3D.h | 265 ++++++ include/astra/Float32VolumeData3DMemory.h | 213 +++++ include/astra/ForwardProjectionAlgorithm.h | 225 +++++ include/astra/Fourier.h | 127 +++ include/astra/Globals.h | 309 +++++++ include/astra/Logger.h | 72 ++ include/astra/ParallelBeamBlobKernelProjector2D.h | 232 +++++ .../astra/ParallelBeamBlobKernelProjector2D.inl | 212 +++++ include/astra/ParallelBeamLineKernelProjector2D.h | 186 ++++ .../astra/ParallelBeamLineKernelProjector2D.inl | 731 ++++++++++++++++ .../astra/ParallelBeamLinearKernelProjector2D.h | 194 +++++ .../astra/ParallelBeamLinearKernelProjector2D.inl | 416 +++++++++ include/astra/ParallelBeamStripKernelProjector2D.h | 191 ++++ .../astra/ParallelBeamStripKernelProjector2D.inl | 739 ++++++++++++++++ include/astra/ParallelProjectionGeometry2D.h | 153 ++++ include/astra/ParallelProjectionGeometry3D.h | 165 ++++ include/astra/ParallelVecProjectionGeometry3D.h | 157 ++++ include/astra/PlatformDepSystemCode.h | 83 ++ include/astra/ProjectionGeometry2D.h | 373 ++++++++ include/astra/ProjectionGeometry3D.h | 589 +++++++++++++ include/astra/Projector2D.h | 204 +++++ include/astra/Projector2DImpl.inl | 37 + include/astra/Projector3D.h | 185 ++++ include/astra/ProjectorTypelist.h | 104 +++ include/astra/ReconstructionAlgorithm2D.h | 222 +++++ include/astra/ReconstructionAlgorithm3D.h | 223 +++++ include/astra/SartAlgorithm.h | 226 +++++ include/astra/Singleton.h | 87 ++ include/astra/SirtAlgorithm.h | 217 +++++ include/astra/SparseMatrix.h | 144 +++ include/astra/SparseMatrixProjectionGeometry2D.h | 154 ++++ include/astra/SparseMatrixProjector2D.h | 210 +++++ include/astra/SparseMatrixProjector2D.inl | 90 ++ include/astra/TypeList.h | 236 +++++ include/astra/Utilities.h | 131 +++ include/astra/Vector3D.h | 131 +++ include/astra/VolumeGeometry2D.h | 608 +++++++++++++ include/astra/VolumeGeometry3D.h | 842 ++++++++++++++++++ include/astra/XMLDocument.h | 101 +++ include/astra/XMLNode.h | 325 +++++++ include/astra/jama_wrapper.h | 35 + include/astra/swrap.h | 41 + 92 files changed, 21069 insertions(+) create mode 100644 include/astra/Algorithm.h create mode 100644 include/astra/AlgorithmTypelist.h create mode 100644 include/astra/ArtAlgorithm.h create mode 100644 include/astra/AstraObjectFactory.h create mode 100644 include/astra/AstraObjectManager.h create mode 100644 include/astra/AsyncAlgorithm.h create mode 100644 include/astra/BackProjectionAlgorithm.h create mode 100644 include/astra/CglsAlgorithm.h create mode 100644 include/astra/ConeProjectionGeometry3D.h create mode 100644 include/astra/ConeVecProjectionGeometry3D.h create mode 100644 include/astra/Config.h create mode 100644 include/astra/CudaBackProjectionAlgorithm.h create mode 100644 include/astra/CudaBackProjectionAlgorithm3D.h create mode 100644 include/astra/CudaCglsAlgorithm.h create mode 100644 include/astra/CudaCglsAlgorithm3D.h create mode 100644 include/astra/CudaDartMaskAlgorithm.h create mode 100644 include/astra/CudaDartMaskAlgorithm3D.h create mode 100644 include/astra/CudaDartSmoothingAlgorithm.h create mode 100644 include/astra/CudaDartSmoothingAlgorithm3D.h create mode 100644 include/astra/CudaDataOperationAlgorithm.h create mode 100644 include/astra/CudaEMAlgorithm.h create mode 100644 include/astra/CudaFDKAlgorithm3D.h create mode 100644 include/astra/CudaFilteredBackProjectionAlgorithm.h create mode 100644 include/astra/CudaForwardProjectionAlgorithm.h create mode 100644 include/astra/CudaForwardProjectionAlgorithm3D.h create mode 100644 include/astra/CudaProjector2D.h create mode 100644 include/astra/CudaProjector3D.h create mode 100644 include/astra/CudaReconstructionAlgorithm2D.h create mode 100644 include/astra/CudaRoiSelectAlgorithm.h create mode 100644 include/astra/CudaSartAlgorithm.h create mode 100644 include/astra/CudaSirtAlgorithm.h create mode 100644 include/astra/CudaSirtAlgorithm3D.h create mode 100644 include/astra/DataProjector.h create mode 100644 include/astra/DataProjectorPolicies.h create mode 100644 include/astra/DataProjectorPolicies.inl create mode 100644 include/astra/FanFlatBeamLineKernelProjector2D.h create mode 100644 include/astra/FanFlatBeamLineKernelProjector2D.inl create mode 100644 include/astra/FanFlatBeamStripKernelProjector2D.h create mode 100644 include/astra/FanFlatBeamStripKernelProjector2D.inl create mode 100644 include/astra/FanFlatProjectionGeometry2D.h create mode 100644 include/astra/FanFlatVecProjectionGeometry2D.h create mode 100644 include/astra/FilteredBackProjectionAlgorithm.h create mode 100644 include/astra/Float32Data.h create mode 100644 include/astra/Float32Data2D.h create mode 100644 include/astra/Float32Data3D.h create mode 100644 include/astra/Float32Data3DMemory.h create mode 100644 include/astra/Float32ProjectionData2D.h create mode 100644 include/astra/Float32ProjectionData3D.h create mode 100644 include/astra/Float32ProjectionData3DMemory.h create mode 100644 include/astra/Float32VolumeData2D.h create mode 100644 include/astra/Float32VolumeData3D.h create mode 100644 include/astra/Float32VolumeData3DMemory.h create mode 100644 include/astra/ForwardProjectionAlgorithm.h create mode 100644 include/astra/Fourier.h create mode 100644 include/astra/Globals.h create mode 100644 include/astra/Logger.h create mode 100644 include/astra/ParallelBeamBlobKernelProjector2D.h create mode 100644 include/astra/ParallelBeamBlobKernelProjector2D.inl create mode 100644 include/astra/ParallelBeamLineKernelProjector2D.h create mode 100644 include/astra/ParallelBeamLineKernelProjector2D.inl create mode 100644 include/astra/ParallelBeamLinearKernelProjector2D.h create mode 100644 include/astra/ParallelBeamLinearKernelProjector2D.inl create mode 100644 include/astra/ParallelBeamStripKernelProjector2D.h create mode 100644 include/astra/ParallelBeamStripKernelProjector2D.inl create mode 100644 include/astra/ParallelProjectionGeometry2D.h create mode 100644 include/astra/ParallelProjectionGeometry3D.h create mode 100644 include/astra/ParallelVecProjectionGeometry3D.h create mode 100644 include/astra/PlatformDepSystemCode.h create mode 100644 include/astra/ProjectionGeometry2D.h create mode 100644 include/astra/ProjectionGeometry3D.h create mode 100644 include/astra/Projector2D.h create mode 100644 include/astra/Projector2DImpl.inl create mode 100644 include/astra/Projector3D.h create mode 100644 include/astra/ProjectorTypelist.h create mode 100644 include/astra/ReconstructionAlgorithm2D.h create mode 100644 include/astra/ReconstructionAlgorithm3D.h create mode 100644 include/astra/SartAlgorithm.h create mode 100644 include/astra/Singleton.h create mode 100644 include/astra/SirtAlgorithm.h create mode 100644 include/astra/SparseMatrix.h create mode 100644 include/astra/SparseMatrixProjectionGeometry2D.h create mode 100644 include/astra/SparseMatrixProjector2D.h create mode 100644 include/astra/SparseMatrixProjector2D.inl create mode 100644 include/astra/TypeList.h create mode 100644 include/astra/Utilities.h create mode 100644 include/astra/Vector3D.h create mode 100644 include/astra/VolumeGeometry2D.h create mode 100644 include/astra/VolumeGeometry3D.h create mode 100644 include/astra/XMLDocument.h create mode 100644 include/astra/XMLNode.h create mode 100644 include/astra/jama_wrapper.h create mode 100644 include/astra/swrap.h (limited to 'include') diff --git a/include/astra/Algorithm.h b/include/astra/Algorithm.h new file mode 100644 index 0000000..d4c73f9 --- /dev/null +++ b/include/astra/Algorithm.h @@ -0,0 +1,135 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_ALGORITHM +#define _INC_ASTRA_ALGORITHM + +#include + +#include "Globals.h" +#include "Config.h" + +namespace astra { + +/** + * This class contains the interface for an algorithm implementation. + */ +class _AstraExport CAlgorithm { + +public: + + /** Default constructor, containing no code. + */ + CAlgorithm(); + + /** Destructor. + */ + virtual ~CAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg) = 0; + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0) = 0; + + /** Has this class been initialized? + * + * @return initialized + */ + bool isInitialized(); + + /** get a description of the class + * + * @return description string + */ + virtual std::string description() const; + + /** Signal the algorithm it should abort soon. + * This is intended to be called from a different thread + * while the algorithm is running. There are no guarantees + * on how soon the algorithm will abort. The state of the + * algorithm object will be consistent (so it is safe to delete it + * normally afterwards), but the algorithm's output is undefined. + * + * Note that specific algorithms may give guarantees on their + * state after an abort. Check their documentation for details. + */ + virtual void signalAbort() { m_bShouldAbort = true; } + +protected: + + //< Has this class been initialized? + bool m_bIsInitialized; + + //< If this is set, the algorithm should try to abort as soon as possible. + volatile bool m_bShouldAbort; + +private: + /** + * Private copy constructor to prevent CAlgorithms from being copied. + */ + CAlgorithm(const CAlgorithm&); + + /** + * Private assignment operator to prevent CAlgorithms from being copied. + */ + CAlgorithm& operator=(const CAlgorithm&); + + //< For Config unused argument checking + ConfigCheckData* configCheckData; + friend class ConfigStackCheck; + +}; + +// inline functions +inline std::string CAlgorithm::description() const { return "Algorithm"; }; +inline bool CAlgorithm::isInitialized() { return m_bIsInitialized; } + +} // end namespace + +#endif diff --git a/include/astra/AlgorithmTypelist.h b/include/astra/AlgorithmTypelist.h new file mode 100644 index 0000000..615c143 --- /dev/null +++ b/include/astra/AlgorithmTypelist.h @@ -0,0 +1,108 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_ALGORITHMTYPELIST +#define _INC_ASTRA_ALGORITHMTYPELIST + +#include "Algorithm.h" +#include "TypeList.h" + +#include "ArtAlgorithm.h" +#include "SirtAlgorithm.h" +#include "SartAlgorithm.h" +#include "ForwardProjectionAlgorithm.h" +#include "BackProjectionAlgorithm.h" +#include "FilteredBackProjectionAlgorithm.h" +#include "CudaBackProjectionAlgorithm.h" +#include "CudaSartAlgorithm.h" +#include "CudaSirtAlgorithm.h" +#include "CudaCglsAlgorithm.h" +#include "CudaEMAlgorithm.h" +#include "CudaForwardProjectionAlgorithm.h" +#include "CglsAlgorithm.h" +#include "CudaCglsAlgorithm3D.h" +#include "CudaSirtAlgorithm3D.h" +#include "CudaForwardProjectionAlgorithm3D.h" +#include "CudaBackProjectionAlgorithm3D.h" +#include "CudaFDKAlgorithm3D.h" +#include "CudaDartMaskAlgorithm.h" +#include "CudaDartMaskAlgorithm3D.h" +#include "CudaDartSmoothingAlgorithm.h" +#include "CudaDartSmoothingAlgorithm3D.h" +#include "CudaDataOperationAlgorithm.h" +#include "CudaRoiSelectAlgorithm.h" + +using namespace astra; + +#ifdef ASTRA_CUDA + +#include "CudaFilteredBackProjectionAlgorithm.h" + +typedef TYPELIST_25( + CArtAlgorithm, + CSartAlgorithm, + CSirtAlgorithm, + CCglsAlgorithm, + CBackProjectionAlgorithm, + CForwardProjectionAlgorithm, + CCudaSartAlgorithm, + CFilteredBackProjectionAlgorithm, + CCudaBackProjectionAlgorithm, + CCudaDartMaskAlgorithm, + CCudaDartMaskAlgorithm3D, + CCudaDartSmoothingAlgorithm, + CCudaDartSmoothingAlgorithm3D, + CCudaDataOperationAlgorithm, + CCudaRoiSelectAlgorithm, + CCudaSirtAlgorithm, + CCudaCglsAlgorithm, + CCudaEMAlgorithm, + CCudaForwardProjectionAlgorithm, + CCudaCglsAlgorithm3D, + CCudaFilteredBackProjectionAlgorithm, + CCudaFDKAlgorithm3D, + CCudaSirtAlgorithm3D, + CCudaForwardProjectionAlgorithm3D, + CCudaBackProjectionAlgorithm3D + ) + AlgorithmTypeList; +#else + +typedef TYPELIST_7( + CArtAlgorithm, + CSartAlgorithm, + CSirtAlgorithm, + CCglsAlgorithm, + CBackProjectionAlgorithm, + CForwardProjectionAlgorithm, + CFilteredBackProjectionAlgorithm + ) AlgorithmTypeList; + +#endif + +#endif diff --git a/include/astra/ArtAlgorithm.h b/include/astra/ArtAlgorithm.h new file mode 100644 index 0000000..bd02fc4 --- /dev/null +++ b/include/astra/ArtAlgorithm.h @@ -0,0 +1,196 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_ARTALGORITHM +#define _INC_ASTRA_ARTALGORITHM + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" +#include "ReconstructionAlgorithm2D.h" + +#include "Projector2D.h" +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + +namespace astra { + +/** + * This class contains the implementation of the ART (Algebraic Reconstruction Technique) algorithm. + * + * The update step of pixel \f$v_j\f$ for ray \f$i\f$ and iteration \f$k\f$ is given by: + * \f[ + * v_j^{(k+1)} = v_j^{(k)} + \lambda \frac{p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}}{\sum_{k=1}^{N} w_{ik}^2} + * \f] + * + * \par XML Configuration + * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.} + * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.} + * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.} + * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.} + * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.} + * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.} + * \astra_xml_item_option{Lamda, float, 1, The relaxation factor.} + * \astra_xml_item_option{RayOrder, string, "sequential", the order in which the rays are updated. 'sequential' or 'custom'} + * \astra_xml_item_option{RayOrderList, n by 2 vector of float, not used, if RayOrder='custom': use this ray order. Each row consist of a projection id and detector id.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('ART');\n + * cfg.ProjectorId = proj_id;\n + * cfg.ProjectionDataId = sino_id;\n + * cfg.ReconstructionDataId = recon_id;\n + * cfg.option.MaskId = mask_id;\n + * cfg.option.UseMinConstraint = 'yes';\n + * cfg.option.UseMaxConstraint = 'yes';\n + * cfg.option.MaxConstraintValue = 1024;\n + * cfg.option.Lamda = 0.7;\n + * cfg.option.RayOrder = 'custom';\n + * cfg.option.RayOrderList = [0\,0; 0\,2; 1\,0];\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('iterate'\, alg_id\, 1000);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + */ +class _AstraExport CArtAlgorithm : public CReconstructionAlgorithm2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - the projector is compatible with both data objects + * - the ray order list only contains valid values + */ + virtual bool _check(); + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CArtAlgorithm(); + + /** Destructor. + */ + virtual ~CArtAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class, use sequential ray order. + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Clear this class. + */ + virtual void clear(); + + /** Set the relaxation factor. + * + * @param _fLambda Relaxation factor + */ + void setLambda(float32 _fLambda); + + /** Set the order in which the rays will be selected + * + * @param _piProjectionOrder Order of the rays, the projections. (size should be _piRayCount) + * @param _piDetectorOrder Order of the rays, the detectors. (size should be _piRayCount) + * @param _piRayCount Number of rays in the two previous arrays. + */ + void setRayOrder(int* _piProjectionOrder, int* _piDetectorOrder, int _piRayCount); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + +protected: + + //< Relaxation Factor + float32 m_fLambda; + + //< Order of the rays, the projections. + int* m_piProjectionOrder; + //< Order of the rays, the detectors. + int* m_piDetectorOrder; + //< Number of rays specified in the ray order arrays. + int m_iRayCount; + //< Current index in the ray order arrays. + int m_iCurrentRay; + +}; + +// inline functions +inline std::string CArtAlgorithm::description() const { return CArtAlgorithm::type; }; + + +} // end namespace + +#endif diff --git a/include/astra/AstraObjectFactory.h b/include/astra/AstraObjectFactory.h new file mode 100644 index 0000000..784d698 --- /dev/null +++ b/include/astra/AstraObjectFactory.h @@ -0,0 +1,149 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_ASTRAOBJECTFACTORY +#define _INC_ASTRA_ASTRAOBJECTFACTORY + +#include "Globals.h" +#include "Config.h" +#include "Singleton.h" +#include "Utilities.h" +#include "TypeList.h" + +#include "ProjectorTypelist.h" + + +#include "AlgorithmTypelist.h" + + +namespace astra { + +/** + * This class contains functionality to create data objects based on their type or on a configuration object. + */ +template +class CAstraObjectFactory : public Singleton > { + +public: + + /** A default constructor that contains not a single line of code. + */ + CAstraObjectFactory(); + + /** Destructor. + */ + ~CAstraObjectFactory(); + + /** Create, but don't initialize, a new projector object. + * + * @param _sType Type of the new projector. + * @return Pointer to a new, unitialized projector. + */ + T* create(std::string _sType); + + /** Create and initialize a new projector object. + * + * @param _cfg Configuration object to create and initialize a new projector. + * @return Pointer to a new, initialized projector. + */ + T* create(const Config& _cfg); + + +}; + + +//---------------------------------------------------------------------------------------- +// Constructor +template +CAstraObjectFactory::CAstraObjectFactory() +{ + +} + +//---------------------------------------------------------------------------------------- +// Destructor +template +CAstraObjectFactory::~CAstraObjectFactory() +{ + +} + +//---------------------------------------------------------------------------------------- +// Create +template +T* CAstraObjectFactory::create(std::string _sType) +{ + functor_find finder = functor_find(); + finder.tofind = _sType; + CreateObject::find(finder); + return finder.res; +} + +//---------------------------------------------------------------------------------------- +// Create with XML +template +T* CAstraObjectFactory::create(const Config& _cfg) +{ + functor_find finder = functor_find(); + finder.tofind = _cfg.self->getAttribute("type"); + CreateObject::find(finder); + if (finder.res == NULL) return NULL; + if (finder.res->initialize(_cfg)) + return finder.res; + + delete finder.res; + return NULL; +} +//---------------------------------------------------------------------------------------- + + + + +//---------------------------------------------------------------------------------------- +// Create the necessary Object Managers +/** + * Class used to create algorithms from a string or a config object +*/ +class _AstraExport CAlgorithmFactory : public CAstraObjectFactory {}; + +/** + * Class used to create 2D projectors from a string or a config object +*/ +class _AstraExport CProjector2DFactory : public CAstraObjectFactory {}; + +/** + * Class used to create 3D projectors from a string or a config object +*/ +class _AstraExport CProjector3DFactory : public CAstraObjectFactory {}; + + + + +} // end namespace + +#endif diff --git a/include/astra/AstraObjectManager.h b/include/astra/AstraObjectManager.h new file mode 100644 index 0000000..afb6312 --- /dev/null +++ b/include/astra/AstraObjectManager.h @@ -0,0 +1,290 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_ASTRAOBJECTMANAGER +#define _INC_ASTRA_ASTRAOBJECTMANAGER + +#include +#include + +#include "Globals.h" +#include "Singleton.h" +#include "Projector2D.h" +#include "Projector3D.h" +#include "Float32Data2D.h" +#include "Float32Data3D.h" +#include "SparseMatrix.h" +#include "Algorithm.h" + +namespace astra { + +/** + * This class contains functionality to store objects. A unique index handle + * will be assigned to each data object by which it can be accessed in the + * future. Indices are always >= 1. + * + * We store them in a special common base class to make indices unique + * among all ObjectManagers. + */ + + +class CAstraIndexManager { +protected: + /** The index of the previously stored data object. + */ + static int m_iPreviousIndex; +}; + + +template +class CAstraObjectManager : public Singleton >, CAstraIndexManager { + +public: + + /** Default constructor. + */ + CAstraObjectManager(); + + /** Destructor. + */ + ~CAstraObjectManager(); + + /** Store the object in the manager and assign a unique index handle to it. + * + * @param _pObject A pointer to the object that should be stored. + * @return The index of the stored data object. If the index in negative, an error occurred + * and the object was NOT stored. + */ + int store(T* _pObject); + + /** Does the manager contain an object with the index _iIndex? + * + * @param _iIndex Index handle to the data object in question. + * @return True if the manager contains an object with the index handle _iIndex. + */ + bool hasIndex(int _iIndex) const; + + /** Fetch the object to which _iIndex refers to. + * + * @param _iIndex Index handle to the data object in question. + * @return Pointer to the stored data object. A null pointer is returned if no object with index _iIndex is found. + */ + T* get(int _iIndex) const; + + /** Delete an object that was previously stored. This actually DELETES the objecy. Therefore, after this + * function call, the object in question will have passed on. It will be no more. It will have ceased + * to be. It will be expired and will go to meet its maker. Bereft of life, it will rest in peace. + * It will be an EX-OBJECT. + * + * @param _iIndex Index handle to the object in question. + * @return Error code. 0 for success. + */ + void remove(int _iIndex); + + /** Get the index of the object, zero if it doesn't exist. + * + * @param _pObject The data object. + * @return Index of the stored object, 0 if not found. + */ + int getIndex(const T* _pObject) const; + + /** Clear all data. This will also delete all the content of each object. + */ + void clear(); + + /** Get info. + */ + std::string info(); + +protected: + + /** Map each data object to a unique index. + */ + std::map m_mIndexToObject; + +}; + +//---------------------------------------------------------------------------------------- +// Constructor +template +CAstraObjectManager::CAstraObjectManager() +{ +} + +//---------------------------------------------------------------------------------------- +// Destructor +template +CAstraObjectManager::~CAstraObjectManager() +{ + +} + +//---------------------------------------------------------------------------------------- +// store data +template +int CAstraObjectManager::store(T* _pDataObject) +{ + m_iPreviousIndex++; + m_mIndexToObject[m_iPreviousIndex] = _pDataObject; + return m_iPreviousIndex; +} + +//---------------------------------------------------------------------------------------- +// has data? +template +bool CAstraObjectManager::hasIndex(int _iIndex) const +{ + typename map::const_iterator it = m_mIndexToObject.find(_iIndex); + return it != m_mIndexToObject.end(); +} + +//---------------------------------------------------------------------------------------- +// get data +template +T* CAstraObjectManager::get(int _iIndex) const +{ + typename map::const_iterator it = m_mIndexToObject.find(_iIndex); + if (it != m_mIndexToObject.end()) + return it->second; + else + return 0; +} + +//---------------------------------------------------------------------------------------- +// delete data +template +void CAstraObjectManager::remove(int _iIndex) +{ + if (!hasIndex(_iIndex)) { + return; + } + // find data + typename map::iterator it = m_mIndexToObject.find(_iIndex); + // delete data + delete (*it).second; + // delete from map + m_mIndexToObject.erase(it); +} + +//---------------------------------------------------------------------------------------- +// Get Index +template +int CAstraObjectManager::getIndex(const T* _pObject) const +{ + for (typename map::const_iterator it = m_mIndexToObject.begin(); it != m_mIndexToObject.end(); it++) { + if ((*it).second == _pObject) return (*it).first; + } + return 0; +} + + +//---------------------------------------------------------------------------------------- +// clear +template +void CAstraObjectManager::clear() +{ + for (typename map::iterator it = m_mIndexToObject.begin(); it != m_mIndexToObject.end(); it++) { + // delete data + delete (*it).second; + (*it).second = 0; + } + + m_mIndexToObject.clear(); +} + +//---------------------------------------------------------------------------------------- +// Print info to string +template +std::string CAstraObjectManager::info() { + std::stringstream res; + res << "id init description" << std::endl; + res << "-----------------------------------------" << std::endl; + for (typename map::iterator it = m_mIndexToObject.begin(); it != m_mIndexToObject.end(); it++) { + res << (*it).first << " \t"; + T* pObject = m_mIndexToObject[(*it).first]; + if (pObject->isInitialized()) { + res << "v "; + } else { + res << "x "; + } + res << pObject->description() << endl; + } + res << "-----------------------------------------" << std::endl; + return res.str(); +} + + + +//---------------------------------------------------------------------------------------- +// Create the necessary Object Managers +/** + * This class contains functionality to store 2D projector objects. A unique index handle will be + * assigned to each data object by which it can be accessed in the future. + * Indices are always >= 1. + */ +class _AstraExport CProjector2DManager : public CAstraObjectManager{}; + +/** + * This class contains functionality to store 3D projector objects. A unique index handle will be + * assigned to each data object by which it can be accessed in the future. + * Indices are always >= 1. + */ +class _AstraExport CProjector3DManager : public CAstraObjectManager{}; + +/** + * This class contains functionality to store 2D data objects. A unique index handle will be + * assigned to each data object by which it can be accessed in the future. + * Indices are always >= 1. + */ +class _AstraExport CData2DManager : public CAstraObjectManager{}; + +/** + * This class contains functionality to store 3D data objects. A unique index handle will be + * assigned to each data object by which it can be accessed in the future. + * Indices are always >= 1. + */ +class _AstraExport CData3DManager : public CAstraObjectManager{}; + +/** + * This class contains functionality to store algorithm objects. A unique index handle will be + * assigned to each data object by which it can be accessed in the future. + * Indices are always >= 1. + */ +class _AstraExport CAlgorithmManager : public CAstraObjectManager{}; + +/** + * This class contains functionality to store matrix objects. A unique index handle will be + * assigned to each data object by which it can be accessed in the future. + * Indices are always >= 1. + */ +class _AstraExport CMatrixManager : public CAstraObjectManager{}; + + +} // end namespace + +#endif diff --git a/include/astra/AsyncAlgorithm.h b/include/astra/AsyncAlgorithm.h new file mode 100644 index 0000000..64f70c3 --- /dev/null +++ b/include/astra/AsyncAlgorithm.h @@ -0,0 +1,128 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_ASYNCALGORITHM +#define _INC_ASTRA_ASYNCALGORITHM + +#include "Config.h" +#include "Algorithm.h" + +#ifdef __linux__ +#define USE_PTHREADS +#include +#else +#include +#endif + + +namespace astra { + +/** + * \brief + * This class contains an wrapper algorithm that allows termination of its wrapped algorithm. + * + * This is used to allow algorithm termination from matlab command line. + */ + +class _AstraExport CAsyncAlgorithm : public CAlgorithm { +public: + /** Default constructor, containing no code. + */ + CAsyncAlgorithm(); + + /** Constructor. + */ + explicit CAsyncAlgorithm(CAlgorithm* _pAlg); + + /** Destructor. + */ + virtual ~CAsyncAlgorithm(); + + /** Initialize using config object. + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize using algorithm pointer. + */ + virtual bool initialize(CAlgorithm* _pAlg); + + /** Run the algorithm. + */ + virtual void run(int _iNrIterations = 0); + + /** Wait for thread to complete and delete thread. + */ + virtual void timedJoin(int _milliseconds); + + /** Return pointer to the wrapped algorithm. + */ + CAlgorithm* getWrappedAlgorithm() { return m_pAlg; } + + /** Is the wrapped algorithm done. + */ + bool isDone() const { return m_bDone; } + + /** Signal abort to the wrapped algorithm. + */ + void signalAbort(); + +protected: + //< Has this class been initialized? + bool m_bInitialized; + + //< Should wrapped algorithm be deleted after completion? + bool m_bAutoFree; + + //< Pointer to wrapped algorithm. + CAlgorithm* m_pAlg; + + //< Is the wrapped algorithm done. + volatile bool m_bDone; + +#ifndef USE_PTHREADS + //< Handle to boost thread object running the wrapped algorithm. + boost::thread* m_pThread; +#else + pthread_t m_thread; + struct AsyncThreadInfo { + int m_iIterations; + CAlgorithm* m_pAlg; + volatile bool* m_pDone; + } m_ThreadInfo; + friend void* runAsync_pthreads(void*); +#endif + bool m_bThreadStarted; + + //< Run the wrapped algorithm. + void runWrapped(int _iNrIterations); + +}; + +} + +#endif diff --git a/include/astra/BackProjectionAlgorithm.h b/include/astra/BackProjectionAlgorithm.h new file mode 100644 index 0000000..d50b406 --- /dev/null +++ b/include/astra/BackProjectionAlgorithm.h @@ -0,0 +1,155 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_BACKPROJECTIONALGORITHM +#define _INC_ASTRA_BACKPROJECTIONALGORITHM + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" +#include "ReconstructionAlgorithm2D.h" + +#include "Projector2D.h" +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + +#include "DataProjector.h" + +namespace astra { + +/** + * \brief + * This class performs an unfiltered backprojection. + * + * \par XML Configuration + * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.} + * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.} + * + */ +class _AstraExport CBackProjectionAlgorithm : public CReconstructionAlgorithm2D { + +protected: + + /** Init stuff + */ + virtual void _init(); + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - valid projector + * - valid data objects + */ + virtual bool _check(); + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CBackProjectionAlgorithm(); + + /** Default constructor + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + */ + CBackProjectionAlgorithm(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Destructor. + */ + virtual ~CBackProjectionAlgorithm(); + + /** Clear this class. + */ + virtual void clear(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return Initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @return Initialization successful? + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Get all information parameters. + * + * @return Map with all available identifier strings and their values. + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier Identifier string to specify which piece of information you want. + * @return One piece of information. + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + +}; + +// inline functions +inline std::string CBackProjectionAlgorithm::description() const { return CBackProjectionAlgorithm::type; }; + + +} // end namespace + +#endif diff --git a/include/astra/CglsAlgorithm.h b/include/astra/CglsAlgorithm.h new file mode 100644 index 0000000..1700d74 --- /dev/null +++ b/include/astra/CglsAlgorithm.h @@ -0,0 +1,182 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CGLSALGORITHM +#define _INC_ASTRA_CGLSALGORITHM + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" +#include "ReconstructionAlgorithm2D.h" + +#include "Projector2D.h" +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + +#include "DataProjector.h" + +namespace astra { + +/** + * \brief + * This class contains the implementation of the CGLS (Conguent Gradient Algorithm) algorithm. + * + * \par XML Configuration + * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 0 = reconstruct on this pixel. 1 = don't reconstruct on this pixel.} + * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 0 = reconstruct using this ray. 1 = don't use this ray while reconstructing.} + * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.} + * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.} + * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.} + * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('CGLS');\n + * cfg.ProjectorId = proj_id;\n + * cfg.ProjectionDataId = sino_id;\n + * cfg.ReconstructionDataId = recon_id;\n + * cfg.option.MaskId = mask_id;\n + * cfg.option.UseMinConstraint = 'yes';\n + * cfg.option.UseMaxConstraint = 'yes';\n + * cfg.option.MaxConstraintValue = 1024;\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('iterate'\, alg_id\, 10);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + * + */ +class _AstraExport CCglsAlgorithm : public CReconstructionAlgorithm2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - valid projector + * - valid data objects + */ + virtual bool _check(); + + CFloat32ProjectionData2D* r; + CFloat32ProjectionData2D* w; + CFloat32VolumeData2D* z; + CFloat32VolumeData2D* p; + + float32 alpha; + float32 beta; + float32 gamma; + + + int m_iIteration; + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCglsAlgorithm(); + + /** Default constructor + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + */ + CCglsAlgorithm(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Destructor. + */ + virtual ~CCglsAlgorithm(); + + /** Clear this class. + */ + virtual void clear(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return Initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @return Initialization successful? + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Get all information parameters. + * + * @return Map with all available identifier strings and their values. + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier Identifier string to specify which piece of information you want. + * @return One piece of information. + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + +}; + +// inline functions +inline std::string CCglsAlgorithm::description() const { return CCglsAlgorithm::type; }; + + +} // end namespace + +#endif diff --git a/include/astra/ConeProjectionGeometry3D.h b/include/astra/ConeProjectionGeometry3D.h new file mode 100644 index 0000000..497ce7d --- /dev/null +++ b/include/astra/ConeProjectionGeometry3D.h @@ -0,0 +1,213 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CONEPROJECTIONGEOMETRY3D +#define _INC_ASTRA_CONEPROJECTIONGEOMETRY3D + +#include "ProjectionGeometry3D.h" + +namespace astra +{ + +/** + * This class defines a 3D cone beam projection geometry. + * + * \par XML Configuration + * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.} + * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.} + * \astra_xml_item{DetectorWidth, float, Width of each detector.} + * \astra_xml_item{DetectorHeight, float, Width of each detector.} + * \astra_xml_item{ProjectionAngles, vector of float, projection angles in radians.} + * \astra_xml_item{DistanceOriginDetector, float, Distance between the center of rotation and the detectorarray.} + * \astra_xml_item{DistanceOriginSource, float, Distance between the center of rotation the the x-ray source.} + * + * \par MATLAB example + * \astra_code{ + * proj_geom = astra_struct('cone');\n + * proj_geom.DetectorRowCount = 512;\n + * proj_geom.DetectorColCount = 512;\n + * proj_geom.DetectorWidth = 1.0;\n + * proj_geom.DetectorHeight = 1.0;\n + * proj_geom.ProjectionAngles = linspace(0,pi,100);\n + * proj_geom.DistanceOriginDetector = 10000;\n + * proj_geom.DistanceOriginSource = 10000;\n + * } + */ +class _AstraExport CConeProjectionGeometry3D : public CProjectionGeometry3D +{ +protected: + + /** + * Distance from the origin of the coordinate system to the source. + */ + float32 m_fOriginSourceDistance; + + /** + * Distance from the origin of the coordinate system to the detector (i.e., the distance between the origin and its orthogonal projection + * onto the detector array). + */ + float32 m_fOriginDetectorDistance; + +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the initialize() methods before the object can be used. Any use before calling initialize() + * is not allowed, except calling the member function isInitialized(). + */ + CConeProjectionGeometry3D(); + + /** Constructor. Create an instance of the CParallelProjectionGeometry3D class. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorRowCount Number of rows of detectors. + * @param _iDetectorColCount Number of columns detectors. + * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _fDetectorHeight Height of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles + * are represented in radians and lie in the [0,2pi[ interval. + */ + CConeProjectionGeometry3D(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + float32 _fDetectorWidth, + float32 _fDetectorHeight, + const float32* _pfProjectionAngles, + float32 _fOriginSourceDistance, + float32 _fOriginDetectorDistance); + + /** Copy constructor. + */ + CConeProjectionGeometry3D(const CConeProjectionGeometry3D& _projGeom); + + /** Destructor. + */ + ~CConeProjectionGeometry3D(); + + /** Initialize the geometry with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the geometry. If the object has been initialized before, the object is reinitialized + * and memory is freed and reallocated if necessary. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorRowCount Number of rows of detectors. + * @param _iDetectorColCount Number of columns detectors. + * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _fDetectorHeight Height of a detector cell, in unit lengths. All detector cells are assumed to have equal height. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles + * are represented in radians and lie in the [0,2pi[ interval. + */ + bool initialize(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + float32 _fDetectorWidth, + float32 _fDetectorHeight, + const float32* _pfProjectionAngles, + float32 _fOriginSourceDistance, + float32 _fOriginDetectorDistance); + + + /** Create a hard copy. + */ + virtual CProjectionGeometry3D* clone() const; + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(const CProjectionGeometry3D*) const; + + /** Returns true if the type of geometry defined in this class is the one specified in _sType. + * + * @param _sType geometry type to compare to. + * @return true if _sType == "cone". + */ + virtual bool isOfType(const std::string& _sType) const; + + /** Turn this object into an XML object. + * + * @param _sNode The XML object to fill. + */ + virtual void toXML(XMLNode* _sNode) const; + + /** Returns the distance from the origin of the coordinate system to the source. + * + * @return Distance from the origin of the coordinate system to the source + */ + float32 getOriginSourceDistance() const; + + /** Returns the distance from the origin of the coordinate system to the detector + * (i.e., the distance between the origin and its orthogonal projection onto the detector array). + * + * @return Distance from the origin of the coordinate system to the detector + */ + float32 getOriginDetectorDistance() const; + + /** Returns the distance from the source to the detector + * (i.e., the distance between the source and its orthogonal projection onto the detector array). + * + * @return Distance from the source to the detector + */ + float32 getSourceDetectorDistance() const; + + /** + * Returns a vector giving the projection direction for a projection and detector index + */ + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const; +}; + +// Returns the distance from the origin of the coordinate system to the source. +inline float32 CConeProjectionGeometry3D::getOriginSourceDistance() const +{ + return m_fOriginSourceDistance; +} + + +// Returns the distance from the origin of the coordinate system to the detector. +inline float32 CConeProjectionGeometry3D::getOriginDetectorDistance() const +{ + return m_fOriginDetectorDistance; +} + + +// Returns the distance from the source to the detector. +inline float32 CConeProjectionGeometry3D::getSourceDetectorDistance() const +{ + return (m_fOriginSourceDistance + m_fOriginDetectorDistance); +} + + +} // namespace astra + +#endif /* _INC_ASTRA_PARALLELPROJECTIONGEOMETRY3D */ diff --git a/include/astra/ConeVecProjectionGeometry3D.h b/include/astra/ConeVecProjectionGeometry3D.h new file mode 100644 index 0000000..1765cdd --- /dev/null +++ b/include/astra/ConeVecProjectionGeometry3D.h @@ -0,0 +1,154 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CONEVECPROJECTIONGEOMETRY3D +#define _INC_ASTRA_CONEVECPROJECTIONGEOMETRY3D + +#include "ProjectionGeometry3D.h" +#include "../cuda/3d/dims3d.h" + +namespace astra +{ + +/** + * This class defines a 3D cone beam projection geometry. + * + * \par XML Configuration + * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.} + * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.} + * \astra_xml_item{Vectors, matrix defining the 3D position of source and detector.} + * + * \par MATLAB example + * \astra_code{ + * proj_geom = astra_struct('cone_vec');\n + * proj_geom.DetectorRowCount = 512;\n + * proj_geom.DetectorColCount = 512;\n + * proj_geom.Vectors = V;\n + * } + * + * \par Vectors + * Vectors is a matrix containing the actual geometry. Each row corresponds + * to a single projection, and consists of: + * ( srcX, srcY, srcZ, dX, dY, dZ, uX, uY, uZ, vX, vY, vZ ) + * src: the ray source + * d : the corner of the detector + * u : the vector from detector pixel (0,0) to (0,1) + * v : the vector from detector pixel (0,0) to (1,0) + */ +class _AstraExport CConeVecProjectionGeometry3D : public CProjectionGeometry3D +{ +protected: + + SConeProjection *m_pProjectionAngles; + +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the initialize() methods before the object can be used. Any use before calling initialize() + * is not allowed, except calling the member function isInitialized(). + */ + CConeVecProjectionGeometry3D(); + + /** Constructor. Create an instance of the CConeVecProjectionGeometry3D class. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorRowCount Number of rows of detectors. + * @param _iDetectorColCount Number of columns detectors. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + */ + CConeVecProjectionGeometry3D(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + const SConeProjection* _pProjectionAngles); + + /** Copy constructor. + */ + CConeVecProjectionGeometry3D(const CConeVecProjectionGeometry3D& _projGeom); + + /** Destructor. + */ + ~CConeVecProjectionGeometry3D(); + + /** Initialize the geometry with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the geometry. If the object has been initialized before, the object is reinitialized + * and memory is freed and reallocated if necessary. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorRowCount Number of rows of detectors. + * @param _iDetectorColCount Number of columns detectors. + * @param _pProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + */ + bool initialize(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + const SConeProjection* _pProjectionAngles); + + virtual bool _check(); + + /** Create a hard copy. + */ + virtual CProjectionGeometry3D* clone() const; + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(const CProjectionGeometry3D*) const; + + /** Returns true if the type of geometry defined in this class is the one specified in _sType. + * + * @param _sType geometry type to compare to. + * @return true if _sType == "cone_vec". + */ + virtual bool isOfType(const std::string& _sType) const; + + /** Turn this object into an XML object. + * + * @param _sNode The XML object to fill. + */ + virtual void toXML(XMLNode* _sNode) const; + + /** + * Returns a vector giving the projection direction for a projection and detector index + */ + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const; + + const SConeProjection* getProjectionVectors() const { return m_pProjectionAngles; } +}; + +} // namespace astra + +#endif /* _INC_ASTRA_CONEVECPROJECTIONGEOMETRY3D */ diff --git a/include/astra/Config.h b/include/astra/Config.h new file mode 100644 index 0000000..5a629a2 --- /dev/null +++ b/include/astra/Config.h @@ -0,0 +1,80 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CONFIG +#define _INC_ASTRA_CONFIG + +#include "Globals.h" +#include "XMLNode.h" + +#include + +namespace astra { + + +/** + * Configuration options for an ASTRA class. + */ +struct _AstraExport Config { + + Config(); + Config(XMLNode* _self); + ~Config(); + + XMLNode* self; + XMLNode* global; +}; + +struct ConfigCheckData { + // For checking for unparsed nodes/options + std::set parsedNodes; + std::set parsedOptions; + unsigned int parseDepth; +}; + + +template +class ConfigStackCheck { +public: + ConfigStackCheck(const char *_name, T* _obj, const Config& _cfg); + ~ConfigStackCheck(); + + bool stopParsing(); // returns true if no unused nodes/options + void markNodeParsed(const std::string& name); + void markOptionParsed(const std::string& name); + + +private: + T* object; + const Config* cfg; + const char* name; +}; + +} // end namespace + +#endif diff --git a/include/astra/CudaBackProjectionAlgorithm.h b/include/astra/CudaBackProjectionAlgorithm.h new file mode 100644 index 0000000..965c734 --- /dev/null +++ b/include/astra/CudaBackProjectionAlgorithm.h @@ -0,0 +1,110 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDABACKPROJECTIONALGORITHM +#define _INC_ASTRA_CUDABACKPROJECTIONALGORITHM + +#include "Globals.h" +#include "Config.h" + +#include "CudaReconstructionAlgorithm2D.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +/** + * \brief + * This class contains a GPU implementation of backprojection. + * + * \par XML Configuration + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('BP_CUDA');\n + * cfg.ProjectionDataId = sino_id;\n + * cfg.ReconstructionDataId = recon_id;\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('iterate'\, alg_id\, 1);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + * + */ +class _AstraExport CCudaBackProjectionAlgorithm : public CCudaReconstructionAlgorithm2D +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaBackProjectionAlgorithm(); + + /** Destructor. + */ + virtual ~CCudaBackProjectionAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. (Ignored) + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @param _iGPUindex GPU to use. + * @param _iPixelSuperSampling Square root of number of samples per voxel, used to compute the backprojection + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction, + int _iGPUindex = 0, int _iPixelSuperSampling = 1); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; +}; + +// inline functions +inline std::string CCudaBackProjectionAlgorithm::description() const { return CCudaBackProjectionAlgorithm::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaBackProjectionAlgorithm3D.h b/include/astra/CudaBackProjectionAlgorithm3D.h new file mode 100644 index 0000000..b069da6 --- /dev/null +++ b/include/astra/CudaBackProjectionAlgorithm3D.h @@ -0,0 +1,152 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDABACKPROJECTIONALGORITHM3D +#define _INC_ASTRA_CUDABACKPROJECTIONALGORITHM3D + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" + +#include "Float32ProjectionData3DMemory.h" +#include "Float32VolumeData3DMemory.h" +#include "ReconstructionAlgorithm3D.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +class _AstraExport CCudaBackProjectionAlgorithm3D : public CReconstructionAlgorithm3D { + +protected: + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - the projector is compatible with both data objects + */ + virtual bool _check(); + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, does not initialize the object. + */ + CCudaBackProjectionAlgorithm3D(); + + /** Constructor with initialization. + * + * @param _pProjector Projector Object. + * @param _pProjectionData ProjectionData3D object containing the projection data. + * @param _pReconstruction VolumeData3D object for storing the reconstructed volume. + */ + CCudaBackProjectionAlgorithm3D(CProjector3D* _pProjector, + CFloat32ProjectionData3DMemory* _pProjectionData, + CFloat32VolumeData3DMemory* _pReconstruction); + + /** Copy constructor. + */ + CCudaBackProjectionAlgorithm3D(const CCudaBackProjectionAlgorithm3D&); + + /** Destructor. + */ + virtual ~CCudaBackProjectionAlgorithm3D(); + + /** Clear this class. + */ +/* virtual void clear();*/ + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. + * @param _pProjectionData ProjectionData3D object containing the projection data. + * @param _pReconstruction VolumeData3D object for storing the reconstructed volume. + * @return initialization successful? + */ + bool initialize(CProjector3D* _pProjector, + CFloat32ProjectionData3DMemory* _pSinogram, + CFloat32VolumeData3DMemory* _pReconstruction); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** + * Sets the index of the used GPU index: first GPU has index 0 + * + * @param _iGPUIndex New GPU index. + */ + void setGPUIndex(int _iGPUIndex); + +protected: + + int m_iGPUIndex; + int m_iVoxelSuperSampling; + +}; + +// inline functions +inline std::string CCudaBackProjectionAlgorithm3D::description() const { return CCudaBackProjectionAlgorithm3D::type; }; + +} // end namespace + +#endif + +#endif diff --git a/include/astra/CudaCglsAlgorithm.h b/include/astra/CudaCglsAlgorithm.h new file mode 100644 index 0000000..7734d6e --- /dev/null +++ b/include/astra/CudaCglsAlgorithm.h @@ -0,0 +1,122 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDACGLSALGORITHM +#define _INC_ASTRA_CUDACGLSALGORITHM + +#include "Globals.h" +#include "Config.h" + +#include "CudaReconstructionAlgorithm2D.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +/** + * \brief + * This class contains a GPU implementation of the CGLS algorithm. + * + * \par XML Configuration + * \astra_xml_item{ProjectionGeometry, integer, Geometry of the projection data.} + * \astra_xml_item{VolumeGeometry, integer, Geometry of the volume data.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 0 = reconstruct on this pixel. 1 = don't reconstruct on this pixel.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('CGLS_CUDA');\n + * cfg.ProjectionGeometry = proj_geom;\n + * cfg.VolumeGeometry = vol_geom;\n + * cfg.ProjectionDataId = sino_id;\n + * cfg.ReconstructionDataId = recon_id;\n + * cfg.option.ReconstructionMaskId = mask_id;\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('iterate'\, alg_id\, 10);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + * + */ + +class AstraCGLS; + +class _AstraExport CCudaCglsAlgorithm : public CCudaReconstructionAlgorithm2D +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaCglsAlgorithm(); + + /** Destructor. + */ + virtual ~CCudaCglsAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class, use sequential order. + * + * @param _pProjector Projector Object. (Ignored) + * @param _pSinogram ProjectionData2D object containing the sinogram + * @param _pReconstruction VolumeData2D for storing the reconstruction + * @param _iGPUindex Index of GPU to use. (Starting at 0.) + * @param _iDetectorSuperSampling Supersampling factor for the FP. + * @param _iPixelSuperSampling Square root of number of samples per voxel, used to compute the backprojection + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction, + int _iGPUindex = 0, int _iDetectorSuperSampling = 1, + int _iPixelSuperSampling = 1); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + +}; + +// inline functions +inline std::string CCudaCglsAlgorithm::description() const { return CCudaCglsAlgorithm::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaCglsAlgorithm3D.h b/include/astra/CudaCglsAlgorithm3D.h new file mode 100644 index 0000000..47b61af --- /dev/null +++ b/include/astra/CudaCglsAlgorithm3D.h @@ -0,0 +1,173 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDACGLSALGORITHM3D +#define _INC_ASTRA_CUDACGLSALGORITHM3D + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" + +#include "Float32ProjectionData3DMemory.h" +#include "Float32VolumeData3DMemory.h" +#include "ReconstructionAlgorithm3D.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +class AstraCGLS3d; + +/** + * \brief + * This class contains the 3D implementation of the CGLS algorithm + * + */ +class _AstraExport CCudaCglsAlgorithm3D : public CReconstructionAlgorithm3D { + +protected: + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - the projector is compatible with both data objects + */ + virtual bool _check(); + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, does not initialize the object. + */ + CCudaCglsAlgorithm3D(); + + /** Constructor with initialization. + * + * @param _pProjector Projector Object. + * @param _pProjectionData ProjectionData3D object containing the projection data. + * @param _pReconstruction VolumeData3D object for storing the reconstructed volume. + */ + CCudaCglsAlgorithm3D(CProjector3D* _pProjector, + CFloat32ProjectionData3DMemory* _pProjectionData, + CFloat32VolumeData3DMemory* _pReconstruction); + + /** Copy constructor. + */ + CCudaCglsAlgorithm3D(const CCudaCglsAlgorithm3D&); + + /** Destructor. + */ + virtual ~CCudaCglsAlgorithm3D(); + + /** Clear this class. + */ +/* virtual void clear();*/ + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. + * @param _pProjectionData ProjectionData3D object containing the projection data. + * @param _pReconstruction VolumeData3D object for storing the reconstructed volume. + * @return initialization successful? + */ + bool initialize(CProjector3D* _pProjector, + CFloat32ProjectionData3DMemory* _pSinogram, + CFloat32VolumeData3DMemory* _pReconstruction); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** + * Sets the index of the used GPU index: first GPU has index 0 + * + * @param _iGPUIndex New GPU index. + */ + void setGPUIndex(int _iGPUIndex); + + + virtual void signalAbort(); + + /** Get the norm of the residual image. + * Only a few algorithms support this method. + * + * @param _fNorm if supported, the norm is returned here + * @return true if this operation is supported + */ + virtual bool getResidualNorm(float32& _fNorm); + +protected: + + AstraCGLS3d* m_pCgls; + + int m_iGPUIndex; + bool m_bAstraCGLSInit; + int m_iDetectorSuperSampling; + int m_iVoxelSuperSampling; +}; + +// inline functions +inline std::string CCudaCglsAlgorithm3D::description() const { return CCudaCglsAlgorithm3D::type; }; + +} // end namespace + +#endif + +#endif diff --git a/include/astra/CudaDartMaskAlgorithm.h b/include/astra/CudaDartMaskAlgorithm.h new file mode 100644 index 0000000..f370f42 --- /dev/null +++ b/include/astra/CudaDartMaskAlgorithm.h @@ -0,0 +1,126 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDADARTMASKALGORITHM +#define _INC_ASTRA_CUDADARTMASKALGORITHM + +#include "Globals.h" +#include "Config.h" +#include "Algorithm.h" +#include "Float32VolumeData2D.h" + + +#ifdef ASTRA_CUDA + +namespace astraCUDA { +class PDART; +} + +namespace astra { + + class _AstraExport CCudaDartMaskAlgorithm : public CAlgorithm +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaDartMaskAlgorithm(); + + /** Destructor. + */ + virtual ~CCudaDartMaskAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class, use sequential order. + * + * @param _pSegmentation ... + * @param iConn ... + */ + //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + +protected: + /** Check this object. + * + * @return object initialized + */ + bool _check(); + + unsigned int m_iConn; + unsigned int m_iThreshold; + unsigned int m_iRadius; + int m_iGPUIndex; + + CFloat32VolumeData2D* m_pSegmentation; + CFloat32VolumeData2D* m_pMask; + +}; + +// inline functions +inline std::string CCudaDartMaskAlgorithm::description() const { return CCudaDartMaskAlgorithm::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaDartMaskAlgorithm3D.h b/include/astra/CudaDartMaskAlgorithm3D.h new file mode 100644 index 0000000..bdbce2b --- /dev/null +++ b/include/astra/CudaDartMaskAlgorithm3D.h @@ -0,0 +1,122 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDADARTMASKALGORITHM3D +#define _INC_ASTRA_CUDADARTMASKALGORITHM3D + +#include "Globals.h" +#include "Config.h" +#include "Algorithm.h" +#include "Float32VolumeData3DMemory.h" + + +#ifdef ASTRA_CUDA + +namespace astra { + + class _AstraExport CCudaDartMaskAlgorithm3D : public CAlgorithm +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaDartMaskAlgorithm3D(); + + /** Destructor. + */ + virtual ~CCudaDartMaskAlgorithm3D(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class, use sequential order. + * + * @param _pSegmentation ... + * @param iConn ... + */ + //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + +protected: + /** Check this object. + * + * @return object initialized + */ + bool _check(); + + unsigned int m_iConn; + unsigned int m_iThreshold; + unsigned int m_iRadius; + int m_iGPUIndex; + + CFloat32VolumeData3DMemory* m_pSegmentation; + CFloat32VolumeData3DMemory* m_pMask; + +}; + +// inline functions +inline std::string CCudaDartMaskAlgorithm3D::description() const { return CCudaDartMaskAlgorithm3D::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaDartSmoothingAlgorithm.h b/include/astra/CudaDartSmoothingAlgorithm.h new file mode 100644 index 0000000..f90f9cf --- /dev/null +++ b/include/astra/CudaDartSmoothingAlgorithm.h @@ -0,0 +1,125 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDADARTSMOOTHINGALGORITHM +#define _INC_ASTRA_CUDADARTSMOOTHINGALGORITHM + +#include "Globals.h" +#include "Config.h" +#include "Algorithm.h" +#include "Float32VolumeData2D.h" + + +#ifdef ASTRA_CUDA + +namespace astraCUDA { +class PDART; +} + +namespace astra { + + class _AstraExport CCudaDartSmoothingAlgorithm : public CAlgorithm +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaDartSmoothingAlgorithm(); + + /** Destructor. + */ + virtual ~CCudaDartSmoothingAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class, use sequential order. + * + * @param _pSegmentation ... + * @param iConn ... + */ + //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + +protected: + /** Check this object. + * + * @return object initialized + */ + bool _check(); + + float m_fB; + unsigned int m_iRadius; + int m_iGPUIndex; + + CFloat32VolumeData2D* m_pIn; + CFloat32VolumeData2D* m_pOut; + +}; + +// inline functions +inline std::string CCudaDartSmoothingAlgorithm::description() const { return CCudaDartSmoothingAlgorithm::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaDartSmoothingAlgorithm3D.h b/include/astra/CudaDartSmoothingAlgorithm3D.h new file mode 100644 index 0000000..9942de8 --- /dev/null +++ b/include/astra/CudaDartSmoothingAlgorithm3D.h @@ -0,0 +1,122 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDADARTSMOOTHINGALGORITHM3D +#define _INC_ASTRA_CUDADARTSMOOTHINGALGORITHM3D + +#include "Globals.h" +#include "Config.h" +#include "Algorithm.h" +#include "Float32VolumeData3DMemory.h" + + +#ifdef ASTRA_CUDA + +namespace astra { + + class _AstraExport CCudaDartSmoothingAlgorithm3D : public CAlgorithm +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaDartSmoothingAlgorithm3D(); + + /** Destructor. + */ + virtual ~CCudaDartSmoothingAlgorithm3D(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class, use sequential order. + * + * @param _pSegmentation ... + * @param iConn ... + */ + //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + +protected: + + /** Check this object. + * + * @return object initialized + */ + bool _check(); + + float m_fB; + unsigned int m_iRadius; + int m_iGPUIndex; + + CFloat32VolumeData3DMemory* m_pIn; + CFloat32VolumeData3DMemory* m_pOut; + +}; + +// inline functions +inline std::string CCudaDartSmoothingAlgorithm3D::description() const { return CCudaDartSmoothingAlgorithm3D::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaDataOperationAlgorithm.h b/include/astra/CudaDataOperationAlgorithm.h new file mode 100644 index 0000000..a5ab01a --- /dev/null +++ b/include/astra/CudaDataOperationAlgorithm.h @@ -0,0 +1,128 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDADATAOPERATIONALGORITHM +#define _INC_ASTRA_CUDADATAOPERATIONALGORITHM + +#include "Globals.h" +#include "Config.h" +#include "Algorithm.h" +#include "Float32VolumeData2D.h" + +#ifdef ASTRA_CUDA + +namespace astraCUDA { +class PDART; +} + +namespace astra { + + class _AstraExport CCudaDataOperationAlgorithm : public CAlgorithm +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaDataOperationAlgorithm(); + + /** Destructor. + */ + virtual ~CCudaDataOperationAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class, use sequential order. + * + * @param _pSegmentation ... + * @param iConn ... + */ + //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + +protected: + /** Check this object. + * + * @return object initialized + */ + bool _check(); + + + + int m_iGPUIndex; + + CFloat32Data2D* m_pMask; + + vector m_pData; + vector m_fScalar; + + string m_sOperation; + +}; + +// inline functions +inline std::string CCudaDataOperationAlgorithm::description() const { return CCudaDataOperationAlgorithm::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaEMAlgorithm.h b/include/astra/CudaEMAlgorithm.h new file mode 100644 index 0000000..ff22dd4 --- /dev/null +++ b/include/astra/CudaEMAlgorithm.h @@ -0,0 +1,92 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDAEMALGORITHM +#define _INC_ASTRA_CUDAEMALGORITHM + +#include "Globals.h" +#include "Config.h" + +#include "CudaReconstructionAlgorithm2D.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +class _AstraExport CCudaEMAlgorithm : public CCudaReconstructionAlgorithm2D +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaEMAlgorithm(); + + /** Destructor. + */ + virtual ~CCudaEMAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. (Ignored) + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @param _iGPUindex GPU to use. + * @param _iDetectorSuperSampling Supersampling factor for the FP. + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction, + int _iGPUindex = 0, int _iDetectorSuperSampling = 1, + int _iPixelSuperSampling = 1); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; +}; + +// inline functions +inline std::string CCudaEMAlgorithm::description() const { return CCudaEMAlgorithm::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaFDKAlgorithm3D.h b/include/astra/CudaFDKAlgorithm3D.h new file mode 100644 index 0000000..7ab9bbe --- /dev/null +++ b/include/astra/CudaFDKAlgorithm3D.h @@ -0,0 +1,164 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDAFDKALGORITHM3D +#define _INC_ASTRA_CUDAFDKALGORITHM3D + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" + +#include "Float32ProjectionData3DMemory.h" +#include "Float32VolumeData3DMemory.h" +#include "ReconstructionAlgorithm3D.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +/** + * \brief + * This class contains the 3D implementation of the FDK algorithm. + * + * \par XML Configuration + * + * \par MATLAB example + * \astra_code{ + * + * } + * + */ +class _AstraExport CCudaFDKAlgorithm3D : public CReconstructionAlgorithm3D { + +protected: + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - the projector is compatible with both data objects + */ + virtual bool _check(); + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, does not initialize the object. + */ + CCudaFDKAlgorithm3D(); + + /** Constructor with initialization. + * + * @param _pProjector Projector Object. + * @param _pProjectionData ProjectionData3D object containing the projection data. + * @param _pReconstruction VolumeData3D object for storing the reconstructed volume. + */ + CCudaFDKAlgorithm3D(CProjector3D* _pProjector, + CFloat32ProjectionData3DMemory* _pProjectionData, + CFloat32VolumeData3DMemory* _pReconstruction); + + /** Copy constructor. + */ + CCudaFDKAlgorithm3D(const CCudaFDKAlgorithm3D&); + + /** Destructor. + */ + virtual ~CCudaFDKAlgorithm3D(); + + /** Clear this class. + */ +/* virtual void clear();*/ + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. + * @param _pProjectionData ProjectionData3D object containing the projection data. + * @param _pReconstruction VolumeData3D object for storing the reconstructed volume. + * @return initialization successful? + */ + bool initialize(CProjector3D* _pProjector, + CFloat32ProjectionData3DMemory* _pSinogram, + CFloat32VolumeData3DMemory* _pReconstruction); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** + * Sets the index of the used GPU index: first GPU has index 0 + * + * @param _iGPUIndex New GPU index. + */ + void setGPUIndex(int _iGPUIndex); + +protected: + + int m_iGPUIndex; + int m_iVoxelSuperSampling; + bool m_bShortScan; +}; + +// inline functions +inline std::string CCudaFDKAlgorithm3D::description() const { return CCudaFDKAlgorithm3D::type; }; + +} // end namespace + +#endif + +#endif diff --git a/include/astra/CudaFilteredBackProjectionAlgorithm.h b/include/astra/CudaFilteredBackProjectionAlgorithm.h new file mode 100644 index 0000000..4b7b904 --- /dev/null +++ b/include/astra/CudaFilteredBackProjectionAlgorithm.h @@ -0,0 +1,94 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef CUDAFILTEREDBACKPROJECTIONALGORITHM2_H +#define CUDAFILTEREDBACKPROJECTIONALGORITHM2_H + +#include +#include +#include + +#include "../../cuda/2d/astra.h" + +namespace astra +{ + +class _AstraExport CCudaFilteredBackProjectionAlgorithm : public CReconstructionAlgorithm2D +{ +public: + static std::string type; + +private: + CFloat32ProjectionData2D * m_pSinogram; + CFloat32VolumeData2D * m_pReconstruction; + int m_iGPUIndex; + int m_iPixelSuperSampling; + E_FBPFILTER m_eFilter; + float * m_pfFilter; + int m_iFilterWidth; // number of elements per projection direction in filter + float m_fFilterParameter; // some filters allow for parameterization (value < 0.0f -> no parameter) + float m_fFilterD; // frequency cut-off + + static E_FBPFILTER _convertStringToFilter(const char * _filterType); + +public: + CCudaFilteredBackProjectionAlgorithm(); + virtual ~CCudaFilteredBackProjectionAlgorithm(); + + virtual bool initialize(const Config& _cfg); + bool initialize(CFloat32ProjectionData2D * _pSinogram, CFloat32VolumeData2D * _pReconstruction, E_FBPFILTER _eFilter, const float * _pfFilter = NULL, int _iFilterWidth = 0, int _iGPUIndex = 0, float _fFilterParameter = -1.0f); + + virtual void run(int _iNrIterations = 0); + + static int calcIdealRealFilterWidth(int _iDetectorCount); + static int calcIdealFourierFilterWidth(int _iDetectorCount); + + //debug + static void testGenFilter(E_FBPFILTER _eFilter, float _fD, int _iProjectionCount, cufftComplex * _pFilter, int _iFFTRealDetectorCount, int _iFFTFourierDetectorCount); + static int getGPUCount(); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + +protected: + bool check(); + + AstraFBP* m_pFBP; + + bool m_bAstraFBPInit; +}; + +// inline functions +inline std::string CCudaFilteredBackProjectionAlgorithm::description() const { return CCudaFilteredBackProjectionAlgorithm::type; }; + +} + +#endif /* CUDAFILTEREDBACKPROJECTIONALGORITHM2_H */ diff --git a/include/astra/CudaForwardProjectionAlgorithm.h b/include/astra/CudaForwardProjectionAlgorithm.h new file mode 100644 index 0000000..53b6c8e --- /dev/null +++ b/include/astra/CudaForwardProjectionAlgorithm.h @@ -0,0 +1,169 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDAFORWARDPROJECTIONALGORITHM2 +#define _INC_ASTRA_CUDAFORWARDPROJECTIONALGORITHM2 + +#include "Globals.h" + +#include "Algorithm.h" + +#include "ParallelProjectionGeometry2D.h" +#include "VolumeGeometry2D.h" + +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +/** + * \brief + * This class contains a GPU implementation of an algorithm that creates a forward projection + * of a volume object and stores it into a sinogram. + * + * \par XML Configuration + * \astra_xml_item{VolumeGeometry, integer, Geometry of the volume data.} + * \astra_xml_item{ProjectionGeometry, integer, Geometry of the projection data.} + * \astra_xml_item{VolumeDataId, integer, Identifier of the volume data object as it is stored in the DataManager.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of the resulting projection data object as it is stored in the DataManager.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('FP_CUDA2');\n + * cfg.VolumeGeometry = vol_geom;\n + * cfg.ProjectionGeometry = proj_geom;\n + * cfg.VolumeDataId = vol_id;\n + * cfg.ProjectionDataId = sino_id;\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('run'\, alg_id);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + * + */ +class _AstraExport CCudaForwardProjectionAlgorithm : public CAlgorithm +{ +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaForwardProjectionAlgorithm(); + + /** Destructor. + */ + virtual ~CCudaForwardProjectionAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pVolumeGeometry Geometry of the volume. + * @param _pProjectionGeometry Geometry of the projection. + * @param _pVolume VolumeData2D object containing the phantom to compute sinogram from + * @param _pSinogram ProjectionData2D object to store sinogram data in. + * @param _iGPUindex Index of GPU to use. (Starting at 0.) + * @param _iDetectorSuperSampling Number of samples per detector element, used to compute the forward projection + * @return success + */ + bool initialize(CProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pVolumeGeometry, + CFloat32VolumeData2D* _pVolume, + CFloat32ProjectionData2D* _pSinogram, + int _iGPUindex = 0, int _iDetectorSuperSampling = 1); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Check this object. + * + * @return object initialized + */ + bool check(); + + CFloat32VolumeData2D* getVolume() { return m_pVolume; } + CFloat32ProjectionData2D* getSinogram() { return m_pSinogram; } + + /** + * Sets the index of the used GPU index: first GPU has index 0 + * + * @param _iGPUIndex New GPU index. + */ + void setGPUIndex(int _iGPUIndex); + +protected: + //< ProjectionData2D object containing the sinogram. + CFloat32ProjectionData2D* m_pSinogram; + //< VolumeData2D object containing the phantom. + CFloat32VolumeData2D* m_pVolume; + + //< Index of GPU to use + int m_iGPUIndex; + //< Number of rays per detector element + int m_iDetectorSuperSampling; + +}; + +// inline functions +inline std::string CCudaForwardProjectionAlgorithm::description() const { return CCudaForwardProjectionAlgorithm::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaForwardProjectionAlgorithm3D.h b/include/astra/CudaForwardProjectionAlgorithm3D.h new file mode 100644 index 0000000..72c6a00 --- /dev/null +++ b/include/astra/CudaForwardProjectionAlgorithm3D.h @@ -0,0 +1,135 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDAFORWARDPROJECTIONALGORITHM3D +#define _INC_ASTRA_CUDAFORWARDPROJECTIONALGORITHM3D + +#include "Globals.h" + +#include "Algorithm.h" + +#include "Float32ProjectionData3DMemory.h" +#include "Float32VolumeData3DMemory.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +class CProjector3D; + +class _AstraExport CCudaForwardProjectionAlgorithm3D : public CAlgorithm +{ +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaForwardProjectionAlgorithm3D(); + + /** Destructor. + */ + virtual ~CCudaForwardProjectionAlgorithm3D(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. + * @param _pProjectionData ProjectionData3D object for storing the projection data. + * @param _pReconstruction VolumeData3D object containing the volume. + * @return initialization successful? + */ + bool initialize(CProjector3D* _pProjector, + CFloat32ProjectionData3DMemory* _pSinogram, + CFloat32VolumeData3DMemory* _pReconstruction, + int _iGPUindex = 0, int _iDetectorSuperSampling = 1); + + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Check this object. + * + * @return object initialized + */ + bool check(); + + /** + * Sets the index of the used GPU index: first GPU has index 0 + * + * @param _iGPUIndex New GPU index. + */ + void setGPUIndex(int _iGPUIndex); + +protected: + CProjector3D* m_pProjector; + CFloat32ProjectionData3DMemory* m_pProjections; + CFloat32VolumeData3DMemory* m_pVolume; + int m_iGPUIndex; + int m_iDetectorSuperSampling; + +}; + +// inline functions +inline std::string CCudaForwardProjectionAlgorithm3D::description() const { return CCudaForwardProjectionAlgorithm3D::type; }; + + +} + +#endif + +#endif diff --git a/include/astra/CudaProjector2D.h b/include/astra/CudaProjector2D.h new file mode 100644 index 0000000..073b299 --- /dev/null +++ b/include/astra/CudaProjector2D.h @@ -0,0 +1,122 @@ +/* +----------------------------------------------------------------------- +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA-Toolbox") + +Copyright: IBBT-Vision Lab, University of Antwerp +Contact: mailto:wim.vanaarle@ua.ac.be +Website: http://astra.ua.ac.be +----------------------------------------------------------------------- +$Id$ +*/ +#ifndef _INC_ASTRA_CUDAPROJECTOR2D +#define _INC_ASTRA_CUDAPROJECTOR2D + +#include "ParallelProjectionGeometry2D.h" +#include "Float32Data2D.h" +#include "Projector2D.h" +#include "../../cuda/2d/astra.h" + +namespace astra +{ + + +/** This is a two-dimensional CUDA-projector. + * It is essentially a fake projector, containing settings relevant for the + * actual CUDA code. + */ +class _AstraExport CCudaProjector2D : public CProjector2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - blobvalues are ok + */ + virtual bool _check(); + +public: + + // type of the projector, needed to register with CProjectorFactory + static std::string type; + + /** Default constructor. + */ + CCudaProjector2D(); + + /** Constructor. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + */ + CCudaProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + ~CCudaProjector2D(); + + /** Initialize the projector with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Clear this class. + */ + virtual void clear(); + + + virtual int getProjectionWeightsCount(int _iProjectionIndex) { return 0; } + + virtual void computeSingleRayWeights(int _iProjectionIndex, + int _iDetectorIndex, + SPixelWeight* _pWeightedPixels, + int _iMaxPixelCount, + int& _iStoredPixelCount) {} + + virtual std::vector projectPoint(int _iRow, int _iCol) + { std::vector x; return x; } + + template + void project(Policy& _policy) {} + template + void projectSingleProjection(int _iProjection, Policy& _policy) {} + template + void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy) {} + + + /** Return the type of this projector. + * + * @return identification type of this projector + */ + virtual std::string getType(); + + /** get a description of the class + * + * @return description string + */ + virtual std::string description() const; + + +protected: + + Cuda2DProjectionKernel m_projectionKernel; +}; + +//---------------------------------------------------------------------------------------- + +inline std::string CCudaProjector2D::getType() +{ + return type; +} + +} // namespace astra + +#endif + diff --git a/include/astra/CudaProjector3D.h b/include/astra/CudaProjector3D.h new file mode 100644 index 0000000..66071f0 --- /dev/null +++ b/include/astra/CudaProjector3D.h @@ -0,0 +1,131 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef INC_ASTRA_CUDAPROJECTOR3D +#define INC_ASTRA_CUDAPROJECTOR3D + +#ifdef ASTRA_CUDA + +#include +#include + +#include "Globals.h" +#include "Config.h" +#include "Projector3D.h" +#include "../../cuda/3d/astra3d.h" + +namespace astra +{ + +/** This is a three-dimensional CUDA-projector. + * It is essentially a fake projector, containing settings relevant for the + * actual CUDA code. + */ +class _AstraExport CCudaProjector3D : public CProjector3D +{ + +protected: + + /** Check variable values. + */ + bool _check(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + * Should only be used by constructors. Otherwise use the clear() function. + */ + void _clear(); + +public: + + // type of the projector, needed to register with CProjectorFactory + static std::string type; + + /** + * Default Constructor. + */ + CCudaProjector3D(); + + /** Destructor, is virtual to show that we are aware subclass destructor is called. + */ + virtual ~CCudaProjector3D(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + */ + void clear(); + + /** Initialize the projector with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + virtual void computeSingleRayWeights(int _iProjectionIndex, + int _iSliceIndex, + int _iDetectorIndex, + SPixelWeight* _pWeightedPixels, + int _iMaxPixelCount, + int& _iStoredPixelCount) {} + virtual int getProjectionWeightsCount(int _iProjectionIndex) { return 0; } + template + void project(Policy& _policy) {} + template + void projectSingleProjection(int _iProjection, Policy& _policy) {} + template + void projectSingleRay(int _iProjection, int _iSlice, int _iDetector, Policy& _policy) {} + + + + /** Return the type of this projector. + * + * @return identification type of this projector + */ + virtual std::string getType() { return type; } + + /** get a description of the class + * + * @return description string + */ + virtual std::string description() const; + + + Cuda3DProjectionKernel getProjectionKernel() const { return m_projectionKernel; } + +protected: + + Cuda3DProjectionKernel m_projectionKernel; + + +}; + + +} // namespace astra + +#endif // ASTRA_CUDA + +#endif /* INC_ASTRA_CUDAPROJECTOR3D */ diff --git a/include/astra/CudaReconstructionAlgorithm2D.h b/include/astra/CudaReconstructionAlgorithm2D.h new file mode 100644 index 0000000..88fc344 --- /dev/null +++ b/include/astra/CudaReconstructionAlgorithm2D.h @@ -0,0 +1,176 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDARECONSTRUCTIONALGORITHM2D +#define _INC_ASTRA_CUDARECONSTRUCTIONALGORITHM2D + +#include "Globals.h" +#include "Config.h" + +#include "ReconstructionAlgorithm2D.h" + +#include "Projector2D.h" +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + +namespace astraCUDA { +class ReconAlgo; +} + +namespace astra { + +/** + * This is a base class for the different CUDA implementations of 2D reconstruction algorithms. + * They don't use a Projector, and share GPUIndex and DetectorSuperSampling options. + * + */ +class _AstraExport CCudaReconstructionAlgorithm2D : public CReconstructionAlgorithm2D { + +public: + + /** Default constructor, containing no code. + */ + CCudaReconstructionAlgorithm2D(); + + /** Destructor. + */ + virtual ~CCudaReconstructionAlgorithm2D(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. (Ignored) + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Initialize class. + * + * @param _pProjector Projector Object. (Ignored) + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @param _iGPUindex GPU to use. + * @param _iDetectorSuperSampling Supersampling factor for the FP. + * @param _iPixelSuperSampling Square root of number of samples per voxel, used to compute the backprojection + */ + virtual bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction, + int _iGPUindex = 0, int _iDetectorSuperSampling = 1, + int _iPixelSuperSampling = 1); + + + /** Clear this class. + */ + virtual void clear(); + + /** Get all information parameters. + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information. + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Get the norm of the residual image. + * Only a few algorithms support this method. + * + * @param _fNorm if supported, the norm is returned here + * @return true if this operation is supported + */ + virtual bool getResidualNorm(float32& _fNorm); + + /** + * Sets the index of the used GPU index: first GPU has index 0 + * + * @param _iGPUIndex New GPU index. + */ + void setGPUIndex(int _iGPUIndex); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + virtual void signalAbort(); + +protected: + + /** Check this object. + * + * @return object initialized + */ + bool _check(); + + /** Initial clearing. Only to be used by constructors. + */ + void _clear(); + + /** Set up geometry. For internal use only. + */ + bool setupGeometry(); + + + /** The internally used CUDA algorithm object + */ + astraCUDA::ReconAlgo *m_pAlgo; + + int m_iDetectorSuperSampling; + int m_iPixelSuperSampling; + int m_iGPUIndex; + + bool m_bAlgoInit; +}; + +// inline functions +inline std::string CCudaReconstructionAlgorithm2D::description() const { return "2D CUDA Reconstruction Algorithm"; }; + +} // end namespace + +#endif diff --git a/include/astra/CudaRoiSelectAlgorithm.h b/include/astra/CudaRoiSelectAlgorithm.h new file mode 100644 index 0000000..1ee9c32 --- /dev/null +++ b/include/astra/CudaRoiSelectAlgorithm.h @@ -0,0 +1,123 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDAROISELECTALGORITHM +#define _INC_ASTRA_CUDAROISELECTALGORITHM + +#include "Globals.h" +#include "Config.h" +#include "Algorithm.h" +#include "Float32VolumeData2D.h" + + +#ifdef ASTRA_CUDA + +namespace astraCUDA { +class PDART; +} + +namespace astra { + + class _AstraExport CCudaRoiSelectAlgorithm : public CAlgorithm +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaRoiSelectAlgorithm(); + + /** Destructor. + */ + virtual ~CCudaRoiSelectAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class, use sequential order. + * + * @param _pSegmentation ... + * @param iConn ... + */ + //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + +protected: + /** Check this object. + * + * @return object initialized + */ + bool _check(); + + float32 m_fRadius; + int m_iGPUIndex; + + CFloat32VolumeData2D* m_pData; + +}; + +// inline functions +inline std::string CCudaRoiSelectAlgorithm::description() const { return CCudaRoiSelectAlgorithm::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaSartAlgorithm.h b/include/astra/CudaSartAlgorithm.h new file mode 100644 index 0000000..319e1e9 --- /dev/null +++ b/include/astra/CudaSartAlgorithm.h @@ -0,0 +1,112 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDASARTALGORITHM +#define _INC_ASTRA_CUDASARTALGORITHM + +#include "Globals.h" +#include "Config.h" + +#include "CudaReconstructionAlgorithm2D.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +/** + * \brief + * This class contains a GPU implementation of the SART algorithm. + * + * \par XML Configuration + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 0 = reconstruct on this pixel. 1 = don't reconstruct on this pixel.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('SART_CUDA');\n + * cfg.ProjectionDataId = sino_id;\n + * cfg.ReconstructionDataId = recon_id;\n + * cfg.option.ReconstructionMaskId = mask_id;\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('iterate'\, alg_id\, 10);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + * + */ +class _AstraExport CCudaSartAlgorithm : public CCudaReconstructionAlgorithm2D +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaSartAlgorithm(); + + /** Destructor. + */ + virtual ~CCudaSartAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. (Ignored) + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @param _iGPUindex GPU to use. + * @param _iDetectorSuperSampling Supersampling factor for the FP. + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction, + int _iGPUindex = 0, int _iDetectorSuperSampling = 1); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; +}; + +// inline functions +inline std::string CCudaSartAlgorithm::description() const { return CCudaSartAlgorithm::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaSirtAlgorithm.h b/include/astra/CudaSirtAlgorithm.h new file mode 100644 index 0000000..7f3d67b --- /dev/null +++ b/include/astra/CudaSirtAlgorithm.h @@ -0,0 +1,131 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDASIRTALGORITHM2 +#define _INC_ASTRA_CUDASIRTALGORITHM2 + +#include "Globals.h" +#include "Config.h" + +#include "CudaReconstructionAlgorithm2D.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +/** + * \brief + * This class contains a GPU implementation of the SIRT (Simultaneous Iterative Reconstruction Technique) algorithm. + * + * The update step of pixel \f$v_j\f$ for iteration \f$k\f$ is given by: + * \f[ + * v_j^{(k+1)} = v_j^{(k)} + \alpha \sum_{i=1}^{M} \left( \frac{w_{ij}\left( p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}\right)}{\sum_{k=1}^{N} w_{ik}} \right) \frac{1}{\sum_{l=1}^{M}w_{lj}} + * \f] + * + * \par XML Configuration + * \astra_xml_item{ProjectionGeometry, integer, Geometry of the projection data.} + * \astra_xml_item{VolumeGeometry, integer, Geometry of the volume data.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 0 = reconstruct on this pixel. 1 = don't reconstruct on this pixel.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('SIRT_CUDA2');\n + * cfg.ProjectionGeometry = proj_geom;\n + * cfg.VolumeGeometry = vol_geom;\n + * cfg.ProjectionDataId = sino_id;\n + * cfg.ReconstructionDataId = recon_id;\n + * cfg.option.ReconstructionMaskId = mask_id;\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('iterate'\, alg_id\, 10);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + * + * \par References + * [1] "Computational Analysis and Improvement of SIRT", J. Gregor, T. Benson, IEEE Transactions on Medical Imaging, Vol. 22, No. 7, July 2008. + */ +class _AstraExport CCudaSirtAlgorithm : public CCudaReconstructionAlgorithm2D +{ + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CCudaSirtAlgorithm(); + + /** Destructor. + */ + virtual ~CCudaSirtAlgorithm(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + virtual void run(int _iNrIterations); + + /** Initialize class. + * + * @param _pProjector Projector Object. (Ignored) + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @param _iGPUindex GPU to use. + * @param _iDetectorSuperSampling Supersampling factor for the FP. + * @param _iPixelSuperSampling Square root of number of samples per voxel, used to compute the backprojection + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction, + int _iGPUindex = 0, int _iDetectorSuperSampling = 1, + int _iPixelSuperSampling = 1); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + +protected: + CFloat32VolumeData2D* m_pMinMask; + CFloat32VolumeData2D* m_pMaxMask; +}; + +// inline functions +inline std::string CCudaSirtAlgorithm::description() const { return CCudaSirtAlgorithm::type; }; + +} // end namespace + +#endif // ASTRA_CUDA + +#endif diff --git a/include/astra/CudaSirtAlgorithm3D.h b/include/astra/CudaSirtAlgorithm3D.h new file mode 100644 index 0000000..c2c794d --- /dev/null +++ b/include/astra/CudaSirtAlgorithm3D.h @@ -0,0 +1,187 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_CUDASIRTALGORITHM3D +#define _INC_ASTRA_CUDASIRTALGORITHM3D + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" + +#include "Float32ProjectionData3DMemory.h" +#include "Float32VolumeData3DMemory.h" +#include "ReconstructionAlgorithm3D.h" + +#ifdef ASTRA_CUDA + +namespace astra { + +class AstraSIRT3d; + +/** + * \brief + * This class contains the 3D implementation of the SIRT (Simultaneous Iterative Reconstruction Technique) algorithm. + * + * The update step of pixel \f$v_j\f$ for iteration \f$k\f$ is given by: + * \f[ + * v_j^{(k+1)} = v_j^{(k)} + \alpha \sum_{i=1}^{M} \left( \frac{w_{ij}\left( p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}\right)}{\sum_{k=1}^{N} w_{ik}} \right) \frac{1}{\sum_{l=1}^{M}w_{lj}} + * \f] + * + * \par XML Configuration + * + * \par MATLAB example + * \astra_code{ + * + * } + * + * \par References + * [1] "Computational Analysis and Improvement of SIRT", J. Gregor, T. Benson, IEEE Transactions on Medical Imaging, Vol. 22, No. 7, July 2008. + */ +class _AstraExport CCudaSirtAlgorithm3D : public CReconstructionAlgorithm3D { + +protected: + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - the projector is compatible with both data objects + */ + virtual bool _check(); + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, does not initialize the object. + */ + CCudaSirtAlgorithm3D(); + + /** Constructor with initialization. + * + * @param _pProjector Projector Object. + * @param _pProjectionData ProjectionData3D object containing the projection data. + * @param _pReconstruction VolumeData3D object for storing the reconstructed volume. + */ + CCudaSirtAlgorithm3D(CProjector3D* _pProjector, + CFloat32ProjectionData3DMemory* _pProjectionData, + CFloat32VolumeData3DMemory* _pReconstruction); + + /** Copy constructor. + */ + CCudaSirtAlgorithm3D(const CCudaSirtAlgorithm3D&); + + /** Destructor. + */ + virtual ~CCudaSirtAlgorithm3D(); + + /** Clear this class. + */ +/* virtual void clear();*/ + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. + * @param _pProjectionData ProjectionData3D object containing the projection data. + * @param _pReconstruction VolumeData3D object for storing the reconstructed volume. + * @return initialization successful? + */ + bool initialize(CProjector3D* _pProjector, + CFloat32ProjectionData3DMemory* _pSinogram, + CFloat32VolumeData3DMemory* _pReconstruction); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** + * Sets the index of the used GPU index: first GPU has index 0 + * + * @param _iGPUIndex New GPU index. + */ + void setGPUIndex(int _iGPUIndex); + + + virtual void signalAbort(); + + /** Get the norm of the residual image. + * Only a few algorithms support this method. + * + * @param _fNorm if supported, the norm is returned here + * @return true if this operation is supported + */ + virtual bool getResidualNorm(float32& _fNorm); + +protected: + + AstraSIRT3d* m_pSirt; + + int m_iGPUIndex; + bool m_bAstraSIRTInit; + int m_iDetectorSuperSampling; + int m_iVoxelSuperSampling; +}; + +// inline functions +inline std::string CCudaSirtAlgorithm3D::description() const { return CCudaSirtAlgorithm3D::type; }; + +} // end namespace + +#endif + +#endif diff --git a/include/astra/DataProjector.h b/include/astra/DataProjector.h new file mode 100644 index 0000000..a324625 --- /dev/null +++ b/include/astra/DataProjector.h @@ -0,0 +1,327 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_DATAPROJECTOR +#define _INC_ASTRA_DATAPROJECTOR + +#include "Projector2D.h" + +#include "TypeList.h" + +#include "ProjectorTypelist.h" + +#include "DataProjectorPolicies.h" + +namespace astra +{ + + +/** + * Interface class for the Data Projector. The sole purpose of this class is to force child classes to implement a series of methods + */ +class CDataProjectorInterface { +public: + CDataProjectorInterface() { } + virtual ~CDataProjectorInterface() { } + virtual void project() = 0; + virtual void projectSingleProjection(int _iProjection) = 0; + virtual void projectSingleRay(int _iProjection, int _iDetector) = 0; +// virtual void projectSingleVoxel(int _iRow, int _iCol) = 0; +// virtual void projectAllVoxels() = 0; +}; + +/** + * Templated Data Projector Class. In this class a specific projector and policies are combined. + */ +template +class CDataProjector: public CDataProjectorInterface { + +private: + + Projector* m_pProjector; + Policy m_pPolicy; + +public: + + CDataProjector() {}; + + CDataProjector(Projector* _p, Policy _a); + ~CDataProjector(); + + virtual void project(); + + virtual void projectSingleProjection(int _iProjection); + + virtual void projectSingleRay(int _iProjection, int _iDetector); + +// virtual void projectSingleVoxel(int _iRow, int _iCol); + +// virtual void projectAllVoxels(); +}; + +//---------------------------------------------------------------------------------------- +/** + * Constructor +*/ +template +CDataProjector::CDataProjector(Projector* _p, Policy _a) +{ + m_pProjector = _p; + m_pPolicy = _a; +} + +//---------------------------------------------------------------------------------------- +/** + * Destructor +*/ +template +CDataProjector::~CDataProjector() +{ + // does nothing +} + +//---------------------------------------------------------------------------------------- +/** + * Compute projection using the algorithm specific to the projector type +*/ +template +void CDataProjector::project() +{ + m_pProjector->project(m_pPolicy); +} + +//---------------------------------------------------------------------------------------- +/** + * Compute just one projection using the algorithm specific to the projector type +*/ +template +void CDataProjector::projectSingleProjection(int _iProjection) +{ + m_pProjector->projectSingleProjection(_iProjection, m_pPolicy); +} + +//---------------------------------------------------------------------------------------- +/** + * Compute projection of one ray using the algorithm specific to the projector type +*/ +template +void CDataProjector::projectSingleRay(int _iProjection, int _iDetector) +{ + m_pProjector->projectSingleRay(_iProjection, _iDetector, m_pPolicy); +} + +//---------------------------------------------------------------------------------------- +//template +//void CDataProjector::projectSingleVoxel(int _iRow, int _iCol) +//{ +// m_pProjector->projectSingleVoxel(_iRow, _iCol, m_pPolicy); +//} + +//---------------------------------------------------------------------------------------- +//template +//void CDataProjector::projectAllVoxels() +//{ +// m_pProjector->projectAllVoxels(m_pPolicy); +//} +//---------------------------------------------------------------------------------------- + + + + +//----------------------------------------------------------------------------------------- +// Create a new datainterface from the projector TypeList +namespace typelist { + template + struct CreateDataProjector { + template + static void find (U& functor, CProjector2D* _pProjector, const Policy& _pPolicy) { + if (functor(TList::Head::type)) { + functor.res = new CDataProjector(static_cast(_pProjector), _pPolicy); + } + CreateDataProjector::find(functor, _pProjector, _pPolicy); + } + }; + template <> + struct CreateDataProjector { + template + static void find(U& functor, CProjector2D* _pProjector, const Policy& _pPolicy) {} + }; + + struct functor_find_datainterface { + functor_find_datainterface() { res = NULL; } + bool operator() (std::string name) { + return strcmp(tofind.c_str(), name.c_str()) == 0; + } + std::string tofind; + CDataProjectorInterface* res; + }; +} +//----------------------------------------------------------------------------------------- + +/** + * Data Projector Dispatcher - 1 Policy + */ +template +static CDataProjectorInterface* dispatchDataProjector(CProjector2D* _pProjector, const Policy& _policy) +{ + typelist::functor_find_datainterface finder = typelist::functor_find_datainterface(); + finder.tofind = _pProjector->getType(); + typelist::CreateDataProjector::find(finder, _pProjector, _policy); + return finder.res; +} + + + +/** + * Data Projector Dispatcher - 2 Policies + */ +template +static CDataProjectorInterface* dispatchDataProjector(CProjector2D* _pProjector, + const Policy1& _policy, + const Policy2& _policy2, + bool _bUsePolicy1 = true, + bool _bUsePolicy2 = true) +{ + if (!_bUsePolicy1 && !_bUsePolicy2) { + return dispatchDataProjector(_pProjector, EmptyPolicy()); + } else if (!_bUsePolicy1) { + return dispatchDataProjector(_pProjector, _policy2); + } else if (!_bUsePolicy2) { + return dispatchDataProjector(_pProjector, _policy); + } else { + return dispatchDataProjector(_pProjector, CombinePolicy(_policy, _policy2)); + } + +} + +/** + * Data Projector Dispatcher - 3 Policies + */ + +template +static CDataProjectorInterface* dispatchDataProjector(CProjector2D* _pProjector, + const Policy1& _policy1, + const Policy2& _policy2, + const Policy3& _policy3, + bool _bUsePolicy1 = true, + bool _bUsePolicy2 = true, + bool _bUsePolicy3 = true) +{ + if (!_bUsePolicy1) { + return dispatchDataProjector(_pProjector, _policy2, _policy3, _bUsePolicy2, _bUsePolicy3); + } else if (!_bUsePolicy2) { + return dispatchDataProjector(_pProjector, _policy1, _policy3, _bUsePolicy1, _bUsePolicy3); + } else if (!_bUsePolicy3) { + return dispatchDataProjector(_pProjector, _policy1, _policy2, _bUsePolicy1, _bUsePolicy2); + } else { + return dispatchDataProjector(_pProjector, Combine3Policy(_policy1, _policy2, _policy3)); + } +} + +/** + * Data Projector Dispatcher - 4 Policies + */ +template +static CDataProjectorInterface* dispatchDataProjector(CProjector2D* _pProjector, + const Policy1& _policy1, + const Policy2& _policy2, + const Policy3& _policy3, + const Policy4& _policy4, + bool _bUsePolicy1 = true, + bool _bUsePolicy2 = true, + bool _bUsePolicy3 = true, + bool _bUsePolicy4 = true) +{ + if (!_bUsePolicy1) { + return dispatchDataProjector(_pProjector, _policy2, _policy3, _policy4, _bUsePolicy2, _bUsePolicy3, _bUsePolicy4); + } else if (!_bUsePolicy2) { + return dispatchDataProjector(_pProjector, _policy1, _policy3, _policy4, _bUsePolicy1, _bUsePolicy3, _bUsePolicy4); + } else if (!_bUsePolicy3) { + return dispatchDataProjector(_pProjector, _policy1, _policy2, _policy4, _bUsePolicy1, _bUsePolicy2, _bUsePolicy4); + } else if (!_bUsePolicy4) { + return dispatchDataProjector(_pProjector, _policy1, _policy2, _policy3, _bUsePolicy1, _bUsePolicy2, _bUsePolicy3); + } else { + return dispatchDataProjector(_pProjector, Combine4Policy(_policy1, _policy2, _policy3, _policy4)); + } +} + +/** + * Data Projector Dispatcher - 5 Policies + */ +template +static CDataProjectorInterface* dispatchDataProjector(CProjector2D* _pProjector, + const Policy1& _policy1, + const Policy2& _policy2, + const Policy3& _policy3, + const Policy4& _policy4, + const Policy5& _policy5, + bool _bUsePolicy1 = true, + bool _bUsePolicy2 = true, + bool _bUsePolicy3 = true, + bool _bUsePolicy4 = true, + bool _bUsePolicy5 = true) +{ + if (!_bUsePolicy1) { + return dispatchDataProjector(_pProjector, _policy2, _policy3, _policy4, _policy5, _bUsePolicy2, _bUsePolicy3, _bUsePolicy4, _bUsePolicy5); + } else if (!_bUsePolicy2) { + return dispatchDataProjector(_pProjector, _policy1, _policy3, _policy4, _policy5, _bUsePolicy1, _bUsePolicy3, _bUsePolicy4, _bUsePolicy5); + } else if (!_bUsePolicy3) { + return dispatchDataProjector(_pProjector, _policy1, _policy2, _policy4, _policy5, _bUsePolicy1, _bUsePolicy2, _bUsePolicy4, _bUsePolicy5); + } else if (!_bUsePolicy4) { + return dispatchDataProjector(_pProjector, _policy1, _policy2, _policy3, _policy5, _bUsePolicy1, _bUsePolicy2, _bUsePolicy3, _bUsePolicy5); + } else if (!_bUsePolicy5) { + return dispatchDataProjector(_pProjector, _policy1, _policy2, _policy3, _policy4, _bUsePolicy1, _bUsePolicy2, _bUsePolicy3, _bUsePolicy4); + } else { + return dispatchDataProjector(_pProjector, CombinePolicy< Combine4Policy, Policy5>( + Combine4Policy(_policy1, _policy2, _policy3, _policy4), + _policy5) + ); + } +} + + + + +//----------------------------------------------------------------------------------------- +/** + * Data Projector Project + */ +template +static void projectData(CProjector2D* _pProjector, const Policy& _policy) +{ + CDataProjectorInterface* dp = dispatchDataProjector(_pProjector, _policy); + dp->project(); + delete dp; +} + + + + +} // namespace astra + +#endif diff --git a/include/astra/DataProjectorPolicies.h b/include/astra/DataProjectorPolicies.h new file mode 100644 index 0000000..5ec08bd --- /dev/null +++ b/include/astra/DataProjectorPolicies.h @@ -0,0 +1,382 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_DATAPROJECTORPOLICIES +#define _INC_ASTRA_DATAPROJECTORPOLICIES + +#include "Globals.h" +#include "Config.h" + +#include + +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + +namespace astra { + +//enum {PixelDrivenPolicy, RayDrivenPolicy, AllPolicy} PolicyType; + + +//---------------------------------------------------------------------------------------- +/** Policy for Default Forward Projection (Ray Driven) + */ +class DefaultFPPolicy { + + //< Projection Data + CFloat32ProjectionData2D* m_pProjectionData; + //< Volume Data + CFloat32VolumeData2D* m_pVolumeData; + +public: + FORCEINLINE DefaultFPPolicy(); + FORCEINLINE DefaultFPPolicy(CFloat32VolumeData2D* _pVolumeData, CFloat32ProjectionData2D* _pProjectionData); + FORCEINLINE ~DefaultFPPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + + +//---------------------------------------------------------------------------------------- +/** Policy for Default Back Projection. (Ray+Pixel Driven) + * This does VolumeData += transpose(ProjectionMap) * ProjectionData. + */ +class DefaultBPPolicy { + + //< Projection Data + CFloat32ProjectionData2D* m_pProjectionData; + //< Volume Data + CFloat32VolumeData2D* m_pVolumeData; + +public: + FORCEINLINE DefaultBPPolicy(); + FORCEINLINE DefaultBPPolicy(CFloat32VolumeData2D* _pVolumeData, CFloat32ProjectionData2D* _pProjectionData); + FORCEINLINE ~DefaultBPPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + + + +//---------------------------------------------------------------------------------------- +/** Policy For Calculating the Projection Difference between Volume Data and Projection Data (Ray Driven) + */ +class DiffFPPolicy { + + CFloat32ProjectionData2D* m_pDiffProjectionData; + CFloat32ProjectionData2D* m_pBaseProjectionData; + CFloat32VolumeData2D* m_pVolumeData; +public: + + FORCEINLINE DiffFPPolicy(); + FORCEINLINE DiffFPPolicy(CFloat32VolumeData2D* _vol_data, CFloat32ProjectionData2D* _proj_data, CFloat32ProjectionData2D* _proj_data_base); + FORCEINLINE ~DiffFPPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + +//---------------------------------------------------------------------------------------- +/** Store Pixel Weights (Ray+Pixel Driven) + */ +class StorePixelWeightsPolicy { + + SPixelWeight* m_pPixelWeights; + int m_iMaxPixelCount; + int m_iStoredPixelCount; + +public: + + FORCEINLINE StorePixelWeightsPolicy(); + FORCEINLINE StorePixelWeightsPolicy(SPixelWeight* _pPixelWeights, int _iMaxPixelCount); + FORCEINLINE ~StorePixelWeightsPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); + + FORCEINLINE int getStoredPixelCount(); +}; + + +//---------------------------------------------------------------------------------------- +/** Policy For Calculating the Total Pixel Weight Multiplied by Sinogram + */ +class TotalPixelWeightBySinogramPolicy { + + CFloat32VolumeData2D* m_pPixelWeight; + CFloat32ProjectionData2D* m_pSinogram; + +public: + + FORCEINLINE TotalPixelWeightBySinogramPolicy(); + FORCEINLINE TotalPixelWeightBySinogramPolicy(CFloat32ProjectionData2D* _pSinogram, CFloat32VolumeData2D* _pPixelWeight); + FORCEINLINE ~TotalPixelWeightBySinogramPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + +//---------------------------------------------------------------------------------------- +/** Policy For Calculating the Total Pixel Weight + */ +class TotalPixelWeightPolicy { + + CFloat32VolumeData2D* m_pPixelWeight; + +public: + + FORCEINLINE TotalPixelWeightPolicy(); + FORCEINLINE TotalPixelWeightPolicy(CFloat32VolumeData2D* _pPixelWeight); + FORCEINLINE ~TotalPixelWeightPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + +//---------------------------------------------------------------------------------------- +/** Policy For Calculating the the Total Ray Length + */ +class TotalRayLengthPolicy { + + CFloat32ProjectionData2D* m_pRayLength; + +public: + + FORCEINLINE TotalRayLengthPolicy(); + FORCEINLINE TotalRayLengthPolicy(CFloat32ProjectionData2D* _pRayLength); + FORCEINLINE ~TotalRayLengthPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + + +//---------------------------------------------------------------------------------------- +/** Policy For Combining Two Policies + */ +template +class CombinePolicy { + + P1 policy1; + P2 policy2; + +public: + + FORCEINLINE CombinePolicy(); + FORCEINLINE CombinePolicy(P1 _policy1, P2 _policy2); + FORCEINLINE ~CombinePolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + +//---------------------------------------------------------------------------------------- +/** Policy For Combining Three Policies + */ +template +class Combine3Policy { + + P1 policy1; + P2 policy2; + P3 policy3; + +public: + + FORCEINLINE Combine3Policy(); + FORCEINLINE Combine3Policy(P1 _policy1, P2 _policy2, P3 _policy3); + FORCEINLINE ~Combine3Policy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + +//---------------------------------------------------------------------------------------- +/** Policy For Combining Four Policies + */ +template +class Combine4Policy { + + P1 policy1; + P2 policy2; + P3 policy3; + P4 policy4; + +public: + + FORCEINLINE Combine4Policy(); + FORCEINLINE Combine4Policy(P1 _policy1, P2 _policy2, P3 _policy3, P4 _policy4); + FORCEINLINE ~Combine4Policy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + +//---------------------------------------------------------------------------------------- +/** Policy For Combining a List of the same Policies + */ +template +class CombineListPolicy { + + std::vector

policyList; + unsigned int size; + +public: + + FORCEINLINE CombineListPolicy(); + FORCEINLINE CombineListPolicy(std::vector

_policyList); + FORCEINLINE ~CombineListPolicy(); + + FORCEINLINE void addPolicy(P _policy); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + +//---------------------------------------------------------------------------------------- +/** Empty Policy + */ +class EmptyPolicy { + +public: + + FORCEINLINE EmptyPolicy(); + FORCEINLINE ~EmptyPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + +//---------------------------------------------------------------------------------------- +/** Policy For SIRT Backprojection + */ +class SIRTBPPolicy { + + CFloat32ProjectionData2D* m_pSinogram; + CFloat32VolumeData2D* m_pReconstruction; + + CFloat32ProjectionData2D* m_pTotalRayLength; + CFloat32VolumeData2D* m_pTotalPixelWeight; + +public: + + FORCEINLINE SIRTBPPolicy(); + FORCEINLINE SIRTBPPolicy(CFloat32VolumeData2D* _pReconstruction, CFloat32ProjectionData2D* _pSinogram, CFloat32VolumeData2D* _pTotalPixelWeight, CFloat32ProjectionData2D* _pTotalRayLength); + FORCEINLINE ~SIRTBPPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + + +//---------------------------------------------------------------------------------------- +/** Policy For Sinogram Mask + */ +class SinogramMaskPolicy { + + CFloat32ProjectionData2D* m_pSinogramMask; + +public: + + FORCEINLINE SinogramMaskPolicy(); + FORCEINLINE SinogramMaskPolicy(CFloat32ProjectionData2D* _pSinogramMask); + FORCEINLINE ~SinogramMaskPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + +//---------------------------------------------------------------------------------------- +/** Policy For Reconstruction Mask + */ +class ReconstructionMaskPolicy { + + CFloat32VolumeData2D* m_pReconstructionMask; + +public: + + FORCEINLINE ReconstructionMaskPolicy(); + FORCEINLINE ReconstructionMaskPolicy(CFloat32VolumeData2D* _pReconstructionMask); + FORCEINLINE ~ReconstructionMaskPolicy(); + + FORCEINLINE bool rayPrior(int _iRayIndex); + FORCEINLINE bool pixelPrior(int _iVolumeIndex); + FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight); + FORCEINLINE void rayPosterior(int _iRayIndex); + FORCEINLINE void pixelPosterior(int _iVolumeIndex); +}; + +//---------------------------------------------------------------------------------------- + +#include "DataProjectorPolicies.inl" + +} // end namespace + +#endif diff --git a/include/astra/DataProjectorPolicies.inl b/include/astra/DataProjectorPolicies.inl new file mode 100644 index 0000000..b2166c3 --- /dev/null +++ b/include/astra/DataProjectorPolicies.inl @@ -0,0 +1,855 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_DATAPROJECTORPOLICIES_INLINE +#define _INC_ASTRA_DATAPROJECTORPOLICIES_INLINE + + + +//---------------------------------------------------------------------------------------- +// DEFAULT FORWARD PROJECTION (Ray Driven) +//---------------------------------------------------------------------------------------- +DefaultFPPolicy::DefaultFPPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +DefaultFPPolicy::DefaultFPPolicy(CFloat32VolumeData2D* _pVolumeData, + CFloat32ProjectionData2D* _pProjectionData) +{ + m_pProjectionData = _pProjectionData; + m_pVolumeData = _pVolumeData; +} +//---------------------------------------------------------------------------------------- +DefaultFPPolicy::~DefaultFPPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +bool DefaultFPPolicy::rayPrior(int _iRayIndex) +{ + m_pProjectionData->getData()[_iRayIndex] = 0.0f; + return true; +} +//---------------------------------------------------------------------------------------- +bool DefaultFPPolicy::pixelPrior(int _iVolumeIndex) +{ + // do nothing + return true; +} +//---------------------------------------------------------------------------------------- +void DefaultFPPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + m_pProjectionData->getData()[_iRayIndex] += m_pVolumeData->getData()[_iVolumeIndex] * _fWeight; +} +//---------------------------------------------------------------------------------------- +void DefaultFPPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void DefaultFPPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------------------- +// DEFAULT BACK PROJECTION (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +DefaultBPPolicy::DefaultBPPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +DefaultBPPolicy::DefaultBPPolicy(CFloat32VolumeData2D* _pVolumeData, + CFloat32ProjectionData2D* _pProjectionData) +{ + m_pProjectionData = _pProjectionData; + m_pVolumeData = _pVolumeData; +} +//---------------------------------------------------------------------------------------- +DefaultBPPolicy::~DefaultBPPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +bool DefaultBPPolicy::rayPrior(int _iRayIndex) +{ + // do nothing + return true; +} +//---------------------------------------------------------------------------------------- +bool DefaultBPPolicy::pixelPrior(int _iVolumeIndex) +{ + // do nothing + return true; +} +//---------------------------------------------------------------------------------------- +void DefaultBPPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + m_pVolumeData->getData()[_iVolumeIndex] += m_pProjectionData->getData()[_iRayIndex] * _fWeight; +} +//---------------------------------------------------------------------------------------- +void DefaultBPPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void DefaultBPPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- + + + + +//---------------------------------------------------------------------------------------- +// FORWARD PROJECTION DIFFERENCE CALCULATION (Ray Driven) +//---------------------------------------------------------------------------------------- +DiffFPPolicy::DiffFPPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +DiffFPPolicy::DiffFPPolicy(CFloat32VolumeData2D* _pVolumeData, + CFloat32ProjectionData2D* _pDiffProjectionData, + CFloat32ProjectionData2D* _pBaseProjectionData) +{ + m_pDiffProjectionData = _pDiffProjectionData; + m_pBaseProjectionData = _pBaseProjectionData; + m_pVolumeData = _pVolumeData; +} +//---------------------------------------------------------------------------------------- +DiffFPPolicy::~DiffFPPolicy() +{ + +} +//---------------------------------------------------------------------------------------- + bool DiffFPPolicy::rayPrior(int _iRayIndex) +{ + m_pDiffProjectionData->getData()[_iRayIndex] = m_pBaseProjectionData->getData()[_iRayIndex]; + return true; +} +//---------------------------------------------------------------------------------------- +bool DiffFPPolicy::pixelPrior(int _iVolumeIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +void DiffFPPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + m_pDiffProjectionData->getData()[_iRayIndex] -= m_pVolumeData->getData()[_iVolumeIndex] * _fWeight; +} +//---------------------------------------------------------------------------------------- +void DiffFPPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void DiffFPPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------------------- +// STORE PIXEL WEIGHT (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +StorePixelWeightsPolicy::StorePixelWeightsPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +StorePixelWeightsPolicy::StorePixelWeightsPolicy(SPixelWeight* _pPixelWeights, int _iMaxPixelCount) +{ + m_iStoredPixelCount = 0; + m_pPixelWeights = _pPixelWeights; + m_iMaxPixelCount = _iMaxPixelCount; +} +//---------------------------------------------------------------------------------------- +StorePixelWeightsPolicy::~StorePixelWeightsPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +bool StorePixelWeightsPolicy::rayPrior(int _iRayIndex) +{ + return (m_iStoredPixelCount < m_iMaxPixelCount); +} +//---------------------------------------------------------------------------------------- +bool StorePixelWeightsPolicy::pixelPrior(int _iVolumeIndex) +{ + return (m_iStoredPixelCount < m_iMaxPixelCount); +} +//---------------------------------------------------------------------------------------- +void StorePixelWeightsPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + m_pPixelWeights[m_iStoredPixelCount].m_fWeight = _fWeight; + m_pPixelWeights[m_iStoredPixelCount].m_iIndex = _iVolumeIndex; + ++m_iStoredPixelCount; +} +//---------------------------------------------------------------------------------------- +void StorePixelWeightsPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void StorePixelWeightsPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +int StorePixelWeightsPolicy::getStoredPixelCount() +{ + return m_iStoredPixelCount; +} +//---------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------------------- +// TOTAL PIXEL WEIGHT MULTIPLIED BY SINOGRAM (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +TotalPixelWeightBySinogramPolicy::TotalPixelWeightBySinogramPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +TotalPixelWeightBySinogramPolicy::TotalPixelWeightBySinogramPolicy(CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pPixelWeight) +{ + m_pPixelWeight = _pPixelWeight; + m_pSinogram = _pSinogram; +} +//---------------------------------------------------------------------------------------- +TotalPixelWeightBySinogramPolicy::~TotalPixelWeightBySinogramPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +bool TotalPixelWeightBySinogramPolicy::rayPrior(int _iRayIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +bool TotalPixelWeightBySinogramPolicy::pixelPrior(int _iVolumeIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +void TotalPixelWeightBySinogramPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + m_pPixelWeight->getData()[_iVolumeIndex] += _fWeight * m_pSinogram->getData()[_iRayIndex]; +} +//---------------------------------------------------------------------------------------- +void TotalPixelWeightBySinogramPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void TotalPixelWeightBySinogramPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- + + + + + +//---------------------------------------------------------------------------------------- +// TOTAL PIXEL WEIGHT (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +TotalPixelWeightPolicy::TotalPixelWeightPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +TotalPixelWeightPolicy::TotalPixelWeightPolicy(CFloat32VolumeData2D* _pPixelWeight) +{ + m_pPixelWeight = _pPixelWeight; +} +//---------------------------------------------------------------------------------------- +TotalPixelWeightPolicy::~TotalPixelWeightPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +bool TotalPixelWeightPolicy::rayPrior(int _iRayIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +bool TotalPixelWeightPolicy::pixelPrior(int _iVolumeIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +void TotalPixelWeightPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + m_pPixelWeight->getData()[_iVolumeIndex] += _fWeight; +} +//---------------------------------------------------------------------------------------- +void TotalPixelWeightPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void TotalPixelWeightPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- + + + + +//---------------------------------------------------------------------------------------- +// TOTAL RAY LENGTH (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +TotalRayLengthPolicy::TotalRayLengthPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +TotalRayLengthPolicy::TotalRayLengthPolicy(CFloat32ProjectionData2D* _pRayLength) +{ + m_pRayLength = _pRayLength; +} +//---------------------------------------------------------------------------------------- +TotalRayLengthPolicy::~TotalRayLengthPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +bool TotalRayLengthPolicy::rayPrior(int _iRayIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +bool TotalRayLengthPolicy::pixelPrior(int _iVolumeIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +void TotalRayLengthPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + m_pRayLength->getData()[_iRayIndex] += _fWeight; +} +//---------------------------------------------------------------------------------------- +void TotalRayLengthPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void TotalRayLengthPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- + + + + + +//---------------------------------------------------------------------------------------- +// COMBINE TWO POLICIES (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +template +CombinePolicy::CombinePolicy() +{ + +} +//---------------------------------------------------------------------------------------- +template +CombinePolicy::CombinePolicy(P1 _policy1, P2 _policy2) +{ + policy1 = _policy1; + policy2 = _policy2; +} +//---------------------------------------------------------------------------------------- +template +CombinePolicy::~CombinePolicy() +{ + +} +//---------------------------------------------------------------------------------------- +template +bool CombinePolicy::rayPrior(int _iRayIndex) +{ + if (!policy1.rayPrior(_iRayIndex)) return false; + return policy2.rayPrior(_iRayIndex); +} +//---------------------------------------------------------------------------------------- +template +bool CombinePolicy::pixelPrior(int _iVolumeIndex) +{ + if (!policy1.pixelPrior(_iVolumeIndex)) return false; + return policy2.pixelPrior(_iVolumeIndex); +} +//---------------------------------------------------------------------------------------- +template +void CombinePolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + policy1.addWeight(_iRayIndex, _iVolumeIndex, _fWeight); + policy2.addWeight(_iRayIndex, _iVolumeIndex, _fWeight); +} +//---------------------------------------------------------------------------------------- +template +void CombinePolicy::rayPosterior(int _iRayIndex) +{ + policy1.rayPosterior(_iRayIndex); + policy2.rayPosterior(_iRayIndex); +} +//---------------------------------------------------------------------------------------- +template +void CombinePolicy::pixelPosterior(int _iVolumeIndex) +{ + policy1.pixelPosterior(_iVolumeIndex); + policy2.pixelPosterior(_iVolumeIndex); +} +//---------------------------------------------------------------------------------------- + + + + +//---------------------------------------------------------------------------------------- +// COMBINE THREE POLICIES (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +template +Combine3Policy::Combine3Policy() +{ + +} +//---------------------------------------------------------------------------------------- +template +Combine3Policy::Combine3Policy(P1 _policy1, P2 _policy2, P3 _policy3) +{ + policy1 = _policy1; + policy2 = _policy2; + policy3 = _policy3; +} +//---------------------------------------------------------------------------------------- +template +Combine3Policy::~Combine3Policy() +{ + +} +//---------------------------------------------------------------------------------------- +template +bool Combine3Policy::rayPrior(int _iRayIndex) +{ + if (!policy1.rayPrior(_iRayIndex)) return false; + if (!policy2.rayPrior(_iRayIndex)) return false; + return policy3.rayPrior(_iRayIndex); +} +//---------------------------------------------------------------------------------------- +template +bool Combine3Policy::pixelPrior(int _iVolumeIndex) +{ + if (!policy1.pixelPrior(_iVolumeIndex)) return false; + if (!policy2.pixelPrior(_iVolumeIndex)) return false; + return policy3.pixelPrior(_iVolumeIndex); +} +//---------------------------------------------------------------------------------------- +template +void Combine3Policy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + policy1.addWeight(_iRayIndex, _iVolumeIndex, _fWeight); + policy2.addWeight(_iRayIndex, _iVolumeIndex, _fWeight); + policy3.addWeight(_iRayIndex, _iVolumeIndex, _fWeight); +} +//---------------------------------------------------------------------------------------- +template +void Combine3Policy::rayPosterior(int _iRayIndex) +{ + policy1.rayPosterior(_iRayIndex); + policy2.rayPosterior(_iRayIndex); + policy3.rayPosterior(_iRayIndex); +} +//---------------------------------------------------------------------------------------- +template +void Combine3Policy::pixelPosterior(int _iVolumeIndex) +{ + policy1.pixelPosterior(_iVolumeIndex); + policy2.pixelPosterior(_iVolumeIndex); + policy3.pixelPosterior(_iVolumeIndex); +} +//---------------------------------------------------------------------------------------- + + + + + + +//---------------------------------------------------------------------------------------- +// COMBINE FOUR POLICIES (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +template +Combine4Policy::Combine4Policy() +{ + +} +//---------------------------------------------------------------------------------------- +template +Combine4Policy::Combine4Policy(P1 _policy1, P2 _policy2, P3 _policy3, P4 _policy4) +{ + policy1 = _policy1; + policy2 = _policy2; + policy3 = _policy3; + policy4 = _policy4; +} +//---------------------------------------------------------------------------------------- +template +Combine4Policy::~Combine4Policy() +{ + +} +//---------------------------------------------------------------------------------------- +template +bool Combine4Policy::rayPrior(int _iRayIndex) +{ + if (!policy1.rayPrior(_iRayIndex)) return false; + if (!policy2.rayPrior(_iRayIndex)) return false; + if (!policy3.rayPrior(_iRayIndex)) return false; + return policy4.rayPrior(_iRayIndex); +} +//---------------------------------------------------------------------------------------- +template +bool Combine4Policy::pixelPrior(int _iVolumeIndex) +{ + if (!policy1.pixelPrior(_iVolumeIndex)) return false; + if (!policy2.pixelPrior(_iVolumeIndex)) return false; + if (!policy3.pixelPrior(_iVolumeIndex)) return false; + return policy4.pixelPrior(_iVolumeIndex); +} +//---------------------------------------------------------------------------------------- +template +void Combine4Policy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + policy1.addWeight(_iRayIndex, _iVolumeIndex, _fWeight); + policy2.addWeight(_iRayIndex, _iVolumeIndex, _fWeight); + policy3.addWeight(_iRayIndex, _iVolumeIndex, _fWeight); + policy4.addWeight(_iRayIndex, _iVolumeIndex, _fWeight); +} +//---------------------------------------------------------------------------------------- +template +void Combine4Policy::rayPosterior(int _iRayIndex) +{ + policy1.rayPosterior(_iRayIndex); + policy2.rayPosterior(_iRayIndex); + policy3.rayPosterior(_iRayIndex); + policy4.rayPosterior(_iRayIndex); +} +//---------------------------------------------------------------------------------------- +template +void Combine4Policy::pixelPosterior(int _iVolumeIndex) +{ + policy1.pixelPosterior(_iVolumeIndex); + policy2.pixelPosterior(_iVolumeIndex); + policy3.pixelPosterior(_iVolumeIndex); + policy4.pixelPosterior(_iVolumeIndex); +} +//---------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------------------- +// COMBINE LIST OF EQUAL POLICIES (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +template +CombineListPolicy

::CombineListPolicy() +{ + size = 0; +} +//---------------------------------------------------------------------------------------- +template +CombineListPolicy

::CombineListPolicy(std::vector

_policyList) +{ + policyList = _policyList; + size = policyList.size(); +} +//---------------------------------------------------------------------------------------- +template +CombineListPolicy

::~CombineListPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +template +void CombineListPolicy

::addPolicy(P _policy) +{ + policyList.push_back(_policy); + size = policyList.size(); +} +//---------------------------------------------------------------------------------------- +template +bool CombineListPolicy

::rayPrior(int _iRayIndex) +{ + for(unsigned int i = 0; i < size; ++i) { + if (!policyList[i].rayPrior(_iRayIndex)) return false; + } + return true; +} +//---------------------------------------------------------------------------------------- +template +bool CombineListPolicy

::pixelPrior(int _iVolumeIndex) +{ + for(unsigned int i = 0; i < size; ++i) { + if (!policyList[i].pixelPrior(_iVolumeIndex)) return false; + } + return true; +} +//---------------------------------------------------------------------------------------- +template +void CombineListPolicy

::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + for(unsigned int i = 0; i < size; ++i) { + policyList[i].addWeight(_iRayIndex, _iVolumeIndex, _fWeight); + } +} +//---------------------------------------------------------------------------------------- +template +void CombineListPolicy

::rayPosterior(int _iRayIndex) +{ + for(unsigned int i = 0; i < size; ++i) { + policyList[i].rayPosterior(_iRayIndex); + } +} +//---------------------------------------------------------------------------------------- +template +void CombineListPolicy

::pixelPosterior(int _iVolumeIndex) +{ + for(unsigned int i = 0; i < size; ++i) { + policyList[i].pixelPosterior(_iVolumeIndex); + } +} +//---------------------------------------------------------------------------------------- + + + + + +//---------------------------------------------------------------------------------------- +// EMPTY POLICY (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +EmptyPolicy::EmptyPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +EmptyPolicy::~EmptyPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +bool EmptyPolicy::rayPrior(int _iRayIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +bool EmptyPolicy::pixelPrior(int _iVolumeIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +void EmptyPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void EmptyPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void EmptyPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------------------- +// SIRT BACKPROJECTION (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +SIRTBPPolicy::SIRTBPPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +SIRTBPPolicy::SIRTBPPolicy(CFloat32VolumeData2D* _pReconstruction, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pTotalPixelWeight, + CFloat32ProjectionData2D* _pTotalRayLength) +{ + m_pReconstruction = _pReconstruction; + m_pSinogram = _pSinogram; + m_pTotalPixelWeight = _pTotalPixelWeight; + m_pTotalRayLength = _pTotalRayLength; +} +//---------------------------------------------------------------------------------------- +SIRTBPPolicy::~SIRTBPPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +bool SIRTBPPolicy::rayPrior(int _iRayIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +bool SIRTBPPolicy::pixelPrior(int _iVolumeIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +void SIRTBPPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + float32 fGammaBeta = m_pTotalPixelWeight->getData()[_iVolumeIndex] * m_pTotalRayLength->getData()[_iRayIndex]; + if ((fGammaBeta > 0.001f) || (fGammaBeta < -0.001f)) { + m_pReconstruction->getData()[_iVolumeIndex] += _fWeight * m_pSinogram->getData()[_iRayIndex] / fGammaBeta; + } +} +//---------------------------------------------------------------------------------------- +void SIRTBPPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void SIRTBPPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- + + + + + +//---------------------------------------------------------------------------------------- +// SINOGRAM MASK (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +SinogramMaskPolicy::SinogramMaskPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +SinogramMaskPolicy::SinogramMaskPolicy(CFloat32ProjectionData2D* _pSinogramMask) +{ + m_pSinogramMask = _pSinogramMask; +} +//---------------------------------------------------------------------------------------- +SinogramMaskPolicy::~SinogramMaskPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +bool SinogramMaskPolicy::rayPrior(int _iRayIndex) +{ + return (m_pSinogramMask->getData()[_iRayIndex] != 0); +} +//---------------------------------------------------------------------------------------- +bool SinogramMaskPolicy::pixelPrior(int _iVolumeIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +void SinogramMaskPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void SinogramMaskPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void SinogramMaskPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- + + + + + +//---------------------------------------------------------------------------------------- +// RECONSTRUCTION MASK (Ray+Pixel Driven) +//---------------------------------------------------------------------------------------- +ReconstructionMaskPolicy::ReconstructionMaskPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +ReconstructionMaskPolicy::ReconstructionMaskPolicy(CFloat32VolumeData2D* _pReconstructionMask) +{ + m_pReconstructionMask = _pReconstructionMask; +} +//---------------------------------------------------------------------------------------- +ReconstructionMaskPolicy::~ReconstructionMaskPolicy() +{ + +} +//---------------------------------------------------------------------------------------- +bool ReconstructionMaskPolicy::rayPrior(int _iRayIndex) +{ + return true; +} +//---------------------------------------------------------------------------------------- +bool ReconstructionMaskPolicy::pixelPrior(int _iVolumeIndex) +{ + return (m_pReconstructionMask->getData()[_iVolumeIndex] != 0); +} +//---------------------------------------------------------------------------------------- +void ReconstructionMaskPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void ReconstructionMaskPolicy::rayPosterior(int _iRayIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- +void ReconstructionMaskPolicy::pixelPosterior(int _iVolumeIndex) +{ + // nothing +} +//---------------------------------------------------------------------------------------- + + + +#endif diff --git a/include/astra/FanFlatBeamLineKernelProjector2D.h b/include/astra/FanFlatBeamLineKernelProjector2D.h new file mode 100644 index 0000000..154504a --- /dev/null +++ b/include/astra/FanFlatBeamLineKernelProjector2D.h @@ -0,0 +1,194 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FANFLATBEAMLINEKERNELPROJECTOR +#define _INC_ASTRA_FANFLATBEAMLINEKERNELPROJECTOR + +#include "FanFlatProjectionGeometry2D.h" +#include "FanFlatVecProjectionGeometry2D.h" +#include "Float32Data2D.h" +#include "Projector2D.h" + +namespace astra +{ + + +/** This class implements a two-dimensional projector based on a line based kernel + * with a fan flat projection geometry. + * + * \par XML Configuration + * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.} + * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('fanflat_line');\n + * cfg.ProjectionGeometry = proj_geom;\n + * cfg.VolumeGeometry = vol_geom;\n + * proj_id = astra_mex_projector('create'\, cfg);\n + * } + */ +class _AstraExport CFanFlatBeamLineKernelProjector2D : public CProjector2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - blobvalues are ok + */ + virtual bool _check(); + +public: + + // type of the projector, needed to register with CProjectorFactory + static std::string type; + + /** Default constructor. + */ + CFanFlatBeamLineKernelProjector2D(); + + /** Constructor. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + */ + CFanFlatBeamLineKernelProjector2D(CFanFlatProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Destructor, is virtual to show that we are aware subclass destructor are called. + */ + ~CFanFlatBeamLineKernelProjector2D(); + + /** Initialize the projector with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the projector. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + * @return initialization successful? + */ + virtual bool initialize(CFanFlatProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Clear this class. + */ + virtual void clear(); + + /** Returns the number of weights required for storage of all weights of one projection. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels. + */ + virtual int getProjectionWeightsCount(int _iProjectionIndex); + + /** Compute the pixel weights for a single ray, from the source to a detector pixel. + * + * @param _iProjectionIndex Index of the projection + * @param _iDetectorIndex Index of the detector pixel + * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements + * of type SPixelWeight. On return, this array contains a list of the index + * and weight for all pixels on the ray. + * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels. + * This number MUST be greater than the total number of pixels on the ray. + * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the + * ray (that have been stored in the list _pWeightedPixels). + */ + virtual void computeSingleRayWeights(int _iProjectionIndex, + int _iDetectorIndex, + SPixelWeight* _pWeightedPixels, + int _iMaxPixelCount, + int& _iStoredPixelCount); + + /** Create a list of detectors that are influenced by point [_iRow, _iCol]. + * + * @param _iRow row of the point + * @param _iCol column of the point + * @return list of SDetector2D structs + */ + virtual std::vector projectPoint(int _iRow, int _iCol); + + /** Policy-based projection of all rays. This function will calculate each non-zero projection + * weight and use this value for a task provided by the policy object. + * + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void project(Policy& _policy); + + /** Policy-based projection of all rays of a single projection. This function will calculate + * each non-zero projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Wwhich projection should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleProjection(int _iProjection, Policy& _policy); + + /** Policy-based projection of a single ray. This function will calculate each non-zero + * projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Which projection should be projected? + * @param _iDetector Which detector should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy); + + /** Return the type of this projector. + * + * @return identification type of this projector + */ + virtual std::string getType(); + + float32 angleBetweenVectors(float32 _fAX, float32 _fAY, float32 _fBX, float32 _fBY); + +}; + +//---------------------------------------------------------------------------------------- + +inline std::string CFanFlatBeamLineKernelProjector2D::getType() +{ + return type; +} + + +} // namespace astra + +#endif + diff --git a/include/astra/FanFlatBeamLineKernelProjector2D.inl b/include/astra/FanFlatBeamLineKernelProjector2D.inl new file mode 100644 index 0000000..e686532 --- /dev/null +++ b/include/astra/FanFlatBeamLineKernelProjector2D.inl @@ -0,0 +1,740 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + + +using namespace astra; + +//---------------------------------------------------------------------------------------- +// PROJECT ALL +template +void CFanFlatBeamLineKernelProjector2D::project(Policy& p) +{ + // variables + float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, S, T, t, I, P, x, x2; + float32 lengthPerRow, updatePerRow, inv_pixelLengthX, lengthPerCol, updatePerCol, inv_pixelLengthY; + int iVolumeIndex, iRayIndex, row, col, iAngle, iDetector, x1; + bool switch_t; + + const CFanFlatProjectionGeometry2D* pProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + const CFanFlatVecProjectionGeometry2D* pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + + float32 old_theta, theta, alpha; + const SFanProjection * proj = 0; + + // loop angles + for (iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) { + + // get theta + if (pProjectionGeometry) { + old_theta = pProjectionGeometry->getProjectionAngle(iAngle); + } + else if (pVecProjectionGeometry) { + proj = &pVecProjectionGeometry->getProjectionVectors()[iAngle]; + old_theta = atan2(-proj->fSrcX, proj->fSrcY); + if (old_theta < 0) old_theta += 2*PI; + } else { + assert(false); + } + + switch_t = false; + if (old_theta >= 7*PIdiv4) old_theta -= 2*PI; + if (old_theta >= 3*PIdiv4) { + old_theta -= PI; + switch_t = true; + } + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get values + if (pProjectionGeometry) { + t = -pProjectionGeometry->indexToDetectorOffset(iDetector); + alpha = atan(t / pProjectionGeometry->getSourceDetectorDistance()); + t = sin(alpha) * pProjectionGeometry->getOriginSourceDistance(); + } + else if (pVecProjectionGeometry) { + float32 detX = proj->fDetSX + proj->fDetUX*(0.5f + iDetector); + float32 detY = proj->fDetSY + proj->fDetUY*(0.5f + iDetector); + alpha = angleBetweenVectors(-proj->fSrcX, -proj->fSrcY, detX - proj->fSrcX, detY - proj->fSrcY); + t = sin(alpha) * sqrt(proj->fSrcX*proj->fSrcX + proj->fSrcY*proj->fSrcY); + } else { + assert(false); + } + + if (switch_t) t = -t; + theta = old_theta + alpha; + + // precalculate sin, cos, 1/cos + sin_theta = sin(theta); + cos_theta = cos(theta); + inv_sin_theta = 1.0f / sin_theta; + inv_cos_theta = 1.0f / cos_theta; + + // precalculate kernel limits + lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta; + updatePerRow = sin_theta * inv_cos_theta; + inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); + + // precalculate kernel limits + lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta; + updatePerCol = cos_theta * inv_sin_theta; + inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); + + // precalculate S and T + S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow); + T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol); + + // vertically + if (old_theta <= PIdiv4) { + + // calculate x for row 0 + P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta; + x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get coords + x1 = int((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerRow; + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue; + + // left + if (x2 < 0.5f-S) { + I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridColCount()*/) {//x1 is always less than or equal to gridColCount because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+S) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // right + else if (x2 <= 1.0f) { + I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridColCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } + + // horizontally + //else if (PIdiv4 <= old_theta && old_theta <= 3*PIdiv4) { + else { + + // calculate point P + P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta; + x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get coords + x1 = int((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerCol; + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue; + + // up + if (x2 < 0.5f-T) { + I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridRowCount()*/) {//x1 is always less than or equal to gridRowCount because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+T) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // down + else if (x2 <= 1.0f) { + I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridRowCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } // end loop col + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end loop detector + } // end loop angles +} + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE PROJECTION +template +void CFanFlatBeamLineKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p) +{ + // variables + float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, S, T, t, I, P, x, x2; + float32 lengthPerRow, updatePerRow, inv_pixelLengthX, lengthPerCol, updatePerCol, inv_pixelLengthY; + int iVolumeIndex, iRayIndex, row, col, iDetector, x1; + bool switch_t; + + const CFanFlatProjectionGeometry2D* pProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + const CFanFlatVecProjectionGeometry2D* pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + + float32 old_theta, theta, alpha; + const SFanProjection * proj = 0; + + //get theta + if (pProjectionGeometry) { + old_theta = pProjectionGeometry->getProjectionAngle(_iProjection); + } + else if (pVecProjectionGeometry) { + proj = &pVecProjectionGeometry->getProjectionVectors()[_iProjection]; + old_theta = atan2(-proj->fSrcX, proj->fSrcY); + if (old_theta < 0) old_theta += 2*PI; + } else { + assert(false); + } + + switch_t = false; + if (old_theta >= 7*PIdiv4) old_theta -= 2*PI; + if (old_theta >= 3*PIdiv4) { + old_theta -= PI; + switch_t = true; + } + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + if (pProjectionGeometry) { + t = -pProjectionGeometry->indexToDetectorOffset(iDetector); + alpha = atan(t / pProjectionGeometry->getSourceDetectorDistance()); + t = sin(alpha) * pProjectionGeometry->getOriginSourceDistance(); + } + else if (pVecProjectionGeometry) { + float32 detX = proj->fDetSX + proj->fDetUX*(0.5f + iDetector); + float32 detY = proj->fDetSY + proj->fDetUY*(0.5f + iDetector); + alpha = angleBetweenVectors(-proj->fSrcX, -proj->fSrcY, detX - proj->fSrcX, detY - proj->fSrcY); + t = sin(alpha) * sqrt(proj->fSrcX*proj->fSrcX + proj->fSrcY*proj->fSrcY); + } else { + assert(false); + } + + if (switch_t) t = -t; + theta = old_theta + alpha; + + // precalculate sin, cos, 1/cos + sin_theta = sin(theta); + cos_theta = cos(theta); + inv_sin_theta = 1.0f / sin_theta; + inv_cos_theta = 1.0f / cos_theta; + + // precalculate kernel limits + lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta; + updatePerRow = sin_theta * inv_cos_theta; + inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); + + // precalculate kernel limits + lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta; + updatePerCol = cos_theta * inv_sin_theta; + inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); + + // precalculate S and T + S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow); + T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol); + + // vertically + if (old_theta <= PIdiv4) { + + // calculate x for row 0 + P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta; + x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get coords + x1 = int((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerRow; + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue; + + // left + if (x2 < 0.5f-S) { + I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridColCount()*/) {//x1 is always less than or equal to gridColCount because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+S) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // right + else if (x2 <= 1.0f) { + I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridColCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } + + // horizontally + else { + + // calculate point P + P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta; + x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get coords + x1 = int((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerCol; + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue; + + // up + if (x2 < 0.5f-T) { + I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridRowCount()*/) {//x1 is always less than or equal to gridRowCount because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+T) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // down + else if (x2 <= 1.0f) { + I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridRowCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } // end loop col + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end loop detector + +} + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE RAY +template +void CFanFlatBeamLineKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p) +{ + // variables + float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, S, T, t, I, P, x, x2; + float32 lengthPerRow, updatePerRow, inv_pixelLengthX, lengthPerCol, updatePerCol, inv_pixelLengthY; + int iVolumeIndex, iRayIndex, row, col, x1; + bool switch_t; + + const CFanFlatProjectionGeometry2D* pProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + const CFanFlatVecProjectionGeometry2D* pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) return; + + float32 old_theta, theta, alpha; + if (pProjectionGeometry) { + old_theta = pProjectionGeometry->getProjectionAngle(_iProjection); + t = -pProjectionGeometry->indexToDetectorOffset(_iDetector); + alpha = atan(t / pProjectionGeometry->getSourceDetectorDistance()); + t = sin(alpha) * pProjectionGeometry->getOriginSourceDistance(); + } + else if (pVecProjectionGeometry) { + const SFanProjection * proj = &pVecProjectionGeometry->getProjectionVectors()[_iProjection]; + old_theta = atan2(-proj->fSrcX, proj->fSrcY); + if (old_theta < 0) old_theta += 2*PI; + + float32 detX = proj->fDetSX + proj->fDetUX*(0.5f + _iDetector); + float32 detY = proj->fDetSY + proj->fDetUY*(0.5f + _iDetector); + alpha = angleBetweenVectors(-proj->fSrcX, -proj->fSrcY, detX - proj->fSrcX, detY - proj->fSrcY); + t = sin(alpha) * sqrt(proj->fSrcX*proj->fSrcX + proj->fSrcY*proj->fSrcY); + } else { + assert(false); + } + + switch_t = false; + if (old_theta >= 7*PIdiv4) old_theta -= 2*PI; + if (old_theta >= 3*PIdiv4) { + old_theta -= PI; + switch_t = true; + } + if (switch_t) t = -t; + theta = old_theta + alpha; + + // precalculate sin, cos, 1/cos + sin_theta = sin(theta); + cos_theta = cos(theta); + inv_sin_theta = 1.0f / sin_theta; + inv_cos_theta = 1.0f / cos_theta; + + // precalculate kernel limits + lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta; + updatePerRow = sin_theta * inv_cos_theta; + inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); + + // precalculate kernel limits + lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta; + updatePerCol = cos_theta * inv_sin_theta; + inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); + + // precalculate S and T + S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow); + T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol); + + // vertically + if (old_theta <= PIdiv4) { + + // calculate x for row 0 + P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta; + x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get coords + x1 = int((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerRow; + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue; + + // left + if (x2 < 0.5f-S) { + I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridColCount()*/) {//x1 is always less than or equal to gridColCount because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+S) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // right + else if (x2 <= 1.0f) { + I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridColCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } + + // horizontally + else { + + // calculate point P + P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta; + x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get coords + x1 = int((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerCol; + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue; + + // up + if (x2 < 0.5f-T) { + I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridRowCount()*/) {//x1 is always less than or equal to gridRowCount because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+T) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // down + else if (x2 <= 1.0f) { + I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridRowCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } // end loop col + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); +} diff --git a/include/astra/FanFlatBeamStripKernelProjector2D.h b/include/astra/FanFlatBeamStripKernelProjector2D.h new file mode 100644 index 0000000..7fed4c8 --- /dev/null +++ b/include/astra/FanFlatBeamStripKernelProjector2D.h @@ -0,0 +1,191 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FANFLATBEAMSTRIPKERNELPROJECTOR +#define _INC_ASTRA_FANFLATBEAMSTRIPKERNELPROJECTOR + +#include "FanFlatProjectionGeometry2D.h" +#include "Float32Data2D.h" +#include "Projector2D.h" + +namespace astra +{ + + +/** This class implements a two-dimensional fan-flat-beam projector based on a strip based kernel. + * + * \par XML Configuration + * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.} + * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('strip_fanflat');\n + * cfg.ProjectionGeometry = proj_geom;\n + * cfg.VolumeGeometry = vol_geom;\n + * proj_id = astra_mex_projector('create'\, cfg);\n + * } + */ +class _AstraExport CFanFlatBeamStripKernelProjector2D : public CProjector2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - blobvalues are ok + */ + virtual bool _check(); + +public: + + // type of the projector, needed to register with CProjectorFactory + static std::string type; + + /** Default constructor. + */ + CFanFlatBeamStripKernelProjector2D(); + + /** Constructor. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + */ + CFanFlatBeamStripKernelProjector2D(CFanFlatProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Destructor, is virtual to show that we are aware subclass destructor are called. + */ + ~CFanFlatBeamStripKernelProjector2D(); + + /** Initialize the projector with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the projector. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + * @return initialization successful? + */ + virtual bool initialize(CFanFlatProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Clear this class. + */ + virtual void clear(); + + /** Returns the number of weights required for storage of all weights of one projection. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels. + */ + virtual int getProjectionWeightsCount(int _iProjectionIndex); + + /** Compute the pixel weights for a single ray, from the source to a detector pixel. + * + * @param _iProjectionIndex Index of the projection + * @param _iDetectorIndex Index of the detector pixel + * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements + * of type SPixelWeight. On return, this array contains a list of the index + * and weight for all pixels on the ray. + * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels. + * This number MUST be greater than the total number of pixels on the ray. + * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the + * ray (that have been stored in the list _pWeightedPixels). + */ + virtual void computeSingleRayWeights(int _iProjectionIndex, + int _iDetectorIndex, + SPixelWeight* _pWeightedPixels, + int _iMaxPixelCount, + int& _iStoredPixelCount); + + /** Create a list of detectors that are influenced by point [_iRow, _iCol]. + * + * @param _iRow row of the point + * @param _iCol column of the point + * @return list of SDetector2D structs + */ + virtual std::vector projectPoint(int _iRow, int _iCol); + + /** Policy-based projection of all rays. This function will calculate each non-zero projection + * weight and use this value for a task provided by the policy object. + * + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void project(Policy& _policy); + + /** Policy-based projection of all rays of a single projection. This function will calculate + * each non-zero projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Wwhich projection should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleProjection(int _iProjection, Policy& _policy); + + /** Policy-based projection of a single ray. This function will calculate each non-zero + * projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Which projection should be projected? + * @param _iDetector Which detector should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy); + + /** Return the type of this projector. + * + * @return identification type of this projector + */ + virtual std::string getType(); + +}; + +//---------------------------------------------------------------------------------------- + +inline std::string CFanFlatBeamStripKernelProjector2D::getType() +{ + return type; +} + +} // namespace astra + + + +#endif + diff --git a/include/astra/FanFlatBeamStripKernelProjector2D.inl b/include/astra/FanFlatBeamStripKernelProjector2D.inl new file mode 100644 index 0000000..e3f8b29 --- /dev/null +++ b/include/astra/FanFlatBeamStripKernelProjector2D.inl @@ -0,0 +1,961 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + + +using namespace astra; + +//---------------------------------------------------------------------------------------- +// PROJECT ALL +template +void CFanFlatBeamStripKernelProjector2D::project(Policy& p) +{ + ASTRA_ASSERT(m_bIsInitialized); + + // Some variables + float32 theta; + int row, col; + int iAngle, iDetector; + float32 res; + int x1L, x1R; + float32 x2L, x2R; + int iVolumeIndex, iRayIndex; + + CFanFlatProjectionGeometry2D* projgeom = static_cast(m_pProjectionGeometry); + + // Other precalculations + float32 PW = m_pVolumeGeometry->getPixelLengthX(); + float32 PH = m_pVolumeGeometry->getPixelLengthY(); + float32 DW = m_pProjectionGeometry->getDetectorWidth(); + float32 inv_PW = 1.0f / PW; + float32 inv_PH = 1.0f / PH; + + // calculate alpha's + float32 alpha; + float32* cos_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1]; + float32* sin_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1]; + for (int i = 0; i < m_pProjectionGeometry->getDetectorCount() + 1; ++i) { + alpha = -atan((i - m_pProjectionGeometry->getDetectorCount()*0.5f) * DW / projgeom->getSourceDetectorDistance()); + cos_alpha[i] = cos(alpha); + sin_alpha[i] = sin(alpha); + } + + // loop angles + for (iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) { + + // get values + theta = m_pProjectionGeometry->getProjectionAngle(iAngle); + bool switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // Precalculate sin, cos, 1/cos + float32 sin_theta = sin(theta); + float32 cos_theta = cos(theta); + + // [-45?,45?] and [135?,225?] + if (theta < PIdiv4) { + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + float32 sin_theta_left, cos_theta_left; + float32 sin_theta_right, cos_theta_right; + + // get theta_l = alpha_left + theta and theta_r = alpha_right + theta + float32 t_l, t_r; + if (!switch_t) { + sin_theta_left = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1]; + sin_theta_right = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector]; + + cos_theta_left = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1]; + cos_theta_right = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector]; + + t_l = sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance(); + t_r = sin_alpha[iDetector] * projgeom->getOriginSourceDistance(); + + } else { + sin_theta_left = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector]; + sin_theta_right = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1]; + + cos_theta_left = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector]; + cos_theta_right = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1]; + + t_l = -sin_alpha[iDetector] * projgeom->getOriginSourceDistance(); + t_r = -sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance(); + } + + float32 inv_cos_theta_left = 1.0f / cos_theta_left; + float32 inv_cos_theta_right = 1.0f / cos_theta_right; + + float32 updateX_left = sin_theta_left * inv_cos_theta_left; + float32 updateX_right = sin_theta_right * inv_cos_theta_right; + + // Precalculate kernel limits + float32 S_l = -0.5f * updateX_left; + if (S_l > 0) {S_l = -S_l;} + float32 T_l = -S_l; + float32 U_l = 1.0f + S_l; + float32 V_l = 1.0f - S_l; + float32 inv_4T_l = 0.25f / T_l; + + float32 S_r = -0.5f * updateX_right; + if (S_r > 0) {S_r = -S_r;} + float32 T_r = -S_r; + float32 U_r = 1.0f + S_r; + float32 V_r = 1.0f - S_r; + float32 inv_4T_r = 0.25f / T_r; + + // calculate strip extremes (volume coordinates) + float32 PL = (t_l - sin_theta_left * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_left; + float32 PR = (t_r - sin_theta_right * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_right; + float32 PLimitL = PL + S_l * PH; + float32 PLimitR = PR - S_r * PH; + + // calculate strip extremes (pixel coordinates) + float32 XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + float32 XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + float32 xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + float32 xR = (PR - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX_left; + XLimitR += updateX_right; + xL += updateX_left; + xR += updateX_right; + + // for each affected col + for (col = x1L; col <= x1R; ++col) { + + if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V_r) res = 1.0f; + else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r; + else if (x2R >= T_r) res = x2R; + else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S_l) {} + else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l; + else if (x2L <= U_l) res -= x2L; + else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end col loop + + } // end row loop + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end detector loop + + // [45?,135?] and [225?,315?] + // horizontaly + } else { + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get theta_l = alpha_left + theta and theta_r = alpha_right + theta + float32 sin_theta_left, cos_theta_left; + float32 sin_theta_right, cos_theta_right; + float32 t_l, t_r; + if (!switch_t) { + sin_theta_left = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector]; + sin_theta_right = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1]; + + cos_theta_left = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector]; + cos_theta_right = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1]; + + t_l = sin_alpha[iDetector] * projgeom->getOriginSourceDistance(); + t_r = sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance(); + + } else { + sin_theta_left = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1]; + sin_theta_right = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector]; + + cos_theta_left = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1]; + cos_theta_right = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector]; + + t_l = -sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance(); + t_r = -sin_alpha[iDetector] * projgeom->getOriginSourceDistance(); + } + + float32 inv_sin_theta_left = 1.0f / sin_theta_left; + float32 inv_sin_theta_right = 1.0f / sin_theta_right; + + float32 updateX_left = cos_theta_left * inv_sin_theta_left; + float32 updateX_right = cos_theta_right * inv_sin_theta_right; + + // Precalculate kernel limits + float32 S_l = -0.5f * updateX_left; + if (S_l > 0) { S_l = -S_l; } + float32 T_l = -S_l; + float32 U_l = 1.0f + S_l; + float32 V_l = 1.0f - S_l; + float32 inv_4T_l = 0.25f / T_l; + + float32 S_r = -0.5f * updateX_right; + if (S_r > 0) { S_r = -S_r; } + float32 T_r = -S_r; + float32 U_r = 1.0f + S_r; + float32 V_r = 1.0f - S_r; + float32 inv_4T_r = 0.25f / T_r; + + // calculate strip extremes (volume coordinates) + float32 PL = (t_l - cos_theta_left * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_left; + float32 PR = (t_r - cos_theta_right * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_right; + float32 PLimitL = PL - S_l * PW; + float32 PLimitR = PR + S_r * PW; + + // calculate strip extremes (pixel coordinates) + float32 XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH; + float32 XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH; + float32 xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH; + float32 xR = (m_pVolumeGeometry->getWindowMaxY() - PR) * inv_PH; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX_left; + XLimitR += updateX_right; + xL += updateX_left; + xR += updateX_right; + + // for each affected row + for (row = x1L; row <= x1R; ++row) { + + if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V_r) res = 1.0f; + else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r; + else if (x2R >= T_r) res = x2R; + else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S_l) {} + else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l; + else if (x2L <= U_l) res -= x2L; + else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end col loop + + } // end row loop + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end detector loop + + } // end theta switch + + } // end angle loop + + delete[] cos_alpha; + delete[] sin_alpha; +} + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE PROJECTION +template +void CFanFlatBeamStripKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p) +{ + ASTRA_ASSERT(m_bIsInitialized); + + // Some variables + float32 theta; + int row, col; + int iDetector; + float32 res; + int x1L, x1R; + float32 x2L, x2R; + int iVolumeIndex, iRayIndex; + + CFanFlatProjectionGeometry2D* projgeom = static_cast(m_pProjectionGeometry); + + // Other precalculations + float32 PW = m_pVolumeGeometry->getPixelLengthX(); + float32 PH = m_pVolumeGeometry->getPixelLengthY(); + float32 DW = m_pProjectionGeometry->getDetectorWidth(); + float32 inv_PW = 1.0f / PW; + float32 inv_PH = 1.0f / PH; + + // calculate alpha's + float32 alpha; + float32* cos_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1]; + float32* sin_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1]; + for (int i = 0; i < m_pProjectionGeometry->getDetectorCount() + 1; ++i) { + alpha = -atan((i - m_pProjectionGeometry->getDetectorCount()*0.5f) * DW / projgeom->getSourceDetectorDistance()); + cos_alpha[i] = cos(alpha); + sin_alpha[i] = sin(alpha); + } + + + // get values + theta = m_pProjectionGeometry->getProjectionAngle(_iProjection); + bool switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // Precalculate sin, cos, 1/cos + float32 sin_theta = sin(theta); + float32 cos_theta = cos(theta); + + // [-45?,45?] and [135?,225?] + if (theta < PIdiv4) { + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + float32 sin_theta_left, cos_theta_left; + float32 sin_theta_right, cos_theta_right; + + // get theta_l = alpha_left + theta and theta_r = alpha_right + theta + float32 t_l, t_r; + if (!switch_t) { + sin_theta_left = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1]; + sin_theta_right = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector]; + + cos_theta_left = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1]; + cos_theta_right = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector]; + + t_l = sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance(); + t_r = sin_alpha[iDetector] * projgeom->getOriginSourceDistance(); + + } else { + sin_theta_left = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector]; + sin_theta_right = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1]; + + cos_theta_left = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector]; + cos_theta_right = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1]; + + t_l = -sin_alpha[iDetector] * projgeom->getOriginSourceDistance(); + t_r = -sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance(); + } + + float32 inv_cos_theta_left = 1.0f / cos_theta_left; + float32 inv_cos_theta_right = 1.0f / cos_theta_right; + + float32 updateX_left = sin_theta_left * inv_cos_theta_left; + float32 updateX_right = sin_theta_right * inv_cos_theta_right; + + // Precalculate kernel limits + float32 S_l = -0.5f * updateX_left; + if (S_l > 0) {S_l = -S_l;} + float32 T_l = -S_l; + float32 U_l = 1.0f + S_l; + float32 V_l = 1.0f - S_l; + float32 inv_4T_l = 0.25f / T_l; + + float32 S_r = -0.5f * updateX_right; + if (S_r > 0) {S_r = -S_r;} + float32 T_r = -S_r; + float32 U_r = 1.0f + S_r; + float32 V_r = 1.0f - S_r; + float32 inv_4T_r = 0.25f / T_r; + + // calculate strip extremes (volume coordinates) + float32 PL = (t_l - sin_theta_left * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_left; + float32 PR = (t_r - sin_theta_right * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_right; + float32 PLimitL = PL + S_l * PH; + float32 PLimitR = PR - S_r * PH; + + // calculate strip extremes (pixel coordinates) + float32 XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + float32 XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + float32 xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + float32 xR = (PR - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX_left; + XLimitR += updateX_right; + xL += updateX_left; + xR += updateX_right; + + // for each affected col + for (col = x1L; col <= x1R; ++col) { + + if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V_r) res = 1.0f; + else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r; + else if (x2R >= T_r) res = x2R; + else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S_l) {} + else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l; + else if (x2L <= U_l) res -= x2L; + else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end col loop + + } // end row loop + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end detector loop + + // [45?,135?] and [225?,315?] + // horizontaly + } else { + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get theta_l = alpha_left + theta and theta_r = alpha_right + theta + float32 sin_theta_left, cos_theta_left; + float32 sin_theta_right, cos_theta_right; + float32 t_l, t_r; + if (!switch_t) { + sin_theta_left = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector]; + sin_theta_right = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1]; + + cos_theta_left = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector]; + cos_theta_right = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1]; + + t_l = sin_alpha[iDetector] * projgeom->getOriginSourceDistance(); + t_r = sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance(); + + } else { + sin_theta_left = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1]; + sin_theta_right = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector]; + + cos_theta_left = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1]; + cos_theta_right = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector]; + + t_l = -sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance(); + t_r = -sin_alpha[iDetector] * projgeom->getOriginSourceDistance(); + } + + float32 inv_sin_theta_left = 1.0f / sin_theta_left; + float32 inv_sin_theta_right = 1.0f / sin_theta_right; + + float32 updateX_left = cos_theta_left * inv_sin_theta_left; + float32 updateX_right = cos_theta_right * inv_sin_theta_right; + + // Precalculate kernel limits + float32 S_l = -0.5f * updateX_left; + if (S_l > 0) { S_l = -S_l; } + float32 T_l = -S_l; + float32 U_l = 1.0f + S_l; + float32 V_l = 1.0f - S_l; + float32 inv_4T_l = 0.25f / T_l; + + float32 S_r = -0.5f * updateX_right; + if (S_r > 0) { S_r = -S_r; } + float32 T_r = -S_r; + float32 U_r = 1.0f + S_r; + float32 V_r = 1.0f - S_r; + float32 inv_4T_r = 0.25f / T_r; + + // calculate strip extremes (volume coordinates) + float32 PL = (t_l - cos_theta_left * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_left; + float32 PR = (t_r - cos_theta_right * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_right; + float32 PLimitL = PL - S_l * PW; + float32 PLimitR = PR + S_r * PW; + + // calculate strip extremes (pixel coordinates) + float32 XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH; + float32 XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH; + float32 xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH; + float32 xR = (m_pVolumeGeometry->getWindowMaxY() - PR) * inv_PH; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX_left; + XLimitR += updateX_right; + xL += updateX_left; + xR += updateX_right; + + // for each affected row + for (row = x1L; row <= x1R; ++row) { + + if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V_r) res = 1.0f; + else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r; + else if (x2R >= T_r) res = x2R; + else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S_l) {} + else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l; + else if (x2L <= U_l) res -= x2L; + else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end col loop + + } // end row loop + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end detector loop + + } // end theta switch + + delete[] cos_alpha; + delete[] sin_alpha; +} + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE RAY +template +void CFanFlatBeamStripKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p) +{ + ASTRA_ASSERT(m_bIsInitialized); + + // Some variables + float32 theta; + int row, col; + float32 res; + int x1L, x1R; + float32 x2L, x2R; + int iVolumeIndex, iRayIndex; + + CFanFlatProjectionGeometry2D* projgeom = static_cast(m_pProjectionGeometry); + + // Other precalculations + float32 PW = m_pVolumeGeometry->getPixelLengthX(); + float32 PH = m_pVolumeGeometry->getPixelLengthY(); + float32 DW = m_pProjectionGeometry->getDetectorWidth(); + float32 inv_PW = 1.0f / PW; + float32 inv_PH = 1.0f / PH; + + // calculate alpha's + float32 alpha; + float32* cos_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1]; + float32* sin_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1]; + for (int i = 0; i < m_pProjectionGeometry->getDetectorCount() + 1; ++i) { + alpha = -atan((i - m_pProjectionGeometry->getDetectorCount()*0.5f) * DW / projgeom->getSourceDetectorDistance()); + cos_alpha[i] = cos(alpha); + sin_alpha[i] = sin(alpha); + } + + + // get values + theta = m_pProjectionGeometry->getProjectionAngle(_iProjection); + bool switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // Precalculate sin, cos, 1/cos + float32 sin_theta = sin(theta); + float32 cos_theta = cos(theta); + + // [-45?,45?] and [135?,225?] + if (theta < PIdiv4) { + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) { delete[] cos_alpha; delete[] sin_alpha; return; } + + float32 sin_theta_left, cos_theta_left; + float32 sin_theta_right, cos_theta_right; + + // get theta_l = alpha_left + theta and theta_r = alpha_right + theta + float32 t_l, t_r; + if (!switch_t) { + sin_theta_left = sin_theta * cos_alpha[_iDetector+1] + cos_theta * sin_alpha[_iDetector+1]; + sin_theta_right = sin_theta * cos_alpha[_iDetector] + cos_theta * sin_alpha[_iDetector]; + + cos_theta_left = cos_theta * cos_alpha[_iDetector+1] - sin_theta * sin_alpha[_iDetector+1]; + cos_theta_right = cos_theta * cos_alpha[_iDetector] - sin_theta * sin_alpha[_iDetector]; + + t_l = sin_alpha[_iDetector+1] * projgeom->getOriginSourceDistance(); + t_r = sin_alpha[_iDetector] * projgeom->getOriginSourceDistance(); + + } else { + sin_theta_left = sin_theta * cos_alpha[_iDetector] + cos_theta * sin_alpha[_iDetector]; + sin_theta_right = sin_theta * cos_alpha[_iDetector+1] + cos_theta * sin_alpha[_iDetector+1]; + + cos_theta_left = cos_theta * cos_alpha[_iDetector] - sin_theta * sin_alpha[_iDetector]; + cos_theta_right = cos_theta * cos_alpha[_iDetector+1] - sin_theta * sin_alpha[_iDetector+1]; + + t_l = -sin_alpha[_iDetector] * projgeom->getOriginSourceDistance(); + t_r = -sin_alpha[_iDetector+1] * projgeom->getOriginSourceDistance(); + } + + float32 inv_cos_theta_left = 1.0f / cos_theta_left; + float32 inv_cos_theta_right = 1.0f / cos_theta_right; + + float32 updateX_left = sin_theta_left * inv_cos_theta_left; + float32 updateX_right = sin_theta_right * inv_cos_theta_right; + + // Precalculate kernel limits + float32 S_l = -0.5f * updateX_left; + if (S_l > 0) {S_l = -S_l;} + float32 T_l = -S_l; + float32 U_l = 1.0f + S_l; + float32 V_l = 1.0f - S_l; + float32 inv_4T_l = 0.25f / T_l; + + float32 S_r = -0.5f * updateX_right; + if (S_r > 0) {S_r = -S_r;} + float32 T_r = -S_r; + float32 U_r = 1.0f + S_r; + float32 V_r = 1.0f - S_r; + float32 inv_4T_r = 0.25f / T_r; + + // calculate strip extremes (volume coordinates) + float32 PL = (t_l - sin_theta_left * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_left; + float32 PR = (t_r - sin_theta_right * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_right; + float32 PLimitL = PL + S_l * PH; + float32 PLimitR = PR - S_r * PH; + + // calculate strip extremes (pixel coordinates) + float32 XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + float32 XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + float32 xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + float32 xR = (PR - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX_left; + XLimitR += updateX_right; + xL += updateX_left; + xR += updateX_right; + + // for each affected col + for (col = x1L; col <= x1R; ++col) { + + if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V_r) res = 1.0f; + else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r; + else if (x2R >= T_r) res = x2R; + else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S_l) {} + else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l; + else if (x2L <= U_l) res -= x2L; + else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end col loop + + } // end row loop + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + // [45?,135?] and [225?,315?] + // horizontaly + } else { + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) { delete[] cos_alpha; delete[] sin_alpha; return; } + + // get theta_l = alpha_left + theta and theta_r = alpha_right + theta + float32 sin_theta_left, cos_theta_left; + float32 sin_theta_right, cos_theta_right; + float32 t_l, t_r; + if (!switch_t) { + sin_theta_left = sin_theta * cos_alpha[_iDetector] + cos_theta * sin_alpha[_iDetector]; + sin_theta_right = sin_theta * cos_alpha[_iDetector+1] + cos_theta * sin_alpha[_iDetector+1]; + + cos_theta_left = cos_theta * cos_alpha[_iDetector] - sin_theta * sin_alpha[_iDetector]; + cos_theta_right = cos_theta * cos_alpha[_iDetector+1] - sin_theta * sin_alpha[_iDetector+1]; + + t_l = sin_alpha[_iDetector] * projgeom->getOriginSourceDistance(); + t_r = sin_alpha[_iDetector+1] * projgeom->getOriginSourceDistance(); + + } else { + sin_theta_left = sin_theta * cos_alpha[_iDetector+1] + cos_theta * sin_alpha[_iDetector+1]; + sin_theta_right = sin_theta * cos_alpha[_iDetector] + cos_theta * sin_alpha[_iDetector]; + + cos_theta_left = cos_theta * cos_alpha[_iDetector+1] - sin_theta * sin_alpha[_iDetector+1]; + cos_theta_right = cos_theta * cos_alpha[_iDetector] - sin_theta * sin_alpha[_iDetector]; + + t_l = -sin_alpha[_iDetector+1] * projgeom->getOriginSourceDistance(); + t_r = -sin_alpha[_iDetector] * projgeom->getOriginSourceDistance(); + } + + float32 inv_sin_theta_left = 1.0f / sin_theta_left; + float32 inv_sin_theta_right = 1.0f / sin_theta_right; + + float32 updateX_left = cos_theta_left * inv_sin_theta_left; + float32 updateX_right = cos_theta_right * inv_sin_theta_right; + + // Precalculate kernel limits + float32 S_l = -0.5f * updateX_left; + if (S_l > 0) { S_l = -S_l; } + float32 T_l = -S_l; + float32 U_l = 1.0f + S_l; + float32 V_l = 1.0f - S_l; + float32 inv_4T_l = 0.25f / T_l; + + float32 S_r = -0.5f * updateX_right; + if (S_r > 0) { S_r = -S_r; } + float32 T_r = -S_r; + float32 U_r = 1.0f + S_r; + float32 V_r = 1.0f - S_r; + float32 inv_4T_r = 0.25f / T_r; + + // calculate strip extremes (volume coordinates) + float32 PL = (t_l - cos_theta_left * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_left; + float32 PR = (t_r - cos_theta_right * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_right; + float32 PLimitL = PL - S_l * PW; + float32 PLimitR = PR + S_r * PW; + + // calculate strip extremes (pixel coordinates) + float32 XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH; + float32 XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH; + float32 xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH; + float32 xR = (m_pVolumeGeometry->getWindowMaxY() - PR) * inv_PH; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX_left; + XLimitR += updateX_right; + xL += updateX_left; + xR += updateX_right; + + // for each affected row + for (row = x1L; row <= x1R; ++row) { + + if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V_r) res = 1.0f; + else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r; + else if (x2R >= T_r) res = x2R; + else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S_l) {} + else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l; + else if (x2L <= U_l) res -= x2L; + else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end col loop + + } // end row loop + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end theta switch + + delete[] cos_alpha; + delete[] sin_alpha; +} diff --git a/include/astra/FanFlatProjectionGeometry2D.h b/include/astra/FanFlatProjectionGeometry2D.h new file mode 100644 index 0000000..0e790ae --- /dev/null +++ b/include/astra/FanFlatProjectionGeometry2D.h @@ -0,0 +1,244 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FANFLATPROJECTIONGEOMETRY2D +#define _INC_ASTRA_FANFLATPROJECTIONGEOMETRY2D + +#include "ProjectionGeometry2D.h" + +#include + +namespace astra +{ + +/** + * This class defines a 2D fan beam geometry with a flat detector that has equally spaced detector cells. + * + * \par XML Configuration + * \astra_xml_item{DetectorCount, int, Number of detectors for each projection.} + * \astra_xml_item{DetectorWidth, float, Width of each detector.} + * \astra_xml_item{ProjectionAngles, vector of float, projection angles in radians.} + * \astra_xml_item{DistanceOriginDetector, float, Distance between the center of rotation and the detectorarray.} + * \astra_xml_item{DistanceOriginSource, float, Distance between the center of rotation the the x-ray source.} + * + * \par MATLAB example + * \astra_code{ + * proj_geom = astra_struct('fanflat');\n + * proj_geom.DetectorCount = 512;\n + * proj_geom.DetectorWidth = 1.0;\n + * proj_geom.ProjectionAngles = linspace(0,pi,100);\n + * proj_geom.DistanceOriginDetector = 300;\n + * proj_geom.DistanceOriginSource = 300;\n + * } + */ +class _AstraExport CFanFlatProjectionGeometry2D : public CProjectionGeometry2D +{ + /** + * Distance from the origin of the coordinate system to the source. + */ + float32 m_fOriginSourceDistance; + + /** + * Distance from the origin of the coordinate system to the detector (i.e., the distance between the origin and its orthogonal projection + * onto the detector array). + */ + float32 m_fOriginDetectorDistance; + +public: + + /** Default constructor. Sets all variables to zero. Note that this constructor leaves the object in an unusable state and must + * be followed by a call to init(). + */ + CFanFlatProjectionGeometry2D(); + + /** Constructor. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle. + * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + * All angles are represented in radians. + * @param _fOriginSourceDistance Distance from the origin of the coordinate system to the source + * @param _fOriginDetectorDistance Distance from the origin of the coordinate system to the detector + */ + CFanFlatProjectionGeometry2D(int _iProjectionAngleCount, + int _iDetectorCount, + float32 _fDetectorWidth, + const float32* _pfProjectionAngles, + float32 _fOriginSourceDistance, + float32 _fOriginDetectorDistance); + + /** Copy constructor. + */ + CFanFlatProjectionGeometry2D(const CFanFlatProjectionGeometry2D& _projGeom); + + /** Assignment operator. + */ + CFanFlatProjectionGeometry2D& operator=(const CFanFlatProjectionGeometry2D& _other); + + /** Destructor. + */ + virtual ~CFanFlatProjectionGeometry2D(); + + /** Initialize the geometry with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialization. This function MUST be called after using the default constructor and MAY be called to + * reset a previously initialized object. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle. + * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + * @param _fOriginSourceDistance Distance from the origin of the coordinate system to the source + * @param _fOriginDetectorDistance Distance from the origin of the coordinate system to the detector + */ + bool initialize(int _iProjectionAngleCount, + int _iDetectorCount, + float32 _fDetectorWidth, + const float32* _pfProjectionAngles, + float32 _fOriginSourceDistance, + float32 _fOriginDetectorDistance); + + /** Create a hard copy. + */ + virtual CProjectionGeometry2D* clone(); + + /** Returns true if the type of geometry defined in this class is the one specified in _sType. + * + * @param _sType geometry type to compare to. + * @return true if _sType == "fanflat". + */ + virtual bool isOfType(const std::string& _sType); + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(CProjectionGeometry2D*) const; + + /** Returns the distance from the origin of the coordinate system to the source. + * + * @return Distance from the origin of the coordinate system to the source + */ + float32 getOriginSourceDistance() const; + + /** Returns the distance from the origin of the coordinate system to the detector + * (i.e., the distance between the origin and its orthogonal projection onto the detector array). + * + * @return Distance from the origin of the coordinate system to the detector + */ + float32 getOriginDetectorDistance() const; + + /** Returns the distance from the source to the detector + * (i.e., the distance between the source and its orthogonal projection onto the detector array). + * + * @return Distance from the source to the detector + */ + float32 getSourceDetectorDistance() const; + + /** Get the value for t and theta, based upon the row and column index. + * + * @param _iRow row index + * @param _iColumn column index + * @param _fT output: value of t + * @param _fTheta output: value of theta, always lies within the [0,pi[ interval. + */ + virtual void getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const; + + /** + * Returns a vector describing the direction of a ray belonging to a certain detector + * + * @param _iProjectionIndex index of projection + * @param _iProjectionIndex index of detector + * + * @return a unit vector describing the direction + */ + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex); +}; + + + +// Returns the distance from the origin of the coordinate system to the source. +inline float32 CFanFlatProjectionGeometry2D::getOriginSourceDistance() const +{ + return m_fOriginSourceDistance; +} + + +// Returns the distance from the origin of the coordinate system to the detector. +inline float32 CFanFlatProjectionGeometry2D::getOriginDetectorDistance() const +{ + return m_fOriginDetectorDistance; +} + + +// Returns the distance from the source to the detector. +inline float32 CFanFlatProjectionGeometry2D::getSourceDetectorDistance() const +{ + return (m_fOriginSourceDistance + m_fOriginDetectorDistance); +} + + +// Get T and Theta +inline void CFanFlatProjectionGeometry2D::getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const +{ + assert(m_bInitialized); + + // get the distance between the center of the detector array and the detector. + float32 det_offset = indexToDetectorOffset(_iColumn); + + // get the angle between the center ray of the projection and the projection. + float32 alpha = atan(det_offset / getSourceDetectorDistance()); + + // calculate t and theta + _fT = m_fOriginSourceDistance * sin(alpha); + _fTheta = getProjectionAngle(_iRow) + alpha; + + // if theta is larger than pi, flip of the origin + if (PI <= _fTheta) { + _fTheta -= PI; + _fT = -_fT; + } + // if theta is below 0, flip + if (_fTheta < 0) { + _fTheta += PI; + _fT = -_fT; + } +} + + + +} // namespace astra + +#endif /* _INC_ASTRA_FANFLATPROJECTIONGEOMETRY2D */ + diff --git a/include/astra/FanFlatVecProjectionGeometry2D.h b/include/astra/FanFlatVecProjectionGeometry2D.h new file mode 100644 index 0000000..d370b24 --- /dev/null +++ b/include/astra/FanFlatVecProjectionGeometry2D.h @@ -0,0 +1,155 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FANFLATVECPROJECTIONGEOMETRY2D +#define _INC_ASTRA_FANFLATVECPROJECTIONGEOMETRY2D + +#include "ProjectionGeometry2D.h" +#include "../cuda/2d/dims.h" + +#include + +// FIXME: Avoid using +using astraCUDA::SFanProjection; + +namespace astra +{ + +/** + * This class defines a 2D fan beam geometry. + * + * \par XML Configuration + * \astra_xml_item{DetectorCount, int, Number of detectors for each projection.} + * \astra_xml_item{Vectors, matrix defining the 2D position of source and detector.} + * + * \par MATLAB example + * \astra_code{ + * proj_geom = astra_struct('fanflat_vec');\n + * proj_geom.DetectorCount = 512;\n + * proj_geom.Vectors = V;\n + * } + */ +class _AstraExport CFanFlatVecProjectionGeometry2D : public CProjectionGeometry2D +{ +protected: + + SFanProjection *m_pProjectionAngles; + +public: + + /** Default constructor. Sets all variables to zero. Note that this constructor leaves the object in an unusable state and must + * be followed by a call to init(). + */ + CFanFlatVecProjectionGeometry2D(); + + /** Constructor. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + */ + CFanFlatVecProjectionGeometry2D(int _iProjectionAngleCount, + int _iDetectorCount, + const SFanProjection* _pfProjectionAngles); + + /** Copy constructor. + */ + CFanFlatVecProjectionGeometry2D(const CFanFlatVecProjectionGeometry2D& _projGeom); + + /** Assignment operator. + */ + CFanFlatVecProjectionGeometry2D& operator=(const CFanFlatVecProjectionGeometry2D& _other); + + /** Destructor. + */ + virtual ~CFanFlatVecProjectionGeometry2D(); + + /** Initialize the geometry with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialization. This function MUST be called after using the default constructor and MAY be called to + * reset a previously initialized object. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + */ + bool initialize(int _iProjectionAngleCount, + int _iDetectorCount, + const SFanProjection* _pfProjectionAngles); + + virtual bool _check(); + + /** Create a hard copy. + */ + virtual CProjectionGeometry2D* clone(); + + /** Returns true if the type of geometry defined in this class is the one specified in _sType. + * + * @param _sType geometry type to compare to. + * @return true if _sType == "fanflat_vec". + */ + virtual bool isOfType(const std::string& _sType); + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(CProjectionGeometry2D*) const; + + /** Get the value for t and theta, based upon the row and column index. + * + * @param _iRow row index + * @param _iColumn column index + * @param _fT output: value of t + * @param _fTheta output: value of theta, always lies within the [0,pi[ interval. + */ + virtual void getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const; + + /** + * Returns a vector describing the direction of a ray belonging to a certain detector + * + * @param _iProjectionIndex index of projection + * @param _iProjectionIndex index of detector + * + * @return a unit vector describing the direction + */ + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex); + + const SFanProjection* getProjectionVectors() const { return m_pProjectionAngles; } +}; + + +} // namespace astra + +#endif /* _INC_ASTRA_FANFLATVECPROJECTIONGEOMETRY2D */ + diff --git a/include/astra/FilteredBackProjectionAlgorithm.h b/include/astra/FilteredBackProjectionAlgorithm.h new file mode 100644 index 0000000..cda7962 --- /dev/null +++ b/include/astra/FilteredBackProjectionAlgorithm.h @@ -0,0 +1,155 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FILTEREDBACKPROJECTION +#define _INC_ASTRA_FILTEREDBACKPROJECTION + +#include "ReconstructionAlgorithm2D.h" + +#include "Globals.h" + +#include "Projector2D.h" +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + + +namespace astra { + +/** + * \brief + * This class contains the implementation of the filtered back projection (FBP) + * reconstruction algorithm. + * + * \par XML Configuration + * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.} + * \astra_xml_item{VolumeDataId, integer, Identifier of the volume data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of the resulting projection data object as it is stored in the DataManager.} + * \astra_xml_item_option{ProjectionIndex, integer, 0, Only reconstruct this specific projection angle. } + + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('FP');\n + * cfg.ProjectorId = proj_id;\n + * cfg.ReconstructionDataId = vol_id;\n + * cfg.ProjectionDataId = sino_id;\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('run'\, alg_id);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + * + */ +class _AstraExport CFilteredBackProjectionAlgorithm : public CReconstructionAlgorithm2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - valid projector + * - valid data objects + * - projection order all within range + */ + virtual bool _check(); + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CFilteredBackProjectionAlgorithm(); + + /** Destructor. + */ + virtual ~CFilteredBackProjectionAlgorithm(); + + /** Initialize class. + * + * @param _pProjector Projector to use. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @return success + */ + bool initialize(CProjector2D* _pProjector, + CFloat32VolumeData2D* _pReconstruction, + CFloat32ProjectionData2D* _pSinogram); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Clear this class. + */ + virtual void clear(); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Performs the filtering of the projection data. + * + * @param _pFilteredSinogram will contain filtered sinogram afterwards + */ + void performFiltering(CFloat32ProjectionData2D * _pFilteredSinogram); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + +}; + +// inline functions +inline std::string CFilteredBackProjectionAlgorithm::description() const { return CFilteredBackProjectionAlgorithm::type; }; + +} // end namespace + +#endif diff --git a/include/astra/Float32Data.h b/include/astra/Float32Data.h new file mode 100644 index 0000000..99bbaf3 --- /dev/null +++ b/include/astra/Float32Data.h @@ -0,0 +1,88 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FLOAT32DATA +#define _INC_ASTRA_FLOAT32DATA + +#include "Globals.h" + +namespace astra { + +/** + * This is a virtual base class for floating point data classes. + */ +class _AstraExport CFloat32Data { + +protected: + + // Protected Member Variables + bool m_bInitialized; ///< has the object been initialized? + int m_iDimensions; ///< the number of dimensions + +public: + + /** + * Default constructor. + */ + CFloat32Data(); + + /** + * Destructor. Free allocated memory + */ + virtual ~CFloat32Data(); + + /** + * Get the initialization state of the object. + * + * @return true iff the object has been initialized + */ + bool isInitialized() const; + + /** + * Get the number of dimensions of this object. + * + * @return number of dimensions + */ + virtual int getDimensionCount() const = 0; + +}; + +//---------------------------------------------------------------------------------------- +// Inline member functions +//---------------------------------------------------------------------------------------- + +// Get the initialization state of the object. +inline bool CFloat32Data::isInitialized() const +{ + return m_bInitialized; +} +//---------------------------------------------------------------------------------------- + +} // end namespace + +#endif diff --git a/include/astra/Float32Data2D.h b/include/astra/Float32Data2D.h new file mode 100644 index 0000000..c89e9f8 --- /dev/null +++ b/include/astra/Float32Data2D.h @@ -0,0 +1,544 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FLOAT32DATA2D +#define _INC_ASTRA_FLOAT32DATA2D + +#include "Globals.h" +#include "Float32Data.h" + +#include + +namespace astra { + +/** + * This class represents a two-dimensional block of float32ing point data. + * It contains member functions for accessing this data and for performing + * elementary computations on the data. + * The data block is "owned" by the class, meaning that the class is + * responsible for deallocation of the memory involved. + */ +class _AstraExport CFloat32Data2D : public CFloat32Data { + +protected: + + int m_iWidth; ///< width of the data (x) + int m_iHeight; ///< height of the data (y) + int m_iSize; ///< total size of the data + + /** Pointer to the data block, represented as a 1-dimensional array. + * Note that the data memory is "owned" by this class, meaning that the + * class is responsible for deallocation of the memory involved. + * To access element (ix, iy) internally, use + * m_pData[iy * m_iWidth + ix] + */ + float32* m_pfData; + + /** Array of float32 pointers, each pointing to a single horizontal + * line in the m_pfData memory block. + * To access element (ix, iy) internally, use m_ppfData2D[iy][ix] + */ + float32** m_ppfData2D; + + float32 m_fGlobalMin; ///< minimum value of the data + float32 m_fGlobalMax; ///< maximum value of the data + float32 m_fGlobalMean; ///< mean value of the data + + /** Allocate memory for m_pfData and m_ppfData2D arrays. + * + * The allocated block consists of m_iSize float32s. The block is + * not cleared after allocation and its contents is undefined. + * This function may NOT be called if memory has already been allocated. + */ + void _allocateData(); + + /** Free memory for m_pfData and m_ppfData2D arrays. + * + * This function may ONLY be called if the memory for both blocks has been + * allocated before. + */ + void _freeData(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + */ + void _clear(); + + /** Un-initialize the object, bringing it back in the uninitialized state. + */ + void _unInit(); + + /** Find the minimum and maximum data value and store them in + * m_fGlobalMin and m_fGlobalMax + */ + void _computeGlobalMinMax(); + + /** Initialization. Initializes an instance of the CFloat32Data2D class, without filling the data block. + * Can only be called by derived classes. + * + * Initializes an instance of the CFloat32Data2D class. Memory is allocated for the + * data block. The allocated memory is not cleared and its contents after + * construction is undefined. Initialization may be followed by a call to + * copyData() to fill the memory block. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * This function does not set m_bInitialized to true if everything is ok. + * + * @param _iWidth width of the 2D data (x-axis), must be > 0 + * @param _iHeight height of the 2D data (y-axis), must be > 0 + * @return initialization of the base class successfull + */ + bool _initialize(int _iWidth, int _iHeight); + + /** Initialization. Initializes an instance of the CFloat32Data2D class with initialization of the data block. + * Can only be called by derived classes. + * + * Initializes an instance of the CFloat32Data2D class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * This function does not set m_bInitialized to true if everything is ok. + * + * @param _iWidth width of the 2D data (x-axis), must be > 0 + * @param _iHeight height of the 2D data (y-axis), must be > 0 + * @param _pfData pointer to a one-dimensional float32 data block + */ + bool _initialize(int _iWidth, int _iHeight, const float32* _pfData); + + /** Initialization. Initializes an instance of the CFloat32Data2D class with initialization of the data + * block with a scalar value. Can only be called by derived classes. + * + * Initializes an instance of the CFloat32Data2D class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * This function does not set m_bInitialized to true if everything is ok. + * + * @param _iWidth width of the 2D data (x-axis), must be > 0 + * @param _iHeight height of the 2D data (y-axis), must be > 0 + * @param _fScalar scalar value to put at each index + */ + bool _initialize(int _iWidth, int _iHeight, float32 _fScalar); + + /** Constructor. Create an instance of the CFloat32Data2D class without initializing the data block. + * Can only be called by derived classes. + * + * Creates an instance of the CFloat32Data2D class. Memory is allocated for the + * data block. The allocated memory is not cleared and its contents after + * construction is undefined. Construction may be followed by a call to + * copyData() to fill the memory block. + * + * @param _iWidth width of the 2D data (x-axis), must be > 0 + * @param _iHeight height of the 2D data (y-axis), must be > 0 + */ + CFloat32Data2D(int _iWidth, int _iHeight); + + /** Constructor. Create an instance of the CFloat32Data2D class with initialization of the data block. + * Can only be called by derived classes. + * + * Creates an instance of the CFloat32Data2D class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * + * @param _iWidth width of the 2D data (x-axis), must be > 0 + * @param _iHeight height of the 2D data (y-axis), must be > 0 + * @param _pfData pointer to a one-dimensional float32 data block + */ + CFloat32Data2D(int _iWidth, int _iHeight, const float32* _pfData); + + /** Constructor. Create an instance of the CFloat32Data2D class with initialization of the data block + * with a scalar value. Can only be called by derived classes. + * + * Creates an instance of the CFloat32Data2D class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * + * @param _iWidth width of the 2D data (x-axis), must be > 0 + * @param _iHeight height of the 2D data (y-axis), must be > 0 + * @param _fScalar scalar value to put at each index + */ + CFloat32Data2D(int _iWidth, int _iHeight, float32 _fScalar); + + /** Copy constructor. + */ + CFloat32Data2D(const CFloat32Data2D&); + +public: + + /** Typedef with available datatypes: BASE, PROJECTION, VOLUME. + */ + typedef enum {BASE, + PROJECTION, + VOLUME} EDataType; + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the initialize() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + * + */ + CFloat32Data2D(); + + /** Destructor. Free allocated memory + */ + virtual ~CFloat32Data2D(); + + /** Copy the data block pointed to by _pfData to the data block pointed to by m_pfData. + * The pointer _pfData must point to a block of m_iSize float32s. + * + * @param _pfData source data block + */ + void copyData(const float32* _pfData); + + /** scale the grey value of the data from 0-255. + * + */ + void scale(); + + /** Set each element of the data to a specified scalar value. + * + * @param _fScalar scalar value + */ + void setData(float32 _fScalar); + + /** Set all data to zero + */ + void clearData(); + + /** Get a pointer to the data block, represented as a 1-dimensional + * array of float32 values. The data memory is still "owned" by the + * CFloat32Data2D instance; this memory may NEVER be freed by the + * caller of this function. If changes are made to this data, the + * function updateStatistics() should be called after completion of + * all changes. + * + * @return pointer to the 1-dimensional 32-bit floating point data block + */ + float32* getData(); + + /** Get a const pointer to the data block, represented as a 1-dimensional + * array of float32 values. The data memory is still "owned" by the + * CFloat32Data2D instance; this memory may NEVER be freed by the + * caller of this function. If changes are made to this data, the + * function updateStatistics() should be called after completion of + * all changes. + * + * @return pointer to the 1-dimensional 32-bit floating point data block + */ + const float32* getDataConst() const; + + /** Get a float32** to the data block, represented as a 2-dimensional array of float32 values. + * + * After the call p = getData2D(), use p[iy][ix] to access element (ix, iy). + * The data memory and pointer array are still "owned" by the CFloat32Data2D + * instance; this memory may NEVER be freed by the caller of this function. + * If changes are made to this data, the function updateStatistics() + * should be called after completion of all changes. + * + * @return pointer to the 2-dimensional 32-bit floating point data block + */ + float32** getData2D(); + + /** Get a const float32** to the data block, represented as a 2-dimensional array of float32 values. + * + * After the call p = getData2D(), use p[iy][ix] to access element (ix, iy). + * The data memory and pointer array are still "owned" by the CFloat32Data2D + * instance; this memory may NEVER be freed by the caller of this function. + * If changes are made to this data, the function updateStatistics() + * should be called after completion of all changes. + * + * @return pointer to the 2-dimensional 32-bit floating point data block + */ + const float32** getData2DConst() const; + + /** Update data statistics, such as minimum and maximum value, after the data has been modified. + */ + virtual void updateStatistics(); + + /** Get the minimum value in the data block. + * If the data has been changed after construction, the function + * updateStatistics() must be called at least once before + * a query can be made on this value. + * + * @return minimum value in the data block + */ + virtual float32 getGlobalMin() const; + + /** Get the maximum value in the data block + * If the data has been changed after construction, the function + * updateStatistics() must be called at least once before + * a query can be made on this value. + * + * @return maximum value in the data block + */ + virtual float32 getGlobalMax() const; + + /** Get the mean value in the data block + * If the data has been changed after construction, the function + * updateStatistics() must be called at least once before + * a query can be made on this value. + * + * @return maximum value in the data block + */ + virtual float32 getGlobalMean() const; + + + /** Get the width of the data block. + * + * @return width of the data block + */ + int getWidth() const; + + /** Get the height of the data block. + * + * @return height of the data block + */ + int getHeight() const; + + /** Get the total size (width*height) of the data block. + * + * @return size of the data block + */ + int getSize() const; + + /** which type is this class? + * + * @return DataType: ASTRA_DATATYPE_FLOAT32_PROJECTION or + * ASTRA_DATATYPE_FLOAT32_VOLUME + */ + virtual EDataType getType() const; + + /** get a description of the class + * + * @return description string + */ + virtual std::string description() const; + + /** Get the number of dimensions of this object. + * + * @return number of dimensions + */ + int getDimensionCount() const; + + /** + * Clamp data to minimum value + * + * @param _fMin minimum value + * @return l-value + */ + CFloat32Data2D& clampMin(float32& _fMin); + + /** + * Clamp data to maximum value + * + * @param _fMax maximum value + * @return l-value + */ + CFloat32Data2D& clampMax(float32& _fMax); + + /** + * Overloaded Operator: data += data (pointwise) + * + * @param _data r-value + * @return l-value + */ + CFloat32Data2D& operator+=(const CFloat32Data2D& _data); + + /** + * Overloaded Operator: data -= data (pointwise) + * + * @param _data r-value + * @return l-value + */ + CFloat32Data2D& operator-=(const CFloat32Data2D& _data); + + /** + * Overloaded Operator: data *= data (pointwise) + * + * @param _data r-value + * @return l-value + */ + CFloat32Data2D& operator*=(const CFloat32Data2D& _data); + + /** + * Overloaded Operator: data *= scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32Data2D& operator*=(const float32& _fScalar); + + /** + * Overloaded Operator: data /= scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32Data2D& operator/=(const float32& _fScalar); + + /** + * Overloaded Operator: data += scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32Data2D& operator+=(const float32& _fScalar); + + /** + * Overloaded Operator: data -= scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32Data2D& operator-=(const float32& _fScalar); + + CFloat32Data2D& operator=(const CFloat32Data2D& _dataIn); + + float32& getData(int _index); + +}; + + +//---------------------------------------------------------------------------------------- +// Inline member functions +//---------------------------------------------------------------------------------------- + +// Get the number of dimensions of this object. +inline int CFloat32Data2D::getDimensionCount() const +{ + return 2; +} + +//---------------------------------------------------------------------------------------- +inline std::string CFloat32Data2D::description() const +{ + std::stringstream res; + res << m_iWidth << "x" << m_iHeight; + if (getType() == CFloat32Data2D::PROJECTION) res << " sinogram data \t"; + if (getType() == CFloat32Data2D::VOLUME) res << " volume data \t"; + return res.str(); +} + +//---------------------------------------------------------------------------------------- +// Get the type of this object. +inline CFloat32Data2D::EDataType CFloat32Data2D::getType() const +{ + return BASE; +} + +//---------------------------------------------------------------------------------------- +// Get the width of the data block. +inline int CFloat32Data2D::getWidth() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iWidth; +} + +//---------------------------------------------------------------------------------------- +// Get the height of the data block. +inline int CFloat32Data2D::getHeight() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iHeight; +} + +//---------------------------------------------------------------------------------------- +// Get the total size (width*height*depth) of the data block. +inline int CFloat32Data2D::getSize() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iSize; +} + +//---------------------------------------------------------------------------------------- +// Get a pointer to the data block, represented as a 1-dimensional array of float32 values. +inline float32* CFloat32Data2D::getData() +{ + //ASTRA_ASSERT(m_bInitialized); + return m_pfData; +} + +//---------------------------------------------------------------------------------------- +// Get a pointer to the data block, represented as a 1-dimensional array of float32 values. +inline float32& CFloat32Data2D::getData(int _index) +{ + //ASTRA_ASSERT(m_bInitialized); + return m_pfData[_index]; +} + +//---------------------------------------------------------------------------------------- +// Get a const pointer to the data block, represented as a 1-dimensional array of float32 values. +inline const float32* CFloat32Data2D::getDataConst() const +{ + ASTRA_ASSERT(m_bInitialized); + return (const float32*)m_pfData; +} + +//---------------------------------------------------------------------------------------- +// Get a float32** to the data block, represented as a 2-dimensional array of float32 values. +inline float32** CFloat32Data2D::getData2D() +{ + ASTRA_ASSERT(m_bInitialized); + return m_ppfData2D; +} + +//---------------------------------------------------------------------------------------- +// Get a const float32** to the data block, represented as a 2-dimensional array of float32 values. +inline const float32** CFloat32Data2D::getData2DConst() const +{ + ASTRA_ASSERT(m_bInitialized); + return (const float32**)m_ppfData2D; +} + +//---------------------------------------------------------------------------------------- +// Get the minimum value in the data block. +inline float32 CFloat32Data2D::getGlobalMin() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fGlobalMin; +} + +//---------------------------------------------------------------------------------------- +// Get the maximum value in the data block +inline float32 CFloat32Data2D::getGlobalMax() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fGlobalMax; +} + +//---------------------------------------------------------------------------------------- +// Get the mean value in the data block +inline float32 CFloat32Data2D::getGlobalMean() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fGlobalMean; +} + + +} // end namespace astra + +#endif // _INC_ASTRA_FLOAT32DATA2D diff --git a/include/astra/Float32Data3D.h b/include/astra/Float32Data3D.h new file mode 100644 index 0000000..8666890 --- /dev/null +++ b/include/astra/Float32Data3D.h @@ -0,0 +1,199 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FLOAT32DATA3D +#define _INC_ASTRA_FLOAT32DATA3D + +#include "Globals.h" +#include "Float32Data.h" +#include "Float32Data2D.h" + +namespace astra { + +/** + * This class represents a three-dimensional block of float32ing point data. + */ +class _AstraExport CFloat32Data3D : public CFloat32Data { + +protected: + + int m_iWidth; ///< width of the data (x) + int m_iHeight; ///< height of the data (y) + int m_iDepth; ///< depth of the data (z) + size_t m_iSize; ///< size of the data (width*height*depth) + + /** + * Compares the size of two CFloat32Data instances. + * + * @param _pA CFloat32Data3D instance A + * @param _pB CFloat32Data3D instance B + * @return True if they have the same size + */ + static bool _data3DSizesEqual(const CFloat32Data3D * _pA, const CFloat32Data3D * _pB); + +public: + + typedef enum {BASE, PROJECTION, VOLUME} EDataType; + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the init() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + */ + CFloat32Data3D(); + + /** Destructor. + */ + virtual ~CFloat32Data3D(); + + /** Get the width of the data block. + * + * @return width of the data block + */ + int getWidth() const; + + /** Get the height of the data block. + * + * @return height of the data block + */ + int getHeight() const; + + /** Get the depth of the data block. + * + * @return depth of the data block + */ + int getDepth() const; + + /** Get the size of the data block. + * + * @return size of the data block + */ + int getSize() const; + + /** Which type is this class? + * + * @return DataType: PROJECTION or VOLUME + */ + virtual EDataType getType() const; + + /** Get the number of dimensions of this object. + * + * @return number of dimensions + */ + int getDimensionCount() const; + + /** + * Clamp data to minimum value + * + * @param _fMin minimum value + * @return l-value + */ + virtual CFloat32Data3D& clampMin(float32& _fMin) = 0; + + /** + * Clamp data to maximum value + * + * @param _fMax maximum value + * @return l-value + */ + virtual CFloat32Data3D& clampMax(float32& _fMax) = 0; + + /** get a description of the class + * + * @return description string + */ + virtual std::string description() const; + +}; +//---------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------------------- +// Get dimension count. +inline int CFloat32Data3D::getDimensionCount() const +{ + return 3; +} + +//---------------------------------------------------------------------------------------- +// Get the width of the data block. +inline int CFloat32Data3D::getWidth() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iWidth; +} + +//---------------------------------------------------------------------------------------- +// Get the height of the data block. +inline int CFloat32Data3D::getHeight() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iHeight; +} + +//---------------------------------------------------------------------------------------- +// Get the height of the data block. +inline int CFloat32Data3D::getDepth() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iDepth; +} + +//---------------------------------------------------------------------------------------- +// Get the size of the data block. +inline int CFloat32Data3D::getSize() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iSize; +} + + +//---------------------------------------------------------------------------------------- +// get type +inline CFloat32Data3D::EDataType CFloat32Data3D::getType() const +{ + return BASE; +} + +//---------------------------------------------------------------------------------------- +// To String +inline std::string CFloat32Data3D::description() const +{ + std::stringstream res; + res << m_iWidth << "x" << m_iHeight << "x" << m_iDepth; + if (getType() == CFloat32Data3D::PROJECTION) res << " sinogram data \t"; + if (getType() == CFloat32Data3D::VOLUME) res << " volume data \t"; + return res.str(); +} +//---------------------------------------------------------------------------------------- + +} // end namespace astra + +#endif // _INC_ASTRA_FLOAT32DATA2D diff --git a/include/astra/Float32Data3DMemory.h b/include/astra/Float32Data3DMemory.h new file mode 100644 index 0000000..3a445b6 --- /dev/null +++ b/include/astra/Float32Data3DMemory.h @@ -0,0 +1,338 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FLOAT32DATA3DMEMORY +#define _INC_ASTRA_FLOAT32DATA3DMEMORY + +#include "Globals.h" +#include "Float32Data3D.h" + +namespace astra { + +/** + * This class represents a three-dimensional block of float32ing point data. + * It contains member functions for accessing this data and for performing + * elementary computations on the data. + * The data block is "owned" by the class, meaning that the class is + * responsible for deallocation of the memory involved. + */ +class _AstraExport CFloat32Data3DMemory : public virtual CFloat32Data3D { + +protected: + + /** Pointer to the data block, represented as a 1-dimensional array. + * Note that the data memory is "owned" by this class, meaning that the + * class is responsible for deallocation of the memory involved. + * To access element (ix, iy, iz) internally, use + * m_pData[iz * m_iWidth * m_iHeight + iy * m_iWidth + ix] + */ + float32* m_pfData; + + /** Array of float32 pointers, each pointing to a single row + * in the m_pfData memory block. + * To access element (ix, iy, iz) internally, use m_ppfDataRowInd[iz * m_iHeight + iy][ix] + */ + float32** m_ppfDataRowInd; + + /** Array of float32 pointers, each pointing to a single slice + * in the m_pfData memory block. + * To access element (ix, iy, iz) internally, use m_pppfDataSliceInd[iz][iy][ix] + */ + float32*** m_pppfDataSliceInd; + + float32 m_fGlobalMin; ///< minimum value of the data + float32 m_fGlobalMax; ///< maximum value of the data + + /** Allocate memory for m_pfData, m_ppfDataRowInd and m_pppfDataSliceInd arrays. + * + * The allocated block consists of m_iSize float32s. The block is + * not cleared after allocation and its contents is undefined. + * This function may NOT be called if memory has already been allocated. + */ + void _allocateData(); + + /** Free memory for m_pfData, m_ppfDataRowInd and m_pppfDataSliceInd arrays. + * + * This function may ONLY be called if the memory for both blocks has been + * allocated before. + */ + void _freeData(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + */ + void _clear(); + + /** Un-initialize the object, bringing it back in the unitialized state. + */ + void _unInit(); + + /** Find the minimum and maximum data value and store them in + * m_fGlobalMin and m_fGlobalMax + */ + void _computeGlobalMinMax(); + + /** Initialization. Initializes an instance of the CFloat32Data3DMemory class, without filling the data block. + * Can only be called by derived classes. + * + * Initializes an instance of the CFloat32Data3DMemory class. Memory is allocated for the + * data block. The allocated memory is not cleared and its contents after + * construction is undefined. Initialization may be followed by a call to + * copyData() to fill the memory block. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * This function does not set m_bInitialized to true if everything is ok. + * + * @param _iWidth width of the 3D data (x-axis), must be > 0 + * @param _iHeight height of the 3D data (y-axis), must be > 0 + * @param _iDepth depth of the 3D data (z-axis), must be > 0 + * @return initialization of the base class successfull + */ + bool _initialize(int _iWidth, int _iHeight, int _iDepth); + + /** Initialization. Initializes an instance of the CFloat32Data3DMemory class with initialization of the data block. + * Can only be called by derived classes. + * + * Initializes an instance of the CFloat32Data3DMemory class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * This function does not set m_bInitialized to true if everything is ok. + * + * @param _iWidth width of the 2D data (x-axis), must be > 0 + * @param _iHeight height of the 2D data (y-axis), must be > 0 + * @param _iDepth depth of the 2D data (z-axis), must be > 0 + * @param _pfData pointer to a one-dimensional float32 data block + * @return initialization of the base class successfull + */ + bool _initialize(int _iWidth, int _iHeight, int _iDepth, const float32* _pfData); + + /** Initialization. Initializes an instance of the CFloat32Data3DMemory class with initialization of the data block. + * Can only be called by derived classes. + * + * Initializes an instance of the CFloat32Data3DMemory class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * This function does not set m_bInitialized to true if everything is ok. + * + * @param _iWidth width of the 2D data (x-axis), must be > 0 + * @param _iHeight height of the 2D data (y-axis), must be > 0 + * @param _iDepth depth of the 2D data (z-axis), must be > 0 + * @param _fScalar scalar value to fill the data + * @return initialization of the base class successfull + */ + bool _initialize(int _iWidth, int _iHeight, int _iDepth, float32 _fScalar); + +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the initialize() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + * + */ + CFloat32Data3DMemory(); + + /** Destructor. Free allocated memory + */ + virtual ~CFloat32Data3DMemory(); + + /** Copy the data block pointed to by _pfData to the data block pointed to by m_pfData. + * The pointer _pfData must point to a block of m_iSize float32s. + * + * @param _pfData source data block + * @param _iSize total number of data elements, must be equal to the allocated size of the object. + */ + void copyData(const float32* _pfData, size_t _iSize); + + /** Set each element of the data to a specified scalar value. + * + * @param _fScalar scalar value + */ + void setData(float32 _fScalar); + + /** Set all data to zero + */ + void clearData(); + + /** Get a pointer to the data block, represented as a 1-dimensional + * array of float32 values. The data memory is still "owned" by the + * CFloat32Data3DMemory instance; this memory may NEVER be freed by the + * caller of this function. If changes are made to this data, the + * function updateStatistics() should be called after completion of + * all changes. + * + * @return pointer to the 1-dimensional 32-bit floating point data block + */ + float32* getData(); + + /** Get a const pointer to the data block, represented as a 1-dimensional + * array of float32 values. The data memory is still "owned" by the + * CFloat32Data3DMemory instance; this memory may NEVER be freed by the + * caller of this function. If changes are made to this data, the + * function updateStatistics() should be called after completion of + * all changes. + * + * @return pointer to the 1-dimensional 32-bit floating point data block + */ + const float32* getDataConst() const; + + /** Get a float32*** to the data block, represented as a 3-dimensional array of float32 values. + * + * After the call p = getData3D(), use p[iz][iy][ix] to access element (ix, iy, iz). + * The data memory and pointer array are still "owned" by the CFloat32Data3DMemory + * instance; this memory may NEVER be freed by the caller of this function. + * If changes are made to this data, the function updateStatistics() + * should be called after completion of all changes. + * + * @return pointer to the 3-dimensional 32-bit floating point data block + */ + float32*** getData3D(); + + /** Get a const float32*** to the data block, represented as a 3-dimensional array of float32 values. + * + * After the call p = getData3D(), use p[iy][ix] to access element (ix, iy, iz). + * The data memory and pointer array are still "owned" by the CFloat32Data3DMemory + * instance; this memory may NEVER be freed by the caller of this function. + * If changes are made to this data, the function updateStatistics() + * should be called after completion of all changes. + * + * @return pointer to the 3-dimensional 32-bit floating point data block + */ + const float32*** getData3DConst() const; + + /** Update data statistics, such as minimum and maximum value, after the data has been modified. + */ + virtual void updateStatistics(); + + /** Get the minimum value in the data block. + * If the data has been changed after construction, the function + * updateStatistics() must be called at least once before + * a query can be made on this value. + * + * @return minimum value in the data block + */ + virtual float32 getGlobalMin() const; + + /** Get the maximum value in the data block + * If the data has been changed after construction, the function + * updateStatistics() must be called at least once before + * a query can be made on this value. + * + * @return maximum value in the data block + */ + virtual float32 getGlobalMax() const; + + /** which type is this class? + * + * @return DataType: ASTRA_DATATYPE_FLOAT32_PROJECTION or + * ASTRA_DATATYPE_FLOAT32_VOLUME + */ + virtual EDataType getType() const; + + /** + * Clamp data to minimum value + * + * @param _fMin minimum value + * @return l-value + */ + virtual CFloat32Data3D& clampMin(float32& _fMin); + + /** + * Clamp data to maximum value + * + * @param _fMax maximum value + * @return l-value + */ + virtual CFloat32Data3D& clampMax(float32& _fMax); +}; + + +//---------------------------------------------------------------------------------------- +// Inline member functions +//---------------------------------------------------------------------------------------- + +//---------------------------------------------------------------------------------------- +// Get the type of this object. +inline CFloat32Data3DMemory::EDataType CFloat32Data3DMemory::getType() const +{ + return BASE; +} + +//---------------------------------------------------------------------------------------- +// Get the minimum value in the data block. +inline float32 CFloat32Data3DMemory::getGlobalMin() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fGlobalMin; +} + +//---------------------------------------------------------------------------------------- +// Get the maximum value in the data block +inline float32 CFloat32Data3DMemory::getGlobalMax() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fGlobalMax; +} + +//---------------------------------------------------------------------------------------- +// Get a pointer to the data block, represented as a 1-dimensional array of float32 values. +inline float32* CFloat32Data3DMemory::getData() +{ + ASTRA_ASSERT(m_bInitialized); + return m_pfData; +} + +//---------------------------------------------------------------------------------------- +// Get a const pointer to the data block, represented as a 1-dimensional array of float32 values. +inline const float32* CFloat32Data3DMemory::getDataConst() const +{ + ASTRA_ASSERT(m_bInitialized); + return (const float32*)m_pfData; +} + +//---------------------------------------------------------------------------------------- +// Get a float32** to the data block, represented as a 3-dimensional array of float32 values. +inline float32*** CFloat32Data3DMemory::getData3D() +{ + ASTRA_ASSERT(m_bInitialized); + return m_pppfDataSliceInd; +} + +//---------------------------------------------------------------------------------------- +// Get a const float32** to the data block, represented as a 3-dimensional array of float32 values. +inline const float32*** CFloat32Data3DMemory::getData3DConst() const +{ + ASTRA_ASSERT(m_bInitialized); + return (const float32***)m_pppfDataSliceInd; +} +//---------------------------------------------------------------------------------------- + +} // end namespace astra + +#endif // _INC_ASTRA_FLOAT32DATA2D diff --git a/include/astra/Float32ProjectionData2D.h b/include/astra/Float32ProjectionData2D.h new file mode 100644 index 0000000..d9fe51a --- /dev/null +++ b/include/astra/Float32ProjectionData2D.h @@ -0,0 +1,247 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FLOAT32PROJECTIONDATA2D +#define _INC_ASTRA_FLOAT32PROJECTIONDATA2D + +#include "Float32Data2D.h" +#include "ProjectionGeometry2D.h" + +namespace astra { + +/** + * This class represents two-dimensional Projection Data. + * + * It contains member functions for accessing this data and for performing + * elementary computations on the data. + * The data block is "owned" by the class, meaning that the class is + * responsible for deallocation of the memory involved. + * + * The projection data is stored as a series of consecutive rows, where + * each row contains the data for a single projection. + */ +class _AstraExport CFloat32ProjectionData2D : public CFloat32Data2D { + +public: + + /** + * Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the init() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + * + */ + CFloat32ProjectionData2D(); + + /** + * Constructor. Create an instance of the CFloat32ProjectionData2D class without initializing the data. + * + * Memory is allocated for the data block. The allocated memory is not cleared and + * its contents after construction is undefined. Construction may be followed by a + * call to copyData() to fill the memory block. + * The size of the data is determined by the specified projection geometry object. + * + * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class. + */ + CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry); + + /** + * Constructor. Create an instance of the CFloat32ProjectionData2D class with initialization of the data. + * + * Creates an instance of the CFloat32ProjectionData2D class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified projection geometry object. + * + * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class. + * @param _pfData pointer to a one-dimensional float32 data block + */ + CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry, float32* _pfData); + + /** + * Constructor. Create an instance of the CFloat32ProjectionData2D class with initialization of the data. + * + * Creates an instance of the CFloat32ProjectionData2D class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified projection geometry object. + * + * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class. + * @param _fScalar scalar value to be put at each index. + */ + CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry, float32 _fScalar); + + /** + * Copy constructor + */ + CFloat32ProjectionData2D(const CFloat32ProjectionData2D& _other); + + /** + * Assignment operator + */ + CFloat32ProjectionData2D& operator=(const CFloat32ProjectionData2D& _other); + + /** + * Destructor. + */ + virtual ~CFloat32ProjectionData2D(); + + /** Initialization. Initializes an instance of the CFloat32ProjectionData2D class, without filling the data block. + * + * Initializes an instance of the CFloat32Data2D class. Memory is allocated for the + * data block. The allocated memory is not cleared and its contents after + * construction is undefined. Initialization may be followed by a call to + * copyData() to fill the memory block. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * + * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class. + * @return Initialization of the base class successfull. + */ + bool initialize(CProjectionGeometry2D* _pGeometry); + + /** Initialization. Initializes an instance of the CFloat32Data2D class with initialization of the data block. + * + * Initializes an instance of the CFloat32Data2D class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * + * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class. + * @param _pfData pointer to a one-dimensional float32 data block + */ + bool initialize(CProjectionGeometry2D* _pGeometry, const float32* _pfData); + + /** Initialization. Initializes an instance of the CFloat32Data2D class with initialization of the data block. + * + * Initializes an instance of the CFloat32Data2D class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * + * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class. + * @param _fScalar scalar value to be put at each index. + */ + bool initialize(CProjectionGeometry2D* _pGeometry, float32 _fScalar); + + /** Get the number of detectors. + * + * @return number of detectors + */ + int getDetectorCount() const; + + /** Get the number of projection angles. + * + * @return number of projection angles + */ + int getAngleCount() const; + + /** Get a pointer to the data of a single projection angle. + * + * The data memory is still "owned" by the + * CFloat32ProjectionData2D instance; this memory may NEVER be freed by the + * caller of this function. If changes are made to this data, the + * function updateStatistics() should be called after completion of + * all changes. + * + * @return pointer to the data + */ + float32* getSingleProjectionData(int _iAngleIndex); + + /** Get a const pointer to the data of a single projection angle. + * + * The data memory is still "owned" by the + * CFloat32ProjectionData2D instance; this memory may NEVER be freed by the + * caller of this function. + * + * @return pointer to the data + */ + const float32* getSingleProjectionDataConst(int _iAngleIndex) const; + + /** Which type is this class? + * + * @return DataType: PROJECTION + */ + virtual EDataType getType() const; + + /** Get the projection geometry. + * + * @return pointer to projection geometry. + */ + virtual CProjectionGeometry2D* getGeometry() const; + + /** Change the projection geometry. + * Note that this can't change the dimensions of the data. + */ + virtual void changeGeometry(CProjectionGeometry2D* pGeometry); + +protected: + + /** The projection geometry for this data. + */ + CProjectionGeometry2D* m_pGeometry; + +}; +//---------------------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------------------- +// Get the number of detectors. +inline int CFloat32ProjectionData2D::getDetectorCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iWidth; +} + +//---------------------------------------------------------------------------------------- +// Get the number of projection angles. +inline int CFloat32ProjectionData2D::getAngleCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iHeight; +} + +//---------------------------------------------------------------------------------------- +// Get the projection geometry. +inline CProjectionGeometry2D* CFloat32ProjectionData2D::getGeometry() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_pGeometry; +} + +//---------------------------------------------------------------------------------------- +// Get type. +inline CFloat32Data2D::EDataType CFloat32ProjectionData2D::getType() const +{ + return PROJECTION; +} +//---------------------------------------------------------------------------------------- + +} // end namespace astra + +#endif // _INC_ASTRA_FLOAT32PROJECTIONDATA2D diff --git a/include/astra/Float32ProjectionData3D.h b/include/astra/Float32ProjectionData3D.h new file mode 100644 index 0000000..92122a7 --- /dev/null +++ b/include/astra/Float32ProjectionData3D.h @@ -0,0 +1,257 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FLOAT32PROJECTIONDATA3D +#define _INC_ASTRA_FLOAT32PROJECTIONDATA3D + +#include "Float32Data3D.h" +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" +#include "ProjectionGeometry3D.h" + +namespace astra { + +/** + * This asbtract class represents three-dimensional Projection Data. + */ +class _AstraExport CFloat32ProjectionData3D : public virtual CFloat32Data3D +{ +protected: + /** The projection geometry for this data. + */ + CProjectionGeometry3D* m_pGeometry; + +public: + + /** Default constructor. + */ + CFloat32ProjectionData3D(); + + /** Destructor. + */ + virtual ~CFloat32ProjectionData3D(); + + /** Get the number of detectors in one detector column. + * + * @return number of detectors + */ + int getDetectorRowCount() const; + + /** Get the number of detectors in one detector row. + * + * @return number of detectors + */ + int getDetectorColCount() const; + + /** Get the total number of detectors. + * + * @return number of detectors + */ + int getDetectorTotCount() const; + + /** Get the number of projection angles. + * + * @return number of projection angles + */ + int getAngleCount() const; + + /** Which type is this class? + * + * @return DataType: ASTRA_DATATYPE_FLOAT32_PROJECTION + */ + virtual CFloat32Data3D::EDataType getType() const; + + /** Fetch a COPY of a projection of the data. Note that if you update the 2D data slice, the data in the + * 3d data object will remain unaltered. To copy the data back in the 3D-volume you must return the data by calling 'returnProjection'. + * + * @param _iProjectionNr projection number + * @return Volume data object + */ + virtual CFloat32VolumeData2D* fetchProjection(int _iProjectionNr) const = 0; + + /** Return a projection slice to the 3d data. The data will be deleted. If the slice was fetched with + * 'fetchProjection', the data will be stored first. + * + * @param _iProjectionNr projection number + * @param _pProjection 2D Projection Data + */ + virtual void returnProjection(int _iProjectionNr, CFloat32VolumeData2D* _pProjection) = 0; + + /** Fetch a COPY of a sinogram slice of the data. Note that if you update the 2D data slice, the data in the + * 3d data object will remain unaltered. To copy the data back in the 3D-volume you must return the data by calling 'returnSlice'. + * + * @param _iSliceNr slice number + * @return Sinogram data object + */ + virtual CFloat32ProjectionData2D* fetchSinogram(int _iSliceNr) const = 0; + + /** Return a sinogram slice to the 3d data. The data will be stored in the 3D Data object. + * + * @param _iSliceNr slice number + * @param _pSinogram2D 2D Sinogram Object. + */ + virtual void returnSinogram(int _iSliceNr, CFloat32ProjectionData2D* _pSinogram2D) = 0; + + /** This SLOW function returns a detector value stored a specific index in the array. + * Reading values in this way might cause a lot of unnecessar__y memory operations, don't + * use it in time-critical code. + * + * @param _iIndex Index in the array if the data were stored completely in main memory + * @return The value the location specified by _iIndex + */ + virtual float32 getDetectorValue(int _iIndex) = 0; + + /** This SLOW function stores a detector value at a specific index in the array. + * Writing values in this way might cause a lot of unnecessary memory operations, don't + * use it in time-critical code. + * + * @param _iIndex Index in the array if the data were stored completely in main memory + * @param _fValue The value to be stored at the location specified by _iIndex + */ + virtual void setDetectorValue(int _iIndex, float32 _fValue) = 0; + + /** + * Overloaded Operator: data += data (pointwise) + * + * @param _data r-value + * @return l-value + */ + CFloat32ProjectionData3D& operator+=(const CFloat32ProjectionData3D& _data); + + /** + * Overloaded Operator: data -= data (pointwise) + * + * @param _data r-value + * @return l-value + */ + CFloat32ProjectionData3D& operator-=(const CFloat32ProjectionData3D& _data); + + /** + * Overloaded Operator: data *= data (pointwise) + * + * @param _data r-value + * @return l-value + */ + CFloat32ProjectionData3D& operator*=(const CFloat32ProjectionData3D& _data); + + /** + * Overloaded Operator: data *= scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32ProjectionData3D& operator*=(const float32& _fScalar); + + /** + * Overloaded Operator: data /= scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32ProjectionData3D& operator/=(const float32& _fScalar); + + /** + * Overloaded Operator: data += scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32ProjectionData3D& operator+=(const float32& _fScalar); + + /** + * Overloaded Operator: data -= scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32ProjectionData3D& operator-=(const float32& _fScalar); + + /** Get the projection geometry. + * + * @return pointer to projection geometry. + */ + virtual CProjectionGeometry3D* getGeometry() const; +}; + + +//---------------------------------------------------------------------------------------- +// Inline member functions +//---------------------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------------------- +// Get the number of detectors. +inline int CFloat32ProjectionData3D::getDetectorColCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iWidth; +} + +//---------------------------------------------------------------------------------------- +// Get the number of detectors. +inline int CFloat32ProjectionData3D::getDetectorRowCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iDepth; +} + +//---------------------------------------------------------------------------------------- +// Get the number of detectors. +inline int CFloat32ProjectionData3D::getDetectorTotCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iWidth * m_iDepth; +} + +//---------------------------------------------------------------------------------------- +// Get the number of projection angles. +inline int CFloat32ProjectionData3D::getAngleCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iHeight; +} + +//---------------------------------------------------------------------------------------- +// Get type +inline CFloat32Data3D::EDataType CFloat32ProjectionData3D::getType() const +{ + return PROJECTION; +} +//---------------------------------------------------------------------------------------- +// Get the projection geometry. +inline CProjectionGeometry3D* CFloat32ProjectionData3D::getGeometry() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_pGeometry; +} +//---------------------------------------------------------------------------------------- + + +} // end namespace astra + +#endif // _INC_ASTRA_FLOAT32PROJECTIONDATA3D diff --git a/include/astra/Float32ProjectionData3DMemory.h b/include/astra/Float32ProjectionData3DMemory.h new file mode 100644 index 0000000..8b61d45 --- /dev/null +++ b/include/astra/Float32ProjectionData3DMemory.h @@ -0,0 +1,218 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FLOAT32PROJECTIONDATA3DMEMORY +#define _INC_ASTRA_FLOAT32PROJECTIONDATA3DMEMORY + +#include "Float32Data3DMemory.h" +#include "Float32ProjectionData3D.h" +#include "ParallelProjectionGeometry2D.h" // TEMP + +namespace astra { + +/** + * This class represents three-dimensional Projection Data. + * + * It contains member functions for accessing this data and for performing + * elementary computations on the data. + * The data block is "owned" by the class, meaning that the class is + * responsible for deallocation of the memory involved. + * + * The projection data is stored as a series of consecutive rows, where + * each row contains the data for a single projection. + */ +class _AstraExport CFloat32ProjectionData3DMemory : public CFloat32Data3DMemory, public CFloat32ProjectionData3D { + +public: + + /** + * Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the init() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + * + */ + CFloat32ProjectionData3DMemory(); + + /** + * Constructor. Create an instance of the CFloat32ProjectionData3DMemory class without initializing the data. + * + * Memory is allocated for the data block. The allocated memory is not cleared and + * its contents after construction is undefined. Construction may be followed by a + * call to copyData() to fill the memory block. + * The size of the data is determined by the specified projection geometry object. + * + * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class. + */ + CFloat32ProjectionData3DMemory(CProjectionGeometry3D* _pGeometry); + + /** + * Constructor. Create an instance of the CFloat32ProjectionData3DMemory class with initialization of the data. + * + * Creates an instance of the CFloat32ProjectionData3DMemory class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified projection geometry object. + * + * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class. + * @param _pfData pointer to a one-dimensional float32 data block + */ + CFloat32ProjectionData3DMemory(CProjectionGeometry3D* _pGeometry, float32* _pfData); + + /** + * Constructor. Create an instance of the CFloat32ProjectionData3DMemory class filled with scalar data. + * + * Creates an instance of the CFloat32ProjectionData3DMemory class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified projection geometry object. + * + * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class. + * @param _fScalar scalar data + */ + CFloat32ProjectionData3DMemory(CProjectionGeometry3D* _pGeometry, float32 _fScalar); + + /** + * Destructor. + */ + virtual ~CFloat32ProjectionData3DMemory(); + + /** Initialization. Initializes an instance of the CFloat32ProjectionData3DMemory class, without filling the data block. + * + * Initializes an instance of the CFloat32ProjectionData3DMemory class. Memory is allocated for the + * data block. The allocated memory is not cleared and its contents after + * construction is undefined. Initialization may be followed by a call to + * copyData() to fill the memory block. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * + * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class. + * @return Initialization of the base class successfull. + */ + bool initialize(CProjectionGeometry3D* _pGeometry); + + /** Initialization. Initializes an instance of the CFloat32ProjectionData3DMemory class with scalar initialization. + * + * Initializes an instance of the CFloat32ProjectionData3DMemory class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * + * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class. + * @param _fScalar scalar value + */ + bool initialize(CProjectionGeometry3D* _pGeometry, float32 _fScalar); + + /** Initialization. Initializes an instance of the CFloat32ProjectionData3DMemory class with initialization of the data block. + * + * Initializes an instance of the CFloat32ProjectionData3DMemory class. Memory + * is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. If the object has been initialized before, the + * object is reinitialized and memory is freed and reallocated if necessary. + * + * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class. + * @param _pfData pointer to a one-dimensional float32 data block + */ + bool initialize(CProjectionGeometry3D* _pGeometry, const float32* _pfData); + + /** Fetch a COPY of a projection of the data. Note that if you update the 2D data slice, the data in the + * 3D data object will remain unaltered. To copy the data back in the 3D-volume you must return the data by calling 'returnProjection'. + * + * @param _iProjectionNr projection number + * @return Volume data object + */ + virtual CFloat32VolumeData2D* fetchProjection(int _iProjectionNr) const; + + /** Return a projection slice to the 3D data. The data will be deleted. If the slice was fetched with + * 'fetchProjection', the data will be stored first. + * + * @param _iProjectionNr projection number + * @param _pProjection 2D Projection image + */ + virtual void returnProjection(int _iProjectionNr, CFloat32VolumeData2D* _pProjection); + + /** Fetch a COPY of a sinogram slice of the data. Note that if you update the 2D data slice, the data in the + * 3D data object will remain unaltered. To copy the data back in the 3D-volume you must return the data by calling 'returnSlice'. + * + * @param _iSliceNr slice number + * @return Sinogram data object + */ + virtual CFloat32ProjectionData2D* fetchSinogram(int _iSliceNr) const; + + /** This SLOW function returns a detector value stored a specific index in the array. + * Reading values in this way might cause a lot of unnecessary memory operations, don't + * use it in time-critical code. + * + * @param _iIndex Index in the array if the data were stored completely in main memory + * @return The value the location specified by _iIndex + */ + virtual float32 getDetectorValue(int _iIndex); + + /** This SLOW function stores a detector value at a specific index in the array. + * Writing values in this way might cause a lot of unnecessary memory operations, don't + * use it in time-critical code. + * + * @param _iIndex Index in the array if the data were stored completely in main memory + * @param _fValue The value to be stored at the location specified by _iIndex + */ + virtual void setDetectorValue(int _iIndex, float32 _fValue); + + /** Return a sinogram slice to the 3d data. The data will be stored in the 3D Data object. + * + * @param _iSliceNr slice number + * @param _pSinogram2D 2D Sinogram Object. + */ + virtual void returnSinogram(int _iSliceNr, CFloat32ProjectionData2D* _pSinogram2D); + + /** Which type is this class? + * + * @return DataType: PROJECTION + */ + virtual EDataType getType() const; + + /** + * Overloaded Operator: data = data (pointwise) + * + * @param _dataIn r-value + * @return l-value + */ + CFloat32ProjectionData3DMemory& operator=(const CFloat32ProjectionData3DMemory& _dataIn); +}; +//---------------------------------------------------------------------------------------- + +//---------------------------------------------------------------------------------------- +// Get type. +inline CFloat32Data3D::EDataType CFloat32ProjectionData3DMemory::getType() const +{ + return PROJECTION; +} +//---------------------------------------------------------------------------------------- + +} // end namespace astra + +#endif // _INC_ASTRA_FLOAT32PROJECTIONDATA3DMEMORY diff --git a/include/astra/Float32VolumeData2D.h b/include/astra/Float32VolumeData2D.h new file mode 100644 index 0000000..d7bf2f6 --- /dev/null +++ b/include/astra/Float32VolumeData2D.h @@ -0,0 +1,183 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FLOAT32VOLUMEDATA2D +#define _INC_ASTRA_FLOAT32VOLUMEDATA2D + +#include "Float32Data2D.h" +#include "VolumeGeometry2D.h" + +namespace astra { + +/** + * This class represents two-dimensional Volume Data. + * + * It contains member functions for accessing this data and for performing + * elementary computations on the data. + * The data block is "owned" by the class, meaning that the class is + * responsible for deallocation of the memory involved. + */ +class _AstraExport CFloat32VolumeData2D : public CFloat32Data2D { + +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the init() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + * + */ + CFloat32VolumeData2D(); + + /** Constructor. Create an instance of the CFloat32VolumeData2D class without initializing the data. + * + * Memory is allocated for the data block. The allocated memory is not cleared and + * its contents after construction is undefined. Construction may be followed by a + * call to copyData() to fill the memory block. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class. + */ + CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry); + + /** Constructor. Create an instance of the CFloat32VolumeData2D class with initialization of the data. + * + * Memory is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class. + * @param _pfData pointer to a one-dimensional float32 data block + */ + CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry, float32* _pfData); + + /** Constructor. Create an instance of the CFloat32VolumeData2D class with a scalar initialization of the data. + * + * Memory is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class. + * @param _fScalar scalar value to be put at each index. + */ + CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry, float32 _fScalar); + + /** + * Copy constructor + */ + CFloat32VolumeData2D(const CFloat32VolumeData2D& _other); + + /** + * Assignment operator + */ + CFloat32VolumeData2D& operator=(const CFloat32VolumeData2D& _other); + + /** Initialization. Initializes of the CFloat32VolumeData2D class without initializing the data. + * + * Memory is allocated for the data block. The allocated memory is not cleared and + * its contents after construction is undefined. Construction may be followed by a + * call to copyData() to fill the memory block. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class. + * @return Initialization of the base class successfull. + */ + bool initialize(CVolumeGeometry2D* _pGeometry); + + /** Initialization. Initializes an instance of the CFloat32VolumeData2D class with initialization of the data. + * + * Memory is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class. + * @param _pfData pointer to a one-dimensional float32 data block + */ + bool initialize(CVolumeGeometry2D* _pGeometry, const float32* _pfData); + + + /** Initialization. Initializes an instance of the CFloat32VolumeData2D class with scalar initialization of the data. + * + * Memory is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class. + * @param _fScalar scalar value to be put at each index. + */ + bool initialize(CVolumeGeometry2D* _pGeometry, float32 _fScalar); + + /** Destructor. + */ + virtual ~CFloat32VolumeData2D(); + + /** Which type is this class? + * + * @return DataType: VOLUME + */ + virtual EDataType getType() const; + + /** Get the volume geometry. + * + * @return pointer to volume geometry. + */ + virtual CVolumeGeometry2D* getGeometry() const; + + /** Change the projection geometry. + * Note that this can't change the dimensions of the data. + */ + virtual void changeGeometry(CVolumeGeometry2D* pGeometry); + +protected: + + /** The projection geometry for this data. + */ + CVolumeGeometry2D* m_pGeometry; + +}; + +//---------------------------------------------------------------------------------------- +// Get the projection geometry. +inline CVolumeGeometry2D* CFloat32VolumeData2D::getGeometry() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_pGeometry; +} + +//---------------------------------------------------------------------------------------- +// Get type +inline CFloat32Data2D::EDataType CFloat32VolumeData2D::getType() const +{ + return VOLUME; +} + + +} // end namespace astra + +#endif // _INC_ASTRA_FLOAT32VOLUMEDATA2D diff --git a/include/astra/Float32VolumeData3D.h b/include/astra/Float32VolumeData3D.h new file mode 100644 index 0000000..0b1bd96 --- /dev/null +++ b/include/astra/Float32VolumeData3D.h @@ -0,0 +1,265 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FLOAT32VOLUMEDATA3D +#define _INC_ASTRA_FLOAT32VOLUMEDATA3D + +#include "Float32Data3D.h" +#include "Float32VolumeData2D.h" +#include "VolumeGeometry3D.h" + +namespace astra { + +/** + * This asbtract class represents three-dimensional Volume Data. + */ +class _AstraExport CFloat32VolumeData3D : public virtual CFloat32Data3D +{ +protected: + CVolumeGeometry3D * m_pGeometry; + +public: + /** Default constructor. + */ + CFloat32VolumeData3D(); + + /** Destructor. + */ + virtual ~CFloat32VolumeData3D(); + + /** + * Returns number of rows + * + * @return number of rows + */ + int getRowCount() const; + + /** + * Returns number of columns + * + * @return number of columns + */ + int getColCount() const; + + /** + * Returns number of slices + * + * @return number of slices + */ + int getSliceCount() const; + + /** + * Returns total number of volumes + * + * @return total number of volumes + */ + int getVoxelTotCount() const; + + /** Which type is this class? + * + * @return DataType: VOLUME + */ + virtual CFloat32Data3D::EDataType getType() const; + + /** Fetch a slice from the data in the x direction. Note that if you update the 2D data slice, the data in the + * 3d data object will remain unaltered. To copy the data you must return the data by calling 'returnSliceX'. + * You should not delete data fetched with this function yourself, instead call the 'returnSliceX' function. + * + * @param _iColumnIndex slice number + * @return Volume data object + */ + virtual CFloat32VolumeData2D* fetchSliceX(int _iColumnIndex) const = 0; + + /** Fetch a slice from the data in the y direction. Note that if you update the 2D data slice, the data in the + * 3d data object will remain unaltered. To copy the data you must return the data by calling 'returnSliceY'. + * You should not delete data fetched with this function yourself, instead call the 'returnSliceY' function. + * + * @param _iRowIndex slice number + * @return Volume data object + */ + virtual CFloat32VolumeData2D* fetchSliceY(int _iRowIndex) const = 0; + + /** Fetch a slice from the data in the z direction. Note that if you update the 2D data slice, the data in the + * 3d data object will remain unaltered. To copy the data you must return the data by calling 'returnSliceZ'. + * You should not delete data fetched with this function yourself, instead call the 'returnSliceZ' function. + * + * @param _iSliceIndex slice number + * @return Volume data object + */ + virtual CFloat32VolumeData2D* fetchSliceZ(int _iSliceIndex) const = 0; + + /** Return a slice from the data in the x direction to the 3d data. The data will be deleted. If the slice was + * fetched with 'fetchSliceX', the data will be stored first. + * + * @param _iColumnIndex slice number + */ + virtual void returnSliceX(int _iColumnIndex, CFloat32VolumeData2D * _pSlice) = 0; + + /** Return a slice from the data in the y direction to the 3d data. The data will be deleted. If the slice was + * fetched with 'fetchSliceY', the data will be stored first. + * + * @param _iRowIndex slice number + */ + virtual void returnSliceY(int _iRowIndex, CFloat32VolumeData2D * _pSlice) = 0; + + /** Return a slice from the data in the z direction to the 3d data. The data will be deleted. If the slice was + * fetched with 'fetchSliceZ', the data will be stored first. + * + * @param _iSliceIndex slice number + */ + virtual void returnSliceZ(int _iSliceIndex, CFloat32VolumeData2D * _pSlice) = 0; + + /** This SLOW function returns a voxel value stored at a specific index in the array. + * Reading values in this way might cause a lot of unnecessary memory operations, don't + * use it in time-critical code. + * + * @param _iIndex Index in the array if the data were stored completely in main memory + * @return The value stored at the location specified by _iIndex + */ + virtual float32 getVoxelValue(int _iIndex) = 0; + + /** This SLOW function stores a voxel value at a specific index in the array. + * Writing values in this way might cause a lot of unnecessary memory operations, don't + * use it in time-critical code. + * + * @param _iIndex Index in the array if the data were stored completely in main memory + * @param _fValue The value to be stored at the location specified by _iIndex + */ + virtual void setVoxelValue(int _iIndex, float32 _fValue) = 0; + + /** + * Overloaded Operator: data += data (pointwise) + * + * @param _data r-value + * @return l-value + */ + CFloat32VolumeData3D& operator+=(const CFloat32VolumeData3D& _data); + + /** + * Overloaded Operator: data -= data (pointwise) + * + * @param _data r-value + * @return l-value + */ + CFloat32VolumeData3D& operator-=(const CFloat32VolumeData3D& _data); + + /** + * Overloaded Operator: data *= data (pointwise) + * + * @param _data r-value + * @return l-value + */ + CFloat32VolumeData3D& operator*=(const CFloat32VolumeData3D& _data); + + /** + * Overloaded Operator: data *= scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32VolumeData3D& operator*=(const float32& _fScalar); + + /** + * Overloaded Operator: data /= scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32VolumeData3D& operator/=(const float32& _fScalar); + + /** + * Overloaded Operator: data += scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32VolumeData3D& operator+=(const float32& _fScalar); + + /** + * Overloaded Operator: data -= scalar (pointwise) + * + * @param _fScalar r-value + * @return l-value + */ + CFloat32VolumeData3D& operator-=(const float32& _fScalar); + + /** + * Gives access to the geometry stored in this class + * + * @return The geometry describing the data stored in this volume + */ + virtual CVolumeGeometry3D* getGeometry() const; +}; + +//---------------------------------------------------------------------------------------- +// get row count +inline int CFloat32VolumeData3D::getRowCount() const +{ + return m_iHeight; +} + +//---------------------------------------------------------------------------------------- +// get column count +inline int CFloat32VolumeData3D::getColCount() const +{ + return m_iWidth; +} + +//---------------------------------------------------------------------------------------- +// get slice count +inline int CFloat32VolumeData3D::getSliceCount() const +{ + return m_iDepth; +} + +//---------------------------------------------------------------------------------------- +// get total voxel count +inline int CFloat32VolumeData3D::getVoxelTotCount() const +{ + return m_iHeight * m_iWidth * m_iDepth; +} + +//---------------------------------------------------------------------------------------- +// get type +inline CFloat32Data3D::EDataType CFloat32VolumeData3D::getType() const +{ + return CFloat32Data3D::VOLUME; +} + +//---------------------------------------------------------------------------------------- +// Get the volume geometry. +inline CVolumeGeometry3D* CFloat32VolumeData3D::getGeometry() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_pGeometry; +} +//---------------------------------------------------------------------------------------- + +} // end namespace astra + +#endif // _INC_ASTRA_FLOAT32VOLUMEDATA2D diff --git a/include/astra/Float32VolumeData3DMemory.h b/include/astra/Float32VolumeData3DMemory.h new file mode 100644 index 0000000..51df93e --- /dev/null +++ b/include/astra/Float32VolumeData3DMemory.h @@ -0,0 +1,213 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FLOAT32VOLUMEDATA3DMEMORY +#define _INC_ASTRA_FLOAT32VOLUMEDATA3DMEMORY + +#include "Float32Data3DMemory.h" +#include "VolumeGeometry3D.h" +#include "Float32VolumeData3D.h" + +namespace astra { + +/** + * This class represents three-dimensional Volume Data where the entire data block is stored in memory. + */ +class _AstraExport CFloat32VolumeData3DMemory : public CFloat32Data3DMemory, public CFloat32VolumeData3D +{ +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the init() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + * + */ + CFloat32VolumeData3DMemory(); + + /** Constructor. Create an instance of the CFloat32VolumeData3DMemory class without initializing the data. + * + * Memory is allocated for the data block. The allocated memory is not cleared and + * its contents after construction is undefined. Construction may be followed by a + * call to copyData() to fill the memory block. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class. + */ + CFloat32VolumeData3DMemory(CVolumeGeometry3D* _pGeometry); + + /** Constructor. Create an instance of the CFloat32VolumeData3DMemory class with initialization of the data. + * + * Memory is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class. + * @param _pfData pointer to a one-dimensional float32 data block + */ + CFloat32VolumeData3DMemory(CVolumeGeometry3D* _pGeometry, const float32* _pfData); + + /** Constructor. Create an instance of the CFloat32VolumeData3DMemory class with scalar initialization of the data. + * + * Memory is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class. + * @param _fScalar scalar value + */ + CFloat32VolumeData3DMemory(CVolumeGeometry3D* _pGeometry, float32 _fScalar); + + /** Destructor. + */ + virtual ~CFloat32VolumeData3DMemory(); + + /** Initialization. Initializes of the CFloat32VolumeData3DMemory class without initializing the data. + * + * Memory is allocated for the data block. The allocated memory is not cleared and + * its contents after construction is undefined. Construction may be followed by a + * call to copyData() to fill the memory block. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class. + * @return Initialization of the base class successful. + */ + bool initialize(CVolumeGeometry3D* _pGeometry); + + /** Initialization. Initializes an instance of the CFloat32VolumeData3DMemory class with initialization of the data. + * + * Memory is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class. + * @param _pfData pointer to a one-dimensional float32 data block + */ + bool initialize(CVolumeGeometry3D* _pGeometry, const float32* _pfData); + + /** Initialization. Initializes an instance of the CFloat32VolumeData3DMemory class with scalar initialization of the data. + * + * Memory is allocated for the data block and the contents of the memory pointed to by + * _pfData is copied into the allocated memory. + * The size of the data is determined by the specified volume geometry object. + * + * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class. + * @param _fScalar scalar value + */ + bool initialize(CVolumeGeometry3D* _pGeometry, float32 _fScalar); + + /** Which type is this class? + * + * @return DataType: VOLUME + */ + virtual CFloat32Data3D::EDataType getType() const; + + /** Get the volume geometry. + * + * @return pointer to volume geometry. + */ + CVolumeGeometry3D* getGeometry(); + + /** + * Gets a slice, containing all voxels with a given x (= column) index. + */ + CFloat32VolumeData2D * fetchSliceX(int _iColumnIndex) const; + + /** + * Gets a slice, containing all voxels with a given y (= row) index. + */ + CFloat32VolumeData2D * fetchSliceY(int _iRowIndex) const; + + /** + * Gets a slice, containing all voxels with a given z (= slice) index. + */ + CFloat32VolumeData2D * fetchSliceZ(int _iSliceIndex) const; + + /** + * Gets a slice, containing all voxels with a given x (= column) index. + */ + void returnSliceX(int _iColumnIndex, CFloat32VolumeData2D * _pSliceData); + + /** + * Gets a slice, containing all voxels with a given y (= row) index. + */ + void returnSliceY(int _iRowIndex, CFloat32VolumeData2D * _pSliceData); + + /** + * Copies data from a 2D slice containing all voxels with a given z (= slice) index to the + * 3D memory stored in this class. + */ + void returnSliceZ(int _iSliceIndex, CFloat32VolumeData2D * _pSliceData); + + /** This SLOW function returns a volume value stored a specific index in the array. + * Reading values in this way might cause a lot of unnecessary memory operations, don't + * use it in time-critical code. + * + * @param _iIndex Index in the array if the data were stored completely in main memory + * @return The value the location specified by _iIndex + */ + virtual float32 getVoxelValue(int _iIndex); + + /** This SLOW function stores a voxel value at a specific index in the array. + * Writing values in this way might cause a lot of unnecessary memory operations, don't + * use it in time-critical code. + * + * @param _iIndex Index in the array if the data were stored completely in main memory + * @param _fValue The value to be stored at the location specified by _iIndex + */ + virtual void setVoxelValue(int _iIndex, float32 _fValue); + + /** + * Overloaded Operator: data = data (pointwise) + * + * @param _dataIn r-value + * @return l-value + */ + CFloat32VolumeData3DMemory& operator=(const CFloat32VolumeData3DMemory& _dataIn); +}; + +//---------------------------------------------------------------------------------------- +// Get the projection geometry. +inline CVolumeGeometry3D* CFloat32VolumeData3DMemory::getGeometry() +{ + ASTRA_ASSERT(m_bInitialized); + return m_pGeometry; +} + +//---------------------------------------------------------------------------------------- +// Get type +inline CFloat32Data3D::EDataType CFloat32VolumeData3DMemory::getType() const +{ + return VOLUME; +} + + +} // end namespace astra + +#endif // _INC_ASTRA_FLOAT32VOLUMEDATA3DMEMORY diff --git a/include/astra/ForwardProjectionAlgorithm.h b/include/astra/ForwardProjectionAlgorithm.h new file mode 100644 index 0000000..147002b --- /dev/null +++ b/include/astra/ForwardProjectionAlgorithm.h @@ -0,0 +1,225 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FORWARDPROJECTIONALGORITHM +#define _INC_ASTRA_FORWARDPROJECTIONALGORITHM + +#include "Algorithm.h" + +#include "Globals.h" + +#include "Projector2D.h" +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + +#include "DataProjector.h" + +namespace astra { + +/** + * \brief + * This class contains the implementation of an algorithm that creates a forward projection + * of a volume object and stores it into a sinogram. + * + * \par XML Configuration + * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.} + * \astra_xml_item{VolumeDataId, integer, Identifier of the volume data object as it is stored in the DataManager.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of the resulting projection data object as it is stored in the DataManager.} + * \astra_xml_item_option{VolumeMaskId, integer, not used, Identifier of a volume data object that acts as a volume mask. 0 = don't use this pixel. 1 = use this pixel. } + * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 0 = don't use this ray. 1 = use this ray.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('FP');\n + * cfg.ProjectorId = proj_id;\n + * cfg.VolumeDataId = vol_id;\n + * cfg.ProjectionDataId = sino_id;\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('run'\, alg_id);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + * + */ +class _AstraExport CForwardProjectionAlgorithm : public CAlgorithm { + +protected: + + /** Init stuff + */ + virtual void _init(); + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - valid projector + * - valid data objects + */ + virtual bool _check(); + + //< Projector object. + CProjector2D* m_pProjector; + //< ProjectionData2D object containing the sinogram. + CFloat32ProjectionData2D* m_pSinogram; + //< VolumeData2D object containing the phantom. + CFloat32VolumeData2D* m_pVolume; + + // data projector + astra::CDataProjectorInterface* m_pForwardProjector; + + // ray or voxel-driven projector code? + bool m_bUseVoxelProjector; + + //< Dataobject containing fixed volume mask (0 = don't project) + CFloat32VolumeData2D* m_pVolumeMask; + //< Use the fixed reconstruction mask? + bool m_bUseVolumeMask; + + //< Dataobject containing fixed reconstruction mask (0 = don't project) + CFloat32ProjectionData2D* m_pSinogramMask; + //< Use the fixed reconstruction mask? + bool m_bUseSinogramMask; + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CForwardProjectionAlgorithm(); + + /** Initializing constructor. + * + * @param _pProjector Projector to use. + * @param _pVolume VolumeData2D object containing the phantom to compute sinogram from + * @param _pSinogram ProjectionData2D object to store sinogram data in. + */ + CForwardProjectionAlgorithm(CProjector2D* _pProjector, + CFloat32VolumeData2D* _pVolume, + CFloat32ProjectionData2D* _pSinogram); + + /** Destructor. + */ + virtual ~CForwardProjectionAlgorithm(); + + /** Clear this class. + */ + virtual void clear(); + + /** Initialize class. + * + * @param _pProjector Projector to use. + * @param _pVolume VolumeData2D object containing the phantom to compute sinogram from + * @param _pSinogram ProjectionData2D object to store sinogram data in. + * @return success + */ + bool initialize(CProjector2D* _pProjector, + CFloat32VolumeData2D* _pVolume, + CFloat32ProjectionData2D* _pSinogram); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Set a fixed reconstruction mask. A pixel will only be used in the reconstruction if the + * corresponding value in the mask is 1. + * + * @param _pMask Volume Data object containing fixed reconstruction mask + * @param _bEnable enable the use of this mask + */ + void setVolumeMask(CFloat32VolumeData2D* _pMask, bool _bEnable = true); + + /** Set a fixed sinogram mask. A detector value will only be used in the reconstruction if the + * corresponding value in the mask is 1. + * + * @param _pMask Projection Data object containing fixed sinogram mask + * @param _bEnable enable the use of this mask + */ + void setSinogramMask(CFloat32ProjectionData2D* _pMask, bool _bEnable = true); + + /** Get projector object + * + * @return projector + */ + CProjector2D* getProjector() const; + + /** Get sinogram data object + * + * @return sinogram data object + */ + CFloat32ProjectionData2D* getSinogram() const; + + /** Get volume data object + * + * @return volume data object + */ + CFloat32VolumeData2D* getVolume() const; + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + +}; + +// inline functions +inline std::string CForwardProjectionAlgorithm::description() const { return CForwardProjectionAlgorithm::type; }; +inline CProjector2D* CForwardProjectionAlgorithm::getProjector() const { return m_pProjector; } +inline CFloat32ProjectionData2D* CForwardProjectionAlgorithm::getSinogram() const { return m_pSinogram; } +inline CFloat32VolumeData2D* CForwardProjectionAlgorithm::getVolume() const { return m_pVolume; } + +} // end namespace + +#endif diff --git a/include/astra/Fourier.h b/include/astra/Fourier.h new file mode 100644 index 0000000..290c094 --- /dev/null +++ b/include/astra/Fourier.h @@ -0,0 +1,127 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_FOURIER +#define _INC_ASTRA_FOURIER + +#include "Globals.h" + +namespace astra { + + +/** + * Perform a 1D DFT or inverse DFT. + * + * @param iLength number of elements + * @param pfRealIn real part of input + * @param pfImaginaryIn imaginary part of input + * @param pfRealOut real part of output + * @param pfImaginaryOut imaginary part of output + * @param iStrideIn distance between elements in pf*In + * @param iStrideOut distance between elements in pf*Out + * @param bInverse if true, perform an inverse DFT + */ + +void _AstraExport discreteFourierTransform1D(unsigned int iLength, + const float32* pfRealIn, + const float32* pfImaginaryIn, + float32* pfRealOut, + float32* pfImaginaryOut, + unsigned int iStrideIn, + unsigned int iStrideOut, + bool bInverse); + +/** + * Perform a 2D DFT or inverse DFT. + * + * @param iHeight number of rows + * @param iWidth number of columns + * @param pfRealIn real part of input + * @param pfImaginaryIn imaginary part of input + * @param pfRealOut real part of output + * @param pfImaginaryOut imaginary part of output + * @param bInverse if true, perform an inverse DFT + */ + +void _AstraExport discreteFourierTransform2D(unsigned int iHeight, unsigned int iWidth, + const float32* pfRealIn, + const float32* pfImaginaryIn, + float32* pfRealOut, + float32* pfImaginaryOut, + bool bInverse); + +/** + * Perform a 1D FFT or inverse FFT. The size must be a power of two. + * This transform can be done in-place, so the input and output pointers + * may point to the same data. + * + * @param iLength number of elements, must be a power of two + * @param pfRealIn real part of input + * @param pfImaginaryIn imaginary part of input + * @param pfRealOut real part of output + * @param pfImaginaryOut imaginary part of output + * @param iStrideIn distance between elements in pf*In + * @param iStrideOut distance between elements in pf*Out + * @param bInverse if true, perform an inverse DFT + */ + +void _AstraExport fastTwoPowerFourierTransform1D(unsigned int iLength, + const float32* pfRealIn, + const float32* pfImaginaryIn, + float32* pfRealOut, + float32* pfImaginaryOut, + unsigned int iStrideIn, + unsigned int iStrideOut, + bool bInverse); + +/** + * Perform a 2D FFT or inverse FFT. The size must be a power of two. + * This transform can be done in-place, so the input and output pointers + * may point to the same data. + * + * @param iHeight number of rows, must be a power of two + * @param iWidth number of columns, must be a power of two + * @param pfRealIn real part of input + * @param pfImaginaryIn imaginary part of input + * @param pfRealOut real part of output + * @param pfImaginaryOut imaginary part of output + * @param bInverse if true, perform an inverse DFT + */ + +void _AstraExport fastTwoPowerFourierTransform2D(unsigned int iHeight, + unsigned int iWidth, + const float32* pfRealIn, + const float32* pfImaginaryIn, + float32* pfRealOut, + float32* pfImaginaryOut, + bool bInverse); + + +} + +#endif diff --git a/include/astra/Globals.h b/include/astra/Globals.h new file mode 100644 index 0000000..9407ef9 --- /dev/null +++ b/include/astra/Globals.h @@ -0,0 +1,309 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_GLOBALS +#define _INC_ASTRA_GLOBALS + +/*! \mainpage The ASTRA-toolbox + * + * + */ + + +//---------------------------------------------------------------------------------------- + +#ifdef _MSC_VER + +// disable warning: 'fopen' was declared deprecated +#pragma warning (disable : 4996) +// disable warning: C++ exception handler used, but unwind semantics are not enables +#pragma warning (disable : 4530) +// disable warning: no suitable definition provided for explicit template instantiation request +#pragma warning (disable : 4661) + +#endif + +//---------------------------------------------------------------------------------------- +// standard includes +#include +#include +#include +#include +#include +#include + +//---------------------------------------------------------------------------------------- +// macro's + +#define ASTRA_TOOLBOXVERSION_MAJOR 1 +#define ASTRA_TOOLBOXVERSION_MINOR 1 +#define ASTRA_TOOLBOXVERSION ((ASTRA_TOOLBOXVERSION_MAJOR)*100 + (ASTRA_TOOLBOXVERSION_MINOR)) +#define ASTRA_TOOLBOXVERSION_STRING "1.1" + + +#define ASTRA_ASSERT(a) assert(a) + +#define ASTRA_CONFIG_CHECK(value, type, msg) if (!(value)) { cout << "Configuration Error in " << type << ": " << msg << endl; return false; } + +#define ASTRA_CONFIG_WARNING(type, msg) { cout << "Warning in " << type << ": " << msg << endl; } + + +#define ASTRA_DELETE(a) if (a) { delete a; a = NULL; } +#define ASTRA_DELETE_ARRAY(a) if (a) { delete[] a; a = NULL; } + +#ifdef _MSC_VER + +#ifdef DLL_EXPORTS +#define _AstraExport __declspec(dllexport) +#define EXPIMP_TEMPLATE +#else +#define _AstraExport __declspec(dllimport) +#define EXPIMP_TEMPLATE extern +#endif + +#else + +#define _AstraExport + +#endif + + +//---------------------------------------------------------------------------------------- +// typedefs +namespace astra { + typedef float float32; + typedef double float64; + typedef unsigned short int uint16; + typedef signed short int sint16; + typedef unsigned char uchar8; + typedef signed char schar8; + + typedef int int32; + typedef short int int16; +} + +//---------------------------------------------------------------------------------------- +// globals vars & functions +//namespace astra { +//#define ToolboxVersion 0.1f; + +//float32 getVersion() { return ToolboxVersion; } + +//_AstraExport bool cudaEnabled() { +//#ifdef ASTRA_CUDA +// return true; +//#else +// return false; +//#endif +//} +//} + +//---------------------------------------------------------------------------------------- +// errors +namespace astra { + +typedef enum {ASTRA_SUCCESS, + ASTRA_ERROR_NOT_INITIALIZED, + ASTRA_ERROR_INVALID_FILE, + ASTRA_ERROR_OUT_OF_RANGE, + ASTRA_ERROR_DIMENSION_MISMATCH, + ASTRA_ERROR_EXTERNAL_LIBRARY, + ASTRA_ERROR_ALLOCATION, + ASTRA_ERROR_NOT_IMPLEMENTED} AstraError; +} + + +//---------------------------------------------------------------------------------------- +// variables +namespace astra { + const float32 PI = 3.14159265358979323846264338328f; + const float32 PI32 = 3.14159265358979323846264338328f; + const float32 PIdiv2 = PI / 2; + const float32 PIdiv4 = PI / 4; + const float32 eps = 1e-7f; +} + +//---------------------------------------------------------------------------------------- +// math +namespace astra { + + inline float32 cos_73s(float32 x) + { + /* + const float32 c1 = 0.999999953464f; + const float32 c2 = -0.4999999053455f; + const float32 c3 = 0.0416635846769f; + const float32 c4 = -0.0013853704264f; + const float32 c5 = 0.000023233f; + */ + const float c1= (float)0.99940307; + const float c2= (float)-0.49558072; + const float c3= (float)0.03679168; + + float32 x2; + x2 = x * x; + //return (c1 + x2*(c2 + x2*(c3 + x2*(c4 + c5*x2)))); + return (c1 + x2*(c2 + c3 * x2)); + } + + inline float32 fast_cos(float32 x) + { + int quad; + + //x = fmod(x, 2*PI); // Get rid of values > 2* pi + if (x < 0) x =- x; // cos(-x) = cos(x) + quad = int(x/PIdiv2); // Get quadrant # (0 to 3) + switch (quad) { + case 0: return cos_73s(x); + case 1: return -cos_73s(PI-x); + case 2: return -cos_73s(x-PI); + case 3: return cos_73s(2*PI-x); + } + return 0.0f; + } + + inline float32 fast_sin(float32 x){ + return fast_cos(PIdiv2-x); + } + +} + +//---------------------------------------------------------------------------------------- +// structs +namespace astra { + /** + * Struct for storing pixel weigths + **/ + struct SPixelWeight + { + int m_iIndex; + float32 m_fWeight; + }; + + /** + * Struct combining some properties of a detector in 1D detector row + **/ + struct SDetector2D + { + int m_iIndex; + int m_iAngleIndex; + int m_iDetectorIndex; + }; + + /** + * Struct combining some properties of a detector in 2D detector array + **/ + struct SDetector3D + { + int m_iIndex; + int m_iAngleIndex; + int m_iDetectorIndex; + int m_iSliceIndex; + }; +} +//---------------------------------------------------------------------------------------- +// some toys + +// safe reinterpret cast +template +To safe_reinterpret_cast(From from) +{ + BOOST_STATIC_ASSERT(sizeof(From) <= sizeof(To)); + return reinterpret_cast(from); +} + +//---------------------------------------------------------------------------------------- +// functions for testing +template +inline void writeArray(T*** arr, int dim1, int dim2, int dim3, const std::string& filename) +{ + std::ofstream out(filename.c_str()); + int i1, i2, i3; + for (i1 = 0; i1 < dim1; ++i1) { + for (i2 = 0; i2 < dim2; ++i2) { + for (i3 = 0; i3 < dim3; ++i3) { + out << arr[i1][i2][i3] << " "; + } + out << std::endl; + } + out << std::endl; + } + out.close(); +} + +template +inline void writeArray(T** arr, int dim1, int dim2, const std::string& filename) +{ + std::ofstream out(filename.c_str()); + for (int i1 = 0; i1 < dim1; i1++) { + for (int i2 = 0; i2 < dim2; i2++) { + out << arr[i1][i2] << " "; + } + out << std::endl; + } + out.close(); +} + +template +inline void writeArray(T* arr, int dim1, const std::string& filename) +{ + std::ofstream out(filename.c_str()); + for (int i1 = 0; i1 < dim1; i1++) { + out << arr[i1] << " "; + } + out.close(); +} +namespace astra { +_AstraExport inline int getVersion() { return ASTRA_TOOLBOXVERSION; } +_AstraExport inline const char* getVersionString() { return ASTRA_TOOLBOXVERSION_STRING; } +#ifdef ASTRA_CUDA +_AstraExport inline bool cudaEnabled() { return true; } +#else +_AstraExport inline bool cudaEnabled() { return false; } +#endif +} +//---------------------------------------------------------------------------------------- +// portability between MSVC and Linux/gcc + +#ifndef _MSC_VER +#include "swrap.h" +#define EXPIMP_TEMPLATE + +#if !defined(FORCEINLINE) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define FORCEINLINE inline __attribute__((__always_inline__)) +#else +#define FORCEINLINE inline +#endif + +#else + +#define FORCEINLINE __forceinline + +#endif + +#endif diff --git a/include/astra/Logger.h b/include/astra/Logger.h new file mode 100644 index 0000000..ae064fe --- /dev/null +++ b/include/astra/Logger.h @@ -0,0 +1,72 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_LOGGER +#define _INC_ASTRA_LOGGER + +#include + +namespace astra +{ + +/** + * This is the first stab at a decent logger. If the file "astra_logger.txt", it will be replaced + * with the text sent to this logger. If the file doesn't exist when the app starts, nothing is written. + */ +class CLogger +{ + static std::FILE * m_pOutFile; + static bool m_bInitialized; + + static void _assureIsInitialized(); + + CLogger(); + +public: + + /** + * Writes a line to the log file (newline is added). Ignored if logging is turned off. + * + * @param _text char pointer to text in line + */ + static void writeLine(const char * _text); + + /** + * Formats and writes a CUDA error to the log file. Ignored if logging is turned off. + * + * @param _fileName filename where error occurred (typically __FILE__) + * @param _line line in file (typically __LINE__) + * @param _errString string describing the error, can be output of cudaGetErrorString + */ + static void writeTerminalCUDAError(const char * _fileName, int _iLine, const char * _errString); +}; + +} + +#endif /* _INC_ASTRA_LOGGER */ + diff --git a/include/astra/ParallelBeamBlobKernelProjector2D.h b/include/astra/ParallelBeamBlobKernelProjector2D.h new file mode 100644 index 0000000..38b209c --- /dev/null +++ b/include/astra/ParallelBeamBlobKernelProjector2D.h @@ -0,0 +1,232 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_PARALLELBEAMBLOBPROJECTOR +#define _INC_ASTRA_PARALLELBEAMBLOBPROJECTOR + +#include "ParallelProjectionGeometry2D.h" +#include "Float32Data2D.h" +#include "Projector2D.h" + +namespace astra +{ + +/** This class implements a two-dimensional projector based on a blob-kernel. + * A more detailed description (in dutch) is available at + * http://www.astra.ua.ac.be/wiki/images/6/6e/Uitleg_blob_projector.pdf + * + * \par XML Configuration + * type = "blob" + * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.} + * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.} + * \astra_xml_item{Kernel, xml node, Kernel details. See below.} + * + * \par XML Configuration of the Kernel + * \astra_xml_item{KernelSize, float, Radius of the kernel.} + * \astra_xml_item{SampleRate, float, Sample rate of the kernel.} + * \astra_xml_item{SampleCount, integer, Number of samples.} + * \astra_xml_item{KernelValues, vector of float, Samples of the kernels starting at distance 0.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('blob');\n + * cfg.ProjectionGeometry = proj_geom;\n + * cfg.VolumeGeometry = vol_geom;\n + * cfg.Kernel.KernelSize = 2;\n + * cfg.Kernel.SampleRate = 0.01;\n + * cfg.Kernel.SampleCount = length(0:0.01:2);\n + * cfg.Kernel.KernelValues = kaiserBessel(2\, 10.4\, 2\, 0:0.01:2);\n + * proj_id = astra_mex_projector('create'\, cfg);\n + * } + */ +class _AstraExport CParallelBeamBlobKernelProjector2D : public CProjector2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - blobvalues are ok + */ + virtual bool _check(); + +public: + + // type of the projector, needed to register with CProjectorFactory + static std::string type; + + /** Default constructor. + */ + CParallelBeamBlobKernelProjector2D(); + + /** Constructor. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + * @param _fBlobSize Width of the blob. In units of PixelSize. + * @param _fBlobSampleRate Spacing between two blob samples. (= _fBlobSize/_iBlobSampleCount) + * @param _iBlobSampleCount Number of samples. + * @param _pfBlobValues Array of _iBlobSampleCount blob evaluations. + */ + CParallelBeamBlobKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry, + float32 _fBlobSize, + float32 _fBlobSampleRate, + int _iBlobSampleCount, + float32* _pfBlobValues); + + /** Destructor, is virtual to show that we are aware subclass destructor are called. + */ + ~CParallelBeamBlobKernelProjector2D(); + + /** Initialize the projector with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the projector. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + * @param _fBlobSize Width of the blob. In units of PixelSize. + * @param _fBlobSampleRate Spacing between two blob samples. (= _fBlobSize/_iBlobSampleCount) + * @param _iBlobSampleCount Number of samples. + * @param _pfBlobValues Array of _iBlobSampleCount blob evaluations. Will be HARDCOPIED. + */ + bool initialize(CParallelProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry, + float32 _fBlobSize, + float32 _fBlobSampleRate, + int _iBlobSampleCount, + float32* _pfBlobValues); + + /** Clear this class. + */ + virtual void clear(); + + /** Returns the number of weights required for storage of all weights of one projection. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels. + */ + virtual int getProjectionWeightsCount(int _iProjectionIndex); + + /** Compute the pixel weights for a single ray, from the source to a detector pixel. + * + * @param _iProjectionIndex Index of the projection + * @param _iDetectorIndex Index of the detector pixel + * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements + * of type SPixelWeight. On return, this array contains a list of the index + * and weight for all pixels on the ray. + * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels. + * This number MUST be greater than the total number of pixels on the ray. + * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the + * ray (that have been stored in the list _pWeightedPixels). + */ + virtual void computeSingleRayWeights(int _iProjectionIndex, + int _iDetectorIndex, + SPixelWeight* _pWeightedPixels, + int _iMaxPixelCount, + int& _iStoredPixelCount); + + /** Create a list of detectors that are influenced by point [_iRow, _iCol]. + * + * @param _iRow row of the point + * @param _iCol column of the point + * @return list of SDetector2D structs + */ + virtual std::vector projectPoint(int _iRow, int _iCol); + + /** Policy-based projection of all rays. This function will calculate each non-zero projection + * weight and use this value for a task provided by the policy object. + * + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void project(Policy& _policy); + + /** Policy-based projection of all rays of a single projection. This function will calculate + * each non-zero projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Wwhich projection should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleProjection(int _iProjection, Policy& _policy); + + /** Policy-based projection of a single ray. This function will calculate each non-zero + * projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Which projection should be projected? + * @param _iDetector Which detector should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy); + + /** Return the type of this projector. + * + * @return identification type of this projector + */ + virtual std::string getType(); + +protected: + + /** Evaluate the blob kernel for a given distance from its center. + * + * @param _fDiff distance between hit point and blob center + * @return blob value + */ + float32 _getBlobValue(float32 _fDiff); + + float32 m_fBlobSize; //< Width of the blob + float32 m_fBlobSampleRate; //< At which interval are the inserted blob values evaluated? + int m_iBlobSampleCount; //< Number of evaluated blob samples + float32* m_pfBlobValues; //< Evaluated blob values + float32* m_pfBlobValuesNeg; //< Evaluated blob values + +}; + +//---------------------------------------------------------------------------------------- + +inline std::string CParallelBeamBlobKernelProjector2D::getType() +{ + return type; +} + +} // namespace astra + +#endif + diff --git a/include/astra/ParallelBeamBlobKernelProjector2D.inl b/include/astra/ParallelBeamBlobKernelProjector2D.inl new file mode 100644 index 0000000..70764b1 --- /dev/null +++ b/include/astra/ParallelBeamBlobKernelProjector2D.inl @@ -0,0 +1,212 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + + + +//---------------------------------------------------------------------------------------- +// PROJECT ALL +template +void CParallelBeamBlobKernelProjector2D::project(Policy& p) +{ + for (int iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) { + for (int iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + projectSingleRay(iAngle, iDetector, p); + } + } +} + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE PROJECTION +template +void CParallelBeamBlobKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p) +{ + for (int iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + projectSingleRay(_iProjection, iDetector, p); + } +} + + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE RAY +template +void CParallelBeamBlobKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p) +{ + ASTRA_ASSERT(m_bIsInitialized); + + int iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) return; + + // get values + float32 t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector); + float32 theta = m_pProjectionGeometry->getProjectionAngle(_iProjection); + if (theta >= 7*PIdiv4) theta -= 2*PI; + + bool flip = false; + + if (theta >= 3*PIdiv4) { + theta -= PI; + t = -t; + flip = true; + } + + + if (theta <= PIdiv4) { // -pi/4 <= theta <= pi/4 + + // precalculate sin, cos, 1/cos + float32 sin_theta = sin(theta); + float32 cos_theta = cos(theta); + float32 inv_cos_theta = 1.0f / cos_theta; + + // precalculate other stuff + float32 lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta; + float32 updatePerRow = sin_theta * lengthPerRow; + float32 inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); + float32 pixelLengthX_over_blobSize = m_pVolumeGeometry->getPixelLengthX() / m_fBlobSize; + + // some variables + int row, col, xmin, xmax; + float32 P, x, d; + + // calculate P and x for row 0 + P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta; + x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // calculate extent + xmin = (int)ceil((P - m_fBlobSize - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f); + xmax = (int)floor((P + m_fBlobSize - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f); + + // add pixels + for (col = xmin; col <= xmax; col++) { + if (col >= 0 && col < m_pVolumeGeometry->getGridColCount()) { + //d = abs(x - col) * pixelLengthX_over_blobSize; + //index = (int)(d*m_iBlobSampleCount+0.5f); + //float32 fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)] * lengthPerRow; + + float32 fWeight; + int index; + if ((x >= col) ^ flip) { + d = abs(x - col) * pixelLengthX_over_blobSize * cos_theta; + index = (int)(d*m_iBlobSampleCount+0.5f); + fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)]; + } else { + d = abs(x - col) * pixelLengthX_over_blobSize * cos_theta; + index = (int)(d*m_iBlobSampleCount+0.5f); + fWeight = m_pfBlobValuesNeg[min(index,m_iBlobSampleCount-1)]; + } + + int iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, fWeight); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // update P and x + P += updatePerRow; + x += updatePerRow * inv_pixelLengthX; + } + + } else { // pi/4 < theta < 3pi/4 + + // precalculate sin cos + float32 sin_90_theta = sin(PIdiv2-theta); + float32 cos_90_theta = cos(PIdiv2-theta); + float32 inv_cos_90_theta = 1.0f / cos_90_theta; + + // precalculate other stuff + float32 lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_cos_90_theta; + float32 updatePerCol = sin_90_theta * lengthPerCol; + float32 inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); + float32 pixelLengthY_over_blobSize = m_pVolumeGeometry->getPixelLengthY() / m_fBlobSize; + + // some variables + int row, col, xmin, xmax; + float32 P,x, d; + + // calculate P and x for col 0 + P = (sin_90_theta * m_pVolumeGeometry->pixelColToCenterX(0) - t) * inv_cos_90_theta; + x = (P - m_pVolumeGeometry->getWindowMinY()) * inv_pixelLengthY - 0.5f; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // calculate extent + xmin = (int)ceil((P - m_fBlobSize - m_pVolumeGeometry->getWindowMinY()) * inv_pixelLengthY - 0.5f); + xmax = (int)floor((P + m_fBlobSize - m_pVolumeGeometry->getWindowMinY()) * inv_pixelLengthY - 0.5f); + + // add pixels + for (row = xmin; row <= xmax; row++) { + if (row >= 0 && row < m_pVolumeGeometry->getGridRowCount()) { + //d = abs(x - row) * pixelLengthY_over_blobSize; + //int index = (int)(d*m_iBlobSampleCount+0.5f); + //float32 fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)] * lengthPerCol; + + float32 fWeight; + int index; + if ((x <= row) ^ flip) { + d = abs(x - row) * pixelLengthY_over_blobSize * cos_90_theta; + index = (int)(d*m_iBlobSampleCount+0.5f); + fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)]; + } else { + d = abs(x - row) * pixelLengthY_over_blobSize * cos_90_theta; + index = (int)(d*m_iBlobSampleCount+0.5f); + fWeight = m_pfBlobValuesNeg[min(index,m_iBlobSampleCount-1)]; + } + + + int iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, fWeight); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // update P and x + P += updatePerCol; + x += updatePerCol * inv_pixelLengthY; + } + + } + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + + +} diff --git a/include/astra/ParallelBeamLineKernelProjector2D.h b/include/astra/ParallelBeamLineKernelProjector2D.h new file mode 100644 index 0000000..9e2cc5a --- /dev/null +++ b/include/astra/ParallelBeamLineKernelProjector2D.h @@ -0,0 +1,186 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_PARALLELBEAMLINEKERNELPROJECTOR +#define _INC_ASTRA_PARALLELBEAMLINEKERNELPROJECTOR + +#include "ParallelProjectionGeometry2D.h" +#include "Float32Data2D.h" +#include "Projector2D.h" + +namespace astra +{ + +/** This class implements a two-dimensional projector based on a line based kernel. + * + * \par XML Configuration + * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.} + * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('line');\n + * cfg.ProjectionGeometry = proj_geom;\n + * cfg.VolumeGeometry = vol_geom;\n + * proj_id = astra_mex_projector('create'\, cfg);\n + * } + */ +class _AstraExport CParallelBeamLineKernelProjector2D : public CProjector2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - blobvalues are ok + */ + virtual bool _check(); + +public: + + // type of the projector, needed to register with CProjectorFactory + static std::string type; + + /** Default constructor. + */ + CParallelBeamLineKernelProjector2D(); + + /** Constructor. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + */ + CParallelBeamLineKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Destructor, is virtual to show that we are aware subclass destructor are called. + */ + ~CParallelBeamLineKernelProjector2D(); + + /** Initialize the projector with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the projector. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + * @return initialization successful? + */ + virtual bool initialize(CParallelProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Clear this class. + */ + virtual void clear(); + + /** Returns the number of weights required for storage of all weights of one projection. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels. + */ + virtual int getProjectionWeightsCount(int _iProjectionIndex); + + /** Compute the pixel weights for a single ray, from the source to a detector pixel. + * + * @param _iProjectionIndex Index of the projection + * @param _iDetectorIndex Index of the detector pixel + * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements + * of type SPixelWeight. On return, this array contains a list of the index + * and weight for all pixels on the ray. + * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels. + * This number MUST be greater than the total number of pixels on the ray. + * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the + * ray (that have been stored in the list _pWeightedPixels). + */ + virtual void computeSingleRayWeights(int _iProjectionIndex, + int _iDetectorIndex, + SPixelWeight* _pWeightedPixels, + int _iMaxPixelCount, + int& _iStoredPixelCount); + + /** Create a list of detectors that are influenced by point [_iRow, _iCol]. + * + * @param _iRow row of the point + * @param _iCol column of the point + * @return list of SDetector2D structs + */ + virtual std::vector projectPoint(int _iRow, int _iCol); + + /** Policy-based projection of all rays. This function will calculate each non-zero projection + * weight and use this value for a task provided by the policy object. + * + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void project(Policy& _policy); + + /** Policy-based projection of all rays of a single projection. This function will calculate + * each non-zero projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Wwhich projection should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleProjection(int _iProjection, Policy& _policy); + + /** Policy-based projection of a single ray. This function will calculate each non-zero + * projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Which projection should be projected? + * @param _iDetector Which detector should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy); + + /** Return the type of this projector. + * + * @return identification type of this projector + */ + virtual std::string getType(); + +}; + +inline std::string CParallelBeamLineKernelProjector2D::getType() +{ + return type; +} + +} // namespace astra + +#endif + diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl new file mode 100644 index 0000000..08bbe5f --- /dev/null +++ b/include/astra/ParallelBeamLineKernelProjector2D.inl @@ -0,0 +1,731 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + + + +//---------------------------------------------------------------------------------------- +// PROJECT ALL +template +void CParallelBeamLineKernelProjector2D::project(Policy& p) +{ + // variables + float32 theta, sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, S, T, t, I, P, x, x2; + float32 lengthPerRow, updatePerRow, inv_pixelLengthX, lengthPerCol, updatePerCol, inv_pixelLengthY; + int iVolumeIndex, iRayIndex, row, col, iAngle, iDetector, x1; + bool switch_t; + + // loop angles + for (iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) { + + // get theta + theta = m_pProjectionGeometry->getProjectionAngle(iAngle); + switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // precalculate sin, cos, 1/cos + sin_theta = sin(theta); + cos_theta = cos(theta); + inv_sin_theta = 1.0f / sin_theta; + inv_cos_theta = 1.0f / cos_theta; + + // precalculate kernel limits + lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta; + updatePerRow = sin_theta * inv_cos_theta; + inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); + + // precalculate kernel limits + lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta; + updatePerCol = cos_theta * inv_sin_theta; + inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); + + // precalculate S and T + S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow); + T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol); + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(iDetector); + if (switch_t) t = -t; + + // vertically + if (theta <= PIdiv4) { + + // calculate x for row 0 + P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta; + x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX; + + // get coords + int nextx1 = int((x > 0.0f) ? x : x-1.0f); + float nextx2 = x - nextx1; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + x1 = nextx1; + x2 = nextx2; + + nextx2 += updatePerRow; + while (nextx2 >= 1.0f) { + nextx2 -= 1.0f; + nextx1++; + } + while (nextx2 < 0.0f) { + nextx2 += 1.0f; + nextx1--; + } + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue; + + // left + if (x2 < 0.5f-S) { + I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+S) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // right + else { + I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } + + // horizontally + else if (PIdiv4 <= theta && theta <= 3*PIdiv4) { + + // calculate point P + P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta; + x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY; + + // get coords + int nextx1 = int((x > 0.0f) ? x : x-1.0f); + float nextx2 = x - nextx1; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + x1 = nextx1; + x2 = nextx2; + + nextx2 += updatePerCol; + while (nextx2 >= 1.0f) { + nextx2 -= 1.0f; + nextx1++; + } + while (nextx2 < 0.0f) { + nextx2 += 1.0f; + nextx1--; + } + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue; + + // up + if (x2 < 0.5f-T) { + I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+T) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // down + else { + I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } // end loop col + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end loop detector + } // end loop angles + +} + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE PROJECTION +template +void CParallelBeamLineKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p) +{ + // variables + float32 theta, sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, S, T, t, I, P, x, x2; + float32 lengthPerRow, updatePerRow, inv_pixelLengthX, lengthPerCol, updatePerCol, inv_pixelLengthY; + int iVolumeIndex, iRayIndex, row, col, iDetector, x1; + bool switch_t; + + // get theta + theta = m_pProjectionGeometry->getProjectionAngle(_iProjection); + switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // precalculate sin, cos, 1/cos + sin_theta = sin(theta); + cos_theta = cos(theta); + inv_sin_theta = 1.0f / sin_theta; + inv_cos_theta = 1.0f / cos_theta; + + // precalculate kernel limits + lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta; + updatePerRow = sin_theta * inv_cos_theta; + inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); + + // precalculate kernel limits + lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta; + updatePerCol = cos_theta * inv_sin_theta; + inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); + + // precalculate S and T + S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow); + T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol); + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(iDetector); + if (switch_t) t = -t; + + // vertically + if (theta <= PIdiv4) { + + // calculate x for row 0 + P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta; + x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX; + + // get coords + int nextx1 = int((x > 0.0f) ? x : x-1.0f); + float nextx2 = x - nextx1; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + x1 = nextx1; + x2 = nextx2; + + nextx2 += updatePerRow; + while (nextx2 >= 1.0f) { + nextx2 -= 1.0f; + nextx1++; + } + while (nextx2 < 0.0f) { + nextx2 += 1.0f; + nextx1--; + } + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue; + + // left + if (x2 < 0.5f-S) { + I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+S) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // right + else { + I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } + + // horizontally + else if (PIdiv4 <= theta && theta <= 3*PIdiv4) { + + // calculate point P + P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta; + x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY; + + // get coords + int nextx1 = int((x > 0.0f) ? x : x-1.0f); + float nextx2 = x - nextx1; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + x1 = nextx1; + x2 = nextx2; + + nextx2 += updatePerCol; + while (nextx2 >= 1.0f) { + nextx2 -= 1.0f; + nextx1++; + } + while (nextx2 < 0.0f) { + nextx2 += 1.0f; + nextx1--; + } + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue; + + // up + if (x2 < 0.5f-T) { + I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+T) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // down + else { + I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } // end loop col + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end loop detector +} + + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE RAY +template +void CParallelBeamLineKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p) +{ + int iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) return; + + // variables + float32 t, I, P, x, x2; + int iVolumeIndex, row, col, x1; + + // get theta + float32 theta = m_pProjectionGeometry->getProjectionAngle(_iProjection); + bool switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector); + if (switch_t) t = -t; + + // vertically + if (theta <= PIdiv4) { + + float32 sin_theta = sin(theta); + float32 inv_cos_theta = 1.0f / cos(theta); + + // precalculate kernel limits + float32 lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta; + float32 updatePerRow = sin_theta * inv_cos_theta; + float32 inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); + float32 S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow); + + // calculate x for row 0 + P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta; + x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX; + + // get coords + int nextx1 = int((x > 0.0f) ? x : x-1.0f); + float nextx2 = x - nextx1; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + x1 = nextx1; + x2 = nextx2; + + nextx2 += updatePerRow; + while (nextx2 >= 1.0f) { + nextx2 -= 1.0f; + nextx1++; + } + while (nextx2 < 0.0f) { + nextx2 += 1.0f; + nextx1--; + } + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue; + + // left + if (x2 < 0.5f-S) { + I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+S) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // right + else { + I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } + + // horizontally + else if (PIdiv4 <= theta && theta <= 3*PIdiv4) { + + float32 cos_theta = cos(theta); + float32 inv_sin_theta = 1.0f / sin(theta); + + // precalculate kernel limits + float32 lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta; + float32 updatePerCol = cos_theta * inv_sin_theta; + float32 inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); + float32 T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol); + + // calculate point P + P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta; + x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY; + + // get coords + int nextx1 = int((x > 0.0f) ? x : x-1.0f); + float nextx2 = x - nextx1; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + x1 = nextx1; + x2 = nextx2; + + nextx2 += updatePerCol; + while (nextx2 >= 1.0f) { + nextx2 -= 1.0f; + nextx1++; + } + while (nextx2 < 0.0f) { + nextx2 += 1.0f; + nextx1--; + } + + if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue; + + // up + if (x2 < 0.5f-T) { + I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // center + else if (x2 <= 0.5f+T) { + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + } + + // down + else { + I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol; + + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, I); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + } // end loop col + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + +} diff --git a/include/astra/ParallelBeamLinearKernelProjector2D.h b/include/astra/ParallelBeamLinearKernelProjector2D.h new file mode 100644 index 0000000..ac5899e --- /dev/null +++ b/include/astra/ParallelBeamLinearKernelProjector2D.h @@ -0,0 +1,194 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_PARALLELLINEARKERNELPROJECTOR +#define _INC_ASTRA_PARALLELLINEARKERNELPROJECTOR + +#include "ParallelProjectionGeometry2D.h" +#include "Float32Data2D.h" +#include "Projector2D.h" + +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + +namespace astra +{ + +/** This class implements a two-dimensional projector based on a lineary interpolated kernel. + * + * \par XML Configuration + * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.} + * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('linear');\n + * cfg.ProjectionGeometry = proj_geom;\n + * cfg.VolumeGeometry = vol_geom;\n + * proj_id = astra_mex_projector('create'\, cfg);\n + * } + */ +class _AstraExport CParallelBeamLinearKernelProjector2D : public CProjector2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - blobvalues are ok + */ + virtual bool _check(); + +public: + + // type of the projector, needed to register with CProjectorFactory + static std::string type; + + /** Default constructor. + */ + CParallelBeamLinearKernelProjector2D(); + + /** Constructor. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + */ + CParallelBeamLinearKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Destructor, is virtual to show that we are aware subclass destructor are called. + */ + ~CParallelBeamLinearKernelProjector2D(); + + /** Initialize the projector with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the projector. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + * @return initialization successful? + */ + virtual bool initialize(CParallelProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pVolumeGeometry); + + /** Clear this class. + */ + virtual void clear(); + + /** Returns the number of weights required for storage of all weights of one projection. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels. + */ + virtual int getProjectionWeightsCount(int _iProjectionIndex); + + /** Compute the pixel weights for a single ray, from the source to a detector pixel. + * + * @param _iProjectionIndex Index of the projection + * @param _iDetectorIndex Index of the detector pixel + * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements + * of type SPixelWeight. On return, this array contains a list of the index + * and weight for all pixels on the ray. + * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels. + * This number MUST be greater than the total number of pixels on the ray. + * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the + * ray (that have been stored in the list _pWeightedPixels). + */ + virtual void computeSingleRayWeights(int _iProjectionIndex, + int _iDetectorIndex, + SPixelWeight* _pWeightedPixels, + int _iMaxPixelCount, + int& _iStoredPixelCount); + + /** Create a list of detectors that are influenced by point [_iRow, _iCol]. + * + * @param _iRow row of the point + * @param _iCol column of the point + * @return list of SDetector2D structs + */ + virtual std::vector projectPoint(int _iRow, int _iCol); + + + /** Policy-based projection of all rays. This function will calculate each non-zero projection + * weight and use this value for a task provided by the policy object. + * + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void project(Policy& _policy); + + /** Policy-based projection of all rays of a single projection. This function will calculate + * each non-zero projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Which projection should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleProjection(int _iProjection, Policy& _policy); + + /** Policy-based projection of a single ray. This function will calculate each non-zero + * projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Which projection should be projected? + * @param _iDetector Which detector should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy); + + /** Return the type of this projector. + * + * @return identification type of this projector + */ + virtual std::string getType(); + +}; + +//---------------------------------------------------------------------------------------- + +inline std::string CParallelBeamLinearKernelProjector2D::getType() +{ + return type; +} + + +} // namespace astra + + +#endif + diff --git a/include/astra/ParallelBeamLinearKernelProjector2D.inl b/include/astra/ParallelBeamLinearKernelProjector2D.inl new file mode 100644 index 0000000..66b1cb2 --- /dev/null +++ b/include/astra/ParallelBeamLinearKernelProjector2D.inl @@ -0,0 +1,416 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + + + +//---------------------------------------------------------------------------------------- +// PROJECT ALL +template +void CParallelBeamLinearKernelProjector2D::project(Policy& p) +{ + // variables + float32 theta, sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, t; + float32 lengthPerRow, updatePerRow, inv_pixelLengthX; + float32 lengthPerCol, updatePerCol, inv_pixelLengthY; + bool switch_t; + int iAngle, iDetector, iVolumeIndex, iRayIndex; + int row, col, x1; + float32 P,x,x2; + + // loop angles + for (iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) { + + // get theta + theta = m_pProjectionGeometry->getProjectionAngle(iAngle); + switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // precalculate sin, cos, 1/cos + sin_theta = sin(theta); + cos_theta = cos(theta); + inv_cos_theta = 1.0f / cos_theta; + inv_sin_theta = 1.0f / sin_theta; + + // precalculate kernel limits + lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta; + updatePerRow = sin_theta * inv_cos_theta; + inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); + + // precalculate kernel limits + lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta; + updatePerCol = cos_theta * inv_sin_theta; + inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(iDetector); + if (switch_t) { + t = -t; + } + + // vertically + if (theta <= PIdiv4) { + + // calculate x for row 0 + P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta; + x = m_pVolumeGeometry->coordXToColF(P) - 0.5f; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get coords + x1 = int((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerRow; + + // add weights + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, (x2) * lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + + // horizontally + else if (PIdiv4 <= theta && theta <= 3*PIdiv4) { + + // calculate point P + P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta; + x = m_pVolumeGeometry->coordYToRowF(P) - 0.5f; + + // for each row + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get coords + x1 = int((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerCol; + + // add weights + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, x2 * lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end loop detector + } // end loop angles + +} + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE PROJECTION +template +void CParallelBeamLinearKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p) +{ + // variables + float32 theta, sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, t; + float32 lengthPerRow, updatePerRow, inv_pixelLengthX; + float32 lengthPerCol, updatePerCol, inv_pixelLengthY; + bool switch_t; + int iDetector, iVolumeIndex, iRayIndex; + int row, col, x1; + float32 P,x,x2; + + // get theta + theta = m_pProjectionGeometry->getProjectionAngle(_iProjection); + switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // precalculate sin, cos, 1/cos + sin_theta = sin(theta); + cos_theta = cos(theta); + inv_cos_theta = 1.0f / cos_theta; + inv_sin_theta = 1.0f / sin_theta; + + // precalculate kernel limits + lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta; + updatePerRow = sin_theta * inv_cos_theta; + inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); + + // precalculate kernel limits + lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta; + updatePerCol = cos_theta * inv_sin_theta; + inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(iDetector); + if (switch_t) { + t = -t; + } + + // vertically + if (theta <= PIdiv4) { + + // calculate x for row 0 + P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta; + x = m_pVolumeGeometry->coordXToColF(P) - 0.5f; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get coords + x1 = (int)((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerRow; + + // add weights + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, (x2) * lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + + // horizontally + else if (PIdiv4 <= theta && theta <= 3*PIdiv4) { + + // calculate point P + P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta; + x = m_pVolumeGeometry->coordYToRowF(P) - 0.5f; + + // for each row + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get coords + x1 = (int)((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerCol; + + // add weights + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, x2 * lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end loop detector +} + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE RAY +template +void CParallelBeamLinearKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p) +{ + int iVolumeIndex, iRayIndex; + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) return; + + // get theta + float32 theta = m_pProjectionGeometry->getProjectionAngle(_iProjection); + bool switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // get t + float32 t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector); + if (switch_t) { + t = -t; + } + + // vertically + if (theta <= PIdiv4) { + + // precalculate sin, 1/cos + float32 sin_theta = sin(theta); + float32 inv_cos_theta = 1.0f / cos(theta); + + // precalculate kernel limits + float32 lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta; + float32 updatePerRow = sin_theta * inv_cos_theta; + + int row, x1; + float32 P,x,x2; + + // calculate x for row 0 + P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta; + x = m_pVolumeGeometry->coordXToColF(P) - 0.5f; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get coords + x1 = (int)((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerRow; + + // add weights + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, (x2) * lengthPerRow); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + + // horizontally + else if (PIdiv4 <= theta && theta <= 3*PIdiv4) { + + // precalculate cos 1/sin + float32 cos_theta = cos(theta); + float32 inv_sin_theta = 1.0f / sin(theta); + + // precalculate kernel limits + float32 lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta; + float32 updatePerCol = cos_theta * inv_sin_theta; + + int col, x1; + float32 P,x,x2; + + // calculate point P + P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta; + x = m_pVolumeGeometry->coordYToRowF(P) - 0.5f; + + // for each row + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get coords + x1 = (int)((x > 0.0f) ? x : x-1.0f); + x2 = x - x1; + x += updatePerCol; + + // add weights + if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridRowCount()) { + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col); + // POLICY: PIXEL PRIOR + ADD + POSTERIOR + if (p.pixelPrior(iVolumeIndex)) { + p.addWeight(iRayIndex, iVolumeIndex, x2 * lengthPerCol); + p.pixelPosterior(iVolumeIndex); + } + } + } + } + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); +} diff --git a/include/astra/ParallelBeamStripKernelProjector2D.h b/include/astra/ParallelBeamStripKernelProjector2D.h new file mode 100644 index 0000000..de056de --- /dev/null +++ b/include/astra/ParallelBeamStripKernelProjector2D.h @@ -0,0 +1,191 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_PARALLELBEAMSTROKEKERNELPROJECTOR +#define _INC_ASTRA_PARALLELBEAMSTROKEKERNELPROJECTOR + +#include "ParallelProjectionGeometry2D.h" +#include "Float32Data2D.h" +#include "Projector2D.h" + +namespace astra +{ + + +/** This class implements a two-dimensional projector based on a strip based kernel. + * + * \par XML Configuration + * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.} + * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('strip');\n + * cfg.ProjectionGeometry = proj_geom;\n + * cfg.VolumeGeometry = vol_geom;\n + * proj_id = astra_mex_projector('create'\, cfg);\n + * } + */ +class _AstraExport CParallelBeamStripKernelProjector2D : public CProjector2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - blobvalues are ok + */ + virtual bool _check(); + +public: + + // type of the projector, needed to register with CProjectorFactory + static std::string type; + + /** Default constructor. + */ + CParallelBeamStripKernelProjector2D(); + + /** Constructor. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + */ + CParallelBeamStripKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Destructor, is virtual to show that we are aware subclass destructor are called. + */ + ~CParallelBeamStripKernelProjector2D(); + + /** Initialize the projector with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the projector. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + * @return initialization successful? + */ + virtual bool initialize(CParallelProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Clear this class. + */ + virtual void clear(); + + /** Returns the number of weights required for storage of all weights of one projection. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels. + */ + virtual int getProjectionWeightsCount(int _iProjectionIndex); + + /** Compute the pixel weights for a single ray, from the source to a detector pixel. + * + * @param _iProjectionIndex Index of the projection + * @param _iDetectorIndex Index of the detector pixel + * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements + * of type SPixelWeight. On return, this array contains a list of the index + * and weight for all pixels on the ray. + * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels. + * This number MUST be greater than the total number of pixels on the ray. + * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the + * ray (that have been stored in the list _pWeightedPixels). + */ + virtual void computeSingleRayWeights(int _iProjectionIndex, + int _iDetectorIndex, + SPixelWeight* _pWeightedPixels, + int _iMaxPixelCount, + int& _iStoredPixelCount); + + /** Create a list of detectors that are influenced by point [_iRow, _iCol]. + * + * @param _iRow row of the point + * @param _iCol column of the point + * @return list of SDetector2D structs + */ + virtual std::vector projectPoint(int _iRow, int _iCol); + + /** Policy-based projection of all rays. This function will calculate each non-zero projection + * weight and use this value for a task provided by the policy object. + * + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void project(Policy& _policy); + + /** Policy-based projection of all rays of a single projection. This function will calculate + * each non-zero projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Wwhich projection should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleProjection(int _iProjection, Policy& _policy); + + /** Policy-based projection of a single ray. This function will calculate each non-zero + * projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Which projection should be projected? + * @param _iDetector Which detector should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy); + +protected: + + /** Return the type of this projector. + * + * @return identification type of this projector + */ + virtual std::string getType(); + +}; + +//---------------------------------------------------------------------------------------- + +inline std::string CParallelBeamStripKernelProjector2D::getType() +{ + return type; +} + +} // namespace astra + +#endif + diff --git a/include/astra/ParallelBeamStripKernelProjector2D.inl b/include/astra/ParallelBeamStripKernelProjector2D.inl new file mode 100644 index 0000000..c55fa8e --- /dev/null +++ b/include/astra/ParallelBeamStripKernelProjector2D.inl @@ -0,0 +1,739 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + + +//---------------------------------------------------------------------------------------- +// PROJECT ALL +template +void CParallelBeamStripKernelProjector2D::project(Policy& p) +{ + ASTRA_ASSERT(m_bIsInitialized); + + // Some variables + float32 theta, t; + int row, col; + int iAngle; + int iDetector; + float32 res; + float32 PL, PLimitL, PLimitR; + float32 xL, xR, XLimitL, XLimitR; + int x1L,x1R; + float32 x2L, x2R, updateX; + int iVolumeIndex, iRayIndex; + + float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta; + float32 fabs_sin_theta, fabs_cos_theta, fabs_inv_sin_theta, fabs_inv_cos_theta; + float32 PW, PH, DW, inv_PW, inv_PH; + float32 S, T, U, V, inv_4T; + + // loop angles + for (iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) { + + // get values + theta = m_pProjectionGeometry->getProjectionAngle(iAngle); + bool switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // Precalculate sin, cos, 1/cos + sin_theta = sin(theta); + cos_theta = cos(theta); + inv_cos_theta = 1.0f / cos_theta; + inv_sin_theta = 1.0f / sin_theta; + + fabs_sin_theta = (sin_theta < 0.0f) ? -sin_theta : sin_theta; + fabs_cos_theta = (cos_theta < 0.0f) ? -cos_theta : cos_theta; + fabs_inv_cos_theta = (inv_cos_theta < 0.0f) ? -inv_cos_theta : inv_cos_theta; + fabs_inv_sin_theta = (inv_sin_theta < 0.0f) ? -inv_sin_theta : inv_sin_theta; + + // Other precalculations + PW = m_pVolumeGeometry->getPixelLengthX(); + PH = m_pVolumeGeometry->getPixelLengthY(); + DW = m_pProjectionGeometry->getDetectorWidth(); + inv_PW = 1.0f / PW; + inv_PH = 1.0f / PH; + + // [-45?,45?] and [135?,225?] + if (theta < PIdiv4) { + + // Precalculate kernel limits + S = -0.5f * fabs_sin_theta * fabs_inv_cos_theta; + T = -S; + U = 1.0f + S; + V = 1.0f - S; + inv_4T = 0.25f / T; + + updateX = sin_theta * inv_cos_theta; + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(iDetector); + if (switch_t) t = -t; + + // calculate left strip extremes (volume coordinates) + PL = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0) - DW*0.5f) * inv_cos_theta; + PLimitL = PL - 0.5f * fabs_sin_theta * fabs_inv_cos_theta * PH; + PLimitR = PLimitL + DW * inv_cos_theta + PH * fabs_sin_theta * fabs_inv_cos_theta; + + // calculate strip extremes (pixel coordinates) + XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + xR = xL + (DW * inv_cos_theta) * inv_PW; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX; + XLimitR += updateX; + xL += updateX; + xR += updateX; + + // for each affected col + for (col = x1L; col <= x1R; ++col) { + + if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V) res = 1.0f; + else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T; + else if (x2R >= T) res = x2R; + else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S) {} // - 0.0f + else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T; + else if (x2L <= U) res -= x2L; + else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end col loop + + } // end row loop + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end detector loop + + // [45?,135?] and [225?,315?] + // horizontaly + } else { + + // Precalculate kernel limits + S = -0.5f * fabs_cos_theta * fabs_inv_sin_theta; + T = -S; + U = 1.0f + S; + V = 1.0f - S; + inv_4T = 0.25f / T; + + updateX = cos_theta * inv_sin_theta; + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(iDetector); + if (switch_t) t = -t; + + // calculate left strip extremes (volume coordinates) + PL = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0) + DW*0.5f) * inv_sin_theta; + PLimitL = PL + 0.5f * fabs_cos_theta * fabs_inv_sin_theta * PW; + PLimitR = PLimitL - DW * inv_sin_theta - PH * fabs_cos_theta * fabs_inv_sin_theta; + + // calculate strip extremes (pixel coordinates) + XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH; + XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH; + xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH; + xR = xL + (DW * fabs_inv_sin_theta) * inv_PH; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX; + XLimitR += updateX; + xL += updateX; + xR += updateX; + + // for each affected col + for (row = x1L; row <= x1R; ++row) { + + if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V) res = 1.0f; + else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T; + else if (x2R >= T) res = x2R; + else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S) {} // - 0.0f + else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T; + else if (x2L <= U) res -= x2L; + else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end row loop + + } // end col loop + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end detector loop + + + } // end theta switch + + } // end angle loop +} + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE PROJECTION +template +void CParallelBeamStripKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p) +{ + // Some variables + float32 theta, t; + int row, col, iDetector; + float32 res; + float32 PL, PLimitL, PLimitR; + float32 xL, xR, XLimitL, XLimitR; + int x1L,x1R; + float32 x2L, x2R, updateX; + int iVolumeIndex, iRayIndex; + + float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta; + float32 fabs_sin_theta, fabs_cos_theta, fabs_inv_sin_theta, fabs_inv_cos_theta; + float32 PW, PH, DW, inv_PW, inv_PH; + float32 S, T, U, V, inv_4T; + + // get values + theta = m_pProjectionGeometry->getProjectionAngle(_iProjection); + bool switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // Precalculate sin, cos, 1/cos + sin_theta = sin(theta); + cos_theta = cos(theta); + inv_cos_theta = 1.0f / cos_theta; + inv_sin_theta = 1.0f / sin_theta; + + fabs_sin_theta = (sin_theta < 0.0f) ? -sin_theta : sin_theta; + fabs_cos_theta = (cos_theta < 0.0f) ? -cos_theta : cos_theta; + fabs_inv_cos_theta = (inv_cos_theta < 0.0f) ? -inv_cos_theta : inv_cos_theta; + fabs_inv_sin_theta = (inv_sin_theta < 0.0f) ? -inv_sin_theta : inv_sin_theta; + + // Other precalculations + PW = m_pVolumeGeometry->getPixelLengthX(); + PH = m_pVolumeGeometry->getPixelLengthY(); + DW = m_pProjectionGeometry->getDetectorWidth(); + inv_PW = 1.0f / PW; + inv_PH = 1.0f / PH; + + // [-45?,45?] and [135?,225?] + if (theta < PIdiv4) { + + // Precalculate kernel limits + S = -0.5f * fabs_sin_theta * fabs_inv_cos_theta; + T = -S; + U = 1.0f + S; + V = 1.0f - S; + inv_4T = 0.25f / T; + + updateX = sin_theta * inv_cos_theta; + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(iDetector); + if (switch_t) t = -t; + + // calculate left strip extremes (volume coordinates) + PL = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0) - DW*0.5f) * inv_cos_theta; + PLimitL = PL - 0.5f * fabs_sin_theta * fabs_inv_cos_theta * PH; + PLimitR = PLimitL + DW * inv_cos_theta + PH * fabs_sin_theta * fabs_inv_cos_theta; + + // calculate strip extremes (pixel coordinates) + XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + xR = xL + (DW * inv_cos_theta) * inv_PW; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX; + XLimitR += updateX; + xL += updateX; + xR += updateX; + + // for each affected col + for (col = x1L; col <= x1R; ++col) { + + if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V) res = 1.0f; + else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T; + else if (x2R >= T) res = x2R; + else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S) {} // - 0.0f + else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T; + else if (x2L <= U) res -= x2L; + else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end col loop + + } // end row loop + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end detector loop + + // [45?,135?] and [225?,315?] + // horizontaly + } else { + + // Precalculate kernel limits + S = -0.5f * fabs_cos_theta * fabs_inv_sin_theta; + T = -S; + U = 1.0f + S; + V = 1.0f - S; + inv_4T = 0.25f / T; + + updateX = cos_theta * inv_sin_theta; + + // loop detectors + for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) { + + iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) continue; + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(iDetector); + if (switch_t) t = -t; + + // calculate left strip extremes (volume coordinates) + PL = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0) + DW*0.5f) * inv_sin_theta; + PLimitL = PL + 0.5f * fabs_cos_theta * fabs_inv_sin_theta * PW; + PLimitR = PLimitL - DW * inv_sin_theta - PH * fabs_cos_theta * fabs_inv_sin_theta; + + // calculate strip extremes (pixel coordinates) + XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH; + XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH; + xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH; + xR = xL + (DW * fabs_inv_sin_theta) * inv_PH; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX; + XLimitR += updateX; + xL += updateX; + xR += updateX; + + // for each affected col + for (row = x1L; row <= x1R; ++row) { + + if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V) res = 1.0f; + else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T; + else if (x2R >= T) res = x2R; + else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S) {} // - 0.0f + else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T; + else if (x2L <= U) res -= x2L; + else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end row loop + + } // end col loop + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + + } // end detector loop + + } // end theta switch +} + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE RAY +template +void CParallelBeamStripKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p) +{ + int iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector; + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) return; + + // Some variables + float32 theta, t; + int row, col; + float32 res; + float32 PL, PLimitL, PLimitR; + float32 xL, xR, XLimitL, XLimitR; + int x1L,x1R; + float32 x2L, x2R, updateX; + int iVolumeIndex; + + float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta; + float32 fabs_sin_theta, fabs_cos_theta, fabs_inv_sin_theta, fabs_inv_cos_theta; + float32 PW, PH, DW, inv_PW, inv_PH; + float32 S, T, U, V, inv_4T; + + // get values + theta = m_pProjectionGeometry->getProjectionAngle(_iProjection); + bool switch_t = false; + if (theta >= 7*PIdiv4) theta -= 2*PI; + if (theta >= 3*PIdiv4) { + theta -= PI; + switch_t = true; + } + + // Precalculate sin, cos, 1/cos + sin_theta = sin(theta); + cos_theta = cos(theta); + inv_cos_theta = 1.0f / cos_theta; + inv_sin_theta = 1.0f / sin_theta; + + fabs_sin_theta = (sin_theta < 0.0f) ? -sin_theta : sin_theta; + fabs_cos_theta = (cos_theta < 0.0f) ? -cos_theta : cos_theta; + fabs_inv_cos_theta = (inv_cos_theta < 0.0f) ? -inv_cos_theta : inv_cos_theta; + fabs_inv_sin_theta = (inv_sin_theta < 0.0f) ? -inv_sin_theta : inv_sin_theta; + + // Other precalculations + PW = m_pVolumeGeometry->getPixelLengthX(); + PH = m_pVolumeGeometry->getPixelLengthY(); + DW = m_pProjectionGeometry->getDetectorWidth(); + inv_PW = 1.0f / PW; + inv_PH = 1.0f / PH; + + // [-45?,45?] and [135?,225?] + if (theta < PIdiv4) { + + // Precalculate kernel limits + S = -0.5f * fabs_sin_theta * fabs_inv_cos_theta; + T = -S; + U = 1.0f + S; + V = 1.0f - S; + inv_4T = 0.25f / T; + + updateX = sin_theta * inv_cos_theta; + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector); + if (switch_t) t = -t; + + // calculate left strip extremes (volume coordinates) + PL = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0) - DW*0.5f) * inv_cos_theta; + PLimitL = PL - 0.5f * fabs_sin_theta * fabs_inv_cos_theta * PH; + PLimitR = PLimitL + DW * inv_cos_theta + PH * fabs_sin_theta * fabs_inv_cos_theta; + + // calculate strip extremes (pixel coordinates) + XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW; + xR = xL + (DW * inv_cos_theta) * inv_PW; + + // for each row + for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX; + XLimitR += updateX; + xL += updateX; + xR += updateX; + + // for each affected col + for (col = x1L; col <= x1R; ++col) { + + if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V) res = 1.0f; + else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T; + else if (x2R >= T) res = x2R; + else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S) {} // - 0.0f + else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T; + else if (x2L <= U) res -= x2L; + else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end col loop + + } // end row loop + + // [45?,135?] and [225?,315?] + // horizontaly + } else { + + // Precalculate kernel limits + S = -0.5f * fabs_cos_theta * fabs_inv_sin_theta; + T = -S; + U = 1.0f + S; + V = 1.0f - S; + inv_4T = 0.25f / T; + + updateX = cos_theta * inv_sin_theta; + + // get t + t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector); + if (switch_t) t = -t; + + // calculate left strip extremes (volume coordinates) + PL = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0) + DW*0.5f) * inv_sin_theta; + PLimitL = PL + 0.5f * fabs_cos_theta * fabs_inv_sin_theta * PW; + PLimitR = PLimitL - DW * inv_sin_theta - PH * fabs_cos_theta * fabs_inv_sin_theta; + + // calculate strip extremes (pixel coordinates) + XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH; + XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH; + xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH; + xR = xL + (DW * fabs_inv_sin_theta) * inv_PH; + + // for each col + for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) { + + // get strip extremes in column indices + x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f); + x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f); + + // get coords w.r.t leftmost column hit by strip + x2L = xL - x1L; + x2R = xR - x1L; + + // update strip extremes for the next row + XLimitL += updateX; + XLimitR += updateX; + xL += updateX; + xR += updateX; + + // for each affected col + for (row = x1L; row <= x1R; ++row) { + + if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col); + + // POLICY: PIXEL PRIOR + if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // right + if (x2R >= V) res = 1.0f; + else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T; + else if (x2R >= T) res = x2R; + else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // left + if (x2L <= S) {} // - 0.0f + else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T; + else if (x2L <= U) res -= x2L; + else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T; + else { x2L -= 1.0f; x2R -= 1.0f; continue; } + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + + x2L -= 1.0f; + x2R -= 1.0f; + + } // end row loop + + } // end col loop + + } // end theta switch + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); + +} diff --git a/include/astra/ParallelProjectionGeometry2D.h b/include/astra/ParallelProjectionGeometry2D.h new file mode 100644 index 0000000..c91fb4d --- /dev/null +++ b/include/astra/ParallelProjectionGeometry2D.h @@ -0,0 +1,153 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_PARALLELPROJECTIONGEOMETRY2D +#define _INC_ASTRA_PARALLELPROJECTIONGEOMETRY2D + +#include "ProjectionGeometry2D.h" + +namespace astra +{ + +/** + * This class defines a 2D parallel beam projection geometry. + * + * + * This geometry is defined by a number of parameters: + * - The number of detectors (DetCount). + * The distance between the first detector and the projection of the origin \f$O\f$ is equal to + * the distance between the last detector and the projection of \f$O\f$. + * - The width of each detector (detector width). All detectors are equidistant. + * - A list of projection angles (\f$\theta\f$), measured w.r.t. the y-axis of the volume. In Radians. Should lie in the interval \f$[-\frac{\pi}{4},\frac{7\pi}{4}]\f$. + * + * This class provides functionality to convert between detector index and detector offset \f$t\f$. + * + * \par XML Configuration + * \astra_xml_item{DetectorCount, int, Number of detectors for each projection.} + * \astra_xml_item{DetectorWidth, float, Width of each detector.} + * \astra_xml_item{ProjectionAngles, vector of float, projection angles w.r.t. the y-axis of the volume in radians.} + * + * \par MATLAB example + * \astra_code{ + * proj_geom = astra_struct('parallel');\n + * proj_geom.DetectorCount = 512;\n + * proj_geom.DetectorWidth = 1.0;\n + * proj_geom.ProjectionAngles = linspace(0\,pi\,100);\n + * } + */ +class _AstraExport CParallelProjectionGeometry2D : public CProjectionGeometry2D +{ +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the init() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + * + */ + CParallelProjectionGeometry2D(); + + /** Constructor. Create an instance of the CParallelProjectionGeometry2D class. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle. + * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + */ + CParallelProjectionGeometry2D(int _iProjectionAngleCount, + int _iDetectorCount, + float32 _fDetectorWidth, + const float32* _pfProjectionAngles, + const float32* _pfExtraDetectorOffsets = 0); + + /** Copy constructor. + */ + CParallelProjectionGeometry2D(const CParallelProjectionGeometry2D& _projGeom); + + /** Destructor. + */ + ~CParallelProjectionGeometry2D(); + + /** Assignment operator. + */ + CParallelProjectionGeometry2D& operator=(const CParallelProjectionGeometry2D& _other); + + /** Initialize the geometry with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialization. Initializes an instance of the CProjectionGeometry2D class. If the object has been + * initialized before, the object is reinitialized and memory is freed and reallocated if necessary. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle. + * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + */ + bool initialize(int _iProjectionAngleCount, + int _iDetectorCount, + float32 _fDetectorWidth, + const float32* _pfProjectionAngles, + const float32* _pfExtraDetectorOffsets = 0); + + /** Create a hard copy. + */ + virtual CProjectionGeometry2D* clone(); + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(CProjectionGeometry2D*) const; + + /** Returns true if the type of geometry defined in this class is the one specified in _sType. + * + * @param _sType geometry type to compare to. + * @return true if _sType == "parallel". + */ + virtual bool isOfType(const std::string& _sType); + + /** + * Returns a vector describing the direction of a ray belonging to a certain detector, + * the direction is the same for all detectors in one projection + * + * @param _iProjectionIndex index of projection + * @param _iProjectionIndex index of detector + * + * @return a unit vector describing the direction + */ + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex = 0); +}; + +} // namespace astra + +#endif /* _INC_ASTRA_PARALLELPROJECTIONGEOMETRY2D */ diff --git a/include/astra/ParallelProjectionGeometry3D.h b/include/astra/ParallelProjectionGeometry3D.h new file mode 100644 index 0000000..85d0687 --- /dev/null +++ b/include/astra/ParallelProjectionGeometry3D.h @@ -0,0 +1,165 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_PARALLELPROJECTIONGEOMETRY3D +#define _INC_ASTRA_PARALLELPROJECTIONGEOMETRY3D + +#include "ProjectionGeometry3D.h" +#include "ParallelProjectionGeometry2D.h" + +namespace astra +{ + +/** + * This class defines a 3D parallel beam projection geometry. + * + * \par XML Configuration + * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.} + * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.} + * \astra_xml_item{DetectorWidth, float, Width of each detector.} + * \astra_xml_item{DetectorHeight, float, Width of each detector.} + * \astra_xml_item{ProjectionAngles, vector of float, projection angles in radians.} + * + * \par MATLAB example + * \astra_code{ + * proj_geom = astra_struct('parallel');\n + * proj_geom.DetectorRowCount = 512;\n + * proj_geom.DetectorColCount = 512;\n + * proj_geom.DetectorWidth = 1.0;\n + * proj_geom.DetectorHeight = 1.0;\n + * proj_geom.ProjectionAngles = linspace(0,pi,100);\n + * } + */ +class _AstraExport CParallelProjectionGeometry3D : public CProjectionGeometry3D +{ +protected: + +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the initialize() methods before the object can be used. Any use before calling initialize() + * is not allowed, except calling the member function isInitialized(). + */ + CParallelProjectionGeometry3D(); + + /** Constructor. Create an instance of the CParallelProjectionGeometry3D class. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorRowCount Number of rows of detectors. + * @param _iDetectorColCount Number of columns detectors. + * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _fDetectorHeight Height of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles + * are represented in radians and lie in the [0,2pi[ interval. + */ + CParallelProjectionGeometry3D(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + float32 _fDetectorWidth, + float32 _fDetectorHeight, + const float32* _pfProjectionAngles, + const float32* _pfExtraDetectorOffsetsX = NULL, + const float32* _pfExtraDetectorOffsetsY = NULL); + + /** Copy constructor. + */ + CParallelProjectionGeometry3D(const CParallelProjectionGeometry3D& _projGeom); + + /** Destructor. + */ + ~CParallelProjectionGeometry3D(); + + /** Initialize the geometry with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the geometry. If the object has been initialized before, the object is reinitialized + * and memory is freed and reallocated if necessary. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorRowCount Number of rows of detectors. + * @param _iDetectorColCount Number of columns detectors. + * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _fDetectorHeight Height of a detector cell, in unit lengths. All detector cells are assumed to have equal height. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles + * are represented in radians and lie in the [0,2pi[ interval. + */ + bool initialize(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + float32 _fDetectorWidth, + float32 _fDetectorHeight, + const float32* _pfProjectionAngles, + const float32* _pfExtraDetectorOffsetsX = NULL, + const float32* _pfExtraDetectorOffsetsY = NULL); + + /** Create a hard copy. + */ + virtual CProjectionGeometry3D* clone() const; + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(const CProjectionGeometry3D*) const; + + /** Returns true if the type of geometry defined in this class is the one specified in _sType. + * + * @param _sType geometry type to compare to. + * @return true if _sType == "parallel". + */ + virtual bool isOfType(const std::string& _sType) const; + + /** Turn this object into an XML object. + * + * @param _sNode The XML object to fill. + */ + virtual void toXML(XMLNode* _sNode) const; + + /** + * Returns a vector giving the projection direction for a projection and detector index + */ + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const; + + /** + * Creates (= allocates) a 2D projection geometry used when projecting one slice using a 2D projector + * + * @return the 2D geometry, this pointer needs to be delete-ed after use. + */ + CParallelProjectionGeometry2D * createProjectionGeometry2D() const; + +}; + +} // namespace astra + +#endif /* _INC_ASTRA_PARALLELPROJECTIONGEOMETRY3D */ diff --git a/include/astra/ParallelVecProjectionGeometry3D.h b/include/astra/ParallelVecProjectionGeometry3D.h new file mode 100644 index 0000000..0b4a766 --- /dev/null +++ b/include/astra/ParallelVecProjectionGeometry3D.h @@ -0,0 +1,157 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_PARALLELVECPROJECTIONGEOMETRY3D +#define _INC_ASTRA_PARALLELVECPROJECTIONGEOMETRY3D + +#include "ProjectionGeometry3D.h" +#include "../cuda/3d/dims3d.h" + +namespace astra +{ + +/** + * This class defines a 3D parallel beam projection geometry. + * + * \par XML Configuration + * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.} + * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.} + * + * \par MATLAB example + * \astra_code{ + * proj_geom = astra_struct('parallel3d_vec');\n + * proj_geom.DetectorRowCount = 512;\n + * proj_geom.DetectorColCount = 512;\n + * proj_geom.Vectors = V;\n + * } + * + * \par Vectors + * Vectors is a matrix containing the actual geometry. Each row corresponds + * to a single projection, and consists of: + * ( rayX, rayY, rayZ, dX, dY, dZ, uX, uY, uZ, vX, vY, vZ ) + * ray: the ray direction + * d : the corner of the detector + * u : the vector from detector pixel (0,0) to (0,1) + * v : the vector from detector pixel (0,0) to (1,0) + */ +class _AstraExport CParallelVecProjectionGeometry3D : public CProjectionGeometry3D +{ +protected: + + SPar3DProjection *m_pProjectionAngles; + +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the initialize() methods before the object can be used. Any use before calling initialize() + * is not allowed, except calling the member function isInitialized(). + */ + CParallelVecProjectionGeometry3D(); + + /** Constructor. Create an instance of the CParallelProjectionGeometry3D class. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorRowCount Number of rows of detectors. + * @param _iDetectorColCount Number of columns detectors. + * @param _pProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + */ + CParallelVecProjectionGeometry3D(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + const SPar3DProjection* _pProjectionAngles); + + /** Copy constructor. + */ + CParallelVecProjectionGeometry3D(const CParallelVecProjectionGeometry3D& _projGeom); + + /** Destructor. + */ + ~CParallelVecProjectionGeometry3D(); + + /** Initialize the geometry with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the geometry. If the object has been initialized before, the object is reinitialized + * and memory is freed and reallocated if necessary. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorRowCount Number of rows of detectors. + * @param _iDetectorColCount Number of columns detectors. + * @param _pProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + */ + bool initialize(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + const SPar3DProjection* _pProjectionAngles); + + + virtual bool _check(); + + /** Create a hard copy. + */ + virtual CProjectionGeometry3D* clone() const; + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(const CProjectionGeometry3D*) const; + + /** Returns true if the type of geometry defined in this class is the one specified in _sType. + * + * @param _sType geometry type to compare to. + * @return true if _sType == "parallel3d_vec". + */ + virtual bool isOfType(const std::string& _sType) const; + + /** Turn this object into an XML object. + * + * @param _sNode The XML object to fill. + */ + virtual void toXML(XMLNode* _sNode) const; + + /** + * Returns a vector giving the projection direction for a projection and detector index + */ + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const; + + + const SPar3DProjection* getProjectionVectors() const { return m_pProjectionAngles; } + + +}; + +} // namespace astra + +#endif /* _INC_ASTRA_PARALLELVECPROJECTIONGEOMETRY3D */ diff --git a/include/astra/PlatformDepSystemCode.h b/include/astra/PlatformDepSystemCode.h new file mode 100644 index 0000000..1e254b4 --- /dev/null +++ b/include/astra/PlatformDepSystemCode.h @@ -0,0 +1,83 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef PLATFORMDEPSYSTEMCODE_H +#define PLATFORMDEPSYSTEMCODE_H + +#include + +#ifndef _WIN32 +#include +#endif + +namespace astra +{ + +#ifdef _WIN32 + typedef __int64 int64; +#else + typedef int64_t int64; +#endif + +class CPlatformDepSystemCode +{ +public: + + /** + * Clock with resolution of 1 ms. Windows implementation will return number of ms since system start, + * but this is not a requirement for the implementation. Just as long as the subtraction of two acquired + * values will result in a time interval in ms. + * + * @return a value that increases with 1 every ms + */ + static unsigned long getMSCount(); + + /** + * fseek variant that works with 64 bit ints. + * + * @param _pStream file handler of file in which needs to be seek-ed + * @param _iOffset 64 bit int telling the new offset in the file + * @param _iOrigin typical fseek directive telling how _iOffset needs to be interpreted (SEEK_SET, ...) + * + * @return 0 if successful + */ + static int fseek64(FILE * _pStream, astra::int64 _iOffset, int _iOrigin); + + /** + * 64-bit ftell variant + * + * @param _pStream file handle + * + * @return the position in the file + */ + static astra::int64 ftell64(FILE * _pStream); +}; + +} + +#endif /* PLATFORMDEPSYSTEMCODE_H */ diff --git a/include/astra/ProjectionGeometry2D.h b/include/astra/ProjectionGeometry2D.h new file mode 100644 index 0000000..bcaee7a --- /dev/null +++ b/include/astra/ProjectionGeometry2D.h @@ -0,0 +1,373 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_PROJECTIONGEOMETRY2D +#define _INC_ASTRA_PROJECTIONGEOMETRY2D + +#include "Globals.h" +#include "Config.h" +#include "Vector3D.h" + +#include +#include +#include + +namespace astra +{ + +/** + * This abstract base class defines the projection geometry. + * It has a number of data fields, such as width of detector + * pixels, projection angles, number of detector pixels and object offsets + * for every projection angle. + */ +class _AstraExport CProjectionGeometry2D +{ + +protected: + + bool m_bInitialized; ///< Has the object been intialized? + + /** Number of projection angles + */ + int m_iProjectionAngleCount; + + /** Number of detectors, i.e., the number of detector measurements for each projection angle. + */ + int m_iDetectorCount; + + /** Width of a detector pixel, i.e., the distance between projected rays (or width of projected strips). + */ + float32 m_fDetectorWidth; + + /** An array of m_iProjectionAngleCount elements containing an extra detector offset for each projection. + */ + float32* m_pfExtraDetectorOffset; + + /** Dynamically allocated array of projection angles. All angles are represented in radians and lie in + * the [0,2pi[ interval. + */ + float32* m_pfProjectionAngles; + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the init() methods before the object can be used. Any use before calling init() is not + * allowed, except calling the member function isInitialized(). + * + */ + CProjectionGeometry2D(); + + /** Constructor. Create an instance of the CProjectionGeometry2D class. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle. + * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + * All angles are represented in radians. + */ + CProjectionGeometry2D(int _iProjectionAngleCount, + int _iDetectorCount, + float32 _fDetectorWidth, + const float32* _pfProjectionAngles, + const float32* _pfExtraDetectorOffsets = 0); + + /** Copy constructor. + */ + CProjectionGeometry2D(const CProjectionGeometry2D& _projGeom); + + /** Check variable values. + */ + bool _check(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + * Should only be used by constructors. Otherwise use the clear() function. + */ + void _clear(); + + /** Initialization. Initializes an instance of the CProjectionGeometry2D class. If the object has been + * initialized before, the object is reinitialized and memory is freed and reallocated if necessary. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle. + * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. + */ + bool _initialize(int _iProjectionAngleCount, + int _iDetectorCount, + float32 _fDetectorWidth, + const float32* _pfProjectionAngles, + const float32* _pfExtraDetectorOffsets = 0); + +public: + + /** Destructor + */ + virtual ~CProjectionGeometry2D(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + */ + virtual void clear(); + + /** Create a hard copy. + */ + virtual CProjectionGeometry2D* clone() = 0; + + /** Initialize the geometry with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Get the initialization state of the object. + * + * @return true iff the object has been initialized + */ + bool isInitialized() const; + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(CProjectionGeometry2D*) const = 0; + + /** Get the number of projection angles. + * + * @return Number of projection angles + */ + int getProjectionAngleCount() const; + + /** Get the number of detectors. + * + * @return Number of detectors, i.e., the number of detector measurements for each projection angle. + */ + int getDetectorCount() const; + + /** Get the width of a detector. + * + * @return Width of a detector, in unit lengths + */ + float32 getDetectorWidth() const; + + /** Get a projection angle, given by its index. The angle is represented in Radians. + * + * @return Projection angle with index _iProjectionIndex + */ + float32 getProjectionAngle(int _iProjectionIndex) const; + + /** Returns a buffer containing all projection angles. The element count of the buffer is equal + * to the number given by getProjectionAngleCount. + * + * The angles are in radians. + * + * @return Pointer to buffer containing the angles. + */ + const float32* getProjectionAngles() const; + + /** Get a projection angle, given by its index. The angle is represented in degrees. + * + * @return Projection angle with index _iProjectionIndex + */ + float32 getProjectionAngleDegrees(int _iProjectionIndex) const; + + float32 getExtraDetectorOffset(int iAngle) const; + const float32* getExtraDetectorOffset() const { return m_pfExtraDetectorOffset; } + + /** Get the index coordinate of a point on a detector array. + * + * @param _fOffset distance between the center of the detector array and a certain point + * @return the location of the point in index coordinates (still float, not rounded) + */ + virtual float32 detectorOffsetToIndexFloat(float32 _fOffset) const; + + /** Get the index coordinate of a point on a detector array. + * + * @param _fOffset distance between the center of the detector array and a certain point + * @return the index of the detector that is hit, -1 if detector array isn't hit. + */ + virtual int detectorOffsetToIndex(float32 _fOffset) const; + + /** Get the offset of a detector based on its index coordinate. + * + * @param _iIndex the index of the detector. + * @return the offset from the center of the detector array. + */ + virtual float32 indexToDetectorOffset(int _iIndex) const; + + /** Get the angle and detector index of a sinogram pixel + * + * @param _iIndex the index of the detector pixel in the sinogram. + * @param _iAngleIndex output: index of angle + * @param _iDetectorIndex output: index of detector + */ + virtual void indexToAngleDetectorIndex(int _iIndex, int& _iAngleIndex, int& _iDetectorIndex) const; + + /** Get the value for t and theta, based upon the row and column index. + * + * @param _iRow row index + * @param _iColumn column index + * @param _fT output: value of t + * @param _fTheta output: value of theta, always lies within the [0,pi[ interval. + */ + virtual void getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const; + + /** Returns true if the type of geometry defined in this class is the one specified in _sType. + * + * @param _sType geometry type to compare to. + * @return true if the type of geometry defined in this class is the one specified in _sType. + */ + virtual bool isOfType(const std::string& _sType) = 0; + + /** + * Returns a vector describing the direction of a ray belonging to a certain detector + * + * @param _iProjectionIndex index of projection + * @param _iProjectionIndex index of detector + * + * @return a unit vector describing the direction + */ + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) = 0; + + + //< For Config unused argument checking + ConfigCheckData* configCheckData; + friend class ConfigStackCheck; +}; + + + +//---------------------------------------------------------------------------------------- +// Inline member functions +//---------------------------------------------------------------------------------------- + + +inline float32 CProjectionGeometry2D::getExtraDetectorOffset(int _iAngle) const +{ + return m_pfExtraDetectorOffset ? m_pfExtraDetectorOffset[_iAngle] : 0.0f; +} + + +// Get the initialization state. +inline bool CProjectionGeometry2D::isInitialized() const +{ + return m_bInitialized; +} + + +// Get the number of detectors. +inline int CProjectionGeometry2D::getDetectorCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iDetectorCount; +} + +// Get the width of a single detector (in unit lengths). +inline float32 CProjectionGeometry2D::getDetectorWidth() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fDetectorWidth; +} + +// Get the number of projection angles. +inline int CProjectionGeometry2D::getProjectionAngleCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iProjectionAngleCount; +} + +// Get pointer to buffer used to store projection angles. +inline const float32* CProjectionGeometry2D::getProjectionAngles() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_pfProjectionAngles; +} + +// Get a projection angle, represented in Radians. +inline float32 CProjectionGeometry2D::getProjectionAngle(int _iProjectionIndex) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iProjectionIndex >= 0); + ASTRA_ASSERT(_iProjectionIndex < m_iProjectionAngleCount); + + return m_pfProjectionAngles[_iProjectionIndex]; +} + +// Get a projection angle, represented in degrees. +inline float32 CProjectionGeometry2D::getProjectionAngleDegrees(int _iProjectionIndex) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iProjectionIndex >= 0); + ASTRA_ASSERT(_iProjectionIndex < m_iProjectionAngleCount); + + return (m_pfProjectionAngles[_iProjectionIndex] * 180.0f / PI32); +} + +// Get T and Theta +inline void CProjectionGeometry2D::getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const +{ + ASTRA_ASSERT(m_bInitialized); + _fT = indexToDetectorOffset(_iColumn); + _fTheta = getProjectionAngle(_iRow); + if (PI <= _fTheta) { + _fTheta -= PI; + _fT = -_fT; + } +} + +// detector offset -> detector index +inline int CProjectionGeometry2D::detectorOffsetToIndex(float32 _fOffset) const +{ + int res = (int)(detectorOffsetToIndexFloat(_fOffset) + 0.5f); + return (res > 0 && res <= m_iDetectorCount) ? res : -1; +} + +// detector offset -> detector index (float) +inline float32 CProjectionGeometry2D::detectorOffsetToIndexFloat(float32 _fOffset) const +{ + return (_fOffset / m_fDetectorWidth) + ((m_iDetectorCount-1.0f) * 0.5f); +} + +// detector index -> detector offset +inline float32 CProjectionGeometry2D::indexToDetectorOffset(int _iIndex) const +{ + return (_iIndex - (m_iDetectorCount-1.0f) * 0.5f) * m_fDetectorWidth; +} + +// sinogram index -> angle and detecor index +inline void CProjectionGeometry2D::indexToAngleDetectorIndex(int _iIndex, int& _iAngleIndex, int& _iDetectorIndex) const +{ + _iAngleIndex = _iIndex / m_iDetectorCount; + _iDetectorIndex = _iIndex % m_iDetectorCount; +} + +} // end namespace astra + +#endif /* _INC_ASTRA_PROJECTIONGEOMETRY2D */ diff --git a/include/astra/ProjectionGeometry3D.h b/include/astra/ProjectionGeometry3D.h new file mode 100644 index 0000000..0deffa6 --- /dev/null +++ b/include/astra/ProjectionGeometry3D.h @@ -0,0 +1,589 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_PROJECTIONGEOMETRY3D +#define _INC_ASTRA_PROJECTIONGEOMETRY3D + +#include "Globals.h" +#include "Config.h" +#include "Vector3D.h" + +#include +#include +#include + +namespace astra +{ + +class XMLNode; + +/** + * This class defines the interface for each 3D projection geometry. + * It has a number of data fields, such as width and height of detector + * pixels, projection angles and number of rows and columns of detector pixels. + * + * \par XML Configuration + * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.} + * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.} + * \astra_xml_item{DetectorWidth, float, Width of each detector.} + * \astra_xml_item{DetectorHeight, float, Width of each detector.} + * \astra_xml_item{ProjectionAngles, vector of float, projection angles in radians.} + */ +class _AstraExport CProjectionGeometry3D +{ + +protected: + + /** Has the object been intialized with acceptable values? + */ + bool m_bInitialized; + + /** Number of projection angles. + */ + int m_iProjectionAngleCount; + + /** Number of rows of detectors. + */ + int m_iDetectorRowCount; + + /** Number of columns of detectors. + */ + int m_iDetectorColCount; + + /** Total number of detectors. + */ + int m_iDetectorTotCount; + + /** The x-distance between projected rays on the detector plate (or width of projected strips). + */ + float32 m_fDetectorSpacingX; + + /** The y-distance between projected rays on the detector plate (or height of projected strips). + */ + float32 m_fDetectorSpacingY; + + /** Dynamically allocated array of projection angles. All angles are represented in radians and lie in + * the [0,2pi[ interval. + */ + float32* m_pfProjectionAngles; + + /** Dynamically allocated array of vectors that represents the amount by which an image has been shifted after + * projection. Each projection image has a 2 shifts associated with it, one x-translation and y-translation + */ + float32* m_pfExtraDetectorOffsetsX; + float32* m_pfExtraDetectorOffsetsY; + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the initialize() methods before the object can be used. Any use before calling initialize() + * is not allowed, except calling the member function isInitialized(). + * + */ + CProjectionGeometry3D(); + + /** Constructor. Create an instance of the CProjectionGeometry3D class. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorRowCount Number of rows of detectors. + * @param _iDetectorColCount Number of columns detectors. + * @param _fDetectorSpacingX Spacing between the detector points on the X-axis, in unit lengths. Assumed to be constant throughout the entire detector plate. + * @param _fDetectorSpacingY Spacing between the detector points on the Y-axis, in unit lengths. Assumed to be constant throughout the entire detector plate. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles + * are represented in radians and lie in the [0,2pi[ interval. + */ + CProjectionGeometry3D(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + float32 _fDetectorSpacingX, + float32 _fDetectorSpacingY, + const float32* _pfProjectionAngles, + const float32* _pfExtraDetectorOffsetsX = NULL, + const float32* _pfExtraDetectorOffsetsY = NULL); + + /** Copy constructor. + */ + CProjectionGeometry3D(const CProjectionGeometry3D& _projGeom); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - number of rows and columns is larger than zero + * - detector spacing is larger than zero + * - number of angles is larger than zero + * - (autofix) each angle lies in [0,2pi[ + */ + bool _check(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + * Should only be used by constructors. Otherwise use the clear() function. + */ + void _clear(); + + /** Initialize the geometry. If the object has been initialized before, the object is reinitialized + * and memory is freed and reallocated if necessary. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorRowCount Number of rows of detectors. + * @param _iDetectorColCount Number of columns detectors. + * @param _fDetectorSpacingX Spacing between the detector points on the X-axis, in unit lengths. Assumed to be constant throughout the entire detector plate. + * @param _fDetectorSpacingY Spacing between the detector points on the Y-axis, in unit lengths. Assumed to be constant throughout the entire detector plate. + * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles + * are represented in radians and lie in the [0,2pi[ interval. + */ + bool _initialize(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + float32 _fDetectorSpacingX, + float32 _fDetectorSpacingY, + const float32* _pfProjectionAngles, + const float32* _pfExtraDetectorOffsetsX = NULL, + const float32* _pfExtraDetectorOffsetsY = NULL); + +public: + + /** Destructor + */ + virtual ~CProjectionGeometry3D(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + */ + virtual void clear(); + + /** Create a hard copy. + */ + virtual CProjectionGeometry3D* clone() const = 0; + + /** Initialize the geometry with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Get the initialization state of the object. + * + * @return true iff the object has been initialized + */ + bool isInitialized() const; + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(const CProjectionGeometry3D *) const = 0; + + /** Get the number of projections. + * + * @return Number of projections + */ + int getProjectionCount() const; + + /** Get the number of rows of detectors. + * + * @return Number of rows of detectors. + */ + int getDetectorRowCount() const; + + /** Get the number of columns of detectors. + * + * @return Number of columns of detectors. + */ + int getDetectorColCount() const; + + /** Get the total number of detectors. + * + * @return Total number of detectors. + */ + int getDetectorTotCount() const; + + /** Get the width of a detector. + * + * @return Width of a detector, in unit lengths + */ + float32 getDetectorSpacingX() const; + + /** Get the height of a detector. + * + * @return Height of a detector, in unit lengths + */ + float32 getDetectorSpacingY() const; + + /** Get a projection angle, given by its index. The angle is represented in Radians. + * + * @return Projection angle with index _iProjectionIndex + */ + float32 getProjectionAngle(int _iProjectionIndex) const; + + /** Get a projection angle, given by its index. The angle is represented in degrees. + * + * @return Projection angle with index _iProjectionIndex + */ +// float32 getProjectionAngleDegrees(int _iProjectionIndex) const; + + /** Returns a buffer containing all projection angles. The element count of the buffer is equal + * to the number given by getProjectionAngleCount. + * + * The angles are in radians. + * + * @return Pointer to buffer containing the angles. + */ + const float32* getProjectionAngles() const; + + const float32* getExtraDetectorOffsetsX() const; + + const float32* getExtraDetectorOffsetsY() const; + + float32 getExtraDetectorOffsetX(int _iProjectionIndex) const; + + float32 getExtraDetectorOffsetY(int _iProjectionIndex) const; + + AstraError setExtraDetectorOffsetsX(float32* _pfExtraDetectorOffsetsX); + + AstraError setExtraDetectorOffsetsY(float32* _pfExtraDetectorOffsetsY); + + /** Get the column index coordinate of a point on a detector array. + * + * @param _fOffsetX Distance between the center of the detector array and a certain point (both on the X-axis). + * @return The location of the point in index X-coordinates (still float, not rounded) + */ + virtual float32 detectorOffsetXToColIndexFloat(float32 _fOffsetX) const; + + /** Get the row index coordinate of a point on a detector array. + * + * @param _fOffsetY Distance between the center of the detector array and a certain point (both on the Y-axis). + * @return The location of the point in index Y-coordinates (still float, not rounded) + */ + virtual float32 detectorOffsetYToRowIndexFloat(float32 _fOffsetY) const; + + /** Get the offset of a detector on the X-axis based on its index coordinate. + * + * @param _iIndex the index of the detector. + * @return the offset from the center of the detector array on the X-axis. + */ + virtual float32 indexToDetectorOffsetX(int _iIndex) const; + + /** Get the offset of a detector on the Y-axis based on its index coordinate. + * + * @param _iIndex the index of the detector. + * @return the offset from the center of the detector array on the Y-axis. + */ + virtual float32 indexToDetectorOffsetY(int _iIndex) const; + + /** Get the offset of a detector on the X-axis based on its column index coordinate. + * + * @param _iIndex the index of the detector. + * @return the offset from the center of the detector array on the X-axis. + */ + virtual float32 colIndexToDetectorOffsetX(int _iIndex) const; + + /** Get the offset of a detector on the Y-axis based on its row index coordinate. + * + * @param _iIndex the index of the detector. + * @return the offset from the center of the detector array on the Y-axis. + */ + virtual float32 rowIndexToDetectorOffsetY(int _iIndex) const; + + /** Get the row and column index of a detector based on its index. + * + * @param _iDetectorIndex in: the index of the detector. + * @param _iDetectorRow out: the row index of the detector. + * @param _iDetectorCol out: the column index of the detector. + */ + virtual void detectorIndexToRowCol(int _iDetectorIndex, int& _iDetectorRow, int& _iDetectorCol) const; + + /** Get the angle and detector index of a detector + * + * @param _iIndex the index of the detector. + * @param _iAngleIndex output: index of angle + * @param _iDetectorIndex output: index of dectecor + */ + virtual void indexToAngleDetectorIndex(int _iIndex, int& _iAngleIndex, int& _iDetectorIndex) const; + + /** Returns true if the type of geometry defined in this class is the one specified in _sType. + * + * @param _sType geometry type to compare to. + * @return true if the type of geometry defined in this class is the one specified in _sType. + */ + virtual bool isOfType(const std::string& _sType) const = 0; + + /** Turn this object into an XML object. + * + * @param _sNode The XML object to fill. + */ + virtual void toXML(XMLNode* _sNode) const = 0; + + /** + * Returns a vector giving the projection direction for a projection and detector index + */ + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const = 0; + + + //< For Config unused argument checking + ConfigCheckData* configCheckData; + friend class ConfigStackCheck; +}; + + + +//---------------------------------------------------------------------------------------- +// Inline member functions +//---------------------------------------------------------------------------------------- +// Get the initialization state. +inline bool CProjectionGeometry3D::isInitialized() const +{ + return m_bInitialized; +} + +//---------------------------------------------------------------------------------------- +// Get the number of detectors. +inline int CProjectionGeometry3D::getDetectorRowCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iDetectorRowCount; +} + +//---------------------------------------------------------------------------------------- +// Get the number of detectors. +inline int CProjectionGeometry3D::getDetectorColCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iDetectorColCount; +} + +//---------------------------------------------------------------------------------------- +// Get the number of detectors. +inline int CProjectionGeometry3D::getDetectorTotCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iDetectorTotCount; +} + +//---------------------------------------------------------------------------------------- +// Get the width of a single detector (in unit lengths). +inline float32 CProjectionGeometry3D::getDetectorSpacingX() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fDetectorSpacingX; +} +//---------------------------------------------------------------------------------------- +// Get the width of a single detector (in unit lengths). +inline float32 CProjectionGeometry3D::getDetectorSpacingY() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fDetectorSpacingY; +} + +//---------------------------------------------------------------------------------------- +// Get the number of projection angles. +inline int CProjectionGeometry3D::getProjectionCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iProjectionAngleCount; +} + +//---------------------------------------------------------------------------------------- +// Get a projection angle, represented in Radians. +inline float32 CProjectionGeometry3D::getProjectionAngle(int _iProjectionIndex) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iProjectionIndex >= 0); + ASTRA_ASSERT(_iProjectionIndex < m_iProjectionAngleCount); + + return m_pfProjectionAngles[_iProjectionIndex]; +} + +/* +//---------------------------------------------------------------------------------------- +// Get a projection angle, represented in degrees. +inline float32 CProjectionGeometry3D::getProjectionAngleDegrees(int _iProjectionIndex) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iProjectionIndex >= 0); + ASTRA_ASSERT(_iProjectionIndex < m_iProjectionAngleCount); + + return (m_pfProjectionAngles[_iProjectionIndex] * 180.0f / PI32); +} +*/ + + +//---------------------------------------------------------------------------------------- +// Get pointer to buffer used to store projection angles. +inline const float32* CProjectionGeometry3D::getProjectionAngles() const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + + return m_pfProjectionAngles; +} + + +//---------------------------------------------------------------------------------------- +// Get pointer to buffer used to store x-translations of the projection images. +inline const float32* CProjectionGeometry3D::getExtraDetectorOffsetsX() const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + + return m_pfExtraDetectorOffsetsX; +} + +//---------------------------------------------------------------------------------------- +// Get pointer to buffer used to store y-translations of the projection images. +inline const float32* CProjectionGeometry3D::getExtraDetectorOffsetsY() const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + + return m_pfExtraDetectorOffsetsY; +} +//---------------------------------------------------------------------------------------- +// Get the x-translation of a specific projection image. +inline float32 CProjectionGeometry3D::getExtraDetectorOffsetX(int _iProjectionIndex) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + + return m_pfExtraDetectorOffsetsX[_iProjectionIndex]; +} + +//---------------------------------------------------------------------------------------- +// Get the y-translation of a specific projection image. +inline float32 CProjectionGeometry3D::getExtraDetectorOffsetY(int _iProjectionIndex) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + + return m_pfExtraDetectorOffsetsX[_iProjectionIndex]; +} +//---------------------------------------------------------------------------------------- +// detector offset X -> detector column index (float) +inline float32 CProjectionGeometry3D::detectorOffsetXToColIndexFloat(float32 _fOffsetX) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + + return (_fOffsetX / m_fDetectorSpacingX) + ((m_iDetectorColCount-1.0f) / 2.0f); +} + +//---------------------------------------------------------------------------------------- +// detector offset Y -> detector row index (float) +inline float32 CProjectionGeometry3D::detectorOffsetYToRowIndexFloat(float32 _fOffsetY) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + + return (_fOffsetY / m_fDetectorSpacingY) + ((m_iDetectorRowCount-1.0f) / 2.0f); +} + +//---------------------------------------------------------------------------------------- +// detector index -> detector offset X +inline float32 CProjectionGeometry3D::indexToDetectorOffsetX(int _iIndex) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iIndex >= 0); + ASTRA_ASSERT(_iIndex < m_iDetectorTotCount); + + _iIndex = _iIndex % m_iDetectorColCount; + return (_iIndex - (m_iDetectorColCount-1.0f) / 2.0f) * m_fDetectorSpacingX; +} + +//---------------------------------------------------------------------------------------- +// detector index -> detector offset Y +inline float32 CProjectionGeometry3D::indexToDetectorOffsetY(int _iIndex) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iIndex >= 0); + ASTRA_ASSERT(_iIndex < m_iDetectorTotCount); + + _iIndex = _iIndex / m_iDetectorColCount; + return -(_iIndex - (m_iDetectorRowCount-1.0f) / 2.0f) * m_fDetectorSpacingY; +} + +//---------------------------------------------------------------------------------------- +// detector index -> detector offset X +inline float32 CProjectionGeometry3D::colIndexToDetectorOffsetX(int _iIndex) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iIndex >= 0); + ASTRA_ASSERT(_iIndex < m_iDetectorColCount); + + return (_iIndex - (m_iDetectorColCount-1.0f) / 2.0f) * m_fDetectorSpacingX; +} + +//---------------------------------------------------------------------------------------- +// detector index -> detector offset Y +inline float32 CProjectionGeometry3D::rowIndexToDetectorOffsetY(int _iIndex) const +{ + // basic checks + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iIndex >= 0); + ASTRA_ASSERT(_iIndex < m_iDetectorRowCount); + + return (_iIndex - (m_iDetectorRowCount-1.0f) / 2.0f) * m_fDetectorSpacingY; +} + +//---------------------------------------------------------------------------------------- +// detector index -> row index & column index +inline void CProjectionGeometry3D::detectorIndexToRowCol(int _iDetectorIndex, int& _iDetectorRow, int& _iDetectorCol) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iDetectorIndex >= 0); + ASTRA_ASSERT(_iDetectorIndex < m_iDetectorTotCount); + + _iDetectorRow = _iDetectorIndex / m_iDetectorColCount; + _iDetectorCol = _iDetectorIndex % m_iDetectorColCount; +} + +//---------------------------------------------------------------------------------------- +inline void CProjectionGeometry3D::indexToAngleDetectorIndex(int _iIndex, int& _iAngleIndex, int& _iDetectorIndex) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iIndex >= 0); + ASTRA_ASSERT(_iIndex < m_iDetectorTotCount * m_iProjectionAngleCount); + +// int det_row = _iIndex / (m_iDetectorColCount*m_iProjectionAngleCount); +// int det_col = _iIndex % m_iDetectorColCount; +// +// _iAngleIndex = _iIndex % (m_iDetectorColCount*m_iProjectionAngleCount) / m_iDetectorColCount; +// _iDetectorIndex = det_row * m_iDetectorColCount + det_col; + + _iAngleIndex = (_iIndex % (m_iDetectorColCount*m_iProjectionAngleCount)) / m_iDetectorColCount; + _iDetectorIndex = _iIndex / m_iProjectionAngleCount + (_iIndex % m_iDetectorColCount); + +} + +//---------------------------------------------------------------------------------------- + +} // end namespace astra + +#endif /* _INC_ASTRA_PROJECTIONGEOMETRY2D */ diff --git a/include/astra/Projector2D.h b/include/astra/Projector2D.h new file mode 100644 index 0000000..a359aba --- /dev/null +++ b/include/astra/Projector2D.h @@ -0,0 +1,204 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef INC_ASTRA_PROJECTOR2D +#define INC_ASTRA_PROJECTOR2D + +#include +#include + +#include "Globals.h" +#include "Config.h" +#include "Float32Data2D.h" +#include "ParallelProjectionGeometry2D.h" +#include "ProjectionGeometry2D.h" +#include "VolumeGeometry2D.h" + +namespace astra +{ + +class CSparseMatrix; + + +/** This is a base interface class for a two-dimensional projector. Each subclass should at least + * implement the core projection functions computeProjectionRayWeights and projectPoint. For + * extra efficiency one might also like to overwrite other functions such as computeProjectionRayWeights, + * computeRayForwardProj_ART, ... + * + * \par XML Configuration + * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.} + * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.} + */ +class _AstraExport CProjector2D +{ + +protected: + CProjectionGeometry2D* m_pProjectionGeometry; ///< Used projection geometry + CVolumeGeometry2D* m_pVolumeGeometry; ///< Used volume geometry + bool m_bIsInitialized; ///< Has this class been initialized? + + /** Default Constructor. + */ + CProjector2D(); + + /** Constructor. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pVolumeGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + */ + CProjector2D(CProjectionGeometry2D* _pProjectionGeometry, CVolumeGeometry2D* _pVolumeGeometry); + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + */ + virtual bool _check(); + +public: + + /** Destructor. + */ + virtual ~CProjector2D(); + + /** Clear this class. + */ + virtual void clear(); + + /** Initialize the projector with a config object. + * This function does not set m_bInitialized to true. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Fetch the Projection Geometry of this projector. + * + * @return Projection Geometry class. + */ + CProjectionGeometry2D* getProjectionGeometry(); + + /** Fetch the Volume Geometry of this projector. + * + * @return Volume Geometry class. + */ + CVolumeGeometry2D* getVolumeGeometry(); + + /** Compute the pixel weights for a single ray, from the source to a detector pixel. + * + * @param _iProjectionIndex Index of the projection + * @param _iDetectorIndex Index of the detector pixel + * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements + * of type SPixelWeight. On return, this array contains a list of the index + * and weight for all pixels on the ray. + * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels. + * This number MUST be greater than the total number of pixels on the ray. + * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the + * ray (that have been stored in the list _pWeightedPixels). + */ + virtual void computeSingleRayWeights(int _iProjectionIndex, + int _iDetectorIndex, + SPixelWeight *_pWeightedPixels, + int _iMaxPixelCount, + int &_iStoredPixelCount) = 0; + + /** Compute the pixel weights for all rays in a single projection, from the source to a each of the + * detector pixels. All pixels and their weights are stored consecutively in the array _pWeightedPixels. + * The array starts with all pixels on the first ray, followed by all pixels on the second ray, the third + * ray, etc. Note that a pixel may occur in the list more than once, as it can be on several rays. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @param _pfWeightedPixels Pointer to a pre-allocated array, consisting of getProjectionWeightsCount() + * elements of type SPixelWeight. On return, this array contains a list of + * the index and weight for all pixels on each of the rays. The elements for + * every ray start at equal offsets (ray_index * _pWeightedPixels / ray_count). + * @param _piRayStoredPixelCount Pointer to a pre-allocated array, containing a single integer for each + * ray in the projection. On return, this array contains the number of + * pixels on the ray, for each ray in the given projection. + */ + virtual void computeProjectionRayWeights(int _iProjectionIndex, + SPixelWeight* _pfWeightedPixels, + int* _piRayStoredPixelCount); + + /** Create a list of detectors that are influenced by point [_iRow, _iCol]. + * + * @param _iRow row of the point + * @param _iCol column of the point + * @return list of SDetector2D structs + */ + virtual std::vector projectPoint(int _iRow, int _iCol) = 0; + + /** Returns the number of weights required for storage of all weights of one projection ray. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels. + */ + virtual int getProjectionWeightsCount(int _iProjectionIndex) = 0; + + /** Returns the projection as an explicit sparse matrix. + * @return a newly allocated CSparseMatrix. Delete afterwards. + */ + CSparseMatrix* getMatrix(); + + /** Has the projector been initialized? + * + * @return initialized successfully + */ + bool isInitialized(); + + /** get a description of the class + * + * @return description string + */ + virtual std::string description() const {return " ";}; + + virtual std::string getType() { return " "; } + +private: + //< For Config unused argument checking + ConfigCheckData* configCheckData; + friend class ConfigStackCheck; +}; + +// inline functions +inline bool CProjector2D::isInitialized() { return m_bIsInitialized; } +inline CProjectionGeometry2D* CProjector2D::getProjectionGeometry() { return m_pProjectionGeometry; } +inline CVolumeGeometry2D* CProjector2D::getVolumeGeometry() { return m_pVolumeGeometry; } + + + + + +} // namespace astra + +#endif /* INC_ASTRA_PROJECTOR2D */ diff --git a/include/astra/Projector2DImpl.inl b/include/astra/Projector2DImpl.inl new file mode 100644 index 0000000..97341c8 --- /dev/null +++ b/include/astra/Projector2DImpl.inl @@ -0,0 +1,37 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + + +#include "ParallelBeamLinearKernelProjector2D.inl" +#include "ParallelBeamLineKernelProjector2D.inl" +#include "ParallelBeamStripKernelProjector2D.inl" +#include "ParallelBeamBlobKernelProjector2D.inl" +#include "FanFlatBeamStripKernelProjector2D.inl" +#include "FanFlatBeamLineKernelProjector2D.inl" +#include "SparseMatrixProjector2D.inl" + diff --git a/include/astra/Projector3D.h b/include/astra/Projector3D.h new file mode 100644 index 0000000..ec81bc8 --- /dev/null +++ b/include/astra/Projector3D.h @@ -0,0 +1,185 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef INC_ASTRA_PROJECTOR3D +#define INC_ASTRA_PROJECTOR3D + +#include +#include + +#include "Globals.h" +#include "Config.h" +#include "ProjectionGeometry3D.h" +#include "VolumeGeometry3D.h" + +namespace astra +{ + +class CSparseMatrix; + + +/** This is a base interface class for a three-dimensional projector. Each subclass should at least + * implement the core projection functions computeProjectionRayWeights and projectPoint. + * + * \par XML Configuration + * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.} + * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.} + */ +class _AstraExport CProjector3D +{ + +protected: + + CProjectionGeometry3D* m_pProjectionGeometry; ///< Used projection geometry + CVolumeGeometry3D* m_pVolumeGeometry; ///< Used volume geometry + bool m_bIsInitialized; ///< Has this class been initialized? + + /** Check variable values. + */ + bool _check(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + * Should only be used by constructors. Otherwise use the clear() function. + */ + void _clear(); + +public: + + /** + * Default Constructor. + */ + CProjector3D(); + + /** Destructor, is virtual to show that we are aware subclass destructor is called. + */ + virtual ~CProjector3D(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + */ + void clear(); + + /** Initialize the projector with a config object. + * This function does not set m_bInitialized to true. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Fetch the Projection Geometry of this projector. + * + * @return Projection Geometry class. + */ + CProjectionGeometry3D* getProjectionGeometry(); + + /** Fetch the Volume Geometry of this projector. + * + * @return Volume Geometry class. + */ + CVolumeGeometry3D* getVolumeGeometry(); + + /** Compute the pixel weights for a single ray, from the source to a detector pixel. + * + * @param _iProjectionIndex Index of the projection. + * @param _iSliceIndex Index of the detector pixel (1-d index). + * @param _iDetectorIndex Index of the detector pixel (1-d index). + * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements + * of type SPixelWeight. On return, this array contains a list of the index + * and weight for all pixels on the ray. + * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels. + * This number MUST be greater than the total number of pixels on the ray. + * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the + * ray (that have been stored in the list _pWeightedPixels). + */ + virtual void computeSingleRayWeights(int _iProjectionIndex, int _iSliceIndex, int _iDetectorIndex, SPixelWeight* _pWeightedPixels, int _iMaxPixelCount, int& _iStoredPixelCount) = 0; + + /** Compute the pixel weights for all rays in a single projection, from the source to a each of the + * detector pixels. All pixels and their weights are stored consecutively in the array _pWeightedPixels. + * The array starts with all pixels on the first ray, followed by all pixels on the second ray, the third + * ray, etc. Note that a pixel may occur in the list more than once, as it can be on several rays. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @param _pfWeightedPixels Pointer to a pre-allocated array, consisting of getProjectionWeightsCount() + * elements of type SPixelWeight. On return, this array contains a list of + * the index and weight for all pixels on each of the rays. The elements for + * every ray start at equal offsets (ray_index * _pWeightedPixels / ray_count). + * @param _piRayStoredPixelCount Pointer to a pre-allocated array, containing a single integer for each + * ray in the projection. On return, this array contains the number of + * pixels on the ray, for each ray in the given projection. + */ + virtual void computeProjectionRayWeights(int _iProjectionIndex, SPixelWeight* _pfWeightedPixels, int* _piRayStoredPixelCount); + + /** Create a list of detectors that are influenced by point [_iRow, _iCol]. + * + * @param _iRow row of the point + * @param _iCol column of the point + * @return list of SDetector2D structs + */ + //virtual std::vector projectPoint(int _iRow, int _iCol) = 0; + + /** Returns the number of weights required for storage of all weights of one projection. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @return Size of buffer (given in SWeightedPixel3D elements) needed to store weighted pixels. + */ + virtual int getProjectionWeightsCount(int _iProjectionIndex) = 0; + + /** Has the projector been initialized? + * + * @return initialized successfully + */ + bool isInitialized(); + + /** get a description of the class + * + * @return description string + */ + virtual std::string description() const = 0; + + /** + * Returns a string describing the projector type + */ + virtual std::string getType() = 0; + +private: + //< For Config unused argument checking + ConfigCheckData* configCheckData; + friend class ConfigStackCheck; + +}; + +// inline functions +inline bool CProjector3D::isInitialized() { return m_bIsInitialized; } +inline CProjectionGeometry3D* CProjector3D::getProjectionGeometry() { return m_pProjectionGeometry; } +inline CVolumeGeometry3D* CProjector3D::getVolumeGeometry() { return m_pVolumeGeometry; } + + + +} // namespace astra + +#endif /* INC_ASTRA_PROJECTOR3D */ diff --git a/include/astra/ProjectorTypelist.h b/include/astra/ProjectorTypelist.h new file mode 100644 index 0000000..ddc345a --- /dev/null +++ b/include/astra/ProjectorTypelist.h @@ -0,0 +1,104 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_PROJECTORTYPELIST +#define _INC_ASTRA_PROJECTORTYPELIST + +#include "Projector2D.h" +#include "TypeList.h" + +using namespace astra; +using namespace astra::typelist; + +// Projector2D +#include "Projector2D.h" +#include "ParallelBeamLineKernelProjector2D.h" +#include "ParallelBeamLinearKernelProjector2D.h" +#include "ParallelBeamBlobKernelProjector2D.h" +#include "ParallelBeamStripKernelProjector2D.h" +#include "SparseMatrixProjector2D.h" +#include "FanFlatBeamLineKernelProjector2D.h" +#include "FanFlatBeamStripKernelProjector2D.h" + +#ifdef ASTRA_CUDA +#include "CudaProjector2D.h" +namespace astra{ + + typedef TYPELIST_8( + CFanFlatBeamLineKernelProjector2D, + CFanFlatBeamStripKernelProjector2D, + CParallelBeamLinearKernelProjector2D, + CParallelBeamLineKernelProjector2D, + CParallelBeamBlobKernelProjector2D, + CParallelBeamStripKernelProjector2D, + CSparseMatrixProjector2D, + CCudaProjector2D) + Projector2DTypeList; +} + + + +#else + +namespace astra{ + typedef TYPELIST_7( + CFanFlatBeamLineKernelProjector2D, + CFanFlatBeamStripKernelProjector2D, + CParallelBeamLinearKernelProjector2D, + CParallelBeamLineKernelProjector2D, + CParallelBeamBlobKernelProjector2D, + CParallelBeamStripKernelProjector2D, + CSparseMatrixProjector2D) + Projector2DTypeList; +} + +#endif + +// Projector3D +#include "Projector3D.h" + +#ifdef ASTRA_CUDA + +#include "CudaProjector3D.h" +namespace astra { + typedef TYPELIST_1( + CCudaProjector3D + ) + Projector3DTypeList; +} + +#else + +namespace astra { + typedef TYPELIST_0 Projector3DTypeList; +} + +#endif + + +#endif diff --git a/include/astra/ReconstructionAlgorithm2D.h b/include/astra/ReconstructionAlgorithm2D.h new file mode 100644 index 0000000..25a6c0a --- /dev/null +++ b/include/astra/ReconstructionAlgorithm2D.h @@ -0,0 +1,222 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_RECONSTRUCTIONALGORITHM2D +#define _INC_ASTRA_RECONSTRUCTIONALGORITHM2D + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" + +#include "Projector2D.h" +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + + +namespace astra { + +/** + * This is a base class for the different implementations of 2D reconstruction algorithms. + * + * \par XML Configuration + * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.} + * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.} + * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.} + * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.} + * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.} + * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.} + */ +class _AstraExport CReconstructionAlgorithm2D : public CAlgorithm { + +public: + + /** Default constructor, containing no code. + */ + CReconstructionAlgorithm2D(); + + /** Destructor. + */ + virtual ~CReconstructionAlgorithm2D(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Clear this class. + */ + virtual void clear(); + + /** Add a min/max constraint to the reconstruction process + * + * @param _bUseMin True if the algorithm should use a min constraint. + * @param _fMinValue Lower value to clip pixel values to. + * @param _bUseMax True if the algorithm should use a max constraint. + * @param _fMaxValue Upper value to clip pixel values to. + */ + void setConstraints(bool _bUseMin, float32 _fMinValue, bool _bUseMax, float32 _fMaxValue); + + /** Set a fixed reconstruction mask. A pixel will only be used in the reconstruction if the + * corresponding value in the mask is 1. + * + * @param _pMask Volume Data object containing fixed reconstruction mask + * @param _bEnable enable the use of this mask + */ + void setReconstructionMask(CFloat32VolumeData2D* _pMask, bool _bEnable = true); + + /** Set a fixed sinogram mask. A detector value will only be used in the reconstruction if the + * corresponding value in the mask is 1. + * + * @param _pMask Projection Data object containing fixed sinogram mask + * @param _bEnable enable the use of this mask + */ + void setSinogramMask(CFloat32ProjectionData2D* _pMask, bool _bEnable = true); + + /** Get all information parameters. + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information. + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Get projector object + * + * @return projector + */ + CProjector2D* getProjector() const; + + /** Get sinogram data object + * + * @return sinogram data object + */ + CFloat32ProjectionData2D* getSinogram() const; + + /** Get Reconstructed Data + * + * @return reconstruction + */ + CFloat32VolumeData2D* getReconstruction() const; + + /** Get Fixed Reconstruction Mask + * + * @return fixed reconstruction mask + */ + CFloat32VolumeData2D* getReconstructionMask() const; + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0) = 0; + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Get the norm of the residual image. + * Only a few algorithms support this method. + * + * @param _fNorm if supported, the norm is returned here + * @return true if this operation is supported + */ + virtual bool getResidualNorm(float32& _fNorm) { return false; } + +protected: + + /** Check this object. + * + * @return object initialized + */ + bool _check(); + + /** Initial clearing. Only to be used by constructors. + */ + void _clear(); + + //< Projector object. + CProjector2D* m_pProjector; + //< ProjectionData2D object containing the sinogram. + CFloat32ProjectionData2D* m_pSinogram; + //< VolumeData2D object for storing the reconstruction volume. + CFloat32VolumeData2D* m_pReconstruction; + + //< Use minimum value constraint? + bool m_bUseMinConstraint; + //< Minimum value constraint. + float32 m_fMinValue; + //< Use maximum value constraint? + bool m_bUseMaxConstraint; + //< Maximum value constraint. + float32 m_fMaxValue; + + //< Dataobject containing fixed reconstruction mask (0 = don't reconstruct) + CFloat32VolumeData2D* m_pReconstructionMask; + //< Use the fixed reconstruction mask? + bool m_bUseReconstructionMask; + + //< Dataobject containing fixed reconstruction mask (0 = don't reconstruct) + CFloat32ProjectionData2D* m_pSinogramMask; + //< Use the fixed reconstruction mask? + bool m_bUseSinogramMask; + +}; + +// inline functions +inline std::string CReconstructionAlgorithm2D::description() const { return "3D Reconstruction Algorithm"; }; +inline CProjector2D* CReconstructionAlgorithm2D::getProjector() const { return m_pProjector; } +inline CFloat32ProjectionData2D* CReconstructionAlgorithm2D::getSinogram() const { return m_pSinogram; } +inline CFloat32VolumeData2D* CReconstructionAlgorithm2D::getReconstruction() const { return m_pReconstruction; } +inline CFloat32VolumeData2D* CReconstructionAlgorithm2D::getReconstructionMask() const { return m_pReconstructionMask; } + +} // end namespace + +#endif diff --git a/include/astra/ReconstructionAlgorithm3D.h b/include/astra/ReconstructionAlgorithm3D.h new file mode 100644 index 0000000..063ff6e --- /dev/null +++ b/include/astra/ReconstructionAlgorithm3D.h @@ -0,0 +1,223 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_RECONSTRUCTIONALGORITHM3D +#define _INC_ASTRA_RECONSTRUCTIONALGORITHM3D + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" + +#include "Float32ProjectionData3D.h" +#include "Float32VolumeData3D.h" + + +namespace astra { + +class CProjector3D; + +/** + * This is a base class for the different implementations of 3D reconstruction algorithms. + * + * \par XML Configuration + * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.} + * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.} + * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.} + * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.} + * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.} + * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.} + */ +class _AstraExport CReconstructionAlgorithm3D : public CAlgorithm { + +public: + + /** Default constructor, containing no code. + */ + CReconstructionAlgorithm3D(); + + /** Destructor. + */ + virtual ~CReconstructionAlgorithm3D(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData3D object containing the sinogram data. + * @param _pReconstruction VolumeData3D object for storing the reconstructed volume. + */ + bool initialize(CProjector3D* _pProjector, + CFloat32ProjectionData3D* _pSinogram, + CFloat32VolumeData3D* _pReconstruction); + + /** Clear this class. + */ + virtual void clear(); + + /** Add a min/max constraint to the reconstruction process + * + * @param _bUseMin True if the algorithm should use a min constraint. + * @param _fMinValue Lower value to clip pixel values to. + * @param _bUseMax True if the algorithm should use a max constraint. + * @param _fMaxValue Upper value to clip pixel values to. + */ + void setConstraints(bool _bUseMin, float32 _fMinValue, bool _bUseMax, float32 _fMaxValue); + + /** Set a fixed reconstruction mask. A pixel will only be used in the reconstruction if the + * corresponding value in the mask is 1. + * + * @param _pMask Volume Data object containing fixed reconstruction mask + * @param _bEnable enable the use of this mask + */ + void setReconstructionMask(CFloat32VolumeData3D* _pMask, bool _bEnable = true); + + /** Set a fixed sinogram mask. A detector value will only be used in the reconstruction if the + * corresponding value in the mask is 1. + * + * @param _pMask Projection Data object containing fixed sinogram mask + * @param _bEnable enable the use of this mask + */ + void setSinogramMask(CFloat32ProjectionData3D* _pMask, bool _bEnable = true); + + /** Get all information parameters. + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information. + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Get projector object + * + * @return projector + */ + CProjector3D* getProjector() const; + + /** Get sinogram data object + * + * @return sinogram data object + */ + CFloat32ProjectionData3D* getSinogram() const; + + /** Get Reconstructed Data + * + * @return reconstruction + */ + CFloat32VolumeData3D* getReconstruction() const; + + /** Get Fixed Reconstruction Mask + * + * @return fixed reconstruction mask + */ + CFloat32VolumeData3D* getReconstructionMask() const; + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0) = 0; + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + + /** Get the norm of the residual image. + * Only a few algorithms support this method. + * + * @param _fNorm if supported, the norm is returned here + * @return true if this operation is supported + */ + virtual bool getResidualNorm(float32& _fNorm) { return false; } + +protected: + + /** Check this object. + * + * @return object initialized + */ + bool _check(); + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + //< Projector object. + CProjector3D* m_pProjector; + //< ProjectionData3D object containing the sinogram. + CFloat32ProjectionData3D* m_pSinogram; + //< VolumeData3D object for storing the reconstruction volume. + CFloat32VolumeData3D* m_pReconstruction; + + //< Use minimum value constraint? + bool m_bUseMinConstraint; + //< Minimum value constraint. + float32 m_fMinValue; + //< Use maximum value constraint? + bool m_bUseMaxConstraint; + //< Maximum value constraint. + float32 m_fMaxValue; + + //< Dataobject containing fixed reconstruction mask (0 = don't reconstruct) + CFloat32VolumeData3D* m_pReconstructionMask; + //< Use the fixed reconstruction mask? + bool m_bUseReconstructionMask; + + //< Dataobject containing fixed reconstruction mask (0 = don't reconstruct) + CFloat32ProjectionData3D* m_pSinogramMask; + //< Use the fixed reconstruction mask? + bool m_bUseSinogramMask; + +}; + +// inline functions +inline std::string CReconstructionAlgorithm3D::description() const { return "3D Reconstruction Algorithm"; }; +inline CProjector3D* CReconstructionAlgorithm3D::getProjector() const { return m_pProjector; } +inline CFloat32ProjectionData3D* CReconstructionAlgorithm3D::getSinogram() const { return m_pSinogram; } +inline CFloat32VolumeData3D* CReconstructionAlgorithm3D::getReconstruction() const { return m_pReconstruction; } +inline CFloat32VolumeData3D* CReconstructionAlgorithm3D::getReconstructionMask() const { return m_pReconstructionMask; } + +} // end namespace + +#endif diff --git a/include/astra/SartAlgorithm.h b/include/astra/SartAlgorithm.h new file mode 100644 index 0000000..1a79a60 --- /dev/null +++ b/include/astra/SartAlgorithm.h @@ -0,0 +1,226 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_SARTALGORITHM +#define _INC_ASTRA_SARTALGORITHM + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" +#include "ReconstructionAlgorithm2D.h" + +#include "Projector2D.h" +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + +#include "DataProjector.h" + +namespace astra { + +/** + * \brief + * This class contains the implementation of the SART (Simultaneous Algebraic Reconstruction Technique) algorithm. + * + * The update step of pixel \f$v_j\f$ for projection \f$phi\f$ and iteration \f$k\f$ is given by: + * \f[ + * v_j^{(k+1)} = v_j^{(k)} + \frac{\sum_{p_i \in P_\phi} \left( \lambda \frac{p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}} {\sum_{r=1}^{N}w_{ir} } \right)} {\sum_{p_i \in P_\phi}w_{ij}} + * \f] + * + * \par XML Configuration + * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.} + * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.} + * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.} + * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.} + * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.} + * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.} + * \astra_xml_item_option{ProjectionOrder, string, "sequential", the order in which the projections are updated. 'sequential', 'random' or 'custom'} + * \astra_xml_item_option{ProjectionOrderList, vector of float, not used, if ProjectionOrder='custom': use this order.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('SART');\n + * cfg.ProjectorId = proj_id;\n + * cfg.ProjectionDataId = sino_id;\n + * cfg.ReconstructionDataId = recon_id;\n + * cfg.option.MaskId = mask_id;\n + * cfg.option.UseMinConstraint = 'yes';\n + * cfg.option.UseMaxConstraint = 'yes';\n + * cfg.option.MaxConstraintValue = 1024;\n + * cfg.option.ProjectionOrder = 'custom';\n +* cfg.option.ProjectionOrderList = randperm(100);\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('iterate'\, alg_id\, 10);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + */ +class _AstraExport CSartAlgorithm : public CReconstructionAlgorithm2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - valid projector + * - valid data objects + * - projection order all within range + */ + virtual bool _check(); + + // temporary data objects + CFloat32ProjectionData2D* m_pTotalRayLength; + CFloat32VolumeData2D* m_pTotalPixelWeight; + CFloat32ProjectionData2D* m_pDiffSinogram; + + int m_iIterationCount; + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CSartAlgorithm(); + + /** Constructor. + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + */ + CSartAlgorithm(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Constructor. + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @param _piProjectionOrder array containing a projection order. + * @param _iProjectionCount number of elements in _piProjectionOrder. + */ + CSartAlgorithm(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction, + int* _piProjectionOrder, + int _iProjectionCount); + + /** Destructor. + */ + virtual ~CSartAlgorithm(); + + /** Clear this class. + */ + virtual void clear(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class, no optionals, use sequential order. + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @return initialization successful? + */ + virtual bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Initialize class, use custom order. + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @param _piProjectionOrder array containing a projection order. + * @param _iProjectionCount number of elements in _piProjectionOrder. + * @return initialization successful? + */ + virtual bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction, + int* _piProjectionOrder, + int _iProjectionCount); + + /** Get all information parameters + * + * @return map with all boost::any object + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier identifier string to specify which piece of information you want + * @return boost::any object + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. Each iteration is a forward and backprojection of + * a single projection index. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 1); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + +protected: + + + //< Order of the projections. + int* m_piProjectionOrder; + //< Number of projections specified in m_piProjectionOrder. + int m_iProjectionCount; + //< Current index in the projection order array. + int m_iCurrentProjection; + +}; + +// inline functions +inline std::string CSartAlgorithm::description() const { return CSartAlgorithm::type; }; + + +} // end namespace + +#endif diff --git a/include/astra/Singleton.h b/include/astra/Singleton.h new file mode 100644 index 0000000..5a494e4 --- /dev/null +++ b/include/astra/Singleton.h @@ -0,0 +1,87 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_SINGLETON +#define _INC_ASTRA_SINGLETON + +#include + +#ifndef _MSC_VER +#include +#endif + +namespace astra { + /** + * This singleton interface class ensures that any of its children can be instatiated only once. This is used by the ObjectFactories. + **/ +template +class Singleton { + + public: + + // constructor + Singleton() { + assert(!m_singleton); + int offset = (uintptr_t)(T*)1 - (uintptr_t)(Singleton*)(T*)1; + m_singleton = (T*)((uintptr_t)this + offset); + }; + + // destructor + virtual ~Singleton() { + assert(m_singleton); + m_singleton = 0; + } + + // get singleton + static T& getSingleton() { + if (!m_singleton) + m_singleton = new T(); + return *m_singleton; + } + static T* getSingletonPtr() { + if (!m_singleton) + m_singleton = new T(); + return m_singleton; + } + + private: + + // the singleton + static T* m_singleton; + +}; + +#define DEFINE_SINGLETON(T) template<> T* Singleton::m_singleton = 0 + +// This is a hack to support statements like +// DEFINE_SINGLETON2(CTemplatedClass); +#define DEFINE_SINGLETON2(A,B) template<> A,B* Singleton::m_singleton = 0 + +} // end namespace + +#endif diff --git a/include/astra/SirtAlgorithm.h b/include/astra/SirtAlgorithm.h new file mode 100644 index 0000000..5cbc4d4 --- /dev/null +++ b/include/astra/SirtAlgorithm.h @@ -0,0 +1,217 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_SIRTALGORITHM +#define _INC_ASTRA_SIRTALGORITHM + +#include "Globals.h" +#include "Config.h" + +#include "Algorithm.h" +#include "ReconstructionAlgorithm2D.h" + +#include "Projector2D.h" +#include "Float32ProjectionData2D.h" +#include "Float32VolumeData2D.h" + +#include "DataProjector.h" + +namespace astra { + +/** + * \brief + * This class contains the implementation of the SIRT (Simultaneous Iterative Reconstruction Technique) algorithm. + * + * The update step of pixel \f$v_j\f$ for iteration \f$k\f$ is given by: + * \f[ + * v_j^{(k+1)} = v_j^{(k)} + \alpha \sum_{i=1}^{M} \left( \frac{w_{ij}\left( p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}\right)}{\sum_{k=1}^{N} w_{ik}} \right) \frac{1}{\sum_{l=1}^{M}w_{lj}} + * \f] + * + * \par XML Configuration + * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.} + * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.} + * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.} + * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.} + * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.} + * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.} + * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.} + * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.} + * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.} + * + * \par XML Example + * \astra_code{ + * <Algorithm type="SIRT">\n + * <ProjectorID>proj_id</ProjectorID>\n + * <ProjectionDataId>sino_id</ProjectionDataId>\n + * <ReconstructionDataId>recon_id</ReconstructionDataId>\n + * <Option key="ReconstructionMaskId" value="3"/>\n + * <Option key="SinogramMaskId" value="4"/>\n + * <Option key="UseMinConstraint" value="yes"/>\n + * <Option key="UseMaxConstraint" value="yes"/>\n + * <Option key="MaxConstraintValue" value="1024"/>\n + * </Algorithm> + * } + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('SIRT');\n + * cfg.ProjectorId = proj_id;\n + * cfg.ProjectionDataId = sino_id;\n + * cfg.ReconstructionDataId = recon_id;\n + * cfg.option.SinogramMaskId = smask_id;\n + * cfg.option.ReconstructionMaskId = mask_id;\n + * cfg.option.UseMinConstraint = 'yes';\n + * cfg.option.UseMaxConstraint = 'yes';\n + * cfg.option.MaxConstraintValue = 1024;\n + * alg_id = astra_mex_algorithm('create'\, cfg);\n + * astra_mex_algorithm('iterate'\, alg_id\, 10);\n + * astra_mex_algorithm('delete'\, alg_id);\n + * } + * + * \par References + * [1] "Computational Analysis and Improvement of SIRT", J. Gregor, T. Benson, IEEE Transactions on Medical Imaging, Vol. 22, No. 7, July 2008. + */ +class _AstraExport CSirtAlgorithm : public CReconstructionAlgorithm2D { + +protected: + + /** Init stuff + */ + virtual void _init(); + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - valid projector + * - valid data objects + */ + virtual bool _check(); + + /** Temporary data object for storing the total ray lengths + */ + CFloat32ProjectionData2D* m_pTotalRayLength; + + /** Temporary data object for storing the total pixel weigths + */ + CFloat32VolumeData2D* m_pTotalPixelWeight; + + /** Temporary data object for storing the difference between the forward projected + * reconstruction, and the measured projection data + */ + CFloat32ProjectionData2D* m_pDiffSinogram; + + /** Temporary data object for storing volume data + */ + CFloat32VolumeData2D* m_pTmpVolume; + + /** The number of performed iterations + */ + int m_iIterationCount; + +public: + + // type of the algorithm, needed to register with CAlgorithmFactory + static std::string type; + + /** Default constructor, containing no code. + */ + CSirtAlgorithm(); + + /** Default constructor + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + */ + CSirtAlgorithm(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Destructor. + */ + virtual ~CSirtAlgorithm(); + + /** Clear this class. + */ + virtual void clear(); + + /** Initialize the algorithm with a config object. + * + * @param _cfg Configuration Object + * @return Initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize class. + * + * @param _pProjector Projector Object. + * @param _pSinogram ProjectionData2D object containing the sinogram data. + * @param _pReconstruction VolumeData2D object for storing the reconstructed volume. + * @return Initialization successful? + */ + bool initialize(CProjector2D* _pProjector, + CFloat32ProjectionData2D* _pSinogram, + CFloat32VolumeData2D* _pReconstruction); + + /** Get all information parameters. + * + * @return Map with all available identifier strings and their values. + */ + virtual map getInformation(); + + /** Get a single piece of information represented as a boost::any + * + * @param _sIdentifier Identifier string to specify which piece of information you want. + * @return One piece of information. + */ + virtual boost::any getInformation(std::string _sIdentifier); + + /** Perform a number of iterations. + * + * @param _iNrIterations amount of iterations to perform. + */ + virtual void run(int _iNrIterations = 0); + + /** Get a description of the class. + * + * @return description string + */ + virtual std::string description() const; + +}; + +// inline functions +inline std::string CSirtAlgorithm::description() const { return CSirtAlgorithm::type; }; + + +} // end namespace + +#endif diff --git a/include/astra/SparseMatrix.h b/include/astra/SparseMatrix.h new file mode 100644 index 0000000..e07be87 --- /dev/null +++ b/include/astra/SparseMatrix.h @@ -0,0 +1,144 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_SPARSEMATRIX +#define _INC_ASTRA_SPARSEMATRIX + +namespace astra +{ + + +/** This class implements a sparse matrix. It is stored as three arrays. + * The values are stored row-by-row. + * m_pfValues contains the values + * m_piColIndices contains the col indices of the values + * m_plRowStarts contains the start offsets of the rows + */ + + +class _AstraExport CSparseMatrix { +public: + CSparseMatrix(); + + // TODO: are ints large enough for width/height? + CSparseMatrix(unsigned int _iHeight, unsigned int _iWidth, + unsigned long _lSize); + + /** Initialize the matrix structure. + * It does not initialize any values. + * + * @param _iHeight number of rows + * @param _iWidth number of columns + * @param _lSize maximum number of non-zero entries + * @return initialization successful? + */ + + bool initialize(unsigned int _iHeight, unsigned int _iWidth, + unsigned long _lSize); + + /** Destructor. + */ + ~CSparseMatrix(); + + /** Has the matrix structure been initialized? + * + * @return initialized successfully + */ + bool isInitialized() const { return m_bInitialized; } + + /** get a description of the class + * + * @return description string + */ + std::string description() const; + + /** get the data for a single row. Entries are stored from left to right. + * + * @param _iRow the row + * @param _iSize the returned number of elements in the row + * @param _pfValues the values of the non-zero entries in the row + * @param _piColIndices the column indices of the non-zero entries + */ + void getRowData(unsigned int _iRow, unsigned int& _iSize, + const float32*& _pfValues, const unsigned int*& _piColIndices) const + { + assert(_iRow < m_iHeight); + unsigned long lStart = m_plRowStarts[_iRow]; + _iSize = m_plRowStarts[_iRow+1] - lStart; + _pfValues = &m_pfValues[lStart]; + _piColIndices = &m_piColIndices[lStart]; + } + + /** get the number of elements in a row + * + * @param _iRow the row + * @return number of stored entries in the row + */ + unsigned int getRowSize(unsigned int _iRow) const + { + assert(_iRow < m_iHeight); + return m_plRowStarts[_iRow+1] - m_plRowStarts[_iRow]; + } + + + /** Matrix width + */ + unsigned int m_iHeight; + + /** Matrix height + */ + unsigned int m_iWidth; + + /** Maximum number of non-zero entries + */ + unsigned long m_lSize; + + /** Contains the numeric values of all non-zero elements + */ + float32* m_pfValues; + + /** Contains the colon index of all non-zero elements + */ + unsigned int* m_piColIndices; + + /** The indices in this array point to the first element of each row in the m_pfValues array + */ + unsigned long* m_plRowStarts; + +protected: + + /** Is the class initialized? + */ + bool m_bInitialized; +}; + + +} + + +#endif diff --git a/include/astra/SparseMatrixProjectionGeometry2D.h b/include/astra/SparseMatrixProjectionGeometry2D.h new file mode 100644 index 0000000..e334dd1 --- /dev/null +++ b/include/astra/SparseMatrixProjectionGeometry2D.h @@ -0,0 +1,154 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_SPARSEMATRIXPROJECTIONGEOMETRY2D +#define _INC_ASTRA_SPARSEMATRIXPROJECTIONGEOMETRY2D + +#include "ProjectionGeometry2D.h" + +namespace astra +{ + +class CSparseMatrix; + +/** + * This class defines a projection geometry determined by an arbitrary + * sparse matrix. + * + * The projection data is assumed to be grouped by 'angle' and 'detector pixel'. + * This does not have any effect on the algorithms, but only on the + * way the projection data is stored and accessed. + */ +class _AstraExport CSparseMatrixProjectionGeometry2D : public CProjectionGeometry2D +{ +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the init() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + * + */ + CSparseMatrixProjectionGeometry2D(); + + /** Constructor. Create an instance of the CSparseMatrixProjectionGeometry2D class. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle. + * @param _pMatrix Pointer to a CSparseMatrix. The caller is responsible for keeping this matrix valid until it is no longer required. + */ + CSparseMatrixProjectionGeometry2D(int _iProjectionAngleCount, + int _iDetectorCount, + const CSparseMatrix* _pMatrix); + + /** Copy constructor. + */ + CSparseMatrixProjectionGeometry2D(const CSparseMatrixProjectionGeometry2D& _projGeom); + + /** Destructor. + */ + ~CSparseMatrixProjectionGeometry2D(); + + /** Assignment operator. + */ + CSparseMatrixProjectionGeometry2D& operator=(const CSparseMatrixProjectionGeometry2D& _other); + + /** Initialize the geometry with a config object. This does not allow + * setting a matrix. Use the setMatrix() method for that afterwards. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialization. Initializes an instance of the CProjectionGeometry2D class. If the object has been + * initialized before, the object is reinitialized and memory is freed and reallocated if necessary. + * + * @param _iProjectionAngleCount Number of projection angles. + * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle. + * @param _pMatrix Pointer to a CSparseMatrix. The caller is responsible for keeping this matrix valid until it is no longer required. + */ + bool initialize(int _iProjectionAngleCount, + int _iDetectorCount, + const CSparseMatrix* _pMatrix); + + /** Set the associated sparse matrix. The previous one is deleted. + * + * @param _pMatrix Pointer to a CSparseMatrix. The caller is responsible for keeping this matrix valid until it is no longer required. + * @return initialization successful? + */ + + bool setMatrix(CSparseMatrix* _pMatrix); + + /** Get a pointer to the associated sparse matrix. + * @return the associated sparse matrix + */ + const CSparseMatrix* getMatrix() const { return m_pMatrix; } + + /** Create a hard copy. + */ + virtual CProjectionGeometry2D* clone(); + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(CProjectionGeometry2D*) const; + + /** Returns true if the type of geometry defined in this class is the one specified in _sType. + * + * @param _sType geometry type to compare to. + * @return true if _sType == "parallel". + */ + virtual bool isOfType(const std::string& _sType); + + /** + * Returns a vector describing the direction of a ray belonging to a certain detector + * + * @param _iProjectionIndex index of projection + * @param _iProjectionIndex index of detector + * + * @return a unit vector describing the direction + */ + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex); + +protected: + + /** Check this object. + * + * @return object initialized + */ + bool _check(); + + const CSparseMatrix* m_pMatrix; +}; + +} // namespace astra + +#endif /* _INC_ASTRA_SPARSEMATRIXPROJECTIONGEOMETRY2D */ diff --git a/include/astra/SparseMatrixProjector2D.h b/include/astra/SparseMatrixProjector2D.h new file mode 100644 index 0000000..f2554bf --- /dev/null +++ b/include/astra/SparseMatrixProjector2D.h @@ -0,0 +1,210 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_SPARSEMATRIXPROJECTOR2D +#define _INC_ASTRA_SPARSEMATRIXPROJECTOR2D + +#include "SparseMatrixProjectionGeometry2D.h" +#include "SparseMatrix.h" +#include "Float32Data2D.h" +#include "Projector2D.h" + +namespace astra +{ + + +/** This class implements a two-dimensional projector using a projection geometry defined by an arbitrary sparse matrix. + * + * \par XML Configuration + * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.} + * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.} + * + * \par MATLAB example + * \astra_code{ + * cfg = astra_struct('sparse_matrix');\n + * cfg.ProjectionGeometry = proj_geom;\n + * cfg.VolumeGeometry = vol_geom;\n + * proj_id = astra_mex_projector('create'\, cfg);\n + * } + */ +class _AstraExport CSparseMatrixProjector2D : public CProjector2D { + +protected: + + /** Initial clearing. Only to be used by constructors. + */ + virtual void _clear(); + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - no NULL pointers + * - all sub-objects are initialized properly + * - matrix dimensions match volume geometry + */ + virtual bool _check(); + +public: + + // type of the projector, needed to register with CProjectorFactory + static std::string type; + + /** Default constructor. + */ + CSparseMatrixProjector2D(); + + /** Constructor. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + */ + CSparseMatrixProjector2D(CSparseMatrixProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Destructor, is virtual to show that we are aware subclass destructor are called. + */ + ~CSparseMatrixProjector2D(); + + /** Initialize the projector with a config object. + * + * @param _cfg Configuration Object + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialize the projector. + * + * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED. + * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED. + * @return initialization successful? + */ + virtual bool initialize(CSparseMatrixProjectionGeometry2D* _pProjectionGeometry, + CVolumeGeometry2D* _pReconstructionGeometry); + + /** Clear this class. + */ + virtual void clear(); + + /** Returns the number of weights required for storage of all weights of one projection. + * + * @param _iProjectionIndex Index of the projection (zero-based). + * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels. + */ + virtual int getProjectionWeightsCount(int _iProjectionIndex); + + /** Compute the pixel weights for a single ray, from the source to a detector pixel. + * + * @param _iProjectionIndex Index of the projection + * @param _iDetectorIndex Index of the detector pixel + * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements + * of type SPixelWeight. On return, this array contains a list of the index + * and weight for all pixels on the ray. + * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels. + * This number MUST be greater than the total number of pixels on the ray. + * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the + * ray (that have been stored in the list _pWeightedPixels). + */ + virtual void computeSingleRayWeights(int _iProjectionIndex, + int _iDetectorIndex, + SPixelWeight* _pWeightedPixels, + int _iMaxPixelCount, + int& _iStoredPixelCount); + + /** Create a list of detectors that are influenced by point [_iRow, _iCol]. + * + * @param _iRow row of the point + * @param _iCol column of the point + * @return list of SDetector2D structs + */ + virtual std::vector projectPoint(int _iRow, int _iCol); + + /** Policy-based projection of all rays. This function will calculate each non-zero projection + * weight and use this value for a task provided by the policy object. + * + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void project(Policy& _policy); + + /** Policy-based projection of all rays of a single projection. This function will calculate + * each non-zero projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Wwhich projection should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleProjection(int _iProjection, Policy& _policy); + + /** Policy-based projection of a single ray. This function will calculate each non-zero + * projection weight and use this value for a task provided by the policy object. + * + * @param _iProjection Which projection should be projected? + * @param _iDetector Which detector should be projected? + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy); + + /** Policy-based voxel-projection of a single pixel. This function will calculate + * each non-zero projection weight and use this value for a task provided by the policy object. + * + * @param _iRow + * @param _iCol + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectSingleVoxel(int _iRow, int _iCol, Policy& _policy) {} + + /** Policy-based voxel-projection of all voxels. This function will calculate + * each non-zero projection weight and use this value for a task provided by the policy object. + * + * @param _policy Policy object. Should contain prior, addWeight and posterior function. + */ + template + void projectAllVoxels(Policy& _policy) {} + +protected: + + /** Return the type of this projector. + * + * @return identification type of this projector + */ + virtual std::string getType(); + +}; + +//---------------------------------------------------------------------------------------- + +inline std::string CSparseMatrixProjector2D::getType() +{ + return type; +} + +} // namespace astra + +#endif + diff --git a/include/astra/SparseMatrixProjector2D.inl b/include/astra/SparseMatrixProjector2D.inl new file mode 100644 index 0000000..8256232 --- /dev/null +++ b/include/astra/SparseMatrixProjector2D.inl @@ -0,0 +1,90 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + + +//---------------------------------------------------------------------------------------- +// PROJECT ALL +template +void CSparseMatrixProjector2D::project(Policy& p) +{ + ASTRA_ASSERT(m_bIsInitialized); + + for (int i = 0; i < m_pProjectionGeometry->getProjectionAngleCount(); ++i) + for (int j = 0; j < m_pProjectionGeometry->getDetectorCount(); ++j) + projectSingleRay(i, j, p); +} + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE PROJECTION +template +void CSparseMatrixProjector2D::projectSingleProjection(int _iProjection, Policy& p) +{ + ASTRA_ASSERT(m_bIsInitialized); + + for (int j = 0; j < m_pProjectionGeometry->getDetectorCount(); ++j) + projectSingleRay(_iProjection, j, p); +} + + +//---------------------------------------------------------------------------------------- +// PROJECT SINGLE RAY +template +void CSparseMatrixProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p) +{ + ASTRA_ASSERT(m_bIsInitialized); + + int iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector; + const CSparseMatrix* pMatrix = dynamic_cast(m_pProjectionGeometry)->getMatrix(); + + // POLICY: RAY PRIOR + if (!p.rayPrior(iRayIndex)) return; + + const unsigned int* piColIndices; + const float32* pfValues; + unsigned int iSize; + + pMatrix->getRowData(iRayIndex, iSize, pfValues, piColIndices); + + for (unsigned int i = 0; i < iSize; ++i) { + unsigned int iVolumeIndex = piColIndices[i]; + + // POLICY: PIXEL PRIOR + if (p.pixelPrior(iVolumeIndex)) { + + // POLICY: ADD + p.addWeight(iRayIndex, iVolumeIndex, pfValues[i]); + + // POLICY: PIXEL POSTERIOR + p.pixelPosterior(iVolumeIndex); + } + } + + // POLICY: RAY POSTERIOR + p.rayPosterior(iRayIndex); +} diff --git a/include/astra/TypeList.h b/include/astra/TypeList.h new file mode 100644 index 0000000..fcf985d --- /dev/null +++ b/include/astra/TypeList.h @@ -0,0 +1,236 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_TYPELIST +#define _INC_ASTRA_TYPELIST + +#include "Globals.h" +#include + +namespace astra { +namespace typelist { + + //----------------------------------------------------------------------------------------- + // basic types + /** + * Type to serve as tail of typelist + **/ + class NullType { }; + struct FalseType { enum { value = false }; }; + struct TrueType { enum { value = true }; }; + + //----------------------------------------------------------------------------------------- + // define typelist + /** + * Typelist definition + * \par References + * [1] Modern C++ design: generic programming and design patterns applied, Andrei Alexandrescu + **/ + template + struct TypeList + { + typedef T Head; + typedef U Tail; + }; + + //----------------------------------------------------------------------------------------- + // linearize typelist + #define TYPELIST_0 NullType + #define TYPELIST_1(T1) TypeList + #define TYPELIST_2(T1,T2) TypeList + #define TYPELIST_3(T1,T2,T3) TypeList + #define TYPELIST_4(T1,T2,T3,T4) TypeList + #define TYPELIST_5(T1,T2,T3,T4,T5) TypeList + #define TYPELIST_6(T1,T2,T3,T4,T5,T6) TypeList + #define TYPELIST_7(T1,T2,T3,T4,T5,T6,T7) TypeList + #define TYPELIST_8(T1,T2,T3,T4,T5,T6,T7,T8) TypeList + #define TYPELIST_9(T1,T2,T3,T4,T5,T6,T7,T8,T9) TypeList + #define TYPELIST_10(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10) \ + TypeList + #define TYPELIST_11(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11) \ + TypeList + #define TYPELIST_12(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12) \ + TypeList + #define TYPELIST_13(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13) \ + TypeList + #define TYPELIST_14(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14) \ + TypeList + #define TYPELIST_15(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15) \ + TypeList + #define TYPELIST_16(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16) \ + TypeList + #define TYPELIST_17(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17) \ + TypeList + #define TYPELIST_18(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18) \ + TypeList + #define TYPELIST_19(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19) \ + TypeList + #define TYPELIST_20(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20) \ + TypeList + #define TYPELIST_21(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21) \ + TypeList + #define TYPELIST_22(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22) \ + TypeList + #define TYPELIST_23(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23) \ + TypeList + + #define TYPELIST_24(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24) \ + TypeList + + #define TYPELIST_25(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25) \ + TypeList + + #define TYPELIST_26(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26) \ + TypeList + + #define TYPELIST_27(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27) \ + TypeList + + #define TYPELIST_28(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28) \ + TypeList + + #define TYPELIST_29(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29) \ + TypeList + + #define TYPELIST_30(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30) \ + TypeList + + #define TYPELIST_31(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31) \ + TypeList + + #define TYPELIST_32(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32) \ + TypeList + + #define TYPELIST_33(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33) \ + TypeList + + #define TYPELIST_34(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34) \ + TypeList + + #define TYPELIST_35(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35) \ + TypeList + + #define TYPELIST_36(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36) \ + TypeList + + #define TYPELIST_37(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37) \ + TypeList + + #define TYPELIST_38(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38) \ + TypeList + + #define TYPELIST_39(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39) \ + TypeList + + #define TYPELIST_40(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40) \ + TypeList + + + //----------------------------------------------------------------------------------------- + // calculate length of a typelist + template struct Length; + template <> struct Length + { + enum { value = 0 }; + }; + template + struct Length< TypeList > + { + enum { value = 1 + Length::value }; + }; + + //----------------------------------------------------------------------------------------- + // indexed access + template struct TypeAt; + template + struct TypeAt , 0> + { + typedef Head Result; + }; + template + struct TypeAt, i> + { + typedef typename TypeAt::Result Result; + }; + + + //----------------------------------------------------------------------------------------- + // append to typelist + template struct Append; + template <> + struct Append { + typedef NullType Result; + }; + template + struct Append { + typedef TYPELIST_1(T) Result; + }; + template + struct Append > { + typedef TypeList Result; + }; + template + struct Append, T> { + typedef TypeList::Result> Result; + }; + + //----------------------------------------------------------------------------------------- + // create a new object + template + struct CreateObject { + template + static void find (U& functor) { + if (functor(TList::Head::type)) { + functor.res = new typename TList::Head(); + } + CreateObject::find(functor); + } + }; + template <> + struct CreateObject { + template + static void find(U& functor) {} + }; + + template + struct functor_find { + functor_find() { res = NULL; } + bool operator() (string name) { + return strcmp(tofind.c_str(), name.c_str()) == 0; + } + string tofind; + Base* res; + }; + + + + +} // end namespace typelist +} // end namespace astra + +#endif diff --git a/include/astra/Utilities.h b/include/astra/Utilities.h new file mode 100644 index 0000000..7bf0cae --- /dev/null +++ b/include/astra/Utilities.h @@ -0,0 +1,131 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_UTILIES +#define _INC_ASTRA_UTILIES + +#include +#include +#include +#include +#include + +#include "Globals.h" + +namespace astra { + +/** + * This class contains some usefull static utility functions for std strings. + */ +class StringUtil { + +public: + /** + * Removes whitespace characters such as spaces and tabs at the extremas. + * Optionally you can specify which extrema to trim (default=both) + * + * @param _sString The string to trim. + * @param _bLeft Trim the left extrema? Default = true. + * @param _bRight Trim the right extrema? Default = true. + */ + static void trim(std::string& _sString, bool _bLeft = true, bool _bRight = true); + + /** + * Returns a vector of strings that contains all the substrings delimited by + * the characters in _sDelims. + * + * @param _sString The string to split. + * @param _sDelims The delimiter string. + * @return Vector of strings. + */ + static std::vector split(const std::string& _sString, const std::string& _sDelims); + + /** + * Cast a string to an integer. + * + * @param _sString The string to cast. + * @param _iValue Output integer parameter. + * @return success? + */ + static bool toInt(const std::string& _sString, int& _iValue); + + /** + * Cast a string to a float32. + * + * @param _sString The string to cast. + * @param _fValue Output float32 parameter. + * @return success? + */ + static bool toFloat32(const std::string& _sString, float32& _fValue); + + /** + * Convert a string to lower case. + * + * @param _sString The string to convert. + */ + static void toLowerCase(std::string& _sString); + + /** + * Convert a string to upper case. + * + * @param _sString The string to convert. + */ + static void toUpperCase(std::string& _sString); +}; + +/** + * This class contains some usefull static utility functions for std strings. + */ +class FileSystemUtil { + +public: + /** + * Get the extensions of a filename. Always in lower case. + * + * @param _sFilename file to get extensions from. + * @return Extension (lower case). Empty string if filename is a directory or not a valid file format. + */ + static std::string getExtension(std::string& _sFilename); + + +}; + + +template +std::map mergeMap(std::map _mMap1, std::map _mMap2) +{ + std::map result = _mMap1; + for (typename std::map::iterator it = _mMap2.begin(); it != _mMap2.end(); it++) { + result[(*it).first] = (*it).second; + } + return result; +} + +} // end namespace + +#endif diff --git a/include/astra/Vector3D.h b/include/astra/Vector3D.h new file mode 100644 index 0000000..ee923c9 --- /dev/null +++ b/include/astra/Vector3D.h @@ -0,0 +1,131 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_VECTOR3D +#define _INC_ASTRA_VECTOR3D + +#include "Globals.h" + +namespace astra { + +/** + * This class defines a three-dimensional vector type. + */ +class CVector3D +{ + float32 m_fX; ///< X Coordinate + float32 m_fY; ///< Y Coordinate + float32 m_fZ; ///< Z Coordinate + +public: + /** + * Default constructor + */ + CVector3D(); + + /** + * Constructor initializing member variables + */ + CVector3D(float32 _fX, float32 _fY, float32 _fZ); + + /** + * Returns the X-coordinate stored in this vector + */ + float32 getX() const; + + /** + * Returns the Y-coordinate stored in this vector + */ + float32 getY() const; + + /** + * Returns the Z-coordinate stored in this vector + */ + float32 getZ() const; + + /** + * Sets the X-coordinate stored in this vector + */ + void setX(float32 _fX); + + /** + * Sets the X-coordinate stored in this vector + */ + void setY(float32 _fY); + + /** + * Sets the X-coordinate stored in this vector + */ + void setZ(float32 _fZ); +}; + +inline CVector3D::CVector3D() +{ + m_fX = m_fY = m_fZ = 0.0f; +} + +inline CVector3D::CVector3D(float32 _fX, float32 _fY, float32 _fZ) +{ + m_fX = _fX; + m_fY = _fY; + m_fZ = _fZ; +} + +inline float32 CVector3D::getX() const +{ + return m_fX; +} + +inline float32 CVector3D::getY() const +{ + return m_fY; +} + +inline float32 CVector3D::getZ() const +{ + return m_fZ; +} + +inline void CVector3D::setX(float32 _fX) +{ + m_fX = _fX; +} + +inline void CVector3D::setY(float32 _fY) +{ + m_fY = _fY; +} + +inline void CVector3D::setZ(float32 _fZ) +{ + m_fZ = _fZ; +} + +} + +#endif /* _INC_ASTRA_VECTOR3D */ diff --git a/include/astra/VolumeGeometry2D.h b/include/astra/VolumeGeometry2D.h new file mode 100644 index 0000000..99d480d --- /dev/null +++ b/include/astra/VolumeGeometry2D.h @@ -0,0 +1,608 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_VOLUMEGEOMETRY2D +#define _INC_ASTRA_VOLUMEGEOMETRY2D + +#include "Globals.h" +#include "Config.h" + +namespace astra +{ + +/** + * This class represents a pixel grid that is placed in the geometry. It defines a rectangular volume window. + * + * \par XML Configuration + * \astra_xml_item{GridColCount, integer, Number of columns in this geometry.} + * \astra_xml_item{GridRowCount, integer, Number of rows in this geometry.} + * \astra_xml_item_option{WindowMinX, float, Minimal X-coordinate in the volume window.} + * \astra_xml_item_option{WindowMaxX, float, Maximal X-coordinate in the volume window.} + * \astra_xml_item_option{WindowMinY, float, Minimal Y-coordinate in the volume window.} + * \astra_xml_item_option{WindowMaxY, float, Maximal Y-coordinate in the volume window.} + * + * \par MATLAB example + * \astra_code{ + * vol_geom = struct();\n + * vol_geom.GridColCount = 1024;\n + * vol_geom.GridRowCount = 768;\n + * vol_geom.option.WindowMinX = -512;\n + * vol_geom.option.WindowMaxX = -384;\n + * vol_geom.option.WindowMinY = 512;\n + * vol_geom.option.WindowMaxY = 384;\n + * } + */ +class _AstraExport CVolumeGeometry2D { + +protected: + bool m_bInitialized; ///< Has this object been initialized? + + int m_iGridColCount; ///< number of columns in the volume grid. + int m_iGridRowCount; ///< number of rows in the volume grid. + int m_iGridTotCount; ///< total number of pixels in the volume grid (= m_iGridColCount * m_iGridRowCount). + + /** Width of the volume window, in unit lengths. + * + * Note that this width is independent of the number of pixels in the X-direction, as the width of a pixel can + * be different from 1. + */ + float32 m_fWindowLengthX; + + /** Height of the volume window, in unit lengths. + * + * Note that this height is independent of the number of pixels in the Y-direction, as the height of a pixel can + * be different from 1. + */ + float32 m_fWindowLengthY; + + float32 m_fWindowArea; ///< Total area of the volume window, in unit lengths squared. + + float32 m_fPixelLengthX; ///< Width of a single pixel, in unit lengths. + float32 m_fPixelLengthY; ///< Height of a single pixel, in unit lengths. + float32 m_fPixelArea; ///< Area of a single pixel, in unit lengths squared. + + float32 m_fDivPixelLengthX; ///< 1/m_fPixelLengthX, used for fast division. + float32 m_fDivPixelLengthY; ///< 1/m_fPixelLengthY, used for fast division. + + float32 m_fWindowMinX; ///< Minimal X-coordinate in the volume window. + float32 m_fWindowMinY; ///< Maximal X-coordinate in the volume window. + float32 m_fWindowMaxX; ///< Minimal Y-coordinate in the volume window. + float32 m_fWindowMaxY; ///< Maximal Y-coordinate in the volume window. + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - number of rows and columns is larger than zero + * - window minima is smaller than window maxima + * - m_iGridTotCount, m_fWindowLengthX, m_fWindowLengthY, m_fWindowArea, m_fPixelLengthX, + * m_fPixelLengthY, m_fPixelArea, m_fDivPixelLengthX and m_fDivPixelLengthY are initialized ok + */ + bool _check(); + + + /** Calculate values of all member variables from m_iGridRow/ColCount, m_fWindow* + */ + void _calculateDependents(); +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the init() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + */ + CVolumeGeometry2D(); + + /** Constructor. Create an instance of the CVolumeGeometry2D class. + * The minimal and coordinates values of the geometry will be set to -/+ the number of rows/columns. + * + * @param _iGridCountX Number of columns in the volume grid. + * @param _iGridCountY Number of rows in the volume grid. + */ + CVolumeGeometry2D(int _iGridCountX, + int _iGridCountY); + + /** Constructor. Create an instance of the CVolumeGeometry2D class. + * + * @param _iGridCountX Number of columns in the volume grid. + * @param _iGridCountY Number of rows in the volume grid. + * @param _fWindowMinX Minimal X-coordinate in the volume window. + * @param _fWindowMinY Minimal Y-coordinate in the volume window. + * @param _fWindowMaxX Maximal X-coordinate in the volume window. + * @param _fWindowMaxY Maximal Y-coordinate in the volume window. + */ + CVolumeGeometry2D(int _iGridCountX, + int _iGridCountY, + float32 _fWindowMinX, + float32 _fWindowMinY, + float32 _fWindowMaxX, + float32 _fWindowMaxY); + + /** Destructor. + */ + virtual ~CVolumeGeometry2D(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + */ + void clear(); + + /** Create a hard copy. + */ + CVolumeGeometry2D* clone(); + + /** Initialize the volume geometry with a config object. + * + * @param _cfg Configuration Object. + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialization. Initializes an instance of the CVolumeGeometry2D class. + * The minimal and maximal coordinates of the geometry will be set to -/+ half the number of rows/columns. + * + * If the object has been initialized before, the object is reinitialized and + * memory is freed and reallocated if necessary. + * + * @param _iGridColCount Number of columns in the volume grid. + * @param _iGridRowCount Number of rows in the volume grid. + * @return initialization successful + */ + bool initialize(int _iGridColCount, int _iGridRowCount); + + /** Initialization. Initializes an instance of the CVolumeGeometry2D class. + * + * If the object has been initialized before, the object is reinitialized and + * memory is freed and reallocated if necessary. + * + * @param _iGridColCount Number of columns in the volume grid. + * @param _iGridRowCount Number of rows in the volume grid. + * @param _fWindowMinX Minimal X-coordinate in the volume window. + * @param _fWindowMinY Minimal Y-coordinate in the volume window. + * @param _fWindowMaxX Maximal X-coordinate in the volume window. + * @param _fWindowMaxY Maximal Y-coordinate in the volume window. + * @return initialization successful + */ + bool initialize(int _iGridColCount, + int _iGridRowCount, + float32 _fWindowMinX, + float32 _fWindowMinY, + float32 _fWindowMaxX, + float32 _fWindowMaxY); + + /** Get the initialization state of the object. + * + * @return true iff the object has been initialized. + */ + bool isInitialized() const; + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(CVolumeGeometry2D*) const; + + /** Get the number of columns in the volume grid. + * + * @return Number of columns in the volume grid. + */ + int getGridColCount() const; + + /** Get the number of rows in the volume grid. + * + * @return Number of rows in the volume grid. + */ + int getGridRowCount() const; + + /** Get the total number of pixels in the volume grid. + * + * @return Total number of pixels. + */ + int getGridTotCount() const; + + /** Get the horizontal length of the volume window, in unit lengths. + * + * @return Horizontal length of the volume window. + */ + float32 getWindowLengthX() const; + + /** Get the vertical length of the volume window, in unit lengths. + * + * @return Vertical length of the volume window. + */ + float32 getWindowLengthY() const; + + /** Get the total area of the volume window, in unit lengths squared. + * + * @return Total area of the volume window. + */ + float32 getWindowArea() const; + + /** Get the horizontal length of a single pixel (i.e., width), in unit lengths. + * + * @return Horizontal length of a single pixel. + */ + float32 getPixelLengthX() const; + + /** Get the vertical length of a single pixel (i.e., height), in unit lengths. + * + * @return Vertical length of a single pixel. + */ + float32 getPixelLengthY() const; + + /** Get the area of a single pixel (width*height), in unit lengths squared. + * + * @return Area of a single pixel. + */ + float32 getPixelArea() const; + + /** Get the minimal X-coordinate in the volume window. + * + * @return Minimal X-coordinate in the volume window. + */ + float32 getWindowMinX() const; + + /** Get the minimal Y-coordinate in the volume window. + * + * @return Minimal Y-coordinate in the volume window. + */ + float32 getWindowMinY() const; + + /** Get the maximal X-coordinate in the volume window. + * + * @return Maximal X-coordinate in the volume window. + */ + float32 getWindowMaxX() const; + + /** Get the maximal Y-coordinate in the volume window. + * + * @return Maximal Y-coordinate in the volume window. + */ + float32 getWindowMaxY() const; + + /** Convert column and row index of a pixel to a single index in the interval [0..getGridTotCount()-1]. + * + * @param _iPixelCol Column index of the pixel, in the interval [0..getGridColCount()-1]. + * @param _iPixelRow Row index of the pixel, in the interval [0..getGridRowCount()-1]. + * @return Computed index of the pixel, in the interval [0..getGridTotCount()-1]. + */ + int pixelRowColToIndex(int _iPixelRow, int _iPixelCol) const; + + /** Convert a pixel index (from the interval [0..getGridTotCount()-1] to a column and row index. + * + * @param _iPixelIndex Index of the pixel, in the interval [0..getGridTotCount()-1]. + * @param _iPixelRow Computed row index of the pixel, in the interval [0..getGridRowCount()-1]. + * @param _iPixelCol Computed column index of the pixel, in the interval [0..getGridColCount()-1]. + */ + void pixelIndexToRowCol(int _iPixelIndex, int &_iPixelRow, int &_iPixelCol) const; + + /** Convert a pixel column index to the X-coordinate of its center. + * + * @param _iPixelCol Column index of the pixel. + * @return X-coordinate of the pixel center. + */ + float32 pixelColToCenterX(int _iPixelCol) const; + + /** Convert a pixel column index to the minimum X-coordinate of points in that column. + * + * @param _iPixelCol Column index of the pixel. + * @return Minimum X-coordinate. + */ + float32 pixelColToMinX(int _iPixelCol) const; + + /** Convert a pixel column index to the maximum X-coordinate of points in that column. + * + * @param _iPixelCol Column index of the pixel. + * @return Maximum X-coordinate. + */ + float32 pixelColToMaxX(int _iPixelCol) const; + + /** Convert a pixel row index to the Y-coordinate of its center. + * + * @param _iPixelRow Row index of the pixel. + * @return Y-coordinate of the pixel center. + */ + float32 pixelRowToCenterY(int _iPixelRow) const; + + /** Convert a pixel row index to the minimum Y-coordinate of points in that row. + * + * @param _iPixelRow Row index of the pixel. + * @return Minimum Y-coordinate. + */ + float32 pixelRowToMinY(int _iPixelRow) const; + + /** Convert a pixel row index to the maximum Y-coordinate of points in that row. + * + * @param _iPixelRow Row index of the pixel. + * @return Maximum Y-coordinate. + */ + float32 pixelRowToMaxY(int _iPixelRow) const; + + /** Convert an X-coordinate to a column index in the volume grid. + * + * @param _fCoordX X-coordinate. + * @return If the X-coordinate falls within a column of the volume grid, the column index is returned. + * Otherwise, a value of -1 is returned. + */ + int coordXToCol(float32 _fCoordX) const; + + /** Convert a Y-coordinate to a row index in the volume grid. + * + * @param _fCoordY Y-coordinate + * @return If the Y-coordinate falls within a row of the volume grid, the row index is returned. + * Otherwise, a value of -1 is returned. + */ + int coordYToRow(float32 _fCoordY) const; + + /** Convert an X-coordinate to an offset in the volume grid. + * WindowMinX is converted to 0. + * + * @param _fCoordX X-coordinate. + * @return The corresponding offset in the volume grid + */ + float coordXToColF(float32 _fCoordX) const; + + /** Convert a Y-coordinate to an offset in the volume grid. + * WindowMaxY is converted to 0. + * + * @param _fCoordY Y-coordinate + * @return The corresponding offset in the volume grid + */ + float coordYToRowF(float32 _fCoordY) const; + + + //< For Config unused argument checking + ConfigCheckData* configCheckData; + friend class ConfigStackCheck; +}; + + + +// Get the initialization state of the object. +inline bool CVolumeGeometry2D::isInitialized() const +{ + return m_bInitialized; +} + +// Get the number of columns in the volume grid. +inline int CVolumeGeometry2D::getGridColCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iGridColCount; +} + +// Get the number of rows in the volume grid. +inline int CVolumeGeometry2D::getGridRowCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iGridRowCount; +} + +// Get the total number of pixels in the volume window. +inline int CVolumeGeometry2D::getGridTotCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iGridTotCount; +} + +// Get the horizontal length of the volume window, in unit lengths. +inline float32 CVolumeGeometry2D::getWindowLengthX() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowLengthX; +} + +// Get the vertical length of the volume window, in unit lengths. +inline float32 CVolumeGeometry2D::getWindowLengthY() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowLengthY; +} + +// Get the total area of the volume window, in unit lengths squared. +inline float32 CVolumeGeometry2D::getWindowArea() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowArea; +} + +// Get the horizontal length of a single pixel (i.e., width), in unit lengths. +inline float32 CVolumeGeometry2D::getPixelLengthX() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fPixelLengthX; +} + +// Get the vertical length of a single pixel (i.e., height), in unit lengths. +inline float32 CVolumeGeometry2D::getPixelLengthY() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fPixelLengthY; +} + +// Get the area of a single pixel (width*height), in unit lengths squared. +inline float32 CVolumeGeometry2D::getPixelArea() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fPixelArea; +} + + // Get the minimal X-coordinate in the volume window. +inline float32 CVolumeGeometry2D::getWindowMinX() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowMinX; +} + + // Get the minimal Y-coordinate in the volume window. +inline float32 CVolumeGeometry2D::getWindowMinY() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowMinY; +} + + // Get the maximal X-coordinate in the volume window. +inline float32 CVolumeGeometry2D::getWindowMaxX() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowMaxX; +} + + // Get the maximal Y-coordinate in the volume window. +inline float32 CVolumeGeometry2D::getWindowMaxY() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowMaxY; +} + +// Convert column and row index of a pixel to a single index in the interval [0..getGridCountTot()-1]. +inline int CVolumeGeometry2D::pixelRowColToIndex(int _iPixelRow, int _iPixelCol) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelCol >= 0); + ASTRA_ASSERT(_iPixelCol < m_iGridColCount); + ASTRA_ASSERT(_iPixelRow >= 0); + ASTRA_ASSERT(_iPixelRow < m_iGridRowCount); + return (_iPixelRow * m_iGridColCount + _iPixelCol); +} + + +// Convert a pixel index (from the interval [0..getGridCountTot()-1] to a column and row index. +inline void CVolumeGeometry2D::pixelIndexToRowCol(int _iPixelIndex, int &_iPixelRow, int &_iPixelCol) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelIndex >= 0); + ASTRA_ASSERT(_iPixelIndex < m_iGridTotCount); + + _iPixelCol = (_iPixelIndex % m_iGridColCount); + _iPixelRow = (_iPixelIndex / m_iGridColCount); +} + +// Convert a pixel column index to the X-coordinate of its center +inline float32 CVolumeGeometry2D::pixelColToCenterX(int _iPixelCol) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelCol >= 0); + ASTRA_ASSERT(_iPixelCol < m_iGridColCount); + + return (m_fWindowMinX + (float32(_iPixelCol) + 0.5f) * m_fPixelLengthX); +} + +// Convert a pixel column index to the minimum X-coordinate of points in that column +inline float32 CVolumeGeometry2D::pixelColToMinX(int _iPixelCol) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelCol >= 0); + ASTRA_ASSERT(_iPixelCol < m_iGridColCount); + + return (m_fWindowMinX + float32(_iPixelCol) * m_fPixelLengthX); +} + +// Convert a pixel column index to the maximum X-coordinate of points in that column +inline float32 CVolumeGeometry2D::pixelColToMaxX(int _iPixelCol) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelCol >= 0); + ASTRA_ASSERT(_iPixelCol < m_iGridColCount); + + return (m_fWindowMinX + (float32(_iPixelCol) + 1.0f) * m_fPixelLengthX); +} + +// Convert a pixel row index to the Y-coordinate of its center +inline float32 CVolumeGeometry2D::pixelRowToCenterY(int _iPixelRow) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelRow >= 0); + ASTRA_ASSERT(_iPixelRow < m_iGridRowCount); + + return (m_fWindowMaxY - (float32(_iPixelRow) + 0.5f) * m_fPixelLengthY); +} + +// Convert a pixel row index to the minimum Y-coordinate of points in that row +inline float32 CVolumeGeometry2D::pixelRowToMinY(int _iPixelRow) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelRow >= 0); + ASTRA_ASSERT(_iPixelRow < m_iGridRowCount); + + return (m_fWindowMaxY - (float32(_iPixelRow) + 1.0f) * m_fPixelLengthY); +} + +// Convert a pixel row index to the maximum Y-coordinate of points in that row +inline float32 CVolumeGeometry2D::pixelRowToMaxY(int _iPixelRow) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelRow >= 0); + ASTRA_ASSERT(_iPixelRow < m_iGridRowCount); + + return (m_fWindowMaxY - (float32(_iPixelRow) * m_fPixelLengthY)); +} + +// Convert an X-coordinate to a column index in the volume grid +inline int CVolumeGeometry2D::coordXToCol(float32 _fCoordX) const +{ + if (_fCoordX < m_fWindowMinX) return -1; + if (_fCoordX > m_fWindowMaxX) return -1; + + int iCol = int((_fCoordX - m_fWindowMinX) * m_fDivPixelLengthX); + ASTRA_ASSERT(iCol >= 0); + ASTRA_ASSERT(iCol < m_iGridColCount); + + return iCol; +} + +// Convert a Y-coordinate to a row index in the volume grid +inline int CVolumeGeometry2D::coordYToRow(float32 _fCoordY) const +{ + if (_fCoordY < m_fWindowMinY) return -1; + if (_fCoordY > m_fWindowMaxY) return -1; + + int iRow = int((m_fWindowMaxY - _fCoordY) * m_fDivPixelLengthY); + ASTRA_ASSERT(iRow >= 0); + ASTRA_ASSERT(iRow < m_iGridRowCount); + + return iRow; +} + +// Convert an X-coordinate to an offset in the volume grid +// (WindowMinX is converted to 0) +inline float CVolumeGeometry2D::coordXToColF(float32 _fCoordX) const +{ + return (_fCoordX - m_fWindowMinX) * m_fDivPixelLengthX; +} + +// Convert a Y-coordinate to an offset in the volume grid +// (WindowMaxY is converted to 0) +inline float CVolumeGeometry2D::coordYToRowF(float32 _fCoordY) const +{ + return (m_fWindowMaxY - _fCoordY) * m_fDivPixelLengthY; +} + + + +} // end namespace astra + +#endif /* _INC_ASTRA_VOLUMEGEOMETRY2D */ diff --git a/include/astra/VolumeGeometry3D.h b/include/astra/VolumeGeometry3D.h new file mode 100644 index 0000000..4ca8042 --- /dev/null +++ b/include/astra/VolumeGeometry3D.h @@ -0,0 +1,842 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_VOLUMEGEOMETRY3D +#define _INC_ASTRA_VOLUMEGEOMETRY3D + +#include "Globals.h" +#include "Config.h" +#include "VolumeGeometry2D.h" + +namespace astra +{ + +/** + * This class represents a 3D pixel grid that is placed in the geometry. It defines a rectangular volume window. + * + * \par XML Configuration + * \astra_xml_item{GridColCount, integer, Number of columns in this geometry.} + * \astra_xml_item{GridRowCount, integer, Number of rows in this geometry.} + * \astra_xml_item{GridSliceCount, integer, Number of slices in this geometry.} + * \astra_xml_item_option{WindowMinX, float, -GridColCount/2, Minimal X-coordinate in the volume window.} + * \astra_xml_item_option{WindowMaxX, float, GridColCount/2, Maximal X-coordinate in the volume window.} + * \astra_xml_item_option{WindowMinY, float, -GridRowCount/2, Minimal Y-coordinate in the volume window.} + * \astra_xml_item_option{WindowMaxY, float, GridRowCount/2, Maximal Y-coordinate in the volume window.} + * \astra_xml_item_option{WindowMinZ, float, -GridSliceCount/2, Minimal Z-coordinate in the volume window.} + * \astra_xml_item_option{WindowMaxZ, float, GridSliceCount/2, Maximal Z-coordinate in the volume window.} + * + * \par MATLAB example + * \astra_code{ + * vol_geom = struct();\n + * vol_geom.GridColCount = 1024;\n + * vol_geom.GridRowCount = 768;\n + * vol_geom.GridSliceCount = 300;\n + * vol_geom.option.WindowMinX = -512;\n + * vol_geom.option.WindowMaxX = -384;\n + * vol_geom.option.WindowMinY = 512;\n + * vol_geom.option.WindowMaxY = 384;\n + * vol_geom.option.WindowMinZ = -150;\n + * vol_geom.option.WindowMaxZ = 150;\n + * } + */ +class _AstraExport CVolumeGeometry3D { + +protected: + bool m_bInitialized; ///< Has this object been initialized? + + int m_iGridColCount; ///< number of columns in the volume grid. + int m_iGridRowCount; ///< number of rows in the volume grid. + int m_iGridSliceCount; ///< number of slices in the volume grid. + int m_iGridTotCount; ///< total number of pixels in the volume grid (= m_iGridColCount * m_iGridRowCount * m_iGridSliceCount). + + /** Width of the volume window, in unit lengths. + * + * Note that this width is independent of the number of pixels in the X-direction, as the width of a pixel can + * be different from 1. + */ + float32 m_fWindowLengthX; + + /** Height of the volume window, in unit lengths. + * + * Note that this height is independent of the number of pixels in the Y-direction, as the height of a pixel can + * be different from 1. + */ + float32 m_fWindowLengthY; + + /** Depth of the volume window, in unit lengths. + * + * Note that this depth is independent of the number of pixels in the Z-direction, as the depth of a pixel can + * be different from 1. + */ + float32 m_fWindowLengthZ; + + /** Total area of the volume window, in unit lengths squared. + */ + float32 m_fWindowArea; + + float32 m_fPixelLengthX; ///< Width of a single pixel, in unit lengths. + float32 m_fPixelLengthY; ///< Height of a single pixel, in unit lengths. + float32 m_fPixelLengthZ; ///< Depth of a single pixel, in unit lengths. + float32 m_fPixelArea; ///< Area of a single pixel, in unit lengths squared. + + float32 m_fDivPixelLengthX; ///< 1/m_fPixelLengthX, used for fast division. + float32 m_fDivPixelLengthY; ///< 1/m_fPixelLengthY, used for fast division. + float32 m_fDivPixelLengthZ; ///< 1/m_fPixelLengthZ, used for fast division. + + float32 m_fWindowMinX; ///< Minimal X-coordinate in the volume window. + float32 m_fWindowMinY; ///< Minimal Y-coordinate in the volume window. + float32 m_fWindowMinZ; ///< Minimal Z-coordinate in the volume window. + float32 m_fWindowMaxX; ///< Maximal X-coordinate in the volume window. + float32 m_fWindowMaxY; ///< Maximal Y-coordinate in the volume window. + float32 m_fWindowMaxZ; ///< Maximal Z-coordinate in the volume window. + + /** Check the values of this object. If everything is ok, the object can be set to the initialized state. + * The following statements are then guaranteed to hold: + * - number of rows, columns and slices is larger than zero + * - window minima is smaller than window maxima + * - m_iGridTotCount, m_fWindowLengthX, m_fWindowLengthY, m_fWindowLengthZ, m_fWindowArea, m_fPixelLengthX, + * m_fPixelLengthY, m_fPixelLengthZ, m_fPixelArea, m_fDivPixelLengthX, m_fDivPixelLengthY + * and m_fDivPixelLengthZ are initialized ok + */ + bool _check(); + +public: + + /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL. + * + * If an object is constructed using this default constructor, it must always be followed by a call + * to one of the init() methods before the object can be used. Any use before calling init() is not allowed, + * except calling the member function isInitialized(). + */ + CVolumeGeometry3D(); + + /** Constructor. Create an instance of the CVolumeGeometry2D class. + * The minimal and coordinates values of the geometry will be set to -/+ the number of rows/columns. + * + * @param _iGridCountX Number of columns in the volume grid. + * @param _iGridCountY Number of rows in the volume grid. + * @param _iGridCountZ Number of slices in the volume grid. + */ + CVolumeGeometry3D(int _iGridCountX, int _iGridCountY, int _iGridCountZ); + + /** Constructor. Create an instance of the CVolumeGeometry2D class. + * + * @param _iGridCountX Number of columns in the volume grid. + * @param _iGridCountY Number of rows in the volume grid. + * @param _iGridCountZ Number of slices in the volume grid. + * @param _fWindowMinX Minimal X-coordinate in the volume window. + * @param _fWindowMinY Minimal Y-coordinate in the volume window. + * @param _fWindowMinZ Minimal Z-coordinate in the volume window. + * @param _fWindowMaxX Maximal X-coordinate in the volume window. + * @param _fWindowMaxY Maximal Y-coordinate in the volume window. + * @param _fWindowMaxZ Maximal Z-coordinate in the volume window. + */ + CVolumeGeometry3D(int _iGridCountX, + int _iGridCountY, + int _iGridCountZ, + float32 _fWindowMinX, + float32 _fWindowMinY, + float32 _fWindowMinZ, + float32 _fWindowMaxX, + float32 _fWindowMaxY, + float32 _fWindowMaxZ); + + /** + * Copy constructor + */ + CVolumeGeometry3D(const CVolumeGeometry3D& _other); + + /** + * Assignment operator + */ + CVolumeGeometry3D& operator=(const CVolumeGeometry3D& _other); + + /** Destructor. + */ + virtual ~CVolumeGeometry3D(); + + /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. + */ + void clear(); + + /** Create a hard copy. + */ + CVolumeGeometry3D* clone() const; + + /** Initialize the volume geometry with a config object. + * + * @param _cfg Configuration Object. + * @return initialization successful? + */ + virtual bool initialize(const Config& _cfg); + + /** Initialization. Initializes an instance of the CVolumeGeometry3D class. + * The minimal and maximal coordinates of the geometry will be set to -/+ half the number of rows/columns/slices. + * + * If the object has been initialized before, the object is reinitialized and + * memory is freed and reallocated if necessary. + * + * @param _iGridColCount Number of columns in the volume grid. + * @param _iGridRowCount Number of rows in the volume grid. + * @param _iGridSliceCount Number of slices in the volume grid. + * @return initialization successful + */ + bool initialize(int _iGridColCount, int _iGridRowCount, int _iGridSliceCount); + + /** Initialization. Initializes an instance of the CVolumeGeometry3D class. + * + * If the object has been initialized before, the object is reinitialized and + * memory is freed and reallocated if necessary. + * + * @param _iGridColCount Number of columns in the volume grid. + * @param _iGridRowCount Number of rows in the volume grid. + * @param _iGridSliceCount Number of slices in the volume grid. + * @param _fWindowMinX Minimal X-coordinate in the volume window. + * @param _fWindowMinY Minimal Y-coordinate in the volume window. + * @param _fWindowMinZ Minimal Z-coordinate in the volume window. + * @param _fWindowMaxX Maximal X-coordinate in the volume window. + * @param _fWindowMaxY Maximal Y-coordinate in the volume window. + * @param _fWindowMaxZ Maximal Z-coordinate in the volume window. + * @return initialization successful + */ + bool initialize(int _iGridColCount, + int _iGridRowCount, + int _iGridSliceCount, + float32 _fWindowMinX, + float32 _fWindowMinY, + float32 _fWindowMinZ, + float32 _fWindowMaxX, + float32 _fWindowMaxY, + float32 _fWindowMaxZ); + + /** Get the initialization state of the object. + * + * @return true iff the object has been initialized. + */ + bool isInitialized() const; + + /** Return true if this geometry instance is the same as the one specified. + * + * @return true if this geometry instance is the same as the one specified. + */ + virtual bool isEqual(const CVolumeGeometry3D*) const; + + /** Get the number of columns in the volume grid. + * + * @return Number of columns in the volume grid. + */ + int getGridColCount() const; + + /** Get the number of rows in the volume grid. + * + * @return Number of rows in the volume grid. + */ + int getGridRowCount() const; + + /** Get the number of slices in the volume grid. + * + * @return Number of slices in the volume grid. + */ + int getGridSliceCount() const; + + /** Get the total number of pixels in the volume grid. + * + * @return Total number of pixels. + */ + int getGridTotCount() const; + + /** Get the horizontal length of the volume window, in unit lengths. + * + * @return Horizontal length of the volume window. + */ + float32 getWindowLengthX() const; + + /** Get the vertical length of the volume window, in unit lengths. + * + * @return Vertical length of the volume window. + */ + float32 getWindowLengthY() const; + + /** Get the depth of the volume window, in unit lengths. + * + * @return Depth of the volume window. + */ + float32 getWindowLengthZ() const; + + /** Get the total area of the volume window, in unit lengths squared. + * + * @return Total area of the volume window. + */ + float32 getWindowArea() const; + + /** Get the horizontal length of a single pixel (i.e., width), in unit lengths. + * + * @return Horizontal length of a single pixel. + */ + float32 getPixelLengthX() const; + + /** Get the vertical length of a single pixel (i.e., height), in unit lengths. + * + * @return Vertical length of a single pixel. + */ + float32 getPixelLengthY() const; + + /** Get the depth of a single pixel in unit lengths. + * + * @return Depth of a single pixel. + */ + float32 getPixelLengthZ() const; + + /** Get the area of a single pixel (width*height*depth), in unit lengths squared. + * + * @return Area of a single pixel. + */ + float32 getPixelArea() const; + + /** Get the minimal X-coordinate in the volume window. + * + * @return Minimal X-coordinate in the volume window. + */ + float32 getWindowMinX() const; + + /** Get the minimal Y-coordinate in the volume window. + * + * @return Minimal Y-coordinate in the volume window. + */ + float32 getWindowMinY() const; + + /** Get the minimal Z-coordinate in the volume window. + * + * @return Minimal Z-coordinate in the volume window. + */ + float32 getWindowMinZ() const; + + /** Get the maximal X-coordinate in the volume window. + * + * @return Maximal X-coordinate in the volume window. + */ + float32 getWindowMaxX() const; + + /** Get the maximal Y-coordinate in the volume window. + * + * @return Maximal Y-coordinate in the volume window. + */ + float32 getWindowMaxY() const; + + /** Get the maximal Z-coordinate in the volume window. + * + * @return Maximal Z-coordinate in the volume window. + */ + float32 getWindowMaxZ() const; + + /** Convert row, column and slice index of a pixel to a single index in the interval [0..getGridTotCount()-1]. + * + * @param _iPixelRow Row index of the pixel, in the interval [0..getGridRowCount()-1]. + * @param _iPixelCol Column index of the pixel, in the interval [0..getGridColCount()-1]. + * @param _iPixelSlice Slice index of the pixel, in the interval [0..getGridSliceCount()-1]. + * @return Computed index of the pixel, in the interval [0..getGridTotCount()-1]. + */ + int pixelRowColSliceToIndex(int _iPixelRow, int _iPixelCol, int _iPixelSlice) const; + + /** Convert a pixel index (from the interval [0..getGridTotCount()-1] to row, column and slice index. + * + * @param _iPixelIndex Index of the pixel, in the interval [0..getGridTotCount()-1]. + * @param _iPixelRow Computed row index of the pixel, in the interval [0..getGridRowCount()-1]. + * @param _iPixelCol Computed column index of the pixel, in the interval [0..getGridColCount()-1]. + * @param _iPixelSlice Computed slice index of the pixel, in the interval [0..getGridSliceCount()-1]. + */ + void pixelIndexToRowColSlice(int _iPixelIndex, int &_iPixelRow, int &_iPixelCol, int &_iPixelSlice) const; + + /** Convert a pixel column index to the X-coordinate of its center. + * + * @param _iPixelCol Column index of the pixel. + * @return X-coordinate of the pixel center. + */ + float32 pixelColToCenterX(int _iPixelCol) const; + + /** Convert a pixel column index to the minimum X-coordinate of points in that column. + * + * @param _iPixelCol Column index of the pixel. + * @return Minimum X-coordinate. + */ + float32 pixelColToMinX(int _iPixelCol) const; + + /** Convert a pixel column index to the maximum X-coordinate of points in that column. + * + * @param _iPixelCol Column index of the pixel. + * @return Maximum X-coordinate. + */ + float32 pixelColToMaxX(int _iPixelCol) const; + + /** Convert a pixel row index to the Y-coordinate of its center. + * + * @param _iPixelRow Row index of the pixel. + * @return Y-coordinate of the pixel center. + */ + float32 pixelRowToCenterY(int _iPixelRow) const; + + /** Convert a pixel row index to the minimum Y-coordinate of points in that row. + * + * @param _iPixelRow Row index of the pixel. + * @return Minimum Y-coordinate. + */ + float32 pixelRowToMinY(int _iPixelRow) const; + + /** Convert a pixel row index to the maximum Y-coordinate of points in that row. + * + * @param _iPixelRow Row index of the pixel. + * @return Maximum Y-coordinate. + */ + float32 pixelRowToMaxY(int _iPixelRow) const; + + /** Convert a pixel slice index to the Z-coordinate of its center. + * + * @param _iPixelSlice Slice index of the pixel. + * @return Z-coordinate of the pixel center. + */ + float32 pixelSliceToCenterZ(int _iPixelSlice) const; + + /** Convert a pixel slice index to the minimum Z-coordinate of points in that slice. + * + * @param _iPixelSlice Slice index of the pixel. + * @return Minimum Z-coordinate. + */ + float32 pixelSliceToMinZ(int _iPixelSlice) const; + + /** Convert a pixel slice index to the maximum Z-coordinate of points in that slice. + * + * @param _iPixelSlice Slice index of the pixel. + * @return Maximum Z-coordinate. + */ + float32 pixelSliceToMaxZ(int _iPixelSlice) const; + + /** Convert an X-coordinate to a column index in the volume grid. + * + * @param _fCoordX X-coordinate. + * @return If the X-coordinate falls within a column of the volume grid, the column index is returned. + * Otherwise, a value of -1 is returned. + */ + int coordXToCol(float32 _fCoordX) const; + + /** Convert a Y-coordinate to a row index in the volume grid. + * + * @param _fCoordY Y-coordinate + * @return If the Y-coordinate falls within a row of the volume grid, the row index is returned. + * Otherwise, a value of -1 is returned. + */ + int coordYToRow(float32 _fCoordY) const; + + /** Convert a Z-coordinate to a slice index in the volume grid. + * + * @param _fCoordZ Z-coordinate + * @return If the Z-coordinate falls within a slice of the volume grid, the slice index is returned. + * Otherwise, a value of -1 is returned. + */ + int coordZToSlice(float32 _fCoordZ) const; + + /** Convert an X-coordinate to a column index in the volume grid. + * + * @param _fCoordX X-coordinate. + * @return If the X-coordinate falls within a column of the volume grid, the column index is returned. + * Otherwise, a value of -1 is returned. + */ + float32 coordXToColFloat(float32 _fCoordX) const; + + /** Convert a Y-coordinate to a row index in the volume grid. + * + * @param _fCoordY Y-coordinate + * @return If the Y-coordinate falls within a row of the volume grid, the row index is returned. + * Otherwise, a value of -1 is returned. + */ + float32 coordYToRowFloat(float32 _fCoordY) const; + + /** Convert a Z-coordinate to a slice index in the volume grid. + * + * @param _fCoordZ Z-coordinate + * @return If the Z-coordinate falls within a slice of the volume grid, the slice index is returned. + * Otherwise, a value of -1 is returned. + */ + float32 coordZToSliceFloat(float32 _fCoordZ) const; + + CVolumeGeometry2D * createVolumeGeometry2D() const; + + + //< For Config unused argument checking + ConfigCheckData* configCheckData; + friend class ConfigStackCheck; +}; + + +//---------------------------------------------------------------------------------------- +// Get the initialization state of the object. +inline bool CVolumeGeometry3D::isInitialized() const +{ + return m_bInitialized; +} + +//---------------------------------------------------------------------------------------- +// Get the number of columns in the volume grid. +inline int CVolumeGeometry3D::getGridColCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iGridColCount; +} + +//---------------------------------------------------------------------------------------- +// Get the number of rows in the volume grid. +inline int CVolumeGeometry3D::getGridRowCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iGridRowCount; +} + +//---------------------------------------------------------------------------------------- +// Get the number of rows in the volume grid. +inline int CVolumeGeometry3D::getGridSliceCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iGridSliceCount; +} + +//---------------------------------------------------------------------------------------- +// Get the total number of pixels in the volume window. +inline int CVolumeGeometry3D::getGridTotCount() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_iGridTotCount; +} + +//---------------------------------------------------------------------------------------- +// Get the horizontal length of the volume window, in unit lengths. +inline float32 CVolumeGeometry3D::getWindowLengthX() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowLengthX; +} + +//---------------------------------------------------------------------------------------- +// Get the vertical length of the volume window, in unit lengths. +inline float32 CVolumeGeometry3D::getWindowLengthY() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowLengthY; +} + +//---------------------------------------------------------------------------------------- +// Get the vertical length of the volume window, in unit lengths. +inline float32 CVolumeGeometry3D::getWindowLengthZ() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowLengthZ; +} + +//---------------------------------------------------------------------------------------- +// Get the total area of the volume window, in unit lengths squared. +inline float32 CVolumeGeometry3D::getWindowArea() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowArea; +} + +//---------------------------------------------------------------------------------------- +// Get the horizontal length of a single pixel (i.e., width), in unit lengths. +inline float32 CVolumeGeometry3D::getPixelLengthX() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fPixelLengthX; +} + +//---------------------------------------------------------------------------------------- +// Get the vertical length of a single pixel (i.e., height), in unit lengths. +inline float32 CVolumeGeometry3D::getPixelLengthY() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fPixelLengthY; +} + +//---------------------------------------------------------------------------------------- +// Get the depth of a single pixel in unit lengths. +inline float32 CVolumeGeometry3D::getPixelLengthZ() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fPixelLengthZ; +} + +//---------------------------------------------------------------------------------------- +// Get the area of a single pixel (width*height), in unit lengths squared. +inline float32 CVolumeGeometry3D::getPixelArea() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fPixelArea; +} + +//---------------------------------------------------------------------------------------- +// Get the minimal X-coordinate in the volume window. +inline float32 CVolumeGeometry3D::getWindowMinX() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowMinX; +} + +//---------------------------------------------------------------------------------------- +// Get the minimal Y-coordinate in the volume window. +inline float32 CVolumeGeometry3D::getWindowMinY() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowMinY; +} + +//---------------------------------------------------------------------------------------- +// Get the minimal Y-coordinate in the volume window. +inline float32 CVolumeGeometry3D::getWindowMinZ() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowMinZ; +} + +//---------------------------------------------------------------------------------------- +// Get the maximal X-coordinate in the volume window. +inline float32 CVolumeGeometry3D::getWindowMaxX() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowMaxX; +} + +//---------------------------------------------------------------------------------------- +// Get the maximal Y-coordinate in the volume window. +inline float32 CVolumeGeometry3D::getWindowMaxY() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowMaxY; +} + +//---------------------------------------------------------------------------------------- +// Get the maximal Z-coordinate in the volume window. +inline float32 CVolumeGeometry3D::getWindowMaxZ() const +{ + ASTRA_ASSERT(m_bInitialized); + return m_fWindowMaxZ; +} + +//---------------------------------------------------------------------------------------- +// Convert row, column and slice index of a pixel to a single index in the interval [0..getGridCountTot()-1]. +inline int CVolumeGeometry3D::pixelRowColSliceToIndex(int _iPixelRow, int _iPixelCol, int _iPixelSlice) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelCol >= 0); + ASTRA_ASSERT(_iPixelCol < m_iGridColCount); + ASTRA_ASSERT(_iPixelRow >= 0); + ASTRA_ASSERT(_iPixelRow < m_iGridRowCount); + ASTRA_ASSERT(_iPixelSlice >= 0); + ASTRA_ASSERT(_iPixelSlice < m_iGridSliceCount); + + return (m_iGridColCount*m_iGridRowCount*_iPixelSlice + _iPixelRow * m_iGridColCount + _iPixelCol); +} + +//---------------------------------------------------------------------------------------- +// Convert a pixel index (from the interval [0..getGridCountTot()-1] to a row, column and slice index. +inline void CVolumeGeometry3D::pixelIndexToRowColSlice(int _iPixelIndex, int &_iPixelRow, int &_iPixelCol, int &_iPixelSlice) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelIndex >= 0); + ASTRA_ASSERT(_iPixelIndex < m_iGridTotCount); + + _iPixelSlice = _iPixelIndex / (m_iGridRowCount*m_iGridColCount); + _iPixelRow = (_iPixelIndex-_iPixelSlice*m_iGridRowCount*m_iGridColCount) / m_iGridColCount; + _iPixelCol = (_iPixelIndex-_iPixelSlice*m_iGridRowCount*m_iGridColCount) % m_iGridColCount; +} + +//---------------------------------------------------------------------------------------- +// Convert a pixel column index to the X-coordinate of its center +inline float32 CVolumeGeometry3D::pixelColToCenterX(int _iPixelCol) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelCol >= 0); + ASTRA_ASSERT(_iPixelCol < m_iGridColCount); + + return (m_fWindowMinX + (float32(_iPixelCol) + 0.5f) * m_fPixelLengthX); +} + +//---------------------------------------------------------------------------------------- +// Convert a pixel column index to the minimum X-coordinate of points in that column +inline float32 CVolumeGeometry3D::pixelColToMinX(int _iPixelCol) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelCol >= 0); + ASTRA_ASSERT(_iPixelCol < m_iGridColCount); + + return (m_fWindowMinX + float32(_iPixelCol) * m_fPixelLengthX); +} + +//---------------------------------------------------------------------------------------- +// Convert a pixel column index to the maximum X-coordinate of points in that column +inline float32 CVolumeGeometry3D::pixelColToMaxX(int _iPixelCol) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelCol >= 0); + ASTRA_ASSERT(_iPixelCol < m_iGridColCount); + + return (m_fWindowMaxX + (float32(_iPixelCol) + 1.0f) * m_fPixelLengthX); +} + +//---------------------------------------------------------------------------------------- +// Convert a pixel row index to the Y-coordinate of its center +inline float32 CVolumeGeometry3D::pixelRowToCenterY(int _iPixelRow) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelRow >= 0); + ASTRA_ASSERT(_iPixelRow < m_iGridRowCount); + + return (m_fWindowMaxY - (float32(_iPixelRow) + 0.5f) * m_fPixelLengthY); +} + +//---------------------------------------------------------------------------------------- +// Convert a pixel row index to the minimum Y-coordinate of points in that row +inline float32 CVolumeGeometry3D::pixelRowToMinY(int _iPixelRow) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelRow >= 0); + ASTRA_ASSERT(_iPixelRow < m_iGridRowCount); + + return (m_fWindowMaxY - (float32(_iPixelRow) + 1.0f) * m_fPixelLengthY); +} + +//---------------------------------------------------------------------------------------- +// Convert a pixel row index to the maximum Y-coordinate of points in that row +inline float32 CVolumeGeometry3D::pixelRowToMaxY(int _iPixelRow) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelRow >= 0); + ASTRA_ASSERT(_iPixelRow < m_iGridRowCount); + + return (m_fWindowMaxY - (float32(_iPixelRow) * m_fPixelLengthY)); +} + +//---------------------------------------------------------------------------------------- +// Convert a pixel slice index to the Z-coordinate of its center +inline float32 CVolumeGeometry3D::pixelSliceToCenterZ(int _iPixelSlice) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelSlice >= 0); + ASTRA_ASSERT(_iPixelSlice < m_iGridSliceCount); + + return (m_fWindowMaxZ - (float32(_iPixelSlice) + 0.5f) * m_fPixelLengthZ); +} + +//---------------------------------------------------------------------------------------- +// Convert a pixel row index to the minimum Y-coordinate of points in that row +inline float32 CVolumeGeometry3D::pixelSliceToMinZ(int _iPixelSlice) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelSlice >= 0); + ASTRA_ASSERT(_iPixelSlice < m_iGridSliceCount); + + return (m_fWindowMaxZ - (float32(_iPixelSlice) + 1.0f) * m_fPixelLengthZ); +} + +//---------------------------------------------------------------------------------------- +// Convert a pixel row index to the maximum Y-coordinate of points in that row +inline float32 CVolumeGeometry3D::pixelSliceToMaxZ(int _iPixelSlice) const +{ + ASTRA_ASSERT(m_bInitialized); + ASTRA_ASSERT(_iPixelSlice >= 0); + ASTRA_ASSERT(_iPixelSlice < m_iGridSliceCount); + + return (m_fWindowMaxZ - (float32(_iPixelSlice) * m_fPixelLengthZ)); +} + +//---------------------------------------------------------------------------------------- +// Convert an X-coordinate to a column index in the volume grid +inline int CVolumeGeometry3D::coordXToCol(float32 _fCoordX) const +{ + if (_fCoordX < m_fWindowMinX) return -1; + if (_fCoordX > m_fWindowMaxX) return -1; + + int iCol = int((_fCoordX - m_fWindowMinX) * m_fDivPixelLengthX); + ASTRA_ASSERT(iCol >= 0); + ASTRA_ASSERT(iCol < m_iGridColCount); + + return iCol; +} + +//---------------------------------------------------------------------------------------- +// Convert a Y-coordinate to a row index in the volume grid +inline int CVolumeGeometry3D::coordYToRow(float32 _fCoordY) const +{ + if (_fCoordY < m_fWindowMinY) return -1; + if (_fCoordY > m_fWindowMaxY) return -1; + + int iRow = int((m_fWindowMaxY - _fCoordY) * m_fDivPixelLengthY); + ASTRA_ASSERT(iRow >= 0); + ASTRA_ASSERT(iRow < m_iGridRowCount); + + return iRow; +} + +//---------------------------------------------------------------------------------------- +// Convert a Z-coordinate to a slice index in the volume grid +inline int CVolumeGeometry3D::coordZToSlice(float32 _fCoordZ) const +{ + if (_fCoordZ < m_fWindowMinZ) return -1; + if (_fCoordZ > m_fWindowMaxZ) return -1; + + int iSlice = int((m_fWindowMaxZ - _fCoordZ) * m_fDivPixelLengthZ); + ASTRA_ASSERT(iSlice >= 0); + ASTRA_ASSERT(iSlice < m_iGridSliceCount); + + return iSlice; +} + +//---------------------------------------------------------------------------------------- +// Convert an X-coordinate to a column index in the volume grid +inline float32 CVolumeGeometry3D::coordXToColFloat(float32 _fCoordX) const +{ + ASTRA_ASSERT(m_bInitialized); + return (_fCoordX - m_fWindowMinX) * m_fDivPixelLengthX; +} + +//---------------------------------------------------------------------------------------- +// Convert a Y-coordinate to a row index in the volume grid +inline float32 CVolumeGeometry3D::coordYToRowFloat(float32 _fCoordY) const +{ + ASTRA_ASSERT(m_bInitialized); + return (m_fWindowMaxY - _fCoordY) * m_fDivPixelLengthY; +} + +//---------------------------------------------------------------------------------------- +// Convert a Z-coordinate to a slice index in the volume grid +inline float32 CVolumeGeometry3D::coordZToSliceFloat(float32 _fCoordZ) const +{ + ASTRA_ASSERT(m_bInitialized); + return (m_fWindowMaxZ - _fCoordZ) * m_fDivPixelLengthZ; +} +//---------------------------------------------------------------------------------------- + +} // end namespace astra + +#endif /* _INC_ASTRA_VOLUMEGEOMETRY2D */ diff --git a/include/astra/XMLDocument.h b/include/astra/XMLDocument.h new file mode 100644 index 0000000..dbcc679 --- /dev/null +++ b/include/astra/XMLDocument.h @@ -0,0 +1,101 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_XMLDOCUMENT +#define _INC_ASTRA_XMLDOCUMENT + +#include + +#if 1 +namespace rapidxml { + template class xml_document; +} +#else +#include "rapidxml.hpp" +#endif + +#include "Globals.h" +#include "XMLNode.h" + +using namespace std; + +namespace astra { + +/** This class encapsulates an XML Document of the Xerces DOM Parser. + */ +class _AstraExport XMLDocument { + +public: + + /** Default Constructor + */ + XMLDocument(); + + /** Destructor + */ + ~XMLDocument(); + + /** Construct an XML DOM tree and Document from an XML file + * + * @param sFilename Location of the XML file. + * @return XML Document containing the DOM tree + */ + static XMLDocument* readFromFile(string sFilename); + + /** Construct an empty XML DOM tree with a specific root tag. + * + * @param sRootName Element name of the root tag. + * @return XML Document with an empty root node + */ + static XMLDocument* createDocument(string sRootName); + + /** Get the rootnode of the XML document + * + * @return first XML node of the document + */ + XMLNode* getRootNode(); + + /** Save an XML DOM tree to an XML file + * + * @param sFilename Location of the XML file. + */ + void saveToFile(string sFilename); + + +private: + + //!< Document of rapidxml + rapidxml::xml_document* fDOMDocument; + + std::string fBuf; + +}; + +} // end namespace + +#endif diff --git a/include/astra/XMLNode.h b/include/astra/XMLNode.h new file mode 100644 index 0000000..3ed6417 --- /dev/null +++ b/include/astra/XMLNode.h @@ -0,0 +1,325 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_XMLNODE +#define _INC_ASTRA_XMLNODE + +#include +#include +#include + +#if 1 +namespace rapidxml { + template class xml_node; +} +#else +#include "rapidxml.hpp" +#endif + +#include "Globals.h" +#include "Utilities.h" + +using namespace std; + +namespace astra { + +/** + * This class encapsulates an XML Node of the Xerces DOM Parser. + */ +class _AstraExport XMLNode { + +friend class XMLDocument; + +public: + + /** Default Constructor + */ + XMLNode(); + + /** Deconstructor + */ + ~XMLNode(); + + + /** Get a single child XML node. If there are more, the first one is returned + * + * @param _sName tagname of the requested child node + * @return first child node with the correct tagname, null pointer if it doesn't exist + */ + XMLNode* getSingleNode(string _sName); + + /** Get all child XML nodes that have the tagname name + * + * @param _sName tagname of the requested child nodes + * @return list with all child nodes with the correct tagname + */ + std::list getNodes(string _sName); + + /** Get all child XML nodes + * + * @return list with all child nodes + */ + std::list getNodes(); + + /** Get the name of this node + * + * @return name of node + */ + std::string getName(); + + /** Get the content of the XML node as a single string. + * + * @return node content + */ + string getContent(); + + /** Get the content of the XML node as a numerical. + * + * @return node content + */ + float32 getContentNumerical(); + + /** Get the content of the XML node as a boolean. + * + * @return node content + */ + bool getContentBool(); + + /** Get the content of the XML node as a vector of strings. + * + * @return node content + */ + vector getContentArray(); + + /** Get the content of the XML node as a c-array of float32 data. + * + * @param _pfData data array, shouldn't be initialized already. + * @param _iSize number of elements stored in _pfData + */ + void getContentNumericalArray(float32*& _pfData, int& _iSize); + + /** Get the content of the XML node as a stl container of float32 data. + * + * @return node content + */ + vector getContentNumericalArray(); + vector getContentNumericalArrayDouble(); + + + + /** Does this node contain an attribute with a certain name? + * + * @param _sName of the attribute. + * @return attribute value, empty string if it doesn't exist. + */ + bool hasAttribute(string _sName); + + /** Get the value of an attribute. + * + * @param _sName of the attribute. + * @param _sDefaultValue value to return if the attribute isn't found + * @return attribute value, _sDefaultValue if it doesn't exist. + */ + string getAttribute(string _sName, string _sDefaultValue = ""); + + /** Get the value of a numerical attribute. + * + * @param _sName of the attribute. + * @param _fDefaultValue value to return if the attribute isn't found + * @return attribute value, _fDefaultValue if it doesn't exist. + */ + float32 getAttributeNumerical(string _sName, float32 _fDefaultValue = 0); + double getAttributeNumericalDouble(string _sName, double _fDefaultValue = 0); + + /** Get the value of a boolean attribute. + * + * @param _sName of the attribute. + * @param _bDefaultValue value to return if the attribute isn't found + * @return attribute value, _bDefaultValue if it doesn't exist. + */ + bool getAttributeBool(string _sName, bool _bDefaultValue = false); + + + + + /** Does this node contain an option with a certain key? + * + * @param _sKey option key + * @return true if option does exist + */ + bool hasOption(string _sKey); + + /** Get the value of an option within this XML Node + * + * @param _sKey option key + * @param _sDefaultValue value to return if key isn't found + * @return option value, _sDefaultValue if the option doesn't exist + */ + string getOption(string _sKey, string _sDefaultValue = ""); + + /** Get the value of an option within this XML Node + * + * @param _sKey option key + * @param _fDefaultValue value to return if key isn't found + * @return option value, _fDefaultValue if the option doesn't exist + */ + float32 getOptionNumerical(string _sKey, float32 _fDefaultValue = 0); + + /** Get the value of an option within this XML Node + * + * @param _sKey option key + * @param _bDefaultValue value to return if key isn't found + * @return option value, _bDefaultValue if the option doesn't exist + */ + bool getOptionBool(string _sKey, bool _bDefaultValue = false); + + /** Get the value of an option within this XML Node + * + * @param _sKey option key + * @return numerical array + */ + vector getOptionNumericalArray(string _sKey); + + + + + + /** Create a new XML node as a child to this one: <...><_sNodeName/></...> + * + * @param _sNodeName the name of the new childnode + * @param _sValue some node content + * @return new child node + */ + XMLNode* addChildNode(string _sNodeName, string _sValue); + + /** Create a new XML node as a child to this one, also add some numerical content: + * <...><_sNodeName>_sValue</_sNodeName></...> + * + * @param _sNodeName the name of the new childnode + * @param _fValue some node content + * @return new child node + */ + XMLNode* addChildNode(string _sNodeName, float32 _fValue); + + /** Create a new XML node as a child to this one, also add a list of numerical content: + * <...><_sNodeName>_sValue</_sNodeName></...> + * + * @param _sNodeName the name of the new childnode + * @param _pfList list data + * @param _iSize number of elements in _pfList + * @return new child node + */ + XMLNode* addChildNode(string _sNodeName, float32* _pfList, int _iSize); + + /** Add some text to the node: <...>_sText</...> + * + * @param _sText text to insert + */ + void setContent(string _sText); + + /** Add a number to the node: <...>_sText</...> + * + * @param _fValue number to insert + */ + void setContent(float32 _fValue); + + /** Add a list of numerical data to the node: <...>_sText</...> + * + * @param _pfList data + * @param _iSize number of elements in the list + */ + void setContent(float32* _pfList, int _iSize); + + /** Add an attribute to this node: <... _sName="_sValue"> + * + * @param _sName name of the attribute + * @param _sValue value of the attribute + */ + void addAttribute(string _sName, string _sValue); + + /** Add an attribute with numerical data to this node: <... _sName="_fValue"> + * + * @param _sName name of the attribute + * @param _sValue value of the attribute + */ + void addAttribute(string _sName, float32 _fValue); + + /** Add an option node as a child: <Option key="<_sKey>" value="<_sValue>"/> + * + * @param _sKey option key + * @param _sValue option value + */ + void addOption(string _sKey, string _sValue); + + /** Add an option node as a child: <Option key="<_sKey>" value="<_sValue>"/> + * + * @param _sKey option key + * @param _sValue option value + */ + void addOption(string _sKey, float32 _fValue); + + + /** Print to String + */ + std::string toString(); + + /** Print the node + */ + void print(); + +protected: + + /** Private Constructor. + * + * @param n rapidxml node + */ + XMLNode(rapidxml::xml_node* n); + + /** Link this object to a rapidxml node + * @param n object of the Xerces C++ library + */ + void setDOMNode(rapidxml::xml_node* n); + + // todo: rename "fDOMElement" to "m_fDOMElement"? + + //!< Node of rapidxml + rapidxml::xml_node* fDOMElement; + +}; + +} // end namespace + +#endif diff --git a/include/astra/jama_wrapper.h b/include/astra/jama_wrapper.h new file mode 100644 index 0000000..2fbdef8 --- /dev/null +++ b/include/astra/jama_wrapper.h @@ -0,0 +1,35 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +// Wrapper include for jama header files + +#ifdef JAMA_NO_SUBDIR +#include "jama_lu.h" +#else +#include +#endif diff --git a/include/astra/swrap.h b/include/astra/swrap.h new file mode 100644 index 0000000..af45838 --- /dev/null +++ b/include/astra/swrap.h @@ -0,0 +1,41 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("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 . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_ASTRA_SWRAP_H +#define _INC_ASTRA_SWRAP_H + +#ifndef _MSC_VER + +#include + +typedef int errno_t; +errno_t fopen_s(FILE** pFile, const char *filename, const char *mode); + +#endif + +#endif -- cgit v1.2.3