Example #1
0
def _centre_fov(n=55, waverange=(1.0, 2.0)):
    xsky = np.array([-n, n]) * u.arcsec.to(u.deg)
    ysky = np.array([-n, n]) * u.arcsec.to(u.deg)
    sky_hdr = imp_utils.header_from_list_of_xy(xsky, ysky, 1/3600.)
    imp_hdr = imp_utils.header_from_list_of_xy([-n, n], [-n, n], 1, "D")
    imp_hdr.update(sky_hdr)
    fov = FieldOfView(imp_hdr, waverange=waverange*u.um, area=1*u.m**2)

    return fov
Example #2
0
def _centre_micado_fov(n=128, waverange=(1.9, 2.4)):
    """ n [arcsec] """
    xsky = np.array([-n, n]) * u.arcsec.to(u.deg)
    ysky = np.array([-n, n]) * u.arcsec.to(u.deg)
    pixscale = 0.004/3600.
    sky_hdr = imp_utils.header_from_list_of_xy(xsky, ysky, pixscale)
    imp_hdr = imp_utils.header_from_list_of_xy([-n, n], [-n, n], pixscale, "D")
    imp_hdr.update(sky_hdr)
    fov = FieldOfView(imp_hdr, waverange=waverange*u.um, area=1*u.m**2)

    return fov
Example #3
0
 def test_is_the_header_split_into_the_right_amount_of_chunks(self):
     hdr = imp_utils.header_from_list_of_xy([-1.024, 1.024],
                                            [-1.024, 1.024], 0.002)
     hdrs = imp_utils.split_header(hdr, 128)
     area_sum = np.sum([hdr["NAXIS1"] * hdr["NAXIS2"] for hdr in hdrs])
     assert len(hdrs) == 64
     assert area_sum == hdr["NAXIS1"] * hdr["NAXIS2"]
Example #4
0
def _long_micado_slit_header():
    x = np.array([-1.5, 13.5]) / 3600.
    y = np.array([-0.01, 0.01]) / 3600.
    pix_scale_deg = 0.004 / 3600.
    header = imp_utils.header_from_list_of_xy(x, y, pix_scale_deg)
    header["APERTURE"] = 0

    return header
    def big_small_hdus(self,
                       big_wh=(20, 10),
                       big_offsets=(0, 0),
                       small_wh=(6, 3),
                       small_offsets=(0, 0),
                       pixel_scale=0.1):
        w, h = np.array(big_wh) // 2
        x = np.array([-w, -w, w, w]) + big_offsets[0]
        y = np.array([h, -h, -h, h]) + big_offsets[1]
        big = imp_utils.header_from_list_of_xy(x, y, pixel_scale)
        im = np.ones([big["NAXIS2"], big["NAXIS1"]])
        big = fits.ImageHDU(header=big, data=im)

        w, h = np.array(small_wh) // 2
        x = np.array([-w, -w, w, w]) + small_offsets[0]
        y = np.array([h, -h, -h, h]) + small_offsets[1]
        small = imp_utils.header_from_list_of_xy(x, y, pixel_scale)
        im = np.ones([small["NAXIS2"], small["NAXIS1"]])
        small = fits.ImageHDU(header=small, data=im)

        return big, small
Example #6
0
    def test_applies_dark_current_with_level_of_dit(self):
        level, dit, hw = 0.5, 10, 16
        hdr = header_from_list_of_xy([-hw, hw], [-hw, hw], 1, "D")
        dtcr = Detector(hdr)
        dtcr.meta["dit"] = dit
        dtcr.meta["ndit"] = 1
        dark_eff = DarkCurrent(value=level, **dtcr.meta)

        dtcr = dark_eff.apply_to(dtcr)

        assert np.average(dtcr.data) == 5.0
        assert np.sum(dtcr.data) == level * dit * (hw * 2)**2
    def test_DarkCurrent_plot(self):
        from scopesim.detector import Detector
        level, dit, hw = 0.5, 10, 16
        from scopesim.optics.image_plane_utils import header_from_list_of_xy
        hdr = header_from_list_of_xy([-hw, hw], [-hw, hw], 1, "D")
        eff = electronic.DarkCurrent(value=0.1, dit=10,
                                     ndit=20)  # raise error for ints!
        dtcr = Detector(hdr)

        if PLOTS:
            eff.plot(dtcr)
            plt.show()
Example #8
0
    def test_add_one_image_to_another_in_the_right_position(self):

        big = imp_utils.header_from_list_of_xy(x=np.array([-20, -20, 20, 20]),
                                               y=np.array([10, -10, -10, 10]),
                                               pixel_scale=0.1)
        im = np.zeros([big["NAXIS2"], big["NAXIS1"]])
        big = fits.ImageHDU(header=big, data=im)

        small = imp_utils.header_from_list_of_xy(
            x=np.array([-3, -3, 3, 3]) + 10,
            y=np.array([1, -1, -1, 1]) - 5,
            pixel_scale=0.1)
        im = np.ones([small["NAXIS2"], small["NAXIS1"]])
        small = fits.ImageHDU(header=small, data=im)

        big = imp_utils.add_imagehdu_to_imagehdu(small, big)
        ycen, xcen = np.array(big.data.shape) // 2
        assert np.sum(big.data[:ycen, xcen:]) == np.sum(small.data)

        if PLOTS:
            plt.imshow(big.data, origin="lower")
            plt.show()
    def test_BinnedImage_plot(self):
        """
        Not implemented yet. What do we plot here?

        """
        from scopesim.detector import Detector
        from scopesim.optics.image_plane_utils import header_from_list_of_xy
        level, dit, hw = 0.5, 10, 16
        hdr = header_from_list_of_xy([-hw, hw], [-hw, hw], 1, "D")
        dtcr = Detector(hdr)
        eff = electronic.BinnedImage(bin_size=4)
        dtcr = eff.apply_to(dtcr)
        if PLOTS:
            plt.imshow(dtcr.data)
            plt.show()
    def test_ShotNoise_plot(self):
        from scopesim.detector import Detector
        level, dit, hw = 0.5, 10, 16
        from scopesim.optics.image_plane_utils import header_from_list_of_xy
        hdr = header_from_list_of_xy([-hw, hw], [-hw, hw], 1, "D")
        eff = electronic.ShotNoise()  # Does it do something?
        dtcr = Detector(hdr)

        if PLOTS:
            fig = plt.figure(figsize=(6, 3))
            plt.subplot(121)
            eff.plot(dtcr)
            plt.subplot(122)
            eff.plot_hist(dtcr)
            plt.show()
    def test_BasicReadoutNoise_plot(self):
        from scopesim.detector import Detector
        level, dit, hw = 0.5, 10, 16
        from scopesim.optics.image_plane_utils import header_from_list_of_xy
        hdr = header_from_list_of_xy([-hw, hw], [-hw, hw], 1, "D")
        eff = electronic.BasicReadoutNoise(noise_std=1, n_channels=1, ndit=1)
        dtcr = Detector(hdr)

        if PLOTS:

            fig = plt.figure(figsize=(6, 3))
            plt.subplot(121)
            eff.plot(dtcr)
            plt.subplot(122)
            eff.plot_hist(dtcr)
            plt.show()
Example #12
0
def is_field_in_fov(fov_header, field, wcs_suffix=""):
    """
    Returns True if Source.field footprint is inside the FieldOfView footprint

    Parameters
    ----------
    fov_header : fits.Header
        Header from a FieldOfView object
    field : [astropy.Table, astropy.ImageHDU]
        Field object from a Source object
    wcs_suffix : str
        ["S", "D"] Coordinate system: Sky or Detector

    Returns
    -------
    is_inside_fov : bool

    """

    if isinstance(field, fits.ImageHDU) and \
            field.header.get("BG_SRC") is not None:
        is_inside_fov = True
    else:
        if isinstance(field, Table):
            x = list(utils.quantity_from_table("x", field,
                                               u.arcsec).to(u.deg).value)
            y = list(utils.quantity_from_table("y", field,
                                               u.arcsec).to(u.deg).value)
            s = wcs_suffix
            cdelt = utils.quantify(fov_header["CDELT1" + s], u.deg).value
            field_header = imp_utils.header_from_list_of_xy(x, y, cdelt, s)
        elif isinstance(field, (fits.ImageHDU, fits.PrimaryHDU)):
            field_header = field.header
        else:
            logging.warning("Input was neither Table nor ImageHDU: {}"
                          "".format(field))
            return False

        ext_xsky, ext_ysky = imp_utils.calc_footprint(field_header, wcs_suffix)
        fov_xsky, fov_ysky = imp_utils.calc_footprint(fov_header, wcs_suffix)

        is_inside_fov = min(ext_xsky) < max(fov_xsky) and \
                        max(ext_xsky) > min(fov_xsky) and \
                        min(ext_ysky) < max(fov_ysky) and \
                        max(ext_ysky) > min(fov_ysky)

    return is_inside_fov
Example #13
0
    def test_returns_headers(self):
        apl = ApertureList(filename="test_aperture_list.dat",
                           no_mask=False, pixel_scale=0.01)
        hdrs = apl.fov_grid()
        assert all([isinstance(hdr, fits.Header) for hdr in hdrs])

        if PLOTS:
            from scopesim.optics.image_plane import ImagePlane
            from scopesim.optics.image_plane_utils import header_from_list_of_xy
            from astropy.io.fits import ImageHDU

            x = np.array([-3, 3]) / 3600.
            y = np.array([-3, 3]) / 3600.
            pixel_scale = 0.01 / 3600
            hdr = header_from_list_of_xy(x, y, pixel_scale)
            implane = ImagePlane(hdr)

            for i in range(4):
                hdu = ImageHDU(data=apl[i].mask.astype(int)+1,
                               header=apl[i].header)
                implane.add(hdu)

            plt.imshow(implane.data, origin="lower")
            plt.show()
Example #14
0
 def test_final_header_is_smaller_for_odd_size(self, x, y, pix):
     hdr = imp_utils.header_from_list_of_xy([-1., x], [-1., y], pix)
     hdrs = imp_utils.split_header(hdr, 100)
     area_sum = np.sum([hdr["NAXIS1"] * hdr["NAXIS2"] for hdr in hdrs])
     assert area_sum == hdr["NAXIS1"] * hdr["NAXIS2"]
Example #15
0
def _basic_dtcr_header(n=20, pix_size=0.01):
    xs = [-pix_size * n / 2, pix_size * n / 2]
    hdr = header_from_list_of_xy(xs, xs, pix_size, "D")
    return hdr
Example #16
0
def extract_area_from_imagehdu(imagehdu, fov_volume):
    """
    Extracts the part of a ImageHDU that fits inside the fov_volume

    Parameters
    ----------
    imagehdu : fits.ImageHDU
        The field ImageHDU, either an image of a wavelength [um] cube
    fov_volume : dict
        Contains {"xs": [xmin, xmax], "ys": [ymin, ymax],
                  "waves": [wave_min, wave_max],
                  "xy_unit": "deg" or "mm", "wave_unit": "um"}

    Returns
    -------
    new_imagehdu : fits.ImageHDU

    """
    hdr = imagehdu.header
    new_hdr = {}

    x_hdu, y_hdu = imp_utils.calc_footprint(imagehdu)  # field edges in "deg"
    x_fov, y_fov = fov_volume["xs"], fov_volume["ys"]

    x0s, x1s = max(min(x_hdu), min(x_fov)), min(max(x_hdu), max(x_fov))
    y0s, y1s = max(min(y_hdu), min(y_fov)), min(max(y_hdu), max(y_fov))

    xp, yp = imp_utils.val2pix(hdr, np.array([x0s, x1s]), np.array([y0s, y1s]))
    (x0p, x1p), (y0p, y1p) = np.round(xp).astype(int), np.round(yp).astype(int)
    if x0p == x1p:
        x1p += 1
    if y0p == y1p:
        y1p += 1

    new_hdr = imp_utils.header_from_list_of_xy([x0s, x1s], [y0s, y1s],
                                               pixel_scale=hdr["CDELT1"])

    if hdr["NAXIS"] == 3:

        # Look 0.5*wdel past the fov edges in each direction to catch any
        # slices where the middle wavelength value doesn't fall inside the
        # fov waverange, but up to 50% of the slice is actually inside the
        # fov waverange:
        # E.g. FOV: [1.92, 2.095], HDU bin centres: [1.9, 2.0, 2.1]
        # CDELT3 = 0.1, and HDU bin edges: [1.85, 1.95, 2.05, 2.15]
        # So 1.9 slice needs to be multiplied by 0.3, and 2.1 slice should be
        # multipled by 0.45 to reach the scaled contribution of the edge slices
        # This scaling factor is:
        # f = ((hdu_bin_centre - fov_edge [+/-] 0.5 * cdelt3) % cdelt3) / cdelt3

        hdu_waves = get_cube_waveset(hdr)
        wdel = hdr["CDELT3"]
        wunit = u.Unit(hdr.get("CUNIT3", "AA"))
        fov_waves = utils.quantify(fov_volume["waves"], u.um).to(wunit).value
        mask = ((hdu_waves > fov_waves[0] - 0.5 * wdel) *
                (hdu_waves <= fov_waves[1] + 0.5 * wdel))  # need to go [+/-] half a bin

        # OC [2021-12-14] if fov range is not covered by the source return nothing
        if not np.any(mask):
            print("FOV {} um - {} um: not covered by Source".format(fov_waves[0], fov_waves[1]))
            return None

        i0p, i1p = np.where(mask)[0][0], np.where(mask)[0][-1]
        f0 = (abs(hdu_waves[i0p] - fov_waves[0] + 0.5 * wdel) % wdel) / wdel    # blue edge
        f1 = (abs(hdu_waves[i1p] - fov_waves[1] - 0.5 * wdel) % wdel) / wdel    # red edge
        data = imagehdu.data[i0p:i1p+1, y0p:y1p, x0p:x1p]
        data[0, :, :] *= f0
        if i1p > i0p:
            data[-1, :, :] *= f1

        # w0, w1 : the closest cube wavelengths outside the fov edge wavelengths
        # fov_waves : the fov edge wavelengths
        # f0, f1 : the scaling factors for the blue and red edge cube slices
        #
        # w0, w1 = hdu_waves[i0p], hdu_waves[i1p]
        # print(f"\nw0: {w0}, f0: {f0}, {fov_waves}, f1: {f1}, w1: {w1}")

        new_hdr.update({"NAXIS": 3,
                        "NAXIS3": data.shape[0],
                        "CRVAL3": hdu_waves[i0p],
                        "CRPIX3": 0,
                        "CDELT3": hdr["CDELT3"],
                        "CUNIT3": hdr["CUNIT3"],
                        "CTYPE3": hdr["CTYPE3"],
                        "BUNIT":  hdr["BUNIT"]})

    else:
        data = imagehdu.data[y0p:y1p, x0p:x1p]
        new_hdr["SPEC_REF"] = hdr.get("SPEC_REF")

    new_imagehdu = fits.ImageHDU(data=data)
    new_imagehdu.header.update(new_hdr)

    return new_imagehdu