Beispiel #1
0
    def test_ab_rotation(self):
        """
        Test typical rotation stage for the SECOM v1 A/B alignment
        """
        child = simulated.Stage("stage", "test", axes=["a", "b"])
        stage = ConvertStage("inclined", "align", {"orig": child},
                             axes=["b", "a"], rotation=math.radians(-135))

        f = stage.moveRel({"x":1e-06, "y":2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x":1e-06, "y":2e-06})
        self.assertPosAlmostEqual(child.position.value, {"a":-2.1213203435596424e-06, "b":7.071067811865477e-07})
        f = stage.moveRel({"x":-1e-06, "y":-2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x":0, "y":0})
        self.assertPosAlmostEqual(child.position.value, {"a":0, "b":0})
Beispiel #2
0
    def setUpClass(cls):

        try:
            test.start_backend(SECOM_LENS_CONFIG)
        except LookupError:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return
        except IOError as exp:
            logging.error(str(exp))
            raise

        # find components by their role
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
        cls.ccd = model.getComponent(role="ccd")
        cls.focus = model.getComponent(role="focus")
        cls.align = model.getComponent(role="align")
        cls.light = model.getComponent(role="light")
        cls.light_filter = model.getComponent(role="filter")

        # Used for OBJECTIVE_MOVE type
        cls.aligner_xy = ConvertStage("converter-ab", "stage",
                                      dependencies={"orig": cls.align},
                                      axes=["b", "a"],
                                      rotation=math.radians(45))
Beispiel #3
0
    def test_ab_rotation(self):
        """
        Test typical rotation stage for the SECOM v1 A/B alignment
        """
        child = simulated.Stage("stage", "test", axes=["a", "b"])
        stage = ConvertStage("inclined", "align", {"orig": child},
                             axes=["b", "a"], rotation=math.radians(-135))

        f = stage.moveRel({"x": 1e-06, "y": 2e-06})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x": 1e-06, "y": 2e-06})
        test.assert_pos_almost_equal(child.position.value, {"a":-2.1213203435596424e-06,
                                                         "b": 7.071067811865477e-07})
        f = stage.moveRel({"x": -1e-06, "y": -2e-06})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x": 0, "y": 0})
        test.assert_pos_almost_equal(child.position.value, {"a": 0, "b": 0})
Beispiel #4
0
    def test_move_abs(self):
        child = simulated.Stage("stage", "test", axes=["x", "y"])

        # no transformation
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"])
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        f = stage.moveAbs({"x": 1e-06, "y": 2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {
            "x": 1e-06,
            "y": 2e-06
        })
        self.assertPosAlmostEqual(child.position.value, {
            "x": 1e-06,
            "y": 2e-06
        })
        f = stage.moveAbs({"x": 0, "y": 0})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        self.assertPosAlmostEqual(child.position.value, {"x": 0, "y": 0})

        # scaling
        stage = ConvertStage("conv",
                             "align", {"orig": child},
                             axes=["x", "y"],
                             scale=(10, 10))
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        f = stage.moveAbs({"x": 1e-06, "y": 2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {
            "x": 1e-06,
            "y": 2e-06
        })
        self.assertPosAlmostEqual(child.position.value, {
            "x": 1e-05,
            "y": 2e-05
        })
        f = stage.moveAbs({"x": 0, "y": 0})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        self.assertPosAlmostEqual(child.position.value, {"x": 0, "y": 0})

        # rotation
        stage = ConvertStage("conv",
                             "align", {"orig": child},
                             axes=["x", "y"],
                             rotation=math.pi / 2)
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        f = stage.moveAbs({"x": 1e-06, "y": 2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {
            "x": 1e-06,
            "y": 2e-06
        })
        self.assertPosAlmostEqual(child.position.value, {
            "x": -2e-06,
            "y": 1e-06
        })
        f = stage.moveAbs({"x": 0, "y": 0})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        self.assertPosAlmostEqual(child.position.value, {"x": 0, "y": 0})

        # offset
        stage = ConvertStage("conv",
                             "align", {"orig": child},
                             axes=["x", "y"],
                             translation=(1e-06, 2e-06))
        self.assertPosAlmostEqual(stage.position.value, {
            "x": -1e-06,
            "y": -2e-06
        })
        f = stage.moveAbs({"x": 0, "y": 0})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        self.assertPosAlmostEqual(child.position.value, {
            "x": 1e-06,
            "y": 2e-06
        })
        f = stage.moveAbs({"x": -1e-06, "y": -2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {
            "x": -1e-06,
            "y": -2e-06
        })
        self.assertPosAlmostEqual(child.position.value, {"x": 0, "y": 0})

        # offset + scaling
        stage = ConvertStage("conv",
                             "align", {"orig": child},
                             axes=["x", "y"],
                             translation=(1e-06, 2e-06),
                             scale=(10, 10))
        self.assertPosAlmostEqual(stage.position.value, {
            "x": -1e-06,
            "y": -2e-06
        })
        f = stage.moveAbs({"x": 0, "y": 0})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        self.assertPosAlmostEqual(child.position.value, {
            "x": 1e-05,
            "y": 2e-05
        })
Beispiel #5
0
    def test_move_abs(self):
        child = simulated.Stage("stage", "test", axes=["x", "y"])

        # no transformation
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"])
        test.assert_pos_almost_equal(stage.position.value, {"x": 0, "y": 0})
        f = stage.moveAbs({"x": 1e-06, "y": 2e-06})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x": 1e-06, "y": 2e-06})
        test.assert_pos_almost_equal(child.position.value, {"x": 1e-06, "y": 2e-06})
        f = stage.moveAbs({"x": 0, "y": 0})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x": 0, "y": 0})
        test.assert_pos_almost_equal(child.position.value, {"x": 0, "y": 0})

        # scaling
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"],
                             scale=(10, 10))
        test.assert_pos_almost_equal(stage.position.value, {"x": 0, "y": 0})
        f = stage.moveAbs({"x": 1e-06, "y": 2e-06})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x": 1e-06, "y": 2e-06})
        test.assert_pos_almost_equal(child.position.value, {"x": 1e-05, "y": 2e-05})
        f = stage.moveAbs({"x": 0, "y": 0})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x": 0, "y": 0})
        test.assert_pos_almost_equal(child.position.value, {"x": 0, "y": 0})

        # rotation
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"],
                             rotation=math.pi / 2)
        test.assert_pos_almost_equal(stage.position.value, {"x": 0, "y": 0})
        f = stage.moveAbs({"x": 1e-06, "y": 2e-06})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x": 1e-06, "y": 2e-06})
        test.assert_pos_almost_equal(child.position.value, {"x":-2e-06, "y": 1e-06})
        f = stage.moveAbs({"x": 0, "y": 0})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x": 0, "y": 0})
        test.assert_pos_almost_equal(child.position.value, {"x": 0, "y": 0})

        # offset
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"],
                             translation=(1e-06, 2e-06))
        test.assert_pos_almost_equal(stage.position.value, {"x":-1e-06, "y":-2e-06})
        f = stage.moveAbs({"x": 0, "y": 0})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x": 0, "y": 0})
        test.assert_pos_almost_equal(child.position.value, {"x": 1e-06, "y": 2e-06})
        f = stage.moveAbs({"x": -1e-06, "y": -2e-06})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x":-1e-06, "y":-2e-06})
        test.assert_pos_almost_equal(child.position.value, {"x": 0, "y": 0})

        # offset + scaling
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"],
                             translation=(1e-06, 2e-06),
                             scale=(10, 10))
        test.assert_pos_almost_equal(stage.position.value, {"x":-1e-06, "y":-2e-06})
        f = stage.moveAbs({"x": 0, "y": 0})
        f.result()
        test.assert_pos_almost_equal(stage.position.value, {"x": 0, "y": 0})
        test.assert_pos_almost_equal(child.position.value, {"x": 1e-05, "y": 2e-05})
Beispiel #6
0
    def test_move_rel(self):
        child = simulated.Stage("stage", "test", axes=["x", "y"])

        # no transformation
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"])
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        f = stage.moveRel({"x": 1e-06, "y": 2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 1e-06, "y": 2e-06})
        self.assertPosAlmostEqual(child.position.value, {"x": 1e-06, "y": 2e-06})
        f = stage.moveRel({"x": -1e-06, "y": -2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        self.assertPosAlmostEqual(child.position.value, {"x": 0, "y": 0})

        # scaling
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"],
                             scale=(10, 10))
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        f = stage.moveRel({"x": 1e-06, "y": 2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 1e-06, "y": 2e-06})
        self.assertPosAlmostEqual(child.position.value, {"x": 10e-06, "y": 20e-06})
        f = stage.moveRel({"x": -1e-06, "y": -2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        self.assertPosAlmostEqual(child.position.value, {"x": 0, "y": 0})

        # rotation
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"],
                             rotation=math.pi / 2)
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        f = stage.moveRel({"x": 1e-06, "y": 2e-06})
        f.result()
        self.assertEqual(stage.position.value, {"x": 1e-06, "y": 2e-06})
        self.assertPosAlmostEqual(child.position.value, {"x": -2e-06, "y": 1e-06})
        f = stage.moveRel({"x": -1e-06, "y": -2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        self.assertPosAlmostEqual(child.position.value, {"x": 0, "y": 0})

        # offset
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"],
                             translation=(1e-06, 2e-06))
        self.assertPosAlmostEqual(stage.position.value, {"x": -1e-06, "y": -2e-06})
        f = stage.moveRel({"x": 1e-06, "y": 2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        self.assertPosAlmostEqual(child.position.value, {"x": 1e-06, "y": 2e-06})
        f = stage.moveRel({"x": -1e-06, "y": -2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": -1e-06, "y": -2e-06})
        self.assertPosAlmostEqual(child.position.value, {"x": 0, "y": 0})

        # offset + scaling
        stage = ConvertStage("conv", "align", {"orig": child}, axes=["x", "y"],
                             translation=(1e-06, 2e-06),
                             scale=(10, 10))
        self.assertPosAlmostEqual(stage.position.value, {"x": -1e-06, "y": -2e-06})
        f = stage.moveRel({"x": 1e-06, "y": 2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": 0, "y": 0})
        self.assertPosAlmostEqual(child.position.value, {"x": 10e-06, "y": 20e-06})
        f = stage.moveRel({"x": -1e-06, "y": -2e-06})
        f.result()
        self.assertPosAlmostEqual(stage.position.value, {"x": -1e-06, "y": -2e-06})
        self.assertPosAlmostEqual(child.position.value, {"x": 0, "y": 0})
Beispiel #7
0
def _DoCenterSpot(future, ccd, stage, escan, mx_steps, type, background,
                  dataflow):
    """
    Iteratively acquires an optical image, finds the coordinates of the spot 
    (center) and moves the stage to this position. Repeats until the found 
    coordinates are at the center of the optical image or a maximum number of 
    steps is reached.
    future (model.ProgressiveFuture): Progressive future provided by the wrapper
    ccd (model.DigitalCamera): The CCD
    stage (model.Actuator): The stage
    escan (model.Emitter): The e-beam scanner
    mx_steps (int): Maximum number of steps to reach the center
    type (string): Type of move in order to align
    returns (float or None):    Final distance to the center #m 
    raises:
            CancelledError() if cancelled
    """
    try:
        logging.debug("Aligning spot...")
        if type == OBJECTIVE_MOVE:
            stage_ab = ConvertStage("converter-ab",
                                    "stage",
                                    children={"orig": stage},
                                    axes=["b", "a"],
                                    rotation=math.radians(-135))
        image = ccd.data.get(asap=False)
        # Center of optical image
        pixelSize = image.metadata[model.MD_PIXEL_SIZE]
        center_pxs = (image.shape[1] / 2, image.shape[0] / 2)
        # Epsilon distance below which the lens is considered centered. The worse of:
        # * 1.5 pixels (because the CCD resolution cannot give us better)
        # * 1 µm (because that's the best resolution of our actuators)
        err_mrg = max(1.5 * pixelSize[0], 1e-06)  # m
        steps = 0
        # Stop once spot is found on the center of the optical image
        dist = None
        while True:
            if future._spot_center_state == CANCELLED:
                raise CancelledError()
            # Or once max number of steps is reached
            if steps >= mx_steps:
                break

            # Wait to make sure no previous spot is detected
            image = SubstractBackground(ccd, dataflow)
            try:
                spot_pxs = FindSpot(image)
            except ValueError:
                return None, None
            tab_pxs = [a - b for a, b in zip(spot_pxs, center_pxs)]
            tab = (tab_pxs[0] * pixelSize[0], tab_pxs[1] * pixelSize[1])
            dist = math.hypot(*tab)
            # If we are already there, stop
            if dist <= err_mrg:
                break

            # Move to the found spot
            if type == OBJECTIVE_MOVE:
                f = stage_ab.moveRel({"x": tab[0], "y": -tab[1]})
                f.result()
            elif type == STAGE_MOVE:
                f = stage.moveRel({"x": -tab[0], "y": tab[1]})
                f.result()
            else:
                escan.translation.value = (-tab_pxs[0], -tab_pxs[1])
            steps += 1
            # Update progress of the future
            future.set_end_time(
                time.time() + estimateCenterTime(ccd.exposureTime.value, dist))

        return dist, tab
    finally:
        with future._center_lock:
            if future._spot_center_state == CANCELLED:
                raise CancelledError()
            future._spot_center_state = FINISHED
Beispiel #8
0
def _DoCenterSpot(future, ccd, stage, escan, mx_steps, type, background, dataflow):
    """
    Iteratively acquires an optical image, finds the coordinates of the spot 
    (center) and moves the stage to this position. Repeats until the found 
    coordinates are at the center of the optical image or a maximum number of 
    steps is reached.
    future (model.ProgressiveFuture): Progressive future provided by the wrapper
    ccd (model.DigitalCamera): The CCD
    stage (model.Actuator): The stage
    escan (model.Emitter): The e-beam scanner
    mx_steps (int): Maximum number of steps to reach the center
    type (string): Type of move in order to align
    returns (float or None):    Final distance to the center #m 
    raises:
            CancelledError() if cancelled
    """
    try:
        logging.debug("Aligning spot...")
        if type == OBJECTIVE_MOVE:
            stage_ab = ConvertStage("converter-ab", "stage",
                                    children={"orig": stage},
                                    axes=["b", "a"],
                                    rotation=math.radians(-135))
        image = ccd.data.get(asap=False)
        # Center of optical image
        pixelSize = image.metadata[model.MD_PIXEL_SIZE]
        center_pxs = (image.shape[1] / 2, image.shape[0] / 2)
        # Epsilon distance below which the lens is considered centered. The worse of:
        # * 1.5 pixels (because the CCD resolution cannot give us better)
        # * 1 µm (because that's the best resolution of our actuators)
        err_mrg = max(1.5 * pixelSize[0], 1e-06)  # m
        steps = 0
        # Stop once spot is found on the center of the optical image
        dist = None
        while True:
            if future._spot_center_state == CANCELLED:
                raise CancelledError()
            # Or once max number of steps is reached
            if steps >= mx_steps:
                break
    
            # Wait to make sure no previous spot is detected
            image = SubstractBackground(ccd, dataflow)
            try:
                spot_pxs = FindSpot(image)
            except ValueError:
                return None, None
            tab_pxs = [a - b for a, b in zip(spot_pxs, center_pxs)]
            tab = (tab_pxs[0] * pixelSize[0], tab_pxs[1] * pixelSize[1])
            dist = math.hypot(*tab)
            # If we are already there, stop
            if dist <= err_mrg:
                break
    
            # Move to the found spot
            if type == OBJECTIVE_MOVE:
                f = stage_ab.moveRel({"x":tab[0], "y":-tab[1]})
                f.result()
            elif type == STAGE_MOVE:
                f = stage.moveRel({"x":-tab[0], "y":tab[1]})
                f.result()
            else:
                escan.translation.value = (-tab_pxs[0], -tab_pxs[1])
            steps += 1
            # Update progress of the future
            future.set_end_time(time.time() +
                                estimateCenterTime(ccd.exposureTime.value, dist))
    
        return dist, tab
    finally:
        with future._center_lock:
            if future._spot_center_state == CANCELLED:
                raise CancelledError()
            future._spot_center_state = FINISHED