Source Building

Tools for constructing polychromatic source dictionaries to pass to calc_psf(source=...).


build_polychromatic_star

from psfcraft.utils import build_polychromatic_star

Builds a flux-weighted spectral source using Planck's black-body law. No external dependencies required.

Example:

from psfcraft.utils import build_polychromatic_star
import psfcraft

# G-star (5800 K) sampled at 7 wavelengths across the J band
src = build_polychromatic_star(temperature=5800, filter_name="J", sampling=7)

print(src["wavelengths"] * 1e6)   # wavelengths in µm
print(src["weights"])             # spectral flux (relative)

tel = psfcraft.NewtonianTelescope(version="1_3")
psf = tel.calc_psf(source=src, fov_pixels=64)

Supported filters:

filter_name Band Wavelength range
"Y" Y band 950 – 1212 nm
"J" J band 1168 – 1567 nm
"H" H band 1522 – 2021 nm

build_polychromatic_star

build_polychromatic_star(temperature: float, filter_name: str, sampling: int) -> dict

Builds a polychromatic star model using a black body spectrum.

Uses Planck's law directly (via astropy constants) — no pysynphot required.

Parameters:
  • temperature (float) –

    The temperature of the star in Kelvin.

  • filter_name (str) –

    Name of the photometric filter used to determine wavelength bounds.

  • sampling (int) –

    Number of wavelength samples within the filter bandpass.

Returns:
  • dict( dict ) –

    Dictionary with keys wavelengths (array, metres) and weights (array, spectral flux density from a black-body at temperature).

Source code in psfcraft/utils.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
def build_polychromatic_star(temperature: float, filter_name: str, sampling: int) -> dict:
    """
    Builds a polychromatic star model using a black body spectrum.

    Uses Planck's law directly (via astropy constants) — no pysynphot required.

    Args:
        temperature (float): The temperature of the star in Kelvin.
        filter_name (str): Name of the photometric filter used to determine wavelength bounds.
        sampling (int): Number of wavelength samples within the filter bandpass.

    Returns:
        dict: Dictionary with keys ``wavelengths`` (array, metres) and ``weights``
            (array, spectral flux density from a black-body at *temperature*).
    """
    bounds = get_filter_bounds(filter_name)
    # bounds are in nm → convert to metres
    wavelengths_m = np.linspace(bounds[0], bounds[1], sampling) * 1e-9
    weights = _planck_law(wavelengths_m, temperature)
    return {'wavelengths': wavelengths_m, 'weights': weights}

Filter constants

from psfcraft import constants as csts

print(csts.FILTER_Y_CUTS)   # [950, 1212]  (nm)
print(csts.FILTER_J_CUTS)   # [1168, 1567] (nm)
print(csts.FILTER_H_CUTS)   # [1522, 2021] (nm)

constants