specsr.linefit¶
Gaussian emission-line fitting, and the S/N derived from it.
Fits a Gaussian on a linear continuum in a window around each expected line and reports amplitude over continuum scatter. This is the measurement behind the paper’s S/N figure.
The continuum scatter is estimated from sidebands — an annulus around the line, excluding its core — rather than from the whole window. Using the window would fold the line itself into the noise estimate and depress the S/N of exactly the strong lines the figure is about.
Note what this quantity is and is not: it references only the spectrum being
measured, never the HR truth, so a high S/N means “a confident detection of
something”, not “the right line flux”. Establishing that a line is correct
needs the reference, which is why
specsr.plotting.plot_line_flux_comparison() exists alongside it. That
figure takes its fluxes from this same fit (measure_line_fluxes()).
Functions
|
Joint fit of H-beta and the [O III] doublet: three Gaussians, one width. |
|
Fit one line. |
|
Gaussian on a linear continuum. |
|
Integrated flux of the fitted Gaussian, |
|
|
|
Robust scatter via MAD, NaN-aware. |
|
Per-line Gaussian-fit flux and S/N for several spectrum sets. |
|
Per-line S/N for several spectrum sets over the same objects. |
- specsr.linefit.fit_hbeta_oiii(wavelength, flux, z, *, window_kms=20000.0, sigma_lo_kms=40.0, sigma_hi_kms=3000.0)[source]¶
Joint fit of H-beta and the [O III] doublet: three Gaussians, one width.
A single Gaussian cannot measure these lines at prism resolution. Centred on H-beta it widens until it holds the [O III] lines as well (fitted sigma ~8000 km/s for half the sample, and ten times the true flux); centred on 5007 it absorbs 4959 and reads a third high. Fitting the three together at fixed centres with a shared width assigns the blended flux to the right line. It is the model
scripts/doublet_deblending.pyuses for the doublet ratio, over a wider window so that the prism’s H-beta wing and the continuum beyond it are inside the fit.The fit runs in velocity about the doublet midpoint, with amplitudes bounded non-negative, for the reasons given there.
Returns
{"amp": (A_hb, A_4959, A_5007), "sigma_um": (...), "sigma_kms": float}, with eachsigma_umthe shared velocity width at that line’s wavelength, orNonewhen the lines fall off the grid or the fit fails.
- specsr.linefit.fit_line_sideband_weighted(x, y, mu0, *, fit_halfwin=0.25, core_halfwin=0.05, sb_gap=0.03, sb_width=0.12, sigma_bounds=(0.001, 0.12), mu_bounds_half=0.01, allow_negative_amp=True, maxfev=40000)[source]¶
Fit one line. Returns a dict of parameters, or
Noneif unfittable.Negative amplitudes are allowed by default: forcing positivity would turn a non-detection into a small positive bump and manufacture signal where there is none.
- specsr.linefit.line_flux_from_fit(fit)[source]¶
Integrated flux of the fitted Gaussian,
sqrt(2 pi) * amp * sigma.In the units of flux times wavelength of the spectrum that was fitted, and NaN for a failed fit. A negative amplitude gives a negative flux: it is a measurement of no emission, and is left to the caller to count.
- specsr.linefit.line_snr_from_fit(fit)[source]¶
(amp/sigma_cont, amp/amp_err)from a fit, or(nan, nan).
- specsr.linefit.mad_sigma(y)[source]¶
Robust scatter via MAD, NaN-aware. NaN when there is too little data.
- specsr.linefit.measure_line_fluxes(wavelength, z, spectra, scales, lines_rest_um, line_names=None, **fit_kw)[source]¶
Per-line Gaussian-fit flux and S/N for several spectrum sets.
The flux counterpart of
measure_line_snr(), from the same fit, so the flux of a line and its S/N are two readings of one measurement.- Parameters:
spectra –
{"LR": array, "SR": array, "HR": array, ...}, each(n, n_lambda), in the normalised flux the fit’s starting values and bounds are tuned for.scales –
{kind: (n,) array}, the per-spectrum factor that turns each set’s normalised flux back into physical flux density. An additive offset needs no undoing: the fit carries its own continuum.
- Returns:
{f"{line}_{quantity}_{kind}": array}for the quantitiesflux(physical flux density times the wavelength unit),
sn,sigmaandmu(both in the wavelength unit). NaN where a line falls off the gridor the fit fails.
- specsr.linefit.measure_line_snr(wavelength, z, spectra, lines_rest_um, line_names=None, **fit_kw)[source]¶
Per-line S/N for several spectrum sets over the same objects.
- Parameters:
spectra –
{"LR": array, "SR": array, "HR": array, ...}, each(n, n_lambda).lines_rest_um – Rest wavelengths, microns. Redshifted per object with
z.
- Returns:
{f"{line}_sn_{kind}": array}with NaN where a line falls off the grid orthe fit fails — left as NaN rather than zero, since “not measurable” and
”measured as zero” are different statements.