From d3bfcf1a51d39f6eba14bc2456dd96c3fa021c03 Mon Sep 17 00:00:00 2001 From: David Hammer <david.hammer@xfel.eu> Date: Tue, 7 Feb 2023 13:16:16 +0100 Subject: [PATCH] LPD memory cell constant parameter and condition checker --- setup.py | 1 + src/calng/base_correction.py | 1 + src/calng/conditions/LpdCondition.py | 31 +++++++++++++ src/calng/corrections/JungfrauCorrection.py | 49 ++++++++------------- src/calng/corrections/LpdCorrection.py | 45 +++++++++++++++++-- src/calng/utils.py | 4 ++ 6 files changed, 97 insertions(+), 34 deletions(-) create mode 100644 src/calng/conditions/LpdCondition.py diff --git a/setup.py b/setup.py index 12f4ff59..cd8c3851 100644 --- a/setup.py +++ b/setup.py @@ -40,6 +40,7 @@ setup(name='calng', 'CalibrationManager = calng.CalibrationManager:CalibrationManager', 'AgipdCondition = calng.conditions:AgipdCondition.AgipdCondition', 'JungfrauCondition = calng.conditions.JungfrauCondition:JungfrauCondition', + 'LpdCondition = calng.conditions.LpdCondition:LpdCondition', 'Agipd1MGeometry = calng.geometries.Agipd1MGeometry:Agipd1MGeometry', 'Dssc1MGeometry = calng.geometries:Dssc1MGeometry.Dssc1MGeometry', 'Epix100Geometry = calng.geometries:Epix100Geometry.Epix100Geometry', diff --git a/src/calng/base_correction.py b/src/calng/base_correction.py index 0073ee26..0ace7697 100644 --- a/src/calng/base_correction.py +++ b/src/calng/base_correction.py @@ -50,6 +50,7 @@ class FramefilterSpecType(enum.Enum): class WarningLampType(enum.Enum): FRAME_FILTER = enum.auto() MEMORY_CELL_RANGE = enum.auto() + CONSTANT_OPERATING_PARAMETERS = enum.auto() PREVIEW_SETTINGS = enum.auto() CORRECTION_RUNNER = enum.auto() OUTPUT_BUFFER = enum.auto() diff --git a/src/calng/conditions/LpdCondition.py b/src/calng/conditions/LpdCondition.py new file mode 100644 index 00000000..6d467fd1 --- /dev/null +++ b/src/calng/conditions/LpdCondition.py @@ -0,0 +1,31 @@ +from karabo.middlelayer import ( + AccessMode, + Assignment, + Slot, + State, + String, + getDevice, + get_array_data, + sleep, +) +from ..corrections import LpdCorrection +from .. import base_condition, utils + + +class LpdCondition(base_condition.ConditionBase): + someCorrectionDeviceId = String( + displayedName="Correction device", + description="Correction devices expose the cell table as a property. Specify " + "the name of one of the correction devices in the pipeline to allow monitoring " + "of the memoryCellOrder parameter.", + assignment=Assignment.MANDATORY, + accessMode=AccessMode.INITONLY, + ) + + @property + def keys_to_get(self): + return { + self.someCorrectionDeviceId.value: [ + ("dataFormat.cellId", "memoryCellOrder", utils.cell_table_to_string) + ] + } diff --git a/src/calng/corrections/JungfrauCorrection.py b/src/calng/corrections/JungfrauCorrection.py index 9d3234b7..e25add50 100644 --- a/src/calng/corrections/JungfrauCorrection.py +++ b/src/calng/corrections/JungfrauCorrection.py @@ -34,6 +34,12 @@ class Constants(enum.Enum): RelativeGain10Hz = enum.auto() +bad_pixel_constants = { + Constants.BadPixelsDark10Hz, + Constants.BadPixelsFF10Hz, +} + + # from pycalibration (TOOD: move to common shared lib) class GainModes(enum.Enum): DYNAMIC_GAIN = "dynamicgain" @@ -119,12 +125,10 @@ class JungfrauBaseRunner(base_kernel_runner.BaseKernelRunner): self.offset_map[:] = self._xp.asarray(constant_data, dtype=np.float32) elif constant is Constants.RelativeGain10Hz: self.rel_gain_map[:] = self._xp.asarray(constant_data, dtype=np.float32) - elif constant in ( - Constants.BadPixelsDark10Hz, - Constants.BadPixelsFF10Hz, - ): + elif constant in bad_pixel_constants: self.bad_pixel_map |= self._xp.asarray(constant_data, dtype=np.uint32) - self.override_bad_pixel_flags_to_use(self._override_bad_pixel_flags) + else: + raise ValueError(f"Unexpected constant type {constant}") @property def preview_data_views(self): @@ -698,6 +702,8 @@ class JungfrauCorrection(base_correction.BaseCorrection): ) def _load_constant_to_runner(self, constant, constant_data): + if constant in bad_pixel_constants: + constant_data &= self._override_bad_pixel_flags self.kernel_runner.load_constant(constant, constant_data) def postReconfigure(self): @@ -713,31 +719,14 @@ class JungfrauCorrection(base_correction.BaseCorrection): if update.has("corrections.badPixels.subsetToUse"): self.log_status_info("Updating bad pixel maps based on subset specified") - if any( - update.get( - f"corrections.badPixels.subsetToUse.{field.name}", default=False - ) - for field in utils.BadPixelValues - ): - self.log_status_info( - "Some fields reenabled, reloading cached bad pixel constants" - ) - with self.calcat_friend.cached_constants_lock: - self.kernel_runner.flush_buffers( - { - Constants.BadPixelsDark10Hz, - Constants.BadPixelsFF10Hz, - } - ) - for ( - constant, - data, - ) in self.calcat_friend.cached_constants.items(): - if "BadPixels" in constant.name: - self._load_constant_to_runner(constant, data) - self.kernel_runner.override_bad_pixel_flags_to_use( - self._override_bad_pixel_flags - ) + # note: now just always reloading from cache for convenience + with self.calcat_friend.cached_constants_lock: + self.kernel_runner.flush_buffers(bad_pixel_constants) + for constant in bad_pixel_constants: + if constant in self.calcat_friend.cached_constants: + self._load_constant_to_runner( + constant, self.calcat_friend.cached_constants[constant] + ) if self._preview_friend is not None: self._preview_friend.reconfigure(update) diff --git a/src/calng/corrections/LpdCorrection.py b/src/calng/corrections/LpdCorrection.py index ffae49dd..31c25ca0 100644 --- a/src/calng/corrections/LpdCorrection.py +++ b/src/calng/corrections/LpdCorrection.py @@ -2,6 +2,7 @@ import enum import numpy as np from karabo.bound import ( + BOOL_ELEMENT, DOUBLE_ELEMENT, KARABO_CLASSINFO, OUTPUT_CHANNEL, @@ -188,8 +189,8 @@ class LpdCalcatFriend(base_calcat.BaseCalcatFriend): @property def _constants_need_conditions(self): return { - Constants.Offset: self.dark_condition, - Constants.BadPixelsDark: self.dark_condition, + Constants.Offset: self.with_cell_condition, + Constants.BadPixelsDark: self.with_cell_condition, Constants.GainAmpMap: self.category_condition, Constants.FFMap: self.category_condition, Constants.RelativeGain: self.category_condition, @@ -249,14 +250,32 @@ class LpdCalcatFriend(base_calcat.BaseCalcatFriend): .defaultValue(0) .reconfigurable() .commit(), + + BOOL_ELEMENT(schema) + .key("constantParameters.useMemoryCellOrder") + .displayedName("Use memory cell order parameter") + .assignmentOptional() + .defaultValue(True) + .reconfigurable() + .commit(), + + STRING_ELEMENT(schema) + .key("constantParameters.memoryCellOrder") + .displayedName("Memory cell order") + .assignmentOptional() + .defaultValue("") + .reconfigurable() + .commit(), ) + managed_keys.add("constantParameters.useMemoryCellOrder") + managed_keys.add("constantParameters.memoryCellOrder") managed_keys.add("constantParameters.feedbackCapacitor") managed_keys.add("constantParameters.photonEnergy") managed_keys.add("constantParameters.category") base_calcat.add_status_schema_from_enum(schema, Constants) - def dark_condition(self): + def basic_condition(self): res = base_calcat.OperatingConditions() res["Memory cells"] = self._get_param("memoryCells") res["Sensor Bias Voltage"] = self._get_param("biasVoltage") @@ -266,8 +285,15 @@ class LpdCalcatFriend(base_calcat.BaseCalcatFriend): return res + def with_cell_condition(self): + res = self.basic_condition() + if self._get_param("useMemoryCellOrder"): + res["Memory cell order"] = self._get_param("memoryCellOrder") + + return res + def illuminated_condition(self): - res = self.dark_condition() + res = self.basic_condition() res["Source Energy"] = self._get_param("photonEnergy") return res @@ -425,6 +451,17 @@ class LpdCorrection(BaseCorrection): cell_table, pulse_table, ): + with self.warning_context( + "processingState", WarningLampType.CONSTANT_OPERATING_PARAMETERS + ) as warn: + if ( + cell_table_string := utils.cell_table_to_string(cell_table) + ) != self.unsafe_get( + "constantParameters.memoryCellOrder" + ) and self.unsafe_get( + "constantParameters.useMemoryCellOrder" + ): + warn(f"Cell order does not match input; input: {cell_table_string}") if self._frame_filter is not None: try: cell_table = cell_table[self._frame_filter] diff --git a/src/calng/utils.py b/src/calng/utils.py index 464a1958..7c48ebf3 100644 --- a/src/calng/utils.py +++ b/src/calng/utils.py @@ -554,3 +554,7 @@ def quadrant_views(A): for row in np.vsplit(A, 2): res.extend(np.hsplit(row, 2)) return res + + +def cell_table_to_string(cell_table): + return ",".join(map(str, cell_table.ravel())) + "," -- GitLab