Spectral weighting (wcc_etc.spectral)

Source-weighted spectral quantities that set the wavelength(s) a PSF is rendered at. See The wavelength the PSF is rendered at for the physics and the size of the effect.

Source-weighted spectral quantities that set the wavelength(s) a PSF is rendered at.

The diffraction scale is linear in wavelength, so the wavelength used to render a PSF has to reflect the source as well as the bandpass. The pivot wavelength (Sensor.wavelength) is a property of the throughput curve alone: it is the same 582 nm for an O5V and an M5V star observed through the WCC broad band, even though the photons those two stars actually deliver through that band average 541 nm and 716 nm respectively. This module supplies the photon-weighted alternatives:

All integrals use scipy.integrate.trapezoid(); numpy.trapz is gone in numpy 2.x, which is what CI runs.

wcc_etc.spectral.photon_weights(bandpass, spectrum=None, wave=None)[source]

Photon weight S(lambda) T(lambda) on a common wavelength grid.

The weights are returned unnormalized – every consumer here divides by its own integral, so the absolute scale (and hence the source magnitude) drops out. That is why callers can pass an un-normalized spectrum.

Parameters:
  • bandpass (SpectralElement) – Total throughput.

  • spectrum (SourceSpectrum, optional) – Source spectrum. None means “flat in photons”, which reduces the weighting to the throughput curve alone.

  • wave (Quantity or array_like, optional) – Wavelength grid (Angstrom if unitless). Defaults to build_waveset().

Returns:

  • wave (Quantity) – The wavelength grid.

  • weight (ndarray) – S(lambda) * T(lambda), clipped at zero.

Raises:

ValueError – If the bandpass and spectrum have no wavelength where the product is positive.

wcc_etc.spectral.effective_wavelength(bandpass, spectrum=None, wave=None)[source]

Photon-weighted effective wavelength of a bandpass times a source SED.

lambda_eff = int(lambda S T dlambda) / int(S T dlambda), with S the source photon flux density and T the total throughput. This is the wavelength to render a monochromatic PSF at: unlike the pivot wavelength it moves with the source colour, and the Airy scale is linear in wavelength.

Parameters:
  • bandpass (SpectralElement) – Total throughput.

  • spectrum (SourceSpectrum, optional) – Source spectrum. None gives the throughput-weighted average wavelength (avgwave), not the pivot wavelength.

  • wave (Quantity or array_like, optional) – Wavelength grid. Defaults to build_waveset().

Returns:

The effective wavelength, in nm.

Return type:

Quantity

Examples

Through the WCC broad band the same filter gives very different effective wavelengths for an O5V and an M5V source (541 nm vs 716 nm), while the pivot wavelength is 582 nm for both.

wcc_etc.spectral.photon_weighted_subbands(bandpass, spectrum=None, n_sub=7, wave=None)[source]

Split a band into n_sub sub-bands of equal photon weight.

Each sub-band contributes one render wavelength (its photon-weighted centroid) and one coadd weight (its share of the in-band photons). The sub-band edges are placed at equal quantiles of the cumulative photon weight, so samples cluster where the source actually delivers light rather than being spread evenly over a filter’s dead tails. The weights therefore come out close to 1/n_sub each, which also means no render is wasted on a negligible sub-band.

n_sub=1 reduces exactly to effective_wavelength() with weight 1.

Parameters:
  • bandpass (SpectralElement) – Total throughput.

  • spectrum (SourceSpectrum, optional) – Source spectrum; None weights by throughput alone.

  • n_sub (int, optional) – Number of sub-bands. 5-9 is enough for a broad optical band; the cost of a polychromatic PSF is linear in this. Default 7.

  • wave (Quantity or array_like, optional) – Wavelength grid. Defaults to build_waveset().

Returns:

  • wavelengths (Quantity) – n_sub increasing sub-band centroids, in nm.

  • weights (ndarray) – n_sub coadd weights summing to 1.