Skip to main content

GCN Circular LLM Parser (gcn-circular-llm)

Python 3.10+ License: MIT

A lightweight Python package for extracting structured astrophysical information from NASA GCN (Gamma-ray Coordinates Network) circulars using an LLM via any OpenAI-compatible API (DeepSeek, OpenAI, Minimax, etc.).

Features

  • Fetch circulars for a given transient event from the NASA GCN archive
  • Extract structured fields with an LLM:
    • Event coordinates (RA, Dec, system, error)
    • Redshift and host galaxy
    • Classification (e.g. Long GRB, SGRB, Supernova)
    • Flux / magnitude measurements with UTC timestamps and optional MJD
    • Observations and instrument references
    • A one-sentence summary per circular
  • Post-extraction validation automatically checks completeness and fills gaps:
    • Cross-fills missing coordinates, redshift, event type from sibling circulars
    • Propagates flux measurement times across matching bands/instruments
    • Regex fallback extracts RA/Dec, redshift, and UTC timestamps from raw text
    • Flags circulars needing manual review in needs_review.json
  • Organized output — all results land in output/<event>/ with JSON, CSV, full extraction log, and review file
  • Export light-curve CSV that aggregates all measurements across circulars with automatic UTC/MJD cross-fill and standardized photometric band names

Installation

pip install gcn-circular-llm

From source

git clone git@github.com:LAujust/gcn_parser.git
cd gcn_parser
pip install .

Requirements

  • Python >= 3.10
  • An API key for any OpenAI-compatible LLM provider

Configuration

Set up your LLM provider via environment variables or a .env file.

Supported env vars

Env Var Default Description
LLM_API_KEY (falls back to DEEPSEEK_API_KEY) API key for your LLM provider
LLM_BASE_URL https://api.deepseek.com API base URL
LLM_MODEL deepseek-v4-flash Default model name

Provider examples

Create a .env file in your working directory (see .env.example for the template):

DeepSeek (default):

LLM_API_KEY=sk-...
# Uses default base URL and model — no additional config needed

OpenAI:

LLM_BASE_URL=https://api.openai.com/v1
LLM_API_KEY=sk-...
LLM_MODEL=gpt-4o

Minimax:

LLM_BASE_URL=https://api.minimax.chat/v1
LLM_API_KEY=your-key-here
LLM_MODEL=minimax-m2.5

For backward compatibility, DEEPSEEK_API_KEY is still supported as a fallback for LLM_API_KEY.

Usage

CLI

After installation, the gcn-parser command is available globally:

# Basic extraction — writes to output/GRB250101A/
gcn-parser GRB250101A

# Specify output directory
gcn-parser GRB250101A -d my_results/GRB250101A

# Use a different model
gcn-parser GRB250101A -m deepseek-v4-pro

# Use OpenAI directly (requires LLM_BASE_URL + LLM_API_KEY in .env)
gcn-parser GRB250101A -m gpt-4o

# Enable debug logging
gcn-parser GRB250101A -v

# List all options
gcn-parser --help

CLI options

Option Description
event Event identifier, e.g. GRB250101A or EP260321a
-d, --outdir Output directory (default: output/<event>)
-m, --model Override the default model (LLM_MODEL env var or deepseek-v4-flash)
-v, --verbose Enable debug-level logging

Output directory structure (after a run):

output/GRB250101A/
  ├── GRB250101A.json      # Full extraction results with _filled_from annotations
  ├── GRB250101A.csv       # Light-curve CSV
  ├── extraction.log       # Timestamped log of the full run
  └── needs_review.json    # Circulars requiring manual inspection

You can also run it as a Python module:

python -m gcn_parser GRB250101A -d output/GRB250101A

Python API

Use the package programmatically in your own scripts:

from gcn_parser import (
    fetch_event_circulars,
    extract_circular,
    cross_fill,
    cross_fill_flux_time,
    check_completeness,
    regex_fallback,
    OutputManager,
)

# Fetch all circulars for an event
circulars = fetch_event_circulars("EP260321a")

# Extract each circular
results = []
for c in circulars:
    extraction = extract_circular(c["text"], model="deepseek-v4-flash")
    results.append({
        "gcn": c["gcn"],
        "extraction": extraction.model_dump(by_alias=True),
        "raw_text": c["text"],
    })

# Post-extraction validation
results = cross_fill(results)            # fill top-level fields from siblings
results = cross_fill_flux_time(results)  # propagate flux times across bands

for r in results:
    missing = check_completeness(r["extraction"])
    if missing:
        fb = regex_fallback(r["raw_text"])
        # apply fb["coordinates"], fb["redshift"], fb["utc_times"] ...

# Write organized output
out = OutputManager("EP260321a")
out.attach_log()
out.write_json(results)
out.write_csv(results)
out.detach_log()

Output

JSON

Each circular produces an object with the following schema. Fields auto-filled from sibling circulars or regex carry a _filled_from annotation tracing their provenance:

[
  {
    "gcn": "GCN 12345",
    "extraction": {
      "event_type": "GRB",
      "coordinates": {
        "ra": "12:34:56.78",
        "dec": "+12:34:56.7",
        "system": "J2000",
        "error_arcsec": 1.2
      },
      "redshift": 0.5,
      "host_galaxy": "Host Galaxy Name",
      "classification": "Long GRB",
      "flux_magnitude": [
        {
          "value": 18.5,
          "err": null,
          "band": "r",
          "instrument": "ZTF",
          "utc": "2025-01-01T12:00:00Z",
          "mjd": null,
          "unit": "AB mag",
          "upper_limit": false
        }
      ],
      "observations": ["Swift/XRT follow-up"],
      "references": ["GCN 12344"],
      "confidence": "high",
      "summary": "...",
      "_filled_from": {
        "coordinates": "GCN 12346",
        "redshift": "GCN 12344"
      }
    }
  }
]

needs_review.json

Circulars that still have missing critical fields after cross-fill and regex fallback are listed with the reason and a snippet of the raw text:

[
  {
    "gcn": "GCN Circular 12347",
    "reason": "missing: flux_magnitude (empty)",
    "raw_text_snippet": "We report on the detection of..."
  }
]

CSV Light-Curve

The --csv option flattens all flux_magnitude entries across circulars into a single table. Before writing, the exporter performs two clean-up steps automatically:

  1. UTC / MJD cross-fill — if one timestamp field is missing, it is computed from the other (UTC ↔ MJD conversion using the MJD epoch).
  2. Band standardization — common aliases are normalized (e.g. r-band, R band, VT_R → r or R).
Column Description
gcn_number Source circular number
utc Observation time in ISO-8601 UTC
mjd Modified Julian Date (optional)
value Numeric measurement
err Measurement error; for upper limits, value is set to 0 and err stores the limit
unit e.g. mag, AB mag, uJy, mJy/beam
band Standardized photometric band or frequency
instrument Telescope or instrument name

Rows are sorted chronologically (by UTC, with MJD as fallback).

Models & Rate Limiting

The default model is deepseek-v4-flash (via DeepSeek) with a default delay of 2s between batches. If you hit rate limits (429 Too Many Requests), the package automatically retries with exponential backoff.

For faster or higher-accuracy analysis, switch models:

# Use a different DeepSeek model
gcn-parser EP260321a -m deepseek-v4-pro

# Via OpenAI (set LLM_BASE_URL and LLM_API_KEY in .env first)
gcn-parser EP260321a -m gpt-4o

Suggested models

Model Speed Cost Notes
deepseek-v4-flash Fast Low Default; good balance of speed and accuracy
deepseek-v4-pro Medium Medium Higher accuracy; supports thinking mode
gpt-4o Fast Low Higher accuracy for complex circulars

Troubleshooting

Issue Cause Solution
429 Too Many Requests Rate limit hit Add delay between requests or switch to a different model
LLM returned an empty response Model did not produce valid output Retry with a different model (e.g. deepseek-v4-pro)
LLM_API_KEY is not set Missing API key Set LLM_API_KEY (or DEEPSEEK_API_KEY as fallback) in .env or export it. Get your key at https://platform.deepseek.com/api_keys
No circulars found Event name typo or GCN has no circulars Check the exact event name on gcn.nasa.gov

License

This project is licensed under the MIT License. See LICENSE for details.

Metadata

Release files for gcn-circular-llm 0.4.0

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

Source distribution (sdist)

Source distribution for gcn-circular-llm 0.4.0
File Size Uploaded Provenance
gcn_circular_llm-0.4.0.tar.gz 21.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for gcn-circular-llm 0.4.0
File Interpreter ABI Platform
gcn_circular_llm-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.3 kB

Release files / gcn_circular_llm-0.4.0.tar.gz

Download URL gcn_circular_llm-0.4.0.tar.gz
Size 21.2 kB
Tags Source
SHA-256 checksum
How to use checksums
4c76891447a9652923a39f7da68cf7df9e9c544528e70520a1dafe5c2ea5d812
BLAKE2b-256 checksum
How to use checksums
d45a79085f24abc45d8812bef7d84ea9093e9e7c4b21e909390eb8506319d309
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.8

Release files / gcn_circular_llm-0.4.0-py3-none-any.whl

Download URL gcn_circular_llm-0.4.0-py3-none-any.whl
Size 22.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
59546c4a4eb68596a5c835dfcfa2e2ad1cdf24961871c100f51b2d41178f6982
BLAKE2b-256 checksum
How to use checksums
b9f11888a300dad3e25c962d84528852a2f7ad61be1d877b3b0d5298d96abf78
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.8

Security for gcn-circular-llm 0.4.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.

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