summaryrefslogtreecommitdiffstats
path: root/python/astra
diff options
context:
space:
mode:
Diffstat (limited to 'python/astra')
-rw-r--r--python/astra/ASTRAProjector.py138
-rw-r--r--python/astra/PyAlgorithmFactory.pxd36
-rw-r--r--python/astra/PyAlgorithmManager.pxd40
-rw-r--r--python/astra/PyData2DManager.pxd39
-rw-r--r--python/astra/PyData3DManager.pxd39
-rw-r--r--python/astra/PyIncludes.pxd215
-rw-r--r--python/astra/PyMatrixManager.pxd39
-rw-r--r--python/astra/PyProjector2DFactory.pxd35
-rw-r--r--python/astra/PyProjector2DManager.pxd39
-rw-r--r--python/astra/PyXMLDocument.pxd65
-rw-r--r--python/astra/__init__.py42
-rw-r--r--python/astra/algorithm.py76
-rw-r--r--python/astra/algorithm_c.pyx106
-rw-r--r--python/astra/astra.py58
-rw-r--r--python/astra/astra_c.pyx79
-rw-r--r--python/astra/creators.py563
-rw-r--r--python/astra/data2d.py120
-rw-r--r--python/astra/data2d_c.pyx241
-rw-r--r--python/astra/data3d.py108
-rw-r--r--python/astra/data3d_c.pyx188
-rw-r--r--python/astra/extrautils.pyx43
-rw-r--r--python/astra/functions.py270
-rw-r--r--python/astra/matlab.py112
-rw-r--r--python/astra/matrix.py86
-rw-r--r--python/astra/matrix_c.pyx116
-rw-r--r--python/astra/projector.py100
-rw-r--r--python/astra/projector_c.pyx119
-rw-r--r--python/astra/utils.pxd37
-rw-r--r--python/astra/utils.pyx260
29 files changed, 3409 insertions, 0 deletions
diff --git a/python/astra/ASTRAProjector.py b/python/astra/ASTRAProjector.py
new file mode 100644
index 0000000..96acb10
--- /dev/null
+++ b/python/astra/ASTRAProjector.py
@@ -0,0 +1,138 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+
+import math
+from . import creators as ac
+from . import data2d
+
+
+class ASTRAProjector2DTranspose():
+ """Implements the ``proj.T`` functionality.
+
+ Do not use directly, since it can be accessed as member ``.T`` of
+ an :class:`ASTRAProjector2D` object.
+
+ """
+ def __init__(self, parentProj):
+ self.parentProj = parentProj
+
+ def __mul__(self, data):
+ return self.parentProj.backProject(data)
+
+
+class ASTRAProjector2D(object):
+ """Helps with various common ASTRA Toolbox 2D operations.
+
+ This class can perform several often used toolbox operations, such as:
+
+ * Forward projecting
+ * Back projecting
+ * Reconstructing
+
+ Note that this class has a some computational overhead, because it
+ copies a lot of data. If you use many repeated operations, directly
+ using the PyAstraToolbox methods directly is faster.
+
+ You can use this class as an abstracted weight matrix :math:`W`: multiplying an instance
+ ``proj`` of this class by an image results in a forward projection of the image, and multiplying
+ ``proj.T`` by a sinogram results in a backprojection of the sinogram::
+
+ proj = ASTRAProjector2D(...)
+ fp = proj*image
+ bp = proj.T*sinogram
+
+ :param proj_geom: The projection geometry.
+ :type proj_geom: :class:`dict`
+ :param vol_geom: The volume geometry.
+ :type vol_geom: :class:`dict`
+ :param proj_type: Projector type, such as ``'line'``, ``'linear'``, ...
+ :type proj_type: :class:`string`
+ :param useCUDA: If ``True``, use CUDA for calculations, when possible.
+ :type useCUDA: :class:`bool`
+ """
+
+ def __init__(self, proj_geom, vol_geom, proj_type, useCUDA=False):
+ self.vol_geom = vol_geom
+ self.recSize = vol_geom['GridColCount']
+ self.angles = proj_geom['ProjectionAngles']
+ self.nDet = proj_geom['DetectorCount']
+ nexpow = int(pow(2, math.ceil(math.log(2 * self.nDet, 2))))
+ self.filterSize = nexpow / 2 + 1
+ self.nProj = self.angles.shape[0]
+ self.proj_geom = proj_geom
+ self.proj_id = ac.create_projector(proj_type, proj_geom, vol_geom)
+ self.useCUDA = useCUDA
+ self.T = ASTRAProjector2DTranspose(self)
+
+ def backProject(self, data):
+ """Backproject a sinogram.
+
+ :param data: The sinogram data or ID.
+ :type data: :class:`numpy.ndarray` or :class:`int`
+ :returns: :class:`numpy.ndarray` -- The backprojection.
+
+ """
+ vol_id, vol = ac.create_backprojection(
+ data, self.proj_id, useCUDA=self.useCUDA, returnData=True)
+ data2d.delete(vol_id)
+ return vol
+
+ def forwardProject(self, data):
+ """Forward project an image.
+
+ :param data: The image data or ID.
+ :type data: :class:`numpy.ndarray` or :class:`int`
+ :returns: :class:`numpy.ndarray` -- The forward projection.
+
+ """
+ sin_id, sino = ac.create_sino(data, self.proj_id, useCUDA=self.useCUDA, returnData=True)
+ data2d.delete(sin_id)
+ return sino
+
+ def reconstruct(self, data, method, **kwargs):
+ """Reconstruct an image from a sinogram.
+
+ :param data: The sinogram data or ID.
+ :type data: :class:`numpy.ndarray` or :class:`int`
+ :param method: Name of the reconstruction algorithm.
+ :type method: :class:`string`
+ :param kwargs: Additional named parameters to pass to :func:`astra.creators.create_reconstruction`.
+ :returns: :class:`numpy.ndarray` -- The reconstruction.
+
+ Example of a SIRT reconstruction using CUDA::
+
+ proj = ASTRAProjector2D(...)
+ rec = proj.reconstruct(sinogram,'SIRT_CUDA',iterations=1000)
+
+ """
+ kwargs['returnData'] = True
+ rec_id, rec = ac.create_reconstruction(
+ method, self.proj_id, data, **kwargs)
+ data2d.delete(rec_id)
+ return rec
+
+ def __mul__(self, data):
+ return self.forwardProject(data)
diff --git a/python/astra/PyAlgorithmFactory.pxd b/python/astra/PyAlgorithmFactory.pxd
new file mode 100644
index 0000000..256d7b2
--- /dev/null
+++ b/python/astra/PyAlgorithmFactory.pxd
@@ -0,0 +1,36 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from libcpp.string cimport string
+from libcpp cimport bool
+from .PyIncludes cimport *
+
+cdef extern from "astra/AstraObjectFactory.h" namespace "astra":
+ cdef cppclass CAlgorithmFactory:
+ CAlgorithmFactory()
+ CAlgorithm *create(string)
+
+cdef extern from "astra/AstraObjectFactory.h" namespace "astra::CAlgorithmFactory":
+ cdef CAlgorithmFactory* getSingletonPtr()
diff --git a/python/astra/PyAlgorithmManager.pxd b/python/astra/PyAlgorithmManager.pxd
new file mode 100644
index 0000000..a99a807
--- /dev/null
+++ b/python/astra/PyAlgorithmManager.pxd
@@ -0,0 +1,40 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from libcpp.string cimport string
+from libcpp cimport bool
+from .PyIncludes cimport *
+
+cdef extern from "astra/AstraObjectManager.h" namespace "astra":
+ cdef cppclass CAlgorithmManager:
+ int store(CAlgorithm *)
+ CAlgorithm * get(int)
+ void remove(int)
+ void clear()
+ string info()
+
+cdef extern from "astra/AstraObjectManager.h" namespace "astra::CAlgorithmManager":
+ cdef CAlgorithmManager* getSingletonPtr()
+
diff --git a/python/astra/PyData2DManager.pxd b/python/astra/PyData2DManager.pxd
new file mode 100644
index 0000000..db8ec84
--- /dev/null
+++ b/python/astra/PyData2DManager.pxd
@@ -0,0 +1,39 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from libcpp.string cimport string
+
+from .PyIncludes cimport *
+
+cdef extern from "astra/AstraObjectManager.h" namespace "astra":
+ cdef cppclass CData2DManager:
+ string info()
+ void clear()
+ void remove(int i)
+ int store(CFloat32Data2D *)
+ CFloat32Data2D * get(int i)
+
+cdef extern from "astra/AstraObjectManager.h" namespace "astra::CData2DManager":
+ cdef CData2DManager* getSingletonPtr()
diff --git a/python/astra/PyData3DManager.pxd b/python/astra/PyData3DManager.pxd
new file mode 100644
index 0000000..9264a82
--- /dev/null
+++ b/python/astra/PyData3DManager.pxd
@@ -0,0 +1,39 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from libcpp.string cimport string
+
+from .PyIncludes cimport *
+
+cdef extern from "astra/AstraObjectManager.h" namespace "astra":
+ cdef cppclass CData3DManager:
+ string info()
+ void clear()
+ void remove(int i)
+ int store(CFloat32Data3D *)
+ CFloat32Data3D * get(int i)
+
+cdef extern from "astra/AstraObjectManager.h" namespace "astra::CData3DManager":
+ cdef CData3DManager* getSingletonPtr()
diff --git a/python/astra/PyIncludes.pxd b/python/astra/PyIncludes.pxd
new file mode 100644
index 0000000..fc5980f
--- /dev/null
+++ b/python/astra/PyIncludes.pxd
@@ -0,0 +1,215 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from libcpp cimport bool
+from libcpp.string cimport string
+from .PyXMLDocument cimport XMLNode
+
+cdef extern from "astra/Globals.h" namespace "astra":
+ ctypedef float float32
+ ctypedef double float64
+ ctypedef unsigned short int uint16
+ ctypedef signed short int sint16
+ ctypedef unsigned char uchar8
+ ctypedef signed char schar8
+ ctypedef int int32
+ ctypedef short int int16
+
+cdef extern from "astra/Config.h" namespace "astra":
+ cdef cppclass Config:
+ Config()
+ XMLNode *self
+
+cdef extern from "astra/VolumeGeometry2D.h" namespace "astra":
+ cdef cppclass CVolumeGeometry2D:
+ bool initialize(Config)
+ int getGridColCount()
+ int getGridRowCount()
+ int getGridTotCount()
+ float32 getWindowLengthX()
+ float32 getWindowLengthY()
+ float32 getWindowArea()
+ float32 getPixelLengthX()
+ float32 getPixelLengthY()
+ float32 getPixelArea()
+ float32 getWindowMinX()
+ float32 getWindowMinY()
+ float32 getWindowMaxX()
+ float32 getWindowMaxY()
+
+
+cdef extern from "astra/Float32VolumeData2D.h" namespace "astra":
+ cdef cppclass CFloat32VolumeData2D:
+ CFloat32VolumeData2D(CVolumeGeometry2D*)
+ CVolumeGeometry2D * getGeometry()
+ int getWidth()
+ int getHeight()
+ void changeGeometry(CVolumeGeometry2D*)
+
+
+
+cdef extern from "astra/ProjectionGeometry2D.h" namespace "astra":
+ cdef cppclass CProjectionGeometry2D:
+ CProjectionGeometry2D()
+ bool initialize(Config)
+ int getDetectorCount()
+ int getProjectionAngleCount()
+ bool isOfType(string)
+ float32 getProjectionAngle(int)
+ float32 getDetectorWidth()
+
+cdef extern from "astra/Float32Data2D.h" namespace "astra::CFloat32Data2D":
+ cdef enum EDataType:
+ BASE,PROJECTION,VOLUME
+
+cdef extern from "astra/Float32Data2D.h" namespace "astra":
+ cdef cppclass CFloat32Data2D:
+ bool isInitialized()
+ int getSize()
+ float32 *getData()
+ float32 **getData2D()
+ int getWidth()
+ int getHeight()
+ EDataType getType()
+
+
+
+
+cdef extern from "astra/SparseMatrixProjectionGeometry2D.h" namespace "astra":
+ cdef cppclass CSparseMatrixProjectionGeometry2D:
+ CSparseMatrixProjectionGeometry2D()
+
+cdef extern from "astra/FanFlatProjectionGeometry2D.h" namespace "astra":
+ cdef cppclass CFanFlatProjectionGeometry2D:
+ CFanFlatProjectionGeometry2D()
+
+cdef extern from "astra/FanFlatVecProjectionGeometry2D.h" namespace "astra":
+ cdef cppclass CFanFlatVecProjectionGeometry2D:
+ CFanFlatVecProjectionGeometry2D()
+
+cdef extern from "astra/ParallelProjectionGeometry2D.h" namespace "astra":
+ cdef cppclass CParallelProjectionGeometry2D:
+ CParallelProjectionGeometry2D()
+
+
+cdef extern from "astra/Float32ProjectionData2D.h" namespace "astra":
+ cdef cppclass CFloat32ProjectionData2D:
+ CFloat32ProjectionData2D(CProjectionGeometry2D*)
+ CProjectionGeometry2D * getGeometry()
+ void changeGeometry(CProjectionGeometry2D*)
+ int getDetectorCount()
+ int getAngleCount()
+
+cdef extern from "astra/Algorithm.h" namespace "astra":
+ cdef cppclass CAlgorithm:
+ bool initialize(Config)
+ void run(int)
+ bool isInitialized()
+
+cdef extern from "astra/ReconstructionAlgorithm2D.h" namespace "astra":
+ cdef cppclass CReconstructionAlgorithm2D:
+ bool getResidualNorm(float32&)
+
+cdef extern from "astra/Projector2D.h" namespace "astra":
+ cdef cppclass CProjector2D:
+ bool isInitialized()
+ CProjectionGeometry2D* getProjectionGeometry()
+ CVolumeGeometry2D* getVolumeGeometry()
+ CSparseMatrix* getMatrix()
+
+cdef extern from "astra/SparseMatrix.h" namespace "astra":
+ cdef cppclass CSparseMatrix:
+ CSparseMatrix(unsigned int,unsigned int,unsigned long)
+ unsigned int m_iWidth
+ unsigned int m_iHeight
+ unsigned long m_lSize
+ bool isInitialized()
+ float32* m_pfValues
+ unsigned int* m_piColIndices
+ unsigned long* m_plRowStarts
+
+cdef extern from "astra/Float32Data3DMemory.h" namespace "astra":
+ cdef cppclass CFloat32Data3DMemory:
+ CFloat32Data3DMemory()
+ bool isInitialized()
+ int getSize()
+ int getWidth()
+ int getHeight()
+ int getDepth()
+ void updateStatistics()
+ float32 *getData()
+ float32 ***getData3D()
+
+
+cdef extern from "astra/VolumeGeometry3D.h" namespace "astra":
+ cdef cppclass CVolumeGeometry3D:
+ CVolumeGeometry3D()
+ bool initialize(Config)
+
+cdef extern from "astra/ProjectionGeometry3D.h" namespace "astra":
+ cdef cppclass CProjectionGeometry3D:
+ CProjectionGeometry3D()
+ bool initialize(Config)
+
+
+cdef extern from "astra/Float32VolumeData3DMemory.h" namespace "astra":
+ cdef cppclass CFloat32VolumeData3DMemory:
+ CFloat32VolumeData3DMemory(CVolumeGeometry3D*)
+
+
+cdef extern from "astra/ParallelProjectionGeometry3D.h" namespace "astra":
+ cdef cppclass CParallelProjectionGeometry3D:
+ CParallelProjectionGeometry3D()
+
+cdef extern from "astra/ParallelVecProjectionGeometry3D.h" namespace "astra":
+ cdef cppclass CParallelVecProjectionGeometry3D:
+ CParallelVecProjectionGeometry3D()
+
+cdef extern from "astra/ConeProjectionGeometry3D.h" namespace "astra":
+ cdef cppclass CConeProjectionGeometry3D:
+ CConeProjectionGeometry3D()
+ bool initialize(Config)
+
+cdef extern from "astra/ConeVecProjectionGeometry3D.h" namespace "astra":
+ cdef cppclass CConeVecProjectionGeometry3D:
+ CConeVecProjectionGeometry3D()
+
+cdef extern from "astra/Float32ProjectionData3DMemory.h" namespace "astra":
+ cdef cppclass CFloat32ProjectionData3DMemory:
+ CFloat32ProjectionData3DMemory(CProjectionGeometry3D*)
+ CFloat32ProjectionData3DMemory(CConeProjectionGeometry3D*)
+
+cdef extern from "astra/Float32Data3D.h" namespace "astra":
+ cdef cppclass CFloat32Data3D:
+ CFloat32Data3D()
+ bool isInitialized()
+ int getSize()
+ int getWidth()
+ int getHeight()
+ int getDepth()
+ void updateStatistics()
+
+
+
diff --git a/python/astra/PyMatrixManager.pxd b/python/astra/PyMatrixManager.pxd
new file mode 100644
index 0000000..b2b84c4
--- /dev/null
+++ b/python/astra/PyMatrixManager.pxd
@@ -0,0 +1,39 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from libcpp.string cimport string
+
+from .PyIncludes cimport *
+
+cdef extern from "astra/AstraObjectManager.h" namespace "astra":
+ cdef cppclass CMatrixManager:
+ string info()
+ void clear()
+ void remove(int i)
+ int store(CSparseMatrix *)
+ CSparseMatrix * get(int i)
+
+cdef extern from "astra/AstraObjectManager.h" namespace "astra::CMatrixManager":
+ cdef CMatrixManager* getSingletonPtr()
diff --git a/python/astra/PyProjector2DFactory.pxd b/python/astra/PyProjector2DFactory.pxd
new file mode 100644
index 0000000..3314544
--- /dev/null
+++ b/python/astra/PyProjector2DFactory.pxd
@@ -0,0 +1,35 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from libcpp.string cimport string
+from libcpp cimport bool
+from .PyIncludes cimport *
+
+cdef extern from "astra/AstraObjectFactory.h" namespace "astra":
+ cdef cppclass CProjector2DFactory:
+ CProjector2D *create(Config)
+
+cdef extern from "astra/AstraObjectFactory.h" namespace "astra::CProjector2DFactory":
+ cdef CProjector2DFactory* getSingletonPtr()
diff --git a/python/astra/PyProjector2DManager.pxd b/python/astra/PyProjector2DManager.pxd
new file mode 100644
index 0000000..92176ba
--- /dev/null
+++ b/python/astra/PyProjector2DManager.pxd
@@ -0,0 +1,39 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from libcpp.string cimport string
+
+from .PyIncludes cimport *
+
+cdef extern from "astra/AstraObjectManager.h" namespace "astra":
+ cdef cppclass CProjector2DManager:
+ string info()
+ void clear()
+ void remove(int i)
+ int store(CProjector2D *)
+ CProjector2D * get(int i)
+
+cdef extern from "astra/AstraObjectManager.h" namespace "astra::CProjector2DManager":
+ cdef CProjector2DManager* getSingletonPtr()
diff --git a/python/astra/PyXMLDocument.pxd b/python/astra/PyXMLDocument.pxd
new file mode 100644
index 0000000..69781f1
--- /dev/null
+++ b/python/astra/PyXMLDocument.pxd
@@ -0,0 +1,65 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+# distutils: language = c++
+# distutils: libraries = astra
+
+from libcpp.string cimport string
+from libcpp cimport bool
+from libcpp.list cimport list
+from libcpp.vector cimport vector
+
+cdef extern from "astra/Globals.h" namespace "astra":
+ ctypedef float float32
+ ctypedef double float64
+ ctypedef unsigned short int uint16
+ ctypedef signed short int sint16
+ ctypedef unsigned char uchar8
+ ctypedef signed char schar8
+ ctypedef int int32
+ ctypedef short int int16
+
+cdef extern from "astra/XMLNode.h" namespace "astra":
+ cdef cppclass XMLNode:
+ string getName()
+ XMLNode *addChildNode(string name)
+ XMLNode *addChildNode(string, string)
+ void addAttribute(string, string)
+ void addAttribute(string, float32)
+ void addOption(string, string)
+ bool hasOption(string)
+ string getAttribute(string)
+ list[XMLNode *] getNodes()
+ vector[float32] getContentNumericalArray()
+ string getContent()
+ bool hasAttribute(string)
+
+cdef extern from "astra/XMLDocument.h" namespace "astra":
+ cdef cppclass XMLDocument:
+ void saveToFile(string sFilename)
+ XMLNode *getRootNode()
+
+cdef extern from "astra/XMLDocument.h" namespace "astra::XMLDocument":
+ cdef XMLDocument *createDocument(string rootname)
diff --git a/python/astra/__init__.py b/python/astra/__init__.py
new file mode 100644
index 0000000..a61aafc
--- /dev/null
+++ b/python/astra/__init__.py
@@ -0,0 +1,42 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from . import matlab as m
+from .creators import astra_dict,create_vol_geom, create_proj_geom, create_backprojection, create_sino, create_reconstruction, create_projector,create_sino3d_gpu, create_backprojection3d_gpu
+from .functions import data_op, add_noise_to_sino, clear, move_vol_geom
+from .extrautils import clipCircle
+from .ASTRAProjector import ASTRAProjector2D
+from . import data2d
+from . import astra
+from . import data3d
+from . import algorithm
+from . import projector
+from . import matrix
+
+import os
+try:
+ astra.set_gpu_index(int(os.environ['ASTRA_GPU_INDEX']))
+except KeyError:
+ pass
diff --git a/python/astra/algorithm.py b/python/astra/algorithm.py
new file mode 100644
index 0000000..46cfccc
--- /dev/null
+++ b/python/astra/algorithm.py
@@ -0,0 +1,76 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+
+from . import algorithm_c as a
+
+def create(config):
+ """Create algorithm object.
+
+ :param config: Algorithm options.
+ :type config: :class:`dict`
+ :returns: :class:`int` -- the ID of the constructed object.
+
+ """
+ return a.create(config)
+
+def run(i, iterations=1):
+ """Run an algorithm.
+
+ :param i: ID of object.
+ :type i: :class:`int`
+ :param iterations: Number of iterations to run.
+ :type iterations: :class:`int`
+
+ """
+ return a.run(i,iterations)
+
+def get_res_norm(i):
+ """Get residual norm of algorithm.
+
+ :param i: ID of object.
+ :type i: :class:`int`
+ :returns: :class:`float` -- The residual norm.
+
+ """
+
+ return a.get_res_norm(i)
+
+def delete(ids):
+ """Delete a matrix object.
+
+ :param ids: ID or list of ID's to delete.
+ :type ids: :class:`int` or :class:`list`
+
+ """
+ return a.delete(ids)
+
+def clear():
+ """Clear all matrix objects."""
+ return a.clear()
+
+def info():
+ """Print info on matrix objects in memory."""
+ return a.info()
diff --git a/python/astra/algorithm_c.pyx b/python/astra/algorithm_c.pyx
new file mode 100644
index 0000000..0c2999c
--- /dev/null
+++ b/python/astra/algorithm_c.pyx
@@ -0,0 +1,106 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+
+# distutils: language = c++
+# distutils: libraries = astra
+
+import six
+from .PyIncludes cimport *
+
+cimport PyAlgorithmManager
+from .PyAlgorithmManager cimport CAlgorithmManager
+
+cimport PyAlgorithmFactory
+from .PyAlgorithmFactory cimport CAlgorithmFactory
+
+cimport PyXMLDocument
+from .PyXMLDocument cimport XMLDocument
+
+cimport utils
+from .utils import wrap_from_bytes
+
+cdef CAlgorithmManager * manAlg = <CAlgorithmManager * >PyAlgorithmManager.getSingletonPtr()
+
+cdef extern from *:
+ CReconstructionAlgorithm2D * dynamic_cast_recAlg "dynamic_cast<CReconstructionAlgorithm2D*>" (CAlgorithm * ) except NULL
+
+
+def create(config):
+ cdef XMLDocument * xml = utils.dict2XML(six.b('Algorithm'), config)
+ cdef Config cfg
+ cdef CAlgorithm * alg
+ cfg.self = xml.getRootNode()
+ alg = PyAlgorithmFactory.getSingletonPtr().create(cfg.self.getAttribute(six.b('type')))
+ if alg == NULL:
+ del xml
+ raise Exception("Unknown algorithm.")
+ if not alg.initialize(cfg):
+ del xml
+ del alg
+ raise Exception("Algorithm not initialized.")
+ del xml
+ return manAlg.store(alg)
+
+cdef CAlgorithm * getAlg(i) except NULL:
+ cdef CAlgorithm * alg = manAlg.get(i)
+ if alg == NULL:
+ raise Exception("Unknown algorithm.")
+ if not alg.isInitialized():
+ raise Exception("Algorithm not initialized.")
+ return alg
+
+
+def run(i, iterations=0):
+ cdef CAlgorithm * alg = getAlg(i)
+ alg.run(iterations)
+
+
+def get_res_norm(i):
+ cdef CReconstructionAlgorithm2D * pAlg2D
+ cdef CAlgorithm * alg = getAlg(i)
+ cdef float32 res = 0.0
+ pAlg2D = dynamic_cast_recAlg(alg)
+ if pAlg2D == NULL:
+ raise Exception("Operation not supported.")
+ if not pAlg2D.getResidualNorm(res):
+ raise Exception("Operation not supported.")
+ return res
+
+
+def delete(ids):
+ try:
+ for i in ids:
+ manAlg.remove(i)
+ except TypeError:
+ manAlg.remove(ids)
+
+
+def clear():
+ manAlg.clear()
+
+
+def info():
+ six.print_(wrap_from_bytes(manAlg.info()))
diff --git a/python/astra/astra.py b/python/astra/astra.py
new file mode 100644
index 0000000..26b1ff0
--- /dev/null
+++ b/python/astra/astra.py
@@ -0,0 +1,58 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+
+from . import astra_c as a
+
+def credits():
+ """Print credits of the ASTRA Toolbox."""
+ return a.credits()
+
+
+def use_cuda():
+ """Test if CUDA is enabled.
+
+ :returns: :class:`bool` -- ``True`` if CUDA is enabled.
+ """
+ return a.use_cuda()
+
+
+def version(printToScreen=False):
+ """Check version of the ASTRA Toolbox.
+
+ :param printToScreen: If ``True``, print version string. If ``False``, return version integer.
+ :type printToScreen: :class:`bool`
+ :returns: :class:`string` or :class:`int` -- The version string or integer.
+
+ """
+ return a.version(printToScreen)
+
+def set_gpu_index(idx):
+ """Set default GPU index to use.
+
+ :param idx: GPU index
+ :type idx: :class:`int`
+ """
+ a.set_gpu_index(idx)
diff --git a/python/astra/astra_c.pyx b/python/astra/astra_c.pyx
new file mode 100644
index 0000000..342a214
--- /dev/null
+++ b/python/astra/astra_c.pyx
@@ -0,0 +1,79 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+# distutils: language = c++
+# distutils: libraries = astra
+
+include "config.pxi"
+import six
+from .utils import wrap_from_bytes
+
+from libcpp.string cimport string
+from libcpp cimport bool
+cdef extern from "astra/Globals.h" namespace "astra":
+ int getVersion()
+ string getVersionString()
+ bool cudaEnabled()
+
+IF HAVE_CUDA==True:
+ cdef extern from "../cuda/2d/darthelper.h" namespace "astraCUDA":
+ bool setGPUIndex(int)
+ELSE:
+ def setGPUIndex():
+ pass
+
+def credits():
+ six.print_("""
+All Scale Tomographic Reconstruction Antwerp Toolbox (ASTRA-Toolbox)
+was developed at the University of Antwerp by
+ * Prof. dr. Joost Batenburg
+ * Andrei Dabravolski
+ * Gert Merckx
+ * Willem Jan Palenstijn
+ * Tom Roelandts
+ * Prof. dr. Jan Sijbers
+ * dr. Wim van Aarle
+ * Sander van der Maar
+ * dr. Gert Van Gompel
+
+Python interface written by
+ * Daniel M. Pelt (CWI, Amsterdam)""")
+
+
+def use_cuda():
+ return cudaEnabled()
+
+
+def version(printToScreen=False):
+ if printToScreen:
+ six.print_(wrap_from_bytes(getVersionString()))
+ else:
+ return getVersion()
+
+def set_gpu_index(idx):
+ if use_cuda()==True:
+ ret = setGPUIndex(idx)
+ if not ret:
+ six.print_("Failed to set GPU " + str(idx))
diff --git a/python/astra/creators.py b/python/astra/creators.py
new file mode 100644
index 0000000..9aba464
--- /dev/null
+++ b/python/astra/creators.py
@@ -0,0 +1,563 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+
+import six
+import numpy as np
+import math
+from . import data2d
+from . import data3d
+from . import projector
+from . import algorithm
+
+def astra_dict(intype):
+ """Creates a dict to use with the ASTRA Toolbox.
+
+ :param intype: Type of the ASTRA object.
+ :type intype: :class:`string`
+ :returns: :class:`dict` -- An ASTRA dict of type ``intype``.
+
+ """
+ if intype == 'SIRT_CUDA2':
+ intype = 'SIRT_CUDA'
+ six.print_('SIRT_CUDA2 has been deprecated. Use SIRT_CUDA instead.')
+ elif intype == 'FP_CUDA2':
+ intype = 'FP_CUDA'
+ six.print_('FP_CUDA2 has been deprecated. Use FP_CUDA instead.')
+ return {'type': intype}
+
+def create_vol_geom(*varargin):
+ """Create a volume geometry structure.
+
+This method can be called in a number of ways:
+
+``create_vol_geom(N)``:
+ :returns: A 2D volume geometry of size :math:`N \\times N`.
+
+``create_vol_geom((M, N))``:
+ :returns: A 2D volume geometry of size :math:`M \\times N`.
+
+``create_vol_geom(M, N)``:
+ :returns: A 2D volume geometry of size :math:`M \\times N`.
+
+``create_vol_geom(M, N, minx, maxx, miny, maxy)``:
+ :returns: A 2D volume geometry of size :math:`M \\times N`, windowed as :math:`minx \\leq x \\leq maxx` and :math:`miny \\leq y \\leq maxy`.
+
+``create_vol_geom((M, N, Z))``:
+ :returns: A 3D volume geometry of size :math:`M \\times N \\times Z`.
+
+``create_vol_geom(M, N, Z)``:
+ :returns: A 3D volume geometry of size :math:`M \\times N \\times Z`.
+
+"""
+ vol_geom = {'option': {}}
+ # astra_create_vol_geom(row_count)
+ if len(varargin) == 1 and isinstance(varargin[0], int) == 1:
+ vol_geom['GridRowCount'] = varargin[0]
+ vol_geom['GridColCount'] = varargin[0]
+ vol_geom['option']['WindowMinX'] = -varargin[0] / 2.
+ vol_geom['option']['WindowMaxX'] = varargin[0] / 2.
+ vol_geom['option']['WindowMinY'] = -varargin[0] / 2.
+ vol_geom['option']['WindowMaxY'] = varargin[0] / 2.
+ # astra_create_vol_geom([row_count col_count])
+ elif len(varargin) == 1 and len(varargin[0]) == 2:
+ vol_geom['GridRowCount'] = varargin[0][0]
+ vol_geom['GridColCount'] = varargin[0][1]
+ vol_geom['option']['WindowMinX'] = -varargin[0][1] / 2.
+ vol_geom['option']['WindowMaxX'] = varargin[0][1] / 2.
+ vol_geom['option']['WindowMinY'] = -varargin[0][0] / 2.
+ vol_geom['option']['WindowMaxY'] = varargin[0][0] / 2.
+ # astra_create_vol_geom([row_count col_count slice_count])
+ elif len(varargin) == 1 and len(varargin[0]) == 3:
+ vol_geom['GridRowCount'] = varargin[0][0]
+ vol_geom['GridColCount'] = varargin[0][1]
+ vol_geom['GridSliceCount'] = varargin[0][2]
+ vol_geom['option']['WindowMinX'] = -varargin[0][1] / 2.
+ vol_geom['option']['WindowMaxX'] = varargin[0][1] / 2.
+ vol_geom['option']['WindowMinY'] = -varargin[0][0] / 2.
+ vol_geom['option']['WindowMaxY'] = varargin[0][0] / 2.
+ vol_geom['option']['WindowMinZ'] = -varargin[0][2] / 2.
+ vol_geom['option']['WindowMaxZ'] = varargin[0][2] / 2.
+ # astra_create_vol_geom(row_count, col_count)
+ elif len(varargin) == 2:
+ vol_geom['GridRowCount'] = varargin[0]
+ vol_geom['GridColCount'] = varargin[1]
+ vol_geom['option']['WindowMinX'] = -varargin[1] / 2.
+ vol_geom['option']['WindowMaxX'] = varargin[1] / 2.
+ vol_geom['option']['WindowMinY'] = -varargin[0] / 2.
+ vol_geom['option']['WindowMaxY'] = varargin[0] / 2.
+ # astra_create_vol_geom(row_count, col_count, min_x, max_x, min_y, max_y)
+ elif len(varargin) == 6:
+ vol_geom['GridRowCount'] = varargin[0]
+ vol_geom['GridColCount'] = varargin[1]
+ vol_geom['option']['WindowMinX'] = varargin[2]
+ vol_geom['option']['WindowMaxX'] = varargin[3]
+ vol_geom['option']['WindowMinY'] = varargin[4]
+ vol_geom['option']['WindowMaxY'] = varargin[5]
+ # astra_create_vol_geom(row_count, col_count, slice_count)
+ elif len(varargin) == 3:
+ vol_geom['GridRowCount'] = varargin[0]
+ vol_geom['GridColCount'] = varargin[1]
+ vol_geom['GridSliceCount'] = varargin[2]
+ return vol_geom
+
+
+def create_proj_geom(intype, *args):
+ """Create a projection geometry.
+
+This method can be called in a number of ways:
+
+``create_proj_geom('parallel', detector_spacing, det_count, angles)``:
+
+:param detector_spacing: Distance between two adjacent detector pixels.
+:type detector_spacing: :class:`float`
+:param det_count: Number of detector pixels.
+:type det_count: :class:`int`
+:param angles: Array of angles in radians.
+:type angles: :class:`numpy.ndarray`
+:returns: A parallel projection geometry.
+
+
+``create_proj_geom('fanflat', det_width, det_count, angles, source_origin, source_det)``:
+
+:param det_width: Size of a detector pixel.
+:type det_width: :class:`float`
+:param det_count: Number of detector pixels.
+:type det_count: :class:`int`
+:param angles: Array of angles in radians.
+:type angles: :class:`numpy.ndarray`
+:param source_origin: Position of the source.
+:param source_det: Position of the detector
+:returns: A fan-beam projection geometry.
+
+``create_proj_geom('fanflat_vec', det_count, V)``:
+
+:param det_count: Number of detector pixels.
+:type det_count: :class:`int`
+:param V: Vector array.
+:type V: :class:`numpy.ndarray`
+:returns: A fan-beam projection geometry.
+
+``create_proj_geom('parallel3d', detector_spacing_x, detector_spacing_y, det_row_count, det_col_count, angles)``:
+
+:param detector_spacing_*: Distance between two adjacent detector pixels.
+:type detector_spacing_*: :class:`float`
+:param det_row_count: Number of detector pixel rows.
+:type det_row_count: :class:`int`
+:param det_col_count: Number of detector pixel columns.
+:type det_col_count: :class:`int`
+:param angles: Array of angles in radians.
+:type angles: :class:`numpy.ndarray`
+:returns: A parallel projection geometry.
+
+``create_proj_geom('cone', detector_spacing_x, detector_spacing_y, det_row_count, det_col_count, angles, source_origin, source_det)``:
+
+:param detector_spacing_*: Distance between two adjacent detector pixels.
+:type detector_spacing_*: :class:`float`
+:param det_row_count: Number of detector pixel rows.
+:type det_row_count: :class:`int`
+:param det_col_count: Number of detector pixel columns.
+:type det_col_count: :class:`int`
+:param angles: Array of angles in radians.
+:type angles: :class:`numpy.ndarray`
+:param source_origin: Distance between point source and origin.
+:type source_origin: :class:`float`
+:param source_det: Distance between the detector and origin.
+:type source_det: :class:`float`
+:returns: A cone-beam projection geometry.
+
+``create_proj_geom('cone_vec', det_row_count, det_col_count, V)``:
+
+:param det_row_count: Number of detector pixel rows.
+:type det_row_count: :class:`int`
+:param det_col_count: Number of detector pixel columns.
+:type det_col_count: :class:`int`
+:param V: Vector array.
+:type V: :class:`numpy.ndarray`
+:returns: A cone-beam projection geometry.
+
+``create_proj_geom('parallel3d_vec', det_row_count, det_col_count, V)``:
+
+:param det_row_count: Number of detector pixel rows.
+:type det_row_count: :class:`int`
+:param det_col_count: Number of detector pixel columns.
+:type det_col_count: :class:`int`
+:param V: Vector array.
+:type V: :class:`numpy.ndarray`
+:returns: A parallel projection geometry.
+
+``create_proj_geom('sparse_matrix', det_width, det_count, angles, matrix_id)``:
+
+:param det_width: Size of a detector pixel.
+:type det_width: :class:`float`
+:param det_count: Number of detector pixels.
+:type det_count: :class:`int`
+:param angles: Array of angles in radians.
+:type angles: :class:`numpy.ndarray`
+:param matrix_id: ID of the sparse matrix.
+:type matrix_id: :class:`int`
+:returns: A projection geometry based on a sparse matrix.
+
+"""
+ if intype == 'parallel':
+ if len(args) < 3:
+ raise Exception(
+ 'not enough variables: astra_create_proj_geom(parallel, detector_spacing, det_count, angles)')
+ return {'type': 'parallel', 'DetectorWidth': args[0], 'DetectorCount': args[1], 'ProjectionAngles': args[2]}
+ elif intype == 'fanflat':
+ if len(args) < 5:
+ raise Exception('not enough variables: astra_create_proj_geom(fanflat, det_width, det_count, angles, source_origin, source_det)')
+ return {'type': 'fanflat', 'DetectorWidth': args[0], 'DetectorCount': args[1], 'ProjectionAngles': args[2], 'DistanceOriginSource': args[3], 'DistanceOriginDetector': args[4]}
+ elif intype == 'fanflat_vec':
+ if len(args) < 2:
+ raise Exception('not enough variables: astra_create_proj_geom(fanflat_vec, det_count, V)')
+ if not args[1].shape[1] == 6:
+ raise Exception('V should be a Nx6 matrix, with N the number of projections')
+ return {'type':'fanflat_vec', 'DetectorCount':args[0], 'Vectors':args[1]}
+ elif intype == 'parallel3d':
+ if len(args) < 5:
+ raise Exception('not enough variables: astra_create_proj_geom(parallel3d, detector_spacing_x, detector_spacing_y, det_row_count, det_col_count, angles)')
+ return {'type':'parallel3d', 'DetectorSpacingX':args[0], 'DetectorSpacingY':args[1], 'DetectorRowCount':args[2], 'DetectorColCount':args[3],'ProjectionAngles':args[4]}
+ elif intype == 'cone':
+ if len(args) < 7:
+ raise Exception('not enough variables: astra_create_proj_geom(cone, detector_spacing_x, detector_spacing_y, det_row_count, det_col_count, angles, source_origin, source_det)')
+ return {'type': 'cone','DetectorSpacingX':args[0], 'DetectorSpacingY':args[1], 'DetectorRowCount':args[2],'DetectorColCount':args[3],'ProjectionAngles':args[4],'DistanceOriginSource': args[5],'DistanceOriginDetector':args[6]}
+ elif intype == 'cone_vec':
+ if len(args) < 3:
+ raise Exception('not enough variables: astra_create_proj_geom(cone_vec, det_row_count, det_col_count, V)')
+ if not args[2].shape[1] == 12:
+ raise Exception('V should be a Nx12 matrix, with N the number of projections')
+ return {'type': 'cone_vec','DetectorRowCount':args[0],'DetectorColCount':args[1],'Vectors':args[2]}
+ elif intype == 'parallel3d_vec':
+ if len(args) < 3:
+ raise Exception('not enough variables: astra_create_proj_geom(parallel3d_vec, det_row_count, det_col_count, V)')
+ if not args[2].shape[1] == 12:
+ raise Exception('V should be a Nx12 matrix, with N the number of projections')
+ return {'type': 'parallel3d_vec','DetectorRowCount':args[0],'DetectorColCount':args[1],'Vectors':args[2]}
+ elif intype == 'sparse_matrix':
+ if len(args) < 4:
+ raise Exception(
+ 'not enough variables: astra_create_proj_geom(sparse_matrix, det_width, det_count, angles, matrix_id)')
+ return {'type': 'sparse_matrix', 'DetectorWidth': args[0], 'DetectorCount': args[1], 'ProjectionAngles': args[2], 'MatrixID': args[3]}
+ else:
+ raise Exception('Error: unknown type ' + intype)
+
+
+def create_backprojection(data, proj_id, useCUDA=False, returnData=True):
+ """Create a backprojection of a sinogram (2D).
+
+:param data: Sinogram data or ID.
+:type data: :class:`numpy.ndarray` or :class:`int`
+:param proj_id: ID of the projector to use.
+:type proj_id: :class:`int`
+:param useCUDA: If ``True``, use CUDA for the calculation.
+:type useCUDA: :class:`bool`
+:param returnData: If False, only return the ID of the backprojection.
+:type returnData: :class:`bool`
+:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the backprojection. Otherwise, returns a tuple containing the ID of the backprojection and the backprojection itself, in that order.
+
+"""
+ proj_geom = projector.projection_geometry(proj_id)
+ vol_geom = projector.volume_geometry(proj_id)
+ if isinstance(data, np.ndarray):
+ sino_id = data2d.create('-sino', proj_geom, data)
+ else:
+ sino_id = data
+ vol_id = data2d.create('-vol', vol_geom, 0)
+
+ algString = 'BP'
+ if useCUDA:
+ algString = algString + '_CUDA'
+
+ cfg = astra_dict(algString)
+ if not useCUDA:
+ cfg['ProjectorId'] = proj_id
+ cfg['ProjectionDataId'] = sino_id
+ cfg['ReconstructionDataId'] = vol_id
+ alg_id = algorithm.create(cfg)
+ algorithm.run(alg_id)
+ algorithm.delete(alg_id)
+
+ if isinstance(data, np.ndarray):
+ data2d.delete(sino_id)
+
+ if returnData:
+ return vol_id, data2d.get(vol_id)
+ else:
+ return vol_id
+
+def create_backprojection3d_gpu(data, proj_geom, vol_geom, returnData=True):
+ """Create a backprojection of a sinogram (3D) using CUDA.
+
+:param data: Sinogram data or ID.
+:type data: :class:`numpy.ndarray` or :class:`int`
+:param proj_geom: Projection geometry.
+:type proj_geom: :class:`dict`
+:param vol_geom: Volume geometry.
+:type vol_geom: :class:`dict`
+:param returnData: If False, only return the ID of the backprojection.
+:type returnData: :class:`bool`
+:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the backprojection. Otherwise, returns a tuple containing the ID of the backprojection and the backprojection itself, in that order.
+
+"""
+ if isinstance(data, np.ndarray):
+ sino_id = data3d.create('-sino', proj_geom, data)
+ else:
+ sino_id = data
+
+ vol_id = data3d.create('-vol', vol_geom, 0)
+
+ cfg = astra_dict('BP3D_CUDA')
+ cfg['ProjectionDataId'] = sino_id
+ cfg['ReconstructionDataId'] = vol_id
+ alg_id = algorithm.create(cfg)
+ algorithm.run(alg_id)
+ algorithm.delete(alg_id)
+
+ if isinstance(data, np.ndarray):
+ data3d.delete(sino_id)
+
+ if returnData:
+ return vol_id, data3d.get(vol_id)
+ else:
+ return vol_id
+
+
+def create_sino(data, proj_id=None, proj_geom=None, vol_geom=None,
+ useCUDA=False, returnData=True, gpuIndex=None):
+ """Create a forward projection of an image (2D).
+
+ :param data: Image data or ID.
+ :type data: :class:`numpy.ndarray` or :class:`int`
+ :param proj_id: ID of the projector to use.
+ :type proj_id: :class:`int`
+ :param proj_geom: Projection geometry.
+ :type proj_geom: :class:`dict`
+ :param vol_geom: Volume geometry.
+ :type vol_geom: :class:`dict`
+ :param useCUDA: If ``True``, use CUDA for the calculation.
+ :type useCUDA: :class:`bool`
+ :param returnData: If False, only return the ID of the forward projection.
+ :type returnData: :class:`bool`
+ :param gpuIndex: Optional GPU index.
+ :type gpuIndex: :class:`int`
+ :returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`)
+
+ If ``returnData=False``, returns the ID of the forward
+ projection. Otherwise, returns a tuple containing the ID of the
+ forward projection and the forward projection itself, in that
+ order.
+
+ The geometry of setup is defined by ``proj_id`` or with
+ ``proj_geom`` and ``vol_geom``. If ``proj_id`` is given, then
+ ``proj_geom`` and ``vol_geom`` must be None and vice versa.
+"""
+ if proj_id is not None:
+ proj_geom = projector.projection_geometry(proj_id)
+ vol_geom = projector.volume_geometry(proj_id)
+ elif proj_geom is not None and vol_geom is not None:
+ if not useCUDA:
+ # We need more parameters to create projector.
+ raise ValueError(
+ """A ``proj_id`` is needed when CUDA is not used.""")
+ else:
+ raise Exception("""The geometry setup is not defined.
+ The geometry of setup is defined by ``proj_id`` or with
+ ``proj_geom`` and ``vol_geom``. If ``proj_id`` is given, then
+ ``proj_geom`` and ``vol_geom`` must be None and vice versa.""")
+
+ if isinstance(data, np.ndarray):
+ volume_id = data2d.create('-vol', vol_geom, data)
+ else:
+ volume_id = data
+ sino_id = data2d.create('-sino', proj_geom, 0)
+ algString = 'FP'
+ if useCUDA:
+ algString = algString + '_CUDA'
+ cfg = astra_dict(algString)
+ if not useCUDA:
+ cfg['ProjectorId'] = proj_id
+ if gpuIndex is not None:
+ cfg['option'] = {'GPUindex': gpuIndex}
+ cfg['ProjectionDataId'] = sino_id
+ cfg['VolumeDataId'] = volume_id
+ alg_id = algorithm.create(cfg)
+ algorithm.run(alg_id)
+ algorithm.delete(alg_id)
+
+ if isinstance(data, np.ndarray):
+ data2d.delete(volume_id)
+ if returnData:
+ return sino_id, data2d.get(sino_id)
+ else:
+ return sino_id
+
+
+
+def create_sino3d_gpu(data, proj_geom, vol_geom, returnData=True, gpuIndex=None):
+ """Create a forward projection of an image (3D).
+
+:param data: Image data or ID.
+:type data: :class:`numpy.ndarray` or :class:`int`
+:param proj_geom: Projection geometry.
+:type proj_geom: :class:`dict`
+:param vol_geom: Volume geometry.
+:type vol_geom: :class:`dict`
+:param returnData: If False, only return the ID of the forward projection.
+:type returnData: :class:`bool`
+:param gpuIndex: Optional GPU index.
+:type gpuIndex: :class:`int`
+:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the forward projection. Otherwise, returns a tuple containing the ID of the forward projection and the forward projection itself, in that order.
+
+"""
+
+ if isinstance(data, np.ndarray):
+ volume_id = data3d.create('-vol', vol_geom, data)
+ else:
+ volume_id = data
+ sino_id = data3d.create('-sino', proj_geom, 0)
+ algString = 'FP3D_CUDA'
+ cfg = astra_dict(algString)
+ if not gpuIndex==None:
+ cfg['option']={'GPUindex':gpuIndex}
+ cfg['ProjectionDataId'] = sino_id
+ cfg['VolumeDataId'] = volume_id
+ alg_id = algorithm.create(cfg)
+ algorithm.run(alg_id)
+ algorithm.delete(alg_id)
+
+ if isinstance(data, np.ndarray):
+ data3d.delete(volume_id)
+ if returnData:
+ return sino_id, data3d.get(sino_id)
+ else:
+ return sino_id
+
+
+def create_reconstruction(rec_type, proj_id, sinogram, iterations=1, use_mask='no', mask=np.array([]), use_minc='no', minc=0, use_maxc='no', maxc=255, returnData=True, filterType=None, filterData=None):
+ """Create a reconstruction of a sinogram (2D).
+
+:param rec_type: Name of the reconstruction algorithm.
+:type rec_type: :class:`string`
+:param proj_id: ID of the projector to use.
+:type proj_id: :class:`int`
+:param sinogram: Sinogram data or ID.
+:type sinogram: :class:`numpy.ndarray` or :class:`int`
+:param iterations: Number of iterations to run.
+:type iterations: :class:`int`
+:param use_mask: Whether to use a mask.
+:type use_mask: ``'yes'`` or ``'no'``
+:param mask: Mask data or ID
+:type mask: :class:`numpy.ndarray` or :class:`int`
+:param use_minc: Whether to force a minimum value on the reconstruction pixels.
+:type use_minc: ``'yes'`` or ``'no'``
+:param minc: Minimum value to use.
+:type minc: :class:`float`
+:param use_maxc: Whether to force a maximum value on the reconstruction pixels.
+:type use_maxc: ``'yes'`` or ``'no'``
+:param maxc: Maximum value to use.
+:type maxc: :class:`float`
+:param returnData: If False, only return the ID of the reconstruction.
+:type returnData: :class:`bool`
+:param filterType: Which type of filter to use for filter-based methods.
+:type filterType: :class:`string`
+:param filterData: Optional filter data for filter-based methods.
+:type filterData: :class:`numpy.ndarray`
+:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the reconstruction. Otherwise, returns a tuple containing the ID of the reconstruction and reconstruction itself, in that order.
+
+"""
+ proj_geom = projector.projection_geometry(proj_id)
+ if isinstance(sinogram, np.ndarray):
+ sino_id = data2d.create('-sino', proj_geom, sinogram)
+ else:
+ sino_id = sinogram
+ vol_geom = projector.volume_geometry(proj_id)
+ recon_id = data2d.create('-vol', vol_geom, 0)
+ cfg = astra_dict(rec_type)
+ if not 'CUDA' in rec_type:
+ cfg['ProjectorId'] = proj_id
+ cfg['ProjectionDataId'] = sino_id
+ cfg['ReconstructionDataId'] = recon_id
+ cfg['options'] = {}
+ if use_mask == 'yes':
+ if isinstance(mask, np.ndarray):
+ mask_id = data2d.create('-vol', vol_geom, mask)
+ else:
+ mask_id = mask
+ cfg['options']['ReconstructionMaskId'] = mask_id
+ if not filterType == None:
+ cfg['FilterType'] = filterType
+ if not filterData == None:
+ if isinstance(filterData, np.ndarray):
+ nexpow = int(
+ pow(2, math.ceil(math.log(2 * proj_geom['DetectorCount'], 2))))
+ filtSize = nexpow / 2 + 1
+ filt_proj_geom = create_proj_geom(
+ 'parallel', 1.0, filtSize, proj_geom['ProjectionAngles'])
+ filt_id = data2d.create('-sino', filt_proj_geom, filterData)
+ else:
+ filt_id = filterData
+ cfg['FilterSinogramId'] = filt_id
+ cfg['options']['UseMinConstraint'] = use_minc
+ cfg['options']['MinConstraintValue'] = minc
+ cfg['options']['UseMaxConstraint'] = use_maxc
+ cfg['options']['MaxConstraintValue'] = maxc
+ cfg['options']['ProjectionOrder'] = 'random'
+ alg_id = algorithm.create(cfg)
+ algorithm.run(alg_id, iterations)
+
+ algorithm.delete(alg_id)
+
+ if isinstance(sinogram, np.ndarray):
+ data2d.delete(sino_id)
+ if use_mask == 'yes' and isinstance(mask, np.ndarray):
+ data2d.delete(mask_id)
+ if not filterData == None:
+ if isinstance(filterData, np.ndarray):
+ data2d.delete(filt_id)
+ if returnData:
+ return recon_id, data2d.get(recon_id)
+ else:
+ return recon_id
+
+
+def create_projector(proj_type, proj_geom, vol_geom):
+ """Create a 2D projector.
+
+:param proj_type: Projector type, such as ``'line'``, ``'linear'``, ...
+:type proj_type: :class:`string`
+:param proj_geom: Projection geometry.
+:type proj_geom: :class:`dict`
+:param vol_geom: Volume geometry.
+:type vol_geom: :class:`dict`
+:returns: :class:`int` -- The ID of the projector.
+
+"""
+ if proj_type == 'blob':
+ raise Exception('Blob type not yet implemented')
+ cfg = astra_dict(proj_type)
+ cfg['ProjectionGeometry'] = proj_geom
+ cfg['VolumeGeometry'] = vol_geom
+ return projector.create(cfg)
diff --git a/python/astra/data2d.py b/python/astra/data2d.py
new file mode 100644
index 0000000..8c4be03
--- /dev/null
+++ b/python/astra/data2d.py
@@ -0,0 +1,120 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from . import data2d_c as d
+
+def clear():
+ """Clear all 2D data objects."""
+ return d.clear()
+
+def delete(ids):
+ """Delete a 2D object.
+
+ :param ids: ID or list of ID's to delete.
+ :type ids: :class:`int` or :class:`list`
+
+ """
+ return d.delete(ids)
+
+def create(datatype, geometry, data=None):
+ """Create a 2D object.
+
+ :param datatype: Data object type, '-vol' or '-sino'.
+ :type datatype: :class:`string`
+ :param geometry: Volume or projection geometry.
+ :type geometry: :class:`dict`
+ :param data: Data to fill the constructed object with, either a scalar or array.
+ :type data: :class:`float` or :class:`numpy.ndarray`
+ :returns: :class:`int` -- the ID of the constructed object.
+
+ """
+ return d.create(datatype,geometry,data)
+
+def store(i, data):
+ """Fill existing 2D object with data.
+
+ :param i: ID of object to fill.
+ :type i: :class:`int`
+ :param data: Data to fill the object with, either a scalar or array.
+ :type data: :class:`float` or :class:`numpy.ndarray`
+
+ """
+ return d.store(i, data)
+
+def get_geometry(i):
+ """Get the geometry of a 2D object.
+
+ :param i: ID of object.
+ :type i: :class:`int`
+ :returns: :class:`dict` -- The geometry of object with ID ``i``.
+
+ """
+ return d.get_geometry(i)
+
+def change_geometry(i, geom):
+ """Change the geometry of a 2D object.
+
+ :param i: ID of object.
+ :type i: :class:`int`
+ :param geom: new geometry.
+ :type geom: :class:`dict`
+
+ """
+ return d.change_geometry(i, geom)
+
+def get(i):
+ """Get a 2D object.
+
+ :param i: ID of object to get.
+ :type i: :class:`int`
+ :returns: :class:`numpy.ndarray` -- The object data.
+
+ """
+ return d.get(i)
+
+def get_shared(i):
+ """Get a 2D object with memory shared between the ASTRA toolbox and numpy array.
+
+ :param i: ID of object to get.
+ :type i: :class:`int`
+ :returns: :class:`numpy.ndarray` -- The object data.
+
+ """
+ return d.get_shared(i)
+
+
+def get_single(i):
+ """Get a 2D object in single precision.
+
+ :param i: ID of object to get.
+ :type i: :class:`int`
+ :returns: :class:`numpy.ndarray` -- The object data.
+
+ """
+ return d.get_single(i)
+
+def info():
+ """Print info on 2D objects in memory."""
+ return d.info()
diff --git a/python/astra/data2d_c.pyx b/python/astra/data2d_c.pyx
new file mode 100644
index 0000000..ec1b478
--- /dev/null
+++ b/python/astra/data2d_c.pyx
@@ -0,0 +1,241 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+# distutils: language = c++
+# distutils: libraries = astra
+
+import six
+
+cimport cython
+from cython cimport view
+
+cimport PyData2DManager
+from .PyData2DManager cimport CData2DManager
+
+cimport PyXMLDocument
+from .PyXMLDocument cimport XMLDocument
+
+import numpy as np
+
+cimport numpy as np
+np.import_array()
+
+
+from .PyIncludes cimport *
+cimport utils
+from .utils import wrap_from_bytes
+
+
+cdef CData2DManager * man2d = <CData2DManager * >PyData2DManager.getSingletonPtr()
+
+
+def clear():
+ man2d.clear()
+
+
+def delete(ids):
+ try:
+ for i in ids:
+ man2d.remove(i)
+ except TypeError:
+ man2d.remove(ids)
+
+
+def create(datatype, geometry, data=None):
+ cdef XMLDocument * xml
+ cdef Config cfg
+ cdef CVolumeGeometry2D * pGeometry
+ cdef CProjectionGeometry2D * ppGeometry
+ cdef CFloat32Data2D * pDataObject2D
+ if datatype == '-vol':
+ xml = utils.dict2XML(six.b('VolumeGeometry'), geometry)
+ cfg.self = xml.getRootNode()
+ pGeometry = new CVolumeGeometry2D()
+ if not pGeometry.initialize(cfg):
+ del xml
+ del pGeometry
+ raise Exception('Geometry class not initialized.')
+ pDataObject2D = <CFloat32Data2D * > new CFloat32VolumeData2D(pGeometry)
+ del xml
+ del pGeometry
+ elif datatype == '-sino':
+ xml = utils.dict2XML(six.b('ProjectionGeometry'), geometry)
+ cfg.self = xml.getRootNode()
+ tpe = wrap_from_bytes(cfg.self.getAttribute(six.b('type')))
+ if (tpe == 'sparse_matrix'):
+ ppGeometry = <CProjectionGeometry2D * >new CSparseMatrixProjectionGeometry2D()
+ elif (tpe == 'fanflat'):
+ ppGeometry = <CProjectionGeometry2D * >new CFanFlatProjectionGeometry2D()
+ elif (tpe == 'fanflat_vec'):
+ ppGeometry = <CProjectionGeometry2D * >new CFanFlatVecProjectionGeometry2D()
+ else:
+ ppGeometry = <CProjectionGeometry2D * >new CParallelProjectionGeometry2D()
+ if not ppGeometry.initialize(cfg):
+ del xml
+ del ppGeometry
+ raise Exception('Geometry class not initialized.')
+ pDataObject2D = <CFloat32Data2D * > new CFloat32ProjectionData2D(ppGeometry)
+ del ppGeometry
+ del xml
+ else:
+ raise Exception("Invalid datatype. Please specify '-vol' or '-sino'.")
+
+ if not pDataObject2D.isInitialized():
+ del pDataObject2D
+ raise Exception("Couldn't initialize data object.")
+
+ fillDataObject(pDataObject2D, data)
+
+ return man2d.store(pDataObject2D)
+
+cdef fillDataObject(CFloat32Data2D * obj, data):
+ if data is None:
+ fillDataObjectScalar(obj, 0)
+ else:
+ if isinstance(data, np.ndarray):
+ fillDataObjectArray(obj, np.ascontiguousarray(data,dtype=np.float32))
+ else:
+ fillDataObjectScalar(obj, np.float32(data))
+
+cdef fillDataObjectScalar(CFloat32Data2D * obj, float s):
+ cdef int i
+ for i in range(obj.getSize()):
+ obj.getData()[i] = s
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+cdef fillDataObjectArray(CFloat32Data2D * obj, float [:,::1] data):
+ if (not data.shape[0] == obj.getHeight()) or (not data.shape[1] == obj.getWidth()):
+ raise Exception(
+ "The dimensions of the data do not match those specified in the geometry.")
+ cdef float [:,::1] cView = <float[:data.shape[0],:data.shape[1]]> obj.getData2D()[0]
+ cView[:] = data
+
+cdef CFloat32Data2D * getObject(i) except NULL:
+ cdef CFloat32Data2D * pDataObject = man2d.get(i)
+ if pDataObject == NULL:
+ raise Exception("Data object not found")
+ if not pDataObject.isInitialized():
+ raise Exception("Data object not initialized properly.")
+ return pDataObject
+
+
+def store(i, data):
+ cdef CFloat32Data2D * pDataObject = getObject(i)
+ fillDataObject(pDataObject, data)
+
+
+def get_geometry(i):
+ cdef CFloat32Data2D * pDataObject = getObject(i)
+ cdef CFloat32ProjectionData2D * pDataObject2
+ cdef CFloat32VolumeData2D * pDataObject3
+ if pDataObject.getType() == PROJECTION:
+ pDataObject2 = <CFloat32ProjectionData2D * >pDataObject
+ geom = utils.createProjectionGeometryStruct(pDataObject2.getGeometry())
+ elif pDataObject.getType() == VOLUME:
+ pDataObject3 = <CFloat32VolumeData2D * >pDataObject
+ geom = utils.createVolumeGeometryStruct(pDataObject3.getGeometry())
+ else:
+ raise Exception("Not a known data object")
+ return geom
+
+
+def change_geometry(i, geom):
+ cdef XMLDocument * xml
+ cdef Config cfg
+ cdef CVolumeGeometry2D * pGeometry
+ cdef CProjectionGeometry2D * ppGeometry
+ cdef CFloat32Data2D * pDataObject = getObject(i)
+ cdef CFloat32ProjectionData2D * pDataObject2
+ cdef CFloat32VolumeData2D * pDataObject3
+ if pDataObject.getType() == PROJECTION:
+ pDataObject2 = <CFloat32ProjectionData2D * >pDataObject
+ xml = utils.dict2XML(six.b('ProjectionGeometry'), geom)
+ cfg.self = xml.getRootNode()
+ tpe = wrap_from_bytes(cfg.self.getAttribute(six.b('type')))
+ if (tpe == 'sparse_matrix'):
+ ppGeometry = <CProjectionGeometry2D * >new CSparseMatrixProjectionGeometry2D()
+ elif (tpe == 'fanflat'):
+ ppGeometry = <CProjectionGeometry2D * >new CFanFlatProjectionGeometry2D()
+ elif (tpe == 'fanflat_vec'):
+ ppGeometry = <CProjectionGeometry2D * >new CFanFlatVecProjectionGeometry2D()
+ else:
+ ppGeometry = <CProjectionGeometry2D * >new CParallelProjectionGeometry2D()
+ if not ppGeometry.initialize(cfg):
+ del xml
+ del ppGeometry
+ raise Exception('Geometry class not initialized.')
+ if (ppGeometry.getDetectorCount() != pDataObject2.getDetectorCount() or ppGeometry.getProjectionAngleCount() != pDataObject2.getAngleCount()):
+ del ppGeometry
+ del xml
+ raise Exception(
+ "The dimensions of the data do not match those specified in the geometry.")
+ pDataObject2.changeGeometry(ppGeometry)
+ del ppGeometry
+ del xml
+ elif pDataObject.getType() == VOLUME:
+ pDataObject3 = <CFloat32VolumeData2D * >pDataObject
+ xml = utils.dict2XML(six.b('VolumeGeometry'), geom)
+ cfg.self = xml.getRootNode()
+ pGeometry = new CVolumeGeometry2D()
+ if not pGeometry.initialize(cfg):
+ del xml
+ del pGeometry
+ raise Exception('Geometry class not initialized.')
+ if (pGeometry.getGridColCount() != pDataObject3.getWidth() or pGeometry.getGridRowCount() != pDataObject3.getHeight()):
+ del xml
+ del pGeometry
+ raise Exception(
+ 'The dimensions of the data do not match those specified in the geometry.')
+ pDataObject3.changeGeometry(pGeometry)
+ del xml
+ del pGeometry
+ else:
+ raise Exception("Not a known data object")
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def get(i):
+ cdef CFloat32Data2D * pDataObject = getObject(i)
+ outArr = np.empty((pDataObject.getHeight(), pDataObject.getWidth()),dtype=np.float32,order='C')
+ cdef float [:,::1] mView = outArr
+ cdef float [:,::1] cView = <float[:outArr.shape[0],:outArr.shape[1]]> pDataObject.getData2D()[0]
+ mView[:] = cView
+ return outArr
+
+def get_shared(i):
+ cdef CFloat32Data2D * pDataObject = getObject(i)
+ cdef np.npy_intp shape[2]
+ shape[0] = <np.npy_intp> pDataObject.getHeight()
+ shape[1] = <np.npy_intp> pDataObject.getWidth()
+ return np.PyArray_SimpleNewFromData(2,shape,np.NPY_FLOAT32,<void *>pDataObject.getData2D()[0])
+
+
+def get_single(i):
+ raise Exception("Not yet implemented")
+
+
+def info():
+ six.print_(wrap_from_bytes(man2d.info()))
diff --git a/python/astra/data3d.py b/python/astra/data3d.py
new file mode 100644
index 0000000..33bde51
--- /dev/null
+++ b/python/astra/data3d.py
@@ -0,0 +1,108 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from . import data3d_c as d
+
+def create(datatype,geometry,data=None):
+ """Create a 3D object.
+
+ :param datatype: Data object type, '-vol' or '-sino'.
+ :type datatype: :class:`string`
+ :param geometry: Volume or projection geometry.
+ :type geometry: :class:`dict`
+ :param data: Data to fill the constructed object with, either a scalar or array.
+ :type data: :class:`float` or :class:`numpy.ndarray`
+ :returns: :class:`int` -- the ID of the constructed object.
+
+ """
+ return d.create(datatype,geometry,data)
+
+def get(i):
+ """Get a 3D object.
+
+ :param i: ID of object to get.
+ :type i: :class:`int`
+ :returns: :class:`numpy.ndarray` -- The object data.
+
+ """
+ return d.get(i)
+
+def get_shared(i):
+ """Get a 3D object with memory shared between the ASTRA toolbox and numpy array.
+
+ :param i: ID of object to get.
+ :type i: :class:`int`
+ :returns: :class:`numpy.ndarray` -- The object data.
+
+ """
+ return d.get_shared(i)
+
+def get_single(i):
+ """Get a 3D object in single precision.
+
+ :param i: ID of object to get.
+ :type i: :class:`int`
+ :returns: :class:`numpy.ndarray` -- The object data.
+
+ """
+ return g.get_single(i)
+
+def store(i,data):
+ """Fill existing 3D object with data.
+
+ :param i: ID of object to fill.
+ :type i: :class:`int`
+ :param data: Data to fill the object with, either a scalar or array.
+ :type data: :class:`float` or :class:`numpy.ndarray`
+
+ """
+ return d.store(i,data)
+
+def dimensions(i):
+ """Get dimensions of a 3D object.
+
+ :param i: ID of object.
+ :type i: :class:`int`
+ :returns: :class:`tuple` -- dimensions of object with ID ``i``.
+
+ """
+ return d.dimensions(i)
+
+def delete(ids):
+ """Delete a 2D object.
+
+ :param ids: ID or list of ID's to delete.
+ :type ids: :class:`int` or :class:`list`
+
+ """
+ return d.delete(ids)
+
+def clear():
+ """Clear all 3D data objects."""
+ return d.clear()
+
+def info():
+ """Print info on 3D objects in memory."""
+ return d.info()
diff --git a/python/astra/data3d_c.pyx b/python/astra/data3d_c.pyx
new file mode 100644
index 0000000..f821aaf
--- /dev/null
+++ b/python/astra/data3d_c.pyx
@@ -0,0 +1,188 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+# distutils: language = c++
+# distutils: libraries = astra
+
+import six
+
+cimport cython
+
+cimport PyData3DManager
+from .PyData3DManager cimport CData3DManager
+
+from .PyIncludes cimport *
+import numpy as np
+
+cimport numpy as np
+np.import_array()
+
+cimport PyXMLDocument
+from .PyXMLDocument cimport XMLDocument
+
+cimport utils
+from .utils import wrap_from_bytes
+
+cdef CData3DManager * man3d = <CData3DManager * >PyData3DManager.getSingletonPtr()
+
+cdef extern from *:
+ CFloat32Data3DMemory * dynamic_cast_mem "dynamic_cast<astra::CFloat32Data3DMemory*>" (CFloat32Data3D * ) except NULL
+
+def create(datatype,geometry,data=None):
+ cdef XMLDocument * xml
+ cdef Config cfg
+ cdef CVolumeGeometry3D * pGeometry
+ cdef CProjectionGeometry3D * ppGeometry
+ cdef CFloat32Data3DMemory * pDataObject3D
+ cdef CConeProjectionGeometry3D* pppGeometry
+ if datatype == '-vol':
+ xml = utils.dict2XML(six.b('VolumeGeometry'), geometry)
+ cfg.self = xml.getRootNode()
+ pGeometry = new CVolumeGeometry3D()
+ if not pGeometry.initialize(cfg):
+ del xml
+ del pGeometry
+ raise Exception('Geometry class not initialized.')
+ pDataObject3D = <CFloat32Data3DMemory * > new CFloat32VolumeData3DMemory(pGeometry)
+ del xml
+ del pGeometry
+ elif datatype == '-sino' or datatype == '-proj3d':
+ xml = utils.dict2XML(six.b('ProjectionGeometry'), geometry)
+ cfg.self = xml.getRootNode()
+ tpe = wrap_from_bytes(cfg.self.getAttribute(six.b('type')))
+ if (tpe == "parallel3d"):
+ ppGeometry = <CProjectionGeometry3D*> new CParallelProjectionGeometry3D();
+ elif (tpe == "parallel3d_vec"):
+ ppGeometry = <CProjectionGeometry3D*> new CParallelVecProjectionGeometry3D();
+ elif (tpe == "cone"):
+ ppGeometry = <CProjectionGeometry3D*> new CConeProjectionGeometry3D();
+ elif (tpe == "cone_vec"):
+ ppGeometry = <CProjectionGeometry3D*> new CConeVecProjectionGeometry3D();
+ else:
+ raise Exception("Invalid geometry type.")
+
+ if not ppGeometry.initialize(cfg):
+ del xml
+ del ppGeometry
+ raise Exception('Geometry class not initialized.')
+ pDataObject3D = <CFloat32Data3DMemory * > new CFloat32ProjectionData3DMemory(ppGeometry)
+ del ppGeometry
+ del xml
+ elif datatype == "-sinocone":
+ xml = utils.dict2XML(six.b('ProjectionGeometry'), geometry)
+ cfg.self = xml.getRootNode()
+ pppGeometry = new CConeProjectionGeometry3D()
+ if not pppGeometry.initialize(cfg):
+ del xml
+ del pppGeometry
+ raise Exception('Geometry class not initialized.')
+ pDataObject3D = <CFloat32Data3DMemory * > new CFloat32ProjectionData3DMemory(pppGeometry)
+ else:
+ raise Exception("Invalid datatype. Please specify '-vol' or '-proj3d'.")
+
+ if not pDataObject3D.isInitialized():
+ del pDataObject3D
+ raise Exception("Couldn't initialize data object.")
+
+ fillDataObject(pDataObject3D, data)
+
+ pDataObject3D.updateStatistics()
+
+ return man3d.store(<CFloat32Data3D*>pDataObject3D)
+
+
+cdef fillDataObject(CFloat32Data3DMemory * obj, data):
+ if data is None:
+ fillDataObjectScalar(obj, 0)
+ else:
+ if isinstance(data, np.ndarray):
+ fillDataObjectArray(obj, np.ascontiguousarray(data,dtype=np.float32))
+ else:
+ fillDataObjectScalar(obj, np.float32(data))
+
+cdef fillDataObjectScalar(CFloat32Data3DMemory * obj, float s):
+ cdef int i
+ for i in range(obj.getSize()):
+ obj.getData()[i] = s
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+cdef fillDataObjectArray(CFloat32Data3DMemory * obj, float [:,:,::1] data):
+ if (not data.shape[0] == obj.getDepth()) or (not data.shape[1] == obj.getHeight()) or (not data.shape[2] == obj.getWidth()):
+ raise Exception(
+ "The dimensions of the data do not match those specified in the geometry.")
+ cdef float [:,:,::1] cView = <float[:data.shape[0],:data.shape[1],:data.shape[2]]> obj.getData3D()[0][0]
+ cView[:] = data
+
+cdef CFloat32Data3D * getObject(i) except NULL:
+ cdef CFloat32Data3D * pDataObject = man3d.get(i)
+ if pDataObject == NULL:
+ raise Exception("Data object not found")
+ if not pDataObject.isInitialized():
+ raise Exception("Data object not initialized properly.")
+ return pDataObject
+
+@cython.boundscheck(False)
+@cython.wraparound(False)
+def get(i):
+ cdef CFloat32Data3DMemory * pDataObject = dynamic_cast_mem(getObject(i))
+ outArr = np.empty((pDataObject.getDepth(),pDataObject.getHeight(), pDataObject.getWidth()),dtype=np.float32,order='C')
+ cdef float [:,:,::1] mView = outArr
+ cdef float [:,:,::1] cView = <float[:outArr.shape[0],:outArr.shape[1],:outArr.shape[2]]> pDataObject.getData3D()[0][0]
+ mView[:] = cView
+ return outArr
+
+def get_shared(i):
+ cdef CFloat32Data3DMemory * pDataObject = dynamic_cast_mem(getObject(i))
+ outArr = np.empty((pDataObject.getDepth(),pDataObject.getHeight(), pDataObject.getWidth()),dtype=np.float32,order='C')
+ cdef np.npy_intp shape[3]
+ shape[0] = <np.npy_intp> pDataObject.getDepth()
+ shape[1] = <np.npy_intp> pDataObject.getHeight()
+ shape[2] = <np.npy_intp> pDataObject.getWidth()
+ return np.PyArray_SimpleNewFromData(3,shape,np.NPY_FLOAT32,<void *>pDataObject.getData3D()[0][0])
+
+def get_single(i):
+ raise Exception("Not yet implemented")
+
+def store(i,data):
+ cdef CFloat32Data3D * pDataObject = getObject(i)
+ fillDataObject(dynamic_cast_mem(pDataObject), data)
+
+def dimensions(i):
+ cdef CFloat32Data3D * pDataObject = getObject(i)
+ return (pDataObject.getWidth(),pDataObject.getHeight(),pDataObject.getDepth())
+
+def delete(ids):
+ try:
+ for i in ids:
+ man3d.remove(i)
+ except TypeError:
+ man3d.remove(ids)
+
+def clear():
+ man3d.clear()
+
+def info():
+ six.print_(wrap_from_bytes(man3d.info()))
diff --git a/python/astra/extrautils.pyx b/python/astra/extrautils.pyx
new file mode 100644
index 0000000..998f5cb
--- /dev/null
+++ b/python/astra/extrautils.pyx
@@ -0,0 +1,43 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+
+def clipCircle(img):
+ cdef int i,j
+ cdef double x2,y2,mid,bnd
+ cdef long sz,sz2
+ sz = img.shape[0]
+ sz2 = sz*sz
+ bnd = sz2/4.
+ mid = (sz-1.)/2.
+ nDel=0
+ for i in range(sz):
+ for j in range(sz):
+ x2 = (i-mid)*(i-mid)
+ y2 = (j-mid)*(j-mid)
+ if x2+y2>bnd:
+ img[i,j]=0
+ nDel=nDel+1
+ return nDel
diff --git a/python/astra/functions.py b/python/astra/functions.py
new file mode 100644
index 0000000..4025468
--- /dev/null
+++ b/python/astra/functions.py
@@ -0,0 +1,270 @@
+#-----------------------------------------------------------------------
+# Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+# Author: Daniel M. Pelt
+# Contact: D.M.Pelt@cwi.nl
+# Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+# This file is part of the Python interface to the
+# All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+# The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+"""Additional functions for PyAstraToolbox.
+
+.. moduleauthor:: Daniel M. Pelt <D.M.Pelt@cwi.nl>
+
+
+"""
+
+from . import creators as ac
+import numpy as np
+from six.moves import range
+
+from . import data2d
+from . import data3d
+from . import projector
+from . import algorithm
+
+
+
+def clear():
+ """Clears all used memory of the ASTRA Toolbox.
+
+ .. note::
+ This is irreversible.
+
+ """
+ data2d.clear()
+ data3d.clear()
+ projector.clear()
+ algorithm.clear()
+
+
+def data_op(op, data, scalar, gpu_core, mask=None):
+ """Perform data operation on data.
+
+ :param op: Operation to perform.
+ :param data: Data to perform operation on.
+ :param scalar: Scalar argument to data operation.
+ :param gpu_core: GPU core to perform operation on.
+ :param mask: Optional mask.
+
+ """
+
+ cfg = ac.astra_dict('DataOperation_CUDA')
+ cfg['Operation'] = op
+ cfg['Scalar'] = scalar
+ cfg['DataId'] = data
+ if not mask == None:
+ cfg['MaskId'] = mask
+ cfg['option']['GPUindex'] = gpu_core
+ alg_id = algorithm.create(cfg)
+ algorithm.run(alg_id)
+ algorithm.delete(alg_id)
+
+
+def add_noise_to_sino(sinogram_in, I0, seed=None):
+ """Adds Poisson noise to a sinogram.
+
+ :param sinogram_in: Sinogram to add noise to.
+ :type sinogram_in: :class:`numpy.ndarray`
+ :param I0: Background intensity. Lower values lead to higher noise.
+ :type I0: :class:`float`
+ :returns: :class:`numpy.ndarray` -- the sinogram with added noise.
+
+ """
+
+ if not seed==None:
+ curstate = np.random.get_state()
+ np.random.seed(seed)
+
+ if isinstance(sinogram_in, np.ndarray):
+ sinogramRaw = sinogram_in
+ else:
+ sinogramRaw = data2d.get(sinogram_in)
+ max_sinogramRaw = sinogramRaw.max()
+ sinogramRawScaled = sinogramRaw / max_sinogramRaw
+ # to detector count
+ sinogramCT = I0 * np.exp(-sinogramRawScaled)
+ # add poison noise
+ sinogramCT_C = np.zeros_like(sinogramCT)
+ for i in range(sinogramCT_C.shape[0]):
+ for j in range(sinogramCT_C.shape[1]):
+ sinogramCT_C[i, j] = np.random.poisson(sinogramCT[i, j])
+ # to density
+ sinogramCT_D = sinogramCT_C / I0
+ sinogram_out = -max_sinogramRaw * np.log(sinogramCT_D)
+
+ if not isinstance(sinogram_in, np.ndarray):
+ at.data2d.store(sinogram_in, sinogram_out)
+
+ if not seed==None:
+ np.random.set_state(curstate)
+
+ return sinogram_out
+
+def move_vol_geom(geom, pos, is_relative=False):
+ """Moves center of volume geometry to new position.
+
+ :param geom: Input volume geometry
+ :type geom: :class:`dict`
+ :param pos: Tuple (x,y[,z]) for new position, with the center of the image at (0,0[,0])
+ :type pos: :class:`tuple`
+ :param is_relative: Whether new position is relative to the old position
+ :type is_relative: :class:`bool`
+ :returns: :class:`dict` -- Volume geometry with the new center
+ """
+
+ ret_geom = geom.copy()
+ ret_geom['option'] = geom['option'].copy()
+
+ if not is_relative:
+ ret_geom['option']['WindowMinX'] = -geom['GridColCount']/2.
+ ret_geom['option']['WindowMaxX'] = geom['GridColCount']/2.
+ ret_geom['option']['WindowMinY'] = -geom['GridRowCount']/2.
+ ret_geom['option']['WindowMaxY'] = geom['GridRowCount']/2.
+ if len(pos)>2:
+ ret_geom['option']['WindowMinZ'] = -geom['GridSliceCount']/2.
+ ret_geom['option']['WindowMaxZ'] = geom['GridSliceCount']/2.
+ ret_geom['option']['WindowMinX'] += pos[0]
+ ret_geom['option']['WindowMaxX'] += pos[0]
+ ret_geom['option']['WindowMinY'] += pos[1]
+ ret_geom['option']['WindowMaxY'] += pos[1]
+ if len(pos)>2:
+ ret_geom['option']['WindowMinZ'] += pos[2]
+ ret_geom['option']['WindowMaxZ'] += pos[2]
+ return ret_geom
+
+
+def geom_size(geom, dim=None):
+ """Returns the size of a volume or sinogram, based on the projection or volume geometry.
+
+ :param geom: Geometry to calculate size from
+ :type geometry: :class:`dict`
+ :param dim: Optional axis index to return
+ :type dim: :class:`int`
+ """
+
+ if 'GridSliceCount' in geom:
+ # 3D Volume geometry?
+ s = (geom['GridSliceCount'], geom[
+ 'GridRowCount'], geom['GridColCount'])
+ elif 'GridColCount' in geom:
+ # 2D Volume geometry?
+ s = (geom['GridRowCount'], geom['GridColCount'])
+ elif geom['type'] == 'parallel' or geom['type'] == 'fanflat':
+ s = (len(geom['ProjectionAngles']), geom['DetectorCount'])
+ elif geom['type'] == 'parallel3d' or geom['type'] == 'cone':
+ s = (geom['DetectorRowCount'], len(
+ geom['ProjectionAngles']), geom['DetectorColCount'])
+ elif geom['type'] == 'fanflat_vec':
+ s = (geom['Vectors'].shape[0], geom['DetectorCount'])
+ elif geom['type'] == 'parallel3d_vec' or geom['type'] == 'cone_vec':
+ s = (geom['DetectorRowCount'], geom[
+ 'Vectors'].shape[0], geom['DetectorColCount'])
+
+ if dim != None:
+ s = s[dim]
+
+ return s
+
+
+def geom_2vec(proj_geom):
+ """Returns a vector-based projection geometry from a basic projection geometry.
+
+ :param proj_geom: Projection geometry to convert
+ :type proj_geom: :class:`dict`
+ """
+ if proj_geom['type'] == 'fanflat':
+ angles = proj_geom['ProjectionAngles']
+ vectors = np.zeros((len(angles), 6))
+ for i in range(len(angles)):
+
+ # source
+ vectors[i, 0] = np.sin(angles[i]) * proj_geom['DistanceOriginSource']
+ vectors[i, 1] = -np.cos(angles[i]) * proj_geom['DistanceOriginSource']
+
+ # center of detector
+ vectors[i, 2] = -np.sin(angles[i]) * proj_geom['DistanceOriginDetector']
+ vectors[i, 3] = np.cos(angles[i]) * proj_geom['DistanceOriginDetector']
+
+ # vector from detector pixel 0 to 1
+ vectors[i, 4] = np.cos(angles[i]) * proj_geom['DetectorWidth']
+ vectors[i, 5] = np.sin(angles[i]) * proj_geom['DetectorWidth']
+ proj_geom_out = ac.create_proj_geom(
+ 'fanflat_vec', proj_geom['DetectorCount'], vectors)
+
+ elif proj_geom['type'] == 'cone':
+ angles = proj_geom['ProjectionAngles']
+ vectors = np.zeros((len(angles), 12))
+ for i in range(len(angles)):
+ # source
+ vectors[i, 0] = np.sin(angles[i]) * proj_geom['DistanceOriginSource']
+ vectors[i, 1] = -np.cos(angles[i]) * proj_geom['DistanceOriginSource']
+ vectors[i, 2] = 0
+
+ # center of detector
+ vectors[i, 3] = -np.sin(angles[i]) * proj_geom['DistanceOriginDetector']
+ vectors[i, 4] = np.cos(angles[i]) * proj_geom['DistanceOriginDetector']
+ vectors[i, 5] = 0
+
+ # vector from detector pixel (0,0) to (0,1)
+ vectors[i, 6] = np.cos(angles[i]) * proj_geom['DetectorSpacingX']
+ vectors[i, 7] = np.sin(angles[i]) * proj_geom['DetectorSpacingX']
+ vectors[i, 8] = 0
+
+ # vector from detector pixel (0,0) to (1,0)
+ vectors[i, 9] = 0
+ vectors[i, 10] = 0
+ vectors[i, 11] = proj_geom['DetectorSpacingY']
+
+ proj_geom_out = ac.create_proj_geom(
+ 'cone_vec', proj_geom['DetectorRowCount'], proj_geom['DetectorColCount'], vectors)
+
+ # PARALLEL
+ elif proj_geom['type'] == 'parallel3d':
+ angles = proj_geom['ProjectionAngles']
+ vectors = np.zeros((len(angles), 12))
+ for i in range(len(angles)):
+
+ # ray direction
+ vectors[i, 0] = np.sin(angles[i])
+ vectors[i, 1] = -np.cos(angles[i])
+ vectors[i, 2] = 0
+
+ # center of detector
+ vectors[i, 3] = 0
+ vectors[i, 4] = 0
+ vectors[i, 5] = 0
+
+ # vector from detector pixel (0,0) to (0,1)
+ vectors[i, 6] = np.cos(angles[i]) * proj_geom['DetectorSpacingX']
+ vectors[i, 7] = np.sin(angles[i]) * proj_geom['DetectorSpacingX']
+ vectors[i, 8] = 0
+
+ # vector from detector pixel (0,0) to (1,0)
+ vectors[i, 9] = 0
+ vectors[i, 10] = 0
+ vectors[i, 11] = proj_geom['DetectorSpacingY']
+
+ proj_geom_out = ac.create_proj_geom(
+ 'parallel3d_vec', proj_geom['DetectorRowCount'], proj_geom['DetectorColCount'], vectors)
+
+ else:
+ raise ValueError(
+ 'No suitable vector geometry found for type: ' + proj_geom['type'])
+ return proj_geom_out
diff --git a/python/astra/matlab.py b/python/astra/matlab.py
new file mode 100644
index 0000000..83b345d
--- /dev/null
+++ b/python/astra/matlab.py
@@ -0,0 +1,112 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+"""This module implements a MATLAB-like interface to the ASTRA Toolbox.
+
+Note that all functions are called with a :class:`string` as the first
+argument, specifying the operation to perform. This un-pythonic way
+is used to make transitioning from MATLAB code to Python code easier, as
+the MATLAB interface uses the same type of method calling.
+
+After an initial ``import astra``, these functions can be accessed in the
+``astra.m`` module.
+
+"""
+
+from . import astra_c
+from . import data2d_c
+from . import data3d_c
+from . import projector_c
+from . import algorithm_c
+from . import matrix_c
+import numpy as np
+
+
+def astra(command, *args):
+ """MATLAB-like interface to the :mod:`astra.astra` module
+
+ For example:
+
+ ``astra.m.astra('use_cuda')`` -- Check if CUDA is enabled.
+
+ """
+ return getattr(astra_c, command)(*args)
+
+
+def data2d(command, *args):
+ """MATLAB-like interface to the :mod:`astra.data2d` module
+
+ For example:
+
+ ``astra.m.data2d('create',type,geometry,data)`` -- Create a 2D object.
+
+ """
+ return getattr(data2d_c, command)(*args)
+
+
+def data3d(command, *args):
+ """MATLAB-like interface to the :mod:`astra.data3d` module
+
+ For example:
+
+ ``astra.m.data3d('get',i)`` -- Get 3D object data.
+
+ """
+ return getattr(data3d_c, command)(*args)
+
+
+def projector(command, *args):
+ """MATLAB-like interface to the :mod:`astra.projector` module
+
+ For example:
+
+ ``astra.m.projector('volume_geometry',i)`` -- Get volume geometry.
+
+ """
+ return getattr(projector_c, command)(*args)
+
+
+def matrix(command, *args):
+ """MATLAB-like interface to the :mod:`astra.matrix` module
+
+ For example:
+
+ ``astra.m.matrix('delete',i)`` -- Delete a matrix.
+
+ """
+ return getattr(matrix_c, command)(*args)
+
+
+def algorithm(command, *args):
+ """MATLAB-like interface to the :mod:`astra.algorithm` module
+
+ For example:
+
+ ``astra.m.algorithm('run',i,1000)`` -- Run an algorithm with 1000 iterations.
+
+ """
+ if command == 'iterate':
+ command = 'run'
+ return getattr(algorithm_c, command)(*args)
diff --git a/python/astra/matrix.py b/python/astra/matrix.py
new file mode 100644
index 0000000..27e4823
--- /dev/null
+++ b/python/astra/matrix.py
@@ -0,0 +1,86 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from . import matrix_c as m
+
+def delete(ids):
+ """Delete a matrix object.
+
+ :param ids: ID or list of ID's to delete.
+ :type ids: :class:`int` or :class:`list`
+
+ """
+ return m.delete(ids)
+
+def clear():
+ """Clear all matrix objects."""
+ return m.clear()
+
+def create(data):
+ """Create matrix object with data.
+
+ :param data: Data to fill the created object with.
+ :type data: :class:`scipy.sparse.csr_matrix`
+ :returns: :class:`int` -- the ID of the constructed object.
+
+ """
+ return m.create(data)
+
+
+def store(i,data):
+ """Fill existing matrix object with data.
+
+ :param i: ID of object to fill.
+ :type i: :class:`int`
+ :param data: Data to fill the object with.
+ :type data: :class:`scipy.sparse.csr_matrix`
+
+ """
+ return m.store(i,data)
+
+def get_size(i):
+ """Get matrix dimensions.
+
+ :param i: ID of object.
+ :type i: :class:`int`
+ :returns: :class:`tuple` -- matrix dimensions.
+ """
+ return m.get_size(i)
+
+def get(i):
+ """Get a matrix object.
+
+ :param i: ID of object to get.
+ :type i: :class:`int`
+ :returns: :class:`scipy.sparse.csr_matrix` -- The object data.
+
+ """
+ return m.get(i)
+
+def info():
+ """Print info on matrix objects in memory."""
+ return m.info()
+
+
diff --git a/python/astra/matrix_c.pyx b/python/astra/matrix_c.pyx
new file mode 100644
index 0000000..b0d8bc4
--- /dev/null
+++ b/python/astra/matrix_c.pyx
@@ -0,0 +1,116 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+# distutils: language = c++
+# distutils: libraries = astra
+
+import six
+from six.moves import range
+import numpy as np
+import scipy.sparse as ss
+
+from libcpp cimport bool
+
+cimport PyMatrixManager
+from .PyMatrixManager cimport CMatrixManager
+from .PyIncludes cimport *
+from .utils import wrap_from_bytes
+
+cdef CMatrixManager * manM = <CMatrixManager * >PyMatrixManager.getSingletonPtr()
+
+
+def delete(ids):
+ try:
+ for i in ids:
+ manM.remove(i)
+ except TypeError:
+ manM.remove(ids)
+
+def clear():
+ manM.clear()
+
+cdef int csr_matrix_to_astra(data,CSparseMatrix *mat) except -1:
+ if isinstance(data,ss.csr_matrix):
+ csrD = data
+ else:
+ csrD = data.tocsr()
+ if not mat.isInitialized():
+ raise Exception("Couldn't initialize data object.")
+ if csrD.nnz > mat.m_lSize or csrD.shape[0] > mat.m_iHeight:
+ raise Exception("Matrix too large to store in this object.")
+ for i in range(len(csrD.indptr)):
+ mat.m_plRowStarts[i] = csrD.indptr[i]
+ for i in range(csrD.nnz):
+ mat.m_piColIndices[i] = csrD.indices[i]
+ mat.m_pfValues[i] = csrD.data[i]
+
+cdef astra_to_csr_matrix(CSparseMatrix *mat):
+ indptr = np.zeros(mat.m_iHeight+1,dtype=np.int)
+ indices = np.zeros(mat.m_plRowStarts[mat.m_iHeight],dtype=np.int)
+ data = np.zeros(mat.m_plRowStarts[mat.m_iHeight])
+ for i in range(mat.m_iHeight+1):
+ indptr[i] = mat.m_plRowStarts[i]
+ for i in range(mat.m_plRowStarts[mat.m_iHeight]):
+ indices[i] = mat.m_piColIndices[i]
+ data[i] = mat.m_pfValues[i]
+ return ss.csr_matrix((data,indices,indptr),shape=(mat.m_iHeight,mat.m_iWidth))
+
+def create(data):
+ cdef CSparseMatrix* pMatrix
+ pMatrix = new CSparseMatrix(data.shape[0], data.shape[1], data.nnz)
+ if not pMatrix.isInitialized():
+ del pMatrix
+ raise Exception("Couldn't initialize data object.")
+ try:
+ csr_matrix_to_astra(data,pMatrix)
+ except:
+ del pMatrix
+ raise Exception("Failed to create data object.")
+
+ return manM.store(pMatrix)
+
+cdef CSparseMatrix * getObject(i) except NULL:
+ cdef CSparseMatrix * pDataObject = manM.get(i)
+ if pDataObject == NULL:
+ raise Exception("Data object not found")
+ if not pDataObject.isInitialized():
+ raise Exception("Data object not initialized properly.")
+ return pDataObject
+
+
+def store(i,data):
+ cdef CSparseMatrix * pDataObject = getObject(i)
+ csr_matrix_to_astra(data,pDataObject)
+
+def get_size(i):
+ cdef CSparseMatrix * pDataObject = getObject(i)
+ return (pDataObject.m_iHeight,pDataObject.m_iWidth)
+
+def get(i):
+ cdef CSparseMatrix * pDataObject = getObject(i)
+ return astra_to_csr_matrix(pDataObject)
+
+def info():
+ six.print_(wrap_from_bytes(manM.info()))
diff --git a/python/astra/projector.py b/python/astra/projector.py
new file mode 100644
index 0000000..c916c52
--- /dev/null
+++ b/python/astra/projector.py
@@ -0,0 +1,100 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from . import projector_c as p
+
+def create(config):
+ """Create projector object.
+
+ :param config: Projector options.
+ :type config: :class:`dict`
+ :returns: :class:`int` -- the ID of the constructed object.
+
+ """
+ return p.create(config)
+
+
+def delete(ids):
+ """Delete a projector object.
+
+ :param ids: ID or list of ID's to delete.
+ :type ids: :class:`int` or :class:`list`
+
+ """
+ return p.delete(ids)
+
+
+def clear():
+ """Clear all projector objects."""
+ return p.clear()
+
+
+def info():
+ """Print info on projector objects in memory."""
+ return p.info()
+
+def projection_geometry(i):
+ """Get projection geometry of a projector.
+
+ :param i: ID of projector.
+ :type i: :class:`int`
+ :returns: :class:`dict` -- projection geometry
+
+ """
+ return p.projection_geometry(i)
+
+
+def volume_geometry(i):
+ """Get volume geometry of a projector.
+
+ :param i: ID of projector.
+ :type i: :class:`int`
+ :returns: :class:`dict` -- volume geometry
+
+ """
+ return p.volume_geometry(i)
+
+
+def weights_single_ray(i, projection_index, detector_index):
+ return p.weights_single_ray(i, projection_index, detector_index)
+
+
+def weights_projection(i, projection_index):
+ return p.weights_projection(i, projection_index)
+
+
+def splat(i, row, col):
+ return p.splat(i, row, col)
+
+
+def matrix(i):
+ """Get sparse matrix of a projector.
+
+ :param i: ID of projector.
+ :type i: :class:`int`
+ :returns: :class:`int` -- ID of sparse matrix.
+
+ """
+ return p.matrix(i)
diff --git a/python/astra/projector_c.pyx b/python/astra/projector_c.pyx
new file mode 100644
index 0000000..978ca09
--- /dev/null
+++ b/python/astra/projector_c.pyx
@@ -0,0 +1,119 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+# distutils: language = c++
+# distutils: libraries = astra
+
+import six
+from .PyIncludes cimport *
+
+cimport utils
+from .utils import wrap_from_bytes
+
+cimport PyProjector2DFactory
+from .PyProjector2DFactory cimport CProjector2DFactory
+
+cimport PyProjector2DManager
+from .PyProjector2DManager cimport CProjector2DManager
+
+cimport PyXMLDocument
+from .PyXMLDocument cimport XMLDocument
+
+cimport PyMatrixManager
+from .PyMatrixManager cimport CMatrixManager
+
+cdef CProjector2DManager * manProj = <CProjector2DManager * >PyProjector2DManager.getSingletonPtr()
+cdef CMatrixManager * manM = <CMatrixManager * >PyMatrixManager.getSingletonPtr()
+
+
+def create(config):
+ cdef XMLDocument * xml = utils.dict2XML(six.b('Projector2D'), config)
+ cdef Config cfg
+ cdef CProjector2D * proj
+ cfg.self = xml.getRootNode()
+ proj = PyProjector2DFactory.getSingletonPtr().create(cfg)
+ if proj == NULL:
+ del xml
+ raise Exception("Error creating projector.")
+ del xml
+ return manProj.store(proj)
+
+
+def delete(ids):
+ try:
+ for i in ids:
+ manProj.remove(i)
+ except TypeError:
+ manProj.remove(ids)
+
+
+def clear():
+ manProj.clear()
+
+
+def info():
+ six.print_(wrap_from_bytes(manProj.info()))
+
+cdef CProjector2D * getObject(i) except NULL:
+ cdef CProjector2D * proj = manProj.get(i)
+ if proj == NULL:
+ raise Exception("Projector not initialized.")
+ if not proj.isInitialized():
+ raise Exception("Projector not initialized.")
+ return proj
+
+
+def projection_geometry(i):
+ cdef CProjector2D * proj = getObject(i)
+ return utils.createProjectionGeometryStruct(proj.getProjectionGeometry())
+
+
+def volume_geometry(i):
+ cdef CProjector2D * proj = getObject(i)
+ return utils.createVolumeGeometryStruct(proj.getVolumeGeometry())
+
+
+def weights_single_ray(i, projection_index, detector_index):
+ raise Exception("Not yet implemented")
+
+
+def weights_projection(i, projection_index):
+ raise Exception("Not yet implemented")
+
+
+def splat(i, row, col):
+ raise Exception("Not yet implemented")
+
+
+def matrix(i):
+ cdef CProjector2D * proj = getObject(i)
+ cdef CSparseMatrix * mat = proj.getMatrix()
+ if mat == NULL:
+ del mat
+ raise Exception("Data object not found")
+ if not mat.isInitialized():
+ del mat
+ raise Exception("Data object not initialized properly.")
+ return manM.store(mat)
diff --git a/python/astra/utils.pxd b/python/astra/utils.pxd
new file mode 100644
index 0000000..55db9d3
--- /dev/null
+++ b/python/astra/utils.pxd
@@ -0,0 +1,37 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+from libcpp.string cimport string
+
+cimport PyXMLDocument
+from .PyXMLDocument cimport XMLDocument
+from .PyXMLDocument cimport XMLNode
+
+from .PyIncludes cimport *
+
+cdef XMLDocument *dict2XML(string rootname, dc)
+cdef XML2dict(XMLDocument *)
+cdef createVolumeGeometryStruct(CVolumeGeometry2D* geom)
+cdef createProjectionGeometryStruct(CProjectionGeometry2D* geom)
diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx
new file mode 100644
index 0000000..53e84a9
--- /dev/null
+++ b/python/astra/utils.pyx
@@ -0,0 +1,260 @@
+#-----------------------------------------------------------------------
+#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam
+#
+#Author: Daniel M. Pelt
+#Contact: D.M.Pelt@cwi.nl
+#Website: http://dmpelt.github.io/pyastratoolbox/
+#
+#
+#This file is part of the Python interface to the
+#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox").
+#
+#The Python interface to 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 Python interface to 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 Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
+#
+#-----------------------------------------------------------------------
+# distutils: language = c++
+# distutils: libraries = astra
+
+import numpy as np
+import six
+from libcpp.string cimport string
+from libcpp.list cimport list
+from libcpp.vector cimport vector
+from cython.operator cimport dereference as deref
+from cpython.version cimport PY_MAJOR_VERSION
+
+cimport PyXMLDocument
+from .PyXMLDocument cimport XMLDocument
+from .PyXMLDocument cimport XMLNode
+from .PyIncludes cimport *
+
+
+cdef XMLDocument * dict2XML(string rootname, dc):
+ cdef XMLDocument * doc = PyXMLDocument.createDocument(rootname)
+ cdef XMLNode * node = doc.getRootNode()
+ try:
+ readDict(node, dc)
+ except:
+ six.print_('Error reading XML')
+ del doc
+ doc = NULL
+ finally:
+ del node
+ return doc
+
+def convert_item(item):
+ if isinstance(item, six.string_types):
+ return item.encode('ascii')
+
+ if type(item) is not dict:
+ return item
+
+ out_dict = {}
+ for k in item:
+ out_dict[convert_item(k)] = convert_item(item[k])
+ return out_dict
+
+
+def wrap_to_bytes(value):
+ if isinstance(value, six.binary_type):
+ return value
+ s = str(value)
+ if PY_MAJOR_VERSION == 3:
+ s = s.encode('ascii')
+ return s
+
+
+def wrap_from_bytes(value):
+ s = value
+ if PY_MAJOR_VERSION == 3:
+ s = s.decode('ascii')
+ return s
+
+
+cdef void readDict(XMLNode * root, _dc):
+ cdef XMLNode * listbase
+ cdef XMLNode * itm
+ cdef int i
+ cdef int j
+
+ dc = convert_item(_dc)
+ for item in dc:
+ val = dc[item]
+ if isinstance(val, np.ndarray):
+ if val.size == 0:
+ break
+ listbase = root.addChildNode(item)
+ listbase.addAttribute(< string > six.b('listsize'), < float32 > val.size)
+ index = 0
+ if val.ndim == 2:
+ for i in range(val.shape[0]):
+ for j in range(val.shape[1]):
+ itm = listbase.addChildNode(six.b('ListItem'))
+ itm.addAttribute(< string > six.b('index'), < float32 > index)
+ itm.addAttribute( < string > six.b('value'), < float32 > val[i, j])
+ index += 1
+ del itm
+ elif val.ndim == 1:
+ for i in range(val.shape[0]):
+ itm = listbase.addChildNode(six.b('ListItem'))
+ itm.addAttribute(< string > six.b('index'), < float32 > index)
+ itm.addAttribute(< string > six.b('value'), < float32 > val[i])
+ index += 1
+ del itm
+ else:
+ raise Exception("Only 1 or 2 dimensions are allowed")
+ del listbase
+ elif isinstance(val, dict):
+ if item == six.b('option') or item == six.b('options') or item == six.b('Option') or item == six.b('Options'):
+ readOptions(root, val)
+ else:
+ itm = root.addChildNode(item)
+ readDict(itm, val)
+ del itm
+ else:
+ if item == six.b('type'):
+ root.addAttribute(< string > six.b('type'), <string> wrap_to_bytes(val))
+ else:
+ itm = root.addChildNode(item, wrap_to_bytes(val))
+ del itm
+
+cdef void readOptions(XMLNode * node, dc):
+ cdef XMLNode * listbase
+ cdef XMLNode * itm
+ cdef int i
+ cdef int j
+ for item in dc:
+ val = dc[item]
+ if node.hasOption(item):
+ raise Exception('Duplicate Option: %s' % item)
+ if isinstance(val, np.ndarray):
+ if val.size == 0:
+ break
+ listbase = node.addChildNode(six.b('Option'))
+ listbase.addAttribute(< string > six.b('key'), < string > item)
+ listbase.addAttribute(< string > six.b('listsize'), < float32 > val.size)
+ index = 0
+ if val.ndim == 2:
+ for i in range(val.shape[0]):
+ for j in range(val.shape[1]):
+ itm = listbase.addChildNode(six.b('ListItem'))
+ itm.addAttribute(< string > six.b('index'), < float32 > index)
+ itm.addAttribute( < string > six.b('value'), < float32 > val[i, j])
+ index += 1
+ del itm
+ elif val.ndim == 1:
+ for i in range(val.shape[0]):
+ itm = listbase.addChildNode(six.b('ListItem'))
+ itm.addAttribute(< string > six.b('index'), < float32 > index)
+ itm.addAttribute(< string > six.b('value'), < float32 > val[i])
+ index += 1
+ del itm
+ else:
+ raise Exception("Only 1 or 2 dimensions are allowed")
+ del listbase
+ else:
+ node.addOption(item, wrap_to_bytes(val))
+
+cdef vectorToNumpy(vector[float32] inp):
+ cdef int i
+ cdef int sz = inp.size()
+ ret = np.empty(sz)
+ for i in range(sz):
+ ret[i] = inp[i]
+ return ret
+
+cdef XMLNode2dict(XMLNode * node):
+ cdef XMLNode * subnode
+ cdef list[XMLNode * ] nodes
+ cdef list[XMLNode * ].iterator it
+ dct = {}
+ if node.hasAttribute(six.b('type')):
+ dct['type'] = node.getAttribute(six.b('type'))
+ nodes = node.getNodes()
+ it = nodes.begin()
+ while it != nodes.end():
+ subnode = deref(it)
+ if subnode.hasAttribute(six.b('listsize')):
+ dct[subnode.getName(
+ )] = vectorToNumpy(subnode.getContentNumericalArray())
+ else:
+ dct[subnode.getName()] = subnode.getContent()
+ del subnode
+ return dct
+
+cdef XML2dict(XMLDocument * xml):
+ cdef XMLNode * node = xml.getRootNode()
+ dct = XMLNode2dict(node)
+ del node;
+ return dct;
+
+cdef createProjectionGeometryStruct(CProjectionGeometry2D * geom):
+ cdef int i
+ cdef CFanFlatVecProjectionGeometry2D * fanvecGeom
+ # cdef SFanProjection* p
+ dct = {}
+ dct['DetectorCount'] = geom.getDetectorCount()
+ if not geom.isOfType(< string > six.b('fanflat_vec')):
+ dct['DetectorWidth'] = geom.getDetectorWidth()
+ angles = np.empty(geom.getProjectionAngleCount())
+ for i in range(geom.getProjectionAngleCount()):
+ angles[i] = geom.getProjectionAngle(i)
+ dct['ProjectionAngles'] = angles
+ else:
+ raise Exception("Not yet implemented")
+ # fanvecGeom = <CFanFlatVecProjectionGeometry2D*> geom
+ # vecs = np.empty(fanvecGeom.getProjectionAngleCount()*6)
+ # iDetCount = pVecGeom.getDetectorCount()
+ # for i in range(fanvecGeom.getProjectionAngleCount()):
+ # p = &fanvecGeom.getProjectionVectors()[i];
+ # out[6*i + 0] = p.fSrcX
+ # out[6*i + 1] = p.fSrcY
+ # out[6*i + 2] = p.fDetSX + 0.5f*iDetCount*p.fDetUX
+ # out[6*i + 3] = p.fDetSY + 0.5f*iDetCount*p.fDetUY
+ # out[6*i + 4] = p.fDetUX
+ # out[6*i + 5] = p.fDetUY
+ # dct['Vectors'] = vecs
+ if (geom.isOfType(< string > six.b('parallel'))):
+ dct["type"] = "parallel"
+ elif (geom.isOfType(< string > six.b('fanflat'))):
+ raise Exception("Not yet implemented")
+ # astra::CFanFlatProjectionGeometry2D* pFanFlatGeom = dynamic_cast<astra::CFanFlatProjectionGeometry2D*>(_pProjGeom)
+ # mGeometryInfo["DistanceOriginSource"] = mxCreateDoubleScalar(pFanFlatGeom->getOriginSourceDistance())
+ # mGeometryInfo["DistanceOriginDetector"] =
+ # mxCreateDoubleScalar(pFanFlatGeom->getOriginDetectorDistance())
+ dct["type"] = "fanflat"
+ elif (geom.isOfType(< string > six.b('sparse_matrix'))):
+ raise Exception("Not yet implemented")
+ # astra::CSparseMatrixProjectionGeometry2D* pSparseMatrixGeom =
+ # dynamic_cast<astra::CSparseMatrixProjectionGeometry2D*>(_pProjGeom);
+ dct["type"] = "sparse_matrix"
+ # dct["MatrixID"] =
+ # mxCreateDoubleScalar(CMatrixManager::getSingleton().getIndex(pSparseMatrixGeom->getMatrix()))
+ elif(geom.isOfType(< string > six.b('fanflat_vec'))):
+ dct["type"] = "fanflat_vec"
+ return dct
+
+cdef createVolumeGeometryStruct(CVolumeGeometry2D * geom):
+ mGeometryInfo = {}
+ mGeometryInfo["GridColCount"] = geom.getGridColCount()
+ mGeometryInfo["GridRowCount"] = geom.getGridRowCount()
+
+ mGeometryOptions = {}
+ mGeometryOptions["WindowMinX"] = geom.getWindowMinX()
+ mGeometryOptions["WindowMaxX"] = geom.getWindowMaxX()
+ mGeometryOptions["WindowMinY"] = geom.getWindowMinY()
+ mGeometryOptions["WindowMaxY"] = geom.getWindowMaxY()
+
+ mGeometryInfo["option"] = mGeometryOptions
+ return mGeometryInfo