Ejemplo n.º 1
0
 def clip_tiling_area_to_range(w, h, pos, tiling_rng):
     """
     Finds the intersection between the requested tiling area and the tiling range.
     w (float): width of the tiling area
     h (float): height of the tiling area
     pos (dict -> float): current position of the stage
     tiling_rng (dict -> list): the tiling range along x and y axes as
       (xmin, ymin, xmax, ymax), or (xmin, ymax, xmax, ymin)
     return (None or tuple of 4 floats): None if there is no intersection, or
       the rectangle representing the intersection as (xmin, ymin, xmax, ymax).
     """
     area_req = (pos["x"] - w / 2, pos["y"] - h / 2, pos["x"] + w / 2,
                 pos["y"] + h / 2)
     # clip the tiling area, if needed (or find the intersection between the active range and the requested area)
     return rect_intersect(area_req,
                           (tiling_rng["x"][0], tiling_rng["y"][1],
                            tiling_rng["x"][1], tiling_rng["y"][0]))
Ejemplo n.º 2
0
def convert_roi_phys_to_ccd(ccd, roi):
    """
    Convert the ROI in physical coordinates into a optical detector (ccd) ROI (in pixels).
    :param roi: (4 floats) The roi (ltrb) position in m.
    :returns: (4 ints or None) The roi (ltrb) position in pixels, or None if no intersection.
    """
    ccd_rect = get_ccd_fov(ccd)
    logging.info("CCD FoV = %s", ccd_rect)
    phys_width = (ccd_rect[2] - ccd_rect[0], ccd_rect[3] - ccd_rect[1])

    logging.info("phys width: " + str(phys_width))
    logging.info("roi: " + str(roi))
    logging.info("ccd rect: " + str(ccd_rect))

    # convert to a proportional ROI
    proi = (
        (roi[0] - ccd_rect[0]) / phys_width[0],
        (roi[1] - ccd_rect[1]) / phys_width[1],
        (roi[2] - ccd_rect[0]) / phys_width[0],
        (roi[3] - ccd_rect[1]) / phys_width[1],
    )
    # inverse Y (because physical Y goes down, while pixel Y goes up)
    proi = (proi[0], 1 - proi[3], proi[2], 1 - proi[1])
    logging.info("proi: " + str(proi))

    # convert to pixel values, rounding to slightly bigger area
    res = ccd.resolution.value
    pxroi = (
        int(proi[0] * res[0]),
        int(proi[1] * res[1]),
        int(math.ceil(proi[2] * res[0])),
        int(math.ceil(proi[3] * res[1])),
    )

    logging.info("pxroi: " + str(pxroi))

    # Limit the ROI to the one visible in the FoV
    trunc_roi = util.rect_intersect(pxroi, (0, 0) + res)
    if trunc_roi is None:
        return None
    if trunc_roi != pxroi:
        logging.warning(
            "CCD FoV doesn't cover the whole ROI, it would need "
            "a ROI of %s in CCD referential.", pxroi)

    return trunc_roi
Ejemplo n.º 3
0
 def get_ROA_rect(w, h, pos, tiling_rng):
     """
     Finds the intersection between the requested tiling area 
         and the tiling range.
     w (float): width of the tiling area
     h (float): height of the tiling area
     pos (dict -> float): current position of the stage
     tiling_rng (dict -> list): the tiling range along x and y axes
     """
     tl = pos["x"] - w / 2, pos["y"] + h / 2
     br = pos["x"] + w / 2, pos["y"] - h / 2
     # clip the tiling area, if needed (or find the intersection between the active range and the requested area)
     # Note: the input is LTRB. The output is LBRT assuming y axis upwards, or LTRB assuming y axis downwards.
     rect_pts = rect_intersect((tl[0], tl[1], br[0], br[1]),
                               (tiling_rng["x"][0], tiling_rng["y"][1],
                                tiling_rng["x"][1], tiling_rng["y"][0]))
     return rect_pts
Ejemplo n.º 4
0
def convert_roi_phys_to_ccd(ccd, roi):
    """
    Convert the ROI in physical coordinates into a CCD ROI (in pixels)
    roi (4 floats): ltrb positions in m
    return (4 ints or None): ltrb positions in pixels, or None if no intersection
    """
    ccd_rect = get_ccd_fov(ccd)
    logging.info("CCD FoV = %s", ccd_rect)
    phys_width = (ccd_rect[2] - ccd_rect[0],
                  ccd_rect[3] - ccd_rect[1])

    logging.info("phys width: " + str(phys_width))
    logging.info("roi: " + str(roi))
    logging.info("ccd rect: " + str(ccd_rect))

    # convert to a proportional ROI
    proi = ((roi[0] - ccd_rect[0]) / phys_width[0],
            (roi[1] - ccd_rect[1]) / phys_width[1],
            (roi[2] - ccd_rect[0]) / phys_width[0],
            (roi[3] - ccd_rect[1]) / phys_width[1],
            )
    # inverse Y (because physical Y goes down, while pixel Y goes up)
    proi = (proi[0], 1 - proi[3], proi[2], 1 - proi[1])
    logging.info("proi: " + str(proi))

    # convert to pixel values, rounding to slightly bigger area
    shape = ccd.shape[0:2]
    pxroi = (int(proi[0] * shape[0]),
             int(proi[1] * shape[1]),
             int(math.ceil(proi[2] * shape[0])),
             int(math.ceil(proi[3] * shape[1])),
             )

    logging.info("pxroi: " + str(pxroi))

    # Limit the ROI to the one visible in the FoV
    trunc_roi = util.rect_intersect(pxroi, (0, 0) + shape)
    if trunc_roi is None:
        return None
    if trunc_roi != pxroi:
        logging.warning("CCD FoV doesn't cover the whole ROI, it would need "
                        "a ROI of %s in CCD referential.", pxroi)

    return trunc_roi
Ejemplo n.º 5
0
    def convert_roi_phys_to_ccd(self, roi):
        """
        Convert the ROI in physical coordinates into a CCD ROI (in pixels)
        roi (4 floats): ltrb positions in m
        return (4 ints or None): ltrb positions in pixels, or None if no intersection
        """
        ccd_rect = self.get_ccd_fov()
        logging.debug("CCD FoV = %s", ccd_rect)
        phys_width = (ccd_rect[2] - ccd_rect[0], ccd_rect[3] - ccd_rect[1])

        # convert to a proportional ROI
        proi = (
            (roi[0] - ccd_rect[0]) / phys_width[0],
            (roi[1] - ccd_rect[1]) / phys_width[1],
            (roi[2] - ccd_rect[0]) / phys_width[0],
            (roi[3] - ccd_rect[1]) / phys_width[1],
        )
        # inverse Y (because physical Y goes down, while pixel Y goes up)
        proi = (proi[0], 1 - proi[3], proi[2], 1 - proi[1])

        # convert to pixel values, rounding to slightly bigger area
        shape = self.ccd.shape[0:2]
        pxroi = (
            int(proi[0] * shape[0]),
            int(proi[1] * shape[1]),
            int(math.ceil(proi[2] * shape[0])),
            int(math.ceil(proi[3] * shape[1])),
        )

        # Limit the ROI to the one visible in the FoV
        trunc_roi = util.rect_intersect(pxroi, (0, 0) + shape)
        if trunc_roi is None:
            return None
        if trunc_roi != pxroi:
            logging.warning(
                "CCD FoV doesn't cover the whole ROI, it would need "
                "a ROI of %s in CCD referential.", pxroi)

        return trunc_roi
Ejemplo n.º 6
0
    def test_clipping(self):

        tmp = "{}: {} - {} -> {}"

        for bb in bounding_boxes:
            outside, touching, overlap = relative_boxes(bb)

            for b in outside:
                r = util.rect_intersect(b, bb)
                msg = tmp.format("outside", b, bb, r)
                self.assertIsNone(r, msg)

            for b in touching:
                r = util.rect_intersect(b, bb)
                msg = tmp.format("touching", b, bb, r)
                self.assertIsNone(r, msg)

            for b in overlap:
                r = util.rect_intersect(b, bb)
                msg = tmp.format("overlap", b, bb, r)
                self.assertIsNotNone(r, msg)

                # 'Manual' checks
                if bb == (-1, -1, 1, 1):
                    if b[:2] == (-2, -2):
                        self.assertEqual(r, (-1, -1, 0, 0), msg)
                    elif b[:2] == (0, -1):
                        self.assertEqual(r, (0, -1, 1, 1), msg)
                    elif b[:2] == (0, 0):
                        self.assertEqual(r, (0, 0, 1, 1), msg)

            # full and exact overlap
            b = bb
            r = util.rect_intersect(b, bb)
            self.assertEqual(r, bb)

            # inner overlap
            b = (bb[0] + 1, bb[1] + 1, bb[2], bb[3])
            r = util.rect_intersect(b, bb)
            self.assertEqual(r, b)

            # overflowing overlap
            b = (bb[0] - 1, bb[1] - 1, bb[2] + 1, bb[2] + 1)
            r = util.rect_intersect(b, bb)
            self.assertEqual(r, bb)
Ejemplo n.º 7
0
    def test_clipping(self):

        tmp = "{}: {} - {} -> {}"

        for bb in bounding_boxes:
            outside, touching, overlap = relative_boxes(bb)

            for b in outside:
                r = util.rect_intersect(b, bb)
                msg = tmp.format("outside", b, bb, r)
                self.assertIsNone(r, msg)

            for b in touching:
                r = util.rect_intersect(b, bb)
                msg = tmp.format("touching", b, bb, r)
                self.assertIsNone(r, msg)

            for b in overlap:
                r = util.rect_intersect(b, bb)
                msg = tmp.format("overlap", b, bb, r)
                self.assertIsNotNone(r, msg)

                # 'Manual' checks
                if bb == (-1, -1, 1, 1):
                    if b[:2] == (-2, -2):
                        self.assertEqual(r, (-1, -1, 0, 0), msg)
                    elif b[:2] == (0, -1):
                        self.assertEqual(r, (0, -1, 1, 1), msg)
                    elif b[:2] == (0, 0):
                        self.assertEqual(r, (0, 0, 1, 1), msg)

            # full and exact overlap
            b = bb
            r = util.rect_intersect(b, bb)
            self.assertEqual(r, bb)

            # inner overlap
            b = (bb[0] + 1, bb[1] + 1, bb[2], bb[3])
            r = util.rect_intersect(b, bb)
            self.assertEqual(r, b)

            # overflowing overlap
            b = (bb[0] - 1, bb[1] - 1, bb[2] + 1, bb[2] + 1)
            r = util.rect_intersect(b, bb)
            self.assertEqual(r, bb)
Ejemplo n.º 8
0
    def convert_roi_phys_to_ccd(self, roi):
        """
        Convert the ROI in physical coordinates into a CCD ROI (in pixels)
        roi (4 floats): ltrb positions in m
        return (4 ints or None): ltrb positions in pixels, or 
        """
        ccd_rect = self.get_ccd_fov()
        logging.debug("CCD FoV = %s", ccd_rect)
        phys_width = (ccd_rect[2] - ccd_rect[0],
                      ccd_rect[3] - ccd_rect[1])

        # convert to a proportional ROI
        proi = ((roi[0] - ccd_rect[0]) / phys_width[0],
                (roi[1] - ccd_rect[1]) / phys_width[1],
                (roi[2] - ccd_rect[0]) / phys_width[0],
                (roi[3] - ccd_rect[1]) / phys_width[1],
                )
        # ensure it's in ltbr order
        proi = util.normalize_rect(proi)

        # convert to pixel values, rounding to slightly bigger area
        shape = self.ccd.shape[0:2]
        pxroi = (int(proi[0] * shape[0]),
                 int(proi[1] * shape[1]),
                 int(math.ceil(proi[2] * shape[0])),
                 int(math.ceil(proi[3] * shape[1])),
                 )

        # Limit the ROI to the one visible in the FoV
        trunc_roi = util.rect_intersect(pxroi, (0, 0) + shape)
        if trunc_roi is None:
            return None
        if trunc_roi != pxroi:
            logging.warning("CCD FoV doesn't cover the whole ROI, it would need "
                            "a ROI of %s in CCD referential.", pxroi)

        return trunc_roi