solprop.processing.spectra#
Spectral post-processing: instrument resolution and explicit bandpass windows.
Two operations that belong to the spectrum rather than to the accessor that fetched it: smoothing a spectral energy density to the resolution of a real instrument, and building the Planck-tapered window of a wavelength bandpass.
Neither is ever applied on its own. A window is a keyword, it is a wavelength range, and the array it produces is returned to the caller to multiply; no window adjusts its own limits as a side channel.
Module Attributes
A wavelength range to taper between, or a ready-made window on the stored axis. |
|
Widest default bandpass edge, in frequency bins (Luna's |
|
Widest default bandpass edge as a fraction of the pass band's angular width. |
Functions
|
Return a Planck-tapered bandpass window on the stored frequency axis. |
|
Smooth a spectral density to an instrument resolution on a uniform axis. |
- solprop.processing.spectra.Bandpass = tuple[float, float] | jaxtyping.Float[ndarray, 'n_omega']#
A wavelength range to taper between, or a ready-made window on the stored axis.
- solprop.processing.spectra.DEFAULT_BANDPASS_BINS = 64#
Widest default bandpass edge, in frequency bins (Luna’s
winwidth = :auto).
- solprop.processing.spectra.DEFAULT_BANDPASS_FRACTION = 0.25#
Widest default bandpass edge as a fraction of the pass band’s angular width.
Each Planck edge is antisymmetric about its midpoint, so it transmits half its width: a window with edges
ftimes the band’s width has an integrated width1 + ftimes the band’s. A quarter keeps that excess to 25 % while each edge still spans a quarter of the band, so the window stays smooth on the band’s own scale; and it leaves every band wider than64 / 0.25 = 256bins on the 64-bin edge it always had.
- solprop.processing.spectra.bandpass(grid, wavelength_limits, *, width=None)[source]#
Return a Planck-tapered bandpass window on the stored frequency axis.
The window is one inside the wavelength range and zero outside it, joined on each side by a Planck taper of the given width in angular frequency. The default edge is the narrower of
DEFAULT_BANDPASS_BINS(64) bin spacings andDEFAULT_BANDPASS_FRACTION(a quarter) of the pass band’s angular width, so a narrow band on a short time window is not swamped by edges wider than itself. It is returned rather than applied, because nothing insolprop.processingwindows a spectrum unless it was asked to.- Parameters:
- gridsolprop.grid.TimeGrid
The grid whose
omegaaxis the window is built on.- wavelength_limitstuple of float
The pass band, m, in either order.
- widthfloat or None
Width of each taper edge, rad/s;
Nonegives the smaller of 64 bin spacings and a quarter of the pass band’s angular width.
- Returns:
- numpy.ndarray
Window values in
[0, 1], shape(n_omega,), in storage order.
- Raises:
- solprop.exceptions.ProcessingError
If a limit is not positive, or the width is not positive – including the default width of an empty pass band (equal limits).
Examples
>>> import numpy as np >>> from solprop.processing._examples import example_grid >>> from solprop.processing.spectra import bandpass >>> grid = example_grid() >>> window = bandpass(grid, (700e-9, 900e-9)) >>> float(window.max()), float(window.min()) (1.0, 0.0)
- solprop.processing.spectra.specres(x, density, resolution, *, weights=None, spec_range=None, samples=10)[source]#
Smooth a spectral density to an instrument resolution on a uniform axis.
The output axis is uniform with
samplespoints per resolution element, and each input bin is spread over it by a unit-area Gaussian whose full width at half maximum isresolution, weighted by the width of the bin it came from:S_out(x_j) = sum_k S(x_k) w_k G(x_j - x_k).Because the kernel integrates to one, the integral of the density – the energy – is preserved to round-off wherever the signal is well inside the range. The input axis need not be uniform, which is what makes this work directly on a wavelength axis derived from a uniform frequency grid: pass the bin widths as
weights.Non-positive output values are not replaced with the smallest positive one to keep a logarithmic plot away from zero: that would change the data.
- Parameters:
- xnumpy.ndarray
Input abscissa, shape
(n_x,), strictly increasing.- densitynumpy.ndarray
Spectral density on that abscissa, shape
(..., n_x), per unit ofx.- resolutionfloat
Instrument resolution as a full width at half maximum, in the units of
x.- weightsnumpy.ndarray or None
Integration measure of each input bin, in the units of
x;Noneuses the central differences ofx.- spec_rangetuple of float or None
Limits of the output axis, clipped to the range of
x;Noneuses all of it.- samplesint
Output points per resolution element, at least one.
- Returns:
- x_outnumpy.ndarray
Uniform output abscissa, shape
(n_out,).- density_outnumpy.ndarray
The smoothed density, shape
(..., n_out).
- Raises:
- solprop.exceptions.ProcessingError
If the resolution or the sampling is not positive, if
xdoes not increase, or if the requested range does not overlap the data.
Examples
>>> import numpy as np >>> from solprop.processing.spectra import specres >>> x = np.linspace(400e-9, 1200e-9, 2001) >>> density = np.exp(-0.5 * ((x - 800e-9) / 20e-9) ** 2) >>> smooth_x, smooth = specres(x, density, 50e-9) >>> bool(smooth.max() < density.max()) True