Reference / API reference / dorothy / dorothy.data / dorothy.data.fits_loader
dorothy.data.fits_loader¶
Load stellar spectra and labels from FITS files, and preprocess spectra.
FITSLoader reads FITS files with DESI, BOSS or LAMOST spectra
cross-matched with APOGEE stellar parameters. The preprocessing functions
(zero_invalid_pixels(), normalize_spectra(),
encode_precision()) are shared with the catalogue loaders.
- Expected FITS file structure:
APOGEE extension: Table with stellar parameters and quality flags
SPECTRA extension: Table with flux arrays for each star
SPEC_IVAR extension: Table with inverse variance arrays
WAVELENGTH extension: Table with wavelength grid
The loader normalizes spectra using median/IQR normalization per-star
and creates the 3-channel input format (flux, sigma, mask) of
SpectralData.get_model_input_3channel().
Functions
|
Create a quality mask based on physical bounds and valid values. |
|
Replace the sigma channel of model inputs with the precision encoding. |
|
Convert inverse variance to error (sigma) and mask. |
|
Per-spectrum median/IQR normalization over valid pixels. |
|
Normalize a single spectrum using median/IQR scaling. |
|
Set the flux and ivar of invalid pixels to 0. |
Classes
|
Loader for FITS files containing stellar spectra and parameters. |
|
Container for loaded spectral data. |
- class dorothy.data.fits_loader.SpectralData(flux, ivar, wavelength, labels, errors, ids, quality_mask, parameter_names=<factory>, spectral_mask=None, spectral_error=None)[source]¶
Bases:
objectContainer for loaded spectral data.
- flux¶
Flux of shape (n_samples, n_wavelengths), normalized if requested, and 0 at invalid pixels (
zero_invalid_pixels()).
- ivar¶
Inverse variance with the same shape, scaled with the flux, and 0 at invalid pixels.
- wavelength¶
Wavelength grid of shape (n_wavelengths,).
- labels¶
Stellar parameter labels of shape (n_samples, n_parameters).
- errors¶
Label uncertainties of shape (n_samples, n_parameters).
- ids¶
Star identifiers (e.g., APOGEE_ID) of length n_samples.
- quality_mask¶
Boolean mask where True = good quality (for samples).
- parameter_names¶
List of parameter names in order.
- spectral_mask¶
Binary mask where 1=valid, 0=masked (per wavelength). Shape is (n_samples, n_wavelengths). Derived from ivar > 0.
- spectral_error¶
Error array (sigma) converted from ivar. Shape is (n_samples, n_wavelengths). Computed as 1/sqrt(ivar).
- property n_samples: int¶
Number of spectra in the dataset.
- property n_wavelengths: int¶
Number of wavelength bins.
- property n_parameters: int¶
Number of stellar parameters.
- get_model_input_3channel(apply_quality_mask=True)[source]¶
Get combined flux/error/mask array for model input (3-channel format).
This format is consistent with label format [values | errors] and includes an explicit mask channel for handling missing data and dynamic block masking augmentation.
- Parameters:
apply_quality_mask (bool) – Whether to filter by sample quality mask.
- Returns:
Array of shape (n_samples, 3, n_wavelengths) containing –
Channel 0: Normalized flux (masked wavelengths → 0)
Channel 1: Error (sigma, converted from ivar, masked → 0)
Channel 2: Mask (1=valid, 0=masked)
- Raises:
ValueError – If spectral_mask or spectral_error are not available.
- Return type:
NDArray[float32]
- dorothy.data.fits_loader.zero_invalid_pixels(flux, ivar, inplace=False)[source]¶
Set the flux and ivar of invalid pixels to 0.
A pixel is valid when its flux is finite and its ivar is finite and positive. Every loading path applies this rule before it builds the model inputs (
normalize_spectra()applies it first), so the mask ivar > 0 marks exactly the valid pixels and a masked pixel enters the model as zeros.- Parameters:
flux (NDArray) – Flux array of shape (n_spectra, n_wavelengths) or (n_wavelengths,).
ivar (NDArray) – Inverse variance array with the same shape as flux.
inplace (bool) – Write the results into
fluxandivar(must be float32 arrays) instead of allocating new ones.
- Returns:
Tuple of (flux, ivar), float32, same shape as input.
- Raises:
ValueError – If flux and ivar differ in shape, or
inplaceis set and they are not float32.- Return type:
tuple[NDArray[float32], NDArray[float32]]
- dorothy.data.fits_loader.normalize_spectra(flux, ivar, chunk_size=4096, inplace=False)[source]¶
Per-spectrum median/IQR normalization over valid pixels.
For each spectrum (row):
normalized_flux = (flux - median) / IQR scaled_ivar = IQR^2 * ivar
where the median and IQR are computed over valid pixels only (finite flux, finite and positive ivar). Invalid pixels are returned with flux = 0 and ivar = 0 (
zero_invalid_pixels()), so downstream code that derives the pixel mask from ivar > 0 treats them as masked. So are pixels whose normalized flux or scaled ivar overflows to infinity. A spectrum with no valid pixels uses median = 0 and IQR = 1; one with zero IQR uses IQR = 1.- Parameters:
flux (NDArray) – Flux array of shape (n_spectra, n_wavelengths) or (n_wavelengths,).
ivar (NDArray) – Inverse variance array with the same shape as flux.
chunk_size (int) – Number of spectra processed at once (bounds peak memory).
inplace (bool) – Write the results into
fluxandivar(must be float32 arrays) instead of allocating new ones.
- Returns:
Tuple of (normalized_flux, scaled_ivar), float32, same shape as input.
- Raises:
ValueError – If flux and ivar differ in shape, or
inplaceis set and they are not float32.- Return type:
tuple[NDArray[float32], NDArray[float32]]
- dorothy.data.fits_loader.encode_precision(spectra, inplace=False)[source]¶
Replace the sigma channel of model inputs with the precision encoding.
For each pixel with uncertainty sigma and mask m:
rho = log(1 + 1/sigma) if m > 0, else 0
Flux and mask are unchanged. rho falls to 0 as sigma grows, so a pixel without information reads like a masked one. Apply it after
zero_invalid_pixels()andnormalize_spectra(), which rescales sigma. A valid pixel needs sigma > 0; a masked pixel may hold any value, including NaN.- Parameters:
spectra (NDArray) – Model inputs of shape (N, 3, n_wavelengths) = [flux, sigma, mask].
inplace (bool) – Write the result into
spectra(must be float32) instead of a new array.
- Returns:
Float32 array of shape (N, 3, n_wavelengths) = [flux, rho, mask].
- Raises:
ValueError – If
spectradoes not have shape (N, 3, n_wavelengths), has sigma <= 0 or NaN at a valid pixel, orinplaceis set and it is not float32.- Return type:
NDArray[float32]
- dorothy.data.fits_loader.normalize_spectrum(flux, ivar)[source]¶
Normalize a single spectrum using median/IQR scaling.
Calls
normalize_spectra()on one spectrum.- Parameters:
flux (NDArray) – Flux array of shape (n_wavelengths,).
ivar (NDArray) – Inverse variance array of shape (n_wavelengths,).
- Returns:
Tuple of (normalized_flux, scaled_ivar), float32.
- Raises:
ValueError – If flux and ivar differ in shape.
- Return type:
tuple[NDArray, NDArray]
- dorothy.data.fits_loader.ivar_to_error_and_mask(ivar)[source]¶
Convert inverse variance to error (sigma) and mask.
- Parameters:
ivar (NDArray[float32]) – Inverse variance array of shape (n_wavelengths,) or (n_samples, n_wavelengths). Can contain NaN, Inf, or <= 0 values indicating invalid data.
- Returns:
Tuple of (error, mask) where –
error: Standard deviation (sigma = 1/sqrt(ivar)) where valid, else 0
mask: Binary mask (1=valid, 0=masked)
- Return type:
tuple[NDArray[float32], NDArray[float32]]
- dorothy.data.fits_loader.apply_quality_filter(labels, errors, parameter_names)[source]¶
Create a quality mask based on physical bounds and valid values.
A star passes if, for every parameter, the value and error are finite, the error is positive, the value lies within
PARAMETER_BOUNDS(if the parameter has bounds) and the value is nonzero (exceptfe_h).- Parameters:
labels (NDArray) – Array of shape (n_samples, n_parameters).
errors (NDArray) – Array of shape (n_samples, n_parameters).
parameter_names (list[str]) – Parameter name of each column.
- Returns:
Boolean mask of shape (n_samples,) where True = good quality.
- Return type:
NDArray[bool]
- class dorothy.data.fits_loader.FITSLoader(fits_path, parameters=None)[source]¶
Bases:
objectLoader for FITS files containing stellar spectra and parameters.
Reads FITS files in the DOROTHY format, normalizes spectra and computes a quality mask from the label values and the APOGEE
ASPCAPFLAGbits.- fits_path¶
Path to the FITS file.
- parameters¶
List of stellar parameter names to load.
Examples
>>> loader = FITSLoader(Path("data/loa_trainingset.fits")) >>> data = loader.load() >>> X = data.get_model_input_3channel() # (n_good_stars, 3, n_wavelengths) >>> y = data.get_labels() # (n_good_stars, n_parameters)
- load(apply_normalization=True, apply_quality_filter=True, compute_spectral_mask=False, require_labels=True)[source]¶
Load spectral data from the FITS file.
- Parameters:
apply_normalization (bool) – Whether to normalize spectra (recommended). Either way, invalid pixels get flux 0 and ivar 0.
apply_quality_filter (bool) – Whether to compute quality mask.
compute_spectral_mask (bool) – Whether to compute spectral_mask and spectral_error from ivar. Required for 3-channel format.
require_labels (bool) – Require an APOGEE extension with all label columns. When False (e.g. for prediction), missing labels are returned as NaN and the quality mask keeps every spectrum.
- Returns:
SpectralData object containing all loaded data.
idscome from the APOGEE_ID or TARGET_ID column; without an APOGEE extension, from the first column of a GAIA_ID extension; else they are the row numbers.wavelengthisarange(n_wavelengths)without a WAVELENGTH extension.- Raises:
FileNotFoundError – If FITS file doesn’t exist.
ValueError – If a required extension is missing, or, with require_labels, the APOGEE extension or a parameter’s columns are missing.
- Return type: