ftsdata
ftsdata is the Fourier-transform spectrometer (FTS) data toolkit for the CONCERTO and KIDS reductions. It provides OPD- and frequency-aware data containers, interferogram/spectrum transforms, FITS and IDIA HDF5 I/O, and inverse-variance co-addition of spectral cubes.
The package used to be the single kidsdata.ftsdata module. It is now an independent distribution, and existing code keeps working through the kidsdata.ftsdata compatibility shim.
Features
Data containers — SingleSidedOpdData, DoubleSidedOpdData, OneSidedOpdData, SpecData, and the retro-compatible FTSData. OpdData is the geometry-agnostic entry point (from_array / read).
Interferogram → spectrum — Forman phase correction, apodisation, zero-padding and ITG binning correction.
Spectrum → interferogram — to_itg for forward modelling.
I/O — FITS products registered with Astropy’s unified I/O, plus export to the IDIA HDF5 schema used by CARTA.
Large cubes — thread-based or dask-backed blockwise processing.
Co-addition — ftsdata_average combines cubes with per-pixel inverse-variance weighting.
Optional kidsdata integration — opacity correction can use kidsdata.forward_model.ATM when kidsdata is installed.
Support policy
ftsdata follows SPEC 0 — Minimum Supported Dependencies for Python and core dependency support, with one explicit exception: Python 3.8 remains supported for the CONCERTO environment used by kidsdata.
On Python 3.8 the package uses the last compatible NumPy, SciPy and Astropy releases; newer Python versions use the current SPEC 0 floors. Minimum versions are raised on minor or major releases, never on patch releases. The current floors and supported versions are listed in docs/min_versions.md.
Python 3.8 and the associated Astropy 5.2 stack are targeted for removal in ftsdata 0.2.0, or once the CONCERTO environment used by kidsdata moves to Python 3.11+ and Astropy 7+.
Installation
The package is not on PyPI yet; install it from this repository (Python 3.8+):
git clone git@gitlab.lam.fr:KISS/ftsdata.git
cd ftsdata
python -m pip install -e .
Optional features are grouped in extras:
python -m pip install -e ".[all]" # h5py, dask, matplotlib, psutil
python -m pip install -e ".[hdf5]" # HDF5 / IDIA export
python -m pip install -e ".[dask]" # dask-backed blockwise transforms
python -m pip install -e ".[plot]" # cube previews
python -m pip install -e ".[docs]" # Sphinx documentation build
python -m pip install -e ".[test]" # pytest and pytest-cov
Only NumPy, SciPy and Astropy are required for the core containers and transforms. h5py enables HDF5 I/O, dask enables dask-backed transforms, matplotlib enables plot_cube_preview, and psutil improves memory detection.
Quick start
import astropy.units as u
import numpy as np
from ftsdata import SingleSidedOpdData
# 101 OPD samples with a 100 µm step, symmetric around the ZPD
opd = np.arange(-50, 51) * 0.1 * u.mm
data = np.random.default_rng(42).normal(size=(opd.size, 16, 16))
# from_array inspects the OPD geometry and returns the matching subclass
itg = SingleSidedOpdData.from_array(opd, data)
print(type(itg).__name__) # DoubleSidedOpdData
# Apodise, zero-pad and FFT to a spectral cube
spectrum = itg.to_spectra(apodization=np.hanning, n_pad=3)
print(spectrum.data.shape) # (nfreq, 16, 16)
print(spectrum.spectral_axis.to("GHz")[:3])
spectrum.write("spectrum.fits", overwrite=True)
Read a product back with a compatible class:
from ftsdata import FTSData
cube = FTSData.read("spectrum.fits")
print(cube.data.shape)
Data model
All containers derive from astropy.nddata.NDDataArray and carry:
Attribute |
Description |
|---|---|
data |
Data cube, normally (nopd, ny, nx) or (nfreq, ny, nx) |
uncertainty |
Astropy uncertainty array |
mask |
Boolean bad-pixel mask (True = invalid) |
wcs |
Full WCS (sky axes plus OPD or frequency) |
meta |
Provenance and pipeline parameters |
hits |
Number of detector samples per voxel |
Class |
Role |
|---|---|
SingleSidedOpdData |
Base interferogram cube; from_array dispatches on OPD geometry |
DoubleSidedOpdData |
Symmetric OPD grid with the ZPD centred |
OneSidedOpdData |
OPD grid starting at the ZPD; real inverse FFT |
SpecData |
Spectrum cube |
FTSData |
Retro-compatible class inheriting from the interferogram and spectrum classes |
OpdData |
Generic entry point when the OPD geometry is unknown; alias of SingleSidedOpdData, so OpdData.from_array / OpdData.read still dispatch |
I/O and co-addition
FITS products use the Astropy unified I/O interface:
from ftsdata import FTSData
spectrum.write("cube.fits", overwrite=True)
spectrum.write("cube-compressed.fits", compress=True, overwrite=True)
cube = FTSData.read("cube.fits")
For CARTA, write the IDIA HDF5 layout directly — the .hdf5 extension selects the registered writer and reader:
from ftsdata import OpdData
cube.write("cube.hdf5", mip_levels=[2, 4, 8], dtype="float32")
cube = OpdData.read("cube.hdf5") # returns the matching geometry subclass
The writer creates the /0 group and the VERSION attribute required by the IDIA schema. Pass format="hdf5" explicitly when the filename lacks an .hdf5 or .h5 extension.
Co-add cubes that share the same WCS grid:
from pathlib import Path
from ftsdata import FTSData, ftsdata_average
cubes = [FTSData.read(path) for path in sorted(Path("products").glob("*_T.fits"))]
combined = ftsdata_average(cubes)
combined.write("combined_T.fits", overwrite=True)
Relationship with kidsdata
ftsdata does not import kidsdata at module import time, so it can be used on its own. When the kidsdata distribution is installed, two integrations become available lazily:
available_memory() uses kidsdata.utils.available_memory when available, which knows about SLURM allocations.
SpecData.correct_opacity() uses kidsdata.forward_model.ATM by default. Without kidsdata, pass a compatible model explicitly:
cube.correct_opacity(elevation=60, pwv=1.0, atm=my_atm_model)
Existing code can keep using the old import path:
from kidsdata.ftsdata import FTSData
New code should import from ftsdata directly.
Documentation
The Sphinx sources live in docs/:
python -m pip install -e ".[docs]"
python -m sphinx -b html docs docs/_build/html
The built pages are published in three places from the main branch:
GitLab Pages: https://ftsdata-7333b4.docs.lam.fr
GitHub Pages: https://abeelen.github.io/ftsdata/ (GitHub Actions)
Read the Docs: https://ftsdata.readthedocs.io/ (configured by .readthedocs.yaml)
Tests
python -m pip install -e ".[all,test]"
python -m pytest --pyargs ftsdata -q
The GitLab and GitHub CI pipelines run the test-suite on several Python versions and build the documentation with warnings treated as errors.
Repository layout
ftsdata/ package modules and pytest suite (ftsdata/tests) docs/ Sphinx sources licenses/ license files pyproject.toml packaging and tool configuration tox.ini test and documentation environments .gitlab-ci.yml tests and GitLab Pages .github/workflows/ GitHub Actions tests and Pages
License
BSD 3-clause. See licenses/LICENSE.rst.
Metadata
Release files for ftsdata 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ftsdata-0.1.0.tar.gz | 87.6 kB | Without provenance | Details for ftsdata-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ftsdata-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for ftsdata-0.1.0-py3-none-any.whl |
Total release size: 156.7 kB
Release files / ftsdata-0.1.0.tar.gz
| Download URL | ftsdata-0.1.0.tar.gz |
|---|---|
| Size | 87.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
57ba1dd89c28349ce0e1772be4aab07f0fc6f964aaf7dd27882a207f67deeb1d
|
|
BLAKE2b-256 checksum How to use checksums |
0b65c73ad457a68c0b8249a54d5b7ee41b3c79d8464efa1699c688897d65caa2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Release files / ftsdata-0.1.0-py3-none-any.whl
| Download URL | ftsdata-0.1.0-py3-none-any.whl |
|---|---|
| Size | 69.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f3fd2ba6605f4918a322d3658a9deb635e0a04906f4db94fabd7299974fb4dfd
|
|
BLAKE2b-256 checksum How to use checksums |
6642e586982a12263bf0ac7efe4f367497eb04e2e1af80187477ec346a78eb63
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Security for ftsdata 0.1.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.