예제 #1
0
    def test_whole_procedure(self):
        """
        Test the whole procedure (acquire + stitch) of acquireTiledArea function
        """
        # With fm streams
        settings_obs = SettingsObserver([self.stage])

        fm_fov = compute_camera_fov(self.ccd)
        # Using "songbird-sim-ccd.h5" in simcam with tile max_res: (260, 348)
        area = (0, 0, fm_fov[0] * 4, fm_fov[1] * 4)  # left, top, right, bottom
        overlap = 0.2
        self.stage.moveAbs({'x': 0, 'y': 0}).result()
        future = acquireTiledArea(self.fm_streams,
                                  self.stage,
                                  area=area,
                                  overlap=overlap,
                                  settings_obs=settings_obs)
        data = future.result()
        self.assertEqual(future._state, FINISHED)
        self.assertEqual(len(data), 2)
        self.assertIsInstance(data[0], odemis.model.DataArray)
        self.assertEqual(len(data[0].shape), 2)

        # With sem stream
        area = (0, 0, 0.00001, 0.00001)
        self.stage.moveAbs({'x': 0, 'y': 0}).result()
        future = acquireTiledArea(self.sem_streams,
                                  self.stage,
                                  area=area,
                                  overlap=overlap)
        data = future.result()
        self.assertEqual(future._state, FINISHED)
        self.assertEqual(len(data), 1)
        self.assertIsInstance(data[0], model.DataArray)
        self.assertEqual(len(data[0].shape), 2)
예제 #2
0
파일: _tiledacq.py 프로젝트: lanery/odemis
 def _getFov(self, sd):
     """
     sd (Stream or DataArray): If it's a stream, it must be a live stream,
       and the FoV will be estimated based on the settings.
     return (float, float): width, height in m
     """
     if isinstance(sd, model.DataArray):
         # The actual FoV, as the data recorded it
         return (sd.shape[0] * sd.metadata[model.MD_PIXEL_SIZE][0],
                 sd.shape[1] * sd.metadata[model.MD_PIXEL_SIZE][1])
     elif isinstance(sd, Stream):
         # Estimate the FoV, based on the emitter/detector settings
         if isinstance(sd, SEMStream):
             return compute_scanner_fov(sd.emitter)
         elif isinstance(sd, CameraStream):
             return compute_camera_fov(sd.detector)
         elif isinstance(sd, RepetitionStream):
             # CL, Spectrum, AR
             ebeam = sd.emitter
             global_fov = (ebeam.shape[0] * ebeam.pixelSize.value[0],
                           ebeam.shape[1] * ebeam.pixelSize.value[1])
             l, t, r, b = sd.roi.value
             fov = abs(r - l) * global_fov[0], abs(b - t) * global_fov[1]
             return fov
         else:
             raise TypeError("Unsupported Stream %s" % (sd, ))
     else:
         raise TypeError("Unsupported object")
예제 #3
0
    def test_compressed_stack(self):
        """
       Test the whole procedure (acquire compressed zstack + stitch) of acquireTiledArea function
       """
        # With fm streams
        settings_obs = SettingsObserver([self.stage])
        fm_fov = compute_camera_fov(self.ccd)
        # Using "songbird-sim-ccd.h5" in simcam with tile max_res: (260, 348)
        area = (0, 0, fm_fov[0] * 2, fm_fov[1] * 2)  # left, top, right, bottom
        overlap = 0.2
        focus_value = self.focus.position.value['z']
        zsteps = 3
        # Create focus zlevels from the given zsteps number
        zlevels = numpy.linspace(focus_value - (zsteps / 2 * 1e-6),
                                 focus_value + (zsteps / 2 * 1e-6),
                                 zsteps).tolist()

        future = acquireTiledArea(self.fm_streams,
                                  self.stage,
                                  area=area,
                                  overlap=overlap,
                                  settings_obs=settings_obs,
                                  zlevels=zlevels)
        data = future.result()
        self.assertTrue(future.done())
        self.assertEqual(len(data), 2)
        self.assertIsInstance(data[0], model.DataArray)
        self.assertEqual(len(data[0].shape), 2)
예제 #4
0
    def test_move_to_tiles(self):
        """
        Test moving the stage to a tile based on its index
        """
        area = (-0.001, -0.001, 0.001, 0.001)
        overlap = 0.2
        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=area,
            overlap=overlap,
            future=model.InstantaneousFuture())
        fov = compute_camera_fov(self.ccd)
        exp_shift = fov[0] * (1 - overlap), fov[1] * (1 - overlap)
        # move to starting position (left, top)
        starting_pos = tiled_acq_task._starting_pos
        self.stage.moveAbs(starting_pos).result()
        logging.debug("Starting position: %s", starting_pos)
        # no change in movement
        tiled_acq_task._moveToTile((0, 0), (0, 0), fov)
        assert_pos_almost_equal(self.stage.position.value,
                                starting_pos,
                                atol=100e-9,
                                match_all=False)

        # Note that we cannot predict precisely, as the algorithm may choose to spread
        # more or less the tiles to fit within the area.
        tiled_acq_task._moveToTile((1, 0), (0, 0), fov)  # move right on x
        exp_pos = {'x': starting_pos["x"] + exp_shift[0] / 2}
        assert_pos_almost_equal(self.stage.position.value,
                                exp_pos,
                                atol=10e-6,
                                match_all=False)

        tiled_acq_task._moveToTile((1, 1), (1, 0), fov)  # move down on y
        exp_pos = {
            'x': starting_pos["x"] + exp_shift[0] / 2,
            'y': starting_pos["y"] - exp_shift[1] / 2
        }
        assert_pos_almost_equal(self.stage.position.value,
                                exp_pos,
                                atol=10e-6,
                                match_all=False)

        tiled_acq_task._moveToTile((0, 1), (1, 1), fov)  # move back on x
        exp_pos = {
            'x': starting_pos["x"],
            'y': starting_pos["y"] - exp_shift[1] / 2
        }
        assert_pos_almost_equal(self.stage.position.value,
                                exp_pos,
                                atol=10e-6,
                                match_all=False)
예제 #5
0
    def get_ccd_fov(self):
        """
        Returns the (theoretical) field of view of the CCD.
        returns (tuple of 4 floats): position in physical coordinates m (l, t, r, b)
        """
        width = compute_camera_fov(self.ccd)
        phys_rect = [-width[0] / 2,  # left
                     - width[1] / 2,  # top
                     width[0] / 2,  # right
                     width[1] / 2]  # bottom

        return phys_rect
예제 #6
0
파일: comp_test.py 프로젝트: effting/odemis
    def test_camera_fov(self):
        # Move a little bit out of the origin, to make it less easy
        self.stage.moveAbsSync({"x": 1e-3, "y": 5e-3})

        fov = compute_camera_fov(self.ccd)
        rect = get_fov_rect(self.ccd, fov)

        # Compare to the actual FoV of an acquired image
        im = self.ccd.data.get()

        pxs_im = im.metadata[model.MD_PIXEL_SIZE]
        fov_im = im.shape[1] * pxs_im[0], im.shape[0] * pxs_im[1]
        self.assertEqual(fov, fov_im)
        center_im = im.metadata[model.MD_POS]
        rect_im = (center_im[0] - fov_im[0] / 2, center_im[1] - fov_im[1] / 2,
                   center_im[0] + fov_im[0] / 2, center_im[1] + fov_im[1] / 2)
        self.assertEqual(rect, rect_im)
예제 #7
0
    def test_get_number_of_tiles(self):
        """
        Test get number of tiles using different values of total area, fov and overlap
        :return:
        """
        fov = compute_camera_fov(self.ccd)

        # use area as multiples of fov (in case simulator parameters changed)
        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, 2 * fov[0], 2 * fov[1]),
            overlap=0.2,
            future=model.InstantaneousFuture())
        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (3, 3))

        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, 2 * fov[0], 2 * fov[1]),
            overlap=0,
            future=model.InstantaneousFuture())
        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (2, 2))

        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, fov[0] / 2, fov[1] / 2),  # smaller than fov
            overlap=0,
            future=model.InstantaneousFuture())

        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (1, 1))

        # Precisely 1 x 2 FoV => should give 1 x 2 tiles
        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, fov[0], 2 * fov[1]),
            overlap=0,
            future=model.InstantaneousFuture())
        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (1, 2))
예제 #8
0
파일: comp_test.py 프로젝트: delmic/odemis
    def test_camera_fov(self):
        # Move a little bit out of the origin, to make it less easy
        self.stage.moveAbsSync({"x": 1e-3, "y": 5e-3})

        fov = compute_camera_fov(self.ccd)
        rect = get_fov_rect(self.ccd, fov)

        # Compare to the actual FoV of an acquired image
        im = self.ccd.data.get()

        pxs_im = im.metadata[model.MD_PIXEL_SIZE]
        fov_im = im.shape[1] * pxs_im[0], im.shape[0] * pxs_im[1]
        self.assertEqual(fov, fov_im)
        center_im = im.metadata[model.MD_POS]
        rect_im = (center_im[0] - fov_im[0] / 2,
                   center_im[1] - fov_im[1] / 2 ,
                   center_im[0] + fov_im[0] / 2,
                   center_im[1] + fov_im[1] / 2)
        self.assertEqual(rect, rect_im)
예제 #9
0
    def test_area(self):
        """
        Test the acquired area matches the requested area
        """
        fm_fov = compute_camera_fov(self.ccd)
        # Using "songbird-sim-ccd.h5" in simcam with tile max_res: (260, 348)
        area = (0, 0, fm_fov[0] * 2, fm_fov[1] * 3)  # left, bottom, right, top
        overlap = 0.2

        # No focuser, to make it faster, and it doesn't affect the FoV
        fs = stream.FluoStream("fluo1", self.ccd, self.ccd.data, self.light,
                               self.light_filter)
        future = acquireTiledArea([fs],
                                  self.stage,
                                  area=area,
                                  overlap=overlap,
                                  registrar=REGISTER_IDENTITY,
                                  weaver=WEAVER_MEAN)
        data = future.result()
        self.assertIsInstance(data[0], model.DataArray)
        self.assertEqual(len(data[0].shape), 2)

        # The center should be almost precisely at the center of the request RoA,
        # modulo the stage precision (which is very good on the simulator).
        # The size can be a little bit bigger (but never smaller), as it's
        # rounded up to a tile.
        bbox = img.getBoundingBox(data[0])
        data_center = data[0].metadata[model.MD_POS]
        area_center = (area[0] + area[2]) / 2, (area[1] + area[3]) / 2
        logging.debug("Expected area: %s %s, actual area: %s %s", area,
                      area_center, bbox, data_center)
        self.assertAlmostEqual(data_center[0], area_center[0],
                               delta=1e-6)  # +- 1µm
        self.assertAlmostEqual(data_center[1], area_center[1],
                               delta=1e-6)  # +- 1µm

        self.assertTrue(area[0] - fm_fov[0] / 2 <= bbox[0] <= area[0])
        self.assertTrue(area[1] - fm_fov[1] / 2 <= bbox[1] <= area[1])
        self.assertTrue(area[2] <= bbox[2] <= area[2] + fm_fov[0] / 2)
        self.assertTrue(area[3] <= bbox[3] <= area[3] + fm_fov[1] / 2)
예제 #10
0
    def calc_stream_size(self):
        """ Calculate the physical size of the current view """

        p_size = None
        # Calculate the stream size (by using the latest stream used)
        for strm in self._data_model.streams.value:
            try:
                bbox = strm.getBoundingBox()
                p_size = (bbox[2] - bbox[0], bbox[3] - bbox[1])
                break
            except ValueError:  # no data (yet) on the stream
                pass

        if p_size is None:
            # fallback to using the SEM FoV or CCD
            if self.main_data.ebeam:
                p_size = comp.compute_scanner_fov(self.main_data.ebeam)
            elif self.main_data.ccd:
                p_size = comp.compute_camera_fov(self.main_data.ccd)
            else:
                logging.debug(u"Unknown FoV, will guess 100 µm")
                p_size = (100e-6, 100e-6)  # m

        return p_size
예제 #11
0
    def test_get_number_of_tiles(self):
        """
        Test get number of tiles using different values of total area, fov and overlap
        :return:
        """
        fov = compute_camera_fov(self.ccd)
        # use area as multiples of fov (in case simulator parameters changed)

        # Smaller than FoV => 1x1
        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, fov[0] / 2, fov[1] / 2),
            overlap=0,
            future=model.InstantaneousFuture())

        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (1, 1))

        # Precisely 2x2 FoV, without overlap => 2x2 tiles
        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, 2 * fov[0], 2 * fov[1]),
            overlap=0,
            future=model.InstantaneousFuture())
        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (2, 2))

        # Precisely 1 x 2 FoV, without overlap => should give 1 x 2 tiles
        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, fov[0], 2 * fov[1]),
            overlap=0,
            future=model.InstantaneousFuture())
        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (1, 2))

        # Precisely 0.8 FoV, with overlap 0.2 => 1x1 tiles
        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, 0.8 * fov[0], 0.8 * fov[1]),
            overlap=0.2,
            future=model.InstantaneousFuture())
        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (1, 1))

        # 2x3 FoV with overlap 0.2 => 3x4
        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, 2 * fov[0], 3 * fov[1]),
            overlap=0.2,
            future=model.InstantaneousFuture())
        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (3, 4))

        # Precisely 4*0.8x7*0.8 FoV, with overlap 0.2 => 4x7 tiles
        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, 4 * 0.8 * fov[0], 7 * 0.8 * fov[1]),
            overlap=0.2,
            future=model.InstantaneousFuture())
        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (4, 7))

        # A tiny bit more 4*0.8x7*0.8 FoV, with overlap 0.2 => 4x7 tiles
        eps = 1e-12
        tiled_acq_task = TiledAcquisitionTask(
            self.fm_streams,
            self.stage,
            area=(0, 0, 4 * 0.8 * fov[0] + eps, 7 * 0.8 * fov[1] + eps),
            overlap=0.2,
            future=model.InstantaneousFuture())
        num_tiles, starting_pos = tiled_acq_task._getNumberOfTiles()
        self.assertEqual(num_tiles, (4, 7))