Пример #1
0
    def test_default_fluo(self):
        """
        Check the default values for the FluoStream are fitting the current HW
        settings
        """
        em_choices = self.light_filter.axes["band"].choices

        # no light info
        self.light.emissions.value = [0] * len(self.light.emissions.value)
        s1 = stream.FluoStream("fluo1", self.ccd, self.ccd.data, self.light,
                               self.light_filter)
        # => stream emission is based on filter
        self.assertEqual(s1.excitation.choices, set(self.light.spectra.value))
        self.assertEqual(set(s1.emission.choices),
                         set(conversion.ensureTuple(em_choices.values())))

        em_idx = self.light_filter.position.value["band"]
        em_hw = em_choices[em_idx]
        self.assertEqual(s1.emission.value, conversion.ensureTuple(em_hw))

        # => stream excitation is light spectra closest below emission
        self.assertIn(s1.excitation.value, self.light.spectra.value)
        em_center = numpy.mean(em_hw)
        ex_centers = [s[2] for s in s1.excitation.choices]
        try:
            expected_ex = min([c for c in ex_centers if c < em_center],
                              key=lambda c: em_center - c)
        except ValueError:  # no excitation < em_center
            expected_ex = min(ex_centers)
        self.assertEqual(s1.excitation.value[2], expected_ex)

        # with light info (last emission is used)
        self.light.emissions.value[-1] = 0.9
        s2 = stream.FluoStream("fluo2", self.ccd, self.ccd.data, self.light,
                               self.light_filter)
        # => stream emission is based on filter
        self.assertEqual(s2.excitation.choices, set(self.light.spectra.value))
        self.assertEqual(set(s2.emission.choices),
                         set(conversion.ensureTuple(em_choices.values())))

        em_idx = self.light_filter.position.value["band"]
        em_hw = em_choices[em_idx]
        self.assertEqual(s2.emission.value, conversion.ensureTuple(em_hw))

        # => stream excitation is based on light.emissions
        self.assertIn(s2.excitation.value, self.light.spectra.value)
        expected_ex = self.light.spectra.value[-1]  # last value of emission
        self.assertEqual(s2.excitation.value, expected_ex)
Пример #2
0
    def test_fluo(self):
        """
        Check that the hardware settings are correctly set based on the settings
        """
        s1 = stream.FluoStream("fluo1", self.ccd, self.ccd.data, self.light,
                               self.light_filter)
        self.ccd.exposureTime = 1  # s, to avoid acquiring too many images

        # Check we manage to get at least one image
        self._image = None
        s1.image.subscribe(self._on_image)

        s1.should_update.value = True
        s1.is_active.value = True

        # change the stream setting (for each possible excitation)
        for i, exc in enumerate(self.light.spectra.value):
            s1.excitation.value = exc
            time.sleep(0.1)
            # check the hardware setting is updated
            exp_intens = [0] * len(self.light.spectra.value)
            exp_intens[i] = 1
            self.assertEqual(self.light.emissions.value, exp_intens)

        time.sleep(2)
        s1.is_active.value = False

        self.assertFalse(self._image is None, "No image received after 2s")
Пример #3
0
    def setUpClass(cls):
        try:
            test.start_backend(CRYOSECOM_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.focus = model.getComponent(role="focus")
        cls.light_filter = model.getComponent(role="filter")
        cls.stage = model.getComponent(role="stage")
        # Create 1 sem stream and 2 fm streams to be used in testing
        ss1 = stream.SEMStream(
            "sem1",
            cls.sed,
            cls.sed.data,
            cls.ebeam,
            emtvas={"dwellTime", "scale", "magnification", "pixelSize"})

        fs1 = stream.FluoStream("fluo1",
                                cls.ccd,
                                cls.ccd.data,
                                cls.light,
                                cls.light_filter,
                                focuser=cls.focus)
        fs1.excitation.value = sorted(fs1.excitation.choices)[0]

        fs2 = stream.FluoStream("fluo2", cls.ccd, cls.ccd.data, cls.light,
                                cls.light_filter)
        fs2.excitation.value = sorted(fs2.excitation.choices)[-1]
        cls.sem_streams = [ss1]
        cls.fm_streams = [fs1, fs2]
Пример #4
0
def acquire_timelapse(num, period, filename):
    """
    num (int or None): if None, will never stop, unless interrupted
    """

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

    # Prepare the streams and acquisition manager
    # The settings of the emissions and excitation are based on the current
    # hardware settings.
    stfm = stream.FluoStream("Fluorescence image", ccd, ccd.data, light, light_filter)
    # Force the excitation light using that command:
    # stfm.excitation.value = (4.72e-07, 4.79e-07, 4.85e-07, 4.91e-07, 4.97e-07)
    stem = stream.SEMStream("Secondary electrons", sed, sed.data, ebeam)
    # Special stream that will run the overlay and update the metadata based on this
    # Note: if more complex overlay is needed (eg, with background subtraction,
    # or with saving the CCD image), we'd need to directly call FindOverlay())
    stovl = stream.OverlayStream("Overlay", ccd, ebeam, sed)
    stovl.dwellTime.value = OVERLAY_DT

    acq_streams = [stem, stfm, stovl]
    
    # Prepare to save each acquisition in a separate file
    exporter = dataio.find_fittest_converter(filename)
    basename, ext = os.path.splitext(filename)
    fn_pattern = basename + "%04d" + ext

    fn_pos = basename + "pos.csv"
    fpos = open(fn_pos, "a")
    fpos.write("time\tX\tY\tZ\n")

    # Run acquisition every period
    try:
        i = 1
        while True:
            logging.info("Acquiring image %d", i)
            start = time.time()

            # Acquire all the images
            f = acq.acquire(acq_streams)
            data, e = f.result()
            if e:
                logging.error("Acquisition failed with %s", e)
                # It can partially fail, so still allow to save the data successfully acquired

            # Note: the actual time of the position is the one when the position was read
            # by the pigcs driver.
            spos = stage.position.value
            fpos.write("%.20g\t%g\t%g\t%g\n" %
                       (time.time(), spos["x"], spos["y"], focus.position.value["z"]))

            # Save the file
            if data:
                exporter.export(fn_pattern % (i,), data)

            # TODO: run autofocus from time to time?

            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)

            if i == num:  # will never be True if num is None
                break
            i += 1

    except KeyboardInterrupt:
        logging.info("Closing after only %d images acquired", i)
    except Exception:
        logging.exception("Failed to acquire all the images.")
        raise

    fpos.close()