diff --git a/src/calng/base_correction.py b/src/calng/base_correction.py index e2cd56cf343945acfbd88fb1609893188895fca3..0073ee26dfa00c226251ee65f9d9a7427ae7c14f 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 7857c8ed88b7803988c2a1d7f4d99d2e336b562f..7d0803b51de20a58d1c11395b805b97f6a2350ee 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 2ee61b848e74c6a6fe3fd9e28a52d25b1f6c353d..3ae2ec2a70bfeb1fef5456b6a6245b0be4fe1b20 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 6705142c6f3a25977001c0772053daf03aaa250e..2a052e5812ffb37847e1cb05b54f0ae27b428211 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 5043e9b6aad29d82286450a48772d14045caed08..c07efd58c2bb6652343ba8d53142cf1abb8fbc3d 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 79314a48eba76234f9651a897bd98847921b4205..9d3234b747893c28887da093291931fa93f4a6b7 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 1e8ab80b0d9cac5e9a55d22a46369268244a0570..ffae49dd607b808cb4ecac79d82280f1f7de24e1 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]