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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ps_eor-1.0.tar.gz (218.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ps_eor-1.0-py3-none-any.whl (234.6 kB view details)

Uploaded Python 3

File details

Details for the file ps_eor-1.0.tar.gz.

File metadata

  • Download URL: ps_eor-1.0.tar.gz
  • Upload date:
  • Size: 218.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.14.4 Linux/7.0.0-28-generic

File hashes

Hashes for ps_eor-1.0.tar.gz
Algorithm Hash digest
SHA256 2b491b93c9790115b66716d8332118b7b350839f7e45d8f756e9e0e8dcf358fe
MD5 fcad53362f480216a2b556e5a0ed7336
BLAKE2b-256 1bc7779a67a14a717af7fd223759b6ddc62e71d7e827e5c40117ddd356284e61

See more details on using hashes here.

File details

Details for the file ps_eor-1.0-py3-none-any.whl.

File metadata

  • Download URL: ps_eor-1.0-py3-none-any.whl
  • Upload date:
  • Size: 234.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.14.4 Linux/7.0.0-28-generic

File hashes

Hashes for ps_eor-1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bd5e53262a2a4322c2ec3043536ee5c5d655df6c1d281b30a446d134030a6693
MD5 f0d36a8ba10feb1940d7a55e69a318de
BLAKE2b-256 5c3be6a4a729d07f23db8d93ec2805b71c5ea0ac1d06724a030b97173dbc8840

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0 This release

2 files

0.34.1

2 files

0.34

2 files

0.33.1

2 files

0.33

2 files

0.32

2 files

0.31

2 files

0.30

2 files

0.29.3

2 files

0.29.2

2 files

0.29.1

2 files

0.29

2 files

0.28

2 files

0.26

2 files

0.25

2 files

0.24

2 files

0.23

2 files

0.22

2 files

0.21

2 files

0.20

2 files

0.19

2 files

0.18

2 files

0.17

2 files

0.16

2 files

0.14

2 files

0.13

2 files

0.12

2 files

0.11.1

2 files

0.11

2 files

0.10

2 files

0.9

2 files

0.8

2 files

0.7.7

2 files

0.7.6

2 files

0.7.5

2 files

0.7.4

2 files

0.7.3

2 files

0.7.2

2 files

0.7.1

2 files

0.7.0

2 files

0.6.0

2 files

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