Skip to main content

FlopPITy

normalizing Flow exoplanet Parameter Inference Toolkyt

FlopPITy is a small Python package for atmospheric retrievals with simulation-based inference. You provide observed spectra, define parameters, and point FlopPITy at a simulator that returns model spectra. FlopPITy trains a posterior with sbi.

This README is the shortest path to running a retrieval. For all options, ARCiS details, binary/multi-component retrievals, output files, resuming, plotting, PCA, and post-processing, see docs/detailed_guide.md.

Install

FlopPITy supports Python >=3.10, <3.13.

conda create -n floppity_env python=3.12.9
conda activate floppity_env
pip install floppity

Observation Files

Each observation file is a plain text table with at least three columns:

# wavelength    observed_value    uncertainty

Minimal Retrieval

import numpy as np
from floppity import Retrieval

def simulator(obs, parameters, thread=0, **kwargs):
    """Return model spectra keyed like obs.

    parameters has shape (n_samples, n_parameters).
    Each returned spectrum has shape (n_samples, n_wavelengths).
    """
    spectra = {}

    for key, obs_array in obs.items():
        wavelength = obs_array[:, 0]
        spectra[key] = # array of shape (n_samples, n_wavelengths)

    return spectra

R = Retrieval(simulator)

R.get_obs(["path/to/observation.txt"])

R.add_parameter("parameter_name", prior_min, prior_max)

R.run()

That is the core FlopPITy workflow:

  1. Create a Retrieval.
  2. Load observations with get_obs.
  3. Add parameters with add_parameter.
  4. Run with run.

To train SBI on residuals instead of the simulated spectra, construct the retrieval with fit_residuals=True. FlopPITy then uses simulation - observation as the training feature and conditions the posterior on a zero residual:

R = Retrieval(simulator, fit_residuals=True)
R.preprocessing = []

Residuals are signed, so this mode cannot be combined with log or log_standardize preprocessing. Use no preprocessing or a transformation that supports signed values.

For positive emission spectra spanning a large dynamic range, log residuals are usually preferable:

R = Retrieval(simulator, obs_type="emis", fit_residuals=True)
R.preprocessing = ["log_residual"]

This trains on log10(simulation) - log10(observation) and conditions on zero. Both arrays are clipped to emission_flux_floor before taking the logarithm.

For log or log_standardize, configure a separate floor when constructing the retrieval. It is applied consistently to simulations and observations directly before log10:

R = Retrieval(simulator, log_flux_floor=1e-30)
R.preprocessing = ["log_standardize"]

Multiple Observations

R.get_obs({
    "prism": "path/to/prism.txt",
    "miri": "path/to/miri.txt",
})

Your simulator should return spectra with the same keys:

return {
    "prism": prism_model,
    "miri": miri_model,
}

Retrieval with ARCiS

FlopPITy comes with an ARCiS wrapper by default that can import the observations and parameters from an ARCiS input file. The workflow would then be:

from floppity import Retrieval
from floppity.simulators import read_ARCiS_input, ARCiS

R = Retrieval(ARCiS)

ARCiS_kwargs = dict(
    input_file = 'path/to/ARCiS/input.txt',
    output_dir = 'path/to/ARCiS/output',
)

parameters, observations = read_ARCiS_input(ARCiS_kwargs['input_file'])

R.get_obs(observations)
R.parameters = parameters

R.run(simulator_kwargs=ARCiS_kwargs)

Retrieval with PICASO

FlopPITy also comes with a PICASO wrapper that can import the observations and parameters from a PICASO retrieval TOML. The workflow mirrors the ARCiS wrapper:

from floppity import Retrieval
from floppity.simulators import read_PICASO_input, PICASO

R = Retrieval(PICASO, obs_type='emis')
R.preprocessing = ['log']

PICASO_kwargs = dict(
    input_file='path/to/PICASO/input.toml',
    picaso_repo='path/to/PICASO',  # optional if picaso is importable
    # pysyn_cdbs='path/to/trds',   # optional if PICASO needs synphot refs
)

parameters, observations = read_PICASO_input(**PICASO_kwargs)

R.get_obs(observations)
R.parameters = parameters

R.run(simulator_kwargs=PICASO_kwargs)

For PICASO simulation fitting, the default is no FlopPITy preprocessing; SBI applies its own x z-scoring. Plain log remains available for experiments. For PICASO residual fitting, use fit_residuals=True with R.preprocessing = ["log_residual"]. Raw residuals remain available with R.preprocessing = [].

PICASO is imported lazily, so it is not a required FlopPITy dependency unless you use this simulator. read_PICASO_input writes temporary FlopPITy observation text files from PICASO's [ObservationData] block. By default those files are written under [InputOutput].retrieval_output in the TOML.

The FlopPITy observations use the data-file errors directly. PICASO err_inf.* priors are ignored because they are likelihood nuisance terms, not part of the simulator training data. PICASO scaling.* and offset.* priors are converted to FlopPITy post-processing parameters like scaling:prism.

Inspecting Results

After run(), the trained posterior proposals are stored on the retrieval:

posterior = R.proposals[-1]
samples = posterior.sample((1000,))

You can also save and load the retrieval checkpoint:

R.save("retrieval.pkl")
R = Retrieval.load("retrieval.pkl")

If save_posterior_samples=True, posterior_samples_round_X.txt stores 1000 posterior samples from each round in natural parameter units. If save_data=True, rounds/round_XXX/training_data.npz stores the sampled parameters, simulated spectra, and per-sample metadata used for that training round. It also writes rounds/round_XXX/sbi_data.npz with the exact normalized theta, x, and default_x arrays passed to SBI.

For stochastic checks, R.run_ensemble(...) repeats the same retrieval, reuses member 1's prior simulations, and writes aggregated samples/data under an aggregated/ folder. Use resume=True, add_members=True to append more members, or resume=True, extend_rounds=True to continue every existing member for more rounds.

Basic troubleshooting

  • It takes a very long time to sample from the posterior. "Only xxx% of samples are accepted, consider changing to MCMC": This probably means that the samples are too dissimilar to the observation. Usual suspects: incorrectly setup model, incorrect priors, or mismatching wavelength axes.

Next Steps

Metadata

Release files for FlopPITy 0.5

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

Source distribution (sdist)

Source distribution for FlopPITy 0.5
File Size Uploaded
floppity-0.5.tar.gz 130.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for FlopPITy 0.5
File Interpreter ABI Platform
floppity-0.5-py3-none-any.whl Python 3 none any Details

Total release size: 221.5 kB

Release files / floppity-0.5.tar.gz

Download URL floppity-0.5.tar.gz
Size 130.9 kB
Tags Source
SHA-256 checksum
How to use checksums
da80d7aa61a039b4685000aa9c1715ccf11f114f7b88ec0679a25fc43e1091ce
BLAKE2b-256 checksum
How to use checksums
addfdcb983ee33b7c5dd9b0e3fa0b97f47dd004fa8d6d90f46562c12b720e885
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / floppity-0.5-py3-none-any.whl

Download URL floppity-0.5-py3-none-any.whl
Size 90.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b35f66eb490c25470d3d765fc9df4c751031a2f6bd6f68be1fcc762dd49f5dbd
BLAKE2b-256 checksum
How to use checksums
c4eb728da449c365c2de45d3cc026a030e8a56153bcb0e43e2ab28019846909c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log
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