Experiments

Experiments connect data acquisition and processing. They can be run multiple times by the base.Experiment.run(), they take care of proper file structure and logging output.

Acquisition

Experiments consist of Acquisition objects which encapsulate data generator and consumers for a particular experiment part (dark fields, radiographs, …). This way the experiments can be broken up into smaller logical pieces. A single acquisition object needs to be reproducible in order to repeat an experiment more times, thus we specify its generator and consumers as callables which return the actual generator or consumer. We need to do this because generators cannot be “restarted”.

It is very important that you enclose the executive part of the production and consumption code in try-finally to ensure proper clean up. E.g. if a producer starts rotating a motor, then in the finally clause there should be the call await motor.stop().

An example of an acquisition could look like this:

from concert.experiments.base import Acquisition

# This is a real generator, num_items is provided somewhere in our session
async def produce():
    try:
        for i in range(num_items):
            yield i
    finally:
        # Clean up here
        pass

# A simple coroutine sink which prints items
async def consume(producer):
    try:
        async for item in producer:
            print(item)
    finally:
        # Clean up here
        pass

acquisition = await Acquisition('foo', produce, consumers=[consume])
# Now we can run the acquisition
await acquisition()
class concert.experiments.base.Acquisition(self, name, producer, consumers=None, acquire=None)

An acquisition acquires data, gets it and sends it to consumers.

producer

a callable with no arguments which returns a generator yielding data items once called.

consumers

a list of callables with no arguments which return a coroutine consuming the data once started, can be empty.

acquire

a coroutine function which acquires the data, takes no arguments, can be None.

Base

Base base.Experiment makes sure all acquisitions are executed. It also holds addons.Addon instances which provide some extra functionality, e.g. live preview, online reconstruction, etc. To make a simple experiment for running the acquisition above and storing log with concert.storage.Walker:

import logging
from concert.experiments.base import Acquisition, Experiment
from concert.storage import DirectoryWalker

LOG = logging.getLogger(__name__)

walker = DirectoryWalker(log=LOG)
acquisitions = [await Acquisition('foo', produce)]
experiment = await Experiment(acquisitions, walker)

await experiment.run()
class concert.experiments.base.Experiment(self, acquisitions, walker=None, separate_scans=True, name_fmt='scan_{:>04}')

Experiment base class. An experiment can be run multiple times with the output data and log stored on disk. You can prepare every run by prepare() and finish the run by finish(). These methods do nothing by default. They can be useful e.g. if you need to reinitialize some experiment parts or want to attach some logging output.

acquisitions

A list of acquisitions this experiment is composed of

walker

A concert.storage.Walker descends to a data set specific for every run if given

separate_scans

If True, walker does not descend to data sets based on specific runs

name_fmt

Since experiment can be run multiple times each iteration will have a separate entry on the disk. The entry consists of a name and a number of the current iteration, so the parameter is a formattable string.

ready_to_prepare_next_sample

asyncio.Event that can be used to tell a processes.experiment.Director that the next iteration can be prepared. Can be set() to allow the preparation while the experiment is still running.

await acquire()

Acquire data by running the acquisitions. This is the method which implements the data acquisition and should be overwritten if more functionality is required, unlike run().

property acquisitions

Acquisitions is a read-only attribute which has to be manipulated by explicit methods provided by this class.

add(acquisition)

Add acquisition to the acquisition list and make it accessible as an attribute:

frames = Acquisition(...)
experiment.add(frames)
# This is possible
experiment.frames
await finish()

Gets executed after every experiment run.

get_acquisition(name)

Get acquisition by its name. In case there are more like it, the first one is returned.

await get_running_acquisition()

Get the currently running acquisition.

await prepare()

Gets executed before every experiment run.

remove(acquisition)

Remove acquisition from experiment.

swap(first, second)

Swap acquisition first with second. If there are more occurrences of either of them then the ones which are found first in the acquisitions list are swapped.

Experiments also have a base.Experiment.log attribute, which gets a new handler on every experiment run and this handler stores the output in the current experiment working directory defined by it’s concert.storage.Walker.

Advanced

Sometimes we need finer control over when exactly is the data acquired and worry about the download later. We can use the acquire argument to Acquisition. This means that the data acquisition can be invoked before data download. Acquisition calls its acquire first and only when it is finished connects producer with consumers.

The Experiment class has the attribute base.Experiment.ready_to_prepare_next_sample which is an instance of an asyncio.Event. This can be used to tell that most of the experiment is finished and a new iteration of this experiment can be prepared (e.g. by the concert.directors.base.Director. In the base.Experiment.run() the base.Experiment.ready_to_prepare_next_sample will be set that at the end of an experiment is is always set. In the beginning of the base.Experiment.run() it will be cleared. This is an example implementation making use of this:

from concert.experiments.base import Experiment, Acquisition
class MyExperiment(Experiment):
        async def __ainit__(self, walker, camera):
                acq = Acquisition("acquisition", self._produce_frames)
                self._camera = camera
                await super().__ainit__([acq], walker)

        async def _produce_frame(self):
                num_frames = 100
                async with self._camera.recording():
                        # Do the acquisition of the frames in camera memory

                # Only the readout and nothing else will happen after this point.
                self.ready_to_prepare_next_sample.set()

                async with self._camera.readout():
                        for i in range(num_frames):
                                yield await self._camera.grab()

Imaging

A basic frame acquisition generator which triggers the camera itself is provided by frames()

async for ... in concert.experiments.imaging.frames(num_frames, camera, callback=None)

A generator which takes num_frames using camera. callback is called after every taken frame.

There are tomography helper functions which make it easier to define the proper settings for conducting a tomographic experiment.

concert.experiments.imaging.tomo_angular_step(frame_width)

Get the angular step required for tomography so that every pixel of the frame rotates no more than one pixel per rotation step. frame_width is frame size in the direction perpendicular to the axis of rotation.

concert.experiments.imaging.tomo_projections_number(frame_width)

Get the minimum number of projections required by a tomographic scan in order to provide enough data points for every distance from the axis of rotation. The minimum angular step is considered to be needed smaller than one pixel in the direction perpendicular to the axis of rotation. The number of pixels in this direction is given by frame_width.

concert.experiments.imaging.tomo_max_speed(frame_width, frame_rate)

Get the maximum rotation speed which introduces motion blur less than one pixel. frame_width is the width of the frame in the direction perpendicular to the rotation and frame_rate defines the time required for recording one frame.

_Note:_ frame rate is required instead of exposure time because the exposure time is usually shorter due to the camera chip readout time. We need to make sure that by the next exposure the sample hasn’t moved more than one pixel from the previous frame, thus we need to take into account the whole frame taking procedure (exposure + readout).

Synchrotron and X-Ray tube experiments

In concert.experiments.synchrotron and concert.experiments.xraytube implementations of Radiography, SteppedTomography, ContinuousTomography and SteppedSpiralTomography, ContinuousSpiralTomography and GratingInterferometryStepping are implemented for the two different source types.

For detailed information how they are implemented, you can have a look at the base classes concert.experiments.imaging.Radiography, concert.experiments.imaging.Tomography, concert.experiments.imaging.SteppedTomography, concert.experiments.imaging.ContinuousTomography, concert.experiments.imaging.SteppedSpiralTomography, concert.experiments.imaging.ContinuousSpiralTomography and concert.experiments.imaging.GratingInterferometryStepping.

In the standard configuration, all tomography and radiography experiments first acquire the dark images, then the flat images and the projection images of the sample at the end. This order can be adjusted by the swap() command.

Radiography

class concert.experiments.synchrotron.Radiography(self, walker, flat_motor, radio_position, flat_position, camera, shutter, num_flats=200, num_darks=200, num_projections=3000, separate_scans=True)

Radiography experiment

await __ainit__(walker, flat_motor, radio_position, flat_position, camera, shutter, num_flats=200, num_darks=200, num_projections=3000, separate_scans=True)
Parameters:
  • walker (concert.storage.Walker) – Walker for storing experiment data.

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • camera (concert.devices.cameras.base.Camera) – Camera to acquire the images.

  • shutter (concert.devices.shutters.base.Shutter) – Stutter

  • num_flats (int) – Number of images for flatfield correction.

  • num_darks (int) – Number of images for dark correction.

  • num_projections (int) – Number of projections.

class concert.experiments.xraytube.Radiography(self, walker, flat_motor, radio_position, flat_position, camera, xray_tube, num_flats=200, num_darks=200, num_projections=3000, separate_scans=True)

Radiography experiment

Parameters:

xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

await __ainit__(walker, flat_motor, radio_position, flat_position, camera, xray_tube, num_flats=200, num_darks=200, num_projections=3000, separate_scans=True)
Parameters:
  • walker (concert.storage.Walker) – Walker for storing experiment data.

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • camera (concert.devices.cameras.base.Camera) – Camera to acquire the images.

  • xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

  • num_flats (int) – Number of images for flatfield correction.

  • num_darks (int) – Number of images for dark correction.

  • num_projections (int) – Number of projections.

SteppedTomography

class concert.experiments.synchrotron.SteppedTomography(self, walker, flat_motor, tomography_motor, radio_position, flat_position, camera, shutter, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)

Stepped tomography

await __ainit__(walker, flat_motor, tomography_motor, radio_position, flat_position, camera, shutter, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)
Parameters:
  • walker (concert.storage.Walker) – Walker for storing experiment data.

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • tomography_motor (concert.devices.motors.base.RotationMotor) – RotationMotor for tomography scan.

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • camera (concert.devices.camera.base.Camera) – Camera to acquire the images.

  • shutter (concert.devices.shutters.base.Shutter) – Stutter

  • num_flats (int) – Number of images for flatfield correction.

  • num_darks (int) – Number of images for dark correction.

  • num_projections (int) – Number of projections.

  • angular_range (q.deg) – Range for the scan of the tomography_motor.

  • start_angle (q.deg) – Start position of tomography_motor for the first projection.

class concert.experiments.xraytube.SteppedTomography(self, walker, flat_motor, tomography_motor, radio_position, flat_position, camera, xray_tube, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(360, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)

Stepped tomography experiment.

Parameters:

xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

await __ainit__(walker, flat_motor, tomography_motor, radio_position, flat_position, camera, xray_tube, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(360, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)
Parameters:
  • walker (concert.storage.Walker) – Walker for storing experiment data.

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • tomography_motor (concert.devices.motors.base.RotationMotor) – RotationMotor for tomography scan.

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • camera (concert.devices.camera.base.Camera) – Camera to acquire the images.

  • xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

  • num_flats (int) – Number of images for flatfield correction.

  • num_darks (int) – Number of images for dark correction.

  • num_projections (int) – Number of projections.

  • angular_range (q.deg) – Range for the scan of the tomography_motor.

  • start_angle (q.deg) – Start position of tomography_motor for the first projection.

ContinuousTomography

class concert.experiments.synchrotron.ContinuousTomography(self, walker, flat_motor, tomography_motor, radio_position, flat_position, camera, shutter, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)

Continuous tomography

await __ainit__(walker, flat_motor, tomography_motor, radio_position, flat_position, camera, shutter, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)
Parameters:
  • walker (concert.storage.Walker) – Walker for storing experiment data.

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • tomography_motor (concert.devices.motors.base.ContinuousRotationMotor) – ContinuousRotationMotor for tomography scan.

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • camera (concert.devices.camera.base.Camera) – Camera to acquire the images.

  • shutter (concert.devices.shutters.base.Shutter) – Stutter

  • num_flats (int) – Number of images for flatfield correction.

  • num_darks (int) – Number of images for dark correction.

  • num_projections (int) – Number of projections.

  • angular_range (q.deg) – Range for the scan of the tomography_motor.

  • start_angle (q.deg) – Start position of tomography_motor for the first projection.

class concert.experiments.xraytube.ContinuousTomography(self, walker, flat_motor, tomography_motor, radio_position, flat_position, camera, xray_tube, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)

Continuous tomography experiment

Parameters:

xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

await __ainit__(walker, flat_motor, tomography_motor, radio_position, flat_position, camera, xray_tube, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)
Parameters:
  • walker (concert.storage.Walker) – Walker for storing experiment data.

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • tomography_motor (concert.devices.motors.base.ContinuousRotationMotor) – ContinuousRotationMotor for tomography scan.

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • camera (concert.devices.camera.base.Camera) – Camera to acquire the images.

  • xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

  • num_flats (int) – Number of images for flatfield correction.

  • num_darks (int) – Number of images for dark correction.

  • num_projections (int) – Number of projections.

  • angular_range (q.deg) – Range for the scan of the tomography_motor.

  • start_angle (q.deg) – Start position of tomography_motor for the first projection.

SteppedSpiralTomography

class concert.experiments.synchrotron.SteppedSpiralTomography(self, walker, flat_motor, tomography_motor, vertical_motor, radio_position, flat_position, camera, shutter, start_position_vertical, sample_height, vertical_shift_per_tomogram, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)

Stepped spiral tomography

await __ainit__(walker, flat_motor, tomography_motor, vertical_motor, radio_position, flat_position, camera, shutter, start_position_vertical, sample_height, vertical_shift_per_tomogram, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)
Parameters:
  • walker (concert.storage.Walker) – Walker for storing experiment data.

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • tomography_motor (concert.devices.motors.base.RotationMotor) – RotationMotor for tomography scan.

  • vertical_motor (concert.devices.motors.base.LinearMotor) – LinearMotor to translate the sample along the tomographic axis.

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • camera (concert.devices.cameras.base.Camera) – Camera to acquire the images.

  • shutter (concert.devices.shutters.base.Shutter) – Stutter

  • start_position_vertical (q.mm) – Start position of vertical_motor.

  • sample_height (q.mm) – Height of the sample.

  • vertical_shift_per_tomogram (q.mm) – Distance vertical_motor is translated during one angular_range.

  • num_flats (int) – Number of images for flatfield correction.

  • num_darks (int) – Number of images for dark correction.

  • num_projections (int) – Number of projections.

  • angular_range (q.deg) – Range for the scan of the tomography_motor.

  • start_angle (q.deg) – Start position of tomography_motor for the first projection.

class concert.experiments.xraytube.SteppedSpiralTomography(self, walker, flat_motor, tomography_motor, vertical_motor, radio_position, flat_position, camera, xray_tube, start_position_vertical, sample_height, vertical_shift_per_tomogram, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)

Stepped spiral tomography experiment

Parameters:

xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

await __ainit__(walker, flat_motor, tomography_motor, vertical_motor, radio_position, flat_position, camera, xray_tube, start_position_vertical, sample_height, vertical_shift_per_tomogram, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)
Parameters:
  • walker (concert.storage.Walker) – Walker for storing experiment data.

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • tomography_motor (concert.devices.motors.base.RotationMotor) – RotationMotor for tomography scan.

  • vertical_motor (concert.devices.motors.base.LinearMotor) – LinearMotor to translate the sample along the tomographic axis.

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • camera (concert.devices.cameras.base.Camera) – Camera to acquire the images.

  • xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

  • start_position_vertical (q.mm) – Start position of vertical_motor.

  • sample_height (q.mm) – Height of the sample.

  • vertical_shift_per_tomogram (q.mm) – Distance vertical_motor is translated during one angular_range.

  • num_flats (int) – Number of images for flatfield correction.

  • num_darks (int) – Number of images for dark correction.

  • num_projections (int) – Number of projections.

  • angular_range (q.deg) – Range for the scan of the tomography_motor.

  • start_angle (q.deg) – Start position of tomography_motor for the first projection.

ContinuousSpiralTomography

class concert.experiments.synchrotron.ContinuousSpiralTomography(self, walker, flat_motor, tomography_motor, vertical_motor, radio_position, flat_position, camera, shutter, start_position_vertical, sample_height, vertical_shift_per_tomogram, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)

Continuous spiral tomography

await __ainit__(walker, flat_motor, tomography_motor, vertical_motor, radio_position, flat_position, camera, shutter, start_position_vertical, sample_height, vertical_shift_per_tomogram, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)
Parameters:
  • walker (concert.storage.Walker) – Walker for storing experiment data.

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • tomography_motor (concert.devices.motors.base.ContinuousRotationMotor) – ContinuousRotationMotor for tomography scan.

  • vertical_motor (concert.devices.motors.base.ContinuousLinearMotor) – ContinuousLinearMotor to translate the sample along the tomographic axis.

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • camera (concert.devices.cameras.base.Camera) – Camera to acquire the images.

  • shutter (concert.devices.shutters.base.Shutter) – Stutter

  • start_position_vertical (q.mm) – Start position of vertical_motor.

  • sample_height (q.mm) – Height of the sample.

  • vertical_shift_per_tomogram (q.mm) – Distance vertical_motor is translated during one angular_range.

  • num_flats (int) – Number of images for flatfield correction.

  • num_darks (int) – Number of images for dark correction.

  • num_projections (int) – Number of projections.

  • angular_range (q.deg) – Range for the scan of the tomography_motor.

  • start_angle (q.deg) – Start position of tomography_motor for the first projection.

class concert.experiments.xraytube.ContinuousSpiralTomography(self, walker, flat_motor, tomography_motor, vertical_motor, radio_position, flat_position, camera, xray_tube, start_position_vertical, sample_height, vertical_shift_per_tomogram, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)

Continuous spiral tomography experiment

Parameters:

xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

await __ainit__(walker, flat_motor, tomography_motor, vertical_motor, radio_position, flat_position, camera, xray_tube, start_position_vertical, sample_height, vertical_shift_per_tomogram, num_flats=200, num_darks=200, num_projections=3000, angular_range=<Quantity(180, 'degree')>, start_angle=<Quantity(0, 'degree')>, separate_scans=True)
Parameters:
  • walker (concert.storage.Walker) – Walker for storing experiment data.

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • tomography_motor (concert.devices.motors.base.ContinuousRotationMotor) – ContinuousRotationMotor for tomography scan.

  • vertical_motor (concert.devices.motors.base.ContinuousLinearMotor) – ContinuousLinearMotor to translate the sample along the tomographic axis.

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • camera (concert.devices.cameras.base.Camera) – Camera to acquire the images.

  • xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

  • start_position_vertical (q.mm) – Start position of vertical_motor.

  • sample_height (q.mm) – Height of the sample.

  • vertical_shift_per_tomogram (q.mm) – Distance vertical_motor is translated during one angular_range.

  • num_flats (int) – Number of images for flatfield correction.

  • num_darks (int) – Number of images for dark correction.

  • num_projections (int) – Number of projections.

  • angular_range (q.deg) – Range for the scan of the tomography_motor.

  • start_angle (q.deg) – Start position of tomography_motor for the first projection.

GratingInterferometryStepping

In this grating based phase contrast imaging implementation a single projection is generated. The grating is stepped with and without the sample while images are recorded. Dark images are also recorded. If the concert.experiments.addons.PhaseGratingSteppingFourierProcessing addon is attached, directly the intensity, visibility and differential phase are reconstructed.

class concert.experiments.synchrotron.GratingInterferometryStepping(self, walker, camera, shutter, flat_motor, stepping_motor, flat_position, radio_position, grating_period, num_darks, stepping_start_position, num_periods, num_steps_per_period, propagation_distance, separate_scans)
await __ainit__(walker, camera, shutter, flat_motor, stepping_motor, flat_position, radio_position, grating_period, num_darks, stepping_start_position, num_periods, num_steps_per_period, propagation_distance, separate_scans)
Parameters:
  • walker (concert.storage.DirectoryWalker) – Walker for the experiment

  • camera (concert.devices.cameras.base.Camera) – Camera to acquire the images

  • shutter (concert.devices.shutters.base.Shutter) – Shutter

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • stepping_motor (concert.devices.motors.base.LinearMotor)

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • grating_period (q.um) – Periodicity of the stepped grating.

  • num_darks (int) – Number of dark images that are acquired.

  • stepping_start_position (q.um) – First stepping position.

  • num_periods (int) – Number of grating periods that are sampled by the stepping.

  • num_steps_per_period (int) – Number stepping positions per grating period.

  • propagation_distance (q.mm) – Distance between the sample and the analyzer grating. Only used by the processing addon to determine the phase shift in angles.

class concert.experiments.xraytube.GratingInterferometryStepping(self, walker, camera, xray_tube, flat_motor, stepping_motor, flat_position, radio_position, grating_period, num_darks, stepping_start_position, num_periods, num_steps_per_period, propagation_distance, separate_scans)
Parameters:

xray_tube (concert.devices.xraytubes.base.XRayTube) – X-ray tube

await __ainit__(walker, camera, xray_tube, flat_motor, stepping_motor, flat_position, radio_position, grating_period, num_darks, stepping_start_position, num_periods, num_steps_per_period, propagation_distance, separate_scans)
Parameters:
  • walker (concert.storage.DirectoryWalker) – Walker for the experiment

  • camera (concert.devices.cameras.base.Camera) – Camera to acquire the images

  • xray_tube (concert.devices.xraytubes.base.XRayTube) – Xray tube

  • flat_motor – Motor for moving sample in and out of the beam. Must feature a ‘position’ property.

  • stepping_motor (concert.devices.motors.base.LinearMotor)

  • radio_position – Position of flat_motor that the sample is positioned in the beam. Unit must be the same as flat_motor[‘position’].

  • flat_position – Position of flat_motor that the sample is positioned out of the beam. Unit must be the same as flat_motor[‘position’].

  • grating_period (q.um) – Periodicity of the stepped grating.

  • num_darks (int) – Number of dark images that are acquired.

  • stepping_start_position (q.um) – First stepping position.

  • num_periods (int) – Number of grating periods that are sampled by the stepping.

  • num_steps_per_period (int) – Number stepping positions per grating period.

  • propagation_distance (q.mm) – Distance between the sample and the analyzer grating. Only used by the processing addon to determine the phase shift in angles.

Control

Experiment automation based on on-line data analysis.

class concert.experiments.control.ClosedLoop

An abstract feedback loop which acquires data, analyzes it on-line and provides feedback to the experiment. The data acquisition procedure is done iteratively until the result of some metric converges to a satisfactory value. Schematically, the class is doing the following in an iterative way:

initialize -> measure -> compare -> OK -> success
                ^            |
                |           NOK
                |            |
                -- control <--
await compare()

Return True if the metric is satisfied, False otherwise. This is the decision making process.

await control()

React on the result of a measurement.

await initialize()

Bring the experimental setup to some defined initial (reference) state.

await measure()

Conduct a measurement from data acquisition to analysis.

await run(self, max_iterations=10)

Run the loop until the metric is satisfied, if we don’t converge in max_iterations then the run is considered unsuccessful and False is returned, otherwise True.

class concert.experiments.control.DummyLoop

A dummy optimization loop.

await compare()

Return True if the metric is satisfied, False otherwise. This is the decision making process.

Addons

Addons are special features which are attached to experiments and operate on their data acquisition. For example, to save images on disk:

from concert.experiments.addons import ImageWriter

# Let's assume an experiment is already defined
writer = ImageWriter(experiment.acquisitions, experiment.walker)
writer.attach()
# Now images are written on disk
await experiment.run()
# To remove the writing addon
writer.detach()

Add-ons for acquisitions are standalone extensions which can be applied to them. They operate on the acquired data, e.g. write images to disk, do tomographic reconstruction etc.

class concert.experiments.addons.Accumulator(acquisitions, shapes=None, dtype=None)

An addon which accumulates data.

acquisitions

a list of Acquisition objects

shapes

a list of shapes for different acquisitions

dtype

the numpy data type

class concert.experiments.addons.Addon(acquisitions)

A base addon class. An addon can be attached, i.e. its functionality is applied to the specified acquisitions and detached.

acquisitions

A list of Acquisition objects. The addon attaches itself on construction.

attach()

Attach the addon to all acquisitions.

detach()

Detach the addon from all acquisitions.

exception concert.experiments.addons.AddonError

Addon errors.

class concert.experiments.addons.Consumer(acquisitions, consumer)

An addon which applies a specific coroutine-based consumer to acquisitions.

acquisitions

a list of Acquisition objects

consumer

A callable which returns a coroutine which processes the incoming data from acquisitions

class concert.experiments.addons.ImageWriter(acquisitions, walker)

An addon which writes images to disk.

acquisitions

a list of Acquisition objects

walker

A Walker instance

class concert.experiments.addons.OnlineReconstruction(self, experiment, reco_args, do_normalization=True, average_normalization=True, walker=None, slice_directory='online-slices')
exception concert.experiments.addons.OnlineReconstructionError
class concert.experiments.addons.PCOTimestampCheck(experiment)
exception concert.experiments.addons.PCOTimestampCheckError
class concert.experiments.addons.PhaseGratingSteppingFourierProcessing(experiment, output_directory='contrasts')

Addon for concert.experiments.imaging.GratingInterferometryStepping to process the raw data. The order of the acquisitions can be changed.

await process_darks(producer)

Processes dark images. All dark images are averaged.

Parameters:

producer – Dark image producer

Returns:

Running an experiment

To demonstrate how a typical experiment can be run in an empty session with dummy devices:

from concert.storage import DirectoryWalker
from concert.ext.viewers import PyplotImageViewer
from concert.experiments.addons import Consumer, ImageWriter
from concert.devices.motors.dummy import LinearMotor, ContinuousRotationMotor
from concert.devices.camera.dummy import Camera
from concert.devices.shutters.dummy import Shutter

# Import experiment
from concert.experiments.synchrotron import ContinuousTomography

# Devices
camera = await Camera()
shutter = await Shutter()
flat_motor = await LinearMotor()
tomo_motor = await ContinuousRotationMotor()


viewer = await PyplotImageViewer()
walker = DirectoryWalker(root="folder to write data")
exp = await ContinuousTomography(walker=walker,
                                 flat_motor=flat_motor,
                                 tomography_motor=tomo_motor,
                                 radio_position=0*q.mm,
                                 flat_position=10*q.mm,
                                 camera=camera,
                                 shutter=shutter)

# Attach live_view to the experiment
live_view = Consumer(exp.acquisitions, viewer)

# Attach image writer to experiment
writer = ImageWriter(exp.acquisitions, walker)

# check all parameters by typing 'exp'

# Run the experiment
f = exp.run()

# Wait until the experiment is done
await f