Accessing stellar spectra¶
In the previous notebook we saw how to configure our DataClass to open ESPRESSO observations. In this, we will see how we can interact with the stellar spectra and the header keywords.
from pathlib import Path
from ASTRA.data_objects.DataClass import DataClass
from ASTRA.Instruments import ESPRESSO
inst_options = {}
data_in_path = list(Path("/home/amiguel/spectra_collection/ESPRESSO/proxima").glob("*.fits"))
data = DataClass(data_in_path, instrument=ESPRESSO, instrument_options=inst_options, storage_path="")
In ASTRA, each observation is called a Frame, with a corresponding (unique) identifier (constructed from the hash of the filename, can take negative values). Furthermore, the division between multiple datasets of each instrument (known as sub-Instruments, e.g., ESPRESSO18, ESPRESSO19) is done automatically.
Through the DataClass interface we can ask for:
- Data for a corresponding frameID
- Data for a given sub-Instrument
- All data that was loaded
Furthermore, at runtime we can reject observations (either by user-imposed conditions or by internal QC checks).
from ASTRA.utils.spectral_conditions import FNAME_condition
print(data)
print("Loaded sub-Instruments", data.get_subInstruments_with_valid_frames())
print("Current frameIDs", data.get_valid_frameIDS())
print("Current (rejected) frameIDs", data.get_invalid_frameIDs())
condition = FNAME_condition(data_in_path[0].name)
data.reject_observations(conditions=condition)
print("---//---")
print("Current frameIDs", data.get_valid_frameIDS())
print("Current (rejected) frameIDs", data.get_invalid_frameIDs())
Data Class from <class 'ASTRA.Instruments.ESPRESSO.ESPRESSO'> holding 0 OBS from ESPRESSO18, 3 OBS from ESPRESSO19 Loaded sub-Instruments ['ESPRESSO19'] Current frameIDs [565306508, 4035951396, 933504894] Current (rejected) frameIDs [] ---//--- Current frameIDs [4035951396, 933504894] Current (rejected) frameIDs [565306508]
Collect header keywords¶
By default, ASTRA collects some header keywords under a common name across multiple instruments, standardizing the information needed to construct the stellar template (see here for a full list). If needed, the collect_KW_observations also accepts a Condition object to select the observations from which we will load header information.
Some values have an internal name that allows easy access:
available_subInstruments = data.get_subInstruments_with_valid_frames()
ccf_rv = data.collect_KW_observations("DRS_RV", subInstruments=available_subInstruments)
Some of the internal values are stored as astropy.Quantity data products, which can be converted to float values through:
from ASTRA.utils.units import convert_data, kilometer_second
convert_data(data=ccf_rv, as_value=True, new_units= kilometer_second)
[-21.3856633997537, -21.3845961288029]
In alternative, we can ask ASTRA to load the keywords directly from the header
data.collect_KW_observations("ESO QC CCF RV", subInstruments=available_subInstruments, from_header=True)
[-21.3856633997537, -21.3845961288029]
Or make a plot, for all available sub-Instruments:
data.plot_quantity("BJD", "DRS_RV", show=True)
Accessing stellar spectra¶
Through the DataClass interface we can directly access the wavelength, flux and uncertainties of the stellar spectra. Furthermore, we also gain access to a pixel-mask, containing the pixels that were rejected by the multiple processes
import matplotlib.pyplot as plt
fig, axis = plt.subplots()
for frameID in data.get_valid_frameIDS():
wave, flux, err, mask = data.get_frame_OBS_order(frameID=frameID,
order=50,
)
good_pixel_mask = ~mask
axis.scatter(wave[good_pixel_mask], flux[good_pixel_mask], s=5)
axis.set_xlabel(r"wavelength $[\AA]$")
axis.set_ylabel("Flux")
Text(0, 0.5, 'Flux')