Skip to main content

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.

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.

Installation

pip install iful

Option 2: Install from Source

Clone the repository and install in editable mode:

git clone https://github.com/williyamshoe/iful.git
cd iful
pip install -e .

To install with testing dependencies:

pip install -e .[test]

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.

Metadata

Release files for iful 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for iful 1.0.0
File Size Uploaded Provenance Actions
iful-1.0.0.tar.gz 40.2 kB Without provenance Details for iful-1.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for iful 1.0.0
File Interpreter ABI Platform Actions
iful-1.0.0-py3-none-any.whl Python 3 none any Details for iful-1.0.0-py3-none-any.whl

Total release size: 75.5 kB

Release files / iful-1.0.0.tar.gz

Download URL iful-1.0.0.tar.gz
Size 40.2 kB
Tags Source
SHA-256 checksum
How to use checksums
0e08030d23d43a3c3b1015c26c0a8cabaf89329f42d6e8dcb990bcb7e6d75fc8
BLAKE2b-256 checksum
How to use checksums
b71cc81853128767c0b5c20541a9390e295267a58ef07ff795edbe3df80196a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.11

Release files / iful-1.0.0-py3-none-any.whl

Download URL iful-1.0.0-py3-none-any.whl
Size 35.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
78bb40a1ada1128796e28cadc29631302204dc563ad773210e32007a16addcab
BLAKE2b-256 checksum
How to use checksums
adc5862b0951c68c562a0409554824140e9d38bd689c5fbeb86c2a5c33578ef6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.11

Security for iful 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page