fix: cleanup, fix mcs_clock

This commit is contained in:
2025-07-21 16:28:24 +02:00
parent cdac29bed1
commit 7679fa1383

View File

@@ -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()