def test_user_supplied_poly_coeff_twodspec(): # Load the image lhs6328_fits = fits.open( os.path.join(HERE, "test_data", "v_e_20180810_12_1_0_0.fits.gz") )[0] spatial_mask = np.arange(50, 200) spec_mask = np.arange(50, 1024) # # Loading two pre-saved spectral traces from a single FITS file. # lhs6328 = spectral_reduction.TwoDSpec( lhs6328_fits, spatial_mask=spatial_mask, spec_mask=spec_mask, cosmicray=True, readnoise=2.34, log_file_name=None, ) # Trace the spectra lhs6328.ap_trace(nspec=2, display=False) # Extract the spectra lhs6328.ap_extract(apwidth=10, optimal=True, skywidth=10, display=False) # Calibrate the 1D spectra lhs6328_onedspec = spectral_reduction.OneDSpec(log_file_name=None) lhs6328_onedspec.from_twodspec(lhs6328) fit_coeff = np.array( [ 3.09833375e03, 5.98842823e00, -2.83963934e-03, 2.84842392e-06, -1.03725267e-09, ] ) fit_type = "poly" # Note that there are two science traces, so two polyfit coefficients # have to be supplied by in a list lhs6328_onedspec.add_fit_coeff(fit_coeff, fit_type) lhs6328_onedspec.apply_wavelength_calibration() # Inspect reduced spectrum lhs6328_onedspec.inspect_reduced_spectrum(display=False) # Save as a FITS file lhs6328_onedspec.save_fits( output="wavecal+count", filename=os.path.join( HERE, "test_output", "user_supplied_wavelength_polyfit_coefficients", ), stype="science", overwrite=True, )
def calibrate_red(science, standard, standard_name): # # Start handling 1D spectra here # # Need to add fringe subtraction here red_onedspec = spectral_reduction.OneDSpec(log_level='INFO', log_file_name=None) # Red spectrum first red_onedspec.from_twodspec(standard, stype='standard') red_onedspec.from_twodspec(science, stype='science') # Find the peaks of the arc red_onedspec.find_arc_lines(display=True, prominence=0.25, top_n_peaks=25, stype='science') red_onedspec.find_arc_lines(display=False, prominence=0.25, top_n_peaks=25, stype='standard') # Configure the wavelength calibrator red_onedspec.initialise_calibrator(stype='science+standard') red_onedspec.add_user_atlas(elements=element_Hg_red, wavelengths=atlas_Hg_red, stype='science+standard') red_onedspec.add_user_atlas(elements=element_Ar_red, wavelengths=atlas_Ar_red, stype='science+standard') red_onedspec.set_hough_properties(num_slopes=5000, xbins=200, ybins=200, min_wavelength=4750, max_wavelength=10750, stype='science+standard') red_onedspec.set_ransac_properties(minimum_matches=13, stype='science+standard') red_onedspec.do_hough_transform(stype='science+standard') # Solve for the pixel-to-wavelength solution red_onedspec.fit(max_tries=5000, stype='science+standard', display=True) # Apply the wavelength calibration and display it red_onedspec.apply_wavelength_calibration(wave_start=5000, wave_end=11000, wave_bin=1, stype='science+standard') red_onedspec.load_standard(standard_name) red_onedspec.get_sensitivity() red_onedspec.apply_flux_calibration() red_onedspec.get_telluric_profile() red_onedspec.apply_telluric_correction() return red_onedspec
def test_telluric_square_wave(): wave = np.arange(1000.0) flux_sci = np.ones(1000) * 5.0 flux_std = np.ones(1000) * 100.0 flux_sci_continuum = copy.deepcopy(flux_sci) flux_std_continuum = copy.deepcopy(flux_std) flux_sci[500:550] *= 0.01 flux_sci[700:750] *= 0.001 flux_sci[850:950] *= 0.1 flux_std[500:550] *= 0.01 flux_std[700:750] *= 0.001 flux_std[850:950] *= 0.1 # Get the telluric profile fluxcal = FluxCalibration(log_file_name=None) telluric_func = fluxcal.get_telluric_profile( wave, flux_std, flux_std_continuum, mask_range=[[495, 551], [700, 753], [848, 960]], return_function=True, ) onedspec = spectral_reduction.OneDSpec(log_file_name=None) onedspec.science_spectrum_list[0].add_wavelength(wave) onedspec.science_spectrum_list[0].add_flux(flux_sci, None, None) onedspec.science_spectrum_list[0].add_flux_continuum(flux_sci_continuum) # onedspec.fluxcal.spectrum1D.add_wavelength(wave) # onedspec.fluxcal.spectrum1D.add_flux(flux_std, None, None) # onedspec.fluxcal.spectrum1D.add_flux_continuum(flux_std_continuum) onedspec.add_telluric_function(telluric_func, stype="science") onedspec.get_telluric_correction() onedspec.apply_telluric_correction() assert np.isclose( np.nansum(onedspec.science_spectrum_list[0].flux), np.nansum(flux_sci_continuum), rtol=1e-2, ) onedspec.inspect_telluric_correction( display=False, return_jsonstring=True, save_fig=True, fig_type="iframe+jpg+png+svg+pdf", filename=os.path.join(HERE, "test_output", "test_telluric"), )
def calibrate_blue(science, standard, standard_name): # Blue spectrum here blue = spectral_reduction.OneDSpec(log_level='INFO', log_file_name=None) blue.from_twodspec(standard, stype='standard') blue.from_twodspec(science, stype='science') blue.find_arc_lines(prominence=0.25, top_n_peaks=10, display=True, stype='science') blue.find_arc_lines(prominence=0.25, top_n_peaks=10, display=False, stype='standard') blue.initialise_calibrator(stype='science+standard') blue.add_user_atlas(elements=element_Hg_blue, wavelengths=atlas_Hg_blue, stype='science+standard') blue.add_user_atlas(elements=element_Ar_blue, wavelengths=atlas_Ar_blue, stype='science+standard') blue.add_user_atlas(elements=element_Zn_blue, wavelengths=atlas_Zn_blue, stype='science+standard') blue.set_hough_properties(num_slopes=2000, xbins=200, ybins=200, min_wavelength=3250, max_wavelength=5850, stype='science+standard') blue.set_ransac_properties(filter_close=True, stype='science+standard') blue.do_hough_transform(stype='science+standard') # Solve for the pixel-to-wavelength solution blue.fit(max_tries=5000, stype='science+standard', display=True) # Apply the wavelength calibration and display it blue.apply_wavelength_calibration(wave_start=3200, wave_end=5600, wave_bin=1, stype='science+standard') blue.load_standard(standard_name) blue.get_sensitivity() blue.apply_flux_calibration() return blue
def test_user_supplied_wavelength_twodspec(mock_show): # Load the image lhs6328_fits = fits.open( os.path.join(HERE, "test_data", "v_e_20180810_12_1_0_0.fits.gz") )[0] spatial_mask = np.arange(50, 200) spec_mask = np.arange(50, 1024) # # Loading two pre-saved spectral traces from a single FITS file. # lhs6328 = spectral_reduction.TwoDSpec( lhs6328_fits, spatial_mask=spatial_mask, spec_mask=spec_mask, cosmicray=True, readnoise=2.34, log_file_name=None, ) # Trace the spectra lhs6328.ap_trace(nspec=2, display=True) # Extract the spectra lhs6328.ap_extract(apwidth=10, optimal=True, skywidth=10, display=True) # Calibrate the 1D spectra lhs6328_onedspec = spectral_reduction.OneDSpec(log_file_name=None) lhs6328_onedspec.from_twodspec(lhs6328) wavelength = np.genfromtxt( os.path.join( HERE, "test_data", "test_full_run_standard_wavelength.csv" ) ) # Manually supply wavelengths lhs6328_onedspec.add_wavelength([wavelength, wavelength]) # Inspect reduced spectrum lhs6328_onedspec.inspect_reduced_spectrum(display=False) # Save as a FITS file lhs6328_onedspec.save_fits( output="count", filename=os.path.join(HERE, "test_output", "user_supplied_wavelength"), stype="science", overwrite=True, )
def test_telluric_real_data(mock_show): std_wave = np.load(os.path.join(HERE, "test_data", "std_wave.npy")) std_flux = np.load(os.path.join(HERE, "test_data", "std_flux.npy")) std_flux_continuum = np.load( os.path.join(HERE, "test_data", "std_flux_continuum.npy")) sci_wave = np.load(os.path.join(HERE, "test_data", "sci_wave.npy")) sci_flux = np.load(os.path.join(HERE, "test_data", "sci_flux.npy")) sci_flux_continuum = np.load( os.path.join(HERE, "test_data", "sci_flux_continuum.npy")) # Get the telluric profile fluxcal = FluxCalibration(log_file_name=None) telluric_func = fluxcal.get_telluric_profile(std_wave, std_flux, std_flux_continuum, return_function=True) onedspec = spectral_reduction.OneDSpec(log_file_name=None) onedspec.science_spectrum_list[0].add_wavelength(sci_wave) onedspec.science_spectrum_list[0].add_flux(sci_flux, None, None) onedspec.science_spectrum_list[0].add_flux_continuum(sci_flux_continuum) onedspec.fluxcal.spectrum1D.add_wavelength(std_wave) onedspec.fluxcal.spectrum1D.add_flux(std_flux, None, None) onedspec.fluxcal.spectrum1D.add_flux_continuum(std_flux_continuum) onedspec.add_telluric_function(telluric_func) onedspec.apply_telluric_correction() assert np.isclose( np.nansum(onedspec.science_spectrum_list[0].flux), np.nansum(sci_flux_continuum), rtol=1e-2, ) onedspec.inspect_telluric_profile( display=True, return_jsonstring=True, save_fig=True, fig_type="iframe+jpg+png+svg+pdf", filename=os.path.join(HERE, "test_output", "test_telluric"), )
optimal=True, display=False, filename=os.path.join( reduced_data_folder_path, obsnight, light_name + '_apextract'), save_iframe=True) twodspec.add_arc(arc_file_path) twodspec.extract_arc_spec(display=False, filename=os.path.join( reduced_data_folder_path, obsnight, light_name + '_arc_spec'), save_iframe=True) onedspec = spectral_reduction.OneDSpec() onedspec.from_twodspec(twodspec, stype='science') # Find the peaks of the arc onedspec.find_arc_lines(display=False, stype='science', filename=os.path.join( reduced_data_folder_path, obsnight, light_name + '_arc_lines'), save_iframe=True) # Configure the wavelength calibrator onedspec.initialise_calibrator(stype='science+') onedspec.set_hough_properties(num_slopes=500, xbins=100, ybins=100,
def test_full_run(mock_show): # Extract two spectra # Line list atlas = [ 4193.5, 4385.77, 4500.98, 4524.68, 4582.75, 4624.28, 4671.23, 4697.02, 4734.15, 4807.02, 4921.48, 5028.28, 5618.88, 5823.89, 5893.29, 5934.17, 6182.42, 6318.06, 6472.841, 6595.56, 6668.92, 6728.01, 6827.32, 6976.18, 7119.60, 7257.9, 7393.8, 7584.68, 7642.02, 7740.31, 7802.65, 7887.40, 7967.34, 8057.258, ] element = ["Xe"] * len(atlas) spatial_mask = np.arange(35, 200) spec_mask = np.arange(50, 1024) # Science frame lhs6328_frame = image_reduction.ImageReduction( log_level="ERROR", log_file_folder=os.path.join(HERE, "test_output")) lhs6328_frame.add_filelist("test/test_data/sprat_LHS6328.list") lhs6328_frame.load_data() lhs6328_frame.reduce() lhs6328_frame.save_fits("test/test_output/test_full_run_standard_image", overwrite=True) lhs6328_twodspec = spectral_reduction.TwoDSpec( lhs6328_frame, spatial_mask=spatial_mask, spec_mask=spec_mask, cosmicray=True, psfmodel="gaussxy", readnoise=5.7, log_level="ERROR", log_file_folder=os.path.join(HERE, "test_output"), ) lhs6328_twodspec.ap_trace(nspec=2, display=False) # Optimal extraction to get the LSF for force extraction below lhs6328_twodspec.ap_extract(apwidth=15, skywidth=10, skydeg=1, optimal=True, display=False) # Force extraction lhs6328_twodspec.ap_extract( apwidth=15, skywidth=10, skydeg=1, optimal=True, forced=True, variances=lhs6328_twodspec.spectrum_list[1].var, display=False, ) # Aperture extraction lhs6328_twodspec.ap_extract( apwidth=15, skywidth=5, skydeg=1, optimal=False, display=False, save_fig=True, filename=os.path.join(HERE, "test_output", "test_full_run_extract"), ) lhs6328_twodspec.inspect_line_spread_function(spec_id=0, display=False, return_jsonstring=True) lhs6328_twodspec.inspect_line_spread_function(display=False, return_jsonstring=True) # Optimal extraction lhs6328_twodspec.ap_extract( apwidth=15, skywidth=5, skydeg=1, optimal=True, forced=True, variances=1000000.0, display=False, save_fig=True, filename=os.path.join(HERE, "test_output", "test_full_run_extract"), ) lhs6328_twodspec.inspect_line_spread_function( save_fig=True, display=True, open_iframe=False, filename=os.path.join(HERE, "test_output", "test_full_run_lsf"), ) lhs6328_twodspec.save_fits( filename=os.path.join(HERE, "test_output", "test_full_run_twospec"), overwrite=True, ) # Standard frame standard_frame = image_reduction.ImageReduction( log_level="ERROR", log_file_folder=os.path.join(HERE, "test_output")) standard_frame.add_filelist( os.path.join(HERE, "test_data", "sprat_Hiltner102.list")) standard_frame.load_data() standard_frame.reduce() standard_frame.save_fits( os.path.join(HERE, "test_output", "test_full_run_standard_image"), overwrite=True, ) hilt102_twodspec = spectral_reduction.TwoDSpec( standard_frame, cosmicray=True, psfmodel="gaussyx", spatial_mask=spatial_mask, spec_mask=spec_mask, readnoise=5.7, log_level="ERROR", log_file_folder=os.path.join(HERE, "test_output"), ) hilt102_twodspec.ap_trace(nspec=1, resample_factor=10, display=False) hilt102_twodspec.ap_extract(apwidth=15, skysep=3, skywidth=5, skydeg=1, optimal=True, display=False) hilt102_twodspec.inspect_line_spread_function( display=True, save_fig=True, fig_type="jpg+png+pdf+svg+iframe", filename=os.path.join(HERE, "test_output", "test_full_run_lsf"), return_jsonstring=True, ) # Extract the 1D arc by aperture sum of the traces provided lhs6328_twodspec.extract_arc_spec( display=True, save_fig=True, fig_type="jpg+png+pdf+svg+iframe", filename=os.path.join(HERE, "test_output", "test_full_run_arc_spec"), return_jsonstring=True, ) hilt102_twodspec.extract_arc_spec(display=True) hilt102_twodspec.create_fits(output="trace+count") # Handle 1D Science spectrum lhs6328_onedspec = spectral_reduction.OneDSpec( log_level="ERROR", log_file_folder=os.path.join(HERE, "test_output")) lhs6328_onedspec.from_twodspec(lhs6328_twodspec, stype="science") lhs6328_onedspec.from_twodspec(hilt102_twodspec, stype="standard") # Create the trace and count as FITS BEFORE flux and wavelength calibration # This is an uncommon operation, but it should work. lhs6328_onedspec.create_fits(output="trace+count", stype="science+standard") # Save the trace and count as FITS BEFORE flux and wavelength calibration # This is an uncommon operation, but it should work. lhs6328_onedspec.save_fits( output="trace+count", filename=os.path.join(HERE, "test_output", "test_full_run"), stype="science+standard", overwrite=True, ) # Find the peaks of the arc lhs6328_onedspec.find_arc_lines(display=True, stype="science+standard") lhs6328_onedspec.find_arc_lines(display=False, stype="science+standard") lhs6328_onedspec.inspect_arc_lines(spec_id=0, display=True, stype="science+standard") lhs6328_onedspec.inspect_arc_lines(spec_id=0, display=False, stype="science+standard") # Configure the wavelength calibrator lhs6328_onedspec.initialise_calibrator(stype="science+standard") lhs6328_onedspec.set_hough_properties( num_slopes=1000, xbins=200, ybins=200, min_wavelength=3500, max_wavelength=8500, stype="science+standard", ) lhs6328_onedspec.set_ransac_properties(filter_close=True, stype="science+standard") lhs6328_onedspec.add_user_atlas(elements=element, wavelengths=atlas, stype="science+standard") lhs6328_onedspec.do_hough_transform() # Solve for the pixel-to-wavelength solution lhs6328_onedspec.fit(max_tries=200, stype="science+standard", display=False) lhs6328_onedspec.robust_refit() # list the matched pixel-peaks lhs6328_onedspec.get_pix_wave_pairs(spec_id=0) lhs6328_onedspec.get_pix_wave_pairs() # get all the calibrators cal = lhs6328_onedspec.get_calibrator() # Apply the wavelength calibration and display it lhs6328_onedspec.apply_wavelength_calibration(stype="science+standard") # Get the standard from the library lhs6328_onedspec.load_standard(target="hiltner102") lhs6328_onedspec.get_continuum() lhs6328_onedspec.get_sensitivity(sens_deg=11, method="polynomial", mask_fit_size=1) lhs6328_onedspec.get_sensitivity(k=3, method="interpolate", mask_fit_size=1) lhs6328_onedspec.apply_flux_calibration(stype="science+standard") lhs6328_onedspec.inspect_reduced_spectrum() lhs6328_onedspec.get_telluric_profile() lhs6328_onedspec.inspect_telluric_profile(display=False) lhs6328_onedspec.apply_telluric_correction() lhs6328_onedspec.inspect_reduced_spectrum() # Apply atmospheric extinction correction lhs6328_onedspec.set_atmospheric_extinction(location="orm") lhs6328_onedspec.apply_atmospheric_extinction_correction() lhs6328_onedspec.inspect_reduced_spectrum() # Create FITS lhs6328_onedspec.create_fits(output="trace+count") # Modify FITS header for the trace lhs6328_onedspec.modify_trace_header(0, "set", "COMMENT", "Hello World!") print(lhs6328_onedspec.science_spectrum_list[0].trace_hdulist[0]. header["COMMENT"]) # Create more FITS lhs6328_onedspec.create_fits( output="trace+count+arc_spec+wavecal", stype="science+standard", recreate=False, ) # Check the modified headers are not overwritten print(lhs6328_onedspec.science_spectrum_list[0].trace_hdulist[0]. header["COMMENT"]) # Save as FITS (and create the ones that were not created earlier) lhs6328_onedspec.save_fits( output="trace+count+arc_spec+wavecal+wavelength+count_resampled+flux+" "flux_resampled", filename=os.path.join(HERE, "test_output", "test_full_run"), stype="science+standard", recreate=False, overwrite=True, ) # Check the modified headers are still not overwritten print(lhs6328_onedspec.science_spectrum_list[0].trace_hdulist[0]. header["COMMENT"]) # Create more FITS lhs6328_onedspec.create_fits(output="trace", stype="science+standard", recreate=True) # Now the FITS header should be back to default print(lhs6328_onedspec.science_spectrum_list[0].trace_hdulist[0].header) # save as CSV lhs6328_onedspec.save_csv( output="trace+count+arc_spec+wavecal+wavelength+count_resampled+flux+" "flux_resampled", filename=os.path.join(HERE, "test_output", "test_full_run"), stype="science+standard", overwrite=True, ) # save figure lhs6328_onedspec.inspect_reduced_spectrum( filename=os.path.join(HERE, "test_output", "test_full_run"), display=False, save_fig=True, fig_type="iframe+png", ) # Plot the hough search space lhs6328_onedspec.plot_search_space( filename=os.path.join(HERE, "test_output", "test_full_run_plot_hough_space"), display=False, save_fig=True, fig_type="iframe+png", )