Metadata-Version: 2.4
Name: pymolfit
Version: 0.5.0
Summary: Independent pure-Python telluric correction based on the ESO Molecfit workflow.
Author: Nikolas Valsamidis
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/nikolasvalsamidis97/PyMolFit
Project-URL: Issues, https://github.com/nikolasvalsamidis97/PyMolFit/issues
Project-URL: Repository, https://github.com/nikolasvalsamidis97/PyMolFit.git
Keywords: astronomy,radiative transfer,spectroscopy,telluric correction
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Astronomy
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: THIRD_PARTY_NOTICES.md
Requires-Dist: numpy>=1.23
Requires-Dist: scipy>=1.9
Requires-Dist: astropy>=5.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Provides-Extra: examples
Requires-Dist: matplotlib>=3.7; extra == "examples"
Provides-Extra: interactive
Requires-Dist: matplotlib>=3.7; extra == "interactive"
Requires-Dist: ipympl>=0.9; extra == "interactive"
Provides-Extra: plot
Requires-Dist: matplotlib>=3.7; extra == "plot"
Dynamic: license-file

# PyMolFit

PyMolFit is an independent pure-Python package for modelling and correcting
telluric absorption in astronomical spectra. It is based on the concepts,
workflow, and radiative-transfer approach of the original
[ESO Molecfit](https://www.eso.org/sci/software/pipelines/skytools/molecfit),
with a Python API for both spectrum files and wavelength-flux arrays.

PyMolFit does not import or run Molecfit and is not affiliated with or endorsed
by ESO.

## Installation

```bash
python -m pip install pymolfit
```

Install plotting support for the tutorial notebooks:

```bash
python -m pip install "pymolfit[interactive]"
```

PyMolFit supports Python 3.10 and newer.

## Correct A Spectrum File

The main API is `correct()`:

```python
from pymolfit import correct

result = correct(
    input_path="spectrum.fits",
    wavelength_medium="air",
)

wavelength = result.corrected.wavelength
corrected_flux = result.corrected.flux
```

Use `wavelength_medium="vacuum"` for vacuum wavelengths. The argument may be
omitted only when the FITS metadata declares the wavelength medium
unambiguously.

For table-based echelle products, PyMolFit uses common order/detector columns
to preserve real physical groups and common quality columns such as `QUAL` or
`DQ` to exclude flagged pixels. Wide orders may be divided into smaller
radiative-transfer chunks for memory control, but those chunks continue to
share one smooth wavelength-alignment model for their physical order.

Results remain in memory unless an output is requested:

```python
from pymolfit import save_corrected_txt, save_fit_product_ecsv

save_corrected_txt(result, "corrected_spectrum.txt")
save_fit_product_ecsv(result, "fit_product.ecsv")
```

The text file contains a compact corrected spectrum. The ECSV product also
contains the fitted transmission, model, masks, metadata, and provenance.
The printed fit summary reports the resolved atmosphere and line data,
numerical chunks versus physical groups, fitted parameters, masked-pixel
counts, and residual line-alignment diagnostics.

## Correct Wavelength And Flux Arrays

Arrays do not have a FITS header, so observing metadata is supplied with an
`Observation`:

```python
from pymolfit import Observation, correct

observation = Observation(
    time="2025-09-28T07:44:51",
    latitude_deg=-24.627,
    longitude_deg=-70.404,
    altitude_m=2635.0,
    airmass=1.18,
    resolving_power=140_000,
    wavelength_frame="observatory",
    instrument="ESPRESSO",
)

result = correct(
    wavelength=wavelength,
    flux=flux,
    wavelength_unit="angstrom",
    wavelength_medium="air",
    observation=observation,
)
```

`wavelength_medium` states whether the numbers are air or vacuum wavelengths.
`wavelength_frame` separately states their velocity reference frame. Supported
frames are `observatory`, `barycentric`, and `heliocentric`.

## Select Fitting Regions Interactively

PyMolFit can save fit and exclusion windows without manually copying
wavelength values from a plot:

```python
from pymolfit import load_spectrum, select_telluric_regions

spectrum = load_spectrum(
    "spectrum.fits",
    wavelength_medium="air",
)

selector = select_telluric_regions(
    spectrum,
    output_path="telluric_regions.ecsv",
)
```

Candidate telluric transitions from the AER catalogue are marked automatically
and colored by molecule. To create an initial selection automatically, enter a
line count such as `100` and press **Automatic**. PyMolFit proposes fit windows
around the strongest covered AER transitions, skips lines in detector/order
gaps, and merges overlapping windows. These proposals can be edited like any
manual selection.

For manual editing, first zoom or pan to the desired area. Choose **Fit** or
**Exclude**, enable the **Draw regions** checkbox, and drag rectangles around
the lines; only their horizontal wavelength limits are stored. Drawing stays
active until you clear the checkbox. Every stored region is numbered on the
plot and listed in the side panel. Edit the filename field if needed, then press
**Save All** once to write the complete collection. In a Jupyter notebook, run
`%matplotlib widget` before opening the selector.

On later runs, the same `output_path` is detected and loaded automatically, so
the selector window is skipped. Pass `reuse_existing=False` to reopen the
saved regions for editing.

The ECSV file records both region types and their wavelength unit and
air/vacuum medium. Apply it directly without transcribing any endpoints:

```python
from pymolfit import correct

result = correct(
    input_path="spectrum.fits",
    wavelength_medium="air",
    region_file="telluric_regions.ecsv",
)
```

`region_file` cannot be combined with explicit `fit_ranges` or
`exclude_ranges`.

## Tutorials

The runnable notebooks in
[`tutorials/`](https://github.com/nikolasvalsamidis97/PyMolFit/tree/main/tutorials)
cover:

1. [Correcting part of a spectrum](https://github.com/nikolasvalsamidis97/PyMolFit/blob/main/tutorials/01_partial_spectrum.ipynb)
2. [Correcting a full spectrum](https://github.com/nikolasvalsamidis97/PyMolFit/blob/main/tutorials/02_full_spectrum.ipynb)
3. [Expert parameters](https://github.com/nikolasvalsamidis97/PyMolFit/blob/main/tutorials/03_expert_mode.ipynb)
4. [Correcting wavelength-flux arrays](https://github.com/nikolasvalsamidis97/PyMolFit/blob/main/tutorials/04_array_input.ipynb)
5. [Selecting telluric fit regions interactively](https://github.com/nikolasvalsamidis97/PyMolFit/blob/main/tutorials/05_telluric_region_selector.ipynb)

Start with Tutorial 1 for a short example or Tutorial 2 for a complete
one-dimensional echelle spectrum.

## Molecular And Atmospheric Data

The standard workflow automatically obtains the versioned AER molecular line
catalogue, verifies its checksum, and caches it under
`~/.cache/pymolfit/aer`. It is not bundled in the Python wheel, and the normal
workflow does not require a HITRAN API key.

Users may instead provide their own HITRAN `.par` files or other supported
line and continuum data.

## Scientific Basis And References

PyMolFit builds on the methods and scientific data developed by several
projects. Publications using PyMolFit should cite the relevant upstream
resources:

- ESO Molecfit:
  [Smette et al. 2015, A&A 576, A77](https://doi.org/10.1051/0004-6361/201423932)
  and
  [Kausch et al. 2015, A&A 576, A78](https://doi.org/10.1051/0004-6361/201423909)
- [AER LBLRTM](https://github.com/AER-RC/LBLRTM) line-by-line
  radiative-transfer methods and data
- [AER MT_CKD](https://github.com/AER-RC/MT_CKD) atmospheric continuum model
- [HITRAN](https://hitran.org/) molecular spectroscopic data
- [MIPAS](https://earth.esa.int/eogateway/instruments/mipas) atmospheric
  reference profiles
- [NOAA GDAS](https://www.ncei.noaa.gov/products/weather-climate-models/global-data-assimilation)
  meteorological profiles

PyMolFit uses [NumPy](https://numpy.org/), [SciPy](https://scipy.org/), and
[Astropy](https://www.astropy.org/).

## Development

```bash
git clone https://github.com/nikolasvalsamidis97/PyMolFit.git
cd PyMolFit
python -m pip install -e ".[dev,plot]"
python -m pytest
```

Report problems through the
[GitHub issue tracker](https://github.com/nikolasvalsamidis97/PyMolFit/issues).

## Licensing And Third-Party Data

PyMolFit's original Python code is available under the
[BSD 3-Clause License](https://github.com/nikolasvalsamidis97/PyMolFit/blob/main/LICENSE).
Scientific datasets and derived coefficient tables retain their upstream
terms and attribution requirements. See
[`THIRD_PARTY_NOTICES.md`](https://github.com/nikolasvalsamidis97/PyMolFit/blob/main/THIRD_PARTY_NOTICES.md)
for the included and automatically downloaded data.
