SimpleRTK: Difference between revisions

From Openrtk
Jump to navigation Jump to search
No edit summary
 
(37 intermediate revisions by 3 users not shown)
Line 1: Line 1:
<span style="color:#ff0000">SimpleRTK has been abandoned since release [https://github.com/SimonRit/RTK/releases/tag/v2.0.0 RTK v2.0.0]. Only python wrappings are available now, see [https://github.com/SimonRit/RTK/blob/master/INSTALLATION.md INSTALLATION.md].</span>
= Introduction =
= Introduction =
SimpleRTK provides a simple interface to RTK in a variety of languages. For now only Python and C# binding have been tested and are supported.
SimpleRTK provides a simple interface to RTK in a variety of languages. For now only Python and C# binding have been tested and are supported but other languages should also work, e.g., R, Ruby and Java. SimpleRTK is provided as part of RTK making it easier to configure, build and use. Note that SimpleRTK is derived from the SimpleITK project for the Insight Toolkit, however it is distributed separately and independently.
SimpleRTK will be provided as part of RTK making it easier to configure, build and use. Note that SimpleRTK is derived from the SimpleITK project for the Insight Toolkit, however it's under its own project.


= Building RTK with SimpleRTK =
= Building RTK with SimpleRTK =
SimpleRTK uses Swig to generate the wrapping for different languages. As the version of Swig should be controlled, SimpleRTK will automatically download the right version of Swig and its dependencies for the different platforms. However you can always point to the installed version of Swig if you'd like to, but this is not recommended.
SimpleRTK uses Swig to generate the wrapping for different languages. As the version of Swig should be controlled, SimpleRTK will automatically download the right version of Swig and its dependencies for the different platforms. However you can always point to the installed version of Swig if you'd like to, but this is not recommended. You will need the development libraries of python (python-devel packages) for the compilation of SimpleRTK to succeed.


Here are the simple steps to build and configure wrapping for RTK:
Here are the simple steps to build and configure wrapping for RTK:
# Run CMake on RTK as you normally do
# Run CMake on RTK as you normally do
# Check the option BUILD_SIMPLERTK (default is OFF)
# Check the option BUILD_SIMPLERTK (default is OFF)
# Ename WRAP_PYTHON and/or WRAP_CSHARP (On Windows)
# Enable WRAP_PYTHON and/or WRAP_CSHARP (On Windows)
# Configure
# Configure
# Build as usual. Note that building will download the require libraries so you should have an internet connection enabled.
# Build as usual. Note that building will download the require libraries so you should have an internet connection enabled.


Note that the configuration and generation step can take some time as CMake as to generate the necessary classes.
Note that the configuration and generation step can take some time as CMake has to generate the necessary classes.


= Python installation =
= Python installation =
To install a built python package into the system Python, as root run:
To install the built python package into the system Python:


  cd SimpleRTK-build/Wrapping
  cd SimpleRTK-build/Wrapping
  python PythonPackage/setup.py install
  sudo python PythonPackage/setup.py install
 
or, for more recent versions,
 
  cd SimpleRTK-build/Wrapping/Python
  sudo python Packaging/setup.py install
 
The PYTHONPATH variable must be set appropriately to let Python know where the module is. The PATH variable must be set to let the system find the ITK and RTK libraries.
 
If you want to install the built python package to a directory that does not require root privileges (e.g., on a lab cluster), you can specify an install directory, for example with $HOME/mypython and python 2.7:
 
  mkdir -p $HOME/mypython/lib/python2.7/site-packages
  export PYTHONPATH=$HOME/mypython/lib/python2.7/site-packages:$PYTHONPATH
  cd SimpleRTK-build/Wrapping
  python PythonPackage/setup.py install --prefix=$HOME/mypython
 
or, for more recent versions,
 
  cd SimpleRTK-build/Wrapping/Python
  sudo python Packaging/setup.py install --prefix=$HOME/mypython


Alternatively, a Python virtual environment can be created and the distribution installed there.
Alternatively, a Python virtual environment can be created and the distribution installed there.
If you build the "dist" target a Python egg will be created in the "Wrapping/dist" directory. Building Python wheels can be enabled with a CMake flag.  
If you build the "dist" target a Python egg will be created in the "Wrapping/dist" directory. Building Python wheels can be enabled with a CMake flag.
 
= Generating Python Wheels =
SimpleRTK can be packaged for PIP (http://pythonwheels.com/). In order to do so, please follow the following instructions:
 
== Windows ==
# Compile SimpleRTK as usual
# Open the project solution file in the RTK-bin/SimpleRTK-build/SimpleRTK.sln
# Compile the dist target
# SimpleRTK-*.whl file is generated in the Wrapping/Python/build directory
 
== Linux ==
* Compile SimpleRTK as usual
* Run the following commands:
  cd RTK-bin/SimpleRTK-build
  make dist
* If necessary you might want to use Python virtual environment for generating the packages
  ccmake .
  Turn SRTK_PYTHON_USE_VIRTUALENV to ON
  make
  make dist
* The package are generated in the SimpleRTK-build/Wrapping/Python/dist directory


= Testing SimpleRTK =
= Testing SimpleRTK =
Line 35: Line 76:
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.cm as cm
 
if len ( sys.argv ) < 2:
if len ( sys.argv ) < 2:
     print( "Usage: RTKFirstReconstruction <output>" )
     print( "Usage: RTKFirstReconstruction <output>" )
     sys.exit ( 1 )
     sys.exit ( 1 )
 
# Defines the RTK geometry object
# Defines the RTK geometry object
geometry = srtk.ThreeDimCircularProjectionGeometry()
geometry = srtk.ThreeDCircularProjectionGeometry()
numberOfProjections = 360
numberOfProjections = 360
firstAngle = 0
firstAngle = 0
Line 52: Line 93:
   angle = firstAngle + x * angularArc / numberOfProjections
   angle = firstAngle + x * angularArc / numberOfProjections
   geometry.AddProjection(sid,sdd,angle,isox,isoy)
   geometry.AddProjection(sid,sdd,angle,isox,isoy)
 
constantImageSource = srtk.ConstantImageSource()
constantImageSource = srtk.ConstantImageSource()
origin = [ -127.5, -127.5, 0. ]
origin = [ -127.5, -127.5, 0. ]
Line 62: Line 103:
constantImageSource.SetConstant(0.0)
constantImageSource.SetConstant(0.0)
source = constantImageSource.Execute()
source = constantImageSource.Execute()
 
rei = srtk.RayEllipsoidIntersectionImageFilter()
rei = srtk.RayEllipsoidIntersectionImageFilter()
semiprincipalaxis = [ 50, 50, 50]
semiprincipalaxis = [ 50, 50, 50]
Line 73: Line 114:
rei.SetGeometry( geometry )
rei.SetGeometry( geometry )
reiImage = rei.Execute(source)
reiImage = rei.Execute(source)
 
 
# Create reconstructed image
# Create reconstructed image
constantImageSource2 = srtk.ConstantImageSource()
constantImageSource2 = srtk.ConstantImageSource()
Line 84: Line 124:
constantImageSource2.SetConstant(0.0)
constantImageSource2.SetConstant(0.0)
source2 = constantImageSource2.Execute()
source2 = constantImageSource2.Execute()
 
print("Performing reconstruction")
print("Performing reconstruction")
feldkamp = srtk.FDKConeBeamReconstructionFilter()
feldkamp = srtk.FDKConeBeamReconstructionFilter()
Line 91: Line 131:
feldkamp.SetHannCutFrequency(0.0);
feldkamp.SetHannCutFrequency(0.0);
image = feldkamp.Execute(source2,reiImage)  
image = feldkamp.Execute(source2,reiImage)  
 
 
pixelID = image.GetPixelIDValue()
print("Masking field-of-view")
fov = srtk.FieldOfViewImageFilter()
fov.SetGeometry(geometry)
fov.SetProjectionsStack(reiImage)
image = fov.Execute(image)


plt.imshow(srtk.GetArrayFromImage(image[:,64,:]), cmap = cm.Greys_r)
plt.imshow(srtk.GetArrayFromImage(image[:,64,:]), cmap = cm.Greys_r)
 
plt.show()
caster = srtk.CastImageFilter()
caster.SetOutputPixelType( pixelID )
image = caster.Execute( image )


writer = srtk.ImageFileWriter()
writer = srtk.ImageFileWriter()
Line 110: Line 151:


= SimpleRTK with SimpleITK =
= SimpleRTK with SimpleITK =
Even if SimpleRTK is based on SimpleRTK, the basic object types (images, transforms) are different and there is no direct compatibility between the two toolkits. However it is fairly straightforward to pass the data from RTK to ITK using the following example:
Even if SimpleRTK is based on SimpleITK, the basic object types (images, transforms) are different and there is no direct compatibility between the two toolkits. However, it is fairly straightforward to pass the image data from RTK to ITK using the following example


   sitk.GetImageFromArray( srtk.GetArrayFromImage( image ) )
   sitk.GetImageFromArray( srtk.GetArrayFromImage( image ) )
 
but meta-information (spacing, origin, direction, etc.) is then discarded. If you need the information, you can use the function
 
  sitkImage.CopyInformation( source )


= Extending SimpleRTK =
= Extending SimpleRTK =
Adding new classes to SimpleRTK should be fairly straightforward. In this section we cover how to add common types as well as filters. Note that common types should only be added when necessary.
Adding new classes to SimpleRTK should be fairly straightforward. In this section, we cover how to add common types as well as filters. Note that common types should only be added when necessary.


The file locate in Wrapping/SimpleRTK.i is the main SWIG file and new types and manually wrapped files should be added there.
The file located in Wrapping/SimpleRTK.i is the main SWIG file and new types and manually wrapped files should be added there.


== Common Type ==
== Common Type ==
One example is for the ThreeDCircularProjectionGeometry object. The code is located in utilities/SimpleRTK/Code/Common.
One example is for the ThreeDCircularProjectionGeometry object. The code is located in utilities/SimpleRTK/Code/Common.
Note that the class is named srtkThreeDimCircularProjectionGeometry to avoid some conflicting type resolution by Swig (this could be tricky).
This class in the namespace rtk::simple provides a PIMPL class implementation of the object as well as a conversion from SimpleRTK to RTK itself to expose the necessary functions.
This class in the namespace rtk::simple provides a PIMPL class implementation of the object as well as a conversion from SimpleRTK to RTK itself to expose the necessary functions.


Line 132: Line 176:
   # Name of the class to be create. This would be prefixed by srtk.  
   # Name of the class to be create. This would be prefixed by srtk.  
   "name" : "FDKConeBeamReconstructionFilter",
   "name" : "FDKConeBeamReconstructionFilter",
   # File that indicates the template to use. This should be RTKImageFilter for image filters
   # File that indicates the template to use. This should be RTKImageFilter for image filters
   "template_code_filename" : "RTKImageFilter",
   "template_code_filename" : "RTKImageFilter",
   # File that indicates the template to use for the test.
   # File that indicates the template to use for the test.
   "template_test_filename" : "ImageFilter",
   "template_test_filename" : "ImageFilter",
   # Number of inputs to the filter.
   # Number of inputs to the filter.
   "number_of_inputs" : 2,
   "number_of_inputs" : 2,
  # Documentation for the class, if any.
   "doc" : "",
   "doc" : "",
   # Type of output image. This creates a typedef OutputImageType. Here we set it to the input image.
   # Type of output image. This creates a typedef OutputImageType. Here we set it to the input image.
   "output_image_type" : "TImageType",
   "output_image_type" : "TImageType",
   # List of supported Pixel types
   # List of supported Pixel types
   "pixel_types" : "RealPixelIDTypeList",
   "pixel_types" : "RealPixelIDTypeList",
   # Definition of the RTK filter
   # Definition of the RTK filter
   "filter_type" : "rtk::FDKConeBeamReconstructionFilter<InputImageType>",
   "filter_type" : "rtk::FDKConeBeamReconstructionFilter<InputImageType>",
   # Array of include files.
   # Array of include files.
   "include_files" : [
   "include_files" : [
     "srtkThreeDimCircularProjectionGeometry.h"
     "srtkThreeDCircularProjectionGeometry.h"
   ],
   ],
</source>
</source>
The next section describes the member functions.
 
The next section describes the member functions. Each member function has a name and a type.
The Set...() and Get...() functions are automatically generated.
 
<source lang="javascript">
<source lang="javascript">
   "members" : [
   "members" : [
{
    {
      # Name of the variable to be Set/Get
       "name" : "Geometry",
       "name" : "Geometry",
       "type" : "ThreeDimCircularProjectionGeometry*",
 
      # Type of the variable
       "type" : "ThreeDCircularProjectionGeometry*",
 
      # Default value of the variable
       "default" : "0",
       "default" : "0",
  "itk_type" : "ThreeDimCircularProjectionGeometry",
     
      # Internal Simple RTK type of the function
      "itk_type" : "ThreeDCircularProjectionGeometry",
 
      # Casting from the itk_type to the internal type
       "custom_itk_cast" : "filter->SetGeometry( this->m_Geometry->GetRTKBase() );\n",
       "custom_itk_cast" : "filter->SetGeometry( this->m_Geometry->GetRTKBase() );\n",
      # Documentation for the member function
       "doc" : "",
       "doc" : "",
       "briefdescriptionSet" : "",
       "briefdescriptionSet" : "",
Line 164: Line 231:
       "briefdescriptionGet" : "",
       "briefdescriptionGet" : "",
       "detaileddescriptionGet" : "Get the object pointer to projection geometry."
       "detaileddescriptionGet" : "Get the object pointer to projection geometry."
    },
    {
      "name" : "TruncationCorrection",
      "type" : "double",
      "default" : "0.0",
  "custom_itk_cast" : "filter->GetRampFilter()->SetTruncationCorrection( this->m_TruncationCorrection );\n",
      "briefdescriptionSet" : "",
      "detaileddescriptionSet" : "Set the percentage of the image widthfeathered with data to correct for truncation.",
      "briefdescriptionGet" : "",
      "detaileddescriptionGet" : "Get he percentage of the image widthfeathered with data to correct for truncation."
    }
{
      "name" : "HannCutFrequency",
      "type" : "double",
      "default" : "0.0",
  "custom_itk_cast" : "filter->GetRampFilter()->SetHannCutFrequency( this->m_HannCutFrequency );\n",
      "briefdescriptionSet" : "",
      "detaileddescriptionSet" : "Set the Hann window frequency.",
      "briefdescriptionGet" : "",
      "detaileddescriptionGet" : "Get the Hann window frequency."
     }
     }
   ],
   ],
</source>
At the end of the file we add the description of the class for documentation purposes.
<source lang="javascript">
   "briefdescription" : "Brief description of the filter",
   "briefdescription" : "Brief description of the filter",
   "detaileddescription" : "Detailed description of the filter"
   "detaileddescription" : "Detailed description of the filter"
Line 191: Line 243:
</source>
</source>


'''Note that you might need to rebuild the solution in order for CMake to take the changes into account.'''
'''Note that you might need to rebuild the solution in order for CMake to take the changes into account.''' Another solution is to manually delete the file  SimpleRTK-prefix/src/SimpleRTK-stamp/SimpleRTK-configure.
The code generated is located in the "SimpleRTK-build/Code/BasicFilters" of your build tree.
 
= Matlab =
SimpleRTK does not include Matlab wrappings. However, Matlab allows [http://fr.mathworks.com/help/matlab/call-python-libraries.html calling Python libraries] since recent versions. This is a simple example written to simulate and display a sinogram in Matlab:
 
<source lang="matlab">
g = py.SimpleRTK.ThreeDCircularProjectionGeometry();
for i=0:359,
    g.AddProjection(500,1000,i);
end
 
size = [512,1,360];
 
const = py.SimpleRTK.ConstantImageSource();
const.SetSpacing(py.list([1,1,1]))
const.SetSize(py.list(int32(size)))
const.SetOrigin(py.list([-255.5,0,0]))
proj = const.Execute()
 
sl = py.SimpleRTK.SheppLoganPhantomFilter()
sl.SetPhantomScale(80)
sl.SetGeometry(g)
proj = sl.Execute(proj)
npproj = py.SimpleRTK.GetArrayFromImage(proj)
 
proj = double(py.array.array('d', npproj.flatten()));
 
imagesc(squeeze(reshape(proj, size)))
colormap gray
</source>
 
The above example in Python has been translated in Matlab:
<source lang="matlab">
geo = py.SimpleRTK.ThreeDCircularProjectionGeometry();
angularArc = 360;
sid = 600;
sdd = 1200;
for i=0:359,
    angle = i * angularArc / 360;
    geo.AddProjection(sid, sdd, angle);
end
 
origin = py.list([ -127.5, -127.5, 0]);
sizeOutput = py.list(int32([ 256, 256, 360]));
spacing = py.list([1.0, 1.0, 1.0]);
 
cstImgSrc = py.SimpleRTK.ConstantImageSource();
cstImgSrc.SetOrigin(origin);
cstImgSrc.SetSpacing(spacing);
cstImgSrc.SetSize(sizeOutput);
cstImgSrc.SetConstant(0.0);
source = cstImgSrc.Execute();
 
 
rei = py.SimpleRTK.RayEllipsoidIntersectionImageFilter();
semiprincipalaxis = py.list([50, 50, 50]);
center = py.list([0, 0, 0]);
rei.SetDensity(20);
rei.SetAngle(0);
rei.SetCenter(center);
rei.SetAxis(semiprincipalaxis);
rei.SetGeometry(geo);
reiImage = rei.Execute(source);
 
constantImageSource2 = py.SimpleRTK.ConstantImageSource();
origin = py.list([ -63.5, -63.5, -63.5]);
sizeOutput = py.list(int32([ 128, 128, 128 ]));
 
constantImageSource2.SetOrigin(origin);
constantImageSource2.SetSpacing(spacing);
constantImageSource2.SetSize(sizeOutput);
constantImageSource2.SetConstant(0.0);
source2 = constantImageSource2.Execute();
 
feldkamp = py.SimpleRTK.FDKConeBeamReconstructionFilter();
feldkamp.SetGeometry(geo);
feldkamp.SetTruncationCorrection(0.0);
feldkamp.SetHannCutFrequency(0.0);
image = feldkamp.Execute(source2, reiImage);
 
fov = py.SimpleRTK.FieldOfViewImageFilter();
fov.SetGeometry(geo);
fov.SetProjectionsStack(reiImage);
image = fov.Execute(image);
 
nppImage = py.SimpleRTK.GetArrayFromImage(image);
 
image = double(py.array.array('d', nppImage.flatten()));
image = reshape(image, [ 128, 128, 128]);
 
imagesc(squeeze(image(64,:,:)));
colormap gray
axis square
</source>

Latest revision as of 15:28, 30 March 2020

SimpleRTK has been abandoned since release RTK v2.0.0. Only python wrappings are available now, see INSTALLATION.md.

Introduction

SimpleRTK provides a simple interface to RTK in a variety of languages. For now only Python and C# binding have been tested and are supported but other languages should also work, e.g., R, Ruby and Java. SimpleRTK is provided as part of RTK making it easier to configure, build and use. Note that SimpleRTK is derived from the SimpleITK project for the Insight Toolkit, however it is distributed separately and independently.

Building RTK with SimpleRTK

SimpleRTK uses Swig to generate the wrapping for different languages. As the version of Swig should be controlled, SimpleRTK will automatically download the right version of Swig and its dependencies for the different platforms. However you can always point to the installed version of Swig if you'd like to, but this is not recommended. You will need the development libraries of python (python-devel packages) for the compilation of SimpleRTK to succeed.

Here are the simple steps to build and configure wrapping for RTK:

  1. Run CMake on RTK as you normally do
  2. Check the option BUILD_SIMPLERTK (default is OFF)
  3. Enable WRAP_PYTHON and/or WRAP_CSHARP (On Windows)
  4. Configure
  5. Build as usual. Note that building will download the require libraries so you should have an internet connection enabled.

Note that the configuration and generation step can take some time as CMake has to generate the necessary classes.

Python installation

To install the built python package into the system Python:

 cd SimpleRTK-build/Wrapping
 sudo python PythonPackage/setup.py install

or, for more recent versions,

cd SimpleRTK-build/Wrapping/Python
sudo python Packaging/setup.py install

The PYTHONPATH variable must be set appropriately to let Python know where the module is. The PATH variable must be set to let the system find the ITK and RTK libraries.

If you want to install the built python package to a directory that does not require root privileges (e.g., on a lab cluster), you can specify an install directory, for example with $HOME/mypython and python 2.7:

 mkdir -p $HOME/mypython/lib/python2.7/site-packages
 export PYTHONPATH=$HOME/mypython/lib/python2.7/site-packages:$PYTHONPATH
 cd SimpleRTK-build/Wrapping
 python PythonPackage/setup.py install --prefix=$HOME/mypython

or, for more recent versions,

 cd SimpleRTK-build/Wrapping/Python
 sudo python Packaging/setup.py install --prefix=$HOME/mypython

Alternatively, a Python virtual environment can be created and the distribution installed there. If you build the "dist" target a Python egg will be created in the "Wrapping/dist" directory. Building Python wheels can be enabled with a CMake flag.

Generating Python Wheels

SimpleRTK can be packaged for PIP (http://pythonwheels.com/). In order to do so, please follow the following instructions:

Windows

  1. Compile SimpleRTK as usual
  2. Open the project solution file in the RTK-bin/SimpleRTK-build/SimpleRTK.sln
  3. Compile the dist target
  4. SimpleRTK-*.whl file is generated in the Wrapping/Python/build directory

Linux

  • Compile SimpleRTK as usual
  • Run the following commands:
 cd RTK-bin/SimpleRTK-build
 make dist
  • If necessary you might want to use Python virtual environment for generating the packages
 ccmake .
 Turn SRTK_PYTHON_USE_VIRTUALENV to ON
 make
 make dist
  • The package are generated in the SimpleRTK-build/Wrapping/Python/dist directory

Testing SimpleRTK

A simple example is located in Utilities/SimpleRTK/Examples/RTKFirstReconstruction.py and shows how to use SimpleRTK

#!/usr/bin/env python
from __future__ import print_function
import SimpleRTK as srtk
import sys
import os
import matplotlib.pyplot as plt
import matplotlib.cm as cm
 
if len ( sys.argv ) < 2:
    print( "Usage: RTKFirstReconstruction <output>" )
    sys.exit ( 1 )
 
# Defines the RTK geometry object
geometry = srtk.ThreeDCircularProjectionGeometry()
numberOfProjections = 360
firstAngle = 0
angularArc = 360
sid = 600 # source to isocenter distance in mm
sdd = 1200 # source to detector distance in mm
isox = 0 # X coordinate on the projection image of isocenter
isoy = 0 # Y coordinate on the projection image of isocenter
for x in range(0,numberOfProjections):
  angle = firstAngle + x * angularArc / numberOfProjections
  geometry.AddProjection(sid,sdd,angle,isox,isoy)
 
constantImageSource = srtk.ConstantImageSource()
origin = [ -127.5, -127.5, 0. ]
sizeOutput = [ 256, 256,  numberOfProjections ]
spacing = [ 1.0, 1.0, 1.0 ]
constantImageSource.SetOrigin( origin )
constantImageSource.SetSpacing( spacing )
constantImageSource.SetSize( sizeOutput )
constantImageSource.SetConstant(0.0)
source = constantImageSource.Execute()
 
rei = srtk.RayEllipsoidIntersectionImageFilter()
semiprincipalaxis = [ 50, 50, 50]
center = [ 0, 0, 0]
# Set GrayScale value, axes, center...
rei.SetDensity(20)
rei.SetAngle(0)
rei.SetCenter(center)
rei.SetAxis(semiprincipalaxis)
rei.SetGeometry( geometry )
reiImage = rei.Execute(source)
 
# Create reconstructed image
constantImageSource2 = srtk.ConstantImageSource()
origin = [ -63.5, -63.5, -63.5 ]
sizeOutput = [ 128, 128, 128 ]
constantImageSource2.SetOrigin( origin )
constantImageSource2.SetSpacing( spacing )
constantImageSource2.SetSize( sizeOutput )
constantImageSource2.SetConstant(0.0)
source2 = constantImageSource2.Execute()
 
print("Performing reconstruction")
feldkamp = srtk.FDKConeBeamReconstructionFilter()
feldkamp.SetGeometry( geometry );
feldkamp.SetTruncationCorrection(0.0);
feldkamp.SetHannCutFrequency(0.0);
image = feldkamp.Execute(source2,reiImage) 

print("Masking field-of-view")
fov = srtk.FieldOfViewImageFilter()
fov.SetGeometry(geometry)
fov.SetProjectionsStack(reiImage)
image = fov.Execute(image)

plt.imshow(srtk.GetArrayFromImage(image[:,64,:]), cmap = cm.Greys_r)
plt.show()

writer = srtk.ImageFileWriter()
writer.SetFileName ( sys.argv[1] )
writer.Execute ( image );

The example displays the central slice of a reconstructed sphere:

Error creating thumbnail: File missing

SimpleRTK with SimpleITK

Even if SimpleRTK is based on SimpleITK, the basic object types (images, transforms) are different and there is no direct compatibility between the two toolkits. However, it is fairly straightforward to pass the image data from RTK to ITK using the following example

 sitk.GetImageFromArray( srtk.GetArrayFromImage( image ) )

but meta-information (spacing, origin, direction, etc.) is then discarded. If you need the information, you can use the function

 sitkImage.CopyInformation( source )

Extending SimpleRTK

Adding new classes to SimpleRTK should be fairly straightforward. In this section, we cover how to add common types as well as filters. Note that common types should only be added when necessary.

The file located in Wrapping/SimpleRTK.i is the main SWIG file and new types and manually wrapped files should be added there.

Common Type

One example is for the ThreeDCircularProjectionGeometry object. The code is located in utilities/SimpleRTK/Code/Common. This class in the namespace rtk::simple provides a PIMPL class implementation of the object as well as a conversion from SimpleRTK to RTK itself to expose the necessary functions.

Filters

Filters are implemented using a json description for simplicity. The best way is to look into already wrapped filters in the: utilities/SimpleRTK/Code/BasicFilters/json directory.

Here we provide a description of the current JSON format.

{
  # Name of the class to be create. This would be prefixed by srtk. 
  "name" : "FDKConeBeamReconstructionFilter",

  # File that indicates the template to use. This should be RTKImageFilter for image filters
  "template_code_filename" : "RTKImageFilter",

  # File that indicates the template to use for the test.
  "template_test_filename" : "ImageFilter",

  # Number of inputs to the filter.
  "number_of_inputs" : 2,

  # Documentation for the class, if any.
  "doc" : "",

  # Type of output image. This creates a typedef OutputImageType. Here we set it to the input image.
  "output_image_type" : "TImageType",

  # List of supported Pixel types
  "pixel_types" : "RealPixelIDTypeList",

  # Definition of the RTK filter
  "filter_type" : "rtk::FDKConeBeamReconstructionFilter<InputImageType>",

  # Array of include files.
  "include_files" : [
    "srtkThreeDCircularProjectionGeometry.h"
  ],

The next section describes the member functions. Each member function has a name and a type. The Set...() and Get...() functions are automatically generated.

  "members" : [
    {
      # Name of the variable to be Set/Get
      "name" : "Geometry",

      # Type of the variable
      "type" : "ThreeDCircularProjectionGeometry*",

      # Default value of the variable
      "default" : "0",
      
      # Internal Simple RTK type of the function
      "itk_type" : "ThreeDCircularProjectionGeometry",

      # Casting from the itk_type to the internal type
      "custom_itk_cast" : "filter->SetGeometry( this->m_Geometry->GetRTKBase() );\n",

      # Documentation for the member function
      "doc" : "",
      "briefdescriptionSet" : "",
      "detaileddescriptionSet" : "Set the object pointer to projection geometry.",
      "briefdescriptionGet" : "",
      "detaileddescriptionGet" : "Get the object pointer to projection geometry."
    }
  ],

At the end of the file we add the description of the class for documentation purposes.

  "briefdescription" : "Brief description of the filter",
  "detaileddescription" : "Detailed description of the filter"
  }

Note that you might need to rebuild the solution in order for CMake to take the changes into account. Another solution is to manually delete the file SimpleRTK-prefix/src/SimpleRTK-stamp/SimpleRTK-configure. The code generated is located in the "SimpleRTK-build/Code/BasicFilters" of your build tree.

Matlab

SimpleRTK does not include Matlab wrappings. However, Matlab allows calling Python libraries since recent versions. This is a simple example written to simulate and display a sinogram in Matlab:

g = py.SimpleRTK.ThreeDCircularProjectionGeometry();
for i=0:359,
    g.AddProjection(500,1000,i);
end

size = [512,1,360];

const = py.SimpleRTK.ConstantImageSource();
const.SetSpacing(py.list([1,1,1]))
const.SetSize(py.list(int32(size)))
const.SetOrigin(py.list([-255.5,0,0]))
proj = const.Execute()

sl = py.SimpleRTK.SheppLoganPhantomFilter()
sl.SetPhantomScale(80)
sl.SetGeometry(g)
proj = sl.Execute(proj)
npproj = py.SimpleRTK.GetArrayFromImage(proj)

proj = double(py.array.array('d', npproj.flatten()));

imagesc(squeeze(reshape(proj, size)))
colormap gray

The above example in Python has been translated in Matlab:

geo = py.SimpleRTK.ThreeDCircularProjectionGeometry();
angularArc = 360;
sid = 600; 
sdd = 1200;
for i=0:359,
    angle = i * angularArc / 360;
    geo.AddProjection(sid, sdd, angle);
end

origin = py.list([ -127.5, -127.5, 0]);
sizeOutput = py.list(int32([ 256, 256, 360]));
spacing = py.list([1.0, 1.0, 1.0]);

cstImgSrc = py.SimpleRTK.ConstantImageSource();
cstImgSrc.SetOrigin(origin);
cstImgSrc.SetSpacing(spacing);
cstImgSrc.SetSize(sizeOutput);
cstImgSrc.SetConstant(0.0);
source = cstImgSrc.Execute();


rei = py.SimpleRTK.RayEllipsoidIntersectionImageFilter();
semiprincipalaxis = py.list([50, 50, 50]);
center = py.list([0, 0, 0]);
rei.SetDensity(20);
rei.SetAngle(0);
rei.SetCenter(center);
rei.SetAxis(semiprincipalaxis);
rei.SetGeometry(geo);
reiImage = rei.Execute(source);

constantImageSource2 = py.SimpleRTK.ConstantImageSource();
origin = py.list([ -63.5, -63.5, -63.5]);
sizeOutput = py.list(int32([ 128, 128, 128 ]));

constantImageSource2.SetOrigin(origin);
constantImageSource2.SetSpacing(spacing);
constantImageSource2.SetSize(sizeOutput);
constantImageSource2.SetConstant(0.0);
source2 = constantImageSource2.Execute();

feldkamp = py.SimpleRTK.FDKConeBeamReconstructionFilter();
feldkamp.SetGeometry(geo);
feldkamp.SetTruncationCorrection(0.0);
feldkamp.SetHannCutFrequency(0.0);
image = feldkamp.Execute(source2, reiImage);

fov = py.SimpleRTK.FieldOfViewImageFilter();
fov.SetGeometry(geo);
fov.SetProjectionsStack(reiImage);
image = fov.Execute(image);

nppImage = py.SimpleRTK.GetArrayFromImage(image);

image = double(py.array.array('d', nppImage.flatten()));
image = reshape(image, [ 128, 128, 128]);

imagesc(squeeze(image(64,:,:)));
colormap gray
axis square