Advent of tomosipo: s002_data2d
Jul 21, 2020
Allard Hendriksen
3 minute read

This is going to be a short post, because data objects are rarely useful in tomosipo.

First, we setup the geometries from the ASTRA code example:

import astra
import tomosipo as ts
import numpy as np

# Create ASTRA geometries
vol_geom = astra.create_vol_geom(256, 256)
angles = np.linspace(0,np.pi,180,False)
proj_geom = astra.create_proj_geom('parallel', 1.0, 384, angles)
# Create tomosipo geometries
vg = ts.volume(shape=(1, 256, 256))
pg = ts.parallel(angles=180, shape=(1, 384))

Transcribing the example

Creating data

ASTRA works with data objects that must be created before use and freed after use. This script creates some data objects:

# Create volumes
# initialized to zero
v0 = astra.data2d.create('-vol', vol_geom)
# initialized to 3.0
v1 = astra.data2d.create('-vol', vol_geom, 3.0)
# initialized to a matrix. A may be a single, double or logical (0/1) array.
array = np.random.normal(size=(256,256))
v2 = astra.data2d.create('-vol', vol_geom, array)

# Projection data
s0 = astra.data2d.create('-sino', proj_geom)
# Initialization to a scalar or a matrix also works, exactly as with a volume.

The same can be accomplished in tomosipo:

# Create a 3D data object initialized to zero
vd0 =
# Initialized to 3.0:
vd1 =, 3.0)
# Initialized to a 3D array:
array64 = np.random.normal(size=(1, 256, 256))
vd2 =, array64)
# The previous code issues a warning, because array contains float64 values.
# ASTRA operates only on float32 values. The array has been copied and converted
# to 32 bits.

# This code does not issue warnings:
array32 = array64.astype(np.float32)
vd2b =, array32)

# For projection geometries, the code is exactly the same. There is no need to
# specify '-vol' or '-sino'. This is automatically inferred from the type of the
# geometry.

Both tomosipo and ASTRA convert 64-bit floating point values to 32-bit floating point values. Tomosipo warns when this happens.

Changing data

ASTRA has a store method to update its data:

# set to zero, 0)
# set to a matrix, array)

In tomosipo, the linked data can be accessed through the data property. The property itself cannot be overwritten, so you need to use [:] to overwrite the data.[:] = 0.0[:] = array32

Retrieving data

Use ASTRA’s get method to get data:

R = astra.data2d.get(v2)

Or tomosipo’s data property:

Freeing data

In ASTRA do not forget to free data:

# Free memory

In tomosipo, you can make sure that a data object is freed using a with block:

with vd0:                       # start using vd0[:] += 1.0
    # Do something with data
    array_clone = np.clone(

# At this point, the data is deleted.

# use array_clone from here on
array_clone -= 1.0

When to use data objects in tomosipo

In tomosipo, it is rarely useful to create data objects, since forward and backprojection can occur on arrays directly — without the need to create an intermediate data object.

Operators have a domain_shape and range_shape property that specify the shape of their domain and range. This can be used as follows:

A = ts.operator(vg, pg)
x = np.ones(A.domain_shape, dtype=np.float32)
y = np.zeros(A.range_shape, dtype=np.float32)

The reason that the properties use the domain and range terms, is because the backprojection operator has these same properties:

W = A.T
y = np.zeros(A.domain_shape, dtype=np.float32)
x = np.zeros(A.range_shape, dtype=np.float32)

Numpy arrays are automatically freed when they fall out of use. To force their removal, use

del x

There is one use case for data objects that is useful for interactive use: displaying data in a window. You can use the following:

from tomosipo.qt import display
# Create hollow box phantom
vd = ts.phantom.hollow_box(
# Display it in an interactive window

The slicer in the window allows you to slice through the volume.


You rarely need data objects in tomosipo, but when you need them

  • use
  • use a with block for cleanup
  • display data with tomosipo.qt.display