Source code for apstools.devices.aps_undulator

"""
APS undulators (Insertion Devices)
++++++++++++++++++++++++++++++++++

.. autosummary::

   ~PlanarUndulator
   ~Revolver_Undulator
   ~STI_Undulator
   ~Undulator2M
   ~Undulator4M

.. note:: The ``ApsUndulator`` and ``ApsUndulatorDual`` device support
    classes have been removed.  These devices are not used in the APS-U era.
"""

import logging

from ophyd import Component
from ophyd import DerivedSignal
from ophyd import Device
from ophyd import EpicsSignal
from ophyd import EpicsSignalRO
from ophyd import PVPositioner


logger = logging.getLogger(__name__)

POSITIONER_DONE = 1


[docs]class UndulatorPositioner(PVPositioner): """A positioner for any of the gap control parameters. Communicates with the parent (presumably the undulator device) to start and stop the device. .. autosummary:: ~setpoint ~readback ~actuate ~stop_signal ~done ~done_value """ setpoint = Component(EpicsSignal, "SetC.VAL") readback = Component(EpicsSignalRO, "M.VAL") actuate = Component(DerivedSignal, derived_from="parent.start_button", kind="omitted") stop_signal = Component(DerivedSignal, derived_from="parent.stop_button", kind="omitted") done = Component(DerivedSignal, derived_from="parent.done", kind="omitted") done_value = POSITIONER_DONE
[docs]class ID_Controls_Mixin(Device): """Common controls components for insertion devices. Works for: Planar & Revolver The signals *busy* and *done* convey complementary information. *busy* comes from the IOC, while *done* comes directly from the controller. .. autosummary:: ~start_button ~stop_button ~busy ~done ~motor_drive_status """ # Signals for moving the undulator start_button = Component(EpicsSignal, "StartC.VAL", put_complete=True, kind="omitted") stop_button = Component(EpicsSignal, "StopC.VAL", kind="omitted") busy = Component(EpicsSignalRO, "BusyM.VAL", kind="omitted") done = Component(EpicsSignalRO, "BusyDeviceM.VAL", kind="omitted") motor_drive_status = Component(EpicsSignalRO, "MotorDriveStatusM.VAL", kind="omitted")
[docs]class ID_Misc_Mixin(Device): """Common miscellaneous components for insertion devices. Works for: Planar & Revolver .. autosummary:: ~gap_deadband ~device_limit ~access_mode ~message1 ~message2 ~device ~magnet ~location ~version_plc ~version_hpmu """ # Miscellaneous control signals gap_deadband = Component(EpicsSignal, "DeadbandGapC", kind="config") device_limit = Component(EpicsSignal, "DeviceLimitM.VAL", kind="config") access_mode = Component(EpicsSignalRO, "AccessSecurityC", kind="omitted") message1 = Component(EpicsSignalRO, "Message1M.VAL", kind="omitted") message2 = Component(EpicsSignalRO, "Message2M.VAL", kind="omitted") device = Component(EpicsSignalRO, "DeviceM", kind="config") magnet = Component(EpicsSignalRO, "DeviceMagnetM", kind="config") location = Component(EpicsSignalRO, "LocationM", kind="config") version_plc = Component(EpicsSignalRO, "PLCVersionM.VAL", kind="config") version_hpmu = Component(EpicsSignalRO, "HPMUVersionM.VAL", kind="config")
[docs]class ID_Spectrum_Mixin(Device): """Common spectrum components for insertion devices. Works for: Planar & Revolver .. autosummary:: ~energy ~energy_taper ~gap ~gap_taper ~harmonic_value ~total_power """ # X-ray spectrum parameters energy = Component(UndulatorPositioner, "Energy") energy_taper = Component(UndulatorPositioner, "TaperEnergy") gap = Component(UndulatorPositioner, "Gap") gap_taper = Component(UndulatorPositioner, "TaperGap") harmonic_value = Component(EpicsSignal, "HarmonicValueC", kind="config") total_power = Component(EpicsSignalRO, "TotalPowerM.VAL", kind="config")
[docs]class PlanarUndulator(ID_Spectrum_Mixin, ID_Controls_Mixin, ID_Misc_Mixin, Device): """APS Planar Undulator. .. index:: Ophyd Device; PlanarUndulator APS Use: 34 devices, including 20ID. EXAMPLE:: undulator = PlanarUndulator("S25ID:USID:", name="undulator") """
[docs]class Revolver_Undulator(ID_Spectrum_Mixin, ID_Controls_Mixin, ID_Misc_Mixin, Device): """APS Revolver Insertion Device. .. index:: Ophyd Device; PlanarUndulator APS Use: Only 08US, 08DS, 34DS. EXAMPLE:: undulator = Revolver_Undulator("S08ID:USID:", name="undulator") """ # Revolver control signals revolver_select = Component(EpicsSignal, "RevolverSelectC.VAL", kind="config") status_position1 = Component(EpicsSignalRO, "Position1M.VAL", kind="config") status_position2 = Component(EpicsSignalRO, "Position2M.VAL", kind="config") status_safe_gap = Component(EpicsSignalRO, "AtSafeGapM.VAL", kind="config")
[docs]class STI_Undulator(PlanarUndulator): """APS Planar Undulator built by STI Optronics. .. index:: Ophyd Device; PlanarUndulator Ophyd Device; STI_Undulator APS Use: 13 devices, including 4ID. EXAMPLE:: undulator = STI_Undulator("S04ID:USID:", name="undulator") """
[docs]class Undulator2M(ID_Spectrum_Mixin, ID_Controls_Mixin, ID_Misc_Mixin, Device): """APS 2M Undulator. .. index:: Ophyd Device; PlanarUndulator Ophyd Device; Undulator2M APS Use: 1ID, downstream. EXAMPLE:: undulator = Undulator2M("S01ID:DSID:", name="undulator") """ # PVs not found busy = None magnet = None version_plc = None version_hpmu = None done = Component(EpicsSignalRO, "BusyM.VAL", kind="omitted") done_value = 0
[docs]class Undulator4M(Undulator2M): """APS 4M Undulator. .. index:: Ophyd Device; PlanarUndulator Ophyd Device; Undulator4M APS Use: 11ID, downstream & upstream. EXAMPLE:: undulator = Undulator4M("S11ID:DSID:", name="undulator") """
# ----------------------------------------------------------------------------- # :author: Pete R. Jemian # :email: jemian@anl.gov # :copyright: (c) 2017-2024, UChicago Argonne, LLC # # Distributed under the terms of the Argonne National Laboratory Open Source License. # # The full license is in the file LICENSE.txt, distributed with this software. # -----------------------------------------------------------------------------