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)
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)
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)