A light-curve fitting framework for astronomical transients
Project description
TransFit
Language: English | 简体中文
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
emceeinstalled by default and optionalzeusanddynestybackends.
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()
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},
}
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:
- Liangduan Liu (liuld@ccnu.edu.cn)
- Yuhao Zhang (zhangyh2001@foxmail.com)
- GuangLei Wu (wuguanglei@mails.ccnu.edu.cn)
Citation
If TransFit is helpful for your work, please consider giving the repository a star. This helps other researchers discover the project.
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
- 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file transfit-0.1.0.tar.gz.
File metadata
- Download URL: transfit-0.1.0.tar.gz
- Upload date:
- Size: 84.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cf86fb322ff22033645b5ba7efa42e5adbd25edcf18185aee44dbf641d1db3b
|
|
| MD5 |
201c27092da1ed86088ce1702757f4ba
|
|
| BLAKE2b-256 |
1d52b8f2266b1eec4fa6bdc8cc34fcc53dd68bdff41598fad4216daa215d1b45
|
Provenance
The following attestation bundles were made for transfit-0.1.0.tar.gz:
Publisher:
publish.yml on YuHaoZhang01/TransFit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
transfit-0.1.0.tar.gz -
Subject digest:
5cf86fb322ff22033645b5ba7efa42e5adbd25edcf18185aee44dbf641d1db3b - Sigstore transparency entry: 1851261337
- Sigstore integration time:
-
Permalink:
YuHaoZhang01/TransFit@0fa81e9e6bbc10b9e54984d2c289b4ef9ca8426b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/YuHaoZhang01
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0fa81e9e6bbc10b9e54984d2c289b4ef9ca8426b -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file transfit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: transfit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 102.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
405e12e9966950e6a49643295c89e4749b5e1ceeddcf2923feb88b90983c499e
|
|
| MD5 |
2166e3c274e8f29990cfc4c6145e684b
|
|
| BLAKE2b-256 |
a9dd4974a0dbba284a478acab63fdb0d743208603ba268492bb59e49231814b8
|
Provenance
The following attestation bundles were made for transfit-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on YuHaoZhang01/TransFit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
transfit-0.1.0-py3-none-any.whl -
Subject digest:
405e12e9966950e6a49643295c89e4749b5e1ceeddcf2923feb88b90983c499e - Sigstore transparency entry: 1851261493
- Sigstore integration time:
-
Permalink:
YuHaoZhang01/TransFit@0fa81e9e6bbc10b9e54984d2c289b4ef9ca8426b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/YuHaoZhang01
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0fa81e9e6bbc10b9e54984d2c289b4ef9ca8426b -
Trigger Event:
workflow_dispatch
-
Statement type: