summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Algorithm.cpp64
-rw-r--r--src/ArtAlgorithm.cpp331
-rw-r--r--src/AstraObjectFactory.cpp39
-rw-r--r--src/AstraObjectManager.cpp43
-rw-r--r--src/AsyncAlgorithm.cpp195
-rw-r--r--src/BackProjectionAlgorithm.cpp192
-rw-r--r--src/CglsAlgorithm.cpp297
-rw-r--r--src/ConeProjectionGeometry3D.cpp228
-rw-r--r--src/ConeVecProjectionGeometry3D.cpp232
-rw-r--r--src/Config.cpp166
-rw-r--r--src/ConvexHullAlgorithm.cpp239
-rw-r--r--src/CudaBackProjectionAlgorithm.cpp96
-rw-r--r--src/CudaBackProjectionAlgorithm3D.cpp222
-rw-r--r--src/CudaCglsAlgorithm.cpp98
-rw-r--r--src/CudaCglsAlgorithm3D.cpp314
-rw-r--r--src/CudaDartMaskAlgorithm.cpp166
-rw-r--r--src/CudaDartMaskAlgorithm3D.cpp168
-rw-r--r--src/CudaDartSmoothingAlgorithm.cpp158
-rw-r--r--src/CudaDartSmoothingAlgorithm3D.cpp160
-rw-r--r--src/CudaDataOperationAlgorithm.cpp208
-rw-r--r--src/CudaEMAlgorithm.cpp97
-rw-r--r--src/CudaFDKAlgorithm3D.cpp192
-rw-r--r--src/CudaFilteredBackProjectionAlgorithm.cpp442
-rw-r--r--src/CudaForwardProjectionAlgorithm.cpp276
-rw-r--r--src/CudaForwardProjectionAlgorithm3D.cpp311
-rw-r--r--src/CudaProjector2D.cpp122
-rw-r--r--src/CudaProjector3D.cpp153
-rw-r--r--src/CudaReconstructionAlgorithm2D.cpp518
-rw-r--r--src/CudaRoiSelectAlgorithm.cpp149
-rw-r--r--src/CudaSartAlgorithm.cpp136
-rw-r--r--src/CudaSirtAlgorithm.cpp154
-rw-r--r--src/CudaSirtAlgorithm3D.cpp306
-rw-r--r--src/DataProjector.cpp36
-rw-r--r--src/DataProjectorPolicies.cpp36
-rw-r--r--src/FanFlatBeamLineKernelProjector2D.cpp179
-rw-r--r--src/FanFlatBeamStripKernelProjector2D.cpp223
-rw-r--r--src/FanFlatProjectionGeometry2D.cpp209
-rw-r--r--src/FanFlatVecProjectionGeometry2D.cpp232
-rw-r--r--src/FilteredBackProjectionAlgorithm.cpp336
-rw-r--r--src/Float32Data.cpp50
-rw-r--r--src/Float32Data2D.cpp523
-rw-r--r--src/Float32Data3D.cpp55
-rw-r--r--src/Float32Data3DMemory.cpp356
-rw-r--r--src/Float32ProjectionData2D.cpp139
-rw-r--r--src/Float32ProjectionData3D.cpp273
-rw-r--r--src/Float32ProjectionData3DMemory.cpp221
-rw-r--r--src/Float32VolumeData2D.cpp135
-rw-r--r--src/Float32VolumeData3D.cpp269
-rw-r--r--src/Float32VolumeData3DMemory.cpp208
-rw-r--r--src/ForwardProjectionAlgorithm.cpp280
-rw-r--r--src/Fourier.cpp233
-rw-r--r--src/Globals.cpp32
-rw-r--r--src/Logger.cpp77
-rw-r--r--src/ParallelBeamBlobKernelProjector2D.cpp271
-rw-r--r--src/ParallelBeamLineKernelProjector2D.cpp222
-rw-r--r--src/ParallelBeamLinearKernelProjector2D.cpp222
-rw-r--r--src/ParallelBeamStripKernelProjector2D.cpp224
-rw-r--r--src/ParallelProjectionGeometry2D.cpp186
-rw-r--r--src/ParallelProjectionGeometry3D.cpp211
-rw-r--r--src/ParallelVecProjectionGeometry3D.cpp230
-rw-r--r--src/PlatformDepSystemCode.cpp76
-rw-r--r--src/ProjectionGeometry2D.cpp203
-rw-r--r--src/ProjectionGeometry3D.cpp329
-rw-r--r--src/Projector2D.cpp217
-rw-r--r--src/Projector3D.cpp121
-rw-r--r--src/ReconstructionAlgorithm2D.cpp275
-rw-r--r--src/ReconstructionAlgorithm3D.cpp306
-rw-r--r--src/ReconstructionAlgorithmMultiSlice2D.cpp288
-rw-r--r--src/SartAlgorithm.cpp452
-rw-r--r--src/SirtAlgorithm.cpp321
-rw-r--r--src/SparseMatrix.cpp91
-rw-r--r--src/SparseMatrixProjectionGeometry2D.cpp203
-rw-r--r--src/SparseMatrixProjector2D.cpp219
-rw-r--r--src/Utilities.cpp128
-rw-r--r--src/Vector3D.cpp29
-rw-r--r--src/VolumeGeometry2D.cpp282
-rw-r--r--src/VolumeGeometry3D.cpp384
-rw-r--r--src/XMLDocument.cpp112
-rw-r--r--src/XMLNode.cpp499
-rw-r--r--src/astra.def6
-rw-r--r--src/swrap.cpp47
81 files changed, 16728 insertions, 0 deletions
diff --git a/src/Algorithm.cpp b/src/Algorithm.cpp
new file mode 100644
index 0000000..38ae65d
--- /dev/null
+++ b/src/Algorithm.cpp
@@ -0,0 +1,64 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Algorithm.h"
+
+using namespace std;
+
+namespace astra {
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CAlgorithm::CAlgorithm() : m_bShouldAbort(false), configCheckData(0) {
+
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CAlgorithm::~CAlgorithm() {
+
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CAlgorithm::getInformation()
+{
+ map<string, boost::any> result;
+ result["Initialized"] = getInformation("Initialized");
+ return result;
+};
+
+//----------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CAlgorithm::getInformation(std::string _sIdentifier)
+{
+ if (_sIdentifier == "Initialized") { return m_bIsInitialized ? "yes" : "no"; }
+ return std::string("not found");
+}
+
+} // namespace astra
diff --git a/src/ArtAlgorithm.cpp b/src/ArtAlgorithm.cpp
new file mode 100644
index 0000000..77ab5ab
--- /dev/null
+++ b/src/ArtAlgorithm.cpp
@@ -0,0 +1,331 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ArtAlgorithm.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CArtAlgorithm::type = "ART";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CArtAlgorithm::CArtAlgorithm()
+ : CReconstructionAlgorithm2D()
+{
+ m_fLambda = 1.0f;
+ m_iRayCount = 0;
+ m_iCurrentRay = 0;
+ m_piProjectionOrder = NULL;
+ m_piDetectorOrder = NULL;
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CArtAlgorithm::~CArtAlgorithm()
+{
+ if (m_piProjectionOrder != NULL)
+ delete[] m_piProjectionOrder;
+ if (m_piDetectorOrder != NULL)
+ delete[] m_piDetectorOrder;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CArtAlgorithm::_clear()
+{
+ CReconstructionAlgorithm2D::_clear();
+ m_piDetectorOrder = NULL;
+ m_piProjectionOrder = NULL;
+ m_iRayCount = 0;
+ m_iCurrentRay = 0;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CArtAlgorithm::clear()
+{
+ CReconstructionAlgorithm2D::clear();
+ if (m_piDetectorOrder) {
+ delete[] m_piDetectorOrder;
+ m_piDetectorOrder = NULL;
+ }
+ if (m_piProjectionOrder) {
+ delete[] m_piProjectionOrder;
+ m_piProjectionOrder = NULL;
+ }
+ m_fLambda = 1.0f;
+ m_iRayCount = 0;
+ m_iCurrentRay = 0;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CArtAlgorithm::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CReconstructionAlgorithm2D::_check(), "ART", "Error in ReconstructionAlgorithm2D initialization");
+
+ // check ray order list
+ for (int i = 0; i < m_iRayCount; i++) {
+ if (m_piProjectionOrder[i] < 0 || m_piProjectionOrder[i] > m_pSinogram->getAngleCount()-1) {
+ ASTRA_CONFIG_CHECK(false, "ART", "Invalid value in ray order list.");
+ }
+ if (m_piDetectorOrder[i] < 0 || m_piDetectorOrder[i] > m_pSinogram->getDetectorCount()-1) {
+ ASTRA_CONFIG_CHECK(false, "ART", "Invalid value in ray order list.");
+ }
+ }
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CArtAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("ArtAlgorithm", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CReconstructionAlgorithm2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // ray order
+ string projOrder = _cfg.self->getOption("RayOrder", "sequential");
+ CC.markOptionParsed("RayOrder");
+ m_iCurrentRay = 0;
+ m_iRayCount = m_pProjector->getProjectionGeometry()->getProjectionAngleCount() *
+ m_pProjector->getProjectionGeometry()->getDetectorCount();
+ if (projOrder == "sequential") {
+ m_piProjectionOrder = new int[m_iRayCount];
+ m_piDetectorOrder = new int[m_iRayCount];
+ for (int i = 0; i < m_iRayCount; i++) {
+ m_piProjectionOrder[i] = (int)floor((float)i / m_pProjector->getProjectionGeometry()->getDetectorCount());
+ m_piDetectorOrder[i] = i % m_pProjector->getProjectionGeometry()->getDetectorCount();
+ }
+ } else if (projOrder == "custom") {
+ vector<float32> rayOrderList = _cfg.self->getOptionNumericalArray("RayOrderList");
+ m_iRayCount = rayOrderList.size() / 2;
+ m_piProjectionOrder = new int[m_iRayCount];
+ m_piDetectorOrder = new int[m_iRayCount];
+ for (int i = 0; i < m_iRayCount; i++) {
+ m_piProjectionOrder[i] = static_cast<int>(rayOrderList[2*i]);
+ m_piDetectorOrder[i] = static_cast<int>(rayOrderList[2*i+1]);
+ }
+ CC.markOptionParsed("RayOrderList");
+ } else {
+ return false;
+ }
+
+ m_fLambda = _cfg.self->getOptionNumerical("Lambda", 1.0f);
+ CC.markOptionParsed("Lambda");
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialize - C++
+bool CArtAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ // ray order
+ m_iCurrentRay = 0;
+ m_iRayCount = _pProjector->getProjectionGeometry()->getDetectorCount() *
+ _pProjector->getProjectionGeometry()->getProjectionAngleCount();
+ m_piProjectionOrder = new int[m_iRayCount];
+ m_piDetectorOrder = new int[m_iRayCount];
+ for (int i = 0; i < m_iRayCount; i++) {
+ m_piProjectionOrder[i] = (int)floor((float)i / _pProjector->getProjectionGeometry()->getDetectorCount());
+ m_piDetectorOrder[i] = i % _pProjector->getProjectionGeometry()->getDetectorCount();
+ }
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Set the relaxation factor.
+void CArtAlgorithm::setLambda(float32 _fLambda)
+{
+ m_fLambda = _fLambda;
+}
+
+//----------------------------------------------------------------------------------------
+// Set the order in which the rays will be selected
+void CArtAlgorithm::setRayOrder(int* _piProjectionOrder, int* _piDetectorOrder, int _iRayCount)
+{
+ if (m_piDetectorOrder) {
+ delete[] m_piDetectorOrder;
+ m_piDetectorOrder = NULL;
+ }
+ if (m_piProjectionOrder) {
+ delete[] m_piProjectionOrder;
+ m_piProjectionOrder = NULL;
+ }
+
+ m_iCurrentRay = 0;
+ m_iRayCount = _iRayCount;
+ m_piProjectionOrder = new int[m_iRayCount];
+ m_piDetectorOrder = new int[m_iRayCount];
+ for (int i = 0; i < m_iRayCount; i++) {
+ m_piProjectionOrder[i] = _piProjectionOrder[i];
+ m_piDetectorOrder[i] = _piDetectorOrder[i];
+ }
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CArtAlgorithm::getInformation()
+{
+ map<string, boost::any> res;
+ res["RayOrder"] = getInformation("RayOrder");
+ res["Lambda"] = getInformation("Lambda");
+ return mergeMap<string,boost::any>(CReconstructionAlgorithm2D::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CArtAlgorithm::getInformation(std::string _sIdentifier)
+{
+ if (_sIdentifier == "Lambda") { return m_fLambda; }
+ if (_sIdentifier == "RayOrder") {
+ vector<float32> res;
+ for (int i = 0; i < m_iRayCount; i++) {
+ res.push_back(m_piProjectionOrder[i]);
+ }
+ for (int i = 0; i < m_iRayCount; i++) {
+ res.push_back(m_piDetectorOrder[i]);
+ }
+ return res;
+ }
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CArtAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ assert(m_bIsInitialized);
+
+ // variables
+ int iIteration, iPixel;
+ int iUsedPixels, iProjection, iDetector;
+ float32 fRayForwardProj, fSumSquaredWeights;
+ float32 fProjectionDifference, fBackProjectionFactor;
+
+ // create a pixel buffer
+ int iPixelBufferSize = m_pProjector->getProjectionWeightsCount(0);
+ SPixelWeight* pPixels = new SPixelWeight[iPixelBufferSize];
+
+ // start iterations
+ for (iIteration = _iNrIterations-1; iIteration >= 0; --iIteration) {
+
+ // step0: compute single weight rays
+ iProjection = m_piProjectionOrder[m_iCurrentRay];
+ iDetector = m_piDetectorOrder[m_iCurrentRay];
+ m_iCurrentRay = (m_iCurrentRay + 1) % m_iRayCount;
+
+ if (m_bUseSinogramMask && m_pSinogramMask->getData2D()[iProjection][iDetector] == 0) continue;
+
+ m_pProjector->computeSingleRayWeights(iProjection, iDetector, pPixels, iPixelBufferSize, iUsedPixels);
+
+ // step1: forward projections
+ fRayForwardProj = 0.0f;
+ fSumSquaredWeights = 0.0f;
+ for (iPixel = iUsedPixels-1; iPixel >= 0; --iPixel) {
+ if (m_bUseReconstructionMask && m_pReconstructionMask->getDataConst()[pPixels[iPixel].m_iIndex] == 0) continue;
+
+ fRayForwardProj += pPixels[iPixel].m_fWeight * m_pReconstruction->getDataConst()[pPixels[iPixel].m_iIndex];
+ fSumSquaredWeights += pPixels[iPixel].m_fWeight * pPixels[iPixel].m_fWeight;
+ }
+ if (fSumSquaredWeights == 0) continue;
+
+ // step2: difference
+ fProjectionDifference = m_pSinogram->getData2D()[iProjection][iDetector] - fRayForwardProj;
+
+ // step3: back projection
+ fBackProjectionFactor = m_fLambda * fProjectionDifference / fSumSquaredWeights;
+ for (iPixel = iUsedPixels-1; iPixel >= 0; --iPixel) {
+
+ // pixel must be loose
+ if (m_bUseReconstructionMask && m_pReconstructionMask->getDataConst()[pPixels[iPixel].m_iIndex] == 0) continue;
+
+ // update
+ m_pReconstruction->getData()[pPixels[iPixel].m_iIndex] += fBackProjectionFactor * pPixels[iPixel].m_fWeight;
+
+ // constraints
+ if (m_bUseMinConstraint && m_pReconstruction->getData()[pPixels[iPixel].m_iIndex] < m_fMinValue) {
+ m_pReconstruction->getData()[pPixels[iPixel].m_iIndex] = m_fMinValue;
+ }
+ if (m_bUseMaxConstraint && m_pReconstruction->getData()[pPixels[iPixel].m_iIndex] > m_fMaxValue) {
+ m_pReconstruction->getData()[pPixels[iPixel].m_iIndex] = m_fMaxValue;
+ }
+ }
+
+ }
+ delete[] pPixels;
+
+ // update statistics
+ m_pReconstruction->updateStatistics();
+}
+
+
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/AstraObjectFactory.cpp b/src/AstraObjectFactory.cpp
new file mode 100644
index 0000000..195c431
--- /dev/null
+++ b/src/AstraObjectFactory.cpp
@@ -0,0 +1,39 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/AstraObjectFactory.h"
+
+using namespace std;
+
+namespace astra {
+
+DEFINE_SINGLETON2(CAstraObjectFactory<CAlgorithm, AlgorithmTypeList>);
+DEFINE_SINGLETON2(CAstraObjectFactory<CProjector2D, Projector2DTypeList>);
+DEFINE_SINGLETON2(CAstraObjectFactory<CProjector3D, Projector3DTypeList>);
+
+} // end namespace
diff --git a/src/AstraObjectManager.cpp b/src/AstraObjectManager.cpp
new file mode 100644
index 0000000..597119d
--- /dev/null
+++ b/src/AstraObjectManager.cpp
@@ -0,0 +1,43 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/AstraObjectManager.h"
+
+
+namespace astra {
+
+int CAstraIndexManager::m_iPreviousIndex = 0;
+
+DEFINE_SINGLETON(CAstraObjectManager<CProjector2D>);
+DEFINE_SINGLETON(CAstraObjectManager<CProjector3D>);
+DEFINE_SINGLETON(CAstraObjectManager<CFloat32Data2D>);
+DEFINE_SINGLETON(CAstraObjectManager<CFloat32Data3D>);
+DEFINE_SINGLETON(CAstraObjectManager<CAlgorithm>);
+DEFINE_SINGLETON(CAstraObjectManager<CSparseMatrix>);
+
+} // end namespace
diff --git a/src/AsyncAlgorithm.cpp b/src/AsyncAlgorithm.cpp
new file mode 100644
index 0000000..431dbbc
--- /dev/null
+++ b/src/AsyncAlgorithm.cpp
@@ -0,0 +1,195 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/AsyncAlgorithm.h"
+#include "astra/AstraObjectFactory.h"
+
+#ifndef USE_PTHREAD
+#include <boost/bind.hpp>
+#endif
+
+namespace astra {
+
+CAsyncAlgorithm::CAsyncAlgorithm()
+{
+ m_bInitialized = false;
+#ifndef USE_PTHREADS
+ m_pThread = 0;
+#endif
+ m_bThreadStarted = false;
+}
+
+CAsyncAlgorithm::CAsyncAlgorithm(CAlgorithm* _pAlg)
+{
+ m_pAlg = _pAlg;
+ m_bInitialized = (m_pAlg != 0);
+#ifndef USE_PTHREADS
+ m_pThread = 0;
+#endif
+ m_bThreadStarted = false;
+ m_bDone = false;
+ m_bAutoFree = false;
+}
+
+bool CAsyncAlgorithm::initialize(const Config& _cfg)
+{
+ if (m_bInitialized && m_bThreadStarted) {
+#ifndef USE_PTHREADS
+ m_pThread->join();
+ delete m_pThread;
+#else
+ pthread_join(m_thread, 0);
+#endif
+ }
+#ifndef USE_PTHREADS
+ m_pThread = 0;
+#endif
+ m_bThreadStarted = false;
+ m_pAlg = 0;
+ m_bDone = false;
+
+ m_pAlg = CAlgorithmFactory::getSingleton().create(_cfg);
+ if (m_pAlg && !m_pAlg->isInitialized()) {
+ if (m_bAutoFree)
+ delete m_pAlg;
+ m_pAlg = 0;
+ }
+ m_bInitialized = (m_pAlg != 0);
+ m_bAutoFree = true;
+ return m_bInitialized;
+}
+
+bool CAsyncAlgorithm::initialize(CAlgorithm* _pAlg)
+{
+ if (m_bInitialized && m_bThreadStarted) {
+#ifndef USE_PTHREADS
+ m_pThread->join();
+ delete m_pThread;
+#else
+ pthread_join(m_thread, 0);
+#endif
+ }
+#ifndef USE_PTHREADS
+ m_pThread = 0;
+#endif
+ m_bThreadStarted = false;
+ m_bDone = false;
+
+ m_pAlg = _pAlg;
+ m_bInitialized = (m_pAlg != 0);
+ m_bAutoFree = false;
+ return m_bInitialized;
+}
+
+CAsyncAlgorithm::~CAsyncAlgorithm()
+{
+ if (m_bInitialized && m_bThreadStarted) {
+#ifndef USE_PTHREADS
+ m_pThread->join();
+ delete m_pThread;
+#else
+ pthread_join(m_thread, 0);
+#endif
+ }
+#ifndef USE_PTHREADS
+ m_pThread = 0;
+#endif
+ m_bThreadStarted = false;
+
+ if (m_bInitialized && m_bAutoFree) {
+ delete m_pAlg;
+ m_pAlg = 0;
+ }
+}
+
+#ifdef USE_PTHREADS
+void* runAsync_pthreads(void* data)
+{
+ CAsyncAlgorithm::AsyncThreadInfo *info = (CAsyncAlgorithm::AsyncThreadInfo*)data;
+ info->m_pAlg->run(info->m_iIterations);
+ *info->m_pDone = true;
+ return 0;
+}
+#endif
+
+void CAsyncAlgorithm::run(int _iNrIterations)
+{
+ if (!m_bInitialized)
+ return;
+
+#ifndef USE_PTHREADS
+ m_pThread = new boost::thread(
+ boost::bind(&CAsyncAlgorithm::runWrapped,
+ this, _iNrIterations));
+#else
+ m_ThreadInfo.m_iIterations = _iNrIterations;
+ m_ThreadInfo.m_pAlg = m_pAlg;
+ m_ThreadInfo.m_pDone = &this->m_bDone;
+ pthread_create(&m_thread, 0, runAsync_pthreads, &this->m_ThreadInfo);
+#endif
+}
+
+void CAsyncAlgorithm::runWrapped(int _iNrIterations)
+{
+ m_pAlg->run(_iNrIterations);
+ m_bDone = true;
+}
+
+void CAsyncAlgorithm::timedJoin(int _milliseconds)
+{
+#ifndef USE_PTHREADS
+ if (m_pThread) {
+ boost::posix_time::milliseconds rel(_milliseconds);
+ bool res = m_pThread->timed_join(rel);
+ if (res) {
+ delete m_pThread;
+ m_pThread = 0;
+ m_bThreadStarted = false;
+ }
+ }
+#else
+ if (m_bThreadStarted) {
+ struct timespec abstime;
+ clock_gettime(CLOCK_REALTIME, &abstime);
+ abstime.tv_sec += _milliseconds / 1000;
+ abstime.tv_nsec += (_milliseconds % 1000) * 1000000L;
+ int err = pthread_timedjoin_np(m_thread, 0, &abstime);
+ if (err == 0) {
+ m_bThreadStarted = false;
+ }
+ }
+#endif
+}
+
+void CAsyncAlgorithm::signalAbort()
+{
+ if (m_pAlg)
+ m_pAlg->signalAbort();
+}
+
+}
diff --git a/src/BackProjectionAlgorithm.cpp b/src/BackProjectionAlgorithm.cpp
new file mode 100644
index 0000000..cf8c9ca
--- /dev/null
+++ b/src/BackProjectionAlgorithm.cpp
@@ -0,0 +1,192 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/BackProjectionAlgorithm.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+
+namespace astra {
+
+#include "astra/Projector2DImpl.inl"
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CBackProjectionAlgorithm::type = "BP";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CBackProjectionAlgorithm::CBackProjectionAlgorithm()
+{
+ _clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+CBackProjectionAlgorithm::CBackProjectionAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ _clear();
+ initialize(_pProjector, _pSinogram, _pReconstruction);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CBackProjectionAlgorithm::~CBackProjectionAlgorithm()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CBackProjectionAlgorithm::_clear()
+{
+ CReconstructionAlgorithm2D::_clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CBackProjectionAlgorithm::clear()
+{
+ CReconstructionAlgorithm2D::_clear();
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CBackProjectionAlgorithm::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CReconstructionAlgorithm2D::_check(), "BP", "Error in ReconstructionAlgorithm2D initialization");
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CBackProjectionAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("BackProjectionAlgorithm", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CReconstructionAlgorithm2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // init data objects and data projectors
+ _init();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CBackProjectionAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ // init data objects and data projectors
+ _init();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize Data Projectors - private
+void CBackProjectionAlgorithm::_init()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CBackProjectionAlgorithm::getInformation()
+{
+ map<string, boost::any> res;
+ return mergeMap<string,boost::any>(CReconstructionAlgorithm2D::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CBackProjectionAlgorithm::getInformation(std::string _sIdentifier)
+{
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CBackProjectionAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ m_bShouldAbort = false;
+
+ CDataProjectorInterface* pBackProjector;
+
+ pBackProjector = dispatchDataProjector(
+ m_pProjector,
+ SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
+ DefaultBPPolicy(m_pReconstruction, m_pSinogram), // backprojection
+ m_bUseSinogramMask, m_bUseReconstructionMask, true // options on/off
+ );
+
+ m_pReconstruction->setData(0.0f);
+ pBackProjector->project();
+
+ ASTRA_DELETE(pBackProjector);
+}
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/CglsAlgorithm.cpp b/src/CglsAlgorithm.cpp
new file mode 100644
index 0000000..f3e1be1
--- /dev/null
+++ b/src/CglsAlgorithm.cpp
@@ -0,0 +1,297 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/CglsAlgorithm.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+
+using namespace std;
+
+namespace astra {
+
+#include "astra/Projector2DImpl.inl"
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCglsAlgorithm::type = "CGLS";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCglsAlgorithm::CCglsAlgorithm()
+{
+ _clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+CCglsAlgorithm::CCglsAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ _clear();
+ initialize(_pProjector, _pSinogram, _pReconstruction);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCglsAlgorithm::~CCglsAlgorithm()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CCglsAlgorithm::_clear()
+{
+ CReconstructionAlgorithm2D::_clear();
+ r = NULL;
+ w = NULL;
+ z = NULL;
+ p = NULL;
+ alpha = 0.0f;
+ beta = 0.0f;
+ gamma = 0.0f;
+ m_iIteration = 0;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CCglsAlgorithm::clear()
+{
+ CReconstructionAlgorithm2D::_clear();
+ ASTRA_DELETE(r);
+ ASTRA_DELETE(w);
+ ASTRA_DELETE(z);
+ ASTRA_DELETE(p);
+ alpha = 0.0f;
+ beta = 0.0f;
+ gamma = 0.0f;
+ m_iIteration = 0;
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCglsAlgorithm::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CReconstructionAlgorithm2D::_check(), "CGLS", "Error in ReconstructionAlgorithm2D initialization");
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCglsAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CglsAlgorithm", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CReconstructionAlgorithm2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // member variables
+ r = new CFloat32ProjectionData2D(m_pSinogram->getGeometry());
+ w = new CFloat32ProjectionData2D(m_pSinogram->getGeometry());
+ z = new CFloat32VolumeData2D(m_pReconstruction->getGeometry());
+ p = new CFloat32VolumeData2D(m_pReconstruction->getGeometry());
+
+ alpha = 0.0f;
+ beta = 0.0f;
+ gamma = 0.0f;
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCglsAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ // member variables
+ r = new CFloat32ProjectionData2D(m_pSinogram->getGeometry());
+ w = new CFloat32ProjectionData2D(m_pSinogram->getGeometry());
+ z = new CFloat32VolumeData2D(m_pReconstruction->getGeometry());
+ p = new CFloat32VolumeData2D(m_pReconstruction->getGeometry());
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCglsAlgorithm::getInformation()
+{
+ map<string, boost::any> res;
+ return mergeMap<string,boost::any>(CReconstructionAlgorithm2D::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCglsAlgorithm::getInformation(std::string _sIdentifier)
+{
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCglsAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ // data projectors
+ CDataProjectorInterface* pForwardProjector;
+ CDataProjectorInterface* pBackProjector;
+
+ // forward projection data projector
+ pForwardProjector = dispatchDataProjector(
+ m_pProjector,
+ SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
+ DefaultFPPolicy(p, w), // forward projection
+ m_bUseSinogramMask, m_bUseReconstructionMask, true // options on/off
+ );
+
+ // backprojection data projector
+ pBackProjector = dispatchDataProjector(
+ m_pProjector,
+ SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
+ DefaultBPPolicy(z, r), // backprojection
+ m_bUseSinogramMask, m_bUseReconstructionMask, true // options on/off
+ );
+
+
+
+ int i;
+
+ if (m_iIteration == 0) {
+ // r = b;
+ r->copyData(m_pSinogram->getData());
+
+ // z = A'*b;
+ z->setData(0.0f);
+ pBackProjector->project();
+ if (m_bUseMinConstraint)
+ z->clampMin(m_fMinValue);
+ if (m_bUseMaxConstraint)
+ z->clampMax(m_fMaxValue);
+
+ // p = z;
+ p->copyData(z->getData());
+
+ // gamma = dot(z,z);
+ gamma = 0.0f;
+ for (i = 0; i < z->getSize(); ++i) {
+ gamma += z->getData()[i] * z->getData()[i];
+ }
+ m_iIteration++;
+ }
+
+
+ // start iterations
+ for (int iIteration = _iNrIterations-1; iIteration >= 0; --iIteration) {
+
+ // w = A*p;
+ pForwardProjector->project();
+
+ // alpha = gamma/dot(w,w);
+ float32 tmp = 0;
+ for (i = 0; i < w->getSize(); ++i) {
+ tmp += w->getData()[i] * w->getData()[i];
+ }
+ alpha = gamma / tmp;
+
+ // x = x + alpha*p;
+ for (i = 0; i < m_pReconstruction->getSize(); ++i) {
+ m_pReconstruction->getData()[i] += alpha * p->getData()[i];
+ }
+
+ // r = r - alpha*w;
+ for (i = 0; i < r->getSize(); ++i) {
+ r->getData()[i] -= alpha * w->getData()[i];
+ }
+
+ // z = A'*r;
+ z->setData(0.0f);
+ pBackProjector->project();
+
+ // CHECKME: should these be here?
+ if (m_bUseMinConstraint)
+ z->clampMin(m_fMinValue);
+ if (m_bUseMaxConstraint)
+ z->clampMax(m_fMaxValue);
+
+ // beta = 1/gamma;
+ beta = 1.0f / gamma;
+
+ // gamma = dot(z,z);
+ gamma = 0;
+ for (i = 0; i < z->getSize(); ++i) {
+ gamma += z->getData()[i] * z->getData()[i];
+ }
+
+ // beta = gamma*beta;
+ beta *= gamma;
+
+ // p = z + beta*p;
+ for (i = 0; i < z->getSize(); ++i) {
+ p->getData()[i] = z->getData()[i] + beta * p->getData()[i];
+ }
+
+ m_iIteration++;
+ }
+
+}
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/ConeProjectionGeometry3D.cpp b/src/ConeProjectionGeometry3D.cpp
new file mode 100644
index 0000000..129e675
--- /dev/null
+++ b/src/ConeProjectionGeometry3D.cpp
@@ -0,0 +1,228 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ConeProjectionGeometry3D.h"
+
+#include <boost/lexical_cast.hpp>
+#include <cstring>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CConeProjectionGeometry3D::CConeProjectionGeometry3D() :
+ CProjectionGeometry3D()
+{
+ m_fOriginSourceDistance = 0.0f;
+ m_fOriginDetectorDistance = 0.0f;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CConeProjectionGeometry3D::CConeProjectionGeometry3D(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorWidth,
+ float32 _fDetectorHeight,
+ const float32* _pfProjectionAngles,
+ float32 _fOriginSourceDistance,
+ float32 _fOriginDetectorDistance) :
+ CProjectionGeometry3D()
+{
+ initialize(_iProjectionAngleCount,
+ _iDetectorRowCount,
+ _iDetectorColCount,
+ _fDetectorWidth,
+ _fDetectorHeight,
+ _pfProjectionAngles,
+ _fOriginSourceDistance,
+ _fOriginDetectorDistance);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CConeProjectionGeometry3D::~CConeProjectionGeometry3D()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CConeProjectionGeometry3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjectionGeometry3D> CC("ConeProjectionGeometry3D", this, _cfg);
+
+ // initialization of parent class
+ CProjectionGeometry3D::initialize(_cfg);
+
+ // Required: DistanceOriginDetector
+ XMLNode* node = _cfg.self->getSingleNode("DistanceOriginDetector");
+ ASTRA_CONFIG_CHECK(node, "ConeProjectionGeometry3D", "No DistanceOriginDetector tag specified.");
+ m_fOriginDetectorDistance = boost::lexical_cast<float32>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DistanceOriginDetector");
+
+ // Required: DetectorOriginSource
+ node = _cfg.self->getSingleNode("DistanceOriginSource");
+ ASTRA_CONFIG_CHECK(node, "ConeProjectionGeometry3D", "No DistanceOriginSource tag specified.");
+ m_fOriginSourceDistance = boost::lexical_cast<float32>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DistanceOriginSource");
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CConeProjectionGeometry3D::initialize(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorWidth,
+ float32 _fDetectorHeight,
+ const float32* _pfProjectionAngles,
+ float32 _fOriginSourceDistance,
+ float32 _fOriginDetectorDistance)
+{
+ _initialize(_iProjectionAngleCount,
+ _iDetectorRowCount,
+ _iDetectorColCount,
+ _fDetectorWidth,
+ _fDetectorHeight,
+ _pfProjectionAngles);
+
+ m_fOriginSourceDistance = _fOriginSourceDistance;
+ m_fOriginDetectorDistance = _fOriginDetectorDistance;
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Clone
+CProjectionGeometry3D* CConeProjectionGeometry3D::clone() const
+{
+ CConeProjectionGeometry3D* res = new CConeProjectionGeometry3D();
+ res->m_bInitialized = m_bInitialized;
+ res->m_iProjectionAngleCount = m_iProjectionAngleCount;
+ res->m_iDetectorRowCount = m_iDetectorRowCount;
+ res->m_iDetectorColCount = m_iDetectorColCount;
+ res->m_iDetectorTotCount = m_iDetectorTotCount;
+ res->m_fDetectorSpacingX = m_fDetectorSpacingX;
+ res->m_fDetectorSpacingY = m_fDetectorSpacingY;
+ res->m_pfProjectionAngles = new float32[m_iProjectionAngleCount];
+ memcpy(res->m_pfProjectionAngles, m_pfProjectionAngles, sizeof(float32)*m_iProjectionAngleCount);
+ res->m_fOriginSourceDistance = m_fOriginSourceDistance;
+ res->m_fOriginDetectorDistance = m_fOriginDetectorDistance;
+ return res;
+}
+
+//----------------------------------------------------------------------------------------
+// is equal
+bool CConeProjectionGeometry3D::isEqual(const CProjectionGeometry3D* _pGeom2) const
+{
+ if (_pGeom2 == NULL) return false;
+
+ // try to cast argument to CParallelProjectionGeometry3D
+ const CConeProjectionGeometry3D* pGeom2 = dynamic_cast<const CConeProjectionGeometry3D*>(_pGeom2);
+ if (pGeom2 == NULL) return false;
+
+ // both objects must be initialized
+ if (!m_bInitialized || !pGeom2->m_bInitialized) return false;
+
+ // check all values
+ if (m_iProjectionAngleCount != pGeom2->m_iProjectionAngleCount) return false;
+ if (m_iDetectorRowCount != pGeom2->m_iDetectorRowCount) return false;
+ if (m_iDetectorColCount != pGeom2->m_iDetectorColCount) return false;
+ if (m_iDetectorTotCount != pGeom2->m_iDetectorTotCount) return false;
+ if (m_fDetectorSpacingX != pGeom2->m_fDetectorSpacingX) return false;
+ if (m_fDetectorSpacingY != pGeom2->m_fDetectorSpacingY) return false;
+ if (m_fOriginSourceDistance != pGeom2->m_fOriginSourceDistance) return false;
+ if (m_fOriginDetectorDistance != pGeom2->m_fOriginDetectorDistance) return false;
+
+ for (int i = 0; i < m_iProjectionAngleCount; ++i) {
+ if (m_pfProjectionAngles[i] != pGeom2->m_pfProjectionAngles[i]) return false;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// is of type
+bool CConeProjectionGeometry3D::isOfType(const std::string& _sType) const
+{
+ return (_sType == "cone");
+}
+
+//----------------------------------------------------------------------------------------
+void CConeProjectionGeometry3D::toXML(XMLNode* _sNode) const
+{
+ _sNode->addAttribute("type", "cone");
+ _sNode->addChildNode("DetectorSpacingX", m_fDetectorSpacingX);
+ _sNode->addChildNode("DetectorSpacingY", m_fDetectorSpacingY);
+ _sNode->addChildNode("DetectorRowCount", m_iDetectorRowCount);
+ _sNode->addChildNode("DetectorColCount", m_iDetectorColCount);
+ _sNode->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount);
+ _sNode->addChildNode("DistanceOriginDetector", m_fOriginDetectorDistance);
+ _sNode->addChildNode("DistanceOriginSource", m_fOriginSourceDistance);
+}
+//----------------------------------------------------------------------------------------
+
+CVector3D CConeProjectionGeometry3D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const
+{
+ float32 fSrcX = -m_fOriginSourceDistance;
+ float32 fSrcY = 0.0f;
+ float32 fSrcZ = 0.0f;
+
+ float32 fDetX = m_fOriginDetectorDistance;
+ float32 fDetY = 0.0f;
+ float32 fDetZ = 0.0f;
+
+ fDetY += indexToDetectorOffsetX(_iDetectorIndex);
+ fDetZ += indexToDetectorOffsetY(_iDetectorIndex);
+
+ float32 angle = m_pfProjectionAngles[_iProjectionIndex];
+
+ #define ROTATE(name,alpha) do { float32 tX = f##name##X * cos(alpha) - f##name##Y * sin(alpha); f##name##Y = f##name##X * sin(alpha) + f##name##Y * cos(alpha); f##name##X = tX; } while(0)
+
+ ROTATE(Src, angle);
+ ROTATE(Det, angle);
+
+ #undef ROTATE
+
+ CVector3D ret(fDetX - fSrcX, fDetY - fSrcY, fDetZ - fDetZ);
+ return ret;
+}
+
+} // end namespace astra
diff --git a/src/ConeVecProjectionGeometry3D.cpp b/src/ConeVecProjectionGeometry3D.cpp
new file mode 100644
index 0000000..875a2c7
--- /dev/null
+++ b/src/ConeVecProjectionGeometry3D.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ConeVecProjectionGeometry3D.h"
+
+#include <cstring>
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CConeVecProjectionGeometry3D::CConeVecProjectionGeometry3D() :
+ CProjectionGeometry3D()
+{
+ m_pProjectionAngles = 0;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CConeVecProjectionGeometry3D::CConeVecProjectionGeometry3D(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ const SConeProjection* _pProjectionAngles
+ ) :
+ CProjectionGeometry3D()
+{
+ initialize(_iProjectionAngleCount,
+ _iDetectorRowCount,
+ _iDetectorColCount,
+ _pProjectionAngles);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CConeVecProjectionGeometry3D::~CConeVecProjectionGeometry3D()
+{
+ delete[] m_pProjectionAngles;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CConeVecProjectionGeometry3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjectionGeometry3D> CC("ConeVecProjectionGeometry3D", this, _cfg);
+
+ XMLNode* node;
+
+ // TODO: Fix up class hierarchy... this class doesn't fit very well.
+ // initialization of parent class
+ //CProjectionGeometry3D::initialize(_cfg);
+
+ // Required: DetectorRowCount
+ node = _cfg.self->getSingleNode("DetectorRowCount");
+ ASTRA_CONFIG_CHECK(node, "ConeVecProjectionGeometry3D", "No DetectorRowCount tag specified.");
+ m_iDetectorRowCount = boost::lexical_cast<int>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorRowCount");
+
+ // Required: DetectorColCount
+ node = _cfg.self->getSingleNode("DetectorColCount");
+ ASTRA_CONFIG_CHECK(node, "ConeVecProjectionGeometry3D", "No DetectorColCount tag specified.");
+ m_iDetectorColCount = boost::lexical_cast<int>(node->getContent());
+ m_iDetectorTotCount = m_iDetectorRowCount * m_iDetectorColCount;
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorColCount");
+
+ // Required: Vectors
+ node = _cfg.self->getSingleNode("Vectors");
+ ASTRA_CONFIG_CHECK(node, "ConeVecProjectionGeometry3D", "No Vectors tag specified.");
+ vector<double> data = node->getContentNumericalArrayDouble();
+ CC.markNodeParsed("Vectors");
+ ASTRA_DELETE(node);
+ ASTRA_CONFIG_CHECK(data.size() % 12 == 0, "ConeVecProjectionGeometry3D", "Vectors doesn't consist of 12-tuples.");
+ m_iProjectionAngleCount = data.size() / 12;
+ m_pProjectionAngles = new SConeProjection[m_iProjectionAngleCount];
+
+ for (int i = 0; i < m_iProjectionAngleCount; ++i) {
+ SConeProjection& p = m_pProjectionAngles[i];
+ p.fSrcX = data[12*i + 0];
+ p.fSrcY = data[12*i + 1];
+ p.fSrcZ = data[12*i + 2];
+ p.fDetUX = data[12*i + 6];
+ p.fDetUY = data[12*i + 7];
+ p.fDetUZ = data[12*i + 8];
+ p.fDetVX = data[12*i + 9];
+ p.fDetVY = data[12*i + 10];
+ p.fDetVZ = data[12*i + 11];
+
+ // The backend code currently expects the corner of the detector, while
+ // the matlab interface supplies the center
+ p.fDetSX = data[12*i + 3] - 0.5f * m_iDetectorRowCount * p.fDetVX - 0.5f * m_iDetectorColCount * p.fDetUX;
+ p.fDetSY = data[12*i + 4] - 0.5f * m_iDetectorRowCount * p.fDetVY - 0.5f * m_iDetectorColCount * p.fDetUY;
+ p.fDetSZ = data[12*i + 5] - 0.5f * m_iDetectorRowCount * p.fDetVZ - 0.5f * m_iDetectorColCount * p.fDetUZ;
+ }
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CConeVecProjectionGeometry3D::initialize(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ const SConeProjection* _pProjectionAngles)
+{
+ m_iProjectionAngleCount = _iProjectionAngleCount;
+ m_iDetectorRowCount = _iDetectorRowCount;
+ m_iDetectorColCount = _iDetectorColCount;
+ m_pProjectionAngles = new SConeProjection[m_iProjectionAngleCount];
+ for (int i = 0; i < m_iProjectionAngleCount; ++i)
+ m_pProjectionAngles[i] = _pProjectionAngles[i];
+
+ // TODO: check?
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Clone
+CProjectionGeometry3D* CConeVecProjectionGeometry3D::clone() const
+{
+ CConeVecProjectionGeometry3D* res = new CConeVecProjectionGeometry3D();
+ res->m_bInitialized = m_bInitialized;
+ res->m_iProjectionAngleCount = m_iProjectionAngleCount;
+ res->m_iDetectorRowCount = m_iDetectorRowCount;
+ res->m_iDetectorColCount = m_iDetectorColCount;
+ res->m_iDetectorTotCount = m_iDetectorTotCount;
+ res->m_fDetectorSpacingX = m_fDetectorSpacingX;
+ res->m_fDetectorSpacingY = m_fDetectorSpacingY;
+ res->m_pProjectionAngles = new SConeProjection[m_iProjectionAngleCount];
+ memcpy(res->m_pProjectionAngles, m_pProjectionAngles, sizeof(m_pProjectionAngles[0])*m_iProjectionAngleCount);
+ return res;
+}
+
+//----------------------------------------------------------------------------------------
+// is equal
+bool CConeVecProjectionGeometry3D::isEqual(const CProjectionGeometry3D * _pGeom2) const
+{
+ if (_pGeom2 == NULL) return false;
+
+ // try to cast argument to CConeProjectionGeometry3D
+ const CConeVecProjectionGeometry3D* pGeom2 = dynamic_cast<const CConeVecProjectionGeometry3D*>(_pGeom2);
+ if (pGeom2 == NULL) return false;
+
+ // both objects must be initialized
+ if (!m_bInitialized || !pGeom2->m_bInitialized) return false;
+
+ // check all values
+ if (m_iProjectionAngleCount != pGeom2->m_iProjectionAngleCount) return false;
+ if (m_iDetectorRowCount != pGeom2->m_iDetectorRowCount) return false;
+ if (m_iDetectorColCount != pGeom2->m_iDetectorColCount) return false;
+ if (m_iDetectorTotCount != pGeom2->m_iDetectorTotCount) return false;
+ //if (m_fDetectorSpacingX != pGeom2->m_fDetectorSpacingX) return false;
+ //if (m_fDetectorSpacingY != pGeom2->m_fDetectorSpacingY) return false;
+
+ for (int i = 0; i < m_iProjectionAngleCount; ++i) {
+ if (memcmp(&m_pProjectionAngles[i], &pGeom2->m_pProjectionAngles[i], sizeof(m_pProjectionAngles[i])) != 0) return false;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// is of type
+bool CConeVecProjectionGeometry3D::isOfType(const std::string& _sType) const
+{
+ return (_sType == "cone3d_vec");
+}
+
+//----------------------------------------------------------------------------------------
+void CConeVecProjectionGeometry3D::toXML(XMLNode* _sNode) const
+{
+ _sNode->addAttribute("type","cone3d_vec");
+ _sNode->addChildNode("DetectorRowCount", m_iDetectorRowCount);
+ _sNode->addChildNode("DetectorColCount", m_iDetectorColCount);
+ // TODO:
+ //_sNode->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount);
+}
+
+CVector3D CConeVecProjectionGeometry3D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const
+{
+ const SConeProjection& p = m_pProjectionAngles[_iProjectionIndex];
+ int u = _iDetectorIndex % m_iDetectorColCount;
+ int v = _iDetectorIndex / m_iDetectorColCount;
+
+ return CVector3D(p.fDetSX + (u+0.5)*p.fDetUX + (v+0.5)*p.fDetVX - p.fSrcX, p.fDetSY + (u+0.5)*p.fDetUY + (v+0.5)*p.fDetVY - p.fSrcY, p.fDetSZ + (u+0.5)*p.fDetUZ + (v+0.5)*p.fDetVZ - p.fSrcZ);
+}
+
+
+//----------------------------------------------------------------------------------------
+
+bool CConeVecProjectionGeometry3D::_check()
+{
+ // TODO
+ return true;
+}
+
+} // end namespace astra
diff --git a/src/Config.cpp b/src/Config.cpp
new file mode 100644
index 0000000..8c5cbf5
--- /dev/null
+++ b/src/Config.cpp
@@ -0,0 +1,166 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Config.h"
+
+// For explicit ConfigStackCheck instantiations
+#include "astra/Algorithm.h"
+#include "astra/VolumeGeometry2D.h"
+#include "astra/VolumeGeometry3D.h"
+#include "astra/ProjectionGeometry2D.h"
+#include "astra/ProjectionGeometry3D.h"
+#include "astra/Projector2D.h"
+#include "astra/Projector3D.h"
+
+using namespace astra;
+using namespace std;
+
+//-----------------------------------------------------------------------------
+// default constructor
+Config::Config()
+{
+ self = 0;
+}
+
+//-----------------------------------------------------------------------------
+// not so default constructor
+Config::Config(XMLNode* _self)
+{
+ self = _self;
+}
+
+Config::~Config()
+{
+ delete self;
+ self = 0;
+}
+
+template <class T>
+ConfigStackCheck<T>::ConfigStackCheck(const char *_name, T* _obj, const Config& _cfg)
+ : object(_obj), cfg(&_cfg), name(_name)
+{
+ assert(object);
+ assert(cfg);
+ if (!object->configCheckData) {
+ object->configCheckData = new ConfigCheckData;
+ object->configCheckData->parseDepth = 0;
+ }
+
+ object->configCheckData->parseDepth++;
+}
+
+template <class T>
+ConfigStackCheck<T>::~ConfigStackCheck()
+{
+ assert(object->configCheckData);
+ assert(object->configCheckData->parseDepth > 0);
+
+
+ if (object->configCheckData->parseDepth == 1) {
+ // Entirely done with parsing this Config object
+
+ if (object->isInitialized())
+ stopParsing();
+
+ delete object->configCheckData;
+ object->configCheckData = 0;
+ } else {
+ object->configCheckData->parseDepth--;
+ }
+}
+
+
+// returns true if no unused nodes/options
+template <class T>
+bool ConfigStackCheck<T>::stopParsing()
+{
+ assert(object->configCheckData);
+ assert(object->configCheckData->parseDepth > 0);
+
+ if (object->configCheckData->parseDepth > 1)
+ return true;
+
+ // If this was the top-level parse function, check
+
+ std::string errors;
+
+ std::list<XMLNode*> nodes = cfg->self->getNodes();
+ for (std::list<XMLNode*>::iterator i = nodes.begin(); i != nodes.end(); ++i)
+ {
+ std::string nodeName = (*i)->getName();
+
+ if (nodeName == "Option") {
+ nodeName = (*i)->getAttribute("key", "");
+ if (object->configCheckData->parsedOptions.find(nodeName) == object->configCheckData->parsedOptions.end()) {
+ if (!errors.empty()) errors += ", ";
+ errors += nodeName;
+ }
+ } else {
+ if (object->configCheckData->parsedNodes.find(nodeName) == object->configCheckData->parsedNodes.end()) {
+ if (!errors.empty()) errors += ", ";
+ errors += nodeName;
+ }
+ }
+ }
+ for (std::list<XMLNode*>::iterator i = nodes.begin(); i != nodes.end(); ++i)
+ delete (*i);
+ nodes.clear();
+
+ if (!errors.empty()) {
+ cout << "Warning: " << name << ": unused configuration options: " << errors << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+template <class T>
+void ConfigStackCheck<T>::markNodeParsed(const std::string& nodeName)
+{
+ assert(object->configCheckData);
+ assert(object->configCheckData->parseDepth > 0);
+ object->configCheckData->parsedNodes.insert(nodeName);
+}
+
+template <class T>
+void ConfigStackCheck<T>::markOptionParsed(const std::string& nodeName)
+{
+ assert(object->configCheckData);
+ assert(object->configCheckData->parseDepth > 0);
+ object->configCheckData->parsedOptions.insert(nodeName);
+}
+
+
+template class ConfigStackCheck<CAlgorithm>;
+template class ConfigStackCheck<CProjectionGeometry2D>;
+template class ConfigStackCheck<CProjectionGeometry3D>;
+template class ConfigStackCheck<CVolumeGeometry2D>;
+template class ConfigStackCheck<CVolumeGeometry3D>;
+template class ConfigStackCheck<CProjector2D>;
+template class ConfigStackCheck<CProjector3D>;
+
diff --git a/src/ConvexHullAlgorithm.cpp b/src/ConvexHullAlgorithm.cpp
new file mode 100644
index 0000000..e769420
--- /dev/null
+++ b/src/ConvexHullAlgorithm.cpp
@@ -0,0 +1,239 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ConvexHullAlgorithm.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+
+namespace astra {
+
+#include "astra/Projector2DImpl.inl"
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CConvexHullAlgorithm::type = "ConvexHull";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CConvexHullAlgorithm::CConvexHullAlgorithm()
+{
+ _clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+CConvexHullAlgorithm::CConvexHullAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstructionMask)
+{
+ _clear();
+ initialize(_pProjector, _pSinogram, _pReconstructionMask);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CConvexHullAlgorithm::~CConvexHullAlgorithm()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CConvexHullAlgorithm::_clear()
+{
+ m_bIsInitialized = false;
+
+ m_pProjectionPixelWeight = NULL;
+ m_pReconstructionMask = NULL;
+ m_pSinogram = NULL;
+
+ m_pProjector = NULL;
+ m_pDataProjector = NULL;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CConvexHullAlgorithm::clear()
+{
+ m_bIsInitialized = false;
+
+ ASTRA_DELETE(m_pProjectionPixelWeight);
+ m_pReconstructionMask = NULL;
+ m_pSinogram = NULL;
+
+ m_pProjector = NULL;
+ ASTRA_DELETE(m_pDataProjector);
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CConvexHullAlgorithm::_check()
+{
+ ASTRA_CONFIG_CHECK(m_pReconstructionMask, "ConvexHull", "Invalid ReconstructionMask Object");
+ ASTRA_CONFIG_CHECK(m_pReconstructionMask->isInitialized(), "ConvexHull", "Invalid ReconstructionMask Object");
+ ASTRA_CONFIG_CHECK(m_pProjectionPixelWeight, "ConvexHull", "Invalid ProjectionPixelWeight Object");
+ ASTRA_CONFIG_CHECK(m_pProjectionPixelWeight->isInitialized(), "ConvexHull", "Invalid ProjectionPixelWeight Object");
+ ASTRA_CONFIG_CHECK(m_pSinogram, "ConvexHull", "Invalid Sinogram Object");
+ ASTRA_CONFIG_CHECK(m_pSinogram->isInitialized(), "ConvexHull", "Invalid Sinogram Object");
+
+ ASTRA_CONFIG_CHECK(m_pDataProjector, "ConvexHull", "Invalid Data Projector Policy");
+ ASTRA_CONFIG_CHECK(m_pProjector, "ConvexHull", "Invalid Projector Object");
+ ASTRA_CONFIG_CHECK(m_pProjector->isInitialized(), "ConvexHull", "Invalid Projector Object");
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CConvexHullAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // projector
+ XMLNode* node = _cfg.self->getSingleNode("ProjectorId");
+ ASTRA_CONFIG_CHECK(node, "ConvexHull", "No ProjectorId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pProjector = CProjector2DManager::getSingleton().get(id);
+ ASTRA_DELETE(node);
+
+ // sinogram data
+ node = _cfg.self->getSingleNode("ProjectionDataId");
+ ASTRA_CONFIG_CHECK(node, "ConvexHull", "No ProjectionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pSinogram = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+
+ // reconstruction mask
+ node = _cfg.self->getSingleNode("ConvexHullDataId");
+ ASTRA_CONFIG_CHECK(node, "ConvexHull", "No ReconstructionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pReconstructionMask = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+
+ // init data objects and data projectors
+ _init();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CConvexHullAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstructionMask)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstructionMask = _pReconstructionMask;
+
+ // init data objects and data projectors
+ _init();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize Data Projectors - private
+void CConvexHullAlgorithm::_init()
+{
+ // create data objects
+ m_pProjectionPixelWeight = new CFloat32VolumeData2D(m_pProjector->getVolumeGeometry());
+ m_pProjectionPixelWeight->setData(0);
+
+ // forward projection data projector
+ m_pDataProjector = dispatchDataProjector(
+ m_pProjector,
+ //SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ TotalPixelWeightBySinogramPolicy(m_pSinogram, m_pProjectionPixelWeight) // pixel weight * sinogram
+ );
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CConvexHullAlgorithm::getInformation()
+{
+ map<string, boost::any> res;
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CConvexHullAlgorithm::getInformation(std::string _sIdentifier)
+{
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CConvexHullAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ m_pReconstructionMask->setData(1.0f);
+
+ // loop angles
+ for (int iProjection = 0; iProjection < m_pProjector->getProjectionGeometry()->getProjectionAngleCount(); ++iProjection) {
+
+ m_pProjectionPixelWeight->setData(0.0f);
+
+ // project
+ m_pDataProjector->projectSingleProjection(iProjection);
+
+ // loop values and set to zero
+ for (int iPixel = 0; iPixel < m_pReconstructionMask->getSize(); ++iPixel) {
+ if (m_pProjectionPixelWeight->getData()[iPixel] == 0) {
+ m_pReconstructionMask->getData()[iPixel] = 0;
+ }
+ }
+
+ }
+
+}
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/CudaBackProjectionAlgorithm.cpp b/src/CudaBackProjectionAlgorithm.cpp
new file mode 100644
index 0000000..7d597b8
--- /dev/null
+++ b/src/CudaBackProjectionAlgorithm.cpp
@@ -0,0 +1,96 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaBackProjectionAlgorithm.h"
+
+#include "../cuda/2d/astra.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaBackProjectionAlgorithm::type = "BP_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaBackProjectionAlgorithm::CCudaBackProjectionAlgorithm()
+{
+ m_bIsInitialized = false;
+ CCudaReconstructionAlgorithm2D::_clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaBackProjectionAlgorithm::~CCudaBackProjectionAlgorithm()
+{
+ // The actual work is done by ~CCudaReconstructionAlgorithm2D
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaBackProjectionAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaBackProjectionAlgorithm", this, _cfg);
+
+ m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_cfg);
+
+ if (!m_bIsInitialized)
+ return false;
+
+ m_pAlgo = new BPalgo();
+ m_bAlgoInit = false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaBackProjectionAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex, int _iPixelSuperSampling)
+{
+ m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction, _iGPUindex, 1, _iPixelSuperSampling);
+
+ if (!m_bIsInitialized)
+ return false;
+
+ m_pAlgo = new BPalgo();
+ m_bAlgoInit = false;
+
+ return true;
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaBackProjectionAlgorithm3D.cpp b/src/CudaBackProjectionAlgorithm3D.cpp
new file mode 100644
index 0000000..b60adf1
--- /dev/null
+++ b/src/CudaBackProjectionAlgorithm3D.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/CudaBackProjectionAlgorithm3D.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+
+#include "astra/ConeProjectionGeometry3D.h"
+#include "astra/ParallelProjectionGeometry3D.h"
+#include "astra/ParallelVecProjectionGeometry3D.h"
+#include "astra/ConeVecProjectionGeometry3D.h"
+
+#include "../cuda/3d/astra3d.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaBackProjectionAlgorithm3D::type = "BP3D_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaBackProjectionAlgorithm3D::CCudaBackProjectionAlgorithm3D()
+{
+ m_bIsInitialized = false;
+ m_iGPUIndex = 0;
+ m_iVoxelSuperSampling = 1;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor with initialization
+CCudaBackProjectionAlgorithm3D::CCudaBackProjectionAlgorithm3D(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pProjectionData,
+ CFloat32VolumeData3DMemory* _pReconstruction)
+{
+ _clear();
+ initialize(_pProjector, _pProjectionData, _pReconstruction);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaBackProjectionAlgorithm3D::~CCudaBackProjectionAlgorithm3D()
+{
+ CReconstructionAlgorithm3D::_clear();
+}
+
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CCudaBackProjectionAlgorithm3D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CReconstructionAlgorithm3D::_check(), "BP3D_CUDA", "Error in ReconstructionAlgorithm3D initialization");
+
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaBackProjectionAlgorithm3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaBackProjectionAlgorithm3D", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CReconstructionAlgorithm3D::initialize(_cfg)) {
+ return false;
+ }
+
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ CC.markOptionParsed("GPUindex");
+ m_iVoxelSuperSampling = (int)_cfg.self->getOptionNumerical("VoxelSuperSampling", 1);
+ CC.markOptionParsed("VoxelSuperSampling");
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaBackProjectionAlgorithm3D::initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pSinogram,
+ CFloat32VolumeData3DMemory* _pReconstruction)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaBackProjectionAlgorithm3D::getInformation()
+{
+ map<string, boost::any> res;
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaBackProjectionAlgorithm3D::getInformation(std::string _sIdentifier)
+{
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaBackProjectionAlgorithm3D::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ CFloat32ProjectionData3DMemory* pSinoMem = dynamic_cast<CFloat32ProjectionData3DMemory*>(m_pSinogram);
+ ASTRA_ASSERT(pSinoMem);
+ CFloat32VolumeData3DMemory* pReconMem = dynamic_cast<CFloat32VolumeData3DMemory*>(m_pReconstruction);
+ ASTRA_ASSERT(pReconMem);
+
+ const CProjectionGeometry3D* projgeom = pSinoMem->getGeometry();
+ const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(projgeom);
+ const CParallelProjectionGeometry3D* par3dgeom = dynamic_cast<const CParallelProjectionGeometry3D*>(projgeom);
+ const CConeVecProjectionGeometry3D* conevecgeom = dynamic_cast<const CConeVecProjectionGeometry3D*>(projgeom);
+ const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(projgeom);
+ const CVolumeGeometry3D& volgeom = *pReconMem->getGeometry();
+
+ if (conegeom) {
+ astraCudaConeBP(pReconMem->getData(), pSinoMem->getDataConst(),
+ volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount(),
+ conegeom->getProjectionCount(),
+ conegeom->getDetectorColCount(),
+ conegeom->getDetectorRowCount(),
+ conegeom->getOriginSourceDistance(),
+ conegeom->getOriginDetectorDistance(),
+ conegeom->getDetectorSpacingX(),
+ conegeom->getDetectorSpacingY(),
+ conegeom->getProjectionAngles(),
+ m_iGPUIndex, m_iVoxelSuperSampling);
+ } else if (par3dgeom) {
+ astraCudaPar3DBP(pReconMem->getData(), pSinoMem->getDataConst(),
+ volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount(),
+ par3dgeom->getProjectionCount(),
+ par3dgeom->getDetectorColCount(),
+ par3dgeom->getDetectorRowCount(),
+ par3dgeom->getDetectorSpacingX(),
+ par3dgeom->getDetectorSpacingY(),
+ par3dgeom->getProjectionAngles(),
+ m_iGPUIndex, m_iVoxelSuperSampling);
+ } else if (parvec3dgeom) {
+ astraCudaPar3DBP(pReconMem->getData(), pSinoMem->getDataConst(),
+ volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount(),
+ parvec3dgeom->getProjectionCount(),
+ parvec3dgeom->getDetectorColCount(),
+ parvec3dgeom->getDetectorRowCount(),
+ parvec3dgeom->getProjectionVectors(),
+ m_iGPUIndex, m_iVoxelSuperSampling);
+ } else if (conevecgeom) {
+ astraCudaConeBP(pReconMem->getData(), pSinoMem->getDataConst(),
+ volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount(),
+ conevecgeom->getProjectionCount(),
+ conevecgeom->getDetectorColCount(),
+ conevecgeom->getDetectorRowCount(),
+ conevecgeom->getProjectionVectors(),
+ m_iGPUIndex, m_iVoxelSuperSampling);
+ } else {
+ ASTRA_ASSERT(false);
+ }
+
+}
+
+
+} // namespace astra
diff --git a/src/CudaCglsAlgorithm.cpp b/src/CudaCglsAlgorithm.cpp
new file mode 100644
index 0000000..c408638
--- /dev/null
+++ b/src/CudaCglsAlgorithm.cpp
@@ -0,0 +1,98 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaCglsAlgorithm.h"
+
+#include "../cuda/2d/cgls.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaCglsAlgorithm::type = "CGLS_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaCglsAlgorithm::CCudaCglsAlgorithm()
+{
+ m_bIsInitialized = false;
+ CReconstructionAlgorithm2D::_clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaCglsAlgorithm::~CCudaCglsAlgorithm()
+{
+ // The actual work is done by ~CCudaReconstructionAlgorithm2D
+}
+
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaCglsAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaCglsAlgorithm", this, _cfg);
+
+ m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_cfg);
+
+ if (!m_bIsInitialized)
+ return false;
+
+ m_pAlgo = new astraCUDA::CGLS();
+ m_bAlgoInit = false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaCglsAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex, int _iDetectorSuperSampling,
+ int _iPixelSuperSampling)
+{
+ m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction, _iGPUindex, _iDetectorSuperSampling, _iPixelSuperSampling);
+
+ if (!m_bIsInitialized)
+ return false;
+
+ m_pAlgo = new astraCUDA::CGLS();
+ m_bAlgoInit = false;
+
+ return true;
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaCglsAlgorithm3D.cpp b/src/CudaCglsAlgorithm3D.cpp
new file mode 100644
index 0000000..07569a2
--- /dev/null
+++ b/src/CudaCglsAlgorithm3D.cpp
@@ -0,0 +1,314 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/CudaCglsAlgorithm3D.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+
+#include "astra/ConeProjectionGeometry3D.h"
+#include "astra/ParallelVecProjectionGeometry3D.h"
+#include "astra/ConeVecProjectionGeometry3D.h"
+
+#include "../cuda/3d/astra3d.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaCglsAlgorithm3D::type = "CGLS3D_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaCglsAlgorithm3D::CCudaCglsAlgorithm3D()
+{
+ m_bIsInitialized = false;
+ m_pCgls = 0;
+ m_iGPUIndex = 0;
+ m_iVoxelSuperSampling = 1;
+ m_iDetectorSuperSampling = 1;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor with initialization
+CCudaCglsAlgorithm3D::CCudaCglsAlgorithm3D(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pProjectionData,
+ CFloat32VolumeData3DMemory* _pReconstruction)
+{
+ _clear();
+ initialize(_pProjector, _pProjectionData, _pReconstruction);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaCglsAlgorithm3D::~CCudaCglsAlgorithm3D()
+{
+ delete m_pCgls;
+ m_pCgls = 0;
+
+ CReconstructionAlgorithm3D::_clear();
+}
+
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CCudaCglsAlgorithm3D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CReconstructionAlgorithm3D::_check(), "CGLS3D", "Error in ReconstructionAlgorithm3D initialization");
+
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaCglsAlgorithm3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaCglsAlgorithm3D", this, _cfg);
+
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CReconstructionAlgorithm3D::initialize(_cfg)) {
+ return false;
+ }
+
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ CC.markOptionParsed("GPUindex");
+ m_iDetectorSuperSampling = (int)_cfg.self->getOptionNumerical("DetectorSuperSampling", 1);
+ CC.markOptionParsed("DetectorSuperSampling");
+ m_iVoxelSuperSampling = (int)_cfg.self->getOptionNumerical("VoxelSuperSampling", 1);
+ CC.markOptionParsed("VoxelSuperSampling");
+
+ m_pCgls = new AstraCGLS3d();
+
+ m_bAstraCGLSInit = false;
+
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaCglsAlgorithm3D::initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pSinogram,
+ CFloat32VolumeData3DMemory* _pReconstruction)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ m_pCgls = new AstraCGLS3d;
+
+ m_bAstraCGLSInit = false;
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaCglsAlgorithm3D::getInformation()
+{
+ map<string, boost::any> res;
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaCglsAlgorithm3D::getInformation(std::string _sIdentifier)
+{
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaCglsAlgorithm3D::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ const CProjectionGeometry3D* projgeom = m_pSinogram->getGeometry();
+ const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(projgeom);
+ const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(projgeom);
+ const CConeVecProjectionGeometry3D* conevec3dgeom = dynamic_cast<const CConeVecProjectionGeometry3D*>(projgeom);
+ const CVolumeGeometry3D& volgeom = *m_pReconstruction->getGeometry();
+
+ bool ok = true;
+
+ if (!m_bAstraCGLSInit) {
+
+ ok &= m_pCgls->setGPUIndex(m_iGPUIndex);
+
+ ok &= m_pCgls->setReconstructionGeometry(volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount());
+/*
+ unsigned int iProjAngles,
+ unsigned int iProjU,
+ unsigned int iProjV,
+ float fOriginSourceDistance,
+ float fOriginDetectorDistance,
+ float fDetUSize,
+ float fDetVSize,
+ const float *pfAngles)
+*/
+ fprintf(stderr, "01: %d\n", ok);
+
+ if (conegeom) {
+ ok &= m_pCgls->setConeGeometry(conegeom->getProjectionCount(),
+ conegeom->getDetectorColCount(),
+ conegeom->getDetectorRowCount(),
+ conegeom->getOriginSourceDistance(),
+ conegeom->getOriginDetectorDistance(),
+ conegeom->getDetectorSpacingX(),
+ conegeom->getDetectorSpacingY(),
+ conegeom->getProjectionAngles());
+ } else if (parvec3dgeom) {
+ ok &= m_pCgls->setPar3DGeometry(parvec3dgeom->getProjectionCount(),
+ parvec3dgeom->getDetectorColCount(),
+ parvec3dgeom->getDetectorRowCount(),
+ parvec3dgeom->getProjectionVectors());
+ } else if (conevec3dgeom) {
+ ok &= m_pCgls->setConeGeometry(conevec3dgeom->getProjectionCount(),
+ conevec3dgeom->getDetectorColCount(),
+ conevec3dgeom->getDetectorRowCount(),
+ conevec3dgeom->getProjectionVectors());
+ } else {
+ ASTRA_ASSERT(false);
+ }
+ fprintf(stderr, "02: %d\n", ok);
+
+ ok &= m_pCgls->enableSuperSampling(m_iVoxelSuperSampling, m_iDetectorSuperSampling);
+
+ if (m_bUseReconstructionMask)
+ ok &= m_pCgls->enableVolumeMask();
+#if 0
+ if (m_bUseSinogramMask)
+ ok &= m_pCgls->enableSinogramMask();
+#endif
+
+ ASTRA_ASSERT(ok);
+ fprintf(stderr, "03: %d\n", ok);
+
+ ok &= m_pCgls->init();
+ fprintf(stderr, "04: %d\n", ok);
+
+ ASTRA_ASSERT(ok);
+
+ m_bAstraCGLSInit = true;
+
+ }
+
+ CFloat32ProjectionData3DMemory* pSinoMem = dynamic_cast<CFloat32ProjectionData3DMemory*>(m_pSinogram);
+ ASTRA_ASSERT(pSinoMem);
+
+ ok = m_pCgls->setSinogram(pSinoMem->getDataConst(), m_pSinogram->getGeometry()->getDetectorColCount());
+
+ fprintf(stderr, "1: %d\n", ok);
+ ASTRA_ASSERT(ok);
+
+ if (m_bUseReconstructionMask) {
+ CFloat32VolumeData3DMemory* pRMaskMem = dynamic_cast<CFloat32VolumeData3DMemory*>(m_pReconstructionMask);
+ ASTRA_ASSERT(pRMaskMem);
+ ok &= m_pCgls->setVolumeMask(pRMaskMem->getDataConst(), volgeom.getGridColCount());
+ }
+#if 0
+ if (m_bUseSinogramMask) {
+ CFloat32ProjectionData3DMemory* pSMaskMem = dynamic_cast<CFloat32ProjectionData3DMemory*>(m_pSinogramMask);
+ ASTRA_ASSERT(pSMaskMem);
+ ok &= m_pCgls->setSinogramMask(pSMaskMem->getDataConst(), m_pSinogramMask->getGeometry()->getDetectorColCount());
+ }
+#endif
+ fprintf(stderr, "2: %d\n", ok);
+
+ CFloat32VolumeData3DMemory* pReconMem = dynamic_cast<CFloat32VolumeData3DMemory*>(m_pReconstruction);
+ ASTRA_ASSERT(pReconMem);
+ ok &= m_pCgls->setStartReconstruction(pReconMem->getDataConst(),
+ volgeom.getGridColCount());
+
+ ASTRA_ASSERT(ok);
+ fprintf(stderr, "3: %d\n", ok);
+
+#if 0
+ if (m_bUseMinConstraint)
+ ok &= m_pCgls->setMinConstraint(m_fMinValue);
+ if (m_bUseMaxConstraint)
+ ok &= m_pCgls->setMaxConstraint(m_fMaxValue);
+#endif
+ fprintf(stderr, "4: %d\n", ok);
+
+ ok &= m_pCgls->iterate(_iNrIterations);
+ ASTRA_ASSERT(ok);
+ fprintf(stderr, "5: %d\n", ok);
+
+ ok &= m_pCgls->getReconstruction(pReconMem->getData(),
+ volgeom.getGridColCount());
+ fprintf(stderr, "6: %d\n", ok);
+ ASTRA_ASSERT(ok);
+
+
+}
+//----------------------------------------------------------------------------------------
+void CCudaCglsAlgorithm3D::signalAbort()
+{
+ if (m_bIsInitialized && m_pCgls) {
+ m_pCgls->signalAbort();
+ }
+}
+
+bool CCudaCglsAlgorithm3D::getResidualNorm(float32& _fNorm)
+{
+ if (!m_bIsInitialized || !m_pCgls)
+ return false;
+
+ _fNorm = m_pCgls->computeDiffNorm();
+
+ return true;
+}
+
+
+
+} // namespace astra
diff --git a/src/CudaDartMaskAlgorithm.cpp b/src/CudaDartMaskAlgorithm.cpp
new file mode 100644
index 0000000..9c9b83f
--- /dev/null
+++ b/src/CudaDartMaskAlgorithm.cpp
@@ -0,0 +1,166 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaDartMaskAlgorithm.h"
+
+#include "../cuda/2d/darthelper.h"
+#include "../cuda/2d/algo.h"
+
+#include "astra/AstraObjectManager.h"
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaDartMaskAlgorithm::type = "DARTMASK_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaDartMaskAlgorithm::CCudaDartMaskAlgorithm()
+{
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaDartMaskAlgorithm::~CCudaDartMaskAlgorithm()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaDartMaskAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaDartMaskAlgorithm", this, _cfg);
+
+ // reconstruction data
+ XMLNode* node = _cfg.self->getSingleNode("SegmentationDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No SegmentationDataId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pSegmentation = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("SegmentationDataId");
+
+ // reconstruction data
+ node = _cfg.self->getSingleNode("MaskDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No MaskDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pMask = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("MaskDataId");
+
+ // Option: GPU number
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUIndex", m_iGPUIndex);
+ CC.markOptionParsed("GPUindex");
+ if (!_cfg.self->hasOption("GPUindex"))
+ CC.markOptionParsed("GPUIndex");
+
+ // Option: Connectivity
+ m_iConn = (unsigned int)_cfg.self->getOptionNumerical("Connectivity", 8);
+ CC.markOptionParsed("Connectivity");
+
+ // Option: Threshold
+ m_iThreshold = (unsigned int)_cfg.self->getOptionNumerical("Threshold", 1);
+ CC.markOptionParsed("Threshold");
+
+ // Option: Radius
+ m_iRadius = (unsigned int)_cfg.self->getOptionNumerical("Radius", 1);
+ CC.markOptionParsed("Radius");
+
+ _check();
+
+ if (!m_bIsInitialized)
+ return false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+//bool CCudaDartMaskAlgorithm::initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn)
+//{
+// return false;
+//}
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaDartMaskAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ const CVolumeGeometry2D& volgeom = *m_pSegmentation->getGeometry();
+ unsigned int width = volgeom.getGridColCount();
+ unsigned int height = volgeom.getGridRowCount();
+
+ astraCUDA::setGPUIndex(m_iGPUIndex);
+ astraCUDA::dartMask(m_pMask->getData(), m_pSegmentation->getDataConst(), m_iConn, m_iRadius, m_iThreshold, width, height);
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaDartMaskAlgorithm::_check()
+{
+
+ // connectivity: 4 of 8
+
+ // gpuindex >= 0
+
+
+ // success
+ m_bIsInitialized = true;
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaDartMaskAlgorithm::getInformation()
+{
+ map<string,boost::any> res;
+ // TODO: add PDART-specific options
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+}
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaDartMaskAlgorithm::getInformation(std::string _sIdentifier)
+{
+ return NULL;
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaDartMaskAlgorithm3D.cpp b/src/CudaDartMaskAlgorithm3D.cpp
new file mode 100644
index 0000000..7965587
--- /dev/null
+++ b/src/CudaDartMaskAlgorithm3D.cpp
@@ -0,0 +1,168 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaDartMaskAlgorithm3D.h"
+
+#include "../cuda/3d/darthelper3d.h"
+#include "../cuda/3d/dims3d.h"
+
+#include "astra/AstraObjectManager.h"
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaDartMaskAlgorithm3D::type = "DARTMASK3D_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaDartMaskAlgorithm3D::CCudaDartMaskAlgorithm3D()
+{
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaDartMaskAlgorithm3D::~CCudaDartMaskAlgorithm3D()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaDartMaskAlgorithm3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaDartMaskAlgorithm", this, _cfg);
+
+ // reconstruction data
+ XMLNode* node = _cfg.self->getSingleNode("SegmentationDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No SegmentationDataId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pSegmentation = dynamic_cast<CFloat32VolumeData3DMemory*>(CData3DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("SegmentationDataId");
+
+ // reconstruction data
+ node = _cfg.self->getSingleNode("MaskDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No MaskDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pMask = dynamic_cast<CFloat32VolumeData3DMemory*>(CData3DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("MaskDataId");
+
+ // Option: GPU number
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUIndex", m_iGPUIndex);
+ CC.markOptionParsed("GPUindex");
+ if (!_cfg.self->hasOption("GPUindex"))
+ CC.markOptionParsed("GPUIndex");
+
+ // Option: Connectivity
+ m_iConn = (unsigned int)_cfg.self->getOptionNumerical("Connectivity", 8);
+ CC.markOptionParsed("Connectivity");
+
+ // Option: Threshold
+ m_iThreshold = (unsigned int)_cfg.self->getOptionNumerical("Threshold", 1);
+ CC.markOptionParsed("Threshold");
+
+ // Option: Radius
+ m_iRadius = (unsigned int)_cfg.self->getOptionNumerical("Radius", 1);
+ CC.markOptionParsed("Radius");
+
+ _check();
+
+ if (!m_bIsInitialized)
+ return false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+//bool CCudaDartMaskAlgorithm3D::initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn)
+//{
+// return false;
+//}
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaDartMaskAlgorithm3D::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ const CVolumeGeometry3D& volgeom = *m_pSegmentation->getGeometry();
+ astraCUDA3d::SDimensions3D dims;
+ dims.iVolX = volgeom.getGridColCount();
+ dims.iVolY = volgeom.getGridRowCount();
+ dims.iVolZ = volgeom.getGridSliceCount();
+
+ astraCUDA3d::setGPUIndex(m_iGPUIndex);
+ astraCUDA3d::dartMasking(m_pMask->getData(), m_pSegmentation->getDataConst(), m_iConn, m_iRadius, m_iThreshold, dims);
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaDartMaskAlgorithm3D::_check()
+{
+
+ // connectivity: 4 of 8
+
+ // gpuindex >= 0
+
+
+ // success
+ m_bIsInitialized = true;
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaDartMaskAlgorithm3D::getInformation()
+{
+ map<string,boost::any> res;
+ // TODO: add PDART-specific options
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+}
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaDartMaskAlgorithm3D::getInformation(std::string _sIdentifier)
+{
+ return NULL;
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaDartSmoothingAlgorithm.cpp b/src/CudaDartSmoothingAlgorithm.cpp
new file mode 100644
index 0000000..91cde6d
--- /dev/null
+++ b/src/CudaDartSmoothingAlgorithm.cpp
@@ -0,0 +1,158 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaDartSmoothingAlgorithm.h"
+
+#include "../cuda/2d/darthelper.h"
+#include "../cuda/2d/algo.h"
+
+#include "astra/AstraObjectManager.h"
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaDartSmoothingAlgorithm::type = "DARTSMOOTHING_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaDartSmoothingAlgorithm::CCudaDartSmoothingAlgorithm()
+{
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaDartSmoothingAlgorithm::~CCudaDartSmoothingAlgorithm()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaDartSmoothingAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaDartSmoothingAlgorithm", this, _cfg);
+
+ // reconstruction data
+ XMLNode* node = _cfg.self->getSingleNode("InDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No InDataId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pIn = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("InDataId");
+
+ // reconstruction data
+ node = _cfg.self->getSingleNode("OutDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No OutDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pOut = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("OutDataId");
+
+ // Option: GPU number
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUIndex", m_iGPUIndex);
+ CC.markOptionParsed("GPUindex");
+ if (!_cfg.self->hasOption("GPUindex"))
+ CC.markOptionParsed("GPUIndex");
+
+ // Option: Radius
+ m_fB = (float)_cfg.self->getOptionNumerical("Intensity", 0.3f);
+ CC.markOptionParsed("Intensity");
+
+ // Option: Radius
+ m_iRadius = (unsigned int)_cfg.self->getOptionNumerical("Radius", 1);
+ CC.markOptionParsed("Radius");
+
+
+ _check();
+
+ if (!m_bIsInitialized)
+ return false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+//bool CCudaDartMaskAlgorithm::initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn)
+//{
+// return false;
+//}
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaDartSmoothingAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ const CVolumeGeometry2D& volgeom = *m_pIn->getGeometry();
+ unsigned int width = volgeom.getGridColCount();
+ unsigned int height = volgeom.getGridRowCount();
+
+ astraCUDA::setGPUIndex(m_iGPUIndex);
+
+ astraCUDA::dartSmoothing(m_pOut->getData(), m_pIn->getDataConst(), m_fB, m_iRadius, width, height);
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaDartSmoothingAlgorithm::_check()
+{
+ // success
+ m_bIsInitialized = true;
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaDartSmoothingAlgorithm::getInformation()
+{
+ map<string,boost::any> res;
+ // TODO: add PDART-specific options
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+}
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaDartSmoothingAlgorithm::getInformation(std::string _sIdentifier)
+{
+ return NULL;
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaDartSmoothingAlgorithm3D.cpp b/src/CudaDartSmoothingAlgorithm3D.cpp
new file mode 100644
index 0000000..50ef847
--- /dev/null
+++ b/src/CudaDartSmoothingAlgorithm3D.cpp
@@ -0,0 +1,160 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaDartSmoothingAlgorithm3D.h"
+
+#include "../cuda/3d/darthelper3d.h"
+#include "../cuda/3d/dims3d.h"
+
+#include "astra/AstraObjectManager.h"
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaDartSmoothingAlgorithm3D::type = "DARTSMOOTHING3D_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaDartSmoothingAlgorithm3D::CCudaDartSmoothingAlgorithm3D()
+{
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaDartSmoothingAlgorithm3D::~CCudaDartSmoothingAlgorithm3D()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaDartSmoothingAlgorithm3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaDartSmoothingAlgorithm", this, _cfg);
+
+ // reconstruction data
+ XMLNode* node = _cfg.self->getSingleNode("InDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No InDataId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pIn = dynamic_cast<CFloat32VolumeData3DMemory*>(CData3DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("InDataId");
+
+ // reconstruction data
+ node = _cfg.self->getSingleNode("OutDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No OutDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pOut = dynamic_cast<CFloat32VolumeData3DMemory*>(CData3DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("OutDataId");
+
+ // Option: GPU number
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUIndex", m_iGPUIndex);
+ CC.markOptionParsed("GPUindex");
+ if (!_cfg.self->hasOption("GPUindex"))
+ CC.markOptionParsed("GPUIndex");
+
+ // Option: Intensity
+ m_fB = (float)_cfg.self->getOptionNumerical("Intensity", 0.3f);
+ CC.markOptionParsed("Intensity");
+
+ // Option: Radius
+ m_iRadius = (unsigned int)_cfg.self->getOptionNumerical("Radius", 1);
+ CC.markOptionParsed("Radius");
+
+ _check();
+
+ if (!m_bIsInitialized)
+ return false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+//bool CCudaDartSmoothingAlgorithm3D::initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn)
+//{
+// return false;
+//}
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaDartSmoothingAlgorithm3D::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ const CVolumeGeometry3D& volgeom = *m_pIn->getGeometry();
+ astraCUDA3d::SDimensions3D dims;
+ dims.iVolX = volgeom.getGridColCount();
+ dims.iVolY = volgeom.getGridRowCount();
+ dims.iVolZ = volgeom.getGridSliceCount();
+
+ astraCUDA3d::setGPUIndex(m_iGPUIndex);
+ astraCUDA3d::dartSmoothing(m_pOut->getData(), m_pIn->getDataConst(), m_fB, m_iRadius, dims);
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaDartSmoothingAlgorithm3D::_check()
+{
+ // geometry of inData must match that of outData
+
+
+ // success
+ m_bIsInitialized = true;
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaDartSmoothingAlgorithm3D::getInformation()
+{
+ map<string,boost::any> res;
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+}
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaDartSmoothingAlgorithm3D::getInformation(std::string _sIdentifier)
+{
+ return NULL;
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaDataOperationAlgorithm.cpp b/src/CudaDataOperationAlgorithm.cpp
new file mode 100644
index 0000000..ed2ac94
--- /dev/null
+++ b/src/CudaDataOperationAlgorithm.cpp
@@ -0,0 +1,208 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaDataOperationAlgorithm.h"
+
+#include "../cuda/2d/dataop.h"
+#include "../cuda/2d/algo.h"
+#include "../cuda/2d/darthelper.h"
+#include "../cuda/2d/arith.h"
+
+#include "astra/AstraObjectManager.h"
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaDataOperationAlgorithm::type = "DataOperation_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaDataOperationAlgorithm::CCudaDataOperationAlgorithm()
+{
+ m_pMask = NULL;
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaDataOperationAlgorithm::~CCudaDataOperationAlgorithm()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaDataOperationAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CCudaDataOperationAlgorithm", this, _cfg);
+
+ // operation
+ XMLNode* node = _cfg.self->getSingleNode("Operation");
+ ASTRA_CONFIG_CHECK(node, "CCudaDataOperationAlgorithm", "No Operation tag specified.");
+ m_sOperation = node->getContent();
+ m_sOperation.erase(std::remove(m_sOperation.begin(), m_sOperation.end(), ' '), m_sOperation.end());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("Operation");
+
+ // data
+ node = _cfg.self->getSingleNode("DataId");
+ ASTRA_CONFIG_CHECK(node, "CCudaDataOperationAlgorithm", "No DataId tag specified.");
+ vector<string> data = node->getContentArray();
+ for (vector<string>::iterator it = data.begin(); it != data.end(); it++){
+ int id = boost::lexical_cast<int>(*it);
+ m_pData.push_back(dynamic_cast<CFloat32Data2D*>(CData2DManager::getSingleton().get(id)));
+ }
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DataId");
+
+ // scalar
+ node = _cfg.self->getSingleNode("Scalar");
+ ASTRA_CONFIG_CHECK(node, "CCudaDataOperationAlgorithm", "No Scalar tag specified.");
+ m_fScalar = node->getContentNumericalArray();
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("Scalar");
+
+ // Option: GPU number
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUIndex", m_iGPUIndex);
+ CC.markOptionParsed("GPUindex");
+ if (!_cfg.self->hasOption("GPUindex"))
+ CC.markOptionParsed("GPUIndex");
+
+ if (_cfg.self->hasOption("MaskId")) {
+ int id = boost::lexical_cast<int>(_cfg.self->getOption("MaskId"));
+ m_pMask = dynamic_cast<CFloat32Data2D*>(CData2DManager::getSingleton().get(id));
+ }
+ CC.markOptionParsed("MaskId");
+
+ _check();
+
+ if (!m_bIsInitialized)
+ return false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+//bool CCudaDartMaskAlgorithm::initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn)
+//{
+// return false;
+//}
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaDataOperationAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ astraCUDA::setGPUIndex(m_iGPUIndex);
+
+ if (m_sOperation == "$1*s1" || m_sOperation == "$1.*s1") // data * scalar
+ {
+ unsigned int width = m_pData[0]->getWidth();
+ unsigned int height = m_pData[0]->getHeight();
+ if (m_pMask == NULL)
+ astraCUDA::processVolCopy<astraCUDA::opMul,astraCUDA::VOL>(m_pData[0]->getData(), m_fScalar[0], width, height);
+ else
+ astraCUDA::processVolCopy<astraCUDA::opMulMask,astraCUDA::VOL>(m_pData[0]->getData(), m_pMask->getDataConst(), m_fScalar[0], width, height);
+ }
+ else if (m_sOperation == "$1/s1" || m_sOperation == "$1./s1") // data / scalar
+ {
+ unsigned int width = m_pData[0]->getWidth();
+ unsigned int height = m_pData[0]->getHeight();
+ if (m_pMask == NULL)
+ astraCUDA::processVolCopy<astraCUDA::opMul,astraCUDA::VOL>(m_pData[0]->getData(), 1.0f/m_fScalar[0], width, height);
+ else
+ astraCUDA::processVolCopy<astraCUDA::opMulMask,astraCUDA::VOL>(m_pData[0]->getData(), m_pMask->getDataConst(), 1.0f/m_fScalar[0], width, height);
+ }
+ else if (m_sOperation == "$1+s1") // data + scalar
+ {
+ unsigned int width = m_pData[0]->getWidth();
+ unsigned int height = m_pData[0]->getHeight();
+ astraCUDA::processVolCopy<astraCUDA::opAdd,astraCUDA::VOL>(m_pData[0]->getData(), m_fScalar[0], width, height);
+ }
+ else if (m_sOperation == "$1-s1") // data - scalar
+ {
+ unsigned int width = m_pData[0]->getWidth();
+ unsigned int height = m_pData[0]->getHeight();
+ astraCUDA::processVolCopy<astraCUDA::opAdd,astraCUDA::VOL>(m_pData[0]->getData(), -m_fScalar[0], width, height);
+ }
+ else if (m_sOperation == "$1.*$2") // data .* data
+ {
+ unsigned int width = m_pData[0]->getWidth();
+ unsigned int height = m_pData[0]->getHeight();
+ astraCUDA::processVolCopy<astraCUDA::opMul,astraCUDA::VOL>(m_pData[0]->getData(), m_pData[1]->getDataConst(), width, height);
+ }
+ else if (m_sOperation == "$1+$2") // data + data
+ {
+ unsigned int width = m_pData[0]->getWidth();
+ unsigned int height = m_pData[0]->getHeight();
+ astraCUDA::processVolCopy<astraCUDA::opAdd,astraCUDA::VOL>(m_pData[0]->getData(), m_pData[1]->getDataConst(), width, height);
+ }
+
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaDataOperationAlgorithm::_check()
+{
+ // s*: 1 data + 1 scalar
+
+ // success
+ m_bIsInitialized = true;
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaDataOperationAlgorithm::getInformation()
+{
+ map<string,boost::any> res;
+ // TODO: add PDART-specific options
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+}
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaDataOperationAlgorithm::getInformation(std::string _sIdentifier)
+{
+ return NULL;
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaEMAlgorithm.cpp b/src/CudaEMAlgorithm.cpp
new file mode 100644
index 0000000..44dd0fd
--- /dev/null
+++ b/src/CudaEMAlgorithm.cpp
@@ -0,0 +1,97 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaEMAlgorithm.h"
+
+#include "../cuda/2d/em.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaEMAlgorithm::type = "EM_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaEMAlgorithm::CCudaEMAlgorithm()
+{
+ m_bIsInitialized = false;
+ CCudaReconstructionAlgorithm2D::_clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaEMAlgorithm::~CCudaEMAlgorithm()
+{
+ // The actual work is done by ~CCudaReconstructionAlgorithm2D
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaEMAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaEMAlgorithm", this, _cfg);
+
+ m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_cfg);
+
+ if (!m_bIsInitialized)
+ return false;
+
+ m_pAlgo = new astraCUDA::EM();
+ m_bAlgoInit = false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaEMAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex, int _iDetectorSuperSampling,
+ int _iPixelSuperSampling)
+{
+ m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction, _iGPUindex, _iDetectorSuperSampling, _iPixelSuperSampling);
+
+ if (!m_bIsInitialized)
+ return false;
+
+ m_pAlgo = new astraCUDA::EM();
+ m_bAlgoInit = false;
+
+ return true;
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaFDKAlgorithm3D.cpp b/src/CudaFDKAlgorithm3D.cpp
new file mode 100644
index 0000000..8f9e7b8
--- /dev/null
+++ b/src/CudaFDKAlgorithm3D.cpp
@@ -0,0 +1,192 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/CudaFDKAlgorithm3D.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+
+#include "astra/ConeProjectionGeometry3D.h"
+
+#include "../cuda/3d/astra3d.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaFDKAlgorithm3D::type = "FDK_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaFDKAlgorithm3D::CCudaFDKAlgorithm3D()
+{
+ m_bIsInitialized = false;
+ m_iGPUIndex = 0;
+ m_iVoxelSuperSampling = 1;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor with initialization
+CCudaFDKAlgorithm3D::CCudaFDKAlgorithm3D(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pProjectionData,
+ CFloat32VolumeData3DMemory* _pReconstruction)
+{
+ _clear();
+ initialize(_pProjector, _pProjectionData, _pReconstruction);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaFDKAlgorithm3D::~CCudaFDKAlgorithm3D()
+{
+ CReconstructionAlgorithm3D::_clear();
+}
+
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CCudaFDKAlgorithm3D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CReconstructionAlgorithm3D::_check(), "CUDA_FDK", "Error in ReconstructionAlgorithm3D initialization");
+
+ const CProjectionGeometry3D* projgeom = m_pSinogram->getGeometry();
+ ASTRA_CONFIG_CHECK(dynamic_cast<const CConeProjectionGeometry3D*>(projgeom), "CUDA_FDK", "Error setting FDK geometry");
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaFDKAlgorithm3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaFDKAlgorithm3D", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CReconstructionAlgorithm3D::initialize(_cfg)) {
+ return false;
+ }
+
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ CC.markOptionParsed("GPUindex");
+ m_iVoxelSuperSampling = (int)_cfg.self->getOptionNumerical("VoxelSuperSampling", 1);
+ CC.markOptionParsed("VoxelSuperSampling");
+
+ m_bShortScan = _cfg.self->getOptionBool("ShortScan", false);
+ CC.markOptionParsed("ShortScan");
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaFDKAlgorithm3D::initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pSinogram,
+ CFloat32VolumeData3DMemory* _pReconstruction)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaFDKAlgorithm3D::getInformation()
+{
+ map<string, boost::any> res;
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaFDKAlgorithm3D::getInformation(std::string _sIdentifier)
+{
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaFDKAlgorithm3D::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ const CProjectionGeometry3D* projgeom = m_pSinogram->getGeometry();
+ const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(projgeom);
+ const CVolumeGeometry3D& volgeom = *m_pReconstruction->getGeometry();
+
+ ASTRA_ASSERT(conegeom);
+
+ CFloat32ProjectionData3DMemory* pSinoMem = dynamic_cast<CFloat32ProjectionData3DMemory*>(m_pSinogram);
+ ASTRA_ASSERT(pSinoMem);
+ CFloat32VolumeData3DMemory* pReconMem = dynamic_cast<CFloat32VolumeData3DMemory*>(m_pReconstruction);
+ ASTRA_ASSERT(pReconMem);
+
+
+ bool ok = true;
+
+ ok = astraCudaFDK(pReconMem->getData(), pSinoMem->getDataConst(),
+ volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount(),
+ conegeom->getProjectionCount(),
+ conegeom->getDetectorColCount(),
+ conegeom->getDetectorRowCount(),
+ conegeom->getOriginSourceDistance(),
+ conegeom->getOriginDetectorDistance(),
+ conegeom->getDetectorSpacingX(),
+ conegeom->getDetectorSpacingY(),
+ conegeom->getProjectionAngles(),
+ m_bShortScan, m_iGPUIndex, m_iVoxelSuperSampling);
+
+ ASTRA_ASSERT(ok);
+
+}
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/CudaFilteredBackProjectionAlgorithm.cpp b/src/CudaFilteredBackProjectionAlgorithm.cpp
new file mode 100644
index 0000000..75a1534
--- /dev/null
+++ b/src/CudaFilteredBackProjectionAlgorithm.cpp
@@ -0,0 +1,442 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include <astra/CudaFilteredBackProjectionAlgorithm.h>
+#include <boost/lexical_cast.hpp>
+#include <cstring>
+
+#include "astra/AstraObjectManager.h"
+
+#include <astra/Logger.h>
+
+using namespace std;
+using namespace astra;
+
+string CCudaFilteredBackProjectionAlgorithm::type = "FBP_CUDA";
+
+CCudaFilteredBackProjectionAlgorithm::CCudaFilteredBackProjectionAlgorithm()
+{
+ m_bIsInitialized = false;
+ CReconstructionAlgorithm2D::_clear();
+ m_pFBP = 0;
+ m_pfFilter = NULL;
+ m_fFilterParameter = -1.0f;
+ m_fFilterD = 1.0f;
+}
+
+CCudaFilteredBackProjectionAlgorithm::~CCudaFilteredBackProjectionAlgorithm()
+{
+ if(m_pfFilter != NULL)
+ {
+ delete [] m_pfFilter;
+ m_pfFilter = NULL;
+ }
+
+ if(m_pFBP != NULL)
+ {
+ delete m_pFBP;
+ m_pFBP = NULL;
+ }
+}
+
+bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaFilteredBackProjectionAlgorithm", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized)
+ {
+ clear();
+ }
+
+ // sinogram data
+ XMLNode* node = _cfg.self->getSingleNode("ProjectionDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaFBP", "No ProjectionDataId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pSinogram = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectionDataId");
+
+ // reconstruction data
+ node = _cfg.self->getSingleNode("ReconstructionDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaFBP", "No ReconstructionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pReconstruction = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ReconstructionDataId");
+
+ // filter type
+ node = _cfg.self->getSingleNode("FilterType");
+ if(node != NULL)
+ {
+ m_eFilter = _convertStringToFilter(node->getContent().c_str());
+ }
+ else
+ {
+ m_eFilter = FILTER_RAMLAK;
+ }
+ CC.markNodeParsed("FilterType");
+ ASTRA_DELETE(node);
+
+ // filter
+ node = _cfg.self->getSingleNode("FilterSinogramId");
+ if(node != NULL)
+ {
+ int id = boost::lexical_cast<int>(node->getContent());
+ const CFloat32ProjectionData2D * pFilterData = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ m_iFilterWidth = pFilterData->getGeometry()->getDetectorCount();
+ int iFilterProjectionCount = pFilterData->getGeometry()->getProjectionAngleCount();
+
+ m_pfFilter = new float[m_iFilterWidth * iFilterProjectionCount];
+ memcpy(m_pfFilter, pFilterData->getDataConst(), sizeof(float) * m_iFilterWidth * iFilterProjectionCount);
+ }
+ else
+ {
+ m_iFilterWidth = 0;
+ m_pfFilter = NULL;
+ }
+ CC.markNodeParsed("FilterSinogramId"); // TODO: Only for some types!
+ ASTRA_DELETE(node);
+
+ // filter parameter
+ node = _cfg.self->getSingleNode("FilterParameter");
+ if(node != NULL)
+ {
+ float fParameter = boost::lexical_cast<float>(node->getContent());
+ m_fFilterParameter = fParameter;
+ }
+ else
+ {
+ m_fFilterParameter = -1.0f;
+ }
+ CC.markNodeParsed("FilterParameter"); // TODO: Only for some types!
+ ASTRA_DELETE(node);
+
+ // D value
+ node = _cfg.self->getSingleNode("FilterD");
+ if(node != NULL)
+ {
+ float fD = boost::lexical_cast<float>(node->getContent());
+ m_fFilterD = fD;
+ }
+ else
+ {
+ m_fFilterD = 1.0f;
+ }
+ CC.markNodeParsed("FilterD"); // TODO: Only for some types!
+ ASTRA_DELETE(node);
+
+ // GPU number
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ CC.markOptionParsed("GPUindex");
+
+ // Pixel supersampling factor
+ m_iPixelSuperSampling = (int)_cfg.self->getOptionNumerical("PixelSuperSampling", 1);
+ CC.markOptionParsed("PixelSuperSampling");
+
+
+ m_pFBP = new AstraFBP;
+ m_bAstraFBPInit = false;
+
+ // success
+ m_bIsInitialized = true;
+ return m_bIsInitialized;
+}
+
+bool CCudaFilteredBackProjectionAlgorithm::initialize(CFloat32ProjectionData2D * _pSinogram, CFloat32VolumeData2D * _pReconstruction, E_FBPFILTER _eFilter, const float * _pfFilter /* = NULL */, int _iFilterWidth /* = 0 */, int _iGPUIndex /* = 0 */, float _fFilterParameter /* = -1.0f */)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized)
+ {
+ clear();
+ }
+
+ // required classes
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+ m_iGPUIndex = _iGPUIndex;
+
+ m_eFilter = _eFilter;
+ m_iFilterWidth = _iFilterWidth;
+
+ // success
+ m_bIsInitialized = true;
+
+ m_pFBP = new AstraFBP;
+
+ m_bAstraFBPInit = false;
+
+ if(_pfFilter != NULL)
+ {
+ int iFilterElementCount = 0;
+
+ if((_eFilter != FILTER_SINOGRAM) && (_eFilter != FILTER_RSINOGRAM))
+ {
+ iFilterElementCount = _iFilterWidth;
+ }
+ else
+ {
+ iFilterElementCount = m_pSinogram->getAngleCount();
+ }
+
+ m_pfFilter = new float[iFilterElementCount];
+ memcpy(m_pfFilter, _pfFilter, iFilterElementCount * sizeof(float));
+ }
+ else
+ {
+ m_pfFilter = NULL;
+ }
+
+ m_fFilterParameter = _fFilterParameter;
+
+ return m_bIsInitialized;
+}
+
+void CCudaFilteredBackProjectionAlgorithm::run(int _iNrIterations /* = 0 */)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ if (!m_bAstraFBPInit) {
+
+ const CVolumeGeometry2D& volgeom = *m_pReconstruction->getGeometry();
+ const CParallelProjectionGeometry2D& projgeom = *dynamic_cast<CParallelProjectionGeometry2D*>(m_pSinogram->getGeometry());
+
+ bool ok = true;
+
+ // TODO: off-center geometry, non-square pixels
+ ok &= m_pFBP->setReconstructionGeometry(volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getPixelLengthX());
+ // TODO: off-center geometry
+ ok &= m_pFBP->setProjectionGeometry(projgeom.getProjectionAngleCount(),
+ projgeom.getDetectorCount(),
+ projgeom.getProjectionAngles(),
+ projgeom.getDetectorWidth());
+
+ ok &= m_pFBP->setPixelSuperSampling(m_iPixelSuperSampling);
+
+ ASTRA_ASSERT(ok);
+
+ const float *pfTOffsets = m_pSinogram->getGeometry()->getExtraDetectorOffset();
+ if (pfTOffsets)
+ ok &= m_pFBP->setTOffsets(pfTOffsets);
+ ASTRA_ASSERT(ok);
+
+ ok &= m_pFBP->init(m_iGPUIndex);
+ ASTRA_ASSERT(ok);
+
+ ok &= m_pFBP->setSinogram(m_pSinogram->getDataConst(), projgeom.getDetectorCount());
+ ASTRA_ASSERT(ok);
+
+ ok &= m_pFBP->setFilter(m_eFilter, m_pfFilter, m_iFilterWidth, m_fFilterD, m_fFilterParameter);
+ ASTRA_ASSERT(ok);
+
+ m_bAstraFBPInit = true;
+ }
+
+ bool ok = m_pFBP->run();
+ ASTRA_ASSERT(ok);
+
+ const CVolumeGeometry2D& volgeom = *m_pReconstruction->getGeometry();
+ ok &= m_pFBP->getReconstruction(m_pReconstruction->getData(), volgeom.getGridColCount());
+
+ ASTRA_ASSERT(ok);
+}
+
+bool CCudaFilteredBackProjectionAlgorithm::check()
+{
+ // check pointers
+ ASTRA_CONFIG_CHECK(m_pSinogram, "FBP_CUDA", "Invalid Projection Data Object.");
+ ASTRA_CONFIG_CHECK(m_pReconstruction, "FBP_CUDA", "Invalid Reconstruction Data Object.");
+
+ if((m_eFilter == FILTER_PROJECTION) || (m_eFilter == FILTER_SINOGRAM) || (m_eFilter == FILTER_RPROJECTION) || (m_eFilter == FILTER_RSINOGRAM))
+ {
+ ASTRA_CONFIG_CHECK(m_pfFilter, "FBP_CUDA", "Invalid filter pointer.");
+ }
+
+ // check initializations
+ ASTRA_CONFIG_CHECK(m_pSinogram->isInitialized(), "FBP_CUDA", "Projection Data Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pReconstruction->isInitialized(), "FBP_CUDA", "Reconstruction Data Object Not Initialized.");
+
+ // check gpu index
+ ASTRA_CONFIG_CHECK(m_iGPUIndex >= 0, "FBP_CUDA", "GPUIndex must be a non-negative integer.");
+ // check pixel supersampling
+ ASTRA_CONFIG_CHECK(m_iPixelSuperSampling >= 0, "FBP_CUDA", "PixelSuperSampling must be a non-negative integer.");
+
+
+ // success
+ m_bIsInitialized = true;
+ return true;
+}
+
+static int calcNextPowerOfTwo(int _iValue)
+{
+ int iOutput = 1;
+
+ while(iOutput < _iValue)
+ {
+ iOutput *= 2;
+ }
+
+ return iOutput;
+}
+
+int CCudaFilteredBackProjectionAlgorithm::calcIdealRealFilterWidth(int _iDetectorCount)
+{
+ return calcNextPowerOfTwo(_iDetectorCount);
+}
+
+int CCudaFilteredBackProjectionAlgorithm::calcIdealFourierFilterWidth(int _iDetectorCount)
+{
+ return (calcNextPowerOfTwo(_iDetectorCount) / 2 + 1);
+}
+
+static bool stringCompareLowerCase(const char * _stringA, const char * _stringB)
+{
+ int iCmpReturn = 0;
+
+#ifdef _MSC_VER
+ iCmpReturn = _stricmp(_stringA, _stringB);
+#else
+ iCmpReturn = strcasecmp(_stringA, _stringB);
+#endif
+
+ return (iCmpReturn == 0);
+}
+
+E_FBPFILTER CCudaFilteredBackProjectionAlgorithm::_convertStringToFilter(const char * _filterType)
+{
+ E_FBPFILTER output = FILTER_NONE;
+
+ if(stringCompareLowerCase(_filterType, "ram-lak"))
+ {
+ output = FILTER_RAMLAK;
+ }
+ else if(stringCompareLowerCase(_filterType, "shepp-logan"))
+ {
+ output = FILTER_SHEPPLOGAN;
+ }
+ else if(stringCompareLowerCase(_filterType, "cosine"))
+ {
+ output = FILTER_COSINE;
+ }
+ else if(stringCompareLowerCase(_filterType, "hamming"))
+ {
+ output = FILTER_HAMMING;
+ }
+ else if(stringCompareLowerCase(_filterType, "hann"))
+ {
+ output = FILTER_HANN;
+ }
+ else if(stringCompareLowerCase(_filterType, "none"))
+ {
+ output = FILTER_NONE;
+ }
+ else if(stringCompareLowerCase(_filterType, "tukey"))
+ {
+ output = FILTER_TUKEY;
+ }
+ else if(stringCompareLowerCase(_filterType, "lanczos"))
+ {
+ output = FILTER_LANCZOS;
+ }
+ else if(stringCompareLowerCase(_filterType, "triangular"))
+ {
+ output = FILTER_TRIANGULAR;
+ }
+ else if(stringCompareLowerCase(_filterType, "gaussian"))
+ {
+ output = FILTER_GAUSSIAN;
+ }
+ else if(stringCompareLowerCase(_filterType, "barlett-hann"))
+ {
+ output = FILTER_BARTLETTHANN;
+ }
+ else if(stringCompareLowerCase(_filterType, "blackman"))
+ {
+ output = FILTER_BLACKMAN;
+ }
+ else if(stringCompareLowerCase(_filterType, "nuttall"))
+ {
+ output = FILTER_NUTTALL;
+ }
+ else if(stringCompareLowerCase(_filterType, "blackman-harris"))
+ {
+ output = FILTER_BLACKMANHARRIS;
+ }
+ else if(stringCompareLowerCase(_filterType, "blackman-nuttall"))
+ {
+ output = FILTER_BLACKMANNUTTALL;
+ }
+ else if(stringCompareLowerCase(_filterType, "flat-top"))
+ {
+ output = FILTER_FLATTOP;
+ }
+ else if(stringCompareLowerCase(_filterType, "kaiser"))
+ {
+ output = FILTER_KAISER;
+ }
+ else if(stringCompareLowerCase(_filterType, "parzen"))
+ {
+ output = FILTER_PARZEN;
+ }
+ else if(stringCompareLowerCase(_filterType, "projection"))
+ {
+ output = FILTER_PROJECTION;
+ }
+ else if(stringCompareLowerCase(_filterType, "sinogram"))
+ {
+ output = FILTER_SINOGRAM;
+ }
+ else if(stringCompareLowerCase(_filterType, "rprojection"))
+ {
+ output = FILTER_RPROJECTION;
+ }
+ else if(stringCompareLowerCase(_filterType, "rsinogram"))
+ {
+ output = FILTER_RSINOGRAM;
+ }
+ else
+ {
+ cerr << "Failed to convert \"" << _filterType << "\" into a filter." << endl;
+ }
+
+ return output;
+}
+
+void CCudaFilteredBackProjectionAlgorithm::testGenFilter(E_FBPFILTER _eFilter, float _fD, int _iProjectionCount, cufftComplex * _pFilter, int _iFFTRealDetectorCount, int _iFFTFourierDetectorCount)
+{
+ genFilter(_eFilter, _fD, _iProjectionCount, _pFilter, _iFFTRealDetectorCount, _iFFTFourierDetectorCount);
+}
+
+int CCudaFilteredBackProjectionAlgorithm::getGPUCount()
+{
+ return 0;
+}
diff --git a/src/CudaForwardProjectionAlgorithm.cpp b/src/CudaForwardProjectionAlgorithm.cpp
new file mode 100644
index 0000000..965c4af
--- /dev/null
+++ b/src/CudaForwardProjectionAlgorithm.cpp
@@ -0,0 +1,276 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/CudaForwardProjectionAlgorithm.h"
+
+#ifdef ASTRA_CUDA
+
+#include "../cuda/2d/astra.h"
+
+#include <driver_types.h>
+#include <cuda_runtime_api.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+#include "astra/FanFlatProjectionGeometry2D.h"
+#include "astra/FanFlatVecProjectionGeometry2D.h"
+#include "astra/CudaProjector2D.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaForwardProjectionAlgorithm::type = "FP_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaForwardProjectionAlgorithm::CCudaForwardProjectionAlgorithm()
+{
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaForwardProjectionAlgorithm::~CCudaForwardProjectionAlgorithm()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaForwardProjectionAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaForwardProjectionAlgorithm", this, _cfg);
+
+ // sinogram data
+ XMLNode* node = _cfg.self->getSingleNode("ProjectionDataId");
+ ASTRA_CONFIG_CHECK(node, "FP_CUDA", "No ProjectionDataId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pSinogram = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectionDataId");
+
+ // volume data
+ node = _cfg.self->getSingleNode("VolumeDataId");
+ ASTRA_CONFIG_CHECK(node, "FP_CUDA", "No VolumeDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pVolume = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("VolumeDataId");
+
+ // GPU number
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUIndex", m_iGPUIndex);
+ CC.markOptionParsed("GPUindex");
+ if (!_cfg.self->hasOption("GPUindex"))
+ CC.markOptionParsed("GPUIndex");
+
+ // Detector supersampling factor
+ m_iDetectorSuperSampling = (int)_cfg.self->getOptionNumerical("DetectorSuperSampling", 1);
+ CC.markOptionParsed("DetectorSuperSampling");
+
+
+ // This isn't used yet, but passing it is not something to warn about
+ node = _cfg.self->getSingleNode("ProjectorId");
+ if (node) {
+ id = boost::lexical_cast<int>(node->getContent());
+ CProjector2D *projector = CProjector2DManager::getSingleton().get(id);
+ if (!dynamic_cast<CCudaProjector2D*>(projector)) {
+ cout << "Warning: non-CUDA Projector2D passed to FP_CUDA" << std::endl;
+ }
+ delete node;
+ }
+ CC.markNodeParsed("ProjectorId");
+
+
+
+ // return success
+ return check();
+}
+
+//----------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaForwardProjectionAlgorithm::initialize(CProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry,
+ CFloat32VolumeData2D* _pVolume,
+ CFloat32ProjectionData2D* _pSinogram,
+ int _iGPUindex, int _iDetectorSuperSampling)
+{
+ // store classes
+ //m_pProjectionGeometry = _pProjectionGeometry;
+ //m_pReconstructionGeometry = _pReconstructionGeometry;
+ m_pVolume = _pVolume;
+ m_pSinogram = _pSinogram;
+
+ m_iDetectorSuperSampling = _iDetectorSuperSampling;
+ m_iGPUIndex = _iGPUindex;
+
+ // return success
+ return check();
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaForwardProjectionAlgorithm::check()
+{
+ // check pointers
+ ASTRA_CONFIG_CHECK(m_pSinogram, "FP_CUDA", "No valid projection data object found.");
+ ASTRA_CONFIG_CHECK(m_pSinogram->isInitialized(), "FP_CUDA", "Projection data not initialized.");
+ ASTRA_CONFIG_CHECK(m_pVolume, "FP_CUDA", "No valid volume data object found.");
+ ASTRA_CONFIG_CHECK(m_pVolume->isInitialized(), "FP_CUDA", "Volume data not initialized.");
+
+ // check restrictions
+ //int iImageSideBlocks = m_pReconstructionGeometry->getGridColCount() / G_BLOCKIMAGESIZE;
+ //ASTRA_CONFIG_CHECK((iImageSideBlocks * G_BLOCKIMAGESIZE) == m_pVolume->getWidth(), "FP_CUDA", "Volume Width must be a multiple of G_BLOCKIMAGESIZE");
+ //ASTRA_CONFIG_CHECK((iImageSideBlocks * G_BLOCKIMAGESIZE) == m_pVolume->getHeight(), "FP_CUDA", "Volume Height must be a multiple of G_BLOCKIMAGESIZE");
+ //ASTRA_CONFIG_CHECK(m_pProjectionGeometry->getDetectorCount() == (m_pVolume->getWidth() * 3 / 2), "SIRT_CUDA", "Number of detectors must be 1.5 times the width of the image");
+
+ ASTRA_CONFIG_CHECK(m_iGPUIndex >= 0, "FP_CUDA", "GPUIndex must be a non-negative integer.");
+
+ // success
+ m_bIsInitialized = true;
+ return true;
+}
+
+void CCudaForwardProjectionAlgorithm::setGPUIndex(int _iGPUIndex)
+{
+ m_iGPUIndex = _iGPUIndex;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaForwardProjectionAlgorithm::getInformation()
+{
+ map<string, boost::any> res;
+ res["ProjectionGeometry"] = getInformation("ProjectionGeometry");
+ res["ReconstructionGeometry"] = getInformation("ReconstructionGeometry");
+ res["ProjectionDataId"] = getInformation("ProjectionDataId");
+ res["VolumeDataId"] = getInformation("VolumeDataId");
+ res["GPUindex"] = getInformation("GPUindex");
+ res["DetectorSuperSampling"] = getInformation("DetectorSuperSampling");
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaForwardProjectionAlgorithm::getInformation(std::string _sIdentifier)
+{
+ if (_sIdentifier == "ProjectionGeometry") { return string("not implemented"); }
+ if (_sIdentifier == "ReconstructionGeometry") { return string("not implemented"); }
+ if (_sIdentifier == "ProjectionDataId") {
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pSinogram);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ if (_sIdentifier == "VolumeDataId") {
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pVolume);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ if (_sIdentifier == "GPUindex") { return m_iGPUIndex; }
+ if (_sIdentifier == "DetectorSuperSampling") { return m_iDetectorSuperSampling; }
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Run
+void CCudaForwardProjectionAlgorithm::run(int)
+{
+ // check initialized
+ assert(m_bIsInitialized);
+
+ CVolumeGeometry2D* pVolGeom = m_pVolume->getGeometry();
+ const CParallelProjectionGeometry2D* parProjGeom = dynamic_cast<CParallelProjectionGeometry2D*>(m_pSinogram->getGeometry());
+ const CFanFlatProjectionGeometry2D* fanProjGeom = dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pSinogram->getGeometry());
+ const CFanFlatVecProjectionGeometry2D* fanVecProjGeom = dynamic_cast<CFanFlatVecProjectionGeometry2D*>(m_pSinogram->getGeometry());
+
+ bool ok = false;
+ if (parProjGeom) {
+ ok = astraCudaFP(m_pVolume->getDataConst(), m_pSinogram->getData(),
+ pVolGeom->getGridColCount(), pVolGeom->getGridRowCount(),
+ parProjGeom->getProjectionAngleCount(),
+ parProjGeom->getDetectorCount(),
+ parProjGeom->getProjectionAngles(),
+ parProjGeom->getExtraDetectorOffset(), parProjGeom->getDetectorWidth() / pVolGeom->getPixelLengthX(),
+ m_iDetectorSuperSampling, m_iGPUIndex);
+
+ } else if (fanProjGeom) {
+
+ ok = astraCudaFanFP(m_pVolume->getDataConst(), m_pSinogram->getData(),
+ pVolGeom->getGridColCount(), pVolGeom->getGridRowCount(),
+ fanProjGeom->getProjectionAngleCount(),
+ fanProjGeom->getDetectorCount(),
+ fanProjGeom->getProjectionAngles(),
+ fanProjGeom->getOriginSourceDistance(),
+ fanProjGeom->getOriginDetectorDistance(),
+ pVolGeom->getPixelLengthX(),
+ fanProjGeom->getDetectorWidth(),
+ m_iDetectorSuperSampling, m_iGPUIndex);
+
+ } else if (fanVecProjGeom) {
+
+ // Rescale projs to fPixelSize == 1
+ float fPixelSize = pVolGeom->getPixelLengthX();
+ const astraCUDA::SFanProjection* projs;
+ projs = fanVecProjGeom->getProjectionVectors();
+
+ astraCUDA::SFanProjection* scaledProjs = new astraCUDA::SFanProjection[fanVecProjGeom->getProjectionAngleCount()];
+#define SCALE(name,i,alpha) do { scaledProjs[i].f##name##X = projs[i].f##name##X * alpha; scaledProjs[i].f##name##Y = projs[i].f##name##Y * alpha; } while (0)
+ for (unsigned int i = 0; i < fanVecProjGeom->getProjectionAngleCount(); ++i) {
+ SCALE(Src,i,1.0f/fPixelSize);
+ SCALE(DetS,i,1.0f/fPixelSize);
+ SCALE(DetU,i,1.0f/fPixelSize);
+ }
+
+
+ ok = astraCudaFanFP(m_pVolume->getDataConst(), m_pSinogram->getData(),
+ pVolGeom->getGridColCount(), pVolGeom->getGridRowCount(),
+ fanVecProjGeom->getProjectionAngleCount(),
+ fanVecProjGeom->getDetectorCount(),
+ scaledProjs,
+ /* 1.0f / pVolGeom->getPixelLengthX(), */
+ m_iDetectorSuperSampling, m_iGPUIndex);
+
+ delete[] scaledProjs;
+
+ } else {
+
+ ASTRA_ASSERT(false);
+
+ }
+
+ ASTRA_ASSERT(ok);
+
+}
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaForwardProjectionAlgorithm3D.cpp b/src/CudaForwardProjectionAlgorithm3D.cpp
new file mode 100644
index 0000000..e9289f1
--- /dev/null
+++ b/src/CudaForwardProjectionAlgorithm3D.cpp
@@ -0,0 +1,311 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/CudaForwardProjectionAlgorithm3D.h"
+
+#ifdef ASTRA_CUDA
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+
+#include "astra/CudaProjector3D.h"
+#include "astra/ConeProjectionGeometry3D.h"
+#include "astra/ParallelProjectionGeometry3D.h"
+#include "astra/ParallelVecProjectionGeometry3D.h"
+#include "astra/ConeVecProjectionGeometry3D.h"
+
+#include "../cuda/3d/astra3d.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaForwardProjectionAlgorithm3D::type = "FP3D_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaForwardProjectionAlgorithm3D::CCudaForwardProjectionAlgorithm3D()
+{
+ m_bIsInitialized = false;
+ m_iGPUIndex = 0;
+ m_iDetectorSuperSampling = 1;
+ m_pProjector = 0;
+ m_pProjections = 0;
+ m_pVolume = 0;
+
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaForwardProjectionAlgorithm3D::~CCudaForwardProjectionAlgorithm3D()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaForwardProjectionAlgorithm3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaForwardProjectionAlgorithm3D", this, _cfg);
+
+ XMLNode* node;
+ int id;
+
+ // sinogram data
+ node = _cfg.self->getSingleNode("ProjectionDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaForwardProjection3D", "No ProjectionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pProjections = dynamic_cast<CFloat32ProjectionData3DMemory*>(CData3DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectionDataId");
+
+ // reconstruction data
+ node = _cfg.self->getSingleNode("VolumeDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaForwardProjection3D", "No VolumeDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pVolume = dynamic_cast<CFloat32VolumeData3DMemory*>(CData3DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("VolumeDataId");
+
+ // optional: projector
+ node = _cfg.self->getSingleNode("ProjectorId");
+ if (node) {
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pProjector = CProjector3DManager::getSingleton().get(id);
+ ASTRA_DELETE(node);
+ } else {
+ m_pProjector = 0; // TODO: or manually construct default projector?
+ }
+ CC.markNodeParsed("ProjectorId");
+
+ // GPU number
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ CC.markOptionParsed("GPUindex");
+ m_iDetectorSuperSampling = (int)_cfg.self->getOptionNumerical("DetectorSuperSampling", 1);
+ CC.markOptionParsed("DetectorSuperSampling");
+
+ // success
+ m_bIsInitialized = check();
+
+ if (!m_bIsInitialized)
+ return false;
+
+ return true;
+}
+
+
+bool CCudaForwardProjectionAlgorithm3D::initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pProjections,
+ CFloat32VolumeData3DMemory* _pVolume,
+ int _iGPUindex, int _iDetectorSuperSampling)
+{
+ m_pProjector = _pProjector;
+
+ // required classes
+ m_pProjections = _pProjections;
+ m_pVolume = _pVolume;
+
+ m_iDetectorSuperSampling = _iDetectorSuperSampling;
+ m_iGPUIndex = _iGPUindex;
+
+ // success
+ m_bIsInitialized = check();
+
+ if (!m_bIsInitialized)
+ return false;
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaForwardProjectionAlgorithm3D::check()
+{
+ // check pointers
+ //ASTRA_CONFIG_CHECK(m_pProjector, "Reconstruction2D", "Invalid Projector Object.");
+ ASTRA_CONFIG_CHECK(m_pProjections, "FP3D_CUDA", "Invalid Projection Data Object.");
+ ASTRA_CONFIG_CHECK(m_pVolume, "FP3D_CUDA", "Invalid Volume Data Object.");
+
+ // check initializations
+ //ASTRA_CONFIG_CHECK(m_pProjector->isInitialized(), "Reconstruction2D", "Projector Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pProjections->isInitialized(), "FP3D_CUDA", "Projection Data Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pVolume->isInitialized(), "FP3D_CUDA", "Volume Data Object Not Initialized.");
+
+ ASTRA_CONFIG_CHECK(m_iDetectorSuperSampling >= 1, "FP3D_CUDA", "DetectorSuperSampling must be a positive integer.");
+ ASTRA_CONFIG_CHECK(m_iGPUIndex >= 0, "FP3D_CUDA", "GPUIndex must be a non-negative integer.");
+
+ // check compatibility between projector and data classes
+// ASTRA_CONFIG_CHECK(m_pSinogram->getGeometry()->isEqual(m_pProjector->getProjectionGeometry()), "SIRT_CUDA", "Projection Data not compatible with the specified Projector.");
+// ASTRA_CONFIG_CHECK(m_pReconstruction->getGeometry()->isEqual(m_pProjector->getVolumeGeometry()), "SIRT_CUDA", "Reconstruction Data not compatible with the specified Projector.");
+
+ // todo: turn some of these back on
+
+// ASTRA_CONFIG_CHECK(m_pProjectionGeometry, "SIRT_CUDA", "ProjectionGeometry not specified.");
+// ASTRA_CONFIG_CHECK(m_pProjectionGeometry->isInitialized(), "SIRT_CUDA", "ProjectionGeometry not initialized.");
+// ASTRA_CONFIG_CHECK(m_pReconstructionGeometry, "SIRT_CUDA", "ReconstructionGeometry not specified.");
+// ASTRA_CONFIG_CHECK(m_pReconstructionGeometry->isInitialized(), "SIRT_CUDA", "ReconstructionGeometry not initialized.");
+
+ // check dimensions
+ //ASTRA_CONFIG_CHECK(m_pSinogram->getAngleCount() == m_pProjectionGeometry->getProjectionAngleCount(), "SIRT_CUDA", "Sinogram data object size mismatch.");
+ //ASTRA_CONFIG_CHECK(m_pSinogram->getDetectorCount() == m_pProjectionGeometry->getDetectorCount(), "SIRT_CUDA", "Sinogram data object size mismatch.");
+ //ASTRA_CONFIG_CHECK(m_pReconstruction->getWidth() == m_pReconstructionGeometry->getGridColCount(), "SIRT_CUDA", "Reconstruction data object size mismatch.");
+ //ASTRA_CONFIG_CHECK(m_pReconstruction->getHeight() == m_pReconstructionGeometry->getGridRowCount(), "SIRT_CUDA", "Reconstruction data object size mismatch.");
+
+ // check restrictions
+ // TODO: check restrictions built into cuda code
+
+ // success
+ m_bIsInitialized = true;
+ return true;
+}
+
+
+void CCudaForwardProjectionAlgorithm3D::setGPUIndex(int _iGPUIndex)
+{
+ m_iGPUIndex = _iGPUIndex;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaForwardProjectionAlgorithm3D::getInformation()
+{
+ map<string,boost::any> res;
+ res["ProjectionGeometry"] = getInformation("ProjectionGeometry");
+ res["VolumeGeometry"] = getInformation("VolumeGeometry");
+ res["ProjectionDataId"] = getInformation("ProjectionDataId");
+ res["VolumeDataId"] = getInformation("VolumeDataId");
+ res["GPUindex"] = getInformation("GPUindex");
+ res["GPUindex"] = getInformation("GPUindex");
+ res["DetectorSuperSampling"] = getInformation("DetectorSuperSampling");
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+}
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaForwardProjectionAlgorithm3D::getInformation(std::string _sIdentifier)
+{
+ // TODO: store these so we can return them?
+ if (_sIdentifier == "ProjectionGeometry") { return string("not implemented"); }
+ if (_sIdentifier == "VolumeGeometry") { return string("not implemented"); }
+ if (_sIdentifier == "GPUindex") { return m_iGPUIndex; }
+ if (_sIdentifier == "DetectorSuperSampling") { return m_iDetectorSuperSampling; }
+
+ if (_sIdentifier == "ProjectionDataId") {
+ int iIndex = CData3DManager::getSingleton().getIndex(m_pProjections);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ if (_sIdentifier == "VolumeDataId") {
+ int iIndex = CData3DManager::getSingleton().getIndex(m_pVolume);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ return CAlgorithm::getInformation(_sIdentifier);
+}
+
+//----------------------------------------------------------------------------------------
+// Run
+void CCudaForwardProjectionAlgorithm3D::run(int)
+{
+ // check initialized
+ assert(m_bIsInitialized);
+
+ const CProjectionGeometry3D* projgeom = m_pProjections->getGeometry();
+ const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(projgeom);
+ const CParallelProjectionGeometry3D* par3dgeom = dynamic_cast<const CParallelProjectionGeometry3D*>(projgeom);
+ const CConeVecProjectionGeometry3D* conevecgeom = dynamic_cast<const CConeVecProjectionGeometry3D*>(projgeom);
+ const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(projgeom);
+ const CVolumeGeometry3D& volgeom = *m_pVolume->getGeometry();
+
+ Cuda3DProjectionKernel projKernel = ker3d_default;
+ if (m_pProjector) {
+ CCudaProjector3D* projector = dynamic_cast<CCudaProjector3D*>(m_pProjector);
+ projKernel = projector->getProjectionKernel();
+ }
+
+ if (conegeom) {
+ astraCudaConeFP(m_pVolume->getDataConst(), m_pProjections->getData(),
+ volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount(),
+ conegeom->getProjectionCount(),
+ conegeom->getDetectorColCount(),
+ conegeom->getDetectorRowCount(),
+ conegeom->getOriginSourceDistance(),
+ conegeom->getOriginDetectorDistance(),
+ conegeom->getDetectorSpacingX(),
+ conegeom->getDetectorSpacingY(),
+ conegeom->getProjectionAngles(),
+ m_iGPUIndex, m_iDetectorSuperSampling);
+ } else if (par3dgeom) {
+ astraCudaPar3DFP(m_pVolume->getDataConst(), m_pProjections->getData(),
+ volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount(),
+ par3dgeom->getProjectionCount(),
+ par3dgeom->getDetectorColCount(),
+ par3dgeom->getDetectorRowCount(),
+ par3dgeom->getDetectorSpacingX(),
+ par3dgeom->getDetectorSpacingY(),
+ par3dgeom->getProjectionAngles(),
+ m_iGPUIndex, m_iDetectorSuperSampling,
+ projKernel);
+ } else if (parvec3dgeom) {
+ astraCudaPar3DFP(m_pVolume->getDataConst(), m_pProjections->getData(),
+ volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount(),
+ parvec3dgeom->getProjectionCount(),
+ parvec3dgeom->getDetectorColCount(),
+ parvec3dgeom->getDetectorRowCount(),
+ parvec3dgeom->getProjectionVectors(),
+ m_iGPUIndex, m_iDetectorSuperSampling,
+ projKernel);
+ } else if (conevecgeom) {
+ astraCudaConeFP(m_pVolume->getDataConst(), m_pProjections->getData(),
+ volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount(),
+ conevecgeom->getProjectionCount(),
+ conevecgeom->getDetectorColCount(),
+ conevecgeom->getDetectorRowCount(),
+ conevecgeom->getProjectionVectors(),
+ m_iGPUIndex, m_iDetectorSuperSampling);
+ } else {
+ ASTRA_ASSERT(false);
+ }
+
+}
+
+
+}
+
+#endif
diff --git a/src/CudaProjector2D.cpp b/src/CudaProjector2D.cpp
new file mode 100644
index 0000000..731a3e1
--- /dev/null
+++ b/src/CudaProjector2D.cpp
@@ -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$
+*/
+#include "astra/CudaProjector2D.h"
+
+
+namespace astra
+{
+
+// type of the projector, needed to register with CProjectorFactory
+std::string CCudaProjector2D::type = "cuda";
+
+
+//----------------------------------------------------------------------------------------
+// Default constructor
+CCudaProjector2D::CCudaProjector2D()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaProjector2D::~CCudaProjector2D()
+{
+ if (m_bIsInitialized) clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Clear for constructors
+void CCudaProjector2D::_clear()
+{
+ m_pProjectionGeometry = NULL;
+ m_pVolumeGeometry = NULL;
+ m_bIsInitialized = false;
+
+ m_projectionKernel = ker2d_default;
+}
+
+//----------------------------------------------------------------------------------------
+// Clear
+void CCudaProjector2D::clear()
+{
+ ASTRA_DELETE(m_pProjectionGeometry);
+ ASTRA_DELETE(m_pVolumeGeometry);
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaProjector2D::_check()
+{
+ // projection geometry
+ ASTRA_CONFIG_CHECK(m_pProjectionGeometry, "CudaProjector2D", "ProjectionGeometry2D not initialized.");
+ ASTRA_CONFIG_CHECK(m_pProjectionGeometry->isInitialized(), "CudaProjector2D", "ProjectionGeometry2D not initialized.");
+
+ // volume geometry
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry, "CudaProjector2D", "VolumeGeometry2D not initialized.");
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->isInitialized(), "CudaProjector2D", "VolumeGeometry2D not initialized.");
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CCudaProjector2D::initialize(const Config& _cfg)
+{
+ assert(_cfg.self);
+ ConfigStackCheck<CProjector2D> CC("CudaProjector2D", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CProjector2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // TODO: Check the projection geometry is a supported type
+
+ XMLNode* node = _cfg.self->getSingleNode("ProjectionKernel");
+ m_projectionKernel = ker2d_default;
+ if (node) {
+ std::string sProjKernel = node->getContent();
+
+ if (sProjKernel == "default") {
+
+ } else {
+ return false;
+ }
+ }
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectionKernel");
+
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+/*
+bool CProjector2D::initialize(astra::CProjectionGeometry2D *, astra::CVolumeGeometry2D *)
+{
+ ASTRA_ASSERT(false);
+
+ return false;
+}
+*/
+
+std::string CCudaProjector2D::description() const
+{
+ return "";
+}
+
+} // end namespace
diff --git a/src/CudaProjector3D.cpp b/src/CudaProjector3D.cpp
new file mode 100644
index 0000000..4687825
--- /dev/null
+++ b/src/CudaProjector3D.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/CudaProjector3D.h"
+
+
+namespace astra
+{
+
+// type of the projector, needed to register with CProjectorFactory
+std::string CCudaProjector3D::type = "cuda3d";
+
+
+//----------------------------------------------------------------------------------------
+// Default constructor
+CCudaProjector3D::CCudaProjector3D()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaProjector3D::~CCudaProjector3D()
+{
+ if (m_bIsInitialized) clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Clear for constructors
+void CCudaProjector3D::_clear()
+{
+ m_pProjectionGeometry = NULL;
+ m_pVolumeGeometry = NULL;
+ m_bIsInitialized = false;
+
+ m_projectionKernel = ker3d_default;
+}
+
+//----------------------------------------------------------------------------------------
+// Clear
+void CCudaProjector3D::clear()
+{
+ ASTRA_DELETE(m_pProjectionGeometry);
+ ASTRA_DELETE(m_pVolumeGeometry);
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaProjector3D::_check()
+{
+ // projection geometry
+ ASTRA_CONFIG_CHECK(m_pProjectionGeometry, "CudaProjector3D", "ProjectionGeometry3D not initialized.");
+ ASTRA_CONFIG_CHECK(m_pProjectionGeometry->isInitialized(), "CudaProjector3D", "ProjectionGeometry3D not initialized.");
+
+ // volume geometry
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry, "CudaProjector3D", "VolumeGeometry3D not initialized.");
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->isInitialized(), "CudaProjector3D", "VolumeGeometry3D not initialized.");
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CCudaProjector3D::initialize(const Config& _cfg)
+{
+ assert(_cfg.self);
+ ConfigStackCheck<CProjector3D> CC("CudaProjector3D", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CProjector3D::initialize(_cfg)) {
+ return false;
+ }
+
+ // TODO: These should go to the parent.
+
+ // ProjectionGeometry
+ XMLNode* node = _cfg.self->getSingleNode("ProjectionGeometry");
+ // TODO: Implement
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectionGeometry");
+
+ // ReconstructionGeometry
+ node = _cfg.self->getSingleNode("VolumeGeometry");
+ // TODO: Implement
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("VolumeGeometry");
+
+ node = _cfg.self->getSingleNode("ProjectionKernel");
+ m_projectionKernel = ker3d_default;
+ if (node) {
+ std::string sProjKernel = node->getContent();
+
+ if (sProjKernel == "default") {
+
+ } else if (sProjKernel == "sum_square_weights") {
+ m_projectionKernel = ker3d_sum_square_weights;
+ } else {
+ return false;
+ }
+ }
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectionKernel");
+
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+/*
+bool CProjector3D::initialize(astra::CProjectionGeometry3D *, astra::CVolumeGeometry3D *)
+{
+ ASTRA_ASSERT(false);
+
+ return false;
+}
+*/
+
+std::string CCudaProjector3D::description() const
+{
+ return "";
+}
+
+} // end namespace
diff --git a/src/CudaReconstructionAlgorithm2D.cpp b/src/CudaReconstructionAlgorithm2D.cpp
new file mode 100644
index 0000000..d567158
--- /dev/null
+++ b/src/CudaReconstructionAlgorithm2D.cpp
@@ -0,0 +1,518 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaReconstructionAlgorithm2D.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+#include "astra/FanFlatProjectionGeometry2D.h"
+#include "astra/FanFlatVecProjectionGeometry2D.h"
+#include "astra/CudaProjector2D.h"
+
+#include "../cuda/2d/algo.h"
+
+#include <ctime>
+
+using namespace std;
+
+namespace astra {
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaReconstructionAlgorithm2D::CCudaReconstructionAlgorithm2D()
+{
+ _clear();
+}
+
+
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaReconstructionAlgorithm2D::~CCudaReconstructionAlgorithm2D()
+{
+ delete m_pAlgo;
+ m_pAlgo = 0;
+ m_bAlgoInit = false;
+}
+
+void CCudaReconstructionAlgorithm2D::clear()
+{
+ delete m_pAlgo;
+ _clear();
+}
+
+void CCudaReconstructionAlgorithm2D::_clear()
+{
+ m_bIsInitialized = false;
+ m_pAlgo = 0;
+ m_bAlgoInit = false;
+ CReconstructionAlgorithm2D::_clear();
+
+ m_iGPUIndex = 0;
+ m_iDetectorSuperSampling = 1;
+ m_iPixelSuperSampling = 1;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaReconstructionAlgorithm2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaReconstructionAlgorithm2D", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // sinogram data
+ XMLNode* node = _cfg.self->getSingleNode("ProjectionDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaSirt2", "No ProjectionDataId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pSinogram = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectionDataId");
+
+ // reconstruction data
+ node = _cfg.self->getSingleNode("ReconstructionDataId");
+ ASTRA_CONFIG_CHECK(node, "CudaSirt2", "No ReconstructionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pReconstruction = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ReconstructionDataId");
+
+ // fixed mask
+ if (_cfg.self->hasOption("ReconstructionMaskId")) {
+ m_bUseReconstructionMask = true;
+ id = boost::lexical_cast<int>(_cfg.self->getOption("ReconstructionMaskId"));
+ m_pReconstructionMask = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ }
+ CC.markOptionParsed("ReconstructionMaskId");
+ // fixed mask
+ if (_cfg.self->hasOption("SinogramMaskId")) {
+ m_bUseSinogramMask = true;
+ id = boost::lexical_cast<int>(_cfg.self->getOption("SinogramMaskId"));
+ m_pSinogramMask = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ }
+ CC.markOptionParsed("SinogramMaskId");
+
+ // Constraints - NEW
+ if (_cfg.self->hasOption("MinConstraint")) {
+ m_bUseMinConstraint = true;
+ m_fMinValue = _cfg.self->getOptionNumerical("MinConstraint", 0.0f);
+ CC.markOptionParsed("MinConstraint");
+ } else {
+ // Constraint - OLD
+ m_bUseMinConstraint = _cfg.self->getOptionBool("UseMinConstraint", false);
+ CC.markOptionParsed("UseMinConstraint");
+ if (m_bUseMinConstraint) {
+ m_fMinValue = _cfg.self->getOptionNumerical("MinConstraintValue", 0.0f);
+ CC.markOptionParsed("MinConstraintValue");
+ }
+ }
+ if (_cfg.self->hasOption("MaxConstraint")) {
+ m_bUseMaxConstraint = true;
+ m_fMaxValue = _cfg.self->getOptionNumerical("MaxConstraint", 255.0f);
+ CC.markOptionParsed("MaxConstraint");
+ } else {
+ // Constraint - OLD
+ m_bUseMaxConstraint = _cfg.self->getOptionBool("UseMaxConstraint", false);
+ CC.markOptionParsed("UseMaxConstraint");
+ if (m_bUseMaxConstraint) {
+ m_fMaxValue = _cfg.self->getOptionNumerical("MaxConstraintValue", 0.0f);
+ CC.markOptionParsed("MaxConstraintValue");
+ }
+ }
+
+ // GPU number
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUIndex", m_iGPUIndex);
+ CC.markOptionParsed("GPUindex");
+ if (!_cfg.self->hasOption("GPUindex"))
+ CC.markOptionParsed("GPUIndex");
+
+ // Detector supersampling factor
+ m_iDetectorSuperSampling = (int)_cfg.self->getOptionNumerical("DetectorSuperSampling", 1);
+ CC.markOptionParsed("DetectorSuperSampling");
+
+ // Pixel supersampling factor
+ m_iPixelSuperSampling = (int)_cfg.self->getOptionNumerical("PixelSuperSampling", 1);
+ CC.markOptionParsed("PixelSuperSampling");
+
+
+ // This isn't used yet, but passing it is not something to warn about
+ node = _cfg.self->getSingleNode("ProjectorId");
+ if (node) {
+ id = boost::lexical_cast<int>(node->getContent());
+ CProjector2D *projector = CProjector2DManager::getSingleton().get(id);
+ if (!dynamic_cast<CCudaProjector2D*>(projector)) {
+ cout << "Warning: non-CUDA Projector2D passed to FP_CUDA" << std::endl;
+ }
+ delete node;
+ }
+ CC.markNodeParsed("ProjectorId");
+
+
+ return _check();
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaReconstructionAlgorithm2D::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ return initialize(_pProjector, _pSinogram, _pReconstruction, 0, 1);
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaReconstructionAlgorithm2D::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex,
+ int _iDetectorSuperSampling,
+ int _iPixelSuperSampling)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ m_pProjector = 0;
+
+ // required classes
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ m_iDetectorSuperSampling = _iDetectorSuperSampling;
+ m_iPixelSuperSampling = _iPixelSuperSampling;
+ m_iGPUIndex = _iGPUindex;
+
+ return _check();
+}
+
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaReconstructionAlgorithm2D::_check()
+{
+ // TODO: CLEAN UP
+
+
+ // check pointers
+ //ASTRA_CONFIG_CHECK(m_pProjector, "Reconstruction2D", "Invalid Projector Object.");
+ ASTRA_CONFIG_CHECK(m_pSinogram, "SIRT_CUDA", "Invalid Projection Data Object.");
+ ASTRA_CONFIG_CHECK(m_pReconstruction, "SIRT_CUDA", "Invalid Reconstruction Data Object.");
+
+ // check initializations
+ //ASTRA_CONFIG_CHECK(m_pProjector->isInitialized(), "Reconstruction2D", "Projector Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pSinogram->isInitialized(), "SIRT_CUDA", "Projection Data Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pReconstruction->isInitialized(), "SIRT_CUDA", "Reconstruction Data Object Not Initialized.");
+
+ ASTRA_CONFIG_CHECK(m_iDetectorSuperSampling >= 1, "SIRT_CUDA", "DetectorSuperSampling must be a positive integer.");
+ ASTRA_CONFIG_CHECK(m_iPixelSuperSampling >= 1, "SIRT_CUDA", "PixelSuperSampling must be a positive integer.");
+ ASTRA_CONFIG_CHECK(m_iGPUIndex >= 0, "SIRT_CUDA", "GPUIndex must be a non-negative integer.");
+
+ // check compatibility between projector and data classes
+// ASTRA_CONFIG_CHECK(m_pSinogram->getGeometry()->isEqual(m_pProjector->getProjectionGeometry()), "SIRT_CUDA", "Projection Data not compatible with the specified Projector.");
+// ASTRA_CONFIG_CHECK(m_pReconstruction->getGeometry()->isEqual(m_pProjector->getVolumeGeometry()), "SIRT_CUDA", "Reconstruction Data not compatible with the specified Projector.");
+
+ // todo: turn some of these back on
+
+// ASTRA_CONFIG_CHECK(m_pProjectionGeometry, "SIRT_CUDA", "ProjectionGeometry not specified.");
+// ASTRA_CONFIG_CHECK(m_pProjectionGeometry->isInitialized(), "SIRT_CUDA", "ProjectionGeometry not initialized.");
+// ASTRA_CONFIG_CHECK(m_pReconstructionGeometry, "SIRT_CUDA", "ReconstructionGeometry not specified.");
+// ASTRA_CONFIG_CHECK(m_pReconstructionGeometry->isInitialized(), "SIRT_CUDA", "ReconstructionGeometry not initialized.");
+
+ // check dimensions
+ //ASTRA_CONFIG_CHECK(m_pSinogram->getAngleCount() == m_pProjectionGeometry->getProjectionAngleCount(), "SIRT_CUDA", "Sinogram data object size mismatch.");
+ //ASTRA_CONFIG_CHECK(m_pSinogram->getDetectorCount() == m_pProjectionGeometry->getDetectorCount(), "SIRT_CUDA", "Sinogram data object size mismatch.");
+ //ASTRA_CONFIG_CHECK(m_pReconstruction->getWidth() == m_pReconstructionGeometry->getGridColCount(), "SIRT_CUDA", "Reconstruction data object size mismatch.");
+ //ASTRA_CONFIG_CHECK(m_pReconstruction->getHeight() == m_pReconstructionGeometry->getGridRowCount(), "SIRT_CUDA", "Reconstruction data object size mismatch.");
+
+ // check restrictions
+ // TODO: check restrictions built into cuda code
+
+
+ // success
+ m_bIsInitialized = true;
+ return true;
+}
+
+void CCudaReconstructionAlgorithm2D::setGPUIndex(int _iGPUIndex)
+{
+ m_iGPUIndex = _iGPUIndex;
+}
+
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaReconstructionAlgorithm2D::getInformation()
+{
+ // TODO: Verify and clean up
+
+ map<string,boost::any> res;
+ res["ProjectionGeometry"] = getInformation("ProjectionGeometry");
+ res["ReconstructionGeometry"] = getInformation("ReconstructionGeometry");
+ res["ProjectionDataId"] = getInformation("ProjectionDataId");
+ res["ReconstructionDataId"] = getInformation("ReconstructionDataId");
+ res["ReconstructionMaskId"] = getInformation("ReconstructionMaskId");
+ res["GPUindex"] = getInformation("GPUindex");
+ res["DetectorSuperSampling"] = getInformation("DetectorSuperSampling");
+ res["PixelSuperSampling"] = getInformation("PixelSuperSampling");
+ res["UseMinConstraint"] = getInformation("UseMinConstraint");
+ res["MinConstraintValue"] = getInformation("MinConstraintValue");
+ res["UseMaxConstraint"] = getInformation("UseMaxConstraint");
+ res["MaxConstraintValue"] = getInformation("MaxConstraintValue");
+ return mergeMap<string,boost::any>(CReconstructionAlgorithm2D::getInformation(), res);
+}
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaReconstructionAlgorithm2D::getInformation(std::string _sIdentifier)
+{
+ // TODO: Verify and clean up
+
+ if (_sIdentifier == "UseMinConstraint") { return m_bUseMinConstraint ? string("yes") : string("no"); }
+ if (_sIdentifier == "MinConstraintValue") { return m_fMinValue; }
+ if (_sIdentifier == "UseMaxConstraint") { return m_bUseMaxConstraint ? string("yes") : string("no"); }
+ if (_sIdentifier == "MaxConstraintValue") { return m_fMaxValue; }
+
+ // TODO: store these so we can return them?
+ if (_sIdentifier == "ProjectionGeometry") { return string("not implemented"); }
+ if (_sIdentifier == "ReconstructionGeometry") { return string("not implemented"); }
+ if (_sIdentifier == "GPUindex") { return m_iGPUIndex; }
+ if (_sIdentifier == "DetectorSuperSampling") { return m_iDetectorSuperSampling; }
+ if (_sIdentifier == "PixelSuperSampling") { return m_iPixelSuperSampling; }
+
+ if (_sIdentifier == "ProjectionDataId") {
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pSinogram);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ if (_sIdentifier == "ReconstructionDataId") {
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pReconstruction);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ if (_sIdentifier == "ReconstructionMaskId") {
+ if (!m_bUseReconstructionMask) return string("not used");
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pReconstructionMask);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ return CReconstructionAlgorithm2D::getInformation(_sIdentifier);
+}
+
+bool CCudaReconstructionAlgorithm2D::setupGeometry()
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+ ASTRA_ASSERT(!m_bAlgoInit);
+
+ bool ok;
+
+ // TODO: Probably not the best place for this...
+ ok = m_pAlgo->setGPUIndex(m_iGPUIndex);
+ if (!ok) return false;
+
+ astraCUDA::SDimensions dims;
+
+ const CVolumeGeometry2D& volgeom = *m_pReconstruction->getGeometry();
+
+ // TODO: off-center geometry, non-square pixels
+ dims.iVolWidth = volgeom.getGridColCount();
+ dims.iVolHeight = volgeom.getGridRowCount();
+ float fPixelSize = volgeom.getPixelLengthX();
+
+ dims.iRaysPerDet = m_iDetectorSuperSampling;
+ dims.iRaysPerPixelDim = m_iPixelSuperSampling;
+
+
+ const CParallelProjectionGeometry2D* parProjGeom = dynamic_cast<CParallelProjectionGeometry2D*>(m_pSinogram->getGeometry());
+ const CFanFlatProjectionGeometry2D* fanProjGeom = dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pSinogram->getGeometry());
+ const CFanFlatVecProjectionGeometry2D* fanVecProjGeom = dynamic_cast<CFanFlatVecProjectionGeometry2D*>(m_pSinogram->getGeometry());
+
+ if (parProjGeom) {
+
+ dims.iProjAngles = parProjGeom->getProjectionAngleCount();
+ dims.iProjDets = parProjGeom->getDetectorCount();
+ dims.fDetScale = parProjGeom->getDetectorWidth() / fPixelSize;
+
+ ok = m_pAlgo->setGeometry(dims, parProjGeom->getProjectionAngles());
+
+ } else if (fanProjGeom) {
+
+ dims.iProjAngles = fanProjGeom->getProjectionAngleCount();
+ dims.iProjDets = fanProjGeom->getDetectorCount();
+ dims.fDetScale = fanProjGeom->getDetectorWidth() / fPixelSize;
+ float fOriginSourceDistance = fanProjGeom->getOriginSourceDistance();
+ float fOriginDetectorDistance = fanProjGeom->getOriginDetectorDistance();
+
+ const float* angles = fanProjGeom->getProjectionAngles();
+
+ astraCUDA::SFanProjection* projs;
+ projs = new astraCUDA::SFanProjection[dims.iProjAngles];
+
+ float fSrcX0 = 0.0f;
+ float fSrcY0 = -fOriginSourceDistance / fPixelSize;
+ float fDetUX0 = dims.fDetScale;
+ float fDetUY0 = 0.0f;
+ float fDetSX0 = dims.iProjDets * fDetUX0 / -2.0f;
+ float fDetSY0 = fOriginDetectorDistance / fPixelSize;
+
+#define ROTATE0(name,i,alpha) do { projs[i].f##name##X = f##name##X0 * cos(alpha) - f##name##Y0 * sin(alpha); projs[i].f##name##Y = f##name##X0 * sin(alpha) + f##name##Y0 * cos(alpha); } while(0)
+ for (unsigned int i = 0; i < dims.iProjAngles; ++i) {
+ ROTATE0(Src, i, angles[i]);
+ ROTATE0(DetS, i, angles[i]);
+ ROTATE0(DetU, i, angles[i]);
+ }
+
+#undef ROTATE0
+
+ ok = m_pAlgo->setFanGeometry(dims, projs);
+ delete[] projs;
+
+ } else if (fanVecProjGeom) {
+
+ dims.iProjAngles = fanVecProjGeom->getProjectionAngleCount();
+ dims.iProjDets = fanVecProjGeom->getDetectorCount();
+ dims.fDetScale = fanVecProjGeom->getDetectorWidth() / fPixelSize;
+
+ const astraCUDA::SFanProjection* projs;
+ projs = fanVecProjGeom->getProjectionVectors();
+
+ // Rescale projs to fPixelSize == 1
+
+ astraCUDA::SFanProjection* scaledProjs = new astraCUDA::SFanProjection[dims.iProjAngles];
+#define SCALE(name,i,alpha) do { scaledProjs[i].f##name##X = projs[i].f##name##X * alpha; scaledProjs[i].f##name##Y = projs[i].f##name##Y * alpha; } while (0)
+ for (unsigned int i = 0; i < dims.iProjAngles; ++i) {
+ SCALE(Src,i,1.0f/fPixelSize);
+ SCALE(DetS,i,1.0f/fPixelSize);
+ SCALE(DetU,i,1.0f/fPixelSize);
+ }
+
+ ok = m_pAlgo->setFanGeometry(dims, scaledProjs);
+
+ delete[] scaledProjs;
+
+ } else {
+
+ ASTRA_ASSERT(false);
+
+ }
+ if (!ok) return false;
+
+
+ if (m_bUseReconstructionMask)
+ ok &= m_pAlgo->enableVolumeMask();
+ if (!ok) return false;
+ if (m_bUseSinogramMask)
+ ok &= m_pAlgo->enableSinogramMask();
+ if (!ok) return false;
+
+ const float *pfTOffsets = m_pSinogram->getGeometry()->getExtraDetectorOffset();
+ if (pfTOffsets)
+ ok &= m_pAlgo->setTOffsets(pfTOffsets);
+ if (!ok) return false;
+
+ ok &= m_pAlgo->init();
+ if (!ok) return false;
+
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaReconstructionAlgorithm2D::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ bool ok = true;
+ const CVolumeGeometry2D& volgeom = *m_pReconstruction->getGeometry();
+
+ if (!m_bAlgoInit) {
+
+ ok = setupGeometry();
+ ASTRA_ASSERT(ok);
+
+ ok = m_pAlgo->allocateBuffers();
+ ASTRA_ASSERT(ok);
+
+ m_bAlgoInit = true;
+ }
+
+ float fPixelSize = volgeom.getPixelLengthX();
+ float fSinogramScale = 1.0f/(fPixelSize*fPixelSize);
+
+ ok = m_pAlgo->copyDataToGPU(m_pSinogram->getDataConst(), m_pSinogram->getGeometry()->getDetectorCount(), fSinogramScale,
+ m_pReconstruction->getDataConst(), volgeom.getGridColCount(),
+ m_bUseReconstructionMask ? m_pReconstructionMask->getDataConst() : 0, volgeom.getGridColCount(),
+ m_bUseSinogramMask ? m_pSinogramMask->getDataConst() : 0, m_pSinogram->getGeometry()->getDetectorCount());
+
+ ASTRA_ASSERT(ok);
+
+ if (m_bUseMinConstraint)
+ ok &= m_pAlgo->setMinConstraint(m_fMinValue);
+ if (m_bUseMaxConstraint)
+ ok &= m_pAlgo->setMaxConstraint(m_fMaxValue);
+
+ ok &= m_pAlgo->iterate(_iNrIterations);
+ ASTRA_ASSERT(ok);
+
+ ok &= m_pAlgo->getReconstruction(m_pReconstruction->getData(),
+ volgeom.getGridColCount());
+
+ ASTRA_ASSERT(ok);
+}
+
+void CCudaReconstructionAlgorithm2D::signalAbort()
+{
+ if (m_bIsInitialized && m_pAlgo) {
+ m_pAlgo->signalAbort();
+ }
+}
+
+bool CCudaReconstructionAlgorithm2D::getResidualNorm(float32& _fNorm)
+{
+ if (!m_bIsInitialized || !m_pAlgo)
+ return false;
+
+ _fNorm = m_pAlgo->computeDiffNorm();
+
+ return true;
+}
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaRoiSelectAlgorithm.cpp b/src/CudaRoiSelectAlgorithm.cpp
new file mode 100644
index 0000000..f835c59
--- /dev/null
+++ b/src/CudaRoiSelectAlgorithm.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaRoiSelectAlgorithm.h"
+
+#include "../cuda/2d/darthelper.h"
+#include "../cuda/2d/algo.h"
+
+#include "astra/AstraObjectManager.h"
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaRoiSelectAlgorithm::type = "RoiSelect_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaRoiSelectAlgorithm::CCudaRoiSelectAlgorithm()
+{
+ m_fRadius = 0.0f;
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaRoiSelectAlgorithm::~CCudaRoiSelectAlgorithm()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaRoiSelectAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaDartMaskAlgorithm", this, _cfg);
+
+ // reconstruction data
+ XMLNode* node = _cfg.self->getSingleNode("DataId");
+ ASTRA_CONFIG_CHECK(node, "CudaRoiSelect", "No DataId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pData = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DataId");
+
+ // Option: GPU number
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUIndex", m_iGPUIndex);
+ CC.markOptionParsed("GPUindex");
+ if (!_cfg.self->hasOption("GPUindex"))
+ CC.markOptionParsed("GPUIndex");
+
+ // Option: Radius
+ m_fRadius = (unsigned int)_cfg.self->getOptionNumerical("Radius", 0.0f);
+ CC.markOptionParsed("Radius");
+
+ _check();
+
+ if (!m_bIsInitialized)
+ return false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+//bool CCudaDartMaskAlgorithm::initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn)
+//{
+// return false;
+//}
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaRoiSelectAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ const CVolumeGeometry2D& volgeom = *m_pData->getGeometry();
+ unsigned int width = volgeom.getGridColCount();
+ unsigned int height = volgeom.getGridRowCount();
+
+ if (m_fRadius == 0){
+ m_fRadius = (width < height) ? width : height;
+ }
+
+ astraCUDA::setGPUIndex(m_iGPUIndex);
+ astraCUDA::roiSelect(m_pData->getData(), m_fRadius, width, height);
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CCudaRoiSelectAlgorithm::_check()
+{
+
+ // success
+ m_bIsInitialized = true;
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaRoiSelectAlgorithm::getInformation()
+{
+ map<string,boost::any> res;
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+}
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaRoiSelectAlgorithm::getInformation(std::string _sIdentifier)
+{
+ return NULL;
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaSartAlgorithm.cpp b/src/CudaSartAlgorithm.cpp
new file mode 100644
index 0000000..610793f
--- /dev/null
+++ b/src/CudaSartAlgorithm.cpp
@@ -0,0 +1,136 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaSartAlgorithm.h"
+
+#include "../cuda/2d/sart.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaSartAlgorithm::type = "SART_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaSartAlgorithm::CCudaSartAlgorithm()
+{
+ m_bIsInitialized = false;
+ CCudaReconstructionAlgorithm2D::_clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaSartAlgorithm::~CCudaSartAlgorithm()
+{
+ // The actual work is done by ~CCudaReconstructionAlgorithm2D
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaSartAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaSartAlgorithm", this, _cfg);
+
+ m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_cfg);
+
+ if (!m_bIsInitialized)
+ return false;
+
+ astraCUDA::SART *sart = new astraCUDA::SART();
+
+ m_pAlgo = sart;
+ m_bAlgoInit = false;
+
+ // projection order
+ int projectionCount = m_pSinogram->getGeometry()->getProjectionAngleCount();
+ int* projectionOrder = NULL;
+ string projOrder = _cfg.self->getOption("ProjectionOrder", "random");
+ CC.markOptionParsed("ProjectionOrder");
+ if (projOrder == "sequential") {
+ projectionOrder = new int[projectionCount];
+ for (int i = 0; i < projectionCount; i++) {
+ projectionOrder[i] = i;
+ }
+ sart->setProjectionOrder(projectionOrder, projectionCount);
+ delete[] projectionOrder;
+ } else if (projOrder == "random") {
+ projectionOrder = new int[projectionCount];
+ for (int i = 0; i < projectionCount; i++) {
+ projectionOrder[i] = i;
+ }
+ for (int i = 0; i < projectionCount-1; i++) {
+ int k = (rand() % (projectionCount - i));
+ int t = projectionOrder[i];
+ projectionOrder[i] = projectionOrder[i + k];
+ projectionOrder[i + k] = t;
+ }
+ sart->setProjectionOrder(projectionOrder, projectionCount);
+ delete[] projectionOrder;
+ } else if (projOrder == "custom") {
+ vector<float32> projOrderList = _cfg.self->getOptionNumericalArray("ProjectionOrderList");
+ projectionOrder = new int[projOrderList.size()];
+ for (int i = 0; i < projOrderList.size(); i++) {
+ projectionOrder[i] = static_cast<int>(projOrderList[i]);
+ }
+ sart->setProjectionOrder(projectionOrder, projectionCount);
+ delete[] projectionOrder;
+ CC.markOptionParsed("ProjectionOrderList");
+ }
+
+
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaSartAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex, int _iDetectorSuperSampling)
+{
+ m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction, _iGPUindex, _iDetectorSuperSampling, 1);
+
+ if (!m_bIsInitialized)
+ return false;
+
+ m_pAlgo = new astraCUDA::SART();
+ m_bAlgoInit = false;
+
+ return true;
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaSirtAlgorithm.cpp b/src/CudaSirtAlgorithm.cpp
new file mode 100644
index 0000000..a2a30eb
--- /dev/null
+++ b/src/CudaSirtAlgorithm.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifdef ASTRA_CUDA
+
+#include "astra/CudaSirtAlgorithm.h"
+
+#include <boost/lexical_cast.hpp>
+#include "astra/AstraObjectManager.h"
+
+#include "../cuda/2d/sirt.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaSirtAlgorithm::type = "SIRT_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaSirtAlgorithm::CCudaSirtAlgorithm()
+{
+ m_bIsInitialized = false;
+ CCudaReconstructionAlgorithm2D::_clear();
+
+ m_pMinMask = 0;
+ m_pMaxMask = 0;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaSirtAlgorithm::~CCudaSirtAlgorithm()
+{
+ // The actual work is done by ~CCudaReconstructionAlgorithm2D
+
+ m_pMinMask = 0;
+ m_pMaxMask = 0;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaSirtAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaSirtAlgorithm", this, _cfg);
+
+ m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_cfg);
+
+ if (!m_bIsInitialized)
+ return false;
+
+ // min/max masks
+ if (_cfg.self->hasOption("MinMaskId")) {
+ int id = boost::lexical_cast<int>(_cfg.self->getOption("MinMaskId"));
+ m_pMinMask = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ }
+ CC.markOptionParsed("MinMaskId");
+ if (_cfg.self->hasOption("MaxMaskId")) {
+ int id = boost::lexical_cast<int>(_cfg.self->getOption("MaxMaskId"));
+ m_pMaxMask = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ }
+ CC.markOptionParsed("MaxMaskId");
+
+
+ m_pAlgo = new astraCUDA::SIRT();
+ m_bAlgoInit = false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaSirtAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex, int _iDetectorSuperSampling,
+ int _iPixelSuperSampling)
+{
+ m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction, _iGPUindex, _iDetectorSuperSampling, _iPixelSuperSampling);
+
+ if (!m_bIsInitialized)
+ return false;
+
+
+
+ m_pAlgo = new astraCUDA::SIRT();
+ m_bAlgoInit = false;
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaSirtAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ if (!m_bAlgoInit) {
+ // We only override the initialisation step to copy the min/max masks
+
+ bool ok = setupGeometry();
+ ASTRA_ASSERT(ok);
+
+ ok = m_pAlgo->allocateBuffers();
+ ASTRA_ASSERT(ok);
+
+ if (m_pMinMask || m_pMaxMask) {
+ const CVolumeGeometry2D& volgeom = *m_pReconstruction->getGeometry();
+ astraCUDA::SIRT* pSirt = dynamic_cast<astraCUDA::SIRT*>(m_pAlgo);
+ const float *pfMinMaskData = 0;
+ const float *pfMaxMaskData = 0;
+ if (m_pMinMask) pfMinMaskData = m_pMinMask->getDataConst();
+ if (m_pMaxMask) pfMaxMaskData = m_pMaxMask->getDataConst();
+ ok = pSirt->uploadMinMaxMasks(pfMinMaskData, pfMaxMaskData, volgeom.getGridColCount());
+ ASTRA_ASSERT(ok);
+ }
+
+ m_bAlgoInit = true;
+ }
+
+ CCudaReconstructionAlgorithm2D::run(_iNrIterations);
+}
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
diff --git a/src/CudaSirtAlgorithm3D.cpp b/src/CudaSirtAlgorithm3D.cpp
new file mode 100644
index 0000000..f23d0f6
--- /dev/null
+++ b/src/CudaSirtAlgorithm3D.cpp
@@ -0,0 +1,306 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/CudaSirtAlgorithm3D.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+
+#include "astra/ConeProjectionGeometry3D.h"
+#include "astra/ParallelProjectionGeometry3D.h"
+#include "astra/ParallelVecProjectionGeometry3D.h"
+#include "astra/ConeVecProjectionGeometry3D.h"
+
+#include "../cuda/3d/astra3d.h"
+
+using namespace std;
+
+namespace astra {
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CCudaSirtAlgorithm3D::type = "SIRT3D_CUDA";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CCudaSirtAlgorithm3D::CCudaSirtAlgorithm3D()
+{
+ m_bIsInitialized = false;
+ m_pSirt = 0;
+ m_iGPUIndex = 0;
+ m_iVoxelSuperSampling = 1;
+ m_iDetectorSuperSampling = 1;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor with initialization
+CCudaSirtAlgorithm3D::CCudaSirtAlgorithm3D(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pProjectionData,
+ CFloat32VolumeData3DMemory* _pReconstruction)
+{
+ _clear();
+ initialize(_pProjector, _pProjectionData, _pReconstruction);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CCudaSirtAlgorithm3D::~CCudaSirtAlgorithm3D()
+{
+ delete m_pSirt;
+ m_pSirt = 0;
+
+ CReconstructionAlgorithm3D::_clear();
+}
+
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CCudaSirtAlgorithm3D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CReconstructionAlgorithm3D::_check(), "SIRT3D", "Error in ReconstructionAlgorithm3D initialization");
+
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CCudaSirtAlgorithm3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("CudaSirtAlgorithm3D", this, _cfg);
+
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CReconstructionAlgorithm3D::initialize(_cfg)) {
+ return false;
+ }
+
+ m_iGPUIndex = (int)_cfg.self->getOptionNumerical("GPUindex", 0);
+ CC.markOptionParsed("GPUindex");
+ m_iDetectorSuperSampling = (int)_cfg.self->getOptionNumerical("DetectorSuperSampling", 1);
+ CC.markOptionParsed("DetectorSuperSampling");
+ m_iVoxelSuperSampling = (int)_cfg.self->getOptionNumerical("VoxelSuperSampling", 1);
+ CC.markOptionParsed("VoxelSuperSampling");
+
+ m_pSirt = new AstraSIRT3d();
+
+ m_bAstraSIRTInit = false;
+
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialize - C++
+bool CCudaSirtAlgorithm3D::initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pSinogram,
+ CFloat32VolumeData3DMemory* _pReconstruction)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ m_pSirt = new AstraSIRT3d;
+
+ m_bAstraSIRTInit = false;
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CCudaSirtAlgorithm3D::getInformation()
+{
+ map<string, boost::any> res;
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CCudaSirtAlgorithm3D::getInformation(std::string _sIdentifier)
+{
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CCudaSirtAlgorithm3D::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ const CProjectionGeometry3D* projgeom = m_pSinogram->getGeometry();
+ const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(projgeom);
+ const CParallelProjectionGeometry3D* par3dgeom = dynamic_cast<const CParallelProjectionGeometry3D*>(projgeom);
+ const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(projgeom);
+ const CConeVecProjectionGeometry3D* conevec3dgeom = dynamic_cast<const CConeVecProjectionGeometry3D*>(projgeom);
+ const CVolumeGeometry3D& volgeom = *m_pReconstruction->getGeometry();
+
+ bool ok = true;
+
+ if (!m_bAstraSIRTInit) {
+
+ ok &= m_pSirt->setGPUIndex(m_iGPUIndex);
+
+ ok &= m_pSirt->setReconstructionGeometry(volgeom.getGridColCount(),
+ volgeom.getGridRowCount(),
+ volgeom.getGridSliceCount());
+ fprintf(stderr, "01: %d\n", ok);
+
+ if (conegeom) {
+ ok &= m_pSirt->setConeGeometry(conegeom->getProjectionCount(),
+ conegeom->getDetectorColCount(),
+ conegeom->getDetectorRowCount(),
+ conegeom->getOriginSourceDistance(),
+ conegeom->getOriginDetectorDistance(),
+ conegeom->getDetectorSpacingX(),
+ conegeom->getDetectorSpacingY(),
+ conegeom->getProjectionAngles());
+ } else if (par3dgeom) {
+ ok &= m_pSirt->setPar3DGeometry(par3dgeom->getProjectionCount(),
+ par3dgeom->getDetectorColCount(),
+ par3dgeom->getDetectorRowCount(),
+ par3dgeom->getDetectorSpacingX(),
+ par3dgeom->getDetectorSpacingY(),
+ par3dgeom->getProjectionAngles());
+ } else if (parvec3dgeom) {
+ ok &= m_pSirt->setPar3DGeometry(parvec3dgeom->getProjectionCount(),
+ parvec3dgeom->getDetectorColCount(),
+ parvec3dgeom->getDetectorRowCount(),
+ parvec3dgeom->getProjectionVectors());
+ } else if (conevec3dgeom) {
+ ok &= m_pSirt->setConeGeometry(conevec3dgeom->getProjectionCount(),
+ conevec3dgeom->getDetectorColCount(),
+ conevec3dgeom->getDetectorRowCount(),
+ conevec3dgeom->getProjectionVectors());
+ } else {
+ ASTRA_ASSERT(false);
+ }
+ fprintf(stderr, "02: %d\n", ok);
+
+ ok &= m_pSirt->enableSuperSampling(m_iVoxelSuperSampling, m_iDetectorSuperSampling);
+
+ if (m_bUseReconstructionMask)
+ ok &= m_pSirt->enableVolumeMask();
+ if (m_bUseSinogramMask)
+ ok &= m_pSirt->enableSinogramMask();
+
+ ASTRA_ASSERT(ok);
+ fprintf(stderr, "03: %d\n", ok);
+
+ ok &= m_pSirt->init();
+ fprintf(stderr, "04: %d\n", ok);
+
+ ASTRA_ASSERT(ok);
+
+ m_bAstraSIRTInit = true;
+
+ }
+
+ CFloat32ProjectionData3DMemory* pSinoMem = dynamic_cast<CFloat32ProjectionData3DMemory*>(m_pSinogram);
+ ASTRA_ASSERT(pSinoMem);
+
+ ok = m_pSirt->setSinogram(pSinoMem->getDataConst(), m_pSinogram->getGeometry()->getDetectorColCount());
+
+ fprintf(stderr, "1: %d\n", ok);
+ ASTRA_ASSERT(ok);
+
+ if (m_bUseReconstructionMask) {
+ CFloat32VolumeData3DMemory* pRMaskMem = dynamic_cast<CFloat32VolumeData3DMemory*>(m_pReconstructionMask);
+ ASTRA_ASSERT(pRMaskMem);
+ ok &= m_pSirt->setVolumeMask(pRMaskMem->getDataConst(), volgeom.getGridColCount());
+ }
+ if (m_bUseSinogramMask) {
+ CFloat32ProjectionData3DMemory* pSMaskMem = dynamic_cast<CFloat32ProjectionData3DMemory*>(m_pSinogramMask);
+ ASTRA_ASSERT(pSMaskMem);
+ ok &= m_pSirt->setSinogramMask(pSMaskMem->getDataConst(), m_pSinogramMask->getGeometry()->getDetectorColCount());
+ }
+ fprintf(stderr, "2: %d\n", ok);
+
+ CFloat32VolumeData3DMemory* pReconMem = dynamic_cast<CFloat32VolumeData3DMemory*>(m_pReconstruction);
+ ASTRA_ASSERT(pReconMem);
+ ok &= m_pSirt->setStartReconstruction(pReconMem->getDataConst(),
+ volgeom.getGridColCount());
+
+ ASTRA_ASSERT(ok);
+ fprintf(stderr, "3: %d\n", ok);
+
+ if (m_bUseMinConstraint)
+ ok &= m_pSirt->setMinConstraint(m_fMinValue);
+ if (m_bUseMaxConstraint)
+ ok &= m_pSirt->setMaxConstraint(m_fMaxValue);
+ fprintf(stderr, "4: %d\n", ok);
+
+ ok &= m_pSirt->iterate(_iNrIterations);
+ ASTRA_ASSERT(ok);
+ fprintf(stderr, "5: %d\n", ok);
+
+ ok &= m_pSirt->getReconstruction(pReconMem->getData(),
+ volgeom.getGridColCount());
+ fprintf(stderr, "6: %d\n", ok);
+ ASTRA_ASSERT(ok);
+
+
+}
+//----------------------------------------------------------------------------------------
+void CCudaSirtAlgorithm3D::signalAbort()
+{
+ if (m_bIsInitialized && m_pSirt) {
+ m_pSirt->signalAbort();
+ }
+}
+
+bool CCudaSirtAlgorithm3D::getResidualNorm(float32& _fNorm)
+{
+ if (!m_bIsInitialized || !m_pSirt)
+ return false;
+
+ _fNorm = m_pSirt->computeDiffNorm();
+
+ return true;
+}
+
+
+} // namespace astra
diff --git a/src/DataProjector.cpp b/src/DataProjector.cpp
new file mode 100644
index 0000000..d4b2f84
--- /dev/null
+++ b/src/DataProjector.cpp
@@ -0,0 +1,36 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/DataProjector.h"
+
+namespace astra {
+
+ // EMPTY
+
+
+} // end namespace astra
diff --git a/src/DataProjectorPolicies.cpp b/src/DataProjectorPolicies.cpp
new file mode 100644
index 0000000..2535706
--- /dev/null
+++ b/src/DataProjectorPolicies.cpp
@@ -0,0 +1,36 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/DataProjectorPolicies.h"
+
+namespace astra {
+
+ // EMPTY
+
+
+} // end namespace astra
diff --git a/src/FanFlatBeamLineKernelProjector2D.cpp b/src/FanFlatBeamLineKernelProjector2D.cpp
new file mode 100644
index 0000000..0891801
--- /dev/null
+++ b/src/FanFlatBeamLineKernelProjector2D.cpp
@@ -0,0 +1,179 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/FanFlatBeamLineKernelProjector2D.h"
+
+#include <cmath>
+#include <cstring>
+#include <boost/lexical_cast.hpp>
+
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+using namespace astra;
+
+#include "astra/FanFlatBeamLineKernelProjector2D.inl"
+
+// type of the projector, needed to register with CProjectorFactory
+std::string CFanFlatBeamLineKernelProjector2D::type = "line_fanflat";
+
+
+//----------------------------------------------------------------------------------------
+// default constructor
+CFanFlatBeamLineKernelProjector2D::CFanFlatBeamLineKernelProjector2D()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// constructor
+CFanFlatBeamLineKernelProjector2D::CFanFlatBeamLineKernelProjector2D(CFanFlatProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry)
+
+{
+ _clear();
+ initialize(_pProjectionGeometry, _pReconstructionGeometry);
+}
+
+//----------------------------------------------------------------------------------------
+// destructor
+CFanFlatBeamLineKernelProjector2D::~CFanFlatBeamLineKernelProjector2D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CFanFlatBeamLineKernelProjector2D::_clear()
+{
+ CProjector2D::_clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CFanFlatBeamLineKernelProjector2D::clear()
+{
+ CProjector2D::clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CFanFlatBeamLineKernelProjector2D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CProjector2D::_check(), "FanFlatBeamLineKernelProjector2D", "Error in Projector2D initialization");
+
+ ASTRA_CONFIG_CHECK(dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pProjectionGeometry) || dynamic_cast<CFanFlatVecProjectionGeometry2D*>(m_pProjectionGeometry), "FanFlatBeamLineKernelProjector2D", "Unsupported projection geometry");
+
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "FanFlatBeamLineKernelProjector2D", "Pixel height must equal pixel width.");
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CFanFlatBeamLineKernelProjector2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CProjector2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize
+bool CFanFlatBeamLineKernelProjector2D::initialize(CFanFlatProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pVolumeGeometry)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // hardcopy geometries
+ m_pProjectionGeometry = _pProjectionGeometry->clone();
+ m_pVolumeGeometry = _pVolumeGeometry->clone();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Get maximum amount of weights on a single ray
+int CFanFlatBeamLineKernelProjector2D::getProjectionWeightsCount(int _iProjectionIndex)
+{
+ int maxDim = max(m_pVolumeGeometry->getGridRowCount(), m_pVolumeGeometry->getGridColCount());
+ return maxDim * 2 + 1;
+}
+
+//----------------------------------------------------------------------------------------
+// Single Ray Weights
+void CFanFlatBeamLineKernelProjector2D::computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+ StorePixelWeightsPolicy p(_pWeightedPixels, _iMaxPixelCount);
+ projectSingleRay(_iProjectionIndex, _iDetectorIndex, p);
+ _iStoredPixelCount = p.getStoredPixelCount();
+}
+
+//----------------------------------------------------------------------------------------
+// Splat a single point
+std::vector<SDetector2D> CFanFlatBeamLineKernelProjector2D::projectPoint(int _iRow, int _iCol)
+{
+ std::vector<SDetector2D> res;
+ return res;
+}
+
+//----------------------------------------------------------------------------------------
+//Result is always in [-PI/2; PI/2]
+float32 CFanFlatBeamLineKernelProjector2D::angleBetweenVectors(float32 _fAX, float32 _fAY, float32 _fBX, float32 _fBY)
+{
+ float32 sinAB = (_fAX*_fBY - _fAY*_fBX)/sqrt((_fAX*_fAX + _fAY*_fAY)*(_fBX*_fBX + _fBY*_fBY));
+ return asin(sinAB);
+}
+
+//----------------------------------------------------------------------------------------
diff --git a/src/FanFlatBeamStripKernelProjector2D.cpp b/src/FanFlatBeamStripKernelProjector2D.cpp
new file mode 100644
index 0000000..87ae8d6
--- /dev/null
+++ b/src/FanFlatBeamStripKernelProjector2D.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/FanFlatBeamStripKernelProjector2D.h"
+
+#include <cmath>
+#include <boost/lexical_cast.hpp>
+
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+using namespace astra;
+
+#include "astra/FanFlatBeamStripKernelProjector2D.inl"
+
+// type of the projector, needed to register with CProjectorFactory
+std::string CFanFlatBeamStripKernelProjector2D::type = "strip_fanflat";
+
+//----------------------------------------------------------------------------------------
+// default constructor
+CFanFlatBeamStripKernelProjector2D::CFanFlatBeamStripKernelProjector2D()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// constructor
+CFanFlatBeamStripKernelProjector2D::CFanFlatBeamStripKernelProjector2D(CFanFlatProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry)
+
+{
+ _clear();
+ initialize(_pProjectionGeometry, _pReconstructionGeometry);
+}
+
+//----------------------------------------------------------------------------------------
+// destructor
+CFanFlatBeamStripKernelProjector2D::~CFanFlatBeamStripKernelProjector2D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CFanFlatBeamStripKernelProjector2D::_clear()
+{
+ CProjector2D::_clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CFanFlatBeamStripKernelProjector2D::clear()
+{
+ CProjector2D::clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CFanFlatBeamStripKernelProjector2D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CProjector2D::_check(), "FanFlatBeamStripKernelProjector2D", "Error in Projector2D initialization");
+
+ ASTRA_CONFIG_CHECK(dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pProjectionGeometry), "FanFlatBeamLineKernelProjector2D", "Unsupported projection geometry");
+
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "FanFlatBeamStripKernelProjector2D", "Pixel height must equal pixel width.");
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CFanFlatBeamStripKernelProjector2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CProjector2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize
+bool CFanFlatBeamStripKernelProjector2D::initialize(CFanFlatProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pVolumeGeometry)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // hardcopy geometries
+ m_pProjectionGeometry = _pProjectionGeometry->clone();
+ m_pVolumeGeometry = _pVolumeGeometry->clone();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+
+//----------------------------------------------------------------------------------------
+// Get maximum amount of weights on a single ray
+int CFanFlatBeamStripKernelProjector2D::getProjectionWeightsCount(int _iProjectionIndex)
+{
+ int maxDim = max(m_pVolumeGeometry->getGridRowCount(), m_pVolumeGeometry->getGridColCount());
+ return maxDim * 10 + 1;
+}
+
+//----------------------------------------------------------------------------------------
+// Single Ray Weights
+void CFanFlatBeamStripKernelProjector2D::computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+ StorePixelWeightsPolicy p(_pWeightedPixels, _iMaxPixelCount);
+ projectSingleRay(_iProjectionIndex, _iDetectorIndex, p);
+ _iStoredPixelCount = p.getStoredPixelCount();
+}
+
+//----------------------------------------------------------------------------------------
+// Splat a single point
+std::vector<SDetector2D> CFanFlatBeamStripKernelProjector2D::projectPoint(int _iRow, int _iCol)
+{
+ //float32 xUL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ //float32 yUL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ //float32 xUR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ //float32 yUR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ //float32 xLL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ //float32 yLL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ //float32 xLR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ //float32 yLR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+
+ std::vector<SDetector2D> res;
+ //// loop projectors and detectors
+ //for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) {
+
+ // // get projection angle
+ // float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection);
+ // if (theta >= 7*PIdiv4) theta -= 2*PI;
+ // bool inverse = false;
+ // if (theta >= 3*PIdiv4) {
+ // theta -= PI;
+ // inverse = true;
+ // }
+
+ // // calculate distance from the center of the voxel to the ray though the origin
+ // float32 tUL = xUL * cos(theta) + yUL * sin(theta);
+ // float32 tUR = xUR * cos(theta) + yUR * sin(theta);
+ // float32 tLL = xLL * cos(theta) + yLL * sin(theta);
+ // float32 tLR = xLR * cos(theta) + yLR * sin(theta);
+ // if (inverse) {
+ // tUL *= -1.0f;
+ // tUR *= -1.0f;
+ // tLL *= -1.0f;
+ // tLR *= -1.0f;
+ // }
+ // float32 tMin = min(tUL, min(tUR, min(tLL,tLR)));
+ // float32 tMax = max(tUL, max(tUR, max(tLL,tLR)));
+
+ // // calculate the offset on the detectorarray (in indices)
+ // int dmin = (int)floor(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMin));
+ // int dmax = (int)ceil(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMax));
+
+ // // add affected detectors to the list
+ // for (int i = dmin; i <= dmax; ++i) {
+ // if (i >= 0 && i < m_pProjectionGeometry->getDetectorCount()) {
+ // SDetector2D det;
+ // det.m_iAngleIndex = iProjection;
+ // det.m_iDetectorIndex = i;
+ // det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i;
+ // res.push_back(det);
+ // }
+ // }
+ //}
+
+ //// return result vector
+ return res;
+
+}
+
+//----------------------------------------------------------------------------------------
diff --git a/src/FanFlatProjectionGeometry2D.cpp b/src/FanFlatProjectionGeometry2D.cpp
new file mode 100644
index 0000000..b74536a
--- /dev/null
+++ b/src/FanFlatProjectionGeometry2D.cpp
@@ -0,0 +1,209 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/FanFlatProjectionGeometry2D.h"
+
+#include <cstring>
+#include <sstream>
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor. Sets all variables to zero.
+CFanFlatProjectionGeometry2D::CFanFlatProjectionGeometry2D()
+{
+ _clear();
+ m_fOriginSourceDistance = 0.0f;
+ m_fOriginDetectorDistance = 0.0f;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CFanFlatProjectionGeometry2D::CFanFlatProjectionGeometry2D(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ float32 _fOriginSourceDistance,
+ float32 _fOriginDetectorDistance)
+{
+ this->initialize(_iProjectionAngleCount,
+ _iDetectorCount,
+ _fDetectorWidth,
+ _pfProjectionAngles,
+ _fOriginSourceDistance,
+ _fOriginDetectorDistance);
+}
+
+//----------------------------------------------------------------------------------------
+// Copy Constructor
+CFanFlatProjectionGeometry2D::CFanFlatProjectionGeometry2D(const CFanFlatProjectionGeometry2D& _projGeom)
+{
+ _clear();
+ this->initialize(_projGeom.m_iProjectionAngleCount,
+ _projGeom.m_iDetectorCount,
+ _projGeom.m_fDetectorWidth,
+ _projGeom.m_pfProjectionAngles,
+ _projGeom.m_fOriginSourceDistance,
+ _projGeom.m_fOriginDetectorDistance);
+}
+
+//----------------------------------------------------------------------------------------
+// Assignment operator.
+CFanFlatProjectionGeometry2D& CFanFlatProjectionGeometry2D::operator=(const CFanFlatProjectionGeometry2D& _other)
+{
+ if (m_bInitialized)
+ delete[] m_pfProjectionAngles;
+ m_bInitialized = _other.m_bInitialized;
+ if (m_bInitialized) {
+ m_iProjectionAngleCount = _other.m_iProjectionAngleCount;
+ m_iDetectorCount = _other.m_iDetectorCount;
+ m_fDetectorWidth = _other.m_fDetectorWidth;
+ m_pfProjectionAngles = new float32[m_iProjectionAngleCount];
+ memcpy(m_pfProjectionAngles, _other.m_pfProjectionAngles, sizeof(float32)*m_iProjectionAngleCount);
+ m_fOriginSourceDistance = _other.m_fOriginSourceDistance;
+ m_fOriginDetectorDistance = _other.m_fOriginDetectorDistance;
+ }
+ return *this;
+}
+//----------------------------------------------------------------------------------------
+// Destructor.
+CFanFlatProjectionGeometry2D::~CFanFlatProjectionGeometry2D()
+{
+
+}
+
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CFanFlatProjectionGeometry2D::initialize(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ float32 _fOriginSourceDistance,
+ float32 _fOriginDetectorDistance)
+{
+ m_fOriginSourceDistance = _fOriginSourceDistance;
+ m_fOriginDetectorDistance = _fOriginDetectorDistance;
+ _initialize(_iProjectionAngleCount,
+ _iDetectorCount,
+ _fDetectorWidth,
+ _pfProjectionAngles);
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization with a Config object
+bool CFanFlatProjectionGeometry2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjectionGeometry2D> CC("FanFlatProjectionGeometry2D", this, _cfg);
+
+ // initialization of parent class
+ CProjectionGeometry2D::initialize(_cfg);
+
+ // Required: DistanceOriginDetector
+ XMLNode* node = _cfg.self->getSingleNode("DistanceOriginDetector");
+ ASTRA_CONFIG_CHECK(node, "FanFlatProjectionGeometry2D", "No DistanceOriginDetector tag specified.");
+ m_fOriginDetectorDistance = boost::lexical_cast<float32>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DistanceOriginDetector");
+
+ // Required: DetectorOriginSource
+ node = _cfg.self->getSingleNode("DistanceOriginSource");
+ ASTRA_CONFIG_CHECK(node, "FanFlatProjectionGeometry2D", "No DistanceOriginSource tag specified.");
+ m_fOriginSourceDistance = boost::lexical_cast<float32>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DistanceOriginSource");
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Clone
+CProjectionGeometry2D* CFanFlatProjectionGeometry2D::clone()
+{
+ return new CFanFlatProjectionGeometry2D(*this);
+}
+
+//----------------------------------------------------------------------------------------
+// is equal
+bool CFanFlatProjectionGeometry2D::isEqual(CProjectionGeometry2D* _pGeom2) const
+{
+ if (_pGeom2 == NULL) return false;
+
+ // try to cast argument to CFanFlatProjectionGeometry2D
+ CFanFlatProjectionGeometry2D* pGeom2 = dynamic_cast<CFanFlatProjectionGeometry2D*>(_pGeom2);
+ if (pGeom2 == NULL) return false;
+
+ // both objects must be initialized
+ if (!m_bInitialized || !pGeom2->m_bInitialized) return false;
+
+ // check all values
+ if (m_iProjectionAngleCount != pGeom2->m_iProjectionAngleCount) return false;
+ if (m_iDetectorCount != pGeom2->m_iDetectorCount) return false;
+ if (m_fDetectorWidth != pGeom2->m_fDetectorWidth) return false;
+ if (m_fOriginSourceDistance != pGeom2->m_fOriginSourceDistance) return false;
+ if (m_fOriginDetectorDistance != pGeom2->m_fOriginDetectorDistance) return false;
+
+ for (int i = 0; i < m_iProjectionAngleCount; ++i) {
+ if (m_pfProjectionAngles[i] != pGeom2->m_pfProjectionAngles[i]) return false;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Is of type
+bool CFanFlatProjectionGeometry2D::isOfType(const std::string& _sType)
+{
+ return (_sType == "fanflat");
+}
+
+CVector3D CFanFlatProjectionGeometry2D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex /* = 0 */)
+{
+ CVector3D vOutput(0.0f, 0.0f, 0.0f);
+
+ // not implemented
+ ASTRA_ASSERT(false);
+
+ return vOutput;
+}
+
+//----------------------------------------------------------------------------------------
+
+
+} // namespace astra
diff --git a/src/FanFlatVecProjectionGeometry2D.cpp b/src/FanFlatVecProjectionGeometry2D.cpp
new file mode 100644
index 0000000..e42a4f1
--- /dev/null
+++ b/src/FanFlatVecProjectionGeometry2D.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/FanFlatVecProjectionGeometry2D.h"
+
+#include <cstring>
+#include <sstream>
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor. Sets all variables to zero.
+CFanFlatVecProjectionGeometry2D::CFanFlatVecProjectionGeometry2D()
+{
+ _clear();
+ m_pProjectionAngles = 0;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CFanFlatVecProjectionGeometry2D::CFanFlatVecProjectionGeometry2D(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ const SFanProjection* _pProjectionAngles)
+{
+ this->initialize(_iProjectionAngleCount,
+ _iDetectorCount,
+ _pProjectionAngles);
+}
+
+//----------------------------------------------------------------------------------------
+// Copy Constructor
+CFanFlatVecProjectionGeometry2D::CFanFlatVecProjectionGeometry2D(const CFanFlatVecProjectionGeometry2D& _projGeom)
+{
+ _clear();
+ this->initialize(_projGeom.m_iProjectionAngleCount,
+ _projGeom.m_iDetectorCount,
+ _projGeom.m_pProjectionAngles);
+}
+
+//----------------------------------------------------------------------------------------
+// Assignment operator.
+CFanFlatVecProjectionGeometry2D& CFanFlatVecProjectionGeometry2D::operator=(const CFanFlatVecProjectionGeometry2D& _other)
+{
+ if (m_bInitialized)
+ delete[] m_pProjectionAngles;
+ m_bInitialized = _other.m_bInitialized;
+ if (m_bInitialized) {
+ m_iProjectionAngleCount = _other.m_iProjectionAngleCount;
+ m_iDetectorCount = _other.m_iDetectorCount;
+ m_pProjectionAngles = new SFanProjection[m_iProjectionAngleCount];
+ memcpy(m_pProjectionAngles, _other.m_pProjectionAngles, sizeof(m_pProjectionAngles[0])*m_iProjectionAngleCount);
+ }
+ return *this;
+}
+//----------------------------------------------------------------------------------------
+// Destructor.
+CFanFlatVecProjectionGeometry2D::~CFanFlatVecProjectionGeometry2D()
+{
+ // TODO
+ delete[] m_pProjectionAngles;
+}
+
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CFanFlatVecProjectionGeometry2D::initialize(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ const SFanProjection* _pProjectionAngles)
+{
+ m_iProjectionAngleCount = _iProjectionAngleCount;
+ m_iDetectorCount = _iDetectorCount;
+ m_pProjectionAngles = new SFanProjection[m_iProjectionAngleCount];
+ for (int i = 0; i < m_iProjectionAngleCount; ++i)
+ m_pProjectionAngles[i] = _pProjectionAngles[i];
+
+ // TODO: check?
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization with a Config object
+bool CFanFlatVecProjectionGeometry2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjectionGeometry2D> CC("FanFlatVecProjectionGeometry2D", this, _cfg);
+
+ XMLNode* node;
+
+ // TODO: Fix up class hierarchy... this class doesn't fit very well.
+ // initialization of parent class
+ //CProjectionGeometry2D::initialize(_cfg);
+
+ // Required: DetectorCount
+ node = _cfg.self->getSingleNode("DetectorCount");
+ ASTRA_CONFIG_CHECK(node, "FanFlatVecProjectionGeometry3D", "No DetectorRowCount tag specified.");
+ m_iDetectorCount = boost::lexical_cast<int>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorCount");
+
+ // Required: Vectors
+ node = _cfg.self->getSingleNode("Vectors");
+ ASTRA_CONFIG_CHECK(node, "FanFlatVecProjectionGeometry3D", "No Vectors tag specified.");
+ vector<float32> data = node->getContentNumericalArray();
+ CC.markNodeParsed("Vectors");
+ ASTRA_DELETE(node);
+ ASTRA_CONFIG_CHECK(data.size() % 6 == 0, "FanFlatVecProjectionGeometry3D", "Vectors doesn't consist of 6-tuples.");
+ m_iProjectionAngleCount = data.size() / 6;
+ m_pProjectionAngles = new SFanProjection[m_iProjectionAngleCount];
+
+ for (int i = 0; i < m_iProjectionAngleCount; ++i) {
+ SFanProjection& p = m_pProjectionAngles[i];
+ p.fSrcX = data[6*i + 0];
+ p.fSrcY = data[6*i + 1];
+ p.fDetUX = data[6*i + 4];
+ p.fDetUY = data[6*i + 5];
+
+ // The backend code currently expects the corner of the detector, while
+ // the matlab interface supplies the center
+ p.fDetSX = data[6*i + 2] - 0.5f * m_iDetectorCount * p.fDetUX;
+ p.fDetSY = data[6*i + 3] - 0.5f * m_iDetectorCount * p.fDetUY;
+ }
+
+
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Clone
+CProjectionGeometry2D* CFanFlatVecProjectionGeometry2D::clone()
+{
+ return new CFanFlatVecProjectionGeometry2D(*this);
+}
+
+//----------------------------------------------------------------------------------------
+// is equal
+bool CFanFlatVecProjectionGeometry2D::isEqual(CProjectionGeometry2D* _pGeom2) const
+{
+ if (_pGeom2 == NULL) return false;
+
+ // try to cast argument to CFanFlatVecProjectionGeometry2D
+ CFanFlatVecProjectionGeometry2D* pGeom2 = dynamic_cast<CFanFlatVecProjectionGeometry2D*>(_pGeom2);
+ if (pGeom2 == NULL) return false;
+
+ // both objects must be initialized
+ if (!m_bInitialized || !pGeom2->m_bInitialized) return false;
+
+ // check all values
+ if (m_iProjectionAngleCount != pGeom2->m_iProjectionAngleCount) return false;
+ if (m_iDetectorCount != pGeom2->m_iDetectorCount) return false;
+
+ for (int i = 0; i < m_iProjectionAngleCount; ++i) {
+ if (memcmp(&m_pProjectionAngles[i], &pGeom2->m_pProjectionAngles[i], sizeof(m_pProjectionAngles[i])) != 0) return false;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Is of type
+bool CFanFlatVecProjectionGeometry2D::isOfType(const std::string& _sType)
+{
+ return (_sType == "fanflat_vec");
+}
+
+//----------------------------------------------------------------------------------------
+
+CVector3D CFanFlatVecProjectionGeometry2D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex /* = 0 */)
+{
+ CVector3D vOutput(0.0f, 0.0f, 0.0f);
+
+ // not implemented
+ ASTRA_ASSERT(false);
+
+ return vOutput;
+}
+
+//----------------------------------------------------------------------------------------
+
+void CFanFlatVecProjectionGeometry2D::getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const
+{
+ // not implemented
+ ASTRA_ASSERT(false);
+}
+
+//----------------------------------------------------------------------------------------
+
+bool CFanFlatVecProjectionGeometry2D::_check()
+{
+ // TODO
+ return true;
+}
+
+
+//----------------------------------------------------------------------------------------
+
+
+} // namespace astra
diff --git a/src/FilteredBackProjectionAlgorithm.cpp b/src/FilteredBackProjectionAlgorithm.cpp
new file mode 100644
index 0000000..8063f7b
--- /dev/null
+++ b/src/FilteredBackProjectionAlgorithm.cpp
@@ -0,0 +1,336 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/FilteredBackProjectionAlgorithm.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include <iostream>
+#include <iomanip>
+#include <math.h>
+
+#include "astra/AstraObjectManager.h"
+#include "astra/ParallelBeamLineKernelProjector2D.h"
+#include "astra/Fourier.h"
+#include "astra/DataProjector.h"
+
+using namespace std;
+
+namespace astra {
+
+#include "astra/Projector2DImpl.inl"
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CFilteredBackProjectionAlgorithm::type = "FBP";
+const int FFT = 1;
+const int IFFT = -1;
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CFilteredBackProjectionAlgorithm::CFilteredBackProjectionAlgorithm()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CFilteredBackProjectionAlgorithm::~CFilteredBackProjectionAlgorithm()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CFilteredBackProjectionAlgorithm::_clear()
+{
+ m_pProjector = NULL;
+ m_pSinogram = NULL;
+ m_pReconstruction = NULL;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CFilteredBackProjectionAlgorithm::clear()
+{
+ m_pProjector = NULL;
+ m_pSinogram = NULL;
+ m_pReconstruction = NULL;
+ m_bIsInitialized = false;
+}
+
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+
+ // projector
+ XMLNode* node = _cfg.self->getSingleNode("ProjectorId");
+ ASTRA_CONFIG_CHECK(node, "FilteredBackProjection", "No ProjectorId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pProjector = CProjector2DManager::getSingleton().get(id);
+ ASTRA_DELETE(node);
+
+ // sinogram data
+ node = _cfg.self->getSingleNode("ProjectionDataId");
+ ASTRA_CONFIG_CHECK(node, "FilteredBackProjection", "No ProjectionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pSinogram = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+
+ // volume data
+ node = _cfg.self->getSingleNode("ReconstructionDataId");
+ ASTRA_CONFIG_CHECK(node, "FilteredBackProjection", "No ReconstructionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pReconstruction = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+
+ node = _cfg.self->getSingleNode("ProjectionIndex");
+ if (node)
+ {
+ vector<float32> projectionIndex = node->getContentNumericalArray();
+
+ int angleCount = projectionIndex.size();
+ int detectorCount = m_pProjector->getProjectionGeometry()->getDetectorCount();
+
+ float32 * sinogramData2D = new float32[angleCount* detectorCount];
+ float32 ** sinogramData = new float32*[angleCount];
+ for (int i = 0; i < angleCount; i++)
+ {
+ sinogramData[i] = &(sinogramData2D[i * detectorCount]);
+ }
+
+ float32 * projectionAngles = new float32[angleCount];
+ float32 detectorWidth = m_pProjector->getProjectionGeometry()->getDetectorWidth();
+
+ for (int i = 0; i < angleCount; i ++) {
+ if (projectionIndex[i] > m_pProjector->getProjectionGeometry()->getProjectionAngleCount() -1 )
+ {
+ cout << "Invalid Projection Index" << endl;
+ return false;
+ } else {
+ int orgIndex = (int)projectionIndex[i];
+
+ for (int iDetector=0; iDetector < detectorCount; iDetector++)
+ {
+ sinogramData2D[i*detectorCount+ iDetector] = m_pSinogram->getData2D()[orgIndex][iDetector];
+ }
+// sinogramData[i] = m_pSinogram->getSingleProjectionData(projectionIndex[i]);
+ projectionAngles[i] = m_pProjector->getProjectionGeometry()->getProjectionAngle((int)projectionIndex[i] );
+
+ }
+ }
+
+ CParallelProjectionGeometry2D * pg = new CParallelProjectionGeometry2D(angleCount, detectorCount,detectorWidth,projectionAngles);
+ m_pProjector = new CParallelBeamLineKernelProjector2D(pg,m_pReconstruction->getGeometry());
+ m_pSinogram = new CFloat32ProjectionData2D(pg, sinogramData2D);
+ }
+ ASTRA_DELETE(node);
+
+ // TODO: check that the angles are linearly spaced between 0 and pi
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Get Information - all
+map<string,boost::any> CFilteredBackProjectionAlgorithm::getInformation()
+{
+ map<string, boost::any> result;
+ result["ProjectorId"] = getInformation("ProjectorId");
+ result["ProjectionDataId"] = getInformation("ProjectionDataId");
+ result["VolumeDataId"] = getInformation("VolumeDataId");
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), result);
+};
+
+//---------------------------------------------------------------------------------------
+// Get Information - specific
+boost::any CFilteredBackProjectionAlgorithm::getInformation(std::string _sIdentifier)
+{
+ if (_sIdentifier == "ProjectorId") {
+ int iIndex = CProjector2DManager::getSingleton().getIndex(m_pProjector);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ } else if (_sIdentifier == "ProjectionDataId") {
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pSinogram);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ } else if (_sIdentifier == "VolumeDataId") {
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pReconstruction);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Initialize
+bool CFilteredBackProjectionAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32VolumeData2D* _pVolume,
+ CFloat32ProjectionData2D* _pSinogram)
+{
+ // store classes
+ m_pProjector = _pProjector;
+ m_pReconstruction = _pVolume;
+ m_pSinogram = _pSinogram;
+
+
+ // TODO: check that the angles are linearly spaced between 0 and pi
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CFilteredBackProjectionAlgorithm::_check()
+{
+ ASTRA_CONFIG_CHECK(CReconstructionAlgorithm2D::_check(), "FBP", "Error in ReconstructionAlgorithm2D initialization");
+
+ // success
+ return true;
+}
+
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CFilteredBackProjectionAlgorithm::run(int _iNrIterations)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ // Filter sinogram
+ CFloat32ProjectionData2D filteredSinogram(m_pSinogram->getGeometry(), m_pSinogram->getData());
+ performFiltering(&filteredSinogram);
+
+ // Back project
+ m_pReconstruction->setData(0.0f);
+ projectData(m_pProjector,
+ DefaultBPPolicy(m_pReconstruction, &filteredSinogram));
+
+ // Scale data
+ int iAngleCount = m_pProjector->getProjectionGeometry()->getProjectionAngleCount();
+ (*m_pReconstruction) *= (PI/2)/iAngleCount;
+
+ m_pReconstruction->updateStatistics();
+}
+
+
+//----------------------------------------------------------------------------------------
+void CFilteredBackProjectionAlgorithm::performFiltering(CFloat32ProjectionData2D * _pFilteredSinogram)
+{
+ ASTRA_ASSERT(_pFilteredSinogram != NULL);
+ ASTRA_ASSERT(_pFilteredSinogram->getAngleCount() == m_pSinogram->getAngleCount());
+ ASTRA_ASSERT(_pFilteredSinogram->getDetectorCount() == m_pSinogram->getDetectorCount());
+
+
+ int iAngleCount = m_pProjector->getProjectionGeometry()->getProjectionAngleCount();
+ int iDetectorCount = m_pProjector->getProjectionGeometry()->getDetectorCount();
+
+
+ // We'll zero-pad to the smallest power of two at least 64 and
+ // at least 2*iDetectorCount
+ int zpDetector = 64;
+ int nextPow2 = 5;
+ while (zpDetector < iDetectorCount*2) {
+ zpDetector *= 2;
+ nextPow2++;
+ }
+
+ // Create filter
+ float32* filter = new float32[zpDetector];
+
+ for (int iDetector = 0; iDetector <= zpDetector/2; iDetector++)
+ filter[iDetector] = (2.0f * iDetector)/zpDetector;
+
+ for (int iDetector = zpDetector/2+1; iDetector < zpDetector; iDetector++)
+ filter[iDetector] = (2.0f * (zpDetector - iDetector)) / zpDetector;
+
+
+ float32* pfRe = new float32[iAngleCount * zpDetector];
+ float32* pfIm = new float32[iAngleCount * zpDetector];
+
+ // Copy and zero-pad data
+ for (int iAngle = 0; iAngle < iAngleCount; ++iAngle) {
+ float32* pfReRow = pfRe + iAngle * zpDetector;
+ float32* pfImRow = pfIm + iAngle * zpDetector;
+ float32* pfDataRow = _pFilteredSinogram->getData() + iAngle * iDetectorCount;
+ for (int iDetector = 0; iDetector < iDetectorCount; ++iDetector) {
+ pfReRow[iDetector] = pfDataRow[iDetector];
+ pfImRow[iDetector] = 0.0f;
+ }
+ for (int iDetector = iDetectorCount; iDetector < zpDetector; ++iDetector) {
+ pfReRow[iDetector] = 0.0f;
+ pfImRow[iDetector] = 0.0f;
+ }
+ }
+
+ // in-place FFT
+ for (int iAngle = 0; iAngle < iAngleCount; ++iAngle) {
+ float32* pfReRow = pfRe + iAngle * zpDetector;
+ float32* pfImRow = pfIm + iAngle * zpDetector;
+
+ fastTwoPowerFourierTransform1D(zpDetector, pfReRow, pfImRow, pfReRow, pfImRow, 1, 1, false);
+ }
+
+ // Filter
+ for (int iAngle = 0; iAngle < iAngleCount; ++iAngle) {
+ float32* pfReRow = pfRe + iAngle * zpDetector;
+ float32* pfImRow = pfIm + iAngle * zpDetector;
+ for (int iDetector = 0; iDetector < zpDetector; ++iDetector) {
+ pfReRow[iDetector] *= filter[iDetector];
+ pfImRow[iDetector] *= filter[iDetector];
+ }
+ }
+
+ // in-place inverse FFT
+ for (int iAngle = 0; iAngle < iAngleCount; ++iAngle) {
+ float32* pfReRow = pfRe + iAngle * zpDetector;
+ float32* pfImRow = pfIm + iAngle * zpDetector;
+
+ fastTwoPowerFourierTransform1D(zpDetector, pfReRow, pfImRow, pfReRow, pfImRow, 1, 1, true);
+ }
+
+ // Copy data back
+ for (int iAngle = 0; iAngle < iAngleCount; ++iAngle) {
+ float32* pfReRow = pfRe + iAngle * zpDetector;
+ float32* pfDataRow = _pFilteredSinogram->getData() + iAngle * iDetectorCount;
+ for (int iDetector = 0; iDetector < iDetectorCount; ++iDetector)
+ pfDataRow[iDetector] = pfReRow[iDetector];
+ }
+
+ delete[] pfRe;
+ delete[] pfIm;
+ delete[] filter;
+}
+
+}
diff --git a/src/Float32Data.cpp b/src/Float32Data.cpp
new file mode 100644
index 0000000..47bbcc9
--- /dev/null
+++ b/src/Float32Data.cpp
@@ -0,0 +1,50 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Float32Data.h"
+
+using namespace std;
+
+namespace astra {
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CFloat32Data::CFloat32Data()
+{
+
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CFloat32Data::~CFloat32Data()
+{
+
+}
+
+
+} // end namespace
diff --git a/src/Float32Data2D.cpp b/src/Float32Data2D.cpp
new file mode 100644
index 0000000..e51935f
--- /dev/null
+++ b/src/Float32Data2D.cpp
@@ -0,0 +1,523 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Float32Data2D.h"
+#include <iostream>
+#include <cstring>
+
+#ifdef _MSC_VER
+#include <malloc.h>
+#else
+#include <cstdlib>
+#endif
+
+namespace astra {
+
+
+ //----------------------------------------------------------------------------------------
+ // Constructors
+//----------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CFloat32Data2D::CFloat32Data2D()
+{
+ _clear();
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32Data2D class, allocating (but not initializing) the data block.
+CFloat32Data2D::CFloat32Data2D(int _iWidth, int _iHeight)
+{
+ m_bInitialized = false;
+ _initialize(_iWidth, _iHeight);
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32Data2D class with initialization of the data block.
+CFloat32Data2D::CFloat32Data2D(int _iWidth, int _iHeight, const float32* _pfData)
+{
+ m_bInitialized = false;
+ _initialize(_iWidth, _iHeight, _pfData);
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32Data2D class with initialization of the data block.
+CFloat32Data2D::CFloat32Data2D(int _iWidth, int _iHeight, float32 _fScalar)
+{
+ m_bInitialized = false;
+ _initialize(_iWidth, _iHeight, _fScalar);
+}
+
+//----------------------------------------------------------------------------------------
+// Copy constructor
+CFloat32Data2D::CFloat32Data2D(const CFloat32Data2D& _other)
+{
+ m_bInitialized = false;
+ *this = _other;
+}
+
+//----------------------------------------------------------------------------------------
+// Assignment operator
+CFloat32Data2D& CFloat32Data2D::operator=(const CFloat32Data2D& _dataIn)
+{
+ ASTRA_ASSERT(_dataIn.m_bInitialized);
+
+ if (m_bInitialized) {
+ if (m_iWidth == _dataIn.m_iWidth && m_iHeight == _dataIn.m_iHeight) {
+ // Same dimensions, so no need to re-allocate memory
+
+ m_fGlobalMin = _dataIn.m_fGlobalMin;
+ m_fGlobalMax = _dataIn.m_fGlobalMax;
+ m_fGlobalMean = _dataIn.m_fGlobalMean;
+
+ ASTRA_ASSERT(m_iSize == (size_t)m_iWidth * m_iHeight);
+ ASTRA_ASSERT(m_pfData);
+
+ memcpy(m_pfData, _dataIn.m_pfData, m_iSize * sizeof(float32));
+ } else {
+ // Re-allocate data
+ _unInit();
+ _initialize(_dataIn.getWidth(), _dataIn.getHeight(), _dataIn.getDataConst());
+ }
+ } else {
+ _initialize(_dataIn.getWidth(), _dataIn.getHeight(), _dataIn.getDataConst());
+ }
+
+ return (*this);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor. Free allocated memory
+CFloat32Data2D::~CFloat32Data2D()
+{
+ if (m_bInitialized)
+ {
+ _unInit();
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Initializes an instance of the CFloat32Data2D class, allocating (but not initializing) the data block.
+bool CFloat32Data2D::_initialize(int _iWidth, int _iHeight)
+{
+ // basic checks
+ ASTRA_ASSERT(_iWidth > 0);
+ ASTRA_ASSERT(_iHeight > 0);
+
+ if (m_bInitialized)
+ {
+ _unInit();
+ }
+
+ // calculate size
+ m_iWidth = _iWidth;
+ m_iHeight = _iHeight;
+ m_iSize = (size_t)m_iWidth * m_iHeight;
+
+ // allocate memory for the data, but do not fill it
+ m_pfData = 0;
+ m_ppfData2D = 0;
+ _allocateData();
+
+ // set minmax to default values
+ m_fGlobalMin = 0.0;
+ m_fGlobalMax = 0.0;
+ m_fGlobalMean = 0.0;
+
+ // initialization complete
+ return true;
+
+}
+
+//----------------------------------------------------------------------------------------
+// Initializes an instance of the CFloat32Data2D class with initialization of the data block.
+bool CFloat32Data2D::_initialize(int _iWidth, int _iHeight, const float32 *_pfData)
+{
+ // basic checks
+ ASTRA_ASSERT(_iWidth > 0);
+ ASTRA_ASSERT(_iHeight > 0);
+ ASTRA_ASSERT(_pfData != NULL);
+
+ if (m_bInitialized)
+ {
+ _unInit();
+ }
+
+ // calculate size
+ m_iWidth = _iWidth;
+ m_iHeight = _iHeight;
+ m_iSize = (size_t)m_iWidth * m_iHeight;
+
+ // allocate memory for the data
+ m_pfData = 0;
+ m_ppfData2D = 0;
+ _allocateData();
+
+ // fill the data block with a copy of the input data
+ size_t i;
+ for (i = 0; i < m_iSize; ++i) {
+ m_pfData[i] = _pfData[i];
+ }
+
+ // initialization complete
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Initializes an instance of the CFloat32Data2D class with a scalar initialization of the data block.
+bool CFloat32Data2D::_initialize(int _iWidth, int _iHeight, float32 _fScalar)
+{
+ // basic checks
+ ASTRA_ASSERT(_iWidth > 0);
+ ASTRA_ASSERT(_iHeight > 0);
+
+ if (m_bInitialized) {
+ _unInit();
+ }
+
+ // calculate size
+ m_iWidth = _iWidth;
+ m_iHeight = _iHeight;
+ m_iSize = (size_t)m_iWidth * m_iHeight;
+
+ // allocate memory for the data
+ m_pfData = 0;
+ m_ppfData2D = 0;
+ _allocateData();
+
+ // fill the data block with a copy of the input data
+ size_t i;
+ for (i = 0; i < m_iSize; ++i)
+ {
+ m_pfData[i] = _fScalar;
+ }
+
+ // initialization complete
+ return true;
+}
+
+
+ //----------------------------------------------------------------------------------------
+ // Memory Allocation
+//----------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------
+// Allocate memory for m_pfData and m_ppfData2D arrays.
+void CFloat32Data2D::_allocateData()
+{
+ // basic checks
+ ASTRA_ASSERT(!m_bInitialized);
+
+ ASTRA_ASSERT(m_iSize > 0);
+ ASTRA_ASSERT(m_iSize == (size_t)m_iWidth * m_iHeight);
+ ASTRA_ASSERT(m_pfData == NULL);
+ ASTRA_ASSERT(m_ppfData2D == NULL);
+
+ // allocate contiguous block
+#ifdef _MSC_VER
+ m_pfData = (float32*)_aligned_malloc(m_iSize * sizeof(float32), 16);
+#else
+ int ret = posix_memalign((void**)&m_pfData, 16, m_iSize * sizeof(float32));
+ ASTRA_ASSERT(ret == 0);
+#endif
+
+ // create array of pointers to each row of the data block
+ m_ppfData2D = new float32*[m_iHeight];
+ for (int iy = 0; iy < m_iHeight; iy++)
+ {
+ m_ppfData2D[iy] = &(m_pfData[iy * m_iWidth]);
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Free memory for m_pfData and m_ppfData2D arrays.
+void CFloat32Data2D::_freeData()
+{
+ // basic checks
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_ppfData2D != NULL);
+
+ // free memory for index table
+ delete[] m_ppfData2D;
+ // free memory for data block
+#ifdef _MSC_VER
+ _aligned_free(m_pfData);
+#else
+ free(m_pfData);
+#endif
+}
+
+
+//----------------------------------------------------------------------------------------
+// Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+void CFloat32Data2D::_clear()
+{
+ m_iWidth = 0;
+ m_iHeight = 0;
+ m_iSize = 0;
+
+ m_pfData = NULL;
+ m_ppfData2D = NULL;
+
+ m_fGlobalMin = 0.0f;
+ m_fGlobalMax = 0.0f;
+}
+
+//----------------------------------------------------------------------------------------
+// Un-initialize the object, bringing it back in the unitialized state.
+void CFloat32Data2D::_unInit()
+{
+ ASTRA_ASSERT(m_bInitialized);
+
+ _freeData();
+ _clear();
+ m_bInitialized = false;
+}
+//----------------------------------------------------------------------------------------
+
+
+
+ //----------------------------------------------------------------------------------------
+ // Data Operations
+//----------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------
+// Copy the data block pointed to by _pfData to the data block pointed to by m_pfData.
+void CFloat32Data2D::copyData(const float32* _pfData)
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_pfData != NULL);
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_iSize > 0);
+
+ // copy data
+ size_t i;
+ for (i = 0; i < m_iSize; ++i) {
+ m_pfData[i] = _pfData[i];
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// scale m_pfData from 0 to 255.
+
+void CFloat32Data2D::scale()
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_iSize > 0);
+
+ _computeGlobalMinMax();
+ for (size_t i = 0; i < m_iSize; i++)
+ {
+ // do checks
+ m_pfData[i]= (m_pfData[i] - m_fGlobalMin) / (m_fGlobalMax - m_fGlobalMin) * 255; ;
+ }
+
+
+}
+
+//----------------------------------------------------------------------------------------
+// Set each element of the data to a specific scalar value
+void CFloat32Data2D::setData(float32 _fScalar)
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_iSize > 0);
+
+ // copy data
+ size_t i;
+ for (i = 0; i < m_iSize; ++i)
+ {
+ m_pfData[i] = _fScalar;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Clear Data
+void CFloat32Data2D::clearData()
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_iSize > 0);
+
+ // set data
+ size_t i;
+ for (i = 0; i < m_iSize; ++i) {
+ m_pfData[i] = 0.0f;
+ }
+}
+//----------------------------------------------------------------------------------------
+
+
+
+ //----------------------------------------------------------------------------------------
+ // Statistics Operations
+//----------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------
+// Update data statistics, such as minimum and maximum value, after the data has been modified.
+void CFloat32Data2D::updateStatistics()
+{
+ _computeGlobalMinMax();
+}
+
+//----------------------------------------------------------------------------------------
+// Find the minimum and maximum data value.
+void CFloat32Data2D::_computeGlobalMinMax()
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_iSize > 0);
+
+ // initial values
+ m_fGlobalMin = m_pfData[0];
+ m_fGlobalMax = m_pfData[0];
+ m_fGlobalMean = 0.0f;
+
+ // loop
+ for (size_t i = 0; i < m_iSize; i++)
+ {
+ // do checks
+ float32 v = m_pfData[i];
+ if (v < m_fGlobalMin) {
+ m_fGlobalMin = v;
+ }
+ if (v > m_fGlobalMax) {
+ m_fGlobalMax = v;
+ }
+ m_fGlobalMean +=v;
+ }
+ m_fGlobalMean /= m_iSize;
+}
+//----------------------------------------------------------------------------------------
+
+
+CFloat32Data2D& CFloat32Data2D::clampMin(float32& _fMin)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ for (size_t i = 0; i < m_iSize; i++) {
+ if (m_pfData[i] < _fMin)
+ m_pfData[i] = _fMin;
+ }
+ return (*this);
+}
+
+CFloat32Data2D& CFloat32Data2D::clampMax(float32& _fMax)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ for (size_t i = 0; i < m_iSize; i++) {
+ if (m_pfData[i] > _fMax)
+ m_pfData[i] = _fMax;
+ }
+ return (*this);
+}
+
+
+//----------------------------------------------------------------------------------------
+// Operator Overloading
+//----------------------------------------------------------------------------------------
+CFloat32Data2D& CFloat32Data2D::operator+=(const CFloat32Data2D& v)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(v.m_bInitialized);
+ ASTRA_ASSERT(getSize() == v.getSize());
+ for (size_t i = 0; i < m_iSize; i++) {
+ m_pfData[i] += v.m_pfData[i];
+ }
+ return (*this);
+}
+
+CFloat32Data2D& CFloat32Data2D::operator-=(const CFloat32Data2D& v)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(v.m_bInitialized);
+ ASTRA_ASSERT(getSize() == v.getSize());
+ for (size_t i = 0; i < m_iSize; i++) {
+ m_pfData[i] -= v.m_pfData[i];
+ }
+ return (*this);
+}
+
+CFloat32Data2D& CFloat32Data2D::operator*=(const CFloat32Data2D& v)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(v.m_bInitialized);
+ ASTRA_ASSERT(getSize() == v.getSize());
+ for (size_t i = 0; i < m_iSize; i++) {
+ m_pfData[i] *= v.m_pfData[i];
+ }
+ return (*this);
+}
+
+CFloat32Data2D& CFloat32Data2D::operator*=(const float32& f)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ for (size_t i = 0; i < m_iSize; i++) {
+ m_pfData[i] *= f;
+ }
+ return (*this);
+}
+
+CFloat32Data2D& CFloat32Data2D::operator/=(const float32& f)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ for (size_t i = 0; i < m_iSize; i++) {
+ m_pfData[i] /= f;
+ }
+ return (*this);
+}
+
+CFloat32Data2D& CFloat32Data2D::operator+=(const float32& f)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ for (size_t i = 0; i < m_iSize; i++) {
+ m_pfData[i] += f;
+ }
+ return (*this);
+}
+
+CFloat32Data2D& CFloat32Data2D::operator-=(const float32& f)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ for (size_t i = 0; i < m_iSize; i++) {
+ m_pfData[i] -= f;
+ }
+ return (*this);
+}
+
+
+
+
+} // end namespace astra
diff --git a/src/Float32Data3D.cpp b/src/Float32Data3D.cpp
new file mode 100644
index 0000000..4280b3b
--- /dev/null
+++ b/src/Float32Data3D.cpp
@@ -0,0 +1,55 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Float32Data3D.h"
+
+using namespace std;
+
+namespace astra {
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CFloat32Data3D::CFloat32Data3D()
+{
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CFloat32Data3D::~CFloat32Data3D()
+{
+
+}
+//----------------------------------------------------------------------------------------
+
+bool CFloat32Data3D::_data3DSizesEqual(const CFloat32Data3D * _pA, const CFloat32Data3D * _pB)
+{
+ return ((_pA->m_iWidth == _pB->m_iWidth) && (_pA->m_iHeight == _pB->m_iHeight) && (_pA->m_iDepth == _pB->m_iDepth));
+}
+
+} // end namespace astra
diff --git a/src/Float32Data3DMemory.cpp b/src/Float32Data3DMemory.cpp
new file mode 100644
index 0000000..386770c
--- /dev/null
+++ b/src/Float32Data3DMemory.cpp
@@ -0,0 +1,356 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Float32Data3DMemory.h"
+#include <iostream>
+
+namespace astra {
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CFloat32Data3DMemory::CFloat32Data3DMemory()
+{
+ _clear();
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor. Free allocated memory
+CFloat32Data3DMemory::~CFloat32Data3DMemory()
+{
+ if (m_bInitialized)
+ {
+ _unInit();
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Initializes an instance of the CFloat32Data2D class, allocating (but not initializing) the data block.
+bool CFloat32Data3DMemory::_initialize(int _iWidth, int _iHeight, int _iDepth)
+{
+ // basic checks
+ ASTRA_ASSERT(_iWidth > 0);
+ ASTRA_ASSERT(_iHeight > 0);
+ ASTRA_ASSERT(_iDepth > 0);
+
+ if (m_bInitialized)
+ {
+ _unInit();
+ }
+
+ // calculate size
+ m_iWidth = _iWidth;
+ m_iHeight = _iHeight;
+ m_iDepth = _iDepth;
+ m_iSize = (size_t)m_iWidth * m_iHeight * m_iDepth;
+
+ // allocate memory for the data, but do not fill it
+ m_pfData = NULL;
+ m_ppfDataRowInd = NULL;
+ m_pppfDataSliceInd = NULL;
+ _allocateData();
+
+ // set minmax to default values
+ m_fGlobalMin = 0.0;
+ m_fGlobalMax = 0.0;
+
+ // initialization complete
+ return true;
+
+}
+
+//----------------------------------------------------------------------------------------
+// Initializes an instance of the CFloat32Data2D class with initialization of the data block.
+bool CFloat32Data3DMemory::_initialize(int _iWidth, int _iHeight, int _iDepth, const float32* _pfData)
+{
+ // basic checks
+ ASTRA_ASSERT(_iWidth > 0);
+ ASTRA_ASSERT(_iHeight > 0);
+ ASTRA_ASSERT(_iDepth > 0);
+ ASTRA_ASSERT(_pfData != NULL);
+
+ if (m_bInitialized) {
+ _unInit();
+ }
+
+ // calculate size
+ m_iWidth = _iWidth;
+ m_iHeight = _iHeight;
+ m_iDepth = _iDepth;
+ m_iSize = (size_t)m_iWidth * m_iHeight * m_iDepth;
+
+ // allocate memory for the data, but do not fill it
+ m_pfData = NULL;
+ m_ppfDataRowInd = NULL;
+ m_pppfDataSliceInd = NULL;
+ _allocateData();
+
+ // fill the data block with a copy of the input data
+ size_t i;
+ for (i = 0; i < m_iSize; ++i)
+ {
+ m_pfData[i] = _pfData[i];
+ }
+
+ // initialization complete
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Initializes an instance of the CFloat32Data2D class with initialization of the data block.
+bool CFloat32Data3DMemory::_initialize(int _iWidth, int _iHeight, int _iDepth, float32 _fScalar)
+{
+ // basic checks
+ ASTRA_ASSERT(_iWidth > 0);
+ ASTRA_ASSERT(_iHeight > 0);
+ ASTRA_ASSERT(_iDepth > 0);
+
+ if (m_bInitialized) {
+ _unInit();
+ }
+
+ // calculate size
+ m_iWidth = _iWidth;
+ m_iHeight = _iHeight;
+ m_iDepth = _iDepth;
+ m_iSize = (size_t)m_iWidth * m_iHeight * m_iDepth;
+
+ // allocate memory for the data, but do not fill it
+ m_pfData = NULL;
+ m_ppfDataRowInd = NULL;
+ m_pppfDataSliceInd = NULL;
+ _allocateData();
+
+ // fill the data block with a copy of the input data
+ size_t i;
+ for (i = 0; i < m_iSize; ++i)
+ {
+ m_pfData[i] = _fScalar;
+ }
+
+ // initialization complete
+ return true;
+}
+//----------------------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------------------
+// Allocate memory for m_pfData and m_ppfData2D arrays.
+void CFloat32Data3DMemory::_allocateData()
+{
+ // basic checks
+ ASTRA_ASSERT(!m_bInitialized);
+
+ ASTRA_ASSERT(m_iSize > 0);
+ ASTRA_ASSERT(m_iSize == (size_t)m_iWidth * m_iHeight * m_iDepth);
+ ASTRA_ASSERT(m_pfData == NULL);
+ ASTRA_ASSERT(m_ppfDataRowInd == NULL);
+ ASTRA_ASSERT(m_pppfDataSliceInd == NULL);
+
+ // allocate contiguous block
+#ifdef _MSC_VER
+ m_pfData = (float32*)_aligned_malloc(m_iSize * sizeof(float32), 16);
+#else
+ int ret = posix_memalign((void**)&m_pfData, 16, m_iSize * sizeof(float32));
+ ASTRA_ASSERT(ret == 0);
+#endif
+ ASTRA_ASSERT(((size_t)m_pfData & 15) == 0);
+
+ // create array of pointers to each row of the data block
+ m_ppfDataRowInd = new float32*[m_iHeight*m_iDepth];
+ for (int iy = 0; iy < m_iHeight*m_iDepth; iy++)
+ {
+ m_ppfDataRowInd[iy] = &(m_pfData[iy * m_iWidth]);
+ }
+
+ // create array of pointers to each row of the data block
+ m_pppfDataSliceInd = new float32**[m_iDepth];
+ for (int iy = 0; iy < m_iDepth; iy++)
+ {
+ m_pppfDataSliceInd[iy] = &(m_ppfDataRowInd[iy * m_iHeight]);
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Free memory for m_pfData and m_ppfData2D arrays.
+void CFloat32Data3DMemory::_freeData()
+{
+ // basic checks
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_ppfDataRowInd != NULL);
+ ASTRA_ASSERT(m_pppfDataSliceInd != NULL);
+
+ // free memory for index table
+ delete[] m_pppfDataSliceInd;
+ // free memory for index table
+ delete[] m_ppfDataRowInd;
+ // free memory for data block
+#ifdef _MSC_VER
+ _aligned_free(m_pfData);
+#else
+ free(m_pfData);
+#endif
+}
+
+//----------------------------------------------------------------------------------------
+// Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+void CFloat32Data3DMemory::_clear()
+{
+ m_iWidth = 0;
+ m_iHeight = 0;
+ m_iDepth = 0;
+ m_iSize = 0;
+
+ m_pfData = NULL;
+ m_ppfDataRowInd = NULL;
+ m_pppfDataSliceInd = NULL;
+
+ //m_fGlobalMin = 0.0f;
+ //m_fGlobalMax = 0.0f;
+}
+
+//----------------------------------------------------------------------------------------
+// Un-initialize the object, bringing it back in the unitialized state.
+void CFloat32Data3DMemory::_unInit()
+{
+ ASTRA_ASSERT(m_bInitialized);
+
+ _freeData();
+ _clear();
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Update data statistics, such as minimum and maximum value, after the data has been modified.
+void CFloat32Data3DMemory::updateStatistics()
+{
+ _computeGlobalMinMax();
+}
+
+//----------------------------------------------------------------------------------------
+// Find the minimum and maximum data value.
+void CFloat32Data3DMemory::_computeGlobalMinMax()
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_iSize > 0);
+
+ // initial values
+ m_fGlobalMin = m_pfData[0];
+ m_fGlobalMax = m_pfData[0];
+
+ // loop
+ size_t i;
+ float32 v;
+ for (i = 0; i < m_iSize; ++i)
+ {
+ v = m_pfData[i];
+ if (v < m_fGlobalMin) m_fGlobalMin = v;
+ if (v > m_fGlobalMax) m_fGlobalMax = v;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Copy the data block pointed to by _pfData to the data block pointed to by m_pfData.
+void CFloat32Data3DMemory::copyData(const float32* _pfData, size_t _iSize)
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_pfData != NULL);
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_iSize > 0);
+ ASTRA_ASSERT(m_iSize == _iSize);
+
+ // copy data
+ size_t i;
+ for (i = 0; i < m_iSize; ++i)
+ {
+ m_pfData[i] = _pfData[i];
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Copy the data block pointed to by _pfData to the data block pointed to by m_pfData.
+void CFloat32Data3DMemory::setData(float32 _fScalar)
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_iSize > 0);
+
+ // copy data
+ size_t i;
+ for (i = 0; i < m_iSize; ++i)
+ {
+ m_pfData[i] = _fScalar;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Clear Data
+void CFloat32Data3DMemory::clearData()
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(m_pfData != NULL);
+ ASTRA_ASSERT(m_iSize > 0);
+
+ // set data
+ size_t i;
+ for (i = 0; i < m_iSize; ++i) {
+ m_pfData[i] = 0.0f;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+
+CFloat32Data3D& CFloat32Data3DMemory::clampMin(float32& _fMin)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ for (size_t i = 0; i < m_iSize; i++) {
+ if (m_pfData[i] < _fMin)
+ m_pfData[i] = _fMin;
+ }
+ return (*this);
+}
+
+CFloat32Data3D& CFloat32Data3DMemory::clampMax(float32& _fMax)
+{
+ ASTRA_ASSERT(m_bInitialized);
+ for (size_t i = 0; i < m_iSize; i++) {
+ if (m_pfData[i] > _fMax)
+ m_pfData[i] = _fMax;
+ }
+ return (*this);
+}
+
+
+
+
+} // end namespace astra
diff --git a/src/Float32ProjectionData2D.cpp b/src/Float32ProjectionData2D.cpp
new file mode 100644
index 0000000..a74fc14
--- /dev/null
+++ b/src/Float32ProjectionData2D.cpp
@@ -0,0 +1,139 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Float32ProjectionData2D.h"
+
+using namespace std;
+
+namespace astra {
+
+//----------------------------------------------------------------------------------------
+// Default constructor
+CFloat32ProjectionData2D::CFloat32ProjectionData2D() :
+ CFloat32Data2D()
+{
+ m_bInitialized = false;
+ m_pGeometry = NULL;
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32ProjectionData2D class, allocating (but not initializing) the data block.
+CFloat32ProjectionData2D::CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry)
+{
+ m_bInitialized = false;
+ initialize(_pGeometry);
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32ProjectionData2D class with initialization of the data.
+CFloat32ProjectionData2D::CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry, float32* _pfData)
+{
+ m_bInitialized = false;
+ m_bInitialized = initialize(_pGeometry, _pfData);
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32ProjectionData2D class with scalar initialization of the data.
+CFloat32ProjectionData2D::CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry, float32 _fScalar)
+{
+ m_bInitialized = false;
+ m_bInitialized = initialize(_pGeometry, _fScalar);
+}
+
+
+//----------------------------------------------------------------------------------------
+// Copy constructor
+CFloat32ProjectionData2D::CFloat32ProjectionData2D(const CFloat32ProjectionData2D& _other) : CFloat32Data2D(_other)
+{
+ // Data is copied by parent constructor
+ m_pGeometry = _other.m_pGeometry->clone();
+ m_bInitialized = true;
+}
+
+// Assignment operator
+
+CFloat32ProjectionData2D& CFloat32ProjectionData2D::operator=(const CFloat32ProjectionData2D& _other)
+{
+ ASTRA_ASSERT(_other.m_bInitialized);
+
+ if (m_bInitialized)
+ delete m_pGeometry;
+ *((CFloat32Data2D*)this) = _other;
+ m_pGeometry = _other.m_pGeometry->clone();
+ m_bInitialized = true;
+
+ return *this;
+}
+
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32ProjectionData2D::initialize(CProjectionGeometry2D* _pGeometry)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getDetectorCount(), m_pGeometry->getProjectionAngleCount());
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32ProjectionData2D::initialize(CProjectionGeometry2D* _pGeometry, const float32* _pfData)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getDetectorCount(), m_pGeometry->getProjectionAngleCount(), _pfData);
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32ProjectionData2D::initialize(CProjectionGeometry2D* _pGeometry, float32 _fScalar)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getDetectorCount(), m_pGeometry->getProjectionAngleCount(), _fScalar);
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CFloat32ProjectionData2D::~CFloat32ProjectionData2D()
+{
+ if (m_bInitialized)
+ delete m_pGeometry;
+ m_pGeometry = 0;
+}
+
+//----------------------------------------------------------------------------------------
+void CFloat32ProjectionData2D::changeGeometry(CProjectionGeometry2D* _pGeometry)
+{
+ if (!m_bInitialized) return;
+
+ delete m_pGeometry;
+ m_pGeometry = _pGeometry->clone();
+}
+
+} // end namespace astra
diff --git a/src/Float32ProjectionData3D.cpp b/src/Float32ProjectionData3D.cpp
new file mode 100644
index 0000000..66bb5e3
--- /dev/null
+++ b/src/Float32ProjectionData3D.cpp
@@ -0,0 +1,273 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Float32ProjectionData3D.h"
+
+using namespace std;
+
+namespace astra {
+
+//----------------------------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------------------------
+
+
+// Default constructor
+CFloat32ProjectionData3D::CFloat32ProjectionData3D() :
+ CFloat32Data3D() {
+}
+
+// Destructor
+CFloat32ProjectionData3D::~CFloat32ProjectionData3D() {
+ delete m_pGeometry;
+ m_pGeometry = 0;
+}
+
+CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator+=(const CFloat32ProjectionData3D& _data)
+{
+ CProjectionGeometry3D * pThisGeometry = getGeometry();
+
+ int iProjectionCount = pThisGeometry->getProjectionCount();
+#ifdef _DEBUG
+ CProjectionGeometry3D * pDataGeometry = _data.getGeometry();
+ int iThisProjectionDetectorCount = pThisGeometry->getDetectorRowCount() * pThisGeometry->getDetectorColCount();
+ int iDataProjectionDetectorCount = pDataGeometry->getDetectorRowCount() * pDataGeometry->getDetectorColCount();
+
+ ASTRA_ASSERT(iProjectionCount == pDataGeometry->getProjectionCount());
+ ASTRA_ASSERT(iThisProjectionDetectorCount == iDataProjectionDetectorCount);
+#endif
+
+ for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex);
+ CFloat32VolumeData2D * pDataProjection = _data.fetchProjection(iProjectionIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+ float32 fDataValue = pDataProjection->getDataConst()[iDetectorIndex];
+
+ fThisValue += fDataValue;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnProjection(iProjectionIndex, pThisProjection);
+
+ delete pThisProjection;
+ delete pDataProjection;
+ }
+
+ return *this;
+}
+
+CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator-=(const CFloat32ProjectionData3D& _data)
+{
+ CProjectionGeometry3D * pThisGeometry = getGeometry();
+
+ int iProjectionCount = pThisGeometry->getProjectionCount();
+#ifdef _DEBUG
+ CProjectionGeometry3D * pDataGeometry = _data.getGeometry();
+ int iThisProjectionDetectorCount = pThisGeometry->getDetectorRowCount() * pThisGeometry->getDetectorColCount();
+ int iDataProjectionDetectorCount = pDataGeometry->getDetectorRowCount() * pDataGeometry->getDetectorColCount();
+
+ ASTRA_ASSERT(iProjectionCount == pDataGeometry->getProjectionCount());
+ ASTRA_ASSERT(iThisProjectionDetectorCount == iDataProjectionDetectorCount);
+#endif
+
+ for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex);
+ CFloat32VolumeData2D * pDataProjection = _data.fetchProjection(iProjectionIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+ float32 fDataValue = pDataProjection->getDataConst()[iDetectorIndex];
+
+ fThisValue -= fDataValue;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnProjection(iProjectionIndex, pThisProjection);
+
+ delete pThisProjection;
+ delete pDataProjection;
+ }
+
+ return *this;
+}
+
+CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator*=(const CFloat32ProjectionData3D& _data)
+{
+ CProjectionGeometry3D * pThisGeometry = getGeometry();
+
+ int iProjectionCount = pThisGeometry->getProjectionCount();
+#ifdef _DEBUG
+ CProjectionGeometry3D * pDataGeometry = _data.getGeometry();
+ int iThisProjectionDetectorCount = pThisGeometry->getDetectorRowCount() * pThisGeometry->getDetectorColCount();
+ int iDataProjectionDetectorCount = pDataGeometry->getDetectorRowCount() * pDataGeometry->getDetectorColCount();
+
+ ASTRA_ASSERT(iProjectionCount == pDataGeometry->getProjectionCount());
+ ASTRA_ASSERT(iThisProjectionDetectorCount == iDataProjectionDetectorCount);
+#endif
+
+ for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex);
+ CFloat32VolumeData2D * pDataProjection = _data.fetchProjection(iProjectionIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+ float32 fDataValue = pDataProjection->getDataConst()[iDetectorIndex];
+
+ fThisValue *= fDataValue;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnProjection(iProjectionIndex, pThisProjection);
+
+ delete pThisProjection;
+ delete pDataProjection;
+ }
+
+ return *this;
+}
+
+CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator*=(const float32& _fScalar)
+{
+ CProjectionGeometry3D * pThisGeometry = getGeometry();
+
+ int iProjectionCount = pThisGeometry->getProjectionCount();
+
+ for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+
+ fThisValue *= _fScalar;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnProjection(iProjectionIndex, pThisProjection);
+
+ delete pThisProjection;
+ }
+
+ return *this;
+}
+
+CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator/=(const float32& _fScalar)
+{
+ CProjectionGeometry3D * pThisGeometry = getGeometry();
+
+ int iProjectionCount = pThisGeometry->getProjectionCount();
+
+ for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+
+ fThisValue /= _fScalar;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnProjection(iProjectionIndex, pThisProjection);
+
+ delete pThisProjection;
+ }
+
+ return *this;
+}
+
+CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator+=(const float32& _fScalar)
+{
+ CProjectionGeometry3D * pThisGeometry = getGeometry();
+
+ int iProjectionCount = pThisGeometry->getProjectionCount();
+
+ for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+
+ fThisValue += _fScalar;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnProjection(iProjectionIndex, pThisProjection);
+
+ delete pThisProjection;
+ }
+
+ return *this;
+}
+
+CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator-=(const float32& _fScalar)
+{
+ CProjectionGeometry3D * pThisGeometry = getGeometry();
+
+ int iProjectionCount = pThisGeometry->getProjectionCount();
+
+ for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+
+ fThisValue -= _fScalar;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnProjection(iProjectionIndex, pThisProjection);
+
+ delete pThisProjection;
+ }
+
+ return *this;
+}
+
+} // end namespace astra
diff --git a/src/Float32ProjectionData3DMemory.cpp b/src/Float32ProjectionData3DMemory.cpp
new file mode 100644
index 0000000..4d23688
--- /dev/null
+++ b/src/Float32ProjectionData3DMemory.cpp
@@ -0,0 +1,221 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Float32ProjectionData3DMemory.h"
+#include "astra/ParallelProjectionGeometry3D.h"
+
+#include <cstring>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor
+CFloat32ProjectionData3DMemory::CFloat32ProjectionData3DMemory() :
+ CFloat32Data3DMemory()
+{
+ m_bInitialized = false;
+ m_pGeometry = NULL;
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32ProjectionData2D class, allocating (but not initializing) the data block.
+CFloat32ProjectionData3DMemory::CFloat32ProjectionData3DMemory(CProjectionGeometry3D* _pGeometry)
+{
+ m_bInitialized = false;
+ initialize(_pGeometry);
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32ProjectionData2D class with initialization of the data.
+CFloat32ProjectionData3DMemory::CFloat32ProjectionData3DMemory(CProjectionGeometry3D* _pGeometry, float32* _pfData)
+{
+ m_bInitialized = false;
+ m_bInitialized = initialize(_pGeometry, _pfData);
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32ProjectionData2D class with initialization of the data.
+CFloat32ProjectionData3DMemory::CFloat32ProjectionData3DMemory(CProjectionGeometry3D* _pGeometry, float32 _fScalar)
+{
+ m_bInitialized = false;
+ m_bInitialized = initialize(_pGeometry, _fScalar);
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32ProjectionData3DMemory::initialize(CProjectionGeometry3D* _pGeometry)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getDetectorColCount(), // width
+ m_pGeometry->getProjectionCount(), // height
+ m_pGeometry->getDetectorRowCount()); // depth
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32ProjectionData3DMemory::initialize(CProjectionGeometry3D* _pGeometry, const float32* _pfData)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getDetectorColCount(), // width
+ m_pGeometry->getProjectionCount(), // height
+ m_pGeometry->getDetectorRowCount(), // depth
+ _pfData);
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32ProjectionData3DMemory::initialize(CProjectionGeometry3D* _pGeometry, float32 _fScalar)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getDetectorColCount(), // width
+ m_pGeometry->getProjectionCount(), // height
+ m_pGeometry->getDetectorRowCount(), // depth
+ _fScalar);
+ return m_bInitialized;
+}
+
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CFloat32ProjectionData3DMemory::~CFloat32ProjectionData3DMemory()
+{
+ //delete m_pGeometry; //delete geom inherited from CFloat32ProjectionData3D
+ //_unInit(); //delete stuff inherited from CFloat32Data3DMemory
+}
+
+//----------------------------------------------------------------------------------------
+// Fetch a projection
+CFloat32VolumeData2D* CFloat32ProjectionData3DMemory::fetchProjection(int _iProjectionNr) const
+{
+ // fetch slice of the geometry
+ CVolumeGeometry2D volGeom(m_pGeometry->getDetectorColCount(), m_pGeometry->getDetectorRowCount());
+ // create new volume data
+ CFloat32VolumeData2D* res = new CFloat32VolumeData2D(&volGeom);
+ // copy data
+ int row, col;
+ for (row = 0; row < m_pGeometry->getDetectorRowCount(); ++row) {
+ for (col = 0; col < m_pGeometry->getDetectorColCount(); ++col) {
+ res->getData()[row*m_pGeometry->getDetectorColCount() + col] =
+ m_pfData[_iProjectionNr * m_pGeometry->getDetectorColCount() + m_pGeometry->getDetectorColCount()* m_pGeometry->getProjectionCount() * row + col];
+ }
+ }
+ // return
+ return res;
+}
+
+//----------------------------------------------------------------------------------------
+// Return a projection
+void CFloat32ProjectionData3DMemory::returnProjection(int _iProjectionNr, CFloat32VolumeData2D* _pProjection)
+{
+ /// TODO: check geometry
+ // copy data
+ int row, col;
+ for (row = 0; row < m_pGeometry->getDetectorRowCount(); ++row) {
+ for (col = 0; col < m_pGeometry->getDetectorColCount(); ++col) {
+ m_pfData[_iProjectionNr * m_pGeometry->getDetectorColCount() + m_pGeometry->getDetectorColCount()* m_pGeometry->getProjectionCount() * row + col] =
+ _pProjection->getData()[row*m_pGeometry->getDetectorColCount() + col];
+ }
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Fetch a sinogram
+CFloat32ProjectionData2D* CFloat32ProjectionData3DMemory::fetchSinogram(int _iSliceNr) const
+{
+ CParallelProjectionGeometry3D * pParallelProjGeo = (CParallelProjectionGeometry3D *)m_pGeometry;
+ CParallelProjectionGeometry2D * pProjGeo2D = pParallelProjGeo->createProjectionGeometry2D();
+
+ // create new projection data
+ CFloat32ProjectionData2D* res = new CFloat32ProjectionData2D(pProjGeo2D);
+ // copy data
+ int row, col;
+
+ int iDetectorColumnCount = m_pGeometry->getDetectorColCount();
+ int iProjectionAngleCount = m_pGeometry->getProjectionCount();
+
+ for (row = 0; row < m_pGeometry->getProjectionCount(); ++row) {
+ for (col = 0; col < m_pGeometry->getDetectorColCount(); ++col)
+ {
+ int iTargetIndex = row * iDetectorColumnCount + col;
+ int iSourceIndex = _iSliceNr * iDetectorColumnCount * iProjectionAngleCount + row * iDetectorColumnCount + col;
+
+ float32 fStoredValue = m_pfData[iSourceIndex];
+
+ res->getData()[iTargetIndex] = fStoredValue;
+ }
+ }
+
+ delete pProjGeo2D;
+
+ // return
+ return res;
+}
+
+//----------------------------------------------------------------------------------------
+// Return a sinogram
+void CFloat32ProjectionData3DMemory::returnSinogram(int _iSliceNr, CFloat32ProjectionData2D* _pSinogram2D)
+{
+ /// TODO: check geometry
+ // copy data
+ int row, col;
+ for (row = 0; row < m_pGeometry->getProjectionCount(); ++row) {
+ for (col = 0; col < m_pGeometry->getDetectorColCount(); ++col) {
+ m_pfData[_iSliceNr*m_pGeometry->getDetectorColCount()*m_pGeometry->getProjectionCount() + row*m_pGeometry->getDetectorColCount() + col] =
+ _pSinogram2D->getData()[row*m_pGeometry->getDetectorColCount() + col];
+ }
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Returns a specific value
+float32 CFloat32ProjectionData3DMemory::getDetectorValue(int _iIndex)
+{
+ return m_pfData[_iIndex];
+}
+
+//----------------------------------------------------------------------------------------
+// Sets a specific value
+void CFloat32ProjectionData3DMemory::setDetectorValue(int _iIndex, float32 _fValue)
+{
+ m_pfData[_iIndex] = _fValue;
+}
+//----------------------------------------------------------------------------------------
+
+CFloat32ProjectionData3DMemory& CFloat32ProjectionData3DMemory::operator=(const CFloat32ProjectionData3DMemory& _dataIn)
+{
+ memcpy(m_pfData, _dataIn.m_pfData, sizeof(float32) * _dataIn.m_pGeometry->getDetectorTotCount());
+
+ return *this;
+}
+
+} // end namespace astra
diff --git a/src/Float32VolumeData2D.cpp b/src/Float32VolumeData2D.cpp
new file mode 100644
index 0000000..f07fd71
--- /dev/null
+++ b/src/Float32VolumeData2D.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Float32VolumeData2D.h"
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor
+CFloat32VolumeData2D::CFloat32VolumeData2D() :
+ CFloat32Data2D()
+{
+ m_pGeometry = NULL;
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32VolumeData2D class, allocating (but not initializing) the data block.
+CFloat32VolumeData2D::CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry)
+{
+ m_bInitialized = false;
+ m_bInitialized = initialize(_pGeometry);
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32VolumeData2D class with initialization of the data.
+CFloat32VolumeData2D::CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry, float32* _pfData)
+{
+ m_bInitialized = false;
+ m_bInitialized = initialize(_pGeometry, _pfData);
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32VolumeData2D class with initialization of the data.
+CFloat32VolumeData2D::CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry, float32 _fScalar)
+{
+ m_bInitialized = false;
+ m_bInitialized = initialize(_pGeometry, _fScalar);
+}
+
+//----------------------------------------------------------------------------------------
+// Copy constructor
+CFloat32VolumeData2D::CFloat32VolumeData2D(const CFloat32VolumeData2D& _other) : CFloat32Data2D(_other)
+{
+ m_pGeometry = _other.m_pGeometry->clone();
+ m_bInitialized = true;
+}
+
+// Assignment operator
+
+CFloat32VolumeData2D& CFloat32VolumeData2D::operator=(const CFloat32VolumeData2D& _other)
+{
+ ASTRA_ASSERT(_other.m_bInitialized);
+
+ if (m_bInitialized)
+ delete m_pGeometry;
+ *((CFloat32Data2D*)this) = _other;
+ m_pGeometry = _other.m_pGeometry->clone();
+ m_bInitialized = true;
+
+ return *this;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CFloat32VolumeData2D::~CFloat32VolumeData2D()
+{
+ if (m_bInitialized)
+ delete m_pGeometry;
+ m_pGeometry = 0;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32VolumeData2D::initialize(CVolumeGeometry2D* _pGeometry)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getGridColCount(), m_pGeometry->getGridRowCount());
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32VolumeData2D::initialize(CVolumeGeometry2D* _pGeometry, const float32* _pfData)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getGridColCount(), m_pGeometry->getGridRowCount(), _pfData);
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32VolumeData2D::initialize(CVolumeGeometry2D* _pGeometry, float32 _fScalar)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getGridColCount(), m_pGeometry->getGridRowCount(), _fScalar);
+ return m_bInitialized;
+}
+//----------------------------------------------------------------------------------------
+void CFloat32VolumeData2D::changeGeometry(CVolumeGeometry2D* _pGeometry)
+{
+ if (!m_bInitialized) return;
+
+ delete m_pGeometry;
+ m_pGeometry = _pGeometry->clone();
+}
+
+
+} // end namespace astra
diff --git a/src/Float32VolumeData3D.cpp b/src/Float32VolumeData3D.cpp
new file mode 100644
index 0000000..d269aa8
--- /dev/null
+++ b/src/Float32VolumeData3D.cpp
@@ -0,0 +1,269 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Float32VolumeData3D.h"
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CFloat32VolumeData3D::CFloat32VolumeData3D() :
+ CFloat32Data3D() {
+
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CFloat32VolumeData3D::~CFloat32VolumeData3D() {
+
+}
+
+CFloat32VolumeData3D& CFloat32VolumeData3D::operator+=(const CFloat32VolumeData3D& _data)
+{
+ CVolumeGeometry3D * pThisGeometry = getGeometry();
+
+ int iSliceCount = pThisGeometry->getGridSliceCount();
+#ifdef _DEBUG
+ CVolumeGeometry3D * pDataGeometry = _data.getGeometry();
+ int iThisSlicePixelCount = pThisGeometry->getGridRowCount() * pThisGeometry->getGridColCount();
+ int iDataSlicePixelCount = pDataGeometry->getGridRowCount() * pDataGeometry->getGridColCount();
+
+ ASTRA_ASSERT(iSliceCount == pDataGeometry->getGridSliceCount());
+ ASTRA_ASSERT(iThisSlicePixelCount == iDataSlicePixelCount);
+#endif
+
+ for(int iSliceIndex = 0; iSliceIndex < iSliceCount; iSliceIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchSliceZ(iSliceIndex);
+ CFloat32VolumeData2D * pDataProjection = _data.fetchSliceZ(iSliceIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+ float32 fDataValue = pDataProjection->getDataConst()[iDetectorIndex];
+
+ fThisValue += fDataValue;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnSliceZ(iSliceIndex, pThisProjection);
+
+ delete pThisProjection;
+ delete pDataProjection;
+ }
+
+ return *this;
+}
+
+CFloat32VolumeData3D& CFloat32VolumeData3D::operator-=(const CFloat32VolumeData3D& _data)
+{
+ CVolumeGeometry3D * pThisGeometry = getGeometry();
+
+ int iSliceCount = pThisGeometry->getGridSliceCount();
+#ifdef _DEBUG
+ CVolumeGeometry3D * pDataGeometry = _data.getGeometry();
+ int iThisSlicePixelCount = pThisGeometry->getGridRowCount() * pThisGeometry->getGridColCount();
+ int iDataSlicePixelCount = pDataGeometry->getGridRowCount() * pDataGeometry->getGridColCount();
+
+ ASTRA_ASSERT(iSliceCount == pDataGeometry->getGridSliceCount());
+ ASTRA_ASSERT(iThisSlicePixelCount == iDataSlicePixelCount);
+#endif
+
+ for(int iSliceIndex = 0; iSliceIndex < iSliceCount; iSliceIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchSliceZ(iSliceIndex);
+ CFloat32VolumeData2D * pDataProjection = _data.fetchSliceZ(iSliceIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+ float32 fDataValue = pDataProjection->getDataConst()[iDetectorIndex];
+
+ fThisValue -= fDataValue;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnSliceZ(iSliceIndex, pThisProjection);
+
+ delete pThisProjection;
+ delete pDataProjection;
+ }
+
+ return *this;
+}
+
+CFloat32VolumeData3D& CFloat32VolumeData3D::operator*=(const CFloat32VolumeData3D& _data)
+{
+ CVolumeGeometry3D * pThisGeometry = getGeometry();
+
+ int iSliceCount = pThisGeometry->getGridSliceCount();
+#ifdef _DEBUG
+ CVolumeGeometry3D * pDataGeometry = _data.getGeometry();
+ int iThisSlicePixelCount = pThisGeometry->getGridRowCount() * pThisGeometry->getGridColCount();
+ int iDataSlicePixelCount = pDataGeometry->getGridRowCount() * pDataGeometry->getGridColCount();
+
+ ASTRA_ASSERT(iSliceCount == pDataGeometry->getGridSliceCount());
+ ASTRA_ASSERT(iThisSlicePixelCount == iDataSlicePixelCount);
+#endif
+
+ for(int iSliceIndex = 0; iSliceIndex < iSliceCount; iSliceIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchSliceZ(iSliceIndex);
+ CFloat32VolumeData2D * pDataProjection = _data.fetchSliceZ(iSliceIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+ float32 fDataValue = pDataProjection->getDataConst()[iDetectorIndex];
+
+ fThisValue *= fDataValue;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnSliceZ(iSliceIndex, pThisProjection);
+
+ delete pThisProjection;
+ delete pDataProjection;
+ }
+
+ return *this;
+}
+
+CFloat32VolumeData3D& CFloat32VolumeData3D::operator*=(const float32& _fScalar)
+{
+ CVolumeGeometry3D * pThisGeometry = getGeometry();
+
+ int iSliceCount = pThisGeometry->getGridSliceCount();
+
+ for(int iSliceIndex = 0; iSliceIndex < iSliceCount; iSliceIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchSliceZ(iSliceIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+
+ fThisValue *= _fScalar;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnSliceZ(iSliceIndex, pThisProjection);
+
+ delete pThisProjection;
+ }
+
+ return *this;
+}
+
+CFloat32VolumeData3D& CFloat32VolumeData3D::operator/=(const float32& _fScalar)
+{
+ CVolumeGeometry3D * pThisGeometry = getGeometry();
+
+ int iSliceCount = pThisGeometry->getGridSliceCount();
+
+ for(int iSliceIndex = 0; iSliceIndex < iSliceCount; iSliceIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchSliceZ(iSliceIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+
+ fThisValue /= _fScalar;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnSliceZ(iSliceIndex, pThisProjection);
+
+ delete pThisProjection;
+ }
+
+ return *this;
+}
+
+CFloat32VolumeData3D& CFloat32VolumeData3D::operator+=(const float32& _fScalar)
+{
+ CVolumeGeometry3D * pThisGeometry = getGeometry();
+
+ int iSliceCount = pThisGeometry->getGridSliceCount();
+
+ for(int iSliceIndex = 0; iSliceIndex < iSliceCount; iSliceIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchSliceZ(iSliceIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+
+ fThisValue += _fScalar;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnSliceZ(iSliceIndex, pThisProjection);
+
+ delete pThisProjection;
+ }
+
+ return *this;
+}
+
+CFloat32VolumeData3D& CFloat32VolumeData3D::operator-=(const float32& _fScalar)
+{
+ CVolumeGeometry3D * pThisGeometry = getGeometry();
+
+ int iSliceCount = pThisGeometry->getGridSliceCount();
+
+ for(int iSliceIndex = 0; iSliceIndex < iSliceCount; iSliceIndex++)
+ {
+ CFloat32VolumeData2D * pThisProjection = fetchSliceZ(iSliceIndex);
+
+ for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++)
+ {
+ float32 fThisValue = pThisProjection->getData()[iDetectorIndex];
+
+ fThisValue -= _fScalar;
+
+ pThisProjection->getData()[iDetectorIndex] = fThisValue;
+ }
+
+ returnSliceZ(iSliceIndex, pThisProjection);
+
+ delete pThisProjection;
+ }
+
+ return *this;
+}
+
+} // end namespace astra
diff --git a/src/Float32VolumeData3DMemory.cpp b/src/Float32VolumeData3DMemory.cpp
new file mode 100644
index 0000000..aa3832b
--- /dev/null
+++ b/src/Float32VolumeData3DMemory.cpp
@@ -0,0 +1,208 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Float32VolumeData3DMemory.h"
+
+#include <cstring>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor
+CFloat32VolumeData3DMemory::CFloat32VolumeData3DMemory() :
+ CFloat32Data3DMemory()
+{
+ m_pGeometry = NULL;
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32VolumeData2D class, allocating (but not initializing) the data block.
+CFloat32VolumeData3DMemory::CFloat32VolumeData3DMemory(CVolumeGeometry3D* _pGeometry)
+{
+ m_bInitialized = false;
+ m_bInitialized = initialize(_pGeometry);
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32VolumeData2D class with initialization of the data.
+CFloat32VolumeData3DMemory::CFloat32VolumeData3DMemory(CVolumeGeometry3D* _pGeometry, const float32* _pfData)
+{
+ m_bInitialized = false;
+ m_bInitialized = initialize(_pGeometry, _pfData);
+}
+
+//----------------------------------------------------------------------------------------
+// Create an instance of the CFloat32VolumeData2D class with initialization of the data.
+CFloat32VolumeData3DMemory::CFloat32VolumeData3DMemory(CVolumeGeometry3D* _pGeometry, float32 _fScalar)
+{
+ m_bInitialized = false;
+ m_bInitialized = initialize(_pGeometry, _fScalar);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CFloat32VolumeData3DMemory::~CFloat32VolumeData3DMemory()
+{
+ if(m_pGeometry){
+ delete m_pGeometry;
+ }
+ m_pGeometry = 0;
+
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32VolumeData3DMemory::initialize(CVolumeGeometry3D* _pGeometry)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getGridColCount(), m_pGeometry->getGridRowCount(), m_pGeometry->getGridSliceCount());
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32VolumeData3DMemory::initialize(CVolumeGeometry3D* _pGeometry, const float32* _pfData)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getGridColCount(), m_pGeometry->getGridRowCount(), m_pGeometry->getGridSliceCount(), _pfData);
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization
+bool CFloat32VolumeData3DMemory::initialize(CVolumeGeometry3D* _pGeometry, float32 _fScalar)
+{
+ m_pGeometry = _pGeometry->clone();
+ m_bInitialized = _initialize(m_pGeometry->getGridColCount(), m_pGeometry->getGridRowCount(), m_pGeometry->getGridSliceCount(), _fScalar);
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Fetch a slice
+CFloat32VolumeData2D * CFloat32VolumeData3DMemory::fetchSliceZ(int _iSliceIndex) const
+{
+ // fetch slice of the geometry
+ int iRowCount = m_pGeometry->getGridRowCount();
+ int iColumnCount = m_pGeometry->getGridColCount();
+ CVolumeGeometry2D volGeom(iColumnCount, iRowCount);
+
+ // create new volume data
+ CFloat32VolumeData2D* res = new CFloat32VolumeData2D(&volGeom);
+
+ // copy data
+ int iSliceCount = m_pGeometry->getGridSliceCount();
+ float * pfTargetData = res->getData();
+ for(int iRowIndex = 0; iRowIndex < iRowCount; iRowIndex++)
+ {
+ for(int iColumnIndex = 0; iColumnIndex < iColumnCount; iColumnIndex++)
+ {
+ int iSourceIndex = _iSliceIndex * iColumnCount * iRowCount + iRowIndex * iColumnCount + iColumnIndex;
+ int iTargetIndex = iRowIndex * iColumnCount + iColumnIndex;
+ float fStoredValue = m_pfData[iSourceIndex];
+ pfTargetData[iTargetIndex] = fStoredValue;
+ }
+ }
+ // return
+ return res;
+}
+
+//----------------------------------------------------------------------------------------
+// Return a slice
+void CFloat32VolumeData3DMemory::returnSliceZ(int _iSliceIndex, CFloat32VolumeData2D * _pSlice)
+{
+ int iRowCount = _pSlice->getGeometry()->getGridRowCount();
+ int iColumnCount = _pSlice->getGeometry()->getGridColCount();
+
+ assert(iRowCount == m_pGeometry->getGridRowCount());
+ assert(iColumnCount == m_pGeometry->getGridColCount());
+
+ for(int iRowIndex = 0; iRowIndex < iRowCount; iRowIndex++)
+ {
+ for(int iColumnIndex = 0; iColumnIndex < iColumnCount; iColumnIndex++)
+ {
+ int iSourceIndex = iRowIndex * iColumnCount + iColumnIndex;
+ int iTargetIndex = _iSliceIndex * iColumnCount * iRowCount + iRowIndex * iColumnCount + iColumnIndex;
+ float fStoredValue = _pSlice->getDataConst()[iSourceIndex];
+ m_pfData[iTargetIndex] = fStoredValue;
+ }
+ }
+}
+
+CFloat32VolumeData2D * CFloat32VolumeData3DMemory::fetchSliceX(int _iColumnIndex) const
+{
+ // TODO:
+ assert(false);
+ return NULL;
+}
+
+CFloat32VolumeData2D * CFloat32VolumeData3DMemory::fetchSliceY(int _iRowIndex) const
+{
+ // TODO:
+ assert(false);
+ return NULL;
+}
+
+void CFloat32VolumeData3DMemory::returnSliceX(int _iColumnIndex, CFloat32VolumeData2D * _pSliceData)
+{
+ // TODO:
+ assert(false);
+}
+
+void CFloat32VolumeData3DMemory::returnSliceY(int _iRowIndex, CFloat32VolumeData2D * _pSliceData)
+{
+ // TODO:
+ assert(false);
+}
+
+//----------------------------------------------------------------------------------------
+// Returns a specific value
+float32 CFloat32VolumeData3DMemory::getVoxelValue(int _iIndex)
+{
+ return m_pfData[_iIndex];
+}
+
+//----------------------------------------------------------------------------------------
+// Sets a specific value
+void CFloat32VolumeData3DMemory::setVoxelValue(int _iIndex, float32 _fValue)
+{
+ m_pfData[_iIndex] = _fValue;
+}
+//----------------------------------------------------------------------------------------
+
+CFloat32VolumeData3DMemory& CFloat32VolumeData3DMemory::operator=(const CFloat32VolumeData3DMemory& _dataIn)
+{
+ memcpy(m_pfData, _dataIn.m_pfData, sizeof(float32) * _dataIn.m_pGeometry->getGridTotCount());
+
+ return *this;
+}
+
+} // end namespace astra
diff --git a/src/ForwardProjectionAlgorithm.cpp b/src/ForwardProjectionAlgorithm.cpp
new file mode 100644
index 0000000..970d5b0
--- /dev/null
+++ b/src/ForwardProjectionAlgorithm.cpp
@@ -0,0 +1,280 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ForwardProjectionAlgorithm.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+
+namespace astra {
+
+#include "astra/Projector2DImpl.inl"
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CForwardProjectionAlgorithm::type = "FP";
+
+//----------------------------------------------------------------------------------------
+// Constructor - Default
+CForwardProjectionAlgorithm::CForwardProjectionAlgorithm()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CForwardProjectionAlgorithm::CForwardProjectionAlgorithm(CProjector2D* _pProjector, CFloat32VolumeData2D* _pVolume, CFloat32ProjectionData2D* _pSinogram)
+{
+ _clear();
+ initialize(_pProjector, _pVolume, _pSinogram);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CForwardProjectionAlgorithm::~CForwardProjectionAlgorithm()
+{
+ delete m_pForwardProjector;
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CForwardProjectionAlgorithm::_clear()
+{
+ m_pProjector = NULL;
+ m_pSinogram = NULL;
+ m_pVolume = NULL;
+ m_pForwardProjector = NULL;
+ m_bUseSinogramMask = false;
+ m_bUseVolumeMask = false;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CForwardProjectionAlgorithm::clear()
+{
+ m_pProjector = NULL;
+ m_pSinogram = NULL;
+ m_pVolume = NULL;
+ m_bUseSinogramMask = false;
+ m_bUseVolumeMask = false;
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CForwardProjectionAlgorithm::_check()
+{
+ // check pointers
+ ASTRA_CONFIG_CHECK(m_pProjector, "ForwardProjection", "Invalid Projector Object.");
+ ASTRA_CONFIG_CHECK(m_pSinogram, "ForwardProjection", "Invalid Projection Data Object.");
+ ASTRA_CONFIG_CHECK(m_pVolume, "ForwardProjection", "Invalid Volume Data Object.");
+
+ // check initializations
+ ASTRA_CONFIG_CHECK(m_pProjector->isInitialized(), "ForwardProjection", "Projector Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pSinogram->isInitialized(), "ForwardProjection", "Projection Data Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pVolume->isInitialized(), "ForwardProjection", "Volume Data Object Not Initialized.");
+
+ // check compatibility between projector and data classes
+ ASTRA_CONFIG_CHECK(m_pSinogram->getGeometry()->isEqual(m_pProjector->getProjectionGeometry()), "ForwardProjection", "Projection Data not compatible with the specified Projector.");
+ ASTRA_CONFIG_CHECK(m_pVolume->getGeometry()->isEqual(m_pProjector->getVolumeGeometry()), "ForwardProjection", "Volume Data not compatible with the specified Projector.");
+
+ ASTRA_CONFIG_CHECK(m_pForwardProjector, "ForwardProjection", "Invalid FP Policy");
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CForwardProjectionAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // projector
+ XMLNode* node = _cfg.self->getSingleNode("ProjectorId");
+ ASTRA_CONFIG_CHECK(node, "ForwardProjection", "No ProjectorId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pProjector = CProjector2DManager::getSingleton().get(id);
+ ASTRA_DELETE(node);
+
+ // sinogram data
+ node = _cfg.self->getSingleNode("ProjectionDataId");
+ ASTRA_CONFIG_CHECK(node, "ForwardProjection", "No ProjectionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pSinogram = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+
+ // volume data
+ node = _cfg.self->getSingleNode("VolumeDataId");
+ ASTRA_CONFIG_CHECK(node, "ForwardProjection", "No VolumeDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pVolume = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+
+ // volume mask
+ if (_cfg.self->hasOption("VolumeMaskId")) {
+ m_bUseVolumeMask = true;
+ id = boost::lexical_cast<int>(_cfg.self->getOption("VolumeMaskId"));
+ m_pVolumeMask = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ }
+
+ // sino mask
+ if (_cfg.self->hasOption("SinogramMaskId")) {
+ m_bUseSinogramMask = true;
+ id = boost::lexical_cast<int>(_cfg.self->getOption("SinogramMaskId"));
+ m_pSinogramMask = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ }
+
+ // ray or voxel-driven projector?
+ //m_bUseVoxelProjector = _cfg.self->getOptionBool("VoxelDriven", false);
+
+ // init data projector
+ _init();
+
+ // return success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Get Information - all
+map<string,boost::any> CForwardProjectionAlgorithm::getInformation()
+{
+ map<string, boost::any> result;
+ result["ProjectorId"] = getInformation("ProjectorId");
+ result["ProjectionDataId"] = getInformation("ProjectionDataId");
+ result["VolumeDataId"] = getInformation("VolumeDataId");
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), result);
+};
+
+//---------------------------------------------------------------------------------------
+// Get Information - specific
+boost::any CForwardProjectionAlgorithm::getInformation(std::string _sIdentifier)
+{
+ if (_sIdentifier == "ProjectorId") {
+ int iIndex = CProjector2DManager::getSingleton().getIndex(m_pProjector);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ } else if (_sIdentifier == "ProjectionDataId") {
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pSinogram);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ } else if (_sIdentifier == "VolumeDataId") {
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pVolume);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Initialize
+bool CForwardProjectionAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32VolumeData2D* _pVolume,
+ CFloat32ProjectionData2D* _pSinogram)
+{
+ // store classes
+ m_pProjector = _pProjector;
+ m_pVolume = _pVolume;
+ m_pSinogram = _pSinogram;
+
+ // init data projector
+ _init();
+
+ // return success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize Data Projectors - private
+void CForwardProjectionAlgorithm::_init()
+{
+ // forward projection data projector
+ m_pForwardProjector = dispatchDataProjector(
+ m_pProjector,
+ SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ ReconstructionMaskPolicy(m_pVolumeMask), // reconstruction mask
+ DefaultFPPolicy(m_pVolume, m_pSinogram), // forward projection
+ m_bUseSinogramMask, m_bUseVolumeMask, true // options on/off
+ );
+}
+
+//----------------------------------------------------------------------------------------
+// Set Fixed Reconstruction Mask
+void CForwardProjectionAlgorithm::setVolumeMask(CFloat32VolumeData2D* _pMask, bool _bEnable)
+{
+ // TODO: check geometry matches volume
+ m_bUseVolumeMask = _bEnable;
+ m_pVolumeMask = _pMask;
+ if (m_pVolumeMask == NULL) {
+ m_bUseVolumeMask = false;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Set Fixed Sinogram Mask
+void CForwardProjectionAlgorithm::setSinogramMask(CFloat32ProjectionData2D* _pMask, bool _bEnable)
+{
+ // TODO: check geometry matches sinogram
+ m_bUseSinogramMask = _bEnable;
+ m_pSinogramMask = _pMask;
+ if (m_pSinogramMask == NULL) {
+ m_bUseSinogramMask = false;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CForwardProjectionAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ m_pSinogram->setData(0.0f);
+
+// if (m_bUseVoxelProjector) {
+// m_pForwardProjector->projectAllVoxels();
+// } else {
+ m_pForwardProjector->project();
+// }
+
+}
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/Fourier.cpp b/src/Fourier.cpp
new file mode 100644
index 0000000..0f7da28
--- /dev/null
+++ b/src/Fourier.cpp
@@ -0,0 +1,233 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Fourier.h"
+
+namespace astra {
+
+
+void discreteFourierTransform1D(unsigned int iLength,
+ const float32* pfRealIn,
+ const float32* pfImaginaryIn,
+ float32* pfRealOut,
+ float32* pfImaginaryOut,
+ unsigned int iStrideIn,
+ unsigned int iStrideOut,
+ bool inverse)
+{
+ for (unsigned int w = 0; w < iLength; w++)
+ {
+ pfRealOut[iStrideOut*w] = pfImaginaryOut[iStrideOut*w] = 0;
+ for (unsigned int y = 0; y < iLength; y++)
+ {
+ float32 a = 2 * PI * w * y / float32(iLength);
+ if (!inverse)
+ a = -a;
+ float32 ca = cos(a);
+ float32 sa = sin(a);
+ pfRealOut[iStrideOut*w] += pfRealIn[iStrideIn*y] * ca - pfImaginaryIn[iStrideIn*y] * sa;
+ pfImaginaryOut[iStrideOut*w] += pfRealIn[iStrideIn*y] * sa + pfImaginaryIn[iStrideIn*y] * ca;
+ }
+ }
+
+ if (inverse) {
+ for (unsigned int x = 0; x < iLength; ++x) {
+ pfRealOut[iStrideOut*x] /= iLength;
+ pfImaginaryOut[iStrideOut*x] /= iLength;
+ }
+ }
+}
+
+void discreteFourierTransform2D(unsigned int iHeight, unsigned int iWidth,
+ const float32* pfRealIn,
+ const float32* pfImaginaryIn,
+ float32* pfRealOut,
+ float32* pfImaginaryOut,
+ bool inverse)
+{
+ float32* reTemp = new float32[iWidth * iHeight];
+ float32* imTemp = new float32[iWidth * iHeight];
+
+ //calculate the fourier transform of the columns
+ for (unsigned int x = 0; x < iWidth; x++)
+ {
+ discreteFourierTransform1D(iHeight, pfRealIn+x, pfImaginaryIn+x,
+ reTemp+x, imTemp+x,
+ iWidth, iWidth, inverse);
+ }
+
+ //calculate the fourier transform of the rows
+ for(unsigned int y = 0; y < iHeight; y++)
+ {
+ discreteFourierTransform1D(iWidth,
+ reTemp+y*iWidth,
+ imTemp+y*iWidth,
+ pfRealOut+y*iWidth,
+ pfImaginaryOut+y*iWidth,
+ 1, 1, inverse);
+ }
+
+ delete[] reTemp;
+ delete[] imTemp;
+}
+
+/** permute the entries from pfDataIn into pfDataOut to prepare for an
+ * in-place FFT. pfDataIn may be equal to pfDataOut.
+ */
+static void bitReverse(unsigned int iLength,
+ const float32* pfDataIn, float32* pfDataOut,
+ unsigned int iStrideShiftIn,
+ unsigned int iStrideShiftOut)
+{
+ if (pfDataIn == pfDataOut) {
+ assert(iStrideShiftIn == iStrideShiftOut);
+ float32 t;
+ unsigned int j = 0;
+ for(unsigned int i = 0; i < iLength - 1; i++) {
+ if (i < j) {
+ t = pfDataOut[i<<iStrideShiftOut];
+ pfDataOut[i<<iStrideShiftOut] = pfDataOut[j<<iStrideShiftOut];
+ pfDataOut[j<<iStrideShiftOut] = t;
+ }
+ unsigned int k = iLength / 2;
+ while (k <= j) {
+ j -= k;
+ k /= 2;
+ }
+ j += k;
+ }
+ } else {
+ unsigned int j = 0;
+ for(unsigned int i = 0; i < iLength - 1; i++) {
+ pfDataOut[i<<iStrideShiftOut] = pfDataIn[j<<iStrideShiftIn];
+ unsigned int k = iLength / 2;
+ while (k <= j) {
+ j -= k;
+ k /= 2;
+ }
+ j += k;
+ }
+ pfDataOut[(iLength-1)<<iStrideShiftOut] = pfDataIn[(iLength-1)<<iStrideShiftOut];
+ }
+}
+
+static unsigned int log2(unsigned int n)
+{
+ unsigned int l = 0;
+ while (n > 1) {
+ n /= 2;
+ ++l;
+ }
+ return l;
+}
+
+/** perform 1D FFT. iLength, iStrideIn, iStrideOut must be powers of two. */
+void fastTwoPowerFourierTransform1D(unsigned int iLength,
+ const float32* pfRealIn,
+ const float32* pfImaginaryIn,
+ float32* pfRealOut,
+ float32* pfImaginaryOut,
+ unsigned int iStrideIn,
+ unsigned int iStrideOut,
+ bool inverse)
+{
+ unsigned int iStrideShiftIn = log2(iStrideIn);
+ unsigned int iStrideShiftOut = log2(iStrideOut);
+ unsigned int iLogLength = log2(iLength);
+
+ bitReverse(iLength, pfRealIn, pfRealOut, iStrideShiftIn, iStrideShiftOut);
+ bitReverse(iLength, pfImaginaryIn, pfImaginaryOut, iStrideShiftIn, iStrideShiftOut);
+
+ float32 ca = -1.0;
+ float32 sa = 0.0;
+ unsigned int l1 = 1, l2 = 1;
+ for(unsigned int l=0; l < iLogLength; ++l)
+ {
+ l1 = l2;
+ l2 *= 2;
+ float32 u1 = 1.0;
+ float32 u2 = 0.0;
+ for(unsigned int j = 0; j < l1; j++)
+ {
+ for(unsigned int i = j; i < iLength; i += l2)
+ {
+ unsigned int i1 = i + l1;
+ float32 t1 = u1 * pfRealOut[i1<<iStrideShiftOut] - u2 * pfImaginaryOut[i1<<iStrideShiftOut];
+ float32 t2 = u1 * pfImaginaryOut[i1<<iStrideShiftOut] + u2 * pfRealOut[i1<<iStrideShiftOut];
+ pfRealOut[i1<<iStrideShiftOut] = pfRealOut[i<<iStrideShiftOut] - t1;
+ pfImaginaryOut[i1<<iStrideShiftOut] = pfImaginaryOut[i<<iStrideShiftOut] - t2;
+ pfRealOut[i<<iStrideShiftOut] += t1;
+ pfImaginaryOut[i<<iStrideShiftOut] += t2;
+ }
+ float32 z = u1 * ca - u2 * sa;
+ u2 = u1 * sa + u2 * ca;
+ u1 = z;
+ }
+ sa = sqrt((1.0 - ca) / 2.0);
+ if (!inverse)
+ sa = -sa;
+ ca = sqrt((1.0 + ca) / 2.0);
+ }
+
+ if (inverse) {
+ for (unsigned int i = 0; i < iLength; ++i) {
+ pfRealOut[i<<iStrideShiftOut] /= iLength;
+ pfImaginaryOut[i<<iStrideShiftOut] /= iLength;
+ }
+ }
+}
+
+void fastTwoPowerFourierTransform2D(unsigned int iHeight,
+ unsigned int iWidth,
+ const float32* pfRealIn,
+ const float32* pfImaginaryIn,
+ float32* pfRealOut,
+ float32* pfImaginaryOut,
+ bool inverse)
+{
+ //calculate the fourier transform of the columns
+ for (unsigned int x = 0; x < iWidth; x++)
+ {
+ fastTwoPowerFourierTransform1D(iHeight, pfRealIn+x, pfImaginaryIn+x,
+ pfRealOut+x, pfImaginaryOut+x,
+ iWidth, iWidth, inverse);
+ }
+
+ //calculate the fourier transform of the rows
+ for (unsigned int y = 0; y < iHeight; y++)
+ {
+ fastTwoPowerFourierTransform1D(iWidth,
+ pfRealOut+y*iWidth,
+ pfImaginaryOut+y*iWidth,
+ pfRealOut+y*iWidth,
+ pfImaginaryOut+y*iWidth,
+ 1, 1, inverse);
+ }
+}
+
+}
diff --git a/src/Globals.cpp b/src/Globals.cpp
new file mode 100644
index 0000000..7f93fae
--- /dev/null
+++ b/src/Globals.cpp
@@ -0,0 +1,32 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Globals.h"
+
+// nothing to see here :)
+
diff --git a/src/Logger.cpp b/src/Logger.cpp
new file mode 100644
index 0000000..28368b2
--- /dev/null
+++ b/src/Logger.cpp
@@ -0,0 +1,77 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include <astra/Logger.h>
+
+using namespace astra;
+
+const char * g_loggerFileName = "astra_logger.txt";
+
+void CLogger::_assureIsInitialized()
+{
+ if(!m_bInitialized)
+ {
+ m_pOutFile = fopen(g_loggerFileName, "r");
+ if(m_pOutFile != NULL)
+ {
+ // file exists, users wants to log
+ fclose(m_pOutFile);
+ m_pOutFile = fopen(g_loggerFileName, "w");
+ }
+
+ m_bInitialized = true;
+ }
+}
+
+void CLogger::writeLine(const char * _text)
+{
+ _assureIsInitialized();
+
+ if(m_pOutFile != NULL)
+ {
+ fprintf(m_pOutFile, "%s\n", _text);
+ fflush(m_pOutFile);
+ }
+}
+
+void CLogger::writeTerminalCUDAError(const char * _fileName, int _iLine, const char * _errString)
+{
+ char buffer[256];
+
+ sprintf(buffer, "Cuda error in file '%s' in line %i : %s.", _fileName, _iLine, _errString);
+
+ writeLine(buffer);
+}
+
+CLogger::CLogger()
+{
+ ;
+}
+
+FILE * CLogger::m_pOutFile = NULL;
+bool CLogger::m_bInitialized = false;
diff --git a/src/ParallelBeamBlobKernelProjector2D.cpp b/src/ParallelBeamBlobKernelProjector2D.cpp
new file mode 100644
index 0000000..e08f616
--- /dev/null
+++ b/src/ParallelBeamBlobKernelProjector2D.cpp
@@ -0,0 +1,271 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ParallelBeamBlobKernelProjector2D.h"
+
+#include <cmath>
+#include <boost/lexical_cast.hpp>
+
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+using namespace astra;
+
+#include "astra/ParallelBeamBlobKernelProjector2D.inl"
+
+// type of the projector, needed to register with CProjectorFactory
+std::string CParallelBeamBlobKernelProjector2D::type = "blob";
+
+//----------------------------------------------------------------------------------------
+// default constructor
+CParallelBeamBlobKernelProjector2D::CParallelBeamBlobKernelProjector2D()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// constructor
+CParallelBeamBlobKernelProjector2D::CParallelBeamBlobKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry,
+ float32 _fBlobSize,
+ float32 _fBlobSampleRate,
+ int _iBlobSampleCount,
+ float32* _pfBlobValues)
+{
+ _clear();
+ initialize(_pProjectionGeometry, _pReconstructionGeometry, _fBlobSize, _fBlobSampleRate, _iBlobSampleCount, _pfBlobValues);
+}
+
+//----------------------------------------------------------------------------------------
+// destructor
+CParallelBeamBlobKernelProjector2D::~CParallelBeamBlobKernelProjector2D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CParallelBeamBlobKernelProjector2D::_clear()
+{
+ CProjector2D::_clear();
+ m_pfBlobValues = NULL;
+ m_iBlobSampleCount = 0;
+ m_fBlobSize = 0;
+ m_fBlobSampleRate = 0;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CParallelBeamBlobKernelProjector2D::clear()
+{
+ CProjector2D::clear();
+ if (m_pfBlobValues) {
+ delete[] m_pfBlobValues;
+ m_pfBlobValues = NULL;
+ }
+ m_iBlobSampleCount = 0;
+ m_fBlobSize = 0;
+ m_fBlobSampleRate = 0;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CParallelBeamBlobKernelProjector2D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CProjector2D::_check(), "ParallelBeamBlobKernelProjector2D", "Error in Projector2D initialization");
+
+ ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamBlobKernelProjector2D", "Unsupported projection geometry");
+
+ ASTRA_CONFIG_CHECK(m_iBlobSampleCount > 0, "ParallelBeamBlobKernelProjector2D", "m_iBlobSampleCount should be strictly positive.");
+ ASTRA_CONFIG_CHECK(m_pfBlobValues, "ParallelBeamBlobKernelProjector2D", "Invalid Volume Geometry Object.");
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CParallelBeamBlobKernelProjector2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CProjector2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // required: Kernel
+ XMLNode* node = _cfg.self->getSingleNode("Kernel");
+ ASTRA_CONFIG_CHECK(node, "BlobProjector", "No Kernel tag specified.");
+ {
+ // Required: KernelSize
+ XMLNode* node2 = node->getSingleNode("KernelSize");
+ ASTRA_CONFIG_CHECK(node2, "BlobProjector", "No Kernel/KernelSize tag specified.");
+ m_fBlobSize = boost::lexical_cast<float32>(node2->getContent());
+
+ // Required: SampleRate
+ node2 = node->getSingleNode("SampleRate");
+ ASTRA_CONFIG_CHECK(node2, "BlobProjector", "No Kernel/SampleRate tag specified.");
+ m_fBlobSampleRate = boost::lexical_cast<float32>(node2->getContent());
+
+ // Required: SampleCount
+ node2 = node->getSingleNode("SampleCount");
+ ASTRA_CONFIG_CHECK(node2, "BlobProjector", "No Kernel/SampleCount tag specified.");
+ m_iBlobSampleCount = boost::lexical_cast<int>(node2->getContent());
+
+ // Required: KernelValues
+ node2 = node->getSingleNode("KernelValues");
+ ASTRA_CONFIG_CHECK(node2, "BlobProjector", "No Kernel/KernelValues tag specified.");
+ vector<float32> values = node2->getContentNumericalArray();
+ ASTRA_CONFIG_CHECK(values.size() == (unsigned int)m_iBlobSampleCount, "BlobProjector", "Number of specified values doesn't match SampleCount.");
+ m_pfBlobValues = new float32[m_iBlobSampleCount];
+ for (int i = 0; i < m_iBlobSampleCount; i++) {
+ m_pfBlobValues[i] = values[i];
+ }
+
+ // Required: KernelValues
+ node2 = node->getSingleNode("KernelValuesNeg");
+ ASTRA_CONFIG_CHECK(node2, "BlobProjector", "No Kernel/KernelValuesNeg tag specified.");
+ vector<float32> values2 = node2->getContentNumericalArray();
+ ASTRA_CONFIG_CHECK(values2.size() == (unsigned int)m_iBlobSampleCount, "BlobProjector", "Number of specified values doesn't match SampleCount.");
+ m_pfBlobValuesNeg = new float32[m_iBlobSampleCount];
+ for (int i = 0; i < m_iBlobSampleCount; i++) {
+ m_pfBlobValuesNeg[i] = values2[i];
+ }
+
+ }
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// initialize
+bool CParallelBeamBlobKernelProjector2D::initialize(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pVolumeGeometry,
+ float32 _fBlobSize,
+ float32 _fBlobSampleRate,
+ int _iBlobSampleCount,
+ float32* _pfBlobValues)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ ASTRA_CONFIG_CHECK(_pProjectionGeometry, "BlobProjector", "Invalid ProjectionGeometry Object");
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry, "BlobProjector", "Invalid ProjectionGeometry Object");
+ m_pProjectionGeometry = _pProjectionGeometry->clone();
+ m_pVolumeGeometry = _pVolumeGeometry->clone();
+ m_fBlobSize = _fBlobSize;
+ m_fBlobSampleRate = _fBlobSampleRate;
+ m_iBlobSampleCount = _iBlobSampleCount;
+ m_pfBlobValues = new float32[_iBlobSampleCount];
+ for (int i = 0; i <_iBlobSampleCount; i++) {
+ m_pfBlobValues[i] = _pfBlobValues[i];
+ }
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Get maximum amount of weights on a single ray
+int CParallelBeamBlobKernelProjector2D::getProjectionWeightsCount(int _iProjectionIndex)
+{
+ int maxDim = max(m_pVolumeGeometry->getGridRowCount(), m_pVolumeGeometry->getGridColCount());
+ return (int)(maxDim * 2 * (m_fBlobSize+2) + 1);
+}
+//----------------------------------------------------------------------------------------
+// Single Ray Weights
+void CParallelBeamBlobKernelProjector2D::computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+ StorePixelWeightsPolicy p(_pWeightedPixels, _iMaxPixelCount);
+ projectSingleRay(_iProjectionIndex, _iDetectorIndex, p);
+ _iStoredPixelCount = p.getStoredPixelCount();
+}
+//----------------------------------------------------------------------------------------
+// Splat a single point
+std::vector<SDetector2D> CParallelBeamBlobKernelProjector2D::projectPoint(int _iRow, int _iCol)
+{
+ float32 x = m_pVolumeGeometry->pixelColToCenterX(_iCol);
+ float32 y = m_pVolumeGeometry->pixelRowToCenterY(_iRow);
+
+ std::vector<SDetector2D> res;
+ // loop projectors and detectors
+ for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) {
+
+ // get projection angle
+ float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection);
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ bool inverse = false;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ inverse = true;
+ }
+
+ // calculate distance from the center of the voxel to the ray though the origin
+ float32 t = x * cos(theta) + y * sin(theta);
+ if (inverse) t *= -1.0f;
+
+ // calculate the offset on the detectorarray (in indices)
+ float32 d = m_pProjectionGeometry->detectorOffsetToIndexFloat(t);
+ int dmin = (int)ceil(d - m_fBlobSize);
+ int dmax = (int)floor(d + m_fBlobSize);
+
+ // add affected detectors to the list
+ for (int i = dmin; i <= dmax; ++i) {
+ if (d >= 0 && d < m_pProjectionGeometry->getDetectorCount()) {
+ SDetector2D det;
+ det.m_iAngleIndex = iProjection;
+ det.m_iDetectorIndex = i;
+ det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i;
+ res.push_back(det);
+ }
+ }
+ }
+
+ // return result vector
+ return res;
+
+}
diff --git a/src/ParallelBeamLineKernelProjector2D.cpp b/src/ParallelBeamLineKernelProjector2D.cpp
new file mode 100644
index 0000000..16cc614
--- /dev/null
+++ b/src/ParallelBeamLineKernelProjector2D.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ParallelBeamLineKernelProjector2D.h"
+
+#include <cmath>
+#include <boost/lexical_cast.hpp>
+
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+using namespace astra;
+
+#include "astra/ParallelBeamLineKernelProjector2D.inl"
+
+// type of the projector, needed to register with CProjectorFactory
+std::string CParallelBeamLineKernelProjector2D::type = "line";
+
+//----------------------------------------------------------------------------------------
+// default constructor
+CParallelBeamLineKernelProjector2D::CParallelBeamLineKernelProjector2D()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// constructor
+CParallelBeamLineKernelProjector2D::CParallelBeamLineKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry)
+
+{
+ _clear();
+ initialize(_pProjectionGeometry, _pReconstructionGeometry);
+}
+
+//----------------------------------------------------------------------------------------
+// destructor
+CParallelBeamLineKernelProjector2D::~CParallelBeamLineKernelProjector2D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CParallelBeamLineKernelProjector2D::_clear()
+{
+ CProjector2D::_clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CParallelBeamLineKernelProjector2D::clear()
+{
+ CProjector2D::clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CParallelBeamLineKernelProjector2D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CProjector2D::_check(), "ParallelBeamLineKernelProjector2D", "Error in Projector2D initialization");
+
+ ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamLineKernelProjector2D", "Unsupported projection geometry");
+
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "ParallelBeamLineKernelProjector2D", "Pixel height must equal pixel width.");
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CParallelBeamLineKernelProjector2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CProjector2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize
+bool CParallelBeamLineKernelProjector2D::initialize(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pVolumeGeometry)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // hardcopy geometries
+ m_pProjectionGeometry = _pProjectionGeometry->clone();
+ m_pVolumeGeometry = _pVolumeGeometry->clone();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Get maximum amount of weights on a single ray
+int CParallelBeamLineKernelProjector2D::getProjectionWeightsCount(int _iProjectionIndex)
+{
+ int maxDim = max(m_pVolumeGeometry->getGridRowCount(), m_pVolumeGeometry->getGridColCount());
+ return maxDim * 2 + 1;
+}
+
+//----------------------------------------------------------------------------------------
+// Single Ray Weights
+void CParallelBeamLineKernelProjector2D::computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+ StorePixelWeightsPolicy p(_pWeightedPixels, _iMaxPixelCount);
+ projectSingleRay(_iProjectionIndex, _iDetectorIndex, p);
+ _iStoredPixelCount = p.getStoredPixelCount();
+}
+
+//----------------------------------------------------------------------------------------
+// Project Point
+std::vector<SDetector2D> CParallelBeamLineKernelProjector2D::projectPoint(int _iRow, int _iCol)
+{
+ float32 xUL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ float32 yUL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ float32 xUR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ float32 yUR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ float32 xLL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ float32 yLL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ float32 xLR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ float32 yLR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+
+ std::vector<SDetector2D> res;
+ // loop projectors and detectors
+ for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) {
+
+ // get projection angle
+ float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection);
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ bool inverse = false;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ inverse = true;
+ }
+
+ // calculate distance from the center of the voxel to the ray though the origin
+ float32 tUL = xUL * cos(theta) + yUL * sin(theta);
+ float32 tUR = xUR * cos(theta) + yUR * sin(theta);
+ float32 tLL = xLL * cos(theta) + yLL * sin(theta);
+ float32 tLR = xLR * cos(theta) + yLR * sin(theta);
+ if (inverse) {
+ tUL *= -1.0f;
+ tUR *= -1.0f;
+ tLL *= -1.0f;
+ tLR *= -1.0f;
+ }
+ float32 tMin = min(tUL, min(tUR, min(tLL,tLR)));
+ float32 tMax = max(tUL, max(tUR, max(tLL,tLR)));
+
+ // calculate the offset on the detectorarray (in indices)
+ int dmin = (int)floor(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMin));
+ int dmax = (int)ceil(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMax));
+
+ // add affected detectors to the list
+ for (int i = dmin; i <= dmax; ++i) {
+ if (i >= 0 && i < m_pProjectionGeometry->getDetectorCount()) {
+ SDetector2D det;
+ det.m_iAngleIndex = iProjection;
+ det.m_iDetectorIndex = i;
+ det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i;
+ res.push_back(det);
+ }
+ }
+ }
+
+ // return result vector
+ return res;
+
+}
+
+//----------------------------------------------------------------------------------------
diff --git a/src/ParallelBeamLinearKernelProjector2D.cpp b/src/ParallelBeamLinearKernelProjector2D.cpp
new file mode 100644
index 0000000..5f1679d
--- /dev/null
+++ b/src/ParallelBeamLinearKernelProjector2D.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ParallelBeamLinearKernelProjector2D.h"
+
+#include <cmath>
+#include <boost/lexical_cast.hpp>
+
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+using namespace astra;
+
+#include "astra/ParallelBeamLinearKernelProjector2D.inl"
+
+// type of the projector, needed to register with CProjectorFactory
+std::string CParallelBeamLinearKernelProjector2D::type = "linear";
+
+//----------------------------------------------------------------------------------------
+// default constructor
+CParallelBeamLinearKernelProjector2D::CParallelBeamLinearKernelProjector2D()
+{
+ _clear();
+}
+
+
+//----------------------------------------------------------------------------------------
+// constructor
+CParallelBeamLinearKernelProjector2D::CParallelBeamLinearKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry)
+
+{
+ _clear();
+ initialize(_pProjectionGeometry, _pReconstructionGeometry);
+}
+
+//----------------------------------------------------------------------------------------
+// destructor
+CParallelBeamLinearKernelProjector2D::~CParallelBeamLinearKernelProjector2D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - CParallelBeamLinearKernelProjector2D
+void CParallelBeamLinearKernelProjector2D::_clear()
+{
+ CProjector2D::_clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CParallelBeamLinearKernelProjector2D::clear()
+{
+ CProjector2D::clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CParallelBeamLinearKernelProjector2D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CProjector2D::_check(), "ParallelBeamLinearKernelProjector2D", "Error in Projector2D initialization");
+
+ ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamLinearKernelProjector2D", "Unsupported projection geometry");
+
+ /// TODO: ADD PIXEL H/W LIMITATIONS
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "ParallelBeamLinearKernelProjector2D", "Pixel height must equal pixel width.");
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CParallelBeamLinearKernelProjector2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CProjector2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize
+bool CParallelBeamLinearKernelProjector2D::initialize(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pVolumeGeometry)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // hardcopy geometries
+ m_pProjectionGeometry = _pProjectionGeometry->clone();
+ m_pVolumeGeometry = _pVolumeGeometry->clone();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Get maximum amount of weights on a single ray
+int CParallelBeamLinearKernelProjector2D::getProjectionWeightsCount(int _iProjectionIndex)
+{
+ int maxDim = max(m_pVolumeGeometry->getGridRowCount(), m_pVolumeGeometry->getGridColCount());
+ return maxDim * 2 + 1;
+}
+
+//----------------------------------------------------------------------------------------
+// Single Ray Weights
+void CParallelBeamLinearKernelProjector2D::computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+ StorePixelWeightsPolicy p(_pWeightedPixels, _iMaxPixelCount);
+ projectSingleRay(_iProjectionIndex, _iDetectorIndex, p);
+ _iStoredPixelCount = p.getStoredPixelCount();
+}
+
+//----------------------------------------------------------------------------------------
+// Splat a single point
+std::vector<SDetector2D> CParallelBeamLinearKernelProjector2D::projectPoint(int _iRow, int _iCol)
+{
+ float32 xUL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 1.5f;
+ float32 yUL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 1.5f;
+ float32 xUR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 1.5f;
+ float32 yUR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 1.5f;
+ float32 xLL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 1.5f;
+ float32 yLL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 1.5f;
+ float32 xLR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 1.5f;
+ float32 yLR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 1.5f;
+
+ std::vector<SDetector2D> res;
+ // loop projectors and detectors
+ for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) {
+
+ // get projection angle
+ float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection);
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ bool inverse = false;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ inverse = true;
+ }
+
+ // calculate distance from the center of the voxel to the ray though the origin
+ float32 tUL = xUL * cos(theta) + yUL * sin(theta);
+ float32 tUR = xUR * cos(theta) + yUR * sin(theta);
+ float32 tLL = xLL * cos(theta) + yLL * sin(theta);
+ float32 tLR = xLR * cos(theta) + yLR * sin(theta);
+ if (inverse) {
+ tUL *= -1.0f;
+ tUR *= -1.0f;
+ tLL *= -1.0f;
+ tLR *= -1.0f;
+ }
+ float32 tMin = min(tUL, min(tUR, min(tLL,tLR)));
+ float32 tMax = max(tUL, max(tUR, max(tLL,tLR)));
+
+ // calculate the offset on the detectorarray (in indices)
+ int dmin = (int)floor(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMin));
+ int dmax = (int)ceil(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMax));
+
+ // add affected detectors to the list
+ for (int i = dmin; i <= dmax; ++i) {
+ if (i >= 0 && i < m_pProjectionGeometry->getDetectorCount()) {
+ SDetector2D det;
+ det.m_iAngleIndex = iProjection;
+ det.m_iDetectorIndex = i;
+ det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i;
+ res.push_back(det);
+ }
+ }
+ }
+
+ // return result vector
+ return res;
+
+}
diff --git a/src/ParallelBeamStripKernelProjector2D.cpp b/src/ParallelBeamStripKernelProjector2D.cpp
new file mode 100644
index 0000000..78997af
--- /dev/null
+++ b/src/ParallelBeamStripKernelProjector2D.cpp
@@ -0,0 +1,224 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ParallelBeamStripKernelProjector2D.h"
+
+#include <cmath>
+#include <boost/lexical_cast.hpp>
+
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+using namespace astra;
+
+#include "astra/ParallelBeamStripKernelProjector2D.inl"
+
+// type of the projector, needed to register with CProjectorFactory
+std::string CParallelBeamStripKernelProjector2D::type = "strip";
+
+//----------------------------------------------------------------------------------------
+// default constructor
+CParallelBeamStripKernelProjector2D::CParallelBeamStripKernelProjector2D()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// constructor
+CParallelBeamStripKernelProjector2D::CParallelBeamStripKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry)
+
+{
+ _clear();
+ initialize(_pProjectionGeometry, _pReconstructionGeometry);
+}
+
+//----------------------------------------------------------------------------------------
+// destructor
+CParallelBeamStripKernelProjector2D::~CParallelBeamStripKernelProjector2D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CParallelBeamStripKernelProjector2D::_clear()
+{
+ CProjector2D::_clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CParallelBeamStripKernelProjector2D::clear()
+{
+ CProjector2D::clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CParallelBeamStripKernelProjector2D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CProjector2D::_check(), "ParallelBeamStripKernelProjector2D", "Error in Projector2D initialization");
+
+ ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamStripKernelProjector2D", "Unsupported projection geometry");
+
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "ParallelBeamStripKernelProjector2D", "Pixel height must equal pixel width.");
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CParallelBeamStripKernelProjector2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CProjector2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize
+bool CParallelBeamStripKernelProjector2D::initialize(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pVolumeGeometry)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // hardcopy geometries
+ m_pProjectionGeometry = _pProjectionGeometry->clone();
+ m_pVolumeGeometry = _pVolumeGeometry->clone();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+
+//----------------------------------------------------------------------------------------
+// Get maximum amount of weights on a single ray
+int CParallelBeamStripKernelProjector2D::getProjectionWeightsCount(int _iProjectionIndex)
+{
+ int maxDim = max(m_pVolumeGeometry->getGridRowCount(), m_pVolumeGeometry->getGridColCount());
+ int scale = m_pProjectionGeometry->getDetectorWidth() / min(m_pVolumeGeometry->getPixelLengthX(), m_pVolumeGeometry->getPixelLengthY());
+ return maxDim * scale * 10 + 1;
+}
+
+//----------------------------------------------------------------------------------------
+// Single Ray Weights
+void CParallelBeamStripKernelProjector2D::computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+ StorePixelWeightsPolicy p(_pWeightedPixels, _iMaxPixelCount);
+ projectSingleRay(_iProjectionIndex, _iDetectorIndex, p);
+ _iStoredPixelCount = p.getStoredPixelCount();
+}
+
+//----------------------------------------------------------------------------------------
+// Splat a single point
+std::vector<SDetector2D> CParallelBeamStripKernelProjector2D::projectPoint(int _iRow, int _iCol)
+{
+ float32 xUL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ float32 yUL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ float32 xUR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ float32 yUR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ float32 xLL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ float32 yLL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ float32 xLR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ float32 yLR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+
+ std::vector<SDetector2D> res;
+ // loop projectors and detectors
+ for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) {
+
+ // get projection angle
+ float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection);
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ bool inverse = false;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ inverse = true;
+ }
+
+ // calculate distance from the center of the voxel to the ray though the origin
+ float32 tUL = xUL * cos(theta) + yUL * sin(theta);
+ float32 tUR = xUR * cos(theta) + yUR * sin(theta);
+ float32 tLL = xLL * cos(theta) + yLL * sin(theta);
+ float32 tLR = xLR * cos(theta) + yLR * sin(theta);
+ if (inverse) {
+ tUL *= -1.0f;
+ tUR *= -1.0f;
+ tLL *= -1.0f;
+ tLR *= -1.0f;
+ }
+ float32 tMin = min(tUL, min(tUR, min(tLL,tLR)));
+ float32 tMax = max(tUL, max(tUR, max(tLL,tLR)));
+
+ // calculate the offset on the detectorarray (in indices)
+ int dmin = (int)floor(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMin));
+ int dmax = (int)ceil(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMax));
+
+ // add affected detectors to the list
+ for (int i = dmin; i <= dmax; ++i) {
+ if (i >= 0 && i < m_pProjectionGeometry->getDetectorCount()) {
+ SDetector2D det;
+ det.m_iAngleIndex = iProjection;
+ det.m_iDetectorIndex = i;
+ det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i;
+ res.push_back(det);
+ }
+ }
+ }
+
+ // return result vector
+ return res;
+
+}
+
+//----------------------------------------------------------------------------------------
diff --git a/src/ParallelProjectionGeometry2D.cpp b/src/ParallelProjectionGeometry2D.cpp
new file mode 100644
index 0000000..79a325b
--- /dev/null
+++ b/src/ParallelProjectionGeometry2D.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ParallelProjectionGeometry2D.h"
+
+#include <cstring>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CParallelProjectionGeometry2D::CParallelProjectionGeometry2D() :
+ CProjectionGeometry2D()
+{
+
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CParallelProjectionGeometry2D::CParallelProjectionGeometry2D(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsets)
+{
+ _clear();
+ initialize(_iProjectionAngleCount,
+ _iDetectorCount,
+ _fDetectorWidth,
+ _pfProjectionAngles,
+ _pfExtraDetectorOffsets);
+}
+
+//----------------------------------------------------------------------------------------
+CParallelProjectionGeometry2D::CParallelProjectionGeometry2D(const CParallelProjectionGeometry2D& _projGeom)
+{
+ _clear();
+ initialize(_projGeom.m_iProjectionAngleCount,
+ _projGeom.m_iDetectorCount,
+ _projGeom.m_fDetectorWidth,
+ _projGeom.m_pfProjectionAngles,
+ _projGeom.m_pfExtraDetectorOffset);
+}
+
+//----------------------------------------------------------------------------------------
+
+CParallelProjectionGeometry2D& CParallelProjectionGeometry2D::operator=(const CParallelProjectionGeometry2D& _other)
+{
+ if (m_bInitialized)
+ delete[] m_pfProjectionAngles;
+ m_bInitialized = _other.m_bInitialized;
+ if (_other.m_bInitialized) {
+ m_iProjectionAngleCount = _other.m_iProjectionAngleCount;
+ m_iDetectorCount = _other.m_iDetectorCount;
+ m_fDetectorWidth = _other.m_fDetectorWidth;
+ m_pfProjectionAngles = new float32[m_iProjectionAngleCount];
+ memcpy(m_pfProjectionAngles, _other.m_pfProjectionAngles, sizeof(float32)*m_iProjectionAngleCount);
+ }
+ return *this;
+
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CParallelProjectionGeometry2D::~CParallelProjectionGeometry2D()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CParallelProjectionGeometry2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjectionGeometry2D> CC("ParallelProjectionGeometry2D", this, _cfg);
+
+
+ // initialization of parent class
+ CProjectionGeometry2D::initialize(_cfg);
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CParallelProjectionGeometry2D::initialize(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsets)
+{
+ _initialize(_iProjectionAngleCount,
+ _iDetectorCount,
+ _fDetectorWidth,
+ _pfProjectionAngles,
+ _pfExtraDetectorOffsets);
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Clone
+CProjectionGeometry2D* CParallelProjectionGeometry2D::clone()
+{
+ return new CParallelProjectionGeometry2D(*this);
+}
+
+//----------------------------------------------------------------------------------------
+// is equal
+bool CParallelProjectionGeometry2D::isEqual(CProjectionGeometry2D* _pGeom2) const
+{
+ if (_pGeom2 == NULL) return false;
+
+ // try to cast argument to CParallelProjectionGeometry2D
+ CParallelProjectionGeometry2D* pGeom2 = dynamic_cast<CParallelProjectionGeometry2D*>(_pGeom2);
+ if (pGeom2 == NULL) return false;
+
+ // both objects must be initialized
+ if (!m_bInitialized || !pGeom2->m_bInitialized) return false;
+
+ // check all values
+ if (m_iProjectionAngleCount != pGeom2->m_iProjectionAngleCount) return false;
+ if (m_iDetectorCount != pGeom2->m_iDetectorCount) return false;
+ if (m_fDetectorWidth != pGeom2->m_fDetectorWidth) return false;
+
+ for (int i = 0; i < m_iProjectionAngleCount; ++i) {
+ // if (m_pfProjectionAngles[i] != pGeom2->m_pfProjectionAngles[i]) return false;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// is of type
+bool CParallelProjectionGeometry2D::isOfType(const std::string& _sType)
+{
+ return (_sType == "parallel");
+}
+//----------------------------------------------------------------------------------------
+
+CVector3D CParallelProjectionGeometry2D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex /* = 0 */)
+{
+ CVector3D vOutput;
+
+ float32 fProjectionAngle = getProjectionAngle(_iProjectionIndex);
+
+ vOutput.setX(cosf(fProjectionAngle));
+ vOutput.setY(sinf(fProjectionAngle));
+ vOutput.setZ(0.0f);
+
+ return vOutput;
+}
+
+} // end namespace astra
diff --git a/src/ParallelProjectionGeometry3D.cpp b/src/ParallelProjectionGeometry3D.cpp
new file mode 100644
index 0000000..c0366bc
--- /dev/null
+++ b/src/ParallelProjectionGeometry3D.cpp
@@ -0,0 +1,211 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ParallelProjectionGeometry3D.h"
+
+#include <cstring>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CParallelProjectionGeometry3D::CParallelProjectionGeometry3D() :
+ CProjectionGeometry3D()
+{
+
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CParallelProjectionGeometry3D::CParallelProjectionGeometry3D(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorWidth,
+ float32 _fDetectorHeight,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsetsX,
+ const float32* _pfExtraDetectorOffsetsY) :
+ CProjectionGeometry3D()
+{
+ initialize(_iProjectionAngleCount,
+ _iDetectorRowCount,
+ _iDetectorColCount,
+ _fDetectorWidth,
+ _fDetectorHeight,
+ _pfProjectionAngles,
+ _pfExtraDetectorOffsetsX,
+ _pfExtraDetectorOffsetsY);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CParallelProjectionGeometry3D::~CParallelProjectionGeometry3D()
+{
+
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CParallelProjectionGeometry3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjectionGeometry3D> CC("ParallelProjectionGeometry3D", this, _cfg);
+
+
+ // initialization of parent class
+ CProjectionGeometry3D::initialize(_cfg);
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CParallelProjectionGeometry3D::initialize(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorWidth,
+ float32 _fDetectorHeight,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsetsX,
+ const float32* _pfExtraDetectorOffsetsY)
+{
+ _initialize(_iProjectionAngleCount,
+ _iDetectorRowCount,
+ _iDetectorColCount,
+ _fDetectorWidth,
+ _fDetectorHeight,
+ _pfProjectionAngles,
+ _pfExtraDetectorOffsetsX,
+ _pfExtraDetectorOffsetsY);
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Clone
+CProjectionGeometry3D* CParallelProjectionGeometry3D::clone() const
+{
+ CParallelProjectionGeometry3D* res = new CParallelProjectionGeometry3D();
+ res->m_bInitialized = m_bInitialized;
+ res->m_iProjectionAngleCount = m_iProjectionAngleCount;
+ res->m_iDetectorRowCount = m_iDetectorRowCount;
+ res->m_iDetectorColCount = m_iDetectorColCount;
+ res->m_iDetectorTotCount = m_iDetectorTotCount;
+ res->m_fDetectorSpacingX = m_fDetectorSpacingX;
+ res->m_fDetectorSpacingY = m_fDetectorSpacingY;
+ res->m_pfProjectionAngles = new float32[m_iProjectionAngleCount];
+ memcpy(res->m_pfProjectionAngles, m_pfProjectionAngles, sizeof(float32)*m_iProjectionAngleCount);
+ res->m_pfExtraDetectorOffsetsX = new float32[m_iProjectionAngleCount];
+ memcpy(res->m_pfExtraDetectorOffsetsX, m_pfExtraDetectorOffsetsX, sizeof(float32)*m_iProjectionAngleCount);
+ res->m_pfExtraDetectorOffsetsY = new float32[m_iProjectionAngleCount];
+ memcpy(res->m_pfExtraDetectorOffsetsY, m_pfExtraDetectorOffsetsY, sizeof(float32)*m_iProjectionAngleCount);
+ return res;
+}
+
+//----------------------------------------------------------------------------------------
+// is equal
+bool CParallelProjectionGeometry3D::isEqual(const CProjectionGeometry3D * _pGeom2) const
+{
+ if (_pGeom2 == NULL) return false;
+
+ // try to cast argument to CParallelProjectionGeometry3D
+ const CParallelProjectionGeometry3D* pGeom2 = dynamic_cast<const CParallelProjectionGeometry3D*>(_pGeom2);
+ if (pGeom2 == NULL) return false;
+
+ // both objects must be initialized
+ if (!m_bInitialized || !pGeom2->m_bInitialized) return false;
+
+ // check all values
+ if (m_iProjectionAngleCount != pGeom2->m_iProjectionAngleCount) return false;
+ if (m_iDetectorRowCount != pGeom2->m_iDetectorRowCount) return false;
+ if (m_iDetectorColCount != pGeom2->m_iDetectorColCount) return false;
+ if (m_iDetectorTotCount != pGeom2->m_iDetectorTotCount) return false;
+ if (m_fDetectorSpacingX != pGeom2->m_fDetectorSpacingX) return false;
+ if (m_fDetectorSpacingY != pGeom2->m_fDetectorSpacingY) return false;
+
+ for (int i = 0; i < m_iProjectionAngleCount; ++i) {
+ if (m_pfProjectionAngles[i] != pGeom2->m_pfProjectionAngles[i]) return false;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// is of type
+bool CParallelProjectionGeometry3D::isOfType(const std::string& _sType) const
+{
+ return (_sType == "parallel");
+}
+
+//----------------------------------------------------------------------------------------
+void CParallelProjectionGeometry3D::toXML(XMLNode* _sNode) const
+{
+ _sNode->addAttribute("type","parallel3d");
+ _sNode->addChildNode("DetectorSpacingX", m_fDetectorSpacingX);
+ _sNode->addChildNode("DetectorSpacingY", m_fDetectorSpacingY);
+ _sNode->addChildNode("DetectorRowCount", m_iDetectorRowCount);
+ _sNode->addChildNode("DetectorColCount", m_iDetectorColCount);
+ _sNode->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount);
+ _sNode->addChildNode("ExtraDetectorOffsetsX", m_pfExtraDetectorOffsetsX, m_iProjectionAngleCount);
+ _sNode->addChildNode("ExtraDetectorOffsetsY", m_pfExtraDetectorOffsetsY, m_iProjectionAngleCount);
+}
+
+CVector3D CParallelProjectionGeometry3D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const
+{
+ float fTheta = m_pfProjectionAngles[_iProjectionIndex];
+
+ float fDirX = cosf(fTheta);
+ float fDirY = sinf(fTheta);
+ float fDirZ = 0.0f;
+
+ return CVector3D(fDirX, fDirY, fDirZ);
+}
+
+CParallelProjectionGeometry2D * CParallelProjectionGeometry3D::createProjectionGeometry2D() const
+{
+ const float32 * pfProjectionAngles = getProjectionAngles(); //new float32[getProjectionCount()];
+ //getProjectionAngles(pfProjectionAngles);
+
+ CParallelProjectionGeometry2D * pOutput = new CParallelProjectionGeometry2D(getProjectionCount(),
+ getDetectorColCount(), getDetectorSpacingX(), pfProjectionAngles,getExtraDetectorOffsetsX());
+
+ //delete [] pfProjectionAngles;
+
+ return pOutput;
+}
+
+//----------------------------------------------------------------------------------------
+
+} // end namespace astra
diff --git a/src/ParallelVecProjectionGeometry3D.cpp b/src/ParallelVecProjectionGeometry3D.cpp
new file mode 100644
index 0000000..c1265dd
--- /dev/null
+++ b/src/ParallelVecProjectionGeometry3D.cpp
@@ -0,0 +1,230 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ParallelVecProjectionGeometry3D.h"
+
+#include <cstring>
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CParallelVecProjectionGeometry3D::CParallelVecProjectionGeometry3D() :
+ CProjectionGeometry3D()
+{
+ m_pProjectionAngles = 0;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CParallelVecProjectionGeometry3D::CParallelVecProjectionGeometry3D(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ const SPar3DProjection* _pProjectionAngles
+ ) :
+ CProjectionGeometry3D()
+{
+ initialize(_iProjectionAngleCount,
+ _iDetectorRowCount,
+ _iDetectorColCount,
+ _pProjectionAngles);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CParallelVecProjectionGeometry3D::~CParallelVecProjectionGeometry3D()
+{
+ delete[] m_pProjectionAngles;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CParallelVecProjectionGeometry3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjectionGeometry3D> CC("ParallelVecProjectionGeometry3D", this, _cfg);
+
+ XMLNode* node;
+
+ // TODO: Fix up class hierarchy... this class doesn't fit very well.
+ // initialization of parent class
+ //CProjectionGeometry3D::initialize(_cfg);
+
+ // Required: DetectorRowCount
+ node = _cfg.self->getSingleNode("DetectorRowCount");
+ ASTRA_CONFIG_CHECK(node, "ParallelVecProjectionGeometry3D", "No DetectorRowCount tag specified.");
+ m_iDetectorRowCount = boost::lexical_cast<int>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorRowCount");
+
+ // Required: DetectorCount
+ node = _cfg.self->getSingleNode("DetectorColCount");
+ ASTRA_CONFIG_CHECK(node, "", "No DetectorColCount tag specified.");
+ m_iDetectorColCount = boost::lexical_cast<int>(node->getContent());
+ m_iDetectorTotCount = m_iDetectorRowCount * m_iDetectorColCount;
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorColCount");
+
+ // Required: Vectors
+ node = _cfg.self->getSingleNode("Vectors");
+ ASTRA_CONFIG_CHECK(node, "ParallelVecProjectionGeometry3D", "No Vectors tag specified.");
+ vector<double> data = node->getContentNumericalArrayDouble();
+ CC.markNodeParsed("Vectors");
+ ASTRA_DELETE(node);
+ ASTRA_CONFIG_CHECK(data.size() % 12 == 0, "ParallelVecProjectionGeometry3D", "Vectors doesn't consist of 12-tuples.");
+ m_iProjectionAngleCount = data.size() / 12;
+ m_pProjectionAngles = new SPar3DProjection[m_iProjectionAngleCount];
+
+ for (int i = 0; i < m_iProjectionAngleCount; ++i) {
+ SPar3DProjection& p = m_pProjectionAngles[i];
+ p.fRayX = data[12*i + 0];
+ p.fRayY = data[12*i + 1];
+ p.fRayZ = data[12*i + 2];
+ p.fDetUX = data[12*i + 6];
+ p.fDetUY = data[12*i + 7];
+ p.fDetUZ = data[12*i + 8];
+ p.fDetVX = data[12*i + 9];
+ p.fDetVY = data[12*i + 10];
+ p.fDetVZ = data[12*i + 11];
+
+ // The backend code currently expects the corner of the detector, while
+ // the matlab interface supplies the center
+ p.fDetSX = data[12*i + 3] - 0.5f * m_iDetectorRowCount * p.fDetVX - 0.5f * m_iDetectorColCount * p.fDetUX;
+ p.fDetSY = data[12*i + 4] - 0.5f * m_iDetectorRowCount * p.fDetVY - 0.5f * m_iDetectorColCount * p.fDetUY;
+ p.fDetSZ = data[12*i + 5] - 0.5f * m_iDetectorRowCount * p.fDetVZ - 0.5f * m_iDetectorColCount * p.fDetUZ;
+ }
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CParallelVecProjectionGeometry3D::initialize(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ const SPar3DProjection* _pProjectionAngles)
+{
+ m_iProjectionAngleCount = _iProjectionAngleCount;
+ m_iDetectorRowCount = _iDetectorRowCount;
+ m_iDetectorColCount = _iDetectorColCount;
+ m_pProjectionAngles = new SPar3DProjection[m_iProjectionAngleCount];
+ for (int i = 0; i < m_iProjectionAngleCount; ++i)
+ m_pProjectionAngles[i] = _pProjectionAngles[i];
+
+ // TODO: check?
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Clone
+CProjectionGeometry3D* CParallelVecProjectionGeometry3D::clone() const
+{
+ CParallelVecProjectionGeometry3D* res = new CParallelVecProjectionGeometry3D();
+ res->m_bInitialized = m_bInitialized;
+ res->m_iProjectionAngleCount = m_iProjectionAngleCount;
+ res->m_iDetectorRowCount = m_iDetectorRowCount;
+ res->m_iDetectorColCount = m_iDetectorColCount;
+ res->m_iDetectorTotCount = m_iDetectorTotCount;
+ res->m_fDetectorSpacingX = m_fDetectorSpacingX;
+ res->m_fDetectorSpacingY = m_fDetectorSpacingY;
+ res->m_pProjectionAngles = new SPar3DProjection[m_iProjectionAngleCount];
+ memcpy(res->m_pProjectionAngles, m_pProjectionAngles, sizeof(m_pProjectionAngles[0])*m_iProjectionAngleCount);
+ return res;
+}
+
+//----------------------------------------------------------------------------------------
+// is equal
+bool CParallelVecProjectionGeometry3D::isEqual(const CProjectionGeometry3D * _pGeom2) const
+{
+ if (_pGeom2 == NULL) return false;
+
+ // try to cast argument to CParallelProjectionGeometry3D
+ const CParallelVecProjectionGeometry3D* pGeom2 = dynamic_cast<const CParallelVecProjectionGeometry3D*>(_pGeom2);
+ if (pGeom2 == NULL) return false;
+
+ // both objects must be initialized
+ if (!m_bInitialized || !pGeom2->m_bInitialized) return false;
+
+ // check all values
+ if (m_iProjectionAngleCount != pGeom2->m_iProjectionAngleCount) return false;
+ if (m_iDetectorRowCount != pGeom2->m_iDetectorRowCount) return false;
+ if (m_iDetectorColCount != pGeom2->m_iDetectorColCount) return false;
+ if (m_iDetectorTotCount != pGeom2->m_iDetectorTotCount) return false;
+ //if (m_fDetectorSpacingX != pGeom2->m_fDetectorSpacingX) return false;
+ //if (m_fDetectorSpacingY != pGeom2->m_fDetectorSpacingY) return false;
+
+ for (int i = 0; i < m_iProjectionAngleCount; ++i) {
+ if (memcmp(&m_pProjectionAngles[i], &pGeom2->m_pProjectionAngles[i], sizeof(m_pProjectionAngles[i])) != 0) return false;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// is of type
+bool CParallelVecProjectionGeometry3D::isOfType(const std::string& _sType) const
+{
+ return (_sType == "parallel3d_vec");
+}
+
+//----------------------------------------------------------------------------------------
+void CParallelVecProjectionGeometry3D::toXML(XMLNode* _sNode) const
+{
+ _sNode->addAttribute("type","parallel3d_vec");
+ _sNode->addChildNode("DetectorRowCount", m_iDetectorRowCount);
+ _sNode->addChildNode("DetectorColCount", m_iDetectorColCount);
+ // TODO:
+ //_sNode->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount);
+}
+
+CVector3D CParallelVecProjectionGeometry3D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const
+{
+ const SPar3DProjection& p = m_pProjectionAngles[_iProjectionIndex];
+
+ return CVector3D(p.fRayX, p.fRayY, p.fRayZ);
+}
+
+
+//----------------------------------------------------------------------------------------
+
+bool CParallelVecProjectionGeometry3D::_check()
+{
+ // TODO
+ return true;
+}
+
+} // end namespace astra
diff --git a/src/PlatformDepSystemCode.cpp b/src/PlatformDepSystemCode.cpp
new file mode 100644
index 0000000..a628aeb
--- /dev/null
+++ b/src/PlatformDepSystemCode.cpp
@@ -0,0 +1,76 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/PlatformDepSystemCode.h"
+
+using namespace astra;
+
+#ifdef _WIN32
+#include "windows.h"
+// windows API available
+
+unsigned long CPlatformDepSystemCode::getMSCount()
+{
+ return ::GetTickCount();
+}
+
+int CPlatformDepSystemCode::fseek64(FILE * _pStream, astra::int64 _iOffset, int _iOrigin)
+{
+ return _fseeki64(_pStream, _iOffset, _iOrigin);
+}
+
+astra::int64 CPlatformDepSystemCode::ftell64(FILE * _pStream)
+{
+ return _ftelli64(_pStream);
+}
+
+#else
+// linux, ...
+
+#include <sys/time.h>
+
+unsigned long CPlatformDepSystemCode::getMSCount()
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return (tv.tv_sec * 1000) + (tv.tv_usec/1000);
+}
+
+int CPlatformDepSystemCode::fseek64(FILE * _pStream, astra::int64 _iOffset, int _iOrigin)
+{
+ return fseeko(_pStream, _iOffset, _iOrigin);
+}
+
+astra::int64 CPlatformDepSystemCode::ftell64(FILE * _pStream)
+{
+ return ftello(_pStream);
+}
+
+
+
+#endif
diff --git a/src/ProjectionGeometry2D.cpp b/src/ProjectionGeometry2D.cpp
new file mode 100644
index 0000000..982a1e4
--- /dev/null
+++ b/src/ProjectionGeometry2D.cpp
@@ -0,0 +1,203 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ProjectionGeometry2D.h"
+
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CProjectionGeometry2D::CProjectionGeometry2D() : configCheckData(0)
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CProjectionGeometry2D::CProjectionGeometry2D(int _iAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsets) : configCheckData(0)
+{
+ _clear();
+ _initialize(_iAngleCount, _iDetectorCount, _fDetectorWidth, _pfProjectionAngles,_pfExtraDetectorOffsets);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CProjectionGeometry2D::~CProjectionGeometry2D()
+{
+ if (m_bInitialized) {
+ clear();
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// 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 CProjectionGeometry2D::_clear()
+{
+ m_iProjectionAngleCount = 0;
+ m_iDetectorCount = 0;
+ m_fDetectorWidth = 0.0f;
+ m_pfProjectionAngles = NULL;
+ m_pfExtraDetectorOffset = NULL;
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+void CProjectionGeometry2D::clear()
+{
+ m_iProjectionAngleCount = 0;
+ m_iDetectorCount = 0;
+ m_fDetectorWidth = 0.0f;
+ if (m_bInitialized){
+ delete[] m_pfProjectionAngles;
+ delete[] m_pfExtraDetectorOffset;
+ }
+ m_pfProjectionAngles = NULL;
+ m_pfExtraDetectorOffset = NULL;
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Check all variable values.
+bool CProjectionGeometry2D::_check()
+{
+ ASTRA_CONFIG_CHECK(m_iDetectorCount > 0, "ProjectionGeometry2D", "Detector Count should be positive.");
+ ASTRA_CONFIG_CHECK(m_fDetectorWidth > 0.0f, "ProjectionGeometry2D", "Detector Width should be positive.");
+ ASTRA_CONFIG_CHECK(m_iProjectionAngleCount > 0, "ProjectionGeometry2D", "ProjectionAngleCount should be positive.");
+ ASTRA_CONFIG_CHECK(m_pfProjectionAngles != NULL, "ProjectionGeometry2D", "ProjectionAngles not initialized");
+
+ // autofix: angles in [0,2pi[
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ while (2*PI <= m_pfProjectionAngles[i]) m_pfProjectionAngles[i] -= 2*PI;
+ while (m_pfProjectionAngles[i] < 0) m_pfProjectionAngles[i] += 2*PI;
+ }
+
+ // success
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization with a Config object
+bool CProjectionGeometry2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjectionGeometry2D> CC("ProjectionGeometry2D", this, _cfg);
+
+ // uninitialize if the object was initialized before
+ if (m_bInitialized) {
+ clear();
+ }
+
+ // Required: DetectorWidth
+ XMLNode* node = _cfg.self->getSingleNode("DetectorWidth");
+ ASTRA_CONFIG_CHECK(node, "ProjectionGeometry2D", "No DetectorWidth tag specified.");
+ m_fDetectorWidth = boost::lexical_cast<float32>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorWidth");
+
+ // Required: DetectorCount
+ node = _cfg.self->getSingleNode("DetectorCount");
+ ASTRA_CONFIG_CHECK(node, "ProjectionGeometry2D", "No DetectorCount tag specified.");
+ m_iDetectorCount = boost::lexical_cast<int>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorCount");
+
+ // Required: ProjectionAngles
+ node = _cfg.self->getSingleNode("ProjectionAngles");
+ ASTRA_CONFIG_CHECK(node, "ProjectionGeometry2D", "No ProjectionAngles tag specified.");
+ vector<float32> angles = node->getContentNumericalArray();
+ delete node;
+ m_iProjectionAngleCount = angles.size();
+ ASTRA_CONFIG_CHECK(m_iProjectionAngleCount > 0, "ProjectionGeometry2D", "Not enough ProjectionAngles specified.");
+ m_pfProjectionAngles = new float32[m_iProjectionAngleCount];
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfProjectionAngles[i] = angles[i];
+ }
+ CC.markNodeParsed("ProjectionAngles");
+
+ vector<float32> offset = _cfg.self->getOptionNumericalArray("ExtraDetectorOffset");
+ m_pfExtraDetectorOffset = new float32[m_iProjectionAngleCount];
+ if (offset.size() == (size_t)m_iProjectionAngleCount) {
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfExtraDetectorOffset[i] = offset[i];
+ }
+ } else {
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfExtraDetectorOffset[i] = 0.0f;
+ }
+ }
+ CC.markOptionParsed("ExtraDetectorOffset");
+
+ // some checks
+ ASTRA_CONFIG_CHECK(m_iDetectorCount > 0, "ProjectionGeometry2D", "DetectorCount should be positive.");
+ ASTRA_CONFIG_CHECK(m_fDetectorWidth > 0.0f, "ProjectionGeometry2D", "DetectorWidth should be positive.");
+ ASTRA_CONFIG_CHECK(m_pfProjectionAngles != NULL, "ProjectionGeometry2D", "ProjectionAngles not initialized");
+
+ // Interface class, so don't return true
+ return false;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CProjectionGeometry2D::_initialize(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsets)
+{
+ if (m_bInitialized) {
+ clear();
+ }
+
+ // copy parameters
+ m_iProjectionAngleCount = _iProjectionAngleCount;
+ m_iDetectorCount = _iDetectorCount;
+ m_fDetectorWidth = _fDetectorWidth;
+ m_pfProjectionAngles = new float32[m_iProjectionAngleCount];
+ m_pfExtraDetectorOffset = new float32[m_iProjectionAngleCount];
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfProjectionAngles[i] = _pfProjectionAngles[i];
+ m_pfExtraDetectorOffset[i] = _pfExtraDetectorOffsets ? _pfExtraDetectorOffsets[i]:0;
+ }
+
+ // Interface class, so don't set m_bInitialized to true
+ return true;
+}
+//---------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/ProjectionGeometry3D.cpp b/src/ProjectionGeometry3D.cpp
new file mode 100644
index 0000000..b78b7b8
--- /dev/null
+++ b/src/ProjectionGeometry3D.cpp
@@ -0,0 +1,329 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ProjectionGeometry3D.h"
+
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Check all variable values.
+bool CProjectionGeometry3D::_check()
+{
+ ASTRA_CONFIG_CHECK(m_iDetectorRowCount > 0, "ProjectionGeometry3D", "DetectorRowCount should be positive.");
+ ASTRA_CONFIG_CHECK(m_iDetectorColCount > 0, "ProjectionGeometry3D", "DetectorColCount should be positive.");
+ ASTRA_CONFIG_CHECK(m_fDetectorSpacingX > 0.0f, "ProjectionGeometry3D", "m_fDetectorSpacingX should be positive.");
+ ASTRA_CONFIG_CHECK(m_fDetectorSpacingY > 0.0f, "ProjectionGeometry3D", "m_fDetectorSpacingY should be positive.");
+ ASTRA_CONFIG_CHECK(m_iProjectionAngleCount > 0, "ProjectionGeometry3D", "ProjectionAngleCount should be positive.");
+ ASTRA_CONFIG_CHECK(m_pfProjectionAngles != NULL, "ProjectionGeometry3D", "ProjectionAngles not initialized");
+
+/*
+ // autofix: angles in [0,2pi[
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ while (2*PI <= m_pfProjectionAngles[i]) m_pfProjectionAngles[i] -= 2*PI;
+ while (m_pfProjectionAngles[i] < 0) m_pfProjectionAngles[i] += 2*PI;
+ }
+*/
+
+ // succes
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CProjectionGeometry3D::CProjectionGeometry3D() : configCheckData(0)
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CProjectionGeometry3D::CProjectionGeometry3D(int _iAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorSpacingX,
+ float32 _fDetectorSpacingY,
+ const float32 *_pfProjectionAngles,
+ const float32 *_pfExtraDetectorOffsetsX,
+ const float32 *_pfExtraDetectorOffsetsY) : configCheckData(0)
+{
+ _clear();
+ _initialize(_iAngleCount,
+ _iDetectorRowCount,
+ _iDetectorColCount,
+ _fDetectorSpacingX,
+ _fDetectorSpacingY,
+ _pfProjectionAngles,
+ _pfExtraDetectorOffsetsX,
+ _pfExtraDetectorOffsetsY);
+}
+
+//----------------------------------------------------------------------------------------
+// Copy constructor.
+CProjectionGeometry3D::CProjectionGeometry3D(const CProjectionGeometry3D& _projGeom)
+{
+ _clear();
+ _initialize(_projGeom.m_iProjectionAngleCount,
+ _projGeom.m_iDetectorRowCount,
+ _projGeom.m_iDetectorColCount,
+ _projGeom.m_fDetectorSpacingX,
+ _projGeom.m_fDetectorSpacingY,
+ _projGeom.m_pfProjectionAngles,
+ _projGeom.m_pfExtraDetectorOffsetsX,
+ _projGeom.m_pfExtraDetectorOffsetsY);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CProjectionGeometry3D::~CProjectionGeometry3D()
+{
+ if (m_bInitialized) {
+ clear();
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// 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 CProjectionGeometry3D::_clear()
+{
+ m_iProjectionAngleCount = 0;
+ m_iDetectorRowCount = 0;
+ m_iDetectorColCount = 0;
+ m_fDetectorSpacingX = 0.0f;
+ m_fDetectorSpacingY = 0.0f;
+ m_pfProjectionAngles = NULL;
+ m_pfExtraDetectorOffsetsX = NULL;
+ m_pfExtraDetectorOffsetsY = NULL;
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+void CProjectionGeometry3D::clear()
+{
+ m_iProjectionAngleCount = 0;
+ m_iDetectorRowCount = 0;
+ m_iDetectorColCount = 0;
+ m_fDetectorSpacingX = 0.0f;
+ m_fDetectorSpacingY = 0.0f;
+ if (m_pfProjectionAngles != NULL) {
+ delete [] m_pfProjectionAngles;
+ }
+ if (m_pfExtraDetectorOffsetsX != NULL) {
+ delete [] m_pfExtraDetectorOffsetsX;
+ }
+ if (m_pfExtraDetectorOffsetsY != NULL) {
+ delete [] m_pfExtraDetectorOffsetsY;
+ }
+ m_pfProjectionAngles = NULL;
+ m_pfExtraDetectorOffsetsX = NULL;
+ m_pfExtraDetectorOffsetsY = NULL;
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization witha Config object
+bool CProjectionGeometry3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjectionGeometry3D> CC("ProjectionGeometry3D", this, _cfg);
+
+ if (m_bInitialized) {
+ clear();
+ }
+
+ ASTRA_ASSERT(_cfg.self);
+
+ // Required: DetectorWidth
+ XMLNode* node = _cfg.self->getSingleNode("DetectorSpacingX");
+ ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorSpacingX tag specified.");
+ m_fDetectorSpacingX = boost::lexical_cast<float32>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorSpacingX");
+
+ // Required: DetectorHeight
+ node = _cfg.self->getSingleNode("DetectorSpacingY");
+ ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorSpacingY tag specified.");
+ m_fDetectorSpacingY = boost::lexical_cast<float32>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorSpacingY");
+
+ // Required: DetectorRowCount
+ node = _cfg.self->getSingleNode("DetectorRowCount");
+ ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorRowCount tag specified.");
+ m_iDetectorRowCount = boost::lexical_cast<int>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorRowCount");
+
+ // Required: DetectorCount
+ node = _cfg.self->getSingleNode("DetectorColCount");
+ ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorColCount tag specified.");
+ m_iDetectorColCount = boost::lexical_cast<int>(node->getContent());
+ m_iDetectorTotCount = m_iDetectorRowCount * m_iDetectorColCount;
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("DetectorColCount");
+
+ // Required: ProjectionAngles
+ node = _cfg.self->getSingleNode("ProjectionAngles");
+ ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No ProjectionAngles tag specified.");
+ vector<float32> angles = node->getContentNumericalArray();
+ m_iProjectionAngleCount = angles.size();
+ ASTRA_CONFIG_CHECK(m_iProjectionAngleCount > 0, "ProjectionGeometry3D", "Not enough ProjectionAngles specified.");
+ m_pfProjectionAngles = new float32[m_iProjectionAngleCount];
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfProjectionAngles[i] = angles[i];
+ }
+ CC.markNodeParsed("ProjectionAngles");
+ ASTRA_DELETE(node);
+
+ // Optional: ExtraDetectorOffsetX
+ node = _cfg.self->getSingleNode("ExtraDetectorOffsetsX");
+ m_pfExtraDetectorOffsetsX = new float32[m_iProjectionAngleCount];
+ if (node) {
+ vector<float32> translationsX = node->getContentNumericalArray();
+ if (translationsX.size() < m_iProjectionAngleCount){
+ cout << "Not enough ExtraDetectorOffsetsX components specified. " << endl;
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfExtraDetectorOffsetsX[i] = 0;
+ }
+ }
+ else {
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfExtraDetectorOffsetsX[i] = translationsX[i];
+ }
+ }
+ }
+ else {
+ //cout << "No ExtraDetectorOffsetsX tag specified." << endl;
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfExtraDetectorOffsetsX[i] = 0;
+ }
+ }
+ CC.markOptionParsed("ExtraDetectorOffsetsX");
+ ASTRA_DELETE(node);
+
+ // Optional: ExtraDetectorOffsetsY
+ node = _cfg.self->getSingleNode("ExtraDetectorOffsetsY");
+ m_pfExtraDetectorOffsetsY = new float32[m_iProjectionAngleCount];
+ if (node) {
+ vector<float32> translationsX = node->getContentNumericalArray();
+ if (translationsX.size() < m_iProjectionAngleCount){
+ cout << "Not enough ExtraDetectorOffsetsY components specified. " << endl;
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfExtraDetectorOffsetsY[i] = 0;
+ }
+ }
+ else {
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfExtraDetectorOffsetsY[i] = translationsX[i];
+ }
+ }
+ }
+ else {
+ //cout << "No ExtraDetectorOffsetsY tag specified." << endl;
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfExtraDetectorOffsetsY[i] = 0;
+ }
+ }
+ CC.markOptionParsed("ExtraDetectorOffsetsY");
+ ASTRA_DELETE(node);
+
+ // Interface class, so don't return true
+ return false;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CProjectionGeometry3D::_initialize(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorSpacingX,
+ float32 _fDetectorSpacingY,
+ const float32 *_pfProjectionAngles,
+ const float32 *_pfExtraDetectorOffsetsX,
+ const float32 *_pfExtraDetectorOffsetsY)
+{
+ if (m_bInitialized) {
+ clear();
+ }
+
+ // copy parameters
+ m_iProjectionAngleCount = _iProjectionAngleCount;
+ m_iDetectorRowCount = _iDetectorRowCount;
+ m_iDetectorColCount = _iDetectorColCount;
+ m_iDetectorTotCount = _iDetectorRowCount * _iDetectorColCount;
+ m_fDetectorSpacingX = _fDetectorSpacingX;
+ m_fDetectorSpacingY = _fDetectorSpacingY;
+ m_pfProjectionAngles = new float32[m_iProjectionAngleCount];
+ m_pfExtraDetectorOffsetsX = new float32[m_iProjectionAngleCount];
+ m_pfExtraDetectorOffsetsY = new float32[m_iProjectionAngleCount];
+ for (int i = 0; i < m_iProjectionAngleCount; i++) {
+ m_pfProjectionAngles[i] = _pfProjectionAngles[i];
+ m_pfExtraDetectorOffsetsX[i] = _pfExtraDetectorOffsetsX ? _pfExtraDetectorOffsetsX[i]:0;
+ m_pfExtraDetectorOffsetsY[i] = _pfExtraDetectorOffsetsY ? _pfExtraDetectorOffsetsY[i]:0;
+ //m_pfExtraDetectorOffsetsX[i] = 0;
+ //m_pfExtraDetectorOffsetsY[i] = 0;
+ }
+
+ m_iDetectorTotCount = m_iProjectionAngleCount * m_iDetectorRowCount * m_iDetectorColCount;
+
+ // Interface class, so don't return true
+ return false;
+}
+
+//---------------------------------------------------------------------------------------
+//
+AstraError CProjectionGeometry3D::setExtraDetectorOffsetsX(float32* _pfExtraDetectorOffsetsX)
+{
+ if (!m_bInitialized)
+ return ASTRA_ERROR_NOT_INITIALIZED;
+
+ for (int iAngle = 0; iAngle<m_iProjectionAngleCount; iAngle++)
+ m_pfExtraDetectorOffsetsX[iAngle] = _pfExtraDetectorOffsetsX[iAngle];
+
+ return ASTRA_SUCCESS;
+}
+
+//---------------------------------------------------------------------------------------
+//
+AstraError CProjectionGeometry3D::setExtraDetectorOffsetsY(float32* _pfExtraDetectorOffsetsY)
+{
+ if (!m_bInitialized)
+ return ASTRA_ERROR_NOT_INITIALIZED;
+
+ for (int iAngle = 0; iAngle<m_iProjectionAngleCount; iAngle++)
+ m_pfExtraDetectorOffsetsY[iAngle] = _pfExtraDetectorOffsetsY[iAngle];
+
+ return ASTRA_SUCCESS;
+}
+} // namespace astra
diff --git a/src/Projector2D.cpp b/src/Projector2D.cpp
new file mode 100644
index 0000000..e67cd0c
--- /dev/null
+++ b/src/Projector2D.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Projector2D.h"
+
+#include "astra/FanFlatProjectionGeometry2D.h"
+#include "astra/FanFlatVecProjectionGeometry2D.h"
+#include "astra/SparseMatrixProjectionGeometry2D.h"
+#include "astra/SparseMatrix.h"
+
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// constructor
+CProjector2D::CProjector2D() : configCheckData(0)
+{
+
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// constructor
+CProjector2D::CProjector2D(CProjectionGeometry2D* _pProjectionGeometry, CVolumeGeometry2D* _pVolumeGeometry) : configCheckData(0)
+{
+ m_pProjectionGeometry = _pProjectionGeometry->clone();
+ m_pVolumeGeometry = _pVolumeGeometry->clone();
+ m_bIsInitialized = true;
+}
+
+//----------------------------------------------------------------------------------------
+// destructor
+CProjector2D::~CProjector2D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CProjector2D::_clear()
+{
+ m_pProjectionGeometry = NULL;
+ m_pVolumeGeometry = NULL;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CProjector2D::clear()
+{
+ if (m_pProjectionGeometry) {
+ delete m_pProjectionGeometry;
+ m_pProjectionGeometry = NULL;
+ }
+ if (m_pVolumeGeometry) {
+ delete m_pVolumeGeometry;
+ m_pVolumeGeometry = NULL;
+ }
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CProjector2D::_check()
+{
+ // check pointers
+ ASTRA_CONFIG_CHECK(m_pProjectionGeometry, "Projector2D", "Invalid Projection Geometry Object.");
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry, "Projector2D", "Invalid Volume Geometry Object.");
+
+ // check initializations
+ ASTRA_CONFIG_CHECK(m_pProjectionGeometry->isInitialized(), "Projector2D", "Projection Geometry Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->isInitialized(), "Projector2D", "Volume Geometry Object Not Initialized.");
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CProjector2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjector2D> CC("Projector2D", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required: ProjectionGeometry
+ XMLNode* node = _cfg.self->getSingleNode("ProjectionGeometry");
+ ASTRA_CONFIG_CHECK(node, "Projector2D", "No ProjectionGeometry tag specified.");
+
+ // FIXME: Change how the base class is created. (This is duplicated
+ // in astra_mex_data2d.cpp.)
+ std::string type = node->getAttribute("type");
+ if (type == "sparse_matrix") {
+ m_pProjectionGeometry = new CSparseMatrixProjectionGeometry2D();
+ m_pProjectionGeometry->initialize(Config(node));
+ } else if (type == "fanflat") {
+ CFanFlatProjectionGeometry2D* pFanFlatProjectionGeometry = new CFanFlatProjectionGeometry2D();
+ pFanFlatProjectionGeometry->initialize(Config(node));
+ m_pProjectionGeometry = pFanFlatProjectionGeometry;
+ } else if (type == "fanflat_vec") {
+ CFanFlatVecProjectionGeometry2D* pFanFlatVecProjectionGeometry = new CFanFlatVecProjectionGeometry2D();
+ pFanFlatVecProjectionGeometry->initialize(Config(node));
+ m_pProjectionGeometry = pFanFlatVecProjectionGeometry;
+ } else {
+ m_pProjectionGeometry = new CParallelProjectionGeometry2D();
+ m_pProjectionGeometry->initialize(Config(node));
+ }
+ // "node" is deleted by the temp Config(node) objects
+ ASTRA_CONFIG_CHECK(m_pProjectionGeometry->isInitialized(), "Projector2D", "ProjectionGeometry not initialized.");
+ CC.markNodeParsed("ProjectionGeometry");
+
+
+ // required: VolumeGeometry
+ node = _cfg.self->getSingleNode("VolumeGeometry");
+ ASTRA_CONFIG_CHECK(node, "Projector2D", "No VolumeGeometry tag specified.");
+ m_pVolumeGeometry = new CVolumeGeometry2D();
+ m_pVolumeGeometry->initialize(Config(node));
+ // "node" is deleted by the temp Config(node) object
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->isInitialized(), "Projector2D", "VolumeGeometry not initialized.");
+ CC.markNodeParsed("VolumeGeometry");
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// weights of each detector in a projection angle
+void CProjector2D::computeProjectionRayWeights(int _iProjection, SPixelWeight* _pfWeightedPixels, int* _piRayStoredPixelCount)
+{
+ int iPixelBufferSize = getProjectionWeightsCount(_iProjection);
+
+ int iDetector;
+ for(iDetector = m_pProjectionGeometry->getDetectorCount()-1; iDetector >= 0; --iDetector) {
+ computeSingleRayWeights(_iProjection, // projector index
+ iDetector, // detector index
+ &_pfWeightedPixels[iDetector*iPixelBufferSize], // pixel buffer
+ iPixelBufferSize, // pixel buffer size
+ _piRayStoredPixelCount[iDetector]); // stored pixel count
+ }
+
+}
+
+//----------------------------------------------------------------------------------------
+// explicit projection matrix
+CSparseMatrix* CProjector2D::getMatrix()
+{
+ unsigned int iProjectionCount = m_pProjectionGeometry->getProjectionAngleCount();
+ unsigned int iDetectorCount = m_pProjectionGeometry->getDetectorCount();
+ unsigned int iRayCount = iProjectionCount * iDetectorCount;
+ unsigned int iVolumeSize = m_pVolumeGeometry->getGridTotCount();
+ unsigned long lSize = 0;
+ unsigned int iMaxRayLength = 0;
+ for (unsigned int i = 0; i < iProjectionCount; ++i) {
+ unsigned int iRayLength = getProjectionWeightsCount(i);
+ lSize += iDetectorCount * iRayLength;
+ if (iRayLength > iMaxRayLength)
+ iMaxRayLength = iRayLength;
+ }
+ CSparseMatrix* pMatrix = new CSparseMatrix(iRayCount, iVolumeSize, lSize);
+
+ if (!pMatrix || !pMatrix->isInitialized()) {
+ delete pMatrix;
+ return 0;
+ }
+
+ SPixelWeight* pEntries = new SPixelWeight[iMaxRayLength];
+ unsigned long lMatrixIndex = 0;
+ for (unsigned int iRay = 0; iRay < iRayCount; ++iRay) {
+ pMatrix->m_plRowStarts[iRay] = lMatrixIndex;
+ int iPixelCount;
+ int iProjIndex, iDetIndex;
+ m_pProjectionGeometry->indexToAngleDetectorIndex(iRay, iProjIndex, iDetIndex);
+ computeSingleRayWeights(iProjIndex, iDetIndex, pEntries, iMaxRayLength, iPixelCount);
+
+ for (int i = 0; i < iPixelCount; ++i) {
+ pMatrix->m_piColIndices[lMatrixIndex] = pEntries[i].m_iIndex;
+ pMatrix->m_pfValues[lMatrixIndex] = pEntries[i].m_fWeight;
+ ++lMatrixIndex;
+ }
+
+ }
+ pMatrix->m_plRowStarts[iRayCount] = lMatrixIndex;
+
+ delete[] pEntries;
+ return pMatrix;
+}
+
+} // end namespace
diff --git a/src/Projector3D.cpp b/src/Projector3D.cpp
new file mode 100644
index 0000000..f8fddf4
--- /dev/null
+++ b/src/Projector3D.cpp
@@ -0,0 +1,121 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Projector3D.h"
+
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor
+CProjector3D::CProjector3D() : configCheckData(0)
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CProjector3D::~CProjector3D()
+{
+ if (m_bIsInitialized) clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Clear for constructors
+void CProjector3D::_clear()
+{
+ m_pProjectionGeometry = NULL;
+ m_pVolumeGeometry = NULL;
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Clear
+void CProjector3D::clear()
+{
+ ASTRA_DELETE(m_pProjectionGeometry);
+ ASTRA_DELETE(m_pVolumeGeometry);
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CProjector3D::_check()
+{
+ // projection geometry
+ ASTRA_CONFIG_CHECK(m_pProjectionGeometry, "Projector3D", "ProjectionGeometry3D not initialized.");
+ ASTRA_CONFIG_CHECK(m_pProjectionGeometry->isInitialized(), "Projector3D", "ProjectionGeometry3D not initialized.");
+
+ // volume geometry
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry, "Projector3D", "VolumeGeometry3D not initialized.");
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->isInitialized(), "Projector3D", "VolumeGeometry3D not initialized.");
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CProjector3D::initialize(const Config& _cfg)
+{
+ assert(_cfg.self);
+
+ return true;
+}
+
+/*
+bool CProjector3D::initialize(astra::CProjectionGeometry3D *, astra::CVolumeGeometry3D *)
+{
+ ASTRA_ASSERT(false);
+
+ return false;
+}
+*/
+
+//----------------------------------------------------------------------------------------
+// Weights of each detector in a projection angle
+void CProjector3D::computeProjectionRayWeights(int _iProjection, SPixelWeight* _pfWeightedPixels, int* _piRayStoredPixelCount)
+{
+ int iPixelBufferSize = getProjectionWeightsCount(_iProjection);
+
+ int iDetector = 0;
+ for(iDetector = m_pProjectionGeometry->getDetectorTotCount()-1; iDetector >= 0; --iDetector) {
+ int iSliceIndex = iDetector / m_pProjectionGeometry->getDetectorColCount();
+ int iDetectorColIndex = iDetector % m_pProjectionGeometry->getDetectorColCount();
+
+ computeSingleRayWeights(_iProjection, // projector index
+ iSliceIndex, // slice index
+ iDetectorColIndex, // detector index
+ &_pfWeightedPixels[iDetector*iPixelBufferSize], // pixel buffer
+ iPixelBufferSize, // pixel buffer size
+ _piRayStoredPixelCount[iDetector]); // stored pixel count
+ }
+}
+//----------------------------------------------------------------------------------------
+
+} // end namespace
diff --git a/src/ReconstructionAlgorithm2D.cpp b/src/ReconstructionAlgorithm2D.cpp
new file mode 100644
index 0000000..ea693e3
--- /dev/null
+++ b/src/ReconstructionAlgorithm2D.cpp
@@ -0,0 +1,275 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ReconstructionAlgorithm2D.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+
+using namespace std;
+
+namespace astra {
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CReconstructionAlgorithm2D::CReconstructionAlgorithm2D()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CReconstructionAlgorithm2D::~CReconstructionAlgorithm2D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CReconstructionAlgorithm2D::_clear()
+{
+ m_pProjector = NULL;
+ m_pSinogram = NULL;
+ m_pReconstruction = NULL;
+ m_bUseMinConstraint = false;
+ m_fMinValue = 0.0f;
+ m_bUseMaxConstraint = false;
+ m_fMaxValue = 0.0f;
+ m_bUseReconstructionMask = false;
+ m_pReconstructionMask = NULL;
+ m_bUseSinogramMask = false;
+ m_pSinogramMask = NULL;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CReconstructionAlgorithm2D::clear()
+{
+ // Nothing to delete, so just _clear()
+ _clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CReconstructionAlgorithm2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("ReconstructionAlgorithm2D", this, _cfg);
+
+ // projector
+ XMLNode* node = _cfg.self->getSingleNode("ProjectorId");
+ ASTRA_CONFIG_CHECK(node, "Reconstruction2D", "No ProjectorId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pProjector = CProjector2DManager::getSingleton().get(id);
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectorId");
+
+ // sinogram data
+ node = _cfg.self->getSingleNode("ProjectionDataId");
+ ASTRA_CONFIG_CHECK(node, "Reconstruction2D", "No ProjectionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pSinogram = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectionDataId");
+
+ // reconstruction data
+ node = _cfg.self->getSingleNode("ReconstructionDataId");
+ ASTRA_CONFIG_CHECK(node, "Reconstruction2D", "No ReconstructionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pReconstruction = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ReconstructionDataId");
+
+ // fixed mask
+ if (_cfg.self->hasOption("ReconstructionMaskId")) {
+ m_bUseReconstructionMask = true;
+ id = boost::lexical_cast<int>(_cfg.self->getOption("ReconstructionMaskId"));
+ m_pReconstructionMask = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ }
+ CC.markOptionParsed("ReconstructionMaskId");
+
+ // fixed mask
+ if (_cfg.self->hasOption("SinogramMaskId")) {
+ m_bUseSinogramMask = true;
+ id = boost::lexical_cast<int>(_cfg.self->getOption("SinogramMaskId"));
+ m_pSinogramMask = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ }
+ CC.markOptionParsed("SinogramMaskId");
+
+ // Constraints - NEW
+ if (_cfg.self->hasOption("MinConstraint")) {
+ m_bUseMinConstraint = true;
+ m_fMinValue = _cfg.self->getOptionNumerical("MinConstraint", 0.0f);
+ CC.markOptionParsed("MinConstraint");
+ } else {
+ // Constraint - OLD
+ m_bUseMinConstraint = _cfg.self->getOptionBool("UseMinConstraint", false);
+ CC.markOptionParsed("UseMinConstraint");
+ if (m_bUseMinConstraint) {
+ m_fMinValue = _cfg.self->getOptionNumerical("MinConstraintValue", 0.0f);
+ CC.markOptionParsed("MinConstraintValue");
+ }
+ }
+ if (_cfg.self->hasOption("MaxConstraint")) {
+ m_bUseMaxConstraint = true;
+ m_fMaxValue = _cfg.self->getOptionNumerical("MaxConstraint", 255.0f);
+ CC.markOptionParsed("MaxConstraint");
+ } else {
+ // Constraint - OLD
+ m_bUseMaxConstraint = _cfg.self->getOptionBool("UseMaxConstraint", false);
+ CC.markOptionParsed("UseMaxConstraint");
+ if (m_bUseMaxConstraint) {
+ m_fMaxValue = _cfg.self->getOptionNumerical("MaxConstraintValue", 0.0f);
+ CC.markOptionParsed("MaxConstraintValue");
+ }
+ }
+
+ // return success
+ return _check();
+}
+
+//----------------------------------------------------------------------------------------
+// Initialize - C++
+bool CReconstructionAlgorithm2D::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ // return success
+ return _check();
+}
+
+//---------------------------------------------------------------------------------------
+// Set Constraints
+void CReconstructionAlgorithm2D::setConstraints(bool _bUseMin, float32 _fMinValue, bool _bUseMax, float32 _fMaxValue)
+{
+ m_bUseMinConstraint = _bUseMin;
+ m_fMinValue = _fMinValue;
+ m_bUseMaxConstraint = _bUseMax;
+ m_fMaxValue = _fMaxValue;
+}
+
+//----------------------------------------------------------------------------------------
+// Set Fixed Reconstruction Mask
+void CReconstructionAlgorithm2D::setReconstructionMask(CFloat32VolumeData2D* _pMask, bool _bEnable)
+{
+ // TODO: check geometry matches volume
+ m_bUseReconstructionMask = _bEnable;
+ m_pReconstructionMask = _pMask;
+ if (m_pReconstructionMask == NULL) {
+ m_bUseReconstructionMask = false;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Set Fixed Sinogram Mask
+void CReconstructionAlgorithm2D::setSinogramMask(CFloat32ProjectionData2D* _pMask, bool _bEnable)
+{
+ // TODO: check geometry matches sinogram
+ m_bUseSinogramMask = _bEnable;
+ m_pSinogramMask = _pMask;
+ if (m_pSinogramMask == NULL) {
+ m_bUseSinogramMask = false;
+ }
+}//----------------------------------------------------------------------------------------
+// Check
+bool CReconstructionAlgorithm2D::_check()
+{
+ // check pointers
+ ASTRA_CONFIG_CHECK(m_pProjector, "Reconstruction2D", "Invalid Projector Object.");
+ ASTRA_CONFIG_CHECK(m_pSinogram, "Reconstruction2D", "Invalid Projection Data Object.");
+ ASTRA_CONFIG_CHECK(m_pReconstruction, "Reconstruction2D", "Invalid Reconstruction Data Object.");
+
+ // check initializations
+ ASTRA_CONFIG_CHECK(m_pProjector->isInitialized(), "Reconstruction2D", "Projector Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pSinogram->isInitialized(), "Reconstruction2D", "Projection Data Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pReconstruction->isInitialized(), "Reconstruction2D", "Reconstruction Data Object Not Initialized.");
+
+ // check compatibility between projector and data classes
+ ASTRA_CONFIG_CHECK(m_pSinogram->getGeometry()->isEqual(m_pProjector->getProjectionGeometry()), "Reconstruction2D", "Projection Data not compatible with the specified Projector.");
+ ASTRA_CONFIG_CHECK(m_pReconstruction->getGeometry()->isEqual(m_pProjector->getVolumeGeometry()), "Reconstruction2D", "Reconstruction Data not compatible with the specified Projector.");
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CReconstructionAlgorithm2D::getInformation()
+{
+ map<string, boost::any> res;
+ res["ProjectorId"] = getInformation("ProjectorId");
+ res["ProjectionDataId"] = getInformation("ProjectionDataId");
+ res["ReconstructionDataId"] = getInformation("ReconstructionDataId");
+ res["UseMinConstraint"] = getInformation("UseMinConstraint");
+ res["MinConstraintValue"] = getInformation("MinConstraintValue");
+ res["UseMaxConstraint"] = getInformation("UseMaxConstraint");
+ res["MaxConstraintValue"] = getInformation("MaxConstraintValue");
+ res["ReconstructionMaskId"] = getInformation("ReconstructionMaskId");
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CReconstructionAlgorithm2D::getInformation(std::string _sIdentifier)
+{
+ if (_sIdentifier == "UseMinConstraint") { return m_bUseMinConstraint ? string("yes") : string("no"); }
+ if (_sIdentifier == "MinConstraintValue") { return m_fMinValue; }
+ if (_sIdentifier == "UseMaxConstraint") { return m_bUseMaxConstraint ? string("yes") : string("no"); }
+ if (_sIdentifier == "MaxConstraintValue") { return m_fMaxValue; }
+ if (_sIdentifier == "ProjectorId") {
+ int iIndex = CProjector2DManager::getSingleton().getIndex(m_pProjector);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ if (_sIdentifier == "ProjectionDataId") {
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pSinogram);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ if (_sIdentifier == "ReconstructionDataId") {
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pReconstruction);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ if (_sIdentifier == "ReconstructionMaskId") {
+ if (!m_bUseReconstructionMask) return string("not used");
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pReconstructionMask);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/ReconstructionAlgorithm3D.cpp b/src/ReconstructionAlgorithm3D.cpp
new file mode 100644
index 0000000..4d9bbc6
--- /dev/null
+++ b/src/ReconstructionAlgorithm3D.cpp
@@ -0,0 +1,306 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ReconstructionAlgorithm3D.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+
+using namespace std;
+
+namespace astra {
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CReconstructionAlgorithm3D::CReconstructionAlgorithm3D()
+{
+ m_pProjector = NULL;
+ m_pSinogram = NULL;
+ m_pReconstruction = NULL;
+ m_bUseMinConstraint = false;
+ m_fMinValue = 0.0f;
+ m_bUseMaxConstraint = false;
+ m_fMaxValue = 0.0f;
+ m_bUseReconstructionMask = false;
+ m_pReconstructionMask = NULL;
+ m_bUseSinogramMask = false;
+ m_pSinogramMask = NULL;
+ m_bIsInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CReconstructionAlgorithm3D::~CReconstructionAlgorithm3D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CReconstructionAlgorithm3D::_clear()
+{
+ m_pProjector = NULL;
+ m_pSinogram = NULL;
+ m_pReconstruction = NULL;
+ m_bUseMinConstraint = false;
+ m_fMinValue = 0.0f;
+ m_bUseMaxConstraint = false;
+ m_fMaxValue = 0.0f;
+ m_bUseReconstructionMask = false;
+ m_pReconstructionMask = NULL;
+ m_bUseSinogramMask = false;
+ m_pSinogramMask = NULL;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CReconstructionAlgorithm3D::clear()
+{
+ m_pProjector = NULL;
+ m_pSinogram = NULL;
+ m_pReconstruction = NULL;
+ m_bUseMinConstraint = false;
+ m_fMinValue = 0.0f;
+ m_bUseMaxConstraint = false;
+ m_fMaxValue = 0.0f;
+ m_bUseReconstructionMask = false;
+ m_pReconstructionMask = NULL;
+ m_bUseSinogramMask = false;
+ m_pSinogramMask = NULL;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CReconstructionAlgorithm3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("ReconstructionAlgorithm3D", this, _cfg);
+
+ XMLNode* node;
+ int id;
+#if 0
+ // projector
+ node = _cfg.self->getSingleNode("ProjectorId");
+ ASTRA_CONFIG_CHECK(node, "Reconstruction3D", "No ProjectorId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pProjector = CProjector3DManager::getSingleton().get(id);
+ ASTRA_DELETE(node);
+#endif
+
+ // sinogram data
+ node = _cfg.self->getSingleNode("ProjectionDataId");
+ ASTRA_CONFIG_CHECK(node, "Reconstruction3D", "No ProjectionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pSinogram = dynamic_cast<CFloat32ProjectionData3D*>(CData3DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectionDataId");
+
+ // reconstruction data
+ node = _cfg.self->getSingleNode("ReconstructionDataId");
+ ASTRA_CONFIG_CHECK(node, "Reconstruction3D", "No ReconstructionDataId tag specified.");
+ id = boost::lexical_cast<int>(node->getContent());
+ m_pReconstruction = dynamic_cast<CFloat32VolumeData3D*>(CData3DManager::getSingleton().get(id));
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ReconstructionDataId");
+
+ // fixed mask
+ if (_cfg.self->hasOption("ReconstructionMaskId")) {
+ m_bUseReconstructionMask = true;
+ id = boost::lexical_cast<int>(_cfg.self->getOption("ReconstructionMaskId"));
+ m_pReconstructionMask = dynamic_cast<CFloat32VolumeData3D*>(CData3DManager::getSingleton().get(id));
+ }
+ CC.markOptionParsed("ReconstructionMaskId");
+
+ // fixed mask
+ if (_cfg.self->hasOption("SinogramMaskId")) {
+ m_bUseSinogramMask = true;
+ id = boost::lexical_cast<int>(_cfg.self->getOption("SinogramMaskId"));
+ m_pSinogramMask = dynamic_cast<CFloat32ProjectionData3D*>(CData3DManager::getSingleton().get(id));
+ }
+
+ // Constraints - NEW
+ if (_cfg.self->hasOption("MinConstraint")) {
+ m_bUseMinConstraint = true;
+ m_fMinValue = _cfg.self->getOptionNumerical("MinConstraint", 0.0f);
+ CC.markOptionParsed("MinConstraint");
+ } else {
+ // Constraint - OLD
+ m_bUseMinConstraint = _cfg.self->getOptionBool("UseMinConstraint", false);
+ CC.markOptionParsed("UseMinConstraint");
+ if (m_bUseMinConstraint) {
+ m_fMinValue = _cfg.self->getOptionNumerical("MinConstraintValue", 0.0f);
+ CC.markOptionParsed("MinConstraintValue");
+ }
+ }
+ if (_cfg.self->hasOption("MaxConstraint")) {
+ m_bUseMaxConstraint = true;
+ m_fMaxValue = _cfg.self->getOptionNumerical("MaxConstraint", 255.0f);
+ CC.markOptionParsed("MaxConstraint");
+ } else {
+ // Constraint - OLD
+ m_bUseMaxConstraint = _cfg.self->getOptionBool("UseMaxConstraint", false);
+ CC.markOptionParsed("UseMaxConstraint");
+ if (m_bUseMaxConstraint) {
+ m_fMaxValue = _cfg.self->getOptionNumerical("MaxConstraintValue", 0.0f);
+ CC.markOptionParsed("MaxConstraintValue");
+ }
+ }
+
+ // return success
+ return _check();
+}
+
+//----------------------------------------------------------------------------------------
+// Initialize - C++
+bool CReconstructionAlgorithm3D::initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3D* _pSinogram,
+ CFloat32VolumeData3D* _pReconstruction)
+{
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ // return success
+ return _check();
+}
+
+//---------------------------------------------------------------------------------------
+// Set Constraints
+void CReconstructionAlgorithm3D::setConstraints(bool _bUseMin, float32 _fMinValue, bool _bUseMax, float32 _fMaxValue)
+{
+ m_bUseMinConstraint = _bUseMin;
+ m_fMinValue = _fMinValue;
+ m_bUseMaxConstraint = _bUseMax;
+ m_fMaxValue = _fMaxValue;
+}
+
+//----------------------------------------------------------------------------------------
+// Set Fixed Reconstruction Mask
+void CReconstructionAlgorithm3D::setReconstructionMask(CFloat32VolumeData3D* _pMask, bool _bEnable)
+{
+ // TODO: check geometry matches volume
+ m_bUseReconstructionMask = _bEnable;
+ m_pReconstructionMask = _pMask;
+ if (m_pReconstructionMask == NULL) {
+ m_bUseReconstructionMask = false;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Set Fixed Sinogram Mask
+void CReconstructionAlgorithm3D::setSinogramMask(CFloat32ProjectionData3D* _pMask, bool _bEnable)
+{
+ // TODO: check geometry matches sinogram
+ m_bUseSinogramMask = _bEnable;
+ m_pSinogramMask = _pMask;
+ if (m_pSinogramMask == NULL) {
+ m_bUseSinogramMask = false;
+ }
+}//----------------------------------------------------------------------------------------
+// Check
+bool CReconstructionAlgorithm3D::_check()
+{
+ // check pointers
+#if 0
+ ASTRA_CONFIG_CHECK(m_pProjector, "Reconstruction3D", "Invalid Projector Object.");
+#endif
+ ASTRA_CONFIG_CHECK(m_pSinogram, "Reconstruction3D", "Invalid Projection Data Object.");
+ ASTRA_CONFIG_CHECK(m_pReconstruction, "Reconstruction3D", "Invalid Reconstruction Data Object.");
+
+ // check initializations
+#if 0
+ ASTRA_CONFIG_CHECK(m_pProjector->isInitialized(), "Reconstruction3D", "Projector Object Not Initialized.");
+#endif
+ ASTRA_CONFIG_CHECK(m_pSinogram->isInitialized(), "Reconstruction3D", "Projection Data Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_pReconstruction->isInitialized(), "Reconstruction3D", "Reconstruction Data Object Not Initialized.");
+
+#if 0
+ // check compatibility between projector and data classes
+ ASTRA_CONFIG_CHECK(m_pSinogram->getGeometry()->isEqual(m_pProjector->getProjectionGeometry()), "Reconstruction3D", "Projection Data not compatible with the specified Projector.");
+ ASTRA_CONFIG_CHECK(m_pReconstruction->getGeometry()->isEqual(m_pProjector->getVolumeGeometry()), "Reconstruction3D", "Reconstruction Data not compatible with the specified Projector.");
+#endif
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CReconstructionAlgorithm3D::getInformation()
+{
+ map<string, boost::any> res;
+ res["ProjectorId"] = getInformation("ProjectorId");
+ res["ProjectionDataId"] = getInformation("ProjectionDataId");
+ res["ReconstructionDataId"] = getInformation("ReconstructionDataId");
+ res["UseMinConstraint"] = getInformation("UseMinConstraint");
+ res["MinConstraintValue"] = getInformation("MinConstraintValue");
+ res["UseMaxConstraint"] = getInformation("UseMaxConstraint");
+ res["MaxConstraintValue"] = getInformation("MaxConstraintValue");
+ res["ReconstructionMaskId"] = getInformation("ReconstructionMaskId");
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CReconstructionAlgorithm3D::getInformation(std::string _sIdentifier)
+{
+ if (_sIdentifier == "UseMinConstraint") { return m_bUseMinConstraint ? string("yes") : string("no"); }
+ if (_sIdentifier == "MinConstraintValue") { return m_fMinValue; }
+ if (_sIdentifier == "UseMaxConstraint") { return m_bUseMaxConstraint ? string("yes") : string("no"); }
+ if (_sIdentifier == "MaxConstraintValue") { return m_fMaxValue; }
+#if 0
+ if (_sIdentifier == "ProjectorId") {
+ int iIndex = CProjector3DManager::getSingleton().getIndex(m_pProjector);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+#endif
+ if (_sIdentifier == "ProjectionDataId") {
+ int iIndex = CData3DManager::getSingleton().getIndex(m_pSinogram);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ if (_sIdentifier == "ReconstructionDataId") {
+ int iIndex = CData3DManager::getSingleton().getIndex(m_pReconstruction);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ if (_sIdentifier == "ReconstructionMaskId") {
+ if (!m_bUseReconstructionMask) return string("not used");
+ int iIndex = CData3DManager::getSingleton().getIndex(m_pReconstructionMask);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/ReconstructionAlgorithmMultiSlice2D.cpp b/src/ReconstructionAlgorithmMultiSlice2D.cpp
new file mode 100644
index 0000000..648db61
--- /dev/null
+++ b/src/ReconstructionAlgorithmMultiSlice2D.cpp
@@ -0,0 +1,288 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/ReconstructionAlgorithmMultiSlice2D.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+
+using namespace std;
+
+namespace astra {
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CReconstructionAlgorithmMultiSlice2D::CReconstructionAlgorithmMultiSlice2D()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CReconstructionAlgorithmMultiSlice2D::~CReconstructionAlgorithmMultiSlice2D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CReconstructionAlgorithmMultiSlice2D::_clear()
+{
+ m_pProjector = NULL;
+ m_iSliceCount = 0;
+ m_bUseMinConstraint = false;
+ m_fMinValue = 0.0f;
+ m_bUseMaxConstraint = false;
+ m_fMaxValue = 0.0f;
+ m_bUseReconstructionMask = false;
+ m_pReconstructionMask = NULL;
+ m_bUseSinogramMask = false;
+ m_pSinogramMask = NULL;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CReconstructionAlgorithmMultiSlice2D::clear()
+{
+ m_pProjector = NULL;
+ m_vpSinogram.clear();
+ m_vpReconstruction.clear();
+ m_iSliceCount = 0;
+ m_bUseMinConstraint = false;
+ m_fMinValue = 0.0f;
+ m_bUseMaxConstraint = false;
+ m_fMaxValue = 0.0f;
+ m_bUseReconstructionMask = false;
+ m_pReconstructionMask = NULL;
+ m_bUseSinogramMask = false;
+ m_pSinogramMask = NULL;
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CReconstructionAlgorithmMultiSlice2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("ReconstructionAlgorithmMultiSlice2D", this, _cfg);
+
+ // projector
+ XMLNode* node = _cfg.self->getSingleNode("ProjectorId");
+ ASTRA_CONFIG_CHECK(node, "Reconstruction2D", "No ProjectorId tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pProjector = CProjector2DManager::getSingleton().get(id);
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectorId");
+
+ // sinogram data
+ node = _cfg.self->getSingleNode("ProjectionDataId");
+ ASTRA_CONFIG_CHECK(node, "Reconstruction2D", "No ProjectionDataId tag specified.");
+ vector<float32> tmpvector = node->getContentNumericalArray();
+ for (unsigned int i = 0; i < tmpvector.size(); ++i) {
+ m_vpSinogram.push_back(dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(int(tmpvector[i]))));
+ }
+ m_iSliceCount = tmpvector.size();
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ProjectionDataId");
+
+ // reconstruction data
+ node = _cfg.self->getSingleNode("ReconstructionDataId");
+ ASTRA_CONFIG_CHECK(node, "Reconstruction2D", "No ReconstructionDataId tag specified.");
+ tmpvector = node->getContentNumericalArray();
+ for (unsigned int i = 0; i < tmpvector.size(); ++i) {
+ m_vpReconstruction.push_back(dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(int(tmpvector[i]))));
+ }
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("ReconstructionDataId");
+
+ // reconstruction masks
+ if (_cfg.self->hasOption("ReconstructionMaskId")) {
+ m_bUseReconstructionMask = true;
+ id = boost::lexical_cast<int>(_cfg.self->getOption("ReconstructionMaskId"));
+ m_pReconstructionMask = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));
+ }
+ CC.markOptionParsed("ReconstructionMaskId");
+
+ // sinogram masks
+ if (_cfg.self->hasOption("SinogramMaskId")) {
+ m_bUseSinogramMask = true;
+ id = boost::lexical_cast<int>(_cfg.self->getOption("SinogramMaskId"));
+ m_pSinogramMask = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));
+ }
+ CC.markOptionParsed("SinogramMaskId");
+
+ // Constraints - NEW
+ if (_cfg.self->hasOption("MinConstraint")) {
+ m_bUseMinConstraint = true;
+ m_fMinValue = _cfg.self->getOptionNumerical("MinConstraint", 0.0f);
+ CC.markOptionParsed("MinConstraint");
+ } else {
+ // Constraint - OLD
+ m_bUseMinConstraint = _cfg.self->getOptionBool("UseMinConstraint", false);
+ CC.markOptionParsed("UseMinConstraint");
+ if (m_bUseMinConstraint) {
+ m_fMinValue = _cfg.self->getOptionNumerical("MinConstraintValue", 0.0f);
+ CC.markOptionParsed("MinConstraintValue");
+ }
+ }
+ if (_cfg.self->hasOption("MaxConstraint")) {
+ m_bUseMaxConstraint = true;
+ m_fMaxValue = _cfg.self->getOptionNumerical("MaxConstraint", 255.0f);
+ CC.markOptionParsed("MaxConstraint");
+ } else {
+ // Constraint - OLD
+ m_bUseMaxConstraint = _cfg.self->getOptionBool("UseMaxConstraint", false);
+ CC.markOptionParsed("UseMaxConstraint");
+ if (m_bUseMaxConstraint) {
+ m_fMaxValue = _cfg.self->getOptionNumerical("MaxConstraintValue", 0.0f);
+ CC.markOptionParsed("MaxConstraintValue");
+ }
+ }
+
+ // return success
+ return _check();
+}
+
+//----------------------------------------------------------------------------------------
+// Initialize - C++
+bool CReconstructionAlgorithmMultiSlice2D::initialize(CProjector2D* _pProjector,
+ vector<CFloat32ProjectionData2D*> _vpSinogram,
+ vector<CFloat32VolumeData2D*> _vpReconstruction)
+{
+ m_pProjector = _pProjector;
+ m_vpSinogram = _vpSinogram;
+ m_vpReconstruction = _vpReconstruction;
+ m_iSliceCount = _vpSinogram.size();
+
+ // return success
+ return _check();
+}
+
+//---------------------------------------------------------------------------------------
+// Set Constraints
+void CReconstructionAlgorithmMultiSlice2D::setConstraints(bool _bUseMin, float32 _fMinValue, bool _bUseMax, float32 _fMaxValue)
+{
+ m_bUseMinConstraint = _bUseMin;
+ m_fMinValue = _fMinValue;
+ m_bUseMaxConstraint = _bUseMax;
+ m_fMaxValue = _fMaxValue;
+}
+
+//----------------------------------------------------------------------------------------
+// Set Fixed Reconstruction Mask
+void CReconstructionAlgorithmMultiSlice2D::setReconstructionMask(CFloat32VolumeData2D* _pMask, bool _bEnable)
+{
+ m_bUseReconstructionMask = _bEnable;
+ m_pReconstructionMask = _pMask;
+ if (m_pReconstructionMask == NULL) {
+ m_bUseReconstructionMask = false;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CReconstructionAlgorithmMultiSlice2D::_check()
+{
+ // check projector
+ ASTRA_CONFIG_CHECK(m_pProjector, "ReconstructionMultiSlice2D", "Invalid Projector Object.");
+ ASTRA_CONFIG_CHECK(m_pProjector->isInitialized(), "ReconstructionMultiSlice2D", "Projector Object Not Initialized.");
+
+ // check list
+ ASTRA_CONFIG_CHECK(m_vpSinogram.size() == (unsigned int)m_iSliceCount, "ReconstructionMultiSlice2D", "Sinogram slicecount mismatch.");
+ ASTRA_CONFIG_CHECK(m_vpReconstruction.size() == (unsigned int)m_iSliceCount, "ReconstructionMultiSlice2D", "Volume slicecount mismatch.");
+
+ for (int i = 0; i < m_iSliceCount; ++i) {
+ // pointers
+ ASTRA_CONFIG_CHECK(m_vpSinogram[i], "ReconstructionMultiSlice2D", "Invalid Projection Data Object.");
+ ASTRA_CONFIG_CHECK(m_vpReconstruction[i], "ReconstructionMultiSlice2D", "Invalid Volume Data Object.");
+
+ // initialized
+ ASTRA_CONFIG_CHECK(m_vpSinogram[i]->isInitialized(), "ReconstructionMultiSlice2D", "Projection Data Object Not Initialized.");
+ ASTRA_CONFIG_CHECK(m_vpReconstruction[i]->isInitialized(), "ReconstructionMultiSlice2D", "Volume Data Object Not Initialized.");
+
+ // geometry compatibility
+ ASTRA_CONFIG_CHECK(m_vpSinogram[i]->getGeometry()->isEqual(m_pProjector->getProjectionGeometry()), "Reconstruction2D", "Projection Data not compatible with the specified Projector.");
+ ASTRA_CONFIG_CHECK(m_vpReconstruction[i]->getGeometry()->isEqual(m_pProjector->getVolumeGeometry()), "Reconstruction2D", "Reconstruction Data not compatible with the specified Projector.");
+ }
+
+ // success
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CReconstructionAlgorithmMultiSlice2D::getInformation()
+{
+ map<string, boost::any> res;
+ res["ProjectorId"] = getInformation("ProjectorId");
+// res["ProjectionDataId"] = getInformation("ProjectionDataId");
+// res["ReconstructionDataId"] = getInformation("ReconstructionDataId");
+ res["UseMinConstraint"] = getInformation("UseMinConstraint");
+ res["MinConstraintValue"] = getInformation("MinConstraintValue");
+ res["UseMaxConstraint"] = getInformation("UseMaxConstraint");
+ res["MaxConstraintValue"] = getInformation("MaxConstraintValue");
+ res["ReconstructionMaskId"] = getInformation("ReconstructionMaskId");
+ return mergeMap<string,boost::any>(CAlgorithm::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CReconstructionAlgorithmMultiSlice2D::getInformation(std::string _sIdentifier)
+{
+ if (_sIdentifier == "UseMinConstraint") { return m_bUseMinConstraint ? string("yes") : string("no"); }
+ if (_sIdentifier == "MinConstraintValue") { return m_fMinValue; }
+ if (_sIdentifier == "UseMaxConstraint") { return m_bUseMaxConstraint ? string("yes") : string("no"); }
+ if (_sIdentifier == "MaxConstraintValue") { return m_fMaxValue; }
+ if (_sIdentifier == "ProjectorId") {
+ int iIndex = CProjector2DManager::getSingleton().getIndex(m_pProjector);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+// if (_sIdentifier == "ProjectionDataId") {
+// int iIndex = CData2DManager::getSingleton().getIndex(m_pSinogram);
+// if (iIndex != 0) return iIndex;
+// return std::string("not in manager");
+// }
+// if (_sIdentifier == "ReconstructionDataId") {
+// int iIndex = CData2DManager::getSingleton().getIndex(m_pReconstruction);
+// if (iIndex != 0) return iIndex;
+// return std::string("not in manager");
+// }
+ if (_sIdentifier == "ReconstructionMaskId") {
+ if (!m_bUseReconstructionMask) return string("not used");
+ int iIndex = CData2DManager::getSingleton().getIndex(m_pReconstructionMask);
+ if (iIndex != 0) return iIndex;
+ return std::string("not in manager");
+ }
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/SartAlgorithm.cpp b/src/SartAlgorithm.cpp
new file mode 100644
index 0000000..d898297
--- /dev/null
+++ b/src/SartAlgorithm.cpp
@@ -0,0 +1,452 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/SartAlgorithm.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+
+namespace astra {
+
+#include "astra/Projector2DImpl.inl"
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CSartAlgorithm::type = "SART";
+
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CSartAlgorithm::_clear()
+{
+ CReconstructionAlgorithm2D::_clear();
+ m_piProjectionOrder = NULL;
+ m_iProjectionCount = 0;
+ m_iCurrentProjection = 0;
+ m_bIsInitialized = false;
+ m_iIterationCount = 0;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CSartAlgorithm::clear()
+{
+ CReconstructionAlgorithm2D::clear();
+ if (m_piProjectionOrder) {
+ delete[] m_piProjectionOrder;
+ m_piProjectionOrder = NULL;
+ }
+ m_iProjectionCount = 0;
+ m_iCurrentProjection = 0;
+ m_bIsInitialized = false;
+ m_iIterationCount = 0;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CSartAlgorithm::CSartAlgorithm()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CSartAlgorithm::CSartAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ _clear();
+ initialize(_pProjector, _pSinogram, _pReconstruction);
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CSartAlgorithm::CSartAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int* _piProjectionOrder,
+ int _iProjectionCount)
+{
+ _clear();
+ initialize(_pProjector, _pSinogram, _pReconstruction, _piProjectionOrder, _iProjectionCount);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CSartAlgorithm::~CSartAlgorithm()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CSartAlgorithm::initialize(const Config& _cfg)
+{
+ assert(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("SartAlgorithm", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CReconstructionAlgorithm2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // projection order
+ m_iCurrentProjection = 0;
+ m_iProjectionCount = m_pProjector->getProjectionGeometry()->getProjectionAngleCount();
+ string projOrder = _cfg.self->getOption("ProjectionOrder", "sequential");
+ CC.markOptionParsed("ProjectionOrder");
+ if (projOrder == "sequential") {
+ m_piProjectionOrder = new int[m_iProjectionCount];
+ for (int i = 0; i < m_iProjectionCount; i++) {
+ m_piProjectionOrder[i] = i;
+ }
+ } else if (projOrder == "random") {
+ m_piProjectionOrder = new int[m_iProjectionCount];
+ for (int i = 0; i < m_iProjectionCount; i++) {
+ m_piProjectionOrder[i] = i;
+ }
+ for (int i = 0; i < m_iProjectionCount-1; i++) {
+ int k = (rand() % (m_iProjectionCount - i));
+ int t = m_piProjectionOrder[i];
+ m_piProjectionOrder[i] = m_piProjectionOrder[i + k];
+ m_piProjectionOrder[i + k] = t;
+ }
+ } else if (projOrder == "custom") {
+ vector<float32> projOrderList = _cfg.self->getOptionNumericalArray("ProjectionOrderList");
+ m_piProjectionOrder = new int[projOrderList.size()];
+ for (int i = 0; i < m_iProjectionCount; i++) {
+ m_piProjectionOrder[i] = static_cast<int>(projOrderList[i]);
+ }
+ CC.markOptionParsed("ProjectionOrderList");
+ }
+
+ // create data objects
+ m_pTotalRayLength = new CFloat32ProjectionData2D(m_pProjector->getProjectionGeometry());
+ m_pTotalPixelWeight = new CFloat32VolumeData2D(m_pProjector->getVolumeGeometry());
+ m_pDiffSinogram = new CFloat32ProjectionData2D(m_pProjector->getProjectionGeometry());
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CSartAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ // ray order
+ m_iCurrentProjection = 0;
+ m_iProjectionCount = _pProjector->getProjectionGeometry()->getProjectionAngleCount();
+ m_piProjectionOrder = new int[m_iProjectionCount];
+ for (int i = 0; i < m_iProjectionCount; i++) {
+ m_piProjectionOrder[i] = i;
+ }
+
+ // create data objects
+ m_pTotalRayLength = new CFloat32ProjectionData2D(m_pProjector->getProjectionGeometry());
+ m_pTotalPixelWeight = new CFloat32VolumeData2D(m_pProjector->getVolumeGeometry());
+ m_pDiffSinogram = new CFloat32ProjectionData2D(m_pProjector->getProjectionGeometry());
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CSartAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int* _piProjectionOrder,
+ int _iProjectionCount)
+{
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ // ray order
+ m_iCurrentProjection = 0;
+ m_iProjectionCount = _iProjectionCount;
+ m_piProjectionOrder = new int[m_iProjectionCount];
+ for (int i = 0; i < m_iProjectionCount; i++) {
+ m_piProjectionOrder[i] = _piProjectionOrder[i];
+ }
+
+ // create data objects
+ m_pTotalRayLength = new CFloat32ProjectionData2D(m_pProjector->getProjectionGeometry());
+ m_pTotalPixelWeight = new CFloat32VolumeData2D(m_pProjector->getVolumeGeometry());
+ m_pDiffSinogram = new CFloat32ProjectionData2D(m_pProjector->getProjectionGeometry());
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+bool CSartAlgorithm::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CReconstructionAlgorithm2D::_check(), "SART", "Error in ReconstructionAlgorithm2D initialization");
+
+ // check projection order all within range
+ for (int i = 0; i < m_iProjectionCount; ++i) {
+ ASTRA_CONFIG_CHECK(0 <= m_piProjectionOrder[i] && m_piProjectionOrder[i] < m_pProjector->getProjectionGeometry()->getProjectionAngleCount(), "SART", "Projection Order out of range.");
+ }
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CSartAlgorithm::getInformation()
+{
+ map<string, boost::any> res;
+ res["ProjectionOrder"] = getInformation("ProjectionOrder");
+ return mergeMap<string,boost::any>(CReconstructionAlgorithm2D::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CSartAlgorithm::getInformation(std::string _sIdentifier)
+{
+ if (_sIdentifier == "ProjectionOrder") {
+ vector<float32> res;
+ for (int i = 0; i < m_iProjectionCount; i++) {
+ res.push_back(m_piProjectionOrder[i]);
+ }
+ return res;
+ }
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CSartAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ m_bShouldAbort = false;
+
+ int iIteration = 0;
+
+ // data projectors
+ CDataProjectorInterface* pForwardProjector;
+ CDataProjectorInterface* pBackProjector;
+
+ m_pTotalRayLength->setData(0.0f);
+ m_pTotalPixelWeight->setData(0.0f);
+
+ // backprojection data projector
+ pBackProjector = dispatchDataProjector(
+ m_pProjector,
+ SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
+ SIRTBPPolicy(m_pReconstruction, m_pDiffSinogram, m_pTotalPixelWeight, m_pTotalRayLength), // SIRT backprojection
+ m_bUseSinogramMask, m_bUseReconstructionMask, true // options on/off
+ );
+
+ // first time forward projection data projector,
+ // also computes total pixel weight and total ray length
+ pForwardProjector = dispatchDataProjector(
+ m_pProjector,
+ SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
+ Combine3Policy<DiffFPPolicy, TotalPixelWeightPolicy, TotalRayLengthPolicy>( // 3 basic operations
+ DiffFPPolicy(m_pReconstruction, m_pDiffSinogram, m_pSinogram), // forward projection with difference calculation
+ TotalPixelWeightPolicy(m_pTotalPixelWeight), // calculate the total pixel weights
+ TotalRayLengthPolicy(m_pTotalRayLength)), // calculate the total ray lengths
+ m_bUseSinogramMask, m_bUseReconstructionMask, true // options on/off
+ );
+
+
+
+ // iteration loop
+ for (; iIteration < _iNrIterations && !m_bShouldAbort; ++iIteration) {
+
+ int iProjection = m_piProjectionOrder[m_iIterationCount % m_iProjectionCount];
+
+ // forward projection and difference calculation
+ m_pTotalPixelWeight->setData(0.0f);
+ pForwardProjector->projectSingleProjection(iProjection);
+ // backprojection
+ pBackProjector->projectSingleProjection(iProjection);
+ // update iteration count
+ m_iIterationCount++;
+
+ if (m_bUseMinConstraint)
+ m_pReconstruction->clampMin(m_fMinValue);
+ if (m_bUseMaxConstraint)
+ m_pReconstruction->clampMax(m_fMaxValue);
+ }
+
+
+ ASTRA_DELETE(pForwardProjector);
+ ASTRA_DELETE(pBackProjector);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ //// check initialized
+ // ASTRA_ASSERT(m_bIsInitialized);
+
+ //// variables
+ //int iIteration, iDetector;
+ //int baseIndex, iPixel;
+ //float32* pfGamma = new float32[m_pReconstruction->getSize()];
+ //float32* pfBeta = new float32[m_pProjector->getProjectionGeometry()->getDetectorCount()];
+ //float32* pfProjectionDiff = new float32[m_pProjector->getProjectionGeometry()->getDetectorCount()];
+
+ //// ITERATE
+ //for (iIteration = _iNrIterations-1; iIteration >= 0; --iIteration) {
+ //
+ // // reset gamma
+ // memset(pfGamma, 0, sizeof(float32) * m_pReconstruction->getSize());
+ // memset(pfBeta, 0, sizeof(float32) * m_pProjector->getProjectionGeometry()->getDetectorCount());
+ //
+ // // get current projection angle
+ // int iProjection = m_piProjectionOrder[m_iCurrentProjection];
+ // m_iCurrentProjection = (m_iCurrentProjection + 1) % m_iProjectionCount;
+ // int iProjectionWeightCount = m_pProjector->getProjectionWeightsCount(iProjection);
+ //
+ // // allocate memory for the pixel buffer
+ // SPixelWeight* pPixels = new SPixelWeight[m_pProjector->getProjectionWeightsCount(iProjection) * m_pProjector->getProjectionGeometry()->getDetectorCount()];
+ // int* piRayStoredPixelCount = new int[m_pProjector->getProjectionGeometry()->getDetectorCount()];
+
+ // // compute weights for this projection
+ // m_pProjector->computeProjectionRayWeights(iProjection, pPixels, piRayStoredPixelCount);
+ //
+ // // calculate projection difference in each detector
+ // for (iDetector = m_pProjector->getProjectionGeometry()->getDetectorCount()-1; iDetector >= 0; --iDetector) {
+
+ // if (m_bUseSinogramMask && m_pSinogramMask->getData2D()[iProjection][iDetector] == 0) continue;
+
+ // // index base of the pixel in question
+ // baseIndex = iDetector * iProjectionWeightCount;
+ //
+ // // set the initial projection difference to the sinogram value
+ // pfProjectionDiff[iDetector] = m_pSinogram->getData2DConst()[iProjection][iDetector];
+ //
+ // // update projection difference, beta and gamma
+ // for (iPixel = piRayStoredPixelCount[iDetector]-1; iPixel >= 0; --iPixel) {
+
+ // // pixel must be loose
+ // if (m_bUseReconstructionMask && m_pReconstructionMask->getData()[pPixels[baseIndex+iPixel].m_iIndex] == 0) continue;
+
+ // // subtract projection value from projection difference
+ // pfProjectionDiff[iDetector] -=
+ // pPixels[baseIndex+iPixel].m_fWeight * m_pReconstruction->getDataConst()[pPixels[baseIndex+iPixel].m_iIndex];
+ //
+ // // update beta and gamma if this pixel lies inside a loose part
+ // pfBeta[iDetector] += pPixels[baseIndex+iPixel].m_fWeight;
+ // pfGamma[pPixels[baseIndex+iPixel].m_iIndex] += pPixels[baseIndex+iPixel].m_fWeight;
+ // }
+ //
+ // }
+ //
+ // // back projection
+ // for (iDetector = m_pProjector->getProjectionGeometry()->getDetectorCount()-1; iDetector >= 0; --iDetector) {
+ //
+ // if (m_bUseSinogramMask && m_pSinogramMask->getData2D()[iProjection][iDetector] == 0) continue;
+
+ // // index base of the pixel in question
+ // baseIndex = iDetector * iProjectionWeightCount;
+
+ // // update pixel values
+ // for (iPixel = piRayStoredPixelCount[iDetector]-1; iPixel >= 0; --iPixel) {
+
+ //
+ // // pixel must be loose
+ // if (m_bUseReconstructionMask && m_pReconstructionMask->getData()[pPixels[baseIndex+iPixel].m_iIndex] == 0) continue;
+
+ //
+
+ // // update reconstruction volume
+ // float32 fGammaBeta = pfGamma[pPixels[baseIndex+iPixel].m_iIndex] * pfBeta[iDetector];
+ // if ((fGammaBeta > 0.01f) || (fGammaBeta < -0.01f)) {
+ // m_pReconstruction->getData()[pPixels[baseIndex+iPixel].m_iIndex] +=
+ // pPixels[baseIndex+iPixel].m_fWeight * pfProjectionDiff[iDetector] / fGammaBeta;
+ // }
+
+ // // constraints
+ // if (m_bUseMinConstraint && m_pReconstruction->getData()[pPixels[baseIndex+iPixel].m_iIndex] < m_fMinValue) {
+ // m_pReconstruction->getData()[pPixels[baseIndex+iPixel].m_iIndex] = m_fMinValue;
+ // }
+ // if (m_bUseMaxConstraint && m_pReconstruction->getData()[pPixels[baseIndex+iPixel].m_iIndex] > m_fMaxValue) {
+ // m_pReconstruction->getData()[pPixels[baseIndex+iPixel].m_iIndex] = m_fMaxValue;
+ // }
+ // }
+ // }
+ //
+ // // garbage disposal
+ // delete[] pPixels;
+ // delete[] piRayStoredPixelCount;
+ //}
+
+ //// garbage disposal
+ //delete[] pfGamma;
+ //delete[] pfBeta;
+ //delete[] pfProjectionDiff;
+
+ //// update statistics
+ //m_pReconstruction->updateStatistics();
+}
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/SirtAlgorithm.cpp b/src/SirtAlgorithm.cpp
new file mode 100644
index 0000000..60cee8a
--- /dev/null
+++ b/src/SirtAlgorithm.cpp
@@ -0,0 +1,321 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/SirtAlgorithm.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "astra/AstraObjectManager.h"
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+
+namespace astra {
+
+#include "astra/Projector2DImpl.inl"
+
+// type of the algorithm, needed to register with CAlgorithmFactory
+std::string CSirtAlgorithm::type = "SIRT";
+
+//----------------------------------------------------------------------------------------
+// Constructor
+CSirtAlgorithm::CSirtAlgorithm()
+{
+ _clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+CSirtAlgorithm::CSirtAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ _clear();
+ initialize(_pProjector, _pSinogram, _pReconstruction);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+CSirtAlgorithm::~CSirtAlgorithm()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CSirtAlgorithm::_clear()
+{
+ CReconstructionAlgorithm2D::_clear();
+ m_bIsInitialized = false;
+
+ m_pTotalRayLength = NULL;
+ m_pTotalPixelWeight = NULL;
+ m_pDiffSinogram = NULL;
+ m_pTmpVolume = NULL;
+
+ m_iIterationCount = 0;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CSirtAlgorithm::clear()
+{
+ CReconstructionAlgorithm2D::_clear();
+ m_bIsInitialized = false;
+
+ ASTRA_DELETE(m_pTotalRayLength);
+ ASTRA_DELETE(m_pTotalPixelWeight);
+ ASTRA_DELETE(m_pDiffSinogram);
+ ASTRA_DELETE(m_pTmpVolume);
+
+ m_iIterationCount = 0;
+}
+
+//----------------------------------------------------------------------------------------
+// Check
+bool CSirtAlgorithm::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CReconstructionAlgorithm2D::_check(), "SIRT", "Error in ReconstructionAlgorithm2D initialization");
+
+ ASTRA_CONFIG_CHECK(m_pTotalRayLength, "SIRT", "Invalid TotalRayLength Object");
+ ASTRA_CONFIG_CHECK(m_pTotalRayLength->isInitialized(), "SIRT", "Invalid TotalRayLength Object");
+ ASTRA_CONFIG_CHECK(m_pTotalPixelWeight, "SIRT", "Invalid TotalPixelWeight Object");
+ ASTRA_CONFIG_CHECK(m_pTotalPixelWeight->isInitialized(), "SIRT", "Invalid TotalPixelWeight Object");
+ ASTRA_CONFIG_CHECK(m_pDiffSinogram, "SIRT", "Invalid DiffSinogram Object");
+ ASTRA_CONFIG_CHECK(m_pDiffSinogram->isInitialized(), "SIRT", "Invalid DiffSinogram Object");
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CSirtAlgorithm::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CAlgorithm> CC("SirtAlgorithm", this, _cfg);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CReconstructionAlgorithm2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // init data objects and data projectors
+ _init();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - C++
+bool CSirtAlgorithm::initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // required classes
+ m_pProjector = _pProjector;
+ m_pSinogram = _pSinogram;
+ m_pReconstruction = _pReconstruction;
+
+ // init data objects and data projectors
+ _init();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize Data Projectors - private
+void CSirtAlgorithm::_init()
+{
+ // create data objects
+ m_pTotalRayLength = new CFloat32ProjectionData2D(m_pProjector->getProjectionGeometry());
+ m_pTotalPixelWeight = new CFloat32VolumeData2D(m_pProjector->getVolumeGeometry());
+ m_pDiffSinogram = new CFloat32ProjectionData2D(m_pProjector->getProjectionGeometry());
+ m_pTmpVolume = new CFloat32VolumeData2D(m_pProjector->getVolumeGeometry());
+}
+
+//---------------------------------------------------------------------------------------
+// Information - All
+map<string,boost::any> CSirtAlgorithm::getInformation()
+{
+ map<string, boost::any> res;
+ return mergeMap<string,boost::any>(CReconstructionAlgorithm2D::getInformation(), res);
+};
+
+//---------------------------------------------------------------------------------------
+// Information - Specific
+boost::any CSirtAlgorithm::getInformation(std::string _sIdentifier)
+{
+ return CAlgorithm::getInformation(_sIdentifier);
+};
+
+//----------------------------------------------------------------------------------------
+// Iterate
+void CSirtAlgorithm::run(int _iNrIterations)
+{
+ // check initialized
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ m_bShouldAbort = false;
+
+ int iIteration = 0;
+
+ // data projectors
+ CDataProjectorInterface* pForwardProjector;
+ CDataProjectorInterface* pBackProjector;
+ CDataProjectorInterface* pFirstForwardProjector;
+
+ m_pTotalRayLength->setData(0.0f);
+ m_pTotalPixelWeight->setData(0.0f);
+
+ // forward projection data projector
+ pForwardProjector = dispatchDataProjector(
+ m_pProjector,
+ SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
+ DiffFPPolicy(m_pReconstruction, m_pDiffSinogram, m_pSinogram), // forward projection with difference calculation
+ m_bUseSinogramMask, m_bUseReconstructionMask, true // options on/off
+ );
+
+ // backprojection data projector
+ pBackProjector = dispatchDataProjector(
+ m_pProjector,
+ SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
+ DefaultBPPolicy(m_pTmpVolume, m_pDiffSinogram), // backprojection
+ m_bUseSinogramMask, m_bUseReconstructionMask, true // options on/off
+ );
+
+ // first time forward projection data projector,
+ // also computes total pixel weight and total ray length
+ pFirstForwardProjector = dispatchDataProjector(
+ m_pProjector,
+ SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
+ Combine3Policy<DiffFPPolicy, TotalPixelWeightPolicy, TotalRayLengthPolicy>( // 3 basic operations
+ DiffFPPolicy(m_pReconstruction, m_pDiffSinogram, m_pSinogram), // forward projection with difference calculation
+ TotalPixelWeightPolicy(m_pTotalPixelWeight), // calculate the total pixel weights
+ TotalRayLengthPolicy(m_pTotalRayLength)), // calculate the total ray lengths
+ m_bUseSinogramMask, m_bUseReconstructionMask, true // options on/off
+ );
+
+
+
+ // forward projection, difference calculation and raylength/pixelweight computation
+ pFirstForwardProjector->project();
+
+ float32* pfT = m_pTotalPixelWeight->getData();
+ for (int i = 0; i < m_pTotalPixelWeight->getSize(); ++i) {
+ float32 x = pfT[i];
+ if (x < -eps || x > eps)
+ x = 1.0f / x;
+ else
+ x = 0.0f;
+ pfT[i] = x;
+ }
+ pfT = m_pTotalRayLength->getData();
+ for (int i = 0; i < m_pTotalRayLength->getSize(); ++i) {
+ float32 x = pfT[i];
+ if (x < -eps || x > eps)
+ x = 1.0f / x;
+ else
+ x = 0.0f;
+ pfT[i] = x;
+ }
+
+ // divide by line weights
+ (*m_pDiffSinogram) *= (*m_pTotalRayLength);
+
+ // backprojection
+ m_pTmpVolume->setData(0.0f);
+ pBackProjector->project();
+
+ // divide by pixel weights
+ (*m_pTmpVolume) *= (*m_pTotalPixelWeight);
+ (*m_pReconstruction) += (*m_pTmpVolume);
+
+ if (m_bUseMinConstraint)
+ m_pReconstruction->clampMin(m_fMinValue);
+ if (m_bUseMaxConstraint)
+ m_pReconstruction->clampMax(m_fMaxValue);
+
+ // update iteration count
+ m_iIterationCount++;
+ iIteration++;
+
+
+
+
+ // iteration loop
+ for (; iIteration < _iNrIterations && !m_bShouldAbort; ++iIteration) {
+ // forward projection and difference calculation
+ pForwardProjector->project();
+
+ // divide by line weights
+ (*m_pDiffSinogram) *= (*m_pTotalRayLength);
+
+
+ // backprojection
+ m_pTmpVolume->setData(0.0f);
+ pBackProjector->project();
+
+ // divide by pixel weights
+ (*m_pTmpVolume) *= (*m_pTotalPixelWeight);
+ (*m_pReconstruction) += (*m_pTmpVolume);
+
+ if (m_bUseMinConstraint)
+ m_pReconstruction->clampMin(m_fMinValue);
+ if (m_bUseMaxConstraint)
+ m_pReconstruction->clampMax(m_fMaxValue);
+
+ // update iteration count
+ m_iIterationCount++;
+ }
+
+
+ ASTRA_DELETE(pForwardProjector);
+ ASTRA_DELETE(pBackProjector);
+ ASTRA_DELETE(pFirstForwardProjector);
+}
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/SparseMatrix.cpp b/src/SparseMatrix.cpp
new file mode 100644
index 0000000..e6d115f
--- /dev/null
+++ b/src/SparseMatrix.cpp
@@ -0,0 +1,91 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include <sstream>
+
+#include "astra/Globals.h"
+#include "astra/SparseMatrix.h"
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// constructor
+
+CSparseMatrix::CSparseMatrix()
+{
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// constructor
+CSparseMatrix::CSparseMatrix(unsigned int _iHeight, unsigned int _iWidth,
+ unsigned long _lSize)
+{
+ initialize(_iHeight, _iWidth, _lSize);
+}
+
+
+//----------------------------------------------------------------------------------------
+// destructor
+CSparseMatrix::~CSparseMatrix()
+{
+ delete[] m_pfValues;
+ delete[] m_piColIndices;
+ delete[] m_plRowStarts;
+}
+
+//----------------------------------------------------------------------------------------
+// initialize
+bool CSparseMatrix::initialize(unsigned int _iHeight, unsigned int _iWidth,
+ unsigned long _lSize)
+{
+ m_iHeight = _iHeight;
+ m_iWidth = _iWidth;
+ m_lSize = _lSize;
+
+ m_pfValues = new float32[_lSize];
+ m_piColIndices = new unsigned int[_lSize];
+ m_plRowStarts = new unsigned long[_iHeight+1];
+ m_bInitialized = true;
+
+ return m_bInitialized;
+}
+
+
+std::string CSparseMatrix::description() const
+{
+ std::stringstream res;
+ res << m_iHeight << "x" << m_iWidth << " sparse matrix";
+ return res.str();
+}
+
+
+
+
+} // end namespace
diff --git a/src/SparseMatrixProjectionGeometry2D.cpp b/src/SparseMatrixProjectionGeometry2D.cpp
new file mode 100644
index 0000000..b95bbf4
--- /dev/null
+++ b/src/SparseMatrixProjectionGeometry2D.cpp
@@ -0,0 +1,203 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/SparseMatrixProjectionGeometry2D.h"
+
+#include <boost/lexical_cast.hpp>
+#include "astra/AstraObjectManager.h"
+
+
+using namespace std;
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CSparseMatrixProjectionGeometry2D::CSparseMatrixProjectionGeometry2D() :
+ CProjectionGeometry2D()
+{
+ m_pMatrix = 0;
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CSparseMatrixProjectionGeometry2D::CSparseMatrixProjectionGeometry2D(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ const CSparseMatrix* _pMatrix)
+{
+ _clear();
+ initialize(_iProjectionAngleCount,
+ _iDetectorCount,
+ _pMatrix);
+}
+
+//----------------------------------------------------------------------------------------
+CSparseMatrixProjectionGeometry2D::CSparseMatrixProjectionGeometry2D(const CSparseMatrixProjectionGeometry2D& _projGeom)
+{
+ _clear();
+ initialize(_projGeom.m_iProjectionAngleCount,
+ _projGeom.m_iDetectorCount,
+ _projGeom.m_pMatrix);
+}
+
+//----------------------------------------------------------------------------------------
+
+CSparseMatrixProjectionGeometry2D& CSparseMatrixProjectionGeometry2D::operator=(const CSparseMatrixProjectionGeometry2D& _other)
+{
+ m_bInitialized = _other.m_bInitialized;
+ if (_other.m_bInitialized) {
+ m_pMatrix = _other.m_pMatrix;
+ m_iDetectorCount = _other.m_iDetectorCount;
+ m_fDetectorWidth = _other.m_fDetectorWidth;
+ }
+ return *this;
+
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CSparseMatrixProjectionGeometry2D::~CSparseMatrixProjectionGeometry2D()
+{
+ m_pMatrix = 0;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize - Config
+bool CSparseMatrixProjectionGeometry2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CProjectionGeometry2D> CC("SparseMatrixProjectionGeometry2D", this, _cfg);
+
+ // initialization of parent class
+ CProjectionGeometry2D::initialize(_cfg);
+
+ // get matrix
+ XMLNode* node = _cfg.self->getSingleNode("MatrixID");
+ ASTRA_CONFIG_CHECK(node, "SparseMatrixProjectionGeometry2D", "No MatrixID tag specified.");
+ int id = boost::lexical_cast<int>(node->getContent());
+ m_pMatrix = CMatrixManager::getSingleton().get(id);
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("MatrixID");
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CSparseMatrixProjectionGeometry2D::initialize(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ const CSparseMatrix* _pMatrix)
+{
+ if (m_bInitialized) {
+ clear();
+ }
+
+ m_iProjectionAngleCount = _iProjectionAngleCount;
+ m_iDetectorCount = _iDetectorCount;
+
+ // FIXME: We should probably require these for consistency?
+ m_fDetectorWidth = 1.0f;
+ m_pfProjectionAngles = new float32[m_iProjectionAngleCount];
+ for (int i = 0; i < m_iProjectionAngleCount; ++i)
+ m_pfProjectionAngles[i] = 0.0f;
+
+ m_pMatrix = _pMatrix;
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Check.
+bool CSparseMatrixProjectionGeometry2D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CProjectionGeometry2D::_check(), "SparseMatrixProjectionGeometry2D", "Error in ProjectionGeometry2D initialization");
+
+ ASTRA_CONFIG_CHECK(m_pMatrix, "SparseMatrixProjectionGeometry2D", "No matrix specified");
+
+ ASTRA_CONFIG_CHECK(m_pMatrix->m_iHeight == (unsigned int)(m_iProjectionAngleCount * m_iDetectorCount), "SparseMatrixProjectionGeometry2D", "Matrix height doesn't match projection geometry");
+
+ return true;
+}
+
+
+//----------------------------------------------------------------------------------------
+// Clone
+CProjectionGeometry2D* CSparseMatrixProjectionGeometry2D::clone()
+{
+ return new CSparseMatrixProjectionGeometry2D(*this);
+}
+
+//----------------------------------------------------------------------------------------
+// is equal
+bool CSparseMatrixProjectionGeometry2D::isEqual(CProjectionGeometry2D* _pGeom2) const
+{
+ if (_pGeom2 == NULL) return false;
+
+ // try to cast argument to CSparseMatrixProjectionGeometry2D
+ CSparseMatrixProjectionGeometry2D* pGeom2 = dynamic_cast<CSparseMatrixProjectionGeometry2D*>(_pGeom2);
+ if (pGeom2 == NULL) return false;
+
+ // both objects must be initialized
+ if (!m_bInitialized || !pGeom2->m_bInitialized) return false;
+
+ // check all values
+ if (m_iProjectionAngleCount != pGeom2->m_iProjectionAngleCount) return false;
+ if (m_iDetectorCount != pGeom2->m_iDetectorCount) return false;
+ if (m_fDetectorWidth != pGeom2->m_fDetectorWidth) return false;
+
+ // Maybe check equality of matrices by element?
+ if (m_pMatrix != pGeom2->m_pMatrix) return false;
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// is of type
+bool CSparseMatrixProjectionGeometry2D::isOfType(const std::string& _sType)
+{
+ return (_sType == "sparse_matrix");
+}
+//----------------------------------------------------------------------------------------
+
+CVector3D CSparseMatrixProjectionGeometry2D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex)
+{
+ CVector3D vOutput(0.0f, 0.0f, 0.0f);
+
+ // not implemented, yet
+ ASTRA_ASSERT(false);
+
+ return vOutput;
+}
+
+} // end namespace astra
diff --git a/src/SparseMatrixProjector2D.cpp b/src/SparseMatrixProjector2D.cpp
new file mode 100644
index 0000000..ba3a46b
--- /dev/null
+++ b/src/SparseMatrixProjector2D.cpp
@@ -0,0 +1,219 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/SparseMatrixProjector2D.h"
+
+#include <cmath>
+#include <boost/lexical_cast.hpp>
+
+#include "astra/DataProjectorPolicies.h"
+
+using namespace std;
+using namespace astra;
+
+#include "astra/SparseMatrixProjector2D.inl"
+
+// type of the projector, needed to register with CProjectorFactory
+std::string CSparseMatrixProjector2D::type = "sparse_matrix";
+
+//----------------------------------------------------------------------------------------
+// default constructor
+CSparseMatrixProjector2D::CSparseMatrixProjector2D()
+{
+ _clear();
+}
+
+//----------------------------------------------------------------------------------------
+// constructor
+CSparseMatrixProjector2D::CSparseMatrixProjector2D(CSparseMatrixProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry)
+
+{
+ _clear();
+ initialize(_pProjectionGeometry, _pReconstructionGeometry);
+}
+
+//----------------------------------------------------------------------------------------
+// destructor
+CSparseMatrixProjector2D::~CSparseMatrixProjector2D()
+{
+ clear();
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Constructors
+void CSparseMatrixProjector2D::_clear()
+{
+ CProjector2D::_clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Clear - Public
+void CSparseMatrixProjector2D::clear()
+{
+ CProjector2D::clear();
+ m_bIsInitialized = false;
+}
+
+//---------------------------------------------------------------------------------------
+// Check
+bool CSparseMatrixProjector2D::_check()
+{
+ // check base class
+ ASTRA_CONFIG_CHECK(CProjector2D::_check(), "SparseMatrixProjector2D", "Error in Projector2D initialization");
+
+ ASTRA_CONFIG_CHECK(m_pVolumeGeometry->isInitialized(), "SparseMatrixProjector2D", "Volume geometry not initialized");
+ ASTRA_CONFIG_CHECK(m_pProjectionGeometry->isInitialized(), "SparseMatrixProjector2D", "Projection geometry not initialized");
+
+
+ ASTRA_CONFIG_CHECK(dynamic_cast<CSparseMatrixProjectionGeometry2D*>(m_pProjectionGeometry), "SparseMatrixProjector2D", "Unsupported projection geometry");
+
+ const CSparseMatrix* pMatrix = dynamic_cast<CSparseMatrixProjectionGeometry2D*>(m_pProjectionGeometry)->getMatrix();
+ ASTRA_CONFIG_CHECK(pMatrix, "SparseMatrixProjector2D", "No matrix specified in projection geometry");
+
+ ASTRA_CONFIG_CHECK(pMatrix->m_iWidth == (unsigned int)m_pVolumeGeometry->getGridTotCount(), "SparseMatrixProjector2D", "Matrix width doesn't match volume geometry");
+
+ return true;
+}
+
+
+//---------------------------------------------------------------------------------------
+// Initialize, use a Config object
+bool CSparseMatrixProjector2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // initialization of parent class
+ if (!CProjector2D::initialize(_cfg)) {
+ return false;
+ }
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+//---------------------------------------------------------------------------------------
+// Initialize
+bool CSparseMatrixProjector2D::initialize(CSparseMatrixProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pVolumeGeometry)
+{
+ // if already initialized, clear first
+ if (m_bIsInitialized) {
+ clear();
+ }
+
+ // hardcopy geometries
+ m_pProjectionGeometry = _pProjectionGeometry->clone();
+ m_pVolumeGeometry = _pVolumeGeometry->clone();
+
+ // success
+ m_bIsInitialized = _check();
+ return m_bIsInitialized;
+}
+
+
+//----------------------------------------------------------------------------------------
+// Get maximum amount of weights on a single ray
+int CSparseMatrixProjector2D::getProjectionWeightsCount(int _iProjectionIndex)
+{
+ const CSparseMatrix* pMatrix = dynamic_cast<CSparseMatrixProjectionGeometry2D*>(m_pProjectionGeometry)->getMatrix();
+
+ unsigned int iMax = 0;
+ unsigned long lSize = m_pProjectionGeometry->getDetectorCount();
+ lSize *= m_pProjectionGeometry->getProjectionAngleCount();
+ for (unsigned long i = 0; i < lSize; ++i) {
+ unsigned int iRowSize = pMatrix->getRowSize(i);
+ if (iRowSize > iMax)
+ iMax = pMatrix->getRowSize(i);
+ }
+ return iMax;
+}
+
+//----------------------------------------------------------------------------------------
+// Single Ray Weights
+void CSparseMatrixProjector2D::computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount)
+{
+ // TODO: Move this default implementation to Projector2D?
+ ASTRA_ASSERT(m_bIsInitialized);
+ StorePixelWeightsPolicy p(_pWeightedPixels, _iMaxPixelCount);
+ projectSingleRay(_iProjectionIndex, _iDetectorIndex, p);
+ _iStoredPixelCount = p.getStoredPixelCount();
+}
+
+//----------------------------------------------------------------------------------------
+// Splat a single point
+std::vector<SDetector2D> CSparseMatrixProjector2D::projectPoint(int _iRow, int _iCol)
+{
+ unsigned int iVolumeIndex = _iCol * m_pVolumeGeometry->getGridRowCount() + _iRow;
+
+ // NOTE: This is very slow currently because we don't have the
+ // sparse matrix stored in an appropriate form for this function.
+ std::vector<SDetector2D> ret;
+
+ const CSparseMatrix* pMatrix = dynamic_cast<CSparseMatrixProjectionGeometry2D*>(m_pProjectionGeometry)->getMatrix();
+
+ for (int iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle)
+ {
+ for (int iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector)
+ {
+ int iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector;
+ const unsigned int* piColIndices;
+ const float32* pfValues;
+ unsigned int iSize;
+
+ pMatrix->getRowData(iRayIndex, iSize, pfValues, piColIndices);
+
+ for (unsigned int i = 0; i < iSize; ++i) {
+ if (piColIndices[i] == iVolumeIndex) {
+ SDetector2D s;
+ s.m_iIndex = iRayIndex;
+ s.m_iAngleIndex = iAngle;
+ s.m_iDetectorIndex = iDetector;
+ ret.push_back(s);
+ break;
+ } else if (piColIndices[i] > iVolumeIndex) {
+ break;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+//----------------------------------------------------------------------------------------
diff --git a/src/Utilities.cpp b/src/Utilities.cpp
new file mode 100644
index 0000000..94992a9
--- /dev/null
+++ b/src/Utilities.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/Utilities.h"
+
+using namespace std;
+using namespace astra;
+
+//-----------------------------------------------------------------------------
+// Trim Whitespace Characters
+void StringUtil::trim(std::string& _sString, bool _bLeft, bool _bRight)
+{
+ // trim right
+ if (_bRight)
+ _sString.erase(_sString.find_last_not_of(" \t\r") + 1);
+
+ // trim left
+ if (_bLeft)
+ _sString.erase(0, _sString.find_first_not_of(" \t\r"));
+}
+//-----------------------------------------------------------------------------
+// Split String
+vector<string> StringUtil::split(const string& _sString, const string& _sDelims)
+{
+ std::vector<string> ret;
+
+ size_t start, pos;
+ start = 0;
+ do {
+ pos = _sString.find_first_of(_sDelims, start);
+ if (pos == start) {
+ // Do nothing
+ start = pos + 1;
+ } else if (pos == string::npos) {
+ // Copy the rest of the string
+ ret.push_back(_sString.substr(start));
+ break;
+ } else {
+ // Copy up to newt delimiter
+ ret.push_back(_sString.substr(start, pos - start));
+ start = pos + 1;
+ }
+
+ // Parse up to next real data (in case there are two delims after each other)
+ start = _sString.find_first_not_of(_sDelims, start);
+ } while (pos != string::npos);
+
+ return ret;
+}
+//-----------------------------------------------------------------------------
+// Cast string to int
+bool StringUtil::toInt(const string& _sString, int& _iValue)
+{
+ std::istringstream ss(_sString);
+ ss >> _iValue;
+ return !ss.fail();
+}
+//-----------------------------------------------------------------------------
+// Cast string to float
+bool StringUtil::toFloat32(const string& _sString, float32& _fValue)
+{
+ std::istringstream ss(_sString);
+ ss >> _fValue;
+ return !ss.fail();
+}
+//-----------------------------------------------------------------------------
+// Convert string to Lower Case
+void StringUtil::toLowerCase(std::string& _sString)
+{
+ std::transform(_sString.begin(),
+ _sString.end(),
+ _sString.begin(),
+ ::tolower);
+}
+//-----------------------------------------------------------------------------
+// Convert string to Upper Case
+void StringUtil::toUpperCase(std::string& _sString)
+{
+ std::transform(_sString.begin(),
+ _sString.end(),
+ _sString.begin(),
+ ::toupper);
+}
+//-----------------------------------------------------------------------------
+
+
+
+
+//-----------------------------------------------------------------------------
+// Get Extension
+string FileSystemUtil::getExtension(string& _sFilename)
+{
+ string sExtension = "";
+ for (int i = _sFilename.length() - 1; 0 < i; i--) {
+ if (_sFilename[i] == '.') {
+ std::transform(sExtension.begin(),sExtension.end(),sExtension.begin(),::tolower);
+ return sExtension;
+ }
+ sExtension = _sFilename[i] + sExtension;
+ }
+ return "";
+}
+//-----------------------------------------------------------------------------
diff --git a/src/Vector3D.cpp b/src/Vector3D.cpp
new file mode 100644
index 0000000..1e571b1
--- /dev/null
+++ b/src/Vector3D.cpp
@@ -0,0 +1,29 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "../include/astra/Vector3D.h"
diff --git a/src/VolumeGeometry2D.cpp b/src/VolumeGeometry2D.cpp
new file mode 100644
index 0000000..01d9b9a
--- /dev/null
+++ b/src/VolumeGeometry2D.cpp
@@ -0,0 +1,282 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/VolumeGeometry2D.h"
+
+#include <boost/lexical_cast.hpp>
+#include <cmath>
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Check all variable values
+bool CVolumeGeometry2D::_check()
+{
+ ASTRA_CONFIG_CHECK(m_iGridColCount > 0, "VolumeGeometry2D", "GridColCount must be strictly positive.");
+ ASTRA_CONFIG_CHECK(m_iGridRowCount > 0, "VolumeGeometry2D", "GridRowCount must be strictly positive.");
+ ASTRA_CONFIG_CHECK(m_fWindowMinX < m_fWindowMaxX, "VolumeGeometry2D", "WindowMinX should be lower than WindowMaxX.");
+ ASTRA_CONFIG_CHECK(m_fWindowMinY < m_fWindowMaxY, "VolumeGeometry2D", "WindowMinY should be lower than WindowMaxY.");
+
+ ASTRA_CONFIG_CHECK(m_iGridTotCount == (m_iGridColCount * m_iGridRowCount), "VolumeGeometry2D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fWindowLengthX == (m_fWindowMaxX - m_fWindowMinX), "VolumeGeometry2D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fWindowLengthY == (m_fWindowMaxY - m_fWindowMinY), "VolumeGeometry2D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fWindowArea == (m_fWindowLengthX * m_fWindowLengthY), "VolumeGeometry2D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fPixelLengthX == (m_fWindowLengthX / (float32)m_iGridColCount), "VolumeGeometry2D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fPixelLengthY == (m_fWindowLengthY / (float32)m_iGridRowCount), "VolumeGeometry2D", "Internal configuration error.");
+
+ ASTRA_CONFIG_CHECK(m_fPixelArea == (m_fPixelLengthX * m_fPixelLengthY), "VolumeGeometry2D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(fabsf(m_fDivPixelLengthX * m_fPixelLengthX - 1.0f) < eps, "VolumeGeometry2D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(fabsf(m_fDivPixelLengthY * m_fPixelLengthY - 1.0f) < eps, "VolumeGeometry2D", "Internal configuration error.");
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+void CVolumeGeometry2D::clear()
+{
+ m_iGridColCount = 0;
+ m_iGridRowCount = 0;
+ m_iGridTotCount = 0;
+
+ m_fWindowLengthX = 0.0f;
+ m_fWindowLengthY = 0.0f;
+ m_fWindowArea = 0.0f;
+
+ m_fPixelLengthX = 0.0f;
+ m_fPixelLengthY = 0.0f;
+ m_fPixelArea = 0.0f;
+
+ m_fDivPixelLengthX = 0.0f;
+ m_fDivPixelLengthY = 0.0f;
+
+ m_fWindowMinX = 0.0f;
+ m_fWindowMinY = 0.0f;
+ m_fWindowMaxX = 0.0f;
+ m_fWindowMaxY = 0.0f;
+
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CVolumeGeometry2D::CVolumeGeometry2D() : configCheckData(0)
+{
+ clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Default constructor
+CVolumeGeometry2D::CVolumeGeometry2D(int _iGridColCount, int _iGridRowCount)
+ : configCheckData(0)
+{
+ clear();
+ initialize(_iGridColCount, _iGridRowCount);
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CVolumeGeometry2D::CVolumeGeometry2D(int _iGridColCount,
+ int _iGridRowCount,
+ float32 _fWindowMinX,
+ float32 _fWindowMinY,
+ float32 _fWindowMaxX,
+ float32 _fWindowMaxY)
+{
+ clear();
+ initialize(_iGridColCount,
+ _iGridRowCount,
+ _fWindowMinX,
+ _fWindowMinY,
+ _fWindowMaxX,
+ _fWindowMaxY);
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CVolumeGeometry2D::~CVolumeGeometry2D()
+{
+ if (m_bInitialized) {
+ clear();
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Clone
+CVolumeGeometry2D* CVolumeGeometry2D::clone()
+{
+ CVolumeGeometry2D* res = new CVolumeGeometry2D();
+ res->m_bInitialized = m_bInitialized;
+ res->m_iGridColCount = m_iGridColCount;
+ res->m_iGridRowCount = m_iGridRowCount;
+ res->m_iGridTotCount = m_iGridTotCount;
+ res->m_fWindowLengthX = m_fWindowLengthX;
+ res->m_fWindowLengthY = m_fWindowLengthY;
+ res->m_fWindowArea = m_fWindowArea;
+ res->m_fPixelLengthX = m_fPixelLengthX;
+ res->m_fPixelLengthY = m_fPixelLengthY;
+ res->m_fPixelArea = m_fPixelArea;
+ res->m_fDivPixelLengthX = m_fDivPixelLengthX;
+ res->m_fDivPixelLengthY = m_fDivPixelLengthY;
+ res->m_fWindowMinX = m_fWindowMinX;
+ res->m_fWindowMinY = m_fWindowMinY;
+ res->m_fWindowMaxX = m_fWindowMaxX;
+ res->m_fWindowMaxY = m_fWindowMaxY;
+ return res;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization witha COnfig object
+bool CVolumeGeometry2D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CVolumeGeometry2D> CC("VolumeGeometry2D", this, _cfg);
+
+ // uninitialize if the object was initialized before
+ if (m_bInitialized) {
+ clear();
+ }
+
+ // Required: GridColCount
+ XMLNode* node = _cfg.self->getSingleNode("GridColCount");
+ ASTRA_CONFIG_CHECK(node, "ReconstructionGeometry2D", "No GridColCount tag specified.");
+ m_iGridColCount = boost::lexical_cast<int>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("GridColCount");
+
+ // Required: GridRowCount
+ node = _cfg.self->getSingleNode("GridRowCount");
+ ASTRA_CONFIG_CHECK(node, "ReconstructionGeometry2D", "No GridRowCount tag specified.");
+ m_iGridRowCount = boost::lexical_cast<int>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("GridRowCount");
+
+ // Optional: Window minima and maxima
+ m_fWindowMinX = _cfg.self->getOptionNumerical("WindowMinX", -m_iGridColCount/2.0f);
+ m_fWindowMaxX = _cfg.self->getOptionNumerical("WindowMaxX", m_iGridColCount/2.0f);
+ m_fWindowMinY = _cfg.self->getOptionNumerical("WindowMinY", -m_iGridRowCount/2.0f);
+ m_fWindowMaxY = _cfg.self->getOptionNumerical("WindowMaxY", m_iGridRowCount/2.0f);
+ CC.markOptionParsed("WindowMinX");
+ CC.markOptionParsed("WindowMaxX");
+ CC.markOptionParsed("WindowMinY");
+ CC.markOptionParsed("WindowMaxY");
+
+ _calculateDependents();
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CVolumeGeometry2D::initialize(int _iGridColCount, int _iGridRowCount)
+{
+ return initialize(_iGridColCount,
+ _iGridRowCount,
+ -_iGridColCount/2.0f,
+ -_iGridRowCount/2.0f,
+ _iGridColCount/2.0f,
+ _iGridRowCount/2.0f);
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CVolumeGeometry2D::initialize(int _iGridColCount,
+ int _iGridRowCount,
+ float32 _fWindowMinX,
+ float32 _fWindowMinY,
+ float32 _fWindowMaxX,
+ float32 _fWindowMaxY)
+{
+ if (m_bInitialized) {
+ clear();
+ }
+
+ m_iGridColCount = _iGridColCount;
+ m_iGridRowCount = _iGridRowCount;
+
+ m_fWindowMinX = _fWindowMinX;
+ m_fWindowMinY = _fWindowMinY;
+ m_fWindowMaxX = _fWindowMaxX;
+ m_fWindowMaxY = _fWindowMaxY;
+
+ _calculateDependents();
+
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+void CVolumeGeometry2D::_calculateDependents()
+{
+ m_iGridTotCount = (m_iGridColCount * m_iGridRowCount);
+
+ m_fWindowLengthX = (m_fWindowMaxX - m_fWindowMinX);
+ m_fWindowLengthY = (m_fWindowMaxY - m_fWindowMinY);
+ m_fWindowArea = (m_fWindowLengthX * m_fWindowLengthY);
+
+ m_fPixelLengthX = (m_fWindowLengthX / (float32)m_iGridColCount);
+ m_fPixelLengthY = (m_fWindowLengthY / (float32)m_iGridRowCount);
+ m_fPixelArea = (m_fPixelLengthX * m_fPixelLengthY);
+
+ m_fDivPixelLengthX = ((float32)m_iGridColCount / m_fWindowLengthX); // == (1.0f / m_fPixelLengthX);
+ m_fDivPixelLengthY = ((float32)m_iGridRowCount / m_fWindowLengthY); // == (1.0f / m_fPixelLengthY);
+}
+
+//----------------------------------------------------------------------------------------
+// is of type
+bool CVolumeGeometry2D::isEqual(CVolumeGeometry2D* _pGeom2) const
+{
+ if (_pGeom2 == NULL) return false;
+
+ // both objects must be initialized
+ if (!m_bInitialized || !_pGeom2->m_bInitialized) return false;
+
+ // check all values
+ if (m_iGridColCount != _pGeom2->m_iGridColCount) return false;
+ if (m_iGridRowCount != _pGeom2->m_iGridRowCount) return false;
+ if (m_iGridTotCount != _pGeom2->m_iGridTotCount) return false;
+ if (m_fWindowLengthX != _pGeom2->m_fWindowLengthX) return false;
+ if (m_fWindowLengthY != _pGeom2->m_fWindowLengthY) return false;
+ if (m_fWindowArea != _pGeom2->m_fWindowArea) return false;
+ if (m_fPixelLengthX != _pGeom2->m_fPixelLengthX) return false;
+ if (m_fPixelLengthY != _pGeom2->m_fPixelLengthY) return false;
+ if (m_fPixelArea != _pGeom2->m_fPixelArea) return false;
+ if (m_fDivPixelLengthX != _pGeom2->m_fDivPixelLengthX) return false;
+ if (m_fDivPixelLengthY != _pGeom2->m_fDivPixelLengthY) return false;
+ if (m_fWindowMinX != _pGeom2->m_fWindowMinX) return false;
+ if (m_fWindowMinY != _pGeom2->m_fWindowMinY) return false;
+ if (m_fWindowMaxX != _pGeom2->m_fWindowMaxX) return false;
+ if (m_fWindowMaxY != _pGeom2->m_fWindowMaxY) return false;
+
+ return true;
+}
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/VolumeGeometry3D.cpp b/src/VolumeGeometry3D.cpp
new file mode 100644
index 0000000..86b8642
--- /dev/null
+++ b/src/VolumeGeometry3D.cpp
@@ -0,0 +1,384 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/VolumeGeometry3D.h"
+
+#include <boost/lexical_cast.hpp>
+
+namespace astra
+{
+
+//----------------------------------------------------------------------------------------
+// Check all variable values
+bool CVolumeGeometry3D::_check()
+{
+ ASTRA_CONFIG_CHECK(m_iGridColCount > 0, "VolumeGeometry3D", "GridColCount must be strictly positive.");
+ ASTRA_CONFIG_CHECK(m_iGridRowCount > 0, "VolumeGeometry3D", "GridRowCount must be strictly positive.");
+ ASTRA_CONFIG_CHECK(m_iGridSliceCount > 0, "VolumeGeometry3D", "GridSliceCount must be strictly positive.");
+ ASTRA_CONFIG_CHECK(m_fWindowMinX < m_fWindowMaxX, "VolumeGeometry3D", "WindowMinX should be lower than WindowMaxX.");
+ ASTRA_CONFIG_CHECK(m_fWindowMinY < m_fWindowMaxY, "VolumeGeometry3D", "WindowMinY should be lower than WindowMaxY.");
+ ASTRA_CONFIG_CHECK(m_fWindowMinZ < m_fWindowMaxZ, "VolumeGeometry3D", "WindowMinZ should be lower than WindowMaxZ.");
+
+ ASTRA_CONFIG_CHECK(m_iGridTotCount == (m_iGridColCount * m_iGridRowCount * m_iGridSliceCount), "VolumeGeometry3D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fWindowLengthX == (m_fWindowMaxX - m_fWindowMinX), "VolumeGeometry3D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fWindowLengthY == (m_fWindowMaxY - m_fWindowMinY), "VolumeGeometry3D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fWindowLengthZ == (m_fWindowMaxZ - m_fWindowMinZ), "VolumeGeometry3D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fWindowArea == (m_fWindowLengthX * m_fWindowLengthY * m_fWindowLengthZ), "VolumeGeometry3D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fPixelLengthX == (m_fWindowLengthX / (float32)m_iGridColCount), "VolumeGeometry3D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fPixelLengthY == (m_fWindowLengthY / (float32)m_iGridRowCount), "VolumeGeometry3D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fPixelLengthZ == (m_fWindowLengthZ / (float32)m_iGridSliceCount), "VolumeGeometry3D", "Internal configuration error.");
+
+ ASTRA_CONFIG_CHECK(m_fPixelArea == (m_fPixelLengthX * m_fPixelLengthY * m_fPixelLengthZ), "VolumeGeometry3D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fDivPixelLengthX == (1.0f / m_fPixelLengthX), "VolumeGeometry3D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fDivPixelLengthY == (1.0f / m_fPixelLengthY), "VolumeGeometry3D", "Internal configuration error.");
+ ASTRA_CONFIG_CHECK(m_fDivPixelLengthZ == (1.0f / m_fPixelLengthZ), "VolumeGeometry3D", "Internal configuration error.");
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+// Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+void CVolumeGeometry3D::clear()
+{
+ m_iGridColCount = 0;
+ m_iGridRowCount = 0;
+ m_iGridSliceCount = 0;
+ m_iGridTotCount = 0;
+
+ m_fWindowLengthX = 0.0f;
+ m_fWindowLengthY = 0.0f;
+ m_fWindowLengthZ = 0.0f;
+ m_fWindowArea = 0.0f;
+
+ m_fPixelLengthX = 0.0f;
+ m_fPixelLengthY = 0.0f;
+ m_fPixelLengthZ = 0.0f;
+ m_fPixelArea = 0.0f;
+
+ m_fDivPixelLengthX = 0.0f;
+ m_fDivPixelLengthY = 0.0f;
+ m_fDivPixelLengthZ = 0.0f;
+
+ m_fWindowMinX = 0.0f;
+ m_fWindowMinY = 0.0f;
+ m_fWindowMinZ = 0.0f;
+ m_fWindowMaxX = 0.0f;
+ m_fWindowMaxY = 0.0f;
+ m_fWindowMaxZ = 0.0f;
+
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Default constructor.
+CVolumeGeometry3D::CVolumeGeometry3D() : configCheckData(0)
+{
+ clear();
+ m_bInitialized = false;
+}
+
+//----------------------------------------------------------------------------------------
+// Default constructor
+CVolumeGeometry3D::CVolumeGeometry3D(int _iGridColCount, int _iGridRowCount, int _iGridSliceCount)
+ : configCheckData(0)
+{
+ clear();
+ initialize(_iGridColCount, _iGridRowCount, _iGridSliceCount);
+}
+
+//----------------------------------------------------------------------------------------
+// Constructor.
+CVolumeGeometry3D::CVolumeGeometry3D(int _iGridColCount,
+ int _iGridRowCount,
+ int _iGridSliceCount,
+ float32 _fWindowMinX,
+ float32 _fWindowMinY,
+ float32 _fWindowMinZ,
+ float32 _fWindowMaxX,
+ float32 _fWindowMaxY,
+ float32 _fWindowMaxZ)
+{
+ clear();
+ initialize(_iGridColCount,
+ _iGridRowCount,
+ _iGridSliceCount,
+ _fWindowMinX,
+ _fWindowMinY,
+ _fWindowMinZ,
+ _fWindowMaxX,
+ _fWindowMaxY,
+ _fWindowMaxZ);
+}
+
+CVolumeGeometry3D::CVolumeGeometry3D(const CVolumeGeometry3D& _other)
+{
+ *this = _other;
+}
+
+CVolumeGeometry3D& CVolumeGeometry3D::operator=(const CVolumeGeometry3D& _other)
+{
+ m_bInitialized = _other.m_bInitialized;
+ m_iGridColCount = _other.m_iGridColCount;
+ m_iGridRowCount = _other.m_iGridRowCount;
+ m_iGridSliceCount = _other.m_iGridSliceCount;
+ m_fWindowLengthX = _other.m_fWindowLengthX;
+ m_fWindowLengthY = _other.m_fWindowLengthY;
+ m_fWindowLengthZ = _other.m_fWindowLengthZ;
+ m_fWindowArea = _other.m_fWindowArea;
+ m_fPixelLengthX = _other.m_fPixelLengthX;
+ m_fPixelLengthY = _other.m_fPixelLengthY;
+ m_fPixelLengthZ = _other.m_fPixelLengthZ;
+ m_fDivPixelLengthX = _other.m_fDivPixelLengthX;
+ m_fDivPixelLengthY = _other.m_fDivPixelLengthY;
+ m_fDivPixelLengthZ = _other.m_fDivPixelLengthZ;
+ m_fWindowMinX = _other.m_fWindowMinX;
+ m_fWindowMinY = _other.m_fWindowMinY;
+ m_fWindowMinZ = _other.m_fWindowMinZ;
+ m_fWindowMaxX = _other.m_fWindowMaxX;
+ m_fWindowMaxY = _other.m_fWindowMaxY;
+ m_fWindowMaxZ = _other.m_fWindowMaxZ;
+
+ m_iGridTotCount = _other.m_iGridTotCount;
+ m_fPixelArea = _other.m_fPixelArea;
+
+ return *this;
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor.
+CVolumeGeometry3D::~CVolumeGeometry3D()
+{
+ if (m_bInitialized) {
+ clear();
+ }
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization with a Config object
+bool CVolumeGeometry3D::initialize(const Config& _cfg)
+{
+ ASTRA_ASSERT(_cfg.self);
+ ConfigStackCheck<CVolumeGeometry3D> CC("VolumeGeometry3D", this, _cfg);
+
+
+ // uninitialize if the object was initialized before
+ if (m_bInitialized) {
+ clear();
+ }
+
+ // Required: GridColCount
+ XMLNode* node = _cfg.self->getSingleNode("GridColCount");
+ ASTRA_CONFIG_CHECK(node, "ReconstructionGeometry2D", "No GridColCount tag specified.");
+ m_iGridColCount = boost::lexical_cast<int>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("GridColCount");
+
+ // Required: GridRowCount
+ node = _cfg.self->getSingleNode("GridRowCount");
+ ASTRA_CONFIG_CHECK(node, "ReconstructionGeometry2D", "No GridRowCount tag specified.");
+ m_iGridRowCount = boost::lexical_cast<int>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("GridRowCount");
+
+ // Required: GridRowCount
+ node = _cfg.self->getSingleNode("GridSliceCount");
+ ASTRA_CONFIG_CHECK(node, "ReconstructionGeometry2D", "No GridSliceCount tag specified.");
+ m_iGridSliceCount = boost::lexical_cast<int>(node->getContent());
+ ASTRA_DELETE(node);
+ CC.markNodeParsed("GridSliceCount");
+
+ // Optional: Window minima and maxima
+ m_fWindowMinX = _cfg.self->getOptionNumerical("WindowMinX", -m_iGridColCount/2.0f);
+ m_fWindowMaxX = _cfg.self->getOptionNumerical("WindowMaxX", m_iGridColCount/2.0f);
+ m_fWindowMinY = _cfg.self->getOptionNumerical("WindowMinY", -m_iGridRowCount/2.0f);
+ m_fWindowMaxY = _cfg.self->getOptionNumerical("WindowMaxY", m_iGridRowCount/2.0f);
+ m_fWindowMinZ = _cfg.self->getOptionNumerical("WindowMinZ", -m_iGridSliceCount/2.0f);
+ m_fWindowMaxZ = _cfg.self->getOptionNumerical("WindowMaxZ", m_iGridSliceCount/2.0f);
+ CC.markOptionParsed("WindowMinX");
+ CC.markOptionParsed("WindowMaxX");
+ CC.markOptionParsed("WindowMinY");
+ CC.markOptionParsed("WindowMaxY");
+ CC.markOptionParsed("WindowMinZ");
+ CC.markOptionParsed("WindowMaxZ");
+
+ // calculate some other things
+ m_iGridTotCount = (m_iGridColCount * m_iGridRowCount * m_iGridSliceCount);
+ m_fWindowLengthX = (m_fWindowMaxX - m_fWindowMinX);
+ m_fWindowLengthY = (m_fWindowMaxY - m_fWindowMinY);
+ m_fWindowLengthZ = (m_fWindowMaxZ - m_fWindowMinZ);
+ m_fWindowArea = (m_fWindowLengthX * m_fWindowLengthY * m_fWindowLengthZ);
+ m_fPixelLengthX = (m_fWindowLengthX / (float32)m_iGridColCount);
+ m_fPixelLengthY = (m_fWindowLengthY / (float32)m_iGridRowCount);
+ m_fPixelLengthZ = (m_fWindowLengthZ / (float32)m_iGridSliceCount);
+
+ m_fPixelArea = (m_fPixelLengthX * m_fPixelLengthY * m_fPixelLengthZ);
+ m_fDivPixelLengthX = ((float32)m_iGridColCount / m_fWindowLengthX); // == (1.0f / m_fPixelLengthX);
+ m_fDivPixelLengthY = ((float32)m_iGridRowCount / m_fWindowLengthY); // == (1.0f / m_fPixelLengthY);
+ m_fDivPixelLengthZ = ((float32)m_iGridSliceCount / m_fWindowLengthZ); // == (1.0f / m_fPixelLengthZ);
+
+ // success
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CVolumeGeometry3D::initialize(int _iGridColCount, int _iGridRowCount, int _iGridSliceCount)
+{
+ return initialize(_iGridColCount,
+ _iGridRowCount,
+ _iGridSliceCount,
+ -_iGridColCount/2.0f,
+ -_iGridRowCount/2.0f,
+ -_iGridSliceCount/2.0f,
+ _iGridColCount/2.0f,
+ _iGridRowCount/2.0f,
+ _iGridSliceCount/2.0f);
+}
+
+//----------------------------------------------------------------------------------------
+// Initialization.
+bool CVolumeGeometry3D::initialize(int _iGridColCount,
+ int _iGridRowCount,
+ int _iGridSliceCount,
+ float32 _fWindowMinX,
+ float32 _fWindowMinY,
+ float32 _fWindowMinZ,
+ float32 _fWindowMaxX,
+ float32 _fWindowMaxY,
+ float32 _fWindowMaxZ)
+{
+ if (m_bInitialized) {
+ clear();
+ }
+
+ m_iGridColCount = _iGridColCount;
+ m_iGridRowCount = _iGridRowCount;
+ m_iGridSliceCount = _iGridSliceCount;
+ m_iGridTotCount = (m_iGridColCount * m_iGridRowCount * m_iGridSliceCount);
+
+ m_fWindowMinX = _fWindowMinX;
+ m_fWindowMinY = _fWindowMinY;
+ m_fWindowMinZ = _fWindowMinZ;
+ m_fWindowMaxX = _fWindowMaxX;
+ m_fWindowMaxY = _fWindowMaxY;
+ m_fWindowMaxZ = _fWindowMaxZ;
+
+ m_fWindowLengthX = (m_fWindowMaxX - m_fWindowMinX);
+ m_fWindowLengthY = (m_fWindowMaxY - m_fWindowMinY);
+ m_fWindowLengthZ = (m_fWindowMaxZ - m_fWindowMinZ);
+ m_fWindowArea = (m_fWindowLengthX * m_fWindowLengthY * m_fWindowLengthZ);
+
+ m_fPixelLengthX = (m_fWindowLengthX / (float32)m_iGridColCount);
+ m_fPixelLengthY = (m_fWindowLengthY / (float32)m_iGridRowCount);
+ m_fPixelLengthZ = (m_fWindowLengthZ / (float32)m_iGridSliceCount);
+ m_fPixelArea = (m_fPixelLengthX * m_fPixelLengthY);
+
+ m_fDivPixelLengthX = ((float32)m_iGridColCount / m_fWindowLengthX); // == (1.0f / m_fPixelLengthX);
+ m_fDivPixelLengthY = ((float32)m_iGridRowCount / m_fWindowLengthY); // == (1.0f / m_fPixelLengthY);
+ m_fDivPixelLengthZ = ((float32)m_iGridSliceCount / m_fWindowLengthZ); // == (1.0f / m_fPixelLengthZ);
+
+ m_bInitialized = _check();
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Clone
+CVolumeGeometry3D* CVolumeGeometry3D::clone() const
+{
+ CVolumeGeometry3D* res = new CVolumeGeometry3D();
+ res->m_bInitialized = m_bInitialized;
+ res->m_iGridColCount = m_iGridColCount;
+ res->m_iGridRowCount = m_iGridRowCount;
+ res->m_iGridSliceCount = m_iGridSliceCount;
+ res->m_iGridTotCount = m_iGridTotCount;
+ res->m_fWindowLengthX = m_fWindowLengthX;
+ res->m_fWindowLengthY = m_fWindowLengthY;
+ res->m_fWindowLengthZ = m_fWindowLengthZ;
+ res->m_fWindowArea = m_fWindowArea;
+ res->m_fPixelLengthX = m_fPixelLengthX;
+ res->m_fPixelLengthY = m_fPixelLengthY;
+ res->m_fPixelLengthZ = m_fPixelLengthZ;
+ res->m_fPixelArea = m_fPixelArea;
+ res->m_fDivPixelLengthX = m_fDivPixelLengthX;
+ res->m_fDivPixelLengthY = m_fDivPixelLengthY;
+ res->m_fDivPixelLengthZ = m_fDivPixelLengthZ;
+ res->m_fWindowMinX = m_fWindowMinX;
+ res->m_fWindowMinY = m_fWindowMinY;
+ res->m_fWindowMinZ = m_fWindowMinZ;
+ res->m_fWindowMaxX = m_fWindowMaxX;
+ res->m_fWindowMaxY = m_fWindowMaxY;
+ res->m_fWindowMaxZ = m_fWindowMaxZ;
+ return res;
+}
+
+//----------------------------------------------------------------------------------------
+// is of type
+bool CVolumeGeometry3D::isEqual(const CVolumeGeometry3D* _pGeom2) const
+{
+ if (_pGeom2 == NULL) return false;
+
+ // both objects must be initialized
+ if (!m_bInitialized || !_pGeom2->m_bInitialized) return false;
+
+ // check all values
+ if (m_iGridColCount != _pGeom2->m_iGridColCount) return false;
+ if (m_iGridRowCount != _pGeom2->m_iGridRowCount) return false;
+ if (m_iGridSliceCount != _pGeom2->m_iGridSliceCount) return false;
+ if (m_iGridTotCount != _pGeom2->m_iGridTotCount) return false;
+ if (m_fWindowLengthX != _pGeom2->m_fWindowLengthX) return false;
+ if (m_fWindowLengthY != _pGeom2->m_fWindowLengthY) return false;
+ if (m_fWindowLengthZ != _pGeom2->m_fWindowLengthZ) return false;
+ if (m_fWindowArea != _pGeom2->m_fWindowArea) return false;
+ if (m_fPixelLengthX != _pGeom2->m_fPixelLengthX) return false;
+ if (m_fPixelLengthY != _pGeom2->m_fPixelLengthY) return false;
+ if (m_fPixelLengthZ != _pGeom2->m_fPixelLengthZ) return false;
+ if (m_fPixelArea != _pGeom2->m_fPixelArea) return false;
+ if (m_fDivPixelLengthX != _pGeom2->m_fDivPixelLengthX) return false;
+ if (m_fDivPixelLengthY != _pGeom2->m_fDivPixelLengthY) return false;
+ if (m_fDivPixelLengthZ != _pGeom2->m_fDivPixelLengthZ) return false;
+ if (m_fWindowMinX != _pGeom2->m_fWindowMinX) return false;
+ if (m_fWindowMinY != _pGeom2->m_fWindowMinY) return false;
+ if (m_fWindowMinZ != _pGeom2->m_fWindowMinZ) return false;
+ if (m_fWindowMaxX != _pGeom2->m_fWindowMaxX) return false;
+ if (m_fWindowMaxY != _pGeom2->m_fWindowMaxY) return false;
+ if (m_fWindowMaxZ != _pGeom2->m_fWindowMaxZ) return false;
+
+ return true;
+}
+
+CVolumeGeometry2D * CVolumeGeometry3D::createVolumeGeometry2D() const
+{
+ CVolumeGeometry2D * pOutput = new CVolumeGeometry2D();
+ pOutput->initialize(getGridColCount(), getGridRowCount());
+ return pOutput;
+}
+
+//----------------------------------------------------------------------------------------
+
+} // namespace astra
diff --git a/src/XMLDocument.cpp b/src/XMLDocument.cpp
new file mode 100644
index 0000000..96d0f80
--- /dev/null
+++ b/src/XMLDocument.cpp
@@ -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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/XMLDocument.h"
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+#ifdef _MSC_VER
+#include "rapidxml/rapidxml.hpp"
+#include "rapidxml/rapidxml_print.hpp"
+#else
+#include "rapidxml.hpp"
+#include "rapidxml_print.hpp"
+#endif
+
+using namespace rapidxml;
+using namespace astra;
+using namespace std;
+
+
+
+//-----------------------------------------------------------------------------
+XMLDocument::XMLDocument()
+{
+ fDOMDocument = 0;
+}
+
+//-----------------------------------------------------------------------------
+XMLDocument::~XMLDocument()
+{
+ delete fDOMDocument;
+ //parser->release();
+}
+
+//-----------------------------------------------------------------------------
+XMLDocument* XMLDocument::readFromFile(string filename)
+{
+ // create the document
+ XMLDocument* res = new XMLDocument();
+ res->fDOMDocument = new xml_document<>();
+
+ std::ifstream file(filename.c_str());
+ std::stringstream reader;
+ reader << file.rdbuf();
+ res->fBuf = reader.str();
+
+ res->fDOMDocument->parse<0>((char*)res->fBuf.c_str());
+
+ // return the document
+ return res;
+
+}
+
+//-----------------------------------------------------------------------------
+// create an XML document with an empty root node
+XMLDocument* XMLDocument::createDocument(string sRootName)
+{
+ XMLDocument* res = new XMLDocument();
+ res->fDOMDocument = new xml_document<>();
+
+ char *node_name = res->fDOMDocument->allocate_string(sRootName.c_str());
+ xml_node<> *node = res->fDOMDocument->allocate_node(node_element, node_name);
+
+ res->fDOMDocument->append_node(node);
+
+ return res;
+}
+
+//-----------------------------------------------------------------------------
+XMLNode* XMLDocument::getRootNode()
+{
+ // TODO: clean up: this 'new' requires callers to do memory management
+ return new XMLNode(fDOMDocument->first_node());
+}
+
+//-----------------------------------------------------------------------------
+void XMLDocument::saveToFile(string sFilename)
+{
+ std::ofstream file(sFilename.c_str());
+
+ file << *fDOMDocument;
+}
+
+//-----------------------------------------------------------------------------
+
diff --git a/src/XMLNode.cpp b/src/XMLNode.cpp
new file mode 100644
index 0000000..e47c3e7
--- /dev/null
+++ b/src/XMLNode.cpp
@@ -0,0 +1,499 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#include "astra/XMLNode.h"
+
+#ifdef _MSC_VER
+#include "rapidxml/rapidxml.hpp"
+#include "rapidxml/rapidxml_print.hpp"
+#else
+#include "rapidxml.hpp"
+#include "rapidxml_print.hpp"
+#endif
+
+#include <boost/lexical_cast.hpp>
+
+using namespace rapidxml;
+using namespace astra;
+using namespace std;
+
+
+//-----------------------------------------------------------------------------
+// Utility function to delete a list of nodes
+static void deleteNodes(list<XMLNode*>& nodes)
+{
+ for (list<XMLNode*>::iterator i = nodes.begin(); i != nodes.end(); ++i)
+ delete (*i);
+
+ nodes.clear();
+}
+
+
+//-----------------------------------------------------------------------------
+// default constructor
+XMLNode::XMLNode()
+{
+
+}
+
+//-----------------------------------------------------------------------------
+// private constructor
+XMLNode::XMLNode(xml_node<>* node)
+{
+ fDOMElement = node;
+}
+
+//-----------------------------------------------------------------------------
+// destructor
+XMLNode::~XMLNode()
+{
+
+}
+
+//-----------------------------------------------------------------------------
+// set DOM node (private)
+void XMLNode::setDOMNode(xml_node<>* n)
+{
+ fDOMElement = n;
+}
+
+//-----------------------------------------------------------------------------
+// print XML Node
+void XMLNode::print()
+{
+ std::cout << fDOMElement;
+}
+
+//-----------------------------------------------------------------------------
+// print XML Node
+std::string XMLNode::toString()
+{
+ std::string s;
+ ::print(std::back_inserter(s), *fDOMElement, 0);
+ return s;
+}
+
+//-----------------------------------------------------------------------------
+// Get single node
+XMLNode* XMLNode::getSingleNode(string name)
+{
+ xml_node<> *node = fDOMElement->first_node(name.c_str());
+
+ if (node)
+ return new XMLNode(node);
+ else
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Get list of nodes
+list<XMLNode*> XMLNode::getNodes(string name)
+{
+ list<XMLNode*> result;
+ xml_node<> *iter;
+ for (iter = fDOMElement->first_node(name.c_str()); iter; iter = iter->next_sibling(name.c_str())) {
+ result.push_back(new XMLNode(iter));
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+// Get list of nodes
+list<XMLNode*> XMLNode::getNodes()
+{
+ list<XMLNode*> result;
+ xml_node<> *iter;
+ for (iter = fDOMElement->first_node(); iter; iter = iter->next_sibling()) {
+ result.push_back(new XMLNode(iter));
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+// Get name of this node
+std::string XMLNode::getName()
+{
+ return fDOMElement->name();
+}
+
+//-----------------------------------------------------------------------------
+// Get node content - STRING
+string XMLNode::getContent()
+{
+ return fDOMElement->value();
+}
+
+//-----------------------------------------------------------------------------
+// Get node content - NUMERICAL
+float32 XMLNode::getContentNumerical()
+{
+ return boost::lexical_cast<float32>(getContent());
+}
+
+//-----------------------------------------------------------------------------
+// Get node content - BOOLEAN
+bool XMLNode::getContentBool()
+{
+ string res = getContent();
+ return ((res == "1") || (res == "yes") || (res == "true") || (res == "on"));
+}
+
+//-----------------------------------------------------------------------------
+// Get node content - STRING LIST
+vector<string> XMLNode::getContentArray()
+{
+ // get listsize
+ int iSize = boost::lexical_cast<int>(getAttribute("listsize"));
+ // create result array
+ vector<string> res(iSize);
+ // loop all list item nodes
+ list<XMLNode*> nodes = getNodes("ListItem");
+ for (list<XMLNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
+ int iIndex = (*it)->getAttributeNumerical("index");
+ string sValue = (*it)->getAttribute("value");
+ ASTRA_ASSERT(iIndex < iSize);
+ res[iIndex] = sValue;
+ }
+ deleteNodes(nodes);
+
+ // return
+ return res;
+}
+
+//-----------------------------------------------------------------------------
+// Get node content - NUMERICAL LIST
+vector<float32> XMLNode::getContentNumericalArray()
+{
+ // is scalar
+ if (!hasAttribute("listsize")) {
+ vector<float32> res(1);
+ res[0] = getContentNumerical();
+ return res;
+ }
+
+ int iSize = boost::lexical_cast<int>(getAttribute("listsize"));
+ // create result array
+ vector<float32> res(iSize);
+ // loop all list item nodes
+ list<XMLNode*> nodes = getNodes("ListItem");
+ for (list<XMLNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
+ int iIndex = (*it)->getAttributeNumerical("index");
+ float32 fValue = (*it)->getAttributeNumerical("value");
+ ASTRA_ASSERT(iIndex < iSize);
+ res[iIndex] = fValue;
+ }
+ deleteNodes(nodes);
+ // return
+ return res;
+}
+
+vector<double> XMLNode::getContentNumericalArrayDouble()
+{
+ // is scalar
+ if (!hasAttribute("listsize")) {
+ vector<double> res(1);
+ res[0] = getContentNumerical();
+ return res;
+ }
+
+ int iSize = boost::lexical_cast<int>(getAttribute("listsize"));
+ // create result array
+ vector<double> res(iSize);
+ // loop all list item nodes
+ list<XMLNode*> nodes = getNodes("ListItem");
+ for (list<XMLNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
+ int iIndex = (*it)->getAttributeNumerical("index");
+ double fValue = (*it)->getAttributeNumericalDouble("value");
+ ASTRA_ASSERT(iIndex < iSize);
+ res[iIndex] = fValue;
+ }
+ deleteNodes(nodes);
+ // return
+ return res;
+}
+
+//-----------------------------------------------------------------------------
+// Get node content - NUMERICAL LIST 2
+void XMLNode::getContentNumericalArray(float32*& _pfData, int& _iSize)
+{
+ // is scalar
+ if (!hasAttribute("listsize")) {
+ _iSize = 1;
+ _pfData = new float32[_iSize];
+ _pfData[0] = getContentNumerical();
+ return;
+ }
+ // get listsize
+ _iSize = boost::lexical_cast<int>(getAttribute("listsize"));
+ // create result array
+ _pfData = new float32[_iSize];
+ // loop all list item nodes
+ list<XMLNode*> nodes = getNodes("ListItem");
+ for (list<XMLNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
+ int iIndex = (*it)->getAttributeNumerical("index");
+ float32 fValue = (*it)->getAttributeNumerical("value");
+ ASTRA_ASSERT(iIndex < _iSize);
+ _pfData[iIndex] = fValue;
+ }
+ deleteNodes(nodes);
+}
+
+//-----------------------------------------------------------------------------
+// Is attribute?
+bool XMLNode::hasAttribute(string _sName)
+{
+ xml_attribute<> *attr = fDOMElement->first_attribute(_sName.c_str());
+ return (attr != 0);
+}
+
+//-----------------------------------------------------------------------------
+// Get attribute - STRING
+string XMLNode::getAttribute(string _sName, string _sDefaultValue)
+{
+ xml_attribute<> *attr = fDOMElement->first_attribute(_sName.c_str());
+
+ if (!attr) return _sDefaultValue;
+
+ return attr->value();
+}
+
+//-----------------------------------------------------------------------------
+// Get attribute - NUMERICAL
+float32 XMLNode::getAttributeNumerical(string _sName, float32 _fDefaultValue)
+{
+ if (!hasAttribute(_sName)) return _fDefaultValue;
+ return boost::lexical_cast<float32>(getAttribute(_sName));
+}
+double XMLNode::getAttributeNumericalDouble(string _sName, double _fDefaultValue)
+{
+ if (!hasAttribute(_sName)) return _fDefaultValue;
+ return boost::lexical_cast<double>(getAttribute(_sName));
+}
+
+//-----------------------------------------------------------------------------
+// Get attribute - BOOLEAN
+bool XMLNode::getAttributeBool(string _sName, bool _bDefaultValue)
+{
+ if (!hasAttribute(_sName)) return _bDefaultValue;
+ string res = getAttribute(_sName);
+ return ((res == "1") || (res == "yes") || (res == "true") || (res == "on"));
+}
+
+//-----------------------------------------------------------------------------
+// Has option?
+bool XMLNode::hasOption(string _sKey)
+{
+ xml_node<> *iter;
+ for (iter = fDOMElement->first_node("Option"); iter; iter = iter->next_sibling("Option")) {
+ xml_attribute<> *attr = iter->first_attribute("key");
+ if (attr && _sKey == attr->value())
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Get option - STRING
+string XMLNode::getOption(string _sKey, string _sDefaultValue)
+{
+ xml_node<> *iter;
+ for (iter = fDOMElement->first_node("Option"); iter; iter = iter->next_sibling("Option")) {
+ xml_attribute<> *attr = iter->first_attribute("key");
+ if (attr && _sKey == attr->value()) {
+ attr = iter->first_attribute("value");
+ if (!attr)
+ return "";
+ return attr->value();
+ }
+ }
+ return _sDefaultValue;
+}
+
+//-----------------------------------------------------------------------------
+// Get option - NUMERICAL
+float32 XMLNode::getOptionNumerical(string _sKey, float32 _fDefaultValue)
+{
+ if (!hasOption(_sKey)) return _fDefaultValue;
+ return boost::lexical_cast<float32>(getOption(_sKey));
+}
+
+//-----------------------------------------------------------------------------
+// Get option - BOOL
+bool XMLNode::getOptionBool(string _sKey, bool _bDefaultValue)
+{
+ bool bHasOption = hasOption(_sKey);
+ if (!bHasOption) return _bDefaultValue;
+ string res = getOption(_sKey);
+ return ((res == "1") || (res == "yes") || (res == "true") || (res == "on"));
+}
+
+//-----------------------------------------------------------------------------
+// Get option - NUMERICAL ARRAY
+vector<float32> XMLNode::getOptionNumericalArray(string _sKey)
+{
+ if (!hasOption(_sKey)) return vector<float32>();
+
+ list<XMLNode*> nodes = getNodes("Option");
+ for (list<XMLNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
+ if ((*it)->getAttribute("key") == _sKey) {
+ vector<float32> vals = (*it)->getContentNumericalArray();
+ deleteNodes(nodes);
+ return vals;
+ }
+ }
+
+ deleteNodes(nodes);
+ return vector<float32>();
+}
+
+//-----------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+//-----------------------------------------------------------------------------
+// BUILD NODE
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Add child node - EMPTY
+XMLNode* XMLNode::addChildNode(string _sNodeName)
+{
+ xml_document<> *doc = fDOMElement->document();
+ char *node_name = doc->allocate_string(_sNodeName.c_str());
+ xml_node<> *node = doc->allocate_node(node_element, node_name);
+ fDOMElement->append_node(node);
+
+ // TODO: clean up: this 'new' requires callers to do memory management
+ return new XMLNode(node);
+}
+
+//-----------------------------------------------------------------------------
+// Add child node - STRING
+XMLNode* XMLNode::addChildNode(string _sNodeName, string _sText)
+{
+ XMLNode* res = addChildNode(_sNodeName);
+ res->setContent(_sText);
+ return res;
+}
+
+//-----------------------------------------------------------------------------
+// Add child node - FLOAT
+XMLNode* XMLNode::addChildNode(string _sNodeName, float32 _fValue)
+{
+ XMLNode* res = addChildNode(_sNodeName);
+ res->setContent(_fValue);
+ return res;
+}
+
+//-----------------------------------------------------------------------------
+// Add child node - LIST
+XMLNode* XMLNode::addChildNode(string _sNodeName, float32* _pfList, int _iSize)
+{
+ XMLNode* res = addChildNode(_sNodeName);
+ res->setContent(_pfList, _iSize);
+ return res;
+}
+
+//-----------------------------------------------------------------------------
+// Set content - STRING
+void XMLNode::setContent(string _sText)
+{
+ xml_document<> *doc = fDOMElement->document();
+ char *text = doc->allocate_string(_sText.c_str());
+ fDOMElement->value(text);
+}
+
+//-----------------------------------------------------------------------------
+// Set content - FLOAT
+void XMLNode::setContent(float32 _fValue)
+{
+ setContent(boost::lexical_cast<string>(_fValue));
+}
+
+//-----------------------------------------------------------------------------
+// Set content - LIST
+void XMLNode::setContent(float32* pfList, int _iSize)
+{
+ addAttribute("listsize", _iSize);
+ for (int i = 0; i < _iSize; i++) {
+ XMLNode* item = addChildNode("ListItem");
+ item->addAttribute("index", i);
+ item->addAttribute("value",pfList[i]);
+ delete item;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Add attribute - STRING
+void XMLNode::addAttribute(string _sName, string _sText)
+{
+ xml_document<> *doc = fDOMElement->document();
+ char *name = doc->allocate_string(_sName.c_str());
+ char *text = doc->allocate_string(_sText.c_str());
+ xml_attribute<> *attr = doc->allocate_attribute(name, text);
+ fDOMElement->append_attribute(attr);
+}
+
+//-----------------------------------------------------------------------------
+// Add attribute - FLOAT
+void XMLNode::addAttribute(string _sName, float32 _fValue)
+{
+ addAttribute(_sName, boost::lexical_cast<string>(_fValue));
+}
+
+//-----------------------------------------------------------------------------
+// Add option - STRING
+void XMLNode::addOption(string _sName, string _sText)
+{
+ XMLNode* node = addChildNode("Option");
+ node->addAttribute("key", _sName);
+ node->addAttribute("value", _sText);
+ delete node;
+}
+
+//-----------------------------------------------------------------------------
+// Add option - FLOAT
+void XMLNode::addOption(string _sName, float32 _sText)
+{
+ XMLNode* node = addChildNode("Option");
+ node->addAttribute("key", _sName);
+ node->addAttribute("value", _sText);
+ delete node;
+}
+//-----------------------------------------------------------------------------
+
+
diff --git a/src/astra.def b/src/astra.def
new file mode 100644
index 0000000..585324c
--- /dev/null
+++ b/src/astra.def
@@ -0,0 +1,6 @@
+; MatlabDLL.def : Declares the module parameters for the DLL.
+
+LIBRARY "astra"
+
+EXPORTS
+ ; Explicit exports can go here
diff --git a/src/swrap.cpp b/src/swrap.cpp
new file mode 100644
index 0000000..be8238e
--- /dev/null
+++ b/src/swrap.cpp
@@ -0,0 +1,47 @@
+/*
+-----------------------------------------------------------------------
+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 <http://www.gnu.org/licenses/>.
+
+-----------------------------------------------------------------------
+$Id$
+*/
+
+#ifndef _MSC_VER
+
+#include "astra/swrap.h"
+#include <cerrno>
+
+errno_t fopen_s(FILE** pFile, const char* filename, const char* mode)
+{
+ if (!pFile)
+ return EINVAL;
+
+ FILE* x = fopen(filename, mode);
+ if (!x)
+ return errno;
+
+ *pFile = x;
+ return 0;
+}
+
+#endif