Do Not Ignore the ASTRA Toolbox!

ASTRA logoASTRA logo.

If you are into computed tomography (CT) from the perspective of algorithm development, or if you want to do the reconstruction yourself instead of using a standard software package (e.g., the one that was included with your scanner), you cannot ignore the ASTRA Tomography Toolbox. Well, I am confident you can, if you put your mind to it, but you shouldn’t. This toolbox is developed by the ASTRA research group (“All Scale Tomographic Reconstruction Antwerp”) of the Vision Lab of the University of Antwerp, together with the Computational Imaging group of the Centrum Wiskunde & Informatica (CWI). Full disclosure: I work at the Vision Lab as a postdoc. However, this article is not sponsored or endorsed by the Vision Lab, it is purely my own opinion.

Quoting from the official description:

It supports 2D parallel and fan beam geometries, and 3D parallel and cone beam. All of them have highly flexible source/detector positioning. A large number of 2D and 3D algorithms are available, including FBP, SIRT, SART, and CGLS. The basic forward and backward projection operations are GPU-accelerated, and directly callable from MATLAB to enable building new algorithms.

During my own PhD research, I have used the ASTRA Toolbox for algorithm development. Because the Toolbox provides GPU implementations of basic components such as projectors, I could use GPU processing already during the experimental stage, allowing me to use real-world (i.e., large) datasets during testing. This is not obvious, since it is often only when an algorithm is complete that a GPU version is written, restricting initial testing to the aptly named academic examples.

MATLAB Wrapper

First of all, to put your mind at rest if you are not a hardcore programmer, the ASTRA Toolbox comes with a user-friendly MATLAB wrapper. All functionality of the Toolbox is available from MATLAB. Since MATLAB is the main way to use the Toolbox, I’ll leave you in the good hands of the official documentation for that, and add an example of my own below that uses the contributed Python wrapper.

Python Wrapper

If you are more of a Python person, there is also a Python wrapper. As an example, I’ve written a Python script that recreates the example with the two white squares on the Wikipedia page on the Radon transform (and additionally also reconstructs the sinogram). The example shows that you can do a lot with only a few lines of code. To keep things brief, there are not a lot of comments, but there are more detailed examples for each part of this script in the samples directory of the Toolbox.

import numpy as np
from scipy import misc
 
import astra
 
# Create phantom.
phantom = np.zeros((128, 128))
phantom[32 : 64, 32 : 64] = np.ones((32, 32))
phantom[64 : 96, 64 : 96] = np.ones((32, 32))
misc.imsave('phantom.png', phantom)
 
# Create geometries and projector.
vol_geom = astra.create_vol_geom(128, 128)
angles = np.linspace(0, np.pi, 180, endpoint=False)
proj_geom = astra.create_proj_geom('parallel', 1., 128, angles)
projector_id = astra.create_projector('linear', proj_geom, vol_geom)
 
# Create sinogram.
sinogram_id, sinogram = astra.create_sino(phantom, projector_id)
misc.imsave('sinogram.png', sinogram)
 
# Create reconstruction.
reconstruction_id = astra.data2d.create('-vol', vol_geom)
cfg = astra.astra_dict('SIRT')
cfg['ReconstructionDataId'] = reconstruction_id
cfg['ProjectionDataId'] = sinogram_id
cfg['ProjectorId'] = projector_id
cfg['option'] = {}
cfg['option']['MinConstraint'] = 0.  # Force solution to be nonnegative.
algorithm_id = astra.algorithm.create(cfg)
astra.algorithm.run(algorithm_id, 100)  # 100 iterations.
reconstruction = astra.data2d.get(reconstruction_id)
misc.imsave('reconstruction.png', reconstruction)
 
# Cleanup.
astra.algorithm.delete(algorithm_id)
astra.data2d.delete(reconstruction_id)
astra.data2d.delete(sinogram_id)
astra.projector.delete(projector_id)

The output of this script is shown below. On the left is the phantom with the two white squares. In the middle is the sinogram, which contains a (2D) projection in each horizontal line. From this sinogram, the reconstruction on the right was created through the algebraic algorithm SIRT.

Phantom (left), sinogram (middle), and reconstruction (right)Phantom (left), sinogram (middle), and reconstruction (right)

For more information on tomography itself, have a look at my series of articles on that subject. There is also a tutorial on creating a 3D reconstruction from 2D cone-beam projections that you might find interesting if you are working with your own datasets.

[update] This post was selected for Writing Clinic at DailyBlogTips! As a result, I was able to make several improvements to the text. Thanks again, Ali!

[update 2] Updated the homepage of the Toolbox; added CWI as a developer; reformulated the text to reflect that the Python wrapper is now an integral part of the Toolbox, instead of a contributed module.

Alex (not verified)

Thu, 02/25/2016 - 15:42

I'm pretty new to using a lot of external libraries in python. My question is, I've downloaded the files for PyASTRA, but I only see install instructions for windows and linux. Do you know if it's possible to install them and use them on an OS X machine?

I’m sorry to have to inform you that OS X is not supported at this time… On a separate note, you don’t have to download the Python interface separately anymore, since it is included in the main ASTRA Toolbox since version 1.6.

D M BAPPY (not verified)

Mon, 04/11/2016 - 13:53

hello
I have some 2D X-ray images of an aluminium model. I want to get the cross sectional CT image of that model. Is it possible using this software? If possible then how?

Tom

Mon, 04/11/2016 - 16:49

In reply to by D M BAPPY (not verified)

If your data is suitable for CT reconstruction, i.e., if you have a sufficient number of images that were taken with a CT scanner, or at least with a fixed source and detector and a rotating stage, then this should be relatively easy. I would like to point you to the examples that are included with the ASTRA Toolbox. Also note that your images must be preprocessed to make them true projections, as I explain in my series of articles on tomography. If your data consists of only a few images, or was taken with unknown source and detector positions, then it will be much more difficult or even impossible.

Thank you for your answer. I have all the information about detector positions and also all the X-ray images as well. But the problem is i got confused about ASTRA toolbox. Inside the toolbox all the examples used a single phantom and than rotate it to different directions. But my question is, how i can use all the available projections for CT reconstruction. I mean i want to use a series of images rather than using a single image and rotate is to different directions. Really waiting for your response.

The examples in the Toolbox often start from a phantom to create a dataset. Of course, you already have a dataset, and only need the second part of the example. It might also be confusing that the examples are often in 2D, where the “X-ray images” are then 1D, and grouped in a so-called sinogram. You could create a sinogram like that from your data by taking a single row from each of them, but it’s probably easier to immediately create a 3D reconstruction. Another tip is that, if your dataset was recorded using a typical source and a flat-panel detector, you’ll probably need to use a cone-beam geometry (and not a parallel-beam one).

PauM (not verified)

Fri, 12/16/2016 - 15:48

Hi, great toolbox!!
I was wondering if it is possible to perform 3D conebeam reconstructions without GPU. I've only found the functions for GPU. Thanks in advance!

Thanks! It is indeed not possible to perform 3D cone beam reconstructions without a GPU, because there are no CPU versions of the 3D algorithms in the Toolbox. And, of course, for cone beam you cannot run a 2D algorithm on a slice-by-slice basis like you can do for parallel beam…

Hi !

Thanks for your very nice webpage. I am discovering the astra toolbox and I was wondering how to use it (for 3D cone beam) in colab ?

Thanks in advance,
Stephane

PauC (not verified)

Thu, 03/30/2017 - 16:08

In response to D M BAPPY on 4/12/16 you mentioned the examples start from a phantom to create the dataset. I have x-ray images from a flat panel detector and the proj_geom and vol_geom are understood. My question is how to get the projection data into sinograms? All the examples seem to forward project the phantom object to get the sinograms which the reconstruction then uses. I am missing how to get the normalized projection data into a sinogram soa reconstruction can then be made. What am I missing?

PauC (not verified)

Thu, 03/30/2017 - 16:12

I am responding to your response to D M BAPPY on 4/12/16. I have cone beam projections for a flat panel and I have set up proj_geom and vol_geom and that all makes sense. What is not clear is how to get sinograms as the reconstruction needs the sinograms to make the reconstruction. All the examples make the sinograms from forward projection of the object. I don't see how to get sinograms from projection data or how to feed projection data into a reconstruction algorithm. Any clarification for this would let me experiment with real world data. Thanks.

I can see that function names such as "astra_create_sino3d_cuda" might be confusing in this respect. In practice, the 3D volume that these functions produce is simply a stack of images, exactly like the images that you get from a scanner. However, there are also sinograms in the data volume. You get these by slicing the volume in a different direction. Sinograms are typically how projection data is viewed when tomography is done in 2D, so when a single slice is reconstructed. But, in 3D, projection data are just images. Hence, there is no need to create sinograms...

Hi Paul,
Have you find a solution to your problem? I have the same questions about how to feed my 2D projected images into Astra for a cone beam reconstruction. If you have a piece of code to share it would be greatly appreciated. It is strange that people seem to avoid giving realistic examples. We cannot use synthetic images of phantoms all the time!
MRB

I would start from example s007_3d_reconstruction.m and adapt that. First of all, you have to intialize proj_geom with the projection geometry of your data, of course. Then, instead of generating the projections from a phantom using astra_create_sino3d_cuda(), create a projection data object directly using astra_mex_data3d('create', '-proj3d', proj_geom, your_data) (see also example s006_3d_data.m). Does this help?

Hello Tom,
As DM Bappy, PauC and Michel Bouchard, I need to reconstruct data, starting from real projections (Tiff files) produced by a CBCT scanner. I tried to follow your advices without any success. Is it possible to get an exemple of code? Thanks

Okay, you guys have convinced me. I’ll write a new post with an example that starts from projection images. You will have to give me a few weeks to find the time to do that, I’m afraid, but it’ll come!

Bruno (not verified)

Fri, 04/14/2017 - 23:25

Hi,

I'm on Windows 7Pro and I have installed Python 3.6 with Miniconda and right after that the Astra package with
"conda install -c astra-toolbox astra-toolbox"

I'm trying to run your example and it seems I'm missing something from scipy.misc? I'm new with all the Python environment stuff, any idea what I'm missing?

Traceback (most recent call last):
File "D:/Tomo/Test.py", line 11, in
misc.imsave('phantom.png', phantom)
AttributeError: module 'scipy.misc' has no attribute 'imsave'

Regards,

Bruno

Tom

Sun, 04/16/2017 - 12:58

In reply to by Bruno (not verified)

I'm not entirely sure, but I think that you might need to install the SciPy package manually (also using conda install) if you use Miniconda. I always install the full Anaconda package, which comes with may packages preinstalled, including NumPy and SciPy.

I tried with Conda and Python 3.6 but maybe some packages are missing? I think I will try again from scratch with a full Anaconda install. On the Astra documentation page

http://www.astra-toolbox.com/

they say they have Windows binaries for Python 2.7 and 3.5. Thinking about it, it's probably because of I used Python 3.6 that it did not work... Which version of Anaconda Python were you using (2.7, 3.4, 3.5, 3.6 are available)?

Regards,

Bruno

Try recent libraries

import numpy as np
from PIL import Image
import astra

# Create phantom.
phantom = np.zeros((128, 128))
phantom[32 : 64, 32 : 64] = np.ones((32, 32))*200
phantom[64 : 96, 64 : 96] = np.ones((32, 32))*200
Image.fromarray(phantom).convert('RGB').save('phantom.png')

# Create geometries and projector.
vol_geom = astra.create_vol_geom(128, 128)
angles = np.linspace(0, np.pi, 180, endpoint=False)
proj_geom = astra.create_proj_geom('parallel', 1., 128, angles)
projector_id = astra.create_projector('linear', proj_geom, vol_geom)

# Create sinogram.
sinogram_id, sinogram = astra.create_sino(phantom, projector_id)

Image.fromarray(sinogram/sinogram.max()*250).convert('RGB').save('sinogram.png')

# Create reconstruction.
reconstruction_id = astra.data2d.create('-vol', vol_geom)
cfg = astra.astra_dict('SIRT')
cfg['ReconstructionDataId'] = reconstruction_id
cfg['ProjectionDataId'] = sinogram_id
cfg['ProjectorId'] = projector_id
cfg['option'] = {}
cfg['option']['MinConstraint'] = 0. # Force solution to be nonnegative.
algorithm_id = astra.algorithm.create(cfg)
astra.algorithm.run(algorithm_id, 100) # 100 iterations.
reconstruction = astra.data2d.get(reconstruction_id)
Image.fromarray(reconstruction).convert('RGB').save('reconstruction.png')

# Cleanup.
astra.algorithm.delete(algorithm_id)
astra.data2d.delete(reconstruction_id)
astra.data2d.delete(sinogram_id)
astra.projector.delete(projector_id)

Add new comment

The content of this field is kept private and will not be shown publicly.
Spam avoidance measure, sorry for this.

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
Submitted on 22 February 2014