Skip to content

pseudo_motor

borealis.pseudo_motor

PseudoMotor(alias, motors, geometries, position_law)

Bases: ControllerComponent

Class for a basic pseudo-motor, meaning a collection of Motor objects plus 0 or 1 detector.

Parameters:

Name Type Description Default
alias str

Name of the pseudo-motor

required
motors list[Motor, PseudoMotor]

List of Motor or PseudoMotor objects.

required
geometries list[Callable[float, float]

List of conversion functions (e.g. lambda (x: ax + b), one for each motor.

required
position_law Callable[[list], float]

Function that takes as input the list of (pseudo)-motors as it was given at instantiation and returns a single float.

required
Source code in borealis/pseudo_motor.py
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
def __init__(self, alias: str, motors: list[Motor, PseudoMotor], geometries: list,
             position_law: Callable[[list], float]) -> None:
    """

    Parameters
    ----------
    alias : str
        Name of the pseudo-motor
    motors : list[Motor, PseudoMotor]
        List of Motor or PseudoMotor objects.
    geometries : list[Callable[float, float]
        List of conversion functions (e.g. lambda (x: ax + b), one for each motor.
    position_law : Callable[[list], float]
        Function that takes as input the list of (pseudo)-motors as it was given at instantiation and returns
         a single float.

    """
    self.motor_name = alias
    # TODO: change list to tuple to avoid changing the motor order by mistake ? same for geometries
    super().__init__(session_orchestrator)
    try:
        assert len(motors) == len(geometries)
    except AssertionError:
        LOGGER.error('Length of motor list (%d) does not match the length of geometry list (%d)',
                     len(motors), len(geometries))
        raise ValueError(f"Length of motor list ({len(motors)}) does not match the length of "
                         f"geometry list ({len(geometries)})")

    self._motors = motors
    self._conversion_laws = geometries
    self._position_law = position_law

    LOGGER.info("PseudoMotor %s created.", self.motor_name)

__str__()

Custom str method for PseudoMotor class.

Source code in borealis/pseudo_motor.py
54
55
56
def __str__(self):
    """Custom __str__ method for PseudoMotor class."""
    return f'{self.__class__.__name__}(alias={self.motor_name})'

check_soft_limits(target_user)

Check if dial value is within the limits (inclusive).

Parameters:

Name Type Description Default
target_user float

Target position in user unit.

required

Raises:

Type Description
SoftLimitError when dial is outside the allowed range.
Source code in borealis/pseudo_motor.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
def check_soft_limits(self, target_user: float) -> None:
    """
    Check if dial value is within the limits (inclusive).

    Parameters
    ----------
    target_user : float
        Target position in user unit.

    Raises
    ------
    SoftLimitError when dial is outside the allowed range.
    """
    LOGGER.debug("Checking all (pseudo)motor soft limits before amove...")
    for idx, motor in enumerate(self._motors):
        motor_pos = self._conversion_laws[idx](target_user)
        motor.check_soft_limits(motor_pos)
        LOGGER.debug("Valid dial %.3f for (pseudo)motor %s", motor_pos, motor.motor_name)

scan(start, stop, step, acq_time=0)

Perform a scan, if acq_time > 0 will also do an acquisition on all sensors.

Parameters:

Name Type Description Default
start float

Start of interval. The interval includes this value.

required
stop float

End of interval. The interval does not include this value.

required
step float

Spacing between values. For any output out, this is the distance between two adjacent values, out[i+1] - out[i].

required
acq_time float
0
Source code in borealis/pseudo_motor.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
def scan(self, start: float, stop: float, step: float, acq_time: float = 0):
    """
    Perform a scan, if acq_time > 0 will also do an acquisition on all sensors.

    Parameters
    ----------
    start : float
        Start of interval.  The interval includes this value.
    stop : float
        End of interval.  The interval does not include this value.
    step : float
        Spacing between values.  For any output `out`, this is the distance
        between two adjacent values, ``out[i+1] - out[i]``.
    acq_time : float

    """
    self._check_is_ready()

    scan_points = np.arange(start, stop, step, dtype=np.float32)
    self.send(message='Scan', scan_points=scan_points, acq_time=acq_time)

where()

Print pseudo-motor position.

Returns:

Type Description
str
Source code in borealis/pseudo_motor.py
82
83
84
85
86
87
88
89
90
91
92
93
def where(self):
    """
    Print pseudo-motor position.

    Returns
    -------
    str

    """
    print(f'{self.motor_name:20} at : {self.user_position:6.2f} (user)')
    for motor in self._motors:
        motor.where()