Positioners¶
Positioners other than EpicsMotor
and SoftPositioner
are not
“ready-to-use”. They require some customization.
PVPositioner¶
For example, this code defines a CS700 temperature controller. A temperature controller is a kind of positioner, from ophyd’s point of view, where the “position” is the temperature.
from ophyd import PVPositioner, EpicsSignal, EpicsSignalRO
from ophyd import Component as Cpt
# Define a new kind of device.
class CS700TemperatureController(PVPositioner):
setpoint = Cpt(EpicsSignal, 'T-SP')
readback = Cpt(EpicsSignalRO, 'T-I')
done = Cpt(EpicsSignalRO, 'Cmd-Busy')
stop_signal = Cpt(EpicsSignal, 'Cmd-Cmd')
# Create an instance of this new kind of device.
prefix = 'XF:28IDC-ES:1{Env:01}'
cs700 = CS700TemperatureController(prefix, name='cs700')
# When the cs700 has reached the set-point temperature, the 'done' signal
# flips to 0.
cs700.done_value = 0
- class ophyd.pv_positioner.PVPositioner(prefix='', *, limits=None, name=None, read_attrs=None, configuration_attrs=None, parent=None, egu='', **kwargs)¶
A Positioner which is controlled using multiple user-defined signals
Keyword arguments are passed through to the base class, Positioner
- 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.
- limits2-element sequence, optional
(low_limit, high_limit)
- namestr
The device name
- egustr, optional
The engineering units (EGU) for the position
- settle_timefloat, optional
The amount of time to wait after moves to report status completion
- timeoutfloat, optional
The default timeout to use for motion requests, in seconds.
- 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
- doneSignal
A readback value indicating whether motion is finished
- done_valueany, optional
The value that the done pv should be when motion has completed
- put_completebool, optional
If set, the specified PV should allow for asynchronous put completion to indicate motion has finished. If actuate is specified, it will be used for put completion. Otherwise, the setpoint will be used. See the -c option from caput for more information.
PseudoPositioner¶
An ophyd PseudoPositioner
relates one or more pseudo (virtual) axes to one
or more real (physical) axes via forward and inverse calculations. To define
such a PseudoPositioner, one must subclass from PseudoPositioner:
from ophyd import (PseudoPositioner, PseudoSingle, EpicsMotor)
from ophyd import (Component as Cpt)
from ophyd.pseudopos import (pseudo_position_argument,
real_position_argument)
class Pseudo3x3(PseudoPositioner):
# The pseudo positioner axes:
px = Cpt(PseudoSingle, limits=(-10, 10))
py = Cpt(PseudoSingle, limits=(-10, 10))
pz = Cpt(PseudoSingle)
# The real (or physical) positioners:
rx = Cpt(EpicsMotor, 'XF:31IDA-OP{Tbl-Ax:X1}Mtr')
ry = Cpt(EpicsMotor, 'XF:31IDA-OP{Tbl-Ax:X2}Mtr')
rz = Cpt(EpicsMotor, 'XF:31IDA-OP{Tbl-Ax:X3}Mtr')
@pseudo_position_argument
def forward(self, pseudo_pos):
'''Run a forward (pseudo -> real) calculation'''
return self.RealPosition(rx=-pseudo_pos.px,
ry=-pseudo_pos.py,
rz=-pseudo_pos.pz)
@real_position_argument
def inverse(self, real_pos):
'''Run an inverse (real -> pseudo) calculation'''
return self.PseudoPosition(px=-real_pos.rx,
py=-real_pos.ry,
pz=-real_pos.rz)
Pseudo3x3
above is a pseudo positioner with 3 pseudo axes and 3 real axes.
The pseudo axes are defined in order as (px, py, pz). Similarly, the real
positioners are (rx, ry, rz).
There is no restriction that the real axes must be tied to physical hardware.
A physical axis could just as well be a SoftPositioner
, or any subclass of
PositionerBase
(with the sole exception of PseudoSingle
).
The forward calculation says that, for any given pseudo position, the real motors should move to the opposite position. For example, for a pseudo position of (px=1, py=2, pz=3), the corresponding real position would be (rx=-1, ry=-2, rz=-3). The inverse calculation is similar, in going from a real position to a pseudo position.
The two decorators @real_position_argument
and
@pseudo_position_argument
are used here for convenience so that one can
call these functions in a variety of ways, all of which generate a correct
PseudoPosition tuple as the first argument to your calculation method.
Positions can be specified in the following ways:
As positional arguments:
pseudo.forward(px, py, pz)
As a sequence or PseudoPosition/RealPosition:
pseudo.forward((px, py, pz))
pseudo.forward(pseudo.PseudoPosition(px, py, pz))
As kwargs:
pseudo.forward(px=1, py=2, pz=3)
move
is decorated like this on PseudoPositioner, meaning you can also call
it with this syntax.
- class ophyd.pseudopos.PseudoSingle(prefix='', *, limits=None, egu='', parent=None, name=None, source='computed', target_initial_position=False, **kwargs)¶
A single axis of a PseudoPositioner
This should not be instantiated on its own, but rather used as a Component in a PseudoPositioner subclass.
- Parameters
- prefixstr, optional
The PV prefix, for compatibility with the Device hierarchy
- limits(low_limit, high_limit)
User-defined limits for this pseudo axis.
- egustr, optional
The engineering units (EGU) for the position
- parentPseudoPositioner instance
The instance of the parent PseudoPositioner
- namestr, optional
The name of the positioner
- sourcestr, optional
Metadata indicating the source of this positioner’s position. Defaults to ‘computed’
- target_initial_positionbool, optional
Use initial inverse-calculated position as the default setpoint/target for this axis
- settle_timefloat, optional
The amount of time to wait after moves to report status completion
- timeoutfloat, optional
The default timeout to use for motion requests, in seconds.
- class ophyd.pseudopos.PseudoPositioner(prefix='', *, concurrent=True, read_attrs=None, configuration_attrs=None, name, egu='', auto_target=True, **kwargs)¶
A pseudo positioner which can be comprised of multiple positioners
- Parameters
- prefixstr
The PV prefix for all components of the device
- concurrentbool, optional
If set, all real motors will be moved concurrently. If not, they will be moved in order of how they were defined initially
- read_attrssequence of attribute names
the components to include in a normal reading (i.e., in
read()
)- configuration_attrssequence of attribute names
the components to be read less often (i.e., in
read_configuration()
) and to adjust viaconfigure()
- namestr, optional
The name of the device
- egustr, optional
The user-defined engineering units for the whole PseudoPositioner
- auto_targetbool, optional
Automatically set the target position of PseudoSingle devices when moving to a single PseudoPosition
- parentinstance or None
The instance of the parent device, if applicable
- settle_timefloat, optional
The amount of time to wait after moves to report status completion
- timeoutfloat, optional
The default timeout to use for motion requests, in seconds.
SoftPositioner¶
A SoftPositioner
is a positioner which has no corresponding physical motor.
On its own, it is most useful for debugging scanning logic when moving physical
motors is either undesirable or not possible.
Used as-is, a SoftPositioner
will “move” to the requested position
immediately.
PseudoSingle
and PseudoPositioner
, for example, are implemented as
heavily customized SoftPositioner
subclasses.
- class ophyd.positioner.PositionerBase(*, name=None, parent=None, settle_time=0.0, timeout=None, **kwargs)¶
The positioner base class
Subclass from this to implement your own positioners.
Note
Subclasses should add an additional ‘wait’ keyword argument on the move method. The MoveStatus object returned from PositionerBase can then be waited on after the subclass finishes the motion configuration.
- class ophyd.positioner.SoftPositioner(*, egu='', limits=None, source='computed', init_pos=None, **kwargs)¶
A positioner which does not communicate with any hardware
SoftPositioner ‘moves’ immediately to the target position when commanded to do so.
- Parameters
- limits(low_limit, high_limit)
Soft limits to use
- egustr, optional
Engineering units (EGU) for a position
- sourcestr, optional
Metadata indicating the source of this positioner’s position. Defaults to ‘computed’
- init_posfloat, optional
Create the positioner with this starting position. Defaults to
None
.
from ophyd import SoftPositioner
my_positioner = SoftPositioner(name='my_positioner')