From abc0229efbee34aa59e8118a682c7a6282eacd81 Mon Sep 17 00:00:00 2001 From: appel_c Date: Tue, 9 Dec 2025 11:03:01 +0100 Subject: [PATCH] fix(timepix): remove status writer from trigger call --- superxas_bec/devices/timepix/timepix.py | 40 ++++++++++++++++--- .../timepix_fly_client/timepix_fly_backend.py | 1 - .../timepix_fly_interface.py | 10 ++++- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/superxas_bec/devices/timepix/timepix.py b/superxas_bec/devices/timepix/timepix.py index 3f3485a..eae4ffc 100644 --- a/superxas_bec/devices/timepix/timepix.py +++ b/superxas_bec/devices/timepix/timepix.py @@ -241,6 +241,14 @@ class Timepix(PSIDeviceBase, TimePixControl): max_size=1000, doc="TDS period recorded by the TimePixFly backend detector.", ) + total_periods = Cpt( + AsyncSignal, + name="total_periods", + ndim=0, + async_update={"type": "add", "max_shape": [None]}, + max_size=1000, + doc="Total TDS periods recorded by the TimePixFly backend detector.", + ) total_events = Cpt( AsyncSignal, name="total_events", @@ -415,8 +423,13 @@ class Timepix(PSIDeviceBase, TimePixControl): # Create return data xes_data = np.zeros((n_energy_points, troin), dtype=np.float32) # dtype from backend code - tds_period = 0 + tds_period = [] tds_total_events = 0 + total_periods = 0 + data_frame_freq = 131000 / start_frame.get("save_interval", 1) # in Hz + logger.info( + f"Processing TimepixFly data: start_frame: {start_frame}, end_frame: {end_frame}" + ) if len(data_frames) == 0: logger.error( f"No data frames received in msg_buffer; for start_frame: {start_frame}, end_frame: {end_frame}" @@ -424,11 +437,26 @@ class Timepix(PSIDeviceBase, TimePixControl): # TODO this should no longer happen now as this was fixed in the backend.. else: for msg in data_frames: - tds_period += msg["period"] + tds_period.append(msg["period"]) tds_total_events += msg["totalEvents"] for ii in range(n_energy_points): xes_data[ii, :] += msg["TDSpectra"][ii::n_energy_points] - xes_data = xes_data.T # Transpose to get shape (troin, n_energy_points) + + tds_period = ( + np.array(tds_period) / start_frame.get("save_interval", 1) / data_frame_freq + ) + + total_periods = end_frame.get("periods", None) + if total_periods is not None: + self.total_periods.put( + total_periods / start_frame.get("save_interval", 1) / data_frame_freq + ) + else: + logger.error(f"Received total_periods: {total_periods} from end_frame {end_frame}.") + + # Transpose to get shape (troin, n_energy_points) + xes_data = xes_data.T + # Put XES data self.tds_period.put(tds_period) self.total_events.put(tds_total_events) @@ -693,6 +721,7 @@ class Timepix(PSIDeviceBase, TimePixControl): TRoiStep=self.troistep, TRoiN=self.troin, output_uri=f"tcp:{self.backend.hostname}:{self.backend.socket_port}", + save_interval=int(131000 / 5) - 5, # Save interval in 131kHz units, ) logger.debug(f"Current TimePixFly configuration: {other_config}") pixel_map = self.pixel_map @@ -733,7 +762,6 @@ class Timepix(PSIDeviceBase, TimePixControl): self.cam.acquire_busy, [ACQUIRESTATUS.DONE, ACQUIRESTATUS.ACQUIRING, ACQUIRESTATUS.DONE] ) img_counter = self.hdf.num_captured.get() - status_writer = CompareStatus(self.hdf.num_captured, img_counter + 1) status_backend = None # First we make sure that the backend reach 'config' state. This needs to happend before each trigger. if self.enable_xes is True: @@ -768,9 +796,9 @@ class Timepix(PSIDeviceBase, TimePixControl): status_backend = self.backend.on_trigger_finished() if status_backend is not None: - return_status = status_camera & status_backend & status_writer + return_status = status_camera & status_backend else: - return_status = status_camera & status_writer + return_status = status_camera self.cancel_on_stop(return_status) self.cam.acquire.put(1) return return_status diff --git a/superxas_bec/devices/timepix/timepix_fly_client/timepix_fly_backend.py b/superxas_bec/devices/timepix/timepix_fly_client/timepix_fly_backend.py index 1999137..54ff054 100644 --- a/superxas_bec/devices/timepix/timepix_fly_client/timepix_fly_backend.py +++ b/superxas_bec/devices/timepix/timepix_fly_client/timepix_fly_backend.py @@ -474,7 +474,6 @@ class TimepixFlyBackend: def run_msg_callbacks(self): """Run callbacks if EndFrame message is received.""" - # TODO start_frame = self.__msg_buffer[0] end_frame = self.__msg_buffer[-1] data_frames = self.__msg_buffer[1:-1] diff --git a/superxas_bec/devices/timepix/timepix_fly_client/timepix_fly_interface.py b/superxas_bec/devices/timepix/timepix_fly_client/timepix_fly_interface.py index 3992ce2..7ce4aa5 100644 --- a/superxas_bec/devices/timepix/timepix_fly_client/timepix_fly_interface.py +++ b/superxas_bec/devices/timepix/timepix_fly_client/timepix_fly_interface.py @@ -138,10 +138,18 @@ class TimepixXESFrame(TimePixResponse): class TimepixEndFrame(TimePixResponse): - """TimepixEndFrame is a Pydantic model that represents the end frame of a TimePix acquisition.""" + """ + TimepixEndFrame is a Pydantic model that represents the end frame of a TimePix acquisition. + + Attributes: + - type: str - The type of the response, default is "EndFrame". + - error: str - If an error occured during acuisition, this field contains the error message. Empty string otherwise. + - periods: int - The last period count minus 3 (3 being the period predictor delay). + """ type: str = "EndFrame" error: str + periods: int # Last period count minus 3 (3 being the period predictor delay) # Habe ein GET /net-addresses call implementiert