What’s New in v2.0.0#

Version 2.0.0 is a complete redesign of ForMoSA. The package has been rebuilt from the ground up around a modern, object-oriented API. While the core physics and nested-sampling approach remain the same, almost every interface has changed. Users coming from v1.x should read this page carefully before upgrading.


Why a new major version?#

The v1.x series accumulated several functional improvements (MOSAIC multi-instrument support, UltraNest, high-contrast models, …), but the underlying code remained largely procedural and tightly coupled to a single INI configuration file. This made it hard to:

  • use ForMoSA interactively in a notebook;

  • compose multiple steps programmatically;

  • extend or test individual components in isolation.

v2.0.0 addresses these limitations with a class-based rewrite that keeps the scientific capabilities of v1.x and adds significant new ones.


New class-based API#

The most visible change is the introduction of the Analysis class as the single entry point for every analysis. In v1.x, a typical workflow was driven by a main.py script that called two standalone functions:

# v1.x (old)
from ForMoSA.global_file import GlobFile
from ForMoSA.adapt.adapt_obs_mod import launch_adapt
from ForMoSA.nested_sampling.nested_sampling import launch_nested_sampling

global_params = GlobFile("config.ini")
launch_adapt(global_params, adapt_model=True)
launch_nested_sampling(global_params)

In v2.0.0 the same workflow becomes:

# v2.0.0 (new)
from ForMoSA import Analysis
from ForMoSA.config.global_config import (
    ConfigPath, ConfigAdapt, ConfigInversion, ConfigParameters
)

config_path = ConfigPath(
    observation_path=["path/to/observation.fits"],
    adapt_store_path="path/to/adapted_grid/",
    result_path="path/to/results/",
    model_path="path/to/model_grid.nc",
)

analysis = Analysis(config_path)
analysis.adapt(ConfigAdapt(), ConfigInversion())
analysis.nested_sampling(
    ConfigParameters(
        par1=["uniform", "500", "3000"],
        par2=["uniform", "2.5", "5.5"],
        r=["uniform", "0.5", "3.0"],
        d=["constant", "50"],
    )
)
analysis.plot(analysis.ns.results)

The Analysis object manages the full lifecycle — loading observations and model grids, adapting the grid, running nested sampling, and producing plots — so you never have to worry about passing state between functions.


Python dataclasses for configuration#

v1.x relied on a single config.ini file, read through the GlobFile class, to control every aspect of an analysis. v2.0.0 replaces this with a set of lightweight Python dataclasses that can be instantiated directly in code or loaded from an INI file:

Dataclass

Controls

ConfigPath

File paths (observations, grid, results)

ConfigAdapt

Grid adaptation settings (method, resolution)

ConfigInversion

Nested-sampling algorithm, likelihood, priors

ConfigParameters

Prior distributions for each fitted parameter

This makes it straightforward to build configuration programmatically, inspect and modify individual values, and loop over parameter grids in notebooks.


Restructured package layout#

The internal package layout has been reorganised into well-separated modules:

ForMoSA/
├── analysis.py          ← new: main Analysis class
├── config/              ← new: dataclass-based configuration
├── core/                ← new: enums, error types, logging
├── filter/              ← new: SVO filter retrieval & caching
├── grid/                ← replaces adapt/: model grids & subgrids
├── nested_sampling/     ← retained & extended
├── observation/         ← new: typed observation classes
├── parameter/           ← new: parameter & prior objects
├── transform/           ← new: physics/observational effect pipeline
└── utils/               ← replaces utils_spec.py

Old top-level scripts (main.py, global_file.py, utils_spec.py) and the flat adapt/ directory are no longer present. Their functionality lives in the modules listed above.


Typed observation classes#

Observations are now represented by proper Python classes instead of raw NumPy arrays read from an INI path list:

  • ObservationSpectroscopy — single spectroscopic dataset

  • ObservationPhotometry — photometric dataset (filter list)

  • ObservationSet — container that groups any mix of the above

The ObservationSet is built automatically from your .fits files when you construct an Analysis object, and it handles the MOSAIC multi-instrument case transparently.


Automatic photometry filter retrieval#

v2.0.0 introduces a PhotometryFilter service that automatically downloads and caches filter transmission curves from the SVO Filter Profile Service. You no longer have to manage filter files manually — just provide the facility, instrument, and filter identifier in your observation file and ForMoSA handles the rest.


Extended plotting#

The plot() method and the underlying Plotting class now produce:

  • Corner plot — joint and marginal posterior distributions

  • Chain diagnostics — nested-sampling chain traces

  • Radar diagram — visual comparison of multiple targets

  • Best-fit spectrum — observed data versus best-fit model with 1-σ and 2-σ confidence intervals

  • CCF — Cross-Correlation Function via plot_ccf()

  • RV–v sin i map — 2-D log-likelihood map via plot_rv_vsini_map()

The CCF and RV–v sin i plots are entirely new in v2.0.0 and require a completed nested-sampling run.


Structured logging#

v2.0.0 adds a proper logging infrastructure built on the Python standard logging module. The verbosity level can be controlled when instantiating Analysis:

analysis = Analysis(config_path, log_level="debug")   # verbose
analysis = Analysis(config_path, log_level="warning")  # quiet

Typed error handling#

All internal errors now raise ForMoSAError (a subclass of Exception) instead of generic exceptions or silent failures. This makes it much easier to catch ForMoSA-specific problems in your own code:

from ForMoSA.core.errors import ForMoSAError

try:
    analysis = Analysis(config_path)
except ForMoSAError as e:
    print(f"ForMoSA configuration error: {e}")

Migrating from v1.x#

The table below summarises the mapping from the v1.x public interface to v2.0.0.

v1.x

v2.0.0

GlobFile("config.ini")

ConfigPath(…) + Analysis(config_path)

launch_adapt(global_params)

analysis.adapt(config_adapt, config_inv)

launch_nested_sampling(global_params)

analysis.nested_sampling(config_params)

plotting_class.py standalone calls

analysis.plot(analysis.ns.results)

ForMoSA/adapt/

ForMoSA/grid/

ForMoSA/utils_spec.py

ForMoSA/utils/

ForMoSA/global_file.py

ForMoSA/config/global_config.py

Important

v2.0.0 is not backwards-compatible with v1.x. Scripts and notebooks written for v1.x will need to be updated. If you need the old behaviour in the short term, pin your installation to formosa==1.1.6.


Summary of changes at a glance#

Feature

v1.x

v2.0.0

Entry point

main.py script

Analysis class

Configuration

config.ini + GlobFile

Python dataclasses

Observations

Raw arrays from INI paths

Typed ObservationSet

Model grid handling

adapt/ functions

grid/ subgrid classes

Photometry filters

Bundled .npz files

SVO auto-download + cache

Nested-sampling back-ends

nestle, PyMultiNest, UltraNest

same (+ improved interface)

CCF / RV-vsini analysis

✗ not available

✓ new

Logging

print statements

Python logging module

Error handling

Generic exceptions

ForMoSAError

Package version

1.1.6

2.0.0