refactor(mcs): imrove documentation for counter updates
This commit is contained in:
+1
-3
@@ -6,6 +6,4 @@ _commit: v1.1.2
|
|||||||
_src_path: https://github.com/bec-project/plugin_copier_template.git
|
_src_path: https://github.com/bec-project/plugin_copier_template.git
|
||||||
make_commit: false
|
make_commit: false
|
||||||
project_name: csaxs_bec
|
project_name: csaxs_bec
|
||||||
widget_plugins_input:
|
widget_plugins_input: []
|
||||||
- name: csaxs_test
|
|
||||||
use_ui: true
|
|
||||||
|
|||||||
@@ -119,8 +119,8 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
|||||||
)
|
)
|
||||||
self._mcs_clock = 1e7 # 10MHz clock -> 1e7 Hz
|
self._mcs_clock = 1e7 # 10MHz clock -> 1e7 Hz
|
||||||
self._pv_timeout = 3 # TODO remove timeout once #129 in ophyd_devices is solved
|
self._pv_timeout = 3 # TODO remove timeout once #129 in ophyd_devices is solved
|
||||||
self._rlock = RLock()
|
self._rlock = RLock() # Needed to ensure thread safety for counter updates
|
||||||
self.counter_mapping = {
|
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}_mca1": "current1",
|
||||||
f"{self.counters.name}_mca2": "current2",
|
f"{self.counters.name}_mca2": "current2",
|
||||||
f"{self.counters.name}_mca3": "current3",
|
f"{self.counters.name}_mca3": "current3",
|
||||||
@@ -166,35 +166,67 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
|||||||
sig.subscribe(self._on_counter_update, run=False)
|
sig.subscribe(self._on_counter_update, run=False)
|
||||||
|
|
||||||
def _on_counter_update(self, value, **kwargs) -> None:
|
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:
|
with self._rlock:
|
||||||
|
# Retrieve the signal object which executes this callback
|
||||||
signal = kwargs.get("obj", None)
|
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}")
|
logger.info(f"Called without 'obj' in kwargs: {kwargs}")
|
||||||
return
|
return
|
||||||
|
# Get the maped signal name from the mapping dictionary
|
||||||
mapped_signal_name = self.counter_mapping.get(signal.name, None)
|
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:
|
if mapped_signal_name is None:
|
||||||
return
|
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)
|
mca_raw = getattr(self.mcs, signal.name.split("_")[-1], None)
|
||||||
if mca_raw is None:
|
if mca_raw is None:
|
||||||
return
|
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):
|
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())
|
mca_raw.put(value.tolist())
|
||||||
|
# compute the count_time in seconds
|
||||||
if mapped_signal_name == "count_time":
|
if mapped_signal_name == "count_time":
|
||||||
value = value / self._mcs_clock
|
value = value / self._mcs_clock
|
||||||
value = float(value.mean())
|
value = float(value.mean())
|
||||||
else:
|
else:
|
||||||
|
# We received a single value, so we can directly push it
|
||||||
mca_raw.put(value)
|
mca_raw.put(value)
|
||||||
|
# compute the count_time in seconds
|
||||||
if mapped_signal_name == "count_time":
|
if mapped_signal_name == "count_time":
|
||||||
value = value / self._mcs_clock
|
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 = getattr(self.bpm, mapped_signal_name)
|
||||||
sig.put(value)
|
sig.put(value)
|
||||||
self.counter_updated.append(signal.name)
|
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())
|
received_all_updates = set(self.counter_updated) == set(self.counter_mapping.keys())
|
||||||
if received_all_updates:
|
if received_all_updates:
|
||||||
self.ready_to_read.put(READYTOREAD.DONE) # Reset happens from DDG class!
|
self.ready_to_read.put(READYTOREAD.DONE)
|
||||||
self.counter_updated.clear()
|
# 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:
|
def _progress_update(self, value, **kwargs) -> None:
|
||||||
"""Callback for progress updates from ophyd subscription on current_channel."""
|
"""Callback for progress updates from ophyd subscription on current_channel."""
|
||||||
|
|||||||
Reference in New Issue
Block a user