refactor(mcs): imrove documentation for counter updates

This commit is contained in:
2025-08-06 11:28:04 +02:00
parent 5c263bdb63
commit f69e643092
3 changed files with 39 additions and 10 deletions

View File

@@ -6,6 +6,4 @@ _commit: v1.1.2
_src_path: https://github.com/bec-project/plugin_copier_template.git
make_commit: false
project_name: csaxs_bec
widget_plugins_input:
- name: csaxs_test
use_ui: true
widget_plugins_input: []

View File

@@ -119,8 +119,8 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
)
self._mcs_clock = 1e7 # 10MHz clock -> 1e7 Hz
self._pv_timeout = 3 # TODO remove timeout once #129 in ophyd_devices is solved
self._rlock = RLock()
self.counter_mapping = {
self._rlock = RLock() # Needed to ensure thread safety for counter updates
self.counter_mapping = { # Any mca counter that should be updated has to be added here
f"{self.counters.name}_mca1": "current1",
f"{self.counters.name}_mca2": "current2",
f"{self.counters.name}_mca3": "current3",
@@ -166,35 +166,67 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
sig.subscribe(self._on_counter_update, run=False)
def _on_counter_update(self, value, **kwargs) -> None:
"""
Callback for counter updates of the mca channels (1-32).
The raw data is pushed to the mcs sub-device (MCSRaw). We need to ensure that
the MCSRaw device has all signals defined for which we want to push the values.
As we may receive multiple readings per point, e.g. if frames_per_trigger > 1,
we also create a mean value for the counter signals. These are then pushed to the bpm device
for plotting and further processing. The signal names are defined and mapped in the
self.counter_mapping dictionary & the bpm sub-device.
There are multiple mca channels, each giving individual updates. We want to ensure that
each is updated before we signal that we are ready to read. In future, these signals may
become asynchronous, but we first need to ensure that we can properly combine monitored
signals with async signals for plotting. Until then, we will keep this logic.
"""
with self._rlock:
# Retrieve the signal object which executes this callback
signal = kwargs.get("obj", None)
if signal is None:
if signal is None: # This should never happen, but just in case
logger.info(f"Called without 'obj' in kwargs: {kwargs}")
return
# Get the maped signal name from the mapping dictionary
mapped_signal_name = self.counter_mapping.get(signal.name, None)
# If we did not map the signal name in counter_mapping, but receive an update
# we will skip it.
if mapped_signal_name is None:
return
# Push the raw values of the mca channels. The signal name has to be defined
# in the self.mcs sub-device (MCSRaw) to be able to push the values. Otherwise
# we will skip the update.
mca_raw = getattr(self.mcs, signal.name.split("_")[-1], None)
if mca_raw is None:
return
# In case there was more than one value received, i.e. frames_per_trigger > 1,
# we will receive a np.array of values.
if isinstance(value, np.ndarray):
# We push the raw values as a list to the mca_raw signal
# And otherwise compute the mean value for plotting of counter signals
mca_raw.put(value.tolist())
# compute the count_time in seconds
if mapped_signal_name == "count_time":
value = value / self._mcs_clock
value = float(value.mean())
else:
# We received a single value, so we can directly push it
mca_raw.put(value)
# compute the count_time in seconds
if mapped_signal_name == "count_time":
value = value / self._mcs_clock
# Mean signal for burst acquisition
# Get the mapped signal from the bpm device and update it
sig = getattr(self.bpm, mapped_signal_name)
sig.put(value)
self.counter_updated.append(signal.name)
# Once all mca channels have been updated, we can signal that we are ready to read
received_all_updates = set(self.counter_updated) == set(self.counter_mapping.keys())
if received_all_updates:
self.ready_to_read.put(READYTOREAD.DONE) # Reset happens from DDG class!
self.counter_updated.clear()
self.ready_to_read.put(READYTOREAD.DONE)
# The reset of the signal is done in the on_trigger method of ddg1 for the next trigger
self.counter_updated.clear() # Clear the list for the next update cycle
def _progress_update(self, value, **kwargs) -> None:
"""Callback for progress updates from ophyd subscription on current_channel."""

View File

@@ -1 +0,0 @@
jjakjda