Explanations of Scan multi-frame handling#

The multi-frame handling allows to specify how individual (detector) frames are assigned to scan points, i.e. to the scanned grid of time and/or motor positions.

The parameter Frame index stepping per scan point defines how the global frame counter is incremented for each scan point. For example, if the value is set to 1, the frame counter will be incremented by 1 for each scan point. This corresponds to a 1:1 relation between scan points and data frames. At a value of 3, the frame counter would be incremented by 3 for each scan point, i.e. scan point #0 would use frame #0, scan point #1 would use frame #3, etc.

The Frames to process per scan point determines how many frames are processed at each scan point. If this value larger than 1, the Frame index stepping per scan point will determine the first frame index that is used for the scan point.

The Multi-frame handling parameter defines how the individual frames should be processed for each scan point. The given operation will be applied per pixel. Note that this parameter is only relevant if the Frames to process per scan point is larger than 1. The options are:

  • Average: The average of the frames is calculated and assigned to the scan point.

  • Sum: The sum of the frames is calculated and assigned to the scan point.

  • Maximum: The maximum of the frames is calculated and assigned to the scan point.

  • Stack: The individual frames are loaded and an image stack is created and assigned to the scan point. This will result in a multi-dimensional dataset.

Note: The multi-frame handling applies to the individual frame, not files. Files with multiple frames per file, e.g. HDF5 files, are compatible because the frames in each file are treated individually.

Note: If multiple frames are processed at each scan point, the number of scan points must be reduced accordingly. For example, if 30 frames have been acquired and 3 frames are processed at each scan point, the number of scan points cannot be larger than 10. If n_frames is the total number of frames, delta is the increment of the frame index per scan point, and m_frames is the number of frames processed at each scan point, the maximum number of scan points is given by: max_scan_points = (n_frames - m_frames + 1) / delta, rounded down to the nearest integer. Please consult the table below for examples of how the number of scan points must be adjusted depending on the parameters:

Total number of frames

Frame index stepping per scan point

Frames to process per scan point

Maximum number of scan points

30

1

1

30

30

3

1

10

If only every third frame is used, the maximum number of scan points must be divided by 3.

30

1

3

28

If 3 frames are processed at each scan point, the maximum number of scan points must be reduced by 2. The scan point #28 will use the frames #28, #29, and #30 and scan point #29 would require up to frame #31.

30

4

6

6

Because 6 frames are processed at each scan point, the maximum number of scan points must be reduced by 5. Since the frame index is incremented by 4 for each scan point, the maximum number of scan points must be divided by 4. Therefore, a total of (30 - 6 + 1) / 4 = 6 scan points can be used. The last scan point #5 (*) will use the frames #20, #21, #22, #23, #24, and #25. The scan point #6 would require up to frame #30 which is not available (**).

(*) Note that counting starts at 0, i.e. #5 is the 6th scan point.

(**) The 30 frames include the frames #0 to #29.

Examples#

The following examples are meant to provide some hands-on guidance on the practical use of the multi-frame handling parameters.

Scan/file naming pattern

Frame index stepping per scan point

Frames to process per scan point

Multi-frame handling

Acquisition of multiple frames per scan point: In this example, multiple frames are acquired per scan point, and the sum of the frames is required:

image_####.tif

3

3

Sum

These settings will result in the following data usage:

Scan point #0: sum(image_0000.tif, image_0001.tif, image_0002.tif)

Scan point #1: sum(image_0003.tif, image_0004.tif, image_0005.tif)

etc.

Analysis with rolling average over multiple scan points: In this example, one frame is acquired per scan point, but the frames of multiple scan points are used to calculate a rolling average.

image_####.tif

1

3

Average

These settings will result in the following data usage:

Scan point #0: mean(image_0000.tif, image_0001.tif, image_0002.tif)

Scan point #1: mean(image_0001.tif, image_0002.tif, image_0003.tif)

etc.

Analysis with rolling average over multiple scan points for groups of scan points: In this example, the acquisition is performed in groups of 4 images per scan point, and a rolling average over 2 scan points is processed as output.

data_##.npy

4

8

Average

These settings will result in the following data usage:

Scan point #0: mean(data_00.npy, data_01.npy, data_02.npy, data_03.npy)

Scan point #1: mean(data_04.npy, data_05.npy, data_06.npy, data_07.npy)

etc.

Analysis with four acquisition per scan point which need to be processed individually further along the pipeline. The Stack option will result in a 3-dimensional dataset of shape (4, det_y, det_x).

data_##.npy

4

4

Stack

These settings will result in the following data usage:

Scan point #0: array([data_00.npy, data_01.npy, data_02.npy, data_03.npy])

Scan point #1: array([data_04.npy, data_05.npy, data_06.npy, data_07.npy])

etc.

Using a single HDF5 file: In this example, the ::<num> syntax is used to specify the index of frames to be processed at each scan point.

data_AB.h5

4

4

Average

These settings will result in the following data usage:

Scan point #0: mean(data_AB.h5::0, data_AB.h5::1, data_AB.h5::2, data_AB.h5::3)

Scan point #1: mean(data_AB.h5::4, data_AB.h5::5, data_AB.h5::6, data_AB.h5::7)

etc.

Programmatic access#

For accessing the ScanContext parameters programmatically, the following keys must be used:

An example of modifying the scan/file naming pattern programmatically is shown below:

Scan = pydidas.contexts.ScanContext()
Scan.set_param("frame_indices_per_scan_point", "5")
Scan.set_param("scan_frames_per_point", 2)
Scan.set_param("scan_multi_frame_handling", "Sum")