Calibrating Delay Scans

Performing uncalibrated scans using the delay macromotor results in positional instability of the beam at the sample. To address this, delay has several methods to characterize and correct the scan.

Warning

The functionality described here has not been commissioned, and should be used with caution.

Characterizing Beam Instability

The main way to characterize the current scan instability is to run the centroid_scan method. The method performs a scan using the inputted scan parameters, measuring the centroids of the beam at Opal 1. The results are then saved and graphed for the user to see.

In [1]: snd.delay.centroid_scan(start, stop, step)

To view the centroids again after the scan has been completed, the method view_centroids can be used to view the centroids from the most recent centroids_scan.

In [2]: snd.delay.view_centroids()

To view the graph displayed after the scan, run the graph_centroids method.

In [3]: snd.delay.graph_centroids()

Note

The results shown by view_centroids and graph_centroids come from the recent centroid scan or calibration. Anytime a new centroid scan is run, the previous scan data is overwritten.

Calibration Operations

In the event centroid_scan reveals the beam drifts too much throughout the scan, there is a routine for building a correction table using the snd.t1.chi1 and snd.t1.y1 motors to correct for the x and y centroids respectively. This correction table is put together using the table generated from a centroid_scan along with parameters to find the scaling information between each of the motor positions and the beam centroids. Together all the information collected during a calibrate run, constitutes a specific calibration.

High-Level Properties

The delay macromotor comes with two high level properties pertaining to the current state of the calibration. has_calibration indicates that a properly configured calibration is currently loaded to the motor, simply returning a bool.

The second high level property is use_calibration which determines whether a calibration should be used during a move. By default, anytime a calibration is created or loaded, use_calibration is set to be True. However, this is primarily useful if there is a move where performing a the correction is not desired. By setting use_calibration to False all moves will be done without corrections

Note

Motor corrections will only be performed on every move command if both has_calibration and use_calibration are True.

Creating a New Calibration

If a new calibration is necessary, the entire calibration routine can be run using the calibrate method along with the desired scan parameters.

In [1]: snd.delay.calibrate(start, stop, step)

The calibration routine itself consists of first performing a centroid scan to measure the current beam drift, and then performing a walk using each of the calibration motors to find the motor position to centroid scaling. Once, complete, the motor will automatically start using the new calibration for all subsequent move commands. Additionally, all the motors will be returned to their original positions after the routine has completed.

Note

A confirmation to overwrite the existing calibration will be required to run calibrate if the motor already has a valid configuration.

Saving and Loading Calibrations

Calibrations used for the delay motor are all saved in the HXRSnD/calibrations directory. Whenever a calibration routine has completed, the calibration is saved into a file named current_calibration.json. To save a calibration more permanently, the method save_calibration can be used by passing a either filename or a full path. Running,

In [1]: snd.delay.save_calibration('my_calibration')

Will save the current calibration as HXRSnD/calibrations/my_calibration.json.

To load this configuration, the load_calibration method takes calibration names, searches the HXRSnD/calibrations directory, and then applies the dound calibration. For example,

In [2]: snd.delay.load_calibration('my_calibration')

loads the my_calibration.json from HXRSnD/calibrations.

Note

Running load_calibration without any inputs automatically loads current_calibration.json.

Inspecting the Calibration

To view the contents of a calibration, the calibration property returns a dictionary with five keys:

  • calib : DataFrame containing the correction table used by the calibration motors.

  • motors : List of Motor objects that refer to the motors used by the calibration.

  • scan : DataFrame containing the results of the centroid scan used to build the correction table.

  • scale : List if values in units of ps/pixel, used to convert between pixel positions and delay position.

  • start : List of starting positions of the motors used to calculate the scale.

Note

calibration is a read-only property and cannot be used to modify the live calibration.

Modifying Calibrations

Each of the five calibration values listed above can be modified outright using the configure method. This is done by running configure and passing the desired change as a keyword argument.

Warning

It is not advisable to change the the calibration in ways not listed below.

Correction Table Post-Processing

A simple reason to modify the correction table would be to apply some level of post processing to the resulting table. For example, to apply a Savitzky-Golay smoothing filter, first capturet he current correction table in a new dataframe using the calibration property,

In [1]: df_calib = snd.delay.calibration['calib']

Then create a new dataframe with the applied filter using some window_length and polyorder (see documentation on scipy.signal.savgol_filter for more details),

In [2]: df_savgol = df_calib.apply(savgol_filter, args=(window_length, polyorder))

And then configure the motor to use this new correction table,

In [3]: snd.delay.configure(calib=df_savgol)

Note

Whenever the correction table is modified using configure, the number of columns must equal the number of motors listed in snd.delay.calibration['motors'].

Rescaling the Correction Table

In the event that the picosecond per pixel scaling factor may need to be redone, the method rescale_calibration will perform the scaling routine and then update the calibration accordingly.

In [1]: snd.delay.rescale_calibration()