From 93089028c65e27a3f5b1b34264cd9af257f2f6e7 Mon Sep 17 00:00:00 2001 From: David Hammer <david.hammer@xfel.eu> Date: Tue, 7 Feb 2023 10:11:50 +0100 Subject: [PATCH] Add cell and pulse tables as properties --- src/calng/base_correction.py | 49 +++++++++++++++++--- src/calng/corrections/AgipdCorrection.py | 3 +- src/calng/corrections/DsscCorrection.py | 2 +- src/calng/corrections/Epix100Correction.py | 2 + src/calng/corrections/Gotthard2Correction.py | 2 + src/calng/corrections/JungfrauCorrection.py | 2 + src/calng/corrections/LpdCorrection.py | 2 +- 7 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/calng/base_correction.py b/src/calng/base_correction.py index e2cd56cf..0073ee26 100644 --- a/src/calng/base_correction.py +++ b/src/calng/base_correction.py @@ -84,6 +84,7 @@ class BaseCorrection(PythonDevice): } # subclass can extend this, /must/ put it in schema as managedKeys _image_data_path = "image.data" # customize for *some* subclasses _cell_table_path = "image.cellId" + _pulse_table_path = "image.pulseId" _warn_memory_cell_range = True # can be disabled for some detectors _cuda_pin_buffers = False @@ -355,6 +356,18 @@ class BaseCorrection(PythonDevice): .initialValue([]) .commit(), + VECTOR_UINT32_ELEMENT(expected) + .key("dataFormat.cellId") + .readOnly() + .initialValue([]) + .commit(), + + VECTOR_UINT32_ELEMENT(expected) + .key("dataFormat.pulseId") + .readOnly() + .initialValue([]) + .commit(), + NODE_ELEMENT(expected) .key("workarounds") .displayedName("Workarounds") @@ -601,6 +614,8 @@ class BaseCorrection(PythonDevice): self._buffer_lock = threading.Lock() self._last_processing_started = 0 # used for processing time and timeout self._last_train_id_processed = 0 # used to keep track (and as fallback) + self._last_cell_table = None # used to check whether to update property + self._last_pulse_table = None # ditto - though not all detectors have this # register slots def constant_override_fun(friend_fun, constant, preserve_fields): @@ -1098,17 +1113,22 @@ class BaseCorrection(PythonDevice): ) as warn: try: image_data = np.asarray(data_hash.get(self._image_data_path)) - if self._cell_table_path is None: - cell_table = None - else: - cell_table = np.asarray( - data_hash.get(self._cell_table_path) - ).ravel() + cell_table = ( + np.asarray(data_hash.get(self._cell_table_path)).ravel() + if self._cell_table_path is not None + else None + ) + pulse_table = ( + np.asarray(data_hash.get(self._pulse_table_path)).ravel() + if self._pulse_table_path is not None + else None + ) except RuntimeError as err: warn( "Failed to load image data; " f"probably empty hash from DAQ: {err}" ) + self._maybe_update_cell_and_pulse_tables(None, None) continue # no more common reasons to skip input, so go to processing @@ -1117,6 +1137,7 @@ class BaseCorrection(PythonDevice): self.updateState(State.PROCESSING) self.log_status_info("Processing data") + self._maybe_update_cell_and_pulse_tables(cell_table, pulse_table) timestamp = Timestamp.fromHashAttributes(metadata.getAttributes("timestamp")) train_id = timestamp.getTrainId() @@ -1206,6 +1227,7 @@ class BaseCorrection(PythonDevice): train_id, image_data, cell_table, + pulse_table, ) self._last_train_id_processed = train_id self._buffered_status_update.set("trainId", train_id) @@ -1235,6 +1257,21 @@ class BaseCorrection(PythonDevice): f"No new train in {PROCESSING_STATE_TIMEOUT} s, switching state." ) self._train_ratio_tracker.reset() + self._maybe_update_cell_and_pulse_tables(None, None) + + def _maybe_update_cell_and_pulse_tables(self, cell_table, pulse_table): + if not np.array_equal(cell_table, self._last_cell_table): + self._last_cell_table = cell_table + if cell_table is None: + self.set("dataFormat.cellId", []) + else: + self.set("dataFormat.cellId", list(map(int, cell_table))) + if not np.array_equal(pulse_table, self._last_pulse_table): + self._last_pulse_table = pulse_table + if pulse_table is None: + self.set("dataFormat.pulseId", []) + else: + self.set("dataFormat.pulseId", list(map(int, pulse_table))) def handle_eos(self, channel): self.updateState(State.ON) diff --git a/src/calng/corrections/AgipdCorrection.py b/src/calng/corrections/AgipdCorrection.py index 7857c8ed..7d0803b5 100644 --- a/src/calng/corrections/AgipdCorrection.py +++ b/src/calng/corrections/AgipdCorrection.py @@ -737,12 +737,11 @@ class AgipdCorrection(base_correction.BaseCorrection): train_id, image_data, cell_table, + pulse_table, ): """Called by input_handler for each data hash. Should correct data, optionally compute preview, write data output, and optionally write preview outputs.""" # original shape: frame, data/raw_gain, x, y - - pulse_table = data_hash.get("image.pulseId").ravel() if self._frame_filter is not None: try: cell_table = cell_table[self._frame_filter] diff --git a/src/calng/corrections/DsscCorrection.py b/src/calng/corrections/DsscCorrection.py index 2ee61b84..3ae2ec2a 100644 --- a/src/calng/corrections/DsscCorrection.py +++ b/src/calng/corrections/DsscCorrection.py @@ -275,8 +275,8 @@ class DsscCorrection(base_correction.BaseCorrection): train_id, image_data, cell_table, + pulse_table, ): - pulse_table = np.ravel(data_hash.get("image.pulseId")) if self._frame_filter is not None: try: cell_table = cell_table[self._frame_filter] diff --git a/src/calng/corrections/Epix100Correction.py b/src/calng/corrections/Epix100Correction.py index 6705142c..2a052e58 100644 --- a/src/calng/corrections/Epix100Correction.py +++ b/src/calng/corrections/Epix100Correction.py @@ -307,6 +307,7 @@ class Epix100Correction(base_correction.BaseCorrection): _managed_keys = base_correction.BaseCorrection._managed_keys.copy() _image_data_path = "data.image.pixels" _cell_table_path = None + _pulse_table_path = None _warn_memory_cell_range = False @staticmethod @@ -416,6 +417,7 @@ class Epix100Correction(base_correction.BaseCorrection): train_id, image_data, cell_table, # will be None + pulse_table, # ditto ): self.kernel_runner.load_data(image_data) diff --git a/src/calng/corrections/Gotthard2Correction.py b/src/calng/corrections/Gotthard2Correction.py index 5043e9b6..c07efd58 100644 --- a/src/calng/corrections/Gotthard2Correction.py +++ b/src/calng/corrections/Gotthard2Correction.py @@ -258,6 +258,7 @@ class Gotthard2Correction(base_correction.BaseCorrection): _managed_keys = base_correction.BaseCorrection._managed_keys.copy() _image_data_path = "data.adc" _cell_table_path = "data.memoryCell" + _pulse_table_path = None _warn_memory_cell_range = False # for now, receiver always writes 255 _cuda_pin_buffers = False @@ -410,6 +411,7 @@ class Gotthard2Correction(base_correction.BaseCorrection): train_id, image_data, cell_table, + pulse_table, ): # cell table currently not used for GOTTHARD2 (assume alternating) gain_map = np.asarray(data_hash.get("data.gain")) diff --git a/src/calng/corrections/JungfrauCorrection.py b/src/calng/corrections/JungfrauCorrection.py index 79314a48..9d3234b7 100644 --- a/src/calng/corrections/JungfrauCorrection.py +++ b/src/calng/corrections/JungfrauCorrection.py @@ -448,6 +448,7 @@ class JungfrauCorrection(base_correction.BaseCorrection): _managed_keys = base_correction.BaseCorrection._managed_keys.copy() _image_data_path = "data.adc" _cell_table_path = "data.memoryCell" + _pulse_table_path = None @staticmethod def expectedParameters(expected): @@ -626,6 +627,7 @@ class JungfrauCorrection(base_correction.BaseCorrection): train_id, image_data, cell_table, + pulse_table, ): if len(cell_table.shape) == 0: cell_table = cell_table[np.newaxis] diff --git a/src/calng/corrections/LpdCorrection.py b/src/calng/corrections/LpdCorrection.py index 1e8ab80b..ffae49dd 100644 --- a/src/calng/corrections/LpdCorrection.py +++ b/src/calng/corrections/LpdCorrection.py @@ -423,8 +423,8 @@ class LpdCorrection(BaseCorrection): train_id, image_data, cell_table, + pulse_table, ): - pulse_table = np.ravel(data_hash.get("image.pulseId")) if self._frame_filter is not None: try: cell_table = cell_table[self._frame_filter] -- GitLab