예제 #1
0
    def test_guess_mode(self):
        # test guess mode for ar
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        ars = stream.ARSettingsStream("test ar", self.ccd, self.ccd.data,
                                      self.ebeam)
        sas = stream.SEMARMDStream("test sem-ar", sems, ars)

        guess = self.optmngr.guessMode(ars)
        self.assertEqual(guess, "ar")

        guess = self.optmngr.guessMode(sas)
        self.assertEqual(guess, "ar")

        # test guess mode for spectral-dedicated
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        specs = stream.SpectrumSettingsStream("test spec", self.spec,
                                              self.spec.data, self.ebeam)
        sps = stream.SEMSpectrumMDStream("test sem-spec", sems, specs)

        guess = self.optmngr.guessMode(specs)
        self.assertIn(guess, ("spectral", "spectral-dedicated"))

        guess = self.optmngr.guessMode(sps)
        self.assertIn(guess, ("spectral", "spectral-dedicated"))
예제 #2
0
    def test_sync_sem_ccd(self):
        """
        try acquisition with fairly complex SEM/CCD stream
        """
        # Create the streams and streamTree
        semsur = stream.SEMStream("test sem", self.sed, self.sed.data,
                                  self.ebeam)
        sems = stream.SEMStream("test sem cl", self.sed, self.sed.data,
                                self.ebeam)
        ars = stream.ARSettingsStream("test ar", self.ccd, self.ccd.data,
                                      self.ebeam)
        semars = stream.SEMARMDStream("test SEM/AR", [sems, ars])
        st = stream.StreamTree(streams=[semsur, semars])

        # SEM survey settings are via the current hardware settings
        self.ebeam.dwellTime.value = self.ebeam.dwellTime.range[0]

        # SEM/AR settings are via the AR stream
        ars.roi.value = (0.1, 0.1, 0.8, 0.8)
        mx_brng = self.ccd.binning.range[1]
        binning = tuple(min(4, mx) for mx in mx_brng)  # try binning 4x4
        self.ccd.binning.value = binning
        self.ccd.exposureTime.value = 1  # s
        ars.repetition.value = (2, 3)
        num_ar = numpy.prod(ars.repetition.value)

        est_time = acq.estimateTime(st.getProjections())

        # prepare callbacks
        self.start = None
        self.end = None
        self.updates = 0
        self.done = 0

        # Run acquisition
        start = time.time()
        f = acq.acquire(st.getProjections())
        f.add_update_callback(self.on_progress_update)
        f.add_done_callback(self.on_done)

        data, e = f.result()
        dur = time.time() - start
        self.assertGreaterEqual(dur, est_time /
                                2)  # Estimated time shouldn't be too small
        self.assertIsInstance(data[0], model.DataArray)
        self.assertIsNone(e)
        self.assertEqual(len(data), num_ar + 2)

        thumb = acq.computeThumbnail(st, f)
        self.assertIsInstance(thumb, model.DataArray)

        self.assertGreaterEqual(self.updates, 1)  # at least one update at end
        self.assertLessEqual(self.end, time.time())
        self.assertTrue(not f.cancelled())

        time.sleep(0.1)
        self.assertEqual(self.done, 1)
예제 #3
0
    def test_only_SEM_streams_with_zstack(self):
        sems = stream.SEMStream("sem", self.sed, self.sed.data, self.ebeam)
        self.streams = [sems]

        zlevels = {}

        est_time = acqmng.estimateZStackAcquisitionTime(self.streams, zlevels)
        # only one sem stream, so should be greater than or equal to 1 sec
        self.assertGreaterEqual(est_time, 1)

        # start the acquisition
        f = acqmng.acquireZStack(self.streams, zlevels)
        f.add_update_callback(self._on_progress_update)

        data, exp = f.result()
        self.assertIsNone(exp)

        for d in data:
            self.assertIsInstance(d, model.DataArray)
            # even if zstack, it's only SEM, so the center has 2 components
            self.assertEqual(len(d.metadata[model.MD_POS]), 2)
            # even if zstack, it's SEM, so the pixel size has 2 components
            self.assertEqual(len(d.metadata[model.MD_PIXEL_SIZE]), 2)

        # 1 streams, so 1 acquisitions
        self.assertEqual(len(data), 1)

        # 1 streams, 1 updates per stream, so 1 updates
        self.assertGreaterEqual(self._nb_updates, 1)
예제 #4
0
    def test_acq_fine_align(self):
        """
        try acquisition with SEM + Optical + overlay streams
        """
        # Create the streams
        sems = stream.SEMStream("test sem", self.sed, self.sed.data, self.ebeam)
        # SEM settings are via the current hardware settings
        self.ebeam.dwellTime.value = self.ebeam.dwellTime.range[0]

        fs1 = stream.FluoStream("test orange", self.ccd, self.ccd.data,
                                self.light, self.light_filter)
        fs1.excitation.value = fs1.excitation.range[0] + 5e-9
        fs1.emission.value = fs1.emission.range[0] + 5e-9
        fs2 = stream.FluoStream("test blue", self.ccd, self.ccd.data,
                                self.light, self.light_filter)
        fs2.excitation.value = fs2.excitation.range[1] - 5e-9
        fs2.emission.value = fs2.emission.range[1] - 5e-9
        self.ccd.exposureTime.value = 0.1 # s

        ovrl = stream.OverlayStream("overlay", self.ccd, self.ebeam, self.sed)
        ovrl.dwellTime.value = 0.3
        ovrl.repetition.value = (7, 7)

        streams = [sems, fs1, fs2, ovrl]
        est_time = acq.estimateTime(streams)

        sum_est_time = sum(s.estimateAcquisitionTime() for s in streams)
        self.assertGreaterEqual(est_time, sum_est_time)

        # prepare callbacks
        self.past = None
        self.left = None
        self.updates = 0
        self.done = 0

        # Run acquisition
        start = time.time()
        f = acq.acquire(streams)
        f.add_update_callback(self.on_progress_update)
        f.add_done_callback(self.on_done)

        data = f.result()
        dur = time.time() - start
        self.assertGreater(dur, est_time / 2) # Estimated time shouldn't be too small

        self.assertIsInstance(data[0], model.DataArray)
        self.assertEqual(len(data), len(streams) - 1)

        # No overlay correction metadata anywhere (it has all been merged)
        for d in data:
            for k in [model.MD_ROTATION_COR, model.MD_PIXEL_SIZE_COR, model.MD_POS_COR]:
                self.assertNotIn(k, d.metadata)

#        thumb = acq.computeThumbnail(st, f)
#        self.assertIsInstance(thumb, model.DataArray)

        self.assertGreaterEqual(self.updates, 1) # at least one update at end
        self.assertEqual(self.left, 0)
        self.assertEqual(self.done, 1)
        self.assertTrue(not f.cancelled())
예제 #5
0
    def test_drift_stream(self):
        escan = self.ebeam
        detector = self.sed
        ccd = self.ccd

        # Create the stream
        sems = stream.SEMStream("test sem", detector, detector.data, escan)
        ars = stream.ARSettingsStream("test ar", ccd, ccd.data, escan)
        sas = stream.SEMARMDStream("test sem-ar", [sems, ars])

        # Long acquisition
        ccd.exposureTime.value = 1e-02  # s

        dc = leech.AnchorDriftCorrector(escan, detector)
        dc.period.value = 5
        dc.roi.value = (0.525, 0.525, 0.6, 0.6)
        dc.dwellTime.value = 1e-04
        sems.leeches.append(dc)

        escan.dwellTime.value = 1e-02

        ars.roi.value = (0.4, 0.4, 0.6, 0.6)
        ars.repetition.value = (5, 5)

        start = time.time()
        for l in sas.leeches:
            l.series_start()
        f = sas.acquire()
        x = f.result()
        for l in sas.leeches:
            l.series_complete(x)
        dur = time.time() - start
        logging.debug("Acquisition took %g s", dur)
        self.assertTrue(f.done())
예제 #6
0
    def test_drift_stream(self):
        escan = self.ebeam
        detector = self.sed
        ccd = self.ccd

        # Create the stream
        sems = stream.SEMStream("test sem", detector, detector.data, escan)
        ars = stream.ARStream("test ar", ccd, ccd.data, escan)
        sas = stream.SEMARMDStream("test sem-ar", sems, ars)

        # Long acquisition
        ccd.exposureTime.value = 1e-02  # s

        sems.dcPeriod.value = 5
        sems.dcRegion.value = (0.525, 0.525, 0.6, 0.6)
        sems.dcDwellTime.value = 1e-04
        escan.dwellTime.value = 1e-02

        ars.roi.value = (0.4, 0.4, 0.6, 0.6)
        ars.repetition.value = (5, 5)

        start = time.time()
        f = sas.acquire()
        x = f.result()
        dur = time.time() - start
        logging.debug("Acquisition took %g s", dur)
        self.assertTrue(f.done())
예제 #7
0
    def test_set_path_stream(self):
        # test guess mode for ar
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        ars = stream.ARSettingsStream("test ar", self.ccd, self.ccd.data,
                                      self.ebeam)
        sas = stream.SEMARMDStream("test sem-ar", sems, ars)

        self.optmngr.setPath(ars).result()
        # Assert that actuator was moved according to mode given
        self.assert_pos_as_in_mode(self.lenswitch, "ar")
        self.assert_pos_as_in_mode(self.slit, "ar")
        self.assert_pos_as_in_mode(self.specgraph, "ar")
        self.assertEqual(self.spec_det_sel.position.value, {'rx': 0})
        self.assertAlmostEqual(self.spec_sel.position.value["x"], 0.022)

        # Change positions back
        self.optmngr.setPath("mirror-align").result()

        self.optmngr.setPath(sas).result()
        # Assert that actuator was moved according to mode given
        self.assert_pos_as_in_mode(self.lenswitch, "ar")
        self.assert_pos_as_in_mode(self.slit, "ar")
        self.assert_pos_as_in_mode(self.specgraph, "ar")
        self.assertEqual(self.spec_det_sel.position.value, {'rx': 0})
        self.assertAlmostEqual(self.spec_sel.position.value["x"], 0.022)

        # test guess mode for spectral-dedicated
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        specs = stream.SpectrumSettingsStream("test spec", self.spec,
                                              self.spec.data, self.ebeam)
        sps = stream.SEMSpectrumMDStream("test sem-spec", sems, specs)

        self.optmngr.setPath(specs).result()
        # Assert that actuator was moved according to mode given
        self.assert_pos_as_in_mode(self.lenswitch, "spectral")
        # No slit/spectrograph as they are not affecting the detector
        self.assertAlmostEqual(self.spec_sel.position.value["x"], 0.026112848)

        # Change positions back
        self.optmngr.setPath("chamber-view").result()

        self.optmngr.setPath(sps).result()
        # Assert that actuator was moved according to mode given
        self.assert_pos_as_in_mode(self.lenswitch, "spectral")
        self.assertAlmostEqual(self.spec_sel.position.value["x"], 0.026112848)
예제 #8
0
    def test_progressive_future(self):
        """
        Test .acquire interface (should return a progressive future with updates)
        """
        self.image = None
        self.done = False
        self.updates = 0

        # Create the stream
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        ars = stream.ARStream("test ar", self.ccd, self.ccd.data, self.ebeam)
        sas = stream.SEMARMDStream("test sem-ar", sems, ars)

        ars.roi.value = (0.1, 0.1, 0.8, 0.8)
        self.ccd.binning.value = (4, 4)  # hopefully always supported

        # Long acquisition
        self.ccd.exposureTime.value = 0.2  # s
        ars.repetition.value = (2, 3)
        exp_shape = ars.repetition.value[::-1]
        num_ar = numpy.prod(ars.repetition.value)

        # Start acquisition
        timeout = 1 + 1.5 * sas.estimateAcquisitionTime()
        f = sas.acquire()
        f.add_update_callback(self.on_progress_update)
        f.add_done_callback(self.on_done)

        data = f.result(timeout)
        self.assertEqual(len(data), num_ar + 1)
        self.assertEqual(data[0].shape, exp_shape)
        self.assertGreaterEqual(self.updates,
                                4)  # at least a couple of updates
        self.assertEqual(self.left, 0)
        self.assertTrue(self.done)
        self.assertTrue(not f.cancelled())

        # short acquisition
        self.done = False
        self.updates = 0
        self.ccd.exposureTime.value = 0.02  # s
        ars.repetition.value = (5, 4)
        exp_shape = ars.repetition.value[::-1]
        num_ar = numpy.prod(ars.repetition.value)

        # Start acquisition
        timeout = 1 + 1.5 * sas.estimateAcquisitionTime()
        f = sas.acquire()
        f.add_update_callback(self.on_progress_update)
        f.add_done_callback(self.on_done)

        data = f.result(timeout)
        self.assertEqual(len(data), num_ar + 1)
        self.assertEqual(data[0].shape, exp_shape)
        self.assertGreaterEqual(self.updates, 5)  # at least a few updates
        self.assertEqual(self.left, 0)
        self.assertTrue(self.done)
        self.assertTrue(not f.cancelled())
예제 #9
0
    def __init__(self, microscope, main_app):
        """
        :param microscope: (Microscope or None) The main back-end component.
        :param main_app: (wx.App) The main GUI component.
        """
        super(CLAcqPlugin, self).__init__(microscope, main_app)

        # Can only be used with a microscope
        if not microscope:
            return
        else:
            # Check which stream the microscope supports
            self.main_data = self.main_app.main_data
            if not (self.main_data.ccd and self.main_data.ebeam):
                return

        self.exposureTime = self.main_data.ccd.exposureTime
        self.binning = self.main_data.ccd.binning
        # Trick to pass the component (ccd to binning_1d_from_2d())
        self.vaconf["binning"]["choices"] = (
            lambda cp, va, cf: cutil.binning_1d_from_2d(
                self.main_data.ccd, va, cf))

        self._survey_stream = None
        self._optical_stream = acqstream.BrightfieldStream(
            "Optical",
            self.main_data.ccd,
            self.main_data.ccd.data,
            emitter=None,
            focuser=self.main_data.focus)
        self._secom_cl_stream = SECOMCLSettingsStream("Secom-CL",
                                                      self.main_data.ccd,
                                                      self.main_data.ccd.data,
                                                      self.main_data.ebeam)
        self._sem_stream = acqstream.SEMStream(
            "Secondary electrons concurrent", self.main_data.sed,
            self.main_data.sed.data, self.main_data.ebeam)

        self._secom_sem_cl_stream = SECOMCLSEMMDStream(
            "SECOM SEM CL", [self._sem_stream, self._secom_cl_stream])

        self._driftCorrector = leech.AnchorDriftCorrector(
            self.main_data.ebeam, self.main_data.sed)

        self.conf = get_acqui_conf()
        self.expectedDuration = model.VigilantAttribute(1,
                                                        unit="s",
                                                        readonly=True)
        self.exposureTime.subscribe(self._update_exp_dur)

        self.filename = self._secom_sem_cl_stream.filename  # duplicate VA
        self.filename.subscribe(self._on_filename)

        self.addMenu("Acquisition/CL acquisition...", self.start)
예제 #10
0
 def start_sem(self):
     main_data = self.main_app.main_data
     sem_stream = stream.SEMStream(
         "Secondary electrons survey",
         main_data.sed,
         main_data.sed.data,
         main_data.ebeam,
         focuser=main_data.ebeam_focus,
         emtvas=get_local_vas(main_data.ebeam),
         detvas=get_local_vas(main_data.sed),
     )
     self.start(sem_stream)
예제 #11
0
    def test_guess_mode(self):
        # test guess mode for ar
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        ars = stream.ARSettingsStream("test ar", self.ccd, self.ccd.data,
                                      self.ebeam)
        sas = stream.SEMARMDStream("test sem-ar", sems, ars)

        guess = self.optmngr.guessMode(ars)
        self.assertEqual(guess, "ar")

        guess = self.optmngr.guessMode(sas)
        self.assertEqual(guess, "ar")

        # test guess mode for spectral
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        specs = stream.SpectrumSettingsStream("test spec", self.spec,
                                              self.spec.data, self.ebeam)
        sps = stream.SEMSpectrumMDStream("test sem-spec", sems, specs)

        guess = self.optmngr.guessMode(specs)
        self.assertEqual(guess, "spectral")

        guess = self.optmngr.guessMode(sps)
        self.assertEqual(guess, "spectral")

        # test guess mode for cli
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        cls = stream.SpectrumSettingsStream("test cl", self.cld, self.cld.data,
                                            self.ebeam)
        sls = stream.SEMSpectrumMDStream("test sem-cl", sems, cls)

        guess = self.optmngr.guessMode(cls)
        self.assertEqual(guess, "cli")

        guess = self.optmngr.guessMode(sls)
        self.assertEqual(guess, "cli")
예제 #12
0
    def setUpClass(cls):
        try:
            test.start_backend(ENZEL_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")
        # Make sure the lens is referenced
        cls.focus.reference({'z'}).result()
        # The 5DoF stage is not referenced automatically, so let's do it now
        stage_axes = set(cls.stage.axes.keys())
        cls.stage.reference(stage_axes).result()
        # 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"})

        cls.ccd.exposureTime.value = cls.ccd.exposureTime.range[0]  # go fast
        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,
                                focuser=cls.focus)
        fs2.excitation.value = sorted(fs2.excitation.choices)[-1]
        cls.sem_streams = [ss1]
        cls.fm_streams = [fs1, fs2]
예제 #13
0
    def test_metadata(self):
        """
        Check if extra metadata are saved
        """
        settings_obs = SettingsObserver(model.getComponents())

        detvas = {"binning", "exposureTime"}
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        specs = stream.SpectrumSettingsStream("test spec",
                                              self.spec,
                                              self.spec.data,
                                              self.ebeam,
                                              detvas=detvas)
        sps = stream.SEMSpectrumMDStream("test sem-spec", [sems, specs])

        specs.roi.value = (0, 0, 1, 1)
        specs.repetition.value = (2, 3)
        specs.detBinning.value = (2, specs.detBinning.value[1])
        specs.detExposureTime.value = 0.1

        specs2 = stream.SpectrumSettingsStream("test spec2",
                                               self.spec,
                                               self.spec.data,
                                               self.ebeam,
                                               detvas=detvas)
        sps2 = stream.SEMSpectrumMDStream("test sem-spec2", [sems, specs2])

        specs2.roi.value = (0, 0, 1, 1)
        specs2.repetition.value = (2, 3)
        specs2.detBinning.value = (4, specs2.detBinning.value[1])
        specs2.detExposureTime.value = 0.05

        f = acqmng.acquire([sps, sps2], settings_obs)
        data = f.result()

        spec1_data = data[0][1]
        spec2_data = data[0][3]
        self.assertEqual(
            spec1_data.metadata[model.MD_EXTRA_SETTINGS][self.spec.name]
            ['binning'], [(2, specs.detBinning.value[1]), 'px'])
        self.assertEqual(
            spec2_data.metadata[model.MD_EXTRA_SETTINGS][self.spec.name]
            ['binning'], [(4, specs2.detBinning.value[1]), 'px'])
        self.assertEqual(
            spec1_data.metadata[model.MD_EXTRA_SETTINGS][self.spec.name]
            ['exposureTime'], [0.1, 's'])
        self.assertEqual(
            spec2_data.metadata[model.MD_EXTRA_SETTINGS][self.spec.name]
            ['exposureTime'], [0.05, 's'])
예제 #14
0
    def test_overview_acquisition(self):
        s = stream.SEMStream(
            "Single beam",
            self.sed,
            self.sed.data,
            self.ebeam,
            focuser=self.
            efocuser,  # Not used during acquisition, but done by the GUI
            hwemtvas={"scale", "dwellTime", "horizontalFoV"})
        # This should be used by the acquisition
        s.dwellTime.value = 1e-6  # s

        # Use random settings and check they are overridden by the overview acquisition
        s.scale.value = (2, 2)
        s.horizontalFoV.value = 20e-6  # m

        # Known position of the center scintillator
        scintillator5_area = (-0.007, -0.007, 0.007, 0.007)  # l, b, r, t
        # Small area for DEBUG (3x3)
        # scintillator5_area = (-0.002, -0.002, 0.002, 0.002)  # l, b, r, t

        est_time = fastem.estimateTiledAcquisitionTime(s, self.stage,
                                                       scintillator5_area)
        # don't use for DEBUG example
        self.assertGreater(est_time,
                           10)  # It should take more than 10s! (expect ~5 min)

        before_start_t = time.time()
        f = fastem.acquireTiledArea(s, self.stage, scintillator5_area)
        time.sleep(1)
        start_t, end_t = f.get_progress()
        self.assertGreater(start_t, before_start_t)
        # don't use for DEBUG example
        self.assertGreater(end_t,
                           time.time() +
                           10)  # Should report still more than 10s

        overview_da = f.result()
        self.assertGreater(overview_da.shape[0], 2000)
        self.assertGreater(overview_da.shape[1], 2000)

        # Check the final area fits the requested area, with possibly a little bit of margin
        bbox = img.getBoundingBox(overview_da)
        fov = bbox[2] - bbox[0], bbox[3] - bbox[1]
        logging.debug("Got image of size %s, with FoV %s = %s",
                      overview_da.shape, fov, bbox)
        self.assertLessEqual(bbox[0], scintillator5_area[0])  # Left
        self.assertLessEqual(bbox[1], scintillator5_area[1])  # Bottom
        self.assertGreaterEqual(bbox[2], scintillator5_area[2])  # Right
        self.assertGreaterEqual(bbox[3], scintillator5_area[3])  # Top
예제 #15
0
    def test_FM_and_SEM_with_zstack(self):
        s1 = stream.FluoStream("fluo1",
                               self.ccd,
                               self.ccd.data,
                               self.light,
                               self.light_filter,
                               focuser=self.fm_focuser)
        s1.excitation.value = sorted(s1.excitation.choices)[0]

        sems = stream.SEMStream("sem", self.sed, self.sed.data, self.ebeam)

        self.streams = [s1, sems]

        zlevels_list = generate_zlevels(self.fm_focuser, [-2e-6, 2e-6], 1e-6)
        zlevels = {}
        for s in self.streams:
            if isinstance(s, stream.FluoStream):
                zlevels[s] = list(zlevels_list)

        est_time = acqmng.estimateZStackAcquisitionTime(self.streams, zlevels)
        # about 5 seconds for fm streams, and 1 sec for sem stream, so should be
        # greater than or equal 5 sec
        self.assertGreaterEqual(est_time, 4)

        # start the acquisition
        f = acqmng.acquireZStack(self.streams, zlevels)
        f.add_update_callback(self._on_progress_update)

        data, exp = f.result()
        self.assertIsNone(exp)

        for i, d in enumerate(data):
            self.assertIsInstance(d, model.DataArray)
            if d.ndim > 2 and d.shape[-3] > 1:  # 3D data (FM)
                # if zstack, so the center has 3 components
                self.assertEqual(len(d.metadata[model.MD_POS]), 3)
                # if zstack, so the pixel size has 3 components
                self.assertEqual(len(d.metadata[model.MD_PIXEL_SIZE]), 3)
            else:  # 2D data (SEM)
                # even if zstack, it's SEM, so the center has 2 components
                self.assertEqual(len(d.metadata[model.MD_POS]), 2)
                # even if zstack, it's SEM, so the pixel size has 2 components
                self.assertEqual(len(d.metadata[model.MD_PIXEL_SIZE]), 2)

        # 2 streams, so 2 acquisitions
        self.assertEqual(len(data), 2)

        # 2 streams, 2 updates per stream, so >= 2 updates
        self.assertGreaterEqual(self._nb_updates, 2)
예제 #16
0
    def test_guess_mode(self):
        # test guess mode for spectral
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        specs = stream.SpectrumSettingsStream("test spec", self.spec,
                                              self.spec.data, self.ebeam)
        sps = stream.SEMSpectrumMDStream("test sem-spec", sems, specs)

        guess = self.optmngr.guessMode(specs)
        self.assertEqual(guess, "spectral")

        guess = self.optmngr.guessMode(sps)
        self.assertEqual(guess, "spectral")

        with self.assertRaises(LookupError):
            guess = self.optmngr.guessMode(sems)
예제 #17
0
    def test_sync_future_cancel(self):
        self.image = None

        # Create the stream
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        ars = stream.ARStream("test ar", self.ccd, self.ccd.data, self.ebeam)
        sas = stream.SEMARMDStream("test sem-ar", sems, ars)

        ars.roi.value = (0.1, 0.1, 0.8, 0.8)
        self.ccd.binning.value = (4, 4)  # hopefully always supported

        # Long acquisition
        self.updates = 0
        self.ccd.exposureTime.value = 0.2  # s
        ars.repetition.value = (2, 3)

        # Start acquisition
        f = sas.acquire()
        f.add_update_callback(self.on_progress_update)
        f.add_done_callback(self.on_done)

        time.sleep(self.ccd.exposureTime.value)  # wait a bit
        f.cancel()

        self.assertGreaterEqual(self.updates, 1)  # at least at the end
        self.assertEqual(self.left, 0)
        self.assertTrue(f.cancelled())

        # short acquisition
        self.updates = 0
        self.ccd.exposureTime.value = 0.02  # s
        ars.repetition.value = (5, 4)

        # Start acquisition
        f = sas.acquire()
        f.add_update_callback(self.on_progress_update)
        f.add_done_callback(self.on_done)

        time.sleep(self.ccd.exposureTime.value)  # wait a bit
        f.cancel()

        self.assertGreaterEqual(self.updates, 1)  # at least at the end
        self.assertEqual(self.left, 0)
        self.assertTrue(f.cancelled())
예제 #18
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]
예제 #19
0
파일: streams.py 프로젝트: arijitxx/odemis
 def addSEMBSD(self, **kwargs):
     """
     Creates a new backscattered electron stream and panel in the stream bar
     returns (StreamPanel): the panel created
     """
     if self._main_data_model.role == "delphi":
         # For the Delphi, the SEM stream needs to be more "clever" because
         # it needs to run a simple spot alignment every time the stage has
         # moved before starting to acquire.
         s = acqstream.AlignedSEMStream("Backscattered electrons",
                                        self._main_data_model.bsd,
                                        self._main_data_model.bsd.data,
                                        self._main_data_model.ebeam,
                                        self._main_data_model.ccd,
                                        self._main_data_model.stage,
                                        shiftebeam="Ebeam shift")
         # Select between "Metadata update" and "Stage move"
         # TODO: use shiftebeam once the phenom driver supports it
     else:
         s = acqstream.SEMStream("Backscattered electrons",
                                 self._main_data_model.bsd,
                                 self._main_data_model.bsd.data,
                                 self._main_data_model.ebeam)
     return self._addStream(s, **kwargs)
예제 #20
0
    def test_set_path_stream(self):
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        ars = stream.ARSettingsStream("test ar", self.ccd, self.ccd.data,
                                      self.ebeam)
        sas = stream.SEMARMDStream("test sem-ar", sems, ars)

        self.optmngr.setPath(ars).result()
        # Assert that actuator was moved according to mode given
        self.assert_pos_as_in_mode(self.lenswitch, "ar")
        self.assert_pos_as_in_mode(self.slit, "ar")
        self.assert_pos_as_in_mode(self.specgraph, "ar")
        self.assertEqual(self.spec_det_sel.position.value, {'rx': 0})

        # Change positions back
        self.optmngr.setPath("mirror-align").result()

        self.optmngr.setPath(sas).result()
        # Assert that actuator was moved according to mode given
        self.assert_pos_as_in_mode(self.lenswitch, "ar")
        self.assert_pos_as_in_mode(self.slit, "ar")
        self.assert_pos_as_in_mode(self.specgraph, "ar")
        self.assertEqual(self.spec_det_sel.position.value, {'rx': 0})

        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        specs = stream.SpectrumSettingsStream("test spec", self.spec,
                                              self.spec.data, self.ebeam)
        sps = stream.SEMSpectrumMDStream("test sem-spec", sems, specs)

        self.optmngr.setPath(specs).result()
        # Assert that actuator was moved according to mode given
        self.assertEqual(self.spec_det_sel.position.value,
                         {'rx': 1.5707963267948966})
        self.assertEqual(self.cl_det_sel.position.value, {'x': 0.01})

        # Change positions back
        self.optmngr.setPath("chamber-view").result()

        self.optmngr.setPath(sps).result()
        # Assert that actuator was moved according to mode given
        self.assert_pos_as_in_mode(self.lenswitch, "spectral")
        self.assert_pos_as_in_mode(self.slit, "spectral")
        self.assert_pos_as_in_mode(self.specgraph, "spectral")
        self.assertEqual(self.spec_det_sel.position.value,
                         {'rx': 1.5707963267948966})
        self.assertEqual(self.cl_det_sel.position.value, {'x': 0.01})

        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        specs = stream.SpectrumSettingsStream("test spec",
                                              self.spec_integrated,
                                              self.spec_integrated.data,
                                              self.ebeam)
        sps = stream.SEMSpectrumMDStream("test sem-spec", sems, specs)

        # Change positions back
        self.optmngr.setPath("chamber-view").result()

        self.optmngr.setPath(specs).result()
        # Assert that actuator was moved according to mode given
        self.assert_pos_as_in_mode(self.lenswitch, "spectral-integrated")
        self.assert_pos_as_in_mode(self.slit, "spectral-integrated")
        self.assert_pos_as_in_mode(self.specgraph, "spectral-integrated")
        self.assertEqual(self.spec_det_sel.position.value, {'rx': 0})
        self.assertEqual(self.cl_det_sel.position.value, {'x': 0.01})

        # Check the focus is remembered before going to chamber-view
        orig_focus = self.focus.position.value

        # Change positions back
        self.optmngr.setPath("chamber-view").result()
        self.focus.moveRel({"z": 1e-3}).result()

        self.optmngr.setPath(sps).result()
        # Assert that actuator was moved according to mode given
        self.assert_pos_as_in_mode(self.lenswitch, "spectral")
        self.assert_pos_as_in_mode(self.slit, "spectral")
        self.assert_pos_as_in_mode(self.specgraph, "spectral")
        self.assertEqual(self.spec_det_sel.position.value, {'rx': 0})
        self.assertEqual(self.cl_det_sel.position.value, {'x': 0.01})
        self.assertEqual(self.focus.position.value, orig_focus)
예제 #21
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()
예제 #22
0
    def test_leech(self):
        """
        try acquisition with leech
        """
        # Create the streams and streamTree
        semsur = stream.SEMStream("test sem", self.sed, self.sed.data,
                                  self.ebeam)
        sems = stream.SEMStream("test sem cl", self.sed, self.sed.data,
                                self.ebeam)
        ars = stream.ARSettingsStream("test ar", self.ccd, self.ccd.data,
                                      self.ebeam)
        semars = stream.SEMARMDStream("test SEM/AR", [sems, ars])
        st = stream.StreamTree(streams=[semsur, semars])

        pcd = Fake0DDetector("test")
        pca = ProbeCurrentAcquirer(pcd)
        sems.leeches.append(pca)
        semsur.leeches.append(pca)

        # SEM survey settings are via the current hardware settings
        self.ebeam.dwellTime.value = self.ebeam.dwellTime.range[0]

        # SEM/AR settings are via the AR stream
        ars.roi.value = (0.1, 0.1, 0.8, 0.8)
        mx_brng = self.ccd.binning.range[1]
        binning = tuple(min(4, mx) for mx in mx_brng)  # try binning 4x4
        self.ccd.binning.value = binning
        self.ccd.exposureTime.value = 1  # s
        ars.repetition.value = (2, 3)
        num_ar = numpy.prod(ars.repetition.value)

        pca.period.value = 10  # Only at beginning and end

        est_time = acq.estimateTime(st.getProjections())

        # prepare callbacks
        self.start = None
        self.end = None
        self.updates = 0
        self.done = 0

        # Run acquisition
        start = time.time()
        f = acq.acquire(st.getProjections())
        f.add_update_callback(self.on_progress_update)
        f.add_done_callback(self.on_done)

        data, e = f.result()
        dur = time.time() - start
        self.assertGreaterEqual(dur, est_time /
                                2)  # Estimated time shouldn't be too small
        self.assertIsInstance(data[0], model.DataArray)
        self.assertIsNone(e)
        self.assertEqual(len(data), num_ar + 2)

        thumb = acq.computeThumbnail(st, f)
        self.assertIsInstance(thumb, model.DataArray)

        self.assertGreaterEqual(self.updates, 1)  # at least one update at end
        self.assertLessEqual(self.end, time.time())
        self.assertTrue(not f.cancelled())

        time.sleep(0.1)
        self.assertEqual(self.done, 1)

        for da in data:
            pcmd = da.metadata[model.MD_EBEAM_CURRENT_TIME]
            self.assertEqual(len(pcmd), 2)
예제 #23
0
    def test_sync_path_guess(self):
        """
        try synchronized acquisition using the Optical Path Manager
        """
        # Create the streams and streamTree
        opmngr = path.OpticalPathManager(self.microscope)
        semsur = stream.SEMStream("test sem", self.sed, self.sed.data,
                                  self.ebeam)
        sems = stream.SEMStream("test sem cl", self.sed, self.sed.data,
                                self.ebeam)
        ars = stream.ARSettingsStream("test ar",
                                      self.ccd,
                                      self.ccd.data,
                                      self.ebeam,
                                      opm=opmngr)
        semars = stream.SEMARMDStream("test SEM/AR", [sems, ars])
        specs = stream.SpectrumSettingsStream("test spec",
                                              self.spec,
                                              self.spec.data,
                                              self.ebeam,
                                              opm=opmngr)
        sps = stream.SEMSpectrumMDStream("test sem-spec", [sems, specs])
        st = stream.StreamTree(streams=[semsur, semars, sps])

        # SEM survey settings are via the current hardware settings
        self.ebeam.dwellTime.value = self.ebeam.dwellTime.range[0]

        # SEM/AR/SPEC settings are via the AR stream
        ars.roi.value = (0.1, 0.1, 0.8, 0.8)
        specs.roi.value = (0.2, 0.2, 0.7, 0.7)
        mx_brng = self.ccd.binning.range[1]
        binning = tuple(min(4, mx) for mx in mx_brng)  # try binning 4x4
        self.ccd.binning.value = binning
        self.ccd.exposureTime.value = 1  # s
        ars.repetition.value = (2, 3)
        specs.repetition.value = (3, 2)
        num_ar = numpy.prod(ars.repetition.value)

        est_time = acq.estimateTime(st.getProjections())

        # prepare callbacks
        self.start = None
        self.end = None
        self.updates = 0
        self.done = 0

        # Run acquisition
        start = time.time()
        f = acq.acquire(st.getProjections())
        f.add_update_callback(self.on_progress_update)
        f.add_done_callback(self.on_done)

        data, e = f.result()
        dur = time.time() - start
        self.assertGreaterEqual(dur, est_time /
                                2)  # Estimated time shouldn't be too small
        self.assertIsInstance(data[0], model.DataArray)
        self.assertIsNone(e)
        self.assertEqual(len(data), num_ar + 4)

        thumb = acq.computeThumbnail(st, f)
        self.assertIsInstance(thumb, model.DataArray)

        self.assertGreaterEqual(self.updates, 1)  # at least one update at end
        self.assertLessEqual(self.end, time.time())
        self.assertTrue(not f.cancelled())

        # assert optical path configuration
        exp_pos = path.SPARC_MODES["spectral"][1]
        self.assertEqual(self.lenswitch.position.value, exp_pos["lens-switch"])
        self.assertEqual(self.spec_det_sel.position.value,
                         exp_pos["spec-det-selector"])
        self.assertEqual(self.ar_spec_sel.position.value,
                         exp_pos["ar-spec-selector"])

        time.sleep(0.1)
        self.assertEqual(self.done, 1)
예제 #24
0
    def test_histogram(self):
        """
        Check the histogram updates correctly, including if the BPP changes
        """
        ebeam = FakeEBeam("ebeam")
        se = FakeDetector("se")
        ss = stream.SEMStream("test", se, se.data, ebeam)

        # without data, the histogram should be empty, and the intensity range
        # based on the depth of the detector
        h = ss.histogram.value
        ir = ss.intensityRange.range
        self.assertEqual(len(h), 0)
        self.assertEqual((ir[0][0], ir[1][1]), (0, se.shape[0] - 1))

        # "start" the stream, so it expects data
        ss.should_update.value = True
        ss.is_active.value = True

        # send a simple 8 bit image (with correct metadata) =>
        #  * The intensity range should update to 8-bit
        #  * The histogram should be 256 long
        d = numpy.zeros(ebeam.shape[::-1], "uint8")
        md = {
            model.MD_BPP: 8,
            model.MD_PIXEL_SIZE: (1e-6, 2e-5),  # m/px
            model.MD_POS: (1e-3, -30e-3),  # m
        }
        da = model.DataArray(d, md)
        se.data.notify(da)

        time.sleep(0.5)  # make sure all the delayed code is executed
        self.assertIsInstance(ss.image.value, model.DataArray)
        h = ss.histogram.value
        ir = ss.intensityRange.range
        self.assertEqual(len(h), 256)
        self.assertEqual((ir[0][0], ir[1][1]), (0, (2**8) - 1))

        # Send a 16 bit image with 16 BPP =>
        #  * The intensity range should update to 16-bit
        #  * The histogram should stay not too long (<=1024 values)
        d = numpy.zeros(ebeam.shape[::-1], "uint16")
        md = {
            model.MD_BPP: 16,
            model.MD_PIXEL_SIZE: (1e-6, 2e-5),  # m/px
            model.MD_POS: (1e-3, -30e-3),  # m
        }
        da = model.DataArray(d, md)
        se.data.notify(da)

        time.sleep(0.5)  # make sure all the delayed code is executed
        self.assertIsInstance(ss.image.value, model.DataArray)
        h = ss.histogram.value
        ir = ss.intensityRange.range
        self.assertLessEqual(len(h), 1024)
        self.assertEqual((ir[0][0], ir[1][1]), (0, (2**16) - 1))

        # Send a 16 bit image with 12 BPP =>
        #  * The intensity range should update to 12-bit
        #  * The histogram should stay not too long (<=1024 values)
        d = numpy.zeros(ebeam.shape[::-1], "uint16")
        md = {
            model.MD_BPP: 12,
            model.MD_PIXEL_SIZE: (1e-6, 2e-5),  # m/px
            model.MD_POS: (1e-3, -30e-3),  # m
        }
        da = model.DataArray(d, md)
        se.data.notify(da)

        time.sleep(0.5)  # make sure all the delayed code is executed
        self.assertIsInstance(ss.image.value, model.DataArray)
        h = ss.histogram.value
        ir = ss.intensityRange.range
        self.assertLessEqual(len(h), 1024)
        self.assertEqual((ir[0][0], ir[1][1]), (0, (2**12) - 1))
예제 #25
0
    def test_acq_ar(self):
        """
        Test short & long acquisition for AR
        """
        # Create the stream
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        ars = stream.ARStream("test ar", self.ccd, self.ccd.data, self.ebeam)
        sas = stream.SEMARMDStream("test sem-ar", sems, ars)

        ars.roi.value = (0.1, 0.1, 0.8, 0.8)
        self.ccd.binning.value = (4, 4)  # hopefully always supported

        # Long acquisition (small rep to avoid being too long)
        # The acquisition method is different for time > 0.1 s, but we had bugs
        # with dwell time > 4s, so let's directly test both.
        self.ccd.exposureTime.value = 5  # s
        ars.repetition.value = (2, 3)
        exp_shape = ars.repetition.value[::-1]
        num_ar = numpy.prod(ars.repetition.value)

        # Start acquisition
        timeout = 1 + 1.5 * sas.estimateAcquisitionTime()
        start = time.time()
        f = sas.acquire()

        # wait until it's over
        data = f.result(timeout)
        dur = time.time() - start
        logging.debug("Acquisition took %g s", dur)
        self.assertTrue(f.done())
        self.assertEqual(len(data), len(sems.raw) + len(ars.raw))
        self.assertEqual(len(sems.raw), 1)
        self.assertEqual(sems.raw[0].shape, exp_shape)
        self.assertEqual(len(ars.raw), num_ar)
        md = ars.raw[0].metadata
        self.assertIn(model.MD_POS, md)
        self.assertIn(model.MD_AR_POLE, md)

        # Short acquisition (< 0.1s)
        self.ccd.exposureTime.value = 0.03  # s
        ars.repetition.value = (30, 20)
        exp_shape = ars.repetition.value[::-1]
        num_ar = numpy.prod(ars.repetition.value)

        # Start acquisition
        timeout = 1 + 1.5 * sas.estimateAcquisitionTime()
        start = time.time()
        f = sas.acquire()

        # wait until it's over
        data = f.result(timeout)
        dur = time.time() - start
        logging.debug("Acquisition took %g s", dur)
        self.assertTrue(f.done())
        self.assertEqual(len(data), len(sems.raw) + len(ars.raw))
        self.assertEqual(len(sems.raw), 1)
        self.assertEqual(sems.raw[0].shape, exp_shape)
        self.assertEqual(len(ars.raw), num_ar)
        md = ars.raw[0].metadata
        self.assertIn(model.MD_POS, md)
        self.assertIn(model.MD_AR_POLE, md)
예제 #26
0
def acquire_spec(wls, wle, res, dt, filename):
    """
    wls (float): start wavelength in m
    wle (float): end wavelength in m
    res (int): number of points to acquire
    dt (float): dwell time in seconds
    filename (str): filename to save to
    """
    # TODO: take a progressive future to update and know if it's the end

    ebeam = model.getComponent(role="e-beam")
    sed = model.getComponent(role="se-detector")
    mchr = model.getComponent(role="monochromator")
    try:
        sgrh = model.getComponent(role="spectrograph")
    except LookupError:
        sgrh = model.getComponent(role="spectrograph-dedicated")
    opm = acq.path.OpticalPathManager(model.getMicroscope())

    prev_dt = ebeam.dwellTime.value
    prev_res = ebeam.resolution.value
    prev_scale = ebeam.scale.value
    prev_trans = ebeam.translation.value
    prev_wl = sgrh.position.value["wavelength"]

    # Create a stream for monochromator scan
    mchr_s = MonochromatorScanStream("Spectrum", mchr, ebeam, sgrh, opm=opm)
    mchr_s.startWavelength.value = wls
    mchr_s.endWavelength.value = wle
    mchr_s.numberOfPixels.value = res
    mchr_s.dwellTime.value = dt
    mchr_s.emtTranslation.value = ebeam.translation.value

    # Create SEM survey stream
    survey_s = stream.SEMStream(
        "Secondary electrons survey",
        sed,
        sed.data,
        ebeam,
        emtvas={"translation", "scale", "resolution", "dwellTime"},
    )
    # max FoV, with scale 4
    survey_s.emtTranslation.value = (0, 0)
    survey_s.emtScale.value = (4, 4)
    survey_s.emtResolution.value = (v / 4 for v in ebeam.resolution.range[1])
    survey_s.emtDwellTime.value = 10e-6  # 10µs is hopefully enough

    # Acquire using the acquisition manager
    # Note: the monochromator scan stream is unknown to the acquisition manager,
    # so it'll be done last
    expt = acq.estimateTime([survey_s, mchr_s])
    f = acq.acquire([survey_s, mchr_s])

    try:
        # Note: the timeout is important, as it allows to catch KeyboardInterrupt
        das, e = f.result(2 * expt + 1)
    except KeyboardInterrupt:
        logging.info("Stopping before end of acquisition")
        f.cancel()
        return
    finally:
        logging.debug("Restoring hardware settings")
        if prev_res != (1, 1):
            ebeam.resolution.value = prev_res
        ebeam.dwellTime.value = prev_dt
        sgrh.moveAbs({"wavelength": prev_wl})
        ebeam.scale.value = prev_scale
        ebeam.translation.value = prev_trans
        if prev_res != (1, 1):
            ebeam.resolution.value = prev_res
        ebeam.dwellTime.value = prev_dt

    if e:
        logging.error("Acquisition failed: %s", e)

    if das:
        # Save the file
        exporter = dataio.find_fittest_converter(filename)
        exporter.export(filename, das)
        logging.info("Spectrum successfully saved to %s", filename)
        input("Press Enter to close.")
예제 #27
0
 def setUp(self):
     self.stream = stream.SEMStream("Single beam", self.sed, self.sed.data, self.ebeam,
                                    focuser=self.efocuser,  # Not used during acquisition, but done by the GUI
                                    hwemtvas={"scale", "dwellTime", "horizontalFoV"})
예제 #28
0
    def __init__(self, microscope, main_app):
        super(QuickCLPlugin, self).__init__(microscope, main_app)
        # Can only be used with a SPARC with CL detector (or monochromator)
        if not microscope:
            return
        main_data = self.main_app.main_data
        if not main_data.ebeam or not (main_data.cld
                                       or main_data.monochromator):
            return

        self.conf = get_acqui_conf()
        self.filename = model.StringVA("")
        self.filename.subscribe(self._on_filename)

        self.expectedDuration = model.VigilantAttribute(1,
                                                        unit="s",
                                                        readonly=True)

        self.hasDatabar = model.BooleanVA(False)

        # Only put the VAs that do directly define the image as local, everything
        # else should be global. The advantage is double: the global VAs will
        # set the hardware even if another stream (also using the e-beam) is
        # currently playing, and if the VAs are changed externally, the settings
        # will be displayed correctly (and not reset the values on next play).
        emtvas = set()
        hwemtvas = set()
        for vaname in get_local_vas(main_data.ebeam,
                                    main_data.hw_settings_config):
            if vaname in ("resolution", "dwellTime", "scale"):
                emtvas.add(vaname)
            else:
                hwemtvas.add(vaname)

        self._sem_stream = stream.SEMStream(
            "Secondary electrons",
            main_data.sed,
            main_data.sed.data,
            main_data.ebeam,
            focuser=main_data.ebeam_focus,
            hwemtvas=hwemtvas,
            hwdetvas=None,
            emtvas=emtvas,
            detvas=get_local_vas(main_data.sed, main_data.hw_settings_config),
        )

        # This stream is used both for rendering and acquisition.
        # LiveCLStream is more or less like a SEMStream, but ensures the icon in
        # the merge slider is correct, and provide a few extra.
        if main_data.cld:
            self._cl_stream = LiveCLStream(
                "CL intensity",
                main_data.cld,
                main_data.cld.data,
                main_data.ebeam,
                focuser=main_data.ebeam_focus,
                emtvas=emtvas,
                detvas=get_local_vas(main_data.cld,
                                     main_data.hw_settings_config),
                opm=main_data.opm,
            )
            # TODO: allow to type in the resolution of the CL?
            # TODO: add the cl-filter axis (or reset it to pass-through?)
            self.logScale = self._cl_stream.logScale

            if hasattr(self._cl_stream, "detGain"):
                self._cl_stream.detGain.subscribe(self._on_cl_gain)

            # Update the acquisition time when it might change (ie, the scan settings
            # change)
            self._cl_stream.emtDwellTime.subscribe(self._update_exp_dur)
            self._cl_stream.emtResolution.subscribe(self._update_exp_dur)

        # Note: for now we don't really support SPARC with BOTH CL-detector and
        # monochromator.
        if main_data.monochromator:
            self._mn_stream = LiveCLStream(
                "Monochromator",
                main_data.monochromator,
                main_data.monochromator.data,
                main_data.ebeam,
                focuser=main_data.ebeam_focus,
                emtvas=emtvas,
                detvas=get_local_vas(main_data.monochromator,
                                     main_data.hw_settings_config),
                opm=main_data.opm,
            )
            self._mn_stream.emtDwellTime.subscribe(self._update_exp_dur)
            self._mn_stream.emtResolution.subscribe(self._update_exp_dur)

            # spg = self._getAffectingSpectrograph(main_data.spectrometer)
            # TODO: show axes

        self._dlg = None

        self.addMenu("Acquisition/Quick CL...\tF2", self.start)
예제 #29
0
    def test_acq_spec(self):
        """
        Test short & long acquisition for Spectrometer
        """
        # Create the stream
        sems = stream.SEMStream("test sem", self.sed, self.sed.data,
                                self.ebeam)
        specs = stream.SpectrumStream("test spec", self.spec, self.spec.data,
                                      self.ebeam)
        sps = stream.SEMSpectrumMDStream("test sem-spec", sems, specs)

        specs.roi.value = (0.15, 0.6, 0.8, 0.8)

        # Long acquisition (small rep to avoid being too long) > 0.1s
        self.spec.exposureTime.value = 0.3  # s
        specs.repetition.value = (5, 6)
        exp_shape = specs.repetition.value[::-1]

        # Start acquisition
        timeout = 1 + 1.5 * sps.estimateAcquisitionTime()
        start = time.time()
        f = sps.acquire()

        # wait until it's over
        data = f.result(timeout)
        dur = time.time() - start
        logging.debug("Acquisition took %g s", dur)
        self.assertTrue(f.done())
        self.assertEqual(len(data), len(sems.raw) + len(specs.raw))
        self.assertEqual(len(sems.raw), 1)
        self.assertEqual(sems.raw[0].shape, exp_shape)
        self.assertEqual(len(specs.raw), 1)
        sshape = specs.raw[0].shape
        self.assertEqual(len(sshape), 5)
        self.assertGreater(sshape[0], 1)  # should have at least 2 wavelengths
        sem_md = sems.raw[0].metadata
        spec_md = specs.raw[0].metadata
        self.assertAlmostEqual(sem_md[model.MD_POS], spec_md[model.MD_POS])
        self.assertAlmostEqual(sem_md[model.MD_PIXEL_SIZE],
                               spec_md[model.MD_PIXEL_SIZE])

        # Short acquisition (< 0.1s)
        self.spec.exposureTime.value = 0.01  # s
        specs.repetition.value = (25, 60)
        exp_shape = specs.repetition.value[::-1]

        # Start acquisition
        timeout = 1 + 1.5 * sps.estimateAcquisitionTime()
        start = time.time()
        f = sps.acquire()

        # wait until it's over
        data = f.result(timeout)
        dur = time.time() - start
        logging.debug("Acquisition took %g s", dur)
        self.assertTrue(f.done())
        self.assertEqual(len(data), len(sems.raw) + len(specs.raw))
        self.assertEqual(len(sems.raw), 1)
        self.assertEqual(sems.raw[0].shape, exp_shape)
        self.assertEqual(len(specs.raw), 1)
        sshape = specs.raw[0].shape
        self.assertEqual(len(sshape), 5)
        self.assertGreater(sshape[0], 1)  # should have at least 2 wavelengths
        sem_md = sems.raw[0].metadata
        spec_md = specs.raw[0].metadata
        self.assertAlmostEqual(sem_md[model.MD_POS], spec_md[model.MD_POS])
        self.assertAlmostEqual(sem_md[model.MD_PIXEL_SIZE],
                               spec_md[model.MD_PIXEL_SIZE])