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
def test_create_segments_around_linemasks(self): #---Create segments around linemasks ------------------------------------------- line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/fe_lines.txt") segments = ispec.create_segments_around_lines(line_regions, margin=0.25) self.assertEqual(len(segments), 132) self.assertAlmostEqual(segments['wave_base'][0], 480.01937) self.assertAlmostEqual(segments['wave_top'][0], 481.08295)
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))
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))
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
def test_adjust_line_masks(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Adjust line masks --------------------------------------------------------- resolution = 80000 smoothed_star_spectrum = ispec.convolve_spectrum( star_spectrum, resolution) line_regions = ispec.read_line_regions(ispec_dir + "/input/regions/fe_lines.txt") linemasks = ispec.adjust_linemasks(smoothed_star_spectrum, line_regions, max_margin=0.5) self.assertAlmostEqual(line_regions['wave_base'][0], 480.26937) self.assertAlmostEqual(line_regions['wave_top'][0], 480.28771) self.assertEqual(len(linemasks), 315) np.testing.assert_equal(line_regions['wave_peak'], linemasks['wave_peak']) self.assertAlmostEqual(linemasks['wave_base'][0], 480.269365109) self.assertAlmostEqual(linemasks['wave_top'][0], 480.319964199)
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)
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)
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
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)
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)
def param_using_grid(normalized_star_spectrum, star_continuum_model, object_id,\ resolution=80000, p0 = [5750.0, 4.5, 0, 0, 2, 0.6, 0], max_iter = 10): ''' Derive spectroscopic parameters using grid model p0 are initial values list: teff, logg, MH, alpha, vsini, limb_darkening coef, vrad Returns params, errors and ispec_pectrum object with spectra form best fit ''' #--- Model spectra -------------------------------------------------------- # Parameters initiall values initial_teff = p0[0] initial_logg = p0[1] initial_MH = p0[2] initial_alpha = p0[3] initial_vmic = ispec.estimate_vmic(initial_teff, initial_logg, initial_MH) initial_vmac = ispec.estimate_vmac(initial_teff, initial_logg, initial_MH) initial_vsini = p0[4] initial_limb_darkening_coeff = p0[5] initial_R = resolution initial_vrad = p0[6] max_iterations = max_iter #load grid code = "grid" precomputed_grid_dir = ispec_dir + "/input/grid/SPECTRUM_MARCS.GES_GESv5_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", "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)) # run model spectra from grid! 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) ##--- Save results --------------------------------------------------------- #logging.info("Saving results...") dump_file = "example_results_synth_grid_%s.dump" % (object_id) #logging.info("Saving results...") 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_grid_%s.fits" % (object_id) ispec.write_spectrum(modeled_synth_spectrum, synth_filename) return params, errors, modeled_synth_spectrum
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
def test_find_linemasks(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Radial Velocity determination with template ------------------------------- # - Read synthetic template #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Arcturus.372_926nm/template.txt.gz") #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Atlas.Sun.372_926nm/template.txt.gz") template = ispec.read_spectrum( ispec_dir + "/input/spectra/templates/NARVAL.Sun.370_1048nm/template.txt.gz") #template = ispec.read_spectrum(ispec_dir + "/input/spectra/templates/Synth.Sun.300_1100nm/template.txt.gz") models, ccf = ispec.cross_correlate_with_template(star_spectrum, template, \ lower_velocity_limit=-200, upper_velocity_limit=200, \ velocity_step=1.0, fourier=False) # Number of models represent the number of components components = len(models) # First component: rv = np.round(models[0].mu(), 2) # km/s rv_err = np.round(models[0].emu(), 2) # km/s #--- Radial Velocity correction ------------------------------------------------ star_spectrum = ispec.correct_velocity(star_spectrum, rv) #--- Telluric velocity shift determination from spectrum -------------------------- # - Telluric telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst" telluric_linelist = ispec.read_telluric_linelist( telluric_linelist_file, minimum_depth=0.0) models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \ lower_velocity_limit=-100, upper_velocity_limit=100, \ velocity_step=0.5, mask_depth=0.01, \ fourier = False, only_one_peak = True) vel_telluric = np.round(models[0].mu(), 2) # km/s vel_telluric_err = np.round(models[0].emu(), 2) # km/s #--- Continuum fit ------------------------------------------------------------- model = "Splines" # "Polynomy" degree = 2 nknots = None # Automatic: 1 spline every 5 nm from_resolution = 80000 # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum order = 'median+max' median_wave_range = 0.05 max_wave_range = 1.0 star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \ nknots=nknots, degree=degree, \ median_wave_range=median_wave_range, \ max_wave_range=max_wave_range, \ model=model, order=order, \ automatic_strong_line_detection=True, \ strong_line_probability=0.5, \ use_errors_for_fitting=True) #--- Find linemasks ------------------------------------------------------------ #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/VALD.300_1100nm/atomic_lines.tsv" #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/VALD.1100_2400nm/atomic_lines.tsv" atomic_linelist_file = ispec_dir + "/input/linelists/transitions/GESv6_atom_hfs_iso.420_920nm/atomic_lines.tsv" #atomic_linelist_file = ispec_dir + "/input/linelists/transitions/GESv6_atom_nohfs_noiso.420_920nm/atomic_lines.tsv" telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst" # Read atomic_linelist = ispec.read_atomic_linelist( atomic_linelist_file, wave_base=np.min(star_spectrum['waveobs']), wave_top=np.max(star_spectrum['waveobs'])) atomic_linelist = atomic_linelist[ atomic_linelist['theoretical_depth'] >= 0.01] # Select lines that have some minimal contribution in the sun #telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.01) #vel_telluric = 17.79 # km/s #telluric_linelist = None #vel_telluric = None resolution = 80000 smoothed_star_spectrum = ispec.convolve_spectrum( star_spectrum, resolution) min_depth = 0.05 max_depth = 1.00 star_linemasks = ispec.find_linemasks(star_spectrum, star_continuum_model, \ atomic_linelist=atomic_linelist, \ max_atomic_wave_diff = 0.005, \ telluric_linelist=telluric_linelist, \ vel_telluric=vel_telluric, \ minimum_depth=min_depth, maximum_depth=max_depth, \ smoothed_spectrum=smoothed_star_spectrum, \ check_derivatives=False, \ discard_gaussian=False, discard_voigt=True, \ closest_match=False) # Exclude lines that have not been successfully cross matched with the atomic data # because we cannot calculate the chemical abundance (it will crash the corresponding routines) rejected_by_atomic_line_not_found = (star_linemasks['wave_nm'] == 0) star_linemasks = star_linemasks[~rejected_by_atomic_line_not_found] # Exclude lines with EW equal to zero rejected_by_zero_ew = (star_linemasks['ew'] == 0) star_linemasks = star_linemasks[~rejected_by_zero_ew] # Select only iron lines iron = star_linemasks['element'] == "Fe 1" iron = np.logical_or(iron, star_linemasks['element'] == "Fe 2") iron_star_linemasks = star_linemasks[iron] self.assertEqual(len(star_linemasks), 1732) self.assertEqual(len(iron_star_linemasks), 883) self.assertAlmostEqual(iron_star_linemasks['ew'][0], 15.82970157775808) self.assertAlmostEqual(iron_star_linemasks['ew'][-1], 15.545342323635188) self.assertAlmostEqual(iron_star_linemasks['ew_err'][0], 1.1187509030236669) self.assertAlmostEqual(iron_star_linemasks['ew_err'][-1], 1.3221015426240295) tmp_filename = tempfile.mktemp() # Write regions with masks limits, cross-matched atomic data and fit data ispec.write_line_regions(star_linemasks, tmp_filename, extended=True) recover_star_linemasks = ispec.read_line_regions(tmp_filename) os.remove(tmp_filename) # Write regions with masks limits and cross-matched atomic data (fit data fields are zeroed) zeroed_star_linemasks = ispec.reset_fitted_data_fields(star_linemasks) np.testing.assert_almost_equal(star_linemasks['wave_nm'], recover_star_linemasks['wave_nm']) np.testing.assert_almost_equal(star_linemasks['ew'], recover_star_linemasks['ew'], decimal=1) np.testing.assert_almost_equal(star_linemasks['wave_base'], recover_star_linemasks['wave_base'], decimal=4) np.testing.assert_almost_equal(star_linemasks['wave_top'], recover_star_linemasks['wave_top'], decimal=4) np.testing.assert_almost_equal(star_linemasks['wave_peak'], recover_star_linemasks['wave_peak'], decimal=4) self.assertTrue(np.all(zeroed_star_linemasks['ew'] == 0))
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)
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
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)
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)
except Exception as e: print "Continuum file", filenames[ 'continuum'], "has an incompatible format!" sys.exit(2) ## Validations if np.any((continuum['wave_top'] - continuum['wave_base']) < 0): raise Exception( "Continuum: wave_top cannot be smaller than wave_base") else: continuum = np.zeros((0, ), dtype=[('wave_base', '<f8'), ('wave_top', '<f8')]) if filenames['lines'] != None: try: lines = ispec.read_line_regions(filenames['lines']) except Exception as e: print "Lines file", filenames[ 'lines'], "has an incompatible format!" sys.exit(2) ## Validations if np.any((lines['wave_top'] - lines['wave_base']) < 0): raise Exception("Lines: wave_top cannot be smaller than wave_base") if np.any((lines['wave_top'] - lines['wave_peak']) < 0): raise Exception("Lines: wave_top cannot be smaller than wave_peak") if np.any((lines['wave_peak'] - lines['wave_base']) < 0): raise Exception( "Lines: wave_peak cannot be smaller than wave_base")
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