galfits.disperser

Module for spectroscopic dispersion modeling, particularly for grism/prism observations.

Disperser Classes

class galfits.disperser.GSDisperser(axeconf, nx, ny, ixmin, iymin, nxs, nys, beam='A', bin=1, convert_to_photos=0, t_area_factor=1)[source]

Bases: object

Grism/Slitless spectroscopy disperser for IFU data cubes.

This class handles the forward modeling of grism/prism observations by dispersing input IFU (Integral Field Unit) data cubes according to instrument-specific dispersion relations and sensitivity curves. It accounts for wavelength-dependent PSF, spectral resolution, and detector response.

Parameters:
  • axeconf (aXeConfBase) – Configuration object containing instrument dispersion and sensitivity information.

  • nx (int) – Total width of the output dispersed image in pixels.

  • ny (int) – Total height of the output dispersed image in pixels.

  • ixmin (int) – Minimum x-coordinate of the input IFU cutout.

  • iymin (int) – Minimum y-coordinate of the input IFU cutout.

  • nxs (int) – Width of the input IFU cutout in pixels.

  • nys (int) – Height of the input IFU cutout in pixels.

  • beam (str, optional) – Spectral order/beam to model (e.g., ‘A’, ‘B’, ‘C’). Default is ‘A’.

  • bin (int, optional) – Binning factor for dispersion calculation (for speed). Default is 1.

  • convert_to_photos (int, optional) – Whether to convert flux to photoelectrons (1) or keep in flux units (0). Default is 0.

  • t_area_factor (float, optional) – Product of exposure time and telescope area for flux-to-counts conversion. Default is 1.

nx, ny

Output image dimensions.

Type:

int

axeconf

Instrument configuration object.

Type:

aXeConfBase

sens_wave

Wavelength grid for sensitivity curve (Angstroms).

Type:

array_like

sens_sens

Sensitivity values in erg/s/cm²/Å per detected count.

Type:

array_like

wave_grid

Wavelength grid for spectral rebinning based on instrument resolution.

Type:

array_like

dy3d, lam3d

3D arrays of trace offsets and wavelengths for each pixel.

Type:

array_like

nxd, nyd

Dimensions of the dispersed spectrum.

Type:

int

dymin, dxmin

Minimum offsets for dispersion geometry.

Type:

int

Notes

The disperser uses JAX for GPU-accelerated dispersion calculation. It performs:

  1. Wavelength-dependent trace calculation

  2. Flux-conserving spectral rebinning to detector resolution

  3. Sensitivity curve application

  4. Conversion to detector counts (if requested)

The class assumes that each spatial pixel in the input IFU can have a different SED, enabling modeling of spatially resolved spectroscopy.

Examples

>>> from galfits.disperser import GSDisperser, aXeConfBase
>>> conf = aXeConfBase('HST_G141')
>>> disperser = GSDisperser(conf, nx=100, ny=100, ixmin=0, iymin=0,
...                          nxs=10, nys=10, beam='A')
>>> wavelength = np.arange(8000, 17000, 10)  # Angstroms
>>> ifu_cube = np.ones((10, 10, len(wavelength)))  # Flat spectrum
>>> dispersed_image = disperser.get_spec_orders(wavelength, ifu_cube)

See also

aXeConfBase

Configuration parser for aXe-format instrument files.

__init__(axeconf, nx, ny, ixmin, iymin, nxs, nys, beam='A', bin=1, convert_to_photos=0, t_area_factor=1)[source]
get_spec_orders(wave, ifu)[source]
class galfits.disperser.aXeConfBase(band='HST_G102')[source]

Bases: object

Configuration parser for aXe-format grism/prism instrument files.

This class reads and parses aXe-style configuration files that describe the dispersion solution, trace geometry, and sensitivity curves for slitless spectroscopy instruments. It provides methods to compute wavelength solutions and trace positions for any location in the detector field of view.

Parameters:

band (str, optional) – Instrument/mode identifier (e.g., ‘HST_G102’, ‘HST_G141’, ‘CSST_GI’). Default is ‘HST_G102’.

conf

Parsed configuration parameters from the .conf file.

Type:

OrderedDict

conf_file

Path to the configuration file.

Type:

str

bandname

Instrument/mode name.

Type:

str

instrument

Instrument identifier.

Type:

str

beams

List of available spectral orders/beams.

Type:

list

dydx_orders, dldp_orders

Polynomial orders for trace and dispersion solutions per beam.

Type:

dict

dydx_corders, dldp_corders

Cross-term polynomial orders per beam.

Type:

dict

dydx_params, dldp_params

Polynomial coefficients for trace and dispersion per beam.

Type:

dict

xoff, yoff

Global coordinate offsets.

Type:

float

Notes

The aXe configuration format defines:

  • Trace solution: dy/dx as a function of position and wavelength offset

  • Dispersion solution: λ as a function of position and pixel offset

  • Sensitivity curves: Instrument throughput vs wavelength

  • Beam geometry: Valid wavelength ranges and pixel offsets

The polynomial solutions typically have the form:

\[f(x, y, \Delta x) = \sum_{i=0}^{N} \left(\sum_{j=0}^{M_i} c_{ij} x^{(M_i-j)} y^j\right) (\Delta x)^i\]

where N is the order and M_i is the cross-term order.

Examples

>>> from galfits.disperser import aXeConfBase
>>> conf = aXeConfBase('HST_G141')
>>> print(conf.beams)
['A', 'B', 'C', 'D', 'E']
>>> sens = conf.get_beam_sens('A')
>>> dx, dy, lam = conf.get_dxdylam(x=512, y=512, beam='A')

See also

GSDisperser

Uses aXeConfBase for forward modeling of dispersed spectra.

References

__init__(band='HST_G102')[source]
get_beam_sens(beam=None)[source]
get_dxdy(*, x, y, beam, force_x_int=False, dydx_params=None, dx=None)[source]
get_dxdylam(x, y, beam, force_x_int=False, dydx_params=None, dldp_params=None, dx=None)[source]
get_dxdylam_3d(xmin, ymin, nx, ny, beam, force_x_int=False, dydx_params=None, dldp_params=None, dx=None, bin=1)[source]
to speed up dispersion,

the output 3d results MUST be in shape of (ny, nx, nlam)

read_conf_file(conf_file)[source]

Helper Functions

galfits.disperser.dispersion_ifu_with_flux_jax(dymin, nxs, nys, nxd, seg, dy3d, lam3d, ifu_wave, ifu_flux, nwave, t_area_factor, sens_wave, sens_sens, nsens, gsimage, convert_to_photo)[source]

JAX-accelerated dispersion of IFU data cube to create grism image.

This function performs the core dispersion calculation, taking an input IFU (Integral Field Unit) data cube with wavelength-dependent flux and dispersing it onto a 2D detector image according to the instrument’s wavelength-dependent trace and sensitivity.

Parameters:
  • dymin (int) – Minimum y-offset for the dispersed spectrum.

  • nxs (int) – Dimensions of the input IFU spatial grid.

  • nys (int) – Dimensions of the input IFU spatial grid.

  • nxd (int) – Number of wavelength pixels in the dispersion direction.

  • seg (array_like) – Segmentation map (not currently used, reserved for future).

  • dy3d (array_like, shape (nys, nxs, nxd)) – 3D array of y-trace offsets for each spatial pixel and wavelength.

  • lam3d (array_like, shape (nys, nxs, nxd)) – 3D array of wavelengths for each spatial pixel and dispersion pixel.

  • ifu_wave (array_like) – Wavelength grid of the input IFU cube (Angstroms).

  • ifu_flux (array_like, shape (nys, nxs, nwave)) – Input IFU flux cube in erg/s/cm²/Å or similar units.

  • nwave (int) – Number of wavelength points in the IFU cube.

  • t_area_factor (float) – Product of exposure time and telescope area for flux-to-counts conversion.

  • sens_wave (array_like) – Wavelength grid for the sensitivity curve (Angstroms).

  • sens_sens (array_like) – Sensitivity curve values (throughput).

  • nsens (int) – Number of points in the sensitivity curve.

  • gsimage (array_like) – Output dispersed image array to be updated.

  • convert_to_photo (int) – If >0, convert flux to photoelectrons.

Returns:

gsimage – Updated dispersed image with flux from all IFU pixels added.

Return type:

array_like

Notes

The dispersion process:

  1. For each spatial pixel in the IFU:

    1. Resample the input spectrum onto the instrument’s wavelength grid

    2. Apply the sensitivity curve

    3. Convert to detector counts (if requested)

    4. Distribute flux along the wavelength-dependent trace

  2. Use linear interpolation between integer pixel positions

The function is JAX-accelerated and can run on GPU for significant speedup on large data cubes.

See also

GSDisperser._disperse_ifu_with_flux

Wrapper function that calls this dispatcher.

galfits.disperser._interp1d_conserve_flux_trapz_sum(x, y, nx, ix, nix, x_bs, ix_bs)[source]

Flux-conserving 1D interpolation using trapezoidal integration (returns integrated flux).

This function performs flux-conserving interpolation from one wavelength grid to another by computing the integrated flux within each output bin. It uses the trapezoidal rule for numerical integration, ensuring total flux is conserved during resampling.

Parameters:
  • x (array_like, shape (nx,)) – Input wavelength/coordinate grid (must be monotonically increasing).

  • y (array_like, shape (nx,)) – Input flux density values (flux per unit wavelength).

  • nx (int) – Number of points in the input grid.

  • ix (array_like, shape (nix,)) – Output wavelength/coordinate grid centers.

  • nix (int) – Number of points in the output grid.

  • x_bs (array_like, shape (nx+1,)) – Workspace array for input bin boundaries (will be computed internally).

  • ix_bs (array_like, shape (nix+1,)) – Workspace array for output bin boundaries (will be computed internally).

Returns:

iy – Integrated flux in each output bin (not flux density). Total integrated flux: sum(iy) ≈ integral of y(x) over overlapping range.

Return type:

array_like, shape (nix,)

Notes

The function:

  1. Computes bin boundaries by averaging adjacent grid points

  2. Uses trapezoidal rule to integrate y(x) within each output bin

  3. Handles edge cases where output bins extend beyond input range (flux=0)

  4. Returns integrated flux, not flux density

This is suitable for resampling spectra when you want to preserve total counts or energy in each bin, such as for detector response modeling.

The algorithm uses JAX control flow (lax.while_loop, lax.fori_loop) for JIT compilation and GPU acceleration.

See also

_interp1d_conserve_flux_trapz_nosum

Returns flux density instead of integrated flux.

_interp1d_conserve_flux_trapz_sum_rewritten

Alternative implementation without loops.

galfits.disperser._interp1d_conserve_flux_trapz_nosum(x, y, nx, ix, nix, x_bs, ix_bs)[source]

Flux-conserving 1D interpolation using trapezoidal integration (returns flux density).

Similar to _interp1d_conserve_flux_trapz_sum, but returns flux density (flux per unit wavelength) rather than integrated flux. This is appropriate for resampling spectral energy distributions where you want to preserve the shape of the spectrum.

Parameters:
  • x (array_like, shape (nx,)) – Input wavelength/coordinate grid (must be monotonically increasing).

  • y (array_like, shape (nx,)) – Input flux density values (flux per unit wavelength).

  • nx (int) – Number of points in the input grid.

  • ix (array_like, shape (nix,)) – Output wavelength/coordinate grid centers.

  • nix (int) – Number of points in the output grid.

  • x_bs (array_like, shape (nx+1,)) – Workspace array for input bin boundaries (computed internally).

  • ix_bs (array_like, shape (nix+1,)) – Workspace array for output bin boundaries (computed internally).

Returns:

iy – Flux density at each output bin center (flux per unit wavelength). Computed as integrated flux divided by bin width.

Return type:

array_like, shape (nix,)

Notes

The relationship between this function and _interp1d_conserve_flux_trapz_sum:

\[y_{density}[i] = \frac{\int_{\lambda_{i,left}}^{\lambda_{i,right}} y(\lambda) d\lambda}{\lambda_{i,right} - \lambda_{i,left}}\]

This preserves the spectral energy distribution shape while allowing different wavelength samplings. Total flux is conserved when comparing integrals over the same wavelength range.

Uses JAX control flow for JIT compilation and GPU acceleration.

See also

_interp1d_conserve_flux_trapz_sum

Returns integrated flux instead of density.

_interp1d_conserve_flux_trapz_nosum_rewritten

Alternative implementation.

galfits.disperser._interp1d_conserve_flux_trapz_nosum_rewritten(x, y, nx, ix, nix, x_bs, ix_bs)[source]

Flux-conserving interpolation using trapezoidal rule, rewritten without dynamic loops. :param x: Input grid points (sorted, shape: [nx]) :param y: Input values (shape: [nx]) :param nx: Number of x points :param ix: Output grid points (sorted, shape: [nix]) :param nix: Number of ix points :param x_bs: Unused boundary array for x (shape: [nx + 1]) :param ix_bs: Unused boundary array for ix (shape: [nix + 1])

Returns:

Interpolated values (shape: [nix])

Return type:

iy

galfits.disperser._interp1d_conserve_flux_trapz_sum_rewritten(x, y, nx, ix, nix, x_bs, ix_bs)[source]

Flux-conserving interpolation using trapezoidal rule, rewritten without dynamic loops. Computes the integral over each bin [ix_bs[k], ix_bs[k+1]] ∩ [x[0], x[nx-1]].

Parameters:
  • x – Input grid points (sorted, shape: [nx])

  • y – Input values (shape: [nx])

  • nx – Number of x points

  • ix – Output grid points (sorted, shape: [nix])

  • nix – Number of ix points

  • x_bs – Unused boundary array for x (shape: [nx + 1])

  • ix_bs – Unused boundary array for ix (shape: [nix + 1])

Returns:

Integrated values over each bin (shape: [nix])

Return type:

iy