Exemple #1
0
def test_curved_equal_vertical_extraction(sample_data, orders):
    # Currently extract always uses the vertical extraction, making this kind of useless
    img, spec, slitf = sample_data
    tilt = 0
    shear = 0

    spec_curved, sunc_curved, slitf_curved, _ = extract.extract(img,
                                                                orders,
                                                                tilt=tilt,
                                                                shear=shear)
    spec_vert, sunc_vert, slitf_vert, _ = extract.extract(img, orders)

    assert np.allclose(spec_curved, spec_vert, rtol=1e-2)
    # assert np.allclose(sunc_curved, sunc_vert, rtol=0.1)
    assert np.allclose(slitf_curved, slitf_vert, rtol=1e-1)
Exemple #2
0
def test_vertical_extraction(sample_data, orders, width, height, noise,
                             oversample):
    img, spec, slitf = sample_data

    spec_vert, sunc_vert, slitf_vert, _ = extract.extract(img, orders)

    assert isinstance(spec_vert, np.ma.masked_array)
    assert spec_vert.ndim == 2
    assert spec_vert.shape[0] == orders.shape[0]
    assert spec_vert.shape[1] == width

    assert isinstance(sunc_vert, np.ma.masked_array)
    assert sunc_vert.ndim == 2
    assert sunc_vert.shape[0] == orders.shape[0]
    assert sunc_vert.shape[1] == width

    assert isinstance(slitf_vert, np.ndarray)
    assert slitf_vert.ndim == 2
    assert slitf_vert.shape[0] == orders.shape[0]
    assert slitf_vert.shape[1] <= height * oversample

    assert not np.any(spec_vert == 0)
    assert np.abs(np.diff(spec / spec_vert[0])).max() <= noise + 1e-1

    assert not np.any(sunc_vert == 0)
    assert np.abs(
        sunc_vert / spec_vert).max() <= noise * 1.1 * oversample + 1e-2
Exemple #3
0
def test_wavecal(files, instr, instrument, mode, mask, orders, settings,
                 order_range):
    name = "wavecal_master"
    if len(files[name]) == 0:
        pytest.skip(f"No wavecal files found for instrument {instrument}")

    orders, column_range = orders
    files = files[name][0]
    orig, thead = instr.load_fits(files, mode, mask=mask)
    thead["obase"] = (0, "base order number")

    # Extract wavecal spectrum
    thar, _, _, _ = extract(
        orig,
        orders,
        gain=thead["e_gain"],
        readnoise=thead["e_readn"],
        dark=thead["e_drk"],
        extraction_type="arc",
        column_range=column_range,
        order_range=order_range,
        extraction_width=settings[name]["extraction_width"],
        plot=False,
    )

    assert isinstance(thar, np.ndarray)
    assert thar.ndim == 2
    assert thar.shape[0] == order_range[1] - order_range[0]
    assert thar.shape[1] == orig.shape[1]
    assert np.issubdtype(thar.dtype, np.floating)

    # assert np.min(thar) == 0
    # assert np.max(thar) == 1

    reference = instr.get_wavecal_filename(thead, mode,
                                           **settings["instrument"])
    reference = np.load(reference, allow_pickle=True)
    linelist = reference["cs_lines"]

    name = "wavecal"
    module = WavelengthCalibration(
        plot=False,
        manual=False,
        threshold=settings[name]["threshold"],
        degree=settings[name]["degree"],
    )
    wave, solution = module.execute(thar, linelist)

    assert isinstance(wave, np.ndarray)
    assert wave.ndim == 2
    assert wave.shape[0] == order_range[1] - order_range[0]
    assert wave.shape[1] == orig.shape[1]
    assert np.issubdtype(wave.dtype, np.floating)
Exemple #4
0
def test_normflat(flat, orders, settings, order_range, scatter, instrument):
    flat, fhead = flat
    orders, column_range = orders
    settings = settings["norm_flat"]

    if flat[0] is None:
        pytest.skip(f"No flat exists for instrument {instrument}")

    norm, _, blaze, _ = extract(
        flat,
        orders,
        scatter=scatter,
        gain=fhead["e_gain"],
        readnoise=fhead["e_readn"],
        dark=fhead["e_drk"],
        column_range=column_range,
        order_range=order_range,
        extraction_type="normalize",
        extraction_width=settings["extraction_width"],
        threshold=settings["threshold"],
        lambda_sf=settings["smooth_slitfunction"],
        lambda_sp=settings["smooth_spectrum"],
        swath_width=settings["swath_width"],
        plot=False,
    )

    assert isinstance(norm, np.ndarray)
    assert norm.ndim == flat.ndim
    assert norm.shape[0] == flat.shape[0]
    assert norm.shape[1] == flat.shape[1]
    assert norm.dtype == flat.dtype
    assert np.ma.min(norm) > 0
    assert not np.any(np.isnan(norm))

    assert isinstance(blaze, np.ndarray)
    assert blaze.ndim == 2
    assert blaze.shape[0] == order_range[1] - order_range[0]
    assert blaze.shape[1] == flat.shape[1]
    assert np.issubdtype(blaze.dtype, np.floating)
    assert not np.any(np.isnan(blaze))

    for i, j in enumerate(range(order_range[0], order_range[1])):
        cr = column_range[j]
        assert np.all(blaze[i, :cr[0]].mask == True)
        assert np.all(blaze[i, cr[1]:].mask == True)
Exemple #5
0
def extracted(original, orders, order_range, settings):
    original, chead = original
    orders, column_range = orders
    settings = settings["curvature"]

    if original is None:
        return None

    extracted, _, _, _ = extract(
        original,
        orders,
        gain=chead["e_gain"],
        readnoise=chead["e_readn"],
        dark=chead["e_drk"],
        extraction_type="arc",
        column_range=column_range,
        order_range=order_range,
        plot=False,
        extraction_width=settings["extraction_width"],
    )
    return extracted
Exemple #6
0
def test_extract(sample_data, orders):
    img, spec, slitf = sample_data

    with pytest.raises(ValueError):
        extract.extract(img, orders, extraction_type="foobar")
Exemple #7
0
def test_science(
    files,
    instrument,
    mode,
    mask,
    extension,
    bias,
    normflat,
    orders,
    settings,
    order_range,
):
    flat, blaze = normflat
    bias, _ = bias
    orders, column_range = orders
    settings = settings["science"]

    # Fix column ranges
    for i in range(blaze.shape[0]):
        column_range[i] = np.where(blaze[i] != 0)[0][[0, -1]]

    f = files["science"][0]

    im, head = util.load_fits(
        f, instrument, mode, extension, mask=mask, dtype=np.float32
    )
    # Correct for bias and flat field
    im -= bias
    im /= flat

    # Optimally extract science spectrum
    spec, sigma, _, _ = extract(
        im,
        orders,
        gain=head["e_gain"],
        readnoise=head["e_readn"],
        dark=head["e_drk"],
        column_range=column_range,
        order_range=order_range,
        extraction_type=settings["extraction_method"],
        extraction_width=settings["extraction_width"],
        lambda_sf=settings["smooth_slitfunction"],
        lambda_sp=settings["smooth_spectrum"],
        osample=settings["oversampling"],
        swath_width=settings["swath_width"],
        plot=False,
    )

    assert isinstance(spec, np.ma.masked_array)
    assert spec.ndim == 2
    assert spec.shape[0] == order_range[1] - order_range[0]
    assert spec.shape[1] == bias.shape[1]
    assert np.issubdtype(spec.dtype, np.floating)
    assert not np.any(np.isnan(spec))
    assert not np.all(np.all(spec.mask, axis=0))

    assert isinstance(sigma, np.ma.masked_array)
    assert sigma.ndim == 2
    assert sigma.shape[0] == order_range[1] - order_range[0]
    assert sigma.shape[1] == bias.shape[1]
    assert np.issubdtype(sigma.dtype, np.floating)
    assert not np.any(np.isnan(sigma))
    assert not np.all(np.all(sigma.mask, axis=0))
Exemple #8
0
def spec(
    files,
    instrument,
    mode,
    mask,
    extension,
    bias,
    normflat,
    orders,
    settings,
    output_dir,
    order_range,
):
    """Load or create science spectrum

    Parameters
    ----------
    files : dict(str:str)
        raw input files
    instrument : str
        instrument name
    mode : str
        observing mode
    mask : array(bool)
        Bad pixel mask
    extension : int
        fits data extension
    bias : array(float)
        bias calibration data
    normflat : array(float)
        normalized flat field
    orders : array(float)
        order tracing polynomials and column_ranges
    settings : dict(str:obj)
        run settings
    output_dir : str
        output data directory

    Returns
    -------
    spec : array(float) of size (norders, ncol)
        extracted science spectra
    sigma : array(float) of size (norders, ncol)
        uncertainty on the extracted science spectra
    """
    orders, column_range = orders
    specfile = os.path.join(output_dir, "test_spec.ech")
    settings = settings["science"]

    try:
        science = echelle.read(specfile, raw=True)
        head = science.header
        spec = science["spec"]
        sigma = science["sig"]

        mask = np.full(spec.shape, True)
        for iord in range(spec.shape[0]):
            cr = column_range[iord]
            mask[iord, cr[0]:cr[1]] = False
        spec = np.ma.array(spec, mask=mask)
        sigma = np.ma.array(sigma, mask=mask)
    except FileNotFoundError:
        flat, blaze = normflat
        bias, _ = bias

        # Fix column ranges
        for i in range(blaze.shape[0]):
            column_range[i] = np.where(blaze[i] != 0)[0][[0, -1]]

        f = files["science"][0]

        im, head = util.load_fits(f,
                                  instrument,
                                  mode,
                                  extension,
                                  mask=mask,
                                  dtype=np.float32)
        # Correct for bias and flat field
        im -= bias
        im /= flat

        # Optimally extract science spectrum
        spec, sigma, _, columns = extract(
            im,
            orders,
            gain=head["e_gain"],
            readnoise=head["e_readn"],
            dark=head["e_drk"],
            column_range=column_range,
            order_range=order_range,
            extraction_type=settings["extraction_method"],
            extraction_width=settings["extraction_width"],
            lambda_sf=settings["smooth_slitfunction"],
            lambda_sp=settings["smooth_spectrum"],
            osample=settings["oversampling"],
            swath_width=settings["swath_width"],
            plot=False,
        )
        echelle.save(specfile, head, spec=spec, sig=sigma, columns=columns)

    return spec, sigma
Exemple #9
0
def wave(files, instrument, mode, extension, mask, orders, settings,
         output_dir, order_range):
    """Load or create wavelength calibration files

    Parameters
    ----------
    files : dict(str:str)
        calibration file names
    instrument : str
        instrument name
    mode : str
        observing mode
    extension : int
        fits data extension
    mask : array(bool)
        Bad pixel mask
    orders : tuple(array, array)
        order tracing polynomials and column ranges
    settings : dict(str:obj)
        run settings
    output_dir : str
        output data directory

    Returns
    -------
    wave : array(float) of size (norder, ncol)
        Wavelength along the spectral orders
    """
    orders, column_range = orders
    wavefile = os.path.join(output_dir, "test_wavecal.thar.ech")
    settings = settings["wavecal"]

    if os.path.exists(wavefile):
        data = np.load(wavefile, allow_pickle=True)

        thar = data["thar"]
        wave = data["wave"]
        solution = data["solution"]
    else:
        files = files["wavecal"][0]
        orig, thead = util.load_fits(files,
                                     instrument,
                                     mode,
                                     extension,
                                     mask=mask)
        thead["obase"] = (0, "base order number")

        # Extract wavecal spectrum
        thar, _, _, _ = extract(
            orig,
            orders,
            gain=thead["e_gain"],
            readnoise=thead["e_readn"],
            dark=thead["e_drk"],
            extraction_type=settings["extraction_method"],
            column_range=column_range,
            order_range=order_range,
            extraction_width=settings["extraction_width"],
            plot=False,
        )

        reference = instruments.instrument_info.get_wavecal_filename(
            thead, instrument, mode)
        reference = np.load(reference, allow_pickle=True)
        linelist = reference["cs_lines"]

        module = WavelengthCalibration(plot=False, manual=False)
        wave, solution = module.execute(thar, linelist)

        np.savez(wavefile, thar=thar, wave=wave, solution=solution)

    return wave, thar
Exemple #10
0
def test_science(
    files,
    instr,
    instrument,
    mode,
    mask,
    bias,
    normflat,
    orders,
    settings,
    order_range,
):
    if len(files["science"]) == 0:
        pytest.skip(f"No science files found for instrument {instrument}")

    flat, blaze = normflat
    bias, bhead = bias
    orders, column_range = orders
    settings = settings["science"]

    # Fix column ranges
    for i in range(blaze.shape[0]):
        column_range[i] = np.where(blaze[i] != 0)[0][[0, -1]]

    f = files["science"][0]

    im, head = combine_calibrate(
        [f],
        instr,
        mode,
        mask=mask,
        bias=bias,
        bhead=bhead,
        norm=flat,
        bias_scaling=settings["bias_scaling"],
    )

    # Optimally extract science spectrum
    spec, sigma, _, _ = extract(
        im,
        orders,
        gain=head["e_gain"],
        readnoise=head["e_readn"],
        dark=head["e_drk"],
        column_range=column_range,
        order_range=order_range,
        extraction_type=settings["extraction_method"],
        extraction_width=settings["extraction_width"],
        lambda_sf=settings["smooth_slitfunction"],
        lambda_sp=settings["smooth_spectrum"],
        osample=settings["oversampling"],
        swath_width=settings["swath_width"],
        plot=False,
    )

    assert isinstance(spec, np.ma.masked_array)
    assert spec.ndim == 2
    assert spec.shape[0] == order_range[1] - order_range[0]
    assert spec.shape[1] == im.shape[1]
    assert np.issubdtype(spec.dtype, np.floating)
    assert not np.any(np.isnan(spec))
    assert not np.all(np.all(spec.mask, axis=0))

    assert isinstance(sigma, np.ma.masked_array)
    assert sigma.ndim == 2
    assert sigma.shape[0] == order_range[1] - order_range[0]
    assert sigma.shape[1] == im.shape[1]
    assert np.issubdtype(sigma.dtype, np.floating)
    assert not np.any(np.isnan(sigma))
    assert not np.all(np.all(sigma.mask, axis=0))