Devices

(ophyd) Devices that might be useful at the APS using Bluesky

Also consult the Index under the Ophyd heading for links to the Devices, Exceptions, Mixins, Signals, and other support items described here.

Categories

APS General Support

ApsCycleDM(*args, **kwargs)

Get the APS cycle name from the APS Data Management system or a local file.

ApsMachineParametersDevice(*args, **kwargs)

Common operational parameters of the APS of general interest.

ApsPssShutter(*args, **kwargs)

APS PSS shutter

ApsPssShutterWithStatus(*args, **kwargs)

APS PSS shutter with separate status PV

SimulatedApsPssShutterWithStatus(*args, **kwargs)

Simulated APS PSS shutter

Area Detector Support

AD_EpicsHdf5FileName(*args, **kwargs)

custom class to define image file name from EPICS

AD_EpicsJpegFileName(*args, **kwargs)

custom class to define image file name from EPICS

AD_plugin_primed(plugin)

Has area detector pushed an NDarray to the file writer plugin? True or False

AD_prime_plugin(detector, plugin)

Prime this area detector's file writer plugin.

AD_setup_FrameType(prefix[, scheme])

configure so frames are identified & handled by type (dark, white, or image)

Detector & Scaler Support

Struck3820(*args, **kwargs)

Struck/SIS 3820 Multi-Channel Scaler (as used by USAXS)

use_EPICS_scaler_channels(scaler)

configure scaler for only the channels with names assigned in EPICS

SynPseudoVoigt(*args, **kwargs)

Evaluate a point on a pseudo-Voigt based on the value of a motor.

Motors, Positioners, Axes, …

AxisTunerException

Exception during execution of AxisTunerBase subclass

AxisTunerMixin(*args, **kwargs)

Mixin class to provide tuning capabilities for an axis

EpicsDescriptionMixin(*args, **kwargs)

add a record's description field to a Device, such as EpicsMotor

EpicsMotorDialMixin(*args, **kwargs)

add motor record's dial coordinate fields to Device

EpicsMotorEnableMixin(*args, **kwargs)

mixin providing access to motor enable/disable

EpicsMotorLimitsMixin(*args, **kwargs)

add motor record HLM & LLM fields & compatibility get_lim() and set_lim()

EpicsMotorRawMixin(*args, **kwargs)

add motor record's raw coordinate fields to Device

EpicsMotorResolutionMixin(*args, **kwargs)

Add motor record's resolution fields to motor.

EpicsMotorServoMixin(*args, **kwargs)

add motor record's servo loop controls to Device

PVPositionerSoftDone(*args, **kwargs)

PVPositioner that computes done as a soft signal.

PVPositionerSoftDoneWithStop(*args, **kwargs)

PVPositionerSoftDone with stop() and inposition.

EpicsMotorShutter(*args, **kwargs)

Shutter, implemented with an EPICS motor moved between two positions

EpicsOnOffShutter(*args, **kwargs)

Shutter using a single EPICS PV moved between two positions

Shutters

ApsPssShutter(*args, **kwargs)

APS PSS shutter

ApsPssShutterWithStatus(*args, **kwargs)

APS PSS shutter with separate status PV

EpicsMotorShutter(*args, **kwargs)

Shutter, implemented with an EPICS motor moved between two positions

EpicsOnOffShutter(*args, **kwargs)

Shutter using a single EPICS PV moved between two positions

OneSignalShutter(*args, **kwargs)

Shutter Device using one Signal for open and close.

ShutterBase(*args, **kwargs)

Base class for all shutter Devices.

SimulatedApsPssShutterWithStatus(*args, **kwargs)

Simulated APS PSS shutter

Slits

XiaSlit2D(*args, **kwargs)

EPICS synApps optics xia_slit.db 2D support: inb out bot top ...

Optics2Slit1D(*args, **kwargs)

EPICS synApps optics 2slit.db 1D support: xn, xp, size, center, sync

Optics2Slit2D_HV(*args, **kwargs)

EPICS synApps optics 2slit.db 2D support: h.xn, h.xp, v.xn, v.xp

Optics2Slit2D_InbOutBotTop(*args, **kwargs)

EPICS synApps optics 2slit.db 2D support: inb, out, bot, top

SlitGeometry(width, height, x, y)

Slit size and center as a named tuple

synApps Support

Temperature Controllers

Eurotherm2216e(*args, **kwargs)

Eurotherm 2216e Temperature Controller

LakeShore336Device(*args, **kwargs)

LakeShore 336 temperature controller.

LakeShore340Device(*args, **kwargs)

LakeShore 340 temperature controller

Linkam_CI94_Device(*args, **kwargs)

Linkam model CI94 temperature controller

Linkam_T96_Device(*args, **kwargs)

Linkam model T96 temperature controller

PTC10AioChannel(*args, **kwargs)

SRS PTC10 AIO module

PTC10RtdChannel(*args, **kwargs)

SRS PTC10 RTD module channel

PTC10TcChannel(*args, **kwargs)

SRS PTC10 Tc (thermocouple) module channel

PTC10PositionerMixin(*args, **kwargs)

Mixin so SRS PTC10 can be used as a (temperature) positioner.

Other Support

ApsBssUserInfoDevice(*args, **kwargs)

Provide current experiment info from the APS BSS.

Pf4FilterSingle(*args, **kwargs)

XIA PF4 Filter: one set of 4 filters (A).

Pf4FilterDual(*args, **kwargs)

XIA PF4 Filter: two sets of 4 filters (A, B).

Pf4FilterTriple(*args, **kwargs)

XIA PF4 Filter: three sets of 4 filters (A, B, C).

Pf4FilterBank(*args, **kwargs)

A single module of XIA PF4 filters (4-blades).

Pf4FilterCommon(*args, **kwargs)

XIA PF4 filters - common support.

DualPf4FilterBox(*args, **kwargs)

LEGACY (use Pf4FilterDual now): Dual (Al, Ti) Xia PF4 filter boxes

EpicsDescriptionMixin(*args, **kwargs)

add a record's description field to a Device, such as EpicsMotor

KohzuSeqCtl_Monochromator(*args, **kwargs)

synApps Kohzu double-crystal monochromator sequence control program

SRS570_PreAmplifier(*args, **kwargs)

Ophyd support for Stanford Research Systems 570 preamplifier from synApps.

Struck3820(*args, **kwargs)

Struck/SIS 3820 Multi-Channel Scaler (as used by USAXS)

Internal Routines

ApsOperatorMessagesDevice(*args, **kwargs)

General messages from the APS main control room.

TrackingSignal(*args, **kwargs)

Non-EPICS signal for use when coordinating Device actions.

DeviceMixinBase(*args, **kwargs)

Base class for apstools Device mixin classes

All Submodules

APS User Proposal and ESAF Information

ApsBssUserInfoDevice(*args, **kwargs)

Provide current experiment info from the APS BSS.

class apstools.devices.aps_bss_user.ApsBssUserInfoDevice(*args: Any, **kwargs: Any)[source]

Provide current experiment info from the APS BSS.

BSS: Beamtime Scheduling System

EXAMPLE:

bss_user_info = ApsBssUserInfoDevice(
                    "9id_bss:",
                    name="bss_user_info")
sd.baseline.append(bss_user_info)

NOTE: There is info provided by the APS proposal & ESAF systems.

Area Detector Support

AD_setup_FrameType(prefix[, scheme])

configure so frames are identified & handled by type (dark, white, or image)

AD_plugin_primed(plugin)

Has area detector pushed an NDarray to the file writer plugin? True or False

AD_prime_plugin(detector, plugin)

Prime this area detector's file writer plugin.

AD_prime_plugin2(plugin)

Prime this area detector's file writer plugin.

AD_EpicsHdf5FileName(*args, **kwargs)

custom class to define image file name from EPICS

AD_EpicsJpegFileName(*args, **kwargs)

custom class to define image file name from EPICS

class apstools.devices.area_detector_support.AD_EpicsHdf5FileName(*args: Any, **kwargs: Any)[source]

custom class to define image file name from EPICS

Caution

Caveat emptor applies here. You assume expertise!

Replace standard Bluesky algorithm where file names are defined as UUID strings, virtually guaranteeing that no existing images files will ever be overwritten.

Also, this method decouples the data files from the databroker, which needs the files to be named by UUID.

make_filename()

overrides default behavior: Get info from EPICS HDF5 plugin.

generate_datum(key, timestamp, datum_kwargs)

Generate a uid and cache it with its key for later insertion.

get_frames_per_point()

overrides default behavior

stage()

overrides default behavior

To allow users to control the file name, we override the make_filename() method here and we need to override some intervening classes.

To allow users to control the file number, we override the stage() method here and triple-comment out that line, and bring in sections from the methods we are replacing here.

The image file name is set in FileStoreBase.make_filename() from ophyd.areadetector.filestore_mixins. This is called (during device staging) from FileStoreBase.stage()

EXAMPLE:

To use this custom class, we need to connect it to some intervening structure. Here are the steps:

  1. override default file naming

  2. use to make your custom iterative writer

  3. use to make your custom HDF5 plugin

  4. use to make your custom AD support

imports:

from bluesky import RunEngine, plans as bp
from ophyd.areadetector import SimDetector, SingleTrigger
from ophyd.areadetector import ADComponent, ImagePlugin, SimDetectorCam
from ophyd.areadetector import HDF5Plugin
from ophyd.areadetector.filestore_mixins import FileStoreIterativeWrite

override default file naming:

from apstools.devices import AD_EpicsHdf5FileName

make a custom iterative writer:

class myHdf5EpicsIterativeWriter(AD_EpicsHdf5FileName, FileStoreIterativeWrite): pass

make a custom HDF5 plugin:

class myHDF5FileNames(HDF5Plugin, myHdf5EpicsIterativeWriter): pass

define support for the detector (simulated detector here):

class MySimDetector(SingleTrigger, SimDetector):
    '''SimDetector with HDF5 file names specified by EPICS'''

    cam = ADComponent(SimDetectorCam, "cam1:")
    image = ADComponent(ImagePlugin, "image1:")

    hdf1 = ADComponent(
        myHDF5FileNames,
        suffix = "HDF1:",
        root = "/",
        write_path_template = "/",
        )

create an instance of the detector:

simdet = MySimDetector("13SIM1:", name="simdet")
if hasattr(simdet.hdf1.stage_sigs, "array_counter"):
    # remove this so array counter is not set to zero each staging
    del simdet.hdf1.stage_sigs["array_counter"]
simdet.hdf1.stage_sigs["file_template"] = '%s%s_%3.3d.h5'

setup the file names using the EPICS HDF5 plugin:

simdet.hdf1.file_path.put("/tmp/simdet_demo/")    # ! ALWAYS end with a "/" !
simdet.hdf1.file_name.put("test")
simdet.hdf1.array_counter.put(0)

If you have not already, create a bluesky RunEngine:

RE = RunEngine({})

take an image:

RE(bp.count([simdet]))

INTERNAL METHODS

generate_datum(key, timestamp, datum_kwargs)[source]

Generate a uid and cache it with its key for later insertion.

get_frames_per_point()[source]

overrides default behavior

make_filename()[source]

overrides default behavior: Get info from EPICS HDF5 plugin.

stage()[source]

overrides default behavior

Set EPICS items before device is staged, then copy EPICS naming template (and other items) to ophyd after staging.

class apstools.devices.area_detector_support.AD_EpicsJpegFileName(*args: Any, **kwargs: Any)[source]

custom class to define image file name from EPICS

Caution

Caveat emptor applies here. You assume expertise!

Replace standard Bluesky algorithm where file names are defined as UUID strings, virtually guaranteeing that no existing images files will ever be overwritten. Also, this method decouples the data files from the databroker, which needs the files to be named by UUID.

make_filename()

overrides default behavior: Get info from EPICS JPEG plugin.

generate_datum(key, timestamp, datum_kwargs)

Generate a uid and cache it with its key for later insertion.

get_frames_per_point()

overrides default behavior

stage()

overrides default behavior Set EPICS items before device is staged, then copy EPICS naming template (and other items) to ophyd after staging.

Patterned on apstools.devices.AD_EpicsHdf5FileName(). (Follow that documentation from this point.)

generate_datum(key, timestamp, datum_kwargs)[source]

Generate a uid and cache it with its key for later insertion.

get_frames_per_point()[source]

overrides default behavior

make_filename()[source]

overrides default behavior: Get info from EPICS JPEG plugin.

stage()[source]

overrides default behavior Set EPICS items before device is staged, then copy EPICS naming template (and other items) to ophyd after staging.

apstools.devices.area_detector_support.AD_plugin_primed(plugin)[source]

Has area detector pushed an NDarray to the file writer plugin? True or False

PARAMETERS

plugin

obj : area detector plugin to be primed (such as detector.hdf1)

EXAMPLE:

AD_plugin_primed(detector.hdf1)

Works around an observed issue: #598 https://github.com/NSLS-II/ophyd/issues/598#issuecomment-414311372

If detector IOC has just been started and has not yet taken an image with the file writer plugin, then a TimeoutError will occur as the file writer plugin “Capture” is set to 1 (Start). In such case, first acquire at least one image with the file writer plugin enabled.

Also issue in apstools (needs a robust method to detect if primed): https://github.com/BCDA-APS/apstools/issues/464

Since Area Detector release 2.1 (2014-10-14).

The prime process is not needed if you select the LazyOpen feature with Stream mode for the file plugin. LazyOpen defers file creation until the first frame arrives in the plugin. This removes the need to initialize the plugin with a dummy frame before starting capture.

apstools.devices.area_detector_support.AD_prime_plugin(detector, plugin)[source]

Prime this area detector’s file writer plugin.

PARAMETERS

detector

obj : area detector (such as detector)

plugin

obj : area detector plugin to be primed (such as detector.hdf1)

EXAMPLE:

AD_prime_plugin(detector, detector.hdf1)
apstools.devices.area_detector_support.AD_prime_plugin2(plugin)[source]

Prime this area detector’s file writer plugin.

Collect and push an NDarray to the file writer plugin. Works with all file writer plugins.

Based on ophyd.areadetector.plugins.HDF5Plugin.warmup().

PARAMETERS

plugin

obj : area detector plugin to be primed (such as detector.hdf1)

EXAMPLE:

AD_prime_plugin2(detector.hdf1)
apstools.devices.area_detector_support.AD_setup_FrameType(prefix, scheme='NeXus')[source]

configure so frames are identified & handled by type (dark, white, or image)

PARAMETERS

prefix

str : EPICS PV prefix of area detector, such as 13SIM1:

scheme

str : any key in the AD_FrameType_schemes dictionary

This routine prepares the EPICS Area Detector to identify frames by image type for handling by clients, such as the HDF5 file writing plugin. With the HDF5 plugin, the FrameType PV is added to the NDattributes and then used in the layout file to direct the acquired frame to the chosen dataset. The FrameType PV value provides the HDF5 address to be used.

To use a different scheme than the defaults, add a new key to the AD_FrameType_schemes dictionary, defining storage values for the fields of the EPICS mbbo record that you will be using.

see: https://nbviewer.jupyter.org/github/BCDA-APS/use_bluesky/blob/main/lessons/sandbox/images_darks_flats.ipynb

EXAMPLE:

AD_setup_FrameType("2bmbPG3:", scheme="DataExchange")
  • Call this function before creating the ophyd area detector object

  • use lower-level PyEpics interface

APS cycles

ApsCycleDM(*args, **kwargs)

Get the APS cycle name from the APS Data Management system or a local file.

class apstools.devices.aps_cycle.ApsCycleDM(*args: Any, **kwargs: Any)[source]

Get the APS cycle name from the APS Data Management system or a local file.

This signal is read-only.

APS Machine Parameters

APS machine parameters

ApsMachineParametersDevice(*args, **kwargs)

Common operational parameters of the APS of general interest.

ApsOperatorMessagesDevice(*args, **kwargs)

General messages from the APS main control room.

class apstools.devices.aps_machine.ApsMachineParametersDevice(*args: Any, **kwargs: Any)[source]

Common operational parameters of the APS of general interest.

EXAMPLE:

import apstools.devices as APS_devices
APS = APS_devices.ApsMachineParametersDevice(name="APS")
aps_current = APS.current

# make sure these values are logged at start and stop of every scan
sd.baseline.append(APS)
# record storage ring current as secondary stream during scans
# name: aps_current_monitor
# db[-1].table("aps_current_monitor")
sd.monitors.append(aps_current)

The sd.baseline and sd.monitors usage relies on this global setup:

from bluesky import SupplementalData sd = SupplementalData() RE.preprocessors.append(sd)

inUserOperations

determine if APS is in User Operations mode (boolean)

aps_cycle

alias of apstools.devices.aps_cycle.ApsCycleDM

property inUserOperations

determine if APS is in User Operations mode (boolean)

Use this property to configure ophyd Devices for direct or simulated hardware. See issue #49 (https://github.com/BCDA-APS/apstools/issues/49) for details.

EXAMPLE:

APS = apstools.devices.ApsMachineParametersDevice(name="APS")

if APS.inUserOperations:
    suspend_APS_current = bluesky.suspenders.SuspendFloor(APS.current, 2, resume_thresh=10)
    RE.install_suspender(suspend_APS_current)
else:
    # use pseudo shutter controls and no current suspenders
    pass
operator_messages

alias of apstools.devices.aps_machine.ApsOperatorMessagesDevice

class apstools.devices.aps_machine.ApsOperatorMessagesDevice(*args: Any, **kwargs: Any)[source]

General messages from the APS main control room.

APS undulator

ApsUndulator(*args, **kwargs)

APS Undulator

ApsUndulatorDual(*args, **kwargs)

APS Undulator with upstream and downstream controls

class apstools.devices.aps_undulator.ApsUndulator(*args: Any, **kwargs: Any)[source]

APS Undulator

EXAMPLE:

undulator = ApsUndulator("ID09ds:", name="undulator")
tracking

alias of apstools.devices.tracking_signal.TrackingSignal

class apstools.devices.aps_undulator.ApsUndulatorDual(*args: Any, **kwargs: Any)[source]

APS Undulator with upstream and downstream controls

EXAMPLE:

undulator = ApsUndulatorDual("ID09", name="undulator")

note:: the trailing : in the PV prefix should be omitted

downstream

alias of apstools.devices.aps_undulator.ApsUndulator

upstream

alias of apstools.devices.aps_undulator.ApsUndulator

Axis Tuner

AxisTunerException

Exception during execution of AxisTunerBase subclass

AxisTunerMixin(*args, **kwargs)

Mixin class to provide tuning capabilities for an axis

exception apstools.devices.axis_tuner.AxisTunerException[source]

Exception during execution of AxisTunerBase subclass

class apstools.devices.axis_tuner.AxisTunerMixin(*args: Any, **kwargs: Any)[source]

Mixin class to provide tuning capabilities for an axis

See the TuneAxis() example in this jupyter notebook: https://github.com/BCDA-APS/apstools/blob/master/docs/source/resources/demo_tuneaxis.ipynb

HOOK METHODS

There are two hook methods (pre_tune_method(), and post_tune_method()) for callers to add additional plan parts, such as opening or closing shutters, setting detector parameters, or other actions.

Each hook method must accept a single argument: an axis object such as EpicsMotor or SynAxis, such as:

def my_pre_tune_hook(axis):
    yield from bps.mv(shutter, "open")
def my_post_tune_hook(axis):
    yield from bps.mv(shutter, "close")

class TunableSynAxis(AxisTunerMixin, SynAxis): pass

myaxis = TunableSynAxis(name="myaxis")
mydet = SynGauss('mydet', myaxis, 'myaxis', center=0.21, Imax=0.98e5, sigma=0.127)
myaxis.tuner = TuneAxis([mydet], myaxis)
myaxis.pre_tune_method = my_pre_tune_hook
myaxis.post_tune_method = my_post_tune_hook

def tune_myaxis():
    yield from myaxis.tune(md={"plan_name": "tune_myaxis"})

RE(tune_myaxis())

Mixin to add EPICS .DESC field

EpicsDescriptionMixin(*args, **kwargs)

add a record's description field to a Device, such as EpicsMotor

class apstools.devices.description_mixin.EpicsDescriptionMixin(*args: Any, **kwargs: Any)[source]

add a record’s description field to a Device, such as EpicsMotor

EXAMPLE:

from ophyd import EpicsMotor
from apstools.devices import EpicsDescriptionMixin

class MyEpicsMotor(EpicsDescriptionMixin, EpicsMotor): pass
m1 = MyEpicsMotor('xxx:m1', name='m1')
print(m1.desc.get())

more ideas:

class TunableSynAxis(AxisTunerMixin, SynAxis):
    '''synthetic axis that can be tuned'''
class TunableEpicsMotor(AxisTunerMixin, EpicsMotor):
    '''EpicsMotor that can be tuned'''
class EpicsMotorWithDescription(EpicsDescriptionMixin, EpicsMotor):
    '''EpicsMotor with description field'''

class EpicsMotorWithMore(
    EpicsDescriptionMixin,
    EpicsMotorLimitsMixin,
    EpicsMotorDialMixin,
    EpicsMotorRawMixin,
    EpicsMotor):
    '''
    EpicsMotor with more fields

    * description (``desc``)
    * soft motor limits (``soft_limit_hi``, ``soft_limit_lo``)
    * dial coordinates (``dial``)
    * raw coordinates (``raw``)
    '''

Eurotherm 2216e Temperature Controller

The 2216e is a temperature controller from Eurotherm.

Eurotherm2216e(*args, **kwargs)

Eurotherm 2216e Temperature Controller

According to their website, the [Eurotherm 2216e Temperature Controller](https://www.eurothermcontrollers.com/eurotherm-2216e-series-controller-now-obsolete/) is obsolete. Please see replacement [EPC3016](https://www.eurothermcontrollers.com/eurotherm-epc3016-1-16-din-process-and-temperature-controller/) in our [EPC3000 Series](https://www.eurothermcontrollers.com/epc3000-series).

New in apstools 1.6.0.

class apstools.devices.eurotherm_2216e.Eurotherm2216e(*args: Any, **kwargs: Any)[source]

Eurotherm 2216e Temperature Controller

cb_sensor(*args, **kwargs)[source]

units: Convert dC from sensor to C

Kohzu double-crystal monochromator

KohzuSeqCtl_Monochromator(*args, **kwargs)

synApps Kohzu double-crystal monochromator sequence control program

class apstools.devices.kohzu_monochromator.KohzuSeqCtl_Monochromator(*args: Any, **kwargs: Any)[source]

synApps Kohzu double-crystal monochromator sequence control program

calibrate_energy(value)[source]

Calibrate the monochromator energy.

PARAMETERS

value: float

New energy for the current monochromator position.

energy

alias of apstools.devices.kohzu_monochromator.KohzuSoftPositioner

theta

alias of apstools.devices.kohzu_monochromator.KohzuSoftPositioner

wavelength

alias of apstools.devices.kohzu_monochromator.KohzuSoftPositioner

class apstools.devices.kohzu_monochromator.KohzuSoftPositioner(*args: Any, **kwargs: Any)[source]
cb_done(*args, **kwargs)[source]

Called when parent’s done signal changes (EPICS CA monitor event).

cb_setpoint(*args, **kwargs)[source]

Called when setpoint changes (EPICS CA monitor event).

When the setpoint is changed, force done=False. For any move, done must transition to != done_value, then back to done_value. Next update will refresh value from parent device.

property inposition

Report (boolean) if positioner is done.

move(*args, **kwargs)[source]

Reposition, with optional wait for completion.

Lakeshore temperature controllers

LakeShore336Device(*args, **kwargs)

LakeShore 336 temperature controller.

LakeShore340Device(*args, **kwargs)

LakeShore 340 temperature controller

class apstools.devices.lakeshore_controllers.LS340_LoopBase(*args: Any, **kwargs: Any)[source]

Base settings for both sample and control loops.

class apstools.devices.lakeshore_controllers.LS340_LoopControl(*args: Any, **kwargs: Any)[source]

Control specific

class apstools.devices.lakeshore_controllers.LS340_LoopSample(*args: Any, **kwargs: Any)[source]

Sample specific

class apstools.devices.lakeshore_controllers.LakeShore336Device(*args: Any, **kwargs: Any)[source]

LakeShore 336 temperature controller.

  • loop 1: temperature positioner AND heater, PID, & ramp controls

  • loop 2: temperature positioner AND heater, PID, & ramp controls

  • loop 3: temperature positioner

  • loop 4: temperature positioner

loop1

alias of apstools.devices.lakeshore_controllers.LakeShore336_LoopControl

loop2

alias of apstools.devices.lakeshore_controllers.LakeShore336_LoopControl

loop3

alias of apstools.devices.lakeshore_controllers.LakeShore336_LoopRO

loop4

alias of apstools.devices.lakeshore_controllers.LakeShore336_LoopRO

serial

alias of apstools.synApps.asyn.AsynRecord

class apstools.devices.lakeshore_controllers.LakeShore336_LoopControl(*args: Any, **kwargs: Any)[source]

LakeShore 336 temperature controller – with heater control.

The LakeShore 336 accepts up to two heaters.

class apstools.devices.lakeshore_controllers.LakeShore336_LoopRO(*args: Any, **kwargs: Any)[source]

LakeShore 336 temperature controller – Read-only loop (no heaters).

class apstools.devices.lakeshore_controllers.LakeShore340Device(*args: Any, **kwargs: Any)[source]

LakeShore 340 temperature controller

control

alias of apstools.devices.lakeshore_controllers.LS340_LoopControl

sample

alias of apstools.devices.lakeshore_controllers.LS340_LoopSample

serial

alias of apstools.synApps.asyn.AsynRecord

Linkam temperature controllers

Linkam_CI94_Device(*args, **kwargs)

Linkam model CI94 temperature controller

Linkam_T96_Device(*args, **kwargs)

Linkam model T96 temperature controller

class apstools.devices.linkam_controllers.Linkam_CI94_Device(*args: Any, **kwargs: Any)[source]

Linkam model CI94 temperature controller

EXAMPLE:

ci94 = Linkam_CI94_Device("IOC:ci94:", name="ci94")
temperature

alias of apstools.devices.positioner_soft_done.PVPositionerSoftDoneWithStop

class apstools.devices.linkam_controllers.Linkam_T96_Device(*args: Any, **kwargs: Any)[source]

Linkam model T96 temperature controller

EXAMPLE:

tc1 = Linkam_T96("IOC:tc1:", name="tc1")
temperature

alias of apstools.devices.linkam_controllers.T96Temperature

class apstools.devices.linkam_controllers.T96Temperature(*args: Any, **kwargs: Any)[source]

Base class for Device Mixins

DeviceMixinBase(*args, **kwargs)

Base class for apstools Device mixin classes

class apstools.devices.mixin_base.DeviceMixinBase(*args: Any, **kwargs: Any)[source]

Base class for apstools Device mixin classes

Mixin classes for Motor Devices

EpicsMotorDialMixin(*args, **kwargs)

add motor record's dial coordinate fields to Device

EpicsMotorEnableMixin(*args, **kwargs)

mixin providing access to motor enable/disable

EpicsMotorLimitsMixin(*args, **kwargs)

add motor record HLM & LLM fields & compatibility get_lim() and set_lim()

EpicsMotorRawMixin(*args, **kwargs)

add motor record's raw coordinate fields to Device

EpicsMotorResolutionMixin(*args, **kwargs)

Add motor record's resolution fields to motor.

EpicsMotorServoMixin(*args, **kwargs)

add motor record's servo loop controls to Device

class apstools.devices.motor_mixins.EpicsMotorDialMixin(*args: Any, **kwargs: Any)[source]

add motor record’s dial coordinate fields to Device

EXAMPLE:

from ophyd import EpicsMotor
from apstools.devices import EpicsMotorDialMixin

class myEpicsMotor(EpicsMotorDialMixin, EpicsMotor): pass
m1 = myEpicsMotor('xxx:m1', name='m1')
print(m1.dial.read())
class apstools.devices.motor_mixins.EpicsMotorEnableMixin(*args: Any, **kwargs: Any)[source]

mixin providing access to motor enable/disable

EXAMPLE:

from ophyd import EpicsMotor
from apstools.devices import EpicsMotorEnableMixin

class MyEpicsMotor(EpicsMotorEnableMixin, EpicsMotor): ...

m1 = MyEpicsMotor('xxx:m1', name='m1')
print(m1.enabled)

In a bluesky plan:

yield from bps.mv(m1.enable_disable, m1.MOTOR_DISABLE)
# ... other activities
yield from bps.mv(m1.enable_disable, m1.MOTOR_ENABLE)
disable_motor()[source]

BLOCKING call to disable motor axis

enable_motor()[source]

BLOCKING call to enable motor axis

class apstools.devices.motor_mixins.EpicsMotorLimitsMixin(*args: Any, **kwargs: Any)[source]

add motor record HLM & LLM fields & compatibility get_lim() and set_lim()

EXAMPLE:

from ophyd import EpicsMotor
from apstools.devices import EpicsMotorLimitsMixin

class myEpicsMotor(EpicsMotorLimitsMixin, EpicsMotor): pass
m1 = myEpicsMotor('xxx:m1', name='m1')
lo = m1.get_lim(-1)
hi = m1.get_lim(1)
m1.set_lim(-25, -5)
print(m1.get_lim(-1), m1.get_lim(1))
m1.set_lim(lo, hi)
get_lim(flag)[source]

Returns the user limit of motor

  • flag > 0: returns high limit

  • flag < 0: returns low limit

  • flag == 0: returns None

Similar with SPEC command

set_lim(low, high)[source]

Sets the low and high limits of motor

  • No action taken if motor is moving.

  • Low limit is set to lesser of (low, high)

  • High limit is set to greater of (low, high)

Similar with SPEC command

class apstools.devices.motor_mixins.EpicsMotorRawMixin(*args: Any, **kwargs: Any)[source]

add motor record’s raw coordinate fields to Device

EXAMPLE:

from ophyd import EpicsMotor
from apstools.devices import EpicsMotorRawMixin

class myEpicsMotor(EpicsMotorRawMixin, EpicsMotor): pass
m1 = myEpicsMotor('xxx:m1', name='m1')
print(m1.raw.read())
class apstools.devices.motor_mixins.EpicsMotorResolutionMixin(*args: Any, **kwargs: Any)[source]

Add motor record’s resolution fields to motor.

Usually, a facility will not provide such high-level access to calibration parameters since these are associated with fixed parameters of hardware. For simulators, it is convenient to provide access so that default settings (typically low-resolution) from the IOC can be changed as part of the device setup in bluesky.

EXAMPLE:

from ophyd import EpicsMotor
from apstools.devices import EpicsMotorResolutionMixin

class myEpicsMotor(EpicsMotorResolutionMixin, EpicsMotor): pass
m1 = myEpicsMotor('xxx:m1', name='m1')
print(f"resolution={m1.resolution.read()}")
print(f"steps_per_rev={m1.steps_per_rev.read()}")
print(f"units_per_rev={m1.units_per_rev.read()}")
class apstools.devices.motor_mixins.EpicsMotorServoMixin(*args: Any, **kwargs: Any)[source]

add motor record’s servo loop controls to Device

EXAMPLE:

from ophyd import EpicsMotor
from apstools.devices import EpicsMotorServoMixin

class myEpicsMotor(EpicsMotorServoMixin, EpicsMotor): pass
m1 = myEpicsMotor('xxx:m1', name='m1')
print(m1.servo.read())

PVPositioner that computes done as a soft signal.

PVPositionerSoftDone(*args, **kwargs)

PVPositioner that computes done as a soft signal.

PVPositionerSoftDoneWithStop(*args, **kwargs)

PVPositionerSoftDone with stop() and inposition.

class apstools.devices.positioner_soft_done.PVPositionerSoftDone(*args: Any, **kwargs: Any)[source]

PVPositioner that computes done as a soft signal.

PARAMETERS

prefixstr, optional

The device prefix used for all sub-positioners. This is optional as it may be desirable to specify full PV names for PVPositioners.

readback_pvstr, optional

PV prefix of the readback signal. Disregarded if readback attribute is created.

setpoint_pvstr, optional

PV prefix of the setpoint signal. Disregarded if setpoint attribute is created.

tolerancefloat, optional

Motion tolerance. The motion is considered done when:

abs(readback-setpoint) <= tolerance

Defaults to 10^(-1*precision), where precision = setpoint.precision.

update_targetbool

True when this object update the target Component directly. Use False if the target Component will be updated externally, such as by the controller when target is an EpicsSignal. Defaults to True.

kwargs :

Passed to ophyd.PVPositioner

ATTRIBUTES

setpointSignal

The setpoint (request) signal

readbackSignal or None

The readback PV (e.g., encoder position PV)

actuateSignal or None

The actuation PV to set when movement is requested

actuate_valueany, optional

The actuation value, sent to the actuate signal when motion is requested

stop_signalSignal or None

The stop PV to set when motion should be stopped

stop_valueany, optional

The value sent to stop_signal when a stop is requested

targetSignal

The target value of a move request.

Override (in subclass) with EpicsSignal to connect with a PV.

In some controllers (such as temperature controllers), the setpoint may be changed incrementally towards this target value (such as a ramp or controlled trajectory). In such cases, the target will be final value while setpoint will be the current desired position.

Otherwise, both setpoint and target will be set to the same value.

(new in apstools 1.5.3)

cb_readback(*args, **kwargs)[source]

Called when readback changes (EPICS CA monitor event).

Computes if the positioner is done moving:

done = |readback - setpoint| <= tolerance
cb_setpoint(*args, **kwargs)[source]

Called when setpoint changes (EPICS CA monitor event).

When the setpoint is changed, force done=False. For any move, done must transition to != done_value, then back to done_value.

Without this response, a small move (within tolerance) will not return. Next update of readback will compute self.done.

class apstools.devices.positioner_soft_done.PVPositionerSoftDoneWithStop(*args: Any, **kwargs: Any)[source]

PVPositionerSoftDone with stop() and inposition.

The stop() method sets the setpoint to the immediate readback value (only when inposition is True). This stops the positioner at the current position.

property inposition

Report (boolean) if positioner is done.

stop(*, success=False)[source]

Hold the current readback when stop() is called and not inposition().

Generalized ophyd Device base class for preamplifiers.

PreamplifierBaseDevice(*args, **kwargs)

Generalized interface (base class) for preamplifiers.

class apstools.devices.preamp_base.PreamplifierBaseDevice(*args: Any, **kwargs: Any)[source]

Generalized interface (base class) for preamplifiers.

All subclasses of PreamplifierBaseDevice must define how to update the gain with the correct value from the amplifier. An example is SRS570_PreAmplifier.

See

https://github.com/BCDA-APS/apstools/issues/544

PTC10 Programmable Temperature Controller

The PTC10 is a programmable temperature controller from SRS (Stanford Research Systems). The PTC10 is a modular system consisting of a base unit and provision for addition of add-on boards.

A single, complete ophyd.Device subclass will not describe all variations that could be installed. But the add-on boards each allow standardization. Each installation must build a custom class that matches their hardware configuration. The APS USAXS instrument has created a custom class based on the ophyd.PVPositioner to use their PTC10 as a temperature positioner.

PTC10AioChannel(*args, **kwargs)

SRS PTC10 AIO module

PTC10RtdChannel(*args, **kwargs)

SRS PTC10 RTD module channel

PTC10TcChannel(*args, **kwargs)

SRS PTC10 Tc (thermocouple) module channel

PTC10PositionerMixin(*args, **kwargs)

Mixin so SRS PTC10 can be used as a (temperature) positioner.

see

https://www.thinksrs.com/products/ptc10.html

EXAMPLE:

from ophyd import PVPositioner

class MyPTC10(PTC10PositionerMixin, PVPositioner):
    readback = Component(EpicsSignalRO, "2A:temperature", kind="hinted")
    setpoint = Component(EpicsSignalWithRBV, "5A:setPoint", kind="hinted")

    rtd = Component(PTC10RtdChannel, "3A:")
    pid = Component(PTC10AioChannel, "5A:")

ptc10 = MyPTC10("IOC_PREFIX:ptc10:", name="ptc10")
ptc10.report_dmov_changes.put(True)  # a diagnostic
ptc10.tolerance.put(1.0)  # done when |readback-setpoint|<=tolerance

New in apstools 1.5.3.

class apstools.devices.ptc10_controller.PTC10AioChannel(*args: Any, **kwargs: Any)[source]

SRS PTC10 AIO module

class apstools.devices.ptc10_controller.PTC10PositionerMixin(*args: Any, **kwargs: Any)[source]

Mixin so SRS PTC10 can be used as a (temperature) positioner.

cb_readback(*args, **kwargs)

Called when readback changes (EPICS CA monitor event).

cb_setpoint(*args, **kwargs)

Called when setpoint changes (EPICS CA monitor event).

inposition

Report (boolean) if positioner is done.

stop(*[, success])

Hold the current readback when the stop() method is called and not done.

cb_readback(*args, **kwargs)[source]

Called when readback changes (EPICS CA monitor event).

cb_setpoint(*args, **kwargs)[source]

Called when setpoint changes (EPICS CA monitor event).

When the setpoint is changed, force done=False. For any move, done MUST change to != done_value, then change back to done_value (True). Without this response, a small move (within tolerance) will not return. Next update of readback will compute self.done.

property inposition

Report (boolean) if positioner is done.

stop(*, success=False)[source]

Hold the current readback when the stop() method is called and not done.

class apstools.devices.ptc10_controller.PTC10RtdChannel(*args: Any, **kwargs: Any)[source]

SRS PTC10 RTD module channel

class apstools.devices.ptc10_controller.PTC10TcChannel(*args: Any, **kwargs: Any)[source]

SRS PTC10 Tc (thermocouple) module channel

Scaler support

use_EPICS_scaler_channels(scaler)

configure scaler for only the channels with names assigned in EPICS

apstools.devices.scaler_support.use_EPICS_scaler_channels(scaler)[source]

configure scaler for only the channels with names assigned in EPICS

Note: For ScalerCH, use scaler.select_channels(None) instead of this code. (Applies only to ophyd.scaler.ScalerCH in releases after 2019-02-27.)

Shutters

ApsPssShutter(*args, **kwargs)

APS PSS shutter

ApsPssShutterWithStatus(*args, **kwargs)

APS PSS shutter with separate status PV

EpicsMotorShutter(*args, **kwargs)

Shutter, implemented with an EPICS motor moved between two positions

EpicsOnOffShutter(*args, **kwargs)

Shutter using a single EPICS PV moved between two positions

OneSignalShutter(*args, **kwargs)

Shutter Device using one Signal for open and close.

ShutterBase(*args, **kwargs)

Base class for all shutter Devices.

SimulatedApsPssShutterWithStatus(*args, **kwargs)

Simulated APS PSS shutter

class apstools.devices.shutters.ApsPssShutter(*args: Any, **kwargs: Any)[source]

APS PSS shutter

  • APS PSS shutters have separate bit PVs for open and close

  • set either bit, the shutter moves, and the bit resets a short time later

  • no indication that the shutter has actually moved from the bits (see ApsPssShutterWithStatus() for alternative)

Since there is no direct indication that a shutter has moved, the state property will always return unknown and the isOpen and isClosed properties will always return False.

A consequence of the unknown state is that the shutter will always be commanded to move (and wait the delay_s time), even if it is already at that position. This device could keep track of the last commanded position, but that is not guaranteed to be true since the shutter could be moved from other software.

The default delay_s has been set at 1.2 s to allow for shutter motion. Change this as desired. Advise if this default should be changed.

EXAMPLE:

shutter_a = ApsPssShutter("2bma:A_shutter:", name="shutter")

shutter_a.open()
shutter_a.close()

shutter_a.set("open")
shutter_a.set("close")

When using the shutter in a plan, be sure to use yield from, such as:

def in_a_plan(shutter):
    yield from abs_set(shutter, "open", wait=True)
    # do something
    yield from abs_set(shutter, "close", wait=True)

RE(in_a_plan(shutter_a))

The strings accepted by set() are defined in two lists: valid_open_values and valid_close_values. These lists are treated (internally to set()) as lower case strings.

Example, add “o” & “x” as aliases for “open” & “close”:

shutter_a.addOpenValue(“o”) shutter_a.addCloseValue(“x”) shutter_a.set(“o”) shutter_a.set(“x”)

close(timeout=10)[source]

request the shutter to close (timeout is ignored)

open(timeout=10)[source]

request the shutter to open (timeout is ignored)

property state

is shutter “open”, “close”, or “unknown”?

class apstools.devices.shutters.ApsPssShutterWithStatus(*args: Any, **kwargs: Any)[source]

APS PSS shutter with separate status PV

  • APS PSS shutters have separate bit PVs for open and close

  • set either bit, the shutter moves, and the bit resets a short time later

  • a separate status PV tells if the shutter is open or closed (see ApsPssShutter() for alternative)

EXAMPLE:

A_shutter = ApsPssShutterWithStatus(
    "2bma:A_shutter:",
    "PA:02BM:STA_A_FES_OPEN_PL",
    name="A_shutter")
B_shutter = ApsPssShutterWithStatus(
    "2bma:B_shutter:",
    "PA:02BM:STA_B_SBS_OPEN_PL",
    name="B_shutter")

A_shutter.open()
A_shutter.close()

or

A_shutter.set("open")
A_shutter.set("close")

When using the shutter in a plan, be sure to use yield from.

def in_a_plan(shutter):

yield from abs_set(shutter, “open”, wait=True) # do something yield from abs_set(shutter, “close”, wait=True)

RE(in_a_plan(A_shutter))

close(timeout=10)[source]

request the shutter to close

open(timeout=10)[source]

request the shutter to open

property state

is shutter “open”, “close”, or “unknown”?

wait_for_state(target, timeout=10, poll_s=0.01)[source]

wait for the PSS state to reach a desired target

PARAMETERS

target

[str] : list of strings containing acceptable values

timeout

non-negative number : maximum amount of time (seconds) to wait for PSS state to reach target

poll_s

non-negative number : Time to wait (seconds) in first polling cycle. After first poll, this will be increased by _poll_factor_ up to a maximum time of _poll_s_max_.

class apstools.devices.shutters.EpicsMotorShutter(*args: Any, **kwargs: Any)[source]

Shutter, implemented with an EPICS motor moved between two positions

EXAMPLE:

tomo_shutter = EpicsMotorShutter("2bma:m23", name="tomo_shutter")
tomo_shutter.close_value = 1.0      # default
tomo_shutter.open_value = 0.0       # default
tomo_shutter.tolerance = 0.01       # default
tomo_shutter.open()
tomo_shutter.close()

# or, when used in a plan
def planA():
    yield from abs_set(tomo_shutter, "open", group="O")
    yield from wait("O")
    yield from abs_set(tomo_shutter, "close", group="X")
    yield from wait("X")
def planA():
    yield from abs_set(tomo_shutter, "open", wait=True)
    yield from abs_set(tomo_shutter, "close", wait=True)
def planA():
    yield from mv(tomo_shutter, "open")
    yield from mv(tomo_shutter, "close")
close()[source]

move motor to BEAM BLOCKED position, interactive use

open()[source]

move motor to BEAM NOT BLOCKED position, interactive use

property state

is shutter “open”, “close”, or “unknown”?

class apstools.devices.shutters.EpicsOnOffShutter(*args: Any, **kwargs: Any)[source]

Shutter using a single EPICS PV moved between two positions

Use for a shutter controlled by a single PV which takes a value for the close command and a different value for the open command. The current position is determined by comparing the value of the control with the expected open and close values.

EXAMPLE:

bit_shutter = EpicsOnOffShutter("2bma:bit1", name="bit_shutter")
bit_shutter.close_value = 0      # default
bit_shutter.open_value = 1       # default
bit_shutter.open()
bit_shutter.close()

# or, when used in a plan
def planA():
    yield from mv(bit_shutter, "open")
    yield from mv(bit_shutter, "close")
class apstools.devices.shutters.OneSignalShutter(*args: Any, **kwargs: Any)[source]

Shutter Device using one Signal for open and close.

PARAMETERS

signal

EpicsSignal or Signal : (override in subclass) The signal is the comunication to the hardware. In a subclass, the hardware may have more than one communication channel to use. See the ApsPssShutter as an example.

See ShutterBase for more parameters.

EXAMPLE

Create a simulated shutter:

shutter = OneSignalShutter(name=”shutter”)

open the shutter (interactively):

shutter.open()

Check the shutter is open:

In [144]: shutter.isOpen Out[144]: True

Use the shutter in a Bluesky plan. Set a post-move delay time of 1.0 seconds. Be sure to use yield from, such as:

def in_a_plan(shutter):
    shutter.delay_s = 1.0
    t0 = time.time()
    print("Shutter state: " + shutter.state, time.time()-t0)
    yield from bps.abs_set(shutter, "open", wait=True)    # wait for completion is optional
    print("Shutter state: " + shutter.state, time.time()-t0)
    yield from bps.mv(shutter, "open")    # do it again
    print("Shutter state: " + shutter.state, time.time()-t0)
    yield from bps.mv(shutter, "close")    # ALWAYS waits for completion
    print("Shutter state: " + shutter.state, time.time()-t0)

RE(in_a_plan(shutter))

which gives this output:

Shutter state: close 1.7642974853515625e-05 Shutter state: open 1.0032124519348145 Shutter state: open 1.0057861804962158 Shutter state: close 2.009695529937744

The strings accepted by set() are defined in two lists: valid_open_values and valid_close_values. These lists are treated (internally to set()) as lower case strings.

Example, add “o” & “x” as aliases for “open” & “close”:

shutter.addOpenValue(“o”) shutter.addCloseValue(“x”) shutter.set(“o”) shutter.set(“x”)

close()[source]

BLOCKING: request shutter to close, called by set()

open()[source]

BLOCKING: request shutter to open, called by set()

property state

is shutter “open”, “close”, or “unknown”?

class apstools.devices.shutters.ShutterBase(*args: Any, **kwargs: Any)[source]

Base class for all shutter Devices.

PARAMETERS

value

str : any from self.choices (typically “open” or “close”)

valid_open_values

[str] : A list of lower-case text values that are acceptable for use with the set() command to open the shutter.

valid_close_values

[str] : A list of lower-case text values that are acceptable for use with the set() command to close the shutter.

open_value

number : The actual value to send to open signal to open the shutter. (default = 1)

close_value

number : The actual value to send to close signal to close the shutter. (default = 0)

delay_s

float : time to wait (s) after move is complete, does not wait if shutter already in position (default = 0)

busy

Signal : (internal) tells if a move is in progress

unknown_state

str : (constant) Text reported by state when not open or closed. cannot move to this position (default = “unknown”)

addCloseValue(text)[source]

a synonym to close the shutter, use with set()

addOpenValue(text)[source]

a synonym to open the shutter, use with set()

property choices

return list of acceptable choices for set()

close()[source]

BLOCKING: request shutter to close, called by set().

Must implement in subclass of ShutterBase()

EXAMPLE:

if not self.isClosed:
    self.signal.put(self.close_value)
    if self.delay_s > 0:
        time.sleep(self.delay_s)    # blocking call OK here
inPosition(target)[source]

is the shutter at the target position?

property isClosed

is the shutter closed?

property isOpen

is the shutter open?

lowerCaseString(value)[source]

ensure any given value is a lower-case string

open()[source]

BLOCKING: request shutter to open, called by set().

Must implement in subclass of ShutterBase()

EXAMPLE:

if not self.isOpen:
    self.signal.put(self.open_value)
    if self.delay_s > 0:
        time.sleep(self.delay_s)    # blocking call OK here
set(value, **kwargs)[source]

plan: request the shutter to open or close

PARAMETERS

value

str : any from self.choices (typically “open” or “close”)

kwargs

dict : ignored at this time

property state

returns open, close, or unknown

Must implement in subclass of ShutterBase()

EXAMPLE:

if self.signal.get() == self.open_value:
    result = self.valid_open_values[0]
elif self.signal.get() == self.close_value:
    result = self.valid_close_values[0]
else:
    result = self.unknown_state
return result
validTarget(target, should_raise=True)[source]

return whether (or not) target value is acceptable for self.set()

raise ValueError if not acceptable (default)

class apstools.devices.shutters.SimulatedApsPssShutterWithStatus(*args: Any, **kwargs: Any)[source]

Simulated APS PSS shutter

EXAMPLE:

sim = SimulatedApsPssShutterWithStatus(name="sim")
property state

is shutter “open”, “close”, or “unknown”?

wait_for_state(target, timeout=10, poll_s=0.01)[source]

wait for the PSS state to reach a desired target

PARAMETERS

target

[str] : list of strings containing acceptable values

timeout

non-negative number : Ignored in the simulation.

poll_s

non-negative number : Ignored in the simulation.

Ophyd support for Stanford Research Systems 570 preamplifier from synApps

Public Structures

SRS570_PreAmplifier(*args, **kwargs)

Ophyd support for Stanford Research Systems 570 preamplifier from synApps.

This device connects with the SRS570 support from synApps. (https://github.com/epics-modules/ip/blob/master/ipApp/Db/SR570.db)

The SRS570 synApps support is part of the ip module: https://htmlpreview.github.io/?https://raw.githubusercontent.com/epics-modules/ip/R3-6-1/documentation/swaitRecord.html

see

https://github.com/epics-modules/ip

class apstools.devices.srs570_preamplifier.SRS570_PreAmplifier(*args: Any, **kwargs: Any)[source]

Ophyd support for Stanford Research Systems 570 preamplifier from synApps.

cb_gain(*args, **kwargs)[source]

Called when sensitivity changes (EPICS CA monitor event).

property computed_gain

Amplifier gain (A/V), as floating-point number.

Struck 3820

Struck3820(*args, **kwargs)

Struck/SIS 3820 Multi-Channel Scaler (as used by USAXS)

class apstools.devices.struck3820.Struck3820(*args: Any, **kwargs: Any)[source]

Struck/SIS 3820 Multi-Channel Scaler (as used by USAXS)

Synthetic pseudo-Voigt function

EXAMPLES:

Simple example of SynPseudoVoigt().
1from apstools.devices import SynPseudoVoigt
2from ophyd.sim import motor
3det = SynPseudoVoigt('det', motor, 'motor',
4    center=0, eta=0.5, scale=1, sigma=1, bkg=0)
5
6# scan the "det" peak with the "motor" positioner
7# RE(bp.scan([det], motor, -2, 2, 41))
Example of SynPseudoVoigt() with randomized values.
 1import numpy as np
 2from apstools.devices import SynPseudoVoigt
 3synthetic_pseudovoigt = SynPseudoVoigt(
 4    'synthetic_pseudovoigt', m1, 'm1',
 5    center=-1.5 + 0.5*np.random.uniform(),
 6    eta=0.2 + 0.5*np.random.uniform(),
 7    sigma=0.001 + 0.05*np.random.uniform(),
 8    scale=1e5,
 9    bkg=0.01*np.random.uniform())
10
11# scan the "synthetic_pseudovoigt" peak with the "m1" positioner
12# RE(bp.scan([synthetic_pseudovoigt], m1, -2, 0, 219))

SynPseudoVoigt(*args, **kwargs)

Evaluate a point on a pseudo-Voigt based on the value of a motor.

class apstools.devices.synth_pseudo_voigt.SynPseudoVoigt(*args: Any, **kwargs: Any)[source]

Evaluate a point on a pseudo-Voigt based on the value of a motor.

Provides a signal to be measured. Acts like a detector.

See

https://en.wikipedia.org/wiki/Voigt_profile

PARAMETERS

name str :

name of detector signal

motor positioner :

The independent coordinate

motor_field str :

name of motor

center float :

(optional) location of maximum value, default=0

eta float :

(optional) 0 <= eta < 1.0: Lorentzian fraction, default=0.5

scale float :

(optional) scale >= 1 : scale factor, default=1

sigma float :

(optional) sigma > 0 : width, default=1

bkg float :

(optional) bkg >= 0 : constant background, default=0

noise "poisson" or "uniform" or None :

Add noise to the result.

noise_multiplier float :

Only relevant for ‘uniform’ noise. Multiply the random amount of noise by ‘noise_multiplier’

Tracking Signal for Device coordination

TrackingSignal(*args, **kwargs)

Non-EPICS signal for use when coordinating Device actions.

class apstools.devices.tracking_signal.TrackingSignal(*args: Any, **kwargs: Any)[source]

Non-EPICS signal for use when coordinating Device actions.

Signal to decide if undulator will be tracked while changing the monochromator energy.

check_value(value)[source]

Check if the value is a boolean.

RAISES

ValueError

XIA PF4 Filters

Pf4FilterSingle(*args, **kwargs)

XIA PF4 Filter: one set of 4 filters (A).

Pf4FilterDual(*args, **kwargs)

XIA PF4 Filter: two sets of 4 filters (A, B).

Pf4FilterTriple(*args, **kwargs)

XIA PF4 Filter: three sets of 4 filters (A, B, C).

Pf4FilterCommon(*args, **kwargs)

XIA PF4 filters - common support.

Pf4FilterBank(*args, **kwargs)

A single module of XIA PF4 filters (4-blades).

DualPf4FilterBox(*args, **kwargs)

LEGACY (use Pf4FilterDual now): Dual (Al, Ti) Xia PF4 filter boxes

class apstools.devices.xia_pf4.DualPf4FilterBox(*args: Any, **kwargs: Any)[source]

LEGACY (use Pf4FilterDual now): Dual (Al, Ti) Xia PF4 filter boxes

Support from synApps (using Al, Ti foils)

EXAMPLE:

pf4 = DualPf4FilterBox("2bmb:pf4:", name="pf4")
pf4_AlTi = DualPf4FilterBox("9idcRIO:pf4:", name="pf4_AlTi")
class apstools.devices.xia_pf4.Pf4FilterBank(*args: Any, **kwargs: Any)[source]

A single module of XIA PF4 filters (4-blades).

EXAMPLES:

pf4B = Pf4FilterBank("ioc:pf4:", name="pf4B", bank="B")

# -or-

class MyTriplePf4(Pf4FilterCommon):
    A = Component(Pf4FilterBank, "", bank="A")
    B = Component(Pf4FilterBank, "", bank="B")
    C = Component(Pf4FilterBank, "", bank="C")

pf4 = MyTriplePf4("ioc:pf4:", name="pf4")
See

https://github.com/epics-modules/optics/blob/master/opticsApp/Db/pf4bank.db

class apstools.devices.xia_pf4.Pf4FilterCommon(*args: Any, **kwargs: Any)[source]

XIA PF4 filters - common support.

Use Pf4FilterCommon to build support for a configuration of PF4 filters (such as 3 or 4 filter banks).

EXAMPLE:

class MyTriplePf4(Pf4FilterCommon):
    A = Component(Pf4FilterBank, "", bank="A")
    B = Component(Pf4FilterBank, "", bank="B")
    C = Component(Pf4FilterBank, "", bank="C")

pf4 = MyTriplePf4("ioc:pf4:", name="pf4")
See

https://github.com/epics-modules/optics/blob/master/opticsApp/Db/pf4common.db

class apstools.devices.xia_pf4.Pf4FilterDual(*args: Any, **kwargs: Any)[source]

XIA PF4 Filter: two sets of 4 filters (A, B).

B

alias of apstools.devices.xia_pf4.Pf4FilterBank

class apstools.devices.xia_pf4.Pf4FilterSingle(*args: Any, **kwargs: Any)[source]

XIA PF4 Filter: one set of 4 filters (A).

A

alias of apstools.devices.xia_pf4.Pf4FilterBank

class apstools.devices.xia_pf4.Pf4FilterTriple(*args: Any, **kwargs: Any)[source]

XIA PF4 Filter: three sets of 4 filters (A, B, C).

C

alias of apstools.devices.xia_pf4.Pf4FilterBank

XIA Slit from EPICS synApps optics: xia_slit.db

Coordinates (viewing from detector towards source):

    top
inb     out
    bot

Each blade 1 (in the XIA slit controller) travels in a _cylindrical_ coordinate system. Positive motion moves a blade outwards from the center with a backlash correction. No backlash correction is applied for negative motion (as the blades close). Size and center are computed by the underlying EPICS support.

hsize = inb + out vsize = top + bot

1

Note that the blade names here are different than the EPICS support. The difference is to make the names of the blades consistent with other slits with the Bluesky framework.

USAGE:

slit = XiaSlitController(“IOC:hsc1:”, name=”slit”) print(slit.geometry)

XiaSlit2D(*args, **kwargs)

EPICS synApps optics xia_slit.db 2D support: inb out bot top ...

class apstools.devices.xia_slit.XiaSlit2D(*args: Any, **kwargs: Any)[source]

EPICS synApps optics xia_slit.db 2D support: inb out bot top …

bot

alias of apstools.devices.positioner_soft_done.PVPositionerSoftDone

property geometry

Return the slit 2D size and center as a namedtuple.

hcenter

alias of apstools.devices.positioner_soft_done.PVPositionerSoftDone

hsize

alias of apstools.devices.positioner_soft_done.PVPositionerSoftDone

inb

alias of apstools.devices.positioner_soft_done.PVPositionerSoftDone

out

alias of apstools.devices.positioner_soft_done.PVPositionerSoftDone

top

alias of apstools.devices.positioner_soft_done.PVPositionerSoftDone

vcenter

alias of apstools.devices.positioner_soft_done.PVPositionerSoftDone

vsize

alias of apstools.devices.positioner_soft_done.PVPositionerSoftDone