From ba3629c6c1bc1d03ccdc6ef2aeae6872ea59559f Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Sat, 20 Jun 2015 00:33:23 +0200 Subject: Fix matlab compilation without CUDA --- matlab/mex/astra_mex_c.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_c.cpp b/matlab/mex/astra_mex_c.cpp index 4a331f5..a9b9654 100644 --- a/matlab/mex/astra_mex_c.cpp +++ b/matlab/mex/astra_mex_c.cpp @@ -36,9 +36,9 @@ $Id$ #include "mexInitFunctions.h" #include "astra/Globals.h" - +#ifdef ASTRA_CUDA #include "../cuda/2d/darthelper.h" - +#endif using namespace std; using namespace astra; -- 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 --- matlab/mex/mexHelpFunctions.cpp | 6 +++++- python/astra/utils.pyx | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'matlab/mex') diff --git a/matlab/mex/mexHelpFunctions.cpp b/matlab/mex/mexHelpFunctions.cpp index 87a9672..58e84d2 100644 --- a/matlab/mex/mexHelpFunctions.cpp +++ b/matlab/mex/mexHelpFunctions.cpp @@ -336,7 +336,11 @@ mxArray* XMLNodeToStruct(astra::XMLNode node) // option if (subnode.getName() == "Option") { - mOptions[subnode.getAttribute("key")] = stringToMxArray(subnode.getAttribute("value")); + if(subnode.hasAttribute("value")){ + mOptions[subnode.getAttribute("key")] = stringToMxArray(subnode.getAttribute("value")); + }else{ + mOptions[subnode.getAttribute("key")] = stringToMxArray(subnode.getContent()); + } } // regular content 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 --- matlab/mex/astra_mex_projector3d_c.cpp | 8 ++++++-- matlab/mex/astra_mex_projector_c.cpp | 9 ++++++--- python/astra/projector3d_c.pyx | 10 ++++++++-- python/astra/projector_c.pyx | 10 ++++++++-- 4 files changed, 28 insertions(+), 9 deletions(-) (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_projector3d_c.cpp b/matlab/mex/astra_mex_projector3d_c.cpp index c3b547f..e25802c 100644 --- a/matlab/mex/astra_mex_projector3d_c.cpp +++ b/matlab/mex/astra_mex_projector3d_c.cpp @@ -137,7 +137,9 @@ void astra_mex_projector3d_get_projection_geometry(int nlhs, mxArray* plhs[], in // step3: get projection_geometry and turn it into a MATLAB struct if (1 <= nlhs) { - plhs[0] = configToStruct(pProjector->getProjectionGeometry()->getConfiguration()); + Config *cfg = pProjector->getProjectionGeometry()->getConfiguration(); + plhs[0] = configToStruct(cfg); + delete cfg; } } @@ -163,7 +165,9 @@ void astra_mex_projector3d_get_volume_geometry(int nlhs, mxArray* plhs[], int nr // step3: get projection_geometry and turn it into a MATLAB struct if (1 <= nlhs) { - plhs[0] = configToStruct(pProjector->getVolumeGeometry()->getConfiguration()); + Config *cfg = pProjector->getVolumeGeometry()->getConfiguration(); + plhs[0] = configToStruct(cfg); + delete cfg; } } diff --git a/matlab/mex/astra_mex_projector_c.cpp b/matlab/mex/astra_mex_projector_c.cpp index 204ba8e..bf701af 100644 --- a/matlab/mex/astra_mex_projector_c.cpp +++ b/matlab/mex/astra_mex_projector_c.cpp @@ -160,7 +160,9 @@ void astra_mex_projector_projection_geometry(int nlhs, mxArray* plhs[], int nrhs // step3: get projection_geometry and turn it into a MATLAB struct if (1 <= nlhs) { - plhs[0] = configToStruct(pProjector->getProjectionGeometry()->getConfiguration()); + Config *cfg = pProjector->getProjectionGeometry()->getConfiguration(); + plhs[0] = configToStruct(cfg); + delete cfg; } } @@ -189,8 +191,9 @@ void astra_mex_projector_volume_geometry(int nlhs, mxArray* plhs[], int nrhs, co // step3: get projection_geometry and turn it into a MATLAB struct if (1 <= nlhs) { - plhs[0] = configToStruct(pProjector->getVolumeGeometry()->getConfiguration()); - + Config *cfg = pProjector->getVolumeGeometry()->getConfiguration(); + plhs[0] = configToStruct(cfg); + delete cfg; } } 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 --- matlab/mex/astra_mex_log_c.cpp | 8 ++++---- matlab/mex/mexInitFunctions.cpp | 2 +- python/astra/log_c.pyx | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_log_c.cpp b/matlab/mex/astra_mex_log_c.cpp index ea4621e..905612c 100644 --- a/matlab/mex/astra_mex_log_c.cpp +++ b/matlab/mex/astra_mex_log_c.cpp @@ -55,7 +55,7 @@ void astra_mex_log_debug(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prh string filename = mexToString(prhs[1]); int linenumber = (int)mxGetScalar(prhs[2]); string message = mexToString(prhs[3]); - astra::CLogger::debug(filename.c_str(),linenumber,message.c_str()); + astra::CLogger::debug(filename.c_str(),linenumber,"%s",message.c_str()); } //----------------------------------------------------------------------------------------- @@ -75,7 +75,7 @@ void astra_mex_log_info(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs string filename = mexToString(prhs[1]); int linenumber = (int)mxGetScalar(prhs[2]); string message = mexToString(prhs[3]); - astra::CLogger::info(filename.c_str(),linenumber,message.c_str()); + astra::CLogger::info(filename.c_str(),linenumber,"%s",message.c_str()); } //----------------------------------------------------------------------------------------- @@ -95,7 +95,7 @@ void astra_mex_log_warn(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs string filename = mexToString(prhs[1]); int linenumber = (int)mxGetScalar(prhs[2]); string message = mexToString(prhs[3]); - astra::CLogger::warn(filename.c_str(),linenumber,message.c_str()); + astra::CLogger::warn(filename.c_str(),linenumber,"%s",message.c_str()); } //----------------------------------------------------------------------------------------- @@ -115,7 +115,7 @@ void astra_mex_log_error(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prh string filename = mexToString(prhs[1]); int linenumber = (int)mxGetScalar(prhs[2]); string message = mexToString(prhs[3]); - astra::CLogger::error(filename.c_str(),linenumber,message.c_str()); + astra::CLogger::error(filename.c_str(),linenumber,"%s",message.c_str()); } //----------------------------------------------------------------------------------------- diff --git a/matlab/mex/mexInitFunctions.cpp b/matlab/mex/mexInitFunctions.cpp index d8a50d7..89a31a1 100644 --- a/matlab/mex/mexInitFunctions.cpp +++ b/matlab/mex/mexInitFunctions.cpp @@ -8,7 +8,7 @@ bool mexIsInitialized=false; * */ void logCallBack(const char *msg, size_t len){ - mexPrintf(msg); + mexPrintf("%s",msg); } /** 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 --- build/linux/Makefile.in | 16 +- include/astra/AstraObjectFactory.h | 13 ++ include/astra/PluginAlgorithm.h | 85 +++++++++++ matlab/mex/astra_mex_plugin_c.cpp | 139 ++++++++++++++++++ python/astra/__init__.py | 1 + python/astra/plugin.py | 95 ++++++++++++ python/astra/plugin_c.pyx | 59 ++++++++ python/astra/utils.pyx | 72 +-------- python/docSRC/index.rst | 1 + python/docSRC/plugins.rst | 8 + samples/python/s018_plugin.py | 138 +++++++++++++++++ src/PluginAlgorithm.cpp | 294 +++++++++++++++++++++++++++++++++++++ 12 files changed, 851 insertions(+), 70 deletions(-) create mode 100644 include/astra/PluginAlgorithm.h create mode 100644 matlab/mex/astra_mex_plugin_c.cpp create mode 100644 python/astra/plugin.py create mode 100644 python/astra/plugin_c.pyx create mode 100644 python/docSRC/plugins.rst create mode 100644 samples/python/s018_plugin.py create mode 100644 src/PluginAlgorithm.cpp (limited to 'matlab/mex') diff --git a/build/linux/Makefile.in b/build/linux/Makefile.in index 2d862f2..e209fa7 100644 --- a/build/linux/Makefile.in +++ b/build/linux/Makefile.in @@ -50,11 +50,17 @@ LDFLAGS+=-fopenmp endif ifeq ($(python),yes) -PYCPPFLAGS = ${CPPFLAGS} +PYTHON = @PYTHON@ +PYLIBDIR = $(shell $(PYTHON) -c 'from distutils.sysconfig import get_config_var; import six; six.print_(get_config_var("LIBDIR"))') +PYINCDIR = $(shell $(PYTHON) -c 'from distutils.sysconfig import get_python_inc; import six; six.print_(get_python_inc())') +PYLIBVER = `basename $(PYINCDIR)` +CPPFLAGS += -DASTRA_PYTHON -I$(PYINCDIR) +PYCPPFLAGS = $(CPPFLAGS) PYCPPFLAGS += -I../include -PYLDFLAGS = ${LDFLAGS} +PYLDFLAGS = $(LDFLAGS) PYLDFLAGS += -L../build/linux/.libs -PYTHON = @PYTHON@ +LIBS += -l$(PYLIBVER) +LDFLAGS += -L$(PYLIBDIR) endif BOOST_CPPFLAGS= @@ -234,6 +240,10 @@ MATLAB_MEX=\ matlab/mex/astra_mex_log_c.$(MEXSUFFIX) \ matlab/mex/astra_mex_data3d_c.$(MEXSUFFIX) +ifeq ($(python),yes) +ALL_OBJECTS+=src/PluginAlgorithm.lo +MATLAB_MEX+=matlab/mex/astra_mex_plugin_c.$(MEXSUFFIX) +endif OBJECT_DIRS = src/ tests/ cuda/2d/ cuda/3d/ matlab/mex/ ./ DEPDIRS = $(addsuffix $(DEPDIR),$(OBJECT_DIRS)) diff --git a/include/astra/AstraObjectFactory.h b/include/astra/AstraObjectFactory.h index 356acf9..325989e 100644 --- a/include/astra/AstraObjectFactory.h +++ b/include/astra/AstraObjectFactory.h @@ -40,6 +40,10 @@ $Id$ #include "AlgorithmTypelist.h" +#ifdef ASTRA_PYTHON +#include "PluginAlgorithm.h" +#endif + namespace astra { @@ -147,6 +151,15 @@ T* CAstraObjectFactory::create(const Config& _cfg) */ class _AstraExport CAlgorithmFactory : public CAstraObjectFactory {}; +#ifdef ASTRA_PYTHON +template <> +inline CAlgorithm* CAstraObjectFactory::findPlugin(std::string _sType) + { + CPluginAlgorithmFactory *fac = CPluginAlgorithmFactory::getSingletonPtr(); + return fac->getPlugin(_sType); + } +#endif + /** * Class used to create 2D projectors from a string or a config object */ diff --git a/include/astra/PluginAlgorithm.h b/include/astra/PluginAlgorithm.h new file mode 100644 index 0000000..7d6c64a --- /dev/null +++ b/include/astra/PluginAlgorithm.h @@ -0,0 +1,85 @@ +/* +----------------------------------------------------------------------- +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_ASTRA_PLUGINALGORITHM +#define _INC_ASTRA_PLUGINALGORITHM + +#ifdef ASTRA_PYTHON + +#include +#include "bytesobject.h" +#include "astra/Algorithm.h" +#include "astra/Singleton.h" +#include "astra/XMLDocument.h" +#include "astra/XMLNode.h" + +namespace astra { +class _AstraExport CPluginAlgorithm : public CAlgorithm { + +public: + + CPluginAlgorithm(PyObject* pyclass); + ~CPluginAlgorithm(); + + bool initialize(const Config& _cfg); + void run(int _iNrIterations); + +private: + PyObject * instance; + +}; + +class _AstraExport CPluginAlgorithmFactory : public Singleton { + +public: + + CPluginAlgorithmFactory(); + ~CPluginAlgorithmFactory(); + + CPluginAlgorithm * getPlugin(std::string name); + + bool registerPlugin(std::string name, std::string className); + bool registerPluginClass(std::string name, PyObject * className); + + PyObject * getRegistered(); + + std::string getHelp(std::string name); + +private: + PyObject * pluginDict; + PyObject *ospath, *inspect, *six, *astra; + std::vector getPluginPathList(); +}; + +PyObject* XMLNode2dict(XMLNode node); + +} + +#endif + +#endif \ No newline at end of file diff --git a/matlab/mex/astra_mex_plugin_c.cpp b/matlab/mex/astra_mex_plugin_c.cpp new file mode 100644 index 0000000..2d9b9a0 --- /dev/null +++ b/matlab/mex/astra_mex_plugin_c.cpp @@ -0,0 +1,139 @@ +/* +----------------------------------------------------------------------- +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$ +*/ + +/** \file astra_mex_plugin_c.cpp + * + * \brief Manages Python plugins. + */ + +#include +#include "mexHelpFunctions.h" +#include "mexInitFunctions.h" + +#include "astra/PluginAlgorithm.h" + +#include "Python.h" +#include "bytesobject.h" + +using namespace std; +using namespace astra; + + +//----------------------------------------------------------------------------------------- +/** astra_mex_plugin('get_registered'); + * + * Print registered plugins. + */ +void astra_mex_plugin_get_registered(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getSingletonPtr(); + PyObject *dict = fact->getRegistered(); + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(dict, &pos, &key, &value)) { + mexPrintf("%s: %s\n",PyBytes_AsString(key),PyBytes_AsString(value)); + } + Py_DECREF(dict); +} + +//----------------------------------------------------------------------------------------- +/** astra_mex_plugin('register', name, class_name); + * + * Register plugin. + */ +void astra_mex_plugin_register(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + if (3 <= nrhs) { + string name = mexToString(prhs[1]); + string class_name = mexToString(prhs[2]); + astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getSingletonPtr(); + fact->registerPlugin(name, class_name); + }else{ + mexPrintf("astra_mex_plugin('register', name, class_name);\n"); + } +} + +//----------------------------------------------------------------------------------------- +/** astra_mex_plugin('get_help', name); + * + * Get help about plugin. + */ +void astra_mex_plugin_get_help(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + if (2 <= nrhs) { + string name = mexToString(prhs[1]); + astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getSingletonPtr(); + mexPrintf((fact->getHelp(name)+"\n").c_str()); + }else{ + mexPrintf("astra_mex_plugin('get_help', name);\n"); + } +} + + +//----------------------------------------------------------------------------------------- + +static void printHelp() +{ + mexPrintf("Please specify a mode of operation.\n"); + mexPrintf(" Valid modes: register, get_registered, get_help\n"); +} + +//----------------------------------------------------------------------------------------- +/** + * ... = astra_mex(type,...); + */ +void mexFunction(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + + // INPUT0: Mode + string sMode = ""; + if (1 <= nrhs) { + sMode = mexToString(prhs[0]); + } else { + printHelp(); + return; + } + + initASTRAMex(); + + // SWITCH (MODE) + if (sMode == std::string("get_registered")) { + astra_mex_plugin_get_registered(nlhs, plhs, nrhs, prhs); + }else if (sMode == std::string("get_help")) { + astra_mex_plugin_get_help(nlhs, plhs, nrhs, prhs); + }else if (sMode == std::string("register")) { + astra_mex_plugin_register(nlhs, plhs, nrhs, prhs); + } else { + printHelp(); + } + + return; +} + + 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 diff --git a/python/docSRC/index.rst b/python/docSRC/index.rst index b7cc6d6..dcc6590 100644 --- a/python/docSRC/index.rst +++ b/python/docSRC/index.rst @@ -19,6 +19,7 @@ Contents: creators functions operator + plugins matlab astra .. astra diff --git a/python/docSRC/plugins.rst b/python/docSRC/plugins.rst new file mode 100644 index 0000000..dc7c607 --- /dev/null +++ b/python/docSRC/plugins.rst @@ -0,0 +1,8 @@ +Plugins: the :mod:`plugin` module +========================================= + +.. automodule:: astra.plugin + :members: + :undoc-members: + :show-inheritance: + diff --git a/samples/python/s018_plugin.py b/samples/python/s018_plugin.py new file mode 100644 index 0000000..6677930 --- /dev/null +++ b/samples/python/s018_plugin.py @@ -0,0 +1,138 @@ +#----------------------------------------------------------------------- +#Copyright 2015 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox is free software: you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation, either version 3 of the License, or +#(at your option) any later version. +# +#The Python interface to the ASTRA Toolbox is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +#along with the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np +import six + +# Define the plugin class (has to subclass astra.plugin.base) +# Note that usually, these will be defined in a separate package/module +class SIRTPlugin(astra.plugin.base): + """Example of an ASTRA plugin class, implementing a simple 2D SIRT algorithm. + + Optional options: + + 'rel_factor': relaxation factor + """ + required_options=[] + optional_options=['rel_factor'] + + def initialize(self,cfg): + self.W = astra.OpTomo(cfg['ProjectorId']) + self.vid = cfg['ReconstructionDataId'] + self.sid = cfg['ProjectionDataId'] + try: + self.rel = cfg['option']['rel_factor'] + except KeyError: + self.rel = 1 + + def run(self, its): + v = astra.data2d.get_shared(self.vid) + s = astra.data2d.get_shared(self.sid) + W = self.W + for i in range(its): + v[:] += self.rel*(W.T*(s - (W*v).reshape(s.shape))).reshape(v.shape)/s.size + +if __name__=='__main__': + + vol_geom = astra.create_vol_geom(256, 256) + proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) + + # As before, create a sinogram from a phantom + import scipy.io + P = scipy.io.loadmat('phantom.mat')['phantom256'] + proj_id = astra.create_projector('cuda',proj_geom,vol_geom) + + # construct the OpTomo object + W = astra.OpTomo(proj_id) + + sinogram = W * P + sinogram = sinogram.reshape([180, 384]) + + # Register the plugin with ASTRA + # A default set of plugins to load can be defined in: + # - /etc/astra-toolbox/plugins.txt + # - [ASTRA_INSTALL_PATH]/python/astra/plugins.txt + # - [USER_HOME_PATH]/.astra-toolbox/plugins.txt + # - [ASTRA_PLUGIN_PATH environment variable]/plugins.txt + # In these files, create a separate line for each plugin with: + # [PLUGIN_ASTRA_NAME] [FULL_PLUGIN_CLASS] + # + # So in this case, it would be a line: + # SIRT-PLUGIN s018_plugin.SIRTPlugin + # + astra.plugin.register('SIRT-PLUGIN','s018_plugin.SIRTPlugin') + + # To get help on a registered plugin, use get_help + six.print_(astra.plugin.get_help('SIRT-PLUGIN')) + + # Create data structures + sid = astra.data2d.create('-sino', proj_geom, sinogram) + vid = astra.data2d.create('-vol', vol_geom) + + # Create config using plugin name + cfg = astra.astra_dict('SIRT-PLUGIN') + cfg['ProjectorId'] = proj_id + cfg['ProjectionDataId'] = sid + cfg['ReconstructionDataId'] = vid + + # Create algorithm object + alg_id = astra.algorithm.create(cfg) + + # Run algorithm for 100 iterations + astra.algorithm.run(alg_id, 100) + + # Get reconstruction + rec = astra.data2d.get(vid) + + # Options for the plugin go in cfg['option'] + cfg = astra.astra_dict('SIRT-PLUGIN') + cfg['ProjectorId'] = proj_id + cfg['ProjectionDataId'] = sid + cfg['ReconstructionDataId'] = vid + cfg['option'] = {} + cfg['option']['rel_factor'] = 1.5 + alg_id_rel = astra.algorithm.create(cfg) + astra.algorithm.run(alg_id_rel, 100) + rec_rel = astra.data2d.get(vid) + + # We can also use OpTomo to call the plugin + rec_op = W.reconstruct('SIRT-PLUGIN', sinogram, 100, extraOptions={'rel_factor':1.5}) + + import pylab as pl + pl.gray() + pl.figure(1) + pl.imshow(rec,vmin=0,vmax=1) + pl.figure(2) + pl.imshow(rec_rel,vmin=0,vmax=1) + pl.figure(3) + pl.imshow(rec_op,vmin=0,vmax=1) + pl.show() + + # Clean up. + astra.projector.delete(proj_id) + astra.algorithm.delete([alg_id, alg_id_rel]) + astra.data2d.delete([vid, sid]) diff --git a/src/PluginAlgorithm.cpp b/src/PluginAlgorithm.cpp new file mode 100644 index 0000000..df13f31 --- /dev/null +++ b/src/PluginAlgorithm.cpp @@ -0,0 +1,294 @@ +/* +----------------------------------------------------------------------- +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 "astra/PluginAlgorithm.h" +#include +#include +#include +#include +#include +#include + +namespace astra { + +CPluginAlgorithm::CPluginAlgorithm(PyObject* pyclass){ + instance = PyObject_CallObject(pyclass, NULL); +} + +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) return false; + m_bIsInitialized = true; + Py_DECREF(retVal); + return m_bIsInitialized; +} + +void CPluginAlgorithm::run(int _iNrIterations){ + if(instance==NULL) return; + PyObject *retVal = PyObject_CallMethod(instance, "run", "i",_iNrIterations); + if(retVal==NULL) return; + Py_DECREF(retVal); +} + +const char ps = +#ifdef _WIN32 + '\\'; +#else + '/'; +#endif + +std::vector CPluginAlgorithmFactory::getPluginPathList(){ + std::vector list; + list.push_back("/etc/astra-toolbox"); + PyObject *ret, *retb; + ret = PyObject_CallMethod(inspect,"getfile","O",astra); + if(ret!=NULL){ + retb = PyObject_CallMethod(six,"b","O",ret); + Py_DECREF(ret); + if(retb!=NULL){ + std::string astra_inst (PyBytes_AsString(retb)); + Py_DECREF(retb); + ret = PyObject_CallMethod(ospath,"dirname","s",astra_inst.c_str()); + if(ret!=NULL){ + retb = PyObject_CallMethod(six,"b","O",ret); + Py_DECREF(ret); + if(retb!=NULL){ + list.push_back(std::string(PyBytes_AsString(retb))); + Py_DECREF(retb); + } + } + } + } + ret = PyObject_CallMethod(ospath,"expanduser","s","~"); + if(ret!=NULL){ + retb = PyObject_CallMethod(six,"b","O",ret); + Py_DECREF(ret); + if(retb!=NULL){ + list.push_back(std::string(PyBytes_AsString(retb)) + ps + ".astra-toolbox"); + Py_DECREF(retb); + } + } + const char *envval = getenv("ASTRA_PLUGIN_PATH"); + if(envval!=NULL){ + list.push_back(std::string(envval)); + } + return list; +} + +CPluginAlgorithmFactory::CPluginAlgorithmFactory(){ + Py_Initialize(); + pluginDict = PyDict_New(); + ospath = PyImport_ImportModule("os.path"); + inspect = PyImport_ImportModule("inspect"); + six = PyImport_ImportModule("six"); + astra = PyImport_ImportModule("astra"); + std::vector fls = getPluginPathList(); + std::vector items; + for(unsigned int i=0;i items; + boost::split(items, str, boost::is_any_of(".")); + PyObject *pyclass = PyImport_ImportModule(items[0].c_str()); + if(pyclass==NULL) return NULL; + PyObject *submod = pyclass; + for(unsigned int i=1;i= 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(row[j]))); + } + PyList_SetItem(mat, i, rowlist); + } + return mat; + } + if(str.find(",")!=std::string::npos){ + std::vector vec; + boost::split(vec, str, boost::is_any_of(",")); + PyObject *veclist = PyList_New(vec.size()); + for(unsigned int i=0;i(vec[i]))); + } + return veclist; + } + try{ + return PyLong_FromLong(boost::lexical_cast(str)); + }catch(const boost::bad_lexical_cast &){ + try{ + return PyFloat_FromDouble(boost::lexical_cast(str)); + }catch(const boost::bad_lexical_cast &){ + return pyStringFromString(str); + } + } +} + +PyObject* XMLNode2dict(XMLNode node){ + PyObject *dct = PyDict_New(); + PyObject *opts = PyDict_New(); + if(node.hasAttribute("type")){ + PyObject *obj = pyStringFromString(node.getAttribute("type").c_str()); + PyDict_SetItemString(dct, "type", obj); + Py_DECREF(obj); + } + std::list nodes = node.getNodes(); + std::list::iterator it = nodes.begin(); + while(it!=nodes.end()){ + XMLNode subnode = *it; + if(subnode.getName()=="Option"){ + PyObject *obj = stringToPythonValue(subnode.getAttribute("value")); + 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 \ No newline at end of file -- cgit v1.2.3 From 3d136b7c819b0b142ad056bf01c8c1191eea9ba0 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Fri, 17 Jul 2015 16:22:05 +0200 Subject: Fix numpy lapack loading when running in Matlab --- include/astra/Globals.h | 2 ++ matlab/mex/mexInitFunctions.cpp | 3 +++ src/Globals.cpp | 3 +++ src/PluginAlgorithm.cpp | 29 +++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+) (limited to 'matlab/mex') diff --git a/include/astra/Globals.h b/include/astra/Globals.h index 4de07d1..dc2d7e6 100644 --- a/include/astra/Globals.h +++ b/include/astra/Globals.h @@ -146,6 +146,8 @@ namespace astra { const float32 PIdiv2 = PI / 2; const float32 PIdiv4 = PI / 4; const float32 eps = 1e-7f; + + extern bool running_in_matlab; } //---------------------------------------------------------------------------------------- diff --git a/matlab/mex/mexInitFunctions.cpp b/matlab/mex/mexInitFunctions.cpp index d8a50d7..c11c7d5 100644 --- a/matlab/mex/mexInitFunctions.cpp +++ b/matlab/mex/mexInitFunctions.cpp @@ -17,6 +17,9 @@ void logCallBack(const char *msg, size_t len){ */ void initASTRAMex(){ if(mexIsInitialized) return; + + astra::running_in_matlab=true; + if(!astra::CLogger::setCallbackScreen(&logCallBack)){ mexErrMsgTxt("Error initializing mex functions."); } diff --git a/src/Globals.cpp b/src/Globals.cpp index 813f9c9..904a459 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -28,5 +28,8 @@ $Id$ #include "astra/Globals.h" +namespace astra{ + bool running_in_matlab=false; +} // nothing to see here :) diff --git a/src/PluginAlgorithm.cpp b/src/PluginAlgorithm.cpp index 8ba6631..c26ee3f 100644 --- a/src/PluginAlgorithm.cpp +++ b/src/PluginAlgorithm.cpp @@ -67,8 +67,37 @@ void CPluginAlgorithm::run(int _iNrIterations){ Py_DECREF(retVal); } +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); + } +} + CPluginAlgorithmFactory::CPluginAlgorithmFactory(){ Py_Initialize(); +#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 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 --- include/astra/PluginAlgorithm.h | 3 ++ matlab/mex/astra_mex_plugin_c.cpp | 23 ++++------ python/astra/plugin.py | 71 ++++++++++++----------------- python/astra/plugin_c.pyx | 14 ++++-- samples/python/s018_plugin.py | 23 +++++----- src/PluginAlgorithm.cpp | 95 +++++++++++++++++++++++++++++++-------- 6 files changed, 138 insertions(+), 91 deletions(-) (limited to 'matlab/mex') diff --git a/include/astra/PluginAlgorithm.h b/include/astra/PluginAlgorithm.h index a82c579..b56228e 100644 --- a/include/astra/PluginAlgorithm.h +++ b/include/astra/PluginAlgorithm.h @@ -64,9 +64,12 @@ public: CPluginAlgorithm * getPlugin(std::string name); bool registerPlugin(std::string name, std::string className); + bool registerPlugin(std::string className); bool registerPluginClass(std::string name, PyObject * className); + bool registerPluginClass(PyObject * className); PyObject * getRegistered(); + std::map getRegisteredMap(); std::string getHelp(std::string name); diff --git a/matlab/mex/astra_mex_plugin_c.cpp b/matlab/mex/astra_mex_plugin_c.cpp index 2d9b9a0..177fcf4 100644 --- a/matlab/mex/astra_mex_plugin_c.cpp +++ b/matlab/mex/astra_mex_plugin_c.cpp @@ -37,9 +37,6 @@ $Id$ #include "astra/PluginAlgorithm.h" -#include "Python.h" -#include "bytesobject.h" - using namespace std; using namespace astra; @@ -52,29 +49,25 @@ using namespace astra; void astra_mex_plugin_get_registered(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getSingletonPtr(); - PyObject *dict = fact->getRegistered(); - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next(dict, &pos, &key, &value)) { - mexPrintf("%s: %s\n",PyBytes_AsString(key),PyBytes_AsString(value)); + std::map mp = fact->getRegisteredMap(); + for(std::map::iterator it=mp.begin();it!=mp.end();it++){ + mexPrintf("%s: %s\n",it->first.c_str(), it->second.c_str()); } - Py_DECREF(dict); } //----------------------------------------------------------------------------------------- -/** astra_mex_plugin('register', name, class_name); +/** astra_mex_plugin('register', class_name); * * Register plugin. */ void astra_mex_plugin_register(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { - if (3 <= nrhs) { - string name = mexToString(prhs[1]); - string class_name = mexToString(prhs[2]); + if (2 <= nrhs) { + string class_name = mexToString(prhs[1]); astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getSingletonPtr(); - fact->registerPlugin(name, class_name); + fact->registerPlugin(class_name); }else{ - mexPrintf("astra_mex_plugin('register', name, class_name);\n"); + mexPrintf("astra_mex_plugin('register', class_name);\n"); } } 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() diff --git a/samples/python/s018_plugin.py b/samples/python/s018_plugin.py index 90e09ac..31cca95 100644 --- a/samples/python/s018_plugin.py +++ b/samples/python/s018_plugin.py @@ -38,6 +38,10 @@ class SIRTPlugin(astra.plugin.base): 'rel_factor': relaxation factor (optional) """ + # The astra_name variable defines the name to use to + # call the plugin from ASTRA + astra_name = "SIRT-PLUGIN" + def initialize(self,cfg, rel_factor = 1): self.W = astra.OpTomo(cfg['ProjectorId']) self.vid = cfg['ReconstructionDataId'] @@ -68,18 +72,13 @@ if __name__=='__main__': sinogram = sinogram.reshape([180, 384]) # Register the plugin with ASTRA - # A default set of plugins to load can be defined in: - # - /etc/astra-toolbox/plugins.txt - # - [ASTRA_INSTALL_PATH]/python/astra/plugins.txt - # - [USER_HOME_PATH]/.astra-toolbox/plugins.txt - # - [ASTRA_PLUGIN_PATH environment variable]/plugins.txt - # In these files, create a separate line for each plugin with: - # [PLUGIN_ASTRA_NAME] [FULL_PLUGIN_CLASS] - # - # So in this case, it would be a line: - # SIRT-PLUGIN s018_plugin.SIRTPlugin - # - astra.plugin.register('SIRT-PLUGIN','s018_plugin.SIRTPlugin') + # First we import the package that contains the plugin + import s018_plugin + # Then, we register the plugin class with ASTRA + astra.plugin.register(s018_plugin.SIRTPlugin) + + # Get a list of registered plugins + six.print_(astra.plugin.get_registered()) # To get help on a registered plugin, use get_help six.print_(astra.plugin.get_help('SIRT-PLUGIN')) diff --git a/src/PluginAlgorithm.cpp b/src/PluginAlgorithm.cpp index d6cf731..7f7ff61 100644 --- a/src/PluginAlgorithm.cpp +++ b/src/PluginAlgorithm.cpp @@ -100,7 +100,10 @@ bool CPluginAlgorithm::initialize(const Config& _cfg){ PyObject *cfgDict = XMLNode2dict(_cfg.self); PyObject *retVal = PyObject_CallMethod(instance, "astra_init", "O",cfgDict); Py_DECREF(cfgDict); - if(retVal==NULL) return false; + if(retVal==NULL){ + logPythonError(); + return false; + } m_bIsInitialized = true; Py_DECREF(retVal); return m_bIsInitialized; @@ -108,8 +111,11 @@ bool CPluginAlgorithm::initialize(const Config& _cfg){ void CPluginAlgorithm::run(int _iNrIterations){ if(instance==NULL) return; - PyObject *retVal = PyObject_CallMethod(instance, "astra_run", "i",_iNrIterations); - if(retVal==NULL) return; + PyObject *retVal = PyObject_CallMethod(instance, "run", "i",_iNrIterations); + if(retVal==NULL){ + logPythonError(); + return; + } Py_DECREF(retVal); } @@ -157,18 +163,6 @@ CPluginAlgorithmFactory::~CPluginAlgorithmFactory(){ if(six!=NULL) Py_DECREF(six); } -bool CPluginAlgorithmFactory::registerPlugin(std::string name, std::string className){ - PyObject *str = PyBytes_FromString(className.c_str()); - PyDict_SetItemString(pluginDict, name.c_str(), str); - Py_DECREF(str); - return true; -} - -bool CPluginAlgorithmFactory::registerPluginClass(std::string name, PyObject * className){ - PyDict_SetItemString(pluginDict, name.c_str(), className); - return true; -} - PyObject * getClassFromString(std::string str){ std::vector items; boost::split(items, str, boost::is_any_of(".")); @@ -190,6 +184,43 @@ PyObject * getClassFromString(std::string str){ return pyclass; } +bool CPluginAlgorithmFactory::registerPlugin(std::string name, std::string className){ + PyObject *str = PyBytes_FromString(className.c_str()); + PyDict_SetItemString(pluginDict, name.c_str(), str); + Py_DECREF(str); + return true; +} + +bool CPluginAlgorithmFactory::registerPlugin(std::string className){ + PyObject *pyclass = getClassFromString(className); + if(pyclass==NULL) return false; + bool ret = registerPluginClass(pyclass); + Py_DECREF(pyclass); + return ret; +} + +bool CPluginAlgorithmFactory::registerPluginClass(std::string name, PyObject * className){ + PyDict_SetItemString(pluginDict, name.c_str(), className); + return true; +} + +bool CPluginAlgorithmFactory::registerPluginClass(PyObject * className){ + PyObject *astra_name = PyObject_GetAttrString(className,"astra_name"); + if(astra_name==NULL){ + logPythonError(); + return false; + } + PyObject *retb = PyObject_CallMethod(six,"b","O",astra_name); + if(retb!=NULL){ + PyDict_SetItemString(pluginDict,PyBytes_AsString(retb),className); + Py_DECREF(retb); + }else{ + logPythonError(); + } + Py_DECREF(astra_name); + return true; +} + CPluginAlgorithm * CPluginAlgorithmFactory::getPlugin(std::string name){ PyObject *className = PyDict_GetItemString(pluginDict, name.c_str()); if(className==NULL) return NULL; @@ -212,12 +243,34 @@ PyObject * CPluginAlgorithmFactory::getRegistered(){ return pluginDict; } +std::map CPluginAlgorithmFactory::getRegisteredMap(){ + std::map ret; + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(pluginDict, &pos, &key, &value)) { + PyObject * keyb = PyObject_Bytes(key); + PyObject * valb = PyObject_Bytes(value); + ret[PyBytes_AsString(keyb)] = PyBytes_AsString(valb); + Py_DECREF(keyb); + Py_DECREF(valb); + } + return ret; +} + std::string CPluginAlgorithmFactory::getHelp(std::string name){ PyObject *className = PyDict_GetItemString(pluginDict, name.c_str()); - if(className==NULL) return ""; - std::string str = std::string(PyBytes_AsString(className)); + if(className==NULL){ + ASTRA_ERROR("Plugin %s not found!",name.c_str()); + return ""; + } std::string ret = ""; - PyObject *pyclass = getClassFromString(str); + 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); @@ -228,9 +281,13 @@ std::string CPluginAlgorithmFactory::getHelp(std::string name){ ret = std::string(PyBytes_AsString(retb)); Py_DECREF(retb); } + }else{ + logPythonError(); } } - Py_DECREF(pyclass); + if(PyBytes_Check(className)){ + Py_DECREF(pyclass); + } return ret; } -- cgit v1.2.3 From 11717f66b49fbe41faf923f267c6893ce9af46ad Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 17 Sep 2015 16:54:37 +0200 Subject: Use mxLogical instead of bool. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should improve compatibility with Octave according to Christian Häggström. --- matlab/mex/astra_mex_data2d_c.cpp | 4 ++-- matlab/mex/astra_mex_matrix_c.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_data2d_c.cpp b/matlab/mex/astra_mex_data2d_c.cpp index 909d229..935e476 100644 --- a/matlab/mex/astra_mex_data2d_c.cpp +++ b/matlab/mex/astra_mex_data2d_c.cpp @@ -222,7 +222,7 @@ void astra_mex_data2d_create(int& nlhs, mxArray* plhs[], int& nrhs, const mxArra // logical data if (mxIsLogical(prhs[3])) { - bool* pbMatlabData = mxGetLogicals(prhs[3]); + mxLogical* pbMatlabData = mxGetLogicals(prhs[3]); int i = 0; int col, row; for (col = 0; col < dims[1]; ++col) { @@ -322,7 +322,7 @@ void astra_mex_data2d_store(int nlhs, mxArray* plhs[], int nrhs, const mxArray* // logical data if (mxIsLogical(prhs[2])) { - bool* pbMatlabData = mxGetLogicals(prhs[2]); + mxLogical* pbMatlabData = mxGetLogicals(prhs[2]); int i = 0; int col, row; for (col = 0; col < dims[1]; ++col) { diff --git a/matlab/mex/astra_mex_matrix_c.cpp b/matlab/mex/astra_mex_matrix_c.cpp index aa31383..e07ddb6 100644 --- a/matlab/mex/astra_mex_matrix_c.cpp +++ b/matlab/mex/astra_mex_matrix_c.cpp @@ -112,7 +112,7 @@ static bool matlab_to_astra(const mxArray* _rhs, CSparseMatrix* _pMatrix) mwIndex *colStarts = mxGetJc(_rhs); mwIndex *rowIndices = mxGetIr(_rhs); double *floatValues = 0; - bool *boolValues = 0; + mxLogical *boolValues = 0; bool bLogical = mxIsLogical(_rhs); if (bLogical) boolValues = mxGetLogicals(_rhs); -- cgit v1.2.3 From 1cc67c1e4d9b6b24c096f52d6f086a3f224ece8a Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 7 Oct 2015 17:29:20 +0200 Subject: Add astra_mex_direct('FP3D'/'BP3D', ...) --- build/linux/Makefile.in | 3 +- matlab/mex/astra_mex_direct_c.cpp | 332 ++++++++++++++++++++++++++++++++++++++ matlab/tools/astra_mex_direct.m | 24 +++ 3 files changed, 358 insertions(+), 1 deletion(-) create mode 100755 matlab/mex/astra_mex_direct_c.cpp create mode 100644 matlab/tools/astra_mex_direct.m (limited to 'matlab/mex') diff --git a/build/linux/Makefile.in b/build/linux/Makefile.in index 2d862f2..abbebe2 100644 --- a/build/linux/Makefile.in +++ b/build/linux/Makefile.in @@ -232,7 +232,8 @@ MATLAB_MEX=\ matlab/mex/astra_mex_projector_c.$(MEXSUFFIX) \ matlab/mex/astra_mex_projector3d_c.$(MEXSUFFIX) \ matlab/mex/astra_mex_log_c.$(MEXSUFFIX) \ - matlab/mex/astra_mex_data3d_c.$(MEXSUFFIX) + matlab/mex/astra_mex_data3d_c.$(MEXSUFFIX) \ + matlab/mex/astra_mex_direct_c.$(MEXSUFFIX) OBJECT_DIRS = src/ tests/ cuda/2d/ cuda/3d/ matlab/mex/ ./ diff --git a/matlab/mex/astra_mex_direct_c.cpp b/matlab/mex/astra_mex_direct_c.cpp new file mode 100755 index 0000000..94eb1cd --- /dev/null +++ b/matlab/mex/astra_mex_direct_c.cpp @@ -0,0 +1,332 @@ +/* +----------------------------------------------------------------------- +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$ +*/ + +/** \file astra_mex_direct_c.cpp + * + * \brief Utility functions for low-overhead FP and BP calls. + */ +#include +#include "mexHelpFunctions.h" +#include "mexCopyDataHelpFunctions.h" +#include "mexDataManagerHelpFunctions.h" + +#include + +#include "astra/Globals.h" + +#include "astra/AstraObjectManager.h" + +#include "astra/Float32ProjectionData2D.h" +#include "astra/Float32VolumeData2D.h" +#include "astra/CudaProjector3D.h" +#include "astra/Projector3D.h" +#include "astra/Float32ProjectionData3DMemory.h" +#include "astra/Float32VolumeData3DMemory.h" + +#include "astra/CudaForwardProjectionAlgorithm3D.h" + +#include "astra/CudaBackProjectionAlgorithm3D.h" + +using namespace std; +using namespace astra; + +#define USE_MATLAB_UNDOCUMENTED + + +class CFloat32CustomMemory_simple : public astra::CFloat32CustomMemory { +public: + CFloat32CustomMemory_simple(float *ptr) { m_fPtr = ptr; } + ~CFloat32CustomMemory_simple() { } +}; + +#ifdef ASTRA_CUDA + +//----------------------------------------------------------------------------------------- +/** + * projection = astra_mex_direct_c('FP3D', projector_id, volume); + * Both 'projection' and 'volume' are Matlab arrays. + */ +void astra_mex_direct_fp3d(int& nlhs, mxArray* plhs[], int& nrhs, const mxArray* prhs[]) +{ + // TODO: Add an optional way of specifying extra options + + if (nrhs < 3) { + mexErrMsgTxt("Not enough arguments. Syntax: astra_mex_direct_c('FP3D', projector_id, data)"); + return; + } + + int iPid = (int)(mxGetScalar(prhs[1])); + astra::CProjector3D* pProjector; + pProjector = astra::CProjector3DManager::getSingleton().get(iPid); + if (!pProjector) { + mexErrMsgTxt("Projector not found."); + return; + } + if (!pProjector->isInitialized()) { + mexErrMsgTxt("Projector not initialized."); + return; + } + bool isCuda = false; + if (dynamic_cast(pProjector)) + isCuda = true; + if (!isCuda) { + mexErrMsgTxt("Only CUDA projectors are currently supported."); + return; + } + + astra::CVolumeGeometry3D* pVolGeom = pProjector->getVolumeGeometry(); + astra::CProjectionGeometry3D* pProjGeom = pProjector->getProjectionGeometry(); + + const mxArray* const data = prhs[2]; + if (!checkDataType(data)) { + mexErrMsgTxt("Data must be single or double."); + return; + } + + if (!checkDataSize(data, pVolGeom)) { + mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry."); + return; + } + + + // Allocate input data + astra::CFloat32VolumeData3DMemory* pInput; + if (mxIsSingle(data)) { + astra::CFloat32CustomMemory* m = new CFloat32CustomMemory_simple((float *)mxGetData(data)); + pInput = new astra::CFloat32VolumeData3DMemory(pVolGeom, m); + } else { + pInput = new astra::CFloat32VolumeData3DMemory(pVolGeom); + copyMexToCFloat32Array(data, pInput->getData(), pInput->getSize()); + } + + + // Allocate output data + // If the input is single, we also allocate single output. + // Otherwise, double. + astra::CFloat32ProjectionData3DMemory* pOutput; + mxArray *pOutputMx; + if (mxIsSingle(data)) { + mwSize dims[3]; + dims[0] = pProjGeom->getDetectorColCount(); + dims[1] = pProjGeom->getProjectionCount(); + dims[2] = pProjGeom->getDetectorRowCount(); + pOutputMx = mxCreateNumericArray(3, dims, mxSINGLE_CLASS, mxREAL); + + astra::CFloat32CustomMemory* m = new CFloat32CustomMemory_simple((float *)mxGetData(pOutputMx)); + pOutput = new astra::CFloat32ProjectionData3DMemory(pProjGeom, m); + } else { + pOutput = new astra::CFloat32ProjectionData3DMemory(pProjGeom); + } + + // Perform FP + + astra::CCudaForwardProjectionAlgorithm3D* pAlg; + pAlg = new astra::CCudaForwardProjectionAlgorithm3D(); + pAlg->initialize(pProjector, pOutput, pInput); + + if (!pAlg->isInitialized()) { + mexErrMsgTxt("Error initializing algorithm."); + // TODO: Delete pOutputMx? + delete pAlg; + delete pInput; + delete pOutput; + return; + } + + pAlg->run(); + + delete pAlg; + + + if (mxIsSingle(data)) { + + } else { + pOutputMx = createEquivMexArray(pOutput); + copyCFloat32ArrayToMex(pOutput->getData(), pOutputMx); + } + plhs[0] = pOutputMx; + + delete pOutput; + delete pInput; +} +//----------------------------------------------------------------------------------------- +/** + * projection = astra_mex_direct_c('BP3D', projector_id, volume); + * Both 'projection' and 'volume' are Matlab arrays. + */ +void astra_mex_direct_bp3d(int& nlhs, mxArray* plhs[], int& nrhs, const mxArray* prhs[]) +{ + // TODO: Add an optional way of specifying extra options + + if (nrhs < 3) { + mexErrMsgTxt("Not enough arguments. Syntax: astra_mex_direct_c('BP3D', projector_id, data)"); + return; + } + + int iPid = (int)(mxGetScalar(prhs[1])); + astra::CProjector3D* pProjector; + pProjector = astra::CProjector3DManager::getSingleton().get(iPid); + if (!pProjector) { + mexErrMsgTxt("Projector not found."); + return; + } + if (!pProjector->isInitialized()) { + mexErrMsgTxt("Projector not initialized."); + return; + } + bool isCuda = false; + if (dynamic_cast(pProjector)) + isCuda = true; + if (!isCuda) { + mexErrMsgTxt("Only CUDA projectors are currently supported."); + return; + } + + astra::CVolumeGeometry3D* pVolGeom = pProjector->getVolumeGeometry(); + astra::CProjectionGeometry3D* pProjGeom = pProjector->getProjectionGeometry(); + + const mxArray* const data = prhs[2]; + if (!checkDataType(data)) { + mexErrMsgTxt("Data must be single or double."); + return; + } + + if (!checkDataSize(data, pProjGeom)) { + mexErrMsgTxt("The dimensions of the data do not match those specified in the geometry."); + return; + } + + + // Allocate input data + astra::CFloat32ProjectionData3DMemory* pInput; + if (mxIsSingle(data)) { + astra::CFloat32CustomMemory* m = new CFloat32CustomMemory_simple((float *)mxGetData(data)); + pInput = new astra::CFloat32ProjectionData3DMemory(pProjGeom, m); + } else { + pInput = new astra::CFloat32ProjectionData3DMemory(pProjGeom); + copyMexToCFloat32Array(data, pInput->getData(), pInput->getSize()); + } + + + // Allocate output data + // If the input is single, we also allocate single output. + // Otherwise, double. + astra::CFloat32VolumeData3DMemory* pOutput; + mxArray *pOutputMx; + if (mxIsSingle(data)) { + mwSize dims[3]; + dims[0] = pVolGeom->getGridColCount(); + dims[1] = pVolGeom->getGridRowCount(); + dims[2] = pVolGeom->getGridSliceCount(); + pOutputMx = mxCreateNumericArray(3, dims, mxSINGLE_CLASS, mxREAL); + + astra::CFloat32CustomMemory* m = new CFloat32CustomMemory_simple((float *)mxGetData(pOutputMx)); + pOutput = new astra::CFloat32VolumeData3DMemory(pVolGeom, m); + } else { + pOutput = new astra::CFloat32VolumeData3DMemory(pVolGeom); + } + + // Perform BP + + astra::CCudaBackProjectionAlgorithm3D* pAlg; + pAlg = new astra::CCudaBackProjectionAlgorithm3D(); + pAlg->initialize(pProjector, pInput, pOutput); + + if (!pAlg->isInitialized()) { + mexErrMsgTxt("Error initializing algorithm."); + // TODO: Delete pOutputMx? + delete pAlg; + delete pInput; + delete pOutput; + return; + } + + pAlg->run(); + + delete pAlg; + + + if (mxIsSingle(data)) { + + } else { + pOutputMx = createEquivMexArray(pOutput); + copyCFloat32ArrayToMex(pOutput->getData(), pOutputMx); + } + plhs[0] = pOutputMx; + + delete pOutput; + delete pInput; +} + +#endif + +//----------------------------------------------------------------------------------------- + +static void printHelp() +{ + mexPrintf("Please specify a mode of operation.\n"); + mexPrintf("Valid modes: FP3D, BP3D\n"); +} + + +//----------------------------------------------------------------------------------------- +/** + * ... = astra_mex_direct_c(mode,...); + */ +void mexFunction(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + + // INPUT: Mode + string sMode; + if (1 <= nrhs) { + sMode = mexToString(prhs[0]); + } else { + printHelp(); + return; + } + +#ifndef ASTRA_CUDA + mexErrMsgTxt("Only CUDA projectors are currently supported."); + return; +#else + + // 3D data + if (sMode == "FP3D") { + astra_mex_direct_fp3d(nlhs, plhs, nrhs, prhs); + } else if (sMode == "BP3D") { + astra_mex_direct_bp3d(nlhs, plhs, nrhs, prhs); + } else { + printHelp(); + } +#endif + + return; +} + + diff --git a/matlab/tools/astra_mex_direct.m b/matlab/tools/astra_mex_direct.m new file mode 100644 index 0000000..58c4fd2 --- /dev/null +++ b/matlab/tools/astra_mex_direct.m @@ -0,0 +1,24 @@ +function [varargout] = astra_mex_direct(varargin) +%------------------------------------------------------------------------ +% Reference page in Help browser +% astra_mex_data3d. +%------------------------------------------------------------------------ +%------------------------------------------------------------------------ +% This file is part of the ASTRA Toolbox +% +% Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp +% 2014-2015, CWI, Amsterdam +% License: Open Source under GPLv3 +% Contact: astra@uantwerpen.be +% Website: http://sf.net/projects/astra-toolbox +%------------------------------------------------------------------------ +% $Id$ +if nargout == 0 + astra_mex_direct_c(varargin{:}); + if exist('ans','var') + varargout{1} = ans; + end +else + varargout = cell(1,nargout); + [varargout{:}] = astra_mex_direct_c(varargin{:}); +end -- cgit v1.2.3 From 793afbc3fa1cca64292716869e503cb66942606d Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 7 Oct 2015 17:29:40 +0200 Subject: Build astra_mex_direct in MSVC --- astra_vc09.sln | 22 ++ astra_vc11.sln | 22 ++ build/msvc/gen.py | 15 +- matlab/mex/astra_mex_direct_vc09.vcproj | 612 +++++++++++++++++++++++++++++++ matlab/mex/astra_mex_direct_vc11.vcxproj | 306 ++++++++++++++++ 5 files changed, 975 insertions(+), 2 deletions(-) create mode 100644 matlab/mex/astra_mex_direct_vc09.vcproj create mode 100644 matlab/mex/astra_mex_direct_vc11.vcxproj (limited to 'matlab/mex') diff --git a/astra_vc09.sln b/astra_vc09.sln index 9b93a0f..371e9b1 100644 --- a/astra_vc09.sln +++ b/astra_vc09.sln @@ -48,6 +48,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "astra_mex_log", "matlab\mex {12926444-6723-46A8-B388-12E65E0577FA} = {12926444-6723-46A8-B388-12E65E0577FA} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "astra_mex_direct", "matlab\mex\astra_mex_direct_vc09.vcproj", "{85FE09A6-FA49-4314-A2B1-59D77C7442A8}" + ProjectSection(ProjectDependencies) = postProject + {12926444-6723-46A8-B388-12E65E0577FA} = {12926444-6723-46A8-B388-12E65E0577FA} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_CUDA|Win32 = Debug_CUDA|Win32 @@ -204,6 +209,22 @@ Global {CA2840B3-DA68-41B5-AC57-F5DFD20ED8F8}.Release|Win32.Build.0 = Release|Win32 {CA2840B3-DA68-41B5-AC57-F5DFD20ED8F8}.Release|x64.ActiveCfg = Release|x64 {CA2840B3-DA68-41B5-AC57-F5DFD20ED8F8}.Release|x64.Build.0 = Release|x64 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Debug_CUDA|Win32.ActiveCfg = Debug_CUDA|Win32 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Debug_CUDA|Win32.Build.0 = Debug_CUDA|Win32 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Debug_CUDA|x64.ActiveCfg = Debug_CUDA|x64 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Debug_CUDA|x64.Build.0 = Debug_CUDA|x64 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Debug|Win32.ActiveCfg = Debug|Win32 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Debug|Win32.Build.0 = Debug|Win32 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Debug|x64.ActiveCfg = Debug|x64 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Debug|x64.Build.0 = Debug|x64 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Release_CUDA|Win32.ActiveCfg = Release_CUDA|Win32 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Release_CUDA|Win32.Build.0 = Release_CUDA|Win32 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Release_CUDA|x64.ActiveCfg = Release_CUDA|x64 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Release_CUDA|x64.Build.0 = Release_CUDA|x64 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Release|Win32.ActiveCfg = Release|Win32 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Release|Win32.Build.0 = Release|Win32 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Release|x64.ActiveCfg = Release|x64 + {85FE09A6-FA49-4314-A2B1-59D77C7442A8}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -217,5 +238,6 @@ Global {4DD6056F-8EEE-4C9A-B2A9-923F01A32E97} = {33EF0AC5-B475-40BF-BAE5-67075B204D10} {F94CCD79-AA11-42DF-AC8A-6C9D2238A883} = {33EF0AC5-B475-40BF-BAE5-67075B204D10} {CA2840B3-DA68-41B5-AC57-F5DFD20ED8F8} = {33EF0AC5-B475-40BF-BAE5-67075B204D10} + {85FE09A6-FA49-4314-A2B1-59D77C7442A8} = {33EF0AC5-B475-40BF-BAE5-67075B204D10} EndGlobalSection EndGlobal diff --git a/astra_vc11.sln b/astra_vc11.sln index 2832eab..92fb584 100644 --- a/astra_vc11.sln +++ b/astra_vc11.sln @@ -48,6 +48,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "astra_mex_log", "matlab\mex {BE9F1326-527C-4284-AE2C-D1E25D539CEA} = {BE9F1326-527C-4284-AE2C-D1E25D539CEA} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "astra_mex_direct", "matlab\mex\astra_mex_direct_vc11.vcxproj", "{0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}" + ProjectSection(ProjectDependencies) = postProject + {BE9F1326-527C-4284-AE2C-D1E25D539CEA} = {BE9F1326-527C-4284-AE2C-D1E25D539CEA} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_CUDA|Win32 = Debug_CUDA|Win32 @@ -204,6 +209,22 @@ Global {03B833F5-4FD6-4FBE-AAF4-E3305CD56D2E}.Release|Win32.Build.0 = Release|Win32 {03B833F5-4FD6-4FBE-AAF4-E3305CD56D2E}.Release|x64.ActiveCfg = Release|x64 {03B833F5-4FD6-4FBE-AAF4-E3305CD56D2E}.Release|x64.Build.0 = Release|x64 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Debug_CUDA|Win32.ActiveCfg = Debug_CUDA|Win32 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Debug_CUDA|Win32.Build.0 = Debug_CUDA|Win32 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Debug_CUDA|x64.ActiveCfg = Debug_CUDA|x64 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Debug_CUDA|x64.Build.0 = Debug_CUDA|x64 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Debug|Win32.ActiveCfg = Debug|Win32 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Debug|Win32.Build.0 = Debug|Win32 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Debug|x64.ActiveCfg = Debug|x64 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Debug|x64.Build.0 = Debug|x64 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Release_CUDA|Win32.ActiveCfg = Release_CUDA|Win32 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Release_CUDA|Win32.Build.0 = Release_CUDA|Win32 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Release_CUDA|x64.ActiveCfg = Release_CUDA|x64 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Release_CUDA|x64.Build.0 = Release_CUDA|x64 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Release|Win32.ActiveCfg = Release|Win32 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Release|Win32.Build.0 = Release|Win32 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Release|x64.ActiveCfg = Release|x64 + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -217,5 +238,6 @@ Global {4DD6056F-8EEE-4C9A-B2A9-923F01A32E97} = {5E99A109-374E-4102-BE9B-99BA1FA8AA30} {F94CCD79-AA11-42DF-AC8A-6C9D2238A883} = {5E99A109-374E-4102-BE9B-99BA1FA8AA30} {03B833F5-4FD6-4FBE-AAF4-E3305CD56D2E} = {5E99A109-374E-4102-BE9B-99BA1FA8AA30} + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7} = {5E99A109-374E-4102-BE9B-99BA1FA8AA30} EndGlobalSection EndGlobal diff --git a/build/msvc/gen.py b/build/msvc/gen.py index aeca3b0..a9bc494 100644 --- a/build/msvc/gen.py +++ b/build/msvc/gen.py @@ -24,6 +24,7 @@ P4 = create_mex_project("astra_mex_matrix", "9D041710-2119-4230-BCF2-5FBE753FDE4 P5 = create_mex_project("astra_mex_projector", "4DD6056F-8EEE-4C9A-B2A9-923F01A32E97", "4DD6056F-8EEE-4C9A-B2A9-923F01A32E97") P6 = create_mex_project("astra_mex_projector3d", "F94CCD79-AA11-42DF-AC8A-6C9D2238A883", "F94CCD79-AA11-42DF-AC8A-6C9D2238A883") P7 = create_mex_project("astra_mex_log", "03B833F5-4FD6-4FBE-AAF4-E3305CD56D2E", "CA2840B3-DA68-41B5-AC57-F5DFD20ED8F8") +P8 = create_mex_project("astra_mex_direct", "0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7", "85FE09A6-FA49-4314-A2B1-59D77C7442A8") F_astra_mex = { "type": siguid, "name": "astra_mex", @@ -31,7 +32,7 @@ F_astra_mex = { "type": siguid, "file09": "astra_mex", "uuid11": "5E99A109-374E-4102-BE9B-99BA1FA8AA30", "uuid09": "33EF0AC5-B475-40BF-BAE5-67075B204D10", - "entries": [ P0, P1, P2, P3, P4, P5, P6, P7 ] } + "entries": [ P0, P1, P2, P3, P4, P5, P6, P7, P8 ] } P0["files"] = [ @@ -98,6 +99,14 @@ P7["files"] = [ "mexInitFunctions.cpp", "mexInitFunctions.h", ] +P8["files"] = [ +"astra_mex_direct_c.cpp", +"mexHelpFunctions.cpp", +"mexHelpFunctions.h", +"mexInitFunctions.cpp", +"mexInitFunctions.h", +] + @@ -407,7 +416,7 @@ for f in P_astra["filters"]: P_astra["files"].extend(P_astra["filters"][f][1:]) P_astra["files"].sort() -projects = [ P_astra, F_astra_mex, P0, P1, P2, P3, P4, P5, P6, P7 ] +projects = [ P_astra, F_astra_mex, P0, P1, P2, P3, P4, P5, P6, P7, P8 ] bom = "\xef\xbb\xbf" @@ -1111,6 +1120,7 @@ if sys.argv[1] in ["vc11", "all"]: write_mex_project11(P5) write_mex_project11(P6) write_mex_project11(P7) + write_mex_project11(P8) if sys.argv[1] in ["vc09", "all"]: # HACK @@ -1126,3 +1136,4 @@ if sys.argv[1] in ["vc09", "all"]: write_mex_project09(P5) write_mex_project09(P6) write_mex_project09(P7) + write_mex_project09(P8) diff --git a/matlab/mex/astra_mex_direct_vc09.vcproj b/matlab/mex/astra_mex_direct_vc09.vcproj new file mode 100644 index 0000000..04b49ac --- /dev/null +++ b/matlab/mex/astra_mex_direct_vc09.vcproj @@ -0,0 +1,612 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/matlab/mex/astra_mex_direct_vc11.vcxproj b/matlab/mex/astra_mex_direct_vc11.vcxproj new file mode 100644 index 0000000..15c3c06 --- /dev/null +++ b/matlab/mex/astra_mex_direct_vc11.vcxproj @@ -0,0 +1,306 @@ + + + + + Debug_CUDA + Win32 + + + Debug_CUDA + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release_CUDA + Win32 + + + Release_CUDA + x64 + + + Release + Win32 + + + Release + x64 + + + + astra_mex_direct + {0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7} + astraMatlab + + + + DynamicLibrary + v110 + + + DynamicLibrary + v110 + + + DynamicLibrary + v110 + + + DynamicLibrary + v110 + + + DynamicLibrary + v110 + + + DynamicLibrary + v110 + + + DynamicLibrary + v110 + + + DynamicLibrary + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>11.0.60610.1 + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(OutDir)obj\$(ProjectName)\ + $(ProjectName)_c + .mexw32 + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(OutDir)obj\$(ProjectName)\ + $(ProjectName)_c + .mexw64 + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(OutDir)obj\$(ProjectName)\ + $(ProjectName)_c + .mexw32 + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(OutDir)obj\$(ProjectName)\ + $(ProjectName)_c + .mexw64 + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(OutDir)obj\$(ProjectName)\ + $(ProjectName)_c + .mexw32 + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(OutDir)obj\$(ProjectName)\ + $(ProjectName)_c + .mexw64 + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(OutDir)obj\$(ProjectName)\ + $(ProjectName)_c + .mexw32 + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(OutDir)obj\$(ProjectName)\ + $(ProjectName)_c + .mexw64 + + + + MultiThreadedDebugDLL + $(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories) + true + StreamingSIMDExtensions2 + Disabled + ASTRA_CUDA;__SSE2__;%(PreprocessorDefinitions) + true + + + $(OutDir)$(ProjectName)_c.mexw32 + AstraCuda32D.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies) + ..\..\lib\win32\;..\..\bin\win32\Debug_CUDA;$(MATLAB_ROOT)\extern\lib\win32\microsoft;%(AdditionalLibraryDirectories) + mex.def + true + + + + + MultiThreadedDebugDLL + $(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories) + true + Disabled + ASTRA_CUDA;__SSE2__;%(PreprocessorDefinitions) + true + + + $(OutDir)$(ProjectName)_c.mexw64 + AstraCuda64D.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies) + ..\..\lib\x64\;..\..\bin\x64\Debug_CUDA;$(MATLAB_ROOT)\extern\lib\win64\microsoft;%(AdditionalLibraryDirectories) + mex.def + true + + + + + MultiThreadedDebugDLL + $(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories) + true + StreamingSIMDExtensions2 + Disabled + __SSE2__;%(PreprocessorDefinitions) + true + + + $(OutDir)$(ProjectName)_c.mexw32 + Astra32D.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies) + ..\..\lib\win32\;..\..\bin\win32\Debug;$(MATLAB_ROOT)\extern\lib\win32\microsoft;%(AdditionalLibraryDirectories) + mex.def + true + + + + + MultiThreadedDebugDLL + $(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories) + true + Disabled + __SSE2__;%(PreprocessorDefinitions) + true + + + $(OutDir)$(ProjectName)_c.mexw64 + Astra64D.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies) + ..\..\lib\x64\;..\..\bin\x64\Debug;$(MATLAB_ROOT)\extern\lib\win64\microsoft;%(AdditionalLibraryDirectories) + mex.def + true + + + + + MultiThreadedDLL + $(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories) + true + StreamingSIMDExtensions2 + MaxSpeed + ASTRA_CUDA;__SSE2__;%(PreprocessorDefinitions) + true + + + $(OutDir)$(ProjectName)_c.mexw32 + AstraCuda32.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies) + ..\..\lib\win32\;..\..\bin\win32\Release_CUDA;$(MATLAB_ROOT)\extern\lib\win32\microsoft;%(AdditionalLibraryDirectories) + mex.def + true + + + + + MultiThreadedDLL + $(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories) + true + MaxSpeed + ASTRA_CUDA;__SSE2__;%(PreprocessorDefinitions) + true + + + $(OutDir)$(ProjectName)_c.mexw64 + AstraCuda64.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies) + ..\..\lib\x64\;..\..\bin\x64\Release_CUDA;$(MATLAB_ROOT)\extern\lib\win64\microsoft;%(AdditionalLibraryDirectories) + mex.def + true + + + + + MultiThreadedDLL + $(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories) + true + StreamingSIMDExtensions2 + MaxSpeed + __SSE2__;%(PreprocessorDefinitions) + true + + + $(OutDir)$(ProjectName)_c.mexw32 + Astra32.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies) + ..\..\lib\win32\;..\..\bin\win32\Release;$(MATLAB_ROOT)\extern\lib\win32\microsoft;%(AdditionalLibraryDirectories) + mex.def + true + + + + + MultiThreadedDLL + $(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories) + true + MaxSpeed + __SSE2__;%(PreprocessorDefinitions) + true + + + $(OutDir)$(ProjectName)_c.mexw64 + Astra64.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies) + ..\..\lib\x64\;..\..\bin\x64\Release;$(MATLAB_ROOT)\extern\lib\win64\microsoft;%(AdditionalLibraryDirectories) + mex.def + true + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 37dd051faf2a8085c1abb5623eb5e79363471642 Mon Sep 17 00:00:00 2001 From: Nicola Vigano Date: Thu, 2 Apr 2015 17:07:25 +0200 Subject: astra_mex_direct: Don't initialize newly allocated mxArray This avoids letting matlab initialize the memory we will overwrite shortly after. --- matlab/mex/astra_mex_direct_c.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_direct_c.cpp b/matlab/mex/astra_mex_direct_c.cpp index 94eb1cd..38b3f59 100755 --- a/matlab/mex/astra_mex_direct_c.cpp +++ b/matlab/mex/astra_mex_direct_c.cpp @@ -135,7 +135,15 @@ void astra_mex_direct_fp3d(int& nlhs, mxArray* plhs[], int& nrhs, const mxArray* dims[0] = pProjGeom->getDetectorColCount(); dims[1] = pProjGeom->getProjectionCount(); dims[2] = pProjGeom->getDetectorRowCount(); - pOutputMx = mxCreateNumericArray(3, dims, mxSINGLE_CLASS, mxREAL); + + // Allocate uninitialized mxArray of size dims. + // (It will be zeroed by CudaForwardProjectionAlgorithm3D) + const mwSize zero_dims[2] = {0, 0}; + pOutputMx = mxCreateNumericArray(2, zero_dims, mxSINGLE_CLASS, mxREAL); + mxSetDimensions(pOutputMx, dims, 3); + const mwSize num_elems = mxGetNumberOfElements(pOutputMx); + const mwSize elem_size = mxGetElementSize(pOutputMx); + mxSetData(pOutputMx, mxMalloc(elem_size * num_elems)); astra::CFloat32CustomMemory* m = new CFloat32CustomMemory_simple((float *)mxGetData(pOutputMx)); pOutput = new astra::CFloat32ProjectionData3DMemory(pProjGeom, m); @@ -243,7 +251,15 @@ void astra_mex_direct_bp3d(int& nlhs, mxArray* plhs[], int& nrhs, const mxArray* dims[0] = pVolGeom->getGridColCount(); dims[1] = pVolGeom->getGridRowCount(); dims[2] = pVolGeom->getGridSliceCount(); - pOutputMx = mxCreateNumericArray(3, dims, mxSINGLE_CLASS, mxREAL); + + // Allocate uninitialized mxArray of size dims. + // (It will be zeroed by CudaBackProjectionAlgorithm3D) + const mwSize zero_dims[2] = {0, 0}; + pOutputMx = mxCreateNumericArray(2, zero_dims, mxSINGLE_CLASS, mxREAL); + mxSetDimensions(pOutputMx, dims, 3); + const mwSize num_elems = mxGetNumberOfElements(pOutputMx); + const mwSize elem_size = mxGetElementSize(pOutputMx); + mxSetData(pOutputMx, mxMalloc(elem_size * num_elems)); astra::CFloat32CustomMemory* m = new CFloat32CustomMemory_simple((float *)mxGetData(pOutputMx)); pOutput = new astra::CFloat32VolumeData3DMemory(pVolGeom, m); -- cgit v1.2.3 From 6d57f7874713e6632c2e49590538c6a48ddcc311 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 2 Dec 2015 14:53:36 +0100 Subject: Fix Windows builds of astra_mex_direct --- build/msvc/gen.py | 4 ++++ matlab/mex/astra_mex_direct_vc09.vcproj | 16 ++++++++++++++++ matlab/mex/astra_mex_direct_vc11.vcxproj | 4 ++++ 3 files changed, 24 insertions(+) (limited to 'matlab/mex') diff --git a/build/msvc/gen.py b/build/msvc/gen.py index a9bc494..72d4582 100644 --- a/build/msvc/gen.py +++ b/build/msvc/gen.py @@ -103,6 +103,10 @@ P8["files"] = [ "astra_mex_direct_c.cpp", "mexHelpFunctions.cpp", "mexHelpFunctions.h", +"mexCopyDataHelpFunctions.cpp", +"mexCopyDataHelpFunctions.h", +"mexDataManagerHelpFunctions.cpp", +"mexDataManagerHelpFunctions.h", "mexInitFunctions.cpp", "mexInitFunctions.h", ] diff --git a/matlab/mex/astra_mex_direct_vc09.vcproj b/matlab/mex/astra_mex_direct_vc09.vcproj index 04b49ac..5d27c65 100644 --- a/matlab/mex/astra_mex_direct_vc09.vcproj +++ b/matlab/mex/astra_mex_direct_vc09.vcproj @@ -598,6 +598,22 @@ RelativePath=".\mexHelpFunctions.h" > + + + + + + + + diff --git a/matlab/mex/astra_mex_direct_vc11.vcxproj b/matlab/mex/astra_mex_direct_vc11.vcxproj index 15c3c06..bc2db62 100644 --- a/matlab/mex/astra_mex_direct_vc11.vcxproj +++ b/matlab/mex/astra_mex_direct_vc11.vcxproj @@ -294,10 +294,14 @@ + + + + -- cgit v1.2.3 From fc86917da1a175c04e9bd2e5f0bedb0a48a81c26 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 17 Dec 2015 14:37:41 +0100 Subject: Replace boost::lexical_cast by stringstreams This is to avoid the dependence of lexical_cast on the current locale. The stringstreams used for the new string parsing/output functions are explicitly imbued with the C/classic locale. --- build/linux/configure.ac | 1 - include/astra/Utilities.h | 51 ++++++++++++++++ include/astra/XMLNode.h | 8 +++ matlab/mex/mexHelpFunctions.cpp | 8 +-- matlab/mex/mexHelpFunctions.h | 1 - src/ArtAlgorithm.cpp | 2 - src/BackProjectionAlgorithm.cpp | 2 - src/CglsAlgorithm.cpp | 2 - src/ConeProjectionGeometry3D.cpp | 5 +- src/ConeVecProjectionGeometry3D.cpp | 30 ++++----- src/CudaBackProjectionAlgorithm3D.cpp | 2 - src/CudaCglsAlgorithm3D.cpp | 2 - src/CudaDartMaskAlgorithm.cpp | 5 +- src/CudaDartMaskAlgorithm3D.cpp | 5 +- src/CudaDartSmoothingAlgorithm.cpp | 5 +- src/CudaDartSmoothingAlgorithm3D.cpp | 5 +- src/CudaDataOperationAlgorithm.cpp | 5 +- src/CudaFDKAlgorithm3D.cpp | 2 - src/CudaFilteredBackProjectionAlgorithm.cpp | 13 ++-- src/CudaForwardProjectionAlgorithm.cpp | 8 +-- src/CudaForwardProjectionAlgorithm3D.cpp | 8 +-- src/CudaReconstructionAlgorithm2D.cpp | 2 - src/CudaRoiSelectAlgorithm.cpp | 3 +- src/CudaSirtAlgorithm.cpp | 5 +- src/CudaSirtAlgorithm3D.cpp | 2 - src/FanFlatBeamLineKernelProjector2D.cpp | 1 - src/FanFlatBeamStripKernelProjector2D.cpp | 1 - src/FanFlatProjectionGeometry2D.cpp | 5 +- src/FanFlatVecProjectionGeometry2D.cpp | 15 +++-- src/FilteredBackProjectionAlgorithm.cpp | 8 +-- src/ForwardProjectionAlgorithm.cpp | 12 ++-- src/ParallelBeamBlobKernelProjector2D.cpp | 7 +-- src/ParallelBeamLineKernelProjector2D.cpp | 1 - src/ParallelBeamLinearKernelProjector2D.cpp | 1 - src/ParallelBeamStripKernelProjector2D.cpp | 1 - src/ParallelProjectionGeometry2D.cpp | 1 - src/ParallelProjectionGeometry3D.cpp | 1 - src/ParallelVecProjectionGeometry3D.cpp | 30 ++++----- src/PluginAlgorithm.cpp | 14 ++--- src/ProjectionGeometry2D.cpp | 6 +- src/ProjectionGeometry3D.cpp | 10 ++- src/ReconstructionAlgorithm2D.cpp | 12 ++-- src/ReconstructionAlgorithm3D.cpp | 12 ++-- src/ReconstructionAlgorithmMultiSlice2D.cpp | 8 +-- src/SartAlgorithm.cpp | 2 - src/SirtAlgorithm.cpp | 2 - src/SparseMatrixProjectionGeometry2D.cpp | 3 +- src/SparseMatrixProjector2D.cpp | 1 - src/Utilities.cpp | 95 +++++++++++++++++++++++++++++ src/VolumeGeometry2D.cpp | 5 +- src/VolumeGeometry3D.cpp | 8 +-- src/XMLNode.cpp | 77 +++++++++-------------- 52 files changed, 297 insertions(+), 224 deletions(-) (limited to 'matlab/mex') diff --git a/build/linux/configure.ac b/build/linux/configure.ac index 85e4324..9b6f7ab 100644 --- a/build/linux/configure.ac +++ b/build/linux/configure.ac @@ -73,7 +73,6 @@ AC_SUBST(HAVEBOOSTUTF) AC_SUBST(LIBS_BOOSTUTF) BOOSTok=yes -AC_CHECK_HEADER([boost/lexical_cast.hpp],[],[BOOSTok=no],[]) AC_CHECK_HEADER([boost/any.hpp],[],[BOOSTok=no],[]) dnl AC_CHECK_HEADER([boost/thread.hpp],[],[BOOSTok=no],[]) dnl AC_CHECK_HEADER([boost/bind.hpp],[],[BOOSTok=no],[]) diff --git a/include/astra/Utilities.h b/include/astra/Utilities.h index a3655a8..3ae0e6c 100644 --- a/include/astra/Utilities.h +++ b/include/astra/Utilities.h @@ -39,6 +39,57 @@ namespace astra { +namespace StringUtil { + +// Exception thrown by functions below +class bad_cast : public std::exception { +public: + bad_cast() { } +}; + + +//< Parse string as int. +//< Throw exception on failure. +int stringToInt(const std::string& s); + +//< Parse string as float. +//< Throw exception on failure. +float stringToFloat(const std::string& s); + +//< Parse string as double. +//< Throw exception on failure. +double stringToDouble(const std::string& s); + +template +T stringTo(const std::string& s); + +//< Parse comma/semicolon-separated string as float vector. +//< Throw exception on failure. +std::vector stringToFloatVector(const std::string& s); + +//< Parse comma/semicolon-separated string as double vector. +//< Throw exception on failure. +std::vector stringToDoubleVector(const std::string& s); + +template +std::vector stringToVector(const std::string& s); + + + +//< Generate string from float. +std::string floatToString(float f); + +//< Generate string from double. +std::string doubleToString(double f); + +template +std::string toString(T f); + +} + + + + template std::map mergeMap(std::map _mMap1, std::map _mMap2) { diff --git a/include/astra/XMLNode.h b/include/astra/XMLNode.h index 4d29d5c..7d1edf5 100644 --- a/include/astra/XMLNode.h +++ b/include/astra/XMLNode.h @@ -101,6 +101,12 @@ public: */ string getContent() const; + /** Get the content of the XML node as an integer + * + * @return node content + */ + int getContentInt() const; + /** Get the content of the XML node as a numerical. * * @return node content @@ -152,6 +158,7 @@ public: */ float32 getAttributeNumerical(string _sName, float32 _fDefaultValue = 0) const; double getAttributeNumericalDouble(string _sName, double _fDefaultValue = 0) const; + int getAttributeInt(string _sName, int _fDefaultValue = 0) const; /** Get the value of a boolean attribute. * @@ -186,6 +193,7 @@ public: * @return option value, _fDefaultValue if the option doesn't exist */ float32 getOptionNumerical(string _sKey, float32 _fDefaultValue = 0) const; + int getOptionInt(string _sKey, int _fDefaultValue = 0) const; /** Get the value of an option within this XML Node * diff --git a/matlab/mex/mexHelpFunctions.cpp b/matlab/mex/mexHelpFunctions.cpp index 58e84d2..13c4ade 100644 --- a/matlab/mex/mexHelpFunctions.cpp +++ b/matlab/mex/mexHelpFunctions.cpp @@ -31,9 +31,9 @@ $Id$ * \brief Contains some functions for interfacing matlab with c data structures */ #include "mexHelpFunctions.h" +#include "astra/Utilities.h" #include -#include #include #include #include @@ -58,7 +58,7 @@ string mexToString(const mxArray* pInput) // is scalar? if (mxIsNumeric(pInput) && mxGetM(pInput)*mxGetN(pInput) == 1) { - return boost::lexical_cast(mxGetScalar(pInput)); + return StringUtil::doubleToString(mxGetScalar(pInput)); } return ""; @@ -378,7 +378,7 @@ mxArray* stringToMxArray(std::string input) boost::split(col_strings, row_strings[row], boost::is_any_of(",")); // check size for (unsigned int col = 0; col < col_strings.size(); col++) { - out[col*rows + row] = boost::lexical_cast(col_strings[col]); + out[col*rows + row] = StringUtil::stringToFloat(col_strings[col]); } } return pMatrix; @@ -397,7 +397,7 @@ mxArray* stringToMxArray(std::string input) // loop elements for (unsigned int i = 0; i < items.size(); i++) { - out[i] = boost::lexical_cast(items[i]); + out[i] = StringUtil::stringToFloat(items[i]); } return pVector; } diff --git a/matlab/mex/mexHelpFunctions.h b/matlab/mex/mexHelpFunctions.h index 3ac5bd8..07edc64 100644 --- a/matlab/mex/mexHelpFunctions.h +++ b/matlab/mex/mexHelpFunctions.h @@ -37,7 +37,6 @@ $Id$ #include #include -#include #include #include "astra/Globals.h" diff --git a/src/ArtAlgorithm.cpp b/src/ArtAlgorithm.cpp index 6a699ec..b59bd93 100644 --- a/src/ArtAlgorithm.cpp +++ b/src/ArtAlgorithm.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/ArtAlgorithm.h" -#include - #include "astra/AstraObjectManager.h" using namespace std; diff --git a/src/BackProjectionAlgorithm.cpp b/src/BackProjectionAlgorithm.cpp index f561a90..c9beee1 100644 --- a/src/BackProjectionAlgorithm.cpp +++ b/src/BackProjectionAlgorithm.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/BackProjectionAlgorithm.h" -#include - #include "astra/AstraObjectManager.h" #include "astra/DataProjectorPolicies.h" diff --git a/src/CglsAlgorithm.cpp b/src/CglsAlgorithm.cpp index b9031e3..1ca2549 100644 --- a/src/CglsAlgorithm.cpp +++ b/src/CglsAlgorithm.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/CglsAlgorithm.h" -#include - #include "astra/AstraObjectManager.h" using namespace std; diff --git a/src/ConeProjectionGeometry3D.cpp b/src/ConeProjectionGeometry3D.cpp index 18f0f8a..99b4bf4 100644 --- a/src/ConeProjectionGeometry3D.cpp +++ b/src/ConeProjectionGeometry3D.cpp @@ -31,7 +31,6 @@ $Id$ #include "astra/Logging.h" #include "astra/GeometryUtil3D.h" -#include #include using namespace std; @@ -90,13 +89,13 @@ bool CConeProjectionGeometry3D::initialize(const Config& _cfg) // Required: DistanceOriginDetector XMLNode node = _cfg.self.getSingleNode("DistanceOriginDetector"); ASTRA_CONFIG_CHECK(node, "ConeProjectionGeometry3D", "No DistanceOriginDetector tag specified."); - m_fOriginDetectorDistance = boost::lexical_cast(node.getContent()); + m_fOriginDetectorDistance = node.getContentNumerical(); CC.markNodeParsed("DistanceOriginDetector"); // Required: DetectorOriginSource node = _cfg.self.getSingleNode("DistanceOriginSource"); ASTRA_CONFIG_CHECK(node, "ConeProjectionGeometry3D", "No DistanceOriginSource tag specified."); - m_fOriginSourceDistance = boost::lexical_cast(node.getContent()); + m_fOriginSourceDistance = node.getContentNumerical(); CC.markNodeParsed("DistanceOriginSource"); // success diff --git a/src/ConeVecProjectionGeometry3D.cpp b/src/ConeVecProjectionGeometry3D.cpp index 86e3bd6..f4f900d 100644 --- a/src/ConeVecProjectionGeometry3D.cpp +++ b/src/ConeVecProjectionGeometry3D.cpp @@ -27,9 +27,9 @@ $Id$ */ #include "astra/ConeVecProjectionGeometry3D.h" +#include "astra/Utilities.h" #include -#include using namespace std; @@ -82,13 +82,13 @@ bool CConeVecProjectionGeometry3D::initialize(const Config& _cfg) // Required: DetectorRowCount node = _cfg.self.getSingleNode("DetectorRowCount"); ASTRA_CONFIG_CHECK(node, "ConeVecProjectionGeometry3D", "No DetectorRowCount tag specified."); - m_iDetectorRowCount = boost::lexical_cast(node.getContent()); + m_iDetectorRowCount = node.getContentInt(); CC.markNodeParsed("DetectorRowCount"); // Required: DetectorColCount node = _cfg.self.getSingleNode("DetectorColCount"); ASTRA_CONFIG_CHECK(node, "ConeVecProjectionGeometry3D", "No DetectorColCount tag specified."); - m_iDetectorColCount = boost::lexical_cast(node.getContent()); + m_iDetectorColCount = node.getContentInt(); m_iDetectorTotCount = m_iDetectorRowCount * m_iDetectorColCount; CC.markNodeParsed("DetectorColCount"); @@ -212,18 +212,18 @@ Config* CConeVecProjectionGeometry3D::getConfiguration() const std::string vectors = ""; for (int i = 0; i < m_iProjectionAngleCount; ++i) { SConeProjection& p = m_pProjectionAngles[i]; - vectors += boost::lexical_cast(p.fSrcX) + ","; - vectors += boost::lexical_cast(p.fSrcY) + ","; - vectors += boost::lexical_cast(p.fSrcZ) + ","; - vectors += boost::lexical_cast(p.fDetSX + 0.5f*m_iDetectorRowCount*p.fDetVX + 0.5f*m_iDetectorColCount*p.fDetUX) + ","; - vectors += boost::lexical_cast(p.fDetSY + 0.5f*m_iDetectorRowCount*p.fDetVY + 0.5f*m_iDetectorColCount*p.fDetUY) + ","; - vectors += boost::lexical_cast(p.fDetSZ + 0.5f*m_iDetectorRowCount*p.fDetVZ + 0.5f*m_iDetectorColCount*p.fDetUZ) + ","; - vectors += boost::lexical_cast(p.fDetUX) + ","; - vectors += boost::lexical_cast(p.fDetUY) + ","; - vectors += boost::lexical_cast(p.fDetUZ) + ","; - vectors += boost::lexical_cast(p.fDetVX) + ","; - vectors += boost::lexical_cast(p.fDetVY) + ","; - vectors += boost::lexical_cast(p.fDetVZ); + vectors += StringUtil::toString(p.fSrcX) + ","; + vectors += StringUtil::toString(p.fSrcY) + ","; + vectors += StringUtil::toString(p.fSrcZ) + ","; + vectors += StringUtil::toString(p.fDetSX + 0.5f*m_iDetectorRowCount*p.fDetVX + 0.5f*m_iDetectorColCount*p.fDetUX) + ","; + vectors += StringUtil::toString(p.fDetSY + 0.5f*m_iDetectorRowCount*p.fDetVY + 0.5f*m_iDetectorColCount*p.fDetUY) + ","; + vectors += StringUtil::toString(p.fDetSZ + 0.5f*m_iDetectorRowCount*p.fDetVZ + 0.5f*m_iDetectorColCount*p.fDetUZ) + ","; + vectors += StringUtil::toString(p.fDetUX) + ","; + vectors += StringUtil::toString(p.fDetUY) + ","; + vectors += StringUtil::toString(p.fDetUZ) + ","; + vectors += StringUtil::toString(p.fDetVX) + ","; + vectors += StringUtil::toString(p.fDetVY) + ","; + vectors += StringUtil::toString(p.fDetVZ); if (i < m_iProjectionAngleCount-1) vectors += ';'; } cfg->self.addChildNode("Vectors", vectors); diff --git a/src/CudaBackProjectionAlgorithm3D.cpp b/src/CudaBackProjectionAlgorithm3D.cpp index ce8e111..76d7b35 100644 --- a/src/CudaBackProjectionAlgorithm3D.cpp +++ b/src/CudaBackProjectionAlgorithm3D.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/CudaBackProjectionAlgorithm3D.h" -#include - #include "astra/AstraObjectManager.h" #include "astra/CudaProjector3D.h" diff --git a/src/CudaCglsAlgorithm3D.cpp b/src/CudaCglsAlgorithm3D.cpp index abc18d1..930a71e 100644 --- a/src/CudaCglsAlgorithm3D.cpp +++ b/src/CudaCglsAlgorithm3D.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/CudaCglsAlgorithm3D.h" -#include - #include "astra/AstraObjectManager.h" #include "astra/CudaProjector3D.h" diff --git a/src/CudaDartMaskAlgorithm.cpp b/src/CudaDartMaskAlgorithm.cpp index 950b428..c2a4cca 100644 --- a/src/CudaDartMaskAlgorithm.cpp +++ b/src/CudaDartMaskAlgorithm.cpp @@ -34,7 +34,6 @@ $Id$ #include "../cuda/2d/algo.h" #include "astra/AstraObjectManager.h" -#include using namespace std; @@ -67,14 +66,14 @@ bool CCudaDartMaskAlgorithm::initialize(const Config& _cfg) // reconstruction data XMLNode node = _cfg.self.getSingleNode("SegmentationDataId"); ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No SegmentationDataId tag specified."); - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pSegmentation = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("SegmentationDataId"); // reconstruction data node = _cfg.self.getSingleNode("MaskDataId"); ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No MaskDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pMask = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("MaskDataId"); diff --git a/src/CudaDartMaskAlgorithm3D.cpp b/src/CudaDartMaskAlgorithm3D.cpp index b0dfc5b..dd12c58 100644 --- a/src/CudaDartMaskAlgorithm3D.cpp +++ b/src/CudaDartMaskAlgorithm3D.cpp @@ -34,7 +34,6 @@ $Id$ #include "../cuda/3d/dims3d.h" #include "astra/AstraObjectManager.h" -#include using namespace std; @@ -67,14 +66,14 @@ bool CCudaDartMaskAlgorithm3D::initialize(const Config& _cfg) // reconstruction data XMLNode node = _cfg.self.getSingleNode("SegmentationDataId"); ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No SegmentationDataId tag specified."); - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pSegmentation = dynamic_cast(CData3DManager::getSingleton().get(id)); CC.markNodeParsed("SegmentationDataId"); // reconstruction data node = _cfg.self.getSingleNode("MaskDataId"); ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No MaskDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pMask = dynamic_cast(CData3DManager::getSingleton().get(id)); CC.markNodeParsed("MaskDataId"); diff --git a/src/CudaDartSmoothingAlgorithm.cpp b/src/CudaDartSmoothingAlgorithm.cpp index 7e22809..425f0a3 100644 --- a/src/CudaDartSmoothingAlgorithm.cpp +++ b/src/CudaDartSmoothingAlgorithm.cpp @@ -34,7 +34,6 @@ $Id$ #include "../cuda/2d/algo.h" #include "astra/AstraObjectManager.h" -#include using namespace std; @@ -67,14 +66,14 @@ bool CCudaDartSmoothingAlgorithm::initialize(const Config& _cfg) // reconstruction data XMLNode node = _cfg.self.getSingleNode("InDataId"); ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No InDataId tag specified."); - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pIn = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("InDataId"); // reconstruction data node = _cfg.self.getSingleNode("OutDataId"); ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No OutDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pOut = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("OutDataId"); diff --git a/src/CudaDartSmoothingAlgorithm3D.cpp b/src/CudaDartSmoothingAlgorithm3D.cpp index 9c4437a..df7e0df 100644 --- a/src/CudaDartSmoothingAlgorithm3D.cpp +++ b/src/CudaDartSmoothingAlgorithm3D.cpp @@ -34,7 +34,6 @@ $Id$ #include "../cuda/3d/dims3d.h" #include "astra/AstraObjectManager.h" -#include using namespace std; @@ -67,14 +66,14 @@ bool CCudaDartSmoothingAlgorithm3D::initialize(const Config& _cfg) // reconstruction data XMLNode node = _cfg.self.getSingleNode("InDataId"); ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No InDataId tag specified."); - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pIn = dynamic_cast(CData3DManager::getSingleton().get(id)); CC.markNodeParsed("InDataId"); // reconstruction data node = _cfg.self.getSingleNode("OutDataId"); ASTRA_CONFIG_CHECK(node, "CudaDartMask", "No OutDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pOut = dynamic_cast(CData3DManager::getSingleton().get(id)); CC.markNodeParsed("OutDataId"); diff --git a/src/CudaDataOperationAlgorithm.cpp b/src/CudaDataOperationAlgorithm.cpp index ae133c2..15886a4 100644 --- a/src/CudaDataOperationAlgorithm.cpp +++ b/src/CudaDataOperationAlgorithm.cpp @@ -35,7 +35,6 @@ $Id$ #include "../cuda/2d/arith.h" #include "astra/AstraObjectManager.h" -#include using namespace std; @@ -78,7 +77,7 @@ bool CCudaDataOperationAlgorithm::initialize(const Config& _cfg) ASTRA_CONFIG_CHECK(node, "CCudaDataOperationAlgorithm", "No DataId tag specified."); vector data = node.getContentArray(); for (vector::iterator it = data.begin(); it != data.end(); it++){ - int id = boost::lexical_cast(*it); + int id = StringUtil::stringToInt(*it); m_pData.push_back(dynamic_cast(CData2DManager::getSingleton().get(id))); } CC.markNodeParsed("DataId"); @@ -97,7 +96,7 @@ bool CCudaDataOperationAlgorithm::initialize(const Config& _cfg) CC.markOptionParsed("GPUIndex"); if (_cfg.self.hasOption("MaskId")) { - int id = boost::lexical_cast(_cfg.self.getOption("MaskId")); + int id = _cfg.self.getOptionInt("MaskId"); m_pMask = dynamic_cast(CData2DManager::getSingleton().get(id)); } CC.markOptionParsed("MaskId"); diff --git a/src/CudaFDKAlgorithm3D.cpp b/src/CudaFDKAlgorithm3D.cpp index 1316daa..b5ce545 100644 --- a/src/CudaFDKAlgorithm3D.cpp +++ b/src/CudaFDKAlgorithm3D.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/CudaFDKAlgorithm3D.h" -#include - #include "astra/AstraObjectManager.h" #include "astra/CudaProjector3D.h" diff --git a/src/CudaFilteredBackProjectionAlgorithm.cpp b/src/CudaFilteredBackProjectionAlgorithm.cpp index bcd70c4..aa97eec 100644 --- a/src/CudaFilteredBackProjectionAlgorithm.cpp +++ b/src/CudaFilteredBackProjectionAlgorithm.cpp @@ -28,7 +28,6 @@ $Id$ #include #include -#include #include #include "astra/AstraObjectManager.h" @@ -100,7 +99,7 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg) XMLNode node = _cfg.self.getSingleNode("ProjectorId"); CCudaProjector2D* pCudaProjector = 0; if (node) { - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); CProjector2D *projector = CProjector2DManager::getSingleton().get(id); pCudaProjector = dynamic_cast(projector); if (!pCudaProjector) { @@ -113,14 +112,14 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg) // sinogram data node = _cfg.self.getSingleNode("ProjectionDataId"); ASTRA_CONFIG_CHECK(node, "CudaFBP", "No ProjectionDataId tag specified."); - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pSinogram = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("ProjectionDataId"); // reconstruction data node = _cfg.self.getSingleNode("ReconstructionDataId"); ASTRA_CONFIG_CHECK(node, "CudaFBP", "No ReconstructionDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pReconstruction = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("ReconstructionDataId"); @@ -140,7 +139,7 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg) node = _cfg.self.getSingleNode("FilterSinogramId"); if (node) { - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); const CFloat32ProjectionData2D * pFilterData = dynamic_cast(CData2DManager::getSingleton().get(id)); m_iFilterWidth = pFilterData->getGeometry()->getDetectorCount(); int iFilterProjectionCount = pFilterData->getGeometry()->getProjectionAngleCount(); @@ -159,7 +158,7 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg) node = _cfg.self.getSingleNode("FilterParameter"); if (node) { - float fParameter = boost::lexical_cast(node.getContent()); + float fParameter = node.getContentNumerical(); m_fFilterParameter = fParameter; } else @@ -172,7 +171,7 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg) node = _cfg.self.getSingleNode("FilterD"); if (node) { - float fD = boost::lexical_cast(node.getContent()); + float fD = node.getContentNumerical(); m_fFilterD = fD; } else diff --git a/src/CudaForwardProjectionAlgorithm.cpp b/src/CudaForwardProjectionAlgorithm.cpp index d38469c..80f2e02 100644 --- a/src/CudaForwardProjectionAlgorithm.cpp +++ b/src/CudaForwardProjectionAlgorithm.cpp @@ -35,8 +35,6 @@ $Id$ #include #include -#include - #include "astra/AstraObjectManager.h" #include "astra/ParallelProjectionGeometry2D.h" #include "astra/FanFlatProjectionGeometry2D.h" @@ -97,7 +95,7 @@ bool CCudaForwardProjectionAlgorithm::initialize(const Config& _cfg) m_pProjector = 0; XMLNode node = _cfg.self.getSingleNode("ProjectorId"); if (node) { - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pProjector = CProjector2DManager::getSingleton().get(id); } CC.markNodeParsed("ProjectorId"); @@ -107,14 +105,14 @@ bool CCudaForwardProjectionAlgorithm::initialize(const Config& _cfg) // sinogram data node = _cfg.self.getSingleNode("ProjectionDataId"); ASTRA_CONFIG_CHECK(node, "FP_CUDA", "No ProjectionDataId tag specified."); - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pSinogram = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("ProjectionDataId"); // volume data node = _cfg.self.getSingleNode("VolumeDataId"); ASTRA_CONFIG_CHECK(node, "FP_CUDA", "No VolumeDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pVolume = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("VolumeDataId"); diff --git a/src/CudaForwardProjectionAlgorithm3D.cpp b/src/CudaForwardProjectionAlgorithm3D.cpp index 209f5a5..f709e34 100644 --- a/src/CudaForwardProjectionAlgorithm3D.cpp +++ b/src/CudaForwardProjectionAlgorithm3D.cpp @@ -30,8 +30,6 @@ $Id$ #ifdef ASTRA_CUDA -#include - #include "astra/AstraObjectManager.h" #include "astra/CudaProjector3D.h" @@ -103,14 +101,14 @@ bool CCudaForwardProjectionAlgorithm3D::initialize(const Config& _cfg) // sinogram data node = _cfg.self.getSingleNode("ProjectionDataId"); ASTRA_CONFIG_CHECK(node, "CudaForwardProjection3D", "No ProjectionDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pProjections = dynamic_cast(CData3DManager::getSingleton().get(id)); CC.markNodeParsed("ProjectionDataId"); // reconstruction data node = _cfg.self.getSingleNode("VolumeDataId"); ASTRA_CONFIG_CHECK(node, "CudaForwardProjection3D", "No VolumeDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pVolume = dynamic_cast(CData3DManager::getSingleton().get(id)); CC.markNodeParsed("VolumeDataId"); @@ -118,7 +116,7 @@ bool CCudaForwardProjectionAlgorithm3D::initialize(const Config& _cfg) node = _cfg.self.getSingleNode("ProjectorId"); m_pProjector = 0; if (node) { - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pProjector = CProjector3DManager::getSingleton().get(id); } CC.markNodeParsed("ProjectorId"); diff --git a/src/CudaReconstructionAlgorithm2D.cpp b/src/CudaReconstructionAlgorithm2D.cpp index 71dddf7..5a1910c 100644 --- a/src/CudaReconstructionAlgorithm2D.cpp +++ b/src/CudaReconstructionAlgorithm2D.cpp @@ -30,8 +30,6 @@ $Id$ #include "astra/CudaReconstructionAlgorithm2D.h" -#include - #include "astra/AstraObjectManager.h" #include "astra/FanFlatProjectionGeometry2D.h" #include "astra/FanFlatVecProjectionGeometry2D.h" diff --git a/src/CudaRoiSelectAlgorithm.cpp b/src/CudaRoiSelectAlgorithm.cpp index 7635c69..dfb8056 100644 --- a/src/CudaRoiSelectAlgorithm.cpp +++ b/src/CudaRoiSelectAlgorithm.cpp @@ -34,7 +34,6 @@ $Id$ #include "../cuda/2d/algo.h" #include "astra/AstraObjectManager.h" -#include using namespace std; @@ -68,7 +67,7 @@ bool CCudaRoiSelectAlgorithm::initialize(const Config& _cfg) // reconstruction data XMLNode node = _cfg.self.getSingleNode("DataId"); ASTRA_CONFIG_CHECK(node, "CudaRoiSelect", "No DataId tag specified."); - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pData = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("DataId"); diff --git a/src/CudaSirtAlgorithm.cpp b/src/CudaSirtAlgorithm.cpp index ab0a418..33e381a 100644 --- a/src/CudaSirtAlgorithm.cpp +++ b/src/CudaSirtAlgorithm.cpp @@ -30,7 +30,6 @@ $Id$ #include "astra/CudaSirtAlgorithm.h" -#include #include "astra/AstraObjectManager.h" #include "../cuda/2d/sirt.h" @@ -77,12 +76,12 @@ bool CCudaSirtAlgorithm::initialize(const Config& _cfg) // min/max masks if (_cfg.self.hasOption("MinMaskId")) { - int id = boost::lexical_cast(_cfg.self.getOption("MinMaskId")); + int id = _cfg.self.getOptionInt("MinMaskId"); m_pMinMask = dynamic_cast(CData2DManager::getSingleton().get(id)); } CC.markOptionParsed("MinMaskId"); if (_cfg.self.hasOption("MaxMaskId")) { - int id = boost::lexical_cast(_cfg.self.getOption("MaxMaskId")); + int id = _cfg.self.getOptionInt("MaxMaskId"); m_pMaxMask = dynamic_cast(CData2DManager::getSingleton().get(id)); } CC.markOptionParsed("MaxMaskId"); diff --git a/src/CudaSirtAlgorithm3D.cpp b/src/CudaSirtAlgorithm3D.cpp index 1fa0da2..605c470 100644 --- a/src/CudaSirtAlgorithm3D.cpp +++ b/src/CudaSirtAlgorithm3D.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/CudaSirtAlgorithm3D.h" -#include - #include "astra/AstraObjectManager.h" #include "astra/ConeProjectionGeometry3D.h" diff --git a/src/FanFlatBeamLineKernelProjector2D.cpp b/src/FanFlatBeamLineKernelProjector2D.cpp index 0681715..fd4195b 100644 --- a/src/FanFlatBeamLineKernelProjector2D.cpp +++ b/src/FanFlatBeamLineKernelProjector2D.cpp @@ -30,7 +30,6 @@ $Id$ #include #include -#include #include "astra/DataProjectorPolicies.h" diff --git a/src/FanFlatBeamStripKernelProjector2D.cpp b/src/FanFlatBeamStripKernelProjector2D.cpp index e94d3da..b48beab 100644 --- a/src/FanFlatBeamStripKernelProjector2D.cpp +++ b/src/FanFlatBeamStripKernelProjector2D.cpp @@ -29,7 +29,6 @@ $Id$ #include "astra/FanFlatBeamStripKernelProjector2D.h" #include -#include #include "astra/DataProjectorPolicies.h" diff --git a/src/FanFlatProjectionGeometry2D.cpp b/src/FanFlatProjectionGeometry2D.cpp index 32a19bc..8bee0d6 100644 --- a/src/FanFlatProjectionGeometry2D.cpp +++ b/src/FanFlatProjectionGeometry2D.cpp @@ -30,7 +30,6 @@ $Id$ #include #include -#include using namespace std; @@ -136,13 +135,13 @@ bool CFanFlatProjectionGeometry2D::initialize(const Config& _cfg) // Required: DistanceOriginDetector XMLNode node = _cfg.self.getSingleNode("DistanceOriginDetector"); ASTRA_CONFIG_CHECK(node, "FanFlatProjectionGeometry2D", "No DistanceOriginDetector tag specified."); - m_fOriginDetectorDistance = boost::lexical_cast(node.getContent()); + m_fOriginDetectorDistance = node.getContentNumerical(); CC.markNodeParsed("DistanceOriginDetector"); // Required: DetectorOriginSource node = _cfg.self.getSingleNode("DistanceOriginSource"); ASTRA_CONFIG_CHECK(node, "FanFlatProjectionGeometry2D", "No DistanceOriginSource tag specified."); - m_fOriginSourceDistance = boost::lexical_cast(node.getContent()); + m_fOriginSourceDistance = node.getContentNumerical(); CC.markNodeParsed("DistanceOriginSource"); // success diff --git a/src/FanFlatVecProjectionGeometry2D.cpp b/src/FanFlatVecProjectionGeometry2D.cpp index 4104379..0b76fc5 100644 --- a/src/FanFlatVecProjectionGeometry2D.cpp +++ b/src/FanFlatVecProjectionGeometry2D.cpp @@ -30,7 +30,6 @@ $Id$ #include #include -#include using namespace std; @@ -125,7 +124,7 @@ bool CFanFlatVecProjectionGeometry2D::initialize(const Config& _cfg) // Required: DetectorCount node = _cfg.self.getSingleNode("DetectorCount"); ASTRA_CONFIG_CHECK(node, "FanFlatVecProjectionGeometry3D", "No DetectorRowCount tag specified."); - m_iDetectorCount = boost::lexical_cast(node.getContent()); + m_iDetectorCount = node.getContentInt(); CC.markNodeParsed("DetectorCount"); // Required: Vectors @@ -235,12 +234,12 @@ Config* CFanFlatVecProjectionGeometry2D::getConfiguration() const std::string vectors = ""; for (int i = 0; i < m_iProjectionAngleCount; ++i) { SFanProjection& p = m_pProjectionAngles[i]; - vectors += boost::lexical_cast(p.fSrcX) + ","; - vectors += boost::lexical_cast(p.fSrcY) + ","; - vectors += boost::lexical_cast(p.fDetSX + 0.5f * m_iDetectorCount * p.fDetUX) + ","; - vectors += boost::lexical_cast(p.fDetSY + 0.5f * m_iDetectorCount * p.fDetUY) + ","; - vectors += boost::lexical_cast(p.fDetUX) + ","; - vectors += boost::lexical_cast(p.fDetUY); + vectors += StringUtil::toString(p.fSrcX) + ","; + vectors += StringUtil::toString(p.fSrcY) + ","; + vectors += StringUtil::toString(p.fDetSX + 0.5f * m_iDetectorCount * p.fDetUX) + ","; + vectors += StringUtil::toString(p.fDetSY + 0.5f * m_iDetectorCount * p.fDetUY) + ","; + vectors += StringUtil::toString(p.fDetUX) + ","; + vectors += StringUtil::toString(p.fDetUY); if (i < m_iProjectionAngleCount-1) vectors += ';'; } cfg->self.addChildNode("Vectors", vectors); diff --git a/src/FilteredBackProjectionAlgorithm.cpp b/src/FilteredBackProjectionAlgorithm.cpp index f494d22..c195578 100644 --- a/src/FilteredBackProjectionAlgorithm.cpp +++ b/src/FilteredBackProjectionAlgorithm.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/FilteredBackProjectionAlgorithm.h" -#include - #include #include #include @@ -96,19 +94,19 @@ bool CFilteredBackProjectionAlgorithm::initialize(const Config& _cfg) // projector XMLNode node = _cfg.self.getSingleNode("ProjectorId"); ASTRA_CONFIG_CHECK(node, "FilteredBackProjection", "No ProjectorId tag specified."); - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pProjector = CProjector2DManager::getSingleton().get(id); // sinogram data node = _cfg.self.getSingleNode("ProjectionDataId"); ASTRA_CONFIG_CHECK(node, "FilteredBackProjection", "No ProjectionDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pSinogram = dynamic_cast(CData2DManager::getSingleton().get(id)); // volume data node = _cfg.self.getSingleNode("ReconstructionDataId"); ASTRA_CONFIG_CHECK(node, "FilteredBackProjection", "No ReconstructionDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pReconstruction = dynamic_cast(CData2DManager::getSingleton().get(id)); node = _cfg.self.getSingleNode("ProjectionIndex"); diff --git a/src/ForwardProjectionAlgorithm.cpp b/src/ForwardProjectionAlgorithm.cpp index f356824..dcf5790 100644 --- a/src/ForwardProjectionAlgorithm.cpp +++ b/src/ForwardProjectionAlgorithm.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/ForwardProjectionAlgorithm.h" -#include - #include "astra/AstraObjectManager.h" #include "astra/DataProjectorPolicies.h" @@ -128,32 +126,32 @@ bool CForwardProjectionAlgorithm::initialize(const Config& _cfg) // projector XMLNode node = _cfg.self.getSingleNode("ProjectorId"); ASTRA_CONFIG_CHECK(node, "ForwardProjection", "No ProjectorId tag specified."); - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pProjector = CProjector2DManager::getSingleton().get(id); // sinogram data node = _cfg.self.getSingleNode("ProjectionDataId"); ASTRA_CONFIG_CHECK(node, "ForwardProjection", "No ProjectionDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pSinogram = dynamic_cast(CData2DManager::getSingleton().get(id)); // volume data node = _cfg.self.getSingleNode("VolumeDataId"); ASTRA_CONFIG_CHECK(node, "ForwardProjection", "No VolumeDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pVolume = dynamic_cast(CData2DManager::getSingleton().get(id)); // volume mask if (_cfg.self.hasOption("VolumeMaskId")) { m_bUseVolumeMask = true; - id = boost::lexical_cast(_cfg.self.getOption("VolumeMaskId")); + id = _cfg.self.getOptionInt("VolumeMaskId"); m_pVolumeMask = dynamic_cast(CData2DManager::getSingleton().get(id)); } // sino mask if (_cfg.self.hasOption("SinogramMaskId")) { m_bUseSinogramMask = true; - id = boost::lexical_cast(_cfg.self.getOption("SinogramMaskId")); + id = _cfg.self.getOptionInt("SinogramMaskId"); m_pSinogramMask = dynamic_cast(CData2DManager::getSingleton().get(id)); } diff --git a/src/ParallelBeamBlobKernelProjector2D.cpp b/src/ParallelBeamBlobKernelProjector2D.cpp index 4559a48..679d5c6 100644 --- a/src/ParallelBeamBlobKernelProjector2D.cpp +++ b/src/ParallelBeamBlobKernelProjector2D.cpp @@ -29,7 +29,6 @@ $Id$ #include "astra/ParallelBeamBlobKernelProjector2D.h" #include -#include #include "astra/DataProjectorPolicies.h" @@ -134,17 +133,17 @@ bool CParallelBeamBlobKernelProjector2D::initialize(const Config& _cfg) // Required: KernelSize XMLNode node2 = node.getSingleNode("KernelSize"); ASTRA_CONFIG_CHECK(node2, "BlobProjector", "No Kernel/KernelSize tag specified."); - m_fBlobSize = boost::lexical_cast(node2.getContent()); + m_fBlobSize = node2.getContentNumerical(); // Required: SampleRate node2 = node.getSingleNode("SampleRate"); ASTRA_CONFIG_CHECK(node2, "BlobProjector", "No Kernel/SampleRate tag specified."); - m_fBlobSampleRate = boost::lexical_cast(node2.getContent()); + m_fBlobSampleRate = node2.getContentNumerical(); // Required: SampleCount node2 = node.getSingleNode("SampleCount"); ASTRA_CONFIG_CHECK(node2, "BlobProjector", "No Kernel/SampleCount tag specified."); - m_iBlobSampleCount = boost::lexical_cast(node2.getContent()); + m_iBlobSampleCount = node2.getContentInt(); // Required: KernelValues node2 = node.getSingleNode("KernelValues"); diff --git a/src/ParallelBeamLineKernelProjector2D.cpp b/src/ParallelBeamLineKernelProjector2D.cpp index 5a23413..e4a1bff 100644 --- a/src/ParallelBeamLineKernelProjector2D.cpp +++ b/src/ParallelBeamLineKernelProjector2D.cpp @@ -29,7 +29,6 @@ $Id$ #include "astra/ParallelBeamLineKernelProjector2D.h" #include -#include #include "astra/DataProjectorPolicies.h" diff --git a/src/ParallelBeamLinearKernelProjector2D.cpp b/src/ParallelBeamLinearKernelProjector2D.cpp index a710664..27aa168 100644 --- a/src/ParallelBeamLinearKernelProjector2D.cpp +++ b/src/ParallelBeamLinearKernelProjector2D.cpp @@ -29,7 +29,6 @@ $Id$ #include "astra/ParallelBeamLinearKernelProjector2D.h" #include -#include #include "astra/DataProjectorPolicies.h" diff --git a/src/ParallelBeamStripKernelProjector2D.cpp b/src/ParallelBeamStripKernelProjector2D.cpp index 44c6fec..3f4e7f3 100644 --- a/src/ParallelBeamStripKernelProjector2D.cpp +++ b/src/ParallelBeamStripKernelProjector2D.cpp @@ -29,7 +29,6 @@ $Id$ #include "astra/ParallelBeamStripKernelProjector2D.h" #include -#include #include "astra/DataProjectorPolicies.h" diff --git a/src/ParallelProjectionGeometry2D.cpp b/src/ParallelProjectionGeometry2D.cpp index 7260b83..cc2a129 100644 --- a/src/ParallelProjectionGeometry2D.cpp +++ b/src/ParallelProjectionGeometry2D.cpp @@ -27,7 +27,6 @@ $Id$ */ #include "astra/ParallelProjectionGeometry2D.h" -#include #include diff --git a/src/ParallelProjectionGeometry3D.cpp b/src/ParallelProjectionGeometry3D.cpp index 7b64fd9..2f80883 100644 --- a/src/ParallelProjectionGeometry3D.cpp +++ b/src/ParallelProjectionGeometry3D.cpp @@ -30,7 +30,6 @@ $Id$ #include "astra/GeometryUtil3D.h" -#include #include using namespace std; diff --git a/src/ParallelVecProjectionGeometry3D.cpp b/src/ParallelVecProjectionGeometry3D.cpp index d04400b..3172818 100644 --- a/src/ParallelVecProjectionGeometry3D.cpp +++ b/src/ParallelVecProjectionGeometry3D.cpp @@ -27,9 +27,9 @@ $Id$ */ #include "astra/ParallelVecProjectionGeometry3D.h" +#include "astra/Utilities.h" #include -#include using namespace std; @@ -82,13 +82,13 @@ bool CParallelVecProjectionGeometry3D::initialize(const Config& _cfg) // Required: DetectorRowCount node = _cfg.self.getSingleNode("DetectorRowCount"); ASTRA_CONFIG_CHECK(node, "ParallelVecProjectionGeometry3D", "No DetectorRowCount tag specified."); - m_iDetectorRowCount = boost::lexical_cast(node.getContent()); + m_iDetectorRowCount = node.getContentInt(); CC.markNodeParsed("DetectorRowCount"); // Required: DetectorCount node = _cfg.self.getSingleNode("DetectorColCount"); ASTRA_CONFIG_CHECK(node, "", "No DetectorColCount tag specified."); - m_iDetectorColCount = boost::lexical_cast(node.getContent()); + m_iDetectorColCount = node.getContentInt(); m_iDetectorTotCount = m_iDetectorRowCount * m_iDetectorColCount; CC.markNodeParsed("DetectorColCount"); @@ -212,18 +212,18 @@ Config* CParallelVecProjectionGeometry3D::getConfiguration() const std::string vectors = ""; for (int i = 0; i < m_iProjectionAngleCount; ++i) { SPar3DProjection& p = m_pProjectionAngles[i]; - vectors += boost::lexical_cast(p.fRayX) + ","; - vectors += boost::lexical_cast(p.fRayY) + ","; - vectors += boost::lexical_cast(p.fRayZ) + ","; - vectors += boost::lexical_cast(p.fDetSX + 0.5f*m_iDetectorRowCount*p.fDetVX + 0.5f*m_iDetectorColCount*p.fDetUX) + ","; - vectors += boost::lexical_cast(p.fDetSY + 0.5f*m_iDetectorRowCount*p.fDetVY + 0.5f*m_iDetectorColCount*p.fDetUY) + ","; - vectors += boost::lexical_cast(p.fDetSZ + 0.5f*m_iDetectorRowCount*p.fDetVZ + 0.5f*m_iDetectorColCount*p.fDetUZ) + ","; - vectors += boost::lexical_cast(p.fDetUX) + ","; - vectors += boost::lexical_cast(p.fDetUY) + ","; - vectors += boost::lexical_cast(p.fDetUZ) + ","; - vectors += boost::lexical_cast(p.fDetVX) + ","; - vectors += boost::lexical_cast(p.fDetVY) + ","; - vectors += boost::lexical_cast(p.fDetVZ); + vectors += StringUtil::toString(p.fRayX) + ","; + vectors += StringUtil::toString(p.fRayY) + ","; + vectors += StringUtil::toString(p.fRayZ) + ","; + vectors += StringUtil::toString(p.fDetSX + 0.5f*m_iDetectorRowCount*p.fDetVX + 0.5f*m_iDetectorColCount*p.fDetUX) + ","; + vectors += StringUtil::toString(p.fDetSY + 0.5f*m_iDetectorRowCount*p.fDetVY + 0.5f*m_iDetectorColCount*p.fDetUY) + ","; + vectors += StringUtil::toString(p.fDetSZ + 0.5f*m_iDetectorRowCount*p.fDetVZ + 0.5f*m_iDetectorColCount*p.fDetUZ) + ","; + vectors += StringUtil::toString(p.fDetUX) + ","; + vectors += StringUtil::toString(p.fDetUY) + ","; + vectors += StringUtil::toString(p.fDetUZ) + ","; + vectors += StringUtil::toString(p.fDetVX) + ","; + vectors += StringUtil::toString(p.fDetVY) + ","; + vectors += StringUtil::toString(p.fDetVZ); if (i < m_iProjectionAngleCount-1) vectors += ';'; } cfg->self.addChildNode("Vectors", vectors); diff --git a/src/PluginAlgorithm.cpp b/src/PluginAlgorithm.cpp index 8f7dfc5..9fc511a 100644 --- a/src/PluginAlgorithm.cpp +++ b/src/PluginAlgorithm.cpp @@ -30,9 +30,9 @@ $Id$ #include "astra/PluginAlgorithm.h" #include "astra/Logging.h" +#include "astra/Utilities.h" #include #include -#include #include #include #include @@ -338,7 +338,7 @@ PyObject* stringToPythonValue(std::string str){ boost::split(row, rows[i], boost::is_any_of(",")); PyObject *rowlist = PyList_New(row.size()); for(unsigned int j=0;j(row[j]))); + PyList_SetItem(rowlist, j, PyFloat_FromDouble(StringUtil::stringToDouble(row[j]))); } PyList_SetItem(mat, i, rowlist); } @@ -349,16 +349,16 @@ PyObject* stringToPythonValue(std::string str){ boost::split(vec, str, boost::is_any_of(",")); PyObject *veclist = PyList_New(vec.size()); for(unsigned int i=0;i(vec[i]))); + PyList_SetItem(veclist, i, PyFloat_FromDouble(StringUtil::stringToDouble(vec[i]))); } return veclist; } try{ - return PyLong_FromLong(boost::lexical_cast(str)); - }catch(const boost::bad_lexical_cast &){ + return PyLong_FromLong(StringUtil::stringToInt(str)); + }catch(const StringUtil::bad_cast &){ try{ - return PyFloat_FromDouble(boost::lexical_cast(str)); - }catch(const boost::bad_lexical_cast &){ + return PyFloat_FromDouble(StringUtil::stringToDouble(str)); + }catch(const StringUtil::bad_cast &){ return pyStringFromString(str); } } diff --git a/src/ProjectionGeometry2D.cpp b/src/ProjectionGeometry2D.cpp index b89605b..8ce06dc 100644 --- a/src/ProjectionGeometry2D.cpp +++ b/src/ProjectionGeometry2D.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/ProjectionGeometry2D.h" -#include - using namespace std; namespace astra @@ -126,13 +124,13 @@ bool CProjectionGeometry2D::initialize(const Config& _cfg) // Required: DetectorWidth XMLNode node = _cfg.self.getSingleNode("DetectorWidth"); ASTRA_CONFIG_CHECK(node, "ProjectionGeometry2D", "No DetectorWidth tag specified."); - m_fDetectorWidth = boost::lexical_cast(node.getContent()); + m_fDetectorWidth = node.getContentNumerical(); CC.markNodeParsed("DetectorWidth"); // Required: DetectorCount node = _cfg.self.getSingleNode("DetectorCount"); ASTRA_CONFIG_CHECK(node, "ProjectionGeometry2D", "No DetectorCount tag specified."); - m_iDetectorCount = boost::lexical_cast(node.getContent()); + m_iDetectorCount = node.getContentInt(); CC.markNodeParsed("DetectorCount"); // Required: ProjectionAngles diff --git a/src/ProjectionGeometry3D.cpp b/src/ProjectionGeometry3D.cpp index ef0246c..281db7c 100644 --- a/src/ProjectionGeometry3D.cpp +++ b/src/ProjectionGeometry3D.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/ProjectionGeometry3D.h" -#include - using namespace std; namespace astra @@ -151,25 +149,25 @@ bool CProjectionGeometry3D::initialize(const Config& _cfg) // Required: DetectorWidth XMLNode node = _cfg.self.getSingleNode("DetectorSpacingX"); ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorSpacingX tag specified."); - m_fDetectorSpacingX = boost::lexical_cast(node.getContent()); + m_fDetectorSpacingX = node.getContentNumerical(); CC.markNodeParsed("DetectorSpacingX"); // Required: DetectorHeight node = _cfg.self.getSingleNode("DetectorSpacingY"); ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorSpacingY tag specified."); - m_fDetectorSpacingY = boost::lexical_cast(node.getContent()); + m_fDetectorSpacingY = node.getContentNumerical(); CC.markNodeParsed("DetectorSpacingY"); // Required: DetectorRowCount node = _cfg.self.getSingleNode("DetectorRowCount"); ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorRowCount tag specified."); - m_iDetectorRowCount = boost::lexical_cast(node.getContent()); + m_iDetectorRowCount = node.getContentInt(); CC.markNodeParsed("DetectorRowCount"); // Required: DetectorCount node = _cfg.self.getSingleNode("DetectorColCount"); ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorColCount tag specified."); - m_iDetectorColCount = boost::lexical_cast(node.getContent()); + m_iDetectorColCount = node.getContentInt(); m_iDetectorTotCount = m_iDetectorRowCount * m_iDetectorColCount; CC.markNodeParsed("DetectorColCount"); diff --git a/src/ReconstructionAlgorithm2D.cpp b/src/ReconstructionAlgorithm2D.cpp index 4575ff7..1c6d855 100644 --- a/src/ReconstructionAlgorithm2D.cpp +++ b/src/ReconstructionAlgorithm2D.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/ReconstructionAlgorithm2D.h" -#include - #include "astra/AstraObjectManager.h" using namespace std; @@ -90,7 +88,7 @@ bool CReconstructionAlgorithm2D::initialize(const Config& _cfg) } int id; if (node) { - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pProjector = CProjector2DManager::getSingleton().get(id); } else { m_pProjector = 0; @@ -100,21 +98,21 @@ bool CReconstructionAlgorithm2D::initialize(const Config& _cfg) // sinogram data node = _cfg.self.getSingleNode("ProjectionDataId"); ASTRA_CONFIG_CHECK(node, "Reconstruction2D", "No ProjectionDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pSinogram = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("ProjectionDataId"); // reconstruction data node = _cfg.self.getSingleNode("ReconstructionDataId"); ASTRA_CONFIG_CHECK(node, "Reconstruction2D", "No ReconstructionDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pReconstruction = dynamic_cast(CData2DManager::getSingleton().get(id)); CC.markNodeParsed("ReconstructionDataId"); // fixed mask if (_cfg.self.hasOption("ReconstructionMaskId")) { m_bUseReconstructionMask = true; - id = boost::lexical_cast(_cfg.self.getOption("ReconstructionMaskId")); + id = _cfg.self.getOptionInt("ReconstructionMaskId"); m_pReconstructionMask = dynamic_cast(CData2DManager::getSingleton().get(id)); ASTRA_CONFIG_CHECK(m_pReconstructionMask, "Reconstruction2D", "Invalid ReconstructionMaskId."); } @@ -123,7 +121,7 @@ bool CReconstructionAlgorithm2D::initialize(const Config& _cfg) // fixed mask if (_cfg.self.hasOption("SinogramMaskId")) { m_bUseSinogramMask = true; - id = boost::lexical_cast(_cfg.self.getOption("SinogramMaskId")); + id = _cfg.self.getOptionInt("SinogramMaskId"); m_pSinogramMask = dynamic_cast(CData2DManager::getSingleton().get(id)); ASTRA_CONFIG_CHECK(m_pSinogramMask, "Reconstruction2D", "Invalid SinogramMaskId."); } diff --git a/src/ReconstructionAlgorithm3D.cpp b/src/ReconstructionAlgorithm3D.cpp index 13d4b07..55f1031 100644 --- a/src/ReconstructionAlgorithm3D.cpp +++ b/src/ReconstructionAlgorithm3D.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/ReconstructionAlgorithm3D.h" -#include - #include "astra/AstraObjectManager.h" using namespace std; @@ -111,7 +109,7 @@ bool CReconstructionAlgorithm3D::initialize(const Config& _cfg) node = _cfg.self.getSingleNode("ProjectorId"); m_pProjector = 0; if (node) { - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pProjector = CProjector3DManager::getSingleton().get(id); if (!m_pProjector) { // TODO: Report @@ -122,21 +120,21 @@ bool CReconstructionAlgorithm3D::initialize(const Config& _cfg) // sinogram data node = _cfg.self.getSingleNode("ProjectionDataId"); ASTRA_CONFIG_CHECK(node, "Reconstruction3D", "No ProjectionDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pSinogram = dynamic_cast(CData3DManager::getSingleton().get(id)); CC.markNodeParsed("ProjectionDataId"); // reconstruction data node = _cfg.self.getSingleNode("ReconstructionDataId"); ASTRA_CONFIG_CHECK(node, "Reconstruction3D", "No ReconstructionDataId tag specified."); - id = boost::lexical_cast(node.getContent()); + id = node.getContentInt(); m_pReconstruction = dynamic_cast(CData3DManager::getSingleton().get(id)); CC.markNodeParsed("ReconstructionDataId"); // fixed mask if (_cfg.self.hasOption("ReconstructionMaskId")) { m_bUseReconstructionMask = true; - id = boost::lexical_cast(_cfg.self.getOption("ReconstructionMaskId")); + id = _cfg.self.getOptionInt("ReconstructionMaskId"); m_pReconstructionMask = dynamic_cast(CData3DManager::getSingleton().get(id)); } CC.markOptionParsed("ReconstructionMaskId"); @@ -144,7 +142,7 @@ bool CReconstructionAlgorithm3D::initialize(const Config& _cfg) // fixed mask if (_cfg.self.hasOption("SinogramMaskId")) { m_bUseSinogramMask = true; - id = boost::lexical_cast(_cfg.self.getOption("SinogramMaskId")); + id = _cfg.self.getOptionInt("SinogramMaskId"); m_pSinogramMask = dynamic_cast(CData3DManager::getSingleton().get(id)); } CC.markOptionParsed("SinogramMaskId"); diff --git a/src/ReconstructionAlgorithmMultiSlice2D.cpp b/src/ReconstructionAlgorithmMultiSlice2D.cpp index fe64c86..39c337f 100644 --- a/src/ReconstructionAlgorithmMultiSlice2D.cpp +++ b/src/ReconstructionAlgorithmMultiSlice2D.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/ReconstructionAlgorithmMultiSlice2D.h" -#include - #include "astra/AstraObjectManager.h" using namespace std; @@ -96,7 +94,7 @@ bool CReconstructionAlgorithmMultiSlice2D::initialize(const Config& _cfg) // projector XMLNode* node = _cfg.self->getSingleNode("ProjectorId"); ASTRA_CONFIG_CHECK(node, "Reconstruction2D", "No ProjectorId tag specified."); - int id = boost::lexical_cast(node->getContent()); + int id = node->getContentInt(); m_pProjector = CProjector2DManager::getSingleton().get(id); ASTRA_DELETE(node); CC.markNodeParsed("ProjectorId"); @@ -125,7 +123,7 @@ bool CReconstructionAlgorithmMultiSlice2D::initialize(const Config& _cfg) // reconstruction masks if (_cfg.self->hasOption("ReconstructionMaskId")) { m_bUseReconstructionMask = true; - id = boost::lexical_cast(_cfg.self->getOption("ReconstructionMaskId")); + id = _cfg.self->getOptionInt("ReconstructionMaskId"); m_pReconstructionMask = dynamic_cast(CData2DManager::getSingleton().get(id)); } CC.markOptionParsed("ReconstructionMaskId"); @@ -133,7 +131,7 @@ bool CReconstructionAlgorithmMultiSlice2D::initialize(const Config& _cfg) // sinogram masks if (_cfg.self->hasOption("SinogramMaskId")) { m_bUseSinogramMask = true; - id = boost::lexical_cast(_cfg.self->getOption("SinogramMaskId")); + id = _cfg.self->getOptionInt("SinogramMaskId"); m_pSinogramMask = dynamic_cast(CData2DManager::getSingleton().get(id)); } CC.markOptionParsed("SinogramMaskId"); diff --git a/src/SartAlgorithm.cpp b/src/SartAlgorithm.cpp index e4dc5c7..9346160 100644 --- a/src/SartAlgorithm.cpp +++ b/src/SartAlgorithm.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/SartAlgorithm.h" -#include - #include "astra/AstraObjectManager.h" #include "astra/DataProjectorPolicies.h" diff --git a/src/SirtAlgorithm.cpp b/src/SirtAlgorithm.cpp index ae3b3bc..d9f3a65 100644 --- a/src/SirtAlgorithm.cpp +++ b/src/SirtAlgorithm.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/SirtAlgorithm.h" -#include - #include "astra/AstraObjectManager.h" #include "astra/DataProjectorPolicies.h" diff --git a/src/SparseMatrixProjectionGeometry2D.cpp b/src/SparseMatrixProjectionGeometry2D.cpp index 073720f..358c992 100644 --- a/src/SparseMatrixProjectionGeometry2D.cpp +++ b/src/SparseMatrixProjectionGeometry2D.cpp @@ -28,7 +28,6 @@ $Id$ #include "astra/SparseMatrixProjectionGeometry2D.h" -#include #include "astra/AstraObjectManager.h" @@ -100,7 +99,7 @@ bool CSparseMatrixProjectionGeometry2D::initialize(const Config& _cfg) // get matrix XMLNode node = _cfg.self.getSingleNode("MatrixID"); ASTRA_CONFIG_CHECK(node, "SparseMatrixProjectionGeometry2D", "No MatrixID tag specified."); - int id = boost::lexical_cast(node.getContent()); + int id = node.getContentInt(); m_pMatrix = CMatrixManager::getSingleton().get(id); CC.markNodeParsed("MatrixID"); diff --git a/src/SparseMatrixProjector2D.cpp b/src/SparseMatrixProjector2D.cpp index bc2e974..be7e069 100644 --- a/src/SparseMatrixProjector2D.cpp +++ b/src/SparseMatrixProjector2D.cpp @@ -29,7 +29,6 @@ $Id$ #include "astra/SparseMatrixProjector2D.h" #include -#include #include "astra/DataProjectorPolicies.h" diff --git a/src/Utilities.cpp b/src/Utilities.cpp index cb54e93..4b80503 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -28,4 +28,99 @@ $Id$ #include "astra/Utilities.h" +#include +#include +#include +#include +#include +#include + +namespace astra { + +namespace StringUtil { + +int stringToInt(const std::string& s) +{ + double i; + std::istringstream iss(s); + iss.imbue(std::locale::classic()); + iss >> i; + if (iss.fail() || !iss.eof()) + throw bad_cast(); + return i; + +} + +float stringToFloat(const std::string& s) +{ + return (float)stringToDouble(s); +} + +double stringToDouble(const std::string& s) +{ + double f; + std::istringstream iss(s); + iss.imbue(std::locale::classic()); + iss >> f; + if (iss.fail() || !iss.eof()) + throw bad_cast(); + return f; +} + +template<> float stringTo(const std::string& s) { return stringToFloat(s); } +template<> double stringTo(const std::string& s) { return stringToDouble(s); } + +std::vector stringToFloatVector(const std::string &s) +{ + return stringToVector(s); +} + +std::vector stringToDoubleVector(const std::string &s) +{ + return stringToVector(s); +} + +template +std::vector stringToVector(const std::string& s) +{ + // split + std::vector items; + boost::split(items, s, boost::is_any_of(",;")); + + // init list + std::vector out; + out.resize(items.size()); + + // loop elements + for (unsigned int i = 0; i < items.size(); i++) { + out[i] = stringTo(items[i]); + } + return out; +} + + +std::string floatToString(float f) +{ + std::ostringstream s; + s.imbue(std::locale::classic()); + s << std::setprecision(9) << f; + return s.str(); +} + +std::string doubleToString(double f) +{ + std::ostringstream s; + s.imbue(std::locale::classic()); + s << std::setprecision(17) << f; + return s.str(); +} + + +template<> std::string toString(float f) { return floatToString(f); } +template<> std::string toString(double f) { return doubleToString(f); } + + +} + +} diff --git a/src/VolumeGeometry2D.cpp b/src/VolumeGeometry2D.cpp index 6eea1b2..9d74e47 100644 --- a/src/VolumeGeometry2D.cpp +++ b/src/VolumeGeometry2D.cpp @@ -28,7 +28,6 @@ $Id$ #include "astra/VolumeGeometry2D.h" -#include #include namespace astra @@ -166,13 +165,13 @@ bool CVolumeGeometry2D::initialize(const Config& _cfg) // Required: GridColCount XMLNode node = _cfg.self.getSingleNode("GridColCount"); ASTRA_CONFIG_CHECK(node, "ReconstructionGeometry2D", "No GridColCount tag specified."); - m_iGridColCount = boost::lexical_cast(node.getContent()); + m_iGridColCount = node.getContentInt(); CC.markNodeParsed("GridColCount"); // Required: GridRowCount node = _cfg.self.getSingleNode("GridRowCount"); ASTRA_CONFIG_CHECK(node, "ReconstructionGeometry2D", "No GridRowCount tag specified."); - m_iGridRowCount = boost::lexical_cast(node.getContent()); + m_iGridRowCount = node.getContentInt(); CC.markNodeParsed("GridRowCount"); // Optional: Window minima and maxima diff --git a/src/VolumeGeometry3D.cpp b/src/VolumeGeometry3D.cpp index 3de146f..5d72c24 100644 --- a/src/VolumeGeometry3D.cpp +++ b/src/VolumeGeometry3D.cpp @@ -28,8 +28,6 @@ $Id$ #include "astra/VolumeGeometry3D.h" -#include - namespace astra { @@ -196,19 +194,19 @@ bool CVolumeGeometry3D::initialize(const Config& _cfg) // Required: GridColCount XMLNode node = _cfg.self.getSingleNode("GridColCount"); ASTRA_CONFIG_CHECK(node, "ReconstructionGeometry2D", "No GridColCount tag specified."); - m_iGridColCount = boost::lexical_cast(node.getContent()); + m_iGridColCount = node.getContentInt(); CC.markNodeParsed("GridColCount"); // Required: GridRowCount node = _cfg.self.getSingleNode("GridRowCount"); ASTRA_CONFIG_CHECK(node, "ReconstructionGeometry2D", "No GridRowCount tag specified."); - m_iGridRowCount = boost::lexical_cast(node.getContent()); + m_iGridRowCount = node.getContentInt(); CC.markNodeParsed("GridRowCount"); // Required: GridRowCount node = _cfg.self.getSingleNode("GridSliceCount"); ASTRA_CONFIG_CHECK(node, "ReconstructionGeometry2D", "No GridSliceCount tag specified."); - m_iGridSliceCount = boost::lexical_cast(node.getContent()); + m_iGridSliceCount = node.getContentInt(); CC.markNodeParsed("GridSliceCount"); // Optional: Window minima and maxima diff --git a/src/XMLNode.cpp b/src/XMLNode.cpp index 0ec701f..40a9b22 100644 --- a/src/XMLNode.cpp +++ b/src/XMLNode.cpp @@ -31,12 +31,6 @@ $Id$ #include "rapidxml/rapidxml.hpp" #include "rapidxml/rapidxml_print.hpp" -#include -#include -#include -#include - - using namespace rapidxml; using namespace astra; @@ -138,8 +132,13 @@ string XMLNode::getContent() const // Get node content - NUMERICAL float32 XMLNode::getContentNumerical() const { - return boost::lexical_cast(getContent()); + return StringUtil::stringToFloat(getContent()); } +int XMLNode::getContentInt() const +{ + return StringUtil::stringToInt(getContent()); +} + //----------------------------------------------------------------------------- // Get node content - BOOLEAN @@ -154,7 +153,7 @@ bool XMLNode::getContentBool() const vector XMLNode::getContentArray() const { // get listsize - int iSize = boost::lexical_cast(getAttribute("listsize")); + int iSize = StringUtil::stringToInt(getAttribute("listsize")); // create result array vector res(iSize); // loop all list item nodes @@ -175,40 +174,12 @@ vector XMLNode::getContentArray() const // NB: A 2D matrix is returned as a linear list vector XMLNode::getContentNumericalArray() const { - string input = getContent(); - - // split - std::vector items; - boost::split(items, input, boost::is_any_of(",;")); - - // init list - vector out; - out.resize(items.size()); - - // loop elements - for (unsigned int i = 0; i < items.size(); i++) { - out[i] = boost::lexical_cast(items[i]); - } - return out; + return StringUtil::stringToFloatVector(getContent()); } vector XMLNode::getContentNumericalArrayDouble() const { - string input = getContent(); - - // split - std::vector items; - boost::split(items, input, boost::is_any_of(",;")); - - // init list - vector out; - out.resize(items.size()); - - // loop elements - for (unsigned int i = 0; i < items.size(); i++) { - out[i] = boost::lexical_cast(items[i]); - } - return out; + return StringUtil::stringToDoubleVector(getContent()); } //----------------------------------------------------------------------------- @@ -235,14 +206,20 @@ string XMLNode::getAttribute(string _sName, string _sDefaultValue) const float32 XMLNode::getAttributeNumerical(string _sName, float32 _fDefaultValue) const { if (!hasAttribute(_sName)) return _fDefaultValue; - return boost::lexical_cast(getAttribute(_sName)); + return StringUtil::stringToFloat(getAttribute(_sName)); } double XMLNode::getAttributeNumericalDouble(string _sName, double _fDefaultValue) const { if (!hasAttribute(_sName)) return _fDefaultValue; - return boost::lexical_cast(getAttribute(_sName)); + return StringUtil::stringToDouble(getAttribute(_sName)); +} +int XMLNode::getAttributeInt(string _sName, int _iDefaultValue) const +{ + if (!hasAttribute(_sName)) return _iDefaultValue; + return StringUtil::stringToInt(getAttribute(_sName)); } + //----------------------------------------------------------------------------- // Get attribute - BOOLEAN bool XMLNode::getAttributeBool(string _sName, bool _bDefaultValue) const @@ -287,9 +264,15 @@ string XMLNode::getOption(string _sKey, string _sDefaultValue) const float32 XMLNode::getOptionNumerical(string _sKey, float32 _fDefaultValue) const { if (!hasOption(_sKey)) return _fDefaultValue; - return boost::lexical_cast(getOption(_sKey)); + return StringUtil::stringToFloat(getOption(_sKey)); +} +int XMLNode::getOptionInt(string _sKey, int _iDefaultValue) const +{ + if (!hasOption(_sKey)) return _iDefaultValue; + return StringUtil::stringToInt(getOption(_sKey)); } + //----------------------------------------------------------------------------- // Get option - BOOL bool XMLNode::getOptionBool(string _sKey, bool _bDefaultValue) const @@ -386,7 +369,7 @@ void XMLNode::setContent(string _sText) // Set content - FLOAT void XMLNode::setContent(float32 _fValue) { - setContent(boost::lexical_cast(_fValue)); + setContent(StringUtil::floatToString(_fValue)); } //----------------------------------------------------------------------------- @@ -394,9 +377,9 @@ void XMLNode::setContent(float32 _fValue) template static std::string setContentList_internal(T* pfList, int _iSize) { - std::string str = (_iSize > 0) ? boost::lexical_cast(pfList[0]) : ""; + std::string str = (_iSize > 0) ? StringUtil::toString(pfList[0]) : ""; for (int i = 1; i < _iSize; i++) { - str += "," + boost::lexical_cast(pfList[i]); + str += "," + StringUtil::toString(pfList[i]); } return str; } @@ -431,9 +414,9 @@ static std::string setContentMatrix_internal(T* _pfMatrix, int _iWidth, int _iHe for (int y = 0; y < _iHeight; ++y) { if (_iWidth > 0) - str += boost::lexical_cast(_pfMatrix[0*s1 + y*s2]); + str += StringUtil::toString(_pfMatrix[0*s1 + y*s2]); for (int x = 1; x < _iWidth; x++) - str += "," + boost::lexical_cast(_pfMatrix[x*s1 + y*s2]); + str += "," + StringUtil::toString(_pfMatrix[x*s1 + y*s2]); if (y != _iHeight-1) str += ";"; @@ -468,7 +451,7 @@ void XMLNode::addAttribute(string _sName, string _sText) // Add attribute - FLOAT void XMLNode::addAttribute(string _sName, float32 _fValue) { - addAttribute(_sName, boost::lexical_cast(_fValue)); + addAttribute(_sName, StringUtil::floatToString(_fValue)); } //----------------------------------------------------------------------------- -- cgit v1.2.3 From e5edadc1db1eac9057ed6b726e1ce6b8e7126ed0 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 5 Jan 2016 16:20:14 +0100 Subject: Remove (long) obsolete file --- matlab/mex/astra_mex.cpp | 124 ----------------------------------------------- 1 file changed, 124 deletions(-) delete mode 100644 matlab/mex/astra_mex.cpp (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex.cpp b/matlab/mex/astra_mex.cpp deleted file mode 100644 index 4bf42dd..0000000 --- a/matlab/mex/astra_mex.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* ------------------------------------------------------------------------ -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$ -*/ - -#include -#include "mexHelpFunctions.h" -#include "mexInitFunctions.h" - -#include "astra/Globals.h" - -using namespace std; -using namespace astra; - - -//----------------------------------------------------------------------------------------- -/** astra_mex('credits'); - * - * Print Credits - */ -void astra_mex_credits(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) -{ - cout << "All Scale Tomographic Reconstruction Antwerp Toolbox (ASTRA-Toolbox) was developed at the University of Antwerp by" << endl; - cout << " * Joost Batenburg, PhD" << endl; - cout << " * Gert Merckx" << endl; - cout << " * Willem Jan Palenstijn" << endl; - cout << " * Tom Roelandts" << endl; - cout << " * Prof. Dr. Jan Sijbers" << endl; - cout << " * Wim van Aarle" << endl; - cout << " * Sander van der Maar" << endl; - cout << " * Gert Van Gompel, PhD" << endl; -} - -//----------------------------------------------------------------------------------------- -/** use_cuda = astra_mex('use_cuda'); - * - * Is CUDA enabled? - */ -void astra_mex_use_cuda(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) -{ - if (1 <= nlhs) { - plhs[0] = mxCreateDoubleScalar(astra::cudaEnabled() ? 1 : 0); - } -} - -//----------------------------------------------------------------------------------------- -/** version_number = astra_mex('version'); - * - * Fetch the version number of the toolbox. - */ -void astra_mex_version(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) -{ - if (1 <= nlhs) { - plhs[0] = mxCreateDoubleScalar(astra::getVersion()); - } else { - cout << "astra toolbox version " << astra::getVersionString() << endl; - } -} - -//----------------------------------------------------------------------------------------- - -static void printHelp() -{ - mexPrintf("Please specify a mode of operation.\n"); - mexPrintf(" Valid modes: version, use_cuda, credits\n"); -} - -//----------------------------------------------------------------------------------------- -/** - * ... = astra_mex(type,...); - */ -void mexFunction(int nlhs, mxArray* plhs[], - int nrhs, const mxArray* prhs[]) -{ - - // INPUT0: Mode - string sMode = ""; - if (1 <= nrhs) { - sMode = mex_util_get_string(prhs[0]); - } else { - printHelp(); - return; - } - - initASTRAMex(); - - // SWITCH (MODE) - if (sMode == std::string("version")) { - astra_mex_version(nlhs, plhs, nrhs, prhs); - } else if (sMode == std::string("use_cuda")) { - astra_mex_use_cuda(nlhs, plhs, nrhs, prhs); - } else if (sMode == std::string("credits")) { - astra_mex_credits(nlhs, plhs, nrhs, prhs); - } else { - printHelp(); - } - - return; -} - - -- 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 --- matlab/mex/astra_mex_c.cpp | 21 ++++++++++++--------- python/astra/astra_c.pyx | 28 +++++++++++++--------------- 2 files changed, 25 insertions(+), 24 deletions(-) (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_c.cpp b/matlab/mex/astra_mex_c.cpp index a9b9654..d34334c 100644 --- a/matlab/mex/astra_mex_c.cpp +++ b/matlab/mex/astra_mex_c.cpp @@ -50,16 +50,19 @@ using namespace astra; */ void astra_mex_credits(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { - mexPrintf("All Scale Tomographic Reconstruction Antwerp Toolbox (ASTRA-Toolbox) was developed at the University of Antwerp by\n"); + mexPrintf("The ASTRA Toolbox has been developed at the University of Antwerp and CWI, Amsterdam by\n"); mexPrintf(" * Prof. dr. Joost Batenburg\n"); - mexPrintf(" * Andrei Dabravolski\n"); - mexPrintf(" * Gert Merckx\n"); - mexPrintf(" * Willem Jan Palenstijn\n"); - mexPrintf(" * Tom Roelandts\n"); mexPrintf(" * Prof. dr. Jan Sijbers\n"); - mexPrintf(" * dr. Wim van Aarle\n"); - mexPrintf(" * Sander van der Maar\n"); - mexPrintf(" * dr. Gert Van Gompel\n"); + mexPrintf(" * Dr. Jeroen Bedorf\n"); + mexPrintf(" * Dr. Folkert Bleichrodt\n"); + mexPrintf(" * Dr. Andrei Dabravolski\n"); + mexPrintf(" * Dr. Willem Jan Palenstijn\n"); + mexPrintf(" * Dr. Tom Roelandts\n"); + mexPrintf(" * Dr. Wim van Aarle\n"); + mexPrintf(" * Dr. Gert Van Gompel\n"); + mexPrintf(" * Sander van der Maar, MSc.\n"); + mexPrintf(" * Gert Merckx, MSc.\n"); + mexPrintf(" * Daan Pelt, MSc.\n"); } //----------------------------------------------------------------------------------------- @@ -100,7 +103,7 @@ void astra_mex_version(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[ if (1 <= nlhs) { plhs[0] = mxCreateDoubleScalar(astra::getVersion()); } else { - mexPrintf("astra toolbox version %s\n", astra::getVersionString()); + mexPrintf("ASTRA Toolbox version %s\n", astra::getVersionString()); } } 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 687c5e244e46e51786afad77f5015cae9abad129 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 6 Jan 2016 15:10:34 +0100 Subject: Add multi-GPU support to CompositeGeometryManager --- cuda/3d/mem3d.h | 2 + include/astra/CompositeGeometryManager.h | 16 ++ matlab/mex/astra_mex_c.cpp | 45 +++- src/CompositeGeometryManager.cpp | 434 +++++++++++++++++++++++-------- 4 files changed, 378 insertions(+), 119 deletions(-) (limited to 'matlab/mex') diff --git a/cuda/3d/mem3d.h b/cuda/3d/mem3d.h index 82bad19..acb72cb 100644 --- a/cuda/3d/mem3d.h +++ b/cuda/3d/mem3d.h @@ -87,6 +87,8 @@ bool copyFromGPUMemory(float *dst, MemHandle3D src, const SSubDimensions3D &pos) bool freeGPUMemory(MemHandle3D handle); +bool setGPUIndex(int index); + bool FP(const astra::CProjectionGeometry3D* pProjGeom, MemHandle3D projData, const astra::CVolumeGeometry3D* pVolGeom, MemHandle3D volData, int iDetectorSuperSampling, astra::Cuda3DProjectionKernel projKernel); diff --git a/include/astra/CompositeGeometryManager.h b/include/astra/CompositeGeometryManager.h index 6610151..49d02a7 100644 --- a/include/astra/CompositeGeometryManager.h +++ b/include/astra/CompositeGeometryManager.h @@ -50,9 +50,16 @@ class CProjectionGeometry3D; class CProjector3D; +struct SGPUParams { + std::vector GPUIndices; + size_t memory; +}; + class _AstraExport CCompositeGeometryManager { public: + CCompositeGeometryManager(); + class CPart; typedef std::list > TPartList; class CPart { @@ -139,10 +146,19 @@ public: bool doFP(CProjector3D *pProjector, const std::vector& volData, const std::vector& projData); bool doBP(CProjector3D *pProjector, const std::vector& volData, const std::vector& projData); + void setGPUIndices(const std::vector& GPUIndices); + + static void setGlobalGPUParams(const SGPUParams& params); + protected: bool splitJobs(TJobSet &jobs, size_t maxSize, int div, TJobSet &split); + std::vector m_GPUIndices; + size_t m_iMaxSize; + + + static SGPUParams* s_params; }; } diff --git a/matlab/mex/astra_mex_c.cpp b/matlab/mex/astra_mex_c.cpp index d34334c..fdf4f33 100644 --- a/matlab/mex/astra_mex_c.cpp +++ b/matlab/mex/astra_mex_c.cpp @@ -38,6 +38,7 @@ $Id$ #include "astra/Globals.h" #ifdef ASTRA_CUDA #include "../cuda/2d/darthelper.h" +#include "astra/CompositeGeometryManager.h" #endif using namespace std; using namespace astra; @@ -83,12 +84,46 @@ void astra_mex_use_cuda(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs * Set active GPU */ void astra_mex_set_gpu_index(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) -{ +{ #ifdef ASTRA_CUDA - if (nrhs >= 2) { - bool ret = astraCUDA::setGPUIndex((int)mxGetScalar(prhs[1])); - if (!ret) - mexPrintf("Failed to set GPU %d\n", (int)mxGetScalar(prhs[1])); + bool usage = false; + if (nrhs != 2 && nrhs != 4) { + usage = true; + } + + astra::SGPUParams params; + params.memory = 0; + + if (!usage && nrhs >= 4) { + std::string s = mexToString(prhs[2]); + if (s != "memory") { + usage = true; + } else { + params.memory = (size_t)mxGetScalar(prhs[3]); + } + } + + if (!usage && nrhs >= 2) { + int n = mxGetN(prhs[1]) * mxGetM(prhs[1]); + params.GPUIndices.resize(n); + double* pdMatlabData = mxGetPr(prhs[1]); + for (int i = 0; i < n; ++i) + params.GPUIndices[i] = (int)pdMatlabData[i]; + + + astra::CCompositeGeometryManager::setGlobalGPUParams(params); + + + // Set first GPU + if (n >= 1) { + bool ret = astraCUDA::setGPUIndex((int)pdMatlabData[0]); + if (!ret) + mexPrintf("Failed to set GPU %d\n", (int)pdMatlabData[0]); + } + } + + if (usage) { + mexPrintf("Usage: astra_mex('set_gpu_index', index/indices [, 'memory', memory])"); } #endif } diff --git a/src/CompositeGeometryManager.cpp b/src/CompositeGeometryManager.cpp index eed06c4..d1b713e 100644 --- a/src/CompositeGeometryManager.cpp +++ b/src/CompositeGeometryManager.cpp @@ -44,11 +44,31 @@ along with the ASTRA Toolbox. If not, see . #include "../cuda/3d/mem3d.h" #include +#include + +#ifndef USE_PTHREADS +#include +#include +#endif namespace astra { + +SGPUParams* CCompositeGeometryManager::s_params = 0; + +CCompositeGeometryManager::CCompositeGeometryManager() +{ + m_iMaxSize = 0; + + if (s_params) { + m_iMaxSize = s_params->memory; + m_GPUIndices = s_params->GPUIndices; + } +} + + // JOB: -// +// // VolumePart // ProjectionPart // FP-or-BP @@ -76,7 +96,6 @@ namespace astra { // (First approach: 0.5/0.5) - bool CCompositeGeometryManager::splitJobs(TJobSet &jobs, size_t maxSize, int div, TJobSet &split) { split.clear(); @@ -848,6 +867,260 @@ bool CCompositeGeometryManager::doBP(CProjector3D *pProjector, const std::vector +static bool doJob(const CCompositeGeometryManager::TJobSet::const_iterator& iter) +{ + CCompositeGeometryManager::CPart* output = iter->first; + const CCompositeGeometryManager::TJobList& L = iter->second; + + assert(!L.empty()); + + bool zero = L.begin()->eMode == CCompositeGeometryManager::SJob::MODE_SET; + + size_t outx, outy, outz; + output->getDims(outx, outy, outz); + + if (L.begin()->eType == CCompositeGeometryManager::SJob::JOB_NOP) { + // just zero output? + if (zero) { + for (size_t z = 0; z < outz; ++z) { + for (size_t y = 0; y < outy; ++y) { + float* ptr = output->pData->getData(); + ptr += (z + output->subX) * (size_t)output->pData->getHeight() * (size_t)output->pData->getWidth(); + ptr += (y + output->subY) * (size_t)output->pData->getWidth(); + ptr += output->subX; + memset(ptr, 0, sizeof(float) * outx); + } + } + } + return true; + } + + + astraCUDA3d::SSubDimensions3D dstdims; + dstdims.nx = output->pData->getWidth(); + dstdims.pitch = dstdims.nx; + dstdims.ny = output->pData->getHeight(); + dstdims.nz = output->pData->getDepth(); + dstdims.subnx = outx; + dstdims.subny = outy; + dstdims.subnz = outz; + ASTRA_DEBUG("dstdims: %d,%d,%d in %d,%d,%d", dstdims.subnx, dstdims.subny, dstdims.subnz, dstdims.nx, dstdims.ny, dstdims.nz); + dstdims.subx = output->subX; + dstdims.suby = output->subY; + dstdims.subz = output->subZ; + float *dst = output->pData->getData(); + + astraCUDA3d::MemHandle3D outputMem = astraCUDA3d::allocateGPUMemory(outx, outy, outz, zero ? astraCUDA3d::INIT_ZERO : astraCUDA3d::INIT_NO); + bool ok = outputMem; + + for (CCompositeGeometryManager::TJobList::const_iterator i = L.begin(); i != L.end(); ++i) { + const CCompositeGeometryManager::SJob &j = *i; + + assert(j.pInput); + + CCudaProjector3D *projector = dynamic_cast(j.pProjector); + Cuda3DProjectionKernel projKernel = ker3d_default; + int detectorSuperSampling = 1; + int voxelSuperSampling = 1; + if (projector) { + projKernel = projector->getProjectionKernel(); + detectorSuperSampling = projector->getDetectorSuperSampling(); + voxelSuperSampling = projector->getVoxelSuperSampling(); + } + + size_t inx, iny, inz; + j.pInput->getDims(inx, iny, inz); + astraCUDA3d::MemHandle3D inputMem = astraCUDA3d::allocateGPUMemory(inx, iny, inz, astraCUDA3d::INIT_NO); + + astraCUDA3d::SSubDimensions3D srcdims; + srcdims.nx = j.pInput->pData->getWidth(); + srcdims.pitch = srcdims.nx; + srcdims.ny = j.pInput->pData->getHeight(); + srcdims.nz = j.pInput->pData->getDepth(); + srcdims.subnx = inx; + srcdims.subny = iny; + srcdims.subnz = inz; + srcdims.subx = j.pInput->subX; + srcdims.suby = j.pInput->subY; + srcdims.subz = j.pInput->subZ; + const float *src = j.pInput->pData->getDataConst(); + + ok = astraCUDA3d::copyToGPUMemory(src, inputMem, srcdims); + if (!ok) ASTRA_ERROR("Error copying input data to GPU"); + + if (j.eType == CCompositeGeometryManager::SJob::JOB_FP) { + assert(dynamic_cast(j.pInput.get())); + assert(dynamic_cast(j.pOutput.get())); + + ASTRA_DEBUG("CCompositeGeometryManager::doJobs: doing FP"); + + ok = astraCUDA3d::FP(((CCompositeGeometryManager::CProjectionPart*)j.pOutput.get())->pGeom, outputMem, ((CCompositeGeometryManager::CVolumePart*)j.pInput.get())->pGeom, inputMem, detectorSuperSampling, projKernel); + if (!ok) ASTRA_ERROR("Error performing sub-FP"); + ASTRA_DEBUG("CCompositeGeometryManager::doJobs: FP done"); + } else if (j.eType == CCompositeGeometryManager::SJob::JOB_BP) { + assert(dynamic_cast(j.pOutput.get())); + assert(dynamic_cast(j.pInput.get())); + + ASTRA_DEBUG("CCompositeGeometryManager::doJobs: doing BP"); + + ok = astraCUDA3d::BP(((CCompositeGeometryManager::CProjectionPart*)j.pInput.get())->pGeom, inputMem, ((CCompositeGeometryManager::CVolumePart*)j.pOutput.get())->pGeom, outputMem, voxelSuperSampling); + if (!ok) ASTRA_ERROR("Error performing sub-BP"); + ASTRA_DEBUG("CCompositeGeometryManager::doJobs: BP done"); + } else { + assert(false); + } + + ok = astraCUDA3d::freeGPUMemory(inputMem); + if (!ok) ASTRA_ERROR("Error freeing GPU memory"); + + } + + ok = astraCUDA3d::copyFromGPUMemory(dst, outputMem, dstdims); + if (!ok) ASTRA_ERROR("Error copying output data from GPU"); + + ok = astraCUDA3d::freeGPUMemory(outputMem); + if (!ok) ASTRA_ERROR("Error freeing GPU memory"); + + return true; +} + + +class WorkQueue { +public: + WorkQueue(CCompositeGeometryManager::TJobSet &_jobs) : m_jobs(_jobs) { +#ifdef USE_PTHREADS + pthread_mutex_init(&m_mutex, 0); +#endif + m_iter = m_jobs.begin(); + } + bool receive(CCompositeGeometryManager::TJobSet::const_iterator &i) { + lock(); + + if (m_iter == m_jobs.end()) { + unlock(); + return false; + } + + i = m_iter++; + + unlock(); + + return true; + } +#ifdef USE_PTHREADS + void lock() { + // TODO: check mutex op return values + pthread_mutex_lock(&m_mutex); + } + void unlock() { + // TODO: check mutex op return values + pthread_mutex_unlock(&m_mutex); + } +#else + void lock() { + m_mutex.lock(); + } + void unlock() { + m_mutex.unlock(); + } +#endif + +private: + CCompositeGeometryManager::TJobSet &m_jobs; + CCompositeGeometryManager::TJobSet::const_iterator m_iter; +#ifdef USE_PTHREADS + pthread_mutex_t m_mutex; +#else + boost::mutex m_mutex; +#endif +}; + +struct WorkThreadInfo { + WorkQueue* m_queue; + unsigned int m_iGPU; +}; + +#ifndef USE_PTHREADS + +void runEntries_boost(WorkThreadInfo* info) +{ + ASTRA_DEBUG("Launching thread on GPU %d\n", info->m_iGPU); + CCompositeGeometryManager::TJobSet::const_iterator i; + while (info->m_queue->receive(i)) { + ASTRA_DEBUG("Running block on GPU %d\n", info->m_iGPU); + astraCUDA3d::setGPUIndex(info->m_iGPU); + boost::this_thread::interruption_point(); + doJob(i); + boost::this_thread::interruption_point(); + } + ASTRA_DEBUG("Finishing thread on GPU %d\n", info->m_iGPU); +} + + +#else + +void* runEntries_pthreads(void* data) { + WorkThreadInfo* info = (WorkThreadInfo*)data; + + ASTRA_DEBUG("Launching thread on GPU %d\n", info->m_iGPU); + + CCompositeGeometryManager::TJobSet::const_iterator i; + + while (info->m_queue->receive(i)) { + ASTRA_DEBUG("Running block on GPU %d\n", info->m_iGPU); + astraCUDA3d::setGPUIndex(info->m_iGPU); + pthread_testcancel(); + doJob(i); + pthread_testcancel(); + } + ASTRA_DEBUG("Finishing thread on GPU %d\n", info->m_iGPU); + + return 0; +} + +#endif + + +void runWorkQueue(WorkQueue &queue, const std::vector & iGPUIndices) { + int iThreadCount = iGPUIndices.size(); + + std::vector infos; +#ifdef USE_PTHREADS + std::vector threads; +#else + std::vector threads; +#endif + infos.resize(iThreadCount); + threads.resize(iThreadCount); + + for (int i = 0; i < iThreadCount; ++i) { + infos[i].m_queue = &queue; + infos[i].m_iGPU = iGPUIndices[i]; +#ifdef USE_PTHREADS + pthread_create(&threads[i], 0, runEntries_pthreads, (void*)&infos[i]); +#else + threads[i] = new boost::thread(runEntries_boost, &infos[i]); +#endif + } + + // Wait for them to finish + for (int i = 0; i < iThreadCount; ++i) { +#ifdef USE_PTHREADS + pthread_join(threads[i], 0); +#else + threads[i]->join(); + delete threads[i]; + threads[i] = 0; +#endif + } +} + + +void CCompositeGeometryManager::setGPUIndices(const std::vector& GPUIndices) +{ + m_GPUIndices = GPUIndices; +} + bool CCompositeGeometryManager::doJobs(TJobList &jobs) { ASTRA_DEBUG("CCompositeGeometryManager::doJobs"); @@ -859,140 +1132,53 @@ bool CCompositeGeometryManager::doJobs(TJobList &jobs) jobset[i->pOutput.get()].push_back(*i); } - size_t maxSize = astraCUDA3d::availableGPUMemory(); + size_t maxSize = m_iMaxSize; if (maxSize == 0) { - ASTRA_WARN("Unable to get available GPU memory. Defaulting to 1GB."); - maxSize = 1024 * 1024 * 1024; + // Get memory from first GPU. Not optimal... + if (!m_GPUIndices.empty()) + astraCUDA3d::setGPUIndex(m_GPUIndices[0]); + maxSize = astraCUDA3d::availableGPUMemory(); + if (maxSize == 0) { + ASTRA_WARN("Unable to get available GPU memory. Defaulting to 1GB."); + maxSize = 1024 * 1024 * 1024; + } else { + ASTRA_DEBUG("Detected %lu bytes of GPU memory", maxSize); + } } else { - ASTRA_DEBUG("Detected %lu bytes of GPU memory", maxSize); + ASTRA_DEBUG("Set to %lu bytes of GPU memory", maxSize); } maxSize = (maxSize * 9) / 10; maxSize /= sizeof(float); int div = 1; - - // TODO: Multi-GPU support + if (!m_GPUIndices.empty()) + div = m_GPUIndices.size(); // Split jobs to fit TJobSet split; splitJobs(jobset, maxSize, div, split); jobset.clear(); - // Run jobs - - for (TJobSet::iterator iter = split.begin(); iter != split.end(); ++iter) { - - CPart* output = iter->first; - TJobList& L = iter->second; - - assert(!L.empty()); + if (m_GPUIndices.size() <= 1) { - bool zero = L.begin()->eMode == SJob::MODE_SET; + // Run jobs + ASTRA_DEBUG("Running single-threaded"); - size_t outx, outy, outz; - output->getDims(outx, outy, outz); + if (!m_GPUIndices.empty()) + astraCUDA3d::setGPUIndex(m_GPUIndices[0]); - if (L.begin()->eType == SJob::JOB_NOP) { - // just zero output? - if (zero) { - for (size_t z = 0; z < outz; ++z) { - for (size_t y = 0; y < outy; ++y) { - float* ptr = output->pData->getData(); - ptr += (z + output->subX) * (size_t)output->pData->getHeight() * (size_t)output->pData->getWidth(); - ptr += (y + output->subY) * (size_t)output->pData->getWidth(); - ptr += output->subX; - memset(ptr, 0, sizeof(float) * outx); - } - } - } - continue; + for (TJobSet::const_iterator iter = split.begin(); iter != split.end(); ++iter) { + doJob(iter); } + } else { - astraCUDA3d::SSubDimensions3D dstdims; - dstdims.nx = output->pData->getWidth(); - dstdims.pitch = dstdims.nx; - dstdims.ny = output->pData->getHeight(); - dstdims.nz = output->pData->getDepth(); - dstdims.subnx = outx; - dstdims.subny = outy; - dstdims.subnz = outz; - ASTRA_DEBUG("dstdims: %d,%d,%d in %d,%d,%d", dstdims.subnx, dstdims.subny, dstdims.subnz, dstdims.nx, dstdims.ny, dstdims.nz); - dstdims.subx = output->subX; - dstdims.suby = output->subY; - dstdims.subz = output->subZ; - float *dst = output->pData->getData(); - - astraCUDA3d::MemHandle3D outputMem = astraCUDA3d::allocateGPUMemory(outx, outy, outz, zero ? astraCUDA3d::INIT_ZERO : astraCUDA3d::INIT_NO); - bool ok = outputMem; - - for (TJobList::iterator i = L.begin(); i != L.end(); ++i) { - SJob &j = *i; - - assert(j.pInput); - - CCudaProjector3D *projector = dynamic_cast(j.pProjector); - Cuda3DProjectionKernel projKernel = ker3d_default; - int detectorSuperSampling = 1; - int voxelSuperSampling = 1; - if (projector) { - projKernel = projector->getProjectionKernel(); - detectorSuperSampling = projector->getDetectorSuperSampling(); - voxelSuperSampling = projector->getVoxelSuperSampling(); - } - - size_t inx, iny, inz; - j.pInput->getDims(inx, iny, inz); - astraCUDA3d::MemHandle3D inputMem = astraCUDA3d::allocateGPUMemory(inx, iny, inz, astraCUDA3d::INIT_NO); - - astraCUDA3d::SSubDimensions3D srcdims; - srcdims.nx = j.pInput->pData->getWidth(); - srcdims.pitch = srcdims.nx; - srcdims.ny = j.pInput->pData->getHeight(); - srcdims.nz = j.pInput->pData->getDepth(); - srcdims.subnx = inx; - srcdims.subny = iny; - srcdims.subnz = inz; - srcdims.subx = j.pInput->subX; - srcdims.suby = j.pInput->subY; - srcdims.subz = j.pInput->subZ; - const float *src = j.pInput->pData->getDataConst(); - - ok = astraCUDA3d::copyToGPUMemory(src, inputMem, srcdims); - if (!ok) ASTRA_ERROR("Error copying input data to GPU"); - - if (j.eType == SJob::JOB_FP) { - assert(dynamic_cast(j.pInput.get())); - assert(dynamic_cast(j.pOutput.get())); - - ASTRA_DEBUG("CCompositeGeometryManager::doJobs: doing FP"); - - ok = astraCUDA3d::FP(((CProjectionPart*)j.pOutput.get())->pGeom, outputMem, ((CVolumePart*)j.pInput.get())->pGeom, inputMem, detectorSuperSampling, projKernel); - if (!ok) ASTRA_ERROR("Error performing sub-FP"); - ASTRA_DEBUG("CCompositeGeometryManager::doJobs: FP done"); - } else if (j.eType == SJob::JOB_BP) { - assert(dynamic_cast(j.pOutput.get())); - assert(dynamic_cast(j.pInput.get())); - - ASTRA_DEBUG("CCompositeGeometryManager::doJobs: doing BP"); - - ok = astraCUDA3d::BP(((CProjectionPart*)j.pInput.get())->pGeom, inputMem, ((CVolumePart*)j.pOutput.get())->pGeom, outputMem, voxelSuperSampling); - if (!ok) ASTRA_ERROR("Error performing sub-BP"); - ASTRA_DEBUG("CCompositeGeometryManager::doJobs: BP done"); - } else { - assert(false); - } + ASTRA_DEBUG("Running multi-threaded"); - ok = astraCUDA3d::freeGPUMemory(inputMem); - if (!ok) ASTRA_ERROR("Error freeing GPU memory"); + WorkQueue wq(split); - } + runWorkQueue(wq, m_GPUIndices); - ok = astraCUDA3d::copyFromGPUMemory(dst, outputMem, dstdims); - if (!ok) ASTRA_ERROR("Error copying output data from GPU"); - - ok = astraCUDA3d::freeGPUMemory(outputMem); - if (!ok) ASTRA_ERROR("Error freeing GPU memory"); } return true; @@ -1000,6 +1186,26 @@ bool CCompositeGeometryManager::doJobs(TJobList &jobs) + +//static +void CCompositeGeometryManager::setGlobalGPUParams(const SGPUParams& params) +{ + delete s_params; + + s_params = new SGPUParams; + *s_params = params; + + ASTRA_DEBUG("CompositeGeometryManager: Setting global GPU params:"); + std::ostringstream s; + s << "GPU indices:"; + for (unsigned int i = 0; i < params.GPUIndices.size(); ++i) + s << " " << params.GPUIndices[i]; + std::string ss = s.str(); + ASTRA_DEBUG(ss.c_str()); + ASTRA_DEBUG("Memory: %llu", params.memory); +} + + } #endif -- cgit v1.2.3 From 2b0177d66197cb613eed2dabe463b9486428a3e3 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 21 Jan 2016 11:12:32 +0100 Subject: Fix file permissions --- matlab/mex/astra_mex_direct_c.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 matlab/mex/astra_mex_direct_c.cpp (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_direct_c.cpp b/matlab/mex/astra_mex_direct_c.cpp old mode 100755 new mode 100644 -- 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 --- build/linux/Makefile.in | 2 - include/astra/AstraObjectFactory.h | 7 +- include/astra/PluginAlgorithm.h | 57 ++-- matlab/mex/astra_mex_plugin_c.cpp | 18 +- python/astra/plugin_c.pyx | 17 +- python/astra/src/PythonPluginAlgorithm.cpp | 402 +++++++++++++++++++++++++++++ python/astra/src/PythonPluginAlgorithm.h | 89 +++++++ python/builder.py | 4 + src/PluginAlgorithm.cpp | 367 +------------------------- 9 files changed, 544 insertions(+), 419 deletions(-) create mode 100644 python/astra/src/PythonPluginAlgorithm.cpp create mode 100644 python/astra/src/PythonPluginAlgorithm.h (limited to 'matlab/mex') diff --git a/build/linux/Makefile.in b/build/linux/Makefile.in index 3018674..d5644bc 100644 --- a/build/linux/Makefile.in +++ b/build/linux/Makefile.in @@ -62,8 +62,6 @@ PYCPPFLAGS := $(CPPFLAGS) PYCPPFLAGS += -I../include PYLDFLAGS = $(LDFLAGS) PYLDFLAGS += -L$(abs_top_builddir)/.libs -LIBS += -l$(PYLIBVER) -LDFLAGS += -L$(PYLIBDIR) endif # This is below where PYCPPFLAGS copies CPPFLAGS. The python code is built diff --git a/include/astra/AstraObjectFactory.h b/include/astra/AstraObjectFactory.h index 325989e..6af9cd8 100644 --- a/include/astra/AstraObjectFactory.h +++ b/include/astra/AstraObjectFactory.h @@ -155,8 +155,11 @@ class _AstraExport CAlgorithmFactory : public CAstraObjectFactory inline CAlgorithm* CAstraObjectFactory::findPlugin(std::string _sType) { - CPluginAlgorithmFactory *fac = CPluginAlgorithmFactory::getSingletonPtr(); - return fac->getPlugin(_sType); + CPluginAlgorithmFactory *fac = CPluginAlgorithmFactory::getFactory(); + if (fac) + return fac->getPlugin(_sType); + else + return 0; } #endif diff --git a/include/astra/PluginAlgorithm.h b/include/astra/PluginAlgorithm.h index 667e813..cbd80fc 100644 --- a/include/astra/PluginAlgorithm.h +++ b/include/astra/PluginAlgorithm.h @@ -29,62 +29,37 @@ $Id$ #ifndef _INC_ASTRA_PLUGINALGORITHM #define _INC_ASTRA_PLUGINALGORITHM -#ifdef ASTRA_PYTHON - -#include "astra/Algorithm.h" -#include "astra/Singleton.h" -#include "astra/XMLDocument.h" -#include "astra/XMLNode.h" - -// Slightly hackish forward declaration of PyObject -struct _object; -typedef _object PyObject; +#include "astra/Globals.h" +#include +#include namespace astra { -class _AstraExport CPluginAlgorithm : public CAlgorithm { - -public: - - CPluginAlgorithm(PyObject* pyclass); - ~CPluginAlgorithm(); - - bool initialize(const Config& _cfg); - void run(int _iNrIterations); - -private: - PyObject * instance; -}; +class CAlgorithm; -class _AstraExport CPluginAlgorithmFactory : public Singleton { +class _AstraExport CPluginAlgorithmFactory { public: + CPluginAlgorithmFactory() { } + virtual ~CPluginAlgorithmFactory() { } - CPluginAlgorithmFactory(); - ~CPluginAlgorithmFactory(); + virtual CAlgorithm * getPlugin(const std::string &name) = 0; - CPluginAlgorithm * getPlugin(std::string name); + virtual bool registerPlugin(std::string name, std::string className) = 0; + virtual bool registerPlugin(std::string className) = 0; - bool registerPlugin(std::string name, std::string className); - bool registerPlugin(std::string className); - bool registerPluginClass(std::string name, PyObject * className); - bool registerPluginClass(PyObject * className); + virtual std::map getRegisteredMap() = 0; - PyObject * getRegistered(); - std::map getRegisteredMap(); - - std::string getHelp(std::string name); + virtual std::string getHelp(const std::string &name) = 0; + + static void registerFactory(CPluginAlgorithmFactory *factory) { m_factory = factory; } + static CPluginAlgorithmFactory* getFactory() { return m_factory; } private: - PyObject * pluginDict; - PyObject *inspect, *six; + static CPluginAlgorithmFactory *m_factory; }; -PyObject* XMLNode2dict(XMLNode node); - } #endif - -#endif diff --git a/matlab/mex/astra_mex_plugin_c.cpp b/matlab/mex/astra_mex_plugin_c.cpp index 177fcf4..0dc0edf 100644 --- a/matlab/mex/astra_mex_plugin_c.cpp +++ b/matlab/mex/astra_mex_plugin_c.cpp @@ -48,7 +48,11 @@ using namespace astra; */ void astra_mex_plugin_get_registered(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { - astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getSingletonPtr(); + astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getFactory(); + if (!fact) { + mexPrintf("Plugin support not initialized."); + return; + } std::map mp = fact->getRegisteredMap(); for(std::map::iterator it=mp.begin();it!=mp.end();it++){ mexPrintf("%s: %s\n",it->first.c_str(), it->second.c_str()); @@ -62,9 +66,13 @@ void astra_mex_plugin_get_registered(int nlhs, mxArray* plhs[], int nrhs, const */ void astra_mex_plugin_register(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { + astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getFactory(); + if (!fact) { + mexPrintf("Plugin support not initialized."); + return; + } if (2 <= nrhs) { string class_name = mexToString(prhs[1]); - astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getSingletonPtr(); fact->registerPlugin(class_name); }else{ mexPrintf("astra_mex_plugin('register', class_name);\n"); @@ -78,9 +86,13 @@ void astra_mex_plugin_register(int nlhs, mxArray* plhs[], int nrhs, const mxArra */ void astra_mex_plugin_get_help(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) { + astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getFactory(); + if (!fact) { + mexPrintf("Plugin support not initialized."); + return; + } if (2 <= nrhs) { string name = mexToString(prhs[1]); - astra::CPluginAlgorithmFactory *fact = astra::CPluginAlgorithmFactory::getSingletonPtr(); mexPrintf((fact->getHelp(name)+"\n").c_str()); }else{ mexPrintf("astra_mex_plugin('get_help', name);\n"); 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 diff --git a/python/builder.py b/python/builder.py index 018b26b..9a77ecc 100644 --- a/python/builder.py +++ b/python/builder.py @@ -70,6 +70,10 @@ ext_modules = [ ] ext_modules = cythonize("astra/*.pyx", language_level=2) cmdclass = { 'build_ext': build_ext } +for m in ext_modules: + if m.name == 'astra.plugin_c': + m.sources.append('astra/src/PythonPluginAlgorithm.cpp') + setup (name = 'PyASTRAToolbox', version = '1.7.1', description = 'Python interface to the ASTRA-Toolbox', diff --git a/src/PluginAlgorithm.cpp b/src/PluginAlgorithm.cpp index 9fc511a..1bcfbdb 100644 --- a/src/PluginAlgorithm.cpp +++ b/src/PluginAlgorithm.cpp @@ -26,376 +26,11 @@ along with the ASTRA Toolbox. If not, see . $Id$ */ -#ifdef ASTRA_PYTHON - #include "astra/PluginAlgorithm.h" -#include "astra/Logging.h" -#include "astra/Utilities.h" -#include -#include -#include -#include -#include - -#include -#include "bytesobject.h" namespace astra { +CPluginAlgorithmFactory *CPluginAlgorithmFactory::m_factory = 0; - -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); - } -} - -CPluginAlgorithmFactory::CPluginAlgorithmFactory(){ - 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"); -} - -CPluginAlgorithmFactory::~CPluginAlgorithmFactory(){ - 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 CPluginAlgorithmFactory::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 CPluginAlgorithmFactory::getHelp(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(CPluginAlgorithmFactory); - -#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 -- 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 --- matlab/mex/astra_mex_plugin_c.cpp | 12 ++++++------ python/astra/src/PythonPluginAlgorithm.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_plugin_c.cpp b/matlab/mex/astra_mex_plugin_c.cpp index 0dc0edf..627e34a 100644 --- a/matlab/mex/astra_mex_plugin_c.cpp +++ b/matlab/mex/astra_mex_plugin_c.cpp @@ -128,12 +128,12 @@ void mexFunction(int nlhs, mxArray* plhs[], initASTRAMex(); // SWITCH (MODE) - if (sMode == std::string("get_registered")) { - astra_mex_plugin_get_registered(nlhs, plhs, nrhs, prhs); - }else if (sMode == std::string("get_help")) { - astra_mex_plugin_get_help(nlhs, plhs, nrhs, prhs); - }else if (sMode == std::string("register")) { - astra_mex_plugin_register(nlhs, plhs, nrhs, prhs); + if (sMode == std::string("get_registered")) { + astra_mex_plugin_get_registered(nlhs, plhs, nrhs, prhs); + }else if (sMode == std::string("get_help")) { + astra_mex_plugin_get_help(nlhs, plhs, nrhs, prhs); + }else if (sMode == std::string("register")) { + astra_mex_plugin_register(nlhs, plhs, nrhs, prhs); } else { printHelp(); } 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 96fa285132bf88462c33c5b24cc1b241fb3d4d73 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 21 Jan 2016 14:30:32 +0100 Subject: Initialize Python plugins when available in Matlab --- build/linux/Makefile.in | 10 ++++++++++ matlab/mex/astra_mex_plugin_c.cpp | 25 ++++++++++++++++++++++++- matlab/mex/mexInitFunctions.cpp | 8 ++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) (limited to 'matlab/mex') diff --git a/build/linux/Makefile.in b/build/linux/Makefile.in index d5644bc..57ed8f8 100644 --- a/build/linux/Makefile.in +++ b/build/linux/Makefile.in @@ -95,6 +95,11 @@ ifeq ($(cuda),yes) MEXFLAGS += -DASTRA_CUDA endif +ifeq ($(python),yes) +MEXPYLDFLAGS='$$LDFLAGS $(LDFLAGS) -L$(PYLIBDIR)' +MEXPYLIBS=$(MEXLIBS) -l$(PYLIBVER) +endif + endif LIBDIR=/usr/local/lib @@ -265,6 +270,11 @@ mex: $(MATLAB_MEX) %.$(MEXSUFFIX): %.o $(MATLAB_CXX_OBJECTS) libastra.la $(MEX) LDFLAGS=$(MEXLDFLAGS) $(MEXFLAGS) $(LIBS) $(MEXLIBS) -lastra -output $* $*.o $(MATLAB_CXX_OBJECTS) + +ifeq ($(python),yes) +matlab/mex/astra_mex_plugin_c.$(MEXSUFFIX): matlab/mex/astra_mex_plugin_c.o $(MATLAB_CXX_OBJECTS) libastra.la + $(MEX) LDFLAGS=$(MEXPYLDFLAGS) $(MEXFLAGS) $(LIBS) $(MEXPYLIBS) -lastra -output matlab/mex/astra_mex_plugin_c $< $(MATLAB_CXX_OBJECTS) +endif endif ifeq ($(python),yes) diff --git a/matlab/mex/astra_mex_plugin_c.cpp b/matlab/mex/astra_mex_plugin_c.cpp index 627e34a..9bd4446 100644 --- a/matlab/mex/astra_mex_plugin_c.cpp +++ b/matlab/mex/astra_mex_plugin_c.cpp @@ -37,10 +37,31 @@ $Id$ #include "astra/PluginAlgorithm.h" +#include + using namespace std; using namespace astra; +//----------------------------------------------------------------------------------------- +/** astra_mex_plugin('init'); + * + * Initialize plugin support by initializing python and importing astra + */ +void astra_mex_plugin_init() +{ + if(!Py_IsInitialized()){ + Py_Initialize(); + PyEval_InitThreads(); + } + + // Importing astra may be overkill, since we only need to initialize + // PythonPluginAlgorithmFactory from astra.plugin_c. + PyObject *mod = PyImport_ImportModule("astra"); + Py_DECREF(mod); +} + + //----------------------------------------------------------------------------------------- /** astra_mex_plugin('get_registered'); * @@ -128,7 +149,9 @@ void mexFunction(int nlhs, mxArray* plhs[], initASTRAMex(); // SWITCH (MODE) - if (sMode == std::string("get_registered")) { + if (sMode == "init") { + astra_mex_plugin_init(); + } else if (sMode == std::string("get_registered")) { astra_mex_plugin_get_registered(nlhs, plhs, nrhs, prhs); }else if (sMode == std::string("get_help")) { astra_mex_plugin_get_help(nlhs, plhs, nrhs, prhs); diff --git a/matlab/mex/mexInitFunctions.cpp b/matlab/mex/mexInitFunctions.cpp index bd3df2c..7245af2 100644 --- a/matlab/mex/mexInitFunctions.cpp +++ b/matlab/mex/mexInitFunctions.cpp @@ -23,5 +23,13 @@ void initASTRAMex(){ if(!astra::CLogger::setCallbackScreen(&logCallBack)){ mexErrMsgTxt("Error initializing mex functions."); } + mexIsInitialized=true; + + + // If we have support for plugins, initialize them. + // (NB: Call this after setting mexIsInitialized, to avoid recursively + // calling initASTRAMex) + mexEvalString("if exist('astra_mex_plugin_c') == 3; astra_mex_plugin_c('init'); end"); + } -- cgit v1.2.3 From 5cb48f351fcc1a7c5b11180edcded083176a2431 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 27 Jan 2016 09:28:10 +0100 Subject: Use Py_XDECREF to guard against null --- matlab/mex/astra_mex_plugin_c.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_plugin_c.cpp b/matlab/mex/astra_mex_plugin_c.cpp index 9bd4446..a279df8 100644 --- a/matlab/mex/astra_mex_plugin_c.cpp +++ b/matlab/mex/astra_mex_plugin_c.cpp @@ -58,7 +58,7 @@ void astra_mex_plugin_init() // Importing astra may be overkill, since we only need to initialize // PythonPluginAlgorithmFactory from astra.plugin_c. PyObject *mod = PyImport_ImportModule("astra"); - Py_DECREF(mod); + Py_XDECREF(mod); } -- 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 --- matlab/mex/astra_mex_plugin_c.cpp | 33 ++++++++++++++++++++++++++++++ python/astra/src/PythonPluginAlgorithm.cpp | 32 ----------------------------- 2 files changed, 33 insertions(+), 32 deletions(-) (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_plugin_c.cpp b/matlab/mex/astra_mex_plugin_c.cpp index a279df8..4ed534e 100644 --- a/matlab/mex/astra_mex_plugin_c.cpp +++ b/matlab/mex/astra_mex_plugin_c.cpp @@ -42,6 +42,35 @@ $Id$ using namespace std; using namespace astra; +static 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); // RTLD_NOW|RTLD_DEEPBIND + 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); + } +} //----------------------------------------------------------------------------------------- /** astra_mex_plugin('init'); @@ -55,6 +84,10 @@ void astra_mex_plugin_init() PyEval_InitThreads(); } +#ifndef _MSC_VER + fixLapackLoading(); +#endif + // Importing astra may be overkill, since we only need to initialize // PythonPluginAlgorithmFactory from astra.plugin_c. PyObject *mod = PyImport_ImportModule("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 8cfe13a410a051e5a6b9835e3a4cd6c808cf5d29 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 16 Feb 2016 15:34:08 +0100 Subject: Add astra_mex delete/info based on index manager --- include/astra/AstraObjectManager.h | 1 + matlab/mex/astra_mex_c.cpp | 49 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) (limited to 'matlab/mex') diff --git a/include/astra/AstraObjectManager.h b/include/astra/AstraObjectManager.h index 8b9da30..35b4534 100644 --- a/include/astra/AstraObjectManager.h +++ b/include/astra/AstraObjectManager.h @@ -53,6 +53,7 @@ namespace astra { */ class CAstraObjectManagerBase { +public: virtual std::string getInfo(int index) const =0; virtual void remove(int index) =0; virtual std::string getType() const =0; diff --git a/matlab/mex/astra_mex_c.cpp b/matlab/mex/astra_mex_c.cpp index fdf4f33..a8623be 100644 --- a/matlab/mex/astra_mex_c.cpp +++ b/matlab/mex/astra_mex_c.cpp @@ -36,10 +36,14 @@ $Id$ #include "mexInitFunctions.h" #include "astra/Globals.h" +#include "astra/AstraObjectManager.h" + #ifdef ASTRA_CUDA #include "../cuda/2d/darthelper.h" #include "astra/CompositeGeometryManager.h" #endif + + using namespace std; using namespace astra; @@ -142,6 +146,47 @@ void astra_mex_version(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[ } } +//----------------------------------------------------------------------------------------- + +void astra_mex_info(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + if (nrhs < 2) { + mexErrMsgTxt("Usage: astra_mex('info', index/indices);\n"); + return; + } + + for (int i = 1; i < nrhs; i++) { + int iDataID = (int)(mxGetScalar(prhs[i])); + CAstraObjectManagerBase *ptr; + ptr = CAstraIndexManager::getSingleton().get(iDataID); + if (ptr) { + mexPrintf("%s\t%s\n", ptr->getType().c_str(), ptr->getInfo(iDataID).c_str()); + } + } + +} + +//----------------------------------------------------------------------------------------- + +void astra_mex_delete(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ + if (nrhs < 2) { + mexErrMsgTxt("Usage: astra_mex('delete', index/indices);\n"); + return; + } + + for (int i = 1; i < nrhs; i++) { + int iDataID = (int)(mxGetScalar(prhs[i])); + CAstraObjectManagerBase *ptr; + ptr = CAstraIndexManager::getSingleton().get(iDataID); + if (ptr) + ptr->remove(iDataID); + } + +} + + + //----------------------------------------------------------------------------------------- static void printHelp() @@ -178,6 +223,10 @@ void mexFunction(int nlhs, mxArray* plhs[], astra_mex_credits(nlhs, plhs, nrhs, prhs); } else if (sMode == std::string("set_gpu_index")) { astra_mex_set_gpu_index(nlhs, plhs, nrhs, prhs); + } else if (sMode == std::string("info")) { + astra_mex_info(nlhs, plhs, nrhs, prhs); + } else if (sMode == std::string("delete")) { + astra_mex_delete(nlhs, plhs, nrhs, prhs); } else { printHelp(); } -- cgit v1.2.3 From da11f9e7c7559eb01cc422ac55c9f7a1cd4bb803 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Mon, 22 Feb 2016 12:17:53 +0100 Subject: Add missing help --- matlab/mex/astra_mex_c.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'matlab/mex') diff --git a/matlab/mex/astra_mex_c.cpp b/matlab/mex/astra_mex_c.cpp index a8623be..f499528 100644 --- a/matlab/mex/astra_mex_c.cpp +++ b/matlab/mex/astra_mex_c.cpp @@ -192,7 +192,7 @@ void astra_mex_delete(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[] static void printHelp() { mexPrintf("Please specify a mode of operation.\n"); - mexPrintf(" Valid modes: version, use_cuda, credits\n"); + mexPrintf(" Valid modes: version, use_cuda, credits, set_gpu_index, info, delete\n"); } //----------------------------------------------------------------------------------------- -- cgit v1.2.3