.. _example: .. _example: Example Round-Trip of Calibration Constants =========================================== Below is an example of roundtripping example calibration data for an AGIPD detector module .. code-block:: python 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. .. code-block:: python fake_constant = np.random.randint(1000, 1200, (256,256,32)) fake_constant = fake_constant.astype(np.short) .. code-block:: python fig = plt.figure() ax = fig.add_subplot(111) im = ax.imshow(fake_constant[...,0], interpolation="nearest") cb = fig.colorbar(im) .. image:: example_files/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. .. code-block:: python 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)) .. parsed-literal:: 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: .. code-block:: python # 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) in () 4 5 # these are not the same modules: ----> 6 assert Detectors.AGIPD1M1.Q1M2 is Detectors.AGIPD.M001 AssertionError: For each detector a `repr`\ esentation 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. .. code-block:: python Detectors.AGIPD1M1 .. raw:: html

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
.. code-block:: python from IPython.display import display display(Detectors.FastCCD1) .. raw:: html

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. .. code-block:: python metadata.send("tcp://localhost:5005") .. parsed-literal:: 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. .. code-block:: python metadata.retrieve("tcp://localhost:5005") .. parsed-literal:: Converting calibration_constant to dict Converting detector_condition to dict Converting calibration_constant_version to dict Successfully retrieved constant from database! Updating self... .. code-block:: python 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) .. image:: example_files/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. .. code-block:: python assert np.allclose(retrieved_constant, fake_constant)