Skip to content

SoftAxis: creating axes on the fly

BLISS provides a helper which wraps any python object with a Axis interface allowing it to be used in a scan.

Given such a python object:

class Maxipix(object):

    _energy = 12.34

    @property
    def energy_threshold(self):
        return self._energy

    @energy_threshold.setter
    def energy_threshold(self, new_energy):
        self._energy = new_energy

    @property
    def temperature(self):
        return 30 + 10*random.random()

mpx1 = Maxipix()

energy threshold property of this object can be scanned by wraping it in a Bliss SoftAxis

A temperature counter has been added to be able to count something in the example.

from bliss.common.standard import ascan, SoftAxis, SoftCounter

# counter from an object property
mpx1_temp = SoftCounter(mpx1, 'temperature', name='mpx1_temp')

# create an Axis out of the Maxipix energy_threshold
# * read the position means read energy_threshold property
# * move means write the energy_threshold property
mpx1_energy = SoftAxis('mpx1_energy', mpx1, position='energy_threshold',
                       move='energy_threshold')

# You can use it like a "normal" bliss axis
# (although no fancy backlash, acceleration, velocity parameter)
print(mpx1_energy.position)

# now you can scan the energy_threshold like this:
ascan(mpx1_energy, 10, 20, 100, 0.1, mpx1_temp)

position and move are flexible. They can be object property names, object method names or reference to object methods. Here is an example:

from bliss.common.standard import SoftAxis

class Pilatus(object):

    _energy = 12.34

    def get_energy(self):
        return self._energy

    def set_energy(self, new_energy):
        self._energy = new_energy

pilatus1 = Pilatus()

ptus_energy = SoftAxis('ptus_energy', pilatus1, position='get_energy',
                       move=pilatus1.set_energy)

Particularly useful might be tango attributes or commands as axes:

from bliss.common.tango import DeviceProxy

magnet1 = DeviceProxy('id31/magnet/1')
mag1_axis = SoftAxis('mfield', magnet1, position='field',
                     move='SetField')

print(mag_axis.position)

Note

Names given to axes must be chosen with care. A name which is already assigned to another Bliss object can hide the original one.

Create a software axis named from any object . The software axis object class will be the standard ‘Axis’ class (see bliss.common.axis).

Keyword arguments:

- `position` (str): the name of a method of <obj> which will return the position of the soft axis
- `move`     (str): the name of a method of <obj> which will start the motion of the soft axis to a given position
- `stop`     (str): the name of a method of <obj> which will stop the motion of the soft axis
- `state`    (str): the name of a method of <obj> which will return the state of the soft axis
                      returned state must be an object of class 'AxisState' (see bliss.common.axis)
                      returned state can be one or a combination of the following states:
                        AxisState("READY")   : "Axis is READY"
                        AxisState("MOVING")  : "Axis is MOVING"
                        AxisState("FAULT")   : "Error from controller"
                        AxisState("LIMPOS")  : "Hardware high limit active"
                        AxisState("LIMNEG")  : "Hardware low limit active"
                        AxisState("HOME")    : "Home signal active"
                        AxisState("OFF")     : "Axis power is off"
                        AxisState("DISABLED"): "Axis cannot move"

- low_limit  (float): the soft axis lower limit
- high_limit (float): the soft axis upper limit
- tolerance  (float): the soft axis tolerance
- unit       (str)  : the soft axis position unit

- export_to_session (bool): export the axis name into the current session env_dict (name must be unique)
- as_positioner     (bool): allow display of the soft axis in wa() as any other real axis
- display_digits    (int): Number of digits used to print positions of this axis