IFUL: Integral Field Unit Lensing

Tests Status PyPI version Python Versions Python Versions Documentation Status

A Python pipeline for joint-modeling and simulation of strong gravitational lensing and their source kinematics.

_images/animation_iful_final.gif

Strong gravitational lensing is a cornerstone probe of observational cosmology—enabling independent measurements of the Hubble constant (\(H_0\)) to break the Hubble tension via time-delay cosmography, constraining the dark energy equation-of-state (\(w\)) and matter density (\(\Omega_{\rm m, 0}\)) via compound lensing systems, and probing dark matter substructure and high-redshift galaxy structures. All of these cosmological and astrophysical applications fundamentally depend on the ability to precisely and accurately model the lensing mass distribution.

IFUL (Integral Field Unit Lensing) introduces an end-to-end forward-modeling framework that incorporates the spatially resolved dynamics of the source galaxy directly into the macro lens model. Observed with modern Integral Field Spectroscopy instruments (e.g., JWST NIRSpec, VLT MUSE, Keck KCWI/KCRM, and OSIRIS), IFUL forward-models every individual spatial pixel (spaxel) in the 3D IFU datacube from a joint parameterization of:

  • Macro Lens Mass & Light Profiles (via lenstronomy, or binned profiles),

  • Source Line-of-Sight Velocity Fields (\(v_{\mathrm{los}}\)) (Arctan, Tanh, Multi-parameter, or binned profiles),

  • Source Velocity Dispersion Fields (\(\sigma_v\)) (Exponential, constant, Keplerian, or binned profiles).

By leveraging dynamical markers within lensed arcs as additional kinematic constraints, isolating source emission line light to completely remove lens-light contamination, and reconstructing unlensed source dynamics across multiple lensed images, IFUL provides tighter constraints on lens mass profiles, profile slopes, and high-redshift source dynamics than imaging data alone.


Key Features

  • Joint Lensing & Kinematics Modeling: Simultaneously model 2D image-plane lensing light/mass distributions and 3D IFU datacube velocity and dispersion fields.

  • Flexible Kinematic Profiles: Support for standard kinematic models including Arctan velocity curves, Tanh profiles, multi-parameter profiles, central supermassive black hole (BH) influence, and custom dispersion profiles.

  • Datacube Processing (ImageSet): Built-in continuum subtraction, outlier rejection (IQR), custom aperture masking, white-light image collapse, and noise estimation.

  • Fast Linear Inversion: Accelerated linear solver for source plane flux maps to reduce MCMC/optimization overhead.

  • Simulation API (simulation_api): Easily generate mock JWST NIRSpec or ground-based IFU lensed galaxy datacubes with realistic PSF convolution and instrument noise for mock challenges and forecast studies.

  • Power Binning Support: Integrated adaptive Power spatial binning (an improvement to traditional Voronoi binning) using powerbin.


See Installation for install instructions.

Quickstart Example

Here is a quick example creating a mock lensed IFU datacube and configuring the lensing and kinematics models:

import numpy as np
from iful.util import *
from iful.simulation_api import (
    SimulationMockImageSet, 
    create_simulation_models, 
    run_galaxy_simulation, 
    add_instrument_noise,
    export_to_fits
)

psf_path = "path/to/psf"
zs = 3.8

imset = SimulationMockImageSet(
    size=40,
    pixscale_arcsec=0.075,
    zs=zs,
    wavelengths_full=np.linspace(23650.0 - 300, 24250.0 + 300, 120),
    psf_path=psf_path
)
imset.restwave_peaks = [4959.0, 5007.0]
# parameters format: [z, sigma_ang, amp_0, ratio (5007/4959 = 3.0)]
imset.init_spec_fit = np.array([zs, 24.0, 1.0, 3.0])

# Setup FlatModel and IFULModel from simulation API
fm, ifulmodel = create_simulation_models(
    imset,
    theta_E=1.0,
    source_x=-0.01,
    source_y=-0.01,
    iful_profiles=["ARCTAN", "EXPONENTIAL", "SERSIC"]
)

# Extract parameters
sim_params = [
    # EPL_Q_PHI (6 params): theta_E, gamma, q, phi, center_x, center_y
    1., 1.8, 0.75, 0.5, -0.1, -0.1,
    # SHEAR (2 params): gamma1, gamma2
    0.05, -0.05,
    # Source (6 params): R_sersic, n_sersic, e1, e2, center_x, center_y
    0.3, 1.2, 0.0, 0.0, -0.01, -0.01,
    # v_los (4 params): v_pa, v_a, v_b, v_c (sys_vel = zs * c)
    -45.0, 300.0, 15, zs * 299792,
    # v_disp (3 params): central_vd, scale_rad, flat_vd
    40.0, 0.02, 175.0,
    # flx (1 param): scale factor
    1e6
]

# Run galaxy simulation from API
results = run_galaxy_simulation(
    ifulmodel, 
    sim_params, 
    source_grid_size=100,
    source_grid_scale=0.015
)
lensed_image, unlensed_source, ra_crit, dec_crit, ra_caustic, dec_caustic = results

res, simulated_datacube = ifulmodel.generate_residuals(
    sim_params, 
    return_datacube=True, 
    vd_plots=False
)
simulated_datacube_noisy, bg_noise = add_instrument_noise(
    simulated_datacube, 
    bg_noise_std_frac=0.02, 
    seed=42
)

# Save simulated datacube using simulation API
fits_filename = "simulated_lensed_galaxy_datacube.fits"
export_to_fits(
    fits_filename,
    simulated_datacube_noisy,
    imset.wavelengths_full,
    imset.aux_info["header_wcs"],
    redshift=zs,
    exptime=1000.0
)

# Display the generated GIF
gif_filename = "simulated_datacube.gif"
gen_obs_gif(
    simulated_datacube_noisy,
    ifulmodel.datacube_mask,
    imset.wavelength,
    gif_filename,
    overwrite=True,
    pixscale=0.075
)

from IPython.display import Image as imp
imp(filename=gif_filename)

For comprehensive tutorials, check out the notebooks in the examples/ directory. In particular, see the s4c_ series of notebooks for a tutorial on simulating and fitting to real data.


Repository & Package Structure

iful/
├── src/iful/                # Package source code 
│   ├── __init__.py
│   ├── image_set.py         # 3D Datacube processing & masking
│   ├── flat_modeling.py     # Lensing model wrapper
│   ├── iful_modeling.py     # Joint lensing + IFU kinematics model
│   ├── simulation_api.py    # Mock dataset creation & FITS export
│   └── util.py              # Mathematical profiles & utilities
├── examples/                # Jupyter notebook tutorials 
├── tests/                   # Automated pytest suite
├── docs/                    # Documentation assets
└── paper/                   # Paper-related files

Documentation

See https://iful.readthedocs.io/en/latest/ for the readthedocs API documentation.


Contributing

Contributions, bug reports, and feature requests are welcome! Please feel free to open an issue or submit a pull request on GitHub.

See CONTRIBUTING.md for details on guidelines and local setup.


License

Distributed under the MIT License. See LICENSE for details.