From 18b6d25f7e4f0943b3592f3bb4f6ca5ed9c285d3 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Fri, 19 Jun 2015 22:28:06 +0200 Subject: Add support for Python algorithm plugins --- samples/python/s018_plugin.py | 138 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 samples/python/s018_plugin.py (limited to 'samples') diff --git a/samples/python/s018_plugin.py b/samples/python/s018_plugin.py new file mode 100644 index 0000000..6677930 --- /dev/null +++ b/samples/python/s018_plugin.py @@ -0,0 +1,138 @@ +#----------------------------------------------------------------------- +#Copyright 2015 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 . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np +import six + +# Define the plugin class (has to subclass astra.plugin.base) +# Note that usually, these will be defined in a separate package/module +class SIRTPlugin(astra.plugin.base): + """Example of an ASTRA plugin class, implementing a simple 2D SIRT algorithm. + + Optional options: + + 'rel_factor': relaxation factor + """ + required_options=[] + optional_options=['rel_factor'] + + def initialize(self,cfg): + self.W = astra.OpTomo(cfg['ProjectorId']) + self.vid = cfg['ReconstructionDataId'] + self.sid = cfg['ProjectionDataId'] + try: + self.rel = cfg['option']['rel_factor'] + except KeyError: + self.rel = 1 + + def run(self, its): + v = astra.data2d.get_shared(self.vid) + s = astra.data2d.get_shared(self.sid) + W = self.W + for i in range(its): + v[:] += self.rel*(W.T*(s - (W*v).reshape(s.shape))).reshape(v.shape)/s.size + +if __name__=='__main__': + + vol_geom = astra.create_vol_geom(256, 256) + proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) + + # As before, create a sinogram from a phantom + import scipy.io + P = scipy.io.loadmat('phantom.mat')['phantom256'] + proj_id = astra.create_projector('cuda',proj_geom,vol_geom) + + # construct the OpTomo object + W = astra.OpTomo(proj_id) + + sinogram = W * P + sinogram = sinogram.reshape([180, 384]) + + # Register the plugin with ASTRA + # A default set of plugins to load can be defined in: + # - /etc/astra-toolbox/plugins.txt + # - [ASTRA_INSTALL_PATH]/python/astra/plugins.txt + # - [USER_HOME_PATH]/.astra-toolbox/plugins.txt + # - [ASTRA_PLUGIN_PATH environment variable]/plugins.txt + # In these files, create a separate line for each plugin with: + # [PLUGIN_ASTRA_NAME] [FULL_PLUGIN_CLASS] + # + # So in this case, it would be a line: + # SIRT-PLUGIN s018_plugin.SIRTPlugin + # + astra.plugin.register('SIRT-PLUGIN','s018_plugin.SIRTPlugin') + + # To get help on a registered plugin, use get_help + six.print_(astra.plugin.get_help('SIRT-PLUGIN')) + + # Create data structures + sid = astra.data2d.create('-sino', proj_geom, sinogram) + vid = astra.data2d.create('-vol', vol_geom) + + # Create config using plugin name + cfg = astra.astra_dict('SIRT-PLUGIN') + cfg['ProjectorId'] = proj_id + cfg['ProjectionDataId'] = sid + cfg['ReconstructionDataId'] = vid + + # Create algorithm object + alg_id = astra.algorithm.create(cfg) + + # Run algorithm for 100 iterations + astra.algorithm.run(alg_id, 100) + + # Get reconstruction + rec = astra.data2d.get(vid) + + # Options for the plugin go in cfg['option'] + cfg = astra.astra_dict('SIRT-PLUGIN') + cfg['ProjectorId'] = proj_id + cfg['ProjectionDataId'] = sid + cfg['ReconstructionDataId'] = vid + cfg['option'] = {} + cfg['option']['rel_factor'] = 1.5 + alg_id_rel = astra.algorithm.create(cfg) + astra.algorithm.run(alg_id_rel, 100) + rec_rel = astra.data2d.get(vid) + + # We can also use OpTomo to call the plugin + rec_op = W.reconstruct('SIRT-PLUGIN', sinogram, 100, extraOptions={'rel_factor':1.5}) + + import pylab as pl + pl.gray() + pl.figure(1) + pl.imshow(rec,vmin=0,vmax=1) + pl.figure(2) + pl.imshow(rec_rel,vmin=0,vmax=1) + pl.figure(3) + pl.imshow(rec_op,vmin=0,vmax=1) + pl.show() + + # Clean up. + astra.projector.delete(proj_id) + astra.algorithm.delete([alg_id, alg_id_rel]) + astra.data2d.delete([vid, sid]) -- cgit v1.2.3 From 11af4b554df9a8a5c31d9dcbc1ea849b32394ba3 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Wed, 24 Jun 2015 18:36:03 +0200 Subject: Better way of passing options to Python plugin using inspect --- samples/python/s018_plugin.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'samples') diff --git a/samples/python/s018_plugin.py b/samples/python/s018_plugin.py index 6677930..90e09ac 100644 --- a/samples/python/s018_plugin.py +++ b/samples/python/s018_plugin.py @@ -33,21 +33,16 @@ import six class SIRTPlugin(astra.plugin.base): """Example of an ASTRA plugin class, implementing a simple 2D SIRT algorithm. - Optional options: + Options: - 'rel_factor': relaxation factor + 'rel_factor': relaxation factor (optional) """ - required_options=[] - optional_options=['rel_factor'] - def initialize(self,cfg): + def initialize(self,cfg, rel_factor = 1): self.W = astra.OpTomo(cfg['ProjectorId']) self.vid = cfg['ReconstructionDataId'] self.sid = cfg['ProjectionDataId'] - try: - self.rel = cfg['option']['rel_factor'] - except KeyError: - self.rel = 1 + self.rel = rel_factor def run(self, its): v = astra.data2d.get_shared(self.vid) -- cgit v1.2.3 From d91b51f6d58003de84a9d6dd8189fceba0e81a5a Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Mon, 20 Jul 2015 14:07:21 +0200 Subject: Allow registering plugins without explicit name, and fix exception handling when running in Matlab --- samples/python/s018_plugin.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'samples') diff --git a/samples/python/s018_plugin.py b/samples/python/s018_plugin.py index 90e09ac..31cca95 100644 --- a/samples/python/s018_plugin.py +++ b/samples/python/s018_plugin.py @@ -38,6 +38,10 @@ class SIRTPlugin(astra.plugin.base): 'rel_factor': relaxation factor (optional) """ + # The astra_name variable defines the name to use to + # call the plugin from ASTRA + astra_name = "SIRT-PLUGIN" + def initialize(self,cfg, rel_factor = 1): self.W = astra.OpTomo(cfg['ProjectorId']) self.vid = cfg['ReconstructionDataId'] @@ -68,18 +72,13 @@ if __name__=='__main__': sinogram = sinogram.reshape([180, 384]) # Register the plugin with ASTRA - # A default set of plugins to load can be defined in: - # - /etc/astra-toolbox/plugins.txt - # - [ASTRA_INSTALL_PATH]/python/astra/plugins.txt - # - [USER_HOME_PATH]/.astra-toolbox/plugins.txt - # - [ASTRA_PLUGIN_PATH environment variable]/plugins.txt - # In these files, create a separate line for each plugin with: - # [PLUGIN_ASTRA_NAME] [FULL_PLUGIN_CLASS] - # - # So in this case, it would be a line: - # SIRT-PLUGIN s018_plugin.SIRTPlugin - # - astra.plugin.register('SIRT-PLUGIN','s018_plugin.SIRTPlugin') + # First we import the package that contains the plugin + import s018_plugin + # Then, we register the plugin class with ASTRA + astra.plugin.register(s018_plugin.SIRTPlugin) + + # Get a list of registered plugins + six.print_(astra.plugin.get_registered()) # To get help on a registered plugin, use get_help six.print_(astra.plugin.get_help('SIRT-PLUGIN')) -- cgit v1.2.3 From e07449189a05e3bcdc8ad4a9fbb95c0751f567bb Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 4 Dec 2015 15:15:16 +0100 Subject: Add sample for experimental composite geometry code --- samples/python/s018_experimental_multires.py | 84 ++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 samples/python/s018_experimental_multires.py (limited to 'samples') diff --git a/samples/python/s018_experimental_multires.py b/samples/python/s018_experimental_multires.py new file mode 100644 index 0000000..cf38e53 --- /dev/null +++ b/samples/python/s018_experimental_multires.py @@ -0,0 +1,84 @@ +#----------------------------------------------------------------------- +#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 . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np +from astra.experimental import do_composite_FP + +astra.log.setOutputScreen(astra.log.STDERR, astra.log.DEBUG) + +# low res part (voxels of 4x4x4) +vol_geom1 = astra.create_vol_geom(32, 16, 32, -64, 0, -64, 64, -64, 64) + +# high res part (voxels of 1x1x1) +vol_geom2 = astra.create_vol_geom(128, 64, 128, 0, 64, -64, 64, -64, 64) + + +# Split the output in two parts as well, for demonstration purposes +angles1 = np.linspace(0, np.pi/2, 90, False) +angles2 = np.linspace(np.pi/2, np.pi, 90, False) +proj_geom1 = astra.create_proj_geom('parallel3d', 1.0, 1.0, 128, 192, angles1) +proj_geom2 = astra.create_proj_geom('parallel3d', 1.0, 1.0, 128, 192, angles2) + +# Create a simple hollow cube phantom +cube1 = np.zeros((32,32,16)) +cube1[4:28,4:28,4:16] = 1 + +cube2 = np.zeros((128,128,64)) +cube2[16:112,16:112,0:112] = 1 +cube2[33:97,33:97,4:28] = 0 + +vol1 = astra.data3d.create('-vol', vol_geom1, cube1) +vol2 = astra.data3d.create('-vol', vol_geom2, cube2) + +proj1 = astra.data3d.create('-proj3d', proj_geom1, 0) +proj2 = astra.data3d.create('-proj3d', proj_geom2, 0) + +# The actual geometries don't matter for this composite FP/BP case +projector = astra.create_projector('cuda3d', proj_geom1, vol_geom1) + +do_composite_FP(projector, [vol1, vol2], [proj1, proj2]) + +proj_data1 = astra.data3d.get(proj1) +proj_data2 = astra.data3d.get(proj2) + +# Display a single projection image +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(proj_data1[:,0,:]) +pylab.figure(2) +pylab.imshow(proj_data2[:,0,:]) +pylab.show() + + +# Clean up. Note that GPU memory is tied up in the algorithm object, +# and main RAM in the data objects. +astra.data3d.delete(vol1) +astra.data3d.delete(vol2) +astra.data3d.delete(proj1) +astra.data3d.delete(proj2) +astra.projector3d.delete(projector) -- cgit v1.2.3