Wavelength Calibration¶
Wavelength calibration in PyReduce happens in multiple steps.
Initial Linelist¶
To start the wavelength calibration we need an initial guess. PyReduce provides
initial guess files in the wavecal directory for supported instruments and modes.
These files are numpy .npz archives containing a recarray with the key cs_lines:
Column |
Type |
Description |
|---|---|---|
|
float64 |
Wavelength (before fit) |
|
float64 |
Wavelength (after fit) |
|
float64 |
Pixel position (before fit) |
|
float64 |
Pixel position (after fit) |
|
int16 |
First pixel of the line |
|
int16 |
Last pixel of the line |
|
float64 |
Width of the line in pixels |
|
float64 |
Relative strength of the line |
|
int16 |
Echelle order the line is found in |
|
bool |
Whether to use the line |
If such a file is not available, or you want to create a new one, it is possible to do so based on a rough initial guess of the wavelength ranges of each order and a reference atlas of known spectral lines for the calibration lamp.
Creating a New Linelist¶
Create the master wavelength calibration spectrum by running the
wavecal_masterstepUse the
wavecal_creator.pyscript in tools to create the linelist, providing rough wavelength guesses (uncertainties up to 20 Angstrom are allowed)
Alternatively, run the wavecal_init step in PyReduce if the instrument provides
the correct initial wavelength guess via the get_wavelength_range function.
The initial line identification detects peaks in the observed spectrum, matches them
to atlas lines using offset voting and iterative polynomial fitting with outlier
rejection. The created linelist should be saved to the location provided by
get_wavecal_filename so wavecal_init only needs to run once.
Spectral Order Numbers¶
PyReduce uses physical spectral order numbers (m) in wavelength calibration. Understanding
how these are assigned is important because the 2D wavelength polynomial depends on them.
What is the Order Number?¶
In echelle spectrographs, light is dispersed by a grating where different wavelengths
satisfy the grating equation at different diffraction orders. The order number m is
this physical diffraction order. Higher orders correspond to shorter wavelengths.
How Order Numbers are Assigned¶
Order numbers are assigned to traces in one of three ways:
From
order_centers.yaml(preferred for new instruments):Instruments can provide a file listing known order centers and their order numbers. During trace detection, detected traces are matched to these centers by y-position and assigned the corresponding order number immediately.
# Example: pyreduce/instruments/ANDES_RIZ/order_centers_r.yaml # Y-position of center fiber at detector center 81: 8371.1 # Order 81 centered at y=8371.1 82: 7772.6 83: 7194.3 ...
From the initial linelist (wavecal_init step):
If no order_centers file exists, traces start with
m = None. The initial linelist file (e.g.,wavecal_middle.npz) contains anobasevalue - the order number of the first trace. Duringwavecalstep, each trace is assignedm = obase + index.Sequential fallback:
For legacy files or modes like MOSAIC where orders cannot be identified,
mmay remain None or be assigned sequentially from 0.
Why Order Numbers Matter¶
The 2D wavelength polynomial fits wavelength as a function of both pixel position (x) and trace index (idx):
wavelength = P(x, idx) = sum_{i,j} c_{i,j} * x^i * idx^j
Currently the fit uses sequential trace indices (0, 1, 2, …) as the order
coordinate, assigned per group. Each trace stores its index in _wave_idx.
When you call Trace.wlen(x), it evaluates the 2D polynomial at the trace’s index:
# Inside Trace.wlen():
wavelength = np.polynomial.polynomial.polyval2d(x, self._wave_idx, self.wave)
Physical order numbers (trace.m) are used for identification and matching, but the
polynomial evaluation uses the sequential index because that is what the fit was built
against.
Gas Lamp Calibration¶
For absolute wavelength reference, most spectrometers use gas lamps (e.g., ThAr). These lamps have well-known spectral lines distributed across the detector range.
The calibration process:
Match observation to linelist using cross correlation in both order and pixel directions
Match observed peaks to closest partners in the linelist
Discard peaks further than a cutoff (typically ~100 m/s)
Fit a 2D polynomial between pixel position and wavelength
Use the polynomial to identify additional peaks
Iterate to refine the solution
PyReduce uses a 2D polynomial where the order number is the second coordinate. This works because wavelength derivatives between orders are similar.
Frequency Comb / Fabry-Perot Interferometer¶
Frequency combs and Fabry-Perot interferometers provide superior wavelength calibration by generating dense, evenly-spaced peaks across all wavelengths.
The key property is constant frequency spacing:
f(n) = f0 + n * fr
where:
f0is the anchor frequencyfris the frequency step between peaksnis the peak number
Frequency Comb Process¶
Identify peaks in each order
Estimate wavelengths using the gas lamp solution
Number peaks consistently across orders (single f0 and fr for all peaks)
Use the grating equation (
n * w = const) to correct peak numberingFit f0 and fr using all peaks
Derive wavelengths for each peak
Fit final polynomial for pixel-to-wavelength mapping
The dense peak coverage provides a much better solution than gas lamps alone.
Reference Spectra¶
ThAr (Thorium-Argon)¶
Palmer, B.A. and Engleman, R., Jr., 1983, Atlas of the Thorium Spectrum, Los Alamos National Laboratory
Norlen, G., 1973, Physica Scripta, 8, 249
UNe (Uranium-Neon)¶
Redman S.L. et al., A High-Resolution Atlas of Uranium-Neon in the H Band
Data Flow and File Updates¶
Understanding which files are read and written by each step is important, especially when re-running steps iteratively.
Pipeline flow¶
trace step
└─ creates traces.fits (order positions, no wavelengths yet)
wavecal_master step
└─ reads traces.fits
└─ extracts calibration lamp spectrum per fiber group
└─ writes {prefix}_{group}.wavecal_master.fits
wavecal_init step
└─ reads wavecal_master output
└─ identifies lines by matching peaks to atlas
└─ writes {prefix}_{group}.linelist.npz
wavecal step
└─ reads {prefix}_{group}.linelist.npz (from wavecal_init or previous wavecal run)
└─ reads wavecal_master output
└─ reads traces.fits
└─ aligns, refines positions, fits 2D polynomial
└─ overwrites {prefix}_{group}.linelist.npz with refined linelist
└─ updates traces.fits with wavelength polynomials (Trace.wave, Trace.m)
science step
└─ reads traces.fits (including wavelength polynomials)
└─ extracts spectra; wavelength scale comes from Trace.wlen()
Linelist iterative refinement¶
The wavecal step both reads and overwrites linelist.{group}.npz. This is
intentional: re-running wavecal uses the previously refined linelist as its
starting point, aligns it to the current observation, re-fits line positions,
rejects outliers, and auto-identifies new lines. Each run improves the linelist.
On the first run, the linelist comes from wavecal_init (or from the
instrument’s bundled wavecal_*.npz file). On subsequent runs, wavecal_init
is skipped because the linelist file already exists, and wavecal refines it
further.
Order numbers in the linelist (lines["order"]) are 0-based trace indices.
They are normalized back to 0-based when saving to prevent alignment offsets
from accumulating across runs.
traces.fits lifecycle¶
traces.fits is created by the trace step with order geometry (polynomial
positions, column ranges, slit curvature) but no wavelength information. The
wavecal step then updates the same file, adding:
Trace.wave— wavelength polynomial coefficients (1D or 2D)Trace.m— physical spectral order number
Later steps (science, continuum, finalize) read traces.fits and use
Trace.wlen(x) to evaluate the wavelength polynomial at each pixel. This is
how the extracted science spectra get their wavelength scale.
Step Dependencies¶
wavecal_master -> wavecal_init -> wavecal
| | |
Extract Initial line Refine solution,
calibration identification update traces.fits
spectrum
For instruments with frequency combs:
freq_comb_master -> freq_comb
| |
Extract Apply frequency
comb spectrum comb calibration
The frequency comb steps use the gas lamp solution as a starting point.