Пример #1
0
    def __init__(self, *args, **kwargs):
        Controller.__init__(self, *args, **kwargs)

        host, port = self.config.get("exporter_address").split(":")
        self._exporter = Exporter(host, int(port))
        self.pos_attr_suffix = "Position"
        self.state_cmd = "getMotorState"
Пример #2
0
class MD2(Controller):

    def __init__(self, *args, **kwargs):
        Controller.__init__(self, *args, **kwargs)

        host, port = self.config.get("exporter_address").split(":")
        self._exporter = Exporter(host, int(port))
        self.pos_attr_suffix = "Position"
        self.state_cmd = "getMotorState"

    def initialize(self):
        """
        Read the state to check if the MD2 application replies
        """
        self._get_swstate()

    def initialize_axis(self, axis):
        axis.root_name = axis.config.get("root_name")

    def read_position(self, axis):
        cmd = axis.root_name+self.pos_attr_suffix
        return self._exporter.readProperty(cmd)

    def state(self, axis):
        state = self._exporter.execute(self.state_cmd, axis.root_name)
        return AxisState(state.upper())

    def start_one(self, motion):
        cmd = motion.axis.root_name+self.pos_attr_suffix
        print motion.target_pos
        self._exporter.writeProperty(cmd, motion.target_pos)

    def stop(self,axis):
        self._exporter.execute("abort")

    def home_search(self, axis, switch=None):
        self._exporter.execute("startHomingMotor", axis.root_name)
        self._wait_ready(40)

    def home_state(self, axis):
        return self.state(axis)
        
    def _get_hwstate(self):
        try:
            return self._exporter.readProperty("HardwareState")
        except Exception:
            return "Ready"

    def _get_swstate(self):
        return self._exporter.readProperty("State")

    def _ready(self):
        if self._get_swstate() == "Ready" and self._get_hwstate() == "Ready":
            return True
        return False

    def _wait_ready(self, timeout=3):
        with gevent.Timeout(timeout):
            while not self._ready():
                gevent.sleep(0.01)  
Пример #3
0
class MD2(Controller):
    def __init__(self, *args, **kwargs):
        Controller.__init__(self, *args, **kwargs)

        host, port = self.config.get("exporter_address").split(":")
        self._exporter = Exporter(host, int(port))
        self.pos_attr_suffix = "Position"
        self.state_cmd = "getMotorState"

    def initialize(self):
        """
        Read the state to check if the MD2 application replies
        """
        self._get_swstate()

    def initialize_axis(self, axis):
        axis.root_name = axis.config.get("root_name")

    def read_position(self, axis):
        cmd = axis.root_name + self.pos_attr_suffix
        return self._exporter.readProperty(cmd)

    def state(self, axis):
        state = self._exporter.execute(self.state_cmd, axis.root_name)
        return AxisState(state.upper())

    def start_one(self, motion):
        cmd = motion.axis.root_name + self.pos_attr_suffix
        print motion.target_pos
        self._exporter.writeProperty(cmd, motion.target_pos)

    def stop(self, axis):
        self._exporter.execute("abort")

    def home_search(self, axis, switch=None):
        self._exporter.execute("startHomingMotor", axis.root_name)
        self._wait_ready(40)

    def home_state(self, axis):
        return self.state(axis)

    def _get_hwstate(self):
        try:
            return self._exporter.readProperty("HardwareState")
        except Exception:
            return "Ready"

    def _get_swstate(self):
        return self._exporter.readProperty("State")

    def _ready(self):
        if self._get_swstate() == "Ready" and self._get_hwstate() == "Ready":
            return True
        return False

    def _wait_ready(self, timeout=3):
        with gevent.Timeout(timeout):
            while not self._ready():
                gevent.sleep(0.01)
Пример #4
0
    def _ready(self):
        if self._exporter is None:
            self._exporter = Exporter(self.host, int(self.port))

        if self._exporter.readProperty(
                "State") == "Ready" and self._exporter.readProperty(
                    "HardwareState") == "Ready":
            return True

        return False
Пример #5
0
    def __init__(self, *args, **kwargs):
        Controller.__init__(self, *args, **kwargs)

        host, port = self.config.get("exporter_address").split(":")
        self._exporter = Exporter(host, int(port))
        self.pos_attr_suffix = "Position"
        self.state_cmd = "getMotorState"
Пример #6
0
    def _ready(self):
        if self._exporter is None:
            self._exporter = Exporter(self.host, int(self.port))

        if self._exporter.readProperty("State") == "Ready" and self._exporter.readProperty("HardwareState") == "Ready":
            return True

        return False
Пример #7
0
    def __init__(self, name, config):
        self.phases = {
            "Centring": 1,
            "BeamLocation": 2,
            "DataCollection": 3,
            "Transfer": 4
        }
        self.timeout = 3  # s by default
        nn, port = config.get("exporter_addr").split(":")
        self._exporter = Exporter(nn, int(port))

        fshutter = config.get("fshutter")
        if fshutter:
            fshutter.set_external_control(
                functools.partial(self._exporter.writeProperty,
                                  "FastShutterIsOpen", "true"),
                functools.partial(self._exporter.writeProperty,
                                  "FastShutterIsOpen", "false"), lambda: self.
                _exporter.readProperty("FastShutterIsOpen") == "true")
Пример #8
0
    def __init__(self, name, config):
        self.phases = {"Centring": 1, "BeamLocation": 2,
                       "DataCollection": 3, "Transfer": 4}
        self.timeout = 3  # s by default
        nn, port = config.get("exporter_addr").split(":")
        self._exporter = Exporter(nn, int(port))

        fshutter = config.get("fshutter")
        if fshutter:
            fshutter.set_external_control(functools.partial(self._exporter.writeProperty, "FastShutterIsOpen", "true"),
                                          functools.partial(self._exporter.writeProperty, "FastShutterIsOpen", "false"),
                                          lambda: self._exporter.readProperty("FastShutterIsOpen") == "true")
Пример #9
0
 def __init__(self, name, config):
     self.phases = {"Centring": 1, "BeamLocation": 2, "DataCollection": 3, "Transfer": 4}
     self.timeout = 3  # s by default
     nn, port = config.get("exporter_addr").split(":")
     self._exporter = Exporter(nn, int(port))
     self._beamviewer_server = config.get("beamviewer_server")
     self._sample_video_server = config.get("sample_video_server")
     self.thgt = config.get("thgt")
     self.ttrans = config.get("ttrans")
     self.transmission = config.get("transmission")
     self.detcover = config.get("detcover")
     self.safshut = config.get("safety_shutter")
Пример #10
0
class md3photodiode(SamplingCounter, Actuator):
    def __init__(self, name, config):
        SamplingCounter.__init__(self, name, None)
        Actuator.__init__(self)

        self.host, self.port = config.get("exporter_address").split(":")
        self._exporter = None

    def _ready(self):
        if self._exporter is None:
            self._exporter = Exporter(self.host, int(self.port))

        if self._exporter.readProperty(
                "State") == "Ready" and self._exporter.readProperty(
                    "HardwareState") == "Ready":
            return True

        return False

    def _set_in(self):
        if self._ready():
            self._exporter.writeProperty("ScintillatorPosition", "PHOTODIODE")

    def _set_out(self):
        if self._ready():
            self._exporter.writeProperty("ScintillatorPosition", "PARK")
        return False

    def _is_in(self):
        if self._ready():
            return self._exporter.readProperty(
                "ScintillatorPosition") == 'PHOTODIODE'
        return False

    def _is_out(self):
        if self._ready():
            return self._exporter.readProperty(
                "ScintillatorPosition") == 'PARK'
        return False

    def read(self):
        if self._ready():
            return self._exporter.execute("readPhotodiodeSignal", 0)
        return None
Пример #11
0
class md3photodiode(SamplingCounter, Actuator):
    def __init__(self, name, config):
        SamplingCounter.__init__(self, name, None)
        Actuator.__init__(self)

        self.host, self.port = config.get("exporter_address").split(":")
        self._exporter = None

    def _ready(self):
        if self._exporter is None:
            self._exporter = Exporter(self.host, int(self.port))

        if self._exporter.readProperty("State") == "Ready" and self._exporter.readProperty("HardwareState") == "Ready":
            return True

        return False

    def _set_in(self):
        if self._ready():
            self._exporter.writeProperty("ScintillatorPosition", "PHOTODIODE")

    def _set_out(self):
        if self._ready():
            self._exporter.writeProperty("ScintillatorPosition", "PARK")
        return False

    def _is_in(self):
        if self._ready():
            return self._exporter.readProperty("ScintillatorPosition") == 'PHOTODIODE'
        return False

    def _is_out(self):
        if self._ready():
            return self._exporter.readProperty("ScintillatorPosition") == 'PARK'
        return False

    def read(self):
        if self._ready():
            return self._exporter.execute("readPhotodiodeSignal", 0)
        return None
Пример #12
0
class MD2S(object):

    def __init__(self, name, config):
        self.phases = {"Centring": 1, "BeamLocation": 2,
                       "DataCollection": 3, "Transfer": 4}
        self.timeout = 3  # s by default
        nn, port = config.get("exporter_addr").split(":")
        self._exporter = Exporter(nn, int(port))

        fshutter = config.get("fshutter")
        if fshutter:
            fshutter.set_external_control(functools.partial(self._exporter.writeProperty, "FastShutterIsOpen", "true"),
                                          functools.partial(self._exporter.writeProperty, "FastShutterIsOpen", "false"),
                                          lambda: self._exporter.readProperty("FastShutterIsOpen") == "true")

    def get_hwstate(self):
        """Read the hardware state (if implemented)
           Returns:
             state(str): the hardware state or Ready (if not implemented)
        """
        try:
            return self._exporter.readProperty("HardwareState")
        except Exception:
            return "Ready"

    def get_swstate(self):
        """Read the software state.
           Returns:
             state(str): the software state
        """
        return self._exporter.readProperty("State")

    def _ready(self):
        if self.get_hwstate() == "Ready" and self.get_swstate() == "Ready":
            return True
        return False

    def _wait_ready(self, timeout=None):
        if timeout <= 0:
            timeout = self.timeout
        tt1 = time.time()
        while time.time() - tt1 < timeout:
            if self._ready():
                break
            else:
                time.sleep(0.5)

    def get_phase(self):
        """Read the current phase
           Returns:
             phase(str): the current phase (Centring, BeamLocation,
                            DataCollection or Transfer)
        """
        return self._exporter.readProperty("CurrentPhase")

    def set_phase(self, phase, wait=False, timeout=40):
        """Set new phase. Wait until finished.
           Args:
               phase(str): Centring, BeamLocation, DataCollection or Transfer
               wait(bool): Wait until finished (True/False)
               timeout(float): wait time [s]
           Returns:
            None
        """
        if phase in self.phases:
            self._exporter.execute("startSetPhase", phase)
            if wait:
                self._wait_ready(timeout)

    def get_camera_calibration(self):
        """Read the pixel per mm - the values are different for each zoom level
           Returns:
             values(list): pixel per mm on Y and Z axis
        """
        # the value depends on the zoom
        px_mm_y = 1./self._exporter.readProperty("CoaxCamScaleX")
        px_mm_z = 1./self._exporter.readProperty("CoaxCamScaleY")
        return [px_mm_y, px_mm_z]

    def move_motors(self, *args):
        """Simultaneous move for all the listed motors.
           Args:
             motor,position(list): motor_object0, position0, motor_object1, ...
        """
        par = ""
        for axis, target in grouped(args, 2):
            par += "%s=%f," % (axis.root_name, target)
        self._exporter.execute("startSimultaneousMoveMotors", par)
        self._wait_ready(20)

    @task
    def _simultaneous_move(self, *args):
        axis_list = []
        for axis, target in grouped(args, 2):
            axis_list.append(axis)
            axis.move(target, wait=False)
        return [axis.wait_move() for axis in axis_list]

    @task
    def _simultaneous_rmove(self, *args):
        axis_list = []
        for axis, target in grouped(args, 2):
            axis_list.append(axis)
            axis.rmove(target, wait=False)
        return [axis.wait_move() for axis in axis_list]

    def msopen(self):
        """Open fast shutter"""
        self._exporter.writeProperty("FastShutterIsOpen", "true")

    def msclose(self):
        """Close fast shutter"""
        self._exporter.writeProperty("FastShutterIsOpen", "false")

    def fldetin(self):
        """Move the fluorescense detector close to the beam position"""
        self._exporter.writeProperty("FluoDetectorIsBack", "false")

    def fldetout(self):
        """Move the fluorescense detector far from the beam position"""
        self._exporter.writeProperty("FluoDetectorIsBack", "true")

    def fldetstate(self):
        """Read the fluorescense detector position
           Returns:
             position(bool): close to the beam - True/False
        """
        self._exporter.readProperty("FluoDetectorIsBack")

    def flight(self, state=None):
        """Switch the front light on/off or read the state
           Args:
             state(bool): on (True), off (False) or None (read only)
           Returns:
             state(bool): on (True)or off (False) - when no args
        """
        if state:
            self._exporter.writeProperty("FrontLightIsOn", state)
        else:
            return self._exporter.readProperty("FrontLightIsOn")

    def blight(self, state=None):
        """Switch the back light on/off or read the state
           Args:
             state(bool): on (True), off (False) or None (read only)
           Returns:
             state(bool): on (True)or off (False) - when no args
        """
        if state:
            self._exporter.writeProperty("BackLightIsOn", state)
        else:
            return self._exporter.readProperty("BackLightIsOn")

    def cryo(self, state=None):
        """Set the cryostat close to/far from the sample or read the position
           Args:
             state(bool): close to (True), far from (False) or None (read only)
           Returns:
             state(bool): close to(True) or far from(False) - when no args
        """
        if state:
            self._exporter.writeProperty("CryoIsBack", state)
        else:
            return self._exporter.readProperty("CryoIsBack")

    def microdiff_init(self, wait=True):
        """Do the homing of all the motors
           Args:
             wait(bool): Wait until finished (True/False)
        """
        self._exporter.execute("startHomingAll")
        if wait:
            self._wait_ready(60)

    def diffractometer_init(self, wait=True):
        self.microdiff_init(wait)

    def phi_init(self, wait=True):
        """Do the homing of omega
           Args:
             wait(bool): Wait until finished (True/False)
        """
        self._exporter.execute("startHomingMotor", "Omega")
        if wait:
            self._wait_ready(10)

    def zoom_init(self, wait=True):
        """Do the homing of the zoom
           Args:
             wait(bool): Wait until finished (True/False)
        """
        self._exporter.execute("startHomingMotor", "Zoom")
        if wait:
            self._wait_ready(10)

    def kappa_init(self, wait=True):
        """Do the homing of the kappa
           Args:
             wait(bool): Wait until finished (True/False)
        """
        self._exporter.execute("startHomingMotor", "Kappa")
        if wait:
            self._wait_ready(10)

        self._exporter.execute("startHomingMotor", "Phi")
        if wait:
            self._wait_ready(10)

    def prepare(self, what, **kwargs):
        """Do actions to prepare the MD2S to use in different procedures like
           centrebeam or alignment. Wait until actions done.
           Args:
             what(string): which is action to follow (see_beam, data_collect)
           Keyword Args:
             zoom_level(int): where to move the zoom to
           Returns:
             zoom_level(int): position before the execition of the action,
                              if relevant
        """
        if what == "data_collect":
            self.set_phase("DataCollection", wait=True, timeout=100)
            if "zoom_level" in kwargs:
                self._exporter.writeProperty("CoaxialCameraZoomValue",
                                             kwargs["zoom_level"])
                self._wait_ready(20)

        if what == "see_beam":
            zoom_level = kwargs.get("zoom_level", 5)
            self.set_phase("BeamLocation", wait=True, timeout=100)
            self._exporter.writeProperty("CapillaryPosition", "OFF")
            self._wait_ready(20)
            self._exporter.writeProperty("AperturePosition", "OFF")
            self._wait_ready(20)
            # get the current zoom position and move zoom to zoom_level
            curr_zoom = self._exporter.readProperty("CoaxialCameraZoomValue")
            self._exporter.writeProperty("CoaxialCameraZoomValue", zoom_level)
            self._wait_ready(20)
            return curr_zoom
Пример #13
0
class MD2S:
    def __init__(self, name, config):
        self.phases = {"Centring": 1, "BeamLocation": 2, "DataCollection": 3, "Transfer": 4}
        self.timeout = 3  # s by default
        nn, port = config.get("exporter_addr").split(":")
        self._exporter = Exporter(nn, int(port))
        self._beamviewer_server = config.get("beamviewer_server")
        self._sample_video_server = config.get("sample_video_server")
        self.thgt = config.get("thgt")
        self.ttrans = config.get("ttrans")
        self.transmission = config.get("transmission")
        self.detcover = config.get("detcover")
        self.safshut = config.get("safety_shutter")

    def get_hwstate(self):
        return self._exporter.readProperty("HardwareState")

    def get_swstate(self):
        return self._exporter.readProperty("State")

    def _ready(self):
        if self.get_hwstate() == "Ready" and self.get_swstate() == "Ready":
            return True
        return False

    def _wait_ready(self, timeout=None):
        if timeout <= 0:
            timeout = self.timeout
        tt1 = time.time()
        while time.time() - tt1 < timeout:
            if self._ready():
                break
            else:
                time.sleep(0.5)

    def get_phase(self):
        return self._exporter.readProperty("CurrentPhase")

    def set_phase(self, phase, wait=False, timeout=40):
        if self.phases.has_key(phase):
            self._exporter.execute("startSetPhase", phase)
            if wait:
                self._wait_ready(timeout)

    def get_cameracalibration(self):
        # the value depends on the zoom
        px_mm_y = 1000000.0 * self._exporter.readProperty("CoaxCamScaleX")
        px_mm_z = 1000000.0 * self._exporter.readProperty("CoaxCamScaleY")
        return [px_mm_y, px_mm_z]

    @task
    def _simultaneous_move(self, *args):
        axis_list = []
        for axis, target in grouped(args, 2):
            axis_list.append(axis)
            axis.move(target, wait=False)
        return [axis.wait_move() for axis in axis_list]

    @task
    def _simultaneous_rmove(self, *args):
        axis_list = []
        for axis, target in grouped(args, 2):
            axis_list.append(axis)
            axis.rmove(target, wait=False)
        return [axis.wait_move() for axis in axis_list]

    def centrebeam(self):
        # stop the procedure if hutch not searched
        stat = self.safshut.get_state()
        if stat == "DISABLE":
            raise RuntimeError("Hutch not searched")
        else:
            self.safshut.open()
        # prepare to see the beam
        self.set_phase("BeamLocation", wait=True, timeout=100)
        self._exporter.writeProperty("CapillaryPosition", "OFF")
        self._wait_ready(20)
        app = self._exporter.readProperty("AperturePosition")
        self._exporter.writeProperty("AperturePosition", "OFF")
        self._wait_ready(20)
        # get the current zoom position and move zoom to 5
        curr_zoom = self._exporter.readProperty("CoaxialCameraZoomValue")
        self._exporter.writeProperty("CoaxialCameraZoomValue", 5)
        self._wait_ready(20)

        # set the camera to read one image
        self.bv_device = DeviceProxy(self._beamviewer_server)
        self.sample_video_device = DeviceProxy(self._sample_video_server)

        def restore_live():
            self.sample_video_device.video_live = True

        # get the image size and camera calibration
        img_width = self.sample_video_device.image_width
        img_height = self.sample_video_device.image_height

        px_mm_y, px_mm_z = self.get_cameracalibration()

        def restore_table(saved_pos=(self.thgt, self.thgt.position(), self.ttrans, self.ttrans.position())):
            # close the fast shutter, if needed
            self.msclose()
            logging.getLogger("user_level_log").info("Restoring table, please wait.")
            self.thgt.stop()
            self.ttrans.stop()
            try:
                self._simultaneous_move(*saved_pos)
            except:
                logging.getLogger("user_level_log").error("Could not restore the table to its initial position")

        def restore_att(old_transmission=self.transmission.transmission_get()):
            self.transmission.transmission_set(old_transmission)
            self._exporter.writeProperty("CoaxialCameraZoomValue", curr_zoom)
            self._wait_ready(20)

        def restore_nobeam():
            self.msclose()
            self.restore_live()
            self.restore_att()

        def do_centrebeam():
            with error_cleanup(restore_att):
                self.msopen()

            with cleanup(restore_live):
                self.sample_video_device.video_live = False
                time.sleep(0.1)
                res = self.bv_device.GetPosition()
                if res[1] < 1500.0:
                    self.transmission.transmission_set(20)
                    time.sleep(0.1)
                    res = self.bv_device.GetPosition()

            by = res[2]
            bz = res[3]
            # check for minimum intensity, stop the procedure if not enough
            with error_cleanup(restore_nobeam):
                if res[1] < 1500.0 or -1 in (by, bz):
                    time.sleep(1)
                    logging.getLogger("user_level_log").error("Could not find beam, centrebeam aborted")
                    raise RuntimeError("Could not find beam")

            dy = (by - (img_width / 2)) / px_mm_y
            dz = (bz - (img_height / 2)) / px_mm_z
            with error_cleanup(restore_live):
                if abs(dy) > 0.1 or abs(dz) > 0.1:
                    logging.getLogger("user_level_log").error("Aborting centrebeam, too big displacement (> 0.1 mm)")
                    time.sleep(1)
                    self.msclose()
                    raise RuntimeError("Aborting centrebeam, too big displacement")
            with error_cleanup(restore_table):
                print "moving ttrans by", -dy
                print "moving thgt by", -dz
                self._simultaneous_rmove(self.thgt, -dz, self.ttrans, -dy)
            return dy, dz

        with cleanup(restore_att):
            self.transmission.transmission_set(1)
            self.detcover.set_in()

            for i in range(7):
                dy, dz = do_centrebeam()
                if abs(dy) < 0.001 and abs(dz) < 0.001:
                    logging.getLogger("user_level_log").info("Centrebeam finished successfully")
                    break
            self.msclose()
            self.set_phase("DataCollection", wait=True, timeout=100)

    def msopen(self):
        self._exporter.writeProperty("FastShutterIsOpen", "true")

    def msclose(self):
        self._exporter.writeProperty("FastShutterIsOpen", "false")

    def fldetin(self):
        self._exporter.writeProperty("FluoDetectorIsBack", "false")

    def fldetout(self):
        self._exporter.writeProperty("FluoDetectorIsBack", "true")

    def fldetstate(self):
        self._exporter.readProperty("FluoDetectorIsBack")

    def flight(self, state=None):
        if state:
            self._exporter.writeProperty("FrontLightIsOn", state)
        else:
            return self._exporter.readProperty("FrontLightIsOn")

    def blight(self, state=None):
        if state:
            self._exporter.writeProperty("BackLightIsOn", state)
        else:
            return self._exporter.readProperty("BackLightIsOn")

    def cryo(self, state=None):
        if state:
            self._exporter.writeProperty("CryoIsBack", state)
        else:
            return self._exporter.readProperty("CryoIsBack")

    def microdiff_init(self, wait=True):
        self._exporter.execute("startHomingAll")
        if wait:
            self._wait_ready(20)

    def phi_init(self, wait=True):
        self._exporter.execute("startHomingMotor", "Omega")
        if wait:
            self._wait_ready(10)

    def zoom_init(self, wait=True):
        self._exporter.execute("startHomingMotor", "Zoom")
        if wait:
            self._wait_ready(10)
Пример #14
0
class MD2S(object):
    def __init__(self, name, config):
        self.phases = {
            "Centring": 1,
            "BeamLocation": 2,
            "DataCollection": 3,
            "Transfer": 4
        }
        self.timeout = 3  # s by default
        nn, port = config.get("exporter_addr").split(":")
        self._exporter = Exporter(nn, int(port))

        fshutter = config.get("fshutter")
        if fshutter:
            fshutter.set_external_control(
                functools.partial(self._exporter.writeProperty,
                                  "FastShutterIsOpen", "true"),
                functools.partial(self._exporter.writeProperty,
                                  "FastShutterIsOpen", "false"), lambda: self.
                _exporter.readProperty("FastShutterIsOpen") == "true")

    def get_hwstate(self):
        """Read the hardware state (if implemented)
           Returns:
             state(str): the hardware state or Ready (if not implemented)
        """
        try:
            return self._exporter.readProperty("HardwareState")
        except Exception:
            return "Ready"

    def get_swstate(self):
        """Read the software state.
           Returns:
             state(str): the software state
        """
        return self._exporter.readProperty("State")

    def _ready(self):
        if self.get_hwstate() == "Ready" and self.get_swstate() == "Ready":
            return True
        return False

    def _wait_ready(self, timeout=None):
        if timeout <= 0:
            timeout = self.timeout
        tt1 = time.time()
        while time.time() - tt1 < timeout:
            if self._ready():
                break
            else:
                time.sleep(0.5)

    def get_phase(self):
        """Read the current phase
           Returns:
             phase(str): the current phase (Centring, BeamLocation,
                            DataCollection or Transfer)
        """
        return self._exporter.readProperty("CurrentPhase")

    def set_phase(self, phase, wait=False, timeout=40):
        """Set new phase. Wait until finished.
           Args:
               phase(str): Centring, BeamLocation, DataCollection or Transfer
               wait(bool): Wait until finished (True/False)
               timeout(float): wait time [s]
           Returns:
            None
        """
        if phase in self.phases:
            self._exporter.execute("startSetPhase", phase)
            if wait:
                self._wait_ready(timeout)

    def get_camera_calibration(self):
        """Read the pixel per mm - the values are different for each zoom level
           Returns:
             values(list): pixel per mm on Y and Z axis
        """
        # the value depends on the zoom
        px_mm_y = 1. / self._exporter.readProperty("CoaxCamScaleX")
        px_mm_z = 1. / self._exporter.readProperty("CoaxCamScaleY")
        return [px_mm_y, px_mm_z]

    def move_motors(self, *args):
        """Simultaneous move for all the listed motors.
           Args:
             motor,position(list): motor_object0, position0, motor_object1, ...
        """
        par = ""
        for axis, target in grouped(args, 2):
            par += "%s=%f," % (axis.root_name, target)
        self._exporter.execute("startSimultaneousMoveMotors", par)
        self._wait_ready(20)

    @task
    def _simultaneous_move(self, *args):
        axis_list = []
        for axis, target in grouped(args, 2):
            axis_list.append(axis)
            axis.move(target, wait=False)
        return [axis.wait_move() for axis in axis_list]

    @task
    def _simultaneous_rmove(self, *args):
        axis_list = []
        for axis, target in grouped(args, 2):
            axis_list.append(axis)
            axis.rmove(target, wait=False)
        return [axis.wait_move() for axis in axis_list]

    def msopen(self):
        """Open fast shutter"""
        self._exporter.writeProperty("FastShutterIsOpen", "true")

    def msclose(self):
        """Close fast shutter"""
        self._exporter.writeProperty("FastShutterIsOpen", "false")

    def fldetin(self):
        """Move the fluorescense detector close to the beam position"""
        self._exporter.writeProperty("FluoDetectorIsBack", "false")

    def fldetout(self):
        """Move the fluorescense detector far from the beam position"""
        self._exporter.writeProperty("FluoDetectorIsBack", "true")

    def fldetstate(self):
        """Read the fluorescense detector position
           Returns:
             position(bool): close to the beam - True/False
        """
        self._exporter.readProperty("FluoDetectorIsBack")

    def flight(self, state=None):
        """Switch the front light on/off or read the state
           Args:
             state(bool): on (True), off (False) or None (read only)
           Returns:
             state(bool): on (True)or off (False) - when no args
        """
        if state:
            self._exporter.writeProperty("FrontLightIsOn", state)
        else:
            return self._exporter.readProperty("FrontLightIsOn")

    def blight(self, state=None):
        """Switch the back light on/off or read the state
           Args:
             state(bool): on (True), off (False) or None (read only)
           Returns:
             state(bool): on (True)or off (False) - when no args
        """
        if state:
            self._exporter.writeProperty("BackLightIsOn", state)
        else:
            return self._exporter.readProperty("BackLightIsOn")

    def cryo(self, state=None):
        """Set the cryostat close to/far from the sample or read the position
           Args:
             state(bool): close to (True), far from (False) or None (read only)
           Returns:
             state(bool): close to(True) or far from(False) - when no args
        """
        if state:
            self._exporter.writeProperty("CryoIsBack", state)
        else:
            return self._exporter.readProperty("CryoIsBack")

    def microdiff_init(self, wait=True):
        """Do the homing of all the motors
           Args:
             wait(bool): Wait until finished (True/False)
        """
        self._exporter.execute("startHomingAll")
        if wait:
            self._wait_ready(60)

    def diffractometer_init(self, wait=True):
        self.microdiff_init(wait)

    def phi_init(self, wait=True):
        """Do the homing of omega
           Args:
             wait(bool): Wait until finished (True/False)
        """
        self._exporter.execute("startHomingMotor", "Omega")
        if wait:
            self._wait_ready(10)

    def zoom_init(self, wait=True):
        """Do the homing of the zoom
           Args:
             wait(bool): Wait until finished (True/False)
        """
        self._exporter.execute("startHomingMotor", "Zoom")
        if wait:
            self._wait_ready(10)

    def kappa_init(self, wait=True):
        """Do the homing of the kappa
           Args:
             wait(bool): Wait until finished (True/False)
        """
        self._exporter.execute("startHomingMotor", "Kappa")
        if wait:
            self._wait_ready(10)

        self._exporter.execute("startHomingMotor", "Phi")
        if wait:
            self._wait_ready(10)

    def prepare(self, what, **kwargs):
        """Do actions to prepare the MD2S to use in different procedures like
           centrebeam or alignment. Wait until actions done.
           Args:
             what(string): which is action to follow (see_beam, data_collect)
           Keyword Args:
             zoom_level(int): where to move the zoom to
           Returns:
             zoom_level(int): position before the execition of the action,
                              if relevant
        """
        if what == "data_collect":
            self.set_phase("DataCollection", wait=True, timeout=100)
            if "zoom_level" in kwargs:
                self._exporter.writeProperty("CoaxialCameraZoomValue",
                                             kwargs["zoom_level"])
                self._wait_ready(20)

        if what == "see_beam":
            zoom_level = kwargs.get("zoom_level", 5)
            self.set_phase("BeamLocation", wait=True, timeout=100)
            self._exporter.writeProperty("CapillaryPosition", "OFF")
            self._wait_ready(20)
            self._exporter.writeProperty("AperturePosition", "OFF")
            self._wait_ready(20)
            # get the current zoom position and move zoom to zoom_level
            curr_zoom = self._exporter.readProperty("CoaxialCameraZoomValue")
            self._exporter.writeProperty("CoaxialCameraZoomValue", zoom_level)
            self._wait_ready(20)
            return curr_zoom