Skip to main content

ps_eor: Power-spectrum analysis and signal separation for 21-cm cosmology

ps_eor provides data containers, power-spectrum estimators, simulations, and signal-separation tools for low-frequency interferometric 21-cm experiments. It supports the path from gridded visibility data to spatial, cylindrical, and spherical power spectra, including Gaussian-process foreground and systematic separation.

📖 Documentation: https://ps-eor.readthedocs.io/en/latest/ — getting started, topic-based user guide, pstool command reference, and full API reference.

Upgrading from ps_eor 0.x to 1.0? Read the ML-GPR migration guide.

What the package does

Data handling — build analysis-ready visibility cubes from calibrated images:

  • read frequency-ordered FITS images (Jy/PSF), using matching PSF files for an accurate Kelvin conversion, or inferring the PSF area from image metadata;
  • select the field of view and baseline range, Fourier-transform to the uv plane, and store visibilities, weights, frequencies, and metadata as HDF5.

Power spectra — measure 21-cm power spectra:

  • spatial, cylindrical, and spherical spectra, plus cross-spectra between independent observations, with the instrumental and cosmological normalizations applied.

Signal separation — suppress foregrounds and systematics, preserve the 21-cm signal:

  • polynomial and PCA foreground models;
  • ML-GPR, a Gaussian-process framework that infers posterior foreground, systematic, noise, and 21-cm components and propagates them to power spectra — for one observation or jointly across many, separating repeatable sky from observation-dependent excess variance.

Simulation and sensitivity — generate test data and forecast performance:

  • draw Gaussian-process component cubes (foreground, 21-cm, systematic; single- or multi-epoch) from covariance kernels or an input power spectrum;
  • generate thermal-noise data cubes from measured weights or a simulated telescope layout and observing strategy;
  • forecast UV coverage and power-spectrum sensitivity, with built-in models for LOFAR, NenuFAR, MWA, SKA-Low, HERA, AARTFAAC, and OVRO-LWA.

The GPR approach follows Mertens et al. (2018); the multi-observation extension relates to Munshi et al. (2025).

Installation

The base package contains the data and power-spectrum functionality:

pip install ps-eor

Install the Gaussian-process backend and its standard samplers, including NUTS through Pyro, with:

pip install "ps-eor[ml-gpr]"

UltraNest is available separately:

pip install "ps-eor[ml-gpr,ultranest]"

For development:

git clone https://gitlab.com/flomertens/ps_eor.git
cd ps_eor
pip install -e ".[ml-gpr,dev]"

Python 3.10 or newer is required.

Creating a visibility cube from FITS images

Given one calibrated image and one matching PSF image per frequency, ps_eor can perform the Jy/PSF-to-Kelvin conversion and construct a weighted CartDataCube. The files are sorted using their FITS frequency metadata:

from pathlib import Path

import numpy as np

from ps_eor import datacube, psutil

image_files = [str(path) for path in Path("fits/images").glob("*.fits")]
psf_files = [str(path) for path in Path("fits/psfs").glob("*.fits")]

image_files = psutil.sort_by_fits_key(image_files, "CRVAL3")
psf_files = psutil.sort_by_fits_key(psf_files, "CRVAL3")

cube = datacube.CartDataCube.load_from_fits_image_and_psf(
    image_files,
    psf_files,
    umin=50,
    umax=250,
    theta_fov=np.deg2rad(4),
    int_time=10,
    total_time=10 * 3600,
)
cube.save("visibilities.h5")

Here, umin and umax are in wavelengths, theta_fov is in radians, and the integration and total observing times are in seconds. The same operation is available as pstool gen_vis_cube.

Basic power-spectrum workflow

import numpy as np

from ps_eor import datacube, pspec

cube = datacube.CartDataCube.load("visibilities.h5")

config = pspec.PowerSpectraConfig(
    el=2 * np.pi * np.arange(cube.ru.min(), cube.ru.max(), 10),
    window_fct="hann",
)
ps_gen = pspec.PowerSpectraBuilder(config).get(cube)

spatial = ps_gen.get_ps(cube)
cylindrical = ps_gen.get_ps2d(cube)

kbins = np.logspace(np.log10(ps_gen.kmin), np.log10(0.5), 10)
spherical = ps_gen.get_ps3d(kbins, cube)

ML-GPR workflow

The high-level fitter is configured from TOML:

from ps_eor.ml_gpr import MLGPRConfigFile, MLGPRForegroundFitter

config = MLGPRConfigFile.get_defaults()
fitter = MLGPRForegroundFitter(config)
noise_for_fit = fitter.process_noise_cube(noise_cube)
result = fitter.run(data_cube, noise_for_fit)

Advanced users can work directly with the lower-level building blocks:

from ps_eor.ml_gpr.kernels import UVScaledKernel
from ps_eor.ml_gpr.multidata import MultiData
from ps_eor.ml_gpr.regressor import MultiGPRegressor

Command-line interface

The package installs pstool, which can run the main analysis and sensitivity workflows without writing Python code:

Command Purpose
gen_vis_cube Read frequency-ordered FITS image and PSF files, convert Jy/PSF to Kelvin, select the field of view and baseline range, and write an HDF5 visibility cube.
run_flagger Identify bad frequency and UV samples from Stokes I and V cubes, then save the flag mask and a diagnostic plot.
even_odd_to_sum_diff Build signal and noise-proxy cubes from an even/odd data split.
diff_cube Subtract two compatible visibility cubes.
combine Combine observations or nights, with optional flagging and noise-based weighting.
combine_sph Combine spherical-harmonic observations.
make_ps Calculate spatial, cylindrical, and spherical power spectra and save their numerical results and diagnostic plots.
run_ml_gpr Separate foreground, systematic, noise, and 21-cm components and produce their posterior power spectra and diagnostics.
run_ml_gpr_inj Inject a simulated 21-cm signal and measure its recovery through ML-GPR.
vis_to_sph Convert a Cartesian visibility cube into a spherical-harmonic cube.
simu_uv Simulate telescope UV coverage for a pointing and observing setup.
simu_noise_img Generate a thermal-noise FITS image cube from simulated UV coverage.
simu_noise_ps Predict spatial, cylindrical, and spherical power-spectrum sensitivity at one redshift.
simu_noise_ps_zrange Follow the sensitivity of a selected (k)-mode across a redshift range.

Each command documents its inputs and options:

pstool --help
pstool COMMAND --help

ML-GPR tutorials

The numbered notebooks form a focused ML-GPR tutorial series:

  1. Quick start
  2. Simulating data
  3. The covariance model
  4. Running a fit
  5. Training the VAE
  6. ML-GPR with the VAE kernel
  7. Config-driven runs
  8. Multi-epoch GPR
  9. Data in-painting
  10. Validation and failure modes

Specialist examples, including Cross-GPR and sampler-prior comparisons, live in the advanced notebooks.

Tests

pytest

Frozen numerical fixtures used to compare the GPyTorch implementation with the former GPy backend are stored under tests/data/gpr_golden/.

License

ps_eor is distributed under the GNU General Public License v3 or later.

Metadata

Release files for ps_eor 1.2

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

Source distribution (sdist)

Source distribution for ps_eor 1.2
File Size Uploaded Provenance Actions
ps_eor-1.2.tar.gz 221.8 kB Without provenance Details for ps_eor-1.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ps_eor 1.2
File Interpreter ABI Platform Actions
ps_eor-1.2-py3-none-any.whl Python 3 none any Details for ps_eor-1.2-py3-none-any.whl

Total release size: 458.6 kB

Release files / ps_eor-1.2.tar.gz

Download URL ps_eor-1.2.tar.gz
Size 221.8 kB
Tags Source
SHA-256 checksum
How to use checksums
6f6d510869eddb275f877b860296dcb24194350e54d81fce80dfdc6ef3e3b87d
BLAKE2b-256 checksum
How to use checksums
5d5a72bf7a713e7a3aa4aded0e3d6596eca2370cfe759986702ef43544fb7123
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.14.4 Linux/7.0.0-38-generic

Release files / ps_eor-1.2-py3-none-any.whl

Download URL ps_eor-1.2-py3-none-any.whl
Size 236.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
74c66e5008a2de8fb3e807a72568b33a8c3b6be72dcce666320f6b9ee1ec9c04
BLAKE2b-256 checksum
How to use checksums
aa59a8098045dbcf26a6798ec341275a113639d719623d05b07abf0cd7a14421
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.14.4 Linux/7.0.0-38-generic

Security for ps_eor 1.2

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.

Release history Release notifications | RSS feed

This release

1.2 This release

2 release files No provenance

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