예제 #1
0
def normaliseContinuum(spec):
    """
    Based on example.py
    normalize_whole_spectrum_strategy1_ignoring_prefixed_strong_lines function
    """
    model = 'Splines'
    degree = 2
    nknots = None
    from_resolution = INSTRUMENT[args.instrument]['RESOLUTION']

    # continuum fit
    order = 'median+max'
    median_wave_range = 0.01
    max_wave_range = 1.0

    strong_lines = ispec.read_line_regions(strongLines)
    continuum_model = ispec.fit_continuum(spec, \
                                          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)
    # continuum normalisation
    spec_norm = ispec.normalize_spectrum(spec, \
                                         continuum_model, \
                                         consider_continuum_errors=False)
    return spec_norm
예제 #2
0
def normalize_whole_spectrum(spec_id, med_wave, max_wave):
    """
    Use the whole spectrum, strategy 'median+max'
    """
    star_spectrum = ispec.read_spectrum(spec_id)

    #--- Continuum fit -------------------------------------------------------------
    model = "Splines" # "Polynomy"
    degree = 2
    nknots = None # Automatic: 1 spline every 5 nm
    from_resolution = 47000

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

    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)

    #--- Continuum normalization ---------------------------------------------------
    logging.info("Continuum normalization...")
    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")
    ispec.write_spectrum(normalized_star_spectrum, spec_id)
예제 #3
0
    def test_normalize_spectrum_in_segments(self):
        """
        Fit continuum in each segment independently, strategy 'median+max'
        """
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")

        #--- Continuum fit -------------------------------------------------------------
        model = "Splines"  # "Polynomy"
        degree = 2
        nknots = 1
        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

        segments = ispec.read_segment_regions(
            ispec_dir + "/input/regions/fe_lines_segments.txt")
        star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \
                                independent_regions=segments, 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)

        #--- Continuum normalization ---------------------------------------------------
        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")
        np.testing.assert_equal(star_spectrum['waveobs'],
                                normalized_star_spectrum['waveobs'])
        self.assertAlmostEqual(star_spectrum['flux'][0], 0.67077)
        self.assertAlmostEqual(star_spectrum['flux'][-1], 2.2169)
        self.assertAlmostEqual(star_spectrum['err'][0], 0.0021259)
        self.assertAlmostEqual(star_spectrum['err'][-1], 0.0043878)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][0], 1.0)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][-1], 1.0)
        self.assertAlmostEqual(normalized_star_spectrum['err'][0], 0.0)
        self.assertAlmostEqual(normalized_star_spectrum['err'][-1], 0.0)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][11],
                               0.9928764307623508)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][58288],
                               0.960387654522309)
        self.assertAlmostEqual(normalized_star_spectrum['err'][11],
                               0.0028468129511384785)
        self.assertAlmostEqual(normalized_star_spectrum['err'][58288],
                               0.0019771951824093786)
        self.assertEqual(
            len(np.where(normalized_star_spectrum['flux'] != 1.)[0]), 33722)
        self.assertTrue(
            np.all(star_continuum_model(star_spectrum['waveobs']) == 1))
예제 #4
0
    def test_normalize_spectrum_using_continuum_regions(self):
        """
        Consider only continuum regions for the fit, strategy 'median+max'
        """
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")

        #--- 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

        continuum_regions = ispec.read_continuum_regions(
            ispec_dir + "/input/regions/fe_lines_continuum.txt")
        star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \
                                continuum_regions=continuum_regions, 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)

        #--- Continuum normalization ---------------------------------------------------
        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")

        np.testing.assert_equal(star_spectrum['waveobs'],
                                normalized_star_spectrum['waveobs'])
        self.assertAlmostEqual(star_spectrum['flux'][0], 0.67077)
        self.assertAlmostEqual(star_spectrum['flux'][-1], 2.2169)
        self.assertAlmostEqual(star_spectrum['err'][0], 0.0021259)
        self.assertAlmostEqual(star_spectrum['err'][-1], 0.0043878)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][0],
                               0.7990890725070141)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][-1],
                               0.9887281323707806)
        self.assertAlmostEqual(normalized_star_spectrum['err'][0],
                               0.0025325871151701197)
        self.assertAlmostEqual(normalized_star_spectrum['err'][-1],
                               0.001956940457042046)
        self.assertTrue(
            np.all(star_continuum_model(star_spectrum['waveobs']) == 1))
예제 #5
0
    def test_normalize_whole_spectrum_ignoring_prefixed_strong_lines(self):
        """
        Use the whole spectrum but ignoring some strong lines, strategy 'median+max'
        """
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")

        #--- 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

        strong_lines = ispec.read_line_regions(
            ispec_dir + "/input/regions/strong_lines/absorption_lines.txt")
        star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \
                                    ignore=strong_lines, \
                                    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)

        #--- Continuum normalization ---------------------------------------------------
        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")
        np.testing.assert_equal(star_spectrum['waveobs'],
                                normalized_star_spectrum['waveobs'])
        self.assertAlmostEqual(star_spectrum['flux'][0], 0.67077)
        self.assertAlmostEqual(star_spectrum['flux'][-1], 2.2169)
        self.assertAlmostEqual(star_spectrum['err'][0], 0.0021259)
        self.assertAlmostEqual(star_spectrum['err'][-1], 0.0043878)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][0],
                               0.8005567874185445)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][-1],
                               0.9874528805693361)
        self.assertAlmostEqual(normalized_star_spectrum['err'][0],
                               0.0025372388067043607)
        self.assertAlmostEqual(normalized_star_spectrum['err'][-1],
                               0.0019544164145257493)
        self.assertTrue(
            np.all(star_continuum_model(star_spectrum['waveobs']) == 1))
예제 #6
0
    def test_normalize_whole_spectrum(self):
        """
        Use the whole spectrum, strategy 'median+max'
        """
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")

        #--- 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)

        #--- Continuum normalization ---------------------------------------------------
        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")
        np.testing.assert_equal(star_spectrum['waveobs'],
                                normalized_star_spectrum['waveobs'])
        self.assertAlmostEqual(star_spectrum['flux'][0], 0.67077)
        self.assertAlmostEqual(star_spectrum['flux'][-1], 2.2169)
        self.assertAlmostEqual(star_spectrum['err'][0], 0.0021259)
        self.assertAlmostEqual(star_spectrum['err'][-1], 0.0043878)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][0],
                               0.8052457389161867)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][-1],
                               0.9895767577073404)
        self.assertAlmostEqual(normalized_star_spectrum['err'][0],
                               0.0025520997008839415)
        self.assertAlmostEqual(normalized_star_spectrum['err'][-1],
                               0.0019586200989978207)
        self.assertTrue(
            np.all(star_continuum_model(star_spectrum['waveobs']) == 1))
예제 #7
0
    def test_normalize_whole_spectrum_with_template(self):
        """
        Use a template to normalize the whole spectrum
        """
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")
        synth_spectrum = ispec.read_spectrum(
            ispec_dir +
            "/input/spectra/templates/Synth.Sun.300_1100nm/template.txt.gz")

        #--- Continuum fit -------------------------------------------------------------
        model = "Template"
        nknots = None  # Automatic: 1 spline every 5 nm (in this case, used to apply a gaussian filter)
        from_resolution = 80000
        median_wave_range = 5.0

        #strong_lines = ispec.read_line_regions(ispec_dir + "/input/regions/strong_lines/absorption_lines.txt")
        strong_lines = ispec.read_line_regions(
            ispec_dir + "/input/regions/relevant/relevant_line_masks.txt")
        #strong_lines = None
        star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \
                                    ignore=strong_lines, \
                                    nknots=nknots, \
                                    median_wave_range=median_wave_range, \
                                    model=model, \
                                    template=synth_spectrum)

        #--- Continuum normalization ---------------------------------------------------
        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")
        np.testing.assert_equal(star_spectrum['waveobs'],
                                normalized_star_spectrum['waveobs'])
        self.assertAlmostEqual(star_spectrum['flux'][0], 0.67077)
        self.assertAlmostEqual(star_spectrum['flux'][-1], 2.2169)
        self.assertAlmostEqual(star_spectrum['err'][0], 0.0021259)
        self.assertAlmostEqual(star_spectrum['err'][-1], 0.0043878)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][0],
                               0.7964201448878107)
        self.assertAlmostEqual(normalized_star_spectrum['flux'][-1],
                               0.997168332612696)
        self.assertAlmostEqual(normalized_star_spectrum['err'][0],
                               0.002524128368914824)
        self.assertAlmostEqual(normalized_star_spectrum['err'][-1],
                               0.0019736457259407225)
        self.assertTrue(
            np.all(star_continuum_model(star_spectrum['waveobs']) == 1))
예제 #8
0
def normalize_spectrum(star_spectrum,
                       res=80000,
                       model="Splines",
                       degree=2,
                       nknots=None):
    '''
    Fit continuum ignoring strong lines and using fe lines template, 
    strategy 'median+max'
    ####
    #### ASSUMING DEFAULT VALUES FOR:
    #### RESOLUTION, MODEL FOR CONTINUUM, DEGREE OF MODEL, NKNOTS!!!!
    #### TAKE CARE!!!!
    ####
    returns normalized star spectrum object and continumm model
    '''
    from_resolution = res  #define 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
    # read continuum regions from Fe lines and strong lines

    continuum_regions = ispec.read_continuum_regions(\
            ispec_dir + "/input/regions/fe_lines_continuum.txt")
    strong_lines = ispec.read_line_regions(\
            ispec_dir + "/input/regions/strong_lines/absorption_lines.txt")

    star_continuum_model = ispec.fit_continuum(star_spectrum,\
            from_resolution=from_resolution, ignore=strong_lines,\
            continuum_regions=continuum_regions, 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)

    #--- Continuum normalization -----------------------------------------------

    logging.info("Continuum normalization...")
    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
    #you need continuum model to be able to synt or interpolate params from grid
    star_continuum_model = ispec.fit_continuum(star_spectrum, \
            fixed_value=1.0, model="Fixed value")
    return normalized_star_spectrum, star_continuum_model
예제 #9
0
    def test_determine_astrophysical_parameters_using_synth_spectra(self):
        code = "spectrum"
        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)
        #--- 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")
        #--- Model spectra ----------------------------------------------------------
        # Parameters
        initial_teff = 5750.0
        initial_logg = 4.5
        initial_MH = 0.00
        initial_alpha = ispec.determine_abundance_enchancements(initial_MH)
        initial_vmic = ispec.estimate_vmic(initial_teff, initial_logg,
                                           initial_MH)
        initial_vmac = ispec.estimate_vmac(initial_teff, initial_logg,
                                           initial_MH)
        initial_vsini = 2.0
        initial_limb_darkening_coeff = 0.6
        initial_R = to_resolution
        initial_vrad = 0
        max_iterations = 6

        # 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"

        isotope_file = ispec_dir + "/input/isotopes/SPECTRUM.lst"

        # Load chemical information and linelist
        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

        isotopes = ispec.read_isotope_data(isotope_file)

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

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

        # Free parameters
        #free_params = ["teff", "logg", "MH", "vmic", "vmac", "vsini", "R", "vrad", "limb_darkening_coeff"]
        free_params = ["teff", "logg", "MH", "vmic", "R"]

        # Free individual element abundance
        free_abundances = None
        linelist_free_loggf = None

        # Line regions
        line_regions = ispec.read_line_regions(
            ispec_dir +
            "/input/regions/47000_GES/{}_synth_good_for_params_all.txt".format(
                code))
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_GES/{}_synth_good_for_params_all_extended.txt".format(code))
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/{}_synth_good_for_params_all.txt".format(code))
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/{}_synth_good_for_params_all_extended.txt".format(code))
        ## Select only some lines to speed up the execution (in a real analysis it is better not to do this)
        line_regions = line_regions[np.logical_or(
            line_regions['note'] == 'Ti 1', line_regions['note'] == 'Ti 2')]
        line_regions = ispec.adjust_linemasks(normalized_star_spectrum,
                                              line_regions,
                                              max_margin=0.5)
        # Read segments if we have them or...
        #segments = ispec.read_segment_regions(ispec_dir + "/input/regions/fe_lines_segments.txt")
        # ... or we can create the segments on the fly:
        segments = ispec.create_segments_around_lines(line_regions,
                                                      margin=0.25)

        ### Add also regions from the wings of strong lines:
        ## H beta
        #hbeta_lines = ispec.read_line_regions(ispec_dir + "input/regions/wings_Hbeta.txt")
        #hbeta_segments = ispec.read_segment_regions(ispec_dir + "input/regions/wings_Hbeta_segments.txt")
        #line_regions = np.hstack((line_regions, hbeta_lines))
        #segments = np.hstack((segments, hbeta_segments))
        ## H alpha
        #halpha_lines = ispec.read_line_regions(ispec_dir + "input/regions/wings_Halpha.txt")
        #halpha_segments = ispec.read_segment_regions(ispec_dir + "input/regions/wings_Halpha_segments.txt")
        #line_regions = np.hstack((line_regions, halpha_lines))
        #segments = np.hstack((segments, halpha_segments))
        ## Magnesium triplet
        #mgtriplet_lines = ispec.read_line_regions(ispec_dir + "input/regions/wings_MgTriplet.txt")
        #mgtriplet_segments = ispec.read_segment_regions(ispec_dir + "input/regions/wings_MgTriplet_segments.txt")
        #line_regions = np.hstack((line_regions, mgtriplet_lines))
        #segments = np.hstack((segments, mgtriplet_segments))

        obs_spec, modeled_synth_spectrum, params, errors, abundances_found, loggf_found, status, stats_linemasks = \
                ispec.model_spectrum(normalized_star_spectrum, star_continuum_model, \
                modeled_layers_pack, atomic_linelist, isotopes, solar_abundances, free_abundances, linelist_free_loggf, initial_teff, \
                initial_logg, initial_MH, initial_alpha, initial_vmic, initial_vmac, initial_vsini, \
                initial_limb_darkening_coeff, initial_R, initial_vrad, free_params, segments=segments, \
                linemasks=line_regions, \
                enhance_abundances=True, \
                use_errors = True, \
                vmic_from_empirical_relation = False, \
                vmac_from_empirical_relation = True, \
                max_iterations=max_iterations, \
                tmp_dir = None, \
                code=code)

        expected_params = {
            'teff': 5696.144535300913,
            'logg': 4.35386512625295,
            'MH': -0.117924251886487,
            'alpha': 0.047169700754594805,
            'vmic': 1.1383979614486783,
            'vmac': 4.04,
            'vsini': 2.0,
            'limb_darkening_coeff': 0.6,
            'R': 49936.32725781359
        }
        for k, v in list(expected_params.items()):
            self.assertAlmostEqual(params[k], v)
        expected_errors = {
            'teff': 66.38643184730074,
            'logg': 0.10101410057739481,
            'MH': 0.07728877921624414,
            'alpha': 0.0,
            'vmic': 0.10922339131594937,
            'vmac': 0.0,
            'vsini': 0.0,
            'limb_darkening_coeff': 0.0,
            'R': 3496.439438356713
        }
        for k, v in list(expected_errors.items()):
            self.assertAlmostEqual(errors[k], v)
        self.assertEqual(len(stats_linemasks), 30)
예제 #10
0
    def test_determine_loggf_line_by_line_using_synth_spectra(self):
        code = "spectrum"
        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)

        #--- 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")
        #--- Model spectra ----------------------------------------------------------
        # Parameters
        initial_teff = 5771.0
        initial_logg = 4.44
        initial_MH = 0.00
        initial_alpha = 0.00
        initial_vmic = ispec.estimate_vmic(initial_teff, initial_logg,
                                           initial_MH)
        initial_vmac = ispec.estimate_vmac(initial_teff, initial_logg,
                                           initial_MH)
        initial_vsini = 1.60  # Sun
        initial_limb_darkening_coeff = 0.6
        initial_R = to_resolution
        initial_vrad = 0
        max_iterations = 6

        # 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"

        isotope_file = ispec_dir + "/input/isotopes/SPECTRUM.lst"

        # Load chemical information and linelist
        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

        isotopes = ispec.read_isotope_data(isotope_file)

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

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

        # Free parameters
        #free_params = ["teff", "logg", "MH", "vmic", "vmac", "vsini", "R", "vrad", "limb_darkening_coeff"]
        #free_params = ["vrad"]
        free_params = []

        # Free individual element abundance (WARNING: it should be coherent with the selected line regions!)
        chemical_elements_file = ispec_dir + "/input/abundances/chemical_elements_symbols.dat"
        chemical_elements = ispec.read_chemical_elements(
            chemical_elements_file)

        # Line regions
        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 the lines to get abundances from
        line_regions_with_atomic_data = line_regions_with_atomic_data[:5]
        line_regions_with_atomic_data = ispec.adjust_linemasks(
            normalized_star_spectrum,
            line_regions_with_atomic_data,
            max_margin=0.5)

        output_dirname = "example_loggf_line_by_line_%s" % (code, )
        #ispec.mkdir_p(output_dirname)
        for i, line in enumerate(line_regions_with_atomic_data):
            # Directory and file names
            #element_name = "_".join(line['element'].split())
            element_name = "_".join(line['note'].split())
            common_filename = "example_" + code + "_individual_" + element_name + "_%.4f" % line[
                'wave_peak']

            # Free individual element abundance (WARNING: it should be coherent with the selected line regions!)
            free_abundances = None

            # Line by line
            individual_line_regions = line_regions_with_atomic_data[
                i:i + 1]  # Keep recarray structure
            linelist_free_loggf = line_regions_with_atomic_data[
                i:i + 1]  # Keep recarray structure

            # Filter the line that we want to determine the loggf from the global atomic linelist
            lfilter = atomic_linelist['element'] == linelist_free_loggf[
                'element'][0]
            for key in [
                    'wave_nm', 'lower_state_eV', 'loggf', 'stark', 'rad',
                    'waals'
            ]:
                lfilter = np.logical_and(
                    lfilter,
                    np.abs(atomic_linelist[key] - linelist_free_loggf[key][0])
                    < 1e-9)

            # Segment
            segments = ispec.create_segments_around_lines(
                individual_line_regions, margin=0.25)
            wfilter = ispec.create_wavelength_filter(
                normalized_star_spectrum,
                regions=segments)  # Only use the segment

            obs_spec, modeled_synth_spectrum, params, errors, abundances_found, loggf_found, status, stats_linemasks = \
                    ispec.model_spectrum(normalized_star_spectrum[wfilter], star_continuum_model, \
                    modeled_layers_pack, atomic_linelist[~lfilter], isotopes, solar_abundances, free_abundances, linelist_free_loggf, initial_teff, \
                    initial_logg, initial_MH, initial_alpha, initial_vmic, initial_vmac, initial_vsini, \
                    initial_limb_darkening_coeff, initial_R, initial_vrad, free_params, segments=segments, \
                    linemasks=individual_line_regions, \
                    enhance_abundances=True, \
                    use_errors = True, \
                    vmic_from_empirical_relation = False, \
                    vmac_from_empirical_relation = False, \
                    max_iterations=max_iterations, \
                    tmp_dir = None, \
                    code=code)

            self.assertAlmostEqual(loggf_found['loggf'][0],
                                   -1.0743873027191777)
            self.assertAlmostEqual(loggf_found['eloggf'][0],
                                   0.11414696354921147)
            self.assertEqual(len(loggf_found['loggf']), 1)
            self.assertEqual(individual_line_regions['lower_state_eV'][0],
                             loggf_found['linelist']['lower_state_eV'][0])
            break
예제 #11
0
    def test_determine_abundances_using_synth_spectra(self):
        code = "spectrum"
        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)

        #--- 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")
        #--- Model spectra ----------------------------------------------------------
        # Parameters
        initial_teff = 5771.0
        initial_logg = 4.44
        initial_MH = 0.00
        initial_alpha = 0.00
        initial_vmic = ispec.estimate_vmic(initial_teff, initial_logg,
                                           initial_MH)
        initial_vmac = ispec.estimate_vmac(initial_teff, initial_logg,
                                           initial_MH)
        initial_vsini = 1.60  # Sun
        initial_limb_darkening_coeff = 0.6
        initial_R = to_resolution
        initial_vrad = 0
        max_iterations = 6

        # 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"

        isotope_file = ispec_dir + "/input/isotopes/SPECTRUM.lst"

        # Load chemical information and linelist
        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

        isotopes = ispec.read_isotope_data(isotope_file)

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

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

        # Free parameters
        #free_params = ["teff", "logg", "MH", "vmic", "vmac", "vsini", "R", "vrad", "limb_darkening_coeff"]
        free_params = ["vrad"]
        #free_params = []

        # Free individual element abundance (WARNING: it should be coherent with the selected line regions!)
        chemical_elements_file = ispec_dir + "/input/abundances/chemical_elements_symbols.dat"
        chemical_elements = ispec.read_chemical_elements(
            chemical_elements_file)

        element_name = "Ca"
        free_abundances = ispec.create_free_abundances_structure(
            [element_name], chemical_elements, solar_abundances)
        free_abundances['Abund'] += initial_MH  # Scale to metallicity

        linelist_free_loggf = None

        # Line regions
        line_regions = ispec.read_line_regions(
            ispec_dir +
            "/input/regions/47000_GES/{}_synth_good_for_params_all.txt".format(
                code))
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_GES/{}_synth_good_for_params_all_extended.txt".format(code))
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/{}_synth_good_for_params_all.txt".format(code))
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/{}_synth_good_for_params_all_extended.txt".format(code))
        # Select only the lines to get abundances from
        line_regions = line_regions[np.logical_or(
            line_regions['note'] == element_name + ' 1',
            line_regions['note'] == element_name + ' 2')]
        line_regions = ispec.adjust_linemasks(normalized_star_spectrum,
                                              line_regions,
                                              max_margin=0.5)

        # Read segments if we have them or...
        #segments = ispec.read_segment_regions(ispec_dir + "/input/regions/fe_lines_segments.txt")
        # ... or we can create the segments on the fly:
        segments = ispec.create_segments_around_lines(line_regions,
                                                      margin=0.25)

        obs_spec, modeled_synth_spectrum, params, errors, abundances_found, loggf_found, status, stats_linemasks = \
                ispec.model_spectrum(normalized_star_spectrum, star_continuum_model, \
                modeled_layers_pack, atomic_linelist, isotopes, solar_abundances, free_abundances, linelist_free_loggf, initial_teff, \
                initial_logg, initial_MH, initial_alpha, initial_vmic, initial_vmac, initial_vsini, \
                initial_limb_darkening_coeff, initial_R, initial_vrad, free_params, segments=segments, \
                linemasks=line_regions, \
                enhance_abundances=True, \
                use_errors = True, \
                vmic_from_empirical_relation = False, \
                vmac_from_empirical_relation = False, \
                max_iterations=max_iterations, \
                tmp_dir = None, \
                code=code)

        expected_params = {
            'teff': 5771.0,
            'logg': 4.44,
            'MH': 0.0,
            'alpha': 0.0,
            'vmic': 1.07,
            'vmac': 4.19,
            'vsini': 1.6,
            'limb_darkening_coeff': 0.6,
            'R': 47000.0,
            'vrad0000': -0.009293697395991595,
            'vrad0001': -0.06018526081728252,
            'vrad0002': -0.015666491320596353,
            'vrad0003': -0.055193632795656256,
            'vrad0004': -0.1567689404172516,
            'vrad0005': -0.22508061064189286,
            'vrad0006': -0.20359311863771612,
            'vrad0007': -0.16078450322612126
        }
        for k, v in list(expected_params.items()):
            self.assertAlmostEqual(params[k], v)
        expected_errors = {
            'teff': 0.0,
            'logg': 0.0,
            'MH': 0.0,
            'alpha': 0.0,
            'vmic': 0.0,
            'vmac': 0.0,
            'vsini': 0.0,
            'limb_darkening_coeff': 0.0,
            'R': 0.0,
            'vrad0000': 2.2914331925224816,
            'vrad0001': 0.6770488621090028,
            'vrad0002': 0.2767472596825708,
            'vrad0003': 1.0820599330375968,
            'vrad0004': 0.47734411482243877,
            'vrad0005': 0.2585031799872256,
            'vrad0006': 0.46187116575854853,
            'vrad0007': 0.23921192411257394
        }
        for k, v in list(expected_errors.items()):
            self.assertAlmostEqual(errors[k], v)
        self.assertEqual(len(stats_linemasks), 8)
        self.assertEqual(abundances_found['element'][0], 'Ca')
        self.assertAlmostEqual(abundances_found['[X/H]'][0],
                               -0.0020078068382556324)
        self.assertAlmostEqual(abundances_found['[X/Fe]'][0],
                               -0.0020078068382556324)
        self.assertAlmostEqual(abundances_found['e[X/H]'][0],
                               0.027149612080779945)
        self.assertAlmostEqual(abundances_found['e[X/Fe]'][0],
                               0.027149612080779945)
예제 #12
0
    def test_determine_astrophysical_parameters_using_grid(self):
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")
        #star_spectrum = ispec.read_spectrum(ispec_dir + "/input/spectra/examples/NARVAL_Arcturus.txt.gz")
        #star_spectrum = ispec.read_spectrum(ispec_dir + "/input/spectra/examples/NARVAL_muCas.txt.gz")
        #star_spectrum = ispec.read_spectrum(ispec_dir + "/input/spectra/examples/NARVAL_muLeo.txt.gz")
        #star_spectrum = ispec.read_spectrum(ispec_dir + "/input/spectra/examples/HARPS.GBOG_Procyon.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)
        #--- 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")
        #--- Model spectra ----------------------------------------------------------
        # Parameters
        initial_teff = 5750.0
        initial_logg = 4.5
        initial_MH = 0.00
        initial_alpha = 0.00
        initial_vmic = ispec.estimate_vmic(initial_teff, initial_logg,
                                           initial_MH)
        initial_vmac = ispec.estimate_vmac(initial_teff, initial_logg,
                                           initial_MH)
        initial_vsini = 2.0
        initial_limb_darkening_coeff = 0.6
        initial_R = to_resolution
        initial_vrad = 0
        max_iterations = 20

        code = "grid"
        precomputed_grid_dir = ispec_dir + "/input/grid/SPECTRUM_MARCS.GES_GESv6_atom_hfs_iso.480_680nm_light/"

        atomic_linelist = None
        isotopes = None
        modeled_layers_pack = None
        solar_abundances = None
        free_abundances = None
        linelist_free_loggf = None

        # Free parameters (vmic cannot be used as a free parameter when using a spectral grid)
        #free_params = ["teff", "logg", "MH", "alpha", "vmic", "vmac", "vsini", "R", "vrad", "limb_darkening_coeff"]
        free_params = ["teff", "logg", "MH", "alpha", "vmic", "R"]

        # Line regions
        line_regions = ispec.read_line_regions(
            ispec_dir +
            "/input/regions/47000_GES/{}_synth_good_for_params_all.txt".format(
                code))
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_GES/{}_synth_good_for_params_all_extended.txt".format(code))
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/{}_synth_good_for_params_all.txt".format(code))
        #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/{}_synth_good_for_params_all_extended.txt".format(code))
        ## Select only some lines to speed up the execution (in a real analysis it is better not to do this)
        #line_regions = line_regions[np.logical_or(line_regions['note'] == 'Ti 1', line_regions['note'] == 'Ti 2')]
        #line_regions = ispec.adjust_linemasks(normalized_star_spectrum, line_regions, max_margin=0.5)
        # Read segments if we have them or...
        #segments = ispec.read_segment_regions(ispec_dir + "/input/regions/fe_lines_segments.txt")
        # ... or we can create the segments on the fly:
        segments = ispec.create_segments_around_lines(line_regions,
                                                      margin=0.25)

        ## Add also regions from the wings of strong lines:
        # H beta
        hbeta_lines = ispec.read_line_regions(ispec_dir +
                                              "input/regions/wings_Hbeta.txt")
        hbeta_segments = ispec.read_segment_regions(
            ispec_dir + "input/regions/wings_Hbeta_segments.txt")
        line_regions = np.hstack((line_regions, hbeta_lines))
        segments = np.hstack((segments, hbeta_segments))
        # H alpha
        halpha_lines = ispec.read_line_regions(
            ispec_dir + "input/regions/wings_Halpha.txt")
        halpha_segments = ispec.read_segment_regions(
            ispec_dir + "input/regions/wings_Halpha_segments.txt")
        line_regions = np.hstack((line_regions, halpha_lines))
        segments = np.hstack((segments, halpha_segments))
        # Magnesium triplet
        mgtriplet_lines = ispec.read_line_regions(
            ispec_dir + "input/regions/wings_MgTriplet.txt")
        mgtriplet_segments = ispec.read_segment_regions(
            ispec_dir + "input/regions/wings_MgTriplet_segments.txt")
        line_regions = np.hstack((line_regions, mgtriplet_lines))
        segments = np.hstack((segments, mgtriplet_segments))

        obs_spec, modeled_synth_spectrum, params, errors, abundances_found, loggf_found, status, stats_linemasks = \
                ispec.model_spectrum(normalized_star_spectrum, star_continuum_model, \
                modeled_layers_pack, atomic_linelist, isotopes, solar_abundances, free_abundances, linelist_free_loggf, initial_teff, \
                initial_logg, initial_MH, initial_alpha, initial_vmic, initial_vmac, initial_vsini, \
                initial_limb_darkening_coeff, initial_R, initial_vrad, free_params, segments=segments, \
                linemasks=line_regions, \
                enhance_abundances=False, \
                use_errors = True, \
                vmic_from_empirical_relation = False, \
                vmac_from_empirical_relation = True, \
                max_iterations=max_iterations, \
                tmp_dir = None, \
                code=code, precomputed_grid_dir=precomputed_grid_dir)

        expected_params = {
            'teff': 5848.516352941799,
            'logg': 4.47140586507073,
            'MH': 0.021745200217247945,
            'alpha': 0.0,
            'vmic': 0.5617098008018283,
            'vmac': 4.5,
            'vsini': 2.0,
            'limb_darkening_coeff': 0.6,
            'R': 78395.52968455742
        }
        for k, v in list(expected_params.items()):
            self.assertAlmostEqual(params[k], v)
        expected_errors = {
            'teff': 16.061649602869444,
            'logg': 0.028408456932473077,
            'MH': 0.007324730574204324,
            'alpha': 0.007733907152934892,
            'vmic': 0.043996803165640905,
            'vmac': 0.0,
            'vsini': 0.0,
            'limb_darkening_coeff': 0.0,
            'R': 3898.724894322937
        }
        for k, v in list(expected_errors.items()):
            self.assertAlmostEqual(errors[k], v)
        self.assertEqual(len(stats_linemasks), 337)
예제 #13
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
예제 #14
0
def determine_parameters(spec_id, lines_id):
    #code = "synthe"
    code = "spectrum"
    star_spectrum = ispec.read_spectrum(spec_id)
    # 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")
    normalized_star_spectrum = ispec.normalize_spectrum(star_spectrum, star_continuum_model, consider_continuum_errors=False)
    #--- Model spectra ----------------------------------------------------------
    params = []
    with open('config.txt', 'r') as cfile:
        for line in cfile:
            params.append(float(str(line)[:-1]))
    # Parameters
    initial_teff = params[0]
    initial_logg = params[1]
    initial_MH = params[2]
    initial_vmic = params[3]
    initial_vmac = params[4]
    initial_vsini = params[5]
    initial_limb_darkening_coeff = params[6]
    initial_R = params[7]
    initial_vrad = params[8]
    max_iterations = params[9]

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

    #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/GESv5_atom_hfs_iso.420_920nm/atomic_lines.tsv"
    #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/GESv5_atom_nohfs_noiso.420_920nm/atomic_lines.tsv"

    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/Grevesse.1998/stdatom.dat"
    #solar_abundances_file = ispec_dir + "/input/abundances/Anders.1989/stdatom.dat"

    isotope_file = ispec_dir + "/input/isotopes/SPECTRUM.lst"

    # Load chemical information and linelist
    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

    isotopes = ispec.read_isotope_data(isotope_file)


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

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

    # Free parameters
    #free_params = ["teff", "logg", "MH", "vmic", "vmac", "vsini", "R", "vrad", "limb_darkening_coeff"]
    free_params = ["teff", "logg", "MH", "vmic", "vmac", "vsini"]

    # Free individual element abundance
    free_abundances = None
    linelist_free_loggf = None

    # Line regions
    line_regions = ispec.read_line_regions(lines_id)
    #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/spectrum_synth_turbospectrum_synth_sme_synth_moog_synth_synthe_synth_good_for_params_all_extended.txt")
    # Select only some lines to speed up the execution (in a real analysis it is better not to do this)
    #line_regions = line_regions[np.logical_or(line_regions['note'] == 'Ti 1', line_regions['note'] == 'Ti 2')]
    #line_regions = ispec.adjust_linemasks(normalized_star_spectrum, line_regions, max_margin=0.5)
    # Read segments if we have them or...
    #segments = ispec.read_segment_regions(ispec_dir + "/input/regions/fe_lines_segments.txt")
    # ... or we can create the segments on the fly:
    segments = ispec.create_segments_around_lines(line_regions, margin=0.25)

    obs_spec, modeled_synth_spectrum, params, errors, abundances_found, loggf_found, status, stats_linemasks = \
            ispec.model_spectrum(normalized_star_spectrum, star_continuum_model, \
            modeled_layers_pack, atomic_linelist, isotopes, solar_abundances, free_abundances, linelist_free_loggf, initial_teff, \
            initial_logg, initial_MH, initial_vmic, initial_vmac, initial_vsini, \
            initial_limb_darkening_coeff, initial_R, initial_vrad, free_params, segments=segments, \
            linemasks=line_regions, \
            enhance_abundances=True, \
            use_errors = True, \
            vmic_from_empirical_relation = False, \
            vmac_from_empirical_relation = False, \
            max_iterations=max_iterations, \
            tmp_dir = None, \
            code=code)
    ##--- Save results -------------------------------------------------------------
    logging.info("Saving results...")
    #dump_file = "example_results_synth_%s.dump" % (code)
    #ispec.save_results(dump_file, (params, errors, abundances_found, loggf_found, status, stats_linemasks))
    # If we need to restore the results from another script:
    #params, errors, abundances_found, loggf_found, status, stats_linemasks = ispec.restore_results(dump_file)

    #logging.info("Saving synthetic spectrum...")
    #synth_filename = "example_modeled_synth_%s.fits" % (code)
    #ispec.write_spectrum(modeled_synth_spectrum, synth_filename)
    
    parameters = "\n" + str(params)
    parameter_errors = "\n" + str(errors)
    file_id = spec_id + "_info.txt"
    
    with open(file_id, "w") as savefile:
        savefile.write(parameters)
        savefile.write(parameter_errors)
예제 #15
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)
예제 #16
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)
예제 #17
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)