Skip to content

CCNUastro/TransFit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

113 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TransFit

Language: English | 简体中文

TransFit logo

Python License Inference Models Data

TransFit is a Python package for forward modeling and fitting astronomical transient light curves. It provides a compact interface for bolometric and multi-band data, with built-in nickel, magnetar, magnetar-plus-nickel, and CSM interaction models.

Features

  • Physical light-curve models with bolometric luminosity, effective temperature, and photospheric radius outputs.
  • Multi-band photometry in flux or magnitude space, including filter, extinction, and SED handling.
  • Bayesian fitting through a consistent result object, with emcee installed by default and optional zeus and dynesty backends.

Installation

python -m pip install transfit

For local development:

git clone <your-repo-url>
cd TransFit
python -m pip install -e ".[plot,examples]"

Install optional sampler backends with:

python -m pip install "transfit[all-samplers]"

Quick Start

Forward bolometric light curve
import matplotlib.pyplot as plt
import transfit as tf

params = {
    "M_ej": 3.0,
    "v_ej": 1.0,
    "E_Th_in": 1.5,
    "M_ni": 0.08,
    "R_0": 120.0,
    "f_ni": 0.2,
    "kappa": 0.12,
    "kappa_gamma": 0.03,
    "T_floor": 4500.0,
}

lc = tf.lightcurve_bol(
    model="nickel",
    params=params,
    z=0.001728,
    t_max_days=120.0,
)

plt.plot(lc.t_days, lc.Lbol)
plt.yscale("log")
plt.xlabel("Observer-frame time (days)")
plt.ylabel("Bolometric luminosity (erg s$^{-1}$)")
plt.show()

Bolometric forward model example

Forward multi-band light curve
import matplotlib.pyplot as plt
import transfit as tf

params = {
    "M_ej": 3.0,
    "v_ej": 1.0,
    "E_Th_in": 1.5,
    "M_ni": 0.08,
    "R_0": 120.0,
    "f_ni": 0.2,
    "kappa": 0.12,
    "kappa_gamma": 0.03,
    "T_floor": 4500.0,
}

filters = {
    "B": "johnson_cousins.B",
    "V": "johnson_cousins.V",
    "R": "johnson_cousins.R",
    "I": "johnson_cousins.I",
}

lc = tf.lightcurve_multiband(
    model="nickel",
    params=params,
    z=0.001728,
    filters=filters,
    bands=["B", "V", "R", "I"],
    y_kind="mag",
    mag_system="vega",
    t_max_days=120.0,
)

for band in lc.bands:
    plt.plot(lc.t_days, lc.y[band], label=band)
plt.gca().invert_yaxis()
plt.xlabel("Observer-frame time (days)")
plt.ylabel("Vega magnitude")
plt.legend()
plt.show()

filters maps the band labels in your data to filter definitions. Built-in filters use string IDs. Custom mono filters should use an effective wavelength:

filters = {
    "g": {"lambda_eff_A": 4770.0},
    "r": {"lambda_eff_nm": 623.1},
}

For custom Vega magnitudes, also provide a Vega zero point:

filters = {
    "B": {"lambda_eff_A": 4400.0, "vega_zero_point_jy": 4260.0},
}

Multi-band forward model example

Fit a bolometric light curve
import numpy as np
import transfit as tf

arr = np.loadtxt("examples/data/sn1993j_lbol.txt")
data = tf.BolometricData(
    t_days=arr[:, 0] - arr[:, 0].min(),
    y=arr[:, 1],
    yerr=arr[:, 2],
)

res = tf.fit_bol(
    data=data,
    model="nickel",
    z=0.001728,
    priors={
        "M_ej": (0.5, 8.0),
        "v_ej": (0.2, 3.0),
        "E_Th_in": (0.05, 8.0),
        "M_ni": ("log10", -3.0, -0.2),
        "R_0": (10.0, 400.0),
        "t_shift": (0.0, 20.0),
    },
    fixed={
        "f_ni": 0.2,
        "kappa": 0.12,
        "kappa_gamma": 0.03,
    },
    sampler_kwargs={"nwalkers": 32, "nsteps": 5000, "burnin": 1000, "thin": 10},
)

print(res.best_params_raw)
tf.save(res, "mcmc_out/sn1993j_bol_nickel.npz")
Fit a multi-band light curve
import numpy as np
import transfit as tf

raw = np.genfromtxt(
    "examples/data/sn2007gr.csv",
    delimiter=",",
    names=True,
    dtype=float,
    encoding="utf-8",
)

bands, t_days, y, yerr = [], [], [], []
t0 = np.nanmin(raw["Phase"])
columns = {
    "B": ("Bmag", "e_Bmag"),
    "V": ("Vmag", "e_Vmag"),
    "R": ("Rmag", "e_Rmag"),
    "I": ("Imag", "e_Imag"),
}

for band, (mag_col, err_col) in columns.items():
    good = (
        np.isfinite(raw["Phase"])
        & np.isfinite(raw[mag_col])
        & np.isfinite(raw[err_col])
        & (raw[err_col] > 0)
    )
    t_days.extend((raw["Phase"][good] - t0).tolist())
    y.extend(raw[mag_col][good].tolist())
    yerr.extend(raw[err_col][good].tolist())
    bands.extend([band] * int(np.sum(good)))

data = tf.MultiBandData(
    t_days=np.asarray(t_days, float),
    band=np.asarray(bands, dtype=object),
    y=np.asarray(y, float),
    yerr=np.asarray(yerr, float),
)

filters = {
    "B": "johnson_cousins.B",
    "V": "johnson_cousins.V",
    "R": "johnson_cousins.R",
    "I": "johnson_cousins.I",
}

res = tf.fit_multiband(
    data=data,
    model="nickel",
    z=0.001728,
    filters=filters,
    y_kind="mag",
    mag_system="vega",
    priors={
        "M_ej": (0.5, 8.0),
        "v_ej": (0.2, 3.0),
        "E_Th_in": (0.05, 8.0),
        "M_ni": ("log10", -3.0, -0.2),
        "R_0": (10.0, 400.0),
        "t_shift": (0.0, 20.0),
    },
    fixed={
        "f_ni": 0.2,
        "kappa": 0.12,
        "kappa_gamma": 0.03,
        "T_floor": 4500.0,
    },
    sampler_kwargs={"nwalkers": 32, "nsteps": 5000, "burnin": 1000, "thin": 10},
)

print(res.best_params_raw)
tf.save(res, "mcmc_out/sn2007gr_multiband_nickel.npz")

Public API

Data containers
tf.BolometricData(t_days, y, yerr, mask=None)
tf.MultiBandData(t_days, band, y, yerr, mask=None)
Model inspection
tf.model_param_names("nickel")
tf.param_template("csm")

Canonical model names are nickel, magnetar, magnetar_ni, and csm.

Forward and prediction
tf.lightcurve_bol(model=..., params=..., z=..., t_max_days=...)
tf.lightcurve_multiband(
    model=...,
    params=...,
    z=...,
    filters=...,
    bands=...,
    y_kind="mag",
)

tf.predict_bol(model=..., params=..., z=..., t_days=...)
tf.predict_multiband(
    model=...,
    params=...,
    z=...,
    filters=...,
    t_days=...,
    band=...,
)
Fitting
tf.fit_bol(
    data=...,
    model=...,
    z=...,
    priors=...,
    fixed=...,
    sampler="emcee",
    sampler_kwargs=None,
    model_kwargs=None,
)

tf.fit_multiband(
    data=...,
    model=...,
    z=...,
    filters=...,
    y_kind="mag",
    priors=...,
    fixed=...,
    sed=None,
    sampler="emcee",
    sampler_kwargs=None,
    model_kwargs=None,
)
Results, plotting, and I/O
res.best_params
res.best_params_raw
res.median_params
res.best_fit
res.best_index
res.best_log_prob
res.best_sample
res.samples
res.log_prob
res.meta

tf.plot.fit_bol(res, data=data)
tf.plot.fit_multiband(res, data=data)
tf.plot.corner(res)

path = tf.save(res, path="mcmc_out/result.npz")
loaded = tf.load(path)

Full details are available in API and parameter reference.

Documentation

Contact

For questions about this project, please contact:

Citation

If TransFit is helpful for your work, please consider giving the repository a star. This helps other researchers discover the project.

GitHub stars

If you use TransFit in research, please cite the TransFit paper:

@ARTICLE{2025ApJ...992...20L,
       author = {{Liu}, Liang-Duan and {Zhang}, Yu-Hao and {Yu}, Yun-Wei and {Du}, Ze-Xin and {Li}, Jing-Yao and {Wu}, Guang-Lei and {Dai}, Zi-Gao},
        title = "{TransFit: An Efficient Framework for Transient Light-curve Fitting with Time-dependent Radiative Diffusion}",
      journal = {\apj},
     keywords = {Supernovae, Radiative transfer, Core-collapse supernovae, Time domain astronomy, 1668, 1335, 304, 2109, High Energy Astrophysical Phenomena, Instrumentation and Methods for Astrophysics},
         year = 2025,
        month = oct,
       volume = {992},
       number = {1},
          eid = {20},
        pages = {20},
          doi = {10.3847/1538-4357/adfed6},
archivePrefix = {arXiv},
       eprint = {2505.13825},
 primaryClass = {astro-ph.HE},
       adsurl = {https://ui.adsabs.harvard.edu/abs/2025ApJ...992...20L},
      adsnote = {Provided by the SAO/NASA Astrophysics Data System}
}

For the csm model, also cite:

@ARTICLE{2026ApJ...999..186Z,
       author = {{Zhang}, Yu-Hao and {Liu}, Liang-Duan and {Du}, Ze-Xin and {Wu}, Guang-Lei and {Li}, Jing-Yao and {Yu}, Yun-Wei},
        title = "{TransFit-CSM: A Fast, Physically Consistent Framework for Interaction-powered Transients}",
      journal = {\apj},
     keywords = {Core-collapse supernovae, Supernovae, Circumstellar matter, Stellar mass loss, 304, 1668, 241, 1613, High Energy Astrophysical Phenomena},
         year = 2026,
        month = mar,
       volume = {999},
       number = {2},
          eid = {186},
        pages = {186},
          doi = {10.3847/1538-4357/ae434a},
archivePrefix = {arXiv},
       eprint = {2511.13265},
 primaryClass = {astro-ph.HE},
       adsurl = {https://ui.adsabs.harvard.edu/abs/2026ApJ...999..186Z},
      adsnote = {Provided by the SAO/NASA Astrophysics Data System}
}

Papers Using TransFit

  • Ni et al., Mapping the Dense Circumstellar Environments of SNe Ibn, SNe Icn, and Fast Blue Optical Transients, arXiv e-print (2026), arXiv:2607.00453.
  • Yuan et al., Thermal X-rays breaking out from pre-explosion ejecta of a dying massive star, arXiv e-print (2026), arXiv:2606.10014.
  • Liu et al., SN 2024igg: A Super-Chandrasekhar/03fg-like SN exhibiting C II-dominated spectra after explosion, submitted to A&A (2026), arXiv:2602.03427.

AI Assistance

Parts of the code and documentation in this project were generated with assistance from OpenAI Codex.

About

TransFit is a fast, physically motivated framework for fitting and inverting light curves of luminous transients, combining improved physical consistency with computational efficiency.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages