def ad(request, ad_factory, path_to_outputs):
    """
    Loads existing input FITS files as AstroData objects, runs the
    `extract1DSpectra` primitive on it, and return the output object containing
    the extracted 1d spectrum. This makes tests more efficient because the
    primitive is run only once, instead of N x Numbes of tests.

    If the input file does not exist, this fixture raises a IOError.

    If the input file does not exist and PyTest is called with the
    `--force-preprocess-data`, this fixture looks for cached raw data and
    process it. If the raw data does not exist, it is then cached via download
    from the Gemini Archive.

    Parameters
    ----------
    request : fixture
        PyTest's built-in fixture with information about the test itself.
    ad_factory : fixture
        Custom fixture defined in the `conftest.py` file that loads cached data,
        or download and/or process it if needed.
    path_to_outputs : fixture
        Custom fixture defined in `astrodata.testing` containing the path to the
        output folder.

    Returns
    -------
    AstroData
        Object containing Wavelength Solution table.

    Raises
    ------
    IOError
        If the input file does not exist and if --force-preprocess-data is False.
    """
    fname, arc_name, ap_center = request.param

    p = primitives_gmos_spect.GMOSSpect([])
    p.viewer = geminidr.dormantViewer(p, None)

    print('\n\n Running test inside folder:\n  {}'.format(path_to_outputs))

    arc_ad = ad_factory(arc_name, preprocess_arc_recipe)

    _ad = ad_factory(fname, preprocess_recipe, center=ap_center, arc=arc_ad)
    ad_out = p.extract1DSpectra([_ad], method="standard", width=None,
                                grow=10)[0]

    tests_failed_before_module = request.session.testsfailed
    yield ad_out

    if request.session.testsfailed > tests_failed_before_module:
        _dir = os.path.join(path_to_outputs, os.path.dirname(fname))
        os.makedirs(_dir, exist_ok=True)

        fname_out = os.path.join(_dir, ad_out.filename)
        ad_out.write(filename=fname_out, overwrite=True)
        print('\n Saved file to:\n  {}\n'.format(fname_out))

    del ad_out
def preprocess_recipe(ad, path):
    """
    Recipe used to generate input data for `distortionDetermine` tests.

    Parameters
    ----------
    ad : AstroData
        Input raw arc data loaded as AstroData.
    path : str
        Path that points to where the input data is cached.

    Returns
    -------
    AstroData
        Pre-processed arc data.
    """
    _p = primitives_gmos_spect.GMOSSpect([ad])

    _p.prepare()
    _p.addDQ(static_bpm=None)
    _p.addVAR(read_noise=True)
    _p.overscanCorrect()
    _p.ADUToElectrons()
    _p.addVAR(poisson_noise=True)
    _p.mosaicDetectors()
    ad = _p.makeIRAFCompatible()[0]

    _p.writeOutputs(outfilename=os.path.join(path, ad.filename))

    return ad
def preprocess_arc_recipe(ad, path):
    """
    Recipe used to generate arc data for `skyCorrectFromSlit` tests.

    Parameters
    ----------
    ad : AstroData
        Input raw arc data loaded as AstroData.
    path : str
        Path that points to where the input data is cached.

    Returns
    -------
    AstroData
        Pre-processed arc data.
    """
    _p = primitives_gmos_spect.GMOSSpect([ad])

    _p.prepare()
    _p.addDQ(static_bpm=None)
    _p.addVAR(read_noise=True)
    _p.overscanCorrect()
    _p.ADUToElectrons()
    _p.addVAR(poisson_noise=True)
    _p.mosaicDetectors()
    _p.makeIRAFCompatible()

    ad = _p.determineDistortion(
        spatial_order=3, spectral_order=4, id_only=False, min_snr=5.,
        fwidth=None, nsum=10, max_shift=0.05, max_missed=5)[0]

    _p.writeOutputs(outfilename=os.path.join(path, ad.filename))

    return ad
예제 #4
0
def test_regression_on_flux_calibration(ad, ref_ad_factory,
                                        change_working_dir):
    """
    Regression test for the :func:`~geminidr.gmos.GMOSSpect.fluxCalibrate`
    primitive.

    Parameters
    ----------
    ad : pytest.fixture (AstroData)
        Fixture that reads the filename and loads as an AstroData object.
    change_working_dir : pytest.fixture
        Fixture that changes the working directory
        (see :mod:`astrodata.testing`).
    reference_ad : pytest.fixture
        Fixture that contains a function used to load the reference AstroData
        object (see :mod:`recipe_system.testing`).
    """

    with change_working_dir():
        logutils.config(
            file_name='log_regression_{:s}.txt'.format(ad.data_label()))
        p = primitives_gmos_spect.GMOSSpect([ad])
        p.fluxCalibrate(standard=ad)
        flux_calibrated_ad = p.writeOutputs().pop()

    ref_ad = ref_ad_factory(flux_calibrated_ad.filename)

    for flux_cal_ext, ref_ext in zip(flux_calibrated_ad, ref_ad):
        np.testing.assert_allclose(flux_cal_ext.data, ref_ext.data, atol=1e-4)
예제 #5
0
def ad(request, ad_factory, path_to_outputs):
    """
    Loads existing input FITS files as AstroData objects, runs the
    `traceApertures` primitive on it, and return the output object containing
    a `.APERTURE` table.

    This makes tests more efficient because the primitive is run only once,
    instead of N x Number of tests.

    If the input file does not exist, this fixture raises a IOError.

    If the input file does not exist and PyTest is called with the
    `--force-preprocess-data`, this fixture looks for cached raw data and
    process it. If the raw data does not exist, it is then cached via download
    from the Gemini Archive.

    Parameters
    ----------
    request : fixture
        PyTest's built-in fixture with information about the test itself.
    ad_factory : fixture
        Custom fixture defined in the `conftest.py` file that loads cached data,
        or download and/or process it if needed.
    path_to_outputs : fixture
        Custom fixture defined in `astrodata.testing` containing the path to the
        output folder.

    Returns
    -------
    AstroData
        Object containing Wavelength Solution table.
    """
    fname, ap_center = request.param

    p = primitives_gmos_spect.GMOSSpect([])
    p.viewer = geminidr.dormantViewer(p, None)

    print('\n\n Running test inside folder:\n  {}'.format(path_to_outputs))

    _ad = ad_factory(fname, preprocess_recipe, **{'center': ap_center})
    ad_out = p.traceApertures([_ad],
                              trace_order=2,
                              nsum=20,
                              step=10,
                              max_shift=0.09,
                              max_missed=5,
                              debug=False)[0]

    tests_failed_before_module = request.session.testsfailed
    yield ad_out

    if request.session.testsfailed > tests_failed_before_module:
        _dir = os.path.join(path_to_outputs, os.path.dirname(fname))
        os.makedirs(_dir, exist_ok=True)

        fname_out = os.path.join(_dir, ad_out.filename)
        ad_out.write(filename=fname_out, overwrite=True)
        print('\n Saved file to:\n  {}\n'.format(fname_out))

    del ad_out
예제 #6
0
def test_regression_on_extract_1d_spectra(ad, ref_ad_factory,
                                          change_working_dir):
    """
    Regression test for the :func:`~geminidr.gmos.GMOSSpect.extract1DSpectra`
    primitive.

    Parameters
    ----------
    ad : pytest.fixture (AstroData)
        Fixture that reads the filename and loads as an AstroData object.
    change_working_dir : pytest.fixture
        Fixture that changes the working directory
        (see :mod:`astrodata.testing`).
    reference_ad : pytest.fixture
        Fixture that contains a function used to load the reference AstroData
        object (see :mod:`recipe_system.testing`).
    """

    with change_working_dir():

        logutils.config(
            file_name='log_regression_{:s}.txt'.format(ad.data_label()))

        p = primitives_gmos_spect.GMOSSpect([ad])
        p.viewer = geminidr.dormantViewer(p, None)
        p.extract1DSpectra(method="standard", width=None, grow=10)
        extracted_ad = p.writeOutputs().pop()

    ref_ad = ref_ad_factory(extracted_ad.filename)

    for ext, ref_ext in zip(extracted_ad, ref_ad):
        assert ext.data.ndim == 1
        np.testing.assert_allclose(ext.data, ref_ext.data, atol=1e-3)
예제 #7
0
def test_regression_for_determine_distortion_using_models_coefficients(
        ad, change_working_dir, ref_ad_factory, request):
    """
    Runs the `determineDistortion` primitive on a preprocessed data and compare
    its model with the one in the reference file.

    Parameters
    ----------
    ad : pytest.fixture (AstroData)
        Fixture that reads the filename and loads as an AstroData object.
    change_working_dir : pytest.fixture
        Fixture that changes the working directory
        (see :mod:`astrodata.testing`).
    reference_ad : pytest.fixture
        Fixture that contains a function used to load the reference AstroData
        object (see :mod:`recipe_system.testing`).
    request : pytest.fixture
        PyTest built-in containing command line options.
    """
    with change_working_dir():
        logutils.config(file_name='log_model_{:s}.txt'.format(ad.data_label()))
        p = primitives_gmos_spect.GMOSSpect([ad])
        p.viewer = geminidr.dormantViewer(p, None)
        p.determineDistortion(**fixed_parameters_for_determine_distortion)
        distortion_determined_ad = p.writeOutputs().pop()

    ref_ad = ref_ad_factory(distortion_determined_ad.filename)
    for ext, ext_ref in zip(distortion_determined_ad, ref_ad):
        c = np.ma.masked_invalid(ext.FITCOORD["coefficients"])
        c_ref = np.ma.masked_invalid(ext_ref.FITCOORD["coefficients"])
        np.testing.assert_allclose(c, c_ref, atol=2)
        
    if request.config.getoption("--do-plots"):
        do_plots(distortion_determined_ad, ref_ad)
def test_resample_only(adinputs, caplog):
    p = primitives_gmos_spect.GMOSSpect(adinputs)
    p.resampleToCommonFrame()
    _check_params(caplog.records, 'w1=508.198 w2=1088.323 dw=0.151 npix=3841')
    caplog.clear()
    adout = p.resampleToCommonFrame(dw=0.15)
    assert 'ALIGN' in adout[0].phu
    _check_params(caplog.records, 'w1=508.198 w2=1088.232 dw=0.150 npix=3868')
def test_resample_only_and_trim(adinputs, caplog):
    p = primitives_gmos_spect.GMOSSpect(adinputs)
    p.resampleToCommonFrame(trim_data=True)
    _check_params(caplog.records, 'w1=614.666 w2=978.802 dw=0.151 npix=2407')
    caplog.clear()
    adout = p.resampleToCommonFrame(dw=0.15)
    assert 'ALIGN' in adout[0].phu
    _check_params(caplog.records, 'w1=614.574 w2=978.648 dw=0.150 npix=2429')
def test_resample_and_linearize(adinputs, caplog):
    p = primitives_gmos_spect.GMOSSpect(adinputs)
    adout = p.resampleToCommonFrame(dw=0.15)
    # we get 3 ad objects with one spectrum
    assert len(adout) == 3
    assert {len(ad) for ad in adout} == {1}
    assert {ad[0].shape[0] for ad in adout} == {3869}
    _check_params(caplog.records, 'w1=508.198 w2=1088.323 dw=0.150 npix=3869')
    assert 'ALIGN' in adout[0].phu
def test_header_offset(adinputs2, caplog):
    """Test that the offset is correctly read from the headers."""
    p = primitives_gmos_spect.GMOSSpect(adinputs2)
    adout = p.adjustSlitOffsetToReference(method='offsets')

    for rec in caplog.records:
        assert not rec.message.startswith('WARNING - Offset from correlation')

    assert np.isclose(adout[0].phu['SLITOFF'], 0)
    assert np.isclose(adout[1].phu['SLITOFF'], -92.9368)
    assert np.isclose(adout[2].phu['SLITOFF'], -92.9368)
    assert np.isclose(adout[3].phu['SLITOFF'], 0)
def test_correlation_and_w1_w2(adinputs, caplog):
    add_fake_offset(adinputs, offset=10)
    p = primitives_gmos_spect.GMOSSpect(adinputs)
    adout = p.adjustSlitOffsetToReference()

    assert adout[1].phu['SLITOFF'] == -10
    assert adout[2].phu['SLITOFF'] == -20

    p.resampleToCommonFrame(dw=0.15, w1=700, w2=850)
    _check_params(caplog.records, 'w1=700.000 w2=850.000 dw=0.150 npix=1001')

    adstack = p.stackFrames()
    assert adstack[0][0].shape == (512, 1001)
def test_resample_linearize_trim_and_stack(adinputs, caplog):
    p = primitives_gmos_spect.GMOSSpect(adinputs)
    adout = p.resampleToCommonFrame(dw=0.15, trim_data=True)
    # we get 3 ad objects with one spectrum
    assert len(adout) == 3
    assert {len(ad) for ad in adout} == {1}
    assert {ad[0].shape[0] for ad in adout} == {2429}
    _check_params(caplog.records, 'w1=614.666 w2=978.802 dw=0.150 npix=2429')

    adout = p.stackFrames()
    assert len(adout) == 1
    assert len(adout[0]) == 1
    assert adout[0][0].shape[0] == 2429
예제 #14
0
def preprocess_recipe(ad, path, center):
    """
    Recipe used to generate input data for `traceAperture` tests.

    Parameters
    ----------
    ad : AstroData
        Input raw arc data loaded as AstroData.
    path : str
        Path that points to where the input data is cached.
    center : int
        Aperture center.

    Returns
    -------
    AstroData
        Pre-processed arc data.
    """
    _p = primitives_gmos_spect.GMOSSpect([ad])

    _p.prepare()
    _p.addDQ(static_bpm=None)
    _p.addVAR(read_noise=True)
    _p.overscanCorrect()
    _p.ADUToElectrons()
    _p.addVAR(poisson_noise=True)
    _p.mosaicDetectors(suffix="_mosaicWithApertureTable")
    ad = _p.makeIRAFCompatible()[0]

    width = ad[0].shape[1]

    aperture = table.Table(
        [
            [1],  # Number
            [1],  # ndim
            [0],  # degree
            [0],  # domain_start
            [width - 1],  # domain_end
            [center],  # c0
            [-10],  # aper_lower
            [10],  # aper_upper
        ],
        names=[
            'number', 'ndim', 'degree', 'domain_start', 'domain_end', 'c0',
            'aper_lower', 'aper_upper'
        ])

    ad[0].APERTURE = aperture
    ad.write(os.path.join(path, ad.filename))

    return ad
def preprocess_recipe(ad, path, arc):
    """Recipe used to generate _skyCorrected files from raw data. """
    p = primitives_gmos_spect.GMOSSpect([ad])
    p.prepare()
    p.addDQ(static_bpm=None)
    p.addVAR(read_noise=True)
    p.overscanCorrect()
    p.ADUToElectrons()
    p.addVAR(poisson_noise=True)
    p.mosaicDetectors()
    p.distortionCorrect(arc=arc)
    p.findSourceApertures(max_apertures=1)
    ad = p.skyCorrectFromSlit()[0]
    return ad
def preprocess_arc_recipe(ad, path):
    """ Recipe used to generate _distortionDetermined files from raw arc."""
    p = primitives_gmos_spect.GMOSSpect([ad])
    p.prepare()
    p.addDQ(static_bpm=None)
    p.addVAR(read_noise=True)
    p.overscanCorrect()
    p.ADUToElectrons()
    p.addVAR(poisson_noise=True)
    p.mosaicDetectors()
    p.makeIRAFCompatible()
    p.determineWavelengthSolution()
    ad = p.determineDistortion()[0]
    return ad
def test_regression_determine_wavelength_solution(ad, fwidth, order, min_snr,
                                                  caplog, change_working_dir,
                                                  ref_ad_factory):
    """
    Make sure that the wavelength solution gives same results on different
    runs.
    """
    caplog.set_level(logging.INFO, logger="geminidr")

    with change_working_dir():
        logutils.config(
            file_name='log_regress_{:s}.txt'.format(ad.data_label()))
        p = primitives_gmos_spect.GMOSSpect([ad])
        p.viewer = geminidr.dormantViewer(p, None)

        p.determineWavelengthSolution(
            order=order,
            min_snr=min_snr,
            fwidth=fwidth,
            **determine_wavelength_solution_parameters)

        wcalibrated_ad = p.writeOutputs().pop()

        for record in caplog.records:
            if record.levelname == "WARNING":
                assert "No acceptable wavelength solution found" not in record.message

    ref_ad = ref_ad_factory(wcalibrated_ad.filename)
    table = wcalibrated_ad[0].WAVECAL
    table_ref = ref_ad[0].WAVECAL

    model = astromodels.dict_to_chebyshev(
        dict(zip(table["name"], table["coefficients"])))

    ref_model = astromodels.dict_to_chebyshev(
        dict(zip(table_ref["name"], table_ref["coefficients"])))

    x = np.arange(wcalibrated_ad[0].shape[1])
    wavelength = model(x)
    ref_wavelength = ref_model(x)

    pixel_scale = wcalibrated_ad[0].pixel_scale()  # arcsec / px
    slit_size_in_arcsec = float(wcalibrated_ad[0].focal_plane_mask().replace(
        'arcsec', ''))
    slit_size_in_px = slit_size_in_arcsec / pixel_scale
    dispersion = abs(
        wcalibrated_ad[0].dispersion(asNanometers=True))  # nm / px

    tolerance = 0.5 * (slit_size_in_px * dispersion)
    np.testing.assert_allclose(wavelength, ref_wavelength, rtol=tolerance)
예제 #18
0
def test_regression_on_calculate_sensitivity(ad, change_working_dir, ref_ad_factory):

    with change_working_dir():
        logutils.config(file_name='log_regression_{:s}.txt'.format(ad.data_label()))
        p = primitives_gmos_spect.GMOSSpect([ad])
        p.calculateSensitivity(bandpass=5, order=6)
        calc_sens_ad = p.writeOutputs().pop()

    assert hasattr(calc_sens_ad[0], 'SENSFUNC')

    ref_ad = ref_ad_factory(ad.filename)

    for calc_sens_ext, ref_ext in zip(ad, ref_ad):
        np.testing.assert_allclose(
            calc_sens_ext.data, ref_ext.data, atol=1e-4)
    def reduce(filename):
        _p = primitives_gmos_spect.GMOSSpect([astrodata.open(filename)])
        _p.viewer = geminidr.dormantViewer(_p, None)

        _p.prepare()
        _p.addDQ(static_bpm=None)
        _p.addVAR(read_noise=True)
        _p.overscanCorrect()
        _p.ADUToElectrons()
        _p.addVAR(poisson_noise=True)
        _p.mosaicDetectors()
        _p.makeIRAFCompatible()
        _p.determineWavelengthSolution(suffix="_arc")

        return _p
def test_header_offset_fallback(adinputs2, caplog):
    """For this dataset the correlation method fails, and give an offset very
    different from the header one. So we check that the fallback to the header
    offset works.
    """
    p = primitives_gmos_spect.GMOSSpect(adinputs2)
    adout = p.adjustSlitOffsetToReference()

    assert caplog.records[3].message.startswith(
        'WARNING - Offset from correlation (0) is too big compared to the '
        'header offset (-92.93680297397756). Using this one instead')

    assert np.isclose(adout[0].phu['SLITOFF'], 0)
    assert np.isclose(adout[1].phu['SLITOFF'], -92.9368)
    assert np.isclose(adout[2].phu['SLITOFF'], -92.9368)
    assert np.isclose(adout[3].phu['SLITOFF'], 0)
    def test_distortion_correction_is_applied_the_same_way(config):
        """
        Applies the same distortion correction model to both output and reference
        arcs and compares the results.
        """
        # Process the output file ---
        basename, ext = os.path.splitext(config.filename)

        basename, _ = basename.split("_")[0], basename.split("_")[1:]

        arc_basename = "{:s}_{:s}{:s}".format(basename, "distortionDetermined",
                                              ext)

        arc_name = os.path.join(config.output_dir, arc_basename)

        if not os.path.exists(arc_name):
            pytest.skip("Arc file not found: {}".format(arc_name))

        ad_out = config.ad
        p = primitives_gmos_spect.GMOSSpect([])

        ad_out = p.distortionCorrect(adinputs=[ad_out], arc=arc_name)[0]
        filename = ad_out.filename

        ad_out = p.determineDistortion(adinputs=[ad_out])[0]

        for ext in ad_out:
            assert hasattr(ext, "FITCOORD")

        ad_out.write(filename=filename, overwrite=True)

        # assert False

        # # Reads the reference file ---
        # reference = os.path.join(config.ref_dir, ad_out.filename)
        #
        # if not os.path.exists(reference):
        #     pytest.fail('Reference file not found: {}'.format(reference))
        #
        # ad_ref = astrodata.open(reference)

        os.rename(filename, os.path.join(config.output_dir, filename))
        # Evaluate them ---

        for ext in ad_out:
            coefficients = dict(
                zip(ext.FITCOORD["name"], ext.FITCOORD["coefficients"]))
예제 #22
0
def create_inputs_recipe():
    """
    Creates input data for tests using pre-processed standard star and its
    calibration files.

    The raw files will be downloaded and saved inside the path stored in the
    `$DRAGONS_TEST/raw_inputs` directory. Processed files will be stored inside
    a new folder called "dragons_test_inputs". The sub-directory structure
    should reflect the one returned by the `path_to_inputs` fixture.
    """
    import os
    from astrodata.testing import download_from_archive

    root_path = os.path.join("./dragons_test_inputs/")
    module_path = "geminidr/gmos/spect/{}/".format(__file__.strip('.py'))
    path = os.path.join(root_path, module_path)

    os.makedirs(path, exist_ok=True)
    os.chdir(path)
    os.makedirs("inputs/", exist_ok=True)
    print('Current working directory:\n    {:s}'.format(os.getcwd()))

    for filename in datasets:
        print('Downloading files...')
        basename = filename.split("_")[0] + ".fits"
        sci_path = download_from_archive(basename)
        sci_ad = astrodata.open(sci_path)
        data_label = sci_ad.data_label()

        print('Reducing pre-processed data:')
        logutils.config(file_name='log_{}.txt'.format(data_label))
        p = primitives_gmos_spect.GMOSSpect([sci_ad])
        p.prepare()
        p.addDQ(static_bpm=None)
        p.addVAR(read_noise=True)
        p.overscanCorrect()
        p.ADUToElectrons()
        p.addVAR(poisson_noise=True)
        p.mosaicDetectors()
        p.makeIRAFCompatible()

        os.chdir("inputs/")
        processed_ad = p.writeOutputs().pop()
        os.chdir("..")
        print("Wrote pre-processed file to:\n"
              "    {:s}".format(processed_ad.filename))
def test_correlation_non_linearize(adinputs, caplog):
    add_fake_offset(adinputs, offset=10)
    p = primitives_gmos_spect.GMOSSpect(adinputs)
    adout = p.adjustSlitOffsetToReference()

    assert adout[1].phu['SLITOFF'] == -10
    assert adout[2].phu['SLITOFF'] == -20

    p.resampleToCommonFrame()
    _check_params(caplog.records, 'w1=508.198 w2=1088.323 dw=0.151 npix=3841')
    caplog.clear()
    adout = p.resampleToCommonFrame(dw=0.15)
    assert 'ALIGN' in adout[0].phu
    _check_params(caplog.records, 'w1=508.198 w2=1088.232 dw=0.150 npix=3868')

    adstack = p.stackFrames()
    assert adstack[0][0].shape == (512, 3868)
def test_regression_extract_1d_spectra(ad, change_working_dir,
                                       ref_ad_factory):

    with change_working_dir():

        logutils.config(
            file_name='log_regression_{}.txt'.format(ad.data_label()))

        p = primitives_gmos_spect.GMOSSpect([ad])
        p.viewer = geminidr.dormantViewer(p, None)
        p.skyCorrectFromSlit(order=5, grow=0)
        sky_subtracted_ad = p.writeOutputs().pop()

    ref_ad = ref_ad_factory(sky_subtracted_ad.filename)

    for ext, ref_ext in zip(sky_subtracted_ad, ref_ad):
        np.testing.assert_allclose(ext.data, ref_ext.data, atol=0.01)
    def test_determine_distortion(config):
        """
        Corrects distortion on both output and reference files using the
        distortion model stored in themselves. Previous tests assures that
        these data are similar and that distortion correct is applied the same
        way. Now, this one tests the model itself.
        """
        if not os.path.exists(config.output_file):
            pytest.skip("Processed arc file not found: {}".format(
                config.output_file))

        ad_out = config.ad

        p = primitives_gmos_spect.GMOSSpect([])

        # Using with id_only=True isolates this test from the wavelength
        # calibration tests
        ad_out = p.determineDistortion(adinputs=[ad_out],
                                       id_only=False,
                                       suffix="_distortionDetermined")[0]
        ad_out.write(overwrite=True)

        os.rename(ad_out.filename,
                  os.path.join(config.output_dir, ad_out.filename))

        # Reads the reference file ---
        reference = os.path.join(config.ref_dir, ad_out.filename)

        if not os.path.exists(reference):
            pytest.fail("Reference file not found: {}".format(reference))

        ad_ref = astrodata.open(reference)

        # Compare them ---
        for ext_out, ext_ref in zip(ad_out, ad_ref):
            coeffs_out = np.ma.masked_invalid(ext_out.FITCOORD["coefficients"])
            coeffs_ref = np.ma.masked_invalid(ext_ref.FITCOORD["coefficients"])

            np.testing.assert_allclose(coeffs_out, coeffs_ref, atol=0.1)

        del ad_out, ad_ref, p
def test_correlation(adinputs, caplog):
    add_fake_offset(adinputs, offset=10)
    p = primitives_gmos_spect.GMOSSpect(adinputs)
    adout = p.adjustSlitOffsetToReference()

    assert adout[1].phu['SLITOFF'] == -10
    assert adout[2].phu['SLITOFF'] == -20

    p.resampleToCommonFrame(dw=0.15)
    _check_params(caplog.records, 'w1=508.198 w2=1088.323 dw=0.150 npix=3869')

    ad = p.stackFrames()[0]
    assert ad[0].shape == (512, 3869)

    caplog.clear()
    ad = p.findSourceApertures()[0]
    assert len(ad[0].APERTURE) == 1
    assert caplog.records[3].message == 'Found sources at rows: 260.7'

    ad = p.extract1DSpectra()[0]
    assert ad[0].shape == (3869, )
def test_correlation_and_trim(adinputs, caplog):
    add_fake_offset(adinputs, offset=10)
    p = primitives_gmos_spect.GMOSSpect(adinputs)
    adout = p.adjustSlitOffsetToReference()

    assert adout[1].phu['SLITOFF'] == -10
    assert adout[2].phu['SLITOFF'] == -20

    p.resampleToCommonFrame(dw=0.15, trim_data=True)
    _check_params(caplog.records, 'w1=614.666 w2=978.802 dw=0.150 npix=2429')

    ad = p.stackFrames()[0]
    assert ad[0].shape == (512, 2429)

    caplog.clear()
    ad = p.findSourceApertures()[0]
    assert len(ad[0].APERTURE) == 1
    assert caplog.records[3].message == 'Found sources at rows: 260.4'

    ad = p.extract1DSpectra()[0]
    assert ad[0].shape == (2429, )
    def test_distortion_correct(config):
        """
        Corrects distortion on both output and reference files using the
        distortion model stored in themselves. Previous tests assures that
        these data are similar and that distortion correct is applied the same
        way. Now, this one tests the model itself.
        """
        # Recover name of the distortion corrected arc files ---
        basename = os.path.basename(config.filename)
        filename, extension = os.path.splitext(basename)
        filename = filename.split("_")[0] + "_distortionDetermined" + extension

        output = os.path.join(config.output_dir, filename)
        reference = os.path.join(config.ref_dir, filename)

        if not os.path.exists(output):
            pytest.fail("Processed arc file not found: {}".format(output))

        if not os.path.exists(reference):
            pytest.fail(
                "Processed reference file not found: {}".format(reference))

        p = primitives_gmos_spect.GMOSSpect([])

        ad_out = astrodata.open(output)
        ad_out_corrected_with_out = p.distortionCorrect([ad_out],
                                                        arc=output)[0]
        ad_out_corrected_with_ref = p.distortionCorrect([ad_out],
                                                        arc=reference)[0]

        ad_out_corrected_with_out.write(
            overwrite=True,
            filename=os.path.join(config.output_dir,
                                  ad_out_corrected_with_out.filename),
        )

        for ext_out, ext_ref in zip(ad_out_corrected_with_out,
                                    ad_out_corrected_with_ref):
            np.testing.assert_allclose(ext_out.data, ext_ref.data)
예제 #29
0
def test_regression_trace_apertures(ad, change_working_dir, ref_ad_factory):

    with change_working_dir():
        logutils.config(file_name="log_regression_{}.txt".format(ad.data_label()))
        p = primitives_gmos_spect.GMOSSpect([ad])
        p.viewer = geminidr.dormantViewer(p, None)
        p.traceApertures()
        aperture_traced_ad = p.writeOutputs().pop()

    ref_ad = ref_ad_factory(aperture_traced_ad.filename)

    for ext, ref_ext in zip(aperture_traced_ad, ref_ad):
        input_table = ext.APERTURE
        reference_table = ref_ext.APERTURE

        assert input_table['aper_lower'][0] <= 0
        assert input_table['aper_upper'][0] >= 0

        keys = ext.APERTURE.colnames
        actual = np.array([input_table[k] for k in keys])
        desired = np.array([reference_table[k] for k in keys])
        np.testing.assert_allclose(desired, actual, atol=0.05)
def test_reduced_arcs_contain_wavelength_solution_model_with_expected_rms(
        ad, caplog, change_working_dir, fwidth, min_snr, order, request):
    """
    Make sure that the WAVECAL model was fitted with an RMS smaller than 0.2
    times the FWHM of the arc lines (i.e., less than half of the standard deviation).
    """
    caplog.set_level(logging.INFO, logger="geminidr")

    with change_working_dir():
        # logutils.config(file_name='log_rms_{:s}.txt'.format(ad.data_label()))
        p = primitives_gmos_spect.GMOSSpect([ad])
        p.viewer = geminidr.dormantViewer(p, None)

        p.determineWavelengthSolution(
            order=order,
            min_snr=min_snr,
            fwidth=fwidth,
            **determine_wavelength_solution_parameters)

        wcalibrated_ad = p.writeOutputs().pop()

        for record in caplog.records:
            if record.levelname == "WARNING":
                assert "No acceptable wavelength solution found" not in record.message

    if request.config.getoption("--do-plots"):
        do_plots(wcalibrated_ad)

    table = wcalibrated_ad[0].WAVECAL
    tdict = dict(zip(table['name'], table['coefficients']))
    rms = tdict['rms']

    fwidth = tdict['fwidth']
    dispersion = abs(
        wcalibrated_ad[0].dispersion(asNanometers=True))  # nm / px
    required_rms = 0.2 * fwidth * dispersion

    np.testing.assert_array_less(rms, required_rms)