Processes

Scanning

async for ... in concert.processes.common.scan(params, values, feedback, go_back=False)

Multi-dimensional scan of concert.base.Parameter instances params, which are set to values. feedback is a coroutine function without parameters called after every iteration. If go_back is True, the original parameter values are restored at the end.

If params is just one parameter and values is one list of values, perform a 1D scan. In this case tuples (x, y) are returned where x are the individual elements from the list of values and y = feedback() is called after every value setting.

If params is a list of parameters and values is a list of lists, assign values[i] to params[i] and do a multi-dimensional scan, where last parameter changes the fastest (in other words a nested scan of all parameters, where feedback is called for every combination of parameter values. The combinations are obtained as a cartesian product of the values. For example, scanning camera exposure times and motor positions with values=[[1, 2] * q.s, [3, 5] * q.mm], would result in this:

[((1 * q.s, 3 * q.mm), feedback()), ((1 * q.s, 5 * q.mm), feedback()),
 ((2 * q.s, 3 * q.mm), feedback()), ((2 * q.s, 5 * q.mm), feedback())]

In general, for n parameters and lists of values, returned are tuples ((x_0, …, x_{n-1}), y), where y = feedback() is called after every value setting (any parameter change). Parameter setting occurs in parallel, is waited for and then feedback is called.

A simple 1D example:

async for vector in scan(camera['exposure_time'], np.arange(1, 10, 1) * q.s, feedback):
    print(vector) # prints (1 * q.s, feedback()) and so on

2D example:

params = [camera['exposure_time'], motor['position']]
values = [np.arange(1, 10, 1) * q.s, np.arange(5, 15, 2) * q.mm]
async for vector in scan(params, values, feedback):
    print(vector) # prints ((1 * q.s, 5 * q.mm), feedback()) and so on
async for ... in concert.processes.common.ascan(param, start, stop, step, feedback, go_back=False, include_last=True)

A convenience function to perform a 1D scan on parameter param, scan from start value to stop with step. feedback and go_back are the same as in the scan(). If include_last is True, the stop value will be included in the created values This function just computes the values from start, stop, step and then calls scan():

scan(param, values, feedback=feedback, go_back=go_back))
async for ... in concert.processes.common.dscan(param, delta, step, feedback, go_back=False, include_last=True)

A convenience function to perform a 1D scan on parameter param, scan from its current value to some delta with step. feedback and go_back are the same as in the scan(). This function just computes the start and stop values and calls ascan():

start = await param.get()
ascan(param, start, start + delta, step, feedback, go_back=go_back)

Focusing

await concert.processes.common.focus(camera, motor, measure=<function std>, opt_kwargs=None, plot_callback=None, frame_callback=None)

Focus camera by moving motor. measure is a callable that computes a scalar that has to be maximized from an image taken with camera. opt_kwargs are keyword arguments sent to the optimization algorithm. plot_callback is (x, y) values, where x is the iteration number and y the metric result. frame_callback is a coroutine function fed with the incoming frames.

This function is returning a future encapsulating the focusing event. Note, that the camera is stopped from recording as soon as the optimal position is found.

Alignment

await concert.processes.common.align_rotation_axis(camera, rotation_motor, x_motor=None, z_motor=None, get_ellipse_points=<function find_needle_tips>, num_frames=10, metric_eps=None, position_eps=<Quantity(0.1, 'degree')>, max_iterations=5, initial_x_coeff=<Quantity(1, 'dimensionless')>, initial_z_coeff=<Quantity(1, 'dimensionless')>, shutter=None, flat_motor=None, flat_position=None, y_0=0, y_1=None, get_ellipse_points_kwargs=None, frame_consumers=None)

align_rotation_axis(camera, rotation_motor, x_motor=None, z_motor=None, get_ellipse_points=find_needle_tips, num_frames=10, metric_eps=None, position_eps=0.1 * q.deg, max_iterations=5, initial_x_coeff=1 * q.dimensionless, initial_z_coeff=1 * q.dimensionless, shutter=None, flat_motor=None, flat_position=None, y_0=0, y_1=None, get_ellipse_points_kwargs=None, frame_consumers=None)

Align rotation axis. camera is used to obtain frames, rotation_motor rotates the sample around the tomographic axis of rotation, x_motor turns the sample around x-axis, z_motor turns the sample around z-axis.

get_ellipse_points is a function with one positional argument, a set of images. It computes the ellipse points from the sample positions as it rotates around the tomographic axis. You can use e.g. concert.imageprocessing.find_needle_tips() and concert.imageprocessing.find_sphere_centers() to extract the ellipse points from needle tips or sphere centers. You can pass additional keyword arguments to the get_ellipse_points function in the get_ellipse_points_kwargs dictionary.

num_frames defines how many frames are acquired and passed to the measure. metric_eps is the metric threshold for stopping the procedure. If not specified, it is calculated automatically to not exceed 0.5 pixels vertically. If max_iterations is reached the procedure stops as well. initial_[x|z]_coeff is the coefficient applied` to the motor motion for the first iteration. If we move the camera instead of the rotation stage, it is often necessary to acquire fresh flat fields. In order to make an up-to-date flat correction, specify shutter if you want fresh dark fields and specify flat_motor and flat_position to acquire flat fields. Crop acquired images to y_0 and y_1. frame_consumers are coroutine functions which will be fed with all acquired frames.

The procedure finishes when it finds the minimum angle between an ellipse extracted from the sample movement and respective axes or the found angle drops below metric_eps. The axis of rotation after the procedure is (0,1,0), which is the direction perpendicular to the beam direction and the lateral direction. x_motor and z_motor do not have to move exactly by the computed angles but their relative motion must be linear with respect to computed angles (e.g. if the motors operate with steps it is fine, also rotation direction does not need to be known).

Coroutines

Sinks

class concert.coroutines.sinks.Accumulate(shape=None, dtype=None, reset_on_call=True)

Accumulate items in a list or a numpy array if shape is given, dtype is the data type. If reset_on_call is True, the saved values will be overwritten every time the accumulator is called, otherwise they will be appended.

class concert.coroutines.sinks.Result

The object is callable and when called it becomes a coroutine which accepts items and stores them in a variable which allows the user to obtain the last stored item at any time point.

await concert.coroutines.sinks.null(producer)

A black-hole.

Filters

class concert.coroutines.filters.Timer

Timer object measures execution times of coroutine-based workflows. It measures the time from when this object receives data until all the subsequent stages finish.

property duration

All iterations summed up.

property mean

Mean iteration execution time.

reset()

Reset the timer.

async for ... in concert.coroutines.filters.absorptivity(producer)

Get the absorptivity from a flat corrected stream of images. The intensity after the object is defined as \(I = I_0 \cdot e^{-\mu t}\) and we extract the absorptivity \(\mu t\) from the stream of flat corrected images \(I / I_0\).

async for ... in concert.coroutines.filters.average_images(producer)

Average images as they come from producer.

async for ... in concert.coroutines.filters.downsize(producer, x_slice=None, y_slice=None, z_slice=None)

Downsize images in 3D. Every argument is either a tuple (start, stop, step). x_slice operates on image width, y_slice on its height and z_slice on the incoming images, i.e. it creates the third time dimension.

Note: the start index is included in the data and the stop index is excluded.

async for ... in concert.coroutines.filters.flat_correct(flat, producer, dark=None)

Flat correcting coroutine which takes a flat field and a dark field (if given) from producer and calculates a flat corrected radiograph.

async for ... in concert.coroutines.filters.stall(producer, per_shot=10, flush_at=None)

Send items once enough is collected from producer. Collect per_shot items. The incoming data might represent a collection of some kind. If the last item is supposed to be sent regardless the current number of collected items, use flush_at by which you specify the collection size and every time the current item counter % flush_at == 0 the item is sent.

Optimization

Optimization is a procedure to iteratively find the best possible match to

\[y = f(x).\]

This module provides execution routines and algorithms for optimization.

exception concert.optimization.OptimizationError

Optimization-related errors.

await concert.optimization.halver(function, x_0, initial_step=None, epsilon=None, max_iterations=100)

Halving the interval, evaluate function based on param. Use initial_step, epsilon precision and max_iterations.

await concert.optimization.optimize(function, x_0, algorithm, alg_args=(), alg_kwargs=None, callback=None)

Optimize y = await function (x), so function must be a coroutine function. x_0 is the initial guess. algorithm is the optimization algorithm to be used:

algorithm(x_0, *alg_args, **alg_kwargs)

callback is a callable called with all the (x, y) values as they are obtained.

await concert.optimization.optimize_parameter(parameter, feedback, x_0, algorithm, alg_args=(), alg_kwargs=None, callback=None)

Optimize parameter and use the feedback (a coroutine function) as a result. Other arguments are the same as by optimize(). The function to be optimized is determined as follows:

await parameter.set(x)
y = await feedback()

callback is the same as by optimize().

await concert.optimization.scipy_minimize(func, x_0, **kwargs)

Use scipy.optimize.minimize(), func is a coroutine function, the translation to scipy is taken care of here. x_0 is the initial guess and kwargs are passed to minimize.