feat: xMAP and FalconX devices

This commit is contained in:
Xiaoqiang Wang 2024-11-19 08:43:00 +01:00 committed by appel_c
parent ebe5db6524
commit 3cf9d15bd3

View File

@ -0,0 +1,165 @@
"""
Base classes for XIA xMAP and FalconX dxp system.
Falcon interfaces with the dxpSITORO epics driver, https://github.com/epics-modules/dxpSITORO.
xMAP interfaces with the dxp epics driver, https://github.com/epics-modules/dxp.
An example usage for a 4-element FalconX system. ::
from ophyd import Component as Cpt
from ophyd_devices.devices.dxp import Falcon, EpicsMCARecord, EpicsDXPFalcon
from ophyd_devices.devices.areadetector.plugins import HDF5Plugin_V35 as HDF5Plugin
class FalconX4(Falcon):
# DXP parameters
dxp1 = Cpt(EpicsDXPFalcon, "dxp1:")
dxp2 = Cpt(EpicsDXPFalcon, "dxp2:")
dxp3 = Cpt(EpicsDXPFalcon, "dxp3:")
dxp4 = Cpt(EpicsDXPFalcon, "dxp4:")
# MCA record with spectrum data
mca1 = Cpt(EpicsMCARecord, "mca1")
mca2 = Cpt(EpicsMCARecord, "mca2")
mca3 = Cpt(EpicsMCARecord, "mca3")
mca4 = Cpt(EpicsMCARecord, "mca4")
# optionally with a HDF5 writer plugin
hdf = Cpt(HDF5Plugin, "HDF1:")
falcon = FalconX4("X07MB-SITORO:", name="falcon")
falcon.collect_mode.put(0) # 0: MCA spectra, 1: MCA mapping
falcon.preset_mode.put("Real time")
falcon.preset_real_time.put(1)
status = falcon.erase_start.set(1)
status.wait()
falcon.mca1.spectrum.get()
"""
from ophyd import Component as Cpt
from ophyd import Kind, EpicsSignal, EpicsSignalRO, Device
from ophyd.mca import EpicsMCARecord as _EpicsMCARecord, EpicsDXPBaseSystem, EpicsDXPMultiElementSystem, EpicsDXPMapping
from ophyd.areadetector import EpicsSignalWithRBV
__all__ = (
'EpicsMCARecord',
'EpicsDXPFalcon',
'Falcon',
'xMAP'
)
class EpicsMCARecord(_EpicsMCARecord):
"""EpicsMCARecord with addtional fields"""
calo = Cpt(EpicsSignal, ".CALO")
cals = Cpt(EpicsSignal, ".CALS")
calq = Cpt(EpicsSignal, ".CALQ")
tth = Cpt(EpicsSignal, ".TTH")
class EpicsDXPFalcon(Device):
"""All high-level DXP parameters for each channel"""
# Detection
detection_filter = Cpt(EpicsSignalWithRBV, "DetectionFilter")
detection_threshold = Cpt(EpicsSignalWithRBV, "DetectionThreshold")
min_pulse_pair_separation = Cpt(EpicsSignalWithRBV, "MinPulsePairSeparation")
# Pre-amp and energe range
detector_polarity = Cpt(EpicsSignalWithRBV, "DetectorPolarity")
decay_time = Cpt(EpicsSignalWithRBV, "DecayTime")
risetime_optimization = Cpt(EpicsSignalWithRBV, "RisetimeOptimization")
scale_factor = Cpt(EpicsSignalWithRBV, "ScaleFactor")
# Presets
preset_events = Cpt(EpicsSignalWithRBV, "PresetEvents")
preset_mode = Cpt(EpicsSignalWithRBV, "PresetMode", string=True)
preset_triggers = Cpt(EpicsSignalWithRBV, "PresetTriggers")
preset_real_time = Cpt(EpicsSignalWithRBV, "PresetReal")
# Couting statistics
elapsed_live_time = Cpt(EpicsSignalRO, "ElapsedLiveTime", lazy=True)
elapsed_real_time = Cpt(EpicsSignalRO, "ElapsedRealTime", lazy=True)
elapsed_trigger_live = Cpt(EpicsSignalRO, "ElapsedTriggerLiveTime", lazy=True)
triggers = Cpt(EpicsSignalRO, "Triggers", lazy=True)
events = Cpt(EpicsSignalRO, "Events", lazy=True)
input_count_rate = Cpt(EpicsSignalRO, "InputCountRate", lazy=True)
output_count_rate = Cpt(EpicsSignalRO, "OutputCountRate", lazy=True)
# Mapping
current_pixel = Cpt(EpicsSignal, "CurrentPixel")
# Diagnostic trace
trace_data = Cpt(EpicsSignal, "TraceData")
class EpicsDXPFalconMultiElementSystem(EpicsDXPBaseSystem):
# Preset control
preset_events = Cpt(EpicsSignal, "PresetEvents")
preset_real_time = Cpt(EpicsSignal, "PresetReal")
preset_mode = Cpt(EpicsSignal, "PresetMode", string=True)
preset_triggers = Cpt(EpicsSignal, "PresetTriggers")
# Acquisition control
erase_all = Cpt(EpicsSignal, "EraseAll")
erase_start = Cpt(EpicsSignal, "EraseStart", put_complete=True, trigger_value=1)
start_all = Cpt(EpicsSignal, "StartAll", put_complete=True, trigger_value=1)
stop_all = Cpt(EpicsSignal, "StopAll")
# Status
set_acquire_busy = Cpt(EpicsSignal, "SetAcquireBusy")
acquire_busy = Cpt(EpicsSignal, "AcquireBusy")
status_all = Cpt(EpicsSignal, "StatusAll")
status_all_once = Cpt(EpicsSignal, "StatusAllOnce")
acquiring = Cpt(EpicsSignal, "Acquiring")
# Reading
read_all = Cpt(EpicsSignal, "ReadAll", kind=Kind.omitted)
read_all_once = Cpt(EpicsSignal, "ReadAllOnce", kind=Kind.omitted)
# As a debugging note, if snl_connected is not '1', your IOC is
# misconfigured:
snl_connected = Cpt(EpicsSignal, "SNL_Connected")
# High-level parameters
copy_decay_time = Cpt(EpicsSignal, "CopyDecayTime", kind=Kind.omitted)
copy_detection_filter = Cpt(EpicsSignal, "CopyDetectionFilter", kind=Kind.omitted)
copy_detection_threshold = Cpt(EpicsSignal, "CopyDetectionThreshold", kind=Kind.omitted)
copy_detector_polarity = Cpt(EpicsSignal, "CopyDetectorPolarity", kind=Kind.omitted)
copy_min_pulse_pair_separation = Cpt(EpicsSignal, "CopyMinPulsePairSeparation", kind=Kind.omitted)
copt_risetime_optimization = Cpt(EpicsSignal, "CopyRisetimeOptimization", kind=Kind.omitted)
copy_scale_factor = Cpt(EpicsSignal, "CopyScaleFactor", kind=Kind.omitted)
read_traces = Cpt(EpicsSignal, "ReadTraces", kind=Kind.omitted)
# ROI and SCA
copy_roic_hannel = Cpt(EpicsSignal, "CopyROIChannel", kind=Kind.omitted)
copy_roie_nergy = Cpt(EpicsSignal, "CopyROIEnergy", kind=Kind.omitted)
copy_roi_sca = Cpt(EpicsSignal, "CopyROI_SCA", kind=Kind.omitted)
# do_* executes the process:
do_read_all = Cpt(EpicsSignal, "DoReadAll", kind=Kind.omitted)
do_status_all = Cpt(EpicsSignal, "DoStatusAll", kind=Kind.omitted)
do_read_traces = Cpt(EpicsSignal, "DoReadTraces", kind=Kind.omitted)
# Statistics
dead_time = Cpt(EpicsSignal, "DeadTime")
idead_time = Cpt(EpicsSignal, "IDeadTime")
max_elapsed_live = Cpt(EpicsSignal, "MaxElapsedLive")
max_elapsed_real = Cpt(EpicsSignal, "MaxElapsedReal")
max_elapsed_trigger_live = Cpt(EpicsSignal, "MaxElapsedTriggerLive")
max_triggers = Cpt(EpicsSignal, "MaxTriggers")
max_events = Cpt(EpicsSignal, "MaxEvents")
max_input_count_rate = Cpt(EpicsSignal, "MaxInputCountRate")
max_output_count_rate = Cpt(EpicsSignal, "MaxOutputCountRate")
class EpicsDxpFalconMapping(EpicsDXPMapping):
auto_apply = None
apply = None
nd_array_mode = Cpt(EpicsSignalWithRBV, "NDArrayMode")
class Falcon(EpicsDXPFalconMultiElementSystem, EpicsDxpFalconMapping):
...
class xMAP(EpicsDXPMultiElementSystem, EpicsDXPMapping):
# Override signals from EpicsDXPMultiElementSystem, so calling `set`` method
# returns a waitable Status object. Otherwise the Status object is immediately done.
erase_start = Cpt(EpicsSignal, "EraseStart", put_complete=True, trigger_value=1)
start_all = Cpt(EpicsSignal, "StartAll", put_complete=True, trigger_value=1)