spherex-helium is a Python package and command-line tool for producing a one-day metastable helium intensity plot from public SPHEREx Level 2 data.
The tool is intentionally date-driven: the user provides one UT observing date, and the package finds the corresponding SPHEREx band 1 FITS files, reads them from IRSA cloud storage, computes the He I intensity for every valid exposure, and overlays the north/south polar-pass points selected from JPL Horizons orbit geometry.
This package currently processes SPHEREx band 1 only because the metastable helium line targeted by this workflow lies in band 1. The wavelength grid and Gaussian fitting window are therefore fixed to the band 1 analysis setup:
wavelength range: 0.734-1.116 um
fit window: 1.06-1.11 um
Other SPHEREx bands are not exposed as command-line options because they do not contain this metastable helium feature for the present analysis goal.
.
|-- README.md
|-- pyproject.toml
|-- src/
| `-- spherex_helium/
| |-- __init__.py
| |-- classification.py
| |-- cli.py
| |-- discovery.py
| |-- fitsio.py
| |-- horizons.py
| |-- pipeline.py
| |-- plotting.py
| |-- processing.py
| |-- timeutils.py
| `-- types.py
`-- tests/
|-- test_core.py
`-- test_pipeline_local.py
The source code follows the standard src/ package layout.
From this repository:
python3 -m pip install -e ".[test]"After installation, the command-line entry point is:
spherex-helium --helpYou can also run directly from the source tree without installing:
PYTHONPATH=src python3 -m spherex_helium.cli --helpFor a full 2025-12-21 band 1 run:
PYTHONPATH=src python3 -m spherex_helium.cli 2025-12-21 \
--output he_20251221.png \
--save-csv he_20251221.csv \
--prefilter-workers 32 \
--process-workers 4Do not use --max-files for a science run. It is only for short smoke tests.
The required positional argument is a UT date:
spherex-helium YYYY-MM-DDFor example:
spherex-helium 2025-12-21The output plot covers 00:00:00 through 24:00:00 UT for that date.
By default the package requests a JPL Horizons observer table for Earth observed from SPHEREx:
Target body: Earth
Observer location: @SPHEREx
Time span: requested UT date
Step size: 1 min
Time digits: fractional seconds
Angle format: decimal degrees
Quantities: 14,23
Quantity 14 provides Observer sub-longitude and Observer sub-latitude. Quantity 23 provides the S-O-T angle used for the optional max-SOT vertical markers in the legacy-style plot.
You can provide a pre-downloaded Horizons text file instead:
spherex-helium 2025-12-21 \
--horizons-file SOT1221.txt \
--output he_20251221.pngThe Horizons file must contain the data section between $$SOE and $$EOE.
The default data source is auto. It uses the public IRSA/SPHEREx S3 bucket:
bucket: nasa-irsa-spherex
root prefix: qr2/level2
band: 1
The public cloud layout is organized by planning period rather than by observing date. The package therefore:
- Lists planning-period prefixes under
qr2/level2. - Prioritizes prefixes near the requested ISO week.
- Enters the Level 2 processing-version directory.
- Keeps only the band 1 directory, i.e. the
/1/detector/band path. - Uses S3 byte-range reads to inspect FITS headers.
- Selects files whose observation time falls on the requested date.
For 2025-12-21, the real public S3 discovery currently resolves to 516 band 1 FITS files. The first and last discovered files are:
first: s3://nasa-irsa-spherex/qr2/level2/2025W51_2A/l2b-v21-2025-357/1/level2_2025W51_2A_0516_1D1_spx_l2b-v21-2025-357.fits
last: s3://nasa-irsa-spherex/qr2/level2/2025W51_2A/l2b-v21-2025-357/1/level2_2025W51_2A_0743_1D1_spx_l2b-v21-2025-357.fits
For each discovered FITS file, the package reads the observation timestamp from the FITS header, preferring:
DATE-AVG
DATE-BEG
DATE-OBS
DATE
It then matches that timestamp to the nearest one-minute Horizons sample. By default the maximum allowed difference is 90 seconds:
--horizons-match-tolerance 90The full-day intensity curve is computed from all valid band 1 FITS files.
Horizons orbit geometry is used only to decide which points should be highlighted:
North: Observer sub-latitude >= +80 deg
South: Observer sub-latitude <= -80 deg
Other: all other valid exposures
The threshold can be changed:
--orbit-pole-lat-threshold 80For 2025-12-21, the default 80 deg threshold labels 37 highlighted polar-pass points among the 516 band 1 files:
North: 15
South: 22
Other: remaining valid exposures
The SPS_ELAT value from the FITS header is no longer used for the default polar selection. It is still written to the CSV for comparison.
For each selected date-matched band 1 FITS file, the package opens the FITS directly from S3 using Astropy/fsspec. It does not stage the entire day of FITS files on local disk.
For each FITS file:
- Read the
IMAGEHDU. - Read the
FLAGSHDU when available. - Keep pixels with
FLAGS == 0. - Set flagged pixels to
NaN. - Skip files with no usable finite pixels or insufficient fitting samples.
The intensity calculation follows the original script logic:
- Average the masked image along axis 1 to form a spectrum.
- Create the band 1 wavelength grid from
0.734to1.116 um. - Flip the spectrum to match the original wavelength ordering.
- Estimate a continuum/background level using iterative one-standard-deviation masks.
- Subtract that background.
- Fit a Gaussian plus offset over
1.06-1.11 um. - Convert the Gaussian integral to Rayleigh using:
rayleigh_conversion_factor = 1.751e4
The CSV output stores the fitted Gaussian parameters and the final intensity.
The plot contains:
black dash-dot curve: full-day He I intensity from all valid band 1 FITS files
red open circles: Horizons-selected north polar points
blue open stars: Horizons-selected south polar points
gray vertical lines: max S-O-T markers, when Horizons S-O-T data are available
The output image is saved as PNG.
The command prints progress bars to the terminal:
Matching Horizons: [#########-------------------] 168/516 32%
Processing FITS: [############----------------] 240/516 46%
Matching Horizons performs small FITS-header reads and orbit matching. It is network-latency dominated because it only needs small byte ranges from S3.
Processing FITS opens the full image data and runs the intensity calculation. It is heavier because it reads larger FITS content and performs numerical fitting.
The recommended acceleration settings are:
--prefilter-workers 32 \
--process-workers 4--prefilter-workers 32 means up to 32 small header reads can happen concurrently. This usually speeds up the Horizons matching step because many small network requests are waiting on S3 response latency.
--process-workers 4 means up to 4 FITS images are processed concurrently. This can speed up the full processing step, but setting it too high may slow the run down because S3 bandwidth, memory, and CPU fitting all start competing.
Good starting values:
local laptop: --prefilter-workers 16 or 32, --process-workers 2 or 4
AWS EC2 us-east-1: --prefilter-workers 32 or 64, --process-workers 4 or 8
Disable progress output with:
--no-progressdate
The observing date in YYYY-MM-DD format.
spherex-helium 2025-12-21--output PATH
PNG plot output path.
--output he_20251221.png--save-csv PATH
Optional CSV output path.
--save-csv he_20251221.csvThe CSV columns are:
time
intensity_rayleigh
label
beta
orbit_sub_lon
orbit_sub_lat
filename
uri
gaussian_amp
gaussian_mu
gaussian_sigma
gaussian_offset
--data-source auto
Default. Discover band 1 FITS from the public IRSA/SPHEREx S3 bucket.
--data-source local
Read FITS files from a local directory:
spherex-helium 2025-12-21 \
--data-source local \
--local-dir /path/to/fits \
--horizons-file SOT1221.txt \
--output he_local.png--data-source s3-prefix
List FITS files under a known S3 prefix:
spherex-helium 2025-12-21 \
--data-source s3-prefix \
--s3-prefix s3://nasa-irsa-spherex/qr2/level2/2025W51_2A/l2b-v21-2025-357 \
--output he_s3prefix.png--data-source manifest
Read one URI or local path per line from a text manifest:
spherex-helium 2025-12-21 \
--data-source manifest \
--manifest spherex_20251221_uris.txt \
--output he_manifest.png--data-source sia
Use the IRSA SIA interface. This is retained as a fallback, but the default S3 discovery is preferred for date-driven processing.
--horizons-file PATH
Use a local Horizons table instead of requesting the JPL API.
--no-fetch-horizons
Skip Horizons download. Use this only when you do not need S-O-T overlays or Horizons polar labels, or when using another classification mode.
--horizons-quantities TEXT
Horizons observer-table quantities. The default is:
--horizons-quantities 14,23Quantity 14 is required for the default orbit-based polar labels.
--classification horizons-orbit
Default. Label polar points using Horizons Observer sub-latitude.
--classification beta
Legacy comparison mode. Label points from the FITS header beta value, using SPS_ELAT.
--classification file-list
Legacy comparison mode. Label points from external north/south file lists:
spherex-helium 2025-12-21 \
--classification file-list \
--polar-list-dir /path/to/polar-lists \
--data-source local \
--local-dir /path/to/fits \
--output he_filelist.pngThe directory must contain:
north_pole_spherex_file_ids.txt
south_pole_spherex_file_ids.txt
--orbit-pole-lat-threshold FLOAT
Absolute Observer sub-latitude threshold for Horizons polar labels. Default:
--orbit-pole-lat-threshold 80--horizons-match-tolerance FLOAT
Maximum time difference in seconds between FITS DATE-AVG and the nearest Horizons sample. Default:
--horizons-match-tolerance 90--prefilter-workers N
Parallel workers for small FITS-header reads during Horizons matching. Default:
--prefilter-workers 16--process-workers N
Parallel workers for full FITS image processing. Default:
--process-workers 4--max-files N
Process only the first N discovered band 1 FITS files. This is for smoke tests only.
--max-files 5--no-progress
Disable progress bars.
--s3-bucket NAME
Default:
--s3-bucket nasa-irsa-spherex--s3-root-prefix PREFIX
Default:
--s3-root-prefix qr2/level2--s3-week-padding N
Number of neighboring ISO weeks to inspect around the requested date. Default:
--s3-week-padding 1from datetime import date
from pathlib import Path
from spherex_helium import RunConfig, run_day
result = run_day(
RunConfig(
observing_date=date(2025, 12, 21),
output_path=Path("he_20251221.png"),
save_csv_path=Path("he_20251221.csv"),
prefilter_workers=32,
process_workers=4,
)
)
print(result.count)Use a short smoke test before a full run:
PYTHONPATH=src python3 -m spherex_helium.cli 2025-12-21 \
--max-files 5 \
--output smoke.png \
--save-csv smoke.csvExpected behavior:
Found 5 band 1 FITS files for 2025-12-21
Matching Horizons: ... 5/5 100%
Processing FITS: ... 5/5 100%
Saved smoke.png
Processed N FITS files; skipped M.
PYTHONPATH=src python3 -m spherex_helium.cli 2025-12-21 \
--output he_20251221.png \
--save-csv he_20251221.csv \
--prefilter-workers 32 \
--process-workers 4For 2025-12-21, public S3 discovery has been verified to find 516 band 1 files. With the default 80 deg orbit threshold, 37 of those files are highlighted as polar-pass points while the full valid set is used for the intensity curve.
The package is configured with pyproject.toml and exposes the console script:
spherex-helium = spherex_helium.cli:main
Build a wheel locally with:
python3 -m pip wheel . --no-deps -w distInstall the generated wheel with:
python3 -m pip install dist/spherex_helium-0.1.0-py3-none-any.whlFor editable development:
python3 -m pip install -e ".[test]"Run tests:
PYTHONPATH=src python3 -m pytest -qSPHEREx data are public IRSA products. For published work, include the SPHEREx acknowledgement requested by IRSA.
The most efficient AWS location for this workflow is generally close to the public S3 bucket region documented by IRSA, us-east-1, because the package streams data from nasa-irsa-spherex.