Exemplo n.º 1
0
def is_field_in_fov(fov_header, table_or_imagehdu, wcs_suffix=""):

    s = wcs_suffix
    pixel_scale = utils.quantify(fov_header["CDELT1" + s], u.deg)

    if isinstance(table_or_imagehdu, Table):
        ext_hdr = imp_utils._make_bounding_header_for_tables(
            [table_or_imagehdu], pixel_scale)
    elif isinstance(table_or_imagehdu, fits.ImageHDU):
        ext_hdr = imp_utils._make_bounding_header_from_imagehdus(
            [table_or_imagehdu], pixel_scale)
    else:
        warnings.warn("Input was neither Table nor ImageHDU: {}"
                      "".format(table_or_imagehdu))
        return False

    ext_xsky, ext_ysky = imp_utils.calc_footprint(ext_hdr, 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
Exemplo n.º 2
0
def extract_range_from_spectrum(spectrum, waverange):
    if not isinstance(spectrum, SourceSpectrum):
        raise ValueError(f"spectrum must be of type synphot.SourceSpectrum: "
                         f"{type(spectrum)}")

    wave_min, wave_max = utils.quantify(waverange, u.um).to(u.AA).value
    spec_waveset = spectrum.waveset.to(u.AA).value
    mask = (spec_waveset > wave_min) * (spec_waveset < wave_max)

    if sum(mask) == 0:
        logging.warning(f"Waverange does not overlap with Spectrum waveset: "
                      f"{[wave_min, wave_max]} <> {spec_waveset} "
                      f"for spectrum {spectrum}")
    if wave_min < min(spec_waveset) or wave_max > max(spec_waveset):
        logging.warning(f"Waverange only partially overlaps with Spectrum waveset: "
                      f"{[wave_min, wave_max]} <> {spec_waveset} "
                      f"for spectrum {spectrum}")

    wave = np.r_[wave_min, spec_waveset[mask], wave_max]
    flux = spectrum(wave)

    new_spectrum = SourceSpectrum(Empirical1D, points=wave, lookup_table=flux)
    new_spectrum.meta.update(spectrum.meta)

    return new_spectrum
Exemplo n.º 3
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
Exemplo n.º 4
0
 def test_return_quantity_for_valid_data(self, item, unit, expected):
     assert utils.quantify(item, unit) == expected
Exemplo n.º 5
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