diff --git a/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py b/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py index 288da5c..e2423f2 100644 --- a/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py +++ b/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py @@ -5,6 +5,7 @@ from __future__ import annotations import enum from threading import RLock from typing import TYPE_CHECKING +import numpy as np from bec_lib.logger import bec_logger from ophyd import Component as Cpt @@ -40,10 +41,13 @@ class READYTOREAD(int, enum.Enum): class BPMDevice(Device): """Class for BPM device of the MCSCard.""" - current1 = Cpt(Signal, name="current1", kind=Kind.normal, doc="Current 1") - current2 = Cpt(Signal, name="current2", kind=Kind.normal, doc="Current 2") - current3 = Cpt(Signal, name="current3", kind=Kind.normal, doc="Current 3") - current4 = Cpt(Signal, name="current4", kind=Kind.normal, doc="Current 4") + current1 = Cpt(Signal, name="current1", kind=Kind.normal, doc="Normalized current 1") + current2 = Cpt(Signal, name="current2", kind=Kind.normal, doc="Normalized current 2") + current3 = Cpt(Signal, name="current3", kind=Kind.normal, doc="Normalized current 3") + current4 = Cpt(Signal, name="current4", kind=Kind.normal, doc="Normalized current 4") + count_time = Cpt( + Signal, name="count_time", kind=Kind.normal, doc="Count time for bpm signal counts" + ) sum = Cpt(SumSignal, kind="hinted", doc="Sum of all currents") x = Cpt( DiffXYSignal, @@ -65,13 +69,14 @@ class BPMDevice(Device): ) -class BPMCountNormalized(BPMDevice): +class MCSRaw(Device): """Class for BPM device of the MCSCard with normalized currents.""" - current1 = Cpt(Signal, name="current1", kind=Kind.normal, doc="Count time normalized current 1") - current2 = Cpt(Signal, name="current2", kind=Kind.normal, doc="Count time normalized current 2") - current3 = Cpt(Signal, name="current3", kind=Kind.normal, doc="Count time normalized current 3") - current4 = Cpt(Signal, name="current4", kind=Kind.normal, doc="Count time normalized current 4") + mca1 = Cpt(Signal, name="current1", kind=Kind.normal, doc="Raw counts on mca1 channel") + mca2 = Cpt(Signal, name="current2", kind=Kind.normal, doc="Raw counts on mca2 channel") + mca3 = Cpt(Signal, name="current3", kind=Kind.normal, doc="Raw counts on mca3 channel") + mca4 = Cpt(Signal, name="current4", kind=Kind.normal, doc="Raw counts on mca4 channel") + mca5 = Cpt(Signal, name="current5", kind=Kind.normal, doc="Raw counts on mca5 channel") class MCSCardCSAXS(PSIDeviceBase, MCSCard): @@ -87,21 +92,18 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard): doc="Signal that indicates if mcs card is ready to be read from after triggers. 0 not ready, 1 ready", ) progress: ProgressSignal = Cpt(ProgressSignal, name="progress") - count_time = Cpt(Signal, name="count_time", kind=Kind.normal) + # Make this an async signal.. + mcs = Cpt( + MCSRaw, + name="mcs", + kind=Kind.normal, + doc="MCS device with raw current and count time readings", + ) bpm = Cpt( - BPMDevice, name="bpm", kind=Kind.normal, doc="BPM device for MCSCard, normalized currents" - ) - bpm_norm = Cpt( - BPMCountNormalized, - name="bpmnorm", - kind=Kind.normal, - doc="BPM device for MCSCard, normalized currents", - ) - bpm_plot = Cpt( BPMDevice, - name="bpm_plot", + name="bpm", kind=Kind.normal, - doc="subdevice with synchronized readings for plotting with monitored signals", + doc="BPM device for MCSCard with count times and normalized currents", ) def __init__( @@ -118,7 +120,7 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard): super().__init__( name=name, prefix=prefix, scan_info=scan_info, device_manager=device_manager, **kwargs ) - self._mcs_clock = 10e-6 # 10MHz clock + self._mcs_clock = 1e-7 # 10MHz clock self._pv_timeout = 2 self._rlock = RLock() self.counter_mapping = { @@ -161,8 +163,8 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard): self.acquire_mode.set(ACQUIREMODE.MCS).wait(timeout=self._pv_timeout) # Subscribe to the mca updates - for name in self.counters.component_names: - sig: EpicsSignalRO = getattr(self.counters, name) + for name in self.counter_mapping.keys(): + sig: EpicsSignalRO = getattr(self.counters, name.split('_')[-1]) sig.subscribe(self._on_counter_update, run=False) def _on_counter_update(self, value, **kwargs) -> None: @@ -173,34 +175,27 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard): return mapped_signal_name = self.counter_mapping.get(signal.name, None) if mapped_signal_name is None: - logger.info(f"Received update from unmapped signal {signal.name}") return - if mapped_signal_name == "count_time": - # Count time is not mapped into bpm signals - self.count_time.put(value) - return - # Update self.bpm + mca_raw = getattr(self.mcs, signal.name.split("_")[-1], None) + if mca_raw is None: + return + logger.info(f"Received update of type {type(value)} for {signal.name}") + if isinstance(value, np.ndarray): + mca_raw.put(value.tolist()) + if mapped_signal_name == "count_time": + value = value*self._mcs_clock + value = float(value.mean()) + else: + mca_raw.put(value) + if mapped_signal_name == "count_time": + value = value*self._mcs_clock + + # Mean signal for burst acquisition sig = getattr(self.bpm, mapped_signal_name) sig.put(value) self.counter_updated.append(signal.name) received_all_updates = set(self.counter_updated) == set(self.counter_mapping.keys()) if received_all_updates: - # Set the normalized currents - count_time = self.count_time.get() - for name in self.counter_mapping.values(): - if name == "count_time": - continue - sig = getattr(self.bpm, name) - sig_norm = getattr(self.bpm_norm, name) - if count_time <= 0: - logger.warning( - f"Count time is zero or negative ({count_time}), setting normalized current to 0." - ) - sig_norm.put(0.0) - continue - sig_norm.put(v / t for v, t in zip(sig.get(), count_time)) - sig_plot = getattr(self.bpm_plot, name) - sig_plot.put(sum(sig_norm.get()) / len(sig_norm.get())) self.ready_to_read.put(1) # Reset happens from DDG class! self.counter_updated.clear()