def test_autofocus_sem_hint(self): """ Test AutoFocus on e-beam with a hint """ self.efocus.moveAbs({"z": self._sem_good_focus + 200e-06}).result() self.ebeam.dwellTime.value = self.ebeam.dwellTime.range[0] # We don't give exactly the good focus position, to make it a little harder future_focus = align.AutoFocus(self.sed, self.ebeam, self.efocus, good_focus=self._sem_good_focus + 100e-9) foc_pos, foc_lev = future_focus.result(timeout=900) self.assertAlmostEqual(foc_pos, self._sem_good_focus, 3) self.assertGreater(foc_lev, 0)
def test_autofocus_optical_start_at_good_focus(self): """ Test if the correct focus position is found when starting at the correct focus position. """ # Move the stage so that the image is out of focus start_position = self._optimal_focus self.ofocus.moveAbs({"z": start_position}).result() # check that it moved to the correct starting position numpy.testing.assert_allclose(self.ofocus.position.value["z"], start_position, atol=1e-7) # Run autofocus future_focus = align.AutoFocus(self.diagnostic_cam, None, self.ofocus) foc_pos, foc_lev = future_focus.result(timeout=900) # Test that the correct focus has been found. logging.debug("found focus at {} good focus at {}".format(foc_pos, self._optimal_focus)) numpy.testing.assert_allclose(foc_pos, self._optimal_focus, atol=0.5e-6)
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("--accuracy", "-a", dest="accuracy", required=True, help="Focus precision in meters") options = parser.parse_args(args[1:]) accuracy = float(options.accuracy) try: ccd = None focus = None # find components by their role for c in model.getComponents(): if c.role == "ccd": ccd = c elif c.role == "focus": focus = c if not all([ccd, focus]): logging.error("Failed to find all the components") raise KeyError("Not all components found") # Measure current focus img = ccd.data.get() fm_cur = autofocus.MeasureFocus(img) logging.debug("Current focus level: %f", fm_cur) # Apply autofocus future_focus = align.AutoFocus(ccd, None, focus, accuracy) foc_pos, fm_final = future_focus.result() logging.debug("Focus level after applying autofocus: %f", fm_final) except: logging.exception("Unexpected error while performing action.") return 127 return 0
def test_autofocus_optical(self): """ Test AutoFocus for a certain starting position and good focus position. """ # Move the stage so that the image is out of focus center_position = 74e-6 self.ofocus.moveAbs({"z": center_position}).result() numpy.testing.assert_allclose(self.ofocus.position.value["z"], center_position, atol=1e-7) # run autofocus future_focus = align.AutoFocus(self.diagnostic_cam, None, self.ofocus) foc_pos, foc_lev = future_focus.result(timeout=900) # Test if the correct focus position was found. logging.debug("found focus at {} good focus at {}".format( foc_pos, self._optimal_focus)) numpy.testing.assert_allclose(foc_pos, self._optimal_focus, atol=0.5e-6)
def test_autofocus_spect(self): """ Test AutoFocus on 1 line CCD for example spectrum. """ # Make sure the image is the example spectrum image, in case this test runs after test_autofocus_slit. data = hdf5.read_data( os.path.dirname(odemis.__file__) + "/driver/sparc-spec-sim.h5") new_img = img.ensure2DImage(data[0]) self.ccd.set_image(new_img) self.focus.moveAbs({"z": self._good_focus - 200e-6}).result() f = align.AutoFocus(self.spectrometer, None, self.focus, method=MTD_BINARY) foc_pos, foc_lev = f.result(timeout=900) logging.debug("Found focus at {} good focus at {}".format( foc_pos, self._good_focus)) # The focus step size is 10.9e-6, the tolerance is set to 2.5e-5; approximately two focus steps. numpy.testing.assert_allclose(foc_pos, self._good_focus, atol=2.5e-5)
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