summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml45
-rw-r--r--build/linux/Makefile.in8
-rw-r--r--cuda/2d/sart.cu7
-rw-r--r--cuda/2d/sart.h4
-rw-r--r--cuda/2d/sirt.cu8
-rw-r--r--cuda/2d/sirt.h4
-rw-r--r--cuda/3d/astra3d.cu13
-rw-r--r--cuda/3d/astra3d.h2
-rw-r--r--cuda/3d/sirt3d.cu8
-rw-r--r--cuda/3d/sirt3d.h5
-rw-r--r--include/astra/ArtAlgorithm.h4
-rw-r--r--include/astra/CudaReconstructionAlgorithm2D.h3
-rw-r--r--include/astra/CudaSartAlgorithm.h10
-rw-r--r--include/astra/CudaSirtAlgorithm.h10
-rw-r--r--include/astra/CudaSirtAlgorithm3D.h3
-rw-r--r--include/astra/DataProjectorPolicies.h4
-rw-r--r--include/astra/DataProjectorPolicies.inl6
-rw-r--r--include/astra/SartAlgorithm.h8
-rw-r--r--include/astra/SirtAlgorithm.h9
-rw-r--r--include/astra/Utilities.h20
-rw-r--r--matlab/tools/opTomo.m81
-rw-r--r--python/astra/data3d.py2
-rw-r--r--python/astra/functions.py2
-rw-r--r--python/astra/optomo.py4
-rw-r--r--python/astra/utils.pyx12
-rw-r--r--python/conda/build.sh10
-rw-r--r--python/conda/libastra/build.sh15
-rw-r--r--python/conda/libastra/meta.yaml22
-rw-r--r--python/conda/meta.yaml7
-rw-r--r--src/ArtAlgorithm.cpp10
-rw-r--r--src/CudaDataOperationAlgorithm.cpp2
-rw-r--r--src/CudaReconstructionAlgorithm2D.cpp22
-rw-r--r--src/CudaSartAlgorithm.cpp17
-rw-r--r--src/CudaSirtAlgorithm.cpp41
-rw-r--r--src/CudaSirtAlgorithm3D.cpp8
-rw-r--r--src/FilteredBackProjectionAlgorithm.cpp14
-rw-r--r--src/Float32VolumeData3DMemory.cpp1
-rw-r--r--src/SartAlgorithm.cpp32
-rw-r--r--src/SirtAlgorithm.cpp11
-rw-r--r--src/XMLNode.cpp4
40 files changed, 346 insertions, 152 deletions
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..4a179f1
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,45 @@
+language: python
+
+python:
+ - "2.7"
+ - "3.5"
+
+os:
+ - linux
+
+sudo: false
+
+addons:
+ apt:
+ packages:
+ - libboost-all-dev
+ - nvidia-common
+ - nvidia-current
+ - nvidia-cuda-toolkit
+ - nvidia-cuda-dev
+env:
+ - CUDA=yes
+ - CUDA=no
+
+before_install:
+ - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
+ wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh;
+ else
+ wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh;
+ fi
+ - bash miniconda.sh -b -p $HOME/miniconda
+ - export PATH="$HOME/miniconda/bin:$PATH"
+ - conda config --set always_yes yes --set changeps1 no
+ - conda update conda
+
+install:
+ - conda install python=$TRAVIS_PYTHON_VERSION six numpy scipy cython
+ - conda info -a
+ - cd build/linux
+ - ./autogen.sh
+ - if [ $CUDA == yes ]; then ./configure --prefix=$HOME/astra --with-python --with-cuda; else ./configure --prefix=$HOME/astra --with-python --without-cuda; fi
+ - make -j 4
+ - make install
+
+script:
+ - LD_LIBRARY_PATH=$HOME/astra/lib/:$LD_LIBRARY_PATH PYTHONPATH=$HOME/astra/python/:$PYTHONPATH python -c "import astra"
diff --git a/build/linux/Makefile.in b/build/linux/Makefile.in
index 9535b4c..a199bf6 100644
--- a/build/linux/Makefile.in
+++ b/build/linux/Makefile.in
@@ -150,6 +150,7 @@ BASE_OBJECTS=\
src/ParallelProjectionGeometry3D.lo \
src/ParallelVecProjectionGeometry3D.lo \
src/PlatformDepSystemCode.lo \
+ src/PluginAlgorithm.lo \
src/ProjectionGeometry2D.lo \
src/ProjectionGeometry3D.lo \
src/Projector2D.lo \
@@ -255,7 +256,6 @@ MATLAB_MEX=\
matlab/mex/astra_mex_direct_c.$(MEXSUFFIX)
ifeq ($(python),yes)
-ALL_OBJECTS+=src/PluginAlgorithm.lo
MATLAB_MEX+=matlab/mex/astra_mex_plugin_c.$(MEXSUFFIX)
endif
@@ -315,8 +315,10 @@ ifeq ($(cuda),yes)
ifeq ($(gen_static_libs),yes)
@$(NVCC) $(NVCCFLAGS) -c $(<) -o $*.o >/dev/null 2>&1
endif
- @# Generate a .d file, with target name $*.lo
- @$(NVCC) $(NVCCFLAGS) -M $(<) -MT $(*F).lo -odir $(*D) -o $(*D)/$(DEPDIR)/$(*F).d
+ @# Generate a .d file, and change the target name in it from .o to .lo
+ @$(NVCC) $(NVCCFLAGS) -M $(<) -odir $(*D) -o $(*D)/$(DEPDIR)/$(*F).d2
+ @sed '1s/\.o :/.lo :/' < $(*D)/$(DEPDIR)/$(*F).d2 > $(*D)/$(DEPDIR)/$(*F).d
+ @rm -f $(*D)/$(DEPDIR)/$(*F).d2
@# Generate empty targets for all dependencies listed in the .d file.
@# This mimics gcc's -MP option.
@for x in `cat $(*D)/$(DEPDIR)/$(*F).d`; do if test a$$x != a: -a a$$x != a\\; then echo -e "\n$$x:\n" >> $(*D)/$(DEPDIR)/$(*F).d; fi; done
diff --git a/cuda/2d/sart.cu b/cuda/2d/sart.cu
index e5cb5bb..c8608a3 100644
--- a/cuda/2d/sart.cu
+++ b/cuda/2d/sart.cu
@@ -71,6 +71,8 @@ SART::SART() : ReconAlgo()
projectionCount = 0;
iteration = 0;
customOrder = false;
+
+ fRelaxation = 1.0f;
}
@@ -98,6 +100,7 @@ void SART::reset()
projectionCount = 0;
iteration = 0;
customOrder = false;
+ fRelaxation = 1.0f;
ReconAlgo::reset();
}
@@ -200,10 +203,10 @@ bool SART::iterate(unsigned int iterations)
// BP, mask, and add back
// TODO: Try putting the masking directly in the BP
zeroVolumeData(D_tmpData, tmpPitch, dims);
- callBP_SART(D_tmpData, tmpPitch, D_projData, projPitch, angle, 1.0f);
+ callBP_SART(D_tmpData, tmpPitch, D_projData, projPitch, angle, fRelaxation);
processVol<opAddMul>(D_volumeData, D_maskData, D_tmpData, volumePitch, dims);
} else {
- callBP_SART(D_volumeData, volumePitch, D_projData, projPitch, angle, 1.0f);
+ callBP_SART(D_volumeData, volumePitch, D_projData, projPitch, angle, fRelaxation);
}
if (useMinConstraint)
diff --git a/cuda/2d/sart.h b/cuda/2d/sart.h
index 7dcd641..eff9ecf 100644
--- a/cuda/2d/sart.h
+++ b/cuda/2d/sart.h
@@ -50,6 +50,8 @@ public:
virtual float computeDiffNorm();
+ void setRelaxation(float r) { fRelaxation = r; }
+
protected:
void reset();
bool precomputeWeights();
@@ -78,6 +80,8 @@ protected:
// Geometry-specific precomputed data
float* D_lineWeight;
unsigned int linePitch;
+
+ float fRelaxation;
};
}
diff --git a/cuda/2d/sirt.cu b/cuda/2d/sirt.cu
index 162ee77..4baaccb 100644
--- a/cuda/2d/sirt.cu
+++ b/cuda/2d/sirt.cu
@@ -50,6 +50,8 @@ SIRT::SIRT() : ReconAlgo()
D_minMaskData = 0;
D_maxMaskData = 0;
+ fRelaxation = 1.0f;
+
freeMinMaxMasks = false;
}
@@ -83,6 +85,8 @@ void SIRT::reset()
useVolumeMask = false;
useSinogramMask = false;
+ fRelaxation = 1.0f;
+
ReconAlgo::reset();
}
@@ -139,6 +143,9 @@ bool SIRT::precomputeWeights()
processVol<opMul>(D_pixelWeight, D_maskData, pixelPitch, dims);
}
+ // Also fold the relaxation factor into pixel weights
+ processVol<opMul>(D_pixelWeight, fRelaxation, pixelPitch, dims);
+
return true;
}
@@ -253,6 +260,7 @@ bool SIRT::iterate(unsigned int iterations)
callBP(D_tmpData, tmpPitch, D_projData, projPitch, 1.0f);
+ // pixel weights also contain the volume mask and relaxation factor
processVol<opAddMul>(D_volumeData, D_pixelWeight, D_tmpData, volumePitch, dims);
if (useMinConstraint)
diff --git a/cuda/2d/sirt.h b/cuda/2d/sirt.h
index 21094a1..bc913f4 100644
--- a/cuda/2d/sirt.h
+++ b/cuda/2d/sirt.h
@@ -53,6 +53,8 @@ public:
bool uploadMinMaxMasks(const float* minMaskData, const float* maxMaskData,
unsigned int pitch);
+ void setRelaxation(float r) { fRelaxation = r; }
+
virtual bool iterate(unsigned int iterations);
virtual float computeDiffNorm();
@@ -81,6 +83,8 @@ protected:
unsigned int minMaskPitch;
float* D_maxMaskData;
unsigned int maxMaskPitch;
+
+ float fRelaxation;
};
bool doSIRT(float* D_volumeData, unsigned int volumePitch,
diff --git a/cuda/3d/astra3d.cu b/cuda/3d/astra3d.cu
index 8328229..5670873 100644
--- a/cuda/3d/astra3d.cu
+++ b/cuda/3d/astra3d.cu
@@ -267,6 +267,7 @@ public:
float fOriginDetectorDistance;
float fSourceZ;
float fDetSize;
+ float fRelaxation;
SConeProjection* projs;
SPar3DProjection* parprojs;
@@ -311,6 +312,8 @@ AstraSIRT3d::AstraSIRT3d()
pData->parprojs = 0;
pData->fOutputScale = 1.0f;
+ pData->fRelaxation = 1.0f;
+
pData->initialized = false;
pData->setStartReconstruction = false;
@@ -389,6 +392,14 @@ bool AstraSIRT3d::enableSuperSampling(unsigned int iVoxelSuperSampling,
return true;
}
+void AstraSIRT3d::setRelaxation(float r)
+{
+ if (pData->initialized)
+ return;
+
+ pData->fRelaxation = r;
+}
+
bool AstraSIRT3d::enableVolumeMask()
{
if (pData->initialized)
@@ -448,6 +459,8 @@ bool AstraSIRT3d::init()
if (!ok)
return false;
+ pData->sirt.setRelaxation(pData->fRelaxation);
+
pData->D_volumeData = allocateVolumeData(pData->dims);
ok = pData->D_volumeData.ptr;
if (!ok)
diff --git a/cuda/3d/astra3d.h b/cuda/3d/astra3d.h
index 2782994..2137587 100644
--- a/cuda/3d/astra3d.h
+++ b/cuda/3d/astra3d.h
@@ -68,6 +68,8 @@ public:
bool enableSuperSampling(unsigned int iVoxelSuperSampling,
unsigned int iDetectorSuperSampling);
+ void setRelaxation(float r);
+
// Enable volume/sinogram masks
//
// This may optionally be called before init().
diff --git a/cuda/3d/sirt3d.cu b/cuda/3d/sirt3d.cu
index 484521e..713944b 100644
--- a/cuda/3d/sirt3d.cu
+++ b/cuda/3d/sirt3d.cu
@@ -59,6 +59,8 @@ SIRT::SIRT() : ReconAlgo3D()
useMinConstraint = false;
useMaxConstraint = false;
+
+ fRelaxation = 1.0f;
}
@@ -89,6 +91,8 @@ void SIRT::reset()
useVolumeMask = false;
useSinogramMask = false;
+ fRelaxation = 1.0f;
+
ReconAlgo3D::reset();
}
@@ -196,6 +200,8 @@ bool SIRT::precomputeWeights()
// scale pixel weights with mask to zero out masked pixels
processVol3D<opMul>(D_pixelWeight, D_maskData, dims);
}
+ processVol3D<opMul>(D_pixelWeight, fRelaxation, dims);
+
return true;
}
@@ -307,7 +313,7 @@ bool SIRT::iterate(unsigned int iterations)
}
#endif
-
+ // pixel weights also contain the volume mask and relaxation factor
processVol3D<opAddMul>(D_volumeData, D_tmpData, D_pixelWeight, dims);
if (useMinConstraint)
diff --git a/cuda/3d/sirt3d.h b/cuda/3d/sirt3d.h
index bb3864a..5e93deb 100644
--- a/cuda/3d/sirt3d.h
+++ b/cuda/3d/sirt3d.h
@@ -48,6 +48,9 @@ public:
// init should be called after setting all geometry
bool init();
+ // Set relaxation factor. This may be called after init and before iterate.
+ void setRelaxation(float r) { fRelaxation = r; }
+
// setVolumeMask should be called after init and before iterate,
// but only if enableVolumeMask was called before init.
// It may be called again after iterate.
@@ -91,6 +94,8 @@ protected:
float fMinConstraint;
float fMaxConstraint;
+ float fRelaxation;
+
cudaPitchedPtr D_maskData;
cudaPitchedPtr D_smaskData;
diff --git a/include/astra/ArtAlgorithm.h b/include/astra/ArtAlgorithm.h
index d232b95..1ad9f3f 100644
--- a/include/astra/ArtAlgorithm.h
+++ b/include/astra/ArtAlgorithm.h
@@ -59,7 +59,7 @@ namespace astra {
* \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.}
* \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.}
* \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.}
- * \astra_xml_item_option{Lamda, float, 1, The relaxation factor.}
+ * \astra_xml_item_option{Relaxation, float, 1, The relaxation factor.}
* \astra_xml_item_option{RayOrder, string, "sequential", the order in which the rays are updated. 'sequential' or 'custom'}
* \astra_xml_item_option{RayOrderList, n by 2 vector of float, not used, if RayOrder='custom': use this ray order. Each row consist of a projection id and detector id.}
*
@@ -73,7 +73,7 @@ namespace astra {
* cfg.option.UseMinConstraint = 'yes';\n
* cfg.option.UseMaxConstraint = 'yes';\n
* cfg.option.MaxConstraintValue = 1024;\n
- * cfg.option.Lamda = 0.7;\n
+ * cfg.option.Relaxation = 0.7;\n
* cfg.option.RayOrder = 'custom';\n
* cfg.option.RayOrderList = [0\,0; 0\,2; 1\,0];\n
* alg_id = astra_mex_algorithm('create'\, cfg);\n
diff --git a/include/astra/CudaReconstructionAlgorithm2D.h b/include/astra/CudaReconstructionAlgorithm2D.h
index dc93a1a..bb5f2a7 100644
--- a/include/astra/CudaReconstructionAlgorithm2D.h
+++ b/include/astra/CudaReconstructionAlgorithm2D.h
@@ -141,6 +141,9 @@ protected:
*/
bool setupGeometry();
+ /** Initialize CUDA algorithm. For internal use only.
+ */
+ virtual void initCUDAAlgorithm();
/** The internally used CUDA algorithm object
*/
diff --git a/include/astra/CudaSartAlgorithm.h b/include/astra/CudaSartAlgorithm.h
index c22dc4f..e5e18f0 100644
--- a/include/astra/CudaSartAlgorithm.h
+++ b/include/astra/CudaSartAlgorithm.h
@@ -46,6 +46,7 @@ namespace astra {
* \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
* \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
* \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 0 = reconstruct on this pixel. 1 = don't reconstruct on this pixel.}
+ * \astra_xml_item_option{Relaxation, float, 1, The relaxation factor.}
*
* \par MATLAB example
* \astra_code{
@@ -53,6 +54,7 @@ namespace astra {
* cfg.ProjectionDataId = sino_id;\n
* cfg.ReconstructionDataId = recon_id;\n
* cfg.option.ReconstructionMaskId = mask_id;\n
+ * cfg.option.Relaxation = 1.0;\n
* alg_id = astra_mex_algorithm('create'\, cfg);\n
* astra_mex_algorithm('iterate'\, alg_id\, 10);\n
* astra_mex_algorithm('delete'\, alg_id);\n
@@ -97,6 +99,14 @@ public:
* @return description string
*/
virtual std::string description() const;
+
+protected:
+
+ /** Relaxation factor
+ */
+ float m_fLambda;
+
+ virtual void initCUDAAlgorithm();
};
// inline functions
diff --git a/include/astra/CudaSirtAlgorithm.h b/include/astra/CudaSirtAlgorithm.h
index 929ac30..3cd8acc 100644
--- a/include/astra/CudaSirtAlgorithm.h
+++ b/include/astra/CudaSirtAlgorithm.h
@@ -53,6 +53,7 @@ namespace astra {
* \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
* \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
* \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 0 = reconstruct on this pixel. 1 = don't reconstruct on this pixel.}
+ * \astra_xml_item_option{Relaxation, float, 1, Relaxation parameter.}
*
* \par MATLAB example
* \astra_code{
@@ -62,6 +63,7 @@ namespace astra {
* cfg.ProjectionDataId = sino_id;\n
* cfg.ReconstructionDataId = recon_id;\n
* cfg.option.ReconstructionMaskId = mask_id;\n
+ * cfg.option.Relaxation = 1.0;\n
* alg_id = astra_mex_algorithm('create'\, cfg);\n
* astra_mex_algorithm('iterate'\, alg_id\, 10);\n
* astra_mex_algorithm('delete'\, alg_id);\n
@@ -93,8 +95,6 @@ public:
*/
virtual bool initialize(const Config& _cfg);
- virtual void run(int _iNrIterations);
-
/** Initialize class.
*
* @param _pProjector Projector Object. (Optional)
@@ -114,6 +114,12 @@ public:
protected:
CFloat32VolumeData2D* m_pMinMask;
CFloat32VolumeData2D* m_pMaxMask;
+
+ /** Relaxation factor
+ */
+ float m_fLambda;
+
+ virtual void initCUDAAlgorithm();
};
// inline functions
diff --git a/include/astra/CudaSirtAlgorithm3D.h b/include/astra/CudaSirtAlgorithm3D.h
index 379720e..60191cd 100644
--- a/include/astra/CudaSirtAlgorithm3D.h
+++ b/include/astra/CudaSirtAlgorithm3D.h
@@ -50,7 +50,7 @@ class AstraSIRT3d;
*
* The update step of pixel \f$v_j\f$ for iteration \f$k\f$ is given by:
* \f[
- * v_j^{(k+1)} = v_j^{(k)} + \alpha \sum_{i=1}^{M} \left( \frac{w_{ij}\left( p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}\right)}{\sum_{k=1}^{N} w_{ik}} \right) \frac{1}{\sum_{l=1}^{M}w_{lj}}
+ * v_j^{(k+1)} = v_j^{(k)} + \lambda \sum_{i=1}^{M} \left( \frac{w_{ij}\left( p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}\right)}{\sum_{k=1}^{N} w_{ik}} \right) \frac{1}{\sum_{l=1}^{M}w_{lj}}
* \f]
*
* \par XML Configuration
@@ -175,6 +175,7 @@ protected:
bool m_bAstraSIRTInit;
int m_iDetectorSuperSampling;
int m_iVoxelSuperSampling;
+ float m_fLambda;
void initializeFromProjector();
};
diff --git a/include/astra/DataProjectorPolicies.h b/include/astra/DataProjectorPolicies.h
index c258f5c..acfb36f 100644
--- a/include/astra/DataProjectorPolicies.h
+++ b/include/astra/DataProjectorPolicies.h
@@ -319,10 +319,12 @@ class SIRTBPPolicy {
CFloat32ProjectionData2D* m_pTotalRayLength;
CFloat32VolumeData2D* m_pTotalPixelWeight;
+ float m_fRelaxation;
+
public:
FORCEINLINE SIRTBPPolicy();
- FORCEINLINE SIRTBPPolicy(CFloat32VolumeData2D* _pReconstruction, CFloat32ProjectionData2D* _pSinogram, CFloat32VolumeData2D* _pTotalPixelWeight, CFloat32ProjectionData2D* _pTotalRayLength);
+ FORCEINLINE SIRTBPPolicy(CFloat32VolumeData2D* _pReconstruction, CFloat32ProjectionData2D* _pSinogram, CFloat32VolumeData2D* _pTotalPixelWeight, CFloat32ProjectionData2D* _pTotalRayLength, float _fRelaxation);
FORCEINLINE ~SIRTBPPolicy();
FORCEINLINE bool rayPrior(int _iRayIndex);
diff --git a/include/astra/DataProjectorPolicies.inl b/include/astra/DataProjectorPolicies.inl
index 0c0eddd..f300761 100644
--- a/include/astra/DataProjectorPolicies.inl
+++ b/include/astra/DataProjectorPolicies.inl
@@ -712,12 +712,14 @@ SIRTBPPolicy::SIRTBPPolicy()
SIRTBPPolicy::SIRTBPPolicy(CFloat32VolumeData2D* _pReconstruction,
CFloat32ProjectionData2D* _pSinogram,
CFloat32VolumeData2D* _pTotalPixelWeight,
- CFloat32ProjectionData2D* _pTotalRayLength)
+ CFloat32ProjectionData2D* _pTotalRayLength,
+ float _fRelaxation)
{
m_pReconstruction = _pReconstruction;
m_pSinogram = _pSinogram;
m_pTotalPixelWeight = _pTotalPixelWeight;
m_pTotalRayLength = _pTotalRayLength;
+ m_fRelaxation = _fRelaxation;
}
//----------------------------------------------------------------------------------------
SIRTBPPolicy::~SIRTBPPolicy()
@@ -739,7 +741,7 @@ void SIRTBPPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight
{
float32 fGammaBeta = m_pTotalPixelWeight->getData()[_iVolumeIndex] * m_pTotalRayLength->getData()[_iRayIndex];
if ((fGammaBeta > 0.001f) || (fGammaBeta < -0.001f)) {
- m_pReconstruction->getData()[_iVolumeIndex] += _fWeight * m_pSinogram->getData()[_iRayIndex] / fGammaBeta;
+ m_pReconstruction->getData()[_iVolumeIndex] += _fWeight * m_fRelaxation * m_pSinogram->getData()[_iRayIndex] / fGammaBeta;
}
}
//----------------------------------------------------------------------------------------
diff --git a/include/astra/SartAlgorithm.h b/include/astra/SartAlgorithm.h
index eb4c61e..cdae029 100644
--- a/include/astra/SartAlgorithm.h
+++ b/include/astra/SartAlgorithm.h
@@ -49,7 +49,7 @@ namespace astra {
*
* The update step of pixel \f$v_j\f$ for projection \f$phi\f$ and iteration \f$k\f$ is given by:
* \f[
- * v_j^{(k+1)} = v_j^{(k)} + \frac{\sum_{p_i \in P_\phi} \left( \lambda \frac{p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}} {\sum_{r=1}^{N}w_{ir} } \right)} {\sum_{p_i \in P_\phi}w_{ij}}
+ * v_j^{(k+1)} = v_j^{(k)} + \lambda \frac{\sum_{p_i \in P_\phi} \left( \frac{p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}} {\sum_{r=1}^{N}w_{ir} } \right)} {\sum_{p_i \in P_\phi}w_{ij}}
* \f]
*
* \par XML Configuration
@@ -64,6 +64,7 @@ namespace astra {
* \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.}
* \astra_xml_item_option{ProjectionOrder, string, "sequential", the order in which the projections are updated. 'sequential', 'random' or 'custom'}
* \astra_xml_item_option{ProjectionOrderList, vector of float, not used, if ProjectionOrder='custom': use this order.}
+ * \astra_xml_item_option{Relaxation, float, 1, The relaxation parameter.}
*
* \par MATLAB example
* \astra_code{
@@ -76,7 +77,8 @@ namespace astra {
* cfg.option.UseMaxConstraint = 'yes';\n
* cfg.option.MaxConstraintValue = 1024;\n
* cfg.option.ProjectionOrder = 'custom';\n
-* cfg.option.ProjectionOrderList = randperm(100);\n
+ * cfg.option.ProjectionOrderList = randperm(100);\n
+ * cfg.option.Relaxation = 1.0;\n
* alg_id = astra_mex_algorithm('create'\, cfg);\n
* astra_mex_algorithm('iterate'\, alg_id\, 10);\n
* astra_mex_algorithm('delete'\, alg_id);\n
@@ -215,6 +217,8 @@ protected:
//< Current index in the projection order array.
int m_iCurrentProjection;
+ //< Relaxation parameter
+ float m_fLambda;
};
// inline functions
diff --git a/include/astra/SirtAlgorithm.h b/include/astra/SirtAlgorithm.h
index 05b3fa9..8044d09 100644
--- a/include/astra/SirtAlgorithm.h
+++ b/include/astra/SirtAlgorithm.h
@@ -49,7 +49,7 @@ namespace astra {
*
* The update step of pixel \f$v_j\f$ for iteration \f$k\f$ is given by:
* \f[
- * v_j^{(k+1)} = v_j^{(k)} + \alpha \sum_{i=1}^{M} \left( \frac{w_{ij}\left( p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}\right)}{\sum_{k=1}^{N} w_{ik}} \right) \frac{1}{\sum_{l=1}^{M}w_{lj}}
+ * v_j^{(k+1)} = v_j^{(k)} + \lambda \sum_{i=1}^{M} \left( \frac{w_{ij}\left( p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}\right)}{\sum_{k=1}^{N} w_{ik}} \right) \frac{1}{\sum_{l=1}^{M}w_{lj}}
* \f]
*
* \par XML Configuration
@@ -62,6 +62,7 @@ namespace astra {
* \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.}
* \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.}
* \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.}
+ * \astra_xml_item_option{Relaxation, float, 1, The relaxation factor.}
*
* \par XML Example
* \astra_code{
@@ -74,6 +75,7 @@ namespace astra {
* &lt;Option key="UseMinConstraint" value="yes"/&gt;\n
* &lt;Option key="UseMaxConstraint" value="yes"/&gt;\n
* &lt;Option key="MaxConstraintValue" value="1024"/&gt;\n
+ * &lt;Option key="Relaxation" value="1"/&gt;\n
* &lt;/Algorithm&gt;
* }
*
@@ -88,6 +90,7 @@ namespace astra {
* cfg.option.UseMinConstraint = 'yes';\n
* cfg.option.UseMaxConstraint = 'yes';\n
* cfg.option.MaxConstraintValue = 1024;\n
+ * cfg.option.Relaxation = 1.0;\n
* alg_id = astra_mex_algorithm('create'\, cfg);\n
* astra_mex_algorithm('iterate'\, alg_id\, 10);\n
* astra_mex_algorithm('delete'\, alg_id);\n
@@ -136,6 +139,10 @@ protected:
*/
int m_iIterationCount;
+ /** Relaxation parameter
+ */
+ float m_fLambda;
+
public:
// type of the algorithm, needed to register with CAlgorithmFactory
diff --git a/include/astra/Utilities.h b/include/astra/Utilities.h
index 3ae0e6c..8d7c44d 100644
--- a/include/astra/Utilities.h
+++ b/include/astra/Utilities.h
@@ -50,40 +50,40 @@ public:
//< Parse string as int.
//< Throw exception on failure.
-int stringToInt(const std::string& s);
+_AstraExport int stringToInt(const std::string& s);
//< Parse string as float.
//< Throw exception on failure.
-float stringToFloat(const std::string& s);
+_AstraExport float stringToFloat(const std::string& s);
//< Parse string as double.
//< Throw exception on failure.
-double stringToDouble(const std::string& s);
+_AstraExport double stringToDouble(const std::string& s);
template<typename T>
-T stringTo(const std::string& s);
+_AstraExport T stringTo(const std::string& s);
//< Parse comma/semicolon-separated string as float vector.
//< Throw exception on failure.
-std::vector<float> stringToFloatVector(const std::string& s);
+_AstraExport std::vector<float> stringToFloatVector(const std::string& s);
//< Parse comma/semicolon-separated string as double vector.
//< Throw exception on failure.
-std::vector<double> stringToDoubleVector(const std::string& s);
+_AstraExport std::vector<double> stringToDoubleVector(const std::string& s);
template<typename T>
-std::vector<T> stringToVector(const std::string& s);
+_AstraExport std::vector<T> stringToVector(const std::string& s);
//< Generate string from float.
-std::string floatToString(float f);
+_AstraExport std::string floatToString(float f);
//< Generate string from double.
-std::string doubleToString(double f);
+_AstraExport std::string doubleToString(double f);
template<typename T>
-std::string toString(T f);
+_AstraExport std::string toString(T f);
}
diff --git a/matlab/tools/opTomo.m b/matlab/tools/opTomo.m
index 71dfb1e..04b3634 100644
--- a/matlab/tools/opTomo.m
+++ b/matlab/tools/opTomo.m
@@ -44,11 +44,9 @@ classdef opTomo < opSpot
vol_id
fp_alg_id
bp_alg_id
+ proj_id
% ASTRA IDs handle
astra_handle
- % geometries
- proj_geom;
- vol_geom;
end % properties
properties ( SetAccess = private, GetAccess = public )
@@ -139,6 +137,17 @@ classdef opTomo < opSpot
error(['Only type ' 39 'cuda' 39 ' is supported ' ...
'for 3D geometries.'])
end
+
+ % setup projector
+ cfg = astra_struct('cuda3d');
+ cfg.ProjectionGeometry = proj_geom;
+ cfg.VolumeGeometry = vol_geom;
+ cfg.option.GPUindex = gpu_index;
+
+ % create projector
+ op.proj_id = astra_mex_projector3d('create', cfg);
+ % create handle to ASTRA object, for cleaning up
+ op.astra_handle = opTomo_helper_handle(op.proj_id);
% create a function handle
op.funHandle = @opTomo_intrnl3D;
@@ -148,8 +157,6 @@ classdef opTomo < opSpot
% pass object properties
op.proj_size = proj_size;
op.vol_size = vol_size;
- op.proj_geom = proj_geom;
- op.vol_geom = vol_geom;
op.cflag = false;
op.sweepflag = false;
@@ -169,10 +176,12 @@ classdef opTomo < opSpot
if issparse(x)
x = full(x);
end
-
- % convert input to single
- if isa(x, 'single') == false
+
+ if isa(x, 'double')
+ isdouble = true;
x = single(x);
+ else
+ isdouble = false;
end
% the multiplication
@@ -180,6 +189,10 @@ classdef opTomo < opSpot
% make sure output is column vector
y = y(:);
+
+ if isdouble
+ y = double(y);
+ end
end % multiply
@@ -194,7 +207,7 @@ classdef opTomo < opSpot
function y = opTomo_intrnl2D(op,x,mode)
if mode == 1
- % X is passed as a vector, reshape it into an image.
+ % x is passed as a vector, reshape it into an image.
x = reshape(x, op.vol_size);
% Matlab data copied to ASTRA data
@@ -206,7 +219,7 @@ classdef opTomo < opSpot
% retrieve Matlab array
y = astra_mex_data2d('get_single', op.sino_id);
else
- % X is passed as a vector, reshape it into a sinogram.
+ % x is passed as a vector, reshape it into a sinogram.
x = reshape(x, op.proj_size);
% Matlab data copied to ASTRA data
@@ -218,6 +231,7 @@ classdef opTomo < opSpot
% retrieve Matlab array
y = astra_mex_data2d('get_single', op.vol_id);
end
+
end % opTomo_intrnl2D
@@ -225,55 +239,16 @@ classdef opTomo < opSpot
function y = opTomo_intrnl3D(op,x,mode)
if mode == 1
- % X is passed as a vector, reshape it into an image
+ % x is passed as a vector, reshape it into an image
x = reshape(x, op.vol_size);
- % initialize output
- y = zeros(op.proj_size, 'single');
-
- % link matlab array to ASTRA
- vol_id = astra_mex_data3d_c('link', '-vol', op.vol_geom, x, 0);
- sino_id = astra_mex_data3d_c('link', '-sino', op.proj_geom, y, 1);
-
- % initialize fp algorithm
- cfg = astra_struct('FP3D_CUDA');
- cfg.ProjectionDataId = sino_id;
- cfg.VolumeDataId = vol_id;
-
- alg_id = astra_mex_algorithm('create', cfg);
-
% forward projection
- astra_mex_algorithm('iterate', alg_id);
-
- % cleanup
- astra_mex_data3d('delete', vol_id);
- astra_mex_data3d('delete', sino_id);
- astra_mex_algorithm('delete', alg_id);
+ y = astra_mex_direct('FP3D', op.proj_id, x);
else
- % X is passed as a vector, reshape it into projection data
+ % x is passed as a vector, reshape it into projection data
x = reshape(x, op.proj_size);
-
- % initialize output
- y = zeros(op.vol_size,'single');
-
- % link matlab array to ASTRA
- vol_id = astra_mex_data3d_c('link', '-vol', op.vol_geom, y, 1);
- sino_id = astra_mex_data3d_c('link', '-sino', op.proj_geom, x, 0);
- % initialize bp algorithm
- cfg = astra_struct('BP3D_CUDA');
- cfg.ProjectionDataId = sino_id;
- cfg.ReconstructionDataId = vol_id;
-
- alg_id = astra_mex_algorithm('create', cfg);
-
- % backprojection
- astra_mex_algorithm('iterate', alg_id);
-
- % cleanup
- astra_mex_data3d('delete', vol_id);
- astra_mex_data3d('delete', sino_id);
- astra_mex_algorithm('delete', alg_id);
+ y = astra_mex_direct('BP3D', op.proj_id, x);
end
end % opTomo_intrnl3D
diff --git a/python/astra/data3d.py b/python/astra/data3d.py
index e5ef6b0..f143659 100644
--- a/python/astra/data3d.py
+++ b/python/astra/data3d.py
@@ -89,7 +89,7 @@ def get_single(i):
:returns: :class:`numpy.ndarray` -- The object data.
"""
- return g.get_single(i)
+ return d.get_single(i)
def store(i,data):
"""Fill existing 3D object with data.
diff --git a/python/astra/functions.py b/python/astra/functions.py
index e38b5bc..3f4aa82 100644
--- a/python/astra/functions.py
+++ b/python/astra/functions.py
@@ -115,7 +115,7 @@ def add_noise_to_sino(sinogram_in, I0, seed=None):
sinogram_out = -max_sinogramRaw * np.log(sinogramCT_D)
if not isinstance(sinogram_in, np.ndarray):
- at.data2d.store(sinogram_in, sinogram_out)
+ data2d.store(sinogram_in, sinogram_out)
if not seed==None:
np.random.set_state(curstate)
diff --git a/python/astra/optomo.py b/python/astra/optomo.py
index 4a64150..dd10713 100644
--- a/python/astra/optomo.py
+++ b/python/astra/optomo.py
@@ -160,7 +160,7 @@ class OpTomo(scipy.sparse.linalg.LinearOperator):
return self._matvec(v)
return scipy.sparse.linalg.LinearOperator.__mul__(self, v)
- def reconstruct(self, method, s, iterations=1, extraOptions = {}):
+ def reconstruct(self, method, s, iterations=1, extraOptions = None):
"""Reconstruct an object.
:param method: Method to use for reconstruction.
@@ -172,6 +172,8 @@ class OpTomo(scipy.sparse.linalg.LinearOperator):
:param extraOptions: Extra options to use during reconstruction (i.e. for cfg['option']).
:type extraOptions: :class:`dict`
"""
+ if extraOptions is None:
+ extraOptions={}
s = self.__checkArray(s, self.sshape)
sid = self.data_mod.link('-sino',self.pg,s)
v = np.zeros(self.vshape,dtype=np.float32)
diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx
index 52c2a8d..34d1902 100644
--- a/python/astra/utils.pyx
+++ b/python/astra/utils.pyx
@@ -32,7 +32,7 @@ import six
if six.PY3:
import builtins
else:
- import __builtin__
+ import __builtin__ as builtins
from libcpp.string cimport string
from libcpp.vector cimport vector
from libcpp.list cimport list
@@ -95,14 +95,14 @@ cdef void readDict(XMLNode root, _dc):
dc = convert_item(_dc)
for item in dc:
val = dc[item]
- if isinstance(val, __builtins__.list) or isinstance(val, tuple):
+ if isinstance(val, builtins.list) or isinstance(val, tuple):
val = np.array(val,dtype=np.float64)
if isinstance(val, np.ndarray):
if val.size == 0:
break
listbase = root.addChildNode(item)
contig_data = np.ascontiguousarray(val,dtype=np.float64)
- data = <double*>np.PyArray_DATA(contig_data)
+ data = <double*>np.PyArray_DATA(contig_data)
if val.ndim == 2:
listbase.setContent(data, val.shape[1], val.shape[0], False)
elif val.ndim == 1:
@@ -119,6 +119,8 @@ cdef void readDict(XMLNode root, _dc):
if item == six.b('type'):
root.addAttribute(< string > six.b('type'), <string> wrap_to_bytes(val))
else:
+ if isinstance(val, builtins.bool):
+ val = int(val)
itm = root.addChildNode(item, wrap_to_bytes(val))
cdef void readOptions(XMLNode node, dc):
@@ -131,7 +133,7 @@ cdef void readOptions(XMLNode node, dc):
val = dc[item]
if node.hasOption(item):
raise Exception('Duplicate Option: %s' % item)
- if isinstance(val, __builtins__.list) or isinstance(val, tuple):
+ if isinstance(val, builtins.list) or isinstance(val, tuple):
val = np.array(val,dtype=np.float64)
if isinstance(val, np.ndarray):
if val.size == 0:
@@ -147,6 +149,8 @@ cdef void readOptions(XMLNode node, dc):
else:
raise Exception("Only 1 or 2 dimensions are allowed")
else:
+ if isinstance(val, builtins.bool):
+ val = int(val)
node.addOption(item, wrap_to_bytes(val))
cdef configToDict(Config *cfg):
diff --git a/python/conda/build.sh b/python/conda/build.sh
index 814ea7e..13ae3f8 100644
--- a/python/conda/build.sh
+++ b/python/conda/build.sh
@@ -5,12 +5,4 @@ if [ $MAKEOPTS == '<UNDEFINED>' ]
then
MAKEOPTS=""
fi
-make $MAKEOPTS install-libraries
-make $MAKEOPTS python-root-install
-LIBPATH=lib
-if [ $ARCH == 64 ]
- then
- LIBPATH+=64
-fi
-cp -P $CUDA_ROOT/$LIBPATH/libcudart.so.* $PREFIX/lib
-cp -P $CUDA_ROOT/$LIBPATH/libcufft.so.* $PREFIX/lib
+make $MAKEOPTS python-root-install \ No newline at end of file
diff --git a/python/conda/libastra/build.sh b/python/conda/libastra/build.sh
new file mode 100644
index 0000000..e1d9700
--- /dev/null
+++ b/python/conda/libastra/build.sh
@@ -0,0 +1,15 @@
+cd build/linux
+./autogen.sh
+./configure --with-cuda=$CUDA_ROOT --prefix=$PREFIX
+if [ $MAKEOPTS == '<UNDEFINED>' ]
+ then
+ MAKEOPTS=""
+fi
+make $MAKEOPTS install-libraries
+LIBPATH=lib
+if [ $ARCH == 64 ]
+ then
+ LIBPATH+=64
+fi
+cp -P $CUDA_ROOT/$LIBPATH/libcudart.so.* $PREFIX/lib
+cp -P $CUDA_ROOT/$LIBPATH/libcufft.so.* $PREFIX/lib
diff --git a/python/conda/libastra/meta.yaml b/python/conda/libastra/meta.yaml
new file mode 100644
index 0000000..73fa0d7
--- /dev/null
+++ b/python/conda/libastra/meta.yaml
@@ -0,0 +1,22 @@
+package:
+ name: libastra
+ version: '1.8b'
+
+source:
+ git_url: https://github.com/astra-toolbox/astra-toolbox.git
+ #git_tag: v1.7.1 # Change to 1.8 after release
+
+build:
+ number: 0
+ script_env:
+ - CUDA_ROOT
+ - MAKEOPTS
+
+about:
+ home: http://www.astra-toolbox.com
+ license: GPLv3
+ summary: 'The ASTRA Toolbox is a Python toolbox of high-performance GPU primitives for 2D and 3D tomography.'
+
+# See
+# http://docs.continuum.io/conda/build.html for
+# more information about meta.yaml
diff --git a/python/conda/meta.yaml b/python/conda/meta.yaml
index 7e4679b..e6a7f52 100644
--- a/python/conda/meta.yaml
+++ b/python/conda/meta.yaml
@@ -1,10 +1,10 @@
package:
name: astra-toolbox
- version: '1.7.1'
+ version: '1.8b'
source:
git_url: https://github.com/astra-toolbox/astra-toolbox.git
- git_tag: v1.7.1
+ #git_tag: v1.7.1 # Change to 1.8 after release
build:
number: 0
@@ -29,10 +29,11 @@ requirements:
- numpy
- scipy
- six
+ - libastra ==1.8b
about:
- home: http://sourceforge.net/p/astra-toolbox/wiki/Home/
+ home: http://www.astra-toolbox.com
license: GPLv3
summary: 'The ASTRA Toolbox is a Python toolbox of high-performance GPU primitives for 2D and 3D tomography.'
diff --git a/src/ArtAlgorithm.cpp b/src/ArtAlgorithm.cpp
index b59bd93..526c263 100644
--- a/src/ArtAlgorithm.cpp
+++ b/src/ArtAlgorithm.cpp
@@ -156,8 +156,12 @@ bool CArtAlgorithm::initialize(const Config& _cfg)
return false;
}
+ // "Lambda" is replaced by the more descriptive "Relaxation"
m_fLambda = _cfg.self.getOptionNumerical("Lambda", 1.0f);
- CC.markOptionParsed("Lambda");
+ m_fLambda = _cfg.self.getOptionNumerical("Relaxation", m_fLambda);
+ if (!_cfg.self.hasOption("Relaxation"))
+ CC.markOptionParsed("Lambda");
+ CC.markOptionParsed("Relaxation");
// success
m_bIsInitialized = _check();
@@ -232,7 +236,7 @@ map<string,boost::any> CArtAlgorithm::getInformation()
{
map<string, boost::any> res;
res["RayOrder"] = getInformation("RayOrder");
- res["Lambda"] = getInformation("Lambda");
+ res["Relaxation"] = getInformation("Relaxation");
return mergeMap<string,boost::any>(CReconstructionAlgorithm2D::getInformation(), res);
};
@@ -240,7 +244,7 @@ map<string,boost::any> CArtAlgorithm::getInformation()
// Information - Specific
boost::any CArtAlgorithm::getInformation(std::string _sIdentifier)
{
- if (_sIdentifier == "Lambda") { return m_fLambda; }
+ if (_sIdentifier == "Relaxation") { return m_fLambda; }
if (_sIdentifier == "RayOrder") {
vector<float32> res;
for (int i = 0; i < m_iRayCount; i++) {
diff --git a/src/CudaDataOperationAlgorithm.cpp b/src/CudaDataOperationAlgorithm.cpp
index 15886a4..82b676b 100644
--- a/src/CudaDataOperationAlgorithm.cpp
+++ b/src/CudaDataOperationAlgorithm.cpp
@@ -76,7 +76,7 @@ bool CCudaDataOperationAlgorithm::initialize(const Config& _cfg)
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++){
+ for (vector<string>::iterator it = data.begin(); it != data.end(); ++it){
int id = StringUtil::stringToInt(*it);
m_pData.push_back(dynamic_cast<CFloat32Data2D*>(CData2DManager::getSingleton().get(id)));
}
diff --git a/src/CudaReconstructionAlgorithm2D.cpp b/src/CudaReconstructionAlgorithm2D.cpp
index 5a1910c..2798434 100644
--- a/src/CudaReconstructionAlgorithm2D.cpp
+++ b/src/CudaReconstructionAlgorithm2D.cpp
@@ -329,6 +329,20 @@ bool CCudaReconstructionAlgorithm2D::setupGeometry()
}
//----------------------------------------------------------------------------------------
+
+void CCudaReconstructionAlgorithm2D::initCUDAAlgorithm()
+{
+ bool ok;
+
+ ok = setupGeometry();
+ ASTRA_ASSERT(ok);
+
+ ok = m_pAlgo->allocateBuffers();
+ ASTRA_ASSERT(ok);
+}
+
+
+//----------------------------------------------------------------------------------------
// Iterate
void CCudaReconstructionAlgorithm2D::run(int _iNrIterations)
{
@@ -339,13 +353,7 @@ void CCudaReconstructionAlgorithm2D::run(int _iNrIterations)
const CVolumeGeometry2D& volgeom = *m_pReconstruction->getGeometry();
if (!m_bAlgoInit) {
-
- ok = setupGeometry();
- ASTRA_ASSERT(ok);
-
- ok = m_pAlgo->allocateBuffers();
- ASTRA_ASSERT(ok);
-
+ initCUDAAlgorithm();
m_bAlgoInit = true;
}
diff --git a/src/CudaSartAlgorithm.cpp b/src/CudaSartAlgorithm.cpp
index d202847..bf97224 100644
--- a/src/CudaSartAlgorithm.cpp
+++ b/src/CudaSartAlgorithm.cpp
@@ -107,7 +107,8 @@ bool CCudaSartAlgorithm::initialize(const Config& _cfg)
CC.markOptionParsed("ProjectionOrderList");
}
-
+ m_fLambda = _cfg.self.getOptionNumerical("Relaxation", 1.0f);
+ CC.markOptionParsed("Relaxation");
return true;
}
@@ -123,12 +124,26 @@ bool CCudaSartAlgorithm::initialize(CProjector2D* _pProjector,
if (!m_bIsInitialized)
return false;
+ m_fLambda = 1.0f;
+
m_pAlgo = new astraCUDA::SART();
m_bAlgoInit = false;
return true;
}
+//----------------------------------------------------------------------------------------
+
+void CCudaSartAlgorithm::initCUDAAlgorithm()
+{
+ CCudaReconstructionAlgorithm2D::initCUDAAlgorithm();
+
+ astraCUDA::SART* pSart = dynamic_cast<astraCUDA::SART*>(m_pAlgo);
+
+ pSart->setRelaxation(m_fLambda);
+}
+
+
} // namespace astra
diff --git a/src/CudaSirtAlgorithm.cpp b/src/CudaSirtAlgorithm.cpp
index 33e381a..c8dc677 100644
--- a/src/CudaSirtAlgorithm.cpp
+++ b/src/CudaSirtAlgorithm.cpp
@@ -50,6 +50,8 @@ CCudaSirtAlgorithm::CCudaSirtAlgorithm()
m_pMinMask = 0;
m_pMaxMask = 0;
+
+ m_fLambda = 1.0f;
}
//----------------------------------------------------------------------------------------
@@ -86,6 +88,8 @@ bool CCudaSirtAlgorithm::initialize(const Config& _cfg)
}
CC.markOptionParsed("MaxMaskId");
+ m_fLambda = _cfg.self.getOptionNumerical("Relaxation", 1.0f);
+ CC.markOptionParsed("Relaxation");
m_pAlgo = new astraCUDA::SIRT();
m_bAlgoInit = false;
@@ -108,41 +112,30 @@ bool CCudaSirtAlgorithm::initialize(CProjector2D* _pProjector,
m_pAlgo = new astraCUDA::SIRT();
m_bAlgoInit = false;
+ m_fLambda = 1.0f;
return true;
}
//----------------------------------------------------------------------------------------
-// Iterate
-void CCudaSirtAlgorithm::run(int _iNrIterations)
+
+void CCudaSirtAlgorithm::initCUDAAlgorithm()
{
- // check initialized
- ASTRA_ASSERT(m_bIsInitialized);
+ CCudaReconstructionAlgorithm2D::initCUDAAlgorithm();
- if (!m_bAlgoInit) {
- // We only override the initialisation step to copy the min/max masks
+ astraCUDA::SIRT* pSirt = dynamic_cast<astraCUDA::SIRT*>(m_pAlgo);
- bool ok = setupGeometry();
+ if (m_pMinMask || m_pMaxMask) {
+ const CVolumeGeometry2D& volgeom = *m_pReconstruction->getGeometry();
+ const float *pfMinMaskData = 0;
+ const float *pfMaxMaskData = 0;
+ if (m_pMinMask) pfMinMaskData = m_pMinMask->getDataConst();
+ if (m_pMaxMask) pfMaxMaskData = m_pMaxMask->getDataConst();
+ bool ok = pSirt->uploadMinMaxMasks(pfMinMaskData, pfMaxMaskData, volgeom.getGridColCount());
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);
+ pSirt->setRelaxation(m_fLambda);
}
diff --git a/src/CudaSirtAlgorithm3D.cpp b/src/CudaSirtAlgorithm3D.cpp
index 605c470..c819f8e 100644
--- a/src/CudaSirtAlgorithm3D.cpp
+++ b/src/CudaSirtAlgorithm3D.cpp
@@ -56,6 +56,7 @@ CCudaSirtAlgorithm3D::CCudaSirtAlgorithm3D()
m_iGPUIndex = -1;
m_iVoxelSuperSampling = 1;
m_iDetectorSuperSampling = 1;
+ m_fLambda = 1.0f;
}
//----------------------------------------------------------------------------------------
@@ -128,6 +129,8 @@ bool CCudaSirtAlgorithm3D::initialize(const Config& _cfg)
return false;
}
+ m_fLambda = _cfg.self.getOptionNumerical("Relaxation");
+
initializeFromProjector();
// Deprecated options
@@ -135,6 +138,7 @@ bool CCudaSirtAlgorithm3D::initialize(const Config& _cfg)
m_iDetectorSuperSampling = (int)_cfg.self.getOptionNumerical("DetectorSuperSampling", m_iDetectorSuperSampling);
m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", m_iGPUIndex);
m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex);
+
CC.markOptionParsed("VoxelSuperSampling");
CC.markOptionParsed("DetectorSuperSampling");
CC.markOptionParsed("GPUIndex");
@@ -164,6 +168,8 @@ bool CCudaSirtAlgorithm3D::initialize(CProjector3D* _pProjector,
clear();
}
+ m_fLambda = 1.0f;
+
// required classes
m_pProjector = _pProjector;
m_pSinogram = _pSinogram;
@@ -224,6 +230,8 @@ void CCudaSirtAlgorithm3D::run(int _iNrIterations)
ASTRA_ASSERT(ok);
+ m_pSirt->setRelaxation(m_fLambda);
+
m_bAstraSIRTInit = true;
}
diff --git a/src/FilteredBackProjectionAlgorithm.cpp b/src/FilteredBackProjectionAlgorithm.cpp
index c195578..ccbfec6 100644
--- a/src/FilteredBackProjectionAlgorithm.cpp
+++ b/src/FilteredBackProjectionAlgorithm.cpp
@@ -117,12 +117,10 @@ bool CFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)
int angleCount = projectionIndex.size();
int detectorCount = m_pProjector->getProjectionGeometry()->getDetectorCount();
+ // TODO: There is no need to allocate this. Better just
+ // create the CFloat32ProjectionData2D object directly, and use its
+ // memory.
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();
@@ -130,6 +128,8 @@ bool CFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)
for (int i = 0; i < angleCount; i ++) {
if (projectionIndex[i] > m_pProjector->getProjectionGeometry()->getProjectionAngleCount() -1 )
{
+ delete[] sinogramData2D;
+ delete[] projectionAngles;
ASTRA_ERROR("Invalid Projection Index");
return false;
} else {
@@ -139,7 +139,6 @@ bool CFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)
{
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] );
}
@@ -148,6 +147,9 @@ bool CFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)
CParallelProjectionGeometry2D * pg = new CParallelProjectionGeometry2D(angleCount, detectorCount,detectorWidth,projectionAngles);
m_pProjector = new CParallelBeamLineKernelProjector2D(pg,m_pReconstruction->getGeometry());
m_pSinogram = new CFloat32ProjectionData2D(pg, sinogramData2D);
+
+ delete[] sinogramData2D;
+ delete[] projectionAngles;
}
// TODO: check that the angles are linearly spaced between 0 and pi
diff --git a/src/Float32VolumeData3DMemory.cpp b/src/Float32VolumeData3DMemory.cpp
index af45cb9..14adb1a 100644
--- a/src/Float32VolumeData3DMemory.cpp
+++ b/src/Float32VolumeData3DMemory.cpp
@@ -136,7 +136,6 @@ CFloat32VolumeData2D * CFloat32VolumeData3DMemory::fetchSliceZ(int _iSliceIndex)
CFloat32VolumeData2D* res = new CFloat32VolumeData2D(&volGeom);
// copy data
- int iSliceCount = m_pGeometry->getGridSliceCount();
float * pfTargetData = res->getData();
for(int iRowIndex = 0; iRowIndex < iRowCount; iRowIndex++)
{
diff --git a/src/SartAlgorithm.cpp b/src/SartAlgorithm.cpp
index 9346160..8df3342 100644
--- a/src/SartAlgorithm.cpp
+++ b/src/SartAlgorithm.cpp
@@ -151,6 +151,9 @@ bool CSartAlgorithm::initialize(const Config& _cfg)
CC.markOptionParsed("ProjectionOrderList");
}
+ m_fLambda = _cfg.self.getOptionNumerical("Relaxation", 1.0f);
+ CC.markOptionParsed("Relaxation");
+
// create data objects
m_pTotalRayLength = new CFloat32ProjectionData2D(m_pProjector->getProjectionGeometry());
m_pTotalPixelWeight = new CFloat32VolumeData2D(m_pProjector->getVolumeGeometry());
@@ -246,6 +249,7 @@ map<string,boost::any> CSartAlgorithm::getInformation()
{
map<string, boost::any> res;
res["ProjectionOrder"] = getInformation("ProjectionOrder");
+ res["Relaxation"] = getInformation("Relaxation");
return mergeMap<string,boost::any>(CReconstructionAlgorithm2D::getInformation(), res);
};
@@ -253,6 +257,8 @@ map<string,boost::any> CSartAlgorithm::getInformation()
// Information - Specific
boost::any CSartAlgorithm::getInformation(std::string _sIdentifier)
{
+ if (_sIdentifier == "Relaxation")
+ return m_fLambda;
if (_sIdentifier == "ProjectionOrder") {
vector<float32> res;
for (int i = 0; i < m_iProjectionCount; i++) {
@@ -272,9 +278,8 @@ void CSartAlgorithm::run(int _iNrIterations)
m_bShouldAbort = false;
- int iIteration = 0;
-
// data projectors
+ CDataProjectorInterface* pFirstForwardProjector;
CDataProjectorInterface* pForwardProjector;
CDataProjectorInterface* pBackProjector;
@@ -286,13 +291,13 @@ void CSartAlgorithm::run(int _iNrIterations)
m_pProjector,
SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
- SIRTBPPolicy(m_pReconstruction, m_pDiffSinogram, m_pTotalPixelWeight, m_pTotalRayLength), // SIRT backprojection
+ SIRTBPPolicy(m_pReconstruction, m_pDiffSinogram, m_pTotalPixelWeight, m_pTotalRayLength, m_fLambda), // 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(
+ pFirstForwardProjector = dispatchDataProjector(
m_pProjector,
SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
@@ -303,16 +308,30 @@ void CSartAlgorithm::run(int _iNrIterations)
m_bUseSinogramMask, m_bUseReconstructionMask, true // options on/off
);
+ // forward projection data projector
+ pForwardProjector = dispatchDataProjector(
+ m_pProjector,
+ SinogramMaskPolicy(m_pSinogramMask), // sinogram mask
+ ReconstructionMaskPolicy(m_pReconstructionMask), // reconstruction mask
+ CombinePolicy<DiffFPPolicy, TotalPixelWeightPolicy>( // 2 basic operations
+ DiffFPPolicy(m_pReconstruction, m_pDiffSinogram, m_pSinogram), // forward projection with difference calculation
+ TotalPixelWeightPolicy(m_pTotalPixelWeight)), // calculate the total pixel weights
+ m_bUseSinogramMask, m_bUseReconstructionMask, true // options on/off
+ );
+
// iteration loop
- for (; iIteration < _iNrIterations && !m_bShouldAbort; ++iIteration) {
+ for (int iIteration = 0; 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);
+ if (iIteration < m_iProjectionCount)
+ pFirstForwardProjector->projectSingleProjection(iProjection);
+ else
+ pForwardProjector->projectSingleProjection(iProjection);
// backprojection
pBackProjector->projectSingleProjection(iProjection);
// update iteration count
@@ -325,6 +344,7 @@ void CSartAlgorithm::run(int _iNrIterations)
}
+ ASTRA_DELETE(pFirstForwardProjector);
ASTRA_DELETE(pForwardProjector);
ASTRA_DELETE(pBackProjector);
diff --git a/src/SirtAlgorithm.cpp b/src/SirtAlgorithm.cpp
index d9f3a65..ff25648 100644
--- a/src/SirtAlgorithm.cpp
+++ b/src/SirtAlgorithm.cpp
@@ -76,6 +76,7 @@ void CSirtAlgorithm::_clear()
m_pDiffSinogram = NULL;
m_pTmpVolume = NULL;
+ m_fLambda = 1.0f;
m_iIterationCount = 0;
}
@@ -91,6 +92,7 @@ void CSirtAlgorithm::clear()
ASTRA_DELETE(m_pDiffSinogram);
ASTRA_DELETE(m_pTmpVolume);
+ m_fLambda = 1.0f;
m_iIterationCount = 0;
}
@@ -128,6 +130,9 @@ bool CSirtAlgorithm::initialize(const Config& _cfg)
return false;
}
+ m_fLambda = _cfg.self.getOptionNumerical("Relaxation", 1.0f);
+ CC.markOptionParsed("Relaxation");
+
// init data objects and data projectors
_init();
@@ -152,6 +157,8 @@ bool CSirtAlgorithm::initialize(CProjector2D* _pProjector,
m_pSinogram = _pSinogram;
m_pReconstruction = _pReconstruction;
+ m_fLambda = 1.0f;
+
// init data objects and data projectors
_init();
@@ -248,7 +255,7 @@ void CSirtAlgorithm::run(int _iNrIterations)
x = 1.0f / x;
else
x = 0.0f;
- pfT[i] = x;
+ pfT[i] = m_fLambda * x;
}
pfT = m_pTotalRayLength->getData();
for (int i = 0; i < m_pTotalRayLength->getSize(); ++i) {
@@ -296,7 +303,7 @@ void CSirtAlgorithm::run(int _iNrIterations)
m_pTmpVolume->setData(0.0f);
pBackProjector->project();
- // divide by pixel weights
+ // multiply with relaxation factor divided by pixel weights
(*m_pTmpVolume) *= (*m_pTotalPixelWeight);
(*m_pReconstruction) += (*m_pTmpVolume);
diff --git a/src/XMLNode.cpp b/src/XMLNode.cpp
index 40a9b22..cf268c2 100644
--- a/src/XMLNode.cpp
+++ b/src/XMLNode.cpp
@@ -158,7 +158,7 @@ vector<string> XMLNode::getContentArray() const
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++) {
+ 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);
@@ -290,7 +290,7 @@ vector<float32> XMLNode::getOptionNumericalArray(string _sKey) const
if (!hasOption(_sKey)) return vector<float32>();
list<XMLNode> nodes = getNodes("Option");
- for (list<XMLNode>::iterator it = nodes.begin(); it != nodes.end(); it++) {
+ for (list<XMLNode>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
if (it->getAttribute("key") == _sKey) {
vector<float32> vals = it->getContentNumericalArray();
return vals;