From 0f577d1fbc2b0c15d85f18cc38eb14e3cbf6c6a2 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Fri, 22 May 2015 14:36:42 +0200 Subject: Fix optomo reconstruction for 1D input --- python/astra/optomo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/astra') diff --git a/python/astra/optomo.py b/python/astra/optomo.py index 2937d9c..0108674 100644 --- a/python/astra/optomo.py +++ b/python/astra/optomo.py @@ -164,7 +164,7 @@ class OpTomo(scipy.sparse.linalg.LinearOperator): :param extraOptions: Extra options to use during reconstruction (i.e. for cfg['option']). :type extraOptions: :class:`dict` """ - self.__checkArray(s, self.sshape) + s = self.__checkArray(s, self.sshape) sid = self.data_mod.link('-sino',self.pg,s) v = np.zeros(self.vshape,dtype=np.float32) vid = self.data_mod.link('-vol',self.vg,v) -- cgit v1.2.3 From 26198f7e1fbed9d294fc2856f796f408c85b66f3 Mon Sep 17 00:00:00 2001 From: Valerii Sokolov Date: Tue, 9 Jun 2015 11:26:42 +0200 Subject: Don't take address of temporary. --- python/astra/utils.pyx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'python/astra') diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx index ddb37aa..a8e9e4e 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -95,7 +95,8 @@ cdef void readDict(XMLNode root, _dc): if val.size == 0: break listbase = root.addChildNode(item) - data = np.PyArray_DATA(np.ascontiguousarray(val,dtype=np.float64)) + contig_data = np.ascontiguousarray(val,dtype=np.float64) + data = np.PyArray_DATA(contig_data) if val.ndim == 2: listbase.setContent(data, val.shape[1], val.shape[0], False) elif val.ndim == 1: @@ -129,7 +130,8 @@ cdef void readOptions(XMLNode node, dc): break listbase = node.addChildNode(six.b('Option')) listbase.addAttribute(< string > six.b('key'), < string > item) - data = np.PyArray_DATA(np.ascontiguousarray(val,dtype=np.float64)) + contig_data = np.ascontiguousarray(val,dtype=np.float64) + data = np.PyArray_DATA(contig_data) if val.ndim == 2: listbase.setContent(data, val.shape[1], val.shape[0], False) elif val.ndim == 1: -- cgit v1.2.3 From 63d78fbaafa7d247347f9052db86f575d89260b7 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Wed, 24 Jun 2015 20:28:46 +0200 Subject: Fix config to struct/dict translation for array options --- python/astra/utils.pyx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'python/astra') diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx index a8e9e4e..260c308 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -204,7 +204,10 @@ cdef XMLNode2dict(XMLNode node): while it != nodes.end(): subnode = deref(it) if castString(subnode.getName())=="Option": - opts[castString(subnode.getAttribute('key'))] = stringToPythonValue(subnode.getAttribute('value')) + if subnode.hasAttribute('value'): + opts[castString(subnode.getAttribute('key'))] = stringToPythonValue(subnode.getAttribute('value')) + else: + opts[castString(subnode.getAttribute('key'))] = stringToPythonValue(subnode.getContent()) else: dct[castString(subnode.getName())] = stringToPythonValue(subnode.getContent()) inc(it) -- cgit v1.2.3 From 9e3472ea9041b8755050427d8bdb8a4701019c55 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Thu, 25 Jun 2015 21:52:07 +0200 Subject: Fix memory leak in configuration code --- python/astra/projector3d_c.pyx | 10 ++++++++-- python/astra/projector_c.pyx | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'python/astra') diff --git a/python/astra/projector3d_c.pyx b/python/astra/projector3d_c.pyx index 8b978d7..aec9cde 100644 --- a/python/astra/projector3d_c.pyx +++ b/python/astra/projector3d_c.pyx @@ -87,12 +87,18 @@ cdef CProjector3D * getObject(i) except NULL: def projection_geometry(i): cdef CProjector3D * proj = getObject(i) - return utils.configToDict(proj.getProjectionGeometry().getConfiguration()) + cdef Config * cfg = proj.getProjectionGeometry().getConfiguration() + dct = utils.configToDict(cfg) + del cfg + return dct def volume_geometry(i): cdef CProjector3D * proj = getObject(i) - return utils.configToDict(proj.getVolumeGeometry().getConfiguration()) + cdef Config * cfg = proj.getVolumeGeometry().getConfiguration() + dct = utils.configToDict(cfg) + del cfg + return dct def weights_single_ray(i, projection_index, detector_index): diff --git a/python/astra/projector_c.pyx b/python/astra/projector_c.pyx index 9aa868e..77c64a4 100644 --- a/python/astra/projector_c.pyx +++ b/python/astra/projector_c.pyx @@ -91,12 +91,18 @@ cdef CProjector2D * getObject(i) except NULL: def projection_geometry(i): cdef CProjector2D * proj = getObject(i) - return utils.configToDict(proj.getProjectionGeometry().getConfiguration()) + cdef Config * cfg = proj.getProjectionGeometry().getConfiguration() + dct = utils.configToDict(cfg) + del cfg + return dct def volume_geometry(i): cdef CProjector2D * proj = getObject(i) - return utils.configToDict(proj.getVolumeGeometry().getConfiguration()) + cdef Config * cfg = proj.getVolumeGeometry().getConfiguration() + dct = utils.configToDict(cfg) + del cfg + return dct def weights_single_ray(i, projection_index, detector_index): -- cgit v1.2.3 From 4d39c35d6c9124c26de64c9d227a25f612903a2a Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Fri, 17 Jul 2015 13:44:59 +0200 Subject: Fix formatting when passing strings to log from high-level code --- python/astra/log_c.pyx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'python/astra') diff --git a/python/astra/log_c.pyx b/python/astra/log_c.pyx index f16329f..55c63e6 100644 --- a/python/astra/log_c.pyx +++ b/python/astra/log_c.pyx @@ -53,19 +53,19 @@ cdef extern from "astra/Logging.h" namespace "astra::CLogger": def log_debug(sfile, sline, message): cstr = list(map(six.b,(sfile,message))) - debug(cstr[0],sline,cstr[1]) + debug(cstr[0],sline,"%s",cstr[1]) def log_info(sfile, sline, message): cstr = list(map(six.b,(sfile,message))) - info(cstr[0],sline,cstr[1]) + info(cstr[0],sline,"%s",cstr[1]) def log_warn(sfile, sline, message): cstr = list(map(six.b,(sfile,message))) - warn(cstr[0],sline,cstr[1]) + warn(cstr[0],sline,"%s",cstr[1]) def log_error(sfile, sline, message): cstr = list(map(six.b,(sfile,message))) - error(cstr[0],sline,cstr[1]) + error(cstr[0],sline,"%s",cstr[1]) def log_enable(): enable() -- cgit v1.2.3 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 --- python/astra/__init__.py | 1 + python/astra/plugin.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++ python/astra/plugin_c.pyx | 59 +++++++++++++++++++++++++++++ python/astra/utils.pyx | 72 +++-------------------------------- 4 files changed, 160 insertions(+), 67 deletions(-) create mode 100644 python/astra/plugin.py create mode 100644 python/astra/plugin_c.pyx (limited to 'python/astra') diff --git a/python/astra/__init__.py b/python/astra/__init__.py index 6c15d30..10ed74d 100644 --- a/python/astra/__init__.py +++ b/python/astra/__init__.py @@ -34,6 +34,7 @@ from . import algorithm from . import projector from . import projector3d from . import matrix +from . import plugin from . import log from .optomo import OpTomo diff --git a/python/astra/plugin.py b/python/astra/plugin.py new file mode 100644 index 0000000..ccdb2cb --- /dev/null +++ b/python/astra/plugin.py @@ -0,0 +1,95 @@ +#----------------------------------------------------------------------- +#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 . +# +#----------------------------------------------------------------------- + +from . import plugin_c as p +from . import log + +class base(object): + + def astra_init(self, cfg): + try: + try: + req = self.required_options + except AttributeError: + log.warn("Plugin '" + self.__class__.__name__ + "' does not specify required options") + req = {} + + try: + opt = self.optional_options + except AttributeError: + log.warn("Plugin '" + self.__class__.__name__ + "' does not specify optional options") + opt = {} + + try: + optDict = cfg['options'] + except KeyError: + optDict = {} + + cfgKeys = set(optDict.keys()) + reqKeys = set(req) + optKeys = set(opt) + + if not reqKeys.issubset(cfgKeys): + for key in reqKeys.difference(cfgKeys): + log.error("Required option '" + key + "' for plugin '" + self.__class__.__name__ + "' not specified") + raise ValueError("Missing required options") + + if not cfgKeys.issubset(reqKeys | optKeys): + log.warn(self.__class__.__name__ + ": unused configuration option: " + str(list(cfgKeys.difference(reqKeys | optKeys)))) + + self.initialize(cfg) + except Exception as e: + log.error(str(e)) + raise + +def register(name, className): + """Register plugin with ASTRA. + + :param name: Plugin name to register + :type name: :class:`str` + :param className: Class name or class object to register + :type className: :class:`str` or :class:`class` + + """ + p.register(name,className) + +def get_registered(): + """Get dictionary of registered plugins. + + :returns: :class:`dict` -- Registered plugins. + + """ + return p.get_registered() + +def get_help(name): + """Get help for registered plugin. + + :param name: Plugin name to get help for + :type name: :class:`str` + :returns: :class:`str` -- Help string (docstring). + + """ + return p.get_help(name) \ No newline at end of file diff --git a/python/astra/plugin_c.pyx b/python/astra/plugin_c.pyx new file mode 100644 index 0000000..91b3cd5 --- /dev/null +++ b/python/astra/plugin_c.pyx @@ -0,0 +1,59 @@ +#----------------------------------------------------------------------- +#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 . +# +#----------------------------------------------------------------------- +# distutils: language = c++ +# distutils: libraries = astra + +import six +import inspect + +from libcpp.string cimport string +from libcpp cimport bool + +cdef CPluginAlgorithmFactory *fact = getSingletonPtr() + +from . import utils + +cdef extern from "astra/PluginAlgorithm.h" namespace "astra": + cdef cppclass CPluginAlgorithmFactory: + bool registerPlugin(string name, string className) + bool registerPluginClass(string name, object className) + object getRegistered() + string getHelp(string name) + +cdef extern from "astra/PluginAlgorithm.h" namespace "astra::CPluginAlgorithmFactory": + cdef CPluginAlgorithmFactory* getSingletonPtr() + +def register(name, className): + if inspect.isclass(className): + fact.registerPluginClass(six.b(name), className) + else: + fact.registerPlugin(six.b(name), six.b(className)) + +def get_registered(): + return fact.getRegistered() + +def get_help(name): + return utils.wrap_from_bytes(fact.getHelp(six.b(name))) diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx index ddb37aa..3746b8e 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -30,7 +30,6 @@ cimport numpy as np 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, preincrement as inc from cpython.version cimport PY_MAJOR_VERSION @@ -40,6 +39,9 @@ from .PyXMLDocument cimport XMLDocument from .PyXMLDocument cimport XMLNode from .PyIncludes cimport * +cdef extern from "astra/PluginAlgorithm.h" namespace "astra": + object XMLNode2dict(XMLNode) + cdef Config * dictToConfig(string rootname, dc): cdef Config * cfg = new Config() @@ -91,6 +93,8 @@ cdef void readDict(XMLNode root, _dc): dc = convert_item(_dc) for item in dc: val = dc[item] + if isinstance(val, list): + val = np.array(val,dtype=np.float64) if isinstance(val, np.ndarray): if val.size == 0: break @@ -142,69 +146,3 @@ cdef void readOptions(XMLNode node, dc): cdef configToDict(Config *cfg): return XMLNode2dict(cfg.self) -def castString3(input): - return input.decode('utf-8') - -def castString2(input): - return input - -if six.PY3: - castString = castString3 -else: - castString = castString2 - -def stringToPythonValue(inputIn): - input = castString(inputIn) - # matrix - if ';' in input: - row_strings = input.split(';') - col_strings = row_strings[0].split(',') - nRows = len(row_strings) - nCols = len(col_strings) - - out = np.empty((nRows,nCols)) - for ridx, row in enumerate(row_strings): - col_strings = row.split(',') - for cidx, col in enumerate(col_strings): - out[ridx,cidx] = float(col) - return out - - # vector - if ',' in input: - items = input.split(',') - out = np.empty(len(items)) - for idx,item in enumerate(items): - out[idx] = float(item) - return out - - try: - # integer - return int(input) - except ValueError: - try: - #float - return float(input) - except ValueError: - # string - return str(input) - - -cdef XMLNode2dict(XMLNode node): - cdef XMLNode subnode - cdef list[XMLNode] nodes - cdef list[XMLNode].iterator it - dct = {} - opts = {} - if node.hasAttribute(six.b('type')): - dct['type'] = castString(node.getAttribute(six.b('type'))) - nodes = node.getNodes() - it = nodes.begin() - while it != nodes.end(): - subnode = deref(it) - if castString(subnode.getName())=="Option": - opts[castString(subnode.getAttribute('key'))] = stringToPythonValue(subnode.getAttribute('value')) - else: - dct[castString(subnode.getName())] = stringToPythonValue(subnode.getContent()) - inc(it) - if len(opts)>0: dct['options'] = opts - return dct -- 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 --- python/astra/plugin.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'python/astra') diff --git a/python/astra/plugin.py b/python/astra/plugin.py index ccdb2cb..891f6c9 100644 --- a/python/astra/plugin.py +++ b/python/astra/plugin.py @@ -26,22 +26,20 @@ from . import plugin_c as p from . import log +import inspect class base(object): def astra_init(self, cfg): try: - try: - req = self.required_options - except AttributeError: - log.warn("Plugin '" + self.__class__.__name__ + "' does not specify required options") - req = {} - - try: - opt = self.optional_options - except AttributeError: - log.warn("Plugin '" + self.__class__.__name__ + "' does not specify optional options") - opt = {} + args, varargs, varkw, defaults = inspect.getargspec(self.initialize) + nopt = len(defaults) + if nopt>0: + req = args[2:-nopt] + opt = args[-nopt:] + else: + req = args[2:] + opt = [] try: optDict = cfg['options'] @@ -60,7 +58,9 @@ class base(object): if not cfgKeys.issubset(reqKeys | optKeys): log.warn(self.__class__.__name__ + ": unused configuration option: " + str(list(cfgKeys.difference(reqKeys | optKeys)))) - self.initialize(cfg) + args = [optDict[k] for k in req] + kwargs = dict((k,optDict[k]) for k in opt if k in optDict) + self.initialize(cfg, *args, **kwargs) except Exception as e: log.error(str(e)) raise -- cgit v1.2.3 From 385865d6ad7a54ee294b4086d4679747f49cff2e Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Wed, 24 Jun 2015 21:04:22 +0200 Subject: Fix passing a python list as option --- python/astra/utils.pyx | 2 ++ 1 file changed, 2 insertions(+) (limited to 'python/astra') diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx index 3746b8e..08ee67b 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -128,6 +128,8 @@ cdef void readOptions(XMLNode node, dc): val = dc[item] if node.hasOption(item): raise Exception('Duplicate Option: %s' % item) + if isinstance(val, list): + val = np.array(val,dtype=np.float64) if isinstance(val, np.ndarray): if val.size == 0: break -- cgit v1.2.3 From edae78481cf0e9cbffe335de1e541821758c5da1 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Wed, 24 Jun 2015 21:36:04 +0200 Subject: Log error when running Python plugin algorithm --- python/astra/plugin.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'python/astra') diff --git a/python/astra/plugin.py b/python/astra/plugin.py index 891f6c9..bbbc450 100644 --- a/python/astra/plugin.py +++ b/python/astra/plugin.py @@ -65,6 +65,13 @@ class base(object): log.error(str(e)) raise + def astra_run(self, its): + try: + self.run(its) + except Exception as e: + log.error(str(e)) + raise + def register(name, className): """Register plugin with ASTRA. -- cgit v1.2.3 From 58af62f543bbb0e66247a37dae36698d9fa5d338 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Thu, 9 Jul 2015 23:13:44 +0200 Subject: Allow plugins without keywords --- python/astra/plugin.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'python/astra') diff --git a/python/astra/plugin.py b/python/astra/plugin.py index bbbc450..be5c155 100644 --- a/python/astra/plugin.py +++ b/python/astra/plugin.py @@ -33,7 +33,10 @@ class base(object): def astra_init(self, cfg): try: args, varargs, varkw, defaults = inspect.getargspec(self.initialize) - nopt = len(defaults) + if not defaults is None: + nopt = len(defaults) + else: + nopt = 0 if nopt>0: req = args[2:-nopt] opt = args[-nopt:] -- cgit v1.2.3 From c4d227e4d8fd8809fb3c3bded5540cc1e82746ef Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Fri, 10 Jul 2015 00:23:18 +0200 Subject: Show more useful information when a plugin raises an exception --- python/astra/plugin.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'python/astra') diff --git a/python/astra/plugin.py b/python/astra/plugin.py index be5c155..f8fc3bd 100644 --- a/python/astra/plugin.py +++ b/python/astra/plugin.py @@ -27,6 +27,7 @@ from . import plugin_c as p from . import log import inspect +import traceback class base(object): @@ -64,15 +65,15 @@ class base(object): args = [optDict[k] for k in req] kwargs = dict((k,optDict[k]) for k in opt if k in optDict) self.initialize(cfg, *args, **kwargs) - except Exception as e: - log.error(str(e)) + except Exception: + log.error(traceback.format_exc().replace("%","%%")) raise def astra_run(self, its): try: self.run(its) - except Exception as e: - log.error(str(e)) + except Exception: + log.error(traceback.format_exc().replace("%","%%")) raise def register(name, className): -- cgit v1.2.3 From f79f072b9bbc5719fbfa3d5c75e886a2bbb7f1ce Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Fri, 10 Jul 2015 00:30:23 +0200 Subject: Also allow tuples to be passed in a config dict --- python/astra/utils.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python/astra') diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx index 08ee67b..9d2e9ab 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -93,7 +93,7 @@ cdef void readDict(XMLNode root, _dc): dc = convert_item(_dc) for item in dc: val = dc[item] - if isinstance(val, list): + if isinstance(val, list) or isinstance(val, tuple): val = np.array(val,dtype=np.float64) if isinstance(val, np.ndarray): if val.size == 0: @@ -128,7 +128,7 @@ cdef void readOptions(XMLNode node, dc): val = dc[item] if node.hasOption(item): raise Exception('Duplicate Option: %s' % item) - if isinstance(val, list): + if isinstance(val, list) or isinstance(val, tuple): val = np.array(val,dtype=np.float64) if isinstance(val, np.ndarray): if val.size == 0: -- 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 --- python/astra/plugin.py | 71 +++++++++++++++++++---------------------------- python/astra/plugin_c.pyx | 14 ++++++++-- 2 files changed, 40 insertions(+), 45 deletions(-) (limited to 'python/astra') diff --git a/python/astra/plugin.py b/python/astra/plugin.py index f8fc3bd..4b32e6e 100644 --- a/python/astra/plugin.py +++ b/python/astra/plugin.py @@ -32,60 +32,47 @@ import traceback class base(object): def astra_init(self, cfg): - try: - args, varargs, varkw, defaults = inspect.getargspec(self.initialize) - if not defaults is None: - nopt = len(defaults) - else: - nopt = 0 - if nopt>0: - req = args[2:-nopt] - opt = args[-nopt:] - else: - req = args[2:] - opt = [] + args, varargs, varkw, defaults = inspect.getargspec(self.initialize) + if not defaults is None: + nopt = len(defaults) + else: + nopt = 0 + if nopt>0: + req = args[2:-nopt] + opt = args[-nopt:] + else: + req = args[2:] + opt = [] - try: - optDict = cfg['options'] - except KeyError: - optDict = {} + try: + optDict = cfg['options'] + except KeyError: + optDict = {} - cfgKeys = set(optDict.keys()) - reqKeys = set(req) - optKeys = set(opt) + cfgKeys = set(optDict.keys()) + reqKeys = set(req) + optKeys = set(opt) - if not reqKeys.issubset(cfgKeys): - for key in reqKeys.difference(cfgKeys): - log.error("Required option '" + key + "' for plugin '" + self.__class__.__name__ + "' not specified") - raise ValueError("Missing required options") + if not reqKeys.issubset(cfgKeys): + for key in reqKeys.difference(cfgKeys): + log.error("Required option '" + key + "' for plugin '" + self.__class__.__name__ + "' not specified") + raise ValueError("Missing required options") - if not cfgKeys.issubset(reqKeys | optKeys): - log.warn(self.__class__.__name__ + ": unused configuration option: " + str(list(cfgKeys.difference(reqKeys | optKeys)))) + if not cfgKeys.issubset(reqKeys | optKeys): + log.warn(self.__class__.__name__ + ": unused configuration option: " + str(list(cfgKeys.difference(reqKeys | optKeys)))) - args = [optDict[k] for k in req] - kwargs = dict((k,optDict[k]) for k in opt if k in optDict) - self.initialize(cfg, *args, **kwargs) - except Exception: - log.error(traceback.format_exc().replace("%","%%")) - raise + args = [optDict[k] for k in req] + kwargs = dict((k,optDict[k]) for k in opt if k in optDict) + self.initialize(cfg, *args, **kwargs) - def astra_run(self, its): - try: - self.run(its) - except Exception: - log.error(traceback.format_exc().replace("%","%%")) - raise - -def register(name, className): +def register(className): """Register plugin with ASTRA. - :param name: Plugin name to register - :type name: :class:`str` :param className: Class name or class object to register :type className: :class:`str` or :class:`class` """ - p.register(name,className) + p.register(className) def get_registered(): """Get dictionary of registered plugins. diff --git a/python/astra/plugin_c.pyx b/python/astra/plugin_c.pyx index 91b3cd5..8d6816b 100644 --- a/python/astra/plugin_c.pyx +++ b/python/astra/plugin_c.pyx @@ -38,7 +38,9 @@ from . import utils cdef extern from "astra/PluginAlgorithm.h" namespace "astra": cdef cppclass CPluginAlgorithmFactory: + bool registerPlugin(string className) bool registerPlugin(string name, string className) + bool registerPluginClass(object className) bool registerPluginClass(string name, object className) object getRegistered() string getHelp(string name) @@ -46,11 +48,17 @@ cdef extern from "astra/PluginAlgorithm.h" namespace "astra": cdef extern from "astra/PluginAlgorithm.h" namespace "astra::CPluginAlgorithmFactory": cdef CPluginAlgorithmFactory* getSingletonPtr() -def register(name, className): +def register(className, name=None): if inspect.isclass(className): - fact.registerPluginClass(six.b(name), className) + if name==None: + fact.registerPluginClass(className) + else: + fact.registerPluginClass(six.b(name), className) else: - fact.registerPlugin(six.b(name), six.b(className)) + if name==None: + fact.registerPlugin(six.b(className)) + else: + fact.registerPlugin(six.b(name), six.b(className)) def get_registered(): return fact.getRegistered() -- cgit v1.2.3 From e509cd013f691acded3dc0d87732ba5257cb0ae4 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Mon, 20 Jul 2015 15:14:50 +0200 Subject: Add ReconstructionAlgorithm2D/3D classes for plugins (matching C++ classes) --- python/astra/PyIncludes.pxd | 2 ++ python/astra/data2d_c.pyx | 27 ++++++++++++++++++++++++++- python/astra/plugin.py | 27 +++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) (limited to 'python/astra') diff --git a/python/astra/PyIncludes.pxd b/python/astra/PyIncludes.pxd index 909f58f..a099c31 100644 --- a/python/astra/PyIncludes.pxd +++ b/python/astra/PyIncludes.pxd @@ -62,6 +62,7 @@ cdef extern from "astra/VolumeGeometry2D.h" namespace "astra": float32 getWindowMaxX() float32 getWindowMaxY() Config* getConfiguration() + bool isEqual(CVolumeGeometry2D*) cdef extern from "astra/Float32Data2D.h" namespace "astra": cdef cppclass CFloat32CustomMemory: @@ -89,6 +90,7 @@ cdef extern from "astra/ProjectionGeometry2D.h" namespace "astra": float32 getProjectionAngle(int) float32 getDetectorWidth() Config* getConfiguration() + bool isEqual(CProjectionGeometry2D*) cdef extern from "astra/Float32Data2D.h" namespace "astra::CFloat32Data2D": cdef enum TWOEDataType "astra::CFloat32Data2D::EDataType": diff --git a/python/astra/data2d_c.pyx b/python/astra/data2d_c.pyx index 4919bf2..801fd8e 100644 --- a/python/astra/data2d_c.pyx +++ b/python/astra/data2d_c.pyx @@ -34,6 +34,9 @@ from cython cimport view cimport PyData2DManager from .PyData2DManager cimport CData2DManager +cimport PyProjector2DManager +from .PyProjector2DManager cimport CProjector2DManager + cimport PyXMLDocument from .PyXMLDocument cimport XMLDocument @@ -54,6 +57,8 @@ import operator from six.moves import reduce cdef CData2DManager * man2d = PyData2DManager.getSingletonPtr() +cdef CProjector2DManager * manProj = PyProjector2DManager.getSingletonPtr() + cdef extern from "CFloat32CustomPython.h": cdef cppclass CFloat32CustomPython: @@ -164,7 +169,6 @@ def store(i, data): cdef CFloat32Data2D * pDataObject = getObject(i) fillDataObject(pDataObject, data) - def get_geometry(i): cdef CFloat32Data2D * pDataObject = getObject(i) cdef CFloat32ProjectionData2D * pDataObject2 @@ -179,6 +183,27 @@ def get_geometry(i): raise Exception("Not a known data object") return geom +cdef CProjector2D * getProjector(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 check_compatible(i, proj_id): + cdef CProjector2D * proj = getProjector(proj_id) + cdef CFloat32Data2D * pDataObject = getObject(i) + cdef CFloat32ProjectionData2D * pDataObject2 + cdef CFloat32VolumeData2D * pDataObject3 + if pDataObject.getType() == TWOPROJECTION: + pDataObject2 = pDataObject + return pDataObject2.getGeometry().isEqual(proj.getProjectionGeometry()) + elif pDataObject.getType() == TWOVOLUME: + pDataObject3 = pDataObject + return pDataObject3.getGeometry().isEqual(proj.getVolumeGeometry()) + else: + raise Exception("Not a known data object") def change_geometry(i, geom): cdef Config *cfg diff --git a/python/astra/plugin.py b/python/astra/plugin.py index 4b32e6e..11cc5cc 100644 --- a/python/astra/plugin.py +++ b/python/astra/plugin.py @@ -26,6 +26,10 @@ from . import plugin_c as p from . import log +from . import data2d +from . import data2d_c +from . import data3d +from . import projector import inspect import traceback @@ -65,6 +69,29 @@ class base(object): kwargs = dict((k,optDict[k]) for k in opt if k in optDict) self.initialize(cfg, *args, **kwargs) +class ReconstructionAlgorithm2D(base): + + def astra_init(self, cfg): + self.pid = cfg['ProjectorId'] + self.s = data2d.get_shared(cfg['ProjectionDataId']) + self.v = data2d.get_shared(cfg['ReconstructionDataId']) + self.vg = projector.volume_geometry(self.pid) + self.pg = projector.projection_geometry(self.pid) + if not data2d_c.check_compatible(cfg['ProjectionDataId'], self.pid): + raise ValueError("Projection data and projector not compatible") + if not data2d_c.check_compatible(cfg['ReconstructionDataId'], self.pid): + raise ValueError("Reconstruction data and projector not compatible") + super(ReconstructionAlgorithm2D,self).astra_init(cfg) + +class ReconstructionAlgorithm3D(base): + + def astra_init(self, cfg): + self.s = data3d.get_shared(cfg['ProjectionDataId']) + self.v = data3d.get_shared(cfg['ReconstructionDataId']) + self.vg = data3d.get_geometry(cfg['ReconstructionDataId']) + self.pg = data3d.get_geometry(cfg['ProjectionDataId']) + super(ReconstructionAlgorithm3D,self).astra_init(cfg) + def register(className): """Register plugin with ASTRA. -- cgit v1.2.3 From 14ce794a1654f82fe8ac414e56e842242bece729 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Tue, 21 Jul 2015 13:51:50 +0200 Subject: Also use ProjectorId in ReconstructionAlgorithm3D plugin base --- python/astra/plugin.py | 1 + 1 file changed, 1 insertion(+) (limited to 'python/astra') diff --git a/python/astra/plugin.py b/python/astra/plugin.py index 11cc5cc..3e3528d 100644 --- a/python/astra/plugin.py +++ b/python/astra/plugin.py @@ -86,6 +86,7 @@ class ReconstructionAlgorithm2D(base): class ReconstructionAlgorithm3D(base): def astra_init(self, cfg): + self.pid = cfg['ProjectorId'] self.s = data3d.get_shared(cfg['ProjectionDataId']) self.v = data3d.get_shared(cfg['ReconstructionDataId']) self.vg = data3d.get_geometry(cfg['ReconstructionDataId']) -- cgit v1.2.3 From 43155c03488ca98c24f8f369e5c8699efa20cca3 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Thu, 30 Jul 2015 15:28:16 +0200 Subject: Fix Python OpTomo for scipy 0.16 scipy 0.16 also uses .T to define a transpose, which conflicts with the old OpTomo implementation. OpTomo now also defines the _transpose() method, which .T will call in scipy 0.16. --- python/astra/optomo.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'python/astra') diff --git a/python/astra/optomo.py b/python/astra/optomo.py index 0108674..19b07e3 100644 --- a/python/astra/optomo.py +++ b/python/astra/optomo.py @@ -86,7 +86,15 @@ class OpTomo(scipy.sparse.linalg.LinearOperator): self.proj_id = proj_id - self.T = OpTomoTranspose(self) + self.transposeOpTomo = OpTomoTranspose(self) + try: + self.T = self.transposeOpTomo + except AttributeError: + # Scipy >= 0.16 defines self.T using self._transpose() + pass + + def _transpose(self): + return self.transposeOpTomo def __checkArray(self, arr, shp): if len(arr.shape)==1: -- cgit v1.2.3 From b4bd441549ea71dd6c34a9f2158bbebc39ba4e9e Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Thu, 30 Jul 2015 15:34:10 +0200 Subject: Define a transpose for the OpTomo transpose as well Allows for chaining .T calls. --- python/astra/optomo.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'python/astra') diff --git a/python/astra/optomo.py b/python/astra/optomo.py index 19b07e3..4a64150 100644 --- a/python/astra/optomo.py +++ b/python/astra/optomo.py @@ -197,6 +197,11 @@ class OpTomoTranspose(scipy.sparse.linalg.LinearOperator): self.parent = parent self.dtype = np.float32 self.shape = (parent.shape[1], parent.shape[0]) + try: + self.T = self.parent + except AttributeError: + # Scipy >= 0.16 defines self.T using self._transpose() + pass def _matvec(self, s): return self.parent.rmatvec(s) @@ -204,6 +209,9 @@ class OpTomoTranspose(scipy.sparse.linalg.LinearOperator): def rmatvec(self, v): return self.parent.matvec(v) + def _transpose(self): + return self.parent + def __mul__(self,s): # Catch the case of a backprojection of 2D/3D data if isinstance(s, np.ndarray) and s.shape==self.parent.sshape: -- cgit v1.2.3 From ee790c305942675e94ee66bfd24896d1ef61335a Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Mon, 10 Aug 2015 16:22:19 +0200 Subject: Release the gil in algorithm.run --- python/astra/PyIncludes.pxd | 2 +- python/astra/algorithm_c.pyx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'python/astra') diff --git a/python/astra/PyIncludes.pxd b/python/astra/PyIncludes.pxd index 909f58f..35dea5f 100644 --- a/python/astra/PyIncludes.pxd +++ b/python/astra/PyIncludes.pxd @@ -143,7 +143,7 @@ cdef extern from "astra/Float32ProjectionData2D.h" namespace "astra": cdef extern from "astra/Algorithm.h" namespace "astra": cdef cppclass CAlgorithm: bool initialize(Config) - void run(int) + void run(int) nogil bool isInitialized() cdef extern from "astra/ReconstructionAlgorithm2D.h" namespace "astra": diff --git a/python/astra/algorithm_c.pyx b/python/astra/algorithm_c.pyx index 966d3d7..3231c1f 100644 --- a/python/astra/algorithm_c.pyx +++ b/python/astra/algorithm_c.pyx @@ -73,7 +73,9 @@ cdef CAlgorithm * getAlg(i) except NULL: def run(i, iterations=0): cdef CAlgorithm * alg = getAlg(i) - alg.run(iterations) + cdef int its = iterations + with nogil: + alg.run(its) def get_res_norm(i): -- cgit v1.2.3 From c39b12fc42a7254bad1e68cbdb948eee0421ad81 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 16 Sep 2015 16:44:10 +0200 Subject: Let astra_create_vol_geom also generate flexible volume geometries --- python/astra/creators.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'python/astra') diff --git a/python/astra/creators.py b/python/astra/creators.py index 68bc8a2..f3474d8 100644 --- a/python/astra/creators.py +++ b/python/astra/creators.py @@ -72,6 +72,10 @@ This method can be called in a number of ways: ``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, minx, maxx, miny, maxy, minz, maxz)``: + :returns: A 3D volume geometry of size :math:`M \\times N \\times Z`, windowed as :math:`minx \\leq x \\leq maxx` and :math:`miny \\leq y \\leq maxy` and :math:`minz \\leq z \\leq maxz` . + + """ vol_geom = {'option': {}} # astra_create_vol_geom(row_count) @@ -122,6 +126,17 @@ This method can be called in a number of ways: vol_geom['GridRowCount'] = varargin[0] vol_geom['GridColCount'] = varargin[1] vol_geom['GridSliceCount'] = varargin[2] + # astra_create_vol_geom(row_count, col_count, slice_count, min_x, max_x, min_y, max_y, min_z, max_z) + elif len(varargin) == 9: + vol_geom['GridRowCount'] = varargin[0] + vol_geom['GridColCount'] = varargin[1] + vol_geom['GridSliceCount'] = varargin[2] + vol_geom['option']['WindowMinX'] = varargin[3] + vol_geom['option']['WindowMaxX'] = varargin[4] + vol_geom['option']['WindowMinY'] = varargin[5] + vol_geom['option']['WindowMaxY'] = varargin[6] + vol_geom['option']['WindowMinZ'] = varargin[7] + vol_geom['option']['WindowMaxZ'] = varargin[8] return vol_geom -- cgit v1.2.3 From 4621453bb753f17614b8ac4b6314a142ecbe278c Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 3 Dec 2015 15:14:25 +0100 Subject: Reduce dependency of python code on libastra --- python/astra/utils.pyx | 82 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 5 deletions(-) (limited to 'python/astra') diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx index 9871ac6..07727ce 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -29,8 +29,13 @@ cimport numpy as np import numpy as np import six +if six.PY3: + import builtins +else: + import __builtin__ from libcpp.string cimport string from libcpp.vector cimport vector +from libcpp.list cimport list from cython.operator cimport dereference as deref, preincrement as inc from cpython.version cimport PY_MAJOR_VERSION @@ -39,9 +44,6 @@ from .PyXMLDocument cimport XMLDocument from .PyXMLDocument cimport XMLNode from .PyIncludes cimport * -cdef extern from "astra/PluginAlgorithm.h" namespace "astra": - object XMLNode2dict(XMLNode) - cdef Config * dictToConfig(string rootname, dc): cdef Config * cfg = new Config() @@ -93,7 +95,7 @@ cdef void readDict(XMLNode root, _dc): dc = convert_item(_dc) for item in dc: val = dc[item] - if isinstance(val, list) or isinstance(val, tuple): + if isinstance(val, __builtins__.list) or isinstance(val, tuple): val = np.array(val,dtype=np.float64) if isinstance(val, np.ndarray): if val.size == 0: @@ -129,7 +131,7 @@ cdef void readOptions(XMLNode node, dc): val = dc[item] if node.hasOption(item): raise Exception('Duplicate Option: %s' % item) - if isinstance(val, list) or isinstance(val, tuple): + if isinstance(val, __builtins__.list) or isinstance(val, tuple): val = np.array(val,dtype=np.float64) if isinstance(val, np.ndarray): if val.size == 0: @@ -149,3 +151,73 @@ cdef void readOptions(XMLNode node, dc): cdef configToDict(Config *cfg): return XMLNode2dict(cfg.self) + +def castString3(input): + return input.decode('utf-8') + +def castString2(input): + return input + +if six.PY3: + castString = castString3 +else: + castString = castString2 + +def stringToPythonValue(inputIn): + input = castString(inputIn) + # matrix + if ';' in input: + row_strings = input.split(';') + col_strings = row_strings[0].split(',') + nRows = len(row_strings) + nCols = len(col_strings) + + out = np.empty((nRows,nCols)) + for ridx, row in enumerate(row_strings): + col_strings = row.split(',') + for cidx, col in enumerate(col_strings): + out[ridx,cidx] = float(col) + return out + + # vector + if ',' in input: + items = input.split(',') + out = np.empty(len(items)) + for idx,item in enumerate(items): + out[idx] = float(item) + return out + + try: + # integer + return int(input) + except ValueError: + try: + #float + return float(input) + except ValueError: + # string + return str(input) + + +cdef XMLNode2dict(XMLNode node): + cdef XMLNode subnode + cdef list[XMLNode] nodes + cdef list[XMLNode].iterator it + dct = {} + opts = {} + if node.hasAttribute(six.b('type')): + dct['type'] = castString(node.getAttribute(six.b('type'))) + nodes = node.getNodes() + it = nodes.begin() + while it != nodes.end(): + subnode = deref(it) + if castString(subnode.getName())=="Option": + if subnode.hasAttribute('value'): + opts[castString(subnode.getAttribute('key'))] = stringToPythonValue(subnode.getAttribute('value')) + else: + opts[castString(subnode.getAttribute('key'))] = stringToPythonValue(subnode.getContent()) + else: + dct[castString(subnode.getName())] = stringToPythonValue(subnode.getContent()) + inc(it) + if len(opts)>0: dct['options'] = opts + return dct -- 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 --- python/astra/PyIncludes.pxd | 2 ++ python/astra/experimental.pyx | 84 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 python/astra/experimental.pyx (limited to 'python/astra') diff --git a/python/astra/PyIncludes.pxd b/python/astra/PyIncludes.pxd index 35dea5f..e9e2bdb 100644 --- a/python/astra/PyIncludes.pxd +++ b/python/astra/PyIncludes.pxd @@ -224,6 +224,7 @@ cdef extern from "astra/Float32VolumeData3DMemory.h" namespace "astra": int getRowCount() int getColCount() int getSliceCount() + bool isInitialized() @@ -255,6 +256,7 @@ cdef extern from "astra/Float32ProjectionData3DMemory.h" namespace "astra": int getDetectorColCount() int getDetectorRowCount() int getAngleCount() + bool isInitialized() cdef extern from "astra/Float32Data3D.h" namespace "astra": cdef cppclass CFloat32Data3D: diff --git a/python/astra/experimental.pyx b/python/astra/experimental.pyx new file mode 100644 index 0000000..da27504 --- /dev/null +++ b/python/astra/experimental.pyx @@ -0,0 +1,84 @@ +#----------------------------------------------------------------------- +# Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp +# 2014-2015, CWI, Amsterdam +# +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox +# +# This file is part of the ASTRA Toolbox. +# +# +# The ASTRA Toolbox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# The ASTRA Toolbox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +# distutils: language = c++ +# distutils: libraries = astra + +include "config.pxi" + +import six +from .PyIncludes cimport * +from libcpp.vector cimport vector + +cdef extern from "astra/CompositeGeometryManager.h" namespace "astra": + cdef cppclass CCompositeGeometryManager: + bool doFP(CProjector3D *, vector[CFloat32VolumeData3DMemory *], vector[CFloat32ProjectionData3DMemory *]) + bool doBP(CProjector3D *, vector[CFloat32VolumeData3DMemory *], vector[CFloat32ProjectionData3DMemory *]) + +cdef extern from *: + CFloat32VolumeData3DMemory * dynamic_cast_vol_mem "dynamic_cast" (CFloat32Data3D * ) except NULL + CFloat32ProjectionData3DMemory * dynamic_cast_proj_mem "dynamic_cast" (CFloat32Data3D * ) except NULL + +cimport PyProjector3DManager +from .PyProjector3DManager cimport CProjector3DManager +cimport PyData3DManager +from .PyData3DManager cimport CData3DManager + +cdef CProjector3DManager * manProj = PyProjector3DManager.getSingletonPtr() +cdef CData3DManager * man3d = PyData3DManager.getSingletonPtr() + +def do_composite(projector_id, vol_ids, proj_ids, t): + cdef vector[CFloat32VolumeData3DMemory *] vol + cdef CFloat32VolumeData3DMemory * pVolObject + cdef CFloat32ProjectionData3DMemory * pProjObject + for v in vol_ids: + pVolObject = dynamic_cast_vol_mem(man3d.get(v)) + if pVolObject == NULL: + raise Exception("Data object not found") + if not pVolObject.isInitialized(): + raise Exception("Data object not initialized properly") + vol.push_back(pVolObject) + cdef vector[CFloat32ProjectionData3DMemory *] proj + for v in proj_ids: + pProjObject = dynamic_cast_proj_mem(man3d.get(v)) + if pProjObject == NULL: + raise Exception("Data object not found") + if not pProjObject.isInitialized(): + raise Exception("Data object not initialized properly") + proj.push_back(pProjObject) + cdef CCompositeGeometryManager m + cdef CProjector3D * projector = manProj.get(projector_id) # may be NULL + if t == "FP": + if not m.doFP(projector, vol, proj): + raise Exception("Failed to perform FP") + else: + if not m.doBP(projector, vol, proj): + raise Exception("Failed to perform BP") + +def do_composite_FP(projector_id, vol_ids, proj_ids): + do_composite(projector_id, vol_ids, proj_ids, "FP") + +def do_composite_BP(projector_id, vol_ids, proj_ids): + do_composite(projector_id, vol_ids, proj_ids, "BP") -- cgit v1.2.3 From 7362fccf97014538320f79cd4b58fc69ab04d648 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 10 Dec 2015 15:11:04 +0100 Subject: Use less ambiguous letters for create_vol_geom docs --- python/astra/creators.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'python/astra') diff --git a/python/astra/creators.py b/python/astra/creators.py index f3474d8..bcacf00 100644 --- a/python/astra/creators.py +++ b/python/astra/creators.py @@ -57,23 +57,23 @@ 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((Y, X))``: + :returns: A 2D volume geometry of size :math:`Y \\times X`. -``create_vol_geom(M, N)``: - :returns: A 2D volume geometry of size :math:`M \\times N`. +``create_vol_geom(Y, X)``: + :returns: A 2D volume geometry of size :math:`Y \\times X`. -``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(Y, X, minx, maxx, miny, maxy)``: + :returns: A 2D volume geometry of size :math:`Y \\times X`, 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((Y, X, Z))``: + :returns: A 3D volume geometry of size :math:`Y \\times X \\times Z`. -``create_vol_geom(M, N, Z)``: - :returns: A 3D volume geometry of size :math:`M \\times N \\times Z`. +``create_vol_geom(Y, X, Z)``: + :returns: A 3D volume geometry of size :math:`Y \\times X \\times Z`. -``create_vol_geom(M, N, Z, minx, maxx, miny, maxy, minz, maxz)``: - :returns: A 3D volume geometry of size :math:`M \\times N \\times Z`, windowed as :math:`minx \\leq x \\leq maxx` and :math:`miny \\leq y \\leq maxy` and :math:`minz \\leq z \\leq maxz` . +``create_vol_geom(Y, X, Z, minx, maxx, miny, maxy, minz, maxz)``: + :returns: A 3D volume geometry of size :math:`Y \\times X \\times Z`, windowed as :math:`minx \\leq x \\leq maxx` and :math:`miny \\leq y \\leq maxy` and :math:`minz \\leq z \\leq maxz` . """ -- cgit v1.2.3 From 823bdc90b6d4ebf5acade43ad909805053c8974e Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 16 Dec 2015 18:09:38 +0100 Subject: Fix origin_det name in create_proj_geom docs --- python/astra/creators.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'python/astra') diff --git a/python/astra/creators.py b/python/astra/creators.py index bcacf00..18504ea 100644 --- a/python/astra/creators.py +++ b/python/astra/creators.py @@ -156,7 +156,7 @@ This method can be called in a number of ways: :returns: A parallel projection geometry. -``create_proj_geom('fanflat', det_width, det_count, angles, source_origin, source_det)``: +``create_proj_geom('fanflat', det_width, det_count, angles, source_origin, origin_det)``: :param det_width: Size of a detector pixel. :type det_width: :class:`float` @@ -165,7 +165,7 @@ This method can be called in a number of ways: :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 +:param origin_det: Position of the detector :returns: A fan-beam projection geometry. ``create_proj_geom('fanflat_vec', det_count, V)``: @@ -188,7 +188,7 @@ This method can be called in a number of ways: :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)``: +``create_proj_geom('cone', detector_spacing_x, detector_spacing_y, det_row_count, det_col_count, angles, source_origin, origin_det)``: :param detector_spacing_*: Distance between two adjacent detector pixels. :type detector_spacing_*: :class:`float` @@ -200,8 +200,8 @@ This method can be called in a number of ways: :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` +:param origin_det: Distance between the detector and origin. +:type origin_det: :class:`float` :returns: A cone-beam projection geometry. ``create_proj_geom('cone_vec', det_row_count, det_col_count, V)``: @@ -244,7 +244,7 @@ This method can be called in a number of ways: 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)') + raise Exception('not enough variables: astra_create_proj_geom(fanflat, det_width, det_count, angles, source_origin, origin_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: @@ -258,7 +258,7 @@ This method can be called in a number of ways: 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)') + 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, origin_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: -- cgit v1.2.3 From 62f66d27fc4d2b3c61e3f18ad14eeac742cb96ec Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 5 Jan 2016 16:32:26 +0100 Subject: Update credits --- python/astra/astra_c.pyx | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'python/astra') diff --git a/python/astra/astra_c.pyx b/python/astra/astra_c.pyx index 342a214..6b246b6 100644 --- a/python/astra/astra_c.pyx +++ b/python/astra/astra_c.pyx @@ -45,21 +45,19 @@ ELSE: 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)""") + six.print_("""The ASTRA Toolbox has been developed at the University of Antwerp and CWI, Amsterdam by + * Prof. dr. Joost Batenburg + * Prof. dr. Jan Sijbers + * Dr. Jeroen Bedorf + * Dr. Folkert Bleichrodt + * Dr. Andrei Dabravolski + * Dr. Willem Jan Palenstijn + * Dr. Tom Roelandts + * Dr. Wim van Aarle + * Dr. Gert Van Gompel + * Sander van der Maar, MSc. + * Gert Merckx, MSc. + * Daan Pelt, MSc.""") def use_cuda(): -- cgit v1.2.3 From bf01d83ac9e57aacbc5d0a99d026327a7239c501 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Tue, 19 Jan 2016 13:24:03 +0100 Subject: Fix experimental.pyx for non-CUDA compilation --- python/astra/experimental.pyx | 96 ++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 47 deletions(-) (limited to 'python/astra') diff --git a/python/astra/experimental.pyx b/python/astra/experimental.pyx index da27504..aafc002 100644 --- a/python/astra/experimental.pyx +++ b/python/astra/experimental.pyx @@ -28,57 +28,59 @@ include "config.pxi" -import six -from .PyIncludes cimport * -from libcpp.vector cimport vector +IF HAVE_CUDA==True: -cdef extern from "astra/CompositeGeometryManager.h" namespace "astra": - cdef cppclass CCompositeGeometryManager: - bool doFP(CProjector3D *, vector[CFloat32VolumeData3DMemory *], vector[CFloat32ProjectionData3DMemory *]) - bool doBP(CProjector3D *, vector[CFloat32VolumeData3DMemory *], vector[CFloat32ProjectionData3DMemory *]) + import six + from .PyIncludes cimport * + from libcpp.vector cimport vector -cdef extern from *: - CFloat32VolumeData3DMemory * dynamic_cast_vol_mem "dynamic_cast" (CFloat32Data3D * ) except NULL - CFloat32ProjectionData3DMemory * dynamic_cast_proj_mem "dynamic_cast" (CFloat32Data3D * ) except NULL + cdef extern from "astra/CompositeGeometryManager.h" namespace "astra": + cdef cppclass CCompositeGeometryManager: + bool doFP(CProjector3D *, vector[CFloat32VolumeData3DMemory *], vector[CFloat32ProjectionData3DMemory *]) + bool doBP(CProjector3D *, vector[CFloat32VolumeData3DMemory *], vector[CFloat32ProjectionData3DMemory *]) -cimport PyProjector3DManager -from .PyProjector3DManager cimport CProjector3DManager -cimport PyData3DManager -from .PyData3DManager cimport CData3DManager + cdef extern from *: + CFloat32VolumeData3DMemory * dynamic_cast_vol_mem "dynamic_cast" (CFloat32Data3D * ) except NULL + CFloat32ProjectionData3DMemory * dynamic_cast_proj_mem "dynamic_cast" (CFloat32Data3D * ) except NULL -cdef CProjector3DManager * manProj = PyProjector3DManager.getSingletonPtr() -cdef CData3DManager * man3d = PyData3DManager.getSingletonPtr() + cimport PyProjector3DManager + from .PyProjector3DManager cimport CProjector3DManager + cimport PyData3DManager + from .PyData3DManager cimport CData3DManager -def do_composite(projector_id, vol_ids, proj_ids, t): - cdef vector[CFloat32VolumeData3DMemory *] vol - cdef CFloat32VolumeData3DMemory * pVolObject - cdef CFloat32ProjectionData3DMemory * pProjObject - for v in vol_ids: - pVolObject = dynamic_cast_vol_mem(man3d.get(v)) - if pVolObject == NULL: - raise Exception("Data object not found") - if not pVolObject.isInitialized(): - raise Exception("Data object not initialized properly") - vol.push_back(pVolObject) - cdef vector[CFloat32ProjectionData3DMemory *] proj - for v in proj_ids: - pProjObject = dynamic_cast_proj_mem(man3d.get(v)) - if pProjObject == NULL: - raise Exception("Data object not found") - if not pProjObject.isInitialized(): - raise Exception("Data object not initialized properly") - proj.push_back(pProjObject) - cdef CCompositeGeometryManager m - cdef CProjector3D * projector = manProj.get(projector_id) # may be NULL - if t == "FP": - if not m.doFP(projector, vol, proj): - raise Exception("Failed to perform FP") - else: - if not m.doBP(projector, vol, proj): - raise Exception("Failed to perform BP") + cdef CProjector3DManager * manProj = PyProjector3DManager.getSingletonPtr() + cdef CData3DManager * man3d = PyData3DManager.getSingletonPtr() -def do_composite_FP(projector_id, vol_ids, proj_ids): - do_composite(projector_id, vol_ids, proj_ids, "FP") + def do_composite(projector_id, vol_ids, proj_ids, t): + cdef vector[CFloat32VolumeData3DMemory *] vol + cdef CFloat32VolumeData3DMemory * pVolObject + cdef CFloat32ProjectionData3DMemory * pProjObject + for v in vol_ids: + pVolObject = dynamic_cast_vol_mem(man3d.get(v)) + if pVolObject == NULL: + raise Exception("Data object not found") + if not pVolObject.isInitialized(): + raise Exception("Data object not initialized properly") + vol.push_back(pVolObject) + cdef vector[CFloat32ProjectionData3DMemory *] proj + for v in proj_ids: + pProjObject = dynamic_cast_proj_mem(man3d.get(v)) + if pProjObject == NULL: + raise Exception("Data object not found") + if not pProjObject.isInitialized(): + raise Exception("Data object not initialized properly") + proj.push_back(pProjObject) + cdef CCompositeGeometryManager m + cdef CProjector3D * projector = manProj.get(projector_id) # may be NULL + if t == "FP": + if not m.doFP(projector, vol, proj): + raise Exception("Failed to perform FP") + else: + if not m.doBP(projector, vol, proj): + raise Exception("Failed to perform BP") -def do_composite_BP(projector_id, vol_ids, proj_ids): - do_composite(projector_id, vol_ids, proj_ids, "BP") + def do_composite_FP(projector_id, vol_ids, proj_ids): + do_composite(projector_id, vol_ids, proj_ids, "FP") + + def do_composite_BP(projector_id, vol_ids, proj_ids): + do_composite(projector_id, vol_ids, proj_ids, "BP") -- cgit v1.2.3 From 76d182ace088b7ab6d64019079c049a0f9a29e69 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 6 Jan 2016 16:40:26 +0100 Subject: Change python set_gpu_index to match --- python/astra/astra.py | 4 ++-- python/astra/astra_c.pyx | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'python/astra') diff --git a/python/astra/astra.py b/python/astra/astra.py index 26b1ff0..9328b6b 100644 --- a/python/astra/astra.py +++ b/python/astra/astra.py @@ -49,10 +49,10 @@ def version(printToScreen=False): """ return a.version(printToScreen) -def set_gpu_index(idx): +def set_gpu_index(idx, memory=0): """Set default GPU index to use. :param idx: GPU index :type idx: :class:`int` """ - a.set_gpu_index(idx) + a.set_gpu_index(idx, memory) diff --git a/python/astra/astra_c.pyx b/python/astra/astra_c.pyx index 6b246b6..2a9c816 100644 --- a/python/astra/astra_c.pyx +++ b/python/astra/astra_c.pyx @@ -31,6 +31,7 @@ import six from .utils import wrap_from_bytes from libcpp.string cimport string +from libcpp.vector cimport vector from libcpp cimport bool cdef extern from "astra/Globals.h" namespace "astra": int getVersion() @@ -43,6 +44,12 @@ IF HAVE_CUDA==True: ELSE: def setGPUIndex(): pass +cdef extern from "astra/CompositeGeometryManager.h" namespace "astra": + cdef cppclass SGPUParams: + vector[int] GPUIndices + size_t memory +cdef extern from "astra/CompositeGeometryManager.h" namespace "astra::CCompositeGeometryManager": + void setGlobalGPUParams(SGPUParams&) def credits(): six.print_("""The ASTRA Toolbox has been developed at the University of Antwerp and CWI, Amsterdam by @@ -70,8 +77,16 @@ def version(printToScreen=False): else: return getVersion() -def set_gpu_index(idx): +def set_gpu_index(idx, memory=0): + import types + import collections + cdef SGPUParams params if use_cuda()==True: - ret = setGPUIndex(idx) + if not isinstance(idx, collections.Iterable) or isinstance(idx, types.StringTypes): + idx = (idx,) + params.memory = memory + params.GPUIndices = idx + setGlobalGPUParams(params) + ret = setGPUIndex(params.GPUIndices[0]) if not ret: - six.print_("Failed to set GPU " + str(idx)) + six.print_("Failed to set GPU " + str(params.GPUIndices[0])) -- cgit v1.2.3 From 5bc9c23c84a3e7f079b75d0bee50c570a7372920 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 6 Jan 2016 16:49:56 +0100 Subject: Allow multiple GPUs in ASTRA_GPU_INDEX envvar --- python/astra/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'python/astra') diff --git a/python/astra/__init__.py b/python/astra/__init__.py index 10ed74d..515d9a2 100644 --- a/python/astra/__init__.py +++ b/python/astra/__init__.py @@ -39,7 +39,7 @@ from . import log from .optomo import OpTomo import os -try: - astra.set_gpu_index(int(os.environ['ASTRA_GPU_INDEX'])) -except KeyError: - pass + +if 'ASTRA_GPU_INDEX' in os.environ: + L = [ int(x) for x in os.environ['ASTRA_GPU_INDEX'].split(',') ] + astra.set_gpu_index(L) -- cgit v1.2.3 From 56809b0359af7e9108adeb1fd21823a225edf6fa Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 20 Jan 2016 18:08:59 +0100 Subject: Remove dependency of libastra on libpython by refactoring PluginAlgorithm --- python/astra/plugin_c.pyx | 17 +- python/astra/src/PythonPluginAlgorithm.cpp | 402 +++++++++++++++++++++++++++++ python/astra/src/PythonPluginAlgorithm.h | 89 +++++++ 3 files changed, 503 insertions(+), 5 deletions(-) create mode 100644 python/astra/src/PythonPluginAlgorithm.cpp create mode 100644 python/astra/src/PythonPluginAlgorithm.h (limited to 'python/astra') diff --git a/python/astra/plugin_c.pyx b/python/astra/plugin_c.pyx index 8d6816b..775ccd4 100644 --- a/python/astra/plugin_c.pyx +++ b/python/astra/plugin_c.pyx @@ -32,21 +32,25 @@ import inspect from libcpp.string cimport string from libcpp cimport bool -cdef CPluginAlgorithmFactory *fact = getSingletonPtr() +cdef CPythonPluginAlgorithmFactory *fact = getSingletonPtr() from . import utils -cdef extern from "astra/PluginAlgorithm.h" namespace "astra": - cdef cppclass CPluginAlgorithmFactory: +cdef extern from "src/PythonPluginAlgorithm.h" namespace "astra": + cdef cppclass CPythonPluginAlgorithmFactory: bool registerPlugin(string className) bool registerPlugin(string name, string className) bool registerPluginClass(object className) bool registerPluginClass(string name, object className) object getRegistered() - string getHelp(string name) + string getHelp(string &name) + +cdef extern from "src/PythonPluginAlgorithm.h" namespace "astra::CPythonPluginAlgorithmFactory": + cdef CPythonPluginAlgorithmFactory* getSingletonPtr() cdef extern from "astra/PluginAlgorithm.h" namespace "astra::CPluginAlgorithmFactory": - cdef CPluginAlgorithmFactory* getSingletonPtr() + # NB: Using wrong pointer type here for convenience + cdef void registerFactory(CPythonPluginAlgorithmFactory *) def register(className, name=None): if inspect.isclass(className): @@ -65,3 +69,6 @@ def get_registered(): def get_help(name): return utils.wrap_from_bytes(fact.getHelp(six.b(name))) + +# Register python plugin factory with astra +registerFactory(fact) diff --git a/python/astra/src/PythonPluginAlgorithm.cpp b/python/astra/src/PythonPluginAlgorithm.cpp new file mode 100644 index 0000000..1ea858d --- /dev/null +++ b/python/astra/src/PythonPluginAlgorithm.cpp @@ -0,0 +1,402 @@ +/* +----------------------------------------------------------------------- +Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp + 2014-2015, CWI, Amsterdam + +Contact: astra@uantwerpen.be +Website: http://sf.net/projects/astra-toolbox + +This file is part of the ASTRA Toolbox. + + +The ASTRA Toolbox is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The ASTRA Toolbox is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the ASTRA Toolbox. If not, see . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifdef ASTRA_PYTHON + +#include "PythonPluginAlgorithm.h" + +#include "astra/Logging.h" +#include "astra/Utilities.h" +#include +#include +#include +#include +#include + +#include +#include "bytesobject.h" + +namespace astra { + + + +void logPythonError(){ + if(PyErr_Occurred()){ + PyObject *ptype, *pvalue, *ptraceback; + PyErr_Fetch(&ptype, &pvalue, &ptraceback); + PyErr_NormalizeException(&ptype, &pvalue, &ptraceback); + PyObject *traceback = PyImport_ImportModule("traceback"); + if(traceback!=NULL){ + PyObject *exc; + if(ptraceback==NULL){ + exc = PyObject_CallMethod(traceback,"format_exception_only","OO",ptype, pvalue); + }else{ + exc = PyObject_CallMethod(traceback,"format_exception","OOO",ptype, pvalue, ptraceback); + } + if(exc!=NULL){ + PyObject *six = PyImport_ImportModule("six"); + if(six!=NULL){ + PyObject *iter = PyObject_GetIter(exc); + if(iter!=NULL){ + PyObject *line; + std::string errStr = ""; + while(line = PyIter_Next(iter)){ + PyObject *retb = PyObject_CallMethod(six,"b","O",line); + if(retb!=NULL){ + errStr += std::string(PyBytes_AsString(retb)); + Py_DECREF(retb); + } + Py_DECREF(line); + } + ASTRA_ERROR("%s",errStr.c_str()); + Py_DECREF(iter); + } + Py_DECREF(six); + } + Py_DECREF(exc); + } + Py_DECREF(traceback); + } + if(ptype!=NULL) Py_DECREF(ptype); + if(pvalue!=NULL) Py_DECREF(pvalue); + if(ptraceback!=NULL) Py_DECREF(ptraceback); + } +} + + +CPluginAlgorithm::CPluginAlgorithm(PyObject* pyclass){ + instance = PyObject_CallObject(pyclass, NULL); + if(instance==NULL) logPythonError(); +} + +CPluginAlgorithm::~CPluginAlgorithm(){ + if(instance!=NULL){ + Py_DECREF(instance); + instance = NULL; + } +} + +bool CPluginAlgorithm::initialize(const Config& _cfg){ + if(instance==NULL) return false; + PyObject *cfgDict = XMLNode2dict(_cfg.self); + PyObject *retVal = PyObject_CallMethod(instance, "astra_init", "O",cfgDict); + Py_DECREF(cfgDict); + if(retVal==NULL){ + logPythonError(); + return false; + } + m_bIsInitialized = true; + Py_DECREF(retVal); + return m_bIsInitialized; +} + +void CPluginAlgorithm::run(int _iNrIterations){ + if(instance==NULL) return; + PyGILState_STATE state = PyGILState_Ensure(); + PyObject *retVal = PyObject_CallMethod(instance, "run", "i",_iNrIterations); + if(retVal==NULL){ + logPythonError(); + }else{ + Py_DECREF(retVal); + } + PyGILState_Release(state); +} + +void fixLapackLoading(){ + // When running in Matlab, we need to force numpy + // to use its internal lapack library instead of + // Matlab's MKL library to avoid errors. To do this, + // we set Python's dlopen flags to RTLD_NOW|RTLD_DEEPBIND + // and import 'numpy.linalg.lapack_lite' here. We reset + // Python's dlopen flags afterwards. + PyObject *sys = PyImport_ImportModule("sys"); + if(sys!=NULL){ + PyObject *curFlags = PyObject_CallMethod(sys,"getdlopenflags",NULL); + if(curFlags!=NULL){ + PyObject *retVal = PyObject_CallMethod(sys, "setdlopenflags", "i",10); + if(retVal!=NULL){ + PyObject *lapack = PyImport_ImportModule("numpy.linalg.lapack_lite"); + if(lapack!=NULL){ + Py_DECREF(lapack); + } + PyObject_CallMethod(sys, "setdlopenflags", "O",curFlags); + Py_DECREF(retVal); + } + Py_DECREF(curFlags); + } + Py_DECREF(sys); + } +} + +CPythonPluginAlgorithmFactory::CPythonPluginAlgorithmFactory(){ + if(!Py_IsInitialized()){ + Py_Initialize(); + PyEval_InitThreads(); + } +#ifndef _MSC_VER + if(astra::running_in_matlab) fixLapackLoading(); +#endif + pluginDict = PyDict_New(); + inspect = PyImport_ImportModule("inspect"); + six = PyImport_ImportModule("six"); +} + +CPythonPluginAlgorithmFactory::~CPythonPluginAlgorithmFactory(){ + if(pluginDict!=NULL){ + Py_DECREF(pluginDict); + } + if(inspect!=NULL) Py_DECREF(inspect); + if(six!=NULL) Py_DECREF(six); +} + +PyObject * getClassFromString(std::string str){ + std::vector items; + boost::split(items, str, boost::is_any_of(".")); + PyObject *pyclass = PyImport_ImportModule(items[0].c_str()); + if(pyclass==NULL){ + logPythonError(); + return NULL; + } + PyObject *submod = pyclass; + for(unsigned int i=1;i CPythonPluginAlgorithmFactory::getRegisteredMap(){ + std::map ret; + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(pluginDict, &pos, &key, &value)) { + PyObject *keystr = PyObject_Str(key); + if(keystr!=NULL){ + PyObject *valstr = PyObject_Str(value); + if(valstr!=NULL){ + PyObject * keyb = PyObject_CallMethod(six,"b","O",keystr); + if(keyb!=NULL){ + PyObject * valb = PyObject_CallMethod(six,"b","O",valstr); + if(valb!=NULL){ + ret[PyBytes_AsString(keyb)] = PyBytes_AsString(valb); + Py_DECREF(valb); + } + Py_DECREF(keyb); + } + Py_DECREF(valstr); + } + Py_DECREF(keystr); + } + logPythonError(); + } + return ret; +} + +std::string CPythonPluginAlgorithmFactory::getHelp(const std::string &name){ + PyObject *className = PyDict_GetItemString(pluginDict, name.c_str()); + if(className==NULL){ + ASTRA_ERROR("Plugin %s not found!",name.c_str()); + PyErr_Clear(); + return ""; + } + std::string ret = ""; + PyObject *pyclass; + if(PyBytes_Check(className)){ + std::string str = std::string(PyBytes_AsString(className)); + pyclass = getClassFromString(str); + }else{ + pyclass = className; + } + if(pyclass==NULL) return ""; + if(inspect!=NULL && six!=NULL){ + PyObject *retVal = PyObject_CallMethod(inspect,"getdoc","O",pyclass); + if(retVal!=NULL){ + if(retVal!=Py_None){ + PyObject *retb = PyObject_CallMethod(six,"b","O",retVal); + if(retb!=NULL){ + ret = std::string(PyBytes_AsString(retb)); + Py_DECREF(retb); + } + } + Py_DECREF(retVal); + }else{ + logPythonError(); + } + } + if(PyBytes_Check(className)){ + Py_DECREF(pyclass); + } + return ret; +} + +DEFINE_SINGLETON(CPythonPluginAlgorithmFactory); + +#if PY_MAJOR_VERSION >= 3 +PyObject * pyStringFromString(std::string str){ + return PyUnicode_FromString(str.c_str()); +} +#else +PyObject * pyStringFromString(std::string str){ + return PyBytes_FromString(str.c_str()); +} +#endif + +PyObject* stringToPythonValue(std::string str){ + if(str.find(";")!=std::string::npos){ + std::vector rows, row; + boost::split(rows, str, boost::is_any_of(";")); + PyObject *mat = PyList_New(rows.size()); + for(unsigned int i=0; i vec; + boost::split(vec, str, boost::is_any_of(",")); + PyObject *veclist = PyList_New(vec.size()); + for(unsigned int i=0;i nodes = node.getNodes(); + std::list::iterator it = nodes.begin(); + while(it!=nodes.end()){ + XMLNode subnode = *it; + if(subnode.getName()=="Option"){ + PyObject *obj; + if(subnode.hasAttribute("value")){ + obj = stringToPythonValue(subnode.getAttribute("value")); + }else{ + obj = stringToPythonValue(subnode.getContent()); + } + PyDict_SetItemString(opts, subnode.getAttribute("key").c_str(), obj); + Py_DECREF(obj); + }else{ + PyObject *obj = stringToPythonValue(subnode.getContent()); + PyDict_SetItemString(dct, subnode.getName().c_str(), obj); + Py_DECREF(obj); + } + ++it; + } + PyDict_SetItemString(dct, "options", opts); + Py_DECREF(opts); + return dct; +} + +} +#endif diff --git a/python/astra/src/PythonPluginAlgorithm.h b/python/astra/src/PythonPluginAlgorithm.h new file mode 100644 index 0000000..0b1309e --- /dev/null +++ b/python/astra/src/PythonPluginAlgorithm.h @@ -0,0 +1,89 @@ +/* +----------------------------------------------------------------------- +Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp + 2014-2015, CWI, Amsterdam + +Contact: astra@uantwerpen.be +Website: http://sf.net/projects/astra-toolbox + +This file is part of the ASTRA Toolbox. + + +The ASTRA Toolbox is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The ASTRA Toolbox is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the ASTRA Toolbox. If not, see . + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifndef _INC_PYTHONPLUGINALGORITHM +#define _INC_PYTHONPLUGINALGORITHM + +#ifdef ASTRA_PYTHON + +#include "astra/Algorithm.h" +#include "astra/Singleton.h" +#include "astra/XMLDocument.h" +#include "astra/XMLNode.h" +#include "astra/PluginAlgorithm.h" + +#include + +namespace astra { +class CPluginAlgorithm : public CAlgorithm { + +public: + + CPluginAlgorithm(PyObject* pyclass); + ~CPluginAlgorithm(); + + bool initialize(const Config& _cfg); + void run(int _iNrIterations); + +private: + PyObject * instance; + +}; + +class CPythonPluginAlgorithmFactory : public CPluginAlgorithmFactory, public Singleton { + +public: + + CPythonPluginAlgorithmFactory(); + virtual ~CPythonPluginAlgorithmFactory(); + + virtual CAlgorithm * getPlugin(const std::string &name); + + virtual bool registerPlugin(std::string name, std::string className); + virtual bool registerPlugin(std::string className); + bool registerPluginClass(std::string name, PyObject * className); + bool registerPluginClass(PyObject * className); + + PyObject * getRegistered(); + virtual std::map getRegisteredMap(); + + virtual std::string getHelp(const std::string &name); + +private: + PyObject * pluginDict; + PyObject *inspect, *six; +}; + +PyObject* XMLNode2dict(XMLNode node); + +} + + +#endif + +#endif -- cgit v1.2.3 From 7f11ed333cdc93e9e93d4677f857d97ffbbfec87 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 21 Jan 2016 12:14:44 +0100 Subject: Fix whitespace --- python/astra/src/PythonPluginAlgorithm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/astra') diff --git a/python/astra/src/PythonPluginAlgorithm.cpp b/python/astra/src/PythonPluginAlgorithm.cpp index 1ea858d..0100bed 100644 --- a/python/astra/src/PythonPluginAlgorithm.cpp +++ b/python/astra/src/PythonPluginAlgorithm.cpp @@ -238,7 +238,7 @@ CAlgorithm * CPythonPluginAlgorithmFactory::getPlugin(const std::string &name){ CPluginAlgorithm *alg = NULL; if(PyBytes_Check(className)){ std::string str = std::string(PyBytes_AsString(className)); - PyObject *pyclass = getClassFromString(str); + PyObject *pyclass = getClassFromString(str); if(pyclass!=NULL){ alg = new CPluginAlgorithm(pyclass); Py_DECREF(pyclass); -- cgit v1.2.3 From cf0eff7075d21ccfa985676eb3a5e30f8694fc4c Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 27 Jan 2016 09:48:25 +0100 Subject: Decrement refcount of CallMethod return value --- python/astra/src/PythonPluginAlgorithm.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'python/astra') diff --git a/python/astra/src/PythonPluginAlgorithm.cpp b/python/astra/src/PythonPluginAlgorithm.cpp index 0100bed..61a56ea 100644 --- a/python/astra/src/PythonPluginAlgorithm.cpp +++ b/python/astra/src/PythonPluginAlgorithm.cpp @@ -144,7 +144,10 @@ void fixLapackLoading(){ if(lapack!=NULL){ Py_DECREF(lapack); } - PyObject_CallMethod(sys, "setdlopenflags", "O",curFlags); + PyObject *retVal2 = PyObject_CallMethod(sys, "setdlopenflags", "O",curFlags); + if(retVal2!=NULL){ + Py_DECREF(retVal2); + } Py_DECREF(retVal); } Py_DECREF(curFlags); -- cgit v1.2.3 From 4a75ab09962015d90acaa3e2be8357a1c917d5eb Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 27 Jan 2016 10:05:57 +0100 Subject: Move fixLapackLoading to astra_mex_plugin --- python/astra/src/PythonPluginAlgorithm.cpp | 32 ------------------------------ 1 file changed, 32 deletions(-) (limited to 'python/astra') diff --git a/python/astra/src/PythonPluginAlgorithm.cpp b/python/astra/src/PythonPluginAlgorithm.cpp index 61a56ea..e34861a 100644 --- a/python/astra/src/PythonPluginAlgorithm.cpp +++ b/python/astra/src/PythonPluginAlgorithm.cpp @@ -127,43 +127,11 @@ void CPluginAlgorithm::run(int _iNrIterations){ PyGILState_Release(state); } -void fixLapackLoading(){ - // When running in Matlab, we need to force numpy - // to use its internal lapack library instead of - // Matlab's MKL library to avoid errors. To do this, - // we set Python's dlopen flags to RTLD_NOW|RTLD_DEEPBIND - // and import 'numpy.linalg.lapack_lite' here. We reset - // Python's dlopen flags afterwards. - PyObject *sys = PyImport_ImportModule("sys"); - if(sys!=NULL){ - PyObject *curFlags = PyObject_CallMethod(sys,"getdlopenflags",NULL); - if(curFlags!=NULL){ - PyObject *retVal = PyObject_CallMethod(sys, "setdlopenflags", "i",10); - if(retVal!=NULL){ - PyObject *lapack = PyImport_ImportModule("numpy.linalg.lapack_lite"); - if(lapack!=NULL){ - Py_DECREF(lapack); - } - PyObject *retVal2 = PyObject_CallMethod(sys, "setdlopenflags", "O",curFlags); - if(retVal2!=NULL){ - Py_DECREF(retVal2); - } - Py_DECREF(retVal); - } - Py_DECREF(curFlags); - } - Py_DECREF(sys); - } -} - CPythonPluginAlgorithmFactory::CPythonPluginAlgorithmFactory(){ if(!Py_IsInitialized()){ Py_Initialize(); PyEval_InitThreads(); } -#ifndef _MSC_VER - if(astra::running_in_matlab) fixLapackLoading(); -#endif pluginDict = PyDict_New(); inspect = PyImport_ImportModule("inspect"); six = PyImport_ImportModule("six"); -- cgit v1.2.3 From d2705f52766716b4d4627a62de92e7a2480b6b86 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 2 Feb 2016 14:12:41 +0100 Subject: Make copyright/license headers consistent with rest of astra --- python/astra/algorithm_c.pyx | 37 +++++++++++++++--------------- python/astra/astra_c.pyx | 36 ++++++++++++++--------------- python/astra/data2d_c.pyx | 36 ++++++++++++++--------------- python/astra/data3d_c.pyx | 36 ++++++++++++++--------------- python/astra/experimental.pyx | 10 ++++---- python/astra/extrautils.pyx | 35 ++++++++++++++-------------- python/astra/log_c.pyx | 36 ++++++++++++++--------------- python/astra/matrix_c.pyx | 36 ++++++++++++++--------------- python/astra/plugin_c.pyx | 36 ++++++++++++++--------------- python/astra/projector3d_c.pyx | 36 ++++++++++++++--------------- python/astra/projector_c.pyx | 36 ++++++++++++++--------------- python/astra/src/PythonPluginAlgorithm.cpp | 5 ++-- python/astra/src/PythonPluginAlgorithm.h | 5 ++-- python/astra/utils.pyx | 36 ++++++++++++++--------------- 14 files changed, 206 insertions(+), 210 deletions(-) (limited to 'python/astra') diff --git a/python/astra/algorithm_c.pyx b/python/astra/algorithm_c.pyx index 3231c1f..4e96578 100644 --- a/python/astra/algorithm_c.pyx +++ b/python/astra/algorithm_c.pyx @@ -1,29 +1,28 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- # -#----------------------------------------------------------------------- - # distutils: language = c++ # distutils: libraries = astra diff --git a/python/astra/astra_c.pyx b/python/astra/astra_c.pyx index 6b246b6..5075fed 100644 --- a/python/astra/astra_c.pyx +++ b/python/astra/astra_c.pyx @@ -1,28 +1,28 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- # -#----------------------------------------------------------------------- # distutils: language = c++ # distutils: libraries = astra diff --git a/python/astra/data2d_c.pyx b/python/astra/data2d_c.pyx index 801fd8e..65e80ce 100644 --- a/python/astra/data2d_c.pyx +++ b/python/astra/data2d_c.pyx @@ -1,28 +1,28 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- # -#----------------------------------------------------------------------- # distutils: language = c++ # distutils: libraries = astra diff --git a/python/astra/data3d_c.pyx b/python/astra/data3d_c.pyx index 3b27ab7..207d9a5 100644 --- a/python/astra/data3d_c.pyx +++ b/python/astra/data3d_c.pyx @@ -1,28 +1,28 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- # -#----------------------------------------------------------------------- # distutils: language = c++ # distutils: libraries = astra diff --git a/python/astra/experimental.pyx b/python/astra/experimental.pyx index aafc002..9bb73a2 100644 --- a/python/astra/experimental.pyx +++ b/python/astra/experimental.pyx @@ -1,6 +1,6 @@ -#----------------------------------------------------------------------- -# Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp -# 2014-2015, CWI, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # # Contact: astra@uantwerpen.be # Website: http://sf.net/projects/astra-toolbox @@ -21,8 +21,8 @@ # You should have received a copy of the GNU General Public License # along with the ASTRA Toolbox. If not, see . # -#----------------------------------------------------------------------- - +# ----------------------------------------------------------------------- +# # distutils: language = c++ # distutils: libraries = astra diff --git a/python/astra/extrautils.pyx b/python/astra/extrautils.pyx index 998f5cb..5bc315f 100644 --- a/python/astra/extrautils.pyx +++ b/python/astra/extrautils.pyx @@ -1,28 +1,27 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . # -#----------------------------------------------------------------------- +# ----------------------------------------------------------------------- def clipCircle(img): cdef int i,j diff --git a/python/astra/log_c.pyx b/python/astra/log_c.pyx index 55c63e6..0d187e9 100644 --- a/python/astra/log_c.pyx +++ b/python/astra/log_c.pyx @@ -1,28 +1,28 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- # -#----------------------------------------------------------------------- # distutils: language = c++ # distutils: libraries = astra diff --git a/python/astra/matrix_c.pyx b/python/astra/matrix_c.pyx index d099a75..f5c0938 100644 --- a/python/astra/matrix_c.pyx +++ b/python/astra/matrix_c.pyx @@ -1,28 +1,28 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- # -#----------------------------------------------------------------------- # distutils: language = c++ # distutils: libraries = astra diff --git a/python/astra/plugin_c.pyx b/python/astra/plugin_c.pyx index 775ccd4..ee04853 100644 --- a/python/astra/plugin_c.pyx +++ b/python/astra/plugin_c.pyx @@ -1,28 +1,28 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- # -#----------------------------------------------------------------------- # distutils: language = c++ # distutils: libraries = astra diff --git a/python/astra/projector3d_c.pyx b/python/astra/projector3d_c.pyx index aec9cde..e355e38 100644 --- a/python/astra/projector3d_c.pyx +++ b/python/astra/projector3d_c.pyx @@ -1,28 +1,28 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- # -#----------------------------------------------------------------------- # distutils: language = c++ # distutils: libraries = astra diff --git a/python/astra/projector_c.pyx b/python/astra/projector_c.pyx index 77c64a4..53d38c3 100644 --- a/python/astra/projector_c.pyx +++ b/python/astra/projector_c.pyx @@ -1,28 +1,28 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- # -#----------------------------------------------------------------------- # distutils: language = c++ # distutils: libraries = astra diff --git a/python/astra/src/PythonPluginAlgorithm.cpp b/python/astra/src/PythonPluginAlgorithm.cpp index e34861a..617c0f4 100644 --- a/python/astra/src/PythonPluginAlgorithm.cpp +++ b/python/astra/src/PythonPluginAlgorithm.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- -Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp - 2014-2015, CWI, Amsterdam +Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp + 2014-2016, CWI, Amsterdam Contact: astra@uantwerpen.be Website: http://sf.net/projects/astra-toolbox @@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License along with the ASTRA Toolbox. If not, see . ----------------------------------------------------------------------- -$Id$ */ #ifdef ASTRA_PYTHON diff --git a/python/astra/src/PythonPluginAlgorithm.h b/python/astra/src/PythonPluginAlgorithm.h index 0b1309e..ea4c6fb 100644 --- a/python/astra/src/PythonPluginAlgorithm.h +++ b/python/astra/src/PythonPluginAlgorithm.h @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- -Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp - 2014-2015, CWI, Amsterdam +Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp + 2014-2016, CWI, Amsterdam Contact: astra@uantwerpen.be Website: http://sf.net/projects/astra-toolbox @@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License along with the ASTRA Toolbox. If not, see . ----------------------------------------------------------------------- -$Id$ */ #ifndef _INC_PYTHONPLUGINALGORITHM diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx index 07727ce..52c2a8d 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -1,28 +1,28 @@ -#----------------------------------------------------------------------- -#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam # -#Author: Daniel M. Pelt -#Contact: D.M.Pelt@cwi.nl -#Website: http://dmpelt.github.io/pyastratoolbox/ +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox # +# This file is part of the ASTRA Toolbox. # -#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 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. +# 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 . +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- # -#----------------------------------------------------------------------- # distutils: language = c++ # distutils: libraries = astra -- cgit v1.2.3 From 0884a3928395dd368aea61eeef768677018f9095 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 17 Feb 2016 16:18:23 +0100 Subject: Add python astra.astra delete/info based on index manager --- python/astra/PyIndexManager.pxd | 40 ++++++++++++++++++++++++++++++++++++++++ python/astra/astra.py | 20 ++++++++++++++++++++ python/astra/astra_c.pyx | 30 ++++++++++++++++++++++++++++-- 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 python/astra/PyIndexManager.pxd (limited to 'python/astra') diff --git a/python/astra/PyIndexManager.pxd b/python/astra/PyIndexManager.pxd new file mode 100644 index 0000000..c1ad502 --- /dev/null +++ b/python/astra/PyIndexManager.pxd @@ -0,0 +1,40 @@ +# ----------------------------------------------------------------------- +# Copyright: 2010-2016, iMinds-Vision Lab, University of Antwerp +# 2013-2016, CWI, Amsterdam +# +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox +# +# This file is part of the ASTRA Toolbox. +# +# +# The ASTRA Toolbox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# The ASTRA Toolbox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see . +# +# ----------------------------------------------------------------------- + +from libcpp.string cimport string + +from .PyIncludes cimport * + +cdef extern from "astra/AstraObjectManager.h" namespace "astra": + cdef cppclass CAstraObjectManagerBase: + string getInfo(int) + void remove(int) + string getType() + cdef cppclass CAstraIndexManager: + CAstraObjectManagerBase* get(int) + +cdef extern from "astra/AstraObjectManager.h" namespace "astra::CAstraIndexManager": + cdef CAstraIndexManager* getSingletonPtr() + diff --git a/python/astra/astra.py b/python/astra/astra.py index 9328b6b..61c26ee 100644 --- a/python/astra/astra.py +++ b/python/astra/astra.py @@ -56,3 +56,23 @@ def set_gpu_index(idx, memory=0): :type idx: :class:`int` """ a.set_gpu_index(idx, memory) + +def delete(ids): + """Delete an astra object. + + :param ids: ID or list of ID's to delete. + :type ids: :class:`int` or :class:`list` + + """ + return a.delete(ids) + +def info(ids): + """Print info about an astra object. + + :param ids: ID or list of ID's to show. + :type ids: :class:`int` or :class:`list` + + """ + return a.info(ids) + + diff --git a/python/astra/astra_c.pyx b/python/astra/astra_c.pyx index 2a9c816..c70bb8e 100644 --- a/python/astra/astra_c.pyx +++ b/python/astra/astra_c.pyx @@ -33,6 +33,9 @@ from .utils import wrap_from_bytes from libcpp.string cimport string from libcpp.vector cimport vector from libcpp cimport bool +cimport PyIndexManager +from .PyIndexManager cimport CAstraObjectManagerBase + cdef extern from "astra/Globals.h" namespace "astra": int getVersion() string getVersionString() @@ -51,6 +54,7 @@ cdef extern from "astra/CompositeGeometryManager.h" namespace "astra": cdef extern from "astra/CompositeGeometryManager.h" namespace "astra::CCompositeGeometryManager": void setGlobalGPUParams(SGPUParams&) + def credits(): six.print_("""The ASTRA Toolbox has been developed at the University of Antwerp and CWI, Amsterdam by * Prof. dr. Joost Batenburg @@ -78,11 +82,10 @@ def version(printToScreen=False): return getVersion() def set_gpu_index(idx, memory=0): - import types import collections cdef SGPUParams params if use_cuda()==True: - if not isinstance(idx, collections.Iterable) or isinstance(idx, types.StringTypes): + if not isinstance(idx, collections.Iterable) or isinstance(idx, six.string_types + (six.text_type,six.binary_type)): idx = (idx,) params.memory = memory params.GPUIndices = idx @@ -90,3 +93,26 @@ def set_gpu_index(idx, memory=0): ret = setGPUIndex(params.GPUIndices[0]) if not ret: six.print_("Failed to set GPU " + str(params.GPUIndices[0])) + +def delete(ids): + import collections + cdef CAstraObjectManagerBase* ptr + if not isinstance(ids, collections.Iterable) or isinstance(ids, six.string_types + (six.text_type,six.binary_type)): + ids = (ids,) + for i in ids: + ptr = PyIndexManager.getSingletonPtr().get(i) + if ptr: + ptr.remove(i) + +def info(ids): + import collections + cdef CAstraObjectManagerBase* ptr + if not isinstance(ids, collections.Iterable) or isinstance(ids, six.string_types + (six.text_type,six.binary_type)): + ids = (ids,) + for i in ids: + ptr = PyIndexManager.getSingletonPtr().get(i) + if ptr: + s = ptr.getType() + six.b("\t") + ptr.getInfo(i) + six.print_(wrap_from_bytes(s)) + + -- cgit v1.2.3 From b74e64aef7845666d27cbf7e876a6a360eefed7f Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Mon, 29 Feb 2016 11:01:21 +0100 Subject: Disable astra.set_gpu_index when building without CUDA --- python/astra/astra_c.pyx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'python/astra') diff --git a/python/astra/astra_c.pyx b/python/astra/astra_c.pyx index 65192b5..baad853 100644 --- a/python/astra/astra_c.pyx +++ b/python/astra/astra_c.pyx @@ -77,7 +77,8 @@ def version(printToScreen=False): else: return getVersion() -def set_gpu_index(idx, memory=0): +IF HAVE_CUDA==True: + def set_gpu_index(idx, memory=0): import types import collections cdef SGPUParams params @@ -90,3 +91,6 @@ def set_gpu_index(idx, memory=0): ret = setGPUIndex(params.GPUIndices[0]) if not ret: six.print_("Failed to set GPU " + str(params.GPUIndices[0])) +ELSE: + def set_gpu_index(idx, memory=0): + raise NotImplementedError("CUDA support is not enabled in ASTRA") -- cgit v1.2.3 From 0fb04ca6fb4fca23b9d1b885b9f075a90542997b Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Wed, 2 Mar 2016 13:49:40 +0100 Subject: Fix small Python errors --- python/astra/data3d.py | 2 +- python/astra/functions.py | 2 +- python/astra/optomo.py | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'python/astra') diff --git a/python/astra/data3d.py b/python/astra/data3d.py index e5ef6b0..f143659 100644 --- a/python/astra/data3d.py +++ b/python/astra/data3d.py @@ -89,7 +89,7 @@ def get_single(i): :returns: :class:`numpy.ndarray` -- The object data. """ - return g.get_single(i) + return d.get_single(i) def store(i,data): """Fill existing 3D object with data. diff --git a/python/astra/functions.py b/python/astra/functions.py index e38b5bc..3f4aa82 100644 --- a/python/astra/functions.py +++ b/python/astra/functions.py @@ -115,7 +115,7 @@ def add_noise_to_sino(sinogram_in, I0, seed=None): sinogram_out = -max_sinogramRaw * np.log(sinogramCT_D) if not isinstance(sinogram_in, np.ndarray): - at.data2d.store(sinogram_in, sinogram_out) + data2d.store(sinogram_in, sinogram_out) if not seed==None: np.random.set_state(curstate) diff --git a/python/astra/optomo.py b/python/astra/optomo.py index 4a64150..dd10713 100644 --- a/python/astra/optomo.py +++ b/python/astra/optomo.py @@ -160,7 +160,7 @@ class OpTomo(scipy.sparse.linalg.LinearOperator): return self._matvec(v) return scipy.sparse.linalg.LinearOperator.__mul__(self, v) - def reconstruct(self, method, s, iterations=1, extraOptions = {}): + def reconstruct(self, method, s, iterations=1, extraOptions = None): """Reconstruct an object. :param method: Method to use for reconstruction. @@ -172,6 +172,8 @@ class OpTomo(scipy.sparse.linalg.LinearOperator): :param extraOptions: Extra options to use during reconstruction (i.e. for cfg['option']). :type extraOptions: :class:`dict` """ + if extraOptions is None: + extraOptions={} s = self.__checkArray(s, self.sshape) sid = self.data_mod.link('-sino',self.pg,s) v = np.zeros(self.vshape,dtype=np.float32) -- cgit v1.2.3 From a3b742fd2dc8ea253addd7342388c73a40f6fd59 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Fri, 4 Mar 2016 18:09:06 +0100 Subject: Encode Python bool as int in XML instead of str --- python/astra/utils.pyx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'python/astra') diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx index 52c2a8d..34d1902 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -32,7 +32,7 @@ import six if six.PY3: import builtins else: - import __builtin__ + import __builtin__ as builtins from libcpp.string cimport string from libcpp.vector cimport vector from libcpp.list cimport list @@ -95,14 +95,14 @@ cdef void readDict(XMLNode root, _dc): dc = convert_item(_dc) for item in dc: val = dc[item] - if isinstance(val, __builtins__.list) or isinstance(val, tuple): + if isinstance(val, builtins.list) or isinstance(val, tuple): val = np.array(val,dtype=np.float64) if isinstance(val, np.ndarray): if val.size == 0: break listbase = root.addChildNode(item) contig_data = np.ascontiguousarray(val,dtype=np.float64) - data = np.PyArray_DATA(contig_data) + data = np.PyArray_DATA(contig_data) if val.ndim == 2: listbase.setContent(data, val.shape[1], val.shape[0], False) elif val.ndim == 1: @@ -119,6 +119,8 @@ cdef void readDict(XMLNode root, _dc): if item == six.b('type'): root.addAttribute(< string > six.b('type'), wrap_to_bytes(val)) else: + if isinstance(val, builtins.bool): + val = int(val) itm = root.addChildNode(item, wrap_to_bytes(val)) cdef void readOptions(XMLNode node, dc): @@ -131,7 +133,7 @@ cdef void readOptions(XMLNode node, dc): val = dc[item] if node.hasOption(item): raise Exception('Duplicate Option: %s' % item) - if isinstance(val, __builtins__.list) or isinstance(val, tuple): + if isinstance(val, builtins.list) or isinstance(val, tuple): val = np.array(val,dtype=np.float64) if isinstance(val, np.ndarray): if val.size == 0: @@ -147,6 +149,8 @@ cdef void readOptions(XMLNode node, dc): else: raise Exception("Only 1 or 2 dimensions are allowed") else: + if isinstance(val, builtins.bool): + val = int(val) node.addOption(item, wrap_to_bytes(val)) cdef configToDict(Config *cfg): -- cgit v1.2.3 From c58929ca7d0201335b5036773b26f82361793f25 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Tue, 19 Apr 2016 16:40:14 +0200 Subject: Use CXX for Python compilation as well --- python/astra/extrautils.pyx | 2 ++ 1 file changed, 2 insertions(+) (limited to 'python/astra') diff --git a/python/astra/extrautils.pyx b/python/astra/extrautils.pyx index 5bc315f..2c7771e 100644 --- a/python/astra/extrautils.pyx +++ b/python/astra/extrautils.pyx @@ -22,6 +22,8 @@ # along with the ASTRA Toolbox. If not, see . # # ----------------------------------------------------------------------- +# distutils: language = c++ + def clipCircle(img): cdef int i,j -- cgit v1.2.3 From 1e26f7602b6685c584fd4d857353f390622e3a34 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Mon, 25 Apr 2016 10:47:59 +0200 Subject: Change flatten to ravel in Python code --- python/astra/optomo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python/astra') diff --git a/python/astra/optomo.py b/python/astra/optomo.py index dd10713..5a92998 100644 --- a/python/astra/optomo.py +++ b/python/astra/optomo.py @@ -125,7 +125,7 @@ class OpTomo(scipy.sparse.linalg.LinearOperator): algorithm.delete(fp_id) self.data_mod.delete([vid,sid]) - return s.flatten() + return s.ravel() def rmatvec(self,s): """Implements the transpose operator. @@ -147,7 +147,7 @@ class OpTomo(scipy.sparse.linalg.LinearOperator): algorithm.delete(bp_id) self.data_mod.delete([vid,sid]) - return v.flatten() + return v.ravel() def __mul__(self,v): """Provides easy forward operator by *. -- cgit v1.2.3 From a33b2a0e4e0663145fb0d4d67a9145948f90341a Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Mon, 25 Apr 2016 11:03:18 +0200 Subject: Reverse output of astra.data3d.dimensions This makes the output directly usable in numpy commands like zeros, reshape. We were not using data3d.dimensions ourselves, as far as I can tell. --- python/astra/data3d_c.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/astra') diff --git a/python/astra/data3d_c.pyx b/python/astra/data3d_c.pyx index 207d9a5..811d1e4 100644 --- a/python/astra/data3d_c.pyx +++ b/python/astra/data3d_c.pyx @@ -264,7 +264,7 @@ def store(i,data): def dimensions(i): cdef CFloat32Data3D * pDataObject = getObject(i) - return (pDataObject.getWidth(),pDataObject.getHeight(),pDataObject.getDepth()) + return (pDataObject.getDepth(),pDataObject.getHeight(),pDataObject.getWidth()) def delete(ids): try: -- cgit v1.2.3 From 63e22423350089a37b188a53164867eedab781ac Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 21 Apr 2016 11:39:51 +0200 Subject: Give OpTomo FP/BP functions with optional out argument This allows more efficient use of allocated arrays. --- python/astra/optomo.py | 96 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 30 deletions(-) (limited to 'python/astra') diff --git a/python/astra/optomo.py b/python/astra/optomo.py index 5a92998..dde719e 100644 --- a/python/astra/optomo.py +++ b/python/astra/optomo.py @@ -111,21 +111,7 @@ class OpTomo(scipy.sparse.linalg.LinearOperator): :param v: Volume to forward project. :type v: :class:`numpy.ndarray` """ - v = self.__checkArray(v, self.vshape) - vid = self.data_mod.link('-vol',self.vg,v) - s = np.zeros(self.sshape,dtype=np.float32) - sid = self.data_mod.link('-sino',self.pg,s) - - cfg = creators.astra_dict('FP'+self.appendString) - cfg['ProjectionDataId'] = sid - cfg['VolumeDataId'] = vid - cfg['ProjectorId'] = self.proj_id - fp_id = algorithm.create(cfg) - algorithm.run(fp_id) - - algorithm.delete(fp_id) - self.data_mod.delete([vid,sid]) - return s.ravel() + return self.FP(v, out=None).ravel() def rmatvec(self,s): """Implements the transpose operator. @@ -133,21 +119,7 @@ class OpTomo(scipy.sparse.linalg.LinearOperator): :param s: The projection data. :type s: :class:`numpy.ndarray` """ - s = self.__checkArray(s, self.sshape) - sid = self.data_mod.link('-sino',self.pg,s) - v = np.zeros(self.vshape,dtype=np.float32) - vid = self.data_mod.link('-vol',self.vg,v) - - cfg = creators.astra_dict('BP'+self.appendString) - cfg['ProjectionDataId'] = sid - cfg['ReconstructionDataId'] = vid - cfg['ProjectorId'] = self.proj_id - bp_id = algorithm.create(cfg) - algorithm.run(bp_id) - - algorithm.delete(bp_id) - self.data_mod.delete([vid,sid]) - return v.ravel() + return self.BP(s, out=None).ravel() def __mul__(self,v): """Provides easy forward operator by *. @@ -189,6 +161,70 @@ class OpTomo(scipy.sparse.linalg.LinearOperator): self.data_mod.delete([vid,sid]) return v + def FP(self,v,out=None): + """Perform forward projection. + + Output must have the right 2D/3D shape. Input may also be flattened. + + Output must also be contiguous and float32. This isn't required for the + input, but it is more efficient if it is. + + :param v: Volume to forward project. + :type v: :class:`numpy.ndarray` + :param out: Array to store result in. + :type out: :class:`numpy.ndarray` + """ + + v = self.__checkArray(v, self.vshape) + vid = self.data_mod.link('-vol',self.vg,v) + if out is None: + out = np.zeros(self.sshape,dtype=np.float32) + sid = self.data_mod.link('-sino',self.pg,out) + + cfg = creators.astra_dict('FP'+self.appendString) + cfg['ProjectionDataId'] = sid + cfg['VolumeDataId'] = vid + cfg['ProjectorId'] = self.proj_id + fp_id = algorithm.create(cfg) + algorithm.run(fp_id) + + algorithm.delete(fp_id) + self.data_mod.delete([vid,sid]) + return out + + def BP(self,s,out=None): + """Perform backprojection. + + Output must have the right 2D/3D shape. Input may also be flattened. + + Output must also be contiguous and float32. This isn't required for the + input, but it is more efficient if it is. + + :param : The projection data. + :type s: :class:`numpy.ndarray` + :param out: Array to store result in. + :type out: :class:`numpy.ndarray` + """ + s = self.__checkArray(s, self.sshape) + sid = self.data_mod.link('-sino',self.pg,s) + if out is None: + out = np.zeros(self.vshape,dtype=np.float32) + vid = self.data_mod.link('-vol',self.vg,out) + + cfg = creators.astra_dict('BP'+self.appendString) + cfg['ProjectionDataId'] = sid + cfg['ReconstructionDataId'] = vid + cfg['ProjectorId'] = self.proj_id + bp_id = algorithm.create(cfg) + algorithm.run(bp_id) + + algorithm.delete(bp_id) + self.data_mod.delete([vid,sid]) + return out + + + + class OpTomoTranspose(scipy.sparse.linalg.LinearOperator): """This object provides the transpose operation (``.T``) of the OpTomo object. -- cgit v1.2.3