Esempio n. 1
0
def clean_telluric_regions(spec_id, clean_percent):
    star_spectrum = ispec.read_spectrum(spec_id)
    #--- Telluric velocity shift determination from spectrum --------------------------
    logging.info("Telluric velocity shift determination...")
    # - Telluric
    telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
    telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.0)

    models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \
                            lower_velocity_limit=-100, upper_velocity_limit=100, \
                            velocity_step=0.5, mask_depth=0.01, \
                            fourier = False,
                            only_one_peak = True)

    bv = np.round(models[0].mu(), 2) # km/s
    bv_err = np.round(models[0].emu(), 2) # km/s

    #--- Clean regions that may be affected by tellurics ---------------------------
    logging.info("Cleaning tellurics...")

    telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
    telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.0)

    # - Filter regions that may be affected by telluric lines
    #bv = 0.0
    min_vel = -30.0
    max_vel = +30.0
    # Only the 25% of the deepest ones:
    dfilter = telluric_linelist['depth'] > np.percentile(telluric_linelist['depth'], clean_percent)
    tfilter = ispec.create_filter_for_regions_affected_by_tellurics(star_spectrum['waveobs'], \
                                telluric_linelist[dfilter], min_velocity=-bv+min_vel, \
                                max_velocity=-bv+max_vel)
    clean_star_spectrum = star_spectrum[~tfilter]
    ispec.write_spectrum(clean_star_spectrum, spec_id)
Esempio n. 2
0
    def test_clean_telluric_regions(self):
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")
        #--- Telluric velocity shift determination from spectrum --------------------------
        # - Telluric
        telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        telluric_linelist = ispec.read_telluric_linelist(
            telluric_linelist_file, minimum_depth=0.0)

        models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \
                                lower_velocity_limit=-100, upper_velocity_limit=100, \
                                velocity_step=0.5, mask_depth=0.01, \
                                fourier = False,
                                only_one_peak = True)

        bv = np.round(models[0].mu(), 2)  # km/s
        bv_err = np.round(models[0].emu(), 2)  # km/s

        #--- Clean regions that may be affected by tellurics ---------------------------
        telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        telluric_linelist = ispec.read_telluric_linelist(
            telluric_linelist_file, minimum_depth=0.0)

        # - Filter regions that may be affected by telluric lines
        #bv = 0.0
        min_vel = -30.0
        max_vel = +30.0
        # Only the 25% of the deepest ones:
        dfilter = telluric_linelist['depth'] > np.percentile(
            telluric_linelist['depth'], 75)
        tfilter = ispec.create_filter_for_regions_affected_by_tellurics(star_spectrum['waveobs'], \
                                    telluric_linelist[dfilter], min_velocity=-bv+min_vel, \
                                    max_velocity=-bv+max_vel)
        clean_star_spectrum = star_spectrum[~tfilter]
        self.assertEqual(len(np.where(tfilter)[0]), 686)
        self.assertEqual(np.where(tfilter)[0][0], 45002)
        self.assertEqual(np.where(tfilter)[0][-1], 46051)
Esempio n. 3
0
def cleanTelluricRegions(spec):
    """
    Remove regions affected by tellurics

    Based on exmaple.py clean_telluric_regions() function
    """
    # determine telluric velocity shift
    linelist_telluric = ispec.read_telluric_linelist(telluricLines, minimum_depth=0.0)
    models, ccf = ispec.cross_correlate_with_mask(spec, \
                                                  linelist_telluric, \
                                                  lower_velocity_limit=-100, \
                                                  upper_velocity_limit=100, \
                                                  velocity_step=0.25, \
                                                  mask_size=2.0, \
                                                  mask_depth=0.01, \
                                                  fourier=False, \
                                                  only_one_peak=True)
    try:
        bv = np.round(models[0].mu(), 2) # km/s
        bv_err = np.round(models[0].emu(), 2) # km/s
    except IndexError:
        print '\n\n\nPROBLEM MEASURING TELLURICS, SKIPPING...\n\n\n'
        return 0.0, 0.0, spec
    # not sure why we load this again, but iSpec example does, so...
    linelist_telluric = ispec.read_telluric_linelist(telluricLines, minimum_depth=0.0)
    # clean regions that may be affected by tellurics
    min_vel = -30.0
    max_vel = +30.0
    # Only the 25% of the deepest ones:
    dfilter = linelist_telluric['depth'] > np.percentile(linelist_telluric['depth'], 75)
    tfilter = ispec.create_filter_for_regions_affected_by_tellurics(spec['waveobs'], \
                                                                    linelist_telluric[dfilter],\
                                                                    min_velocity=-bv+min_vel, \
                                                                    max_velocity=-bv+max_vel)
    clean_spec = spec[~tfilter]
    return bv, bv_err, clean_spec
Esempio n. 4
0
    def test_determine_tellurics_shift_with_mask(self):
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")
        #--- Telluric velocity shift determination from spectrum --------------------------
        # - Telluric
        telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        telluric_linelist = ispec.read_telluric_linelist(
            telluric_linelist_file, minimum_depth=0.0)

        models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \
                                lower_velocity_limit=-100, upper_velocity_limit=100, \
                                velocity_step=0.5, mask_depth=0.01, \
                                fourier = False,
                                only_one_peak = True)

        bv = models[0].mu()  # km/s
        bv_err = models[0].emu()  # km/s
        self.assertAlmostEqual(bv, 8.139999999999954)
        self.assertAlmostEqual(bv_err, 0.031123202937016047)
Esempio n. 5
0
def clean_telluric_regions(star_spectrum, replace_mask_zero=False):
    ''' Clean telluric regions from given spectrum and return clean spectrum and
    velocity offset '''
    logging.info("Telluric velocity shift determination...")
    # - Read telluric linelist
    telluric_linelist_file = ispec_dir + \
            "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
    telluric_linelist = ispec.read_telluric_linelist(\
            telluric_linelist_file, minimum_depth=0.0)

    # find cross correlation function of star_spectrum and selected mask
    # in this case, mask is telluric_line_mask
    # with preset limit velocity
    # and find extreme values
    models, ccf = ispec.cross_correlate_with_mask(star_spectrum, \
            telluric_linelist, lower_velocity_limit=-100, \
            upper_velocity_limit=100, velocity_step=0.5, \
            mask_depth=0.01, fourier = False, only_one_peak = True)

    #round down to 2 decimals
    bv = np.round(models[0].mu(), 2)  # km/s
    bv_err = np.round(models[0].emu(), 2)  # km/s

    # - Filter regions that may be affected by telluric lines
    #bv = 0.0
    min_vel = -30.0
    max_vel = +30.0
    # Only the 25% of the deepest ones:
    dfilter = telluric_linelist['depth'] > np.percentile(
        telluric_linelist['depth'], 75)
    tfilter = ispec.create_filter_for_regions_affected_by_tellurics(\
            star_spectrum['waveobs'], telluric_linelist[dfilter], \
            min_velocity=-bv+min_vel, max_velocity=-bv+max_vel)
    clean_star_spectrum = star_spectrum[~tfilter]

    #if you want to replace removed flux with 0
    if replace_mask_zero:
        clean_star_spectrum = star_spectrum.copy()
        clean_star_spectrum['flux'][tfilter] = 0

    return clean_star_spectrum, bv
Esempio n. 6
0
    def test_find_linemasks(self):
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")
        #--- Radial Velocity determination with template -------------------------------
        # - Read synthetic template
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Arcturus.372_926nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Sun.372_926nm/template.txt.gz")
        template = ispec.read_spectrum(
            ispec_dir +
            "/input/spectra/templates/NARVAL.Sun.370_1048nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Synth.Sun.300_1100nm/template.txt.gz")

        models, ccf = ispec.cross_correlate_with_template(star_spectrum, template, \
                                lower_velocity_limit=-200, upper_velocity_limit=200, \
                                velocity_step=1.0, fourier=False)

        # Number of models represent the number of components
        components = len(models)
        # First component:
        rv = np.round(models[0].mu(), 2)  # km/s
        rv_err = np.round(models[0].emu(), 2)  # km/s
        #--- Radial Velocity correction ------------------------------------------------
        star_spectrum = ispec.correct_velocity(star_spectrum, rv)
        #--- Telluric velocity shift determination from spectrum --------------------------
        # - Telluric
        telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        telluric_linelist = ispec.read_telluric_linelist(
            telluric_linelist_file, minimum_depth=0.0)

        models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \
                                lower_velocity_limit=-100, upper_velocity_limit=100, \
                                velocity_step=0.5, mask_depth=0.01, \
                                fourier = False,
                                only_one_peak = True)

        vel_telluric = np.round(models[0].mu(), 2)  # km/s
        vel_telluric_err = np.round(models[0].emu(), 2)  # km/s
        #--- Continuum fit -------------------------------------------------------------
        model = "Splines"  # "Polynomy"
        degree = 2
        nknots = None  # Automatic: 1 spline every 5 nm
        from_resolution = 80000

        # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum
        order = 'median+max'
        median_wave_range = 0.05
        max_wave_range = 1.0

        star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \
                                    nknots=nknots, degree=degree, \
                                    median_wave_range=median_wave_range, \
                                    max_wave_range=max_wave_range, \
                                    model=model, order=order, \
                                    automatic_strong_line_detection=True, \
                                    strong_line_probability=0.5, \
                                    use_errors_for_fitting=True)
        #--- Find linemasks ------------------------------------------------------------
        #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/VALD.300_1100nm/atomic_lines.tsv"
        #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/VALD.1100_2400nm/atomic_lines.tsv"
        atomic_linelist_file = ispec_dir + "/input/linelists/transitions/GESv6_atom_hfs_iso.420_920nm/atomic_lines.tsv"
        #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/GESv6_atom_nohfs_noiso.420_920nm/atomic_lines.tsv"

        telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"

        # Read
        atomic_linelist = ispec.read_atomic_linelist(
            atomic_linelist_file,
            wave_base=np.min(star_spectrum['waveobs']),
            wave_top=np.max(star_spectrum['waveobs']))
        atomic_linelist = atomic_linelist[
            atomic_linelist['theoretical_depth'] >=
            0.01]  # Select lines that have some minimal contribution in the sun
        #telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.01)
        #vel_telluric = 17.79  # km/s
        #telluric_linelist = None
        #vel_telluric = None

        resolution = 80000
        smoothed_star_spectrum = ispec.convolve_spectrum(
            star_spectrum, resolution)
        min_depth = 0.05
        max_depth = 1.00
        star_linemasks = ispec.find_linemasks(star_spectrum, star_continuum_model, \
                                atomic_linelist=atomic_linelist, \
                                max_atomic_wave_diff = 0.005, \
                                telluric_linelist=telluric_linelist, \
                                vel_telluric=vel_telluric, \
                                minimum_depth=min_depth, maximum_depth=max_depth, \
                                smoothed_spectrum=smoothed_star_spectrum, \
                                check_derivatives=False, \
                                discard_gaussian=False, discard_voigt=True, \
                                closest_match=False)
        # Exclude lines that have not been successfully cross matched with the atomic data
        # because we cannot calculate the chemical abundance (it will crash the corresponding routines)
        rejected_by_atomic_line_not_found = (star_linemasks['wave_nm'] == 0)
        star_linemasks = star_linemasks[~rejected_by_atomic_line_not_found]

        # Exclude lines with EW equal to zero
        rejected_by_zero_ew = (star_linemasks['ew'] == 0)
        star_linemasks = star_linemasks[~rejected_by_zero_ew]

        # Select only iron lines
        iron = star_linemasks['element'] == "Fe 1"
        iron = np.logical_or(iron, star_linemasks['element'] == "Fe 2")
        iron_star_linemasks = star_linemasks[iron]

        self.assertEqual(len(star_linemasks), 1732)
        self.assertEqual(len(iron_star_linemasks), 883)
        self.assertAlmostEqual(iron_star_linemasks['ew'][0], 15.82970157775808)
        self.assertAlmostEqual(iron_star_linemasks['ew'][-1],
                               15.545342323635188)
        self.assertAlmostEqual(iron_star_linemasks['ew_err'][0],
                               1.1187509030236669)
        self.assertAlmostEqual(iron_star_linemasks['ew_err'][-1],
                               1.3221015426240295)

        tmp_filename = tempfile.mktemp()
        # Write regions with masks limits, cross-matched atomic data and fit data
        ispec.write_line_regions(star_linemasks, tmp_filename, extended=True)
        recover_star_linemasks = ispec.read_line_regions(tmp_filename)
        os.remove(tmp_filename)
        # Write regions with masks limits and cross-matched atomic data (fit data fields are zeroed)
        zeroed_star_linemasks = ispec.reset_fitted_data_fields(star_linemasks)

        np.testing.assert_almost_equal(star_linemasks['wave_nm'],
                                       recover_star_linemasks['wave_nm'])
        np.testing.assert_almost_equal(star_linemasks['ew'],
                                       recover_star_linemasks['ew'],
                                       decimal=1)
        np.testing.assert_almost_equal(star_linemasks['wave_base'],
                                       recover_star_linemasks['wave_base'],
                                       decimal=4)
        np.testing.assert_almost_equal(star_linemasks['wave_top'],
                                       recover_star_linemasks['wave_top'],
                                       decimal=4)
        np.testing.assert_almost_equal(star_linemasks['wave_peak'],
                                       recover_star_linemasks['wave_peak'],
                                       decimal=4)
        self.assertTrue(np.all(zeroed_star_linemasks['ew'] == 0))
Esempio n. 7
0
    def _determine_abundances_from_ew(self, code):
        use_ares = False
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")
        #--- Radial Velocity determination with template -------------------------------
        # - Read synthetic template
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Arcturus.372_926nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Sun.372_926nm/template.txt.gz")
        template = ispec.read_spectrum(
            ispec_dir +
            "/input/spectra/templates/NARVAL.Sun.370_1048nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Synth.Sun.300_1100nm/template.txt.gz")

        models, ccf = ispec.cross_correlate_with_template(star_spectrum, template, \
                                lower_velocity_limit=-200, upper_velocity_limit=200, \
                                velocity_step=1.0, fourier=False)

        # Number of models represent the number of components
        components = len(models)
        # First component:
        rv = np.round(models[0].mu(), 2)  # km/s
        rv_err = np.round(models[0].emu(), 2)  # km/s
        #--- Radial Velocity correction ------------------------------------------------
        star_spectrum = ispec.correct_velocity(star_spectrum, rv)
        #--- Telluric velocity shift determination from spectrum --------------------------
        # - Telluric
        telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        telluric_linelist = ispec.read_telluric_linelist(
            telluric_linelist_file, minimum_depth=0.0)

        models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \
                                lower_velocity_limit=-100, upper_velocity_limit=100, \
                                velocity_step=0.5, mask_depth=0.01, \
                                fourier = False,
                                only_one_peak = True)

        vel_telluric = np.round(models[0].mu(), 2)  # km/s
        vel_telluric_err = np.round(models[0].emu(), 2)  # km/s
        #--- Resolution degradation ----------------------------------------------------
        # NOTE: The line selection was built based on a solar spectrum with R ~ 47,000 and GES/VALD atomic linelist.
        from_resolution = 80000
        to_resolution = 47000
        star_spectrum = ispec.convolve_spectrum(star_spectrum, to_resolution,
                                                from_resolution)
        #--- Continuum fit -------------------------------------------------------------
        model = "Splines"  # "Polynomy"
        degree = 2
        nknots = None  # Automatic: 1 spline every 5 nm
        #from_resolution = 80000
        from_resolution = to_resolution

        # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum
        order = 'median+max'
        median_wave_range = 0.05
        max_wave_range = 1.0

        star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \
                                    nknots=nknots, degree=degree, \
                                    median_wave_range=median_wave_range, \
                                    max_wave_range=max_wave_range, \
                                    model=model, order=order, \
                                    automatic_strong_line_detection=True, \
                                    strong_line_probability=0.5, \
                                    use_errors_for_fitting=True)
        #--- Normalize -------------------------------------------------------------
        normalized_star_spectrum = ispec.normalize_spectrum(
            star_spectrum,
            star_continuum_model,
            consider_continuum_errors=False)
        # Use a fixed value because the spectrum is already normalized
        star_continuum_model = ispec.fit_continuum(star_spectrum,
                                                   fixed_value=1.0,
                                                   model="Fixed value")

        #telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        #telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.01)
        #vel_telluric = 17.79 # km/s
        #telluric_linelist = None
        #vel_telluric = None

        #--- Read lines and adjust them ------------------------------------------------
        if code in ['width', 'moog']:
            line_regions_with_atomic_data = ispec.read_line_regions(
                ispec_dir +
                "/input/regions/47000_GES/{}_ew_ispec_good_for_params_all_extended.txt"
                .format(code))
            #line_regions_with_atomic_data = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/{}_ew_ispec_good_for_params_all_extended.txt".format(code))
        else:
            line_regions_with_atomic_data = ispec.read_line_regions(
                ispec_dir +
                "/input/regions/47000_GES/{}_synth_good_for_params_all_extended.txt"
                .format(code))
            #line_regions_with_atomic_data = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/{}_synth_good_for_params_all_extended.txt".format(code))

        # Select only iron lines
        line_regions_with_atomic_data = line_regions_with_atomic_data[
            np.logical_or(line_regions_with_atomic_data['note'] == "Fe 1",
                          line_regions_with_atomic_data['note'] == "Fe 2")]

        smoothed_star_spectrum = ispec.convolve_spectrum(
            star_spectrum, 2 * to_resolution)
        line_regions_with_atomic_data = ispec.adjust_linemasks(
            smoothed_star_spectrum,
            line_regions_with_atomic_data,
            max_margin=0.5)

        #--- Fit the lines but do NOT cross-match with any atomic linelist since they already have that information
        linemasks = ispec.fit_lines(line_regions_with_atomic_data, normalized_star_spectrum, star_continuum_model, \
                                    atomic_linelist = None, \
                                    max_atomic_wave_diff = 0.005, \
                                    telluric_linelist = telluric_linelist, \
                                    check_derivatives = False, \
                                    vel_telluric = vel_telluric, discard_gaussian=False, \
                                    smoothed_spectrum=None, \
                                    discard_voigt=True, \
                                    free_mu=True, crossmatch_with_mu=False, closest_match=False)

        # Discard bad masks
        flux_peak = normalized_star_spectrum['flux'][linemasks['peak']]
        flux_base = normalized_star_spectrum['flux'][linemasks['base']]
        flux_top = normalized_star_spectrum['flux'][linemasks['top']]
        bad_mask = np.logical_or(
            linemasks['wave_peak'] <= linemasks['wave_base'],
            linemasks['wave_peak'] >= linemasks['wave_top'])
        bad_mask = np.logical_or(bad_mask, flux_peak >= flux_base)
        bad_mask = np.logical_or(bad_mask, flux_peak >= flux_top)
        linemasks = linemasks[~bad_mask]

        # Exclude lines with EW equal to zero
        rejected_by_zero_ew = (linemasks['ew'] == 0)
        linemasks = linemasks[~rejected_by_zero_ew]

        # Exclude lines that may be affected by tellurics
        rejected_by_telluric_line = (linemasks['telluric_wave_peak'] != 0)
        linemasks = linemasks[~rejected_by_telluric_line]
        linemasks = linemasks[:20]

        if use_ares:
            # Replace the measured equivalent widths by the ones computed by ARES
            old_linemasks = linemasks.copy()
            ### Different rejection parameters (check ARES papers):
            ##   - http://adsabs.harvard.edu/abs/2007A%26A...469..783S
            ##   - http://adsabs.harvard.edu/abs/2015A%26A...577A..67S
            #linemasks = ispec.update_ew_with_ares(normalized_star_spectrum, linemasks, rejt="0.995", tmp_dir=None, verbose=0)
            #linemasks = ispec.update_ew_with_ares(normalized_star_spectrum, linemasks, rejt="3;5764,5766,6047,6052,6068,6076", tmp_dir=None, verbose=0)
            snr = 50
            linemasks = ispec.update_ew_with_ares(normalized_star_spectrum,
                                                  linemasks,
                                                  rejt="%s" % (snr),
                                                  tmp_dir=None,
                                                  verbose=0)

        #--- Determining abundances by EW of the previously fitted lines ---------------
        # Parameters
        teff = 5777.0
        logg = 4.44
        MH = 0.00
        alpha = 0.00
        microturbulence_vel = 1.0

        # Selected model amtosphere and solar abundances
        #model = ispec_dir + "/input/atmospheres/MARCS/"
        model = ispec_dir + "/input/atmospheres/MARCS.GES/"
        #model = ispec_dir + "/input/atmospheres/MARCS.APOGEE/"
        #model = ispec_dir + "/input/atmospheres/ATLAS9.APOGEE/"
        #model = ispec_dir + "/input/atmospheres/ATLAS9.Castelli/"
        #model = ispec_dir + "/input/atmospheres/ATLAS9.Kurucz/"
        #model = ispec_dir + "/input/atmospheres/ATLAS9.Kirby/"

        if "ATLAS" in model:
            solar_abundances_file = ispec_dir + "/input/abundances/Grevesse.1998/stdatom.dat"
        else:
            # MARCS
            solar_abundances_file = ispec_dir + "/input/abundances/Grevesse.2007/stdatom.dat"
        #solar_abundances_file = ispec_dir + "/input/abundances/Asplund.2005/stdatom.dat"
        #solar_abundances_file = ispec_dir + "/input/abundances/Asplund.2009/stdatom.dat"
        #solar_abundances_file = ispec_dir + "/input/abundances/Anders.1989/stdatom.dat"

        # Load model atmospheres
        modeled_layers_pack = ispec.load_modeled_layers_pack(model)
        # Load SPECTRUM abundances
        solar_abundances = ispec.read_solar_abundances(solar_abundances_file)

        # Validate parameters
        if not ispec.valid_atmosphere_target(modeled_layers_pack, {
                'teff': teff,
                'logg': logg,
                'MH': MH,
                'alpha': alpha
        }):
            msg = "The specified effective temperature, gravity (log g) and metallicity [M/H] \
                    fall out of theatmospheric models."

            print(msg)

        # Prepare atmosphere model
        atmosphere_layers = ispec.interpolate_atmosphere_layers(
            modeled_layers_pack, {
                'teff': teff,
                'logg': logg,
                'MH': MH,
                'alpha': alpha
            },
            code=code)
        spec_abund, normal_abund, x_over_h, x_over_fe = ispec.determine_abundances(atmosphere_layers, \
                teff, logg, MH, alpha, linemasks, solar_abundances, microturbulence_vel = microturbulence_vel, \
                verbose=1, code=code)
        return linemasks, x_over_h
Esempio n. 8
0
    def test_determine_astrophysical_parameters_from_ew(self):
        code = "moog"
        use_ares = False
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")
        #--- Radial Velocity determination with template -------------------------------
        # - Read synthetic template
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Arcturus.372_926nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Sun.372_926nm/template.txt.gz")
        template = ispec.read_spectrum(
            ispec_dir +
            "/input/spectra/templates/NARVAL.Sun.370_1048nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Synth.Sun.300_1100nm/template.txt.gz")

        models, ccf = ispec.cross_correlate_with_template(star_spectrum, template, \
                                lower_velocity_limit=-200, upper_velocity_limit=200, \
                                velocity_step=1.0, fourier=False)

        # Number of models represent the number of components
        components = len(models)
        # First component:
        rv = np.round(models[0].mu(), 2)  # km/s
        rv_err = np.round(models[0].emu(), 2)  # km/s
        #--- Radial Velocity correction ------------------------------------------------
        star_spectrum = ispec.correct_velocity(star_spectrum, rv)
        #--- Telluric velocity shift determination from spectrum --------------------------
        # - Telluric
        telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        telluric_linelist = ispec.read_telluric_linelist(
            telluric_linelist_file, minimum_depth=0.0)

        models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \
                                lower_velocity_limit=-100, upper_velocity_limit=100, \
                                velocity_step=0.5, mask_depth=0.01, \
                                fourier = False,
                                only_one_peak = True)

        vel_telluric = np.round(models[0].mu(), 2)  # km/s
        vel_telluric_err = np.round(models[0].emu(), 2)  # km/s
        #--- Resolution degradation ----------------------------------------------------
        # NOTE: The line selection was built based on a solar spectrum with R ~ 47,000 and GES/VALD atomic linelist.
        from_resolution = 80000
        to_resolution = 47000
        star_spectrum = ispec.convolve_spectrum(star_spectrum, to_resolution,
                                                from_resolution)
        #--- Continuum fit -------------------------------------------------------------
        model = "Splines"  # "Polynomy"
        degree = 2
        nknots = None  # Automatic: 1 spline every 5 nm
        #from_resolution = 80000
        from_resolution = to_resolution

        # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum
        order = 'median+max'
        median_wave_range = 0.05
        max_wave_range = 1.0

        star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \
                                    nknots=nknots, degree=degree, \
                                    median_wave_range=median_wave_range, \
                                    max_wave_range=max_wave_range, \
                                    model=model, order=order, \
                                    automatic_strong_line_detection=True, \
                                    strong_line_probability=0.5, \
                                    use_errors_for_fitting=True)
        #--- Normalize -------------------------------------------------------------
        normalized_star_spectrum = ispec.normalize_spectrum(
            star_spectrum,
            star_continuum_model,
            consider_continuum_errors=False)
        # Use a fixed value because the spectrum is already normalized
        star_continuum_model = ispec.fit_continuum(star_spectrum,
                                                   fixed_value=1.0,
                                                   model="Fixed value")

        #telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        #telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.01)
        #vel_telluric = 17.79 # km/s
        #telluric_linelist = None
        #vel_telluric = None

        #--- Read lines and adjust them ------------------------------------------------
        if code in ['width', 'moog']:
            line_regions_with_atomic_data = ispec.read_line_regions(
                ispec_dir +
                "/input/regions/47000_GES/{}_ew_ispec_good_for_params_all_extended.txt"
                .format(code))
            #line_regions_with_atomic_data = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/{}_ew_ispec_good_for_params_all_extended.txt".format(code))
        else:
            line_regions_with_atomic_data = ispec.read_line_regions(
                ispec_dir +
                "/input/regions/47000_GES/{}_synth_good_for_params_all_extended.txt"
                .format(code))
            #line_regions_with_atomic_data = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/{}_synth_good_for_params_all_extended.txt".format(code))

        # Select only iron lines
        line_regions_with_atomic_data = line_regions_with_atomic_data[
            np.logical_or(line_regions_with_atomic_data['note'] == "Fe 1",
                          line_regions_with_atomic_data['note'] == "Fe 2")]

        smoothed_star_spectrum = ispec.convolve_spectrum(
            star_spectrum, 2 * to_resolution)
        line_regions_with_atomic_data = ispec.adjust_linemasks(
            smoothed_star_spectrum,
            line_regions_with_atomic_data,
            max_margin=0.5)

        #--- Fit the lines but do NOT cross-match with any atomic linelist since they already have that information
        linemasks = ispec.fit_lines(line_regions_with_atomic_data, normalized_star_spectrum, star_continuum_model, \
                                    atomic_linelist = None, \
                                    max_atomic_wave_diff = 0.005, \
                                    telluric_linelist = telluric_linelist, \
                                    check_derivatives = False, \
                                    vel_telluric = vel_telluric, discard_gaussian=False, \
                                    smoothed_spectrum=None, \
                                    discard_voigt=True, \
                                    free_mu=True, crossmatch_with_mu=False, closest_match=False)

        # Discard bad masks
        flux_peak = normalized_star_spectrum['flux'][linemasks['peak']]
        flux_base = normalized_star_spectrum['flux'][linemasks['base']]
        flux_top = normalized_star_spectrum['flux'][linemasks['top']]
        bad_mask = np.logical_or(
            linemasks['wave_peak'] <= linemasks['wave_base'],
            linemasks['wave_peak'] >= linemasks['wave_top'])
        bad_mask = np.logical_or(bad_mask, flux_peak >= flux_base)
        bad_mask = np.logical_or(bad_mask, flux_peak >= flux_top)
        linemasks = linemasks[~bad_mask]

        # Exclude lines with EW equal to zero
        rejected_by_zero_ew = (linemasks['ew'] == 0)
        linemasks = linemasks[~rejected_by_zero_ew]

        # Exclude lines that may be affected by tellurics
        rejected_by_telluric_line = (linemasks['telluric_wave_peak'] != 0)
        linemasks = linemasks[~rejected_by_telluric_line]

        if use_ares:
            # Replace the measured equivalent widths by the ones computed by ARES
            old_linemasks = linemasks.copy()
            ### Different rejection parameters (check ARES papers):
            ##   - http://adsabs.harvard.edu/abs/2007A%26A...469..783S
            ##   - http://adsabs.harvard.edu/abs/2015A%26A...577A..67S
            #linemasks = ispec.update_ew_with_ares(normalized_star_spectrum, linemasks, rejt="0.995", tmp_dir=None, verbose=0)
            #linemasks = ispec.update_ew_with_ares(normalized_star_spectrum, linemasks, rejt="3;5764,5766,6047,6052,6068,6076", tmp_dir=None, verbose=0)
            snr = 50
            linemasks = ispec.update_ew_with_ares(normalized_star_spectrum,
                                                  linemasks,
                                                  rejt="%s" % (snr),
                                                  tmp_dir=None,
                                                  verbose=0)

        #--- Model spectra from EW --------------------------------------------------
        # Parameters
        initial_teff = 5777.0
        initial_logg = 4.44
        initial_MH = 0.00
        initial_alpha = 0.00
        initial_vmic = ispec.estimate_vmic(initial_teff, initial_logg,
                                           initial_MH)
        max_iterations = 10

        # Selected model amtosphere, linelist and solar abundances
        #model = ispec_dir + "/input/atmospheres/MARCS/"
        model = ispec_dir + "/input/atmospheres/MARCS.GES/"
        #model = ispec_dir + "/input/atmospheres/MARCS.APOGEE/"
        #model = ispec_dir + "/input/atmospheres/ATLAS9.APOGEE/"
        #model = ispec_dir + "/input/atmospheres/ATLAS9.Castelli/"
        #model = ispec_dir + "/input/atmospheres/ATLAS9.Kurucz/"
        #model = ispec_dir + "/input/atmospheres/ATLAS9.Kirby/"

        #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/VALD.300_1100nm/atomic_lines.tsv"
        #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/VALD.1100_2400nm/atomic_lines.tsv"
        atomic_linelist_file = ispec_dir + "/input/linelists/transitions/GESv6_atom_hfs_iso.420_920nm/atomic_lines.tsv"
        #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/GESv6_atom_nohfs_noiso.420_920nm/atomic_lines.tsv"

        if "ATLAS" in model:
            solar_abundances_file = ispec_dir + "/input/abundances/Grevesse.1998/stdatom.dat"
        else:
            # MARCS
            solar_abundances_file = ispec_dir + "/input/abundances/Grevesse.2007/stdatom.dat"
        #solar_abundances_file = ispec_dir + "/input/abundances/Asplund.2005/stdatom.dat"
        #solar_abundances_file = ispec_dir + "/input/abundances/Asplund.2009/stdatom.dat"
        #solar_abundances_file = ispec_dir + "/input/abundances/Anders.1989/stdatom.dat"

        # Load model atmospheres
        modeled_layers_pack = ispec.load_modeled_layers_pack(model)

        # Load SPECTRUM abundances
        solar_abundances = ispec.read_solar_abundances(solar_abundances_file)

        # Validate parameters
        if not ispec.valid_atmosphere_target(
                modeled_layers_pack, {
                    'teff': initial_teff,
                    'logg': initial_logg,
                    'MH': initial_MH,
                    'alpha': initial_alpha
                }):
            msg = "The specified effective temperature, gravity (log g) and metallicity [M/H] \
                    fall out of theatmospheric models."

            print(msg)

        # Reduced equivalent width
        # Filter too weak/strong lines
        # * Criteria presented in paper of GALA
        #efilter = np.logical_and(linemasks['ewr'] >= -5.8, linemasks['ewr'] <= -4.65)
        efilter = np.logical_and(linemasks['ewr'] >= -6.0,
                                 linemasks['ewr'] <= -4.3)
        # Filter high excitation potential lines
        # * Criteria from Eric J. Bubar "Equivalent Width Abundance Analysis In Moog"
        efilter = np.logical_and(efilter, linemasks['lower_state_eV'] <= 5.0)
        efilter = np.logical_and(efilter, linemasks['lower_state_eV'] >= 0.5)
        ## Filter also bad fits
        efilter = np.logical_and(efilter, linemasks['rms'] < 1.00)
        # no flux
        noflux = normalized_star_spectrum['flux'][linemasks['peak']] < 1.0e-10
        efilter = np.logical_and(efilter, np.logical_not(noflux))
        unfitted = linemasks['fwhm'] == 0
        efilter = np.logical_and(efilter, np.logical_not(unfitted))

        results = ispec.model_spectrum_from_ew(linemasks[efilter], modeled_layers_pack, \
                            solar_abundances, initial_teff, initial_logg, initial_MH, initial_alpha, initial_vmic, \
                            free_params=["teff", "logg", "vmic"], \
                            adjust_model_metalicity=True, \
                            max_iterations=max_iterations, \
                            enhance_abundances=True, \
                            #outliers_detection = "robust", \
                            #outliers_weight_limit = 0.90, \
                            outliers_detection = "sigma_clipping", \
                            #sigma_level = 3, \
                            tmp_dir = None, \
                            code=code)
        params, errors, status, x_over_h, selected_x_over_h, fitted_lines_params, used_linemasks = results

        expected_params = {
            'teff': 5825.366401775263,
            'logg': 4.3929210834771535,
            'MH': 0.03500000000000014,
            'alpha': 0.0,
            'vmic': 1.1670939448402673
        }
        for k, v in list(expected_params.items()):
            self.assertAlmostEqual(params[k], v)
        expected_errors = {
            'teff': 59.030776466850426,
            'logg': 0.08775700534919817,
            'MH': 0.0606561589029185,
            'alpha': 0.0,
            'vmic': 0.03900548810240552
        }
        for k, v in list(expected_errors.items()):
            self.assertAlmostEqual(errors[k], v)
Esempio n. 9
0
#mask_file = ispec_dir + "input/linelists/CCF/Narval.Sun.370_1048nm/mask.lst"
#mask_file = ispec_dir + "input/linelists/CCF/Atlas.Arcturus.372_926nm/mask.lst""
#mask_file = ispec_dir + "input/linelists/CCF/Atlas.Sun.372_926nm/mask.lst"
#mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.A0.350_1095nm/mask.lst"
#mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.F0.360_698nm/mask.lst"
#mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.G2.375_679nm/mask.lst"
#mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.K0.378_679nm/mask.lst"
#mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.K5.378_680nm/mask.lst"
#mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.M5.400_687nm/mask.lst"
#mask_file = ispec_dir + "input/linelists/CCF/Synthetic.Sun.350_1100nm/mask.lst"
mask_file = ispec_dir + "input/linelists/CCF/VALD.Sun.300_1100nm/mask.lst"

ccf_mask = ispec.read_cross_correlation_mask(mask_file)

telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.0)

resolution = 80000

#--- Below it loads and sets up the template spectrum ---------
#templatefile = "/Users/edermartioli/Desktop/51Peg/testdata/1603681o.m.fits.gz"
templatefile = "/Users/edermartioli/Desktop/51Peg/testdata/1604052o.m.fits.gz"

if options.template :
    templatefile = options.template
    templatespectrum = loadtemplatespectrum(templatefile, resolution, telluric_linelist, ccf_mask, velocity_step, options.wavemask)
#---------------

output = []

for filepath in filelist :
Esempio n. 10
0
    def test_fit_lines_already_crossmatched_with_atomic_data_and_determine_ew(self):
        use_ares = False
        star_spectrum = ispec.read_spectrum(ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")
        #--- Radial Velocity determination with template -------------------------------
        # - Read synthetic template
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Arcturus.372_926nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Sun.372_926nm/template.txt.gz")
        template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/NARVAL.Sun.370_1048nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Synth.Sun.300_1100nm/template.txt.gz")

        models, ccf = ispec.cross_correlate_with_template(star_spectrum, template, \
                                lower_velocity_limit=-200, upper_velocity_limit=200, \
                                velocity_step=1.0, fourier=False)

        # Number of models represent the number of components
        components = len(models)
        # First component:
        rv = np.round(models[0].mu(), 2) # km/s
        rv_err = np.round(models[0].emu(), 2) # km/s
        #--- Radial Velocity correction ------------------------------------------------
        star_spectrum = ispec.correct_velocity(star_spectrum, rv)
        #--- Telluric velocity shift determination from spectrum --------------------------
        # - Telluric
        telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.0)

        models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \
                                lower_velocity_limit=-100, upper_velocity_limit=100, \
                                velocity_step=0.5, mask_depth=0.01, \
                                fourier = False,
                                only_one_peak = True)

        vel_telluric = np.round(models[0].mu(), 2) # km/s
        vel_telluric_err = np.round(models[0].emu(), 2) # km/s
        #--- Resolution degradation ----------------------------------------------------
        # NOTE: The line selection was built based on a solar spectrum with R ~ 47,000 and GES/VALD atomic linelist.
        from_resolution = 80000
        to_resolution = 47000
        star_spectrum = ispec.convolve_spectrum(star_spectrum, to_resolution, from_resolution)
        #--- Continuum fit -------------------------------------------------------------
        model = "Splines" # "Polynomy"
        degree = 2
        nknots = None # Automatic: 1 spline every 5 nm
        from_resolution = to_resolution

        # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum
        order='median+max'
        median_wave_range=0.05
        max_wave_range=1.0

        star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \
                                    nknots=nknots, degree=degree, \
                                    median_wave_range=median_wave_range, \
                                    max_wave_range=max_wave_range, \
                                    model=model, order=order, \
                                    automatic_strong_line_detection=True, \
                                    strong_line_probability=0.5, \
                                    use_errors_for_fitting=True)
        #--- Normalize -------------------------------------------------------------
        normalized_star_spectrum = ispec.normalize_spectrum(star_spectrum, star_continuum_model, consider_continuum_errors=False)
        # Use a fixed value because the spectrum is already normalized
        star_continuum_model = ispec.fit_continuum(star_spectrum, fixed_value=1.0, model="Fixed value")

        #--- Read lines with atomic data ------------------------------------------------
        line_regions_with_atomic_data = ispec.read_line_regions(ispec_dir + "/input/regions/47000_GES/moog_synth_good_for_params_all_extended.txt")
        #line_regions_with_atomic_data = ispec.read_line_regions(ispec_dir + "/input/regions/47000_GES/width_synth_good_for_params_all_extended.txt")
        #line_regions_with_atomic_data = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/moog_synth_good_for_params_all_extended.txt")
        #line_regions_with_atomic_data = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/width_synth_good_for_params_all_extended.txt")

        smoothed_star_spectrum = ispec.convolve_spectrum(star_spectrum, 2*to_resolution)
        line_regions_with_atomic_data = ispec.adjust_linemasks(smoothed_star_spectrum, line_regions_with_atomic_data, max_margin=0.5)

        #telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        #telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.01)
        #vel_telluric = 17.79 # km/s
        #telluric_linelist = None
        #vel_telluric = None

        #--- Fit the lines but do NOT cross-match with any atomic linelist since they already have that information
        linemasks = ispec.fit_lines(line_regions_with_atomic_data, normalized_star_spectrum, star_continuum_model, \
                                    atomic_linelist = None, \
                                    max_atomic_wave_diff = 0.005, \
                                    telluric_linelist = telluric_linelist, \
                                    check_derivatives = False, \
                                    vel_telluric = vel_telluric, discard_gaussian=False, \
                                    smoothed_spectrum=None, \
                                    discard_voigt=True, \
                                    free_mu=True, crossmatch_with_mu=False, closest_match=False)

        # Discard bad masks
        flux_peak = normalized_star_spectrum['flux'][linemasks['peak']]
        flux_base = normalized_star_spectrum['flux'][linemasks['base']]
        flux_top = normalized_star_spectrum['flux'][linemasks['top']]
        bad_mask = np.logical_or(linemasks['wave_peak'] <= linemasks['wave_base'], linemasks['wave_peak'] >= linemasks['wave_top'])
        bad_mask = np.logical_or(bad_mask, flux_peak >= flux_base)
        bad_mask = np.logical_or(bad_mask, flux_peak >= flux_top)
        linemasks = linemasks[~bad_mask]

        # Exclude lines with EW equal to zero
        rejected_by_zero_ew = (linemasks['ew'] == 0)
        linemasks = linemasks[~rejected_by_zero_ew]

        # Exclude lines that may be affected by tellurics
        rejected_by_telluric_line = (linemasks['telluric_wave_peak'] != 0)
        linemasks = linemasks[~rejected_by_telluric_line]

        if use_ares:
            # Replace the measured equivalent widths by the ones computed by ARES
            old_linemasks = linemasks.copy()
            ### Different rejection parameters (check ARES papers):
            ##   - http://adsabs.harvard.edu/abs/2007A%26A...469..783S
            ##   - http://adsabs.harvard.edu/abs/2015A%26A...577A..67S
            #linemasks = ispec.update_ew_with_ares(normalized_star_spectrum, linemasks, rejt="0.995", tmp_dir=None, verbose=0)
            #linemasks = ispec.update_ew_with_ares(normalized_star_spectrum, linemasks, rejt="3;5764,5766,6047,6052,6068,6076", tmp_dir=None, verbose=0)
            snr = 50
            linemasks = ispec.update_ew_with_ares(normalized_star_spectrum, linemasks, rejt="%s" % (snr), tmp_dir=None, verbose=0)

        self.assertEqual(len(linemasks), 281)
        self.assertAlmostEqual(linemasks['ew'][0], 68.62459244466727)
        self.assertAlmostEqual(linemasks['ew'][-3], 46.23135207295078)
        self.assertEqual(linemasks['element'][0], 'Fe 1')
        self.assertEqual(linemasks['element'][-3], 'Si 1')
        self.assertAlmostEqual(linemasks['loggf'][0], -1.028)
        self.assertAlmostEqual(linemasks['loggf'][-3], -1.062)
Esempio n. 11
0
    def test_fit_lines_determine_ew_and_crossmatch_with_atomic_data(self):
        use_ares = False
        star_spectrum = ispec.read_spectrum(ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")
        #--- Radial Velocity determination with template -------------------------------
        # - Read synthetic template
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Arcturus.372_926nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Sun.372_926nm/template.txt.gz")
        template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/NARVAL.Sun.370_1048nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Synth.Sun.300_1100nm/template.txt.gz")

        models, ccf = ispec.cross_correlate_with_template(star_spectrum, template, \
                                lower_velocity_limit=-200, upper_velocity_limit=200, \
                                velocity_step=1.0, fourier=False)

        # Number of models represent the number of components
        components = len(models)
        # First component:
        rv = np.round(models[0].mu(), 2) # km/s
        rv_err = np.round(models[0].emu(), 2) # km/s
        #--- Radial Velocity correction ------------------------------------------------
        star_spectrum = ispec.correct_velocity(star_spectrum, rv)
        #--- Telluric velocity shift determination from spectrum --------------------------
        # - Telluric
        telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.0)

        models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \
                                lower_velocity_limit=-100, upper_velocity_limit=100, \
                                velocity_step=0.5, mask_depth=0.01, \
                                fourier = False,
                                only_one_peak = True)

        vel_telluric = np.round(models[0].mu(), 2) # km/s
        vel_telluric_err = np.round(models[0].emu(), 2) # km/s
        #--- Resolution degradation ----------------------------------------------------
        # NOTE: The line selection was built based on a solar spectrum with R ~ 47,000 and GES/VALD atomic linelist.
        from_resolution = 80000
        to_resolution = 47000
        star_spectrum = ispec.convolve_spectrum(star_spectrum, to_resolution, from_resolution)
        #--- Continuum fit -------------------------------------------------------------
        model = "Splines" # "Polynomy"
        degree = 2
        nknots = None # Automatic: 1 spline every 5 nm
        from_resolution = 80000

        # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum
        order='median+max'
        median_wave_range=0.05
        max_wave_range=1.0

        star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \
                                    nknots=nknots, degree=degree, \
                                    median_wave_range=median_wave_range, \
                                    max_wave_range=max_wave_range, \
                                    model=model, order=order, \
                                    automatic_strong_line_detection=True, \
                                    strong_line_probability=0.5, \
                                    use_errors_for_fitting=True)
        #--- Normalize -------------------------------------------------------------
        normalized_star_spectrum = ispec.normalize_spectrum(star_spectrum, star_continuum_model, consider_continuum_errors=False)
        # Use a fixed value because the spectrum is already normalized
        star_continuum_model = ispec.fit_continuum(star_spectrum, fixed_value=1.0, model="Fixed value")
        #--- Fit lines -----------------------------------------------------------------
        #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/VALD.300_1100nm/atomic_lines.tsv"
        #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/VALD.1100_2400nm/atomic_lines.tsv"
        atomic_linelist_file = ispec_dir + "/input/linelists/transitions/GESv6_atom_hfs_iso.420_920nm/atomic_lines.tsv"
        #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/GESv6_atom_nohfs_noiso.420_920nm/atomic_lines.tsv"


        # Read
        atomic_linelist = ispec.read_atomic_linelist(atomic_linelist_file, wave_base=np.min(star_spectrum['waveobs']), wave_top=np.max(star_spectrum['waveobs']))
        atomic_linelist = atomic_linelist[atomic_linelist['theoretical_depth'] >= 0.01] # Select lines that have some minimal contribution in the sun

        #telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst"
        #telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.01)
        #vel_telluric = 17.79 # km/s
        #telluric_linelist = None
        #vel_telluric = None

        line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_GES/moog_synth_good_for_params_all.txt")
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_GES/width_synth_good_for_params_all.txt")
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/moog_synth_good_for_params_all.txt")
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/width_synth_good_for_params_all.txt")
        line_regions = ispec.adjust_linemasks(normalized_star_spectrum, line_regions, max_margin=0.5)

        linemasks = ispec.fit_lines(line_regions, normalized_star_spectrum, star_continuum_model, \
                                    atomic_linelist = atomic_linelist, \
                                    #max_atomic_wave_diff = 0.005, \
                                    max_atomic_wave_diff = 0.00, \
                                    telluric_linelist = telluric_linelist, \
                                    smoothed_spectrum = None, \
                                    check_derivatives = False, \
                                    vel_telluric = vel_telluric, discard_gaussian=False, \
                                    discard_voigt=True, \
                                    free_mu=True, crossmatch_with_mu=False, closest_match=False)
        # Discard lines that are not cross matched with the same original element stored in the note
        linemasks = linemasks[linemasks['element'] == line_regions['note']]

        # Exclude lines that have not been successfully cross matched with the atomic data
        # because we cannot calculate the chemical abundance (it will crash the corresponding routines)
        rejected_by_atomic_line_not_found = (linemasks['wave_nm'] == 0)
        linemasks = linemasks[~rejected_by_atomic_line_not_found]

        # Exclude lines with EW equal to zero
        rejected_by_zero_ew = (linemasks['ew'] == 0)
        linemasks = linemasks[~rejected_by_zero_ew]

        # Exclude lines that may be affected by tellurics
        rejected_by_telluric_line = (linemasks['telluric_wave_peak'] != 0)
        linemasks = linemasks[~rejected_by_telluric_line]

        if use_ares:
            # Replace the measured equivalent widths by the ones computed by ARES
            old_linemasks = linemasks.copy()
            ### Different rejection parameters (check ARES papers):
            ##   - http://adsabs.harvard.edu/abs/2007A%26A...469..783S
            ##   - http://adsabs.harvard.edu/abs/2015A%26A...577A..67S
            #linemasks = ispec.update_ew_with_ares(normalized_star_spectrum, linemasks, rejt="0.995", tmp_dir=None, verbose=0)
            #linemasks = ispec.update_ew_with_ares(normalized_star_spectrum, linemasks, rejt="3;5764,5766,6047,6052,6068,6076", tmp_dir=None, verbose=0)
            snr = 50
            linemasks = ispec.update_ew_with_ares(normalized_star_spectrum, linemasks, rejt="%s" % (snr), tmp_dir=None, verbose=0)

        self.assertEqual(len(linemasks), 281)
        self.assertAlmostEqual(linemasks['ew'][0], 68.48284589709996)
        self.assertAlmostEqual(linemasks['ew'][-3], 46.17583047097995)
        self.assertEqual(linemasks['element'][0], 'Fe 1')
        self.assertEqual(linemasks['element'][-3], 'Si 1')
        self.assertAlmostEqual(linemasks['loggf'][0], -1.028)
        self.assertAlmostEqual(linemasks['loggf'][-3], -1.062)