NIFTY
Near-Infrared Fitting for T and Y Dwarfs
Kevin Hainline, Jake Helton, and Evan Chen
NIFTY is a code designed to fit JWST NIRCam/MIRI photometry or NIRSpec prism spectroscopy of cold brown dwarf candidates with the LOWZ (Meisner et al. 2021), ATMO2020 (Phillips et al. 2020), Sonora Flame Skimmer (Mang et al. 2026), Sonora Elf Owl v2 (Mukherjee et al. 2024, Wogan et al. 2025), or earlier Sonora Elf Owl (with PH3, Beiler et al. 2024) atmospheric models, using a Bayesian framework with the emcee sampler (https://emcee.readthedocs.io/en/stable/user/sampler/) or the Nautilus sampler (https://nautilus-sampler.readthedocs.io/en/latest/). This code was described in Hainline et al. (2026) (doi.org/10.48550/arXiv.2510.00111).
NIFTY operates in two modes:
phot— fit broadband photometry from a catalog of one or more sources.spec— fit a single NIRSpec prism spectrum.
In both modes, NIFTY produces a corner plot, a best-fit SED or spectrum plot, and a text file with the 16th, 50th, and 84th percentiles of all fit parameters. Photometry fits typically converge in under 3 minutes per source for ~14 bands, though convergence time varies, especially at high SNR. Spectroscopic fits are slightly longer.
Installation
The installation comes with the NIFTY Python package and the commands nifty
and build_model.
The easiest way to install NIFTY is through pip:
pip install astro-nifty
The main pip installation only includes the dependencies required for sampling. If you also want to build your own models, install the optional dependencies:
pip install astro-nifty[build-model]
If you are installing with pip, it is recommended that you install within a virtual environment to keep dependencies clean. See the Python tutorial on virtual environments and packages for more information.
Alternatively, you can clone the NIFTY repository and set up an environment using conda or micromamba:
conda env create -f environment.yml
conda activate NIFTY
Running NIFTY
The easiest way to run NIFTY is through the nifty command.
NIFTY runs in two modes: photometry mode and spectroscopy mode, which require
slightly different arguments.
To see the available arguments, you can run: nifty phot -h or nifty spec -h
to display the help message for that mode.
Photometry mode (nifty phot)
Fit broadband photometry for one or more sources from a catalog.
Single source:
nifty phot \
--model path/to/model_grid.tar.gz \
--stub JADES-GS \
--config BD_NIRCam_MIRI_filters.json \
--id 20541 \
path/to/photometry_file.fits
List of IDs from a file (one ID per line):
nifty phot \
--model path/to/model_grid.tar.gz \
--stub JADES-GS \
--config BD_NIRCam_MIRI_filters.json \
--idlist all_source_IDs.dat \
path/to/photometry_file.fits
Multiple IDs:
nifty phot \
--model path/to/model_grid.tar.gz \
--stub JADES-GS \
--config BD_NIRCam_MIRI_filters.json \
--id 20541 --id 452029 --id 430165 \
path/to/photometry_file.fits
Spectroscopy mode (nifty spec)
Fit a single NIRSpec prism spectrum. The spectrum file should be a
whitespace-delimited text file with three columns: wavelength (microns),
flux (nJy), and flux error (nJy). The --id argument is used only to
label output files.
nifty spec \
--model path/to/model_grid.tar.gz \
--stub JADES-GS \
--id 20541 \
path/to/spectrum.txt
Optional arguments
| Argument | Description |
|---|---|
--output |
Output folder (default: <Model>_output/) |
--frac_model_floor |
Fractional model flux floor added in quadrature to photometry errors, to account for model systematics (e.g. 0.03 for 3%). Photometry mode only; no floor is applied in spectroscopy mode. |
--sampler |
Sampler used to estimate the posterior. Currently supports mcmc and nautilus |
--notex |
Use matplotlib Mathtext instead of system TeX for plots. |
Configuration File (--config)
NIFTY uses a single JSON file to describe all filter information needed for photometry fitting. Here is a sample entry:
{
"filter_columns": {
"JWST_F115W": {
"extension": "CIRC",
"flux": "F115W_CIRC3",
"error": "F115W_CIRC3_e",
},
"JWST_F444W": {
"extension": "CIRC",
"flux": "F444W_CIRC3",
"error": "F444W_CIRC3_e",
}
}
}
The filter name must match a valid sedpy filter. If no telescope prefix is provided, the prefix is assumed to be "JWST_".
extension: the FITS HDU name where this filter's data lives. Ignored for plain-text catalogs.flux/error: exact column names in the photometry file.
An example config file for JADES NIRCam + MIRI observations is included as
BD_NIRCam_MIRI_filters.json.
Photometry File Format
NIFTY can read:
- FITS files, with filter fluxes and errors in named HDU extensions and columns as specified in the config JSON.
- Plain-text catalogs, whitespace-delimited, one row per object.
For plain-text catalogs, include an ID column (case-sensitive) and flux/error
columns whose names match the config JSON exactly. Do not prefix the header
line with #. Example:
ID F115W_CIRC3 F115W_CIRC3_e F444W_CIRC3 F444W_CIRC3_e
101 0.123 0.010 0.456 0.025
All fluxes and errors should be in nJy. A minimum relative flux error of 5% is
applied automatically; errors below this floor are inflated to 0.05 * flux.
Output Files
For each fitted source, NIFTY writes the following files to the output directory:
Each file name is prefixed with <stub>_<ID>_<Model>_.
| File | Description |
|---|---|
sampler_backend.h5 |
Backend file for sampler (e.g. MCMC chains) |
corner.png |
Corner plot of the posterior |
SED.png |
Best-fit SED or spectrum plot |
SED.txt |
Model spectrum envelope (16th, 50th, 84th percentile flux, in nJy, vs wavelength in microns) |
parameters.txt |
16th, 50th, and 84th percentile parameter values, plus chi-square. Distance is in parsecs. |
model_photometry.txt / model_spectroscopy.txt |
50th percentile model fit for either spectroscopy or photometry depending on mode. |
Model Parameters
| Model | Parameters fit |
|---|---|
SonoraFlameSkimmerQuickstart |
Teff, log(g), log(Kzz), [M/H], C/O, distance (pc) |
SonoraElfOwl |
Teff, log(g), log(Kzz), [M/H], C/O, distance (pc) |
SonoraElfOwlPH3 |
Teff, log(g), log(Kzz), [M/H], C/O, distance (pc) |
ATMO2020 |
Teff, log(g), [M/H], distance (pc) |
LOWZ |
Teff, log(g), log(Kzz), [M/H], C/O, distance (pc) |
All fits assume a source radius of 1 Jupiter radius. Distances are always reported in parsecs.
The ModelGrid Files
While you can create your own ModelGrid files for fitting (see below), we have prepared files for the ATMO2020, LOWZ, Sonora Elf Owl, SonoraElfOwlPH3, and SonoraFlameSkimmerQuickstart fits at this link:
https://arizona.box.com/v/NiftyModelGrids
These files range in size from 2 - 300 MB, and you can point NIFTY at these to run fits. They include all of the JWST NIRCam and MIRI filters, as well as the Roman WFI filters for use with future Roman HLWAS observations.
Creating the ModelGrid Files
Before running NIFTY, download the model grids you want to fit against, then
run build_model to build the model grid file that NIFTY uses during fitting.
For a more detailed description of parameters, run build_model -h.
build_model \
--path path/to/model/files/ \
--config BD_NIRCam_MIRI_filters.json \
ModelName
The valid model names are SonoraFlameSkimmerQuickstart, SonoraElfOwl,
SonoraElfOwlPH3, ATMO2020, LOWZ. At this time, NIFTY does not support
creating the SonoraFlameSkimmer complete models from scratch.
Typically, there are two ModelGrid files outputted. The raw grid is the grid created by reading in all the points that are part of the model. However, many models do not have values at all grid points, so missing points are filled. with NaN. The complete grid has values for all grid points. If the raw grid is missing values, they are filled by a fitting procedure (see code for details). If the raw grid is already complete, only the complete grid is saved.
By default, the output model grid files are named
<Model>_raw_ModelGrid.tar.gz and <Model>_complete_ModelGrid.tar.gz.
The Sonora Elf Owl model grid spans several tens of GB and can take a few hours to process. The other grids are considerably smaller.
Expected Model File Layouts
SonoraFlameSkimmerQuickstart — A single zip file:
spectra_R3k_quickstart.zip
SonoraElfOwl — directory of temperature-range tarballs containing NetCDF files:
Sonora_Elf_Owl_v2/
teff_275_325.tar.gz
teff_350_400.tar.gz
...
SonoraElfOwlPH3 — a single .npz file:
elf_owl_disequilibrium_PH3.npz
ATMO2020 — per-metallicity subdirectories containing .dat files:
meisner_2023/
grid_m1.0/
spec_jwst_t700_g3.5_m1.0_kg_g3.5.dat
...
grid_m0.5/
grid_p0/
grid_p0.3/
LOWZ — CSV index and models tarball
LOWZ/
LOWZ_models_index.csv
models.tar.gz
References
- Meisner et al. 2021 (LOWZ): https://doi.org/10.3847/1538-4357/ac013c
- Phillips et al. 2020 (ATMO2020): https://doi.org/10.1051/0004-6361/201937381
- Mukherjee et al. 2024 (Sonora Elf Owl): https://doi.org/10.3847/1538-4357/ad18c2
- Wogan et al. 2025 (Sonora Elf Owl v2): https://doi.org/10.3847/2515-5172/add407
- Beiler et al. 2024: https://doi.org/10.5281/zenodo.11370829
- Foreman-Mackey et al. 2013 (emcee): https://doi.org/10.1086/670067
- Lange 2023 (nautilus): https://doi.org/10.1093/mnras/stad2441
- Mang et al. 2026 (Sonora Flame Skimmer): https://doi.org/10.48550/arXiv.2608.06454
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 astro_nifty-0.1.2.tar.gz.
File metadata
- Download URL: astro_nifty-0.1.2.tar.gz
- Upload date:
- Size: 149.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc3bde147b1a451b24cb6ab9e615a1400376e786447ee385cf12dea984797de7
|
|
| MD5 |
558e3232c77d88924377f9d3216efdf0
|
|
| BLAKE2b-256 |
d211b329c1e0e31b8dcc96d7332a6e48713cf63b63f32c2d2a4a8c2293af5ab5
|
Provenance
The following attestation bundles were made for astro_nifty-0.1.2.tar.gz:
Publisher:
publish.yml on kevinhainline/NIFTY
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
astro_nifty-0.1.2.tar.gz -
Subject digest:
bc3bde147b1a451b24cb6ab9e615a1400376e786447ee385cf12dea984797de7 - Sigstore transparency entry: 2585579329
- Sigstore integration time:
-
Permalink:
kevinhainline/NIFTY@7ac12a25bd63455745a247e9ce1a541978c4b200 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/kevinhainline
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7ac12a25bd63455745a247e9ce1a541978c4b200 -
Trigger Event:
push
-
Statement type:
File details
Details for the file astro_nifty-0.1.2-py3-none-any.whl.
File metadata
- Download URL: astro_nifty-0.1.2-py3-none-any.whl
- Upload date:
- Size: 36.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e775750fd820a0a8c1a8c6a4690b15b323a5f5b8a0f144921ec8891f52efd48b
|
|
| MD5 |
3291fc0c942bbfd9c132df49a02c58c8
|
|
| BLAKE2b-256 |
c144a5c073b01b146f85c7ff7e2d8426de8e1ab5fa25ce6bea9ab583f09a9d4b
|
Provenance
The following attestation bundles were made for astro_nifty-0.1.2-py3-none-any.whl:
Publisher:
publish.yml on kevinhainline/NIFTY
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
astro_nifty-0.1.2-py3-none-any.whl -
Subject digest:
e775750fd820a0a8c1a8c6a4690b15b323a5f5b8a0f144921ec8891f52efd48b - Sigstore transparency entry: 2585580478
- Sigstore integration time:
-
Permalink:
kevinhainline/NIFTY@7ac12a25bd63455745a247e9ce1a541978c4b200 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/kevinhainline
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7ac12a25bd63455745a247e9ce1a541978c4b200 -
Trigger Event:
push
-
Statement type: