Python library for solar radio astronomy

ecallistolib

Bring e-CALLISTO observations into your Python workflow. Find, download, read, process and plot solar radio dynamic spectra in scripts and notebooks.

v1.5.0Python 3.10–3.14MIT LicenseOpen source · Python API and CLI
From archive to figure

Build your own analysis workflow.

Use the library directly in Python for repeatable analysis, batch processing and notebook exploration.

Find and download

List FITS files by UTC date, hour and station, then download observations with retries and parallel workers.

Read FITS in Python

Open .fit and .fit.gz files as DynamicSpectrum objects with intensity data, frequency and time axes, and observation metadata.

Process and clean

Subtract backgrounds, reduce noise, crop time and frequency ranges, and mitigate radio frequency interference.

Combine observations

Combine frequency bands or time segments, and group files by station and UTC day while retaining provenance.

Plot and compare

Create dynamic spectra and light curves, add official GOES X-ray flux data, and save figures at your chosen DPI.

Explore burst catalogs

Search published burst reports by date, station and type. Preview candidate FITS files before selecting what to download.

Installation

Start with the tools you need.

Use Python 3.10–3.14. Install the download and plotting extras to follow all the examples below.

Terminal · recommended for these examples
python -m pip install "ecallistolib[download,plot]"

Package details, published releases and distribution files are available on ecallistolib on PyPI.

Core library

Read FITS files, process arrays and crop spectra. NumPy and Astropy are included as dependencies.

Terminal · core install
python -m pip install ecallistolib

Optional extras

download
Archive downloads and burst catalog search
plot
Matplotlib spectra and light curves
rfi
SciPy-based RFI mitigation
goes
Official GOES XRS retrieval and netCDF support
Terminal · all extras
python -m pip install "ecallistolib[all]"
Usage examples

A few lines to get started.

Run these examples in your own Python environment. Archive access and catalog searches require an internet connection.

01 · Local FITS file

Read, process and plot

Replace the filename with a downloaded e-CALLISTO observation. This example subtracts the background, clips the intensity range and saves the figure.

Requires the plot extra.
Read, process and plot · Python
import ecallistolib as ecl
import matplotlib.pyplot as plt

spectrum = ecl.read_fits("STATION_20230101_120000_01.fit.gz")
print(spectrum.shape)  # (n_freq, n_time)
print(spectrum.freq_range_mhz)

fig, ax, image = ecl.plot_dynamic_spectrum(
    spectrum,
    process="noise_reduced",
    clip_low=-5,
    clip_high=20,
    title="Solar radio observation",
    dpi=180,
    save_path="observation.png",
)
plt.show()
02 · Archive access

Download observations

Choose a UTC day and hour, and replace the station filter with your instrument’s name. Inspect the listing, then download the selected files.

Requires the download extra.
Download observations · Python
from datetime import date
import ecallistolib as ecl

remote_files = ecl.list_remote_fits(
    day=date(2023, 6, 15),
    hour=14,
    station_substring="station-name",
)
for remote_file in remote_files:
    print(remote_file.name)

paths = ecl.download_files(
    remote_files,
    out_dir="./data",
    workers=4,
    retries=2,
    overwrite="skip",
)
print(paths)
03 · Burst event catalog

Search reported bursts

Search published Type III reports for a UTC date and station. Check coverage and parsing diagnostics even when the search returns no events.

Requires the download extra.
Published reports, with source context.

Catalog search finds reported events; it does not detect or classify bursts in FITS data. Missing reports do not imply zero solar activity.

Search reported bursts · Python
from datetime import date
import ecallistolib as ecl

catalog = ecl.search_bursts(
    date(2026, 9, 1),
    station="BIR",
    burst_type="III",
    cache_dir=".cache/bursts",
)
for event in catalog:
    print(event.start, event.end, event.type_label)

print(catalog.coverage)
print(catalog.diagnostics)

if catalog:
    selection = ecl.list_burst_files(
        catalog[0], stations="BIR", padding_s=120,
    )
    print(selection.by_station)
    print(selection.unresolved_stations)