예제 #1
0
    def test_multi_det(self):
        """
        Test AutoFocus Spectrometer with multiple detectors
        """
        # Note: a full procedure would start by setting the slit to the smallest position
        # (cf optical path mode "spec-focus") and activating an energy source

        self.focus.moveAbs({"z": self._good_focus + 400e-6}).result()
        f = align.AutoFocusSpectrometer(self.spgr, self.focus,
                                        [self.ccd, self.spccd], self.selector)
        res = f.result(timeout=900)
        for (g, d), fpos in res.items():
            self.assertIn(d, (self.ccd, self.spccd))
            # Only check that the focus is correct with the CCD as the simulator
            # doesn't actually connects the focus position to the spccd image
            # (so the image is always the same, and the autofocus procedure
            # picks a random position)
            if d is self.ccd:
                self.assertAlmostEqual(fpos, self._good_focus, 3)

        # The number of entries depend on the implementation. For now, we expect
        # an entry for each combination grating/detector
        ngs = len(self.spgr.axes["grating"].choices)
        nds = 2
        self.assertEqual(len(res), ngs * nds)
예제 #2
0
 def test_cancel(self):
     """
     Test cancelling does cancel (relatively quickly)
     """
     self.focus.moveAbs({"z": self._good_focus + 400e-6}).result()
     f = align.AutoFocusSpectrometer(self.spgr, self.focus, [self.ccd])
     time.sleep(2)
     f.cancel()
     self.assertTrue(f.cancelled())
     with self.assertRaises(CancelledError):
         res = f.result(timeout=900)
예제 #3
0
    def test_one_det(self):
        """
        Test AutoFocus Spectrometer on CCD
        """
        self.focus.moveAbs({"z": self._good_focus - 200e-6}).result()
        f = align.AutoFocusSpectrometer(self.spgr, self.focus, self.ccd)
        res = f.result(timeout=900)
        for (g, d), fpos in res.items():
            self.assertIs(d, self.ccd)
            self.assertAlmostEqual(fpos, self._good_focus, 3)

        self.assertEqual(len(res.keys()), len(self.spgr.axes["grating"].choices))
예제 #4
0
def main(args):
    """
    Handles the command line arguments
    args is the list of arguments passed
    return (int): value to return to the OS as program exit code
    """

    # arguments handling
    parser = argparse.ArgumentParser(description="Automated focus procedure")

    parser.add_argument("--detector", "-d", dest="detector", default="ccd",
                        help="role of the detector (default: ccd)")
    parser.add_argument("--focuser", "-f", dest="focuser", default="focus",
                        help="role of the focus component (default: focus). "
                             "It must be an actuator with a 'z' axis.")
    parser.add_argument("--spectrograph", "-s", dest="spectrograph",
                        help="role of the spectrograph component. "
                             "If provided, a full spectrometer autofocus will be executed.")
    parser.add_argument("--log-level", dest="loglev", metavar="<level>", type=int,
                        default=1, help="set verbosity level (0-2, default = 1)")

    options = parser.parse_args(args[1:])

    # Set up logging before everything else
    if options.loglev < 0:
        logging.error("Log-level must be positive.")
        return 127
    loglev_names = [logging.WARNING, logging.INFO, logging.DEBUG]
    loglev = loglev_names[min(len(loglev_names) - 1, options.loglev)]
    logging.getLogger().setLevel(loglev)

    try:
        # find components by their role
        try:
            det = model.getComponent(role=options.detector)
        except LookupError:
            raise ValueError("Failed to find detector '%s'" % (options.detector,))
        try:
            focuser = model.getComponent(role=options.focuser)
        except LookupError:
            raise ValueError("Failed to find focuser '%s'" % (options.focuser,))

        emt = None
        if det.role in ("se-detector", "bs-detector", "cl-detector"):
            # For EM images, the emitter is not necessary, but helps to get a
            # better step size in the search (and time estimation)
            try:
                emt = model.getComponent(role="e-beam")
            except LookupError:
                logging.info("Failed to find e-beam emitter")
                pass

        if options.spectrograph:
            try:
                spgr = model.getComponent(role=options.spectrograph)
                # TODO: allow multiple detectors
            except LookupError:
                raise ValueError("Failed to find spectrograph '%s'" % (options.spectrograph,))
        else:
            spgr = None

        logging.info("Original focus position: %f m", focuser.position.value["z"])

        # Apply autofocus
        try:
            if spgr:
                future_focus = align.AutoFocusSpectrometer(spgr, focuser, det)
                foc = future_focus.result(1000)  # putting a timeout allows to get KeyboardInterrupts
                logging.info("Focus levels after applying autofocus: %s",
                             "".join("\n\tgrating %d on %s @ %f m" % (g, d.name, f) for (g, d), f in foc.items()))
            else:
                future_focus = align.AutoFocus(det, emt, focuser)
                foc_pos, fm_final = future_focus.result(1000)  # putting a timeout allows to get KeyboardInterrupts
                logging.info("Focus level after applying autofocus: %f @ %f m", fm_final, foc_pos)
        except KeyboardInterrupt:
            future_focus.cancel()
            raise

    except KeyboardInterrupt:
        logging.info("Interrupted before the end of the execution")
        return 1
    except ValueError as exp:
        logging.error("%s", exp)
        return 127
    except Exception:
        logging.exception("Unexpected error while performing action.")
        return 127

    return 0