Esempio n. 1
0
    def __init__(self, fn, number):
        self.number = number

        # get the components
        self.light = model.getComponent(role="light")
        self.ccd = model.getComponent(role="ccd")

        # TODO: only support TIFF
        # prepare the data export
        self.exporter = dataio.find_fittest_converter(fn)

        # Make the name "fn" -> "~/Pictures/fn-XXXXXX.ext"
        path, base = os.path.split(fn)
        bn, ext = os.path.splitext(base)
        tmpl = os.path.join(path, bn + "-%06d" + ext)
        if path.startswith("/"):
            # if fn starts with / => don't add ~/Pictures
            self.fntmpl = tmpl
        else:
            self.fntmpl = os.path.join(get_picture_folder(), tmpl)

        self._acq_done = threading.Event()
        self._n = 0
        self._startt = 0  # starting time of acquisition

        self._q = Queue.Queue()  # queue of tuples (str, DataArray) for saving data
        # TODO: find the right number of threads, based on CPU numbers (but with
        # python threading that might be a bit overkill)
        for i in range(4):
            t = threading.Thread(target=self._saving_thread, args=(i,))
            t.daemon = True
            t.start()
Esempio n. 2
0
    def __init__(self, microscope, main_app):
        super(MonoScanPlugin, self).__init__(microscope, main_app)

        # Can only be used on a Sparc with a monochromator
        if not microscope:
            return
        try:
            self.ebeam = model.getComponent(role="e-beam")
            self.mchr = model.getComponent(role="monochromator")
            self.sgrh = model.getComponent(role="spectrograph")
        except LookupError:
            logging.debug("No mochromator and spectrograph found, cannot use the plugin")
            return

        self.addMenu("Acquisition/Monochromator scan...", self.start)

        # the SEM survey stream (will be updated when showing the window)
        self._survey_s = None

        # Create a stream for monochromator scan
        self._mchr_s = MonochromatorScanStream("Spectrum", self.mchr, self.ebeam, self.sgrh)

        # The settings to be displayed in the dialog
        # Trick: we use the same VAs as the stream, so they are directly synchronised
        self.startWavelength = self._mchr_s.startWavelength
        self.endWavelength = self._mchr_s.endWavelength
        self.numberOfPixels = self._mchr_s.numberOfPixels
        self.dwellTime = self._mchr_s.dwellTime

        self.filename = model.StringVA("a.h5")
        self.expectedDuration = model.VigilantAttribute(1, unit="s", readonly=True)

        # Update the expected duration when values change
        self.dwellTime.subscribe(self._update_exp_dur)
        self.numberOfPixels.subscribe(self._update_exp_dur)
Esempio n. 3
0
    def setUpClass(cls):

        if driver.get_backend_status() == driver.BACKEND_RUNNING:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return

        # run the backend as a daemon
        # we cannot run it normally as the child would also think he's in a unittest
        cmd = ODEMISD_CMD + ODEMISD_ARG + [SECOM_LENS_CONFIG]
        ret = subprocess.call(cmd)
        if ret != 0:
            logging.error("Failed starting backend with '%s'", cmd)
        time.sleep(1)  # time to start

        # find components by their role
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="bs-detector")
        cls.ccd = model.getComponent(role="ccd")
        cls.sem_stage = model.getComponent(role="sem-stage")
        cls.opt_stage = model.getComponent(role="align")
        cls.ebeam_focus = model.getComponent(role="ebeam-focus")
        cls.focus = model.getComponent(role="focus")
        cls.light = model.getComponent(role="light")
        cls.light_filter = model.getComponent(role="filter")
        cls.combined_stage = model.getComponent(role="stage")
Esempio n. 4
0
    def setUpClass(cls):

        try:
            test.start_backend(SECOM_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

        # create some streams connected to the backend
        cls.microscope = model.getMicroscope()
        cls.ccd = model.getComponent(role="ccd")
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
        cls.light = model.getComponent(role="light")
        cls.light_filter = model.getComponent(role="filter")

        s1 = stream.FluoStream("fluo1", cls.ccd, cls.ccd.data,
                               cls.light, cls.light_filter)
        s1.excitation.value = sorted(s1.excitation.choices)[0]
        s2 = stream.FluoStream("fluo2", cls.ccd, cls.ccd.data,
                               cls.light, cls.light_filter)
        s2.excitation.value = sorted(s2.excitation.choices)[-1]
        s3 = stream.BrightfieldStream("bf", cls.ccd, cls.ccd.data, cls.light)
        cls.streams = [s1, s2, s3]
Esempio n. 5
0
def cryoTiltSample(rx, rz=0):
    """
    Provide the ability to switch between imaging and tilted position, withing bumping into anything.
    Imaging position is considered when rx and rz are equal 0, otherwise it's considered tilting
    :param rx: (float) rotation movement in x axis
    :param rz: (float) rotation movement in z axis
    :return (CancellableFuture -> None): cancellable future of the move to observe the progress, and control raising the ValueError exception
    """
    # Get the stage and align components from the backend components
    stage = model.getComponent(role='stage')
    align = model.getComponent(role='align')

    f = model.CancellableFuture()
    f.task_canceller = _cancelCryoMoveSample
    f._task_state = RUNNING
    f._task_lock = threading.Lock()
    f._running_subf = model.InstantaneousFuture()
    # Run in separate thread
    executeAsyncTask(f, _doCryoTiltSample, args=(
        f,
        stage,
        align,
        rx,
        rz,
    ))
    return f
Esempio n. 6
0
    def setUpClass(cls):
        test.start_backend(ENZEL_CONFIG)

        # find components by their role
        cls.stage = model.getComponent(role="stage")
        cls.aligner = model.getComponent(role="align")

        cls.stage_active = cls.stage.getMetadata()[model.MD_FAV_POS_ACTIVE]
        cls.stage_deactive = cls.stage.getMetadata()[model.MD_FAV_POS_DEACTIVE]
        cls.stage_coating = cls.stage.getMetadata()[model.MD_FAV_POS_COATING]
        cls.stage_alignment = cls.stage.getMetadata()[model.MD_FAV_POS_ALIGN]
        cls.stage_sem_imaging = cls.stage.getMetadata()[model.MD_FAV_POS_SEM_IMAGING]
        cls.stage_3beams = get3beamsSafePos(cls.stage.getMetadata()[model.MD_FAV_POS_ACTIVE], SAFETY_MARGIN_5DOF)
        cls.align_deactive = cls.aligner.getMetadata()[model.MD_FAV_POS_DEACTIVE]
        cls.align_alignment = cls.aligner.getMetadata()[model.MD_FAV_POS_ALIGN]
        cls.align_active = cls.aligner.getMetadata()[model.MD_FAV_POS_ACTIVE]
        cls.align_3beams = get3beamsSafePos(cls.aligner.getMetadata()[model.MD_FAV_POS_ACTIVE], SAFETY_MARGIN_3DOF)

        # Make sure the lens is referenced too (small move will only complete after the referencing)
        cls.aligner.moveRelSync({"x": 1e-6})

        # The 5DoF stage is not referenced automatically, so let's do it now
        if not all(cls.stage.referenced.value.values()):
            stage_axes = set(cls.stage.axes.keys())
            cls.stage.reference(stage_axes).result()

        # Set custom value that works well within the simulator range
        cls.rx_angle = 0.3
        cls.rz_angle = 0.1
Esempio n. 7
0
    def test_properties_set(self):
        """Test creating component with specific properties"""
        filename = "example-secom.odm.yaml"
        cmdline = "--log-level=2 --log-target=testdaemon.log --daemonize %s" % filename
        ret = subprocess.call(ODEMISD_CMD + cmdline.split())
        self.assertEqual(ret, 0, "trying to run '%s'" % cmdline)

        # eventually it should say it's running
        ret = self._wait_backend_starts(10)
        self.assertEqual(ret, 0, "backend status check returned %d" % (ret,))

        # Check that the specific properties are set
        ccd = model.getComponent(role="ccd")
        self.assertEqual(ccd.exposureTime.value, 0.3)

        ebeam = model.getComponent(role="e-beam")
        self.assertEqual(ebeam.horizontalFoV.value, 1e-6)

        # stop the backend
        cmdline = "odemisd --log-level=2 --log-target=test.log --kill"
        ret = main.main(cmdline.split())
        self.assertEqual(ret, 0, "trying to run '%s'" % cmdline)

        time.sleep(5) # give some time to stop
        ret = main.main(cmdline.split())
        os.remove("test.log")
        os.remove("testdaemon.log")
Esempio n. 8
0
    def __init__(self, microscope, main_app):
        super(MonoScanPlugin, self).__init__(microscope, main_app)

        # Can only be used on a Sparc with a monochromator
        if not microscope:
            return
        try:
            self.ebeam = model.getComponent(role="e-beam")
            self.mchr = model.getComponent(role="monochromator")
            self.sgrh = model.getComponent(role="spectrograph")
        except LookupError:
            logging.debug("No mochromator and spectrograph found, cannot use the plugin")
            return

        self.addMenu("Acquisition/Monochromator scan...", self.start)

        # the SEM survey stream (will be updated when showing the window)
        self._survey_s = None

        # Create a stream for monochromator scan
        self._mchr_s = MonochromatorScanStream("Spectrum", self.mchr, self.ebeam, self.sgrh)

        # The settings to be displayed in the dialog
        # Trick: we use the same VAs as the stream, so they are directly synchronised
        self.startWavelength = self._mchr_s.startWavelength
        self.endWavelength = self._mchr_s.endWavelength
        self.numberOfPixels = self._mchr_s.numberOfPixels
        self.dwellTime = self._mchr_s.dwellTime

        self.filename = model.StringVA("a.h5")
        self.expectedDuration = model.VigilantAttribute(1, unit="s", readonly=True)

        # Update the expected duration when values change
        self.dwellTime.subscribe(self._update_exp_dur)
        self.numberOfPixels.subscribe(self._update_exp_dur)
Esempio n. 9
0
    def test_properties_set(self):
        """Test creating component with specific properties"""
        filename = "example-secom.odm.yaml"
        cmdline = "--log-level=2 --log-target=testdaemon.log --daemonize %s" % filename
        ret = subprocess.call(ODEMISD_CMD + cmdline.split())
        self.assertEqual(ret, 0, "trying to run '%s'" % cmdline)

        # eventually it should say it's running
        ret = self._wait_backend_starts(10)
        self.assertEqual(ret, 0, "backend status check returned %d" % (ret,))

        # Check that the specific properties are set
        ccd = model.getComponent(role="ccd")
        self.assertEqual(ccd.exposureTime.value, 0.3)

        ebeam = model.getComponent(role="e-beam")
        self.assertEqual(ebeam.horizontalFoV.value, 1e-6)

        # stop the backend
        cmdline = "odemisd --log-level=2 --log-target=test.log --kill"
        ret = main.main(cmdline.split())
        self.assertEqual(ret, 0, "trying to run '%s'" % cmdline)

        time.sleep(5) # give some time to stop
        ret = main.main(cmdline.split())
        os.remove("test.log")
        os.remove("testdaemon.log")
Esempio n. 10
0
    def __init__(self, fn, number):
        self.number = number

        # get the components
        self.light = model.getComponent(role="light")
        self.ccd = model.getComponent(role="ccd")

        # TODO: only support TIFF
        # prepare the data export
        self.exporter = dataio.find_fittest_converter(fn)

        # Make the name "fn" -> "~/Pictures/fn-XXXXXX.ext"
        path, base = os.path.split(fn)
        bn, ext = os.path.splitext(base)
        tmpl = os.path.join(path, bn + "-%06d" + ext)
        if path.startswith("/"):
            # if fn starts with / => don't add ~/Pictures
            self.fntmpl = tmpl
        else:
            self.fntmpl = os.path.join(get_picture_folder(), tmpl)

        self._acq_done = threading.Event()
        self._n = 0
        self._startt = 0  # starting time of acquisition

        self._q = queue.Queue()  # queue of tuples (str, DataArray) for saving data
        # TODO: find the right number of threads, based on CPU numbers (but with
        # python threading that might be a bit overkill)
        for i in range(4):
            t = threading.Thread(target=self._saving_thread, args=(i,))
            t.daemon = True
            t.start()
Esempio n. 11
0
def acquire_zstack(num, interval, filename):
    """
    Acquire a focus stack of num slices centered around current position, with
    given interval and save to file.
    """
    logging.info("Preparing to acquire z-stack of %d images with interval "
                 "%.3f µm giving total stack size of %.3f µm.",
                 num, interval, num * interval)

    # find component by their role
    ccd = model.getComponent(role="ccd")
    focus = model.getComponent(role="focus")

    origpos = focus.position.value['z']
    interval *= 1.0e-6  # convert to µm

    images = []
    try:
        for i in range(num):
            islice = i - num // 2  # Make the stack centered around the origpos
            pos = origpos + islice * interval
            logging.info("Request move to target position %.8f", pos)
            focus.moveAbs({'z': pos}).result()
            logging.info("Acquiring image %d of %d", i + 1, num)
            images.append(ccd.data.get())
    finally:
        # return to original position
        focus.moveAbs({'z': origpos})

    # save the file
    exporter = dataio.find_fittest_converter(filename)
    exporter.export(filename, images)
Esempio n. 12
0
    def setUpClass(cls):

        try:
            test.start_backend(SECOM_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

        # create some streams connected to the backend
        cls.microscope = model.getMicroscope()
        cls.ccd = model.getComponent(role="ccd")
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
        cls.light = model.getComponent(role="light")
        cls.light_filter = model.getComponent(role="filter")

        s1 = stream.FluoStream("fluo1", cls.ccd, cls.ccd.data, cls.light,
                               cls.light_filter)
        s1.excitation.value = sorted(s1.excitation.choices)[0]
        s2 = stream.FluoStream("fluo2", cls.ccd, cls.ccd.data, cls.light,
                               cls.light_filter)
        s2.excitation.value = sorted(s2.excitation.choices)[-1]
        s3 = stream.BrightfieldStream("bf", cls.ccd, cls.ccd.data, cls.light)
        cls.streams = [s1, s2, s3]
Esempio n. 13
0
    def __init__(self, microscope, main_app):
        # Called when the plugin is loaed (ie, at GUI initialisation)
        super(Correlator2D, self).__init__(microscope, main_app)
        if not microscope or microscope.role not in ("sparc", "sparc2"):
            return
        try:
            self.ebeam = model.getComponent(role="e-beam")
            self.correlator = model.getComponent(role="time-correlator")
            self.sed = model.getComponent(role="se-detector")

        except LookupError:
            logging.debug("Hardware not found, cannot use the plugin")
            return

        # the SEM survey stream (will be updated when showing the window)
        self._survey_s = None

        # Create a stream for correlator spectral measurement
        self._correlator_s = CorrelatorScanStream("Correlator data",
                                                  self.correlator, self.sed,
                                                  self.ebeam,
                                                  main_app.main_data.opm)

        # For reading the ROA and anchor ROI
        self._acqui_tab = main_app.main_data.getTabByName(
            "sparc_acqui").tab_data_model

        self.dwellTime = self._correlator_s.dwellTime
        self.pixelDuration = self._correlator_s.pixelDuration
        self.syncOffset = self._correlator_s.syncOffset
        self.syncDiv = self._correlator_s.syncDiv

        # The scanning positions are defined by ROI (as selected in the acquisition tab) + stepsize
        # Based on these values, the scanning resolution is computed
        self.roi = self._correlator_s.roi
        self.stepsize = self._correlator_s.stepsize
        self.cropvalue = self._correlator_s.cropvalue
        self.xres = model.IntVA(1, unit="px")
        self.yres = model.IntVA(1, unit="px")

        self.nDC = self._correlator_s.nDC

        self.filename = model.StringVA("a.h5")
        self.expectedDuration = model.VigilantAttribute(1,
                                                        unit="s",
                                                        readonly=True)

        # Update the expected duration when values change, depends both dwell time and # of pixels
        self.dwellTime.subscribe(self._update_exp_dur)
        self.stepsize.subscribe(self._update_exp_dur)
        self.nDC.subscribe(self._update_exp_dur)

        # subscribe to update X/Y res
        self.stepsize.subscribe(self._update_res)
        self.roi.subscribe(self._update_res)

        self.addMenu("Acquisition/CL time correlator scan...", self.start)
def main(args):
    """
    Handles the command line arguments.

    Parameters
    ----------
    args: The list of arguments passed.

    Returns
    -------
    (int)
        value to return to the OS as program exit code.
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('--debug', action="store_true", default=False)
    parser.add_argument("--role", dest="role", default="diagnostic-ccd",
                        metavar="<component>",
                        help="Role of the camera to connect to via the Odemis "
                             "back-end. Ex: 'ccd'.")
    parser.add_argument("--channel", dest="channel", default=1,
                        metavar="<component>",
                        help="Number of the AWG output channel.")
    parser.add_argument("--auto", dest="auto", default=True,
                        metavar="<component>",
                        help="If True automatically align the ebeam scan to"
                             "multiprobe. To do this a server must be running "
                             "on the microscope PC.")

    options = parser.parse_args(args[1:])
    if options.debug:
        logging.getLogger().setLevel(logging.DEBUG)
    else:
        logging.getLogger().setLevel(logging.WARNING)

    if get_backend_status() != BACKEND_RUNNING:
        raise ValueError("Backend is not running.")

    ccd = model.getComponent(role=options.role)
    try:
        sem_rotation = get_sem_rotation(ccd, auto=options.auto,
                                        channel=options.channel)
        if options.auto:
            scanner = model.getComponent(role="ebeam-control")
            val = scanner.rotation.value
            scanner.rotation.value = val + sem_rotation
            print("Added {:.2f}° to the scan rotation using SEM PC."
                  "Rotation is now set to: {:.2f}°".format(
                math.degrees(sem_rotation),
                math.degrees(scanner.rotation.value)))
        else:
            print("Add {:.2f}° to the scan rotation using SEM PC. If negative"
                  "subtract this value from the scan rotation.".format(
                math.degrees(sem_rotation)))
    except Exception as exp:
        logging.error("%s", exp, exc_info=True)
        return 128
    return 0
Esempio n. 15
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
    """
    parser = argparse.ArgumentParser(
        description="Record a series of image brightness "
        "for different angles of a given polarizer.")
    parser.add_argument("--polarizer",
                        "-p",
                        dest="polarizer",
                        required=True,
                        choices=("linear", "qwp"),
                        help="Actuator to use")
    parser.add_argument("--output",
                        "-o",
                        dest="filename",
                        required=True,
                        help="Output filename (in tab-separate values)")

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

    try:
        if "." not in options.filename[-5:]:
            raise ValueError("Output argument must contain extension, "
                             "but got '%s'" % (options.filename, ))

        if options.polarizer == "linear":
            role = "lin-pol"
        else:  # qwp
            # Search for qwp = 0 by optimizing RHC
            role = "quarter-wave-plate"
            logging.info("Moving the linear polarizer to positive diagonal")
            linpol = model.getComponent(role="lin-pol")
            linpol.moveAbsSync({"rz": math.radians(45)})

        polarizer = model.getComponent(role=role)
        # 180° (every 2°) + 25% to check it's indeed repeating
        angles = numpy.arange(0, math.pi * 1.25, math.radians(2))
        brightness = acquire_angles(polarizer, angles)
        logging.debug("Acquired brightness: %s", brightness)

        # Stores the file
        with open(options.filename, "w+") as f:
            for a, b in zip(angles, brightness):
                f.write("%f\t%f\n" % (a, b))

        # Show on a graph
        plt.plot(angles, brightness)
        plt.show()
    except Exception:
        logging.exception("Unexpected error while performing action.")
        return 129

    return 0
Esempio n. 16
0
    def setUpClass(cls):
        if TEST_NOHW:
            raise unittest.SkipTest('No HW present. Skipping tests.')

        test.start_backend(CLSPOTS_CONFIG)

        # find components by their role
        cls.diagnostic_cam = model.getComponent(role="diagnostic-ccd")
        cls.stage = model.getComponent(role="stage")
        cls._optimal_focus = 40e-6  # update with actual value
Esempio n. 17
0
    def setUpClass(cls):
        try:
            import fastem_calibrations
        except ImportError as err:
            raise unittest.SkipTest(
                f"Skipping the fastem tests, correct libraries "
                f"to perform the tests are not available.\n"
                f"Got the error: {err}")

        if TEST_NOHW:
            test.start_backend(FASTEM_CONFIG)
        elif driver.get_backend_status() != driver.BACKEND_RUNNING:
            raise IOError(
                "Backend controlling a real hardware should be started before running this test case"
            )

        # get the hardware components
        cls.scanner = model.getComponent(role='e-beam')
        cls.asm = model.getComponent(role="asm")
        cls.mppc = model.getComponent(role="mppc")
        cls.multibeam = model.getComponent(role="multibeam")
        cls.descanner = model.getComponent(role="descanner")
        cls.stage = model.getComponent(
            role="stage"
        )  # TODO replace with stage-scan when ROA conversion method available
        cls.ccd = model.getComponent(role="diagnostic-ccd")
        cls.beamshift = model.getComponent(role="ebeam-shift")
        cls.det_rotator = model.getComponent(role="det-rotator")
Esempio n. 18
0
    def setUpClass(cls):
        if TEST_NOHW:
            test.start_backend(FASTEM_CONFIG)
        elif driver.get_backend_status() != driver.BACKEND_RUNNING:
            raise IOError("Backend controlling a real hardware should be started before running this test case")

        cls.ebeam = model.getComponent(role="e-beam")
        cls.efocuser = model.getComponent(role="ebeam-focus")
        cls.sed = model.getComponent(role="se-detector")
        cls.stage = model.getComponent(role="stage")
        cls.stage.reference({"x", "y"}).result()
Esempio n. 19
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
    """
    parser = argparse.ArgumentParser(description="Measure the needed SEM calibration")

    parser.add_argument("--move", dest="move", action='store_true',
                        help="First to move to the standard location for Delphi calibration on the sample")
    parser.add_argument("--autofocus", "-f", dest="focus", action='store_true',
                        help="Auto focus the SEM image before calibrating")
    options = parser.parse_args(args[1:])

    try:
        escan = model.getComponent(role="e-beam")
        bsd = model.getComponent(role="bs-detector")

        # This moves the SEM stage precisely on the hole, as the calibration does it
        if options.move:
            semstage = model.getComponent(role="sem-stage")
            semstage.moveAbs(delphi.SHIFT_DETECTION).result()

        if options.focus:
            efocus = model.getComponent(role="ebeam-focus")
            efocus.moveAbs({"z": delphi.SEM_KNOWN_FOCUS}).result()
            f = autofocus.AutoFocus(bsd, escan, efocus)
            focus, fm_level = f.result()
            print("SEM focused @ %g m" % (focus,))

        logging.debug("Starting Phenom SEM calibration...")

        blank_md = dict.fromkeys(delphi.MD_CALIB_SEM, (0, 0))
        escan.updateMetadata(blank_md)

        # Compute spot shift percentage
        f = delphi.ScaleShiftFactor(bsd, escan, logpath="./")
        spot_shift = f.result()
        print("Spot shift = %s" % (spot_shift,))

        # Compute HFW-related values
        f = delphi.HFWShiftFactor(bsd, escan, logpath="./")
        hfw_shift = f.result()
        print("HFW shift = %s" % (hfw_shift,))

        # Compute resolution-related values
        f = delphi.ResolutionShiftFactor(bsd, escan, logpath="./")
        res_sa, res_sb = f.result()
        print("res A = %s, res B = %s" % (res_sa, res_sb))
    except Exception:
        logging.exception("Unexpected error while performing action.")
        return 127

    return 0
Esempio n. 20
0
def acquire_volts(volts, detector):
    """
    vots (list of floats > 0): voltage in kV
    detector (str): role of the spectrometer to use
    returns (list of DataArray): all the spectra, in order
    """
    ebeam = model.getComponent(role="e-beam")
    sed = model.getComponent(role="se-detector")
    spmt = model.getComponent(role=detector)
    hw_settings = save_hw_settings(ebeam)

    # Go to spot mode (ie, res = 1x1)
    if ebeam.resolution.value != (1, 1):
        ebeam.resolution.value = (1, 1)
        ebeam.translation.value = (0, 0)  # at the center of the FoV
    else:
        logging.info("Leaving the e-beam in spot mode at %s",
                     ebeam.translation.value)

    ebeam.dwellTime.value = 0.1

    try:
        # Activate the e-beam
        sed.data.subscribe(discard_data)

        das = []
        for vstr in volts:
            v = float(vstr) * 1000
            ebeam.accelVoltage.value = v
            if not util.almost_equal(ebeam.accelVoltage.value, v):
                logging.warning(
                    "Voltage requested at %g kV, but e-beam set at %g kV",
                    v / 1000, ebeam.accelVoltage.value / 1000)
            else:
                logging.info("Acquiring at %g kV", v / 1000)

            # Acquire one spectrum
            spec = spmt.data.get()
            # Add dimensions to make it a spectrum (X, first dim -> C, 5th dim)
            spec.shape = (spec.shape[-1], 1, 1, 1, 1)

            # Add some useful metadata
            spec.metadata[model.MD_DESCRIPTION] = "Spectrum at %g kV" % (v /
                                                                         1000)
            spec.metadata[model.MD_EBEAM_VOLTAGE] = v
            # TODO: store the spot position in MD_POS
            das.append(spec)

    finally:
        sed.data.unsubscribe(discard_data)  # Just to be sure
        resume_hw_settings(ebeam, hw_settings)

    return das
Esempio n. 21
0
    def __init__(self, dt, roi, pxs, subpx=1, lpower=0.2):
        """
        pxs (0<float): distance in m between center of each tile 
        subpx (1<=int): number of sub-pixels
        """
        if subpx < 1 or (math.sqrt(subpx) % 1) != 0:
            raise ValueError("subpx must be square of an integer")

        self.dt = dt
        self.roi = roi
        subpx_x = math.trunc(math.sqrt(subpx))
        self.pxs = pxs
        self.subpxs = pxs / subpx_x
        logging.info("Sub-pixels will be spaced by %f nm", self.subpxs * 1e9)
        self.tile_shape = (subpx_x, subpx_x
                           )  # for now always the same in x and y
        self.lpower = lpower

        # Get the components we need
        self.sed = model.getComponent(role="se-detector")
        self.ebeam = model.getComponent(role="e-beam")
        self.light = model.getComponent(role="light")
        self.ccd = model.getComponent(role="ccd")
        self.stage = model.getComponent(role="stage")

        # Find the index with maximum power to use to set lpower
        self.max_power_index = list(self.light.power.range[1]).index(
            max(self.light.power.range[1]))
        lprng = self.light.power.range
        if not (lprng[0][self.max_power_index] < lpower <
                lprng[1][self.max_power_index]):
            raise ValueError("starting light power value must be between %s" %
                             (lprng, ))

        # counter-intuitively, to get the smaller pixel size, no sub-pixel
        # should be used. That's because when there is no sub-pixel we can use
        # spot mode, which allows to go at less than scale=1.
        # It could easily be fixed by allowsing scale down to 0.1 in the driver.

        if (self.ebeam.pixelSize.value[0] > 10 * pxs
                or self.ebeam.pixelSize.value[0] > self.subpxs):
            raise ValueError("Pixel size requested (%g nm/%g nm) is too small "
                             "compared to recommended SEM pixel size (%g nm)" %
                             (pxs * 1e9, self.subpxs * 1e9,
                              self.ebeam.pixelSize.value[0] * 1e9))

        elif self.ebeam.pixelSize.value[0] > pxs:
            logging.warning(
                "Pixel size requested (%g nm) is smaller than "
                "recommended SEM pixel size (%g nm) at the current "
                "mag.", pxs * 1e9, self.ebeam.pixelSize.value[0] * 1e9)

        self._hw_settings = ()  # will be used to save/resume SEM settings
Esempio n. 22
0
    def __init__(self, microscope, main_app):
        super(RGBCLIntensity, self).__init__(microscope, main_app)

        # Can only be used on a SPARC with a CL-intensity detector
        if not microscope:
            return
        try:
            self.ebeam = model.getComponent(role="e-beam")
            self.cldetector = model.getComponent(role="cl-detector")
            self.filterwheel = model.getComponent(role="cl-filter")
            self.sed = model.getComponent(role="se-detector")
            # We could also check the filter wheel has at least 3 filters, but
            # let's not be too picky, if the user has installed the plugin, he
            # probably wants to use it anyway.
        except LookupError:
            logging.info("Hardware not found, cannot use the RGB CL plugin")
            return

        # The SEM survey and CLi stream (will be updated when showing the window)
        self._survey_s = None
        self._cl_int_s = None
        self._acqui_tab = main_app.main_data.getTabByName(
            "sparc_acqui").tab_data_model

        # The settings to be displayed in the dialog
        # TODO: pick better default filters than first 3 filters
        # => based on the wavelengths fitting best RGB, or the names (eg, "Blue"),
        # and avoid "pass-through".
        fbchoices = self.filterwheel.axes["band"].choices
        if isinstance(fbchoices, dict):
            fbvalues = sorted(fbchoices.keys())
        else:
            fbvalues = fbchoices
        # FloatEnumerated because filter positions can be in rad (ie, not int positions)
        self.filter1 = model.FloatEnumerated(fbvalues[0], choices=fbchoices)
        self.filter2 = model.FloatEnumerated(fbvalues[min(
            1,
            len(fbvalues) - 1)],
                                             choices=fbchoices)
        self.filter3 = model.FloatEnumerated(fbvalues[min(
            2,
            len(fbvalues) - 1)],
                                             choices=fbchoices)

        self._filters = [self.filter1, self.filter2, self.filter3]
        self._colours = [(0, 0, 255), (0, 255, 0), (255, 0, 0)]  # B, G, R

        self.filename = model.StringVA("a.tiff")
        self.expectedDuration = model.VigilantAttribute(1,
                                                        unit="s",
                                                        readonly=True)

        self.addMenu("Acquisition/RGB CL intensity...", self.start)
Esempio n. 23
0
    def __init__(self, microscope, main_app):
        # Called when the plugin is loaed (ie, at GUI initialisation)
        super(Correlator2D, self).__init__(microscope, main_app)
        if not microscope or microscope.role not in ("sparc", "sparc2"):
            return
        try:
            self.ebeam = model.getComponent(role="e-beam")
            self.correlator = model.getComponent(role="time-correlator")
            self.sed = model.getComponent(role="se-detector")

        except LookupError:
            logging.debug("Hardware not found, cannot use the plugin")
            return

        # the SEM survey stream (will be updated when showing the window)
        self._survey_s = None

        # Create a stream for correlator spectral measurement
        self._correlator_s = CorrelatorScanStream("Correlator data", self.correlator, self.sed, self.ebeam,
                                                  main_app.main_data.opm)

        # For reading the ROA and anchor ROI
        self._acqui_tab = main_app.main_data.getTabByName("sparc_acqui").tab_data_model

        self.dwellTime = self._correlator_s.dwellTime
        self.pixelDuration = self._correlator_s.pixelDuration
        self.syncOffset = self._correlator_s.syncOffset
        self.syncDiv = self._correlator_s.syncDiv

        # The scanning positions are defined by ROI (as selected in the acquisition tab) + stepsize
        # Based on these values, the scanning resolution is computed
        self.roi = self._correlator_s.roi
        self.stepsize = self._correlator_s.stepsize
        self.cropvalue = self._correlator_s.cropvalue
        self.xres = model.IntVA(1, unit="px")
        self.yres = model.IntVA(1, unit="px")

        self.nDC = self._correlator_s.nDC

        self.filename = model.StringVA("a.h5")
        self.expectedDuration = model.VigilantAttribute(1, unit="s", readonly=True)

        # Update the expected duration when values change, depends both dwell time and # of pixels
        self.dwellTime.subscribe(self._update_exp_dur)
        self.stepsize.subscribe(self._update_exp_dur)
        self.nDC.subscribe(self._update_exp_dur)

        # subscribe to update X/Y res
        self.stepsize.subscribe(self._update_res)
        self.roi.subscribe(self._update_res)

        self.addMenu("Acquisition/CL time correlator scan...", self.start)
Esempio n. 24
0
    def setUpClass(cls):
        if TEST_NOHW:
            test.start_backend(FASTEM_CONFIG_ASM)
        elif driver.get_backend_status() != driver.BACKEND_RUNNING:
            raise IOError("Backend controlling a real hardware should be started before running this test case")

        # get the hardware components
        cls.asm = model.getComponent(role="asm")
        cls.mppc = model.getComponent(role="mppc")
        cls.multibeam = model.getComponent(role="multibeam")
        cls.descanner = model.getComponent(role="descanner")
        cls.stage = model.getComponent(
            role="stage")  # TODO replace with stage-scan when ROA conversion method available
        cls.stage.reference({"x", "y"}).result()
Esempio n. 25
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")
        cls.stage = model.getComponent(role="stage")

        # Used for OBJECTIVE_MOVE type
        cls.aligner_xy = ConvertStage("converter-ab", "stage",
                                      children={"orig": cls.align},
                                      axes=["b", "a"],
                                      rotation=math.radians(45))
Esempio n. 26
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")
        cls.stage = model.getComponent(role="stage")

        # Used for OBJECTIVE_MOVE type
        cls.aligner_xy = ConvertStage("converter-ab", "stage",
                                      children={"orig": cls.align},
                                      axes=["b", "a"],
                                      rotation=math.radians(45))
Esempio n. 27
0
def acquire_volts(volts, detector):
    """
    vots (list of floats > 0): voltage in kV
    detector (str): role of the spectrometer to use
    returns (list of DataArray): all the spectra, in order
    """
    ebeam = model.getComponent(role="e-beam")
    sed = model.getComponent(role="se-detector")
    spmt = model.getComponent(role=detector)
    hw_settings = save_hw_settings(ebeam)

    # Go to spot mode (ie, res = 1x1)
    if ebeam.resolution.value != (1, 1):
        ebeam.resolution.value = (1, 1)
        ebeam.translation.value = (0, 0) # at the center of the FoV
    else:
        logging.info("Leaving the e-beam in spot mode at %s", ebeam.translation.value)

    ebeam.dwellTime.value = 0.1

    try:
        # Activate the e-beam
        sed.data.subscribe(discard_data)

        das = []
        for vstr in volts:
            v = float(vstr) * 1000
            ebeam.accelVoltage.value = v
            if not util.almost_equal(ebeam.accelVoltage.value, v):
                logging.warning("Voltage requested at %g kV, but e-beam set at %g kV",
                                v / 1000, ebeam.accelVoltage.value / 1000)
            else:
                logging.info("Acquiring at %g kV", v / 1000)

            # Acquire one spectrum
            spec = spmt.data.get()
            # Add dimensions to make it a spectrum (X, first dim -> C, 5th dim)
            spec.shape = (spec.shape[-1], 1, 1, 1, 1)

            # Add some useful metadata
            spec.metadata[model.MD_DESCRIPTION] = "Spectrum at %g kV" % (v / 1000)
            spec.metadata[model.MD_EBEAM_VOLTAGE] = v
            # TODO: store the spot position in MD_POS
            das.append(spec)

    finally:
        sed.data.unsubscribe(discard_data)  # Just to be sure
        resume_hw_settings(ebeam, hw_settings)

    return das
Esempio n. 28
0
    def setUpClass(cls):
        if TEST_NOHW is True:
            raise unittest.SkipTest(
                "No simulator running or HW present. Skip fastem ROA tests.")

        # get the hardware components
        cls.microscope = model.getMicroscope()
        cls.asm = model.getComponent(role="asm")
        cls.mppc = model.getComponent(role="mppc")
        cls.multibeam = model.getComponent(role="multibeam")
        cls.descanner = model.getComponent(role="descanner")
        cls.stage = model.getComponent(
            role="stage"
        )  # TODO replace with stage-scan when ROA conversion method available
        cls.stage.reference({"x", "y"}).result()
Esempio n. 29
0
    def __init__(self):
        # find components by their role
        # the ebeam scanner
        self.escan = model.getComponent(role="e-beam")
        # the secondary electron detector
        self.sed = model.getComponent(role="se-detector")
        # the spectrometer
        self.spect = model.getComponent(role="spectrometer")
        
        # For acquisition
        self.spec_data = None
        self.acq_done = threading.Event()

        # For drift correction
        self.drift = (0, 0)
    def setUpClass(cls):
        try:
            test.start_backend(CLSPOTS_SIM_CONFIG)
        except LookupError:
            logging.debug("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.diagnostic_cam = model.getComponent(role="diagnostic-ccd")
        cls.stage = model.getComponent(role="stage")
        cls.ofocus = model.getComponent(role="diagnostic-cam-focus")
Esempio n. 31
0
    def __init__(self):
        # find components by their role
        # the ebeam scanner
        self.escan = model.getComponent(role="e-beam")
        # the secondary electron detector
        self.sed = model.getComponent(role="se-detector")
        # the spectrometer
        self.spect = model.getComponent(role="spectrometer")

        # For acquisition
        self.spec_data = None
        self.acq_done = threading.Event()

        # For drift correction
        self.drift = (0, 0)
    def setUpClass(cls):
        try:
            test.start_backend(CLSPOTS_SIM_CONFIG)
        except LookupError:
            logging.debug("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.diagnostic_cam = model.getComponent(role="diagnostic-ccd")
        cls.stage = model.getComponent(role="stage")
        cls.ofocus = model.getComponent(role="diagnostic-cam-focus")
Esempio n. 33
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
    """
    parser = argparse.ArgumentParser(description="Record a series of image brightness "
                                     "for different angles of a given polarizer.")
    parser.add_argument("--polarizer", "-p", dest="polarizer", required=True,
                        choices=("linear", "qwp"), help="Actuator to use")
    parser.add_argument("--output", "-o", dest="filename", required=True,
                        help="Output filename (in tab-separate values)")

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

    try:
        if "." not in options.filename[-5:]:
            raise ValueError("Output argument must contain extension, "
                             "but got '%s'" % (options.filename,))

        if options.polarizer == "linear":
            role = "lin-pol"
        else: # qwp
            # Search for qwp = 0 by optimizing RHC
            role = "quarter-wave-plate"
            logging.info("Moving the linear polarizer to positive diagonal")
            linpol = model.getComponent(role="lin-pol")
            linpol.moveAbsSync({"rz": math.radians(45)})

        polarizer = model.getComponent(role=role)
        # 180° (every 2°) + 25% to check it's indeed repeating
        angles = numpy.arange(0, math.pi * 1.25, math.radians(2))
        brightness = acquire_angles(polarizer, angles)
        logging.debug("Acquired brightness: %s", brightness)
        
        # Stores the file
        with open(options.filename, "w+") as f:
            for a, b in zip(angles, brightness):
                f.write("%f\t%f\n" % (a, b))

        # Show on a graph
        plt.plot(angles, brightness)
        plt.show()
    except Exception:
        logging.exception("Unexpected error while performing action.")
        return 129

    return 0
Esempio n. 34
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
    """
    global n
    ccd = model.getComponent(role="ccd")


    # TODO: decrease exposure time until it seems to not follow?
    # How to detects drops?
    fps_goal = 10000 # Hz
    ccd.exposureTime.value = 1 / fps_goal # s

    prev_n = n
    ccd.data.subscribe(_on_image)
    try:
        for i in range(100):
            time.sleep(1)
            newn = n
            fps = newn - prev_n
            prev_n = newn
            print("%d fps" % fps)
    except KeyboardInterrupt:
        pass
    except Exception:
        logging.exception("Failed to estimate FPS due to error")
    finally:
        ccd.data.unsubscribe(_on_image)

    return 0
Esempio n. 35
0
    def setUpClass(cls):
        if driver.get_backend_status() in driver.BACKEND_RUNNING:
            microscope = model.getMicroscope()
            if microscope.role != "meteor":
                logging.info(
                    "There is already running backend. It will be turned off, and the backend of METEOR will be turned on."
                )
                test.stop_backend()
                test.start_backend(METEOR_CONFIG)
            else:
                logging.info(
                    "There is METEOR backend already running. It will be used."
                )
        else:
            try:
                logging.info("METEOR backend will be turned on.")
                test.start_backend(METEOR_CONFIG)
            except Exception:
                raise

        # get the stage components
        cls.stage = model.getComponent(role="stage-bare")

        # get the metadata
        stage_md = cls.stage.getMetadata()
        cls.stage_grid_centers = stage_md[model.MD_SAMPLE_CENTERS]
        cls.stage_loading = stage_md[model.MD_FAV_POS_DEACTIVE]
Esempio n. 36
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
    """
    ebeam = model.getComponent(role="e-beam")
    while ebeam.resolution.value != (1, 1):
        raw_input("Please select spot mode and pick a point and press Enter...")

    wls = getNumber("Starting wavelength (in nm): ") * 1e-9
    wle = getNumber("Ending wavelength (in nm): ") * 1e-9
    nbp = getNumber("Number of wavelengths to acquire: ")
    dt = getNumber("Dwell time (in ms): ") * 1e-3
    exp_time = nbp * (dt + 0.05)  # 50 ms to change wavelength
    print("Expected duration: %s" % (units.readable_time(math.ceil(exp_time)),))

    filename = raw_input("Filename to store the spectrum: ")
    if "." not in filename:
        # No extension -> force hdf5
        filename += ".h5"

    print("Press Ctrl+C to cancel the acquisition")

    try:
        acquire_spec(wls, wle, int(nbp), dt, filename)
    except Exception:
        logging.exception("Unexpected error while performing action.")
        return 127

    return 0
Esempio n. 37
0
    def setUpClass(cls):
        try:
            test.start_backend(DELPHI_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.stage = model.getComponent(role="stage")
        cls.sem_stage = model.getComponent(role="sem-stage")
        cls.align = model.getComponent(role="align")
        cls.tmcm = model.getComponent(name="Sample Holder Actuators")  # low level actuator
Esempio n. 38
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()
    parser.add_argument("--role", dest="role", metavar="<component>",
                        help="display and update an image on the screen")
    parser.add_argument("--gridsize", dest="gridsize", nargs=2, metavar="<gridsize>", type=int, default=None,
                        help="size of the grid of spots in x y, default 14 14")
    parser.add_argument("--log-level", dest="loglev", metavar="<level>", type=int, choices=[0, 1, 2],
                        default=0, help="set verbosity level (0-2, default = 0)")
    options = parser.parse_args(args[1:])
    # Set up logging before everything else
    loglev_names = [logging.WARNING, logging.INFO, logging.DEBUG]
    loglev = loglev_names[min(len(loglev_names) - 1, options.loglev)]

    # change the log format to be more descriptive
    handler = logging.StreamHandler()
    logging.getLogger().setLevel(loglev)
    handler.setFormatter(logging.Formatter('%(asctime)s (%(module)s) %(levelname)s: %(message)s'))
    logging.getLogger().addHandler(handler)

    if options.role:
        if get_backend_status() != BACKEND_RUNNING:
            raise ValueError("Backend is not running while role command is specified.")
        ccd = model.getComponent(role=options.role)
        live_display(ccd, ccd.data, kill_ccd=False, gridsize=options.gridsize)
    else:
        ccd = ueye.Camera("camera", "ccd", device=None)
        ccd.SetFrameRate(2)
        live_display(ccd, ccd.data, gridsize=options.gridsize)
    return 0
Esempio n. 39
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
    """
    ebeam = model.getComponent(role="e-beam")
    while ebeam.resolution.value != (1, 1):
        input("Please select spot mode and pick a point and press Enter...")

    wls = getNumber("Starting wavelength (in nm): ") * 1e-9
    wle = getNumber("Ending wavelength (in nm): ") * 1e-9
    nbp = getNumber("Number of wavelengths to acquire: ")
    dt = getNumber("Dwell time (in ms): ") * 1e-3
    exp_time = nbp * (dt + 0.05)  # 50 ms to change wavelength
    print("Expected duration: %s" %
          (units.readable_time(math.ceil(exp_time)), ))

    filename = input("Filename to store the spectrum: ")
    if "." not in filename:
        # No extension -> force hdf5
        filename += ".h5"

    print("Press Ctrl+C to cancel the acquisition")

    try:
        acquire_spec(wls, wle, int(nbp), dt, filename)
    except Exception:
        logging.exception("Unexpected error while performing action.")
        return 127

    return 0
Esempio n. 40
0
def acquire_timelapse(num, period, filename):

    # find components by their role
#    ebeam = model.getComponent(role="ebeam")
    sed = model.getComponent(role="se-detector")

    images = []
    try:
        for i in range(num):
            logging.info("Acquiring image %d/%d", i + 1, num)
            start = time.time()
            images.append(sed.data.get())
            left = period - (time.time() - start)
            if left < 0:
                logging.warning("Acquisition took longer than the period (%g s overdue)", -left)
            else:
                logging.info("Sleeping for another %g s", left)
                time.sleep(left)
    except KeyboardInterrupt:
        logging.info("Closing after only %d images acquired", i + 1)
    except Exception:
        logging.exception("Failed to acquire all the images, will try to save anyway")
    
    # save the file
    exporter = dataio.find_fittest_exporter(filename)
    exporter.export(filename, images)
Esempio n. 41
0
def acquire_angles(polarizer, angles):
    """
    Acquire an image from "ccd" for the given polarizer for each angle
    returns (list of float): the average brightness for each of these angles. 
    """
    logging.info("Preparing to acquire brightness of %d angles on %s",
                 len(angles), polarizer.name)

    # find component by their role
    ccd = model.getComponent(role="ccd")

    origpos = polarizer.position.value['rz']

    brightness = []
    i = 0
    try:
        for a in angles:
            i += 1
            logging.info("Request move to target position %.8f rad (%d/%d)",
                         a, i, len(angles))
            polarizer.moveAbs({'rz': a % (2 * math.pi)}).result()
            brightness.append(numpy.average(ccd.data.get()))
    finally:
        # return to original position
        polarizer.moveAbs({"rz": origpos})

    return brightness
Esempio n. 42
0
def acquire_angles(polarizer, angles):
    """
    Acquire an image from "ccd" for the given polarizer for each angle
    returns (list of float): the average brightness for each of these angles. 
    """
    logging.info("Preparing to acquire brightness of %d angles on %s",
                 len(angles), polarizer.name)

    # find component by their role
    ccd = model.getComponent(role="ccd")

    origpos = polarizer.position.value['rz']

    brightness = []
    i = 0
    try:
        for a in angles:
            i += 1
            logging.info("Request move to target position %.8f rad (%d/%d)",
                         a, i, len(angles))
            polarizer.moveAbs({'rz': a % (2 * math.pi)}).result()
            brightness.append(numpy.average(ccd.data.get()))
    finally:
        # return to original position
        polarizer.moveAbs({"rz": origpos})

    return brightness
Esempio n. 43
0
def acquire(det, fn_beg):
    scanner = model.getComponent(role="laser-mirror")

    min_dt = scanner.dwellTime.range[0]

    for zoom in (1, 50, 1.1, 1.25, 1.5, 1.75, 2, 4, 8, 16, 20, 30):
        for kdt in (1, 2, 4, 8, 12, 16, 24, 32, 40, 64, 80):
            dt = min_dt * kdt
            if dt > scanner.dwellTime.range[1]:
                continue
            det.gain.value = int(GAIN_INIT - math.log(kdt, 2) * GAIN_DECREASE)
            logging.info("Gain is now %g", det.gain.value)
            for xres in (64, 128, 256, 512, 1024, 2048):
                #for yres in (64, 128, 256, 512, 1024, 2048):
                yres = xres  # only square images
                fn = "%s_z%g_d%g_r%dx%d.tiff" % (fn_beg, zoom, dt * 1e6, xres,
                                                 yres)
                logging.info("Acquiring %s", fn)
                im = acquire_settings(scanner, det, (xres, yres), zoom, dt)
                if im is not None:
                    tiff.export(fn, im)

    # Acquire at the end another time the first image, to check the drift
    zoom = 1
    dt = min_dt
    xres = yres = 2048
    im = acquire_settings(scanner, det, (xres, yres), zoom, dt)
    fn = "%s_z%g_d%g_r%dx%d_after.tiff" % (fn_beg, zoom, dt * 1e6, xres, yres)
    tiff.export(fn, im)
Esempio n. 44
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
    """
    global n
    ccd = model.getComponent(role="ccd")

    # TODO: decrease exposure time until it seems to not follow?
    # How to detects drops?
    fps_goal = 10000  # Hz
    ccd.exposureTime.value = 1 / fps_goal  # s

    prev_n = n
    ccd.data.subscribe(_on_image)
    try:
        for i in range(100):
            time.sleep(1)
            newn = n
            fps = newn - prev_n
            prev_n = newn
            print "%d fps" % fps
    except KeyboardInterrupt:
        pass
    except Exception:
        logging.exception("Failed to estimate FPS due to error")
    finally:
        ccd.data.unsubscribe(_on_image)

    return 0
Esempio n. 45
0
    def __init__(self, dt, roi, pxs, subpx=1, lpower=0.2):
        """
        pxs (0<float): distance in m between center of each tile 
        subpx (1<=int): number of sub-pixels
        """
        if subpx < 1 or (math.sqrt(subpx) % 1) != 0:
            raise ValueError("subpx must be square of an integer")
        
        self.dt = dt
        self.roi = roi
        subpx_x = math.trunc(math.sqrt(subpx))
        self.pxs = pxs
        self.subpxs = pxs / subpx_x
        logging.info("Sub-pixels will be spaced by %f nm", self.subpxs * 1e9)
        self.tile_shape = (subpx_x, subpx_x) # for now always the same in x and y
        self.lpower = lpower

        # Get the components we need
        self.sed = model.getComponent(role="se-detector")
        self.ebeam = model.getComponent(role="e-beam")
        self.light = model.getComponent(role="light")
        self.ccd = model.getComponent(role="ccd")
        self.stage = model.getComponent(role="stage")
        
        lprng = self.light.power.range
        if not (lprng[0] < lpower < lprng[1]):
            raise ValueError("starting light power value must be between %s", lprng)

        # counter-intuitively, to get the smaller pixel size, no sub-pixel
        # should be used. That's because when there is no sub-pixel we can use
        # spot mode, which allows to go at less than scale=1.
        # It could easily be fixed by allowsing scale down to 0.1 in the driver.

        if (self.ebeam.pixelSize.value[0] > 10 * pxs or
            self.ebeam.pixelSize.value[0] > self.subpxs):
            raise ValueError("Pixel size requested (%g nm/%g nm) is too small "
                             "compared to recommended SEM pixel size (%g nm)"
                             % (pxs * 1e9, self.subpxs * 1e9,
                                self.ebeam.pixelSize.value[0] * 1e9))
            
        elif self.ebeam.pixelSize.value[0] > pxs:
            logging.warning("Pixel size requested (%g nm) is smaller than "
                            "recommended SEM pixel size (%g nm) at the current "
                            "mag.", 
                            pxs * 1e9, self.ebeam.pixelSize.value[0] * 1e9)

        self._hw_settings = () # will be used to save/resume SEM settings
Esempio n. 46
0
    def __init__(self, microscope, main_app):
        super(RGBCLIntensity, self).__init__(microscope, main_app)

        # Can only be used on a SPARC with a CL-intensity detector
        if not microscope:
            return
        try:
            self.ebeam = model.getComponent(role="e-beam")
            self.cldetector = model.getComponent(role="cl-detector")
            self.filterwheel = model.getComponent(role="cl-filter")
            self.sed = model.getComponent(role="se-detector")
            # We could also check the filter wheel has at least 3 filters, but
            # let's not be too picky, if the user has installed the plugin, he
            # probably wants to use it anyway.
        except LookupError:
            logging.info("Hardware not found, cannot use the RGB CL plugin")
            return

        # The SEM survey and CLi stream (will be updated when showing the window)
        self._survey_s = None
        self._cl_int_s = None
        self._acqui_tab = main_app.main_data.getTabByName("sparc_acqui").tab_data_model

        # The settings to be displayed in the dialog
        # TODO: pick better default filters than first 3 filters
        # => based on the wavelengths fitting best RGB, or the names (eg, "Blue"),
        # and avoid "pass-through".
        fbchoices = self.filterwheel.axes["band"].choices
        if isinstance(fbchoices, dict):
            fbvalues = sorted(fbchoices.keys())
        else:
            fbvalues = fbchoices
        # FloatEnumerated because filter positions can be in rad (ie, not int positions)
        self.filter1 = model.FloatEnumerated(fbvalues[0],
                                             choices=fbchoices)
        self.filter2 = model.FloatEnumerated(fbvalues[min(1, len(fbvalues) - 1)],
                                             choices=fbchoices)
        self.filter3 = model.FloatEnumerated(fbvalues[min(2, len(fbvalues) - 1)],
                                             choices=fbchoices)

        self._filters = [self.filter1, self.filter2, self.filter3]
        self._colours = [(0, 0, 255), (0, 255, 0), (255, 0, 0)]  # B, G, R

        self.filename = model.StringVA("a.tiff")
        self.expectedDuration = model.VigilantAttribute(1, unit="s", readonly=True)

        self.addMenu("Acquisition/RGB CL intensity...", self.start)
Esempio n. 47
0
    def setUpClass(cls):
        try:
            test.start_backend(SPARC2_FOCUS_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.ccd = model.getComponent(role="ccd")
        cls.spectrometer = model.getComponent(role="spectrometer-integrated")

        cls.focus = model.getComponent(role="focus")
        cls._good_focus = cls.focus.position.value["z"]
Esempio n. 48
0
    def setUpClass(cls):

        try:
            test.start_backend(SECOM_FLIM_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 confocal (light + laser-mirror) and FLIM (time-correlator) components
        cls.sft = model.getComponent(role="time-correlator")
        cls.tc_scanner = model.getComponent(role="tc-scanner")
        cls.ex_light = model.getComponent(role="light")
        cls.lscanner = model.getComponent(role="laser-mirror")
        cls.apd = model.getComponent(role="tc-detector")
        cls.tcdl = model.getComponent(role="tc-detector-live")
        cls.detector = model.getComponent(role="photo-detector0")

        cls.ex_light.period.value = 0.0001
        em = [0] * len(cls.ex_light.emissions.value)
        cls.ex_light.emissions.value = em
        cls.ex_light.power.value = 0.25
Esempio n. 49
0
    def setUpClass(cls):

        try:
            test.start_backend(SPARC2_FOCUS_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.ccd = model.getComponent(role="ccd")
        cls.spccd = model.getComponent(role="sp-ccd")
        cls.focus = model.getComponent(role="focus")
        cls.bl = model.getComponent(role="brightlight")
        cls.spgr = model.getComponent(role="spectrograph")
        cls.spgr_ded = model.getComponent(role="spectrograph-dedicated")
        cls.aligner = model.getComponent(role="fiber-aligner")
        cls.microscope = model.getMicroscope()
        cls.optmngr = path.OpticalPathManager(cls.microscope)
        cls.specline_ccd = stream.BrightfieldStream("Spectrograph_line_ccd", cls.ccd, cls.ccd.data, cls.bl)
        cls.specline_spccd = stream.BrightfieldStream("Spectrograph_line_spccd", cls.spccd, cls.spccd.data, cls.bl)

        # The good focus position is the start up position
        cls._good_focus = cls.focus.position.value["z"]
Esempio n. 50
0
    def setUpClass(cls):
        try:
            test.start_backend(SPEC_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

        # Microscope component
        cls.microscope = model.getComponent(role="sparc")
        # Find CCD & SEM components
        cls.spec = model.getComponent(role="spectrometer")
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
        cls.optmngr = path.OpticalPathManager(cls.microscope)
Esempio n. 51
0
def get_component(comp_name):
    """
    return the component with the given name
    comp_name (string): name of the component to find
    raises
        ValueError if the component doesn't exist
        other exception if there is an error while contacting the backend
    """
    logging.debug("Looking for component %s", comp_name)
    try:
        return model.getComponent(name=comp_name)
    except LookupError:
        try:
            comp = model.getComponent(role=comp_name)
            logging.info("Using component %s with role %s", comp.name, comp.role)
            return comp
        except LookupError:
            raise ValueError("No component found with name or role '%s'" % comp_name)
Esempio n. 52
0
    def setUpClass(cls):

        try:
            test.start_backend(SECOM_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.light = model.getComponent(role="light")
        cls.light_filter = model.getComponent(role="filter")
Esempio n. 53
0
    def __init__(self, microscope, main_app):
        super(SpecExtraPlugin, self).__init__(microscope, main_app)
        # Can only be used with a SPARC with spectrometer(s)
        main_data = self.main_app.main_data
        if microscope and main_data.role.startswith("sparc"):
            self._tab = self.main_app.main_data.getTabByName("sparc_acqui")
            stctrl = self._tab.streambar_controller

            try:
                # It's normally not handled by the GUI, to need to get it ourselves
                self._lens2 = model.getComponent(role="lens-switch")
            except LookupError:
                logging.info("%s plugin cannot load as there is no lens 2",
                             self.name)
                return

            if hasattr(main_data, "spectrometers"):  # From Odemis 2.10
                sptms = main_data.spectrometers
            else:  # Odemis 2.9
                sptms = [main_data.spectrometer, main_data.spectrometer_int]
                sptms = [s for s in sptms if s is not None]
            if not sptms:
                logging.info("%s plugin cannot load as there are no spectrometers",
                             self.name)
                return
        else:
            logging.info("%s plugin cannot load as the microscope is not a SPARC",
                         self.name)
            return

        for sptm in sptms:
            if len(sptms) <= 1:
                actname = "LA Spectrum"
            else:
                actname = "LA Spectrum with %s" % (sptm.name,)
            act = functools.partial(self.addSpectrum, name=actname, detector=sptm)
            stctrl.add_action(actname, act)

        # We "patch" the gui.conf.data for our special stream
        data.STREAM_SETTINGS_CONFIG[LASpectrumSettingsStream] = (
            OrderedDict((
                ("polarization", {
                    # "control_type": odemis.gui.CONTROL_COMBO,
                }),
                ("wavelength", {
                    "tooltip": "Center wavelength of the spectrograph",
                    "control_type": odemis.gui.CONTROL_FLT,
                    "range": (0.0, 1900e-9),
                }),
                ("grating", {}),
                ("slit-in", {
                    "label": "Input slit",
                    "tooltip": u"Opening size of the spectrograph input slit.\nA wide opening means more light and a worse resolution.",
                }),
            ))
        )
    def setUpClass(cls):
        try:
            test.start_backend(CLSPOTS_CONFIG)
        except LookupError:
            logging.debug("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return
        except IOError as exp:
            logging.error(str(exp))
            raise

        if TEST_NOHW:
            raise unittest.SkipTest('No HW present. Skipping tests.')

        # find components by their role
        cls.diagnostic_cam = model.getComponent(role="diagnostic-ccd")
        cls.stage = model.getComponent(role="stage")
        cls.ofocus = model.getComponent(role="diagnostic-cam-focus")
        cls._optimal_focus = 40e-6  # update with actual value
Esempio n. 55
0
    def setUpClass(cls):
        if driver.get_backend_status() == driver.BACKEND_RUNNING:
            logging.info("A running backend is already found, skipping tests")
            cls.backend_was_running = True
            return

        # run the backend as a daemon
        # we cannot run it normally as the child would also think he's in a unittest
        cmd = ODEMISD_CMD + ODEMISD_ARG + [SPARC_CONFIG]
        ret = subprocess.call(cmd)
        if ret != 0:
            logging.error("Failed starting backend with '%s'", cmd)
        time.sleep(1) # time to start

        # Find CCD & SEM components
        cls.ccd = model.getComponent(role="ccd")
        cls.spec = model.getComponent(role="spectrometer")
        cls.ebeam = model.getComponent(role="e-beam")
        cls.sed = model.getComponent(role="se-detector")
Esempio n. 56
0
    def __init__(self, res):
        """
        res (int, int): number of pixel in X and Y
        """
        self.res = res
        self.escan = model.getComponent(role="e-beam")
        try:
            self.edet = model.getComponent(role="se-detector")
        except LookupError:
            self.edet = model.getComponent(role="bs-detector")
        self.ccd = model.getComponent(role="ccd")

        self._must_stop = False

        self._ccd_data = []
        self._ccd_data_received = threading.Event()
        self._sem_data = []
        self._sem_data_received = threading.Event()

        self._hw_settings = None
Esempio n. 57
0
    def __init__(self, fn, number):
        self.number = number

        # get the components
        self.light = model.getComponent(role="light")
        self.ccd = model.getComponent(role="ccd")

        # prepare the data export
        self.exporter = dataio.find_fittest_converter(fn)
        
        # Make the name "fn" -> "~/Pictures + fn + fn-XXXX.ext"
        path, base = os.path.split(fn)
        bn, ext = os.path.splitext(base)
        tmpl = os.path.join(path, bn, bn + "-%05d." + ext)
        if path.startswith("/"):
            # if fn starts with / => don't add ~/Pictures
            self.fntmpl = tmpl
        else:
            self.fntmpl = os.path.join(get_picture_folder(), tmpl)


        self._n = 0
Esempio n. 58
0
    def _getComponent(self, role):
        """
        same as model.getComponent, but optimised by caching the result
        return Component
        raise LookupError: if no component found
        """
        try:
            comp = self._known_comps[role]
        except LookupError:
            comp = model.getComponent(role=role)
            self._known_comps[role] = comp

        return comp