diff options
| author | Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl> | 2015-12-04 16:35:00 +0100 | 
|---|---|---|
| committer | Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl> | 2015-12-04 16:35:00 +0100 | 
| commit | f3ac1849f2b141ea1845752e1ca2317845e90e3a (patch) | |
| tree | adcdc9013af5cca4165857408ed7181ffdf0de64 | |
| parent | 8144bf0397ee1913b830d82058ccd40df741f1b3 (diff) | |
| parent | 0d015b1c91581ee5ef3e936f03e4c62fbc7ea362 (diff) | |
| download | astra-f3ac1849f2b141ea1845752e1ca2317845e90e3a.tar.gz astra-f3ac1849f2b141ea1845752e1ca2317845e90e3a.tar.bz2 astra-f3ac1849f2b141ea1845752e1ca2317845e90e3a.tar.xz astra-f3ac1849f2b141ea1845752e1ca2317845e90e3a.zip  | |
Merge branch 'master'
113 files changed, 5874 insertions, 1651 deletions
@@ -9,6 +9,20 @@ Contact: astra@uantwerpen.be  Website: http://sf.net/projects/astra-toolbox  ----------------------------------------------------------------------- +1.7beta (2015-12-04) +  * NB: This release has a beta tag as it contains two new +    big experimental features. +  * experimental MPI distributed computing support in Python +  * experimental support in Python for FP and BP of objects +    composited from multiple 3d data objects, at possibly different resolutions. +    This also removes some restrictions on data size for 3D GPU FP and BP. +  * support for Python algorithm plugins +  * removed restrictions on volume geometries: +        The volume no longer has to be centered. +        Voxels still have to be cubes, but no longer 1x1x1. +  * build fixes for newer platforms +  * various consistency and bug fixes +  1.6 (2015-05-29)    * integrate and improve python interface    * integrate opSpot-based opTomo operator 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_vc09.vcproj b/astra_vc09.vcproj index e5d7731..f2cf62a 100644 --- a/astra_vc09.vcproj +++ b/astra_vc09.vcproj @@ -749,6 +749,10 @@  					>  				</File>  				<File +					RelativePath=".\include\astra\PluginAlgorithm.h" +					> +				</File> +				<File  					RelativePath=".\include\astra\ReconstructionAlgorithm2D.h"  					>  				</File> @@ -797,6 +801,10 @@  					>  				</File>  				<File +					RelativePath=".\src\PluginAlgorithm.cpp" +					> +				</File> +				<File  					RelativePath=".\src\ReconstructionAlgorithm2D.cpp"  					>  				</File> @@ -933,6 +941,10 @@  					>  				</File>  				<File +					RelativePath=".\include\astra\CompositeGeometryManager.h" +					> +				</File> +				<File  					RelativePath=".\include\astra\Config.h"  					>  				</File> @@ -989,6 +1001,10 @@  					>  				</File>  				<File +					RelativePath=".\src\CompositeGeometryManager.cpp" +					> +				</File> +				<File  					RelativePath=".\src\Config.cpp"  					>  				</File> @@ -2229,6 +2245,10 @@  					>  				</File>  				<File +					RelativePath=".\cuda\3d\mem3d.h" +					> +				</File> +				<File  					RelativePath=".\cuda\3d\par3d_bp.h"  					>  				</File> @@ -3041,6 +3061,42 @@  					</FileConfiguration>  				</File>  				<File +					RelativePath=".\cuda\3d\mem3d.cu" +					> +					<FileConfiguration +						Name="Debug|Win32" +						ExcludedFromBuild="true" +						> +						<Tool +							Name="Cudart Build Rule" +						/> +					</FileConfiguration> +					<FileConfiguration +						Name="Debug|x64" +						ExcludedFromBuild="true" +						> +						<Tool +							Name="Cudart Build Rule" +						/> +					</FileConfiguration> +					<FileConfiguration +						Name="Release|Win32" +						ExcludedFromBuild="true" +						> +						<Tool +							Name="Cudart Build Rule" +						/> +					</FileConfiguration> +					<FileConfiguration +						Name="Release|x64" +						ExcludedFromBuild="true" +						> +						<Tool +							Name="Cudart Build Rule" +						/> +					</FileConfiguration> +				</File> +				<File  					RelativePath=".\cuda\3d\par3d_bp.cu"  					>  					<FileConfiguration 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/astra_vc11.vcxproj b/astra_vc11.vcxproj index bc11b23..d050b96 100644 --- a/astra_vc11.vcxproj +++ b/astra_vc11.vcxproj @@ -380,6 +380,7 @@      <ClCompile Include="src\AsyncAlgorithm.cpp" />      <ClCompile Include="src\BackProjectionAlgorithm.cpp" />      <ClCompile Include="src\CglsAlgorithm.cpp" /> +    <ClCompile Include="src\CompositeGeometryManager.cpp" />      <ClCompile Include="src\ConeProjectionGeometry3D.cpp" />      <ClCompile Include="src\ConeVecProjectionGeometry3D.cpp" />      <ClCompile Include="src\Config.cpp" /> @@ -539,6 +540,7 @@      <ClCompile Include="src\ParallelProjectionGeometry3D.cpp" />      <ClCompile Include="src\ParallelVecProjectionGeometry3D.cpp" />      <ClCompile Include="src\PlatformDepSystemCode.cpp" /> +    <ClCompile Include="src\PluginAlgorithm.cpp" />      <ClCompile Include="src\ProjectionGeometry2D.cpp" />      <ClCompile Include="src\ProjectionGeometry3D.cpp" />      <ClCompile Include="src\Projector2D.cpp" /> @@ -582,6 +584,7 @@      <ClInclude Include="cuda\3d\darthelper3d.h" />      <ClInclude Include="cuda\3d\dims3d.h" />      <ClInclude Include="cuda\3d\fdk.h" /> +    <ClInclude Include="cuda\3d\mem3d.h" />      <ClInclude Include="cuda\3d\par3d_bp.h" />      <ClInclude Include="cuda\3d\par3d_fp.h" />      <ClInclude Include="cuda\3d\sirt3d.h" /> @@ -594,6 +597,7 @@      <ClInclude Include="include\astra\AsyncAlgorithm.h" />      <ClInclude Include="include\astra\BackProjectionAlgorithm.h" />      <ClInclude Include="include\astra\CglsAlgorithm.h" /> +    <ClInclude Include="include\astra\CompositeGeometryManager.h" />      <ClInclude Include="include\astra\ConeProjectionGeometry3D.h" />      <ClInclude Include="include\astra\ConeVecProjectionGeometry3D.h" />      <ClInclude Include="include\astra\Config.h" /> @@ -649,6 +653,7 @@      <ClInclude Include="include\astra\ParallelProjectionGeometry3D.h" />      <ClInclude Include="include\astra\ParallelVecProjectionGeometry3D.h" />      <ClInclude Include="include\astra\PlatformDepSystemCode.h" /> +    <ClInclude Include="include\astra\PluginAlgorithm.h" />      <ClInclude Include="include\astra\ProjectionGeometry2D.h" />      <ClInclude Include="include\astra\ProjectionGeometry3D.h" />      <ClInclude Include="include\astra\Projector2D.h" /> @@ -804,6 +809,12 @@        <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>        <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>      </CudaCompile> +    <CudaCompile Include="cuda\3d\mem3d.cu"> +      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> +      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> +      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> +      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> +    </CudaCompile>      <CudaCompile Include="cuda\3d\par3d_bp.cu">        <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>        <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> diff --git a/astra_vc11.vcxproj.filters b/astra_vc11.vcxproj.filters index a597962..dd7f574 100644 --- a/astra_vc11.vcxproj.filters +++ b/astra_vc11.vcxproj.filters @@ -67,6 +67,9 @@      <CudaCompile Include="cuda\3d\fdk.cu">        <Filter>CUDA\cuda source</Filter>      </CudaCompile> +    <CudaCompile Include="cuda\3d\mem3d.cu"> +      <Filter>CUDA\cuda source</Filter> +    </CudaCompile>      <CudaCompile Include="cuda\3d\par3d_bp.cu">        <Filter>CUDA\cuda source</Filter>      </CudaCompile> @@ -102,6 +105,9 @@      <ClCompile Include="src\ForwardProjectionAlgorithm.cpp">        <Filter>Algorithms\source</Filter>      </ClCompile> +    <ClCompile Include="src\PluginAlgorithm.cpp"> +      <Filter>Algorithms\source</Filter> +    </ClCompile>      <ClCompile Include="src\ReconstructionAlgorithm2D.cpp">        <Filter>Algorithms\source</Filter>      </ClCompile> @@ -153,6 +159,9 @@      <ClCompile Include="src\AstraObjectManager.cpp">        <Filter>Global & Other\source</Filter>      </ClCompile> +    <ClCompile Include="src\CompositeGeometryManager.cpp"> +      <Filter>Global & Other\source</Filter> +    </ClCompile>      <ClCompile Include="src\Config.cpp">        <Filter>Global & Other\source</Filter>      </ClCompile> @@ -344,6 +353,9 @@      <ClInclude Include="include\astra\ForwardProjectionAlgorithm.h">        <Filter>Algorithms\headers</Filter>      </ClInclude> +    <ClInclude Include="include\astra\PluginAlgorithm.h"> +      <Filter>Algorithms\headers</Filter> +    </ClInclude>      <ClInclude Include="include\astra\ReconstructionAlgorithm2D.h">        <Filter>Algorithms\headers</Filter>      </ClInclude> @@ -398,6 +410,9 @@      <ClInclude Include="include\astra\clog.h">        <Filter>Global & Other\headers</Filter>      </ClInclude> +    <ClInclude Include="include\astra\CompositeGeometryManager.h"> +      <Filter>Global & Other\headers</Filter> +    </ClInclude>      <ClInclude Include="include\astra\Config.h">        <Filter>Global & Other\headers</Filter>      </ClInclude> @@ -641,6 +656,9 @@      <ClInclude Include="cuda\3d\fdk.h">        <Filter>CUDA\cuda headers</Filter>      </ClInclude> +    <ClInclude Include="cuda\3d\mem3d.h"> +      <Filter>CUDA\cuda headers</Filter> +    </ClInclude>      <ClInclude Include="cuda\3d\par3d_bp.h">        <Filter>CUDA\cuda headers</Filter>      </ClInclude> diff --git a/build/linux/Makefile.in b/build/linux/Makefile.in index 2d862f2..8eb5ffe 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= @@ -99,6 +105,7 @@ BASE_OBJECTS=\  	src/AstraObjectManager.lo \  	src/BackProjectionAlgorithm.lo \  	src/CglsAlgorithm.lo \ +	src/CompositeGeometryManager.lo \  	src/ConeProjectionGeometry3D.lo \  	src/ConeVecProjectionGeometry3D.lo \  	src/Config.lo \ @@ -197,7 +204,8 @@ CUDA_OBJECTS=\  	cuda/3d/sirt3d.lo \  	cuda/3d/astra3d.lo \  	cuda/3d/util3d.lo \ -	cuda/3d/arith3d.lo +	cuda/3d/arith3d.lo \ +	cuda/3d/mem3d.lo  ALL_OBJECTS=$(BASE_OBJECTS)  ifeq ($(cuda),yes) @@ -232,8 +240,13 @@ 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) +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)) @@ -253,6 +266,10 @@ py: libastra.la  	cd ../../python; CPPFLAGS="${PYCPPFLAGS}" LDFLAGS="${PYLDFLAGS}" $(PYTHON) builder.py install \  	--install-base=./finalbuild --install-headers=./finalbuild --install-purelib=./finalbuild \  	--install-platlib=./finalbuild --install-scripts=./finalbuild --install-data=./finalbuild + +python-root-install: libastra.la +	cd ../../python; CPPFLAGS="${PYCPPFLAGS}" LDFLAGS="${PYLDFLAGS}" $(PYTHON) builder.py install +  endif diff --git a/build/linux/configure.ac b/build/linux/configure.ac index 7c314f3..38c2946 100644 --- a/build/linux/configure.ac +++ b/build/linux/configure.ac @@ -24,7 +24,7 @@ dnl  dnl -----------------------------------------------------------------------  dnl $Id$ -AC_INIT(astra_toolbox, 1.6.0) +AC_INIT(astra_toolbox, 1.7.0)  AC_CONFIG_SRCDIR([Makefile.in])  LT_INIT([disable-static]) diff --git a/build/msvc/gen.py b/build/msvc/gen.py index aeca3b0..999710f 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,18 @@ P7["files"] = [  "mexInitFunctions.cpp",  "mexInitFunctions.h",  ] +P8["files"] = [ +"astra_mex_direct_c.cpp", +"mexHelpFunctions.cpp", +"mexHelpFunctions.h", +"mexCopyDataHelpFunctions.cpp", +"mexCopyDataHelpFunctions.h", +"mexDataManagerHelpFunctions.cpp", +"mexDataManagerHelpFunctions.h", +"mexInitFunctions.cpp", +"mexInitFunctions.h", +] + @@ -155,6 +168,7 @@ P_astra["filters"]["CUDA\\cuda source"] = [  "cuda\\3d\\cone_fp.cu",  "cuda\\3d\\darthelper3d.cu",  "cuda\\3d\\fdk.cu", +"cuda\\3d\\mem3d.cu",  "cuda\\3d\\par3d_bp.cu",  "cuda\\3d\\par3d_fp.cu",  "cuda\\3d\\sirt3d.cu", @@ -169,6 +183,7 @@ P_astra["filters"]["Algorithms\\source"] = [  "src\\CglsAlgorithm.cpp",  "src\\FilteredBackProjectionAlgorithm.cpp",  "src\\ForwardProjectionAlgorithm.cpp", +"src\\PluginAlgorithm.cpp",  "src\\ReconstructionAlgorithm2D.cpp",  "src\\ReconstructionAlgorithm3D.cpp",  "src\\SartAlgorithm.cpp", @@ -192,6 +207,7 @@ P_astra["filters"]["Global & Other\\source"] = [  "1546cb47-7e5b-42c2-b695-ef172024c14b",  "src\\AstraObjectFactory.cpp",  "src\\AstraObjectManager.cpp", +"src\\CompositeGeometryManager.cpp",  "src\\Config.cpp",  "src\\Fourier.cpp",  "src\\Globals.cpp", @@ -282,6 +298,7 @@ P_astra["filters"]["CUDA\\cuda headers"] = [  "cuda\\3d\\darthelper3d.h",  "cuda\\3d\\dims3d.h",  "cuda\\3d\\fdk.h", +"cuda\\3d\\mem3d.h",  "cuda\\3d\\par3d_bp.h",  "cuda\\3d\\par3d_fp.h",  "cuda\\3d\\sirt3d.h", @@ -299,6 +316,7 @@ P_astra["filters"]["Algorithms\\headers"] = [  "include\\astra\\CudaBackProjectionAlgorithm3D.h",  "include\\astra\\FilteredBackProjectionAlgorithm.h",  "include\\astra\\ForwardProjectionAlgorithm.h", +"include\\astra\\PluginAlgorithm.h",  "include\\astra\\ReconstructionAlgorithm2D.h",  "include\\astra\\ReconstructionAlgorithm3D.h",  "include\\astra\\SartAlgorithm.h", @@ -323,6 +341,7 @@ P_astra["filters"]["Global & Other\\headers"] = [  "include\\astra\\AstraObjectFactory.h",  "include\\astra\\AstraObjectManager.h",  "include\\astra\\clog.h", +"include\\astra\\CompositeGeometryManager.h",  "include\\astra\\Config.h",  "include\\astra\\Fourier.h",  "include\\astra\\Globals.h", @@ -407,7 +426,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 +1130,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 +1146,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/cuda/2d/algo.cu b/cuda/2d/algo.cu index 144fabd..dc74e51 100644 --- a/cuda/2d/algo.cu +++ b/cuda/2d/algo.cu @@ -336,16 +336,17 @@ bool ReconAlgo::callFP(float* D_volumeData, unsigned int volumePitch,  }  bool ReconAlgo::callBP(float* D_volumeData, unsigned int volumePitch, -                       float* D_projData, unsigned int projPitch) +                       float* D_projData, unsigned int projPitch, +                       float outputScale)  {  	if (angles) {  		assert(!fanProjs);  		return BP(D_volumeData, volumePitch, D_projData, projPitch, -		          dims, angles, TOffsets); +		          dims, angles, TOffsets, outputScale);  	} else {  		assert(fanProjs);  		return FanBP(D_volumeData, volumePitch, D_projData, projPitch, -		             dims, fanProjs); +		             dims, fanProjs, outputScale);  	}  } diff --git a/cuda/2d/algo.h b/cuda/2d/algo.h index a75905e..99959c8 100644 --- a/cuda/2d/algo.h +++ b/cuda/2d/algo.h @@ -118,7 +118,8 @@ protected:  	            float* D_projData, unsigned int projPitch,  	            float outputScale);  	bool callBP(float* D_volumeData, unsigned int volumePitch, -	            float* D_projData, unsigned int projPitch); +	            float* D_projData, unsigned int projPitch, +	            float outputScale);  	SDimensions dims; diff --git a/cuda/2d/astra.cu b/cuda/2d/astra.cu index 2f72db0..4c69628 100644 --- a/cuda/2d/astra.cu +++ b/cuda/2d/astra.cu @@ -368,21 +368,19 @@ bool AstraFBP::run()  	} +	float fOutputScale = (M_PI / 2.0f) / (float)pData->dims.iProjAngles; +  	if (pData->bFanBeam) { -		ok = FanBP_FBPWeighted(pData->D_volumeData, pData->volumePitch, pData->D_sinoData, pData->sinoPitch, pData->dims, pData->fanProjections); +		ok = FanBP_FBPWeighted(pData->D_volumeData, pData->volumePitch, pData->D_sinoData, pData->sinoPitch, pData->dims, pData->fanProjections, fOutputScale);  	} else { -		ok = BP(pData->D_volumeData, pData->volumePitch, pData->D_sinoData, pData->sinoPitch, pData->dims, pData->angles, pData->TOffsets); +		ok = BP(pData->D_volumeData, pData->volumePitch, pData->D_sinoData, pData->sinoPitch, pData->dims, pData->angles, pData->TOffsets, fOutputScale);  	}  	if(!ok)  	{  		return false;  	} -	processVol<opMul>(pData->D_volumeData, -	                      (M_PI / 2.0f) / (float)pData->dims.iProjAngles, -	                      pData->volumePitch, pData->dims); -  	return true;  } @@ -594,7 +592,7 @@ bool BPalgo::iterate(unsigned int)  {  	// TODO: This zeroVolume makes an earlier memcpy of D_volumeData redundant  	zeroVolumeData(D_volumeData, volumePitch, dims); -	callBP(D_volumeData, volumePitch, D_sinoData, sinoPitch); +	callBP(D_volumeData, volumePitch, D_sinoData, sinoPitch, 1.0f);  	return true;  } diff --git a/cuda/2d/cgls.cu b/cuda/2d/cgls.cu index 9ead563..f402914 100644 --- a/cuda/2d/cgls.cu +++ b/cuda/2d/cgls.cu @@ -135,7 +135,7 @@ bool CGLS::iterate(unsigned int iterations)  		// p = A'*r  		zeroVolumeData(D_p, pPitch, dims); -		callBP(D_p, pPitch, D_r, rPitch); +		callBP(D_p, pPitch, D_r, rPitch, 1.0f);  		if (useVolumeMask)  			processVol<opMul>(D_p, D_maskData, pPitch, dims); @@ -166,7 +166,7 @@ bool CGLS::iterate(unsigned int iterations)  		// z = A'*r  		zeroVolumeData(D_z, zPitch, dims); -		callBP(D_z, zPitch, D_r, rPitch); +		callBP(D_z, zPitch, D_r, rPitch, 1.0f);  		if (useVolumeMask)  			processVol<opMul>(D_z, D_maskData, zPitch, dims); diff --git a/cuda/2d/em.cu b/cuda/2d/em.cu index 00127c0..8593b08 100644 --- a/cuda/2d/em.cu +++ b/cuda/2d/em.cu @@ -102,7 +102,7 @@ bool EM::precomputeWeights()  #endif  	{  		processSino<opSet>(D_projData, 1.0f, projPitch, dims); -		callBP(D_pixelWeight, pixelPitch, D_projData, projPitch); +		callBP(D_pixelWeight, pixelPitch, D_projData, projPitch, 1.0f);  	}  	processVol<opInvert>(D_pixelWeight, pixelPitch, dims); @@ -137,7 +137,7 @@ bool EM::iterate(unsigned int iterations)  		// Do BP of projData into tmpData  		zeroVolumeData(D_tmpData, tmpPitch, dims); -		callBP(D_tmpData, tmpPitch, D_projData, projPitch); +		callBP(D_tmpData, tmpPitch, D_projData, projPitch, 1.0f);  		// Multiply volumeData with tmpData divided by pixel weights  		processVol<opMul2>(D_volumeData, D_tmpData, D_pixelWeight, pixelPitch, dims); diff --git a/cuda/2d/fan_bp.cu b/cuda/2d/fan_bp.cu index 74e8b12..b4321ba 100644 --- a/cuda/2d/fan_bp.cu +++ b/cuda/2d/fan_bp.cu @@ -77,7 +77,7 @@ static bool bindProjDataTexture(float* data, unsigned int pitch, unsigned int wi  	return true;  } -__global__ void devFanBP(float* D_volData, unsigned int volPitch, unsigned int startAngle, const SDimensions dims) +__global__ void devFanBP(float* D_volData, unsigned int volPitch, unsigned int startAngle, const SDimensions dims, float fOutputScale)  {  	const int relX = threadIdx.x;  	const int relY = threadIdx.y; @@ -121,11 +121,11 @@ __global__ void devFanBP(float* D_volData, unsigned int volPitch, unsigned int s  		fA += 1.0f;  	} -	volData[Y*volPitch+X] += fVal; +	volData[Y*volPitch+X] += fVal * fOutputScale;  }  // supersampling version -__global__ void devFanBP_SS(float* D_volData, unsigned int volPitch, unsigned int startAngle, const SDimensions dims) +__global__ void devFanBP_SS(float* D_volData, unsigned int volPitch, unsigned int startAngle, const SDimensions dims, float fOutputScale)  {  	const int relX = threadIdx.x;  	const int relY = threadIdx.y; @@ -146,6 +146,8 @@ __global__ void devFanBP_SS(float* D_volData, unsigned int volPitch, unsigned in  	float* volData = (float*)D_volData; +	fOutputScale /= (dims.iRaysPerPixelDim * dims.iRaysPerPixelDim); +  	float fVal = 0.0f;  	float fA = startAngle + 0.5f; @@ -180,14 +182,14 @@ __global__ void devFanBP_SS(float* D_volData, unsigned int volPitch, unsigned in  		fA += 1.0f;  	} -	volData[Y*volPitch+X] += fVal / (dims.iRaysPerPixelDim * dims.iRaysPerPixelDim); +	volData[Y*volPitch+X] += fVal * fOutputScale;  }  // BP specifically for SART.  // It includes (free) weighting with voxel weight.  // It assumes the proj texture is set up _without_ padding, unlike regular BP. -__global__ void devFanBP_SART(float* D_volData, unsigned int volPitch, const SDimensions dims) +__global__ void devFanBP_SART(float* D_volData, unsigned int volPitch, const SDimensions dims, float fOutputScale)  {  	const int relX = threadIdx.x;  	const int relY = threadIdx.y; @@ -222,12 +224,12 @@ __global__ void devFanBP_SART(float* D_volData, unsigned int volPitch, const SDi  	const float fT = fNum / fDen;  	const float fVal = tex2D(gT_FanProjTexture, fT, 0.5f); -	volData[Y*volPitch+X] += fVal; +	volData[Y*volPitch+X] += fVal * fOutputScale;  }  // Weighted BP for use in fan beam FBP  // Each pixel/ray is weighted by 1/L^2 where L is the distance to the source. -__global__ void devFanBP_FBPWeighted(float* D_volData, unsigned int volPitch, unsigned int startAngle, const SDimensions dims) +__global__ void devFanBP_FBPWeighted(float* D_volData, unsigned int volPitch, unsigned int startAngle, const SDimensions dims, float fOutputScale)  {  	const int relX = threadIdx.x;  	const int relY = threadIdx.y; @@ -273,13 +275,14 @@ __global__ void devFanBP_FBPWeighted(float* D_volData, unsigned int volPitch, un  		fA += 1.0f;  	} -	volData[Y*volPitch+X] += fVal; +	volData[Y*volPitch+X] += fVal * fOutputScale;  }  bool FanBP_internal(float* D_volumeData, unsigned int volumePitch,             float* D_projData, unsigned int projPitch, -           const SDimensions& dims, const SFanProjection* angles) +           const SDimensions& dims, const SFanProjection* angles, +           float fOutputScale)  {  	assert(dims.iProjAngles <= g_MaxAngles); @@ -310,9 +313,9 @@ bool FanBP_internal(float* D_volumeData, unsigned int volumePitch,  	for (unsigned int i = 0; i < dims.iProjAngles; i += g_anglesPerBlock) {  		if (dims.iRaysPerPixelDim > 1) -			devFanBP_SS<<<dimGrid, dimBlock, 0, stream>>>(D_volumeData, volumePitch, i, dims); +			devFanBP_SS<<<dimGrid, dimBlock, 0, stream>>>(D_volumeData, volumePitch, i, dims, fOutputScale);  		else -			devFanBP<<<dimGrid, dimBlock, 0, stream>>>(D_volumeData, volumePitch, i, dims); +			devFanBP<<<dimGrid, dimBlock, 0, stream>>>(D_volumeData, volumePitch, i, dims, fOutputScale);  	}  	cudaThreadSynchronize(); @@ -325,7 +328,8 @@ bool FanBP_internal(float* D_volumeData, unsigned int volumePitch,  bool FanBP_FBPWeighted_internal(float* D_volumeData, unsigned int volumePitch,             float* D_projData, unsigned int projPitch, -           const SDimensions& dims, const SFanProjection* angles) +           const SDimensions& dims, const SFanProjection* angles, +           float fOutputScale)  {  	assert(dims.iProjAngles <= g_MaxAngles); @@ -355,7 +359,7 @@ bool FanBP_FBPWeighted_internal(float* D_volumeData, unsigned int volumePitch,  	cudaStreamCreate(&stream);  	for (unsigned int i = 0; i < dims.iProjAngles; i += g_anglesPerBlock) { -		devFanBP_FBPWeighted<<<dimGrid, dimBlock, 0, stream>>>(D_volumeData, volumePitch, i, dims); +		devFanBP_FBPWeighted<<<dimGrid, dimBlock, 0, stream>>>(D_volumeData, volumePitch, i, dims, fOutputScale);  	}  	cudaThreadSynchronize(); @@ -370,7 +374,8 @@ bool FanBP_FBPWeighted_internal(float* D_volumeData, unsigned int volumePitch,  bool FanBP_SART(float* D_volumeData, unsigned int volumePitch,                  float* D_projData, unsigned int projPitch,                  unsigned int angle, -                const SDimensions& dims, const SFanProjection* angles) +                const SDimensions& dims, const SFanProjection* angles, +                float fOutputScale)  {  	// only one angle  	bindProjDataTexture(D_projData, projPitch, dims.iProjDets, 1, cudaAddressModeClamp); @@ -391,7 +396,7 @@ bool FanBP_SART(float* D_volumeData, unsigned int volumePitch,  	dim3 dimGrid((dims.iVolWidth+g_blockSlices-1)/g_blockSlices,  	             (dims.iVolHeight+g_blockSliceSize-1)/g_blockSliceSize); -	devFanBP_SART<<<dimGrid, dimBlock>>>(D_volumeData, volumePitch, dims); +	devFanBP_SART<<<dimGrid, dimBlock>>>(D_volumeData, volumePitch, dims, fOutputScale);  	cudaThreadSynchronize();  	cudaTextForceKernelsCompletion(); @@ -401,7 +406,8 @@ bool FanBP_SART(float* D_volumeData, unsigned int volumePitch,  bool FanBP(float* D_volumeData, unsigned int volumePitch,             float* D_projData, unsigned int projPitch, -           const SDimensions& dims, const SFanProjection* angles) +           const SDimensions& dims, const SFanProjection* angles, +           float fOutputScale)  {  	for (unsigned int iAngle = 0; iAngle < dims.iProjAngles; iAngle += g_MaxAngles) {  		SDimensions subdims = dims; @@ -413,7 +419,7 @@ bool FanBP(float* D_volumeData, unsigned int volumePitch,  		bool ret;  		ret = FanBP_internal(D_volumeData, volumePitch,  		                  D_projData + iAngle * projPitch, projPitch, -		                  subdims, angles + iAngle); +		                  subdims, angles + iAngle, fOutputScale);  		if (!ret)  			return false;  	} @@ -422,7 +428,8 @@ bool FanBP(float* D_volumeData, unsigned int volumePitch,  bool FanBP_FBPWeighted(float* D_volumeData, unsigned int volumePitch,             float* D_projData, unsigned int projPitch, -           const SDimensions& dims, const SFanProjection* angles) +           const SDimensions& dims, const SFanProjection* angles, +           float fOutputScale)  {  	for (unsigned int iAngle = 0; iAngle < dims.iProjAngles; iAngle += g_MaxAngles) {  		SDimensions subdims = dims; @@ -434,7 +441,7 @@ bool FanBP_FBPWeighted(float* D_volumeData, unsigned int volumePitch,  		bool ret;  		ret = FanBP_FBPWeighted_internal(D_volumeData, volumePitch,  		                  D_projData + iAngle * projPitch, projPitch, -		                  subdims, angles + iAngle); +		                  subdims, angles + iAngle, fOutputScale);  		if (!ret)  			return false; @@ -498,7 +505,7 @@ int main()  	copyVolumeToDevice(img, dims.iVolWidth, dims.iVolWidth, dims.iVolHeight, D_volumeData, volumePitch);  	copySinogramToDevice(sino, dims.iProjDets, dims.iProjDets, dims.iProjAngles, D_projData, projPitch); -	FanBP(D_volumeData, volumePitch, D_projData, projPitch, dims, projs); +	FanBP(D_volumeData, volumePitch, D_projData, projPitch, dims, projs, 1.0f);  	copyVolumeFromDevice(img, dims.iVolWidth, dims.iVolWidth, dims.iVolHeight, D_volumeData, volumePitch); diff --git a/cuda/2d/fan_bp.h b/cuda/2d/fan_bp.h index e4e69b0..3ebe1e8 100644 --- a/cuda/2d/fan_bp.h +++ b/cuda/2d/fan_bp.h @@ -33,16 +33,19 @@ namespace astraCUDA {  _AstraExport bool FanBP(float* D_volumeData, unsigned int volumePitch,             float* D_projData, unsigned int projPitch, -           const SDimensions& dims, const SFanProjection* angles); +           const SDimensions& dims, const SFanProjection* angles, +           float fOutputScale);  _AstraExport bool FanBP_SART(float* D_volumeData, unsigned int volumePitch,                  float* D_projData, unsigned int projPitch,                  unsigned int angle, -                const SDimensions& dims, const SFanProjection* angles); +                const SDimensions& dims, const SFanProjection* angles, +                float fOutputScale);  _AstraExport bool FanBP_FBPWeighted(float* D_volumeData, unsigned int volumePitch,             float* D_projData, unsigned int projPitch, -           const SDimensions& dims, const SFanProjection* angles); +           const SDimensions& dims, const SFanProjection* angles, +           float fOutputScale);  } diff --git a/cuda/2d/par_bp.cu b/cuda/2d/par_bp.cu index 635200f..d9f7325 100644 --- a/cuda/2d/par_bp.cu +++ b/cuda/2d/par_bp.cu @@ -73,7 +73,7 @@ static bool bindProjDataTexture(float* data, unsigned int pitch, unsigned int wi  	return true;  } -__global__ void devBP(float* D_volData, unsigned int volPitch, unsigned int startAngle, bool offsets, const SDimensions dims) +__global__ void devBP(float* D_volData, unsigned int volPitch, unsigned int startAngle, bool offsets, const SDimensions dims, float fOutputScale)  {  	const int relX = threadIdx.x;  	const int relY = threadIdx.y; @@ -123,11 +123,11 @@ __global__ void devBP(float* D_volData, unsigned int volPitch, unsigned int star  	} -	volData[Y*volPitch+X] += fVal; +	volData[Y*volPitch+X] += fVal * fOutputScale;  }  // supersampling version -__global__ void devBP_SS(float* D_volData, unsigned int volPitch, unsigned int startAngle, bool offsets, const SDimensions dims) +__global__ void devBP_SS(float* D_volData, unsigned int volPitch, unsigned int startAngle, bool offsets, const SDimensions dims, float fOutputScale)  {  	const int relX = threadIdx.x;  	const int relY = threadIdx.y; @@ -152,6 +152,8 @@ __global__ void devBP_SS(float* D_volData, unsigned int volPitch, unsigned int s  	float fA = startAngle + 0.5f;  	const float fT_base = 0.5f*dims.iProjDets - 0.5f + 0.5f; +	fOutputScale /= (dims.iRaysPerPixelDim * dims.iRaysPerPixelDim); +  	if (offsets) {  		for (int angle = startAngle; angle < endAngle; ++angle) @@ -196,10 +198,10 @@ __global__ void devBP_SS(float* D_volData, unsigned int volPitch, unsigned int s  	} -	volData[Y*volPitch+X] += fVal / (dims.iRaysPerPixelDim * dims.iRaysPerPixelDim); +	volData[Y*volPitch+X] += fVal * fOutputScale;  } -__global__ void devBP_SART(float* D_volData, unsigned int volPitch, float offset, float angle_sin, float angle_cos, const SDimensions dims) +__global__ void devBP_SART(float* D_volData, unsigned int volPitch, float offset, float angle_sin, float angle_cos, const SDimensions dims, float fOutputScale)  {  	const int relX = threadIdx.x;  	const int relY = threadIdx.y; @@ -218,13 +220,13 @@ __global__ void devBP_SART(float* D_volData, unsigned int volPitch, float offset  	const float fT = fT_base + fX * angle_cos - fY * angle_sin + offset;  	const float fVal = tex2D(gT_projTexture, fT, 0.5f); -	D_volData[Y*volPitch+X] += fVal; +	D_volData[Y*volPitch+X] += fVal * fOutputScale;  }  bool BP_internal(float* D_volumeData, unsigned int volumePitch,          float* D_projData, unsigned int projPitch, -        const SDimensions& dims, const float* angles, const float* TOffsets) +        const SDimensions& dims, const float* angles, const float* TOffsets, float fOutputScale)  {  	// TODO: process angles block by block  	assert(dims.iProjAngles <= g_MaxAngles); @@ -261,9 +263,9 @@ bool BP_internal(float* D_volumeData, unsigned int volumePitch,  	for (unsigned int i = 0; i < dims.iProjAngles; i += g_anglesPerBlock) {  		if (dims.iRaysPerPixelDim > 1) -			devBP_SS<<<dimGrid, dimBlock, 0, stream>>>(D_volumeData, volumePitch, i, (TOffsets != 0), dims); +			devBP_SS<<<dimGrid, dimBlock, 0, stream>>>(D_volumeData, volumePitch, i, (TOffsets != 0), dims, fOutputScale);  		else -			devBP<<<dimGrid, dimBlock, 0, stream>>>(D_volumeData, volumePitch, i, (TOffsets != 0), dims); +			devBP<<<dimGrid, dimBlock, 0, stream>>>(D_volumeData, volumePitch, i, (TOffsets != 0), dims, fOutputScale);  	}  	cudaThreadSynchronize(); @@ -276,7 +278,7 @@ bool BP_internal(float* D_volumeData, unsigned int volumePitch,  bool BP(float* D_volumeData, unsigned int volumePitch,          float* D_projData, unsigned int projPitch, -        const SDimensions& dims, const float* angles, const float* TOffsets) +        const SDimensions& dims, const float* angles, const float* TOffsets, float fOutputScale)  {  	for (unsigned int iAngle = 0; iAngle < dims.iProjAngles; iAngle += g_MaxAngles) {  		SDimensions subdims = dims; @@ -289,7 +291,8 @@ bool BP(float* D_volumeData, unsigned int volumePitch,  		ret = BP_internal(D_volumeData, volumePitch,  		                  D_projData + iAngle * projPitch, projPitch,  		                  subdims, angles + iAngle, -		                  TOffsets ? TOffsets + iAngle : 0); +		                  TOffsets ? TOffsets + iAngle : 0, +		                  fOutputScale);  		if (!ret)  			return false;  	} @@ -300,7 +303,7 @@ bool BP(float* D_volumeData, unsigned int volumePitch,  bool BP_SART(float* D_volumeData, unsigned int volumePitch,               float* D_projData, unsigned int projPitch,               unsigned int angle, const SDimensions& dims, -             const float* angles, const float* TOffsets) +             const float* angles, const float* TOffsets, float fOutputScale)  {  	// Only one angle.  	// We need to Clamp to the border pixels instead of to zero, because @@ -318,7 +321,7 @@ bool BP_SART(float* D_volumeData, unsigned int volumePitch,  	dim3 dimGrid((dims.iVolWidth+g_blockSlices-1)/g_blockSlices,  	             (dims.iVolHeight+g_blockSliceSize-1)/g_blockSliceSize); -	devBP_SART<<<dimGrid, dimBlock>>>(D_volumeData, volumePitch, offset, angle_sin, angle_cos, dims); +	devBP_SART<<<dimGrid, dimBlock>>>(D_volumeData, volumePitch, offset, angle_sin, angle_cos, dims, fOutputScale);  	cudaThreadSynchronize();  	cudaTextForceKernelsCompletion(); @@ -369,7 +372,7 @@ int main()  	for (unsigned int i = 0; i < dims.iProjAngles; ++i)  		angle[i] = i*(M_PI/dims.iProjAngles); -	BP(D_volumeData, volumePitch, D_projData, projPitch, dims, angle, 0); +	BP(D_volumeData, volumePitch, D_projData, projPitch, dims, angle, 0, 1.0f);  	delete[] angle; diff --git a/cuda/2d/par_bp.h b/cuda/2d/par_bp.h index eaeafd8..64bcd34 100644 --- a/cuda/2d/par_bp.h +++ b/cuda/2d/par_bp.h @@ -36,12 +36,12 @@ namespace astraCUDA {  _AstraExport bool BP(float* D_volumeData, unsigned int volumePitch,          float* D_projData, unsigned int projPitch,          const SDimensions& dims, const float* angles, -        const float* TOffsets); +        const float* TOffsets, float fOutputScale);  _AstraExport bool BP_SART(float* D_volumeData, unsigned int volumePitch,               float* D_projData, unsigned int projPitch,               unsigned int angle, const SDimensions& dims, -             const float* angles, const float* TOffsets); +             const float* angles, const float* TOffsets, float fOutputScale);  } diff --git a/cuda/2d/sart.cu b/cuda/2d/sart.cu index 29670c3..e5cb5bb 100644 --- a/cuda/2d/sart.cu +++ b/cuda/2d/sart.cu @@ -200,10 +200,10 @@ bool SART::iterate(unsigned int iterations)  			// BP, mask, and add back  			// TODO: Try putting the masking directly in the BP  			zeroVolumeData(D_tmpData, tmpPitch, dims); -			callBP_SART(D_tmpData, tmpPitch, D_projData, projPitch, angle); +			callBP_SART(D_tmpData, tmpPitch, D_projData, projPitch, angle, 1.0f);  			processVol<opAddMul>(D_volumeData, D_maskData, D_tmpData, volumePitch, dims);  		} else { -			callBP_SART(D_volumeData, volumePitch, D_projData, projPitch, angle); +			callBP_SART(D_volumeData, volumePitch, D_projData, projPitch, angle, 1.0f);  		}  		if (useMinConstraint) @@ -264,16 +264,16 @@ bool SART::callFP_SART(float* D_volumeData, unsigned int volumePitch,  bool SART::callBP_SART(float* D_volumeData, unsigned int volumePitch,                         float* D_projData, unsigned int projPitch, -                       unsigned int angle) +                       unsigned int angle, float outputScale)  {  	if (angles) {  		assert(!fanProjs);  		return BP_SART(D_volumeData, volumePitch, D_projData, projPitch, -		               angle, dims, angles, TOffsets); +		               angle, dims, angles, TOffsets, outputScale);  	} else {  		assert(fanProjs);  		return FanBP_SART(D_volumeData, volumePitch, D_projData, projPitch, -		                  angle, dims, fanProjs); +		                  angle, dims, fanProjs, outputScale);  	}  } diff --git a/cuda/2d/sart.h b/cuda/2d/sart.h index 6574a6f..7dcd641 100644 --- a/cuda/2d/sart.h +++ b/cuda/2d/sart.h @@ -59,7 +59,7 @@ protected:  	                 unsigned int angle, float outputScale);  	bool callBP_SART(float* D_volumeData, unsigned int volumePitch,  	                 float* D_projData, unsigned int projPitch, -	                 unsigned int angle); +	                 unsigned int angle, float outputScale);  	// projection angle variables diff --git a/cuda/2d/sirt.cu b/cuda/2d/sirt.cu index a6194a5..162ee77 100644 --- a/cuda/2d/sirt.cu +++ b/cuda/2d/sirt.cu @@ -127,10 +127,10 @@ bool SIRT::precomputeWeights()  	zeroVolumeData(D_pixelWeight, pixelPitch, dims);  	if (useSinogramMask) { -		callBP(D_pixelWeight, pixelPitch, D_smaskData, smaskPitch); +		callBP(D_pixelWeight, pixelPitch, D_smaskData, smaskPitch, 1.0f);  	} else {  		processSino<opSet>(D_projData, 1.0f, projPitch, dims); -		callBP(D_pixelWeight, pixelPitch, D_projData, projPitch); +		callBP(D_pixelWeight, pixelPitch, D_projData, projPitch, 1.0f);  	}  	processVol<opInvert>(D_pixelWeight, pixelPitch, dims); @@ -251,7 +251,7 @@ bool SIRT::iterate(unsigned int iterations)  		zeroVolumeData(D_tmpData, tmpPitch, dims); -		callBP(D_tmpData, tmpPitch, D_projData, projPitch); +		callBP(D_tmpData, tmpPitch, D_projData, projPitch, 1.0f);  		processVol<opAddMul>(D_volumeData, D_pixelWeight, D_tmpData, volumePitch, dims); diff --git a/cuda/3d/algo3d.cu b/cuda/3d/algo3d.cu index 7f61280..cc86b70 100644 --- a/cuda/3d/algo3d.cu +++ b/cuda/3d/algo3d.cu @@ -41,6 +41,7 @@ ReconAlgo3D::ReconAlgo3D()  	coneProjs = 0;  	par3DProjs = 0;  	shouldAbort = false; +	fOutputScale = 1.0f;  }  ReconAlgo3D::~ReconAlgo3D() @@ -57,9 +58,10 @@ void ReconAlgo3D::reset()  	shouldAbort = false;  } -bool ReconAlgo3D::setConeGeometry(const SDimensions3D& _dims, const SConeProjection* _angles) +bool ReconAlgo3D::setConeGeometry(const SDimensions3D& _dims, const SConeProjection* _angles, float _outputScale)  {  	dims = _dims; +	fOutputScale = _outputScale;  	coneProjs = new SConeProjection[dims.iProjAngles];  	par3DProjs = 0; @@ -69,9 +71,10 @@ bool ReconAlgo3D::setConeGeometry(const SDimensions3D& _dims, const SConeProject  	return true;  } -bool ReconAlgo3D::setPar3DGeometry(const SDimensions3D& _dims, const SPar3DProjection* _angles) +bool ReconAlgo3D::setPar3DGeometry(const SDimensions3D& _dims, const SPar3DProjection* _angles, float _outputScale)  {  	dims = _dims; +	fOutputScale = _outputScale;  	par3DProjs = new SPar3DProjection[dims.iProjAngles];  	coneProjs = 0; @@ -87,19 +90,20 @@ bool ReconAlgo3D::callFP(cudaPitchedPtr& D_volumeData,                         float outputScale)  {  	if (coneProjs) { -		return ConeFP(D_volumeData, D_projData, dims, coneProjs, outputScale); +		return ConeFP(D_volumeData, D_projData, dims, coneProjs, outputScale * this->fOutputScale);  	} else { -		return Par3DFP(D_volumeData, D_projData, dims, par3DProjs, outputScale); +		return Par3DFP(D_volumeData, D_projData, dims, par3DProjs, outputScale * this->fOutputScale);  	}  }  bool ReconAlgo3D::callBP(cudaPitchedPtr& D_volumeData, -                       cudaPitchedPtr& D_projData) +                       cudaPitchedPtr& D_projData, +                       float outputScale)  {  	if (coneProjs) { -		return ConeBP(D_volumeData, D_projData, dims, coneProjs); +		return ConeBP(D_volumeData, D_projData, dims, coneProjs, outputScale * this->fOutputScale);  	} else { -		return Par3DBP(D_volumeData, D_projData, dims, par3DProjs); +		return Par3DBP(D_volumeData, D_projData, dims, par3DProjs, outputScale * this->fOutputScale);  	}  } diff --git a/cuda/3d/algo3d.h b/cuda/3d/algo3d.h index f4c6a87..886b092 100644 --- a/cuda/3d/algo3d.h +++ b/cuda/3d/algo3d.h @@ -39,8 +39,8 @@ public:  	ReconAlgo3D();  	~ReconAlgo3D(); -	bool setConeGeometry(const SDimensions3D& dims, const SConeProjection* projs); -	bool setPar3DGeometry(const SDimensions3D& dims, const SPar3DProjection* projs); +	bool setConeGeometry(const SDimensions3D& dims, const SConeProjection* projs, float fOutputScale); +	bool setPar3DGeometry(const SDimensions3D& dims, const SPar3DProjection* projs, float fOutputScale);  	void signalAbort() { shouldAbort = true; } @@ -51,12 +51,15 @@ protected:  	            cudaPitchedPtr& D_projData,   	            float outputScale);  	bool callBP(cudaPitchedPtr& D_volumeData,  -	            cudaPitchedPtr& D_projData); +	            cudaPitchedPtr& D_projData, +	            float outputScale);  	SDimensions3D dims;  	SConeProjection* coneProjs;  	SPar3DProjection* par3DProjs; +	float fOutputScale; +  	volatile bool shouldAbort;  }; diff --git a/cuda/3d/astra3d.cu b/cuda/3d/astra3d.cu index 0b9c70b..8328229 100644 --- a/cuda/3d/astra3d.cu +++ b/cuda/3d/astra3d.cu @@ -40,6 +40,12 @@ $Id$  #include "arith3d.h"  #include "astra3d.h" +#include "astra/ParallelProjectionGeometry3D.h" +#include "astra/ParallelVecProjectionGeometry3D.h" +#include "astra/ConeProjectionGeometry3D.h" +#include "astra/ConeVecProjectionGeometry3D.h" +#include "astra/VolumeGeometry3D.h" +  #include <iostream>  using namespace astraCUDA3d; @@ -52,86 +58,200 @@ enum CUDAProjectionType3d {  }; -static SConeProjection* genConeProjections(unsigned int iProjAngles, -                                           unsigned int iProjU, -                                           unsigned int iProjV, -                                           double fOriginSourceDistance, -                                           double fOriginDetectorDistance, -                                           double fDetUSize, -                                           double fDetVSize, -                                           const float *pfAngles) -{ -	SConeProjection base; -	base.fSrcX = 0.0f; -	base.fSrcY = -fOriginSourceDistance; -	base.fSrcZ = 0.0f; -	base.fDetSX = iProjU * fDetUSize * -0.5f; -	base.fDetSY = fOriginDetectorDistance; -	base.fDetSZ = iProjV * fDetVSize * -0.5f; -	base.fDetUX = fDetUSize; -	base.fDetUY = 0.0f; -	base.fDetUZ = 0.0f; -	base.fDetVX = 0.0f; -	base.fDetVY = 0.0f; -	base.fDetVZ = fDetVSize; -	SConeProjection* p = new SConeProjection[iProjAngles]; +// adjust pProjs to normalize volume geometry +template<typename ProjectionT> +static bool convertAstraGeometry_internal(const CVolumeGeometry3D* pVolGeom, +                          unsigned int iProjectionAngleCount, +                          ProjectionT*& pProjs, +                          float& fOutputScale) +{ +	assert(pVolGeom); +	assert(pProjs); + +	// TODO: Relative instead of absolute +	const float EPS = 0.00001f; +	if (abs(pVolGeom->getPixelLengthX() - pVolGeom->getPixelLengthY()) > EPS) +		return false; +	if (abs(pVolGeom->getPixelLengthX() - pVolGeom->getPixelLengthZ()) > EPS) +		return false; -#define ROTATE0(name,i,alpha) do { p[i].f##name##X = base.f##name##X * cos(alpha) - base.f##name##Y * sin(alpha); p[i].f##name##Y = base.f##name##X * sin(alpha) + base.f##name##Y * cos(alpha); p[i].f##name##Z = base.f##name##Z; } while(0) -	for (unsigned int i = 0; i < iProjAngles; ++i) { -		ROTATE0(Src, i, pfAngles[i]); -		ROTATE0(DetS, i, pfAngles[i]); -		ROTATE0(DetU, i, pfAngles[i]); -		ROTATE0(DetV, i, pfAngles[i]); +	// Translate +	float dx = -(pVolGeom->getWindowMinX() + pVolGeom->getWindowMaxX()) / 2; +	float dy = -(pVolGeom->getWindowMinY() + pVolGeom->getWindowMaxY()) / 2; +	float dz = -(pVolGeom->getWindowMinZ() + pVolGeom->getWindowMaxZ()) / 2; + +	float factor = 1.0f / pVolGeom->getPixelLengthX(); + +	for (int i = 0; i < iProjectionAngleCount; ++i) { +		// CHECKME: Order of scaling and translation +		pProjs[i].translate(dx, dy, dz); +		pProjs[i].scale(factor);  	} -#undef ROTATE0 +	// CHECKME: Check factor +	fOutputScale *= pVolGeom->getPixelLengthX(); + +	return true; +} + + +bool convertAstraGeometry_dims(const CVolumeGeometry3D* pVolGeom, +                               const CProjectionGeometry3D* pProjGeom, +                               SDimensions3D& dims) +{ +	dims.iVolX = pVolGeom->getGridColCount(); +	dims.iVolY = pVolGeom->getGridRowCount(); +	dims.iVolZ = pVolGeom->getGridSliceCount(); +	dims.iProjAngles = pProjGeom->getProjectionCount(); +	dims.iProjU = pProjGeom->getDetectorColCount(), +	dims.iProjV = pProjGeom->getDetectorRowCount(), +	dims.iRaysPerDetDim = 1; +	dims.iRaysPerVoxelDim = 1; + +	if (dims.iVolX <= 0 || dims.iVolX <= 0 || dims.iVolX <= 0) +		return false; +	if (dims.iProjAngles <= 0 || dims.iProjU <= 0 || dims.iProjV <= 0) +		return false; -	return p; +	return true;  } -static SPar3DProjection* genPar3DProjections(unsigned int iProjAngles, -                                             unsigned int iProjU, -                                             unsigned int iProjV, -                                             double fDetUSize, -                                             double fDetVSize, -                                             const float *pfAngles) + +bool convertAstraGeometry(const CVolumeGeometry3D* pVolGeom, +                          const CParallelProjectionGeometry3D* pProjGeom, +                          SPar3DProjection*& pProjs, float& fOutputScale)  { -	SPar3DProjection base; -	base.fRayX = 0.0f; -	base.fRayY = 1.0f; -	base.fRayZ = 0.0f; +	assert(pVolGeom); +	assert(pProjGeom); +	assert(pProjGeom->getProjectionAngles()); -	base.fDetSX = iProjU * fDetUSize * -0.5f; -	base.fDetSY = 0.0f; -	base.fDetSZ = iProjV * fDetVSize * -0.5f; +	int nth = pProjGeom->getProjectionCount(); -	base.fDetUX = fDetUSize; -	base.fDetUY = 0.0f; -	base.fDetUZ = 0.0f; +	pProjs = genPar3DProjections(nth, +	                             pProjGeom->getDetectorColCount(), +	                             pProjGeom->getDetectorRowCount(), +	                             pProjGeom->getDetectorSpacingX(), +	                             pProjGeom->getDetectorSpacingY(), +	                             pProjGeom->getProjectionAngles()); -	base.fDetVX = 0.0f; -	base.fDetVY = 0.0f; -	base.fDetVZ = fDetVSize; +	bool ok; -	SPar3DProjection* p = new SPar3DProjection[iProjAngles]; +	fOutputScale = 1.0f; -#define ROTATE0(name,i,alpha) do { p[i].f##name##X = base.f##name##X * cos(alpha) - base.f##name##Y * sin(alpha); p[i].f##name##Y = base.f##name##X * sin(alpha) + base.f##name##Y * cos(alpha); p[i].f##name##Z = base.f##name##Z; } while(0) +	ok = convertAstraGeometry_internal(pVolGeom, nth, pProjs, fOutputScale); -	for (unsigned int i = 0; i < iProjAngles; ++i) { -		ROTATE0(Ray, i, pfAngles[i]); -		ROTATE0(DetS, i, pfAngles[i]); -		ROTATE0(DetU, i, pfAngles[i]); -		ROTATE0(DetV, i, pfAngles[i]); -	} +	return ok; +} + +bool convertAstraGeometry(const CVolumeGeometry3D* pVolGeom, +                          const CParallelVecProjectionGeometry3D* pProjGeom, +                          SPar3DProjection*& pProjs, float& fOutputScale) +{ +	assert(pVolGeom); +	assert(pProjGeom); +	assert(pProjGeom->getProjectionVectors()); + +	int nth = pProjGeom->getProjectionCount(); + +	pProjs = new SPar3DProjection[nth]; +	for (int i = 0; i < nth; ++i) +		pProjs[i] = pProjGeom->getProjectionVectors()[i]; + +	bool ok; + +	fOutputScale = 1.0f; + +	ok = convertAstraGeometry_internal(pVolGeom, nth, pProjs, fOutputScale); + +	return ok; +} + +bool convertAstraGeometry(const CVolumeGeometry3D* pVolGeom, +                          const CConeProjectionGeometry3D* pProjGeom, +                          SConeProjection*& pProjs, float& fOutputScale) +{ +	assert(pVolGeom); +	assert(pProjGeom); +	assert(pProjGeom->getProjectionAngles()); + +	int nth = pProjGeom->getProjectionCount(); + +	pProjs = genConeProjections(nth, +	                            pProjGeom->getDetectorColCount(), +	                            pProjGeom->getDetectorRowCount(), +	                            pProjGeom->getOriginSourceDistance(), +	                            pProjGeom->getOriginDetectorDistance(), +	                            pProjGeom->getDetectorSpacingX(), +	                            pProjGeom->getDetectorSpacingY(), +	                            pProjGeom->getProjectionAngles()); + +	bool ok; + +	fOutputScale = 1.0f; + +	ok = convertAstraGeometry_internal(pVolGeom, nth, pProjs, fOutputScale); + +	return ok; +} + +bool convertAstraGeometry(const CVolumeGeometry3D* pVolGeom, +                          const CConeVecProjectionGeometry3D* pProjGeom, +                          SConeProjection*& pProjs, float& fOutputScale) +{ +	assert(pVolGeom); +	assert(pProjGeom); +	assert(pProjGeom->getProjectionVectors()); + +	int nth = pProjGeom->getProjectionCount(); + +	pProjs = new SConeProjection[nth]; +	for (int i = 0; i < nth; ++i) +		pProjs[i] = pProjGeom->getProjectionVectors()[i]; + +	bool ok; + +	fOutputScale = 1.0f; + +	ok = convertAstraGeometry_internal(pVolGeom, nth, pProjs, fOutputScale); + +	return ok; +} + + +bool convertAstraGeometry(const CVolumeGeometry3D* pVolGeom, +                          const CProjectionGeometry3D* pProjGeom, +                          SPar3DProjection*& pParProjs, +                          SConeProjection*& pConeProjs, +                          float& fOutputScale) +{ +	const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(pProjGeom); +	const CParallelProjectionGeometry3D* par3dgeom = dynamic_cast<const CParallelProjectionGeometry3D*>(pProjGeom); +	const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(pProjGeom); +	const CConeVecProjectionGeometry3D* conevec3dgeom = dynamic_cast<const CConeVecProjectionGeometry3D*>(pProjGeom); + +	pConeProjs = 0; +	pParProjs = 0; -#undef ROTATE0 +	bool ok; -	return p; +	if (conegeom) { +		ok = convertAstraGeometry(pVolGeom, conegeom, pConeProjs, fOutputScale); +	} else if (conevec3dgeom) { +		ok = convertAstraGeometry(pVolGeom, conevec3dgeom, pConeProjs, fOutputScale); +	} else if (par3dgeom) { +		ok = convertAstraGeometry(pVolGeom, par3dgeom, pParProjs, fOutputScale); +	} else if (parvec3dgeom) { +		ok = convertAstraGeometry(pVolGeom, parvec3dgeom, pParProjs, fOutputScale); +	} else { +		ok = false; +	} + +	return ok;  } @@ -151,7 +271,7 @@ public:  	SConeProjection* projs;  	SPar3DProjection* parprojs; -	float fPixelSize; +	float fOutputScale;  	bool initialized;  	bool setStartReconstruction; @@ -188,6 +308,8 @@ AstraSIRT3d::AstraSIRT3d()  	pData->dims.iRaysPerVoxelDim = 1;  	pData->projs = 0; +	pData->parprojs = 0; +	pData->fOutputScale = 1.0f;  	pData->initialized = false;  	pData->setStartReconstruction = false; @@ -220,127 +342,37 @@ AstraSIRT3d::~AstraSIRT3d()  	pData = 0;  } -bool AstraSIRT3d::setReconstructionGeometry(unsigned int iVolX, -                                            unsigned int iVolY, -                                            unsigned int iVolZ/*, -                                            float fPixelSize = 1.0f*/) -{ -	if (pData->initialized) -		return false; - -	pData->dims.iVolX = iVolX; -	pData->dims.iVolY = iVolY; -	pData->dims.iVolZ = iVolZ; - -	return (iVolX > 0 && iVolY > 0 && iVolZ > 0); -} - - -bool AstraSIRT3d::setPar3DGeometry(unsigned int iProjAngles, -                                   unsigned int iProjU, -                                   unsigned int iProjV, -                                   const SPar3DProjection* projs) -{ -	if (pData->initialized) -		return false; - -	pData->dims.iProjAngles = iProjAngles; -	pData->dims.iProjU = iProjU; -	pData->dims.iProjV = iProjV; - -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || projs == 0) -		return false; - -	pData->parprojs = new SPar3DProjection[iProjAngles]; -	memcpy(pData->parprojs, projs, iProjAngles * sizeof(projs[0])); - -	pData->projType = PROJ_PARALLEL; - -	return true; -} - -bool AstraSIRT3d::setPar3DGeometry(unsigned int iProjAngles, -                                   unsigned int iProjU, -                                   unsigned int iProjV, -                                   float fDetUSize, -                                   float fDetVSize, -                                   const float *pfAngles) +bool AstraSIRT3d::setGeometry(const CVolumeGeometry3D* pVolGeom, +	                      const CProjectionGeometry3D* pProjGeom)  {  	if (pData->initialized)  		return false; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; - -	SPar3DProjection* p = genPar3DProjections(iProjAngles, -                                              iProjU, iProjV, -                                              fDetUSize, fDetVSize, -                                              pfAngles); -	pData->dims.iProjAngles = iProjAngles; -	pData->dims.iProjU = iProjU; -	pData->dims.iProjV = iProjV; - -	pData->parprojs = p; -	pData->projType = PROJ_PARALLEL; +	bool ok = convertAstraGeometry_dims(pVolGeom, pProjGeom, pData->dims); -	return true; -} - - - -bool AstraSIRT3d::setConeGeometry(unsigned int iProjAngles, -                                  unsigned int iProjU, -                                  unsigned int iProjV, -                                  const SConeProjection* projs) -{ -	if (pData->initialized) +	if (!ok)  		return false; -	pData->dims.iProjAngles = iProjAngles; -	pData->dims.iProjU = iProjU; -	pData->dims.iProjV = iProjV; +	pData->projs = 0; +	pData->parprojs = 0; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || projs == 0) +	ok = convertAstraGeometry(pVolGeom, pProjGeom, +	                          pData->parprojs, pData->projs, +	                          pData->fOutputScale); +	if (!ok)  		return false; -	pData->projs = new SConeProjection[iProjAngles]; -	memcpy(pData->projs, projs, iProjAngles * sizeof(projs[0])); - -	pData->projType = PROJ_CONE; +	if (pData->projs) { +		assert(pData->parprojs == 0); +		pData->projType = PROJ_CONE; +	} else { +		assert(pData->parprojs != 0); +		pData->projType = PROJ_PARALLEL; +	}  	return true;  } -bool AstraSIRT3d::setConeGeometry(unsigned int iProjAngles, -                                  unsigned int iProjU, -                                  unsigned int iProjV, -                                  float fOriginSourceDistance, -                                  float fOriginDetectorDistance, -                                  float fDetUSize, -                                  float fDetVSize, -                                  const float *pfAngles) -{ -	if (pData->initialized) -		return false; - -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; - -	SConeProjection* p = genConeProjections(iProjAngles, -                                            iProjU, iProjV, -                                            fOriginSourceDistance, -                                            fOriginDetectorDistance, -                                            fDetUSize, fDetVSize, -                                            pfAngles); -	pData->dims.iProjAngles = iProjAngles; -	pData->dims.iProjU = iProjU; -	pData->dims.iProjV = iProjV; - -	pData->projs = p; -	pData->projType = PROJ_CONE; - -	return true; -}  bool AstraSIRT3d::enableSuperSampling(unsigned int iVoxelSuperSampling,                                        unsigned int iDetectorSuperSampling) @@ -404,9 +436,9 @@ bool AstraSIRT3d::init()  	bool ok;  	if (pData->projType == PROJ_PARALLEL) { -		ok = pData->sirt.setPar3DGeometry(pData->dims, pData->parprojs); +		ok = pData->sirt.setPar3DGeometry(pData->dims, pData->parprojs, pData->fOutputScale);  	} else { -		ok = pData->sirt.setConeGeometry(pData->dims, pData->projs); +		ok = pData->sirt.setConeGeometry(pData->dims, pData->projs, pData->fOutputScale);  	}  	if (!ok) @@ -618,7 +650,7 @@ public:  	SConeProjection* projs;  	SPar3DProjection* parprojs; -	float fPixelSize; +	float fOutputScale;  	bool initialized;  	bool setStartReconstruction; @@ -655,6 +687,8 @@ AstraCGLS3d::AstraCGLS3d()  	pData->dims.iRaysPerVoxelDim = 1;  	pData->projs = 0; +	pData->parprojs = 0; +	pData->fOutputScale = 1.0f;  	pData->initialized = false;  	pData->setStartReconstruction = false; @@ -687,125 +721,33 @@ AstraCGLS3d::~AstraCGLS3d()  	pData = 0;  } -bool AstraCGLS3d::setReconstructionGeometry(unsigned int iVolX, -                                            unsigned int iVolY, -                                            unsigned int iVolZ/*, -                                            float fPixelSize = 1.0f*/) -{ -	if (pData->initialized) -		return false; - -	pData->dims.iVolX = iVolX; -	pData->dims.iVolY = iVolY; -	pData->dims.iVolZ = iVolZ; - -	return (iVolX > 0 && iVolY > 0 && iVolZ > 0); -} - - -bool AstraCGLS3d::setPar3DGeometry(unsigned int iProjAngles, -                                   unsigned int iProjU, -                                   unsigned int iProjV, -                                   const SPar3DProjection* projs) -{ -	if (pData->initialized) -		return false; - -	pData->dims.iProjAngles = iProjAngles; -	pData->dims.iProjU = iProjU; -	pData->dims.iProjV = iProjV; - -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || projs == 0) -		return false; - -	pData->parprojs = new SPar3DProjection[iProjAngles]; -	memcpy(pData->parprojs, projs, iProjAngles * sizeof(projs[0])); - -	pData->projType = PROJ_PARALLEL; - -	return true; -} - -bool AstraCGLS3d::setPar3DGeometry(unsigned int iProjAngles, -                                   unsigned int iProjU, -                                   unsigned int iProjV, -                                   float fDetUSize, -                                   float fDetVSize, -                                   const float *pfAngles) -{ -	if (pData->initialized) -		return false; - -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; - -	SPar3DProjection* p = genPar3DProjections(iProjAngles, -                                              iProjU, iProjV, -                                              fDetUSize, fDetVSize, -                                              pfAngles); -	pData->dims.iProjAngles = iProjAngles; -	pData->dims.iProjU = iProjU; -	pData->dims.iProjV = iProjV; - -	pData->parprojs = p; -	pData->projType = PROJ_PARALLEL; - -	return true; -} - - - -bool AstraCGLS3d::setConeGeometry(unsigned int iProjAngles, -                                  unsigned int iProjU, -                                  unsigned int iProjV, -                                  const SConeProjection* projs) +bool AstraCGLS3d::setGeometry(const CVolumeGeometry3D* pVolGeom, +	                      const CProjectionGeometry3D* pProjGeom)  {  	if (pData->initialized)  		return false; -	pData->dims.iProjAngles = iProjAngles; -	pData->dims.iProjU = iProjU; -	pData->dims.iProjV = iProjV; +	bool ok = convertAstraGeometry_dims(pVolGeom, pProjGeom, pData->dims); -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || projs == 0) +	if (!ok)  		return false; -	pData->projs = new SConeProjection[iProjAngles]; -	memcpy(pData->projs, projs, iProjAngles * sizeof(projs[0])); - -	pData->projType = PROJ_CONE; - -	return true; -} - -bool AstraCGLS3d::setConeGeometry(unsigned int iProjAngles, -                                  unsigned int iProjU, -                                  unsigned int iProjV, -                                  float fOriginSourceDistance, -                                  float fOriginDetectorDistance, -                                  float fDetUSize, -                                  float fDetVSize, -                                  const float *pfAngles) -{ -	if (pData->initialized) -		return false; +	pData->projs = 0; +	pData->parprojs = 0; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) +	ok = convertAstraGeometry(pVolGeom, pProjGeom, +	                          pData->parprojs, pData->projs, +	                          pData->fOutputScale); +	if (!ok)  		return false; -	SConeProjection* p = genConeProjections(iProjAngles, -                                            iProjU, iProjV, -                                            fOriginSourceDistance, -                                            fOriginDetectorDistance, -                                            fDetUSize, fDetVSize, -                                            pfAngles); - -	pData->dims.iProjAngles = iProjAngles; -	pData->dims.iProjU = iProjU; -	pData->dims.iProjV = iProjV; - -	pData->projs = p; -	pData->projType = PROJ_CONE; +	if (pData->projs) { +		assert(pData->parprojs == 0); +		pData->projType = PROJ_CONE; +	} else { +		assert(pData->parprojs != 0); +		pData->projType = PROJ_PARALLEL; +	}  	return true;  } @@ -874,9 +816,9 @@ bool AstraCGLS3d::init()  	bool ok;  	if (pData->projType == PROJ_PARALLEL) { -		ok = pData->cgls.setPar3DGeometry(pData->dims, pData->parprojs); +		ok = pData->cgls.setPar3DGeometry(pData->dims, pData->parprojs, pData->fOutputScale);  	} else { -		ok = pData->cgls.setConeGeometry(pData->dims, pData->projs); +		ok = pData->cgls.setConeGeometry(pData->dims, pData->projs, pData->fOutputScale);  	}  	if (!ok) @@ -1077,179 +1019,31 @@ float AstraCGLS3d::computeDiffNorm() -bool astraCudaConeFP(const float* pfVolume, float* pfProjections, -                     unsigned int iVolX, -                     unsigned int iVolY, -                     unsigned int iVolZ, -                     unsigned int iProjAngles, -                     unsigned int iProjU, -                     unsigned int iProjV, -                     float fOriginSourceDistance, -                     float fOriginDetectorDistance, -                     float fDetUSize, -                     float fDetVSize, -                     const float *pfAngles, -                     int iGPUIndex, int iDetectorSuperSampling) -{ -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) -		return false; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; - -	SConeProjection* p = genConeProjections(iProjAngles, -                                            iProjU, iProjV, -                                            fOriginSourceDistance, -                                            fOriginDetectorDistance, -                                            fDetUSize, fDetVSize, -                                            pfAngles); - -	bool ok; -	ok = astraCudaConeFP(pfVolume, pfProjections, iVolX, iVolY, iVolZ, -	                     iProjAngles, iProjU, iProjV, p, iGPUIndex, iDetectorSuperSampling); - -	delete[] p; - -	return ok; -} - -bool astraCudaConeFP(const float* pfVolume, float* pfProjections, -                     unsigned int iVolX, -                     unsigned int iVolY, -                     unsigned int iVolZ, -                     unsigned int iProjAngles, -                     unsigned int iProjU, -                     unsigned int iProjV, -                     const SConeProjection *pfAngles, -                     int iGPUIndex, int iDetectorSuperSampling) +bool astraCudaFP(const float* pfVolume, float* pfProjections, +                 const CVolumeGeometry3D* pVolGeom, +                 const CProjectionGeometry3D* pProjGeom, +                 int iGPUIndex, int iDetectorSuperSampling, +                 Cuda3DProjectionKernel projKernel)  {  	SDimensions3D dims; -	dims.iVolX = iVolX; -	dims.iVolY = iVolY; -	dims.iVolZ = iVolZ; -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) -		return false; - -	dims.iProjAngles = iProjAngles; -	dims.iProjU = iProjU; -	dims.iProjV = iProjV; - -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) +	bool ok = convertAstraGeometry_dims(pVolGeom, pProjGeom, dims); +	if (!ok)  		return false;  	dims.iRaysPerDetDim = iDetectorSuperSampling; -  	if (iDetectorSuperSampling == 0)  		return false; -	if (iGPUIndex != -1) { -		cudaSetDevice(iGPUIndex); -		cudaError_t err = cudaGetLastError(); - -		// Ignore errors caused by calling cudaSetDevice multiple times -		if (err != cudaSuccess && err != cudaErrorSetOnActiveProcess) -			return false; -	} - -	cudaPitchedPtr D_volumeData = allocateVolumeData(dims); -	bool ok = D_volumeData.ptr; -	if (!ok) -		return false; - -	cudaPitchedPtr D_projData = allocateProjectionData(dims); -	ok = D_projData.ptr; -	if (!ok) { -		cudaFree(D_volumeData.ptr); -		return false; -	} - -	ok &= copyVolumeToDevice(pfVolume, D_volumeData, dims, dims.iVolX); - -	ok &= zeroProjectionData(D_projData, dims); - -	if (!ok) { -		cudaFree(D_volumeData.ptr); -		cudaFree(D_projData.ptr); -		return false; -	} - -	ok &= ConeFP(D_volumeData, D_projData, dims, pfAngles, 1.0f); - -	ok &= copyProjectionsFromDevice(pfProjections, D_projData, -	                                dims, dims.iProjU); - - -	cudaFree(D_volumeData.ptr); -	cudaFree(D_projData.ptr); - -	return ok; - -} - -bool astraCudaPar3DFP(const float* pfVolume, float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      float fDetUSize, -                      float fDetVSize, -                      const float *pfAngles, -                      int iGPUIndex, int iDetectorSuperSampling, -                      Cuda3DProjectionKernel projKernel) -{ -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) -		return false; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; - -	SPar3DProjection* p = genPar3DProjections(iProjAngles, -                                             iProjU, iProjV, -                                             fDetUSize, fDetVSize, -                                             pfAngles); - -	bool ok; -	ok = astraCudaPar3DFP(pfVolume, pfProjections, iVolX, iVolY, iVolZ, -	                      iProjAngles, iProjU, iProjV, p, iGPUIndex, iDetectorSuperSampling, -	                      projKernel); - -	delete[] p; - -	return ok; -} - - -bool astraCudaPar3DFP(const float* pfVolume, float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      const SPar3DProjection *pfAngles, -                      int iGPUIndex, int iDetectorSuperSampling, -                      Cuda3DProjectionKernel projKernel) -{ -	SDimensions3D dims; - -	dims.iVolX = iVolX; -	dims.iVolY = iVolY; -	dims.iVolZ = iVolZ; -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) -		return false; +	SPar3DProjection* pParProjs; +	SConeProjection* pConeProjs; -	dims.iProjAngles = iProjAngles; -	dims.iProjU = iProjU; -	dims.iProjV = iProjV; +	float outputScale; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; +	ok = convertAstraGeometry(pVolGeom, pProjGeom, +	                          pParProjs, pConeProjs, +	                          outputScale); -	dims.iRaysPerDetDim = iDetectorSuperSampling; - -	if (iDetectorSuperSampling == 0) -		return false;  	if (iGPUIndex != -1) {  		cudaSetDevice(iGPUIndex); @@ -1262,7 +1056,7 @@ bool astraCudaPar3DFP(const float* pfVolume, float* pfProjections,  	cudaPitchedPtr D_volumeData = allocateVolumeData(dims); -	bool ok = D_volumeData.ptr; +	ok = D_volumeData.ptr;  	if (!ok)  		return false; @@ -1283,15 +1077,25 @@ bool astraCudaPar3DFP(const float* pfVolume, float* pfProjections,  		return false;  	} -	switch (projKernel) { -	case ker3d_default: -		ok &= Par3DFP(D_volumeData, D_projData, dims, pfAngles, 1.0f); -		break; -	case ker3d_sum_square_weights: -		ok &= Par3DFP_SumSqW(D_volumeData, D_projData, dims, pfAngles, 1.0f); -		break; -	default: -		assert(false); +	if (pParProjs) { +		switch (projKernel) { +		case ker3d_default: +			ok &= Par3DFP(D_volumeData, D_projData, dims, pParProjs, outputScale); +			break; +		case ker3d_sum_square_weights: +			ok &= Par3DFP_SumSqW(D_volumeData, D_projData, dims, pParProjs, outputScale*outputScale); +			break; +		default: +			assert(false); +		} +	} else { +		switch (projKernel) { +		case ker3d_default: +			ok &= ConeFP(D_volumeData, D_projData, dims, pConeProjs, outputScale); +			break; +		default: +			assert(false); +		}  	}  	ok &= copyProjectionsFromDevice(pfProjections, D_projData, @@ -1305,207 +1109,28 @@ bool astraCudaPar3DFP(const float* pfVolume, float* pfProjections,  } -bool astraCudaConeBP(float* pfVolume, const float* pfProjections, -                     unsigned int iVolX, -                     unsigned int iVolY, -                     unsigned int iVolZ, -                     unsigned int iProjAngles, -                     unsigned int iProjU, -                     unsigned int iProjV, -                     float fOriginSourceDistance, -                     float fOriginDetectorDistance, -                     float fDetUSize, -                     float fDetVSize, -                     const float *pfAngles, -                     int iGPUIndex, int iVoxelSuperSampling) -{ -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) -		return false; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; - -	SConeProjection* p = genConeProjections(iProjAngles, -                                            iProjU, iProjV, -                                            fOriginSourceDistance, -                                            fOriginDetectorDistance, -                                            fDetUSize, fDetVSize, -                                            pfAngles); - -	bool ok; -	ok = astraCudaConeBP(pfVolume, pfProjections, iVolX, iVolY, iVolZ, -	                     iProjAngles, iProjU, iProjV, p, iGPUIndex, iVoxelSuperSampling); -	delete[] p; - -	return ok; -} - -bool astraCudaConeBP(float* pfVolume, const float* pfProjections, -                     unsigned int iVolX, -                     unsigned int iVolY, -                     unsigned int iVolZ, -                     unsigned int iProjAngles, -                     unsigned int iProjU, -                     unsigned int iProjV, -                     const SConeProjection *pfAngles, -                     int iGPUIndex, int iVoxelSuperSampling) +bool astraCudaBP(float* pfVolume, const float* pfProjections, +                 const CVolumeGeometry3D* pVolGeom, +                 const CProjectionGeometry3D* pProjGeom, +                 int iGPUIndex, int iVoxelSuperSampling)  {  	SDimensions3D dims; -	dims.iVolX = iVolX; -	dims.iVolY = iVolY; -	dims.iVolZ = iVolZ; -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) -		return false; - -	dims.iProjAngles = iProjAngles; -	dims.iProjU = iProjU; -	dims.iProjV = iProjV; - -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; - -	dims.iRaysPerVoxelDim = iVoxelSuperSampling; - -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; - -	if (iGPUIndex != -1) { -		cudaSetDevice(iGPUIndex); -		cudaError_t err = cudaGetLastError(); - -		// Ignore errors caused by calling cudaSetDevice multiple times -		if (err != cudaSuccess && err != cudaErrorSetOnActiveProcess) -			return false; -	} - -	cudaPitchedPtr D_volumeData = allocateVolumeData(dims); -	bool ok = D_volumeData.ptr; +	bool ok = convertAstraGeometry_dims(pVolGeom, pProjGeom, dims);  	if (!ok)  		return false; -	cudaPitchedPtr D_projData = allocateProjectionData(dims); -	ok = D_projData.ptr; -	if (!ok) { -		cudaFree(D_volumeData.ptr); -		return false; -	} - -	ok &= copyProjectionsToDevice(pfProjections, D_projData, -	                              dims, dims.iProjU); - -	ok &= zeroVolumeData(D_volumeData, dims); - -	if (!ok) { -		cudaFree(D_volumeData.ptr); -		cudaFree(D_projData.ptr); -		return false; -	} - -	ok &= ConeBP(D_volumeData, D_projData, dims, pfAngles); - -	ok &= copyVolumeFromDevice(pfVolume, D_volumeData, dims, dims.iVolX); - - -	cudaFree(D_volumeData.ptr); -	cudaFree(D_projData.ptr); - -	return ok; - -} - -bool astraCudaPar3DBP(float* pfVolume, const float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      float fDetUSize, -                      float fDetVSize, -                      const float *pfAngles, -                      int iGPUIndex, int iVoxelSuperSampling) -{ -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) -		return false; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; - -	SPar3DProjection* p = genPar3DProjections(iProjAngles, -                                             iProjU, iProjV, -                                             fDetUSize, fDetVSize, -                                             pfAngles); - -	bool ok; -	ok = astraCudaPar3DBP(pfVolume, pfProjections, iVolX, iVolY, iVolZ, -	                      iProjAngles, iProjU, iProjV, p, iGPUIndex, iVoxelSuperSampling); - -	delete[] p; - -	return ok; -} - -// This computes the column weights, divides by them, and adds the -// result to the current volume. This is both more expensive and more -// GPU memory intensive than the regular BP, but allows saving system RAM. -bool astraCudaPar3DBP_SIRTWeighted(float* pfVolume, const float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      float fDetUSize, -                      float fDetVSize, -                      const float *pfAngles, -                      int iGPUIndex, int iVoxelSuperSampling) -{ -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) -		return false; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; - -	SPar3DProjection* p = genPar3DProjections(iProjAngles, -                                             iProjU, iProjV, -                                             fDetUSize, fDetVSize, -                                             pfAngles); - -	bool ok; -	ok = astraCudaPar3DBP_SIRTWeighted(pfVolume, pfProjections, iVolX, iVolY, iVolZ, -	                      iProjAngles, iProjU, iProjV, p, iGPUIndex, iVoxelSuperSampling); - -	delete[] p; - -	return ok; -} - - -bool astraCudaPar3DBP(float* pfVolume, const float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      const SPar3DProjection *pfAngles, -                      int iGPUIndex, int iVoxelSuperSampling) -{ -	SDimensions3D dims; - -	dims.iVolX = iVolX; -	dims.iVolY = iVolY; -	dims.iVolZ = iVolZ; -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) -		return false; +	dims.iRaysPerVoxelDim = iVoxelSuperSampling; -	dims.iProjAngles = iProjAngles; -	dims.iProjU = iProjU; -	dims.iProjV = iProjV; +	SPar3DProjection* pParProjs; +	SConeProjection* pConeProjs; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; +	float outputScale; -	dims.iRaysPerVoxelDim = iVoxelSuperSampling; +	ok = convertAstraGeometry(pVolGeom, pProjGeom, +	                          pParProjs, pConeProjs, +	                          outputScale);  	if (iGPUIndex != -1) {  		cudaSetDevice(iGPUIndex); @@ -1518,7 +1143,7 @@ bool astraCudaPar3DBP(float* pfVolume, const float* pfProjections,  	cudaPitchedPtr D_volumeData = allocateVolumeData(dims); -	bool ok = D_volumeData.ptr; +	ok = D_volumeData.ptr;  	if (!ok)  		return false; @@ -1540,7 +1165,10 @@ bool astraCudaPar3DBP(float* pfVolume, const float* pfProjections,  		return false;  	} -	ok &= Par3DBP(D_volumeData, D_projData, dims, pfAngles); +	if (pParProjs) +		ok &= Par3DBP(D_volumeData, D_projData, dims, pParProjs, outputScale); +	else +		ok &= ConeBP(D_volumeData, D_projData, dims, pConeProjs, outputScale);  	ok &= copyVolumeFromDevice(pfVolume, D_volumeData, dims, dims.iVolX); @@ -1556,33 +1184,28 @@ bool astraCudaPar3DBP(float* pfVolume, const float* pfProjections,  // This computes the column weights, divides by them, and adds the  // result to the current volume. This is both more expensive and more  // GPU memory intensive than the regular BP, but allows saving system RAM. -bool astraCudaPar3DBP_SIRTWeighted(float* pfVolume, +bool astraCudaBP_SIRTWeighted(float* pfVolume,                        const float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      const SPar3DProjection *pfAngles, +                      const CVolumeGeometry3D* pVolGeom, +                      const CProjectionGeometry3D* pProjGeom,                        int iGPUIndex, int iVoxelSuperSampling)  {  	SDimensions3D dims; -	dims.iVolX = iVolX; -	dims.iVolY = iVolY; -	dims.iVolZ = iVolZ; -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) +	bool ok = convertAstraGeometry_dims(pVolGeom, pProjGeom, dims); +	if (!ok)  		return false; -	dims.iProjAngles = iProjAngles; -	dims.iProjU = iProjU; -	dims.iProjV = iProjV; +	dims.iRaysPerVoxelDim = iVoxelSuperSampling; -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) -		return false; +	SPar3DProjection* pParProjs; +	SConeProjection* pConeProjs; -	dims.iRaysPerVoxelDim = iVoxelSuperSampling; +	float outputScale; + +	ok = convertAstraGeometry(pVolGeom, pProjGeom, +	                          pParProjs, pConeProjs, +	                          outputScale);  	if (iGPUIndex != -1) {  		cudaSetDevice(iGPUIndex); @@ -1595,7 +1218,7 @@ bool astraCudaPar3DBP_SIRTWeighted(float* pfVolume,  	cudaPitchedPtr D_pixelWeight = allocateVolumeData(dims); -	bool ok = D_pixelWeight.ptr; +	ok = D_pixelWeight.ptr;  	if (!ok)  		return false; @@ -1617,7 +1240,12 @@ bool astraCudaPar3DBP_SIRTWeighted(float* pfVolume,  	// Compute weights  	ok &= zeroVolumeData(D_pixelWeight, dims);  	processSino3D<opSet>(D_projData, 1.0f, dims); -	ok &= Par3DBP(D_pixelWeight, D_projData, dims, pfAngles); + +	if (pParProjs) +		ok &= Par3DBP(D_pixelWeight, D_projData, dims, pParProjs, outputScale); +	else +		ok &= ConeBP(D_pixelWeight, D_projData, dims, pConeProjs, outputScale); +  	processVol3D<opInvert>(D_pixelWeight, dims);  	if (!ok) {  		cudaFree(D_pixelWeight.ptr); @@ -1630,7 +1258,11 @@ bool astraCudaPar3DBP_SIRTWeighted(float* pfVolume,  	                              dims, dims.iProjU);  	ok &= zeroVolumeData(D_volumeData, dims);  	// Do BP into D_volumeData -	ok &= Par3DBP(D_volumeData, D_projData, dims, pfAngles); +	if (pParProjs) +		ok &= Par3DBP(D_volumeData, D_projData, dims, pParProjs, outputScale); +	else +		ok &= ConeBP(D_volumeData, D_projData, dims, pConeProjs, outputScale); +  	// Multiply with weights  	processVol3D<opMul>(D_volumeData, D_pixelWeight, dims); @@ -1653,6 +1285,9 @@ bool astraCudaPar3DBP_SIRTWeighted(float* pfVolume,  	cudaFree(D_volumeData.ptr);  	cudaFree(D_projData.ptr); +	delete[] pParProjs; +	delete[] pConeProjs; +  	return ok;  } @@ -1660,33 +1295,19 @@ bool astraCudaPar3DBP_SIRTWeighted(float* pfVolume,  bool astraCudaFDK(float* pfVolume, const float* pfProjections, -                  unsigned int iVolX, -                  unsigned int iVolY, -                  unsigned int iVolZ, -                  unsigned int iProjAngles, -                  unsigned int iProjU, -                  unsigned int iProjV, -                  float fOriginSourceDistance, -                  float fOriginDetectorDistance, -                  float fDetUSize, -                  float fDetVSize, -                  const float *pfAngles, +                  const CVolumeGeometry3D* pVolGeom, +                  const CConeProjectionGeometry3D* pProjGeom,                    bool bShortScan,                    int iGPUIndex, int iVoxelSuperSampling)  {  	SDimensions3D dims; -	dims.iVolX = iVolX; -	dims.iVolY = iVolY; -	dims.iVolZ = iVolZ; -	if (iVolX == 0 || iVolY == 0 || iVolZ == 0) -		return false; +	bool ok = convertAstraGeometry_dims(pVolGeom, pProjGeom, dims); -	dims.iProjAngles = iProjAngles; -	dims.iProjU = iProjU; -	dims.iProjV = iProjV; +	// TODO: Check that pVolGeom is normalized, since we don't support +	// other volume geometries yet -	if (iProjAngles == 0 || iProjU == 0 || iProjV == 0 || pfAngles == 0) +	if (!ok)  		return false;  	dims.iRaysPerVoxelDim = iVoxelSuperSampling; @@ -1703,9 +1324,8 @@ bool astraCudaFDK(float* pfVolume, const float* pfProjections,  			return false;  	} -  	cudaPitchedPtr D_volumeData = allocateVolumeData(dims); -	bool ok = D_volumeData.ptr; +	ok = D_volumeData.ptr;  	if (!ok)  		return false; @@ -1726,6 +1346,13 @@ bool astraCudaFDK(float* pfVolume, const float* pfProjections,  		return false;  	} +	float fOriginSourceDistance = pProjGeom->getOriginSourceDistance(); +	float fOriginDetectorDistance = pProjGeom->getOriginDetectorDistance(); +	float fDetUSize = pProjGeom->getDetectorSpacingX(); +	float fDetVSize = pProjGeom->getDetectorSpacingY(); +	const float *pfAngles = pProjGeom->getProjectionAngles(); + +  	// TODO: Offer interface for SrcZ, DetZ  	ok &= FDK(D_volumeData, D_projData, fOriginSourceDistance,  	          fOriginDetectorDistance, 0, 0, fDetUSize, fDetVSize, diff --git a/cuda/3d/astra3d.h b/cuda/3d/astra3d.h index f91fe26..2782994 100644 --- a/cuda/3d/astra3d.h +++ b/cuda/3d/astra3d.h @@ -42,7 +42,12 @@ enum Cuda3DProjectionKernel {  	ker3d_sum_square_weights  }; - +class CProjectionGeometry3D; +class CParallelProjectionGeometry3D; +class CParallelVecProjectionGeometry3D; +class CConeProjectionGeometry3D; +class CConeVecProjectionGeometry3D; +class CVolumeGeometry3D;  class AstraSIRT3d_internal; @@ -52,37 +57,9 @@ public:  	AstraSIRT3d();  	~AstraSIRT3d(); -	// Set the number of pixels in the reconstruction rectangle, -	// and the length of the edge of a pixel. -	// Volume pixels are assumed to be square. -	// This must be called before setting the projection geometry. -	bool setReconstructionGeometry(unsigned int iVolX, -	                               unsigned int iVolY, -	                               unsigned int iVolZ/*, -	                               float fPixelSize = 1.0f*/); - -	bool setConeGeometry(unsigned int iProjAngles, -	                     unsigned int iProjU, -	                     unsigned int iProjV, -	                     const SConeProjection* projs); -	bool setConeGeometry(unsigned int iProjAngles, -	                     unsigned int iProjU, -	                     unsigned int iProjV, -	                     float fOriginSourceDistance, -	                     float fOriginDetectorDistance, -	                     float fSourceZ, -	                     float fDetSize, -	                     const float *pfAngles); -	bool setPar3DGeometry(unsigned int iProjAngles, -	                      unsigned int iProjU, -	                      unsigned int iProjV, -	                      const SPar3DProjection* projs); -	bool setPar3DGeometry(unsigned int iProjAngles, -	                      unsigned int iProjU, -	                      unsigned int iProjV, -	                      float fSourceZ, -	                      float fDetSize, -	                      const float *pfAngles); +	// Set the volume and projection geometry +	bool setGeometry(const CVolumeGeometry3D* pVolGeom, +	                 const CProjectionGeometry3D* pProjGeom);  	// Enable supersampling.  	// @@ -197,37 +174,9 @@ public:  	AstraCGLS3d();  	~AstraCGLS3d(); -	// Set the number of pixels in the reconstruction rectangle, -	// and the length of the edge of a pixel. -	// Volume pixels are assumed to be square. -	// This must be called before setting the projection geometry. -	bool setReconstructionGeometry(unsigned int iVolX, -	                               unsigned int iVolY, -	                               unsigned int iVolZ/*, -	                               float fPixelSize = 1.0f*/); - -	bool setConeGeometry(unsigned int iProjAngles, -	                     unsigned int iProjU, -	                     unsigned int iProjV, -	                     const SConeProjection* projs); -	bool setConeGeometry(unsigned int iProjAngles, -	                     unsigned int iProjU, -	                     unsigned int iProjV, -	                     float fOriginSourceDistance, -	                     float fOriginDetectorDistance, -	                     float fSourceZ, -	                     float fDetSize, -	                     const float *pfAngles); -	bool setPar3DGeometry(unsigned int iProjAngles, -	                      unsigned int iProjU, -	                      unsigned int iProjV, -	                      const SPar3DProjection* projs); -	bool setPar3DGeometry(unsigned int iProjAngles, -	                      unsigned int iProjU, -	                      unsigned int iProjV, -	                      float fSourceZ, -	                      float fDetSize, -	                      const float *pfAngles); +	// Set the volume and projection geometry +	bool setGeometry(const CVolumeGeometry3D* pVolGeom, +	                 const CProjectionGeometry3D* pProjGeom);  	// Enable supersampling.  	// @@ -332,140 +281,40 @@ protected:  	AstraCGLS3d_internal *pData;  }; +bool convertAstraGeometry_dims(const CVolumeGeometry3D* pVolGeom, +                               const CProjectionGeometry3D* pProjGeom, +                               astraCUDA3d::SDimensions3D& dims); +bool convertAstraGeometry(const CVolumeGeometry3D* pVolGeom, +                          const CProjectionGeometry3D* pProjGeom, +                          SPar3DProjection*& pParProjs, +                          SConeProjection*& pConeProjs, +                          float& fOutputScale); -_AstraExport bool astraCudaConeFP(const float* pfVolume, float* pfProjections, -                     unsigned int iVolX, -                     unsigned int iVolY, -                     unsigned int iVolZ, -                     unsigned int iProjAngles, -                     unsigned int iProjU, -                     unsigned int iProjV, -                     float fOriginSourceDistance, -                     float fOriginDetectorDistance, -                     float fDetUSize, -                     float fDetVSize, -                     const float *pfAngles, -                     int iGPUIndex, int iDetectorSuperSampling); - -_AstraExport bool astraCudaConeFP(const float* pfVolume, float* pfProjections, -                     unsigned int iVolX, -                     unsigned int iVolY, -                     unsigned int iVolZ, -                     unsigned int iProjAngles, -                     unsigned int iProjU, -                     unsigned int iProjV, -                     const SConeProjection *pfAngles, -                     int iGPUIndex, int iDetectorSuperSampling); - -_AstraExport bool astraCudaPar3DFP(const float* pfVolume, float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      float fDetUSize, -                      float fDetVSize, -                      const float *pfAngles, +_AstraExport bool astraCudaFP(const float* pfVolume, float* pfProjections, +                      const CVolumeGeometry3D* pVolGeom, +                      const CProjectionGeometry3D* pProjGeom,                        int iGPUIndex, int iDetectorSuperSampling,                        Cuda3DProjectionKernel projKernel); -_AstraExport bool astraCudaPar3DFP(const float* pfVolume, float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      const SPar3DProjection *pfAngles, -                      int iGPUIndex, int iDetectorSuperSampling, -                      Cuda3DProjectionKernel projKernel); - -_AstraExport bool astraCudaConeBP(float* pfVolume, const float* pfProjections, -                     unsigned int iVolX, -                     unsigned int iVolY, -                     unsigned int iVolZ, -                     unsigned int iProjAngles, -                     unsigned int iProjU, -                     unsigned int iProjV, -                     float fOriginSourceDistance, -                     float fOriginDetectorDistance, -                     float fDetUSize, -                     float fDetVSize, -                     const float *pfAngles, -                     int iGPUIndex, int iVoxelSuperSampling); - -_AstraExport bool astraCudaConeBP(float* pfVolume, const float* pfProjections, -                     unsigned int iVolX, -                     unsigned int iVolY, -                     unsigned int iVolZ, -                     unsigned int iProjAngles, -                     unsigned int iProjU, -                     unsigned int iProjV, -                     const SConeProjection *pfAngles, -                     int iGPUIndex, int iVoxelSuperSampling); - -_AstraExport bool astraCudaPar3DBP(float* pfVolume, const float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      float fDetUSize, -                      float fDetVSize, -                      const float *pfAngles, +_AstraExport bool astraCudaBP(float* pfVolume, const float* pfProjections, +                      const CVolumeGeometry3D* pVolGeom, +                      const CProjectionGeometry3D* pProjGeom,                        int iGPUIndex, int iVoxelSuperSampling); -_AstraExport bool astraCudaPar3DBP(float* pfVolume, const float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      const SPar3DProjection *pfAngles, -                      int iGPUIndex, int iVoxelSuperSampling); - -_AstraExport bool astraCudaPar3DBP_SIRTWeighted(float* pfVolume, const float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      float fDetUSize, -                      float fDetVSize, -                      const float *pfAngles, -                      int iGPUIndex, int iVoxelSuperSampling); - -_AstraExport bool astraCudaPar3DBP_SIRTWeighted(float* pfVolume, const float* pfProjections, -                      unsigned int iVolX, -                      unsigned int iVolY, -                      unsigned int iVolZ, -                      unsigned int iProjAngles, -                      unsigned int iProjU, -                      unsigned int iProjV, -                      const SPar3DProjection *pfAngles, +_AstraExport bool astraCudaBP_SIRTWeighted(float* pfVolume, const float* pfProjections, +                      const CVolumeGeometry3D* pVolGeom, +                      const CProjectionGeometry3D* pProjGeom,                        int iGPUIndex, int iVoxelSuperSampling);  _AstraExport bool astraCudaFDK(float* pfVolume, const float* pfProjections, -                  unsigned int iVolX, -                  unsigned int iVolY, -                  unsigned int iVolZ, -                  unsigned int iProjAngles, -                  unsigned int iProjU, -                  unsigned int iProjV, -                  float fOriginSourceDistance, -                  float fOriginDetectorDistance, -                  float fDetUSize, -                  float fDetVSize, -                  const float *pfAngles, +                  const CVolumeGeometry3D* pVolGeom, +                  const CConeProjectionGeometry3D* pProjGeom,                    bool bShortScan,                    int iGPUIndex, int iVoxelSuperSampling); +  } diff --git a/cuda/3d/cgls3d.cu b/cuda/3d/cgls3d.cu index 5071a9b..dd0e8a0 100644 --- a/cuda/3d/cgls3d.cu +++ b/cuda/3d/cgls3d.cu @@ -165,7 +165,7 @@ bool CGLS::iterate(unsigned int iterations)  		// p = A'*r  		zeroVolumeData(D_p, dims); -		callBP(D_p, D_r); +		callBP(D_p, D_r, 1.0f);  		if (useVolumeMask)  			processVol3D<opMul>(D_p, D_maskData, dims); @@ -195,7 +195,7 @@ bool CGLS::iterate(unsigned int iterations)  		// z = A'*r  		zeroVolumeData(D_z, dims); -		callBP(D_z, D_r); +		callBP(D_z, D_r, 1.0f);  		if (useVolumeMask)  			processVol3D<opMul>(D_z, D_maskData, dims); @@ -242,7 +242,7 @@ bool doCGLS(cudaPitchedPtr& D_volumeData,  	CGLS cgls;  	bool ok = true; -	ok &= cgls.setConeGeometry(dims, angles); +	ok &= cgls.setConeGeometry(dims, angles, 1.0f);  	if (D_maskData.ptr)  		ok &= cgls.enableVolumeMask(); diff --git a/cuda/3d/cone_bp.cu b/cuda/3d/cone_bp.cu index 5648d6f..4a41f6a 100644 --- a/cuda/3d/cone_bp.cu +++ b/cuda/3d/cone_bp.cu @@ -78,7 +78,8 @@ bool bindProjDataTexture(const cudaArray* array)  //__launch_bounds__(32*16, 4)  __global__ void dev_cone_BP(void* D_volData, unsigned int volPitch, int startAngle, -                            int angleOffset, const astraCUDA3d::SDimensions3D dims) +                            int angleOffset, const astraCUDA3d::SDimensions3D dims, +                            float fOutputScale)  {  	float* volData = (float*)D_volData; @@ -147,13 +148,13 @@ __global__ void dev_cone_BP(void* D_volData, unsigned int volPitch, int startAng  		endZ = dims.iVolZ - startZ;  	for(int i=0; i < endZ; i++) -		volData[((startZ+i)*dims.iVolY+Y)*volPitch+X] += Z[i]; +		volData[((startZ+i)*dims.iVolY+Y)*volPitch+X] += Z[i] * fOutputScale;  } //End kernel  // supersampling version -__global__ void dev_cone_BP_SS(void* D_volData, unsigned int volPitch, int startAngle, int angleOffset, const SDimensions3D dims) +__global__ void dev_cone_BP_SS(void* D_volData, unsigned int volPitch, int startAngle, int angleOffset, const SDimensions3D dims, float fOutputScale)  {  	float* volData = (float*)D_volData; @@ -189,6 +190,9 @@ __global__ void dev_cone_BP_SS(void* D_volData, unsigned int volPitch, int start  	float fZ = startZ - 0.5f*dims.iVolZ + 0.5f - 0.5f + 0.5f/dims.iRaysPerVoxelDim;  	const float fSubStep = 1.0f/dims.iRaysPerVoxelDim; +	fOutputScale /= (dims.iRaysPerVoxelDim*dims.iRaysPerVoxelDim*dims.iRaysPerVoxelDim); + +  	for (int Z = startZ; Z < endZ; ++Z, fZ += 1.0f)  	{ @@ -236,14 +240,15 @@ __global__ void dev_cone_BP_SS(void* D_volData, unsigned int volPitch, int start  		} -		volData[(Z*dims.iVolY+Y)*volPitch+X] += fVal / (dims.iRaysPerVoxelDim*dims.iRaysPerVoxelDim*dims.iRaysPerVoxelDim); +		volData[(Z*dims.iVolY+Y)*volPitch+X] += fVal * fOutputScale;  	}  }  bool ConeBP_Array(cudaPitchedPtr D_volumeData,                    cudaArray *D_projArray, -                  const SDimensions3D& dims, const SConeProjection* angles) +                  const SDimensions3D& dims, const SConeProjection* angles, +                  float fOutputScale)  {  	bindProjDataTexture(D_projArray); @@ -291,9 +296,9 @@ bool ConeBP_Array(cudaPitchedPtr D_volumeData,  		for (unsigned int i = 0; i < angleCount; i += g_anglesPerBlock) {  		// printf("Calling BP: %d, %dx%d, %dx%d to %p\n", i, dimBlock.x, dimBlock.y, dimGrid.x, dimGrid.y, (void*)D_volumeData.ptr);   			if (dims.iRaysPerVoxelDim == 1) -				dev_cone_BP<<<dimGrid, dimBlock>>>(D_volumeData.ptr, D_volumeData.pitch/sizeof(float), i, th, dims); +				dev_cone_BP<<<dimGrid, dimBlock>>>(D_volumeData.ptr, D_volumeData.pitch/sizeof(float), i, th, dims, fOutputScale);  			else -				dev_cone_BP_SS<<<dimGrid, dimBlock>>>(D_volumeData.ptr, D_volumeData.pitch/sizeof(float), i, th, dims); +				dev_cone_BP_SS<<<dimGrid, dimBlock>>>(D_volumeData.ptr, D_volumeData.pitch/sizeof(float), i, th, dims, fOutputScale);  		}  		cudaTextForceKernelsCompletion(); @@ -309,14 +314,15 @@ bool ConeBP_Array(cudaPitchedPtr D_volumeData,  bool ConeBP(cudaPitchedPtr D_volumeData,              cudaPitchedPtr D_projData, -            const SDimensions3D& dims, const SConeProjection* angles) +            const SDimensions3D& dims, const SConeProjection* angles, +            float fOutputScale)  {  	// transfer projections to array  	cudaArray* cuArray = allocateProjectionArray(dims);  	transferProjectionsToArray(D_projData, cuArray, dims); -	bool ret = ConeBP_Array(D_volumeData, cuArray, dims, angles); +	bool ret = ConeBP_Array(D_volumeData, cuArray, dims, angles, fOutputScale);  	cudaFreeArray(cuArray); @@ -473,7 +479,7 @@ int main()  	}  #endif -	astraCUDA3d::ConeBP(volData, projData, dims, angle); +	astraCUDA3d::ConeBP(volData, projData, dims, angle, 1.0f);  #if 0  	float* buf = new float[256*256]; diff --git a/cuda/3d/cone_bp.h b/cuda/3d/cone_bp.h index cba6d9f..4d3d2dd 100644 --- a/cuda/3d/cone_bp.h +++ b/cuda/3d/cone_bp.h @@ -33,13 +33,14 @@ namespace astraCUDA3d {  _AstraExport bool ConeBP_Array(cudaPitchedPtr D_volumeData,                    cudaArray *D_projArray, -                  const SDimensions3D& dims, const SConeProjection* angles); +                  const SDimensions3D& dims, const SConeProjection* angles, +                  float fOutputScale);  _AstraExport bool ConeBP(cudaPitchedPtr D_volumeData,              cudaPitchedPtr D_projData, -            const SDimensions3D& dims, const SConeProjection* angles); +            const SDimensions3D& dims, const SConeProjection* angles, +            float fOutputScale); -  }  #endif diff --git a/cuda/3d/mem3d.cu b/cuda/3d/mem3d.cu new file mode 100644 index 0000000..6d81dc0 --- /dev/null +++ b/cuda/3d/mem3d.cu @@ -0,0 +1,270 @@ +/* +----------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +$Id$ +*/ + +#include <cstdio> +#include <cassert> + +#include "util3d.h" + +#include "mem3d.h" + +#include "astra3d.h" +#include "cone_fp.h" +#include "cone_bp.h" +#include "par3d_fp.h" +#include "par3d_bp.h" + +#include "astra/Logging.h" + + +namespace astraCUDA3d { + + +struct SMemHandle3D_internal +{ +	cudaPitchedPtr ptr; +	unsigned int nx; +	unsigned int ny; +	unsigned int nz; +}; + +size_t availableGPUMemory() +{ +	size_t free, total; +	cudaError_t err = cudaMemGetInfo(&free, &total); +	if (err != cudaSuccess) +		return 0; +	return free; +} + +MemHandle3D allocateGPUMemory(unsigned int x, unsigned int y, unsigned int z, Mem3DZeroMode zero) +{ +	SMemHandle3D_internal hnd; +	hnd.nx = x; +	hnd.ny = y; +	hnd.nz = z; + +	size_t free = availableGPUMemory(); + +	cudaError_t err; +	err = cudaMalloc3D(&hnd.ptr, make_cudaExtent(sizeof(float)*x, y, z)); + +	if (err != cudaSuccess) { +		return MemHandle3D(); +	} + +	size_t free2 = availableGPUMemory(); + +	ASTRA_DEBUG("Allocated %d x %d x %d on GPU. (Pre: %lu, post: %lu)", x, y, z, free, free2); + + + +	if (zero == INIT_ZERO) { +		err = cudaMemset3D(hnd.ptr, 0, make_cudaExtent(sizeof(float)*x, y, z)); +		if (err != cudaSuccess) { +			cudaFree(hnd.ptr.ptr); +			return MemHandle3D(); +		} +	} + +	MemHandle3D ret; +	ret.d = boost::shared_ptr<SMemHandle3D_internal>(new SMemHandle3D_internal); +	*ret.d = hnd; + +	return ret; +} + +bool freeGPUMemory(MemHandle3D handle) +{ +	size_t free = availableGPUMemory(); +	cudaError_t err = cudaFree(handle.d->ptr.ptr); +	size_t free2 = availableGPUMemory(); + +	ASTRA_DEBUG("Freeing memory. (Pre: %lu, post: %lu)", free, free2); + +	return err == cudaSuccess; +} + +bool copyToGPUMemory(const float *src, MemHandle3D dst, const SSubDimensions3D &pos) +{ +	ASTRA_DEBUG("Copying %d x %d x %d to GPU", pos.subnx, pos.subny, pos.subnz); +	ASTRA_DEBUG("Offset %d,%d,%d", pos.subx, pos.suby, pos.subz); +	cudaPitchedPtr s; +	s.ptr = (void*)src; // const cast away +	s.pitch = pos.pitch * sizeof(float); +	s.xsize = pos.nx * sizeof(float); +	s.ysize = pos.ny; +	ASTRA_DEBUG("Pitch %d, xsize %d, ysize %d", s.pitch, s.xsize, s.ysize); + +	cudaMemcpy3DParms p; +	p.srcArray = 0; +	p.srcPos = make_cudaPos(pos.subx * sizeof(float), pos.suby, pos.subz); +	p.srcPtr = s; + +	p.dstArray = 0; +	p.dstPos = make_cudaPos(0, 0, 0); +	p.dstPtr = dst.d->ptr; + +	p.extent = make_cudaExtent(pos.subnx * sizeof(float), pos.subny, pos.subnz); + +	p.kind = cudaMemcpyHostToDevice; + +	cudaError_t err = cudaMemcpy3D(&p); + +	return err == cudaSuccess; +} + + +bool copyFromGPUMemory(float *dst, MemHandle3D src, const SSubDimensions3D &pos) +{ +	ASTRA_DEBUG("Copying %d x %d x %d from GPU", pos.subnx, pos.subny, pos.subnz); +	ASTRA_DEBUG("Offset %d,%d,%d", pos.subx, pos.suby, pos.subz); +	cudaPitchedPtr d; +	d.ptr = (void*)dst; +	d.pitch = pos.pitch * sizeof(float); +	d.xsize = pos.nx * sizeof(float); +	d.ysize = pos.ny; +	ASTRA_DEBUG("Pitch %d, xsize %d, ysize %d", d.pitch, d.xsize, d.ysize); + +	cudaMemcpy3DParms p; +	p.srcArray = 0; +	p.srcPos = make_cudaPos(0, 0, 0); +	p.srcPtr = src.d->ptr; + +	p.dstArray = 0; +	p.dstPos = make_cudaPos(pos.subx * sizeof(float), pos.suby, pos.subz); +	p.dstPtr = d; + +	p.extent = make_cudaExtent(pos.subnx * sizeof(float), pos.subny, pos.subnz); + +	p.kind = cudaMemcpyDeviceToHost; + +	cudaError_t err = cudaMemcpy3D(&p); + +	return err == cudaSuccess; + +} + + +bool FP(const astra::CProjectionGeometry3D* pProjGeom, MemHandle3D projData, const astra::CVolumeGeometry3D* pVolGeom, MemHandle3D volData, int iDetectorSuperSampling, astra::Cuda3DProjectionKernel projKernel) +{ +	SDimensions3D dims; + +	bool ok = convertAstraGeometry_dims(pVolGeom, pProjGeom, dims); +	if (!ok) +		return false; + +#if 1 +	dims.iRaysPerDetDim = iDetectorSuperSampling; +	if (iDetectorSuperSampling == 0) +		return false; +#else +	dims.iRaysPerDetDim = 1; +	astra::Cuda3DProjectionKernel projKernel = astra::ker3d_default; +#endif + + +	SPar3DProjection* pParProjs; +	SConeProjection* pConeProjs; + +	float outputScale = 1.0f; + +	ok = convertAstraGeometry(pVolGeom, pProjGeom, +	                          pParProjs, pConeProjs, +	                          outputScale); + +	if (pParProjs) { +#if 0 +		for (int i = 0; i < dims.iProjAngles; ++i) { +			ASTRA_DEBUG("Vec: %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n", +			    pParProjs[i].fRayX, pParProjs[i].fRayY, pParProjs[i].fRayZ, +			    pParProjs[i].fDetSX, pParProjs[i].fDetSY, pParProjs[i].fDetSZ, +			    pParProjs[i].fDetUX, pParProjs[i].fDetUY, pParProjs[i].fDetUZ, +			    pParProjs[i].fDetVX, pParProjs[i].fDetVY, pParProjs[i].fDetVZ); +		} +#endif + +		switch (projKernel) { +		case astra::ker3d_default: +			ok &= Par3DFP(volData.d->ptr, projData.d->ptr, dims, pParProjs, outputScale); +			break; +		case astra::ker3d_sum_square_weights: +			ok &= Par3DFP_SumSqW(volData.d->ptr, projData.d->ptr, dims, pParProjs, outputScale*outputScale); +			break; +		default: +			ok = false; +		} +	} else { +		switch (projKernel) { +		case astra::ker3d_default: +			ok &= ConeFP(volData.d->ptr, projData.d->ptr, dims, pConeProjs, outputScale); +			break; +		default: +			ok = false; +		} +	} + +	return ok; +} + +bool BP(const astra::CProjectionGeometry3D* pProjGeom, MemHandle3D projData, const astra::CVolumeGeometry3D* pVolGeom, MemHandle3D volData, int iVoxelSuperSampling) +{ +	SDimensions3D dims; + +	bool ok = convertAstraGeometry_dims(pVolGeom, pProjGeom, dims); +	if (!ok) +		return false; + +#if 1 +	dims.iRaysPerVoxelDim = iVoxelSuperSampling; +#else +	dims.iRaysPerVoxelDim = 1; +#endif + +	SPar3DProjection* pParProjs; +	SConeProjection* pConeProjs; + +	float outputScale = 1.0f; + +	ok = convertAstraGeometry(pVolGeom, pProjGeom, +	                          pParProjs, pConeProjs, +	                          outputScale); + +	if (pParProjs) +		ok &= Par3DBP(volData.d->ptr, projData.d->ptr, dims, pParProjs, outputScale); +	else +		ok &= ConeBP(volData.d->ptr, projData.d->ptr, dims, pConeProjs, outputScale); + +	return ok; + +} + + + + +} diff --git a/cuda/3d/mem3d.h b/cuda/3d/mem3d.h new file mode 100644 index 0000000..82bad19 --- /dev/null +++ b/cuda/3d/mem3d.h @@ -0,0 +1,99 @@ +/* +----------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +*/ + +#ifndef _CUDA_MEM3D_H +#define _CUDA_MEM3D_H + +#include <boost/shared_ptr.hpp> + +#include "astra3d.h" + +namespace astra { +class CVolumeGeometry3D; +class CProjectionGeometry3D;	 +} + +namespace astraCUDA3d { + +// TODO: Make it possible to delete these handles when they're no longer +// necessary inside the FP/BP +// +// TODO: Add functions for querying capacity + +struct SMemHandle3D_internal; + +struct MemHandle3D { +	boost::shared_ptr<SMemHandle3D_internal> d; +	operator bool() const { return (bool)d; } +}; + +struct SSubDimensions3D { +	unsigned int nx; +	unsigned int ny; +	unsigned int nz; +	unsigned int pitch; +	unsigned int subnx; +	unsigned int subny; +	unsigned int subnz; +	unsigned int subx; +	unsigned int suby; +	unsigned int subz; +}; + +/* +// Useful or not? +enum Mem3DCopyMode { +	MODE_SET, +	MODE_ADD +}; +*/ + +enum Mem3DZeroMode { +	INIT_NO, +	INIT_ZERO +}; + +size_t availableGPUMemory(); + +MemHandle3D allocateGPUMemory(unsigned int x, unsigned int y, unsigned int z, Mem3DZeroMode zero); + +bool copyToGPUMemory(const float *src, MemHandle3D dst, const SSubDimensions3D &pos); + +bool copyFromGPUMemory(float *dst, MemHandle3D src, const SSubDimensions3D &pos); + +bool freeGPUMemory(MemHandle3D handle); + + +bool FP(const astra::CProjectionGeometry3D* pProjGeom, MemHandle3D projData, const astra::CVolumeGeometry3D* pVolGeom, MemHandle3D volData, int iDetectorSuperSampling, astra::Cuda3DProjectionKernel projKernel); + +bool BP(const astra::CProjectionGeometry3D* pProjGeom, MemHandle3D projData, const astra::CVolumeGeometry3D* pVolGeom, MemHandle3D volData, int iVoxelSuperSampling); + + + +} + +#endif diff --git a/cuda/3d/par3d_bp.cu b/cuda/3d/par3d_bp.cu index 0c33280..cafab46 100644 --- a/cuda/3d/par3d_bp.cu +++ b/cuda/3d/par3d_bp.cu @@ -77,7 +77,7 @@ static bool bindProjDataTexture(const cudaArray* array)  } -__global__ void dev_par3D_BP(void* D_volData, unsigned int volPitch, int startAngle, int angleOffset, const SDimensions3D dims) +__global__ void dev_par3D_BP(void* D_volData, unsigned int volPitch, int startAngle, int angleOffset, const SDimensions3D dims, float fOutputScale)  {  	float* volData = (float*)D_volData; @@ -139,11 +139,11 @@ __global__ void dev_par3D_BP(void* D_volData, unsigned int volPitch, int startAn  		endZ = dims.iVolZ - startZ;  	for(int i=0; i < endZ; i++) -		volData[((startZ+i)*dims.iVolY+Y)*volPitch+X] += Z[i]; +		volData[((startZ+i)*dims.iVolY+Y)*volPitch+X] += Z[i] * fOutputScale;  }  // supersampling version -__global__ void dev_par3D_BP_SS(void* D_volData, unsigned int volPitch, int startAngle, int angleOffset, const SDimensions3D dims) +__global__ void dev_par3D_BP_SS(void* D_volData, unsigned int volPitch, int startAngle, int angleOffset, const SDimensions3D dims, float fOutputScale)  {  	float* volData = (float*)D_volData; @@ -180,6 +180,9 @@ __global__ void dev_par3D_BP_SS(void* D_volData, unsigned int volPitch, int star  	const float fSubStep = 1.0f/dims.iRaysPerVoxelDim; +	fOutputScale /= (dims.iRaysPerVoxelDim*dims.iRaysPerVoxelDim*dims.iRaysPerVoxelDim); + +  	for (int Z = startZ; Z < endZ; ++Z, fZ += 1.0f)  	{ @@ -217,14 +220,15 @@ __global__ void dev_par3D_BP_SS(void* D_volData, unsigned int volPitch, int star  		} -		volData[(Z*dims.iVolY+Y)*volPitch+X] += fVal / (dims.iRaysPerVoxelDim*dims.iRaysPerVoxelDim*dims.iRaysPerVoxelDim); +		volData[(Z*dims.iVolY+Y)*volPitch+X] += fVal * fOutputScale;  	}  }  bool Par3DBP_Array(cudaPitchedPtr D_volumeData,                     cudaArray *D_projArray, -                   const SDimensions3D& dims, const SPar3DProjection* angles) +                   const SDimensions3D& dims, const SPar3DProjection* angles, +                   float fOutputScale)  {  	bindProjDataTexture(D_projArray); @@ -271,9 +275,9 @@ bool Par3DBP_Array(cudaPitchedPtr D_volumeData,  		for (unsigned int i = 0; i < angleCount; i += g_anglesPerBlock) {  			// printf("Calling BP: %d, %dx%d, %dx%d to %p\n", i, dimBlock.x, dimBlock.y, dimGrid.x, dimGrid.y, (void*)D_volumeData.ptr);   			if (dims.iRaysPerVoxelDim == 1) -				dev_par3D_BP<<<dimGrid, dimBlock>>>(D_volumeData.ptr, D_volumeData.pitch/sizeof(float), i, th, dims); +				dev_par3D_BP<<<dimGrid, dimBlock>>>(D_volumeData.ptr, D_volumeData.pitch/sizeof(float), i, th, dims, fOutputScale);  			else -				dev_par3D_BP_SS<<<dimGrid, dimBlock>>>(D_volumeData.ptr, D_volumeData.pitch/sizeof(float), i, th, dims); +				dev_par3D_BP_SS<<<dimGrid, dimBlock>>>(D_volumeData.ptr, D_volumeData.pitch/sizeof(float), i, th, dims, fOutputScale);  		}  		cudaTextForceKernelsCompletion(); @@ -288,14 +292,15 @@ bool Par3DBP_Array(cudaPitchedPtr D_volumeData,  bool Par3DBP(cudaPitchedPtr D_volumeData,              cudaPitchedPtr D_projData, -            const SDimensions3D& dims, const SPar3DProjection* angles) +            const SDimensions3D& dims, const SPar3DProjection* angles, +            float fOutputScale)  {  	// transfer projections to array  	cudaArray* cuArray = allocateProjectionArray(dims);  	transferProjectionsToArray(D_projData, cuArray, dims); -	bool ret = Par3DBP_Array(D_volumeData, cuArray, dims, angles); +	bool ret = Par3DBP_Array(D_volumeData, cuArray, dims, angles, fOutputScale);  	cudaFreeArray(cuArray); @@ -445,7 +450,7 @@ int main()  		cudaMemcpy3D(&p);  	} -	astraCUDA3d::Par3DBP(volData, projData, dims, angle); +	astraCUDA3d::Par3DBP(volData, projData, dims, angle, 1.0f);  #if 1  	float* buf = new float[256*256]; diff --git a/cuda/3d/par3d_bp.h b/cuda/3d/par3d_bp.h index ece37d1..f1fc62d 100644 --- a/cuda/3d/par3d_bp.h +++ b/cuda/3d/par3d_bp.h @@ -33,11 +33,13 @@ namespace astraCUDA3d {  _AstraExport bool Par3DBP_Array(cudaPitchedPtr D_volumeData,                     cudaArray *D_projArray, -                   const SDimensions3D& dims, const SPar3DProjection* angles); +                   const SDimensions3D& dims, const SPar3DProjection* angles, +                   float fOutputScale);  _AstraExport bool Par3DBP(cudaPitchedPtr D_volumeData,               cudaPitchedPtr D_projData, -             const SDimensions3D& dims, const SPar3DProjection* angles); +             const SDimensions3D& dims, const SPar3DProjection* angles, +             float fOutputScale);  } diff --git a/cuda/3d/sirt3d.cu b/cuda/3d/sirt3d.cu index 389ee6b..484521e 100644 --- a/cuda/3d/sirt3d.cu +++ b/cuda/3d/sirt3d.cu @@ -160,10 +160,10 @@ bool SIRT::precomputeWeights()  	zeroVolumeData(D_pixelWeight, dims);  	if (useSinogramMask) { -		callBP(D_pixelWeight, D_smaskData); +		callBP(D_pixelWeight, D_smaskData, 1.0f);  	} else {  		processSino3D<opSet>(D_projData, 1.0f, dims); -		callBP(D_pixelWeight, D_projData); +		callBP(D_pixelWeight, D_projData, 1.0f);  	}  #if 0  	float* bufp = new float[512*512]; @@ -293,7 +293,7 @@ bool SIRT::iterate(unsigned int iterations)  #endif -		callBP(D_tmpData, D_projData); +		callBP(D_tmpData, D_projData, 1.0f);  #if 0  	printf("Dumping tmpData: %p\n", (void*)D_tmpData.ptr);  	float* buf = new float[256*256]; @@ -347,7 +347,7 @@ bool doSIRT(cudaPitchedPtr& D_volumeData,  	SIRT sirt;  	bool ok = true; -	ok &= sirt.setConeGeometry(dims, angles); +	ok &= sirt.setConeGeometry(dims, angles, 1.0f);  	if (D_maskData.ptr)  		ok &= sirt.enableVolumeMask(); diff --git a/include/astra/AstraObjectFactory.h b/include/astra/AstraObjectFactory.h index 1ed4955..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 { @@ -59,20 +63,27 @@ public:  	 */  	~CAstraObjectFactory(); -	/** Create, but don't initialize, a new projector object. +	/** Create, but don't initialize, a new object.  	 * -	 * @param _sType Type of the new projector. -	 * @return Pointer to a new, unitialized projector. +	 * @param _sType Type of the new object. +	 * @return Pointer to a new, uninitialized object.  	 */  	T* create(std::string _sType); -	/** Create and initialize a new projector object. +	/** Create and initialize a new object.  	 * -	 * @param _cfg Configuration object to create and initialize a new projector. +	 * @param _cfg Configuration object to create and initialize a new object.  	 * @return Pointer to a new, initialized projector.  	 */  	T* create(const Config& _cfg); +	/** Find a plugin. +	* +	* @param _sType Name of plugin to find. +	* @return Pointer to a new, uninitialized object, or NULL if not found. +	*/ +	T* findPlugin(std::string _sType); +  }; @@ -93,6 +104,15 @@ CAstraObjectFactory<T, TypeList>::~CAstraObjectFactory()  } + +//---------------------------------------------------------------------------------------- +// Hook for finding plugin in registered plugins. +template <typename T, typename TypeList> +T* CAstraObjectFactory<T, TypeList>::findPlugin(std::string _sType) +{ +	return NULL; +} +  //----------------------------------------------------------------------------------------  // Create   template <typename T, typename TypeList> @@ -101,6 +121,9 @@ T* CAstraObjectFactory<T, TypeList>::create(std::string _sType)  	functor_find<T> finder = functor_find<T>();  	finder.tofind = _sType;  	CreateObject<TypeList>::find(finder); +	if (finder.res == NULL) { +		finder.res = findPlugin(_sType); +	}  	return finder.res;  } @@ -109,14 +132,11 @@ T* CAstraObjectFactory<T, TypeList>::create(std::string _sType)  template <typename T, typename TypeList>  T* CAstraObjectFactory<T, TypeList>::create(const Config& _cfg)  { -	functor_find<T> finder = functor_find<T>(); -	finder.tofind = _cfg.self.getAttribute("type"); -	CreateObject<TypeList>::find(finder); -	if (finder.res == NULL) return NULL; -	if (finder.res->initialize(_cfg)) -		return finder.res; - -	delete finder.res; +	T* object = create(_cfg.self.getAttribute("type")); +	if (object == NULL) return NULL; +	if (object->initialize(_cfg)) +		return object; +	delete object;  	return NULL;  }  //---------------------------------------------------------------------------------------- @@ -131,6 +151,15 @@ T* CAstraObjectFactory<T, TypeList>::create(const Config& _cfg)  */  class _AstraExport CAlgorithmFactory : public CAstraObjectFactory<CAlgorithm, AlgorithmTypeList> {}; +#ifdef ASTRA_PYTHON +template <> +inline CAlgorithm* CAstraObjectFactory<CAlgorithm, AlgorithmTypeList>::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/CompositeGeometryManager.h b/include/astra/CompositeGeometryManager.h new file mode 100644 index 0000000..6610151 --- /dev/null +++ b/include/astra/CompositeGeometryManager.h @@ -0,0 +1,152 @@ +/* +----------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +*/ + +#ifndef _INC_ASTRA_COMPOSITEGEOMETRYMANAGER +#define _INC_ASTRA_COMPOSITEGEOMETRYMANAGER + +#include "Globals.h" + +#ifdef ASTRA_CUDA + +#include <list> +#include <map> +#include <vector> +#include <boost/shared_ptr.hpp> + + +namespace astra { + +class CCompositeVolume; +class CCompositeProjections; +class CFloat32Data3DMemory; +class CFloat32ProjectionData3DMemory; +class CFloat32VolumeData3DMemory; +class CVolumeGeometry3D; +class CProjectionGeometry3D; +class CProjector3D; + + + +class _AstraExport CCompositeGeometryManager { +public: +	class CPart; +	typedef std::list<boost::shared_ptr<CPart> > TPartList; +	class CPart { +	public: +		CPart() { } +		CPart(const CPart& other); +		virtual ~CPart() { } + +		enum { +			PART_VOL, PART_PROJ +		} eType; + +		CFloat32Data3DMemory* pData; +		unsigned int subX; +		unsigned int subY; +		unsigned int subZ; + +		bool uploadToGPU(); +		bool downloadFromGPU(/*mode?*/); +		virtual TPartList split(size_t maxSize, int div) = 0; +		virtual CPart* reduce(const CPart *other) = 0; +		virtual void getDims(size_t &x, size_t &y, size_t &z) = 0; +		size_t getSize(); +	}; + +	class CVolumePart : public CPart { +	public: +		CVolumePart() { eType = PART_VOL; } +		CVolumePart(const CVolumePart& other); +		virtual ~CVolumePart(); + +		CVolumeGeometry3D* pGeom; + +		virtual TPartList split(size_t maxSize, int div); +		virtual CPart* reduce(const CPart *other); +		virtual void getDims(size_t &x, size_t &y, size_t &z); + +		CVolumePart* clone() const; +	}; +	class CProjectionPart : public CPart { +	public: +		CProjectionPart() { eType = PART_PROJ; } +		CProjectionPart(const CProjectionPart& other); +		virtual ~CProjectionPart(); + +		CProjectionGeometry3D* pGeom; + +		virtual TPartList split(size_t maxSize, int div); +		virtual CPart* reduce(const CPart *other); +		virtual void getDims(size_t &x, size_t &y, size_t &z); + +		CProjectionPart* clone() const; +	}; + +	struct SJob { +	public: +		boost::shared_ptr<CPart> pInput; +		boost::shared_ptr<CPart> pOutput; +		CProjector3D *pProjector; // For a `global' geometry. It will not match +		                          // the geometries of the input and output. + + +		enum { +			JOB_FP, JOB_BP, JOB_NOP +		} eType; +		enum { +			MODE_ADD, MODE_SET +		} eMode; + +	}; + +	typedef std::list<SJob> TJobList; +	// output part -> list of jobs for that output +	typedef std::map<CPart*, TJobList > TJobSet; + +	bool doJobs(TJobList &jobs); + +	// Convenience functions for creating and running a single FP or BP job +	bool doFP(CProjector3D *pProjector, CFloat32VolumeData3DMemory *pVolData, +	          CFloat32ProjectionData3DMemory *pProjData); +	bool doBP(CProjector3D *pProjector, CFloat32VolumeData3DMemory *pVolData, +	          CFloat32ProjectionData3DMemory *pProjData); + +	bool doFP(CProjector3D *pProjector, const std::vector<CFloat32VolumeData3DMemory *>& volData, const std::vector<CFloat32ProjectionData3DMemory *>& projData); +	bool doBP(CProjector3D *pProjector, const std::vector<CFloat32VolumeData3DMemory *>& volData, const std::vector<CFloat32ProjectionData3DMemory *>& projData); + +protected: + +	bool splitJobs(TJobSet &jobs, size_t maxSize, int div, TJobSet &split); + +}; + +} + +#endif + +#endif diff --git a/include/astra/ConeProjectionGeometry3D.h b/include/astra/ConeProjectionGeometry3D.h index 00e72ce..dede6e1 100644 --- a/include/astra/ConeProjectionGeometry3D.h +++ b/include/astra/ConeProjectionGeometry3D.h @@ -186,9 +186,15 @@ public:  	 */  	virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const; -	virtual void projectPoint(float32 fX, float32 fY, float32 fZ, +	virtual void projectPoint(double fX, double fY, double fZ,  	                          int iAngleIndex, -	                          float32 &fU, float32 &fV) const; +	                          double &fU, double &fV) const; +	virtual void backprojectPointX(int iAngleIndex, double fU, double fV, +	                               double fX, double &fY, double &fZ) const; +	virtual void backprojectPointY(int iAngleIndex, double fU, double fV, +	                               double fY, double &fX, double &fZ) const; +	virtual void backprojectPointZ(int iAngleIndex, double fU, double fV, +	                               double fZ, double &fX, double &fY) const;  }; diff --git a/include/astra/ConeVecProjectionGeometry3D.h b/include/astra/ConeVecProjectionGeometry3D.h index 71e8010..f76f9dd 100644 --- a/include/astra/ConeVecProjectionGeometry3D.h +++ b/include/astra/ConeVecProjectionGeometry3D.h @@ -148,9 +148,16 @@ public:  	const SConeProjection* getProjectionVectors() const { return m_pProjectionAngles; } -	virtual void projectPoint(float32 fX, float32 fY, float32 fZ, +	virtual void projectPoint(double fX, double fY, double fZ,  	                          int iAngleIndex, -	                          float32 &fU, float32 &fV) const; +	                          double &fU, double &fV) const; +	virtual void backprojectPointX(int iAngleIndex, double fU, double fV, +	                               double fX, double &fY, double &fZ) const; +	virtual void backprojectPointY(int iAngleIndex, double fU, double fV, +	                               double fY, double &fX, double &fZ) const; +	virtual void backprojectPointZ(int iAngleIndex, double fU, double fV, +	                               double fZ, double &fX, double &fY) const; +  };  } // namespace astra diff --git a/include/astra/CudaBackProjectionAlgorithm.h b/include/astra/CudaBackProjectionAlgorithm.h index 84899b0..2450376 100644 --- a/include/astra/CudaBackProjectionAlgorithm.h +++ b/include/astra/CudaBackProjectionAlgorithm.h @@ -85,13 +85,10 @@ public:  	 * @param _pProjector		Projector Object. (Ignored)  	 * @param _pSinogram		ProjectionData2D object containing the sinogram data.  	 * @param _pReconstruction	VolumeData2D object for storing the reconstructed volume. -	 * @param _iGPUindex		GPU to use. -	 * @param _iPixelSuperSampling  Square root of number of samples per voxel, used to compute the backprojection  	 */  	bool initialize(CProjector2D* _pProjector,  	                CFloat32ProjectionData2D* _pSinogram,  -					CFloat32VolumeData2D* _pReconstruction, -					int _iGPUindex = -1, int _iPixelSuperSampling = 1); +					CFloat32VolumeData2D* _pReconstruction);  	/** Get a description of the class.  	 * diff --git a/include/astra/CudaBackProjectionAlgorithm3D.h b/include/astra/CudaBackProjectionAlgorithm3D.h index 2d98218..74aeec8 100644 --- a/include/astra/CudaBackProjectionAlgorithm3D.h +++ b/include/astra/CudaBackProjectionAlgorithm3D.h @@ -147,6 +147,8 @@ protected:  	 */  	bool m_bSIRTWeighting; + +	void initializeFromProjector();  };  // inline functions diff --git a/include/astra/CudaCglsAlgorithm.h b/include/astra/CudaCglsAlgorithm.h index c51093c..6aa0343 100644 --- a/include/astra/CudaCglsAlgorithm.h +++ b/include/astra/CudaCglsAlgorithm.h @@ -91,18 +91,13 @@ public:  	/** Initialize class, use sequential order.  	 * -	 * @param _pProjector		Projector Object. (Ignored) +	 * @param _pProjector		Projector Object. (Optional)  	 * @param _pSinogram		ProjectionData2D object containing the sinogram  	 * @param _pReconstruction	VolumeData2D for storing the reconstruction -	 * @param _iGPUindex		Index of GPU to use. (Starting at 0.) -	 * @param _iDetectorSuperSampling Supersampling factor for the FP. -	 * @param _iPixelSuperSampling  Square root of number of samples per voxel, used to compute the backprojection  	 */  	bool initialize(CProjector2D* _pProjector,   					CFloat32ProjectionData2D* _pSinogram,  -					CFloat32VolumeData2D* _pReconstruction, -					int _iGPUindex = -1, int _iDetectorSuperSampling = 1, -					int _iPixelSuperSampling = 1); +					CFloat32VolumeData2D* _pReconstruction);  	/** Get a description of the class.  	 * diff --git a/include/astra/CudaCglsAlgorithm3D.h b/include/astra/CudaCglsAlgorithm3D.h index 77c41c1..3e4084b 100644 --- a/include/astra/CudaCglsAlgorithm3D.h +++ b/include/astra/CudaCglsAlgorithm3D.h @@ -161,6 +161,8 @@ protected:  	bool m_bAstraCGLSInit;  	int m_iDetectorSuperSampling;  	int m_iVoxelSuperSampling; + +	void initializeFromProjector();  };  // inline functions diff --git a/include/astra/CudaEMAlgorithm.h b/include/astra/CudaEMAlgorithm.h index 97eb7ca..a9d2711 100644 --- a/include/astra/CudaEMAlgorithm.h +++ b/include/astra/CudaEMAlgorithm.h @@ -63,17 +63,13 @@ public:  	/** Initialize class.  	 * -	 * @param _pProjector		Projector Object. (Ignored) +	 * @param _pProjector		Projector Object. (Optional)  	 * @param _pSinogram		ProjectionData2D object containing the sinogram data.  	 * @param _pReconstruction	VolumeData2D object for storing the reconstructed volume. -	 * @param _iGPUindex		GPU to use. -	 * @param _iDetectorSuperSampling Supersampling factor for the FP.  	 */  	bool initialize(CProjector2D* _pProjector, -	                CFloat32ProjectionData2D* _pSinogram,  -					CFloat32VolumeData2D* _pReconstruction, -	                int _iGPUindex = -1, int _iDetectorSuperSampling = 1, -	                int _iPixelSuperSampling = 1); +	                CFloat32ProjectionData2D* _pSinogram, +	                CFloat32VolumeData2D* _pReconstruction);  	/** Get a description of the class.  	 * diff --git a/include/astra/CudaFDKAlgorithm3D.h b/include/astra/CudaFDKAlgorithm3D.h index 1b025f1..63f07fd 100644 --- a/include/astra/CudaFDKAlgorithm3D.h +++ b/include/astra/CudaFDKAlgorithm3D.h @@ -152,6 +152,8 @@ protected:  	int m_iGPUIndex;  	int m_iVoxelSuperSampling;  	bool m_bShortScan; + +	void initializeFromProjector();  };  // inline functions diff --git a/include/astra/CudaFilteredBackProjectionAlgorithm.h b/include/astra/CudaFilteredBackProjectionAlgorithm.h index 33445b6..cf1f19f 100644 --- a/include/astra/CudaFilteredBackProjectionAlgorithm.h +++ b/include/astra/CudaFilteredBackProjectionAlgorithm.h @@ -85,6 +85,9 @@ protected:  	AstraFBP* m_pFBP;  	bool m_bAstraFBPInit; + +	void initializeFromProjector(); +	virtual bool requiresProjector() const { return false; }  };  // inline functions diff --git a/include/astra/CudaForwardProjectionAlgorithm.h b/include/astra/CudaForwardProjectionAlgorithm.h index d172a7a..449a610 100644 --- a/include/astra/CudaForwardProjectionAlgorithm.h +++ b/include/astra/CudaForwardProjectionAlgorithm.h @@ -33,16 +33,15 @@ $Id$  #include "Algorithm.h" -#include "ParallelProjectionGeometry2D.h" -#include "VolumeGeometry2D.h" - -#include "Float32ProjectionData2D.h" -#include "Float32VolumeData2D.h" -  #ifdef ASTRA_CUDA  namespace astra { +class CProjector2D; +class CProjectionGeometry2D; +class CFloat32ProjectionData2D; +class CFloat32VolumeData2D; +  /**   * \brief   * This class contains a GPU implementation of an algorithm that creates a forward projection  @@ -91,19 +90,15 @@ public:  	/** Initialize class.  	 * -	 * @param _pVolumeGeometry		Geometry of the volume. -	 * @param _pProjectionGeometry	Geometry of the projection. +	 * @param _pProjector		Projector2D object. (Optional)  	 * @param _pVolume				VolumeData2D object containing the phantom to compute sinogram from		  	 * @param _pSinogram			ProjectionData2D object to store sinogram data in. -	 * @param _iGPUindex		Index of GPU to use. (Starting at 0.) -	 * @param _iDetectorSuperSampling  Number of samples per detector element, used to compute the forward projection  	 * @return success  	 */ -	bool initialize(CProjectionGeometry2D* _pProjectionGeometry, -					CVolumeGeometry2D* _pVolumeGeometry,  -					CFloat32VolumeData2D* _pVolume,  -					CFloat32ProjectionData2D* _pSinogram, -					int _iGPUindex = -1, int _iDetectorSuperSampling = 1); +	bool initialize(CProjector2D* _pProjector, +	                CFloat32VolumeData2D* _pVolume, +	                CFloat32ProjectionData2D* _pSinogram); +  	/** Get all information parameters  	 * @@ -147,6 +142,9 @@ public:  	void setGPUIndex(int _iGPUIndex);  protected: +	//< Optional Projector2D object +	CProjector2D* m_pProjector; +  	//< ProjectionData2D object containing the sinogram.  	CFloat32ProjectionData2D* m_pSinogram;  	//< VolumeData2D object containing the phantom. @@ -157,6 +155,7 @@ protected:  	//< Number of rays per detector element  	int m_iDetectorSuperSampling; +	void initializeFromProjector();  };  // inline functions diff --git a/include/astra/CudaForwardProjectionAlgorithm3D.h b/include/astra/CudaForwardProjectionAlgorithm3D.h index bdd1356..4198d56 100644 --- a/include/astra/CudaForwardProjectionAlgorithm3D.h +++ b/include/astra/CudaForwardProjectionAlgorithm3D.h @@ -122,6 +122,7 @@ protected:  	int m_iGPUIndex;  	int m_iDetectorSuperSampling; +	void initializeFromProjector();  };  // inline functions diff --git a/include/astra/CudaProjector2D.h b/include/astra/CudaProjector2D.h index ecfca41..2b4bacb 100644 --- a/include/astra/CudaProjector2D.h +++ b/include/astra/CudaProjector2D.h @@ -124,12 +124,14 @@ public:  	Cuda2DProjectionKernel getProjectionKernel() const { return m_projectionKernel; }  	int getVoxelSuperSampling() const { return m_iVoxelSuperSampling; }  	int getDetectorSuperSampling() const { return m_iDetectorSuperSampling; } +	int getGPUIndex() const { return m_iGPUIndex; }  protected:  	Cuda2DProjectionKernel m_projectionKernel;  	int m_iVoxelSuperSampling;  	int m_iDetectorSuperSampling; +	int m_iGPUIndex;  };  //---------------------------------------------------------------------------------------- diff --git a/include/astra/CudaProjector3D.h b/include/astra/CudaProjector3D.h index 1d570fe..da88d6d 100644 --- a/include/astra/CudaProjector3D.h +++ b/include/astra/CudaProjector3D.h @@ -117,12 +117,14 @@ public:  	Cuda3DProjectionKernel getProjectionKernel() const { return m_projectionKernel; }  	int getVoxelSuperSampling() const { return m_iVoxelSuperSampling; }  	int getDetectorSuperSampling() const { return m_iDetectorSuperSampling; } +	int getGPUIndex() const { return m_iGPUIndex; }  protected:  	Cuda3DProjectionKernel m_projectionKernel;  	int m_iVoxelSuperSampling;  	int m_iDetectorSuperSampling; +	int m_iGPUIndex;  }; diff --git a/include/astra/CudaReconstructionAlgorithm2D.h b/include/astra/CudaReconstructionAlgorithm2D.h index e19bb8f..dc93a1a 100644 --- a/include/astra/CudaReconstructionAlgorithm2D.h +++ b/include/astra/CudaReconstructionAlgorithm2D.h @@ -70,28 +70,13 @@ public:  	/** Initialize class.  	 * -	 * @param _pProjector		Projector Object. (Ignored) +	 * @param _pProjector		Projector Object. (Optional)  	 * @param _pSinogram		ProjectionData2D object containing the sinogram data.  	 * @param _pReconstruction	VolumeData2D object for storing the reconstructed volume.  	 */ -	bool initialize(CProjector2D* _pProjector,  -					CFloat32ProjectionData2D* _pSinogram,  -					CFloat32VolumeData2D* _pReconstruction); - -	/** Initialize class. -	 * -	 * @param _pProjector		Projector Object. (Ignored) -	 * @param _pSinogram		ProjectionData2D object containing the sinogram data. -	 * @param _pReconstruction	VolumeData2D object for storing the reconstructed volume. -	 * @param _iGPUindex		GPU to use. -	 * @param _iDetectorSuperSampling Supersampling factor for the FP. -	 * @param _iPixelSuperSampling  Square root of number of samples per voxel, used to compute the backprojection -	 */  	virtual bool initialize(CProjector2D* _pProjector,   	                        CFloat32ProjectionData2D* _pSinogram,  -	                        CFloat32VolumeData2D* _pReconstruction, -	                        int _iGPUindex = -1, int _iDetectorSuperSampling = 1, -	                        int _iPixelSuperSampling = 1); +	                        CFloat32VolumeData2D* _pReconstruction);  	/** Clear this class. @@ -166,6 +151,9 @@ protected:  	int m_iGPUIndex;  	bool m_bAlgoInit; + +	void initializeFromProjector(); +	virtual bool requiresProjector() const { return false; }  };  // inline functions diff --git a/include/astra/CudaSartAlgorithm.h b/include/astra/CudaSartAlgorithm.h index b370bd0..c22dc4f 100644 --- a/include/astra/CudaSartAlgorithm.h +++ b/include/astra/CudaSartAlgorithm.h @@ -84,16 +84,13 @@ public:  	/** Initialize class.  	 * -	 * @param _pProjector		Projector Object. (Ignored) +	 * @param _pProjector		Projector Object. (Optional)  	 * @param _pSinogram		ProjectionData2D object containing the sinogram data.  	 * @param _pReconstruction	VolumeData2D object for storing the reconstructed volume. -	 * @param _iGPUindex		GPU to use. -	 * @param _iDetectorSuperSampling Supersampling factor for the FP.  	 */  	bool initialize(CProjector2D* _pProjector, -	                CFloat32ProjectionData2D* _pSinogram,  -					CFloat32VolumeData2D* _pReconstruction, -					int _iGPUindex = -1, int _iDetectorSuperSampling = 1); +	                CFloat32ProjectionData2D* _pSinogram, +	                CFloat32VolumeData2D* _pReconstruction);  	/** Get a description of the class.  	 * diff --git a/include/astra/CudaSirtAlgorithm.h b/include/astra/CudaSirtAlgorithm.h index 607889a..929ac30 100644 --- a/include/astra/CudaSirtAlgorithm.h +++ b/include/astra/CudaSirtAlgorithm.h @@ -97,18 +97,13 @@ public:  	/** Initialize class.  	 * -	 * @param _pProjector		Projector Object. (Ignored) +	 * @param _pProjector		Projector Object. (Optional)  	 * @param _pSinogram		ProjectionData2D object containing the sinogram data.  	 * @param _pReconstruction	VolumeData2D object for storing the reconstructed volume. -	 * @param _iGPUindex		GPU to use. -	 * @param _iDetectorSuperSampling Supersampling factor for the FP. -	 * @param _iPixelSuperSampling  Square root of number of samples per voxel, used to compute the backprojection  	 */  	bool initialize(CProjector2D* _pProjector, -	                CFloat32ProjectionData2D* _pSinogram,  -					CFloat32VolumeData2D* _pReconstruction, -					int _iGPUindex = -1, int _iDetectorSuperSampling = 1, -					int _iPixelSuperSampling = 1); +	                CFloat32ProjectionData2D* _pSinogram, +	                CFloat32VolumeData2D* _pReconstruction);  	/** Get a description of the class.  	 * diff --git a/include/astra/CudaSirtAlgorithm3D.h b/include/astra/CudaSirtAlgorithm3D.h index fda4635..379720e 100644 --- a/include/astra/CudaSirtAlgorithm3D.h +++ b/include/astra/CudaSirtAlgorithm3D.h @@ -175,6 +175,8 @@ protected:  	bool m_bAstraSIRTInit;  	int m_iDetectorSuperSampling;  	int m_iVoxelSuperSampling; + +	void initializeFromProjector();  };  // inline functions diff --git a/include/astra/GeometryUtil3D.h b/include/astra/GeometryUtil3D.h index 698372e..e4d73e4 100644 --- a/include/astra/GeometryUtil3D.h +++ b/include/astra/GeometryUtil3D.h @@ -43,6 +43,33 @@ struct SConeProjection {  	// the V-edge of a detector pixel  	double fDetVX, fDetVY, fDetVZ; + + + + +	void translate(double dx, double dy, double dz) { +		fSrcX += dx; +		fSrcY += dy; +		fSrcZ += dz; +		fDetSX += dx; +		fDetSY += dy; +		fDetSZ += dz; + +	} +	void scale(double factor) { +		fSrcX *= factor; +		fSrcY *= factor; +		fSrcZ *= factor; +		fDetSX *= factor; +		fDetSY *= factor; +		fDetSZ *= factor; +		fDetUX *= factor; +		fDetUY *= factor; +		fDetUZ *= factor; +		fDetVX *= factor; +		fDetVY *= factor; +		fDetVZ *= factor; +	}  };  struct SPar3DProjection { @@ -57,6 +84,29 @@ struct SPar3DProjection {  	// the V-edge of a detector pixel  	double fDetVX, fDetVY, fDetVZ; + + + + +	void translate(double dx, double dy, double dz) { +		fDetSX += dx; +		fDetSY += dy; +		fDetSZ += dz; +	} +	void scale(double factor) { +		fRayX *= factor; +		fRayY *= factor; +		fRayZ *= factor; +		fDetSX *= factor; +		fDetSY *= factor; +		fDetSZ *= factor; +		fDetUX *= factor; +		fDetUY *= factor; +		fDetUZ *= factor; +		fDetVX *= factor; +		fDetVY *= factor; +		fDetVZ *= factor; +	}  };  void computeBP_UV_Coeffs(const SPar3DProjection& proj, @@ -68,6 +118,26 @@ void computeBP_UV_Coeffs(const SConeProjection& proj,                           double &fVX, double &fVY, double &fVZ, double &fVC,                           double &fDX, double &fDY, double &fDZ, double &fDC); + +SConeProjection* genConeProjections(unsigned int iProjAngles, +                                    unsigned int iProjU, +                                    unsigned int iProjV, +                                    double fOriginSourceDistance, +                                    double fOriginDetectorDistance, +                                    double fDetUSize, +                                    double fDetVSize, +                                    const float *pfAngles); + +SPar3DProjection* genPar3DProjections(unsigned int iProjAngles, +                                      unsigned int iProjU, +                                      unsigned int iProjV, +                                      double fDetUSize, +                                      double fDetVSize, +                                      const float *pfAngles); + + + +  }  #endif diff --git a/include/astra/Globals.h b/include/astra/Globals.h index 4de07d1..31f1371 100644 --- a/include/astra/Globals.h +++ b/include/astra/Globals.h @@ -61,9 +61,9 @@ $Id$  // macro's  #define ASTRA_TOOLBOXVERSION_MAJOR 1 -#define ASTRA_TOOLBOXVERSION_MINOR 6 +#define ASTRA_TOOLBOXVERSION_MINOR 7  #define ASTRA_TOOLBOXVERSION ((ASTRA_TOOLBOXVERSION_MAJOR)*100 + (ASTRA_TOOLBOXVERSION_MINOR)) -#define ASTRA_TOOLBOXVERSION_STRING "1.6" +#define ASTRA_TOOLBOXVERSION_STRING "1.7"  #define ASTRA_ASSERT(a) assert(a) @@ -146,6 +146,8 @@ namespace astra {  	const float32 PIdiv2 = PI / 2;  	const float32 PIdiv4 = PI / 4;  	const float32 eps = 1e-7f; +	 +	extern _AstraExport bool running_in_matlab;  }  //---------------------------------------------------------------------------------------- diff --git a/include/astra/ParallelProjectionGeometry3D.h b/include/astra/ParallelProjectionGeometry3D.h index 72401e5..d95c050 100644 --- a/include/astra/ParallelProjectionGeometry3D.h +++ b/include/astra/ParallelProjectionGeometry3D.h @@ -147,9 +147,16 @@ public:  	  */  	virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const; -	virtual void projectPoint(float32 fX, float32 fY, float32 fZ, +	virtual void projectPoint(double fX, double fY, double fZ,  	                          int iAngleIndex, -	                          float32 &fU, float32 &fV) const; +	                          double &fU, double &fV) const; +	virtual void backprojectPointX(int iAngleIndex, double fU, double fV, +	                               double fX, double &fY, double &fZ) const; +	virtual void backprojectPointY(int iAngleIndex, double fU, double fV, +	                               double fY, double &fX, double &fZ) const; +	virtual void backprojectPointZ(int iAngleIndex, double fU, double fV, +	                               double fZ, double &fX, double &fY) const; +  	 /**  	  * Creates (= allocates) a 2D projection geometry used when projecting one slice using a 2D projector diff --git a/include/astra/ParallelVecProjectionGeometry3D.h b/include/astra/ParallelVecProjectionGeometry3D.h index 59238c8..ec91086 100644 --- a/include/astra/ParallelVecProjectionGeometry3D.h +++ b/include/astra/ParallelVecProjectionGeometry3D.h @@ -149,9 +149,15 @@ public:  	const SPar3DProjection* getProjectionVectors() const { return m_pProjectionAngles; } -	virtual void projectPoint(float32 fX, float32 fY, float32 fZ, +	virtual void projectPoint(double fX, double fY, double fZ,  	                          int iAngleIndex, -	                          float32 &fU, float32 &fV) const; +	                          double &fU, double &fV) const; +	virtual void backprojectPointX(int iAngleIndex, double fU, double fV, +	                               double fX, double &fY, double &fZ) const; +	virtual void backprojectPointY(int iAngleIndex, double fU, double fV, +	                               double fY, double &fX, double &fZ) const; +	virtual void backprojectPointZ(int iAngleIndex, double fU, double fV, +	                               double fZ, double &fX, double &fY) const;  };  } // namespace astra diff --git a/include/astra/PluginAlgorithm.h b/include/astra/PluginAlgorithm.h new file mode 100644 index 0000000..667e813 --- /dev/null +++ b/include/astra/PluginAlgorithm.h @@ -0,0 +1,90 @@ +/* +----------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +$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; + + +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<CPluginAlgorithmFactory> { + +public: + +    CPluginAlgorithmFactory(); +    ~CPluginAlgorithmFactory(); + +    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<std::string, std::string> getRegisteredMap(); +     +    std::string getHelp(std::string name); + +private: +    PyObject * pluginDict; +    PyObject *inspect, *six; +}; + +PyObject* XMLNode2dict(XMLNode node); + +} + +#endif + +#endif diff --git a/include/astra/ProjectionGeometry3D.h b/include/astra/ProjectionGeometry3D.h index 19ac3ab..0b60287 100644 --- a/include/astra/ProjectionGeometry3D.h +++ b/include/astra/ProjectionGeometry3D.h @@ -317,9 +317,24 @@ public:  	 * @param iAngleIndex	the index of the angle to use  	 * @param fU,fV		the projected point.  	 */ -	virtual void projectPoint(float32 fX, float32 fY, float32 fZ, +	virtual void projectPoint(double fX, double fY, double fZ,  	                          int iAngleIndex, -	                          float32 &fU, float32 &fV) const = 0; +	                          double &fU, double &fV) const = 0; + +	/* Backproject a point onto a plane parallel to a coordinate plane. +	 * The 2D point coordinates are the (unrounded) indices of the detector +	 * column and row. The output is in 3D coordinates in units. +	 * are in units. The output fU,fV are the (unrounded) indices of the +	 * detector column and row. +	 * This may fall outside of the actual detector. +	 */ +	virtual void backprojectPointX(int iAngleIndex, double fU, double fV, +	                               double fX, double &fY, double &fZ) const = 0; +	virtual void backprojectPointY(int iAngleIndex, double fU, double fV, +	                               double fY, double &fX, double &fZ) const = 0; +	virtual void backprojectPointZ(int iAngleIndex, double fU, double fV, +	                               double fZ, double &fX, double &fY) const = 0; +  	/** Returns true if the type of geometry defined in this class is the one specified in _sType.  	 * diff --git a/include/astra/ReconstructionAlgorithm2D.h b/include/astra/ReconstructionAlgorithm2D.h index 60584e0..ac87c4f 100644 --- a/include/astra/ReconstructionAlgorithm2D.h +++ b/include/astra/ReconstructionAlgorithm2D.h @@ -208,6 +208,9 @@ protected:  	//< Use the fixed reconstruction mask?  	bool m_bUseSinogramMask; + +	//< Specify if initialize/check should check for a valid Projector +	virtual bool requiresProjector() const { return true; }  };  // inline functions 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_direct_c.cpp b/matlab/mex/astra_mex_direct_c.cpp new file mode 100755 index 0000000..38b3f59 --- /dev/null +++ b/matlab/mex/astra_mex_direct_c.cpp @@ -0,0 +1,348 @@ +/* +----------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +$Id$ +*/ + +/** \file astra_mex_direct_c.cpp + * + *  \brief Utility functions for low-overhead FP and BP calls. + */ +#include <mex.h> +#include "mexHelpFunctions.h" +#include "mexCopyDataHelpFunctions.h" +#include "mexDataManagerHelpFunctions.h" + +#include <list> + +#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<CCudaProjector3D*>(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(); + +		// 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); +	} 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<mxDOUBLE_CLASS>(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<CCudaProjector3D*>(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(); + +		// 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); +	} 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<mxDOUBLE_CLASS>(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/mex/astra_mex_direct_vc09.vcproj b/matlab/mex/astra_mex_direct_vc09.vcproj new file mode 100644 index 0000000..5d27c65 --- /dev/null +++ b/matlab/mex/astra_mex_direct_vc09.vcproj @@ -0,0 +1,628 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject +	ProjectType="Visual C++" +	Version="9.00" +	Name="astra_mex_direct" +	ProjectGUID="{85FE09A6-FA49-4314-A2B1-59D77C7442A8}" +	RootNamespace="astraMatlab" +	TargetFrameworkVersion="131072" +	> +	<Platforms> +		<Platform +			Name="Win32" +		/> +		<Platform +			Name="x64" +		/> +	</Platforms> +	<ToolFiles> +	</ToolFiles> +	<Configurations> +		<Configuration +			Name="Debug_CUDA|Win32" +			OutputDirectory="$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)" +			IntermediateDirectory="$(OutDir)\obj\$(ProjectName)" +			ConfigurationType="2" +			> +			<Tool +				Name="VCPreBuildEventTool" +			/> +			<Tool +				Name="VCCustomBuildTool" +			/> +			<Tool +				Name="VCXMLDataGeneratorTool" +			/> +			<Tool +				Name="VCWebServiceProxyGeneratorTool" +			/> +			<Tool +				Name="VCMIDLTool" +			/> +			<Tool +				Name="VCManagedResourceCompilerTool" +			/> +			<Tool +				Name="VCResourceCompilerTool" +			/> +			<Tool +				Name="VCPreLinkEventTool" +			/> +			<Tool +				Name="VCALinkTool" +			/> +			<Tool +				Name="VCManifestTool" +			/> +			<Tool +				Name="VCXDCMakeTool" +			/> +			<Tool +				Name="VCBscMakeTool" +			/> +			<Tool +				Name="VCFxCopTool" +			/> +			<Tool +				Name="VCAppVerifierTool" +			/> +			<Tool +				Name="VCPostBuildEventTool" +			/> +			<Tool +				Name="VCCLCompilerTool" +				AdditionalIncludeDirectories="$(MATLAB_ROOT)\extern\include\;"$(CUDA_INC_PATH)";..\..\lib\include;..\..\include" +				PreprocessorDefinitions="ASTRA_CUDA;__SSE2__" +				Optimization="0" +				RuntimeLibrary="3" +				EnableEnhancedInstructionSet="2" +				OpenMP="true" +				AdditionalOptions="/MP" +			/> +			<Tool +				Name="VCLinkerTool" +				AdditionalDependencies="AstraCuda32D.lib libmex.lib libmx.lib libut.lib" +				OutputFile="$(OutDir)\$(ProjectName)_c.mexw32" +				AdditionalLibraryDirectories="..\..\bin\win32;$(MATLAB_ROOT)\extern\lib\win32\microsoft;..\..\lib\win32" +				ModuleDefinitionFile="mex.def" +				GenerateDebugInformation="true" +				TargetMachine="1" +			/> +		</Configuration> +		<Configuration +			Name="Debug_CUDA|x64" +			OutputDirectory="$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)" +			IntermediateDirectory="$(OutDir)\obj\$(ProjectName)" +			ConfigurationType="2" +			> +			<Tool +				Name="VCPreBuildEventTool" +			/> +			<Tool +				Name="VCCustomBuildTool" +			/> +			<Tool +				Name="VCXMLDataGeneratorTool" +			/> +			<Tool +				Name="VCWebServiceProxyGeneratorTool" +			/> +			<Tool +				Name="VCMIDLTool" +			/> +			<Tool +				Name="VCManagedResourceCompilerTool" +			/> +			<Tool +				Name="VCResourceCompilerTool" +			/> +			<Tool +				Name="VCPreLinkEventTool" +			/> +			<Tool +				Name="VCALinkTool" +			/> +			<Tool +				Name="VCManifestTool" +			/> +			<Tool +				Name="VCXDCMakeTool" +			/> +			<Tool +				Name="VCBscMakeTool" +			/> +			<Tool +				Name="VCFxCopTool" +			/> +			<Tool +				Name="VCAppVerifierTool" +			/> +			<Tool +				Name="VCPostBuildEventTool" +			/> +			<Tool +				Name="VCCLCompilerTool" +				AdditionalIncludeDirectories="$(MATLAB_ROOT)\extern\include\;"$(CUDA_INC_PATH)";..\..\lib\include;..\..\include" +				PreprocessorDefinitions="ASTRA_CUDA;__SSE2__" +				Optimization="0" +				RuntimeLibrary="3" +				OpenMP="true" +				AdditionalOptions="/MP" +			/> +			<Tool +				Name="VCLinkerTool" +				AdditionalDependencies="AstraCuda64D.lib libmex.lib libmx.lib libut.lib" +				OutputFile="$(OutDir)\$(ProjectName)_c.mexw64" +				AdditionalLibraryDirectories="..\..\bin\x64;$(MATLAB_ROOT)\extern\lib\win64\microsoft;..\..\lib\x64" +				ModuleDefinitionFile="mex.def" +				GenerateDebugInformation="true" +				TargetMachine="17" +			/> +		</Configuration> +		<Configuration +			Name="Debug|Win32" +			OutputDirectory="$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)" +			IntermediateDirectory="$(OutDir)\obj\$(ProjectName)" +			ConfigurationType="2" +			> +			<Tool +				Name="VCPreBuildEventTool" +			/> +			<Tool +				Name="VCCustomBuildTool" +			/> +			<Tool +				Name="VCXMLDataGeneratorTool" +			/> +			<Tool +				Name="VCWebServiceProxyGeneratorTool" +			/> +			<Tool +				Name="VCMIDLTool" +			/> +			<Tool +				Name="VCManagedResourceCompilerTool" +			/> +			<Tool +				Name="VCResourceCompilerTool" +			/> +			<Tool +				Name="VCPreLinkEventTool" +			/> +			<Tool +				Name="VCALinkTool" +			/> +			<Tool +				Name="VCManifestTool" +			/> +			<Tool +				Name="VCXDCMakeTool" +			/> +			<Tool +				Name="VCBscMakeTool" +			/> +			<Tool +				Name="VCFxCopTool" +			/> +			<Tool +				Name="VCAppVerifierTool" +			/> +			<Tool +				Name="VCPostBuildEventTool" +			/> +			<Tool +				Name="VCCLCompilerTool" +				AdditionalIncludeDirectories="$(MATLAB_ROOT)\extern\include\;..\..\lib\include;..\..\include" +				PreprocessorDefinitions="__SSE2__" +				Optimization="0" +				RuntimeLibrary="3" +				EnableEnhancedInstructionSet="2" +				OpenMP="true" +				AdditionalOptions="/MP" +			/> +			<Tool +				Name="VCLinkerTool" +				AdditionalDependencies="Astra32D.lib libmex.lib libmx.lib libut.lib" +				OutputFile="$(OutDir)\$(ProjectName)_c.mexw32" +				AdditionalLibraryDirectories="..\..\bin\win32;$(MATLAB_ROOT)\extern\lib\win32\microsoft;..\..\lib\win32" +				ModuleDefinitionFile="mex.def" +				GenerateDebugInformation="true" +				TargetMachine="1" +			/> +		</Configuration> +		<Configuration +			Name="Debug|x64" +			OutputDirectory="$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)" +			IntermediateDirectory="$(OutDir)\obj\$(ProjectName)" +			ConfigurationType="2" +			> +			<Tool +				Name="VCPreBuildEventTool" +			/> +			<Tool +				Name="VCCustomBuildTool" +			/> +			<Tool +				Name="VCXMLDataGeneratorTool" +			/> +			<Tool +				Name="VCWebServiceProxyGeneratorTool" +			/> +			<Tool +				Name="VCMIDLTool" +			/> +			<Tool +				Name="VCManagedResourceCompilerTool" +			/> +			<Tool +				Name="VCResourceCompilerTool" +			/> +			<Tool +				Name="VCPreLinkEventTool" +			/> +			<Tool +				Name="VCALinkTool" +			/> +			<Tool +				Name="VCManifestTool" +			/> +			<Tool +				Name="VCXDCMakeTool" +			/> +			<Tool +				Name="VCBscMakeTool" +			/> +			<Tool +				Name="VCFxCopTool" +			/> +			<Tool +				Name="VCAppVerifierTool" +			/> +			<Tool +				Name="VCPostBuildEventTool" +			/> +			<Tool +				Name="VCCLCompilerTool" +				AdditionalIncludeDirectories="$(MATLAB_ROOT)\extern\include\;..\..\lib\include;..\..\include" +				PreprocessorDefinitions="__SSE2__" +				Optimization="0" +				RuntimeLibrary="3" +				OpenMP="true" +				AdditionalOptions="/MP" +			/> +			<Tool +				Name="VCLinkerTool" +				AdditionalDependencies="Astra64D.lib libmex.lib libmx.lib libut.lib" +				OutputFile="$(OutDir)\$(ProjectName)_c.mexw64" +				AdditionalLibraryDirectories="..\..\bin\x64;$(MATLAB_ROOT)\extern\lib\win64\microsoft;..\..\lib\x64" +				ModuleDefinitionFile="mex.def" +				GenerateDebugInformation="true" +				TargetMachine="17" +			/> +		</Configuration> +		<Configuration +			Name="Release_CUDA|Win32" +			OutputDirectory="$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)" +			IntermediateDirectory="$(OutDir)\obj\$(ProjectName)" +			ConfigurationType="2" +			> +			<Tool +				Name="VCPreBuildEventTool" +			/> +			<Tool +				Name="VCCustomBuildTool" +			/> +			<Tool +				Name="VCXMLDataGeneratorTool" +			/> +			<Tool +				Name="VCWebServiceProxyGeneratorTool" +			/> +			<Tool +				Name="VCMIDLTool" +			/> +			<Tool +				Name="VCManagedResourceCompilerTool" +			/> +			<Tool +				Name="VCResourceCompilerTool" +			/> +			<Tool +				Name="VCPreLinkEventTool" +			/> +			<Tool +				Name="VCALinkTool" +			/> +			<Tool +				Name="VCManifestTool" +			/> +			<Tool +				Name="VCXDCMakeTool" +			/> +			<Tool +				Name="VCBscMakeTool" +			/> +			<Tool +				Name="VCFxCopTool" +			/> +			<Tool +				Name="VCAppVerifierTool" +			/> +			<Tool +				Name="VCPostBuildEventTool" +			/> +			<Tool +				Name="VCCLCompilerTool" +				AdditionalIncludeDirectories="$(MATLAB_ROOT)\extern\include\;"$(CUDA_INC_PATH)";..\..\lib\include;..\..\include" +				PreprocessorDefinitions="ASTRA_CUDA;__SSE2__" +				Optimization="2" +				RuntimeLibrary="2" +				EnableEnhancedInstructionSet="2" +				OpenMP="true" +				AdditionalOptions="/MP" +			/> +			<Tool +				Name="VCLinkerTool" +				AdditionalDependencies="AstraCuda32.lib libmex.lib libmx.lib libut.lib" +				OutputFile="$(OutDir)\$(ProjectName)_c.mexw32" +				AdditionalLibraryDirectories="..\..\bin\win32;$(MATLAB_ROOT)\extern\lib\win32\microsoft;..\..\lib\win32" +				ModuleDefinitionFile="mex.def" +				GenerateDebugInformation="false" +				TargetMachine="1" +			/> +		</Configuration> +		<Configuration +			Name="Release_CUDA|x64" +			OutputDirectory="$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)" +			IntermediateDirectory="$(OutDir)\obj\$(ProjectName)" +			ConfigurationType="2" +			> +			<Tool +				Name="VCPreBuildEventTool" +			/> +			<Tool +				Name="VCCustomBuildTool" +			/> +			<Tool +				Name="VCXMLDataGeneratorTool" +			/> +			<Tool +				Name="VCWebServiceProxyGeneratorTool" +			/> +			<Tool +				Name="VCMIDLTool" +			/> +			<Tool +				Name="VCManagedResourceCompilerTool" +			/> +			<Tool +				Name="VCResourceCompilerTool" +			/> +			<Tool +				Name="VCPreLinkEventTool" +			/> +			<Tool +				Name="VCALinkTool" +			/> +			<Tool +				Name="VCManifestTool" +			/> +			<Tool +				Name="VCXDCMakeTool" +			/> +			<Tool +				Name="VCBscMakeTool" +			/> +			<Tool +				Name="VCFxCopTool" +			/> +			<Tool +				Name="VCAppVerifierTool" +			/> +			<Tool +				Name="VCPostBuildEventTool" +			/> +			<Tool +				Name="VCCLCompilerTool" +				AdditionalIncludeDirectories="$(MATLAB_ROOT)\extern\include\;"$(CUDA_INC_PATH)";..\..\lib\include;..\..\include" +				PreprocessorDefinitions="ASTRA_CUDA;__SSE2__" +				Optimization="2" +				RuntimeLibrary="2" +				OpenMP="true" +				AdditionalOptions="/MP" +			/> +			<Tool +				Name="VCLinkerTool" +				AdditionalDependencies="AstraCuda64.lib libmex.lib libmx.lib libut.lib" +				OutputFile="$(OutDir)\$(ProjectName)_c.mexw64" +				AdditionalLibraryDirectories="..\..\bin\x64;$(MATLAB_ROOT)\extern\lib\win64\microsoft;..\..\lib\x64" +				ModuleDefinitionFile="mex.def" +				GenerateDebugInformation="false" +				TargetMachine="17" +			/> +		</Configuration> +		<Configuration +			Name="Release|Win32" +			OutputDirectory="$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)" +			IntermediateDirectory="$(OutDir)\obj\$(ProjectName)" +			ConfigurationType="2" +			> +			<Tool +				Name="VCPreBuildEventTool" +			/> +			<Tool +				Name="VCCustomBuildTool" +			/> +			<Tool +				Name="VCXMLDataGeneratorTool" +			/> +			<Tool +				Name="VCWebServiceProxyGeneratorTool" +			/> +			<Tool +				Name="VCMIDLTool" +			/> +			<Tool +				Name="VCManagedResourceCompilerTool" +			/> +			<Tool +				Name="VCResourceCompilerTool" +			/> +			<Tool +				Name="VCPreLinkEventTool" +			/> +			<Tool +				Name="VCALinkTool" +			/> +			<Tool +				Name="VCManifestTool" +			/> +			<Tool +				Name="VCXDCMakeTool" +			/> +			<Tool +				Name="VCBscMakeTool" +			/> +			<Tool +				Name="VCFxCopTool" +			/> +			<Tool +				Name="VCAppVerifierTool" +			/> +			<Tool +				Name="VCPostBuildEventTool" +			/> +			<Tool +				Name="VCCLCompilerTool" +				AdditionalIncludeDirectories="$(MATLAB_ROOT)\extern\include\;..\..\lib\include;..\..\include" +				PreprocessorDefinitions="__SSE2__" +				Optimization="2" +				RuntimeLibrary="2" +				EnableEnhancedInstructionSet="2" +				OpenMP="true" +				AdditionalOptions="/MP" +			/> +			<Tool +				Name="VCLinkerTool" +				AdditionalDependencies="Astra32.lib libmex.lib libmx.lib libut.lib" +				OutputFile="$(OutDir)\$(ProjectName)_c.mexw32" +				AdditionalLibraryDirectories="..\..\bin\win32;$(MATLAB_ROOT)\extern\lib\win32\microsoft;..\..\lib\win32" +				ModuleDefinitionFile="mex.def" +				GenerateDebugInformation="false" +				TargetMachine="1" +			/> +		</Configuration> +		<Configuration +			Name="Release|x64" +			OutputDirectory="$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)" +			IntermediateDirectory="$(OutDir)\obj\$(ProjectName)" +			ConfigurationType="2" +			> +			<Tool +				Name="VCPreBuildEventTool" +			/> +			<Tool +				Name="VCCustomBuildTool" +			/> +			<Tool +				Name="VCXMLDataGeneratorTool" +			/> +			<Tool +				Name="VCWebServiceProxyGeneratorTool" +			/> +			<Tool +				Name="VCMIDLTool" +			/> +			<Tool +				Name="VCManagedResourceCompilerTool" +			/> +			<Tool +				Name="VCResourceCompilerTool" +			/> +			<Tool +				Name="VCPreLinkEventTool" +			/> +			<Tool +				Name="VCALinkTool" +			/> +			<Tool +				Name="VCManifestTool" +			/> +			<Tool +				Name="VCXDCMakeTool" +			/> +			<Tool +				Name="VCBscMakeTool" +			/> +			<Tool +				Name="VCFxCopTool" +			/> +			<Tool +				Name="VCAppVerifierTool" +			/> +			<Tool +				Name="VCPostBuildEventTool" +			/> +			<Tool +				Name="VCCLCompilerTool" +				AdditionalIncludeDirectories="$(MATLAB_ROOT)\extern\include\;..\..\lib\include;..\..\include" +				PreprocessorDefinitions="__SSE2__" +				Optimization="2" +				RuntimeLibrary="2" +				OpenMP="true" +				AdditionalOptions="/MP" +			/> +			<Tool +				Name="VCLinkerTool" +				AdditionalDependencies="Astra64.lib libmex.lib libmx.lib libut.lib" +				OutputFile="$(OutDir)\$(ProjectName)_c.mexw64" +				AdditionalLibraryDirectories="..\..\bin\x64;$(MATLAB_ROOT)\extern\lib\win64\microsoft;..\..\lib\x64" +				ModuleDefinitionFile="mex.def" +				GenerateDebugInformation="false" +				TargetMachine="17" +			/> +		</Configuration> +	</Configurations> +	<References> +	</References> +	<Files> +		<File +			RelativePath=".\astra_mex_direct_c.cpp" +			> +		</File> +		<File +			RelativePath=".\mexHelpFunctions.cpp" +			> +		</File> +		<File +			RelativePath=".\mexHelpFunctions.h" +			> +		</File> +		<File +			RelativePath=".\mexCopyDataHelpFunctions.cpp" +			> +		</File> +		<File +			RelativePath=".\mexCopyDataHelpFunctions.h" +			> +		</File> +		<File +			RelativePath=".\mexDataManagerHelpFunctions.cpp" +			> +		</File> +		<File +			RelativePath=".\mexDataManagerHelpFunctions.h" +			> +		</File> +		<File +			RelativePath=".\mexInitFunctions.cpp" +			> +		</File> +		<File +			RelativePath=".\mexInitFunctions.h" +			> +		</File> +	</Files> +	<Globals> +	</Globals> +</VisualStudioProject> diff --git a/matlab/mex/astra_mex_direct_vc11.vcxproj b/matlab/mex/astra_mex_direct_vc11.vcxproj new file mode 100644 index 0000000..bc2db62 --- /dev/null +++ b/matlab/mex/astra_mex_direct_vc11.vcxproj @@ -0,0 +1,310 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +  <ItemGroup Label="ProjectConfigurations"> +    <ProjectConfiguration Include="Debug_CUDA|Win32"> +      <Configuration>Debug_CUDA</Configuration> +      <Platform>Win32</Platform> +    </ProjectConfiguration> +    <ProjectConfiguration Include="Debug_CUDA|x64"> +      <Configuration>Debug_CUDA</Configuration> +      <Platform>x64</Platform> +    </ProjectConfiguration> +    <ProjectConfiguration Include="Debug|Win32"> +      <Configuration>Debug</Configuration> +      <Platform>Win32</Platform> +    </ProjectConfiguration> +    <ProjectConfiguration Include="Debug|x64"> +      <Configuration>Debug</Configuration> +      <Platform>x64</Platform> +    </ProjectConfiguration> +    <ProjectConfiguration Include="Release_CUDA|Win32"> +      <Configuration>Release_CUDA</Configuration> +      <Platform>Win32</Platform> +    </ProjectConfiguration> +    <ProjectConfiguration Include="Release_CUDA|x64"> +      <Configuration>Release_CUDA</Configuration> +      <Platform>x64</Platform> +    </ProjectConfiguration> +    <ProjectConfiguration Include="Release|Win32"> +      <Configuration>Release</Configuration> +      <Platform>Win32</Platform> +    </ProjectConfiguration> +    <ProjectConfiguration Include="Release|x64"> +      <Configuration>Release</Configuration> +      <Platform>x64</Platform> +    </ProjectConfiguration> +  </ItemGroup> +  <PropertyGroup Label="Globals"> +    <ProjectName>astra_mex_direct</ProjectName> +    <ProjectGuid>{0F68F4E2-BE1B-4A9A-B101-AECF4C069CC7}</ProjectGuid> +    <RootNamespace>astraMatlab</RootNamespace> +  </PropertyGroup> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_CUDA|Win32'" Label="Configuration"> +    <ConfigurationType>DynamicLibrary</ConfigurationType> +    <PlatformToolset>v110</PlatformToolset> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_CUDA|x64'" Label="Configuration"> +    <ConfigurationType>DynamicLibrary</ConfigurationType> +    <PlatformToolset>v110</PlatformToolset> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> +    <ConfigurationType>DynamicLibrary</ConfigurationType> +    <PlatformToolset>v110</PlatformToolset> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> +    <ConfigurationType>DynamicLibrary</ConfigurationType> +    <PlatformToolset>v110</PlatformToolset> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_CUDA|Win32'" Label="Configuration"> +    <ConfigurationType>DynamicLibrary</ConfigurationType> +    <PlatformToolset>v110</PlatformToolset> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_CUDA|x64'" Label="Configuration"> +    <ConfigurationType>DynamicLibrary</ConfigurationType> +    <PlatformToolset>v110</PlatformToolset> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> +    <ConfigurationType>DynamicLibrary</ConfigurationType> +    <PlatformToolset>v110</PlatformToolset> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> +    <ConfigurationType>DynamicLibrary</ConfigurationType> +    <PlatformToolset>v110</PlatformToolset> +  </PropertyGroup> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> +  <ImportGroup Label="ExtensionSettings"> +  </ImportGroup> +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug_CUDA|Win32'"> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +  </ImportGroup> +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug_CUDA|x64'"> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +  </ImportGroup> +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +  </ImportGroup> +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +  </ImportGroup> +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release_CUDA|Win32'"> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +  </ImportGroup> +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release_CUDA|x64'"> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +  </ImportGroup> +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +  </ImportGroup> +  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +  </ImportGroup> +  <PropertyGroup Label="UserMacros" /> +  <PropertyGroup> +    <_ProjectFileVersion>11.0.60610.1</_ProjectFileVersion> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_CUDA|Win32'"> +    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir> +    <IntDir>$(OutDir)obj\$(ProjectName)\</IntDir> +    <TargetName>$(ProjectName)_c</TargetName> +    <TargetExt>.mexw32</TargetExt> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_CUDA|x64'"> +    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir> +    <IntDir>$(OutDir)obj\$(ProjectName)\</IntDir> +    <TargetName>$(ProjectName)_c</TargetName> +    <TargetExt>.mexw64</TargetExt> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> +    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir> +    <IntDir>$(OutDir)obj\$(ProjectName)\</IntDir> +    <TargetName>$(ProjectName)_c</TargetName> +    <TargetExt>.mexw32</TargetExt> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> +    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir> +    <IntDir>$(OutDir)obj\$(ProjectName)\</IntDir> +    <TargetName>$(ProjectName)_c</TargetName> +    <TargetExt>.mexw64</TargetExt> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_CUDA|Win32'"> +    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir> +    <IntDir>$(OutDir)obj\$(ProjectName)\</IntDir> +    <TargetName>$(ProjectName)_c</TargetName> +    <TargetExt>.mexw32</TargetExt> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_CUDA|x64'"> +    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir> +    <IntDir>$(OutDir)obj\$(ProjectName)\</IntDir> +    <TargetName>$(ProjectName)_c</TargetName> +    <TargetExt>.mexw64</TargetExt> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> +    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir> +    <IntDir>$(OutDir)obj\$(ProjectName)\</IntDir> +    <TargetName>$(ProjectName)_c</TargetName> +    <TargetExt>.mexw32</TargetExt> +  </PropertyGroup> +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> +    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir> +    <IntDir>$(OutDir)obj\$(ProjectName)\</IntDir> +    <TargetName>$(ProjectName)_c</TargetName> +    <TargetExt>.mexw64</TargetExt> +  </PropertyGroup> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug_CUDA|Win32'"> +    <ClCompile> +      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> +      <AdditionalIncludeDirectories>$(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> +      <OpenMPSupport>true</OpenMPSupport> +      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> +      <Optimization>Disabled</Optimization> +      <PreprocessorDefinitions>ASTRA_CUDA;__SSE2__;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <MultiProcessorCompilation>true</MultiProcessorCompilation> +    </ClCompile> +    <Link> +      <OutputFile>$(OutDir)$(ProjectName)_c.mexw32</OutputFile> +      <AdditionalDependencies>AstraCuda32D.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalLibraryDirectories>..\..\lib\win32\;..\..\bin\win32\Debug_CUDA;$(MATLAB_ROOT)\extern\lib\win32\microsoft;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> +      <ModuleDefinitionFile>mex.def</ModuleDefinitionFile> +      <GenerateDebugInformation>true</GenerateDebugInformation> +    </Link> +  </ItemDefinitionGroup> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug_CUDA|x64'"> +    <ClCompile> +      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> +      <AdditionalIncludeDirectories>$(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> +      <OpenMPSupport>true</OpenMPSupport> +      <Optimization>Disabled</Optimization> +      <PreprocessorDefinitions>ASTRA_CUDA;__SSE2__;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <MultiProcessorCompilation>true</MultiProcessorCompilation> +    </ClCompile> +    <Link> +      <OutputFile>$(OutDir)$(ProjectName)_c.mexw64</OutputFile> +      <AdditionalDependencies>AstraCuda64D.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalLibraryDirectories>..\..\lib\x64\;..\..\bin\x64\Debug_CUDA;$(MATLAB_ROOT)\extern\lib\win64\microsoft;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> +      <ModuleDefinitionFile>mex.def</ModuleDefinitionFile> +      <GenerateDebugInformation>true</GenerateDebugInformation> +    </Link> +  </ItemDefinitionGroup> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> +    <ClCompile> +      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> +      <AdditionalIncludeDirectories>$(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> +      <OpenMPSupport>true</OpenMPSupport> +      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> +      <Optimization>Disabled</Optimization> +      <PreprocessorDefinitions>__SSE2__;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <MultiProcessorCompilation>true</MultiProcessorCompilation> +    </ClCompile> +    <Link> +      <OutputFile>$(OutDir)$(ProjectName)_c.mexw32</OutputFile> +      <AdditionalDependencies>Astra32D.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalLibraryDirectories>..\..\lib\win32\;..\..\bin\win32\Debug;$(MATLAB_ROOT)\extern\lib\win32\microsoft;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> +      <ModuleDefinitionFile>mex.def</ModuleDefinitionFile> +      <GenerateDebugInformation>true</GenerateDebugInformation> +    </Link> +  </ItemDefinitionGroup> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> +    <ClCompile> +      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> +      <AdditionalIncludeDirectories>$(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> +      <OpenMPSupport>true</OpenMPSupport> +      <Optimization>Disabled</Optimization> +      <PreprocessorDefinitions>__SSE2__;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <MultiProcessorCompilation>true</MultiProcessorCompilation> +    </ClCompile> +    <Link> +      <OutputFile>$(OutDir)$(ProjectName)_c.mexw64</OutputFile> +      <AdditionalDependencies>Astra64D.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalLibraryDirectories>..\..\lib\x64\;..\..\bin\x64\Debug;$(MATLAB_ROOT)\extern\lib\win64\microsoft;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> +      <ModuleDefinitionFile>mex.def</ModuleDefinitionFile> +      <GenerateDebugInformation>true</GenerateDebugInformation> +    </Link> +  </ItemDefinitionGroup> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_CUDA|Win32'"> +    <ClCompile> +      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> +      <AdditionalIncludeDirectories>$(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> +      <OpenMPSupport>true</OpenMPSupport> +      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> +      <Optimization>MaxSpeed</Optimization> +      <PreprocessorDefinitions>ASTRA_CUDA;__SSE2__;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <MultiProcessorCompilation>true</MultiProcessorCompilation> +    </ClCompile> +    <Link> +      <OutputFile>$(OutDir)$(ProjectName)_c.mexw32</OutputFile> +      <AdditionalDependencies>AstraCuda32.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalLibraryDirectories>..\..\lib\win32\;..\..\bin\win32\Release_CUDA;$(MATLAB_ROOT)\extern\lib\win32\microsoft;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> +      <ModuleDefinitionFile>mex.def</ModuleDefinitionFile> +      <GenerateDebugInformation>true</GenerateDebugInformation> +    </Link> +  </ItemDefinitionGroup> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_CUDA|x64'"> +    <ClCompile> +      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> +      <AdditionalIncludeDirectories>$(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> +      <OpenMPSupport>true</OpenMPSupport> +      <Optimization>MaxSpeed</Optimization> +      <PreprocessorDefinitions>ASTRA_CUDA;__SSE2__;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <MultiProcessorCompilation>true</MultiProcessorCompilation> +    </ClCompile> +    <Link> +      <OutputFile>$(OutDir)$(ProjectName)_c.mexw64</OutputFile> +      <AdditionalDependencies>AstraCuda64.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalLibraryDirectories>..\..\lib\x64\;..\..\bin\x64\Release_CUDA;$(MATLAB_ROOT)\extern\lib\win64\microsoft;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> +      <ModuleDefinitionFile>mex.def</ModuleDefinitionFile> +      <GenerateDebugInformation>true</GenerateDebugInformation> +    </Link> +  </ItemDefinitionGroup> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> +    <ClCompile> +      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> +      <AdditionalIncludeDirectories>$(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> +      <OpenMPSupport>true</OpenMPSupport> +      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> +      <Optimization>MaxSpeed</Optimization> +      <PreprocessorDefinitions>__SSE2__;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <MultiProcessorCompilation>true</MultiProcessorCompilation> +    </ClCompile> +    <Link> +      <OutputFile>$(OutDir)$(ProjectName)_c.mexw32</OutputFile> +      <AdditionalDependencies>Astra32.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalLibraryDirectories>..\..\lib\win32\;..\..\bin\win32\Release;$(MATLAB_ROOT)\extern\lib\win32\microsoft;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> +      <ModuleDefinitionFile>mex.def</ModuleDefinitionFile> +      <GenerateDebugInformation>true</GenerateDebugInformation> +    </Link> +  </ItemDefinitionGroup> +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> +    <ClCompile> +      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> +      <AdditionalIncludeDirectories>$(MATLAB_ROOT)\extern\include\;$(CUDA_PATH)\include;..\..\lib\include;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> +      <OpenMPSupport>true</OpenMPSupport> +      <Optimization>MaxSpeed</Optimization> +      <PreprocessorDefinitions>__SSE2__;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <MultiProcessorCompilation>true</MultiProcessorCompilation> +    </ClCompile> +    <Link> +      <OutputFile>$(OutDir)$(ProjectName)_c.mexw64</OutputFile> +      <AdditionalDependencies>Astra64.lib;libmex.lib;libmx.lib;libut.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalLibraryDirectories>..\..\lib\x64\;..\..\bin\x64\Release;$(MATLAB_ROOT)\extern\lib\win64\microsoft;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> +      <ModuleDefinitionFile>mex.def</ModuleDefinitionFile> +      <GenerateDebugInformation>true</GenerateDebugInformation> +    </Link> +  </ItemDefinitionGroup> +  <ItemGroup> +    <ClCompile Include="astra_mex_direct_c.cpp" /> +    <ClCompile Include="mexHelpFunctions.cpp" /> +    <ClCompile Include="mexCopyDataHelpFunctions.cpp" /> +    <ClCompile Include="mexDataManagerHelpFunctions.cpp" /> +    <ClCompile Include="mexInitFunctions.cpp" /> +  </ItemGroup> +  <ItemGroup> +    <ClInclude Include="mexHelpFunctions.h" /> +    <ClInclude Include="mexCopyDataHelpFunctions.h" /> +    <ClInclude Include="mexDataManagerHelpFunctions.h" /> +    <ClInclude Include="mexInitFunctions.h" /> +  </ItemGroup> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +  <ImportGroup Label="ExtensionTargets"> +  </ImportGroup> +</Project>
\ No newline at end of file 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); diff --git a/matlab/mex/astra_mex_plugin_c.cpp b/matlab/mex/astra_mex_plugin_c.cpp new file mode 100644 index 0000000..177fcf4 --- /dev/null +++ b/matlab/mex/astra_mex_plugin_c.cpp @@ -0,0 +1,132 @@ +/* +----------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +$Id$ +*/ + +/** \file astra_mex_plugin_c.cpp + * + *  \brief Manages Python plugins. + */ + +#include <mex.h> +#include "mexHelpFunctions.h" +#include "mexInitFunctions.h" + +#include "astra/PluginAlgorithm.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(); +    std::map<std::string, std::string> mp = fact->getRegisteredMap(); +    for(std::map<std::string,std::string>::iterator it=mp.begin();it!=mp.end();it++){ +        mexPrintf("%s: %s\n",it->first.c_str(), it->second.c_str()); +    } +} + +//----------------------------------------------------------------------------------------- +/** astra_mex_plugin('register', class_name); + * + * Register plugin. + */ +void astra_mex_plugin_register(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) +{ +    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"); +    } +} + +//----------------------------------------------------------------------------------------- +/** 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/matlab/mex/mexInitFunctions.cpp b/matlab/mex/mexInitFunctions.cpp index 89a31a1..bd3df2c 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/matlab/tools/astra_create_projector.m b/matlab/tools/astra_create_projector.m index da9c083..9bbef9e 100644 --- a/matlab/tools/astra_create_projector.m +++ b/matlab/tools/astra_create_projector.m @@ -1,7 +1,7 @@ -function proj_id = astra_create_projector(type, proj_geom, vol_geom) +function proj_id = astra_create_projector(type, proj_geom, vol_geom, options)  %-------------------------------------------------------------------------- -% proj_id = astra_create_projector(type, proj_geom, vol_geom) +% proj_id = astra_create_projector(type, proj_geom, vol_geom, options)  %   % Create a new projector object based on projection and volume geometry.    % Used when the default values of each projector are sufficient.   @@ -9,6 +9,7 @@ function proj_id = astra_create_projector(type, proj_geom, vol_geom)  % type: type of the projector.  'blob', 'line', 'linear' 'strip', ... See API for more information.  % proj_geom: MATLAB struct containing the projection geometry.  % vol_geom: MATLAB struct containing the volume geometry. +% options: Optional MATLAB struct containing projector options (like: 'GPUindex', 'DetectorSuperSampling', and 'VoxelSuperSampling')  % proj_id: identifier of the projector as it is now stored in the astra-library.  %--------------------------------------------------------------------------  %-------------------------------------------------------------------------- @@ -38,6 +39,10 @@ if strcmp(type,'blob')  	cfg_proj.Kernel.KernelValues = blob_values;  end +if exist('options', 'var') +    cfg_proj.options = options; +end +  if strcmp(type,'linear3d') || strcmp(type,'linearcone') || strcmp(type,'cuda3d')  	proj_id = astra_mex_projector3d('create', cfg_proj);  else diff --git a/matlab/tools/astra_create_vol_geom.m b/matlab/tools/astra_create_vol_geom.m index ea975e6..a3ba7de 100644 --- a/matlab/tools/astra_create_vol_geom.m +++ b/matlab/tools/astra_create_vol_geom.m @@ -15,6 +15,7 @@ function vol_geom = astra_create_vol_geom(varargin)  % vol_geom: MATLAB struct containing all information of the geometry.  %--------------------------------------------------------------------------  % vol_geom = astra_create_vol_geom(row_count, col_count, slice_count); +% vol_geom = astra_create_vol_geom(row_count, col_count, slice_count, min_x, max_x, min_y, max_y, min_z, max_z);  %  % Create a 3D volume geometry.  See the API for more information.  % row_count: number of rows. @@ -93,4 +94,18 @@ elseif numel(varargin) == 3  	vol_geom.GridRowCount =	varargin{1};  	vol_geom.GridColCount = varargin{2};  	vol_geom.GridSliceCount = varargin{3}; + +% astra_create_vol_geom(row_count, col_count, slice_count, min_x, max_x, min_y, max_y, min_z, max_z) +elseif numel(varargin) == 9 +	vol_geom = struct(); +	vol_geom.GridRowCount = varargin{1}; +	vol_geom.GridColCount = varargin{2}; +	vol_geom.GridSliceCount = varargin{3}; +	vol_geom.option.WindowMinX = varargin{4}; +	vol_geom.option.WindowMaxX = varargin{5}; +	vol_geom.option.WindowMinY = varargin{6}; +	vol_geom.option.WindowMaxY = varargin{7}; +	vol_geom.option.WindowMinZ = varargin{8}; +	vol_geom.option.WindowMaxZ = varargin{9}; +  end 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 +%    <a href="matlab:docsearch('astra_mex_direct' )">astra_mex_data3d</a>. +%------------------------------------------------------------------------ +%------------------------------------------------------------------------ +% 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 diff --git a/matlab/tools/astra_mex_plugin.m b/matlab/tools/astra_mex_plugin.m new file mode 100644 index 0000000..4159365 --- /dev/null +++ b/matlab/tools/astra_mex_plugin.m @@ -0,0 +1,24 @@ +function [varargout] = astra_mex_plugin(varargin) +%------------------------------------------------------------------------ +% Reference page in Help browser +%    <a href="matlab:docsearch('astra_mex_plugin' )">astra_mex_plugin</a>. +%------------------------------------------------------------------------ +%------------------------------------------------------------------------ +% 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_plugin_c(varargin{:}); +    if exist('ans','var') +        varargout{1} = ans; +    end +else +    varargout = cell(1,nargout); +    [varargout{:}] = astra_mex_plugin_c(varargin{:}); +end
\ No newline at end of file diff --git a/python/astra/PyIncludes.pxd b/python/astra/PyIncludes.pxd index 35dea5f..4a4ce43 100644 --- a/python/astra/PyIncludes.pxd +++ b/python/astra/PyIncludes.pxd @@ -62,6 +62,7 @@ cdef extern from "astra/VolumeGeometry2D.h" namespace "astra":  		float32 getWindowMaxX()  		float32 getWindowMaxY()  		Config* getConfiguration() +		bool isEqual(CVolumeGeometry2D*)  cdef extern from "astra/Float32Data2D.h" namespace "astra":  	cdef cppclass CFloat32CustomMemory: @@ -89,6 +90,7 @@ cdef extern from "astra/ProjectionGeometry2D.h" namespace "astra":  		float32 getProjectionAngle(int)  		float32 getDetectorWidth()  		Config* getConfiguration() +		bool isEqual(CProjectionGeometry2D*)  cdef extern from "astra/Float32Data2D.h" namespace "astra::CFloat32Data2D":  	cdef enum TWOEDataType "astra::CFloat32Data2D::EDataType": @@ -224,6 +226,7 @@ cdef extern from "astra/Float32VolumeData3DMemory.h" namespace "astra":  		int getRowCount()  		int getColCount()  		int getSliceCount() +		bool isInitialized() @@ -255,6 +258,7 @@ cdef extern from "astra/Float32ProjectionData3DMemory.h" namespace "astra":  		int getDetectorColCount()  		int getDetectorRowCount()  		int getAngleCount() +		bool isInitialized()  cdef extern from "astra/Float32Data3D.h" namespace "astra":  	cdef cppclass CFloat32Data3D: diff --git a/python/astra/__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/creators.py b/python/astra/creators.py index 68bc8a2..f3474d8 100644 --- a/python/astra/creators.py +++ b/python/astra/creators.py @@ -72,6 +72,10 @@ This method can be called in a number of ways:  ``create_vol_geom(M, N, Z)``:      :returns: A 3D volume geometry of size :math:`M \\times N \\times Z`. +``create_vol_geom(M, N, Z, minx, maxx, miny, maxy, minz, maxz)``: +    :returns: A 3D volume geometry of size :math:`M \\times N \\times Z`, windowed as :math:`minx \\leq x \\leq maxx` and :math:`miny \\leq y \\leq maxy` and :math:`minz \\leq z \\leq maxz` . + +  """      vol_geom = {'option': {}}      # astra_create_vol_geom(row_count) @@ -122,6 +126,17 @@ This method can be called in a number of ways:          vol_geom['GridRowCount'] = varargin[0]          vol_geom['GridColCount'] = varargin[1]          vol_geom['GridSliceCount'] = varargin[2] +    # astra_create_vol_geom(row_count, col_count, slice_count, min_x, max_x, min_y, max_y, min_z, max_z) +    elif len(varargin) == 9: +        vol_geom['GridRowCount'] = varargin[0] +        vol_geom['GridColCount'] = varargin[1] +        vol_geom['GridSliceCount'] = varargin[2] +        vol_geom['option']['WindowMinX'] = varargin[3] +        vol_geom['option']['WindowMaxX'] = varargin[4] +        vol_geom['option']['WindowMinY'] = varargin[5] +        vol_geom['option']['WindowMaxY'] = varargin[6] +        vol_geom['option']['WindowMinZ'] = varargin[7] +        vol_geom['option']['WindowMaxZ'] = varargin[8]      return vol_geom diff --git a/python/astra/data2d_c.pyx b/python/astra/data2d_c.pyx index 4919bf2..801fd8e 100644 --- a/python/astra/data2d_c.pyx +++ b/python/astra/data2d_c.pyx @@ -34,6 +34,9 @@ from cython cimport view  cimport PyData2DManager  from .PyData2DManager cimport CData2DManager +cimport PyProjector2DManager +from .PyProjector2DManager cimport CProjector2DManager +  cimport PyXMLDocument  from .PyXMLDocument cimport XMLDocument @@ -54,6 +57,8 @@ import operator  from six.moves import reduce  cdef CData2DManager * man2d = <CData2DManager * >PyData2DManager.getSingletonPtr() +cdef CProjector2DManager * manProj = <CProjector2DManager * >PyProjector2DManager.getSingletonPtr() +  cdef extern from "CFloat32CustomPython.h":      cdef cppclass CFloat32CustomPython: @@ -164,7 +169,6 @@ def store(i, data):      cdef CFloat32Data2D * pDataObject = getObject(i)      fillDataObject(pDataObject, data) -  def get_geometry(i):      cdef CFloat32Data2D * pDataObject = getObject(i)      cdef CFloat32ProjectionData2D * pDataObject2 @@ -179,6 +183,27 @@ def get_geometry(i):          raise Exception("Not a known data object")      return geom +cdef CProjector2D * getProjector(i) except NULL: +    cdef CProjector2D * proj = manProj.get(i) +    if proj == NULL: +        raise Exception("Projector not initialized.") +    if not proj.isInitialized(): +        raise Exception("Projector not initialized.") +    return proj + +def check_compatible(i, proj_id): +    cdef CProjector2D * proj = getProjector(proj_id) +    cdef CFloat32Data2D * pDataObject = getObject(i) +    cdef CFloat32ProjectionData2D * pDataObject2 +    cdef CFloat32VolumeData2D * pDataObject3 +    if pDataObject.getType() == TWOPROJECTION: +        pDataObject2 = <CFloat32ProjectionData2D * >pDataObject +        return pDataObject2.getGeometry().isEqual(proj.getProjectionGeometry()) +    elif pDataObject.getType() == TWOVOLUME: +        pDataObject3 = <CFloat32VolumeData2D * >pDataObject +        return pDataObject3.getGeometry().isEqual(proj.getVolumeGeometry()) +    else: +        raise Exception("Not a known data object")  def change_geometry(i, geom):      cdef Config *cfg diff --git a/python/astra/experimental.pyx b/python/astra/experimental.pyx new file mode 100644 index 0000000..da27504 --- /dev/null +++ b/python/astra/experimental.pyx @@ -0,0 +1,84 @@ +#----------------------------------------------------------------------- +# Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp +#            2014-2015, CWI, Amsterdam +# +# Contact: astra@uantwerpen.be +# Website: http://sf.net/projects/astra-toolbox +# +# This file is part of the ASTRA Toolbox. +# +# +# The ASTRA Toolbox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# The ASTRA Toolbox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>. +# +#----------------------------------------------------------------------- + +# distutils: language = c++ +# distutils: libraries = astra + +include "config.pxi" + +import six +from .PyIncludes cimport * +from libcpp.vector cimport vector + +cdef extern from "astra/CompositeGeometryManager.h" namespace "astra": +    cdef cppclass CCompositeGeometryManager: +        bool doFP(CProjector3D *, vector[CFloat32VolumeData3DMemory *], vector[CFloat32ProjectionData3DMemory *]) +        bool doBP(CProjector3D *, vector[CFloat32VolumeData3DMemory *], vector[CFloat32ProjectionData3DMemory *]) + +cdef extern from *: +    CFloat32VolumeData3DMemory * dynamic_cast_vol_mem "dynamic_cast<astra::CFloat32VolumeData3DMemory*>" (CFloat32Data3D * ) except NULL +    CFloat32ProjectionData3DMemory * dynamic_cast_proj_mem "dynamic_cast<astra::CFloat32ProjectionData3DMemory*>" (CFloat32Data3D * ) except NULL + +cimport PyProjector3DManager +from .PyProjector3DManager cimport CProjector3DManager +cimport PyData3DManager +from .PyData3DManager cimport CData3DManager + +cdef CProjector3DManager * manProj = <CProjector3DManager * >PyProjector3DManager.getSingletonPtr() +cdef CData3DManager * man3d = <CData3DManager * >PyData3DManager.getSingletonPtr() + +def do_composite(projector_id, vol_ids, proj_ids, t): +    cdef vector[CFloat32VolumeData3DMemory *] vol +    cdef CFloat32VolumeData3DMemory * pVolObject +    cdef CFloat32ProjectionData3DMemory * pProjObject +    for v in vol_ids: +        pVolObject = dynamic_cast_vol_mem(man3d.get(v)) +        if pVolObject == NULL: +            raise Exception("Data object not found") +        if not pVolObject.isInitialized(): +            raise Exception("Data object not initialized properly") +        vol.push_back(pVolObject) +    cdef vector[CFloat32ProjectionData3DMemory *] proj +    for v in proj_ids: +        pProjObject = dynamic_cast_proj_mem(man3d.get(v)) +        if pProjObject == NULL: +            raise Exception("Data object not found") +        if not pProjObject.isInitialized(): +            raise Exception("Data object not initialized properly") +        proj.push_back(pProjObject) +    cdef CCompositeGeometryManager m +    cdef CProjector3D * projector = manProj.get(projector_id) # may be NULL +    if t == "FP": +        if not m.doFP(projector, vol, proj): +            raise Exception("Failed to perform FP") +    else: +        if not m.doBP(projector, vol, proj): +            raise Exception("Failed to perform BP") + +def do_composite_FP(projector_id, vol_ids, proj_ids): +    do_composite(projector_id, vol_ids, proj_ids, "FP") + +def do_composite_BP(projector_id, vol_ids, proj_ids): +    do_composite(projector_id, vol_ids, proj_ids, "BP") diff --git a/python/astra/plugin.py b/python/astra/plugin.py new file mode 100644 index 0000000..3e3528d --- /dev/null +++ b/python/astra/plugin.py @@ -0,0 +1,121 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox is free software: you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation, either version 3 of the License, or +#(at your option) any later version. +# +#The Python interface to the ASTRA Toolbox is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +#along with the Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>. +# +#----------------------------------------------------------------------- + +from . import plugin_c as p +from . import log +from . import data2d +from . import data2d_c +from . import data3d +from . import projector +import inspect +import traceback + +class base(object): + +    def astra_init(self, cfg): +        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 = {} + +        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)))) + +        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) + +class ReconstructionAlgorithm2D(base): + +    def astra_init(self, cfg): +        self.pid = cfg['ProjectorId'] +        self.s = data2d.get_shared(cfg['ProjectionDataId']) +        self.v = data2d.get_shared(cfg['ReconstructionDataId']) +        self.vg = projector.volume_geometry(self.pid) +        self.pg = projector.projection_geometry(self.pid) +        if not data2d_c.check_compatible(cfg['ProjectionDataId'], self.pid): +            raise ValueError("Projection data and projector not compatible") +        if not data2d_c.check_compatible(cfg['ReconstructionDataId'], self.pid): +            raise ValueError("Reconstruction data and projector not compatible") +        super(ReconstructionAlgorithm2D,self).astra_init(cfg) + +class ReconstructionAlgorithm3D(base): + +    def astra_init(self, cfg): +        self.pid = cfg['ProjectorId'] +        self.s = data3d.get_shared(cfg['ProjectionDataId']) +        self.v = data3d.get_shared(cfg['ReconstructionDataId']) +        self.vg = data3d.get_geometry(cfg['ReconstructionDataId']) +        self.pg = data3d.get_geometry(cfg['ProjectionDataId']) +        super(ReconstructionAlgorithm3D,self).astra_init(cfg) + +def register(className): +    """Register plugin with ASTRA. +     +    :param className: Class name or class object to register +    :type className: :class:`str` or :class:`class` +     +    """ +    p.register(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..8d6816b --- /dev/null +++ b/python/astra/plugin_c.pyx @@ -0,0 +1,67 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox is free software: you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation, either version 3 of the License, or +#(at your option) any later version. +# +#The Python interface to the ASTRA Toolbox is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +#along with the Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>. +# +#----------------------------------------------------------------------- +# distutils: language = c++ +# distutils: libraries = astra + +import six +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 className) +        bool registerPlugin(string name, string className) +        bool registerPluginClass(object 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(className, name=None): +    if inspect.isclass(className): +        if name==None: +            fact.registerPluginClass(className) +        else: +            fact.registerPluginClass(six.b(name), className) +    else: +        if name==None: +            fact.registerPlugin(six.b(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 260c308..07727ce 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -29,9 +29,13 @@  cimport numpy as np  import numpy as np  import six +if six.PY3: +    import builtins +else: +    import __builtin__  from libcpp.string cimport string -from libcpp.list cimport list  from libcpp.vector cimport vector +from libcpp.list cimport list  from cython.operator cimport dereference as deref, preincrement as inc  from cpython.version cimport PY_MAJOR_VERSION @@ -91,6 +95,8 @@ cdef void readDict(XMLNode root, _dc):      dc = convert_item(_dc)      for item in dc:          val = dc[item] +        if isinstance(val, __builtins__.list) or isinstance(val, tuple): +            val = np.array(val,dtype=np.float64)          if isinstance(val, np.ndarray):              if val.size == 0:                  break @@ -125,6 +131,8 @@ cdef void readOptions(XMLNode node, dc):          val = dc[item]          if node.hasOption(item):              raise Exception('Duplicate Option: %s' % item) +        if isinstance(val, __builtins__.list) or isinstance(val, tuple): +            val = np.array(val,dtype=np.float64)          if isinstance(val, np.ndarray):              if val.size == 0:                  break diff --git a/python/builder.py b/python/builder.py index cfdb7d1..5322182 100644 --- a/python/builder.py +++ b/python/builder.py @@ -41,6 +41,12 @@ try:          usecuda=True  except KeyError:      pass +try: +    if os.environ['CL'].find('/DASTRA_CUDA')!=-1: +        usecuda=True +except KeyError: +    pass +  cfgToWrite = 'DEF HAVE_CUDA=' + str(usecuda) + "\n"  cfgHasToBeUpdated = True @@ -65,7 +71,7 @@ ext_modules = cythonize("astra/*.pyx", language_level=2)  cmdclass = { 'build_ext': build_ext }  setup (name = 'PyASTRAToolbox', -       version = '1.6', +       version = '1.7',         description = 'Python interface to the ASTRA-Toolbox',         author='D.M. Pelt',         author_email='D.M.Pelt@cwi.nl', diff --git a/python/conda/build.sh b/python/conda/build.sh new file mode 100644 index 0000000..814ea7e --- /dev/null +++ b/python/conda/build.sh @@ -0,0 +1,16 @@ +cd build/linux +./autogen.sh +./configure --with-python --with-cuda=$CUDA_ROOT --prefix=$PREFIX +if [ $MAKEOPTS == '<UNDEFINED>' ] +  then +    MAKEOPTS="" +fi +make $MAKEOPTS install-libraries +make $MAKEOPTS python-root-install +LIBPATH=lib +if [ $ARCH == 64 ] +  then +    LIBPATH+=64 +fi +cp -P $CUDA_ROOT/$LIBPATH/libcudart.so.* $PREFIX/lib +cp -P $CUDA_ROOT/$LIBPATH/libcufft.so.* $PREFIX/lib diff --git a/python/conda/meta.yaml b/python/conda/meta.yaml new file mode 100644 index 0000000..e1adc83 --- /dev/null +++ b/python/conda/meta.yaml @@ -0,0 +1,40 @@ +package: +  name: astra-toolbox +  version: '1.7' + +source: +  git_url: https://github.com/astra-toolbox/astra-toolbox.git +  git_tag: v1.7 + +build: +  number: 0 +  script_env: +    - CUDA_ROOT +    - MAKEOPTS + +test: +  imports: +    - astra + +requirements: +  build: +    - python +    - cython >=0.13 +    - numpy +    - six + +  run: +    - python +    - numpy +    - scipy +    - six + + +about: +  home: http://sourceforge.net/p/astra-toolbox/wiki/Home/ +  license: GPLv3 +  summary: 'The ASTRA Toolbox is a Python toolbox of high-performance GPU primitives for 2D and 3D tomography.' + +# See +# http://docs.continuum.io/conda/build.html for +# more information about meta.yaml diff --git a/python/docSRC/conf.py b/python/docSRC/conf.py index e54bbb8..cc95a80 100644 --- a/python/docSRC/conf.py +++ b/python/docSRC/conf.py @@ -48,9 +48,9 @@ copyright = u'2013, Centrum Wiskunde & Informatica, Amsterdam'  # built documents.  #  # The short X.Y version. -version = '1.6' +version = '1.7'  # The full version, including alpha/beta/rc tags. -release = '1.6' +release = '1.7'  # The language for content autogenerated by Sphinx. Refer to documentation  # for a list of supported languages. 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_experimental_multires.py b/samples/python/s018_experimental_multires.py new file mode 100644 index 0000000..cf38e53 --- /dev/null +++ b/samples/python/s018_experimental_multires.py @@ -0,0 +1,84 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox is free software: you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation, either version 3 of the License, or +#(at your option) any later version. +# +#The Python interface to the ASTRA Toolbox is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +#along with the Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>. +# +#----------------------------------------------------------------------- + +import astra +import numpy as np +from astra.experimental import do_composite_FP + +astra.log.setOutputScreen(astra.log.STDERR, astra.log.DEBUG) + +# low res part (voxels of 4x4x4) +vol_geom1 = astra.create_vol_geom(32, 16, 32, -64, 0, -64, 64, -64, 64) + +# high res part (voxels of 1x1x1) +vol_geom2 = astra.create_vol_geom(128, 64, 128, 0, 64, -64, 64, -64, 64) + + +# Split the output in two parts as well, for demonstration purposes +angles1 = np.linspace(0, np.pi/2, 90, False) +angles2 = np.linspace(np.pi/2, np.pi, 90, False) +proj_geom1 = astra.create_proj_geom('parallel3d', 1.0, 1.0, 128, 192, angles1) +proj_geom2 = astra.create_proj_geom('parallel3d', 1.0, 1.0, 128, 192, angles2) + +# Create a simple hollow cube phantom +cube1 = np.zeros((32,32,16)) +cube1[4:28,4:28,4:16] = 1 + +cube2 = np.zeros((128,128,64)) +cube2[16:112,16:112,0:112] = 1 +cube2[33:97,33:97,4:28] = 0 + +vol1 = astra.data3d.create('-vol', vol_geom1, cube1) +vol2 = astra.data3d.create('-vol', vol_geom2, cube2) + +proj1 = astra.data3d.create('-proj3d', proj_geom1, 0) +proj2 = astra.data3d.create('-proj3d', proj_geom2, 0) + +# The actual geometries don't matter for this composite FP/BP case +projector = astra.create_projector('cuda3d', proj_geom1, vol_geom1) + +do_composite_FP(projector, [vol1, vol2], [proj1, proj2]) + +proj_data1 = astra.data3d.get(proj1) +proj_data2 = astra.data3d.get(proj2) + +# Display a single projection image +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(proj_data1[:,0,:]) +pylab.figure(2) +pylab.imshow(proj_data2[:,0,:]) +pylab.show() + + +# Clean up. Note that GPU memory is tied up in the algorithm object, +# and main RAM in the data objects. +astra.data3d.delete(vol1) +astra.data3d.delete(vol2) +astra.data3d.delete(proj1) +astra.data3d.delete(proj2) +astra.projector3d.delete(projector) diff --git a/samples/python/s018_plugin.py b/samples/python/s018_plugin.py new file mode 100644 index 0000000..31cca95 --- /dev/null +++ b/samples/python/s018_plugin.py @@ -0,0 +1,132 @@ +#----------------------------------------------------------------------- +#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 <http://www.gnu.org/licenses/>. +# +#----------------------------------------------------------------------- + +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. + +    Options: + +    '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'] +        self.sid = cfg['ProjectionDataId'] +        self.rel = rel_factor + +    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 +    # 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')) + +    # 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/CompositeGeometryManager.cpp b/src/CompositeGeometryManager.cpp new file mode 100644 index 0000000..9be4797 --- /dev/null +++ b/src/CompositeGeometryManager.cpp @@ -0,0 +1,993 @@ +/* +----------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +*/ + +#include "astra/CompositeGeometryManager.h" + +#ifdef ASTRA_CUDA + +#include "astra/GeometryUtil3D.h" +#include "astra/VolumeGeometry3D.h" +#include "astra/ConeProjectionGeometry3D.h" +#include "astra/ConeVecProjectionGeometry3D.h" +#include "astra/ParallelProjectionGeometry3D.h" +#include "astra/ParallelVecProjectionGeometry3D.h" +#include "astra/Projector3D.h" +#include "astra/CudaProjector3D.h" +#include "astra/Float32ProjectionData3DMemory.h" +#include "astra/Float32VolumeData3DMemory.h" +#include "astra/Logging.h" + +#include "../cuda/3d/mem3d.h" + +#include <cstring> + +namespace astra { + +// JOB: +//   +// VolumePart +// ProjectionPart +// FP-or-BP +// SET-or-ADD + + +// Running a set of jobs: +// +// [ Assume OUTPUT Parts in a single JobSet don't alias?? ] +// Group jobs by output Part +// One thread per group? + +// Automatically split parts if too large +// Performance model for odd-sized tasks? +// Automatically split parts if not enough tasks to fill available GPUs + + +// Splitting: +// Constraints: +//   number of sub-parts divisible by N +//   max size of sub-parts + +// For splitting on both input and output side: +//   How to divide up memory? (Optimization problem; compute/benchmark) +//   (First approach: 0.5/0.5) + + + +bool CCompositeGeometryManager::splitJobs(TJobSet &jobs, size_t maxSize, int div, TJobSet &split) +{ +	split.clear(); + +	for (TJobSet::const_iterator i = jobs.begin(); i != jobs.end(); ++i) +	{ +		CPart* pOutput = i->first; +		const TJobList &L = i->second; + +		// 1. Split output part +		// 2. Per sub-part: +		//    a. reduce input part +		//    b. split input part +		//    c. create jobs for new (input,output) subparts + +		TPartList splitOutput = pOutput->split(maxSize/3, div); + +		for (TJobList::const_iterator j = L.begin(); j != L.end(); ++j) +		{ +			const SJob &job = *j; + +			for (TPartList::iterator i_out = splitOutput.begin(); +			     i_out != splitOutput.end(); ++i_out) +			{ +				boost::shared_ptr<CPart> outputPart = *i_out; + +				SJob newjob; +				newjob.pOutput = outputPart; +				newjob.eType = j->eType; +				newjob.eMode = j->eMode; +				newjob.pProjector = j->pProjector; + +				CPart* input = job.pInput->reduce(outputPart.get()); + +				if (input->getSize() == 0) { +					ASTRA_DEBUG("Empty input"); +					newjob.eType = SJob::JOB_NOP; +					split[outputPart.get()].push_back(newjob); +					continue; +				} + +				size_t remainingSize = ( maxSize - outputPart->getSize() ) / 2; + +				TPartList splitInput = input->split(remainingSize, 1); +				delete input; +				ASTRA_DEBUG("Input split into %d parts", splitInput.size()); + +				for (TPartList::iterator i_in = splitInput.begin(); +				     i_in != splitInput.end(); ++i_in) +				{ +					newjob.pInput = *i_in; + +					split[outputPart.get()].push_back(newjob); + +					// Second and later (input) parts should always be added to +					// output of first (input) part. +					newjob.eMode = SJob::MODE_ADD; +				} + +			 +			} + +		} +	} + +	return true; +} + +CCompositeGeometryManager::CPart::CPart(const CPart& other) +{ +	eType = other.eType; +	pData = other.pData; +	subX = other.subX; +	subY = other.subY; +	subZ = other.subZ; +} + +CCompositeGeometryManager::CVolumePart::CVolumePart(const CVolumePart& other) + : CPart(other) +{ +	pGeom = other.pGeom->clone(); +} + +CCompositeGeometryManager::CVolumePart::~CVolumePart() +{ +	delete pGeom; +} + +void CCompositeGeometryManager::CVolumePart::getDims(size_t &x, size_t &y, size_t &z) +{ +	if (!pGeom) { +		x = y = z = 0; +		return; +	} + +	x = pGeom->getGridColCount(); +	y = pGeom->getGridRowCount(); +	z = pGeom->getGridSliceCount(); +} + +size_t CCompositeGeometryManager::CPart::getSize() +{ +	size_t x, y, z; +	getDims(x, y, z); +	return x * y * z; +} + + + +CCompositeGeometryManager::CPart* CCompositeGeometryManager::CVolumePart::reduce(const CPart *_other) +{ +	const CProjectionPart *other = dynamic_cast<const CProjectionPart *>(_other); +	assert(other); + +	// TODO: Is 0.5 sufficient? +	double umin = -0.5; +	double umax = other->pGeom->getDetectorColCount() + 0.5; +	double vmin = -0.5; +	double vmax = other->pGeom->getDetectorRowCount() + 0.5; + +	double uu[4]; +	double vv[4]; +	uu[0] = umin; vv[0] = vmin; +	uu[1] = umin; vv[1] = vmax; +	uu[2] = umax; vv[2] = vmin; +	uu[3] = umax; vv[3] = vmax; + +	double pixx = pGeom->getPixelLengthX(); +	double pixy = pGeom->getPixelLengthY(); +	double pixz = pGeom->getPixelLengthZ(); + +	double xmin = pGeom->getWindowMinX() - 0.5 * pixx; +	double xmax = pGeom->getWindowMaxX() + 0.5 * pixx; +	double ymin = pGeom->getWindowMinY() - 0.5 * pixy; +	double ymax = pGeom->getWindowMaxY() + 0.5 * pixy; + +	// NB: Flipped +	double zmax = pGeom->getWindowMinZ() - 2.5 * pixz; +	double zmin = pGeom->getWindowMaxZ() + 2.5 * pixz; + +	// TODO: This isn't as tight as it could be. +	// In particular it won't detect the detector being +	// missed entirely on the u side. + +	for (int i = 0; i < other->pGeom->getProjectionCount(); ++i) { +		for (int j = 0; j < 4; ++j) { +			double px, py, pz; + +			other->pGeom->backprojectPointX(i, uu[j], vv[j], xmin, py, pz); +			//ASTRA_DEBUG("%f %f (%f - %f)", py, pz, ymin, ymax); +			if (pz < zmin) zmin = pz; +			if (pz > zmax) zmax = pz; +			other->pGeom->backprojectPointX(i, uu[j], vv[j], xmax, py, pz); +			//ASTRA_DEBUG("%f %f (%f - %f)", py, pz, ymin, ymax); +			if (pz < zmin) zmin = pz; +			if (pz > zmax) zmax = pz; + +			other->pGeom->backprojectPointY(i, uu[j], vv[j], ymin, px, pz); +			//ASTRA_DEBUG("%f %f (%f - %f)", px, pz, xmin, xmax); +			if (pz < zmin) zmin = pz; +			if (pz > zmax) zmax = pz; +			other->pGeom->backprojectPointY(i, uu[j], vv[j], ymax, px, pz); +			//ASTRA_DEBUG("%f %f (%f - %f)", px, pz, xmin, xmax); +			if (pz < zmin) zmin = pz; +			if (pz > zmax) zmax = pz; +		} +	} + +	//ASTRA_DEBUG("coord extent: %f - %f", zmin, zmax); + +	zmin = (zmin - pixz - pGeom->getWindowMinZ()) / pixz; +	zmax = (zmax + pixz - pGeom->getWindowMinZ()) / pixz; + +	int _zmin = (int)floor(zmin); +	int _zmax = (int)ceil(zmax); + +	//ASTRA_DEBUG("index extent: %d - %d", _zmin, _zmax); + +	if (_zmin < 0) +		_zmin = 0; +	if (_zmax > pGeom->getGridSliceCount()) +		_zmax = pGeom->getGridSliceCount(); + +	if (_zmax <= _zmin) { +		_zmin = _zmax = 0; +	} +	//ASTRA_DEBUG("adjusted extent: %d - %d", _zmin, _zmax); + +	CVolumePart *sub = new CVolumePart(); +	sub->subX = this->subX; +	sub->subY = this->subY; +	sub->subZ = this->subZ + _zmin; +	sub->pData = pData; + +	if (_zmin == _zmax) { +		sub->pGeom = 0; +	} else { +		sub->pGeom = new CVolumeGeometry3D(pGeom->getGridColCount(), +		                                   pGeom->getGridRowCount(), +		                                   _zmax - _zmin, +		                                   pGeom->getWindowMinX(), +		                                   pGeom->getWindowMinY(), +		                                   pGeom->getWindowMinZ() + _zmin * pixz, +		                                   pGeom->getWindowMaxX(), +		                                   pGeom->getWindowMaxY(), +		                                   pGeom->getWindowMinZ() + _zmax * pixz); +	} + +	ASTRA_DEBUG("Reduce volume from %d - %d to %d - %d", this->subZ, this->subZ +  pGeom->getGridSliceCount(), this->subZ + _zmin, this->subZ + _zmax); + +	return sub; +} + + + +static size_t ceildiv(size_t a, size_t b) { +    return (a + b - 1) / b; +} + +static size_t computeVerticalSplit(size_t maxBlock, int div, size_t sliceCount) +{ +    size_t blockSize = maxBlock; +    size_t blockCount = ceildiv(sliceCount, blockSize); + +    // Increase number of blocks to be divisible by div +    size_t divCount = div * ceildiv(blockCount, div); + +    // If divCount is above sqrt(number of slices), then +    // we can't guarantee divisibility by div, but let's try anyway +    if (ceildiv(sliceCount, ceildiv(sliceCount, divCount)) % div == 0) { +        blockCount = divCount; +    } else { +        // If divisibility isn't achievable, we may want to optimize +        // differently. +        // TODO: Figure out how to model and optimize this. +    } + +    // Final adjustment to make blocks more evenly sized +    // (This can't make the blocks larger) +    blockSize = ceildiv(sliceCount, blockCount);  + +    ASTRA_DEBUG("%ld %ld -> %ld * %ld", sliceCount, maxBlock, blockCount, blockSize); + +    assert(blockSize <= maxBlock); +    assert((divCount * divCount > sliceCount) || (blockCount % div) == 0); + +    return blockSize; +} + +template<class V, class P> +static V* getProjectionVectors(const P* geom); + +template<> +SConeProjection* getProjectionVectors(const CConeProjectionGeometry3D* pProjGeom) +{ +	return genConeProjections(pProjGeom->getProjectionCount(), +	                          pProjGeom->getDetectorColCount(), +	                          pProjGeom->getDetectorRowCount(), +	                          pProjGeom->getOriginSourceDistance(), +	                          pProjGeom->getOriginDetectorDistance(), +	                          pProjGeom->getDetectorSpacingX(), +	                          pProjGeom->getDetectorSpacingY(), +	                          pProjGeom->getProjectionAngles()); +} + +template<> +SConeProjection* getProjectionVectors(const CConeVecProjectionGeometry3D* pProjGeom) +{ +	int nth = pProjGeom->getProjectionCount(); + +	SConeProjection* pProjs = new SConeProjection[nth]; +	for (int i = 0; i < nth; ++i) +		pProjs[i] = pProjGeom->getProjectionVectors()[i]; + +	return pProjs; +} + +template<> +SPar3DProjection* getProjectionVectors(const CParallelProjectionGeometry3D* pProjGeom) +{ +	return genPar3DProjections(pProjGeom->getProjectionCount(), +	                           pProjGeom->getDetectorColCount(), +	                           pProjGeom->getDetectorRowCount(), +	                           pProjGeom->getDetectorSpacingX(), +	                           pProjGeom->getDetectorSpacingY(), +	                           pProjGeom->getProjectionAngles()); +} + +template<> +SPar3DProjection* getProjectionVectors(const CParallelVecProjectionGeometry3D* pProjGeom) +{ +	int nth = pProjGeom->getProjectionCount(); + +	SPar3DProjection* pProjs = new SPar3DProjection[nth]; +	for (int i = 0; i < nth; ++i) +		pProjs[i] = pProjGeom->getProjectionVectors()[i]; + +	return pProjs; +} + + +template<class V> +static void translateProjectionVectors(V* pProjs, int count, double dv) +{ +	for (int i = 0; i < count; ++i) { +		pProjs[i].fDetSX += dv * pProjs[i].fDetVX; +		pProjs[i].fDetSY += dv * pProjs[i].fDetVY; +		pProjs[i].fDetSZ += dv * pProjs[i].fDetVZ; +	} +} + + + +static CProjectionGeometry3D* getSubProjectionGeometry(const CProjectionGeometry3D* pProjGeom, int v, int size) +{ +	// First convert to vectors, then translate, then convert into new object + +	const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(pProjGeom); +	const CParallelProjectionGeometry3D* par3dgeom = dynamic_cast<const CParallelProjectionGeometry3D*>(pProjGeom); +	const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(pProjGeom); +	const CConeVecProjectionGeometry3D* conevec3dgeom = dynamic_cast<const CConeVecProjectionGeometry3D*>(pProjGeom); + +	if (conegeom || conevec3dgeom) { +		SConeProjection* pConeProjs; +		if (conegeom) { +			pConeProjs = getProjectionVectors<SConeProjection>(conegeom); +		} else { +			pConeProjs = getProjectionVectors<SConeProjection>(conevec3dgeom); +		} + +		translateProjectionVectors(pConeProjs, pProjGeom->getProjectionCount(), v); + +		CProjectionGeometry3D* ret = new CConeVecProjectionGeometry3D(pProjGeom->getProjectionCount(), +		                                                              size, +		                                                              pProjGeom->getDetectorColCount(), +		                                                              pConeProjs); + + +		delete[] pConeProjs; +		return ret; +	} else { +		assert(par3dgeom || parvec3dgeom); +		SPar3DProjection* pParProjs; +		if (par3dgeom) { +			pParProjs = getProjectionVectors<SPar3DProjection>(par3dgeom); +		} else { +			pParProjs = getProjectionVectors<SPar3DProjection>(parvec3dgeom); +		} + +		translateProjectionVectors(pParProjs, pProjGeom->getProjectionCount(), v); + +		CProjectionGeometry3D* ret = new CParallelVecProjectionGeometry3D(pProjGeom->getProjectionCount(), +		                                                                  size, +		                                                                  pProjGeom->getDetectorColCount(), +		                                                                  pParProjs); + +		delete[] pParProjs; +		return ret; +	} + +} + + + +// split self into sub-parts: +// - each no bigger than maxSize +// - number of sub-parts is divisible by div +// - maybe all approximately the same size? +CCompositeGeometryManager::TPartList CCompositeGeometryManager::CVolumePart::split(size_t maxSize, int div) +{ +	TPartList ret; + +	if (true) { +		// Split in vertical direction only at first, until we figure out +		// a model for splitting in other directions + +		size_t sliceSize = ((size_t) pGeom->getGridColCount()) * pGeom->getGridRowCount(); +		int sliceCount = pGeom->getGridSliceCount(); +		size_t blockSize = computeVerticalSplit(maxSize / sliceSize, div, sliceCount); + +		int rem = sliceCount % blockSize; + +		ASTRA_DEBUG("From %d to %d step %d", -(rem / 2), sliceCount, blockSize); + +		for (int z = -(rem / 2); z < sliceCount; z += blockSize) { +			int newsubZ = z; +			if (newsubZ < 0) newsubZ = 0; +			int endZ = z + blockSize; +			if (endZ > sliceCount) endZ = sliceCount; +			int size = endZ - newsubZ; + +			CVolumePart *sub = new CVolumePart(); +			sub->subX = this->subX; +			sub->subY = this->subY; +			sub->subZ = this->subZ + newsubZ; + +			ASTRA_DEBUG("VolumePart split %d %d %d -> %p", sub->subX, sub->subY, sub->subZ, (void*)sub); + +			double shift = pGeom->getPixelLengthZ() * newsubZ; + +			sub->pData = pData; +			sub->pGeom = new CVolumeGeometry3D(pGeom->getGridColCount(), +			                                   pGeom->getGridRowCount(), +			                                   size, +			                                   pGeom->getWindowMinX(), +			                                   pGeom->getWindowMinY(), +			                                   pGeom->getWindowMinZ() + shift, +			                                   pGeom->getWindowMaxX(), +			                                   pGeom->getWindowMaxY(), +			                                   pGeom->getWindowMinZ() + shift + size * pGeom->getPixelLengthZ()); + +			ret.push_back(boost::shared_ptr<CPart>(sub)); +		} +	} + +	return ret; +} + +CCompositeGeometryManager::CVolumePart* CCompositeGeometryManager::CVolumePart::clone() const +{ +	return new CVolumePart(*this); +} + +CCompositeGeometryManager::CProjectionPart::CProjectionPart(const CProjectionPart& other) + : CPart(other) +{ +	pGeom = other.pGeom->clone(); +} + +CCompositeGeometryManager::CProjectionPart::~CProjectionPart() +{ +	delete pGeom; +} + +void CCompositeGeometryManager::CProjectionPart::getDims(size_t &x, size_t &y, size_t &z) +{ +	if (!pGeom) { +		x = y = z = 0; +		return; +	} + +	x = pGeom->getDetectorColCount(); +	y = pGeom->getProjectionCount(); +	z = pGeom->getDetectorRowCount(); +} + + +CCompositeGeometryManager::CPart* CCompositeGeometryManager::CProjectionPart::reduce(const CPart *_other) +{ +	const CVolumePart *other = dynamic_cast<const CVolumePart *>(_other); +	assert(other); + +	double vmin_g, vmax_g; + +	// reduce self to only cover intersection with projection of VolumePart +	// (Project corners of volume, take bounding box) + +	for (int i = 0; i < pGeom->getProjectionCount(); ++i) { + +		double vol_u[8]; +		double vol_v[8]; + +		double pixx = other->pGeom->getPixelLengthX(); +		double pixy = other->pGeom->getPixelLengthY(); +		double pixz = other->pGeom->getPixelLengthZ(); + +		// TODO: Is 0.5 sufficient? +		double xmin = other->pGeom->getWindowMinX() - 0.5 * pixx; +		double xmax = other->pGeom->getWindowMaxX() + 0.5 * pixx; +		double ymin = other->pGeom->getWindowMinY() - 0.5 * pixy; +		double ymax = other->pGeom->getWindowMaxY() + 0.5 * pixy; +		double zmin = other->pGeom->getWindowMinZ() - 0.5 * pixz; +		double zmax = other->pGeom->getWindowMaxZ() + 0.5 * pixz; + +		pGeom->projectPoint(xmin, ymin, zmin, i, vol_u[0], vol_v[0]); +		pGeom->projectPoint(xmin, ymin, zmax, i, vol_u[1], vol_v[1]); +		pGeom->projectPoint(xmin, ymax, zmin, i, vol_u[2], vol_v[2]); +		pGeom->projectPoint(xmin, ymax, zmax, i, vol_u[3], vol_v[3]); +		pGeom->projectPoint(xmax, ymin, zmin, i, vol_u[4], vol_v[4]); +		pGeom->projectPoint(xmax, ymin, zmax, i, vol_u[5], vol_v[5]); +		pGeom->projectPoint(xmax, ymax, zmin, i, vol_u[6], vol_v[6]); +		pGeom->projectPoint(xmax, ymax, zmax, i, vol_u[7], vol_v[7]); + +		double vmin = vol_v[0]; +		double vmax = vol_v[0]; + +		for (int j = 1; j < 8; ++j) { +			if (vol_v[j] < vmin) +				vmin = vol_v[j]; +			if (vol_v[j] > vmax) +				vmax = vol_v[j]; +		} + +		if (i == 0 || vmin < vmin_g) +			vmin_g = vmin; +		if (i == 0 || vmax > vmax_g) +			vmax_g = vmax; +	} + +	// fprintf(stderr, "v extent: %f %f\n", vmin_g, vmax_g); + +	int _vmin = (int)floor(vmin_g - 1.0f); +	int _vmax = (int)ceil(vmax_g + 1.0f); +	if (_vmin < 0) +		_vmin = 0; +	if (_vmax > pGeom->getDetectorRowCount()) +		_vmax = pGeom->getDetectorRowCount(); + +	if (_vmin >= _vmax) { +		_vmin = _vmax = 0; +	} + +	CProjectionPart *sub = new CProjectionPart(); +	sub->subX = this->subX; +	sub->subY = this->subY; +	sub->subZ = this->subZ + _vmin; + +	sub->pData = pData; + +	if (_vmin == _vmax) { +		sub->pGeom = 0; +	} else { +		sub->pGeom = getSubProjectionGeometry(pGeom, _vmin, _vmax - _vmin); +	} + +	ASTRA_DEBUG("Reduce projection from %d - %d to %d - %d", this->subZ, this->subZ + pGeom->getDetectorRowCount(), this->subZ + _vmin, this->subZ + _vmax); + +	return sub; +} + + +CCompositeGeometryManager::TPartList CCompositeGeometryManager::CProjectionPart::split(size_t maxSize, int div) +{ +	TPartList ret; + +	if (true) { +		// Split in vertical direction only at first, until we figure out +		// a model for splitting in other directions + +		size_t sliceSize = ((size_t) pGeom->getDetectorColCount()) * pGeom->getProjectionCount(); +		int sliceCount = pGeom->getDetectorRowCount(); +		size_t blockSize = computeVerticalSplit(maxSize / sliceSize, div, sliceCount); + +		int rem = sliceCount % blockSize; + +		for (int z = -(rem / 2); z < sliceCount; z += blockSize) { +			int newsubZ = z; +			if (newsubZ < 0) newsubZ = 0; +			int endZ = z + blockSize; +			if (endZ > sliceCount) endZ = sliceCount; +			int size = endZ - newsubZ; + +			CProjectionPart *sub = new CProjectionPart(); +			sub->subX = this->subX; +			sub->subY = this->subY; +			sub->subZ = this->subZ + newsubZ; + +			ASTRA_DEBUG("ProjectionPart split %d %d %d -> %p", sub->subX, sub->subY, sub->subZ, (void*)sub); + +			sub->pData = pData; + +			sub->pGeom = getSubProjectionGeometry(pGeom, newsubZ, size); + +			ret.push_back(boost::shared_ptr<CPart>(sub)); +		} +	} + +	return ret; + +} + +CCompositeGeometryManager::CProjectionPart* CCompositeGeometryManager::CProjectionPart::clone() const +{ +	return new CProjectionPart(*this); +} + + +bool CCompositeGeometryManager::doFP(CProjector3D *pProjector, CFloat32VolumeData3DMemory *pVolData, +                                     CFloat32ProjectionData3DMemory *pProjData) +{ +	ASTRA_DEBUG("CCompositeGeometryManager::doFP"); +	// Create single job for FP +	// Run result + +	CVolumePart *input = new CVolumePart(); +	input->pData = pVolData; +	input->subX = 0; +	input->subY = 0; +	input->subZ = 0; +	input->pGeom = pVolData->getGeometry()->clone(); +	ASTRA_DEBUG("Main FP VolumePart -> %p", (void*)input); + +	CProjectionPart *output = new CProjectionPart(); +	output->pData = pProjData; +	output->subX = 0; +	output->subY = 0; +	output->subZ = 0; +	output->pGeom = pProjData->getGeometry()->clone(); +	ASTRA_DEBUG("Main FP ProjectionPart -> %p", (void*)output); + +	SJob FP; +	FP.pInput = boost::shared_ptr<CPart>(input); +	FP.pOutput = boost::shared_ptr<CPart>(output); +	FP.pProjector = pProjector; +	FP.eType = SJob::JOB_FP; +	FP.eMode = SJob::MODE_SET; + +	TJobList L; +	L.push_back(FP); + +	return doJobs(L); +} + +bool CCompositeGeometryManager::doBP(CProjector3D *pProjector, CFloat32VolumeData3DMemory *pVolData, +                                     CFloat32ProjectionData3DMemory *pProjData) +{ +	ASTRA_DEBUG("CCompositeGeometryManager::doBP"); +	// Create single job for BP +	// Run result + +	CProjectionPart *input = new CProjectionPart(); +	input->pData = pProjData; +	input->subX = 0; +	input->subY = 0; +	input->subZ = 0; +	input->pGeom = pProjData->getGeometry()->clone(); + +	CVolumePart *output = new CVolumePart(); +	output->pData = pVolData; +	output->subX = 0; +	output->subY = 0; +	output->subZ = 0; +	output->pGeom = pVolData->getGeometry()->clone(); + +	SJob BP; +	BP.pInput = boost::shared_ptr<CPart>(input); +	BP.pOutput = boost::shared_ptr<CPart>(output); +	BP.pProjector = pProjector; +	BP.eType = SJob::JOB_BP; +	BP.eMode = SJob::MODE_SET; + +	TJobList L; +	L.push_back(BP); + +	return doJobs(L); +} + +bool CCompositeGeometryManager::doFP(CProjector3D *pProjector, const std::vector<CFloat32VolumeData3DMemory *>& volData, const std::vector<CFloat32ProjectionData3DMemory *>& projData) +{ +	ASTRA_DEBUG("CCompositeGeometryManager::doFP, multi-volume"); + +	std::vector<CFloat32VolumeData3DMemory *>::const_iterator i; +	std::vector<boost::shared_ptr<CPart> > inputs; + +	for (i = volData.begin(); i != volData.end(); ++i) { +		CVolumePart *input = new CVolumePart(); +		input->pData = *i; +		input->subX = 0; +		input->subY = 0; +		input->subZ = 0; +		input->pGeom = (*i)->getGeometry()->clone(); + +		inputs.push_back(boost::shared_ptr<CPart>(input)); +	} + +	std::vector<CFloat32ProjectionData3DMemory *>::const_iterator j; +	std::vector<boost::shared_ptr<CPart> > outputs; + +	for (j = projData.begin(); j != projData.end(); ++j) { +		CProjectionPart *output = new CProjectionPart(); +		output->pData = *j; +		output->subX = 0; +		output->subY = 0; +		output->subZ = 0; +		output->pGeom = (*j)->getGeometry()->clone(); + +		outputs.push_back(boost::shared_ptr<CPart>(output)); +	} + +	std::vector<boost::shared_ptr<CPart> >::iterator i2; +	std::vector<boost::shared_ptr<CPart> >::iterator j2; +	TJobList L; + +	for (i2 = outputs.begin(); i2 != outputs.end(); ++i2) { +		SJob FP; +		FP.eMode = SJob::MODE_SET; +		for (j2 = inputs.begin(); j2 != inputs.end(); ++j2) { +			FP.pInput = *j2; +			FP.pOutput = *i2; +			FP.pProjector = pProjector; +			FP.eType = SJob::JOB_FP; +			L.push_back(FP); + +			// Set first, add rest +			FP.eMode = SJob::MODE_ADD; +		} +	} + +	return doJobs(L); +} + +bool CCompositeGeometryManager::doBP(CProjector3D *pProjector, const std::vector<CFloat32VolumeData3DMemory *>& volData, const std::vector<CFloat32ProjectionData3DMemory *>& projData) +{ +	ASTRA_DEBUG("CCompositeGeometryManager::doBP, multi-volume"); + + +	std::vector<CFloat32VolumeData3DMemory *>::const_iterator i; +	std::vector<boost::shared_ptr<CPart> > outputs; + +	for (i = volData.begin(); i != volData.end(); ++i) { +		CVolumePart *output = new CVolumePart(); +		output->pData = *i; +		output->subX = 0; +		output->subY = 0; +		output->subZ = 0; +		output->pGeom = (*i)->getGeometry()->clone(); + +		outputs.push_back(boost::shared_ptr<CPart>(output)); +	} + +	std::vector<CFloat32ProjectionData3DMemory *>::const_iterator j; +	std::vector<boost::shared_ptr<CPart> > inputs; + +	for (j = projData.begin(); j != projData.end(); ++j) { +		CProjectionPart *input = new CProjectionPart(); +		input->pData = *j; +		input->subX = 0; +		input->subY = 0; +		input->subZ = 0; +		input->pGeom = (*j)->getGeometry()->clone(); + +		inputs.push_back(boost::shared_ptr<CPart>(input)); +	} + +	std::vector<boost::shared_ptr<CPart> >::iterator i2; +	std::vector<boost::shared_ptr<CPart> >::iterator j2; +	TJobList L; + +	for (i2 = outputs.begin(); i2 != outputs.end(); ++i2) { +		SJob BP; +		BP.eMode = SJob::MODE_SET; +		for (j2 = inputs.begin(); j2 != inputs.end(); ++j2) { +			BP.pInput = *j2; +			BP.pOutput = *i2; +			BP.pProjector = pProjector; +			BP.eType = SJob::JOB_BP; +			L.push_back(BP); + +			// Set first, add rest +			BP.eMode = SJob::MODE_ADD; +		} +	} + +	return doJobs(L); +} + + + + +bool CCompositeGeometryManager::doJobs(TJobList &jobs) +{ +	ASTRA_DEBUG("CCompositeGeometryManager::doJobs"); + +	// Sort job list into job set by output part +	TJobSet jobset; + +	for (TJobList::iterator i = jobs.begin(); i != jobs.end(); ++i) { +		jobset[i->pOutput.get()].push_back(*i); +	} + +	size_t 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); +	} +	maxSize = (maxSize * 9) / 10; + +	maxSize /= sizeof(float); +	int div = 1; + +	// TODO: Multi-GPU support + +	// 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()); + +		bool zero = L.begin()->eMode == SJob::MODE_SET; + +		size_t outx, outy, outz; +		output->getDims(outx, outy, outz); + +		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; +		} + + +		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<CCudaProjector3D*>(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<CVolumePart*>(j.pInput.get())); +				assert(dynamic_cast<CProjectionPart*>(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<CVolumePart*>(j.pOutput.get())); +				assert(dynamic_cast<CProjectionPart*>(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); +			} + +			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; +} + + + +} + +#endif diff --git a/src/ConeProjectionGeometry3D.cpp b/src/ConeProjectionGeometry3D.cpp index dd22eba..18f0f8a 100644 --- a/src/ConeProjectionGeometry3D.cpp +++ b/src/ConeProjectionGeometry3D.cpp @@ -29,6 +29,7 @@ $Id$  #include "astra/ConeProjectionGeometry3D.h"  #include "astra/Logging.h" +#include "astra/GeometryUtil3D.h"  #include <boost/lexical_cast.hpp>  #include <cstring> @@ -230,14 +231,14 @@ CVector3D CConeProjectionGeometry3D::getProjectionDirection(int _iProjectionInde  	return ret;  } -void CConeProjectionGeometry3D::projectPoint(float32 fX, float32 fY, float32 fZ, -                                                 int iAngleIndex, -                                                 float32 &fU, float32 &fV) const +void CConeProjectionGeometry3D::projectPoint(double fX, double fY, double fZ, +                                             int iAngleIndex, +                                             double &fU, double &fV) const  {  	ASTRA_ASSERT(iAngleIndex >= 0);  	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); -	float alpha = m_pfProjectionAngles[iAngleIndex]; +	double alpha = m_pfProjectionAngles[iAngleIndex];  	// Project point onto optical axis @@ -245,14 +246,14 @@ void CConeProjectionGeometry3D::projectPoint(float32 fX, float32 fY, float32 fZ,  	// Vector source->origin is (-sin(alpha), cos(alpha))  	// Distance from source, projected on optical axis -	float fD = -sin(alpha) * fX + cos(alpha) * fY + m_fOriginSourceDistance; +	double fD = -sin(alpha) * fX + cos(alpha) * fY + m_fOriginSourceDistance;  	// Scale fZ to detector plane  	fV = detectorOffsetYToRowIndexFloat( (fZ * (m_fOriginSourceDistance + m_fOriginDetectorDistance)) / fD );  	// Orthogonal distance in XY-plane to optical axis -	float fS = cos(alpha) * fX + sin(alpha) * fY; +	double fS = cos(alpha) * fX + sin(alpha) * fY;  	// Scale fS to detector plane  	fU = detectorOffsetXToColIndexFloat( (fS * (m_fOriginSourceDistance + m_fOriginDetectorDistance)) / fD ); @@ -261,5 +262,84 @@ void CConeProjectionGeometry3D::projectPoint(float32 fX, float32 fY, float32 fZ,  } +void CConeProjectionGeometry3D::backprojectPointX(int iAngleIndex, double fU, double fV, +	                               double fX, double &fY, double &fZ) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SConeProjection *projs = genConeProjections(1, m_iDetectorColCount, m_iDetectorRowCount, +	                                           m_fOriginSourceDistance, +	                                           m_fOriginDetectorDistance, +	                                           m_fDetectorSpacingX, m_fDetectorSpacingY, +	                                           &m_pfProjectionAngles[iAngleIndex]); + +	SConeProjection &proj = projs[0]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fX - proj.fSrcX) / (px - proj.fSrcX); + +	fY = proj.fSrcY + a * (py - proj.fSrcY); +	fZ = proj.fSrcZ + a * (pz - proj.fSrcZ); + +	delete[] projs; +} + +void CConeProjectionGeometry3D::backprojectPointY(int iAngleIndex, double fU, double fV, +	                               double fY, double &fX, double &fZ) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SConeProjection *projs = genConeProjections(1, m_iDetectorColCount, m_iDetectorRowCount, +	                                           m_fOriginSourceDistance, +	                                           m_fOriginDetectorDistance, +	                                           m_fDetectorSpacingX, m_fDetectorSpacingY, +	                                           &m_pfProjectionAngles[iAngleIndex]); + +	SConeProjection &proj = projs[0]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fY - proj.fSrcY) / (py - proj.fSrcY); + +	fX = proj.fSrcX + a * (px - proj.fSrcX); +	fZ = proj.fSrcZ + a * (pz - proj.fSrcZ); + +	delete[] projs; +} + +void CConeProjectionGeometry3D::backprojectPointZ(int iAngleIndex, double fU, double fV, +	                               double fZ, double &fX, double &fY) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SConeProjection *projs = genConeProjections(1, m_iDetectorColCount, m_iDetectorRowCount, +	                                           m_fOriginSourceDistance, +	                                           m_fOriginDetectorDistance, +	                                           m_fDetectorSpacingX, m_fDetectorSpacingY, +	                                           &m_pfProjectionAngles[iAngleIndex]); + +	SConeProjection &proj = projs[0]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fZ - proj.fSrcZ) / (pz - proj.fSrcZ); + +	fX = proj.fSrcX + a * (px - proj.fSrcX); +	fY = proj.fSrcY + a * (py - proj.fSrcY); + +	delete[] projs; +} + +  } // end namespace astra diff --git a/src/ConeVecProjectionGeometry3D.cpp b/src/ConeVecProjectionGeometry3D.cpp index 47ed630..86e3bd6 100644 --- a/src/ConeVecProjectionGeometry3D.cpp +++ b/src/ConeVecProjectionGeometry3D.cpp @@ -241,9 +241,9 @@ CVector3D CConeVecProjectionGeometry3D::getProjectionDirection(int _iProjectionI  	return CVector3D(p.fDetSX + (u+0.5)*p.fDetUX + (v+0.5)*p.fDetVX - p.fSrcX, p.fDetSY + (u+0.5)*p.fDetUY + (v+0.5)*p.fDetVY - p.fSrcY, p.fDetSZ + (u+0.5)*p.fDetUZ + (v+0.5)*p.fDetVZ - p.fSrcZ);  } -void CConeVecProjectionGeometry3D::projectPoint(float32 fX, float32 fY, float32 fZ, +void CConeVecProjectionGeometry3D::projectPoint(double fX, double fY, double fZ,                                                   int iAngleIndex, -                                                 float32 &fU, float32 &fV) const +                                                 double &fU, double &fV) const  {  	ASTRA_ASSERT(iAngleIndex >= 0);  	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); @@ -262,6 +262,60 @@ void CConeVecProjectionGeometry3D::projectPoint(float32 fX, float32 fY, float32  } +void CConeVecProjectionGeometry3D::backprojectPointX(int iAngleIndex, double fU, double fV, +	                               double fX, double &fY, double &fZ) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SConeProjection &proj = m_pProjectionAngles[iAngleIndex]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fX - proj.fSrcX) / (px - proj.fSrcX); + +	fY = proj.fSrcY + a * (py - proj.fSrcY); +	fZ = proj.fSrcZ + a * (pz - proj.fSrcZ); +} + +void CConeVecProjectionGeometry3D::backprojectPointY(int iAngleIndex, double fU, double fV, +	                               double fY, double &fX, double &fZ) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SConeProjection &proj = m_pProjectionAngles[iAngleIndex]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fY - proj.fSrcY) / (py - proj.fSrcY); + +	fX = proj.fSrcX + a * (px - proj.fSrcX); +	fZ = proj.fSrcZ + a * (pz - proj.fSrcZ); +} + +void CConeVecProjectionGeometry3D::backprojectPointZ(int iAngleIndex, double fU, double fV, +	                               double fZ, double &fX, double &fY) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SConeProjection &proj = m_pProjectionAngles[iAngleIndex]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fZ - proj.fSrcZ) / (pz - proj.fSrcZ); + +	fX = proj.fSrcX + a * (px - proj.fSrcX); +	fY = proj.fSrcY + a * (py - proj.fSrcY); +} +  //----------------------------------------------------------------------------------------  bool CConeVecProjectionGeometry3D::_check() diff --git a/src/CudaBackProjectionAlgorithm.cpp b/src/CudaBackProjectionAlgorithm.cpp index 365e058..a73f895 100644 --- a/src/CudaBackProjectionAlgorithm.cpp +++ b/src/CudaBackProjectionAlgorithm.cpp @@ -76,10 +76,9 @@ bool CCudaBackProjectionAlgorithm::initialize(const Config& _cfg)  // Initialize - C++  bool CCudaBackProjectionAlgorithm::initialize(CProjector2D* _pProjector,                                       CFloat32ProjectionData2D* _pSinogram,  -                                     CFloat32VolumeData2D* _pReconstruction, -                                     int _iGPUindex, int _iPixelSuperSampling) +                                     CFloat32VolumeData2D* _pReconstruction)  { -	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction, _iGPUindex, 1, _iPixelSuperSampling); +	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction);  	if (!m_bIsInitialized)  		return false; diff --git a/src/CudaBackProjectionAlgorithm3D.cpp b/src/CudaBackProjectionAlgorithm3D.cpp index e8e0433..ce8e111 100644 --- a/src/CudaBackProjectionAlgorithm3D.cpp +++ b/src/CudaBackProjectionAlgorithm3D.cpp @@ -37,6 +37,9 @@ $Id$  #include "astra/ParallelProjectionGeometry3D.h"  #include "astra/ParallelVecProjectionGeometry3D.h"  #include "astra/ConeVecProjectionGeometry3D.h" +#include "astra/CompositeGeometryManager.h" + +#include "astra/Logging.h"  #include "../cuda/3d/astra3d.h" @@ -87,6 +90,24 @@ bool CCudaBackProjectionAlgorithm3D::_check()  }  //--------------------------------------------------------------------------------------- +void CCudaBackProjectionAlgorithm3D::initializeFromProjector() +{ +	m_iVoxelSuperSampling = 1; +	m_iGPUIndex = -1; + +	CCudaProjector3D* pCudaProjector = dynamic_cast<CCudaProjector3D*>(m_pProjector); +	if (!pCudaProjector) { +		if (m_pProjector) { +			ASTRA_WARN("non-CUDA Projector3D passed to BP3D_CUDA"); +		} +	} else { +		m_iVoxelSuperSampling = pCudaProjector->getVoxelSuperSampling(); +		m_iGPUIndex = pCudaProjector->getGPUIndex(); +	} + +} + +//---------------------------------------------------------------------------------------  // Initialize - Config  bool CCudaBackProjectionAlgorithm3D::initialize(const Config& _cfg)  { @@ -103,32 +124,21 @@ bool CCudaBackProjectionAlgorithm3D::initialize(const Config& _cfg)  		return false;  	} -	CCudaProjector3D* pCudaProjector = 0; -	pCudaProjector = dynamic_cast<CCudaProjector3D*>(m_pProjector); -	if (!pCudaProjector) { -		// TODO: Report -	} +	initializeFromProjector(); -	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); -	CC.markOptionParsed("GPUindex"); - - -	m_iVoxelSuperSampling = 1; -	if (pCudaProjector) -		m_iVoxelSuperSampling = pCudaProjector->getVoxelSuperSampling(); +	// Deprecated options  	m_iVoxelSuperSampling = (int)_cfg.self.getOptionNumerical("VoxelSuperSampling", m_iVoxelSuperSampling); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", m_iGPUIndex); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex);  	CC.markOptionParsed("VoxelSuperSampling"); +	CC.markOptionParsed("GPUIndex"); +	if (!_cfg.self.hasOption("GPUIndex")) +		CC.markOptionParsed("GPUindex"); -	CFloat32ProjectionData3DMemory* pSinoMem = dynamic_cast<CFloat32ProjectionData3DMemory*>(m_pSinogram); -	ASTRA_ASSERT(pSinoMem); -	const CProjectionGeometry3D* projgeom = pSinoMem->getGeometry(); -const CParallelProjectionGeometry3D* par3dgeom = dynamic_cast<const CParallelProjectionGeometry3D*>(projgeom); -	const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(projgeom); -	if (parvec3dgeom || par3dgeom) { -		// This option is only supported for Par3D currently -		m_bSIRTWeighting = _cfg.self.getOptionBool("SIRTWeighting", false); -		CC.markOptionParsed("SIRTWeighting"); -	} + + +	m_bSIRTWeighting = _cfg.self.getOptionBool("SIRTWeighting", false); +	CC.markOptionParsed("SIRTWeighting");  	// success  	m_bIsInitialized = _check(); @@ -151,6 +161,8 @@ bool CCudaBackProjectionAlgorithm3D::initialize(CProjector3D* _pProjector,  	m_pSinogram = _pSinogram;  	m_pReconstruction = _pReconstruction; +	initializeFromProjector(); +  	// success  	m_bIsInitialized = _check();  	return m_bIsInitialized; @@ -184,88 +196,24 @@ void CCudaBackProjectionAlgorithm3D::run(int _iNrIterations)  	ASTRA_ASSERT(pReconMem);  	const CProjectionGeometry3D* projgeom = pSinoMem->getGeometry(); -	const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(projgeom); -	const CParallelProjectionGeometry3D* par3dgeom = dynamic_cast<const CParallelProjectionGeometry3D*>(projgeom); -	const CConeVecProjectionGeometry3D* conevecgeom = dynamic_cast<const CConeVecProjectionGeometry3D*>(projgeom); -	const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(projgeom);  	const CVolumeGeometry3D& volgeom = *pReconMem->getGeometry(); -	if (conegeom) { -		astraCudaConeBP(pReconMem->getData(), pSinoMem->getDataConst(), -		                volgeom.getGridColCount(), -		                volgeom.getGridRowCount(), -		                volgeom.getGridSliceCount(), -		                conegeom->getProjectionCount(), -		                conegeom->getDetectorColCount(), -		                conegeom->getDetectorRowCount(), -		                conegeom->getOriginSourceDistance(), -		                conegeom->getOriginDetectorDistance(), -		                conegeom->getDetectorSpacingX(), -		                conegeom->getDetectorSpacingY(), -		                conegeom->getProjectionAngles(), -		                m_iGPUIndex, m_iVoxelSuperSampling); -	} else if (par3dgeom) { -		if (!m_bSIRTWeighting) { -			astraCudaPar3DBP(pReconMem->getData(), pSinoMem->getDataConst(), -			                 volgeom.getGridColCount(), -			                 volgeom.getGridRowCount(), -			                 volgeom.getGridSliceCount(), -			                 par3dgeom->getProjectionCount(), -			                 par3dgeom->getDetectorColCount(), -			                 par3dgeom->getDetectorRowCount(), -			                 par3dgeom->getDetectorSpacingX(), -			                 par3dgeom->getDetectorSpacingY(), -			                 par3dgeom->getProjectionAngles(), -			                 m_iGPUIndex, m_iVoxelSuperSampling); -		} else { -			astraCudaPar3DBP_SIRTWeighted(pReconMem->getData(), -			                 pSinoMem->getDataConst(), -			                 volgeom.getGridColCount(), -			                 volgeom.getGridRowCount(), -			                 volgeom.getGridSliceCount(), -			                 par3dgeom->getProjectionCount(), -			                 par3dgeom->getDetectorColCount(), -			                 par3dgeom->getDetectorRowCount(), -			                 par3dgeom->getDetectorSpacingX(), -			                 par3dgeom->getDetectorSpacingY(), -			                 par3dgeom->getProjectionAngles(), -			                 m_iGPUIndex, m_iVoxelSuperSampling); -		} -	} else if (parvec3dgeom) { -		if (!m_bSIRTWeighting) { -			astraCudaPar3DBP(pReconMem->getData(), pSinoMem->getDataConst(), -			                 volgeom.getGridColCount(), -			                 volgeom.getGridRowCount(), -			                 volgeom.getGridSliceCount(), -			                 parvec3dgeom->getProjectionCount(), -			                 parvec3dgeom->getDetectorColCount(), -			                 parvec3dgeom->getDetectorRowCount(), -			                 parvec3dgeom->getProjectionVectors(), -			                 m_iGPUIndex, m_iVoxelSuperSampling); -		} else { -			astraCudaPar3DBP_SIRTWeighted(pReconMem->getData(), -			                 pSinoMem->getDataConst(), -			                 volgeom.getGridColCount(), -			                 volgeom.getGridRowCount(), -			                 volgeom.getGridSliceCount(), -			                 parvec3dgeom->getProjectionCount(), -			                 parvec3dgeom->getDetectorColCount(), -			                 parvec3dgeom->getDetectorRowCount(), -			                 parvec3dgeom->getProjectionVectors(), -			                 m_iGPUIndex, m_iVoxelSuperSampling); -		} -	} else if (conevecgeom) { -		astraCudaConeBP(pReconMem->getData(), pSinoMem->getDataConst(), -		                volgeom.getGridColCount(), -		                volgeom.getGridRowCount(), -		                volgeom.getGridSliceCount(), -		                conevecgeom->getProjectionCount(), -		                conevecgeom->getDetectorColCount(), -		                conevecgeom->getDetectorRowCount(), -		                conevecgeom->getProjectionVectors(), -		                m_iGPUIndex, m_iVoxelSuperSampling); +	if (m_bSIRTWeighting) { +		astraCudaBP_SIRTWeighted(pReconMem->getData(), +		                         pSinoMem->getDataConst(), +		                         &volgeom, projgeom, +		                         m_iGPUIndex, m_iVoxelSuperSampling);  	} else { -		ASTRA_ASSERT(false); + +#if 1 +		CCompositeGeometryManager cgm; + +		cgm.doBP(m_pProjector, pReconMem, pSinoMem); +#else +		astraCudaBP(pReconMem->getData(), pSinoMem->getDataConst(), +		            &volgeom, projgeom, +		            m_iGPUIndex, m_iVoxelSuperSampling); +#endif  	}  } diff --git a/src/CudaCglsAlgorithm.cpp b/src/CudaCglsAlgorithm.cpp index 0cedff6..9dd4f78 100644 --- a/src/CudaCglsAlgorithm.cpp +++ b/src/CudaCglsAlgorithm.cpp @@ -77,11 +77,9 @@ bool CCudaCglsAlgorithm::initialize(const Config& _cfg)  // Initialize - C++  bool CCudaCglsAlgorithm::initialize(CProjector2D* _pProjector,                                      CFloat32ProjectionData2D* _pSinogram,  -                                    CFloat32VolumeData2D* _pReconstruction, -                                    int _iGPUindex, int _iDetectorSuperSampling, -                                    int _iPixelSuperSampling) +                                    CFloat32VolumeData2D* _pReconstruction)  { -	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction, _iGPUindex, _iDetectorSuperSampling, _iPixelSuperSampling); +	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction);  	if (!m_bIsInitialized)  		return false; diff --git a/src/CudaCglsAlgorithm3D.cpp b/src/CudaCglsAlgorithm3D.cpp index f527dc5..abc18d1 100644 --- a/src/CudaCglsAlgorithm3D.cpp +++ b/src/CudaCglsAlgorithm3D.cpp @@ -37,6 +37,8 @@ $Id$  #include "astra/ParallelVecProjectionGeometry3D.h"  #include "astra/ConeVecProjectionGeometry3D.h" +#include "astra/Logging.h" +  #include "../cuda/3d/astra3d.h"  using namespace std; @@ -90,6 +92,26 @@ bool CCudaCglsAlgorithm3D::_check()  }  //--------------------------------------------------------------------------------------- +void CCudaCglsAlgorithm3D::initializeFromProjector() +{ +	m_iVoxelSuperSampling = 1; +	m_iDetectorSuperSampling = 1; +	m_iGPUIndex = -1; + +	CCudaProjector3D* pCudaProjector = dynamic_cast<CCudaProjector3D*>(m_pProjector); +	if (!pCudaProjector) { +		if (m_pProjector) { +			ASTRA_WARN("non-CUDA Projector3D passed to CGLS3D_CUDA"); +		} +	} else { +		m_iVoxelSuperSampling = pCudaProjector->getVoxelSuperSampling(); +		m_iDetectorSuperSampling = pCudaProjector->getDetectorSuperSampling(); +		m_iGPUIndex = pCudaProjector->getGPUIndex(); +	} + +} + +//---------------------------------------------------------------------------------------  // Initialize - Config  bool CCudaCglsAlgorithm3D::initialize(const Config& _cfg)  { @@ -107,27 +129,20 @@ bool CCudaCglsAlgorithm3D::initialize(const Config& _cfg)  		return false;  	} -	CCudaProjector3D* pCudaProjector = 0; -	pCudaProjector = dynamic_cast<CCudaProjector3D*>(m_pProjector); -	if (!pCudaProjector) { -		// TODO: Report -	} +	initializeFromProjector(); -	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); -	CC.markOptionParsed("GPUindex"); - -	m_iVoxelSuperSampling = 1; -	m_iDetectorSuperSampling = 1; -	if (pCudaProjector) { -		// New interface -		m_iVoxelSuperSampling = pCudaProjector->getVoxelSuperSampling(); -		m_iDetectorSuperSampling = pCudaProjector->getDetectorSuperSampling(); -	}  	// Deprecated options  	m_iVoxelSuperSampling = (int)_cfg.self.getOptionNumerical("VoxelSuperSampling", m_iVoxelSuperSampling);  	m_iDetectorSuperSampling = (int)_cfg.self.getOptionNumerical("DetectorSuperSampling", m_iDetectorSuperSampling); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", m_iGPUIndex); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex);  	CC.markOptionParsed("VoxelSuperSampling");  	CC.markOptionParsed("DetectorSuperSampling"); +	CC.markOptionParsed("GPUIndex"); +	if (!_cfg.self.hasOption("GPUIndex")) +		CC.markOptionParsed("GPUindex"); + +  	m_pCgls = new AstraCGLS3d(); @@ -155,6 +170,8 @@ bool CCudaCglsAlgorithm3D::initialize(CProjector3D* _pProjector,  	m_pSinogram = _pSinogram;  	m_pReconstruction = _pReconstruction; +	initializeFromProjector(); +  	m_pCgls = new AstraCGLS3d;  	m_bAstraCGLSInit = false; @@ -187,9 +204,6 @@ void CCudaCglsAlgorithm3D::run(int _iNrIterations)  	ASTRA_ASSERT(m_bIsInitialized);  	const CProjectionGeometry3D* projgeom = m_pSinogram->getGeometry(); -	const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(projgeom); -	const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(projgeom); -	const CConeVecProjectionGeometry3D* conevec3dgeom = dynamic_cast<const CConeVecProjectionGeometry3D*>(projgeom);  	const CVolumeGeometry3D& volgeom = *m_pReconstruction->getGeometry();  	bool ok = true; @@ -198,41 +212,7 @@ void CCudaCglsAlgorithm3D::run(int _iNrIterations)  		ok &= m_pCgls->setGPUIndex(m_iGPUIndex); -		ok &= m_pCgls->setReconstructionGeometry(volgeom.getGridColCount(), -		                                         volgeom.getGridRowCount(), -		                                         volgeom.getGridSliceCount()); -/* -                                  unsigned int iProjAngles, -                                  unsigned int iProjU, -                                  unsigned int iProjV, -                                  float fOriginSourceDistance, -                                  float fOriginDetectorDistance, -                                  float fDetUSize, -                                  float fDetVSize, -                                  const float *pfAngles) -*/ -		if (conegeom) { -			ok &= m_pCgls->setConeGeometry(conegeom->getProjectionCount(), -			                               conegeom->getDetectorColCount(), -			                               conegeom->getDetectorRowCount(), -			                               conegeom->getOriginSourceDistance(), -			                               conegeom->getOriginDetectorDistance(), -			                               conegeom->getDetectorSpacingX(), -			                               conegeom->getDetectorSpacingY(), -			                               conegeom->getProjectionAngles()); -		} else if (parvec3dgeom) { -			ok &= m_pCgls->setPar3DGeometry(parvec3dgeom->getProjectionCount(), -			                                parvec3dgeom->getDetectorColCount(), -			                                parvec3dgeom->getDetectorRowCount(), -			                                parvec3dgeom->getProjectionVectors()); -		} else if (conevec3dgeom) { -			ok &= m_pCgls->setConeGeometry(conevec3dgeom->getProjectionCount(), -			                               conevec3dgeom->getDetectorColCount(), -			                               conevec3dgeom->getDetectorRowCount(), -			                               conevec3dgeom->getProjectionVectors()); -		} else { -			ASTRA_ASSERT(false); -		} +		ok &= m_pCgls->setGeometry(&volgeom, projgeom);  		ok &= m_pCgls->enableSuperSampling(m_iVoxelSuperSampling, m_iDetectorSuperSampling); diff --git a/src/CudaEMAlgorithm.cpp b/src/CudaEMAlgorithm.cpp index 5c71f3d..d0afd80 100644 --- a/src/CudaEMAlgorithm.cpp +++ b/src/CudaEMAlgorithm.cpp @@ -76,11 +76,9 @@ bool CCudaEMAlgorithm::initialize(const Config& _cfg)  // Initialize - C++  bool CCudaEMAlgorithm::initialize(CProjector2D* _pProjector,                                       CFloat32ProjectionData2D* _pSinogram,  -                                     CFloat32VolumeData2D* _pReconstruction, -                                     int _iGPUindex, int _iDetectorSuperSampling, -                                     int _iPixelSuperSampling) +                                     CFloat32VolumeData2D* _pReconstruction)  { -	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction, _iGPUindex, _iDetectorSuperSampling, _iPixelSuperSampling); +	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction);  	if (!m_bIsInitialized)  		return false; diff --git a/src/CudaFDKAlgorithm3D.cpp b/src/CudaFDKAlgorithm3D.cpp index 667d926..1316daa 100644 --- a/src/CudaFDKAlgorithm3D.cpp +++ b/src/CudaFDKAlgorithm3D.cpp @@ -35,6 +35,8 @@ $Id$  #include "astra/CudaProjector3D.h"  #include "astra/ConeProjectionGeometry3D.h" +#include "astra/Logging.h" +  #include "../cuda/3d/astra3d.h"  using namespace std; @@ -85,6 +87,24 @@ bool CCudaFDKAlgorithm3D::_check()  }  //--------------------------------------------------------------------------------------- +void CCudaFDKAlgorithm3D::initializeFromProjector() +{ +	m_iVoxelSuperSampling = 1; +	m_iGPUIndex = -1; + +	CCudaProjector3D* pCudaProjector = dynamic_cast<CCudaProjector3D*>(m_pProjector); +	if (!pCudaProjector) { +		if (m_pProjector) { +			ASTRA_WARN("non-CUDA Projector3D passed to FDK_CUDA"); +		} +	} else { +		m_iVoxelSuperSampling = pCudaProjector->getVoxelSuperSampling(); +		m_iGPUIndex = pCudaProjector->getGPUIndex(); +	} + +} + +//---------------------------------------------------------------------------------------  // Initialize - Config  bool CCudaFDKAlgorithm3D::initialize(const Config& _cfg)  { @@ -101,20 +121,18 @@ bool CCudaFDKAlgorithm3D::initialize(const Config& _cfg)  		return false;  	} -	CCudaProjector3D* pCudaProjector = 0; -	pCudaProjector = dynamic_cast<CCudaProjector3D*>(m_pProjector); -	if (!pCudaProjector) { -		// TODO: Report -	} - -	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); -	CC.markOptionParsed("GPUindex"); +	initializeFromProjector(); -	m_iVoxelSuperSampling = 1; -	if (pCudaProjector) -		m_iVoxelSuperSampling = pCudaProjector->getVoxelSuperSampling(); +	// Deprecated options  	m_iVoxelSuperSampling = (int)_cfg.self.getOptionNumerical("VoxelSuperSampling", m_iVoxelSuperSampling); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", m_iGPUIndex); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex);  	CC.markOptionParsed("VoxelSuperSampling"); +	CC.markOptionParsed("GPUIndex"); +	if (!_cfg.self.hasOption("GPUIndex")) +		CC.markOptionParsed("GPUindex"); + +  	m_bShortScan = _cfg.self.getOptionBool("ShortScan", false);  	CC.markOptionParsed("ShortScan"); @@ -182,17 +200,7 @@ void CCudaFDKAlgorithm3D::run(int _iNrIterations)  	bool ok = true;  	ok = astraCudaFDK(pReconMem->getData(), pSinoMem->getDataConst(), -	                  volgeom.getGridColCount(), -	                  volgeom.getGridRowCount(), -	                  volgeom.getGridSliceCount(), -	                  conegeom->getProjectionCount(), -	                  conegeom->getDetectorColCount(), -	                  conegeom->getDetectorRowCount(), -	                  conegeom->getOriginSourceDistance(), -	                  conegeom->getOriginDetectorDistance(), -	                  conegeom->getDetectorSpacingX(), -	                  conegeom->getDetectorSpacingY(), -	                  conegeom->getProjectionAngles(), +	                  &volgeom, conegeom,  	                  m_bShortScan, m_iGPUIndex, m_iVoxelSuperSampling);  	ASTRA_ASSERT(ok); diff --git a/src/CudaFilteredBackProjectionAlgorithm.cpp b/src/CudaFilteredBackProjectionAlgorithm.cpp index aac96d6..bcd70c4 100644 --- a/src/CudaFilteredBackProjectionAlgorithm.cpp +++ b/src/CudaFilteredBackProjectionAlgorithm.cpp @@ -67,6 +67,24 @@ CCudaFilteredBackProjectionAlgorithm::~CCudaFilteredBackProjectionAlgorithm()  	}  } +void CCudaFilteredBackProjectionAlgorithm::initializeFromProjector() +{ +	m_iPixelSuperSampling = 1; +	m_iGPUIndex = -1; + +	// Projector +	CCudaProjector2D* pCudaProjector = dynamic_cast<CCudaProjector2D*>(m_pProjector); +	if (!pCudaProjector) { +		if (m_pProjector) { +			ASTRA_WARN("non-CUDA Projector2D passed to FBP_CUDA"); +		} +	} else { +		m_iPixelSuperSampling = pCudaProjector->getVoxelSuperSampling(); +		m_iGPUIndex = pCudaProjector->getGPUIndex(); +	} + +} +  bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)  {  	ASTRA_ASSERT(_cfg.self); @@ -163,35 +181,30 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)  	}  	CC.markNodeParsed("FilterD"); // TODO: Only for some types! -	// GPU number -	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); -	CC.markOptionParsed("GPUindex"); - -	m_iPixelSuperSampling = 1; -	if (pCudaProjector) { -		// New interface -		m_iPixelSuperSampling = pCudaProjector->getVoxelSuperSampling(); -	} -	// Deprecated options -	m_iPixelSuperSampling = (int)_cfg.self.getOptionNumerical("PixelSuperSampling", m_iPixelSuperSampling); -	CC.markOptionParsed("PixelSuperSampling"); - -  	// Fan beam short scan mode  	if (m_pSinogram && dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pSinogram->getGeometry())) {  		m_bShortScan = (int)_cfg.self.getOptionBool("ShortScan", false);  		CC.markOptionParsed("ShortScan");  	} +	initializeFromProjector(); + +	// Deprecated options +	m_iPixelSuperSampling = (int)_cfg.self.getOptionNumerical("PixelSuperSampling", m_iPixelSuperSampling); +	CC.markOptionParsed("PixelSuperSampling"); +	// GPU number +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex); +	CC.markOptionParsed("GPUIndex"); +	if (!_cfg.self.hasOption("GPUIndex")) +		CC.markOptionParsed("GPUindex");  	m_pFBP = new AstraFBP;  	m_bAstraFBPInit = false; -	// success -	m_bIsInitialized = true; -	return m_bIsInitialized; +	return check();  }  bool CCudaFilteredBackProjectionAlgorithm::initialize(CFloat32ProjectionData2D * _pSinogram, CFloat32VolumeData2D * _pReconstruction, E_FBPFILTER _eFilter, const float * _pfFilter /* = NULL */, int _iFilterWidth /* = 0 */, int _iGPUIndex /* = 0 */, float _fFilterParameter /* = -1.0f */) @@ -241,7 +254,7 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(CFloat32ProjectionData2D *  	m_fFilterParameter = _fFilterParameter; -	return m_bIsInitialized; +	return check();  }  void CCudaFilteredBackProjectionAlgorithm::run(int _iNrIterations /* = 0 */) @@ -361,7 +374,7 @@ bool CCudaFilteredBackProjectionAlgorithm::check()  	ASTRA_CONFIG_CHECK(m_pReconstruction->isInitialized(), "FBP_CUDA", "Reconstruction Data Object Not Initialized.");  	// check gpu index -	ASTRA_CONFIG_CHECK(m_iGPUIndex >= -1, "FBP_CUDA", "GPUIndex must be a non-negative integer."); +	ASTRA_CONFIG_CHECK(m_iGPUIndex >= -1, "FBP_CUDA", "GPUIndex must be a non-negative integer or -1.");  	// check pixel supersampling  	ASTRA_CONFIG_CHECK(m_iPixelSuperSampling >= 0, "FBP_CUDA", "PixelSuperSampling must be a non-negative integer."); diff --git a/src/CudaForwardProjectionAlgorithm.cpp b/src/CudaForwardProjectionAlgorithm.cpp index b382f2e..9ca13ae 100644 --- a/src/CudaForwardProjectionAlgorithm.cpp +++ b/src/CudaForwardProjectionAlgorithm.cpp @@ -38,8 +38,11 @@ $Id$  #include <boost/lexical_cast.hpp>  #include "astra/AstraObjectManager.h" +#include "astra/ParallelProjectionGeometry2D.h"  #include "astra/FanFlatProjectionGeometry2D.h"  #include "astra/FanFlatVecProjectionGeometry2D.h" +#include "astra/Float32ProjectionData2D.h" +#include "astra/Float32VolumeData2D.h"  #include "astra/CudaProjector2D.h"  #include "astra/Logging.h" @@ -66,6 +69,24 @@ CCudaForwardProjectionAlgorithm::~CCudaForwardProjectionAlgorithm()  }  //--------------------------------------------------------------------------------------- +void CCudaForwardProjectionAlgorithm::initializeFromProjector() +{ +	m_iDetectorSuperSampling = 1; +	m_iGPUIndex = -1; + +	// Projector +	CCudaProjector2D* pCudaProjector = dynamic_cast<CCudaProjector2D*>(m_pProjector); +	if (!pCudaProjector) { +		if (m_pProjector) { +			ASTRA_WARN("non-CUDA Projector2D passed to FP_CUDA"); +		} +	} else { +		m_iDetectorSuperSampling = pCudaProjector->getDetectorSuperSampling(); +		m_iGPUIndex = pCudaProjector->getGPUIndex(); +	} +} + +//---------------------------------------------------------------------------------------  // Initialize - Config  bool CCudaForwardProjectionAlgorithm::initialize(const Config& _cfg)  { @@ -74,14 +95,9 @@ bool CCudaForwardProjectionAlgorithm::initialize(const Config& _cfg)  	// Projector  	XMLNode node = _cfg.self.getSingleNode("ProjectorId"); -	CCudaProjector2D* pCudaProjector = 0;  	if (node) {  		int id = boost::lexical_cast<int>(node.getContent()); -		CProjector2D *projector = CProjector2DManager::getSingleton().get(id); -		pCudaProjector = dynamic_cast<CCudaProjector2D*>(projector); -		if (!pCudaProjector) { -			ASTRA_WARN("non-CUDA Projector2D passed to FP_CUDA"); -		} +		m_pProjector = CProjector2DManager::getSingleton().get(id);  	}  	CC.markNodeParsed("ProjectorId"); @@ -101,22 +117,18 @@ bool CCudaForwardProjectionAlgorithm::initialize(const Config& _cfg)  	m_pVolume = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id));  	CC.markNodeParsed("VolumeDataId"); +	initializeFromProjector(); + +	// Deprecated options +	m_iDetectorSuperSampling = (int)_cfg.self.getOptionNumerical("DetectorSuperSampling", m_iDetectorSuperSampling); +	CC.markOptionParsed("DetectorSuperSampling");  	// GPU number  	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1);  	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex); -	CC.markOptionParsed("GPUindex"); -	if (!_cfg.self.hasOption("GPUindex")) -		CC.markOptionParsed("GPUIndex"); +	CC.markOptionParsed("GPUIndex"); +	if (!_cfg.self.hasOption("GPUIndex")) +		CC.markOptionParsed("GPUindex"); -	// Detector supersampling factor -	m_iDetectorSuperSampling = 1; -	if (pCudaProjector) { -		// New interface -		m_iDetectorSuperSampling = pCudaProjector->getDetectorSuperSampling(); -	} -	// Deprecated option -	m_iDetectorSuperSampling = (int)_cfg.self.getOptionNumerical("DetectorSuperSampling", m_iDetectorSuperSampling); -	CC.markOptionParsed("DetectorSuperSampling");  	// return success @@ -125,20 +137,16 @@ bool CCudaForwardProjectionAlgorithm::initialize(const Config& _cfg)  //----------------------------------------------------------------------------------------  // Initialize - C++ -bool CCudaForwardProjectionAlgorithm::initialize(CProjectionGeometry2D* _pProjectionGeometry, -												 CVolumeGeometry2D* _pReconstructionGeometry, +bool CCudaForwardProjectionAlgorithm::initialize(CProjector2D* _pProjector,  												 CFloat32VolumeData2D* _pVolume, -												 CFloat32ProjectionData2D* _pSinogram, -												 int _iGPUindex, int _iDetectorSuperSampling) +												 CFloat32ProjectionData2D* _pSinogram)  {  	// store classes -	//m_pProjectionGeometry = _pProjectionGeometry; -	//m_pReconstructionGeometry = _pReconstructionGeometry; +	m_pProjector = _pProjector;  	m_pVolume = _pVolume;  	m_pSinogram = _pSinogram; -	m_iDetectorSuperSampling = _iDetectorSuperSampling; -	m_iGPUIndex = _iGPUindex; +	initializeFromProjector();  	// return success  	return check(); diff --git a/src/CudaForwardProjectionAlgorithm3D.cpp b/src/CudaForwardProjectionAlgorithm3D.cpp index 46dab12..209f5a5 100644 --- a/src/CudaForwardProjectionAlgorithm3D.cpp +++ b/src/CudaForwardProjectionAlgorithm3D.cpp @@ -40,6 +40,8 @@ $Id$  #include "astra/ParallelVecProjectionGeometry3D.h"  #include "astra/ConeVecProjectionGeometry3D.h" +#include "astra/CompositeGeometryManager.h" +  #include "astra/Logging.h"  #include "../cuda/3d/astra3d.h" @@ -72,6 +74,23 @@ CCudaForwardProjectionAlgorithm3D::~CCudaForwardProjectionAlgorithm3D()  }  //--------------------------------------------------------------------------------------- +void CCudaForwardProjectionAlgorithm3D::initializeFromProjector() +{ +	m_iDetectorSuperSampling = 1; +	m_iGPUIndex = -1; + +	CCudaProjector3D* pCudaProjector = dynamic_cast<CCudaProjector3D*>(m_pProjector); +	if (!pCudaProjector) { +		if (m_pProjector) { +			ASTRA_WARN("non-CUDA Projector3D passed to FP3D_CUDA"); +		} +	} else { +		m_iDetectorSuperSampling = pCudaProjector->getDetectorSuperSampling(); +		m_iGPUIndex = pCudaProjector->getGPUIndex(); +	} +} + +//---------------------------------------------------------------------------------------  // Initialize - Config  bool CCudaForwardProjectionAlgorithm3D::initialize(const Config& _cfg)  { @@ -97,29 +116,21 @@ bool CCudaForwardProjectionAlgorithm3D::initialize(const Config& _cfg)  	// optional: projector  	node = _cfg.self.getSingleNode("ProjectorId"); -	CCudaProjector3D* pCudaProjector = 0;  	m_pProjector = 0;  	if (node) {  		id = boost::lexical_cast<int>(node.getContent());  		m_pProjector = CProjector3DManager::getSingleton().get(id); -		pCudaProjector = dynamic_cast<CCudaProjector3D*>(CProjector3DManager::getSingleton().get(id)); -		m_pProjector = pCudaProjector; -		if (!pCudaProjector) { -			// TODO: Report -		}  	}  	CC.markNodeParsed("ProjectorId"); -	// GPU number -	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); -	CC.markOptionParsed("GPUindex"); - +	initializeFromProjector(); -	m_iDetectorSuperSampling = 1; -	if (pCudaProjector) -		m_iDetectorSuperSampling = pCudaProjector->getDetectorSuperSampling(); +	// Deprecated options  	m_iDetectorSuperSampling = (int)_cfg.self.getOptionNumerical("DetectorSuperSampling", m_iDetectorSuperSampling); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", m_iGPUIndex);  	CC.markOptionParsed("DetectorSuperSampling"); +	CC.markOptionParsed("GPUindex"); +  	// success  	m_bIsInitialized = check(); @@ -142,8 +153,15 @@ bool CCudaForwardProjectionAlgorithm3D::initialize(CProjector3D* _pProjector,  	m_pProjections = _pProjections;  	m_pVolume = _pVolume; -	m_iDetectorSuperSampling = _iDetectorSuperSampling; -	m_iGPUIndex = _iGPUindex; +	CCudaProjector3D* pCudaProjector = dynamic_cast<CCudaProjector3D*>(m_pProjector); +	if (!pCudaProjector) { +		// TODO: Report +		m_iDetectorSuperSampling = _iDetectorSuperSampling; +		m_iGPUIndex = _iGPUindex; +	} else { +		m_iDetectorSuperSampling = pCudaProjector->getDetectorSuperSampling(); +		m_iGPUIndex = pCudaProjector->getGPUIndex(); +	}  	// success  	m_bIsInitialized = check(); @@ -247,11 +265,13 @@ void CCudaForwardProjectionAlgorithm3D::run(int)  	// check initialized  	assert(m_bIsInitialized); +#if 1 +	CCompositeGeometryManager cgm; + +	cgm.doFP(m_pProjector, m_pVolume, m_pProjections); + +#else  	const CProjectionGeometry3D* projgeom = m_pProjections->getGeometry(); -	const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(projgeom); -	const CParallelProjectionGeometry3D* par3dgeom = dynamic_cast<const CParallelProjectionGeometry3D*>(projgeom); -	const CConeVecProjectionGeometry3D* conevecgeom = dynamic_cast<const CConeVecProjectionGeometry3D*>(projgeom); -	const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(projgeom);  	const CVolumeGeometry3D& volgeom = *m_pVolume->getGeometry();  	Cuda3DProjectionKernel projKernel = ker3d_default; @@ -279,58 +299,10 @@ void CCudaForwardProjectionAlgorithm3D::run(int)  	}  #endif -	if (conegeom) { -		astraCudaConeFP(m_pVolume->getDataConst(), m_pProjections->getData(), -		                volgeom.getGridColCount(), -		                volgeom.getGridRowCount(), -		                volgeom.getGridSliceCount(), -		                conegeom->getProjectionCount(), -		                conegeom->getDetectorColCount(), -		                conegeom->getDetectorRowCount(), -		                conegeom->getOriginSourceDistance(), -		                conegeom->getOriginDetectorDistance(), -		                conegeom->getDetectorSpacingX(), -		                conegeom->getDetectorSpacingY(), -		                conegeom->getProjectionAngles(), -		                m_iGPUIndex, m_iDetectorSuperSampling); -	} else if (par3dgeom) { -		astraCudaPar3DFP(m_pVolume->getDataConst(), m_pProjections->getData(), -		                 volgeom.getGridColCount(), -		                 volgeom.getGridRowCount(), -		                 volgeom.getGridSliceCount(), -		                 par3dgeom->getProjectionCount(), -		                 par3dgeom->getDetectorColCount(), -		                 par3dgeom->getDetectorRowCount(), -		                 par3dgeom->getDetectorSpacingX(), -		                 par3dgeom->getDetectorSpacingY(), -		                 par3dgeom->getProjectionAngles(), -		                 m_iGPUIndex, m_iDetectorSuperSampling, -		                 projKernel); -	} else if (parvec3dgeom) { -		astraCudaPar3DFP(m_pVolume->getDataConst(), m_pProjections->getData(), -		                 volgeom.getGridColCount(), -		                 volgeom.getGridRowCount(), -		                 volgeom.getGridSliceCount(), -		                 parvec3dgeom->getProjectionCount(), -		                 parvec3dgeom->getDetectorColCount(), -		                 parvec3dgeom->getDetectorRowCount(), -		                 parvec3dgeom->getProjectionVectors(), -		                 m_iGPUIndex, m_iDetectorSuperSampling, -		                 projKernel); -	} else if (conevecgeom) { -		astraCudaConeFP(m_pVolume->getDataConst(), m_pProjections->getData(), -		                volgeom.getGridColCount(), -		                volgeom.getGridRowCount(), -		                volgeom.getGridSliceCount(), -		                conevecgeom->getProjectionCount(), -		                conevecgeom->getDetectorColCount(), -		                conevecgeom->getDetectorRowCount(), -		                conevecgeom->getProjectionVectors(), -		                m_iGPUIndex, m_iDetectorSuperSampling); -	} else { -		ASTRA_ASSERT(false); -	} - +	astraCudaFP(m_pVolume->getDataConst(), m_pProjections->getData(), +	            &volgeom, projgeom, +	            m_iGPUIndex, m_iDetectorSuperSampling, projKernel); +#endif  } diff --git a/src/CudaProjector2D.cpp b/src/CudaProjector2D.cpp index a26e32d..acf6000 100644 --- a/src/CudaProjector2D.cpp +++ b/src/CudaProjector2D.cpp @@ -61,6 +61,7 @@ void CCudaProjector2D::_clear()  	m_projectionKernel = ker2d_default;  	m_iVoxelSuperSampling = 1;  	m_iDetectorSuperSampling = 1; +	m_iGPUIndex = -1;  }  //---------------------------------------------------------------------------------------- @@ -125,18 +126,18 @@ bool CCudaProjector2D::initialize(const Config& _cfg)  	m_iDetectorSuperSampling = (int)_cfg.self.getOptionNumerical("DetectorSuperSampling", 1);  	CC.markOptionParsed("DetectorSuperSampling"); +	// GPU number +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex); +	CC.markOptionParsed("GPUIndex"); +	if (!_cfg.self.hasOption("GPUIndex")) +		CC.markOptionParsed("GPUindex"); + +  	m_bIsInitialized = _check();  	return m_bIsInitialized;  } -/* -bool CProjector2D::initialize(astra::CProjectionGeometry2D *, astra::CVolumeGeometry2D *) -{ -	ASTRA_ASSERT(false); - -	return false; -} -*/  std::string CCudaProjector2D::description() const  { diff --git a/src/CudaProjector3D.cpp b/src/CudaProjector3D.cpp index d2fd74c..bbfbd34 100644 --- a/src/CudaProjector3D.cpp +++ b/src/CudaProjector3D.cpp @@ -64,6 +64,7 @@ void CCudaProjector3D::_clear()  	m_projectionKernel = ker3d_default;  	m_iVoxelSuperSampling = 1;  	m_iDetectorSuperSampling = 1; +	m_iGPUIndex = -1;  }  //---------------------------------------------------------------------------------------- @@ -128,6 +129,12 @@ bool CCudaProjector3D::initialize(const Config& _cfg)  	m_iDetectorSuperSampling = (int)_cfg.self.getOptionNumerical("DetectorSuperSampling", 1);  	CC.markOptionParsed("DetectorSuperSampling"); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex); +	CC.markOptionParsed("GPUIndex"); +	if (!_cfg.self.hasOption("GPUIndex")) +		CC.markOptionParsed("GPUindex"); +  	m_bIsInitialized = _check();  	return m_bIsInitialized;  } diff --git a/src/CudaReconstructionAlgorithm2D.cpp b/src/CudaReconstructionAlgorithm2D.cpp index 71b6637..71dddf7 100644 --- a/src/CudaReconstructionAlgorithm2D.cpp +++ b/src/CudaReconstructionAlgorithm2D.cpp @@ -84,111 +84,51 @@ void CCudaReconstructionAlgorithm2D::_clear()  }  //--------------------------------------------------------------------------------------- -// Initialize - Config -bool CCudaReconstructionAlgorithm2D::initialize(const Config& _cfg) +void CCudaReconstructionAlgorithm2D::initializeFromProjector()  { -	ASTRA_ASSERT(_cfg.self); -	ConfigStackCheck<CAlgorithm> CC("CudaReconstructionAlgorithm2D", this, _cfg); - -	// if already initialized, clear first -	if (m_bIsInitialized) { -		clear(); -	} +	m_iPixelSuperSampling = 1; +	m_iDetectorSuperSampling = 1; +	m_iGPUIndex = -1;  	// Projector -	XMLNode node = _cfg.self.getSingleNode("ProjectorId"); -	CCudaProjector2D* pCudaProjector = 0; -	if (node) { -		int id = boost::lexical_cast<int>(node.getContent()); -		CProjector2D *projector = CProjector2DManager::getSingleton().get(id); -		pCudaProjector = dynamic_cast<CCudaProjector2D*>(projector); -		if (!pCudaProjector) { +	CCudaProjector2D* pCudaProjector = dynamic_cast<CCudaProjector2D*>(m_pProjector); +	if (!pCudaProjector) { +		if (m_pProjector) {  			ASTRA_WARN("non-CUDA Projector2D passed");  		} -	} -	CC.markNodeParsed("ProjectorId"); - - -	// sinogram data -	node = _cfg.self.getSingleNode("ProjectionDataId"); -	ASTRA_CONFIG_CHECK(node, "CudaSirt2", "No ProjectionDataId tag specified."); -	int id = boost::lexical_cast<int>(node.getContent()); -	m_pSinogram = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id)); -	CC.markNodeParsed("ProjectionDataId"); - -	// reconstruction data -	node = _cfg.self.getSingleNode("ReconstructionDataId"); -	ASTRA_CONFIG_CHECK(node, "CudaSirt2", "No ReconstructionDataId tag specified."); -	id = boost::lexical_cast<int>(node.getContent()); -	m_pReconstruction = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id)); -	CC.markNodeParsed("ReconstructionDataId"); - -	// fixed mask -	if (_cfg.self.hasOption("ReconstructionMaskId")) { -		m_bUseReconstructionMask = true; -		id = boost::lexical_cast<int>(_cfg.self.getOption("ReconstructionMaskId")); -		m_pReconstructionMask = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id)); -		ASTRA_CONFIG_CHECK(m_pReconstructionMask, "CudaReconstruction2D", "Invalid ReconstructionMaskId."); -	} -	CC.markOptionParsed("ReconstructionMaskId"); -	// fixed mask -	if (_cfg.self.hasOption("SinogramMaskId")) { -		m_bUseSinogramMask = true; -		id = boost::lexical_cast<int>(_cfg.self.getOption("SinogramMaskId")); -		m_pSinogramMask = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id)); -		ASTRA_CONFIG_CHECK(m_pSinogramMask, "CudaReconstruction2D", "Invalid SinogramMaskId."); -	} -	CC.markOptionParsed("SinogramMaskId"); - -	// Constraints - NEW -	if (_cfg.self.hasOption("MinConstraint")) { -		m_bUseMinConstraint = true; -		m_fMinValue = _cfg.self.getOptionNumerical("MinConstraint", 0.0f); -		CC.markOptionParsed("MinConstraint"); -	} else { -		// Constraint - OLD -		m_bUseMinConstraint = _cfg.self.getOptionBool("UseMinConstraint", false); -		CC.markOptionParsed("UseMinConstraint"); -		if (m_bUseMinConstraint) { -			m_fMinValue = _cfg.self.getOptionNumerical("MinConstraintValue", 0.0f); -			CC.markOptionParsed("MinConstraintValue"); -		} -	} -	if (_cfg.self.hasOption("MaxConstraint")) { -		m_bUseMaxConstraint = true; -		m_fMaxValue = _cfg.self.getOptionNumerical("MaxConstraint", 255.0f); -		CC.markOptionParsed("MaxConstraint");  	} else { -		// Constraint - OLD -		m_bUseMaxConstraint = _cfg.self.getOptionBool("UseMaxConstraint", false); -		CC.markOptionParsed("UseMaxConstraint"); -		if (m_bUseMaxConstraint) { -			m_fMaxValue = _cfg.self.getOptionNumerical("MaxConstraintValue", 0.0f); -			CC.markOptionParsed("MaxConstraintValue"); -		} -	} - -	// GPU number -	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); -	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex); -	CC.markOptionParsed("GPUindex"); -	if (!_cfg.self.hasOption("GPUindex")) -		CC.markOptionParsed("GPUIndex"); - -	// Supersampling factors -	m_iDetectorSuperSampling = 1; -	m_iPixelSuperSampling = 1; -	if (pCudaProjector) { -		// New interface  		m_iDetectorSuperSampling = pCudaProjector->getDetectorSuperSampling();  		m_iPixelSuperSampling = pCudaProjector->getVoxelSuperSampling(); +		m_iGPUIndex = pCudaProjector->getGPUIndex();  	} +} + +//--------------------------------------------------------------------------------------- +// Initialize - Config +bool CCudaReconstructionAlgorithm2D::initialize(const Config& _cfg) +{ +	ASTRA_ASSERT(_cfg.self); +	ConfigStackCheck<CAlgorithm> CC("CudaReconstructionAlgorithm2D", this, _cfg); + +	m_bIsInitialized = CReconstructionAlgorithm2D::initialize(_cfg); + +	if (!m_bIsInitialized) +		return false; + +	initializeFromProjector(); +  	// Deprecated options  	m_iDetectorSuperSampling = (int)_cfg.self.getOptionNumerical("DetectorSuperSampling", m_iDetectorSuperSampling);  	m_iPixelSuperSampling = (int)_cfg.self.getOptionNumerical("PixelSuperSampling", m_iPixelSuperSampling);  	CC.markOptionParsed("DetectorSuperSampling");  	CC.markOptionParsed("PixelSuperSampling"); +	// GPU number +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex); +	CC.markOptionParsed("GPUIndex"); +	if (!_cfg.self.hasOption("GPUIndex")) +		CC.markOptionParsed("GPUindex");  	return _check();  } @@ -199,32 +139,18 @@ bool CCudaReconstructionAlgorithm2D::initialize(CProjector2D* _pProjector,                                       CFloat32ProjectionData2D* _pSinogram,                                        CFloat32VolumeData2D* _pReconstruction)  { -	return initialize(_pProjector, _pSinogram, _pReconstruction, 0, 1); -} - -//--------------------------------------------------------------------------------------- -// Initialize - C++ -bool CCudaReconstructionAlgorithm2D::initialize(CProjector2D* _pProjector, -                                     CFloat32ProjectionData2D* _pSinogram,  -                                     CFloat32VolumeData2D* _pReconstruction, -                                     int _iGPUindex, -                                     int _iDetectorSuperSampling, -                                     int _iPixelSuperSampling) -{  	// if already initialized, clear first  	if (m_bIsInitialized) {  		clear();  	} -	m_pProjector = 0; +	m_pProjector = _pProjector;  	// required classes  	m_pSinogram = _pSinogram;  	m_pReconstruction = _pReconstruction; -	m_iDetectorSuperSampling = _iDetectorSuperSampling; -	m_iPixelSuperSampling = _iPixelSuperSampling; -	m_iGPUIndex = _iGPUindex; +	initializeFromProjector();  	return _check();  } @@ -234,40 +160,13 @@ bool CCudaReconstructionAlgorithm2D::initialize(CProjector2D* _pProjector,  // Check  bool CCudaReconstructionAlgorithm2D::_check()   { -	// TODO: CLEAN UP - - -	// check pointers -	//ASTRA_CONFIG_CHECK(m_pProjector, "Reconstruction2D", "Invalid Projector Object."); -	ASTRA_CONFIG_CHECK(m_pSinogram, "SIRT_CUDA", "Invalid Projection Data Object."); -	ASTRA_CONFIG_CHECK(m_pReconstruction, "SIRT_CUDA", "Invalid Reconstruction Data Object."); - -	// check initializations -	//ASTRA_CONFIG_CHECK(m_pProjector->isInitialized(), "Reconstruction2D", "Projector Object Not Initialized."); -	ASTRA_CONFIG_CHECK(m_pSinogram->isInitialized(), "SIRT_CUDA", "Projection Data Object Not Initialized."); -	ASTRA_CONFIG_CHECK(m_pReconstruction->isInitialized(), "SIRT_CUDA", "Reconstruction Data Object Not Initialized."); - -	ASTRA_CONFIG_CHECK(m_iDetectorSuperSampling >= 1, "SIRT_CUDA", "DetectorSuperSampling must be a positive integer."); -	ASTRA_CONFIG_CHECK(m_iPixelSuperSampling >= 1, "SIRT_CUDA", "PixelSuperSampling must be a positive integer."); -	ASTRA_CONFIG_CHECK(m_iGPUIndex >= -1, "SIRT_CUDA", "GPUIndex must be a non-negative integer."); - -	// check compatibility between projector and data classes -//	ASTRA_CONFIG_CHECK(m_pSinogram->getGeometry()->isEqual(m_pProjector->getProjectionGeometry()), "SIRT_CUDA", "Projection Data not compatible with the specified Projector."); -//	ASTRA_CONFIG_CHECK(m_pReconstruction->getGeometry()->isEqual(m_pProjector->getVolumeGeometry()), "SIRT_CUDA", "Reconstruction Data not compatible with the specified Projector."); - -	// todo: turn some of these back on +	if (!CReconstructionAlgorithm2D::_check()) +		return false; -// 	ASTRA_CONFIG_CHECK(m_pProjectionGeometry, "SIRT_CUDA", "ProjectionGeometry not specified."); -// 	ASTRA_CONFIG_CHECK(m_pProjectionGeometry->isInitialized(), "SIRT_CUDA", "ProjectionGeometry not initialized."); -// 	ASTRA_CONFIG_CHECK(m_pReconstructionGeometry, "SIRT_CUDA", "ReconstructionGeometry not specified."); -// 	ASTRA_CONFIG_CHECK(m_pReconstructionGeometry->isInitialized(), "SIRT_CUDA", "ReconstructionGeometry not initialized."); +	ASTRA_CONFIG_CHECK(m_iDetectorSuperSampling >= 1, "CudaReconstructionAlgorithm2D", "DetectorSuperSampling must be a positive integer."); +	ASTRA_CONFIG_CHECK(m_iPixelSuperSampling >= 1, "CudaReconstructionAlgorithm2D", "PixelSuperSampling must be a positive integer."); +	ASTRA_CONFIG_CHECK(m_iGPUIndex >= -1, "CudaReconstructionAlgorithm2D", "GPUIndex must be a non-negative integer or -1."); -	// check dimensions -	//ASTRA_CONFIG_CHECK(m_pSinogram->getAngleCount() == m_pProjectionGeometry->getProjectionAngleCount(), "SIRT_CUDA", "Sinogram data object size mismatch."); -	//ASTRA_CONFIG_CHECK(m_pSinogram->getDetectorCount() == m_pProjectionGeometry->getDetectorCount(), "SIRT_CUDA", "Sinogram data object size mismatch."); -	//ASTRA_CONFIG_CHECK(m_pReconstruction->getWidth() == m_pReconstructionGeometry->getGridColCount(), "SIRT_CUDA", "Reconstruction data object size mismatch."); -	//ASTRA_CONFIG_CHECK(m_pReconstruction->getHeight() == m_pReconstructionGeometry->getGridRowCount(), "SIRT_CUDA", "Reconstruction data object size mismatch."); -	  	// check restrictions  	// TODO: check restrictions built into cuda code @@ -462,10 +361,18 @@ void CCudaReconstructionAlgorithm2D::run(int _iNrIterations)  	ASTRA_ASSERT(ok); -	if (m_bUseMinConstraint) -		ok &= m_pAlgo->setMinConstraint(m_fMinValue); -	if (m_bUseMaxConstraint) -		ok &= m_pAlgo->setMaxConstraint(m_fMaxValue); +	if (m_bUseMinConstraint) { +		bool ret = m_pAlgo->setMinConstraint(m_fMinValue); +		if (!ret) { +			ASTRA_WARN("This algorithm ignores MinConstraint"); +		} +	} +	if (m_bUseMaxConstraint) { +		bool ret= m_pAlgo->setMaxConstraint(m_fMaxValue); +		if (!ret) { +			ASTRA_WARN("This algorithm ignores MaxConstraint"); +		} +	}  	ok &= m_pAlgo->iterate(_iNrIterations);  	ASTRA_ASSERT(ok); diff --git a/src/CudaSartAlgorithm.cpp b/src/CudaSartAlgorithm.cpp index 8c0c6d7..d202847 100644 --- a/src/CudaSartAlgorithm.cpp +++ b/src/CudaSartAlgorithm.cpp @@ -116,10 +116,9 @@ bool CCudaSartAlgorithm::initialize(const Config& _cfg)  // Initialize - C++  bool CCudaSartAlgorithm::initialize(CProjector2D* _pProjector,                                       CFloat32ProjectionData2D* _pSinogram,  -                                     CFloat32VolumeData2D* _pReconstruction, -                                     int _iGPUindex, int _iDetectorSuperSampling) +                                     CFloat32VolumeData2D* _pReconstruction)  { -	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction, _iGPUindex, _iDetectorSuperSampling, 1); +	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction);  	if (!m_bIsInitialized)  		return false; diff --git a/src/CudaSirtAlgorithm.cpp b/src/CudaSirtAlgorithm.cpp index d424915..ab0a418 100644 --- a/src/CudaSirtAlgorithm.cpp +++ b/src/CudaSirtAlgorithm.cpp @@ -98,11 +98,9 @@ bool CCudaSirtAlgorithm::initialize(const Config& _cfg)  // Initialize - C++  bool CCudaSirtAlgorithm::initialize(CProjector2D* _pProjector,                                       CFloat32ProjectionData2D* _pSinogram,  -                                     CFloat32VolumeData2D* _pReconstruction, -                                     int _iGPUindex, int _iDetectorSuperSampling, -                                     int _iPixelSuperSampling) +                                     CFloat32VolumeData2D* _pReconstruction)  { -	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction, _iGPUindex, _iDetectorSuperSampling, _iPixelSuperSampling); +	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_pProjector, _pSinogram, _pReconstruction);  	if (!m_bIsInitialized)  		return false; diff --git a/src/CudaSirtAlgorithm3D.cpp b/src/CudaSirtAlgorithm3D.cpp index abbb9fd..1fa0da2 100644 --- a/src/CudaSirtAlgorithm3D.cpp +++ b/src/CudaSirtAlgorithm3D.cpp @@ -38,6 +38,8 @@ $Id$  #include "astra/ConeVecProjectionGeometry3D.h"  #include "astra/CudaProjector3D.h" +#include "astra/Logging.h" +  #include "../cuda/3d/astra3d.h"  using namespace std; @@ -90,7 +92,27 @@ bool CCudaSirtAlgorithm3D::_check()  	return true;  } -//--------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +void CCudaSirtAlgorithm3D::initializeFromProjector() +{ +	m_iVoxelSuperSampling = 1; +	m_iDetectorSuperSampling = 1; +	m_iGPUIndex = -1; + +	CCudaProjector3D* pCudaProjector = dynamic_cast<CCudaProjector3D*>(m_pProjector); +	if (!pCudaProjector) { +		if (m_pProjector) { +			ASTRA_WARN("non-CUDA Projector3D passed to SIRT3D_CUDA"); +		} +	} else { +		m_iVoxelSuperSampling = pCudaProjector->getVoxelSuperSampling(); +		m_iDetectorSuperSampling = pCudaProjector->getDetectorSuperSampling(); +		m_iGPUIndex = pCudaProjector->getGPUIndex(); +	} + +} + +//--------------------------------------------------------------------------------------  // Initialize - Config  bool CCudaSirtAlgorithm3D::initialize(const Config& _cfg)  { @@ -108,28 +130,20 @@ bool CCudaSirtAlgorithm3D::initialize(const Config& _cfg)  		return false;  	} -	CCudaProjector3D* pCudaProjector = 0; -	pCudaProjector = dynamic_cast<CCudaProjector3D*>(m_pProjector); -	if (!pCudaProjector) { -		// TODO: Report -	} +	initializeFromProjector(); -	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); -	CC.markOptionParsed("GPUindex"); - - -	m_iVoxelSuperSampling = 1; -	m_iDetectorSuperSampling = 1; -	if (pCudaProjector) { -		// New interface -		m_iVoxelSuperSampling = pCudaProjector->getVoxelSuperSampling(); -		m_iDetectorSuperSampling = pCudaProjector->getDetectorSuperSampling(); -	}  	// Deprecated options  	m_iVoxelSuperSampling = (int)_cfg.self.getOptionNumerical("VoxelSuperSampling", m_iVoxelSuperSampling);  	m_iDetectorSuperSampling = (int)_cfg.self.getOptionNumerical("DetectorSuperSampling", m_iDetectorSuperSampling); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", m_iGPUIndex); +	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex);  	CC.markOptionParsed("VoxelSuperSampling");  	CC.markOptionParsed("DetectorSuperSampling"); +	CC.markOptionParsed("GPUIndex"); +	if (!_cfg.self.hasOption("GPUIndex")) +		CC.markOptionParsed("GPUindex"); + +  	m_pSirt = new AstraSIRT3d(); @@ -189,10 +203,6 @@ void CCudaSirtAlgorithm3D::run(int _iNrIterations)  	ASTRA_ASSERT(m_bIsInitialized);  	const CProjectionGeometry3D* projgeom = m_pSinogram->getGeometry(); -	const CConeProjectionGeometry3D* conegeom = dynamic_cast<const CConeProjectionGeometry3D*>(projgeom); -	const CParallelProjectionGeometry3D* par3dgeom = dynamic_cast<const CParallelProjectionGeometry3D*>(projgeom); -	const CParallelVecProjectionGeometry3D* parvec3dgeom = dynamic_cast<const CParallelVecProjectionGeometry3D*>(projgeom); -	const CConeVecProjectionGeometry3D* conevec3dgeom = dynamic_cast<const CConeVecProjectionGeometry3D*>(projgeom);  	const CVolumeGeometry3D& volgeom = *m_pReconstruction->getGeometry();  	bool ok = true; @@ -201,39 +211,7 @@ void CCudaSirtAlgorithm3D::run(int _iNrIterations)  		ok &= m_pSirt->setGPUIndex(m_iGPUIndex); -		ok &= m_pSirt->setReconstructionGeometry(volgeom.getGridColCount(), -		                                         volgeom.getGridRowCount(), -		                                         volgeom.getGridSliceCount()); - -		if (conegeom) { -			ok &= m_pSirt->setConeGeometry(conegeom->getProjectionCount(), -			                               conegeom->getDetectorColCount(), -			                               conegeom->getDetectorRowCount(), -			                               conegeom->getOriginSourceDistance(), -			                               conegeom->getOriginDetectorDistance(), -			                               conegeom->getDetectorSpacingX(), -			                               conegeom->getDetectorSpacingY(), -			                               conegeom->getProjectionAngles()); -		} else if (par3dgeom) { -			ok &= m_pSirt->setPar3DGeometry(par3dgeom->getProjectionCount(), -			                                par3dgeom->getDetectorColCount(), -			                                par3dgeom->getDetectorRowCount(), -			                                par3dgeom->getDetectorSpacingX(), -			                                par3dgeom->getDetectorSpacingY(), -			                                par3dgeom->getProjectionAngles()); -		} else if (parvec3dgeom) { -			ok &= m_pSirt->setPar3DGeometry(parvec3dgeom->getProjectionCount(), -			                                parvec3dgeom->getDetectorColCount(), -			                                parvec3dgeom->getDetectorRowCount(), -			                                parvec3dgeom->getProjectionVectors()); -		} else if (conevec3dgeom) { -			ok &= m_pSirt->setConeGeometry(conevec3dgeom->getProjectionCount(), -			                               conevec3dgeom->getDetectorColCount(), -			                               conevec3dgeom->getDetectorRowCount(), -			                               conevec3dgeom->getProjectionVectors()); -		} else { -			ASTRA_ASSERT(false); -		} +		ok &= m_pSirt->setGeometry(&volgeom, projgeom);  		ok &= m_pSirt->enableSuperSampling(m_iVoxelSuperSampling, m_iDetectorSuperSampling); diff --git a/src/Float32ProjectionData3D.cpp b/src/Float32ProjectionData3D.cpp index 2bd0447..680ad55 100644 --- a/src/Float32ProjectionData3D.cpp +++ b/src/Float32ProjectionData3D.cpp @@ -53,13 +53,13 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator+=(const CFloat32Pro  	CProjectionGeometry3D * pThisGeometry = getGeometry();  	int iProjectionCount = pThisGeometry->getProjectionCount(); +	int iDetectorCount = pThisGeometry->getDetectorTotCount();  #ifdef _DEBUG  	CProjectionGeometry3D * pDataGeometry = _data.getGeometry(); -	int iThisProjectionDetectorCount = pThisGeometry->getDetectorRowCount() * pThisGeometry->getDetectorColCount(); -	int iDataProjectionDetectorCount = pDataGeometry->getDetectorRowCount() * pDataGeometry->getDetectorColCount(); +	int iDataProjectionDetectorCount = pDataGeometry->getDetectorTotCount();  	ASTRA_ASSERT(iProjectionCount == pDataGeometry->getProjectionCount()); -	ASTRA_ASSERT(iThisProjectionDetectorCount == iDataProjectionDetectorCount); +	ASTRA_ASSERT(iDetectorCount == iDataProjectionDetectorCount);  #endif  	for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++) @@ -67,7 +67,7 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator+=(const CFloat32Pro  		CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex);  		CFloat32VolumeData2D * pDataProjection = _data.fetchProjection(iProjectionIndex); -		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++) +		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorCount; iDetectorIndex++)  		{  			float32 fThisValue = pThisProjection->getData()[iDetectorIndex];  			float32 fDataValue = pDataProjection->getDataConst()[iDetectorIndex]; @@ -91,13 +91,13 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator-=(const CFloat32Pro  	CProjectionGeometry3D * pThisGeometry = getGeometry();  	int iProjectionCount = pThisGeometry->getProjectionCount(); +	int iDetectorCount = pThisGeometry->getDetectorTotCount();  #ifdef _DEBUG  	CProjectionGeometry3D * pDataGeometry = _data.getGeometry(); -	int iThisProjectionDetectorCount = pThisGeometry->getDetectorRowCount() * pThisGeometry->getDetectorColCount(); -	int iDataProjectionDetectorCount = pDataGeometry->getDetectorRowCount() * pDataGeometry->getDetectorColCount(); +	int iDataProjectionDetectorCount = pDataGeometry->getDetectorTotCount();  	ASTRA_ASSERT(iProjectionCount == pDataGeometry->getProjectionCount()); -	ASTRA_ASSERT(iThisProjectionDetectorCount == iDataProjectionDetectorCount); +	ASTRA_ASSERT(iDetectorCount == iDataProjectionDetectorCount);  #endif  	for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++) @@ -105,7 +105,7 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator-=(const CFloat32Pro  		CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex);  		CFloat32VolumeData2D * pDataProjection = _data.fetchProjection(iProjectionIndex); -		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++) +		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorCount; iDetectorIndex++)  		{  			float32 fThisValue = pThisProjection->getData()[iDetectorIndex];  			float32 fDataValue = pDataProjection->getDataConst()[iDetectorIndex]; @@ -129,13 +129,13 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator*=(const CFloat32Pro  	CProjectionGeometry3D * pThisGeometry = getGeometry();  	int iProjectionCount = pThisGeometry->getProjectionCount(); +	int iDetectorCount = pThisGeometry->getDetectorTotCount();  #ifdef _DEBUG  	CProjectionGeometry3D * pDataGeometry = _data.getGeometry(); -	int iThisProjectionDetectorCount = pThisGeometry->getDetectorRowCount() * pThisGeometry->getDetectorColCount(); -	int iDataProjectionDetectorCount = pDataGeometry->getDetectorRowCount() * pDataGeometry->getDetectorColCount(); +	int iDataProjectionDetectorCount = pDataGeometry->getDetectorTotCount();  	ASTRA_ASSERT(iProjectionCount == pDataGeometry->getProjectionCount()); -	ASTRA_ASSERT(iThisProjectionDetectorCount == iDataProjectionDetectorCount); +	ASTRA_ASSERT(iDetectorCount == iDataProjectionDetectorCount);  #endif  	for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++) @@ -143,7 +143,7 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator*=(const CFloat32Pro  		CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex);  		CFloat32VolumeData2D * pDataProjection = _data.fetchProjection(iProjectionIndex); -		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++) +		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorCount; iDetectorIndex++)  		{  			float32 fThisValue = pThisProjection->getData()[iDetectorIndex];  			float32 fDataValue = pDataProjection->getDataConst()[iDetectorIndex]; @@ -167,12 +167,13 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator*=(const float32& _f  	CProjectionGeometry3D * pThisGeometry = getGeometry();  	int iProjectionCount = pThisGeometry->getProjectionCount(); +	int iDetectorCount = pThisGeometry->getDetectorTotCount();  	for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)  	{  		CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex); -		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++) +		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorCount; iDetectorIndex++)  		{  			float32 fThisValue = pThisProjection->getData()[iDetectorIndex]; @@ -194,12 +195,13 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator/=(const float32& _f  	CProjectionGeometry3D * pThisGeometry = getGeometry();  	int iProjectionCount = pThisGeometry->getProjectionCount(); +	int iDetectorCount = pThisGeometry->getDetectorTotCount();  	for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)  	{  		CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex); -		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++) +		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorCount; iDetectorIndex++)  		{  			float32 fThisValue = pThisProjection->getData()[iDetectorIndex]; @@ -221,12 +223,13 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator+=(const float32& _f  	CProjectionGeometry3D * pThisGeometry = getGeometry();  	int iProjectionCount = pThisGeometry->getProjectionCount(); +	int iDetectorCount = pThisGeometry->getDetectorTotCount();  	for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)  	{  		CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex); -		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++) +		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorCount; iDetectorIndex++)  		{  			float32 fThisValue = pThisProjection->getData()[iDetectorIndex]; @@ -248,12 +251,13 @@ CFloat32ProjectionData3D& CFloat32ProjectionData3D::operator-=(const float32& _f  	CProjectionGeometry3D * pThisGeometry = getGeometry();  	int iProjectionCount = pThisGeometry->getProjectionCount(); +	int iDetectorCount = pThisGeometry->getDetectorTotCount();  	for(int iProjectionIndex = 0; iProjectionIndex < iProjectionCount; iProjectionIndex++)  	{  		CFloat32VolumeData2D * pThisProjection = fetchProjection(iProjectionIndex); -		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorIndex; iDetectorIndex++) +		for(int iDetectorIndex = 0; iDetectorIndex < iDetectorCount; iDetectorIndex++)  		{  			float32 fThisValue = pThisProjection->getData()[iDetectorIndex]; diff --git a/src/GeometryUtil3D.cpp b/src/GeometryUtil3D.cpp index 52dd5a9..c6bfd8b 100644 --- a/src/GeometryUtil3D.cpp +++ b/src/GeometryUtil3D.cpp @@ -28,8 +28,96 @@ $Id$  #include "astra/GeometryUtil3D.h" +#include <cmath> +  namespace astra { + +SConeProjection* genConeProjections(unsigned int iProjAngles, +                                    unsigned int iProjU, +                                    unsigned int iProjV, +                                    double fOriginSourceDistance, +                                    double fOriginDetectorDistance, +                                    double fDetUSize, +                                    double fDetVSize, +                                    const float *pfAngles) +{ +	SConeProjection base; +	base.fSrcX = 0.0f; +	base.fSrcY = -fOriginSourceDistance; +	base.fSrcZ = 0.0f; + +	base.fDetSX = iProjU * fDetUSize * -0.5f; +	base.fDetSY = fOriginDetectorDistance; +	base.fDetSZ = iProjV * fDetVSize * -0.5f; + +	base.fDetUX = fDetUSize; +	base.fDetUY = 0.0f; +	base.fDetUZ = 0.0f; + +	base.fDetVX = 0.0f; +	base.fDetVY = 0.0f; +	base.fDetVZ = fDetVSize; + +	SConeProjection* p = new SConeProjection[iProjAngles]; + +#define ROTATE0(name,i,alpha) do { p[i].f##name##X = base.f##name##X * cos(alpha) - base.f##name##Y * sin(alpha); p[i].f##name##Y = base.f##name##X * sin(alpha) + base.f##name##Y * cos(alpha); p[i].f##name##Z = base.f##name##Z; } while(0) + +	for (unsigned int i = 0; i < iProjAngles; ++i) { +		ROTATE0(Src, i, pfAngles[i]); +		ROTATE0(DetS, i, pfAngles[i]); +		ROTATE0(DetU, i, pfAngles[i]); +		ROTATE0(DetV, i, pfAngles[i]); +	} + +#undef ROTATE0 + +	return p; +} + +SPar3DProjection* genPar3DProjections(unsigned int iProjAngles, +                                      unsigned int iProjU, +                                      unsigned int iProjV, +                                      double fDetUSize, +                                      double fDetVSize, +                                      const float *pfAngles) +{ +	SPar3DProjection base; +	base.fRayX = 0.0f; +	base.fRayY = 1.0f; +	base.fRayZ = 0.0f; + +	base.fDetSX = iProjU * fDetUSize * -0.5f; +	base.fDetSY = 0.0f; +	base.fDetSZ = iProjV * fDetVSize * -0.5f; + +	base.fDetUX = fDetUSize; +	base.fDetUY = 0.0f; +	base.fDetUZ = 0.0f; + +	base.fDetVX = 0.0f; +	base.fDetVY = 0.0f; +	base.fDetVZ = fDetVSize; + +	SPar3DProjection* p = new SPar3DProjection[iProjAngles]; + +#define ROTATE0(name,i,alpha) do { p[i].f##name##X = base.f##name##X * cos(alpha) - base.f##name##Y * sin(alpha); p[i].f##name##Y = base.f##name##X * sin(alpha) + base.f##name##Y * cos(alpha); p[i].f##name##Z = base.f##name##Z; } while(0) + +	for (unsigned int i = 0; i < iProjAngles; ++i) { +		ROTATE0(Ray, i, pfAngles[i]); +		ROTATE0(DetS, i, pfAngles[i]); +		ROTATE0(DetU, i, pfAngles[i]); +		ROTATE0(DetV, i, pfAngles[i]); +	} + +#undef ROTATE0 + +	return p; +} + + + +  // (See declaration in header for (mathematical) description of these functions) @@ -72,4 +160,88 @@ void computeBP_UV_Coeffs(const SConeProjection& proj, double &fUX, double &fUY,  } +// TODO: Handle cases of rays parallel to coordinate planes + +void backprojectPointX(const SPar3DProjection& proj, double fU, double fV, +                       double fX, double &fY, double &fZ) +{ +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fX - px) / proj.fRayX; + +	fY = py + a * proj.fRayY; +	fZ = pz + a * proj.fRayZ; +} + +void backprojectPointY(const SPar3DProjection& proj, double fU, double fV, +                       double fY, double &fX, double &fZ) +{ +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fY - py) / proj.fRayY; + +	fX = px + a * proj.fRayX; +	fZ = pz + a * proj.fRayZ; + +} + +void backprojectPointZ(const SPar3DProjection& proj, double fU, double fV, +                       double fZ, double &fX, double &fY) +{ +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fZ - pz) / proj.fRayZ; + +	fX = px + a * proj.fRayX; +	fY = py + a * proj.fRayY; +} + + + +void backprojectPointX(const SConeProjection& proj, double fU, double fV, +                       double fX, double &fY, double &fZ) +{ +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fX - proj.fSrcX) / (px - proj.fSrcX); + +	fY = proj.fSrcY + a * (py - proj.fSrcY); +	fZ = proj.fSrcZ + a * (pz - proj.fSrcZ); +} + +void backprojectPointY(const SConeProjection& proj, double fU, double fV, +                       double fY, double &fX, double &fZ) +{ +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fY - proj.fSrcY) / (py - proj.fSrcY); + +	fX = proj.fSrcX + a * (px - proj.fSrcX); +	fZ = proj.fSrcZ + a * (pz - proj.fSrcZ); +} + +void backprojectPointZ(const SConeProjection& proj, double fU, double fV, +                       double fZ, double &fX, double &fY) +{ +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fZ - proj.fSrcZ) / (pz - proj.fSrcZ); + +	fX = proj.fSrcX + a * (px - proj.fSrcX); +	fY = proj.fSrcY + a * (py - proj.fSrcY); +} + +  } 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/Logging.cpp b/src/Logging.cpp index 8290ca0..cd7e3f0 100644 --- a/src/Logging.cpp +++ b/src/Logging.cpp @@ -70,37 +70,65 @@ void CLogger::disable()  void CLogger::debug(const char *sfile, int sline, const char *fmt, ...)  {  	_assureIsInitialized(); -	va_list ap; -	va_start(ap, fmt); -	if(m_bEnabledScreen) clog_debug(sfile,sline,0,fmt,ap); -	if(m_bEnabledFile && m_bFileProvided) clog_debug(sfile,sline,1,fmt,ap); +	va_list ap, apf; +	if(m_bEnabledScreen){ +        va_start(ap, fmt); +        clog_debug(sfile,sline,0,fmt,ap); +        va_end(ap); +    } +	if(m_bEnabledFile && m_bFileProvided){ +        va_start(apf, fmt); +        clog_debug(sfile,sline,1,fmt,apf); +        va_end(apf); +    }  }  void CLogger::info(const char *sfile, int sline, const char *fmt, ...)  {  	_assureIsInitialized(); -	va_list ap; -	va_start(ap, fmt); -	if(m_bEnabledScreen) clog_info(sfile,sline,0,fmt,ap); -	if(m_bEnabledFile && m_bFileProvided) clog_info(sfile,sline,1,fmt,ap); +	va_list ap, apf; +	if(m_bEnabledScreen){ +        va_start(ap, fmt); +        clog_info(sfile,sline,0,fmt,ap); +        va_end(ap); +    } +	if(m_bEnabledFile && m_bFileProvided){ +        va_start(apf, fmt); +        clog_info(sfile,sline,1,fmt,apf); +        va_end(apf); +    }  }  void CLogger::warn(const char *sfile, int sline, const char *fmt, ...)  {  	_assureIsInitialized(); -	va_list ap; -	va_start(ap, fmt); -	if(m_bEnabledScreen) clog_warn(sfile,sline,0,fmt,ap); -	if(m_bEnabledFile && m_bFileProvided) clog_warn(sfile,sline,1,fmt,ap); +	va_list ap, apf; +	if(m_bEnabledScreen){ +        va_start(ap, fmt); +        clog_warn(sfile,sline,0,fmt,ap); +        va_end(ap); +    } +	if(m_bEnabledFile && m_bFileProvided){ +        va_start(apf, fmt); +        clog_warn(sfile,sline,1,fmt,apf); +        va_end(apf); +    }  }  void CLogger::error(const char *sfile, int sline, const char *fmt, ...)  {  	_assureIsInitialized(); -	va_list ap; -	va_start(ap, fmt); -	if(m_bEnabledScreen) clog_error(sfile,sline,0,fmt,ap); -	if(m_bEnabledFile && m_bFileProvided) clog_error(sfile,sline,1,fmt,ap); +	va_list ap, apf; +	if(m_bEnabledScreen){ +        va_start(ap, fmt); +        clog_error(sfile,sline,0,fmt,ap); +        va_end(ap); +    } +	if(m_bEnabledFile && m_bFileProvided){ +        va_start(apf, fmt); +        clog_error(sfile,sline,1,fmt,apf); +        va_end(apf); +    }  }  void CLogger::_setLevel(int id, log_level m_eLevel) diff --git a/src/ParallelProjectionGeometry3D.cpp b/src/ParallelProjectionGeometry3D.cpp index 1c87157..7b64fd9 100644 --- a/src/ParallelProjectionGeometry3D.cpp +++ b/src/ParallelProjectionGeometry3D.cpp @@ -27,8 +27,10 @@ $Id$  */  #include "astra/ParallelProjectionGeometry3D.h" -#include <boost/lexical_cast.hpp> +#include "astra/GeometryUtil3D.h" + +#include <boost/lexical_cast.hpp>  #include <cstring>  using namespace std; @@ -185,9 +187,9 @@ CVector3D CParallelProjectionGeometry3D::getProjectionDirection(int _iProjection  	return CVector3D(fDirX, fDirY, fDirZ);  } -void CParallelProjectionGeometry3D::projectPoint(float32 fX, float32 fY, float32 fZ, +void CParallelProjectionGeometry3D::projectPoint(double fX, double fY, double fZ,                                                   int iAngleIndex, -                                                 float32 &fU, float32 &fV) const +                                                 double &fU, double &fV) const  {  	ASTRA_ASSERT(iAngleIndex >= 0);  	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); @@ -214,6 +216,79 @@ CParallelProjectionGeometry2D * CParallelProjectionGeometry3D::createProjectionG  	return pOutput;  } +void CParallelProjectionGeometry3D::backprojectPointX(int iAngleIndex, double fU, double fV, +	                               double fX, double &fY, double &fZ) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SPar3DProjection *projs = genPar3DProjections(1, m_iDetectorColCount, m_iDetectorRowCount, +	                                           m_fDetectorSpacingX, m_fDetectorSpacingY, +	                                           &m_pfProjectionAngles[iAngleIndex]); + +	SPar3DProjection &proj = projs[0]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fX - px) / proj.fRayX; + +	fY = py + a * proj.fRayY; +	fZ = pz + a * proj.fRayZ; + +	delete[] projs; +} + +void CParallelProjectionGeometry3D::backprojectPointY(int iAngleIndex, double fU, double fV, +	                               double fY, double &fX, double &fZ) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SPar3DProjection *projs = genPar3DProjections(1, m_iDetectorColCount, m_iDetectorRowCount, +	                                           m_fDetectorSpacingX, m_fDetectorSpacingY, +	                                           &m_pfProjectionAngles[iAngleIndex]); + +	SPar3DProjection &proj = projs[0]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fY - py) / proj.fRayY; + +	fX = px + a * proj.fRayX; +	fZ = pz + a * proj.fRayZ; + +	delete[] projs; +} + +void CParallelProjectionGeometry3D::backprojectPointZ(int iAngleIndex, double fU, double fV, +	                               double fZ, double &fX, double &fY) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SPar3DProjection *projs = genPar3DProjections(1, m_iDetectorColCount, m_iDetectorRowCount, +	                                           m_fDetectorSpacingX, m_fDetectorSpacingY, +	                                           &m_pfProjectionAngles[iAngleIndex]); + +	SPar3DProjection &proj = projs[0]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fZ - pz) / proj.fRayZ; + +	fX = px + a * proj.fRayX; +	fY = py + a * proj.fRayY; + +	delete[] projs; +} + +  //----------------------------------------------------------------------------------------  } // end namespace astra diff --git a/src/ParallelVecProjectionGeometry3D.cpp b/src/ParallelVecProjectionGeometry3D.cpp index ffad6d0..d04400b 100644 --- a/src/ParallelVecProjectionGeometry3D.cpp +++ b/src/ParallelVecProjectionGeometry3D.cpp @@ -239,9 +239,9 @@ CVector3D CParallelVecProjectionGeometry3D::getProjectionDirection(int _iProject  	return CVector3D(p.fRayX, p.fRayY, p.fRayZ);  } -void CParallelVecProjectionGeometry3D::projectPoint(float32 fX, float32 fY, float32 fZ, -                                                 int iAngleIndex, -                                                 float32 &fU, float32 &fV) const +void CParallelVecProjectionGeometry3D::projectPoint(double fX, double fY, double fZ, +                                                    int iAngleIndex, +                                                    double &fU, double &fV) const  {  	ASTRA_ASSERT(iAngleIndex >= 0);  	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); @@ -258,6 +258,61 @@ void CParallelVecProjectionGeometry3D::projectPoint(float32 fX, float32 fY, floa  } +void CParallelVecProjectionGeometry3D::backprojectPointX(int iAngleIndex, double fU, double fV, +	                               double fX, double &fY, double &fZ) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SPar3DProjection &proj = m_pProjectionAngles[iAngleIndex]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fX - px) / proj.fRayX; + +	fY = py + a * proj.fRayY; +	fZ = pz + a * proj.fRayZ; +} + +void CParallelVecProjectionGeometry3D::backprojectPointY(int iAngleIndex, double fU, double fV, +	                               double fY, double &fX, double &fZ) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SPar3DProjection &proj = m_pProjectionAngles[iAngleIndex]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fY - py) / proj.fRayY; + +	fX = px + a * proj.fRayX; +	fZ = pz + a * proj.fRayZ; +} + +void CParallelVecProjectionGeometry3D::backprojectPointZ(int iAngleIndex, double fU, double fV, +	                               double fZ, double &fX, double &fY) const +{ +	ASTRA_ASSERT(iAngleIndex >= 0); +	ASTRA_ASSERT(iAngleIndex < m_iProjectionAngleCount); + +	SPar3DProjection &proj = m_pProjectionAngles[iAngleIndex]; + +	double px = proj.fDetSX + fU * proj.fDetUX + fV * proj.fDetVX; +	double py = proj.fDetSY + fU * proj.fDetUY + fV * proj.fDetVY; +	double pz = proj.fDetSZ + fU * proj.fDetUZ + fV * proj.fDetVZ; + +	double a = (fZ - pz) / proj.fRayZ; + +	fX = px + a * proj.fRayX; +	fY = py + a * proj.fRayY; +} + +  //----------------------------------------------------------------------------------------  bool CParallelVecProjectionGeometry3D::_check() diff --git a/src/PluginAlgorithm.cpp b/src/PluginAlgorithm.cpp new file mode 100644 index 0000000..8f7dfc5 --- /dev/null +++ b/src/PluginAlgorithm.cpp @@ -0,0 +1,401 @@ +/* +----------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +$Id$ +*/ + +#ifdef ASTRA_PYTHON + +#include "astra/PluginAlgorithm.h" +#include "astra/Logging.h" +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/split.hpp> +#include <boost/lexical_cast.hpp> +#include <iostream> +#include <fstream> +#include <string> + +#include <Python.h> +#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); +    } +} + +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<std::string> 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<items.size();i++){ +        submod = PyObject_GetAttrString(submod,items[i].c_str()); +        Py_DECREF(pyclass); +        pyclass = submod; +        if(pyclass==NULL){ +            logPythonError(); +            return NULL; +        } +    } +    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; +    CPluginAlgorithm *alg = NULL; +    if(PyBytes_Check(className)){ +        std::string str = std::string(PyBytes_AsString(className)); +    	PyObject *pyclass = getClassFromString(str); +        if(pyclass!=NULL){ +            alg = new CPluginAlgorithm(pyclass); +            Py_DECREF(pyclass); +        } +    }else{ +        alg = new CPluginAlgorithm(className); +    } +    return alg; +} + +PyObject * CPluginAlgorithmFactory::getRegistered(){ +    Py_INCREF(pluginDict); +    return pluginDict; +} + +std::map<std::string, std::string> CPluginAlgorithmFactory::getRegisteredMap(){ +    std::map<std::string, std::string> 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<std::string> rows, row; +        boost::split(rows, str, boost::is_any_of(";")); +        PyObject *mat = PyList_New(rows.size()); +        for(unsigned int i=0; i<rows.size(); i++){ +            boost::split(row, rows[i], boost::is_any_of(",")); +            PyObject *rowlist = PyList_New(row.size()); +            for(unsigned int j=0;j<row.size();j++){ +                PyList_SetItem(rowlist, j, PyFloat_FromDouble(boost::lexical_cast<double>(row[j]))); +            } +            PyList_SetItem(mat, i, rowlist); +        } +        return mat; +    } +    if(str.find(",")!=std::string::npos){ +        std::vector<std::string> vec; +        boost::split(vec, str, boost::is_any_of(",")); +        PyObject *veclist = PyList_New(vec.size()); +        for(unsigned int i=0;i<vec.size();i++){ +            PyList_SetItem(veclist, i, PyFloat_FromDouble(boost::lexical_cast<double>(vec[i]))); +        } +        return veclist; +    } +    try{ +        return PyLong_FromLong(boost::lexical_cast<long>(str)); +    }catch(const boost::bad_lexical_cast &){ +        try{ +            return PyFloat_FromDouble(boost::lexical_cast<double>(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<XMLNode> nodes = node.getNodes(); +    std::list<XMLNode>::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/src/ReconstructionAlgorithm2D.cpp b/src/ReconstructionAlgorithm2D.cpp index 767efe6..4575ff7 100644 --- a/src/ReconstructionAlgorithm2D.cpp +++ b/src/ReconstructionAlgorithm2D.cpp @@ -85,9 +85,16 @@ bool CReconstructionAlgorithm2D::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<int>(node.getContent()); -	m_pProjector = CProjector2DManager::getSingleton().get(id); +	if (requiresProjector()) { +		ASTRA_CONFIG_CHECK(node, "Reconstruction2D", "No ProjectorId tag specified."); +	} +	int id; +	if (node) { +		id = boost::lexical_cast<int>(node.getContent()); +		m_pProjector = CProjector2DManager::getSingleton().get(id); +	} else { +		m_pProjector = 0; +	}  	CC.markNodeParsed("ProjectorId");  	// sinogram data @@ -205,18 +212,22 @@ void CReconstructionAlgorithm2D::setSinogramMask(CFloat32ProjectionData2D* _pMas  bool CReconstructionAlgorithm2D::_check()   {  	// check pointers -	ASTRA_CONFIG_CHECK(m_pProjector, "Reconstruction2D", "Invalid Projector Object."); +	if (requiresProjector()) +		ASTRA_CONFIG_CHECK(m_pProjector, "Reconstruction2D", "Invalid Projector Object.");  	ASTRA_CONFIG_CHECK(m_pSinogram, "Reconstruction2D", "Invalid Projection Data Object.");  	ASTRA_CONFIG_CHECK(m_pReconstruction, "Reconstruction2D", "Invalid Reconstruction Data Object.");  	// check initializations -	ASTRA_CONFIG_CHECK(m_pProjector->isInitialized(), "Reconstruction2D", "Projector Object Not Initialized."); +	if (requiresProjector()) +		ASTRA_CONFIG_CHECK(m_pProjector->isInitialized(), "Reconstruction2D", "Projector Object Not Initialized.");  	ASTRA_CONFIG_CHECK(m_pSinogram->isInitialized(), "Reconstruction2D", "Projection Data Object Not Initialized.");  	ASTRA_CONFIG_CHECK(m_pReconstruction->isInitialized(), "Reconstruction2D", "Reconstruction Data Object Not Initialized.");  	// check compatibility between projector and data classes -	ASTRA_CONFIG_CHECK(m_pSinogram->getGeometry()->isEqual(m_pProjector->getProjectionGeometry()), "Reconstruction2D", "Projection Data not compatible with the specified Projector."); -	ASTRA_CONFIG_CHECK(m_pReconstruction->getGeometry()->isEqual(m_pProjector->getVolumeGeometry()), "Reconstruction2D", "Reconstruction Data not compatible with the specified Projector."); +	if (requiresProjector()) { +		ASTRA_CONFIG_CHECK(m_pSinogram->getGeometry()->isEqual(m_pProjector->getProjectionGeometry()), "Reconstruction2D", "Projection Data not compatible with the specified Projector."); +		ASTRA_CONFIG_CHECK(m_pReconstruction->getGeometry()->isEqual(m_pProjector->getVolumeGeometry()), "Reconstruction2D", "Reconstruction Data not compatible with the specified Projector."); +	}  	// success  	return true; diff --git a/src/VolumeGeometry3D.cpp b/src/VolumeGeometry3D.cpp index a1cf424..3de146f 100644 --- a/src/VolumeGeometry3D.cpp +++ b/src/VolumeGeometry3D.cpp @@ -45,6 +45,7 @@ bool CVolumeGeometry3D::_check()  	ASTRA_CONFIG_CHECK(m_fWindowMinZ < m_fWindowMaxZ, "VolumeGeometry3D", "WindowMinZ should be lower than WindowMaxZ.");  	ASTRA_CONFIG_CHECK(m_iGridTotCount == (m_iGridColCount * m_iGridRowCount * m_iGridSliceCount), "VolumeGeometry3D", "Internal configuration error."); +#if 0  	ASTRA_CONFIG_CHECK(m_fWindowLengthX == (m_fWindowMaxX - m_fWindowMinX), "VolumeGeometry3D", "Internal configuration error.");  	ASTRA_CONFIG_CHECK(m_fWindowLengthY == (m_fWindowMaxY - m_fWindowMinY), "VolumeGeometry3D", "Internal configuration error.");  	ASTRA_CONFIG_CHECK(m_fWindowLengthZ == (m_fWindowMaxZ - m_fWindowMinZ), "VolumeGeometry3D", "Internal configuration error."); @@ -57,6 +58,7 @@ bool CVolumeGeometry3D::_check()  	ASTRA_CONFIG_CHECK(m_fDivPixelLengthX == (1.0f / m_fPixelLengthX), "VolumeGeometry3D", "Internal configuration error.");  	ASTRA_CONFIG_CHECK(m_fDivPixelLengthY == (1.0f / m_fPixelLengthY), "VolumeGeometry3D", "Internal configuration error.");  	ASTRA_CONFIG_CHECK(m_fDivPixelLengthZ == (1.0f / m_fPixelLengthZ), "VolumeGeometry3D", "Internal configuration error."); +#endif  	return true;  }  | 
