Example Round-Trip of Calibration Constants

Below is an example of roundtripping example calibration data for an AGIPD detector module

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

from iCalibrationDB import ConstantMetaData, Constants, Conditions, Detectors, Versions

We first create a fake constant for multi-memory cell data.

fake_constant = np.random.randint(1000, 1200, (256,256,32))
fake_constant = fake_constant.astype(np.short)
fig = plt.figure()
ax = fig.add_subplot(111)
im = ax.imshow(fake_constant[...,0], interpolation="nearest")
cb = fig.colorbar(im)
../_images/example_4_0.png

In the following we set up the meta data for this constant. Common constants, operating conditions and versions of these constants are already pre-defined and can be directly used from the library.

For our example we’ve created an AGIPD offset constant, which was taken at an AGIPD dark condition with 32 memory cells and a bias voltage of 200V. Furthermore we are creating a new version, reflected by using Versions.Now. This version is for the Q1M1 module of the AGIPD1M1 detector.

metadata = ConstantMetaData()

# set the constant
offset = Constants.AGIPD.Offset()
offset.data = fake_constant
metadata.calibration_constant = offset

# set the operating condition
condition = Conditions.Dark.AGIPD(memory_cells=32, bias_voltage=200)
metadata.detector_condition = condition

# specify the a version for this constant
metadata.calibration_constant_version = Versions.Now(device=Detectors.AGIPD1M1.Q1M1)

# this will have auto-assigned a device uuid and device name:
print("Device name is: {}".format(metadata.calibration_constant_version.device_name))
print("Device uuid is: {}".format(metadata.calibration_constant_version.device_uuid))
Device name is: AGIPD_M001
Device uuid is: 00100001100000

As shown above, calibration constants map to detector modules for segmented detectors, or to a single detector (module) for monolithic detectors. These modules are internally identified by a uuid, but are also identified by a module name and mapped to their current physical location in a detector instance. The latter may be altered to reflect updates in module usage. Through the combination of name and uuid the correct module will still be identified:

# these are the same modules, once identified by location, once my name
assert Detectors.AGIPD1M1.Q1M1 is Detectors.AGIPD.M001
assert Detectors.AGIPD1M1.Q1M2 is Detectors.AGIPD.M002

# these are not the same modules:
assert Detectors.AGIPD1M1.Q1M2 is Detectors.AGIPD.M001
---------------------------------------------------------------------------

AssertionError                            Traceback (most recent call last)

<ipython-input-5-70f3f4000e6d> in <module>()
      4
      5 # these are not the same modules:
----> 6 assert Detectors.AGIPD1M1.Q1M2 is Detectors.AGIPD.M001


AssertionError:

For each detector a representation is availble to show the current location mapping. You can access it simply by typing the instance name as the last command into a notebook cell or by using display(Detectors.AGIPD1M1) explicitly.

Detectors.AGIPD1M1

Detector: AGIPD1M1, Detector UUID: 001, Modules: 16

AGIPD_M013: 00100011300000 AGIPD_M001: 00100001100000
AGIPD_M014: 00100011400000 AGIPD_M002: 00100001200000
AGIPD_M015: 00100011500000 AGIPD_M003: 00100001300000
AGIPD_M016: 00100011600000 AGIPD_M004: 00100001400000
AGIPD_M009: 00100001900000 AGIPD_M005: 00100001500000
AGIPD_M010: 00100011000000 AGIPD_M006: 00100001600000
AGIPD_M011: 00100011100000 AGIPD_M007: 00100001700000
AGIPD_M012: 00100011200000 AGIPD_M008: 00100001800000
from IPython.display import display
display(Detectors.FastCCD1)

Detector: FastCCD1, Detector UUID: 005, Modules: 1

FastCCD1: 00500000000000

With our meta data complete and having assured ourselves that we are referring to the correct module, we can now send the data to the database. This requires passing the ZMQ address of a running CalibrationDbRemote Karabo device, which is accessible to us. It need not be on localhost; this is only used in this example.

metadata.send("tcp://localhost:5005")
Converting calibration_constant to dict
Converting detector_condition to dict
Converting calibration_constant_version to dict
Successfully sent constant to database!

Retrieving data works in a similar fashion. Again we need to pass an address of a CalibrationDbRemote device we would like to connect to.

If a constant matching our meta-data is found it is returned and the meta-data is updated to reflect it.

metadata.retrieve("tcp://localhost:5005")
Converting calibration_constant to dict
Converting detector_condition to dict
Converting calibration_constant_version to dict
Successfully retrieved constant from database!
Updating self...
retrieved_constant = metadata.calibration_constant.data
fig = plt.figure()
ax = fig.add_subplot(111)
im = ax.imshow(retrieved_constant[...,0], interpolation="nearest")
cb = fig.colorbar(im)
../_images/example_16_0.png

Since we basically round-tripped the calibration constant in this example the two should be identical. Here we explicitely verify that.

assert np.allclose(retrieved_constant, fake_constant)