Exemplo n.º 1
0
    def test_calculate_theoretical_ew_and_depth(self):
        code = "spectrum"
        #--- Calculate theoretical equivalent widths and depths for a linelist ---------
        # Parameters
        teff = 5777.0
        logg = 4.44
        MH = 0.00
        alpha = 0.00
        microturbulence_vel = 1.0

        # 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)
        atomic_linelist = atomic_linelist[:
                                          100]  # Select only the first 100 lines (just to reduce execution time, don't do it in a real analysis)

        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)

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

        # Synthesis
        #output_wave, output_code, output_ew, output_depth = ispec.calculate_theoretical_ew_and_depth(atmosphere_layers, \
        new_atomic_linelist = ispec.calculate_theoretical_ew_and_depth(atmosphere_layers, \
                teff, logg, MH, alpha, \
                atomic_linelist[:10], isotopes, solar_abundances, microturbulence_vel=microturbulence_vel, \
                verbose=1, gui_queue=None, timeout=900)
        #ispec.write_atomic_linelist(new_atomic_linelist, linelist_filename="example_linelist.txt")

        np.testing.assert_almost_equal(
            new_atomic_linelist['theoretical_ew'][:10],
            np.array([
                2.500e-01, 1.180e+00, 3.000e-02, 2.000e-02, 6.492e+01,
                1.381e+01, 1.040e+00, 1.000e-02, 0.000e+00, 1.810e+00
            ]))
        np.testing.assert_almost_equal(
            new_atomic_linelist['theoretical_depth'][:10],
            np.array([0.01, 0.04, 0., 0., 0.81, 0.3, 0.02, 0., 0.959, 0.04]))
Exemplo n.º 2
0
    def _synthesize_spectrum(self, code):
        #--- Synthesizing spectrum -----------------------------------------------------
        # Parameters
        teff = 5771.0
        logg = 4.44
        MH = 0.00
        alpha = ispec.determine_abundance_enchancements(MH)
        microturbulence_vel = ispec.estimate_vmic(teff, logg, MH)  # 1.07
        macroturbulence = ispec.estimate_vmac(teff, logg, MH)  # 4.21
        vsini = 1.60  # Sun
        limb_darkening_coeff = 0.6
        resolution = 300000
        wave_step = 0.001

        # Wavelengths to synthesis
        #regions = ispec.read_segment_regions(ispec_dir + "/input/regions/fe_lines_segments.txt")
        regions = None
        wave_base = 515.0  # Magnesium triplet region
        wave_top = 525.0

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

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

        # Load chemical information and linelist
        atomic_linelist = ispec.read_atomic_linelist(atomic_linelist_file,
                                                     wave_base=wave_base,
                                                     wave_top=wave_top)
        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)

        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)

        ## Custom fixed abundances
        #fixed_abundances = ispec.create_free_abundances_structure(["C", "N", "O"], chemical_elements, solar_abundances)
        #fixed_abundances['Abund'] = [-3.49, -3.71, -3.54] # Abundances in SPECTRUM scale (i.e., x - 12.0 - 0.036) and in the same order ["C", "N", "O"]
        ## No fixed abundances
        fixed_abundances = None

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

        # Synthesis
        synth_spectrum = ispec.create_spectrum_structure(
            np.arange(wave_base, wave_top, wave_step))
        synth_spectrum['flux'] = ispec.generate_spectrum(synth_spectrum['waveobs'], \
                atmosphere_layers, teff, logg, MH, alpha, atomic_linelist, isotopes, solar_abundances, \
                fixed_abundances, microturbulence_vel = microturbulence_vel, \
                macroturbulence=macroturbulence, vsini=vsini, limb_darkening_coeff=limb_darkening_coeff, \
                R=resolution, regions=regions, verbose=1,
                code=code)
        return synth_spectrum
Exemplo n.º 3
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)
Exemplo n.º 4
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
Exemplo n.º 5
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)
Exemplo n.º 6
0
def synthesize_spectrum(theta, code="moog"):
    teff, logg, MH, vsini = theta
    resolution = 48000

    microturbulence_vel = ispec.estimate_vmic(teff, logg, MH)
    macroturbulence = ispec.estimate_vmac(teff, logg, MH)

    limb_darkening_coeff = 0.6
    regions = None
    wave_base = 609.0
    wave_top = 620.0

    model = ispec_dir + "/input/atmospheres/ATLAS9.Castelli/"

    atomic_linelist_file = ispec_dir + "/input/linelists/transitions/VALD.300_1100nm/atomic_lines.tsv"
    #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/GESv5_atom_hfs_iso.420_920nm/atomic_lines.tsv"

    isotope_file = ispec_dir + "/input/isotopes/SPECTRUM.lst"
    alpha = ispec.determine_abundance_enchancements(MH)

    atomic_linelist = ispec.read_atomic_linelist(atomic_linelist_file,
                                                 wave_base=wave_base,
                                                 wave_top=wave_top)
    atomic_linelist = atomic_linelist[
        atomic_linelist['theoretical_depth'] >= 0.01]

    isotopes = ispec.read_isotope_data(isotope_file)

    solar_abundances_file = ispec_dir + "/input/abundances/Asplund.2009/stdatom.dat"

    solar_abundances = ispec.read_solar_abundances(solar_abundances_file)
    fixed_abundances = None
    modeled_layers_pack = ispec.load_modeled_layers_pack(model)
    atmosphere_layers = ispec.interpolate_atmosphere_layers(
        modeled_layers_pack, {
            'teff': teff,
            'logg': logg,
            'MH': MH,
            'alpha': alpha
        },
        code=code)
    synth_spectrum = ispec.create_spectrum_structure(x)
    synth_spectrum['flux'] = ispec.generate_spectrum(
        synth_spectrum['waveobs'],
        atmosphere_layers,
        teff,
        logg,
        MH,
        alpha,
        atomic_linelist,
        isotopes,
        solar_abundances,
        fixed_abundances,
        microturbulence_vel=microturbulence_vel,
        macroturbulence=macroturbulence,
        vsini=vsini,
        limb_darkening_coeff=limb_darkening_coeff,
        R=resolution,
        regions=regions,
        verbose=0,
        code=code)

    return synth_spectrum
Exemplo n.º 7
0
    def _determine_abundances_from_ew(self, code):
        use_ares = False
        star_spectrum = ispec.read_spectrum(
            ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz")
        #--- Radial Velocity determination with template -------------------------------
        # - Read synthetic template
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Arcturus.372_926nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Sun.372_926nm/template.txt.gz")
        template = ispec.read_spectrum(
            ispec_dir +
            "/input/spectra/templates/NARVAL.Sun.370_1048nm/template.txt.gz")
        #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Synth.Sun.300_1100nm/template.txt.gz")

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            print(msg)

        # Prepare atmosphere model
        atmosphere_layers = ispec.interpolate_atmosphere_layers(
            modeled_layers_pack, {
                'teff': teff,
                'logg': logg,
                'MH': MH,
                'alpha': alpha
            },
            code=code)
        spec_abund, normal_abund, x_over_h, x_over_fe = ispec.determine_abundances(atmosphere_layers, \
                teff, logg, MH, alpha, linemasks, solar_abundances, microturbulence_vel = microturbulence_vel, \
                verbose=1, code=code)
        return linemasks, x_over_h
Exemplo n.º 8
0
def determine_abundances(spec_id, species, params):
    multiprocessing.current_process().daemon=False
    #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")
    #--- Model spectra ----------------------------------------------------------
    # Parameters
    initial_teff = params[1]
    initial_logg = params[5]
    initial_MH = params[4]
    initial_vmic = params[2]
    initial_vmac = params[0]
    initial_vsini = params[3]
    initial_limb_darkening_coeff = params[7]
    initial_R = params[6]
    initial_vrad = 0
    max_iterations = 6

    # 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 = ["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 = species[:-2]
    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
    
    linemask_id = species.replace(" ", "_") + "_linemasks.txt"

    # Line regions
    line_regions = ispec.read_line_regions(linemask_id)
    #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/limited_but_with_missing_elements_spectrum_synth_good_for_abundances_all_extended.txt")
    #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/limited_but_with_missing_elements_turobspectrum_synth_good_for_abundances_all_extended.txt")
    #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/limited_but_with_missing_elements_sme_synth_good_for_abundances_all_extended.txt")
    #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/limited_but_with_missing_elements_moog_synth_good_for_abundances_all_extended.txt")
    #line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/47000_VALD/limited_but_with_missing_elements_synthe_synth_good_for_abundances_all_extended.txt")
    # 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(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)

    abundance = str(abundances_found)
    results = abundance.split()
    del results[0:4]
    del results[1:3]
    del results[2:5]
    for i in range(0, len(results)):
        results[i] = float(results[i].replace(",",""))
    
    return results
Exemplo n.º 9
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)
Exemplo n.º 10
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)
Exemplo n.º 11
0
def abund_line_by_line(star_spectrum,
                       param,
                       star_continuum_model,
                       object_id,
                       code="grid"):
    ''' more or less same function as one above but i created wraper
    just to make things clear;
    The idea is that we use grid interpolation but only free param is metalicity
    and to fix everything else from previously derived model atmh;
    Drawback is it only returns metalicity, not abundance of elements
    because you cant interpolate abundances in grid
    But with line mask and fitting by segment, metalicity you get is bassicaly
    abundance for that spectral line; One elements creates multiple line
    so just take averages afterwards and you can use that for rough estimate'''

    normalized_star_spectrum = star_spectrum
    precomputed_grid_dir = ispec_dir + "/input/grid/SPECTRUM_MARCS.GES_GESv5_atom_hfs_iso.480_680nm_light/"

    #--- Model spectra ----------------------------------------------------------
    # Parameters
    initial_teff = param['teff']
    initial_logg = param['logg']
    initial_MH = param['MH']
    initial_alpha = param['alpha']
    initial_vmic = param['vmic']
    initial_vmac = param['vmac']
    initial_vsini = param['vsini']
    initial_limb_darkening_coeff = param['limb_darkening_coeff']
    initial_R = param['R']
    initial_vrad = 0
    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/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']))
    # Select lines that have some minimal contribution in the sun
    atomic_linelist = atomic_linelist[
        atomic_linelist['theoretical_depth'] >= 0.01]

    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 = ["MH"]
    #this is where we fix drawback; if we use synth we could use abundances
    free_abundances = None
    # 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 = ispec.read_line_regions(
        ispec_dir +
        "/input/regions/47000_GES/grid_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[0:5]
    line_regions = ispec.adjust_linemasks(normalized_star_spectrum,
                                          line_regions,
                                          max_margin=0.5)

    output_dirname = "example_abundance_line_by_line_%s" % (code, )
    ispec.mkdir_p(output_dirname)
    abund_array = np.array(())
    #create empty text file

    for i, line in enumerate(line_regions):
        # 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']
        print("=========ELEMENT NAME==============")
        print(element_name)

        linelist_free_loggf = None

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

        # 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

        #skip this line if flux is 0 somewhere in region or there is no data

        if len(normalized_star_spectrum[wfilter]) == 0 or np.any(
                normalized_star_spectrum[wfilter] == 0):
            continue

        #this sometimes fails for different reasons
        #if it does, lets ignore this line
        try:
            obs_spec, modeled_synth_spectrum, derived_params, errors,\
        abundances_found, loggf_found, status, stats_linemasks = \
        ispec.model_spectrum(normalized_star_spectrum[wfilter],\
        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=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, precomputed_grid_dir=precomputed_grid_dir)

        except Exception:
            continue

        #Write every element abundance to separate file
        #We use tihs ugly stuff here because if model_spectrum fails
        #it raises exception and i dont currently know how to handle it
        abundances_file = open(
            output_dirname + "/abd/%s_%s_abundances.txt" %
            (object_id, element_name), "a")
        abundances_file.write("%f\t%f\n" %
                              (derived_params['MH'], errors['MH']))
        abundances_file.close()

        ##--- Save results -------------------------------------------------------------
        dump_file = output_dirname + "/" + 'dumps' + '/' + common_filename + ".dump"
        logging.info("Saving results...")
        ispec.save_results(dump_file,
                           (derived_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 = output_dirname + "/" + common_filename + ".fits"
        ispec.write_spectrum(modeled_synth_spectrum, synth_filename)

    return abund_array