wip falcon slim
This commit is contained in:
@@ -2,15 +2,16 @@
|
||||
|
||||
import enum
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
from bec_lib.devicemanager import ScanInfo
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_lib.logger import bec_logger
|
||||
from bec_lib.messages import DeviceMessage
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from ophyd_devices import CompareStatus, TransitionStatus
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import DeviceStatus, Kind, Signal, StatusBase, Staged
|
||||
from ophyd import DeviceStatus, Kind, Signal, Staged, StatusBase
|
||||
from ophyd.status import SubscriptionStatus
|
||||
from ophyd_devices import CompareStatus, TransitionStatus
|
||||
from ophyd_devices.devices.dxp import EpicsDXPFalcon, EpicsMCARecord, Falcon
|
||||
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
|
||||
|
||||
@@ -23,7 +24,8 @@ class FalconAcquiringStatus(int, enum.Enum):
|
||||
DONE = 0
|
||||
ACQUIRING = 1
|
||||
|
||||
def compute_dead_time_corrected_signal(icr:float, ocr:float, roi:float, ert:float):
|
||||
|
||||
def compute_dead_time_corrected_signal(icr: float, ocr: float, roi: float, ert: float):
|
||||
_dead_time = 1.182e-7
|
||||
if icr == 0 or ocr == 0:
|
||||
return 0
|
||||
@@ -89,8 +91,7 @@ class FalconSuperXAS(PSIDeviceBase, FalconControl):
|
||||
preview = Cpt(
|
||||
Signal, name="preview", kind=Kind.omitted, doc="Preview signal for Falcon detector"
|
||||
)
|
||||
icr = Cpt(
|
||||
Signal, name="icr", kind=Kind.normal)
|
||||
icr = Cpt(Signal, name="icr", kind=Kind.normal)
|
||||
ocr = Cpt(Signal, name="icr", kind=Kind.normal)
|
||||
elap_real_time = Cpt(Signal, name="icr", kind=Kind.normal)
|
||||
roi0_count = Cpt(Signal, name="icr", kind=Kind.normal)
|
||||
@@ -98,14 +99,21 @@ class FalconSuperXAS(PSIDeviceBase, FalconControl):
|
||||
Signal,
|
||||
name="dead_cor_roi0_count",
|
||||
doc="Async dead time corrected ROI 0 count signal",
|
||||
kind=Kind.normal
|
||||
kind=Kind.normal,
|
||||
)
|
||||
|
||||
########################################
|
||||
# Beamline Specific Implementations #
|
||||
########################################
|
||||
|
||||
def __init__(self, name: str, prefix: str = "", scan_info: ScanInfo | None = None, device_manager=None, **kwargs):
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
prefix: str = "",
|
||||
scan_info: ScanInfo | None = None,
|
||||
device_manager=None,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
Initialize Falcon device.
|
||||
|
||||
@@ -115,7 +123,9 @@ class FalconSuperXAS(PSIDeviceBase, FalconControl):
|
||||
scan_info (ScanInfo): Information about the scan
|
||||
**kwargs: Additional keyword arguments
|
||||
"""
|
||||
super().__init__(name=name, prefix=prefix, scan_info=scan_info, device_manager=device_manager, **kwargs)
|
||||
super().__init__(
|
||||
name=name, prefix=prefix, scan_info=scan_info, device_manager=device_manager, **kwargs
|
||||
)
|
||||
self.device_manager = device_manager
|
||||
self.mca1.stage_sigs = {}
|
||||
self._pv_timeout = 5
|
||||
@@ -195,14 +205,14 @@ class FalconSuperXAS(PSIDeviceBase, FalconControl):
|
||||
logger.info(f"Sending data for {self.name} at {time_started}")
|
||||
icr = self.dxp1.input_count_rate.get()
|
||||
ocr = self.dxp1.output_count_rate.get()
|
||||
roi = self.mca1.elapsed_real_time.get()
|
||||
roi = self.mca1.rois.count.get()
|
||||
ert = self.mca1.elapsed_real_time.get()
|
||||
self.icr.put(icr)
|
||||
logger.info(f"Data to plot {self.icr.get()}")
|
||||
self.ocr.put(ocr)
|
||||
self.elap_real_time.put(ert)
|
||||
self.roi0_count.put(roi)
|
||||
self.dead_cor_roi0_count.put(compute_dead_time_corrected_signal(icr,ocr,roi,ert))
|
||||
self.dead_cor_roi0_count.put(compute_dead_time_corrected_signal(icr, ocr, roi, ert))
|
||||
# self._send_preview_async()
|
||||
logger.info(f"Data sent for {self.name} at {time.time()- time_started}")
|
||||
|
||||
|
||||
150
superxas_bec/devices/falcon_slim.py
Normal file
150
superxas_bec/devices/falcon_slim.py
Normal file
@@ -0,0 +1,150 @@
|
||||
import enum
|
||||
|
||||
import numpy as np
|
||||
from bec_lib.logger import bec_logger
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV, Kind, Signal
|
||||
from ophyd_devices import CompareStatus, DeviceStatus, PreviewSignal, StatusBase
|
||||
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
|
||||
class FalconAcquiringStatus(int, enum.Enum):
|
||||
"""Status of Falcon"""
|
||||
|
||||
DONE = 0
|
||||
ACQUIRING = 1
|
||||
|
||||
|
||||
class FalconControlSlim(Device):
|
||||
"""Slim Falcon Control class for SuperXAS. prefix: 'X10DA-SITORO:'"""
|
||||
|
||||
start = Cpt(EpicsSignal, "EraseStart", doc="XMAP start signal")
|
||||
stop = Cpt(EpicsSignal, "StopAll", doc="XMAP stop signal")
|
||||
acquiring = Cpt(EpicsSignalRO, "Acquiring", auto_monitor=True, doc="XMAP acquiring signal")
|
||||
icr = Cpt(EpicsSignalRO, "dxp1:InputCountRate", doc="XMAP input count rate")
|
||||
ocr = Cpt(EpicsSignalRO, "dxp1:OutputCountRate", doc="XMAP output count rate")
|
||||
ert = Cpt(EpicsSignalRO, "mca1.ERTM", doc="XMAP elapsed real time")
|
||||
roi = Cpt(EpicsSignalRO, "mca1.R0", kind=Kind.hinted, doc="XMAP ROI signal")
|
||||
label = Cpt(EpicsSignalRO, "mca1.R0NM", kind=Kind.config, doc="XMAP ROI signal")
|
||||
spectrum_val = Cpt(EpicsSignalRO, "mca1.VAL", kind=Kind.omitted)
|
||||
|
||||
# Preview Signal for Falcon detector
|
||||
spectrum = Cpt(
|
||||
PreviewSignal, name="spectrum", ndim=1, doc="Preview signal for Falcon detector spectrum"
|
||||
)
|
||||
|
||||
# Configuration attributes
|
||||
collect_mode = Cpt(EpicsSignal, "CollectMode", doc="Collect mode signal")
|
||||
preset_real_time = Cpt(EpicsSignalWithRBV, "PresetRealTime", doc="Preset real time signal")
|
||||
|
||||
# Computed signal for dead time corrected counts
|
||||
dead_cor_roi0_count = Cpt(Signal, "dead_cor_roi0_count", doc="Dead time corrected ROI 0 count")
|
||||
|
||||
|
||||
def compute_dead_time_corrected_signal(icr: float, ocr: float, roi: float, ert: float):
|
||||
_dead_time = 1.182e-7
|
||||
if icr == 0 or ocr == 0:
|
||||
return 0
|
||||
|
||||
# Check that relative change is large enough
|
||||
test = 1e9
|
||||
test_icr = icr
|
||||
n = 0
|
||||
while test > _dead_time and n < 30:
|
||||
try:
|
||||
true_icr = icr * np.exp(test_icr * _dead_time)
|
||||
test = (true_icr - test_icr) / test_icr
|
||||
test_icr = true_icr
|
||||
n += 1
|
||||
except Exception as e: # pylint: disable=broad-except
|
||||
logger.info(f"Error in computation of deadtime corrected signal, error: {e}")
|
||||
return 0
|
||||
|
||||
# Return corrected roi counts
|
||||
cor_roi_cnts = 0
|
||||
if ocr * ert != 0:
|
||||
cor_roi_cnts = roi * true_icr / (ocr * ert)
|
||||
return cor_roi_cnts
|
||||
|
||||
|
||||
class FalconSuperXASSlim(PSIDeviceBase, FalconControlSlim):
|
||||
"""Slim Falcon implementation at SuperXAS. prefix: 'X10DA-SITORO:'"""
|
||||
|
||||
def __init__(self, *, name, prefix="", scan_info=None, device_manager=None, **kwargs):
|
||||
super().__init__(
|
||||
name=name, prefix=prefix, scan_info=scan_info, device_manager=device_manager, **kwargs
|
||||
)
|
||||
self._pv_timeout = 5 # seconds
|
||||
|
||||
def on_init(self) -> None:
|
||||
"""
|
||||
Called when the device is initialized.
|
||||
|
||||
No signals are connected at this point. If you like to
|
||||
set default values on signals, please use on_connected instead.
|
||||
"""
|
||||
|
||||
def on_connected(self) -> None:
|
||||
"""
|
||||
Called after the device is connected and its signals are connected.
|
||||
Default values for signals should be set here.
|
||||
"""
|
||||
|
||||
def on_stage(self) -> DeviceStatus | StatusBase | None:
|
||||
"""
|
||||
Called while staging the device.
|
||||
|
||||
Information about the upcoming scan can be accessed from the scan_info (self.scan_info.msg) object.
|
||||
"""
|
||||
if self.acquiring.get() != FalconAcquiringStatus.DONE:
|
||||
logger.info(f"Falcon state was {self.acquiring.get()} during stage. Calling stop_all")
|
||||
status = CompareStatus(self.acquiring, FalconAcquiringStatus.DONE)
|
||||
self.cancel_on_stop(status)
|
||||
self.stop_all.put(1)
|
||||
status.wait(timeout=self._pv_timeout)
|
||||
|
||||
self.collect_mode.set(0).wait(timeout=self._pv_timeout)
|
||||
self.preset_real_time.set(0).wait(timeout=self._pv_timeout)
|
||||
|
||||
def on_unstage(self) -> DeviceStatus | StatusBase | None:
|
||||
"""Called while unstaging the device."""
|
||||
if self.acquiring.get() != FalconAcquiringStatus.DONE:
|
||||
self.stop_all.put(1)
|
||||
status = CompareStatus(self.acquiring, FalconAcquiringStatus.DONE)
|
||||
self.cancel_on_stop(status)
|
||||
return status
|
||||
|
||||
def on_pre_scan(self) -> DeviceStatus | StatusBase | None:
|
||||
"""Called right before the scan starts on all devices automatically."""
|
||||
|
||||
def on_trigger(self) -> DeviceStatus | StatusBase | None:
|
||||
"""Called when the device is triggered."""
|
||||
|
||||
def on_complete(self) -> DeviceStatus | StatusBase | None:
|
||||
"""Called to inquire if a device has completed a scans."""
|
||||
|
||||
def on_kickoff(self) -> DeviceStatus | StatusBase | None:
|
||||
"""Called to kickoff a device for a fly scan. Has to be called explicitly."""
|
||||
|
||||
def on_stop(self) -> None:
|
||||
"""Called when the device is stopped."""
|
||||
self.stop_all.put(1)
|
||||
|
||||
def update_data(self):
|
||||
"""
|
||||
Set the dead time corrected signal based on input count rate, output count rate, ROI count, and elapsed real time.
|
||||
|
||||
Parameters:
|
||||
icr (float): Input count rate.
|
||||
ocr (float): Output count rate.
|
||||
roi (float): ROI count.
|
||||
ert (float): Elapsed real time.
|
||||
"""
|
||||
|
||||
dead_time_corrected_signal = compute_dead_time_corrected_signal(
|
||||
self.icr.get(), self.ocr.get(), self.roi.get(), self.ert.get()
|
||||
)
|
||||
self.dead_cor_roi0_count.put(dead_time_corrected_signal)
|
||||
self.spectrum.put(self.spectrum_val.get())
|
||||
@@ -10,7 +10,7 @@ from ophyd import Device, DeviceStatus, EpicsSignal, EpicsSignalRO, Kind, Status
|
||||
from ophyd_devices import CompareStatus, TransitionStatus
|
||||
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
|
||||
|
||||
from superxas_bec.devices.falcon import FalconAcquiringStatus, FalconSuperXAS
|
||||
from superxas_bec.devices.falcon_slim import FalconAcquiringStatus, FalconSuperXASSlim
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
@@ -119,43 +119,34 @@ class Trigger(PSIDeviceBase, TriggerControl):
|
||||
and the sampling is done before data is being read from the device.
|
||||
"""
|
||||
if self.scan_info.msg.scan_name == "exafs_scan":
|
||||
exp_time = self.scan_info.msg.scan_parameters['integ_time'][self._trigger_index]
|
||||
self._trigger_index +=1
|
||||
exp_time = self.scan_info.msg.scan_parameters["integ_time"][self._trigger_index]
|
||||
self._trigger_index += 1
|
||||
self.set_exposure_time(exp_time).wait()
|
||||
time_started = time.time()
|
||||
logger.info(f"Triggering device {self.name} at {time_started}")
|
||||
|
||||
falcon = self.device_manager.devices.get("falcon", None)
|
||||
if falcon is not None and falcon.enabled is True:
|
||||
falcon: FalconSuperXAS
|
||||
falcon: FalconSuperXASSlim
|
||||
status = CompareStatus(falcon.acquiring, FalconAcquiringStatus.ACQUIRING)
|
||||
self.cancel_on_stop(status)
|
||||
falcon.erase_start.put(1)
|
||||
print(f"Acquiring state after erase_start: {FalconAcquiringStatus(falcon.acquiring.get())}")
|
||||
status.wait(timeout=5)
|
||||
time.sleep(0.4)
|
||||
status_smpl = TransitionStatus(
|
||||
self.smpl_done, [SamplingDone.RUNNING, SamplingDone.DONE]
|
||||
)
|
||||
status.wait(timeout=self._pv_timeout)
|
||||
time.sleep(0.4)
|
||||
status_smpl = TransitionStatus(self.smpl_done, [SamplingDone.RUNNING, SamplingDone.DONE])
|
||||
logger.info(f"Triggering sampling for {self.name} at {time.time() - time_started}")
|
||||
self.smpl.put(1)
|
||||
self.cancel_on_stop(status_smpl)
|
||||
status_smpl.wait()
|
||||
status_smpl.wait(timeout=self._pv_timeout)
|
||||
logger.info(f"Sampling done for {self.name} at {time.time() - time_started}")
|
||||
if falcon is not None and falcon.enabled is True:
|
||||
time.sleep(0.4)# Simulate some processing time
|
||||
time.sleep(0.4) # Simulate some processing time
|
||||
status = CompareStatus(falcon.acquiring, FalconAcquiringStatus.DONE)
|
||||
self.cancel_on_stop(status)
|
||||
falcon.stop_all.put(1)
|
||||
status.wait(timeout=5)
|
||||
status.wait(timeout=self._pv_timeout)
|
||||
time.sleep(0.4) # Simulate some processing time
|
||||
print(falcon.mca1.rois.roi0.count.get())
|
||||
print(falcon.mca1.elapsed_live_time.get())
|
||||
print(falcon.mca1.elapsed_real_time.get())
|
||||
print(falcon.max_elapsed_live.get())
|
||||
print(falcon.max_elapsed_real.get())
|
||||
# falcon.send_data()
|
||||
time.sleep(2) # Sleep currently needed until Falcon acquiring/readout discussion is resolved
|
||||
falcon.update_data()
|
||||
return status_smpl
|
||||
|
||||
def on_complete(self) -> DeviceStatus | StatusBase | None:
|
||||
|
||||
Reference in New Issue
Block a user