Ejemplo n.º 1
0
def test_improved_gradient_reduces_precision(test_spec):
    """Check that the gradient produces larger RV error."""
    wav = test_spec[0]
    flux = test_spec[1]
    transmission = test_spec[2]

    a = Q.rv_precision(wav, flux, mask=transmission, grad=False).value
    b = Q.rv_precision(wav, flux, mask=transmission, grad=True).value
    assert a <= b
Ejemplo n.º 2
0
def test_relation_of_rv_to_sqrtsumwis(test_spec, wav_unit, flux_unit, trans_unit):
    """Test relation of sqrtsumwis to rv_precision."""
    wav = test_spec[0] * wav_unit
    flux = test_spec[1] * flux_unit
    mask = test_spec[2]
    if test_spec[2] is not None:
        mask *= trans_unit
        mask = mask ** 2
    assert np.all(
        Q.rv_precision(wav, flux, mask=mask) == c / Q.sqrt_sum_wis(wav, flux, mask=mask)
    )
Ejemplo n.º 3
0
def test_sqrt_sum_wis_with_mask_with_unit_fails(
    test_spec, wav_unit, flux_unit, trans_unit2
):
    """Assert a transmission with a unit fails with type error."""
    wav = test_spec[0] * wav_unit
    flux = test_spec[1] * flux_unit
    transmission = np.random.rand(len(wav)) * trans_unit2

    with pytest.raises(TypeError):
        Q.sqrt_sum_wis(wav, flux, mask=transmission ** 2)

    with pytest.raises(TypeError):
        Q.rv_precision(wav, flux, mask=transmission ** 2)
Ejemplo n.º 4
0
def test_transmission_reduces_precision(test_spec):
    """Check that a transmission vector reduces precision calculation."""
    wav = test_spec[0]
    flux = test_spec[1]
    transmission = test_spec[2]

    # Value should be less then normal if trans <=1
    if transmission is not None:
        assert Q.rv_precision(wav, flux, mask=None) < Q.rv_precision(
            wav, flux, mask=transmission
        )
    # mask=None is the same as mask of all 1.
    assert Q.rv_precision(wav, flux, mask=None) == Q.rv_precision(
        wav, flux, mask=np.ones_like(wav)
    )
Ejemplo n.º 5
0
def test_sqrt_sum_wis(test_spec, wav_unit, flux_unit, trans_unit):
    """Test that sqrt_sum_wis can handle inputs as Quantities or unitless.

    Returns a dimensionless unscaled Quantity.
    """
    wav = test_spec[0] * wav_unit
    flux = test_spec[1] * flux_unit
    mask = test_spec[2]
    if test_spec[2] is not None:
        mask *= trans_unit

    sqrtsumwis = Q.sqrt_sum_wis(wav, flux, mask)
    print("wav", wav, type(wav))
    print("flux", flux, type(flux))
    print("mask", mask, type(mask))
    print("sqrtsumwis", sqrtsumwis, type(sqrtsumwis))
    if (
        (isinstance(wav, Quantity))
        or (isinstance(flux, Quantity))
        or (isinstance(mask, Quantity) and (test_spec[2] is not None))
    ):
        assert isinstance(sqrtsumwis, u.Quantity)
        # Check is unscaled and dimensionless Quantity
        assert sqrtsumwis.unit == u.dimensionless_unscaled
        assert not hasattr(sqrtsumwis.value, "__len__")  # assert value is a scalar
    else:
        assert not hasattr(sqrtsumwis, "__len__")  # assert value is a scalar
Ejemplo n.º 6
0
def test_increments_rv_accumulate_same_as_full(real_spec, increment_percent, no_mask):
    """Assuming that the weighted rv from the steps should equal the rv from the band."""
    wav, flux, mask = real_spec[0], real_spec[1], real_spec[2]
    if no_mask:
        # Try with mask= None also.
        mask = None

    rv_full = Q.rv_precision(wav, flux, mask=mask).value
    x, incremented_rv = Q.incremental_rv(
        wav, flux, mask=mask, percent=increment_percent
    )
    incremented_weighted = weighted_error(incremented_rv)

    assert np.round(rv_full, 2) == np.round(incremented_weighted, 2)
    assert x[0] > wav[0]
    assert [-1] < wav[-1]
Ejemplo n.º 7
0
def test_sqrt_sum_wis_with_no_units(test_spec):
    """Test that sqrt_sum_wis can handle inputs as Quantities or unitless.
    Returns a dimensionless unscaled Quantity.
    """
    sqrtsumwis = Q.sqrt_sum_wis(test_spec[0], test_spec[1], test_spec[2])
    # Doesn't turn into quantity if does not have to.
    assert not isinstance(sqrtsumwis, u.Quantity)
    assert not hasattr(sqrtsumwis, "__len__")  # assert value is a scalar
Ejemplo n.º 8
0
def test_sqrtsumwis_warns_nonfinite(grad_flag):
    """Some warning tests."""
    with pytest.warns(UserWarning, match="This will cause infinite errors."):
        Q.sqrt_sum_wis(
            np.array([1, 2, 3]),
            np.array([1, 2, 3]),
            np.array([0, 0, 0]),
            grad=grad_flag,
        )  # All masked

    with pytest.warns(UserWarning, match="Weight sum is not finite"):
        Q.sqrt_sum_wis(
            np.array([2, 2, 2]),
            np.array([1, 2, 3]),
            np.array([1, 1, 1]),
            grad=grad_flag,
        )  # infinite gradient
Ejemplo n.º 9
0
def test_rvprev_calc_with_lists(test_spec):
    """Test that it can handle list input also."""
    wav = list(test_spec[0])
    flux = list(test_spec[1])
    mask = test_spec[2]
    rv = Q.rv_precision(wav, flux, mask)
    assert not hasattr(rv.value, "__len__")  # assert value is a scalar
    assert isinstance(rv, u.Quantity)
    assert rv.unit == m_per_s
Ejemplo n.º 10
0
def test_quality_independent_of_units(test_spec, wav_unit, flux_unit):
    """Quality should be returned as unitless (not a quantity)."""
    wave = test_spec[0] * wav_unit
    flux = test_spec[1] * flux_unit
    q = Q.quality(wave, flux)

    assert not isinstance(q, Quantity)
    assert isinstance(q, float)
    assert not hasattr(q, "__len__")  # assert value is a scalar
Ejemplo n.º 11
0
def test_normalize_flux_new_verse_old(resampled_data):
    """Test only small differences due to new normalization."""
    id_string, wav, flux = resampled_data

    print("wav in max =", wav[0], wav[-1])
    new_norm = eniric.obsolete.snr_norm.normalize_flux(flux,
                                                       id_string,
                                                       new=True)
    old_norm = eniric.obsolete.snr_norm.normalize_flux(flux,
                                                       id_string,
                                                       new=False)

    print("new norm", new_norm)
    print("old_norm", old_norm)

    rvprec_new = Q.rv_precision(wav, new_norm)
    rvprec_old = Q.rv_precision(wav, old_norm)

    print("new rv=", rvprec_new, "old rv=", rvprec_old)
    assert np.abs(rvprec_new.value - rvprec_old.value) < 0.4
Ejemplo n.º 12
0
def test_rvprev_calc(test_spec, wav_unit, flux_unit, trans_unit):
    """Test that rv_precision can handle inputs as Quantities or unitless and returns a scalar Quantity."""
    wav = test_spec[0] * wav_unit
    flux = test_spec[1] * flux_unit
    mask = test_spec[2]
    if test_spec[2] is not None:
        mask *= trans_unit

    rv = Q.rv_precision(wav, flux, mask)
    assert rv.unit == m_per_s
    assert not hasattr(rv.value, "__len__")  # assert value is a scalar
    assert isinstance(rv, u.Quantity)
Ejemplo n.º 13
0
def test_increments_rv_gives_reasonable_length(real_spec, increment_percent):
    """The expected number of steps would be between the
     wavelength difference divided by the
     first and last point * the percent increment.
     """
    wav, flux, mask = real_spec[0], real_spec[1], real_spec[2]
    x, rv = Q.incremental_rv(wav, flux, mask=mask, percent=increment_percent)
    d1 = wav[0] * increment_percent / 100
    d2 = wav[-1] * increment_percent / 100
    dlambda = wav[-1] - wav[0]
    len_rv = len(rv)

    assert len_rv >= np.floor(dlambda / d1)
    assert len_rv <= np.ceil(dlambda / d2 + 1)
    assert len(x) == len_rv
Ejemplo n.º 14
0
def test_increment_quality_gives_reasonable_length(real_spec, increment_percent):
    """The expected number of steps would be between the
    wavelength difference divided by the
    first and last point * the percent increment.
    """
    print(real_spec)
    wav, flux = real_spec[0], real_spec[1]
    x, q = Q.incremental_quality(wav, flux, percent=increment_percent)
    d1 = wav[0] * increment_percent / 100
    d2 = wav[-1] * increment_percent / 100
    dlambda = wav[-1] - wav[0]
    len_q = len(q)

    assert len_q >= np.floor(dlambda / d1)
    assert len_q <= np.ceil(dlambda / d2 + 1)
    assert len(x) == len_q
Ejemplo n.º 15
0
def test_sqrt_sum_wis_transmission_outofbounds(test_spec, wav_unit, flux_unit):
    """Transmission must be within 0-1."""
    wav = test_spec[0] * wav_unit
    flux = test_spec[1] * flux_unit
    mask_1 = np.random.randn(len(wav))
    mask_2 = np.random.rand(len(wav))

    mask_1[0] = 5  # Outside 0-1
    mask_2[-1] = -2  # Outside 0-1

    # Higher value
    with pytest.raises(ValueError):
        Q.rv_precision(wav, flux, mask=mask_1)

    with pytest.raises(ValueError):
        Q.sqrt_sum_wis(wav, flux, mask=mask_1)

        # Lower value
    with pytest.raises(ValueError):
        Q.sqrt_sum_wis(wav, flux, mask=mask_2)

    with pytest.raises(ValueError):
        Q.sqrt_sum_wis(wav, flux, mask=mask_2)
Ejemplo n.º 16
0
def calculate_prec(
    spectral_types,
    bands,
    vsini,
    resolution,
    sampling,
    plot_atm=False,
    plot_ste=False,
    plot_flux=True,
    paper_plots=True,
    rv_offset=0.0,
    use_unshifted=False,
    snr=100,
    ref_band="J",
    new=True,
    grad=True,
):
    """Calculate precisions for given combinations.

    grad: bool
        Use more precise gradient function.
    """
    # TODO: iterate over band last so that the J band normalization value can be
    # obtained first and applied to each band.

    print("using new config.yaml file here!!!!!!!!!!!!!!")
    results = {}  # creating empty dictionary for the results
    wav_plot_m0 = []  # creating empty lists for the plots
    flux_plot_m0 = []
    wav_plot_m3 = []
    flux_plot_m3 = []
    wav_plot_m6 = []
    flux_plot_m6 = []
    wav_plot_m9 = []
    flux_plot_m9 = []

    for band in bands:

        if use_unshifted:
            atmmodel = os.path.join(
                eniric.paths["atmmodel"],
                "{0}_{1}.dat".format(eniric.atmmodel["base"], band),
            )
            print("Reading atmospheric model...")
            atm = Atmosphere.from_file(atmmodel)
            wav_atm, flux_atm, std_flux_atm, mask_atm = (
                atm.wl,
                atm.transmission,
                atm.std,
                atm.mask,
            )

            print(
                (
                    "There were {0:d} unmasked pixels out of {1:d}., or {2:.1%}." ""
                ).format(
                    np.sum(mask_atm), len(mask_atm), np.sum(mask_atm) / len(mask_atm)
                )
            )

            print(
                "The model ranges from {0:4.2f} to {1:4.2f} micron.".format(
                    wav_atm[0], wav_atm[-1]
                )
            )
            print("Done.")
            print("Calculating impact of Barycentric movement on mask...")
            # mask_atm = atm.old_barycenter_shift(wav_atm, mask_atm, rv_offset=rv_offset)
            mask_atm = barycenter_shift(wav_atm, mask_atm, rv_offset=rv_offset)
        else:
            shifted_atmmodel = os.path.join(
                eniric.paths["atmmodel"],
                "{0}_{1}_bary.dat".format(eniric.atmmodel["base"], band),
            )
            print("Reading pre-doppler-shifted atmospheric model...")
            atm = Atmosphere.from_file(shifted_atmmodel)
            wav_atm, flux_atm, std_flux_atm, mask_atm = (
                atm.wl,
                atm.transmission,
                atm.std,
                atm.mask,
            )

        print("Done.")

        print(
            ("There were {0:d} unmasked pixels out of {1:d}, or {2:.1%}." "").format(
                np.sum(mask_atm), len(mask_atm), np.sum(mask_atm) / len(mask_atm)
            )
        )

        if plot_atm:
            # moved plotting code to separate code, eniric.obsolete.plotting_functions.py
            plt_functions.plot_atmosphere_model(wav_atm, flux_atm, mask_atm)

        # theoretical ratios calculation
        # wav_m0, flux_m0, wav_m3, flux_m3, wav_m6, flux_m6, wav_m9, flux_m9 = read_nIRspectra()

        iterations = itertools.product(spectral_types, vsini, resolution, sampling)
        # for star in spectral_types:
        #     for vel in vsini:
        #         for res in resolution:
        #             for smpl in sampling:
        for (star, vel, res, smpl) in iterations:
            file_to_read = (
                "Spectrum_{0}-PHOENIX-ACES_{1}band_vsini{2}_R{3}" "_res{4:2.01f}.dat"
            ).format(star, band, vel, res, float(smpl))
            # print("Working on "+file_to_read+".")
            try:
                wav_stellar, flux_stellar = io.pdread_2col(
                    os.path.join(eniric.paths["resampled"], file_to_read)
                )
            except FileNotFoundError:
                # Turn list of strings into strings without symbols  ["J", "K"] -> J K
                spectral_str = re.sub(r"[\[\]\"\',]", "", str(spectral_types))
                band_str = re.sub(r"[\[\]\"\',]", "", str(bands))
                vsini_str = re.sub(r"[\[\]\"\',]", "", str(vsini))
                res_str = re.sub(r"[\[\]\"\',]", "", str(resolution))
                sampling_str = re.sub(r"[\[\]\"\',]", "", str(sampling))

                print(
                    (
                        "\nFor just this file I suggest you run\n\tpython nIR_run.py -s {0} -b {1} -v {2} -R {3} "
                        "--sample_rate {4}\nOr for all the combinations you ran here\n\tpython nIR_run.py -s {5}"
                        " -b {6} -v {7} -R {8} --sample_rate {9}"
                        ""
                    ).format(
                        star,
                        band,
                        vel,
                        res,
                        smpl,
                        spectral_str,
                        band_str,
                        vsini_str,
                        res_str,
                        sampling_str,
                    )
                )
                raise
            if len(wav_stellar) == 0 or len(flux_stellar) == 0:
                raise Exception("The file {0} is empty".format(file_to_read))
            # Removing boundary effects
            wav_stellar = wav_stellar[2:-2]
            flux_stellar = flux_stellar[2:-2]

            # sample was left aside because only one value existed
            # TODO: Add metallicity and logg into id string
            id_string = "{0:s}-{1:s}-{2:.1f}-{3:s}".format(star, band, float(vel), res)

            # Getting the wav, flux and mask values from the atm model
            # that are the closest to the stellar wav values, see
            # https://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array
            index_atm = np.searchsorted(wav_atm, wav_stellar)
            # replace indexes outside the array, at the very end, by the value at the very end
            # index_atm = [index if(index < len(wav_atm)) else len(wav_atm)-1 for index in index_atm]
            indx_mask = index_atm >= len(wav_atm)  # find broken indexs
            index_atm[indx_mask] = len(wav_atm) - 1  # replace with index of end.

            wav_atm_selected = wav_atm[index_atm]
            flux_atm_selected = flux_atm[index_atm]
            mask_atm_selected = mask_atm[index_atm]

            # Check mask masks out deep atmosphere absorption
            if np.any(flux_atm_selected[mask_atm_selected] < 0.98):
                print(
                    "####WARNGING####\nThis absorption mask does not mask out deep atmosphere transmission!"
                )
                print(
                    "Min flux_atm_selected[mask_atm_selected] = {} < 0.98\n####".format(
                        np.min(flux_atm_selected[mask_atm_selected])
                    )
                )

            # Normalize to SNR 100 in middle of J band 1.25 micron!
            # flux_stellar = normalize_flux(flux_stellar, id_string)
            # flux_stellar = snrnorm.normalize_flux(flux_stellar, id_string, new=True)  # snr=100, ref_band="J"
            flux_stellar = eniric.obsolete.snr_norm.normalize_flux(
                flux_stellar,
                id_string,
                new=new,
                snr=snr,
                ref_band=ref_band,
                sampling=smpl,
            )

            if id_string in [
                "M0-J-1.0-100k",
                "M3-J-1.0-100k",
                "M6-J-1.0-100k",
                "M9-J-1.0-100k",
            ]:
                index_ref = np.searchsorted(
                    wav_stellar, 1.25
                )  # searching for the index closer to 1.25 micron
                snr_estimate = np.sqrt(
                    np.sum(flux_stellar[index_ref - 1 : index_ref + 2])
                )
                print(
                    "\tSanity Check: The S/N for the {0:s} reference model was of {1:4.2f}.".format(
                        id_string, snr_estimate
                    )
                )
            elif "J" in id_string:
                index_ref = np.searchsorted(
                    wav_stellar, 1.25
                )  # searching for the index closer to 1.25 micron
                snr_estimate = np.sqrt(
                    np.sum(flux_stellar[index_ref - 1 : index_ref + 2])
                )
                print(
                    "\tSanity Check: The S/N for the {0:s} non-reference model was of {1:4.2f}.".format(
                        id_string, snr_estimate
                    )
                )

            # Precision given by the first method:
            print("Performing analysis for: ", id_string)
            prec_1 = Qcalculator.rv_precision(wav_stellar, flux_stellar, grad=grad)

            # Precision as given by the second_method
            wav_stellar_chunks, flux_stellar_chunks = eniric.legacy.mask_clumping(
                wav_stellar, flux_stellar, mask_atm_selected
            )

            prec_2_old = eniric.legacy.RVprec_calc_masked(
                wav_stellar_chunks, flux_stellar_chunks, grad=grad
            )
            prec_2 = eniric.legacy.RVprec_calc_masked(
                wav_stellar, flux_stellar, mask_atm_selected, grad=grad
            )

            assert np.all(prec_2_old == prec_2)

            """
            # histogram checking
            lengths = [len(chunk) for chunk in flux_stellar_chunks_unformatted]
            n, bins, patches = plt.hist(lengths, 500, range=[0.5, 500.5], histtype='stepfilled')
            plt.title(id_string)
            plt.show()
            """

            # Precision as given by the third_method
            prec_3 = Qcalculator.rv_precision(
                wav_stellar, flux_stellar, mask=flux_atm_selected ** 2, grad=grad
            )

            # Adding Precision results to the dictionary
            results[id_string] = [prec_1, prec_2, prec_3]

            # Prepare/Do for the plotting.
            if plot_ste or plot_ste == id_string:
                plt_functions.plot_stellar_spectum(
                    wav_stellar, flux_stellar, wav_atm_selected, mask_atm_selected
                )

            plot_ids = [
                "M3-Z-1.0-100k",
                "M3-Y-1.0-100k",
                "M3-J-1.0-100k",
                "M3-H-1.0-100k",
                "M3-K-1.0-100k",
            ]

            if plot_flux and id_string in plot_ids:
                wav_plot_m0.append(wav_stellar)
                flux_plot_m0.append(flux_stellar)
            if plot_flux and id_string in plot_ids:
                wav_plot_m3.append(wav_stellar)
                flux_plot_m3.append(flux_stellar)
            if plot_flux and id_string in plot_ids:
                wav_plot_m6.append(wav_stellar)
                flux_plot_m6.append(flux_stellar)
            if plot_flux and id_string in plot_ids:
                wav_plot_m9.append(wav_stellar)
                flux_plot_m9.append(flux_stellar)

    if plot_flux:
        plt_functions.plot_nIR_flux()

    if paper_plots:
        plt_functions.plot_paper_plots()

    else:
        return results
Ejemplo n.º 17
0
def test_quality_independent_of_flux_level(scale):
    """Q of a spectrum is independent of flux level."""
    wavelength = np.arange(100)
    flux = np.random.random(100)
    assert np.allclose(Q.quality(wavelength, flux), Q.quality(wavelength, flux * scale))