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 test_determine_radial_velocity_with_mask(self): mu_cas_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_muCas.txt.gz") #--- Radial Velocity determination with linelist mask -------------------------- # - Read atomic data mask_file = ispec_dir + "input/linelists/CCF/Narval.Sun.370_1048nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/Atlas.Arcturus.372_926nm/mask.lst"" #mask_file = ispec_dir + "input/linelists/CCF/Atlas.Sun.372_926nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.A0.350_1095nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.F0.360_698nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.G2.375_679nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.K0.378_679nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.K5.378_680nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.M5.400_687nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/Synthetic.Sun.350_1100nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/VALD.Sun.300_1100nm/mask.lst" ccf_mask = ispec.read_cross_correlation_mask(mask_file) models, ccf = ispec.cross_correlate_with_mask(mu_cas_spectrum, ccf_mask, \ lower_velocity_limit=-200, upper_velocity_limit=200, \ velocity_step=1.0, mask_depth=0.01, \ fourier=False) # Number of models represent the number of components components = len(models) # First component: rv = models[0].mu() # km/s rv_err = models[0].emu() # km/s self.assertEqual(components, 1) self.assertAlmostEqual(rv, -96.43) self.assertAlmostEqual(rv_err, 0.03736164048308909)
def read_write_spectrum(spec_id): #--- Reading spectra ----------------------------------------------------------- logging.info("Reading spectra") star_spectrum = ispec.read_spectrum(spec_id + "_datafile.txt") ##--- Save spectrum ------------------------------------------------------------ logging.info("Saving spectrum...") ispec.write_spectrum(star_spectrum, spec_id + "_processed.fits")
def clean_telluric_regions(spec_id, clean_percent): star_spectrum = ispec.read_spectrum(spec_id) #--- Telluric velocity shift determination from spectrum -------------------------- logging.info("Telluric velocity shift determination...") # - Telluric telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst" telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.0) models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \ lower_velocity_limit=-100, upper_velocity_limit=100, \ velocity_step=0.5, mask_depth=0.01, \ fourier = False, only_one_peak = True) bv = np.round(models[0].mu(), 2) # km/s bv_err = np.round(models[0].emu(), 2) # km/s #--- Clean regions that may be affected by tellurics --------------------------- logging.info("Cleaning tellurics...") telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst" telluric_linelist = ispec.read_telluric_linelist(telluric_linelist_file, minimum_depth=0.0) # - Filter regions that may be affected by telluric lines #bv = 0.0 min_vel = -30.0 max_vel = +30.0 # Only the 25% of the deepest ones: dfilter = telluric_linelist['depth'] > np.percentile(telluric_linelist['depth'], clean_percent) tfilter = ispec.create_filter_for_regions_affected_by_tellurics(star_spectrum['waveobs'], \ telluric_linelist[dfilter], min_velocity=-bv+min_vel, \ max_velocity=-bv+max_vel) clean_star_spectrum = star_spectrum[~tfilter] ispec.write_spectrum(clean_star_spectrum, spec_id)
def normalize_whole_spectrum(spec_id, med_wave, max_wave): """ Use the whole spectrum, strategy 'median+max' """ star_spectrum = ispec.read_spectrum(spec_id) #--- Continuum fit ------------------------------------------------------------- model = "Splines" # "Polynomy" degree = 2 nknots = None # Automatic: 1 spline every 5 nm from_resolution = 47000 # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum order='median+max' median_wave_range=med_wave max_wave_range=max_wave star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \ nknots=nknots, degree=degree, \ median_wave_range=median_wave_range, \ max_wave_range=max_wave_range, \ model=model, order=order, \ automatic_strong_line_detection=True, \ strong_line_probability=0.5, \ use_errors_for_fitting=True) #--- Continuum normalization --------------------------------------------------- logging.info("Continuum normalization...") normalized_star_spectrum = ispec.normalize_spectrum(star_spectrum, star_continuum_model, consider_continuum_errors=False) # Use a fixed value because the spectrum is already normalized star_continuum_model = ispec.fit_continuum(star_spectrum, fixed_value=1.0, model="Fixed value") ispec.write_spectrum(normalized_star_spectrum, spec_id)
def test_normalize_spectrum_in_segments(self): """ Fit continuum in each segment independently, strategy 'median+max' """ star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Continuum fit ------------------------------------------------------------- model = "Splines" # "Polynomy" degree = 2 nknots = 1 from_resolution = 80000 # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum order = 'median+max' median_wave_range = 0.05 max_wave_range = 1.0 segments = ispec.read_segment_regions( ispec_dir + "/input/regions/fe_lines_segments.txt") star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \ independent_regions=segments, nknots=nknots, degree=degree,\ median_wave_range=median_wave_range, \ max_wave_range=max_wave_range, \ model=model, order=order, \ automatic_strong_line_detection=True, \ strong_line_probability=0.5, \ use_errors_for_fitting=True) #--- Continuum normalization --------------------------------------------------- normalized_star_spectrum = ispec.normalize_spectrum( star_spectrum, star_continuum_model, consider_continuum_errors=False) # Use a fixed value because the spectrum is already normalized star_continuum_model = ispec.fit_continuum(star_spectrum, fixed_value=1.0, model="Fixed value") np.testing.assert_equal(star_spectrum['waveobs'], normalized_star_spectrum['waveobs']) self.assertAlmostEqual(star_spectrum['flux'][0], 0.67077) self.assertAlmostEqual(star_spectrum['flux'][-1], 2.2169) self.assertAlmostEqual(star_spectrum['err'][0], 0.0021259) self.assertAlmostEqual(star_spectrum['err'][-1], 0.0043878) self.assertAlmostEqual(normalized_star_spectrum['flux'][0], 1.0) self.assertAlmostEqual(normalized_star_spectrum['flux'][-1], 1.0) self.assertAlmostEqual(normalized_star_spectrum['err'][0], 0.0) self.assertAlmostEqual(normalized_star_spectrum['err'][-1], 0.0) self.assertAlmostEqual(normalized_star_spectrum['flux'][11], 0.9928764307623508) self.assertAlmostEqual(normalized_star_spectrum['flux'][58288], 0.960387654522309) self.assertAlmostEqual(normalized_star_spectrum['err'][11], 0.0028468129511384785) self.assertAlmostEqual(normalized_star_spectrum['err'][58288], 0.0019771951824093786) self.assertEqual( len(np.where(normalized_star_spectrum['flux'] != 1.)[0]), 33722) self.assertTrue( np.all(star_continuum_model(star_spectrum['waveobs']) == 1))
def determine_radial_velocity_with_mask(spec_id): mu_cas_spectrum = ispec.read_spectrum(spec_id) #--- Radial Velocity determination with linelist mask -------------------------- logging.info("Radial velocity determination with linelist mask...") # - Read atomic data mask_file = ispec_dir + "input/linelists/CCF/Narval.Sun.370_1048nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/Atlas.Arcturus.372_926nm/mask.lst"" #mask_file = ispec_dir + "input/linelists/CCF/Atlas.Sun.372_926nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.A0.350_1095nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.F0.360_698nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.G2.375_679nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.K0.378_679nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.K5.378_680nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/HARPS_SOPHIE.M5.400_687nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/Synthetic.Sun.350_1100nm/mask.lst" #mask_file = ispec_dir + "input/linelists/CCF/VALD.Sun.300_1100nm/mask.lst" ccf_mask = ispec.read_cross_correlation_mask(mask_file) models, ccf = ispec.cross_correlate_with_mask(mu_cas_spectrum, ccf_mask, \ lower_velocity_limit=-200, upper_velocity_limit=200, \ velocity_step=1.0, mask_depth=0.01, \ 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 # Applying correction logging.info("Applying radial velocity correction...") #rv = -96.40 # km/s mu_cas_spectrum = ispec.correct_velocity(mu_cas_spectrum, rv) ispec.write_spectrum(mu_cas_spectrum, spec_id)
def test_filter_cosmic_rays(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Continuum fit ------------------------------------------------------------- model = "Splines" # "Polynomy" degree = 2 nknots = None # Automatic: 1 spline every 5 nm from_resolution = 80000 # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum order = 'median+max' median_wave_range = 0.05 max_wave_range = 1.0 star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \ nknots=nknots, degree=degree, \ median_wave_range=median_wave_range, \ max_wave_range=max_wave_range, \ model=model, order=order, \ automatic_strong_line_detection=True, \ strong_line_probability=0.5, \ use_errors_for_fitting=True) #--- Filtering cosmic rays ----------------------------------------------------- # Spectrum should be already normalized cosmics = ispec.create_filter_cosmic_rays(star_spectrum, star_continuum_model, \ resampling_wave_step=0.001, window_size=15, \ variation_limit=0.01) clean_star_spectrum = star_spectrum[~cosmics] np.testing.assert_equal( np.where(cosmics)[0], np.array([ 730, 1472, 2626, 2635, 2703, 2704, 5319, 5773, 5782, 6075, 6500, 6610, 11814, 11846, 11883, 12050, 12104, 16562, 16862, 25310, 25311, 25948, 29402, 32355, 34342, 46984, 49469, 57858 ]))
def resample_spectrum(spec_id, min_wl, max_wl): star_spectrum = ispec.read_spectrum(spec_id) #--- Resampling -------------------------------------------------------------- logging.info("Resampling...") wavelengths = np.arange(min_wl, max_wl, 0.002) #resampled_star_spectrum = ispec.resample_spectrum(star_spectrum, wavelengths, method="bessel", zero_edges=True) resampled_star_spectrum = ispec.resample_spectrum(star_spectrum, wavelengths, method="linear", zero_edges=True) ispec.write_spectrum(resampled_star_spectrum, spec_id)
def degrade_resolution(spec_id, initial_res, final_res): star_spectrum = ispec.read_spectrum(spec_id) #--- Resolution degradation ---------------------------------------------------- logging.info("Degrading resolution...") from_resolution = initial_res to_resolution = final_res convolved_star_spectrum = ispec.convolve_spectrum(star_spectrum, to_resolution, \ from_resolution=from_resolution) ispec.write_spectrum(convolved_star_spectrum, spec_id)
def estimate_snr_from_flux(spec_id): star_spectrum = ispec.read_spectrum(spec_id) ## WARNING: To compare SNR estimation between different spectra, they should ## be homogeneously sampled (consider a uniform re-sampling) #--- Estimate SNR from flux ---------------------------------------------------- logging.info("Estimating SNR from fluxes...") num_points = 10 estimated_snr = ispec.estimate_snr(star_spectrum['flux'], num_points=num_points) return estimated_snr
def test_correct_radial_velocity(self): mu_cas_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_muCas.txt.gz") #--- Radial Velocity correction ------------------------------------------------ rv = -96.40 # km/s mu_cas_spectrum = ispec.correct_velocity(mu_cas_spectrum, rv) self.assertAlmostEqual(mu_cas_spectrum['waveobs'][0], 480.15547196) self.assertAlmostEqual(mu_cas_spectrum['flux'][0], 0.19076) self.assertAlmostEqual(mu_cas_spectrum['err'][0], 0.00095993)
def find_linemasks(spec_id, species): #code = "synthe" code = "spectrum" star_spectrum = ispec.read_spectrum(spec_id) #--- Continuum fit ------------------------------------------------------------- logging.info("Fitting fixed continuum...") star_continuum_model = ispec.fit_continuum(star_spectrum, fixed_value=1.0, model="Fixed value") #--- Find linemasks ------------------------------------------------------------ logging.info("Finding line masks...") #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" #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 = 47000 smoothed_star_spectrum = ispec.convolve_spectrum(star_spectrum, resolution) min_depth = 0.10 #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=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 lines of desired species elmt = star_linemasks['element'] == species elmt_star_linemasks = star_linemasks[elmt] file_id = species.replace(" ", "_") + "_linemasks.txt" # Write line regions with only masks limits and note: ispec.write_line_regions(elmt_star_linemasks, file_id)
def test_determine_tellurics_shift_with_template(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Telluric velocity shift determination from spectrum -------------------------- # - Read synthetic template template = ispec.read_spectrum( ispec_dir + "/input/spectra/templates/Synth.Tellurics.350_1100nm/template.txt.gz" ) models, ccf = ispec.cross_correlate_with_template(star_spectrum, template, \ lower_velocity_limit=-100, upper_velocity_limit=100, \ velocity_step=0.5, fourier=False, \ only_one_peak = True) bv = models[0].mu() # km/s bv_err = models[0].emu() # km/s self.assertAlmostEqual(bv, 8.169999999999954) self.assertAlmostEqual(bv_err, 0.6605884013888695)
def test_estimate_snr_from_flux(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") ## WARNING: To compare SNR estimation between different spectra, they should ## be homogeneously sampled (consider a uniform re-sampling) #--- Estimate SNR from flux ---------------------------------------------------- num_points = 10 estimated_snr = ispec.estimate_snr(star_spectrum['flux'], num_points=num_points) self.assertAlmostEqual(estimated_snr, 139.92497450174938)
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_spectrum_using_continuum_regions(self): """ Consider only continuum regions for the fit, strategy 'median+max' """ star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Continuum fit ------------------------------------------------------------- model = "Splines" # "Polynomy" degree = 2 nknots = None # Automatic: 1 spline every 5 nm from_resolution = 80000 # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum order = 'median+max' median_wave_range = 0.05 max_wave_range = 1.0 continuum_regions = ispec.read_continuum_regions( ispec_dir + "/input/regions/fe_lines_continuum.txt") star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \ continuum_regions=continuum_regions, nknots=nknots, degree=degree, \ median_wave_range=median_wave_range, \ max_wave_range=max_wave_range, \ model=model, order=order, \ automatic_strong_line_detection=True, \ strong_line_probability=0.5, \ use_errors_for_fitting=True) #--- Continuum normalization --------------------------------------------------- normalized_star_spectrum = ispec.normalize_spectrum( star_spectrum, star_continuum_model, consider_continuum_errors=False) # Use a fixed value because the spectrum is already normalized star_continuum_model = ispec.fit_continuum(star_spectrum, fixed_value=1.0, model="Fixed value") np.testing.assert_equal(star_spectrum['waveobs'], normalized_star_spectrum['waveobs']) self.assertAlmostEqual(star_spectrum['flux'][0], 0.67077) self.assertAlmostEqual(star_spectrum['flux'][-1], 2.2169) self.assertAlmostEqual(star_spectrum['err'][0], 0.0021259) self.assertAlmostEqual(star_spectrum['err'][-1], 0.0043878) self.assertAlmostEqual(normalized_star_spectrum['flux'][0], 0.7990890725070141) self.assertAlmostEqual(normalized_star_spectrum['flux'][-1], 0.9887281323707806) self.assertAlmostEqual(normalized_star_spectrum['err'][0], 0.0025325871151701197) self.assertAlmostEqual(normalized_star_spectrum['err'][-1], 0.001956940457042046) self.assertTrue( np.all(star_continuum_model(star_spectrum['waveobs']) == 1))
def estimate_snr_from_err(spec_id): star_spectrum = ispec.read_spectrum(spec_id) #--- Estimate SNR from errors -------------------------------------------------- logging.info("Estimating SNR from errors...") efilter = star_spectrum['err'] > 0 filtered_star_spectrum = star_spectrum[efilter] if len(filtered_star_spectrum) > 1: estimated_snr = np.median(filtered_star_spectrum['flux'] / filtered_star_spectrum['err']) else: # All the errors are set to zero and we cannot calculate SNR using them estimated_snr = 0 return estimated_snr
def test_normalize_whole_spectrum(self): """ Use the whole spectrum, strategy 'median+max' """ star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Continuum fit ------------------------------------------------------------- model = "Splines" # "Polynomy" degree = 2 nknots = None # Automatic: 1 spline every 5 nm from_resolution = 80000 # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum order = 'median+max' median_wave_range = 0.05 max_wave_range = 1.0 star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \ nknots=nknots, degree=degree, \ median_wave_range=median_wave_range, \ max_wave_range=max_wave_range, \ model=model, order=order, \ automatic_strong_line_detection=True, \ strong_line_probability=0.5, \ use_errors_for_fitting=True) #--- Continuum normalization --------------------------------------------------- normalized_star_spectrum = ispec.normalize_spectrum( star_spectrum, star_continuum_model, consider_continuum_errors=False) # Use a fixed value because the spectrum is already normalized star_continuum_model = ispec.fit_continuum(star_spectrum, fixed_value=1.0, model="Fixed value") np.testing.assert_equal(star_spectrum['waveobs'], normalized_star_spectrum['waveobs']) self.assertAlmostEqual(star_spectrum['flux'][0], 0.67077) self.assertAlmostEqual(star_spectrum['flux'][-1], 2.2169) self.assertAlmostEqual(star_spectrum['err'][0], 0.0021259) self.assertAlmostEqual(star_spectrum['err'][-1], 0.0043878) self.assertAlmostEqual(normalized_star_spectrum['flux'][0], 0.8052457389161867) self.assertAlmostEqual(normalized_star_spectrum['flux'][-1], 0.9895767577073404) self.assertAlmostEqual(normalized_star_spectrum['err'][0], 0.0025520997008839415) self.assertAlmostEqual(normalized_star_spectrum['err'][-1], 0.0019586200989978207) self.assertTrue( np.all(star_continuum_model(star_spectrum['waveobs']) == 1))
def determine_radial_velocity_with_template(self): mu_cas_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_muCas.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(mu_cas_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 = models[0].mu() # km/s rv_err = models[0].emu() # km/s self.assertEqual(components, 1) self.assertAlmostEqual(rv, -96.43) self.assertAlmostEqual(rv_err, 0.03736164048308909)
def test_smooth_spectrum(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Smoothing spectrum (resolution will be affected) -------------------------- resolution = 80000 smoothed_star_spectrum = ispec.convolve_spectrum( star_spectrum, resolution) np.testing.assert_equal(star_spectrum['waveobs'], smoothed_star_spectrum['waveobs']) self.assertAlmostEqual(smoothed_star_spectrum['flux'][0], 0.6973069596669491) self.assertAlmostEqual(smoothed_star_spectrum['flux'][-1], 2.2207560753191666) self.assertAlmostEqual(smoothed_star_spectrum['err'][0], 0.002174423029777254) self.assertAlmostEqual(smoothed_star_spectrum['err'][-1], 0.004451564365118501)
def test_cut_spectrum_from_segments(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Cut ----------------------------------------------------------------------- # Keep only points inside a list of segments segments = ispec.read_segment_regions( ispec_dir + "/input/regions/fe_lines_segments.txt") wfilter = ispec.create_wavelength_filter(star_spectrum, regions=segments) cutted_star_spectrum = star_spectrum[wfilter] self.assertEqual(len(segments), 132) self.assertAlmostEqual(segments['wave_base'][0], 480.01937) self.assertAlmostEqual(segments['wave_top'][0], 481.08295) self.assertEqual(len(cutted_star_spectrum), 33722) self.assertAlmostEqual(cutted_star_spectrum['waveobs'][0], 480.02156956) self.assertAlmostEqual(cutted_star_spectrum['flux'][0], 0.81984) self.assertAlmostEqual(cutted_star_spectrum['err'][0], 0.0023458)
def test_degrade_resolution(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Resolution degradation ---------------------------------------------------- from_resolution = 80000 to_resolution = 47000 convolved_star_spectrum = ispec.convolve_spectrum(star_spectrum, to_resolution, \ from_resolution=from_resolution) np.testing.assert_equal(star_spectrum['waveobs'], convolved_star_spectrum['waveobs']) self.assertAlmostEqual(convolved_star_spectrum['flux'][0], 0.7109576121207318) self.assertAlmostEqual(convolved_star_spectrum['flux'][-1], 2.2237382541838007) self.assertAlmostEqual(convolved_star_spectrum['err'][0], 0.0021974272902411723) self.assertAlmostEqual(convolved_star_spectrum['err'][-1], 0.004453852796214372)
def test_add_noise_to_spectrum(self): """ Add noise to an spectrum (ideally to a synthetic one) based on a given SNR. """ star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") np.random.seed(42) #--- Adding poisson noise ----------------------------------------------------- snr = 100 distribution = "poisson" # "gaussian" noisy_star_spectrum = ispec.add_noise(star_spectrum, snr, distribution) np.testing.assert_almost_equal( noisy_star_spectrum['flux'][:10], np.array([ 0.6678, 0.7459, 0.776, 0.7796, 0.802, 0.7953, 0.7383, 0.7164, 0.7381, 0.7876 ])) np.testing.assert_equal(star_spectrum['waveobs'], noisy_star_spectrum['waveobs'])
def test_convert_air_to_vacuum(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Converting wavelengths from air to vacuum and viceversa ------------------- star_spectrum_vacuum = ispec.air_to_vacuum(star_spectrum) star_spectrum_air = ispec.vacuum_to_air(star_spectrum_vacuum) np.testing.assert_equal(star_spectrum['flux'], star_spectrum_vacuum['flux']) np.testing.assert_equal(star_spectrum['err'], star_spectrum_vacuum['err']) np.testing.assert_equal(star_spectrum['flux'], star_spectrum_air['flux']) np.testing.assert_equal(star_spectrum['err'], star_spectrum_air['err']) np.testing.assert_almost_equal(star_spectrum['waveobs'], star_spectrum_air['waveobs']) self.assertAlmostEqual(star_spectrum_vacuum['waveobs'][0], 480.12574305216896) self.assertAlmostEqual(star_spectrum_vacuum['waveobs'][-1], 680.175349351457)
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 test_determine_tellurics_shift_with_mask(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Telluric velocity shift determination from spectrum -------------------------- # - Telluric telluric_linelist_file = ispec_dir + "/input/linelists/CCF/Synth.Tellurics.500_1100nm/mask.lst" telluric_linelist = ispec.read_telluric_linelist( telluric_linelist_file, minimum_depth=0.0) models, ccf = ispec.cross_correlate_with_mask(star_spectrum, telluric_linelist, \ lower_velocity_limit=-100, upper_velocity_limit=100, \ velocity_step=0.5, mask_depth=0.01, \ fourier = False, only_one_peak = True) bv = models[0].mu() # km/s bv_err = models[0].emu() # km/s self.assertAlmostEqual(bv, 8.139999999999954) self.assertAlmostEqual(bv_err, 0.031123202937016047)
def test_find_continuum_regions(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Continuum fit ------------------------------------------------------------- model = "Splines" # "Polynomy" degree = 2 nknots = None # Automatic: 1 spline every 5 nm from_resolution = 80000 # Strategy: Filter first median values and secondly MAXIMUMs in order to find the continuum order = 'median+max' median_wave_range = 0.05 max_wave_range = 1.0 star_continuum_model = ispec.fit_continuum(star_spectrum, from_resolution=from_resolution, \ nknots=nknots, degree=degree, \ median_wave_range=median_wave_range, \ max_wave_range=max_wave_range, \ model=model, order=order, \ automatic_strong_line_detection=True, \ strong_line_probability=0.5, \ use_errors_for_fitting=True) #--- Find continuum regions ---------------------------------------------------- resolution = 80000 sigma = 0.001 max_continuum_diff = 1.0 fixed_wave_step = 0.05 star_continuum_regions = ispec.find_continuum(star_spectrum, resolution, \ max_std_continuum = sigma, \ continuum_model = star_continuum_model, \ max_continuum_diff=max_continuum_diff, \ fixed_wave_step=fixed_wave_step) #ispec.write_continuum_regions(star_continuum_regions, "example_star_fe_lines_continuum.txt") self.assertEqual(len(star_continuum_regions), 2) self.assertAlmostEqual(star_continuum_regions['wave_base'][0], 528.6665701) self.assertAlmostEqual(star_continuum_regions['wave_top'][0], 528.6915701) self.assertAlmostEqual(star_continuum_regions['wave_base'][1], 608.4415701) self.assertAlmostEqual(star_continuum_regions['wave_top'][1], 608.4665701)
def test_resample_spectrum(self): star_spectrum = ispec.read_spectrum( ispec_dir + "/input/spectra/examples/NARVAL_Sun_Vesta-1.txt.gz") #--- Resampling -------------------------------------------------------------- wavelengths = np.arange(480.0, 680.0, 0.001) resampled_star_spectrum = ispec.resample_spectrum(star_spectrum, wavelengths, method="linear", zero_edges=True) #resampled_star_spectrum = ispec.resample_spectrum(star_spectrum, wavelengths, method="bessel", zero_edges=True) self.assertEqual(len(resampled_star_spectrum), 200000) self.assertAlmostEqual(resampled_star_spectrum['waveobs'][0], 480.) self.assertAlmostEqual(resampled_star_spectrum['waveobs'][-1], 680. - 0.001) self.assertAlmostEqual(resampled_star_spectrum['flux'][0], 0.7957469310344828) self.assertAlmostEqual(resampled_star_spectrum['flux'][-1], 0.0) self.assertAlmostEqual(resampled_star_spectrum['err'][0], 0.002313683448275862) self.assertAlmostEqual(resampled_star_spectrum['err'][-1], 0.0)
def determine_radial_velocity_with_template(star_spectrum): ''' Determine radial velocity of star_spectrum compared with some template Chose template wisely; Return Radial velocity and err''' logging.info("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) # First component: rv = np.round(models[0].mu(), 2) # km/s rv_err = np.round(models[0].emu(), 2) # km/s return rv, rv_err
# set up the plots if args.plot: #fig, ax = plt.subplots(3, 1, figsize=(10, 10)) #ax[0].set_title('Spectral Analysis - {}'.format(swasp_id)) plt.ion() ax_spec = plt.subplot2grid((6, 4), (0, 0), colspan=4, rowspan=2) ax_spec.set_title('{} {}'.format(swasp_id, spectrum)) ax_mask_rv = plt.subplot2grid((6, 4), (2, 0), colspan=2, rowspan=2) ax_mask_rv.set_title('RV wrt {}'.format(mask_type)) ax_mask_ccf = plt.subplot2grid((6, 4), (4, 0), colspan=2, rowspan=2) ax_mask_ccf.set_title('CCF wrt {}'.format(mask_type)) plt.subplots_adjust(hspace=1.0) plt.show() # read in the spectrum spec = ispec.read_spectrum(spectrum) print('{} Loaded...'.format(spectrum)) # chop out the wavelength range we want to work on # accesss the data using column names # e.g. s['waveobs' | 'flux' | 'err'] wave_filter = ispec.create_wavelength_filter(spec, \ wave_base=INSTRUMENT[args.instrument]['WV_LLIM'], \ wave_top=INSTRUMENT[args.instrument]['WV_ULIM']) spec = spec[wave_filter] print('{} Wavelength range restricted to {}-{}'.format(spectrum, \ INSTRUMENT[args.instrument]['WV_LLIM'], \ INSTRUMENT[args.instrument]['WV_ULIM'])) if args.plot: ax_spec.plot(spec['waveobs'], spec['flux'], 'r-')