Skip to main content

Extract structured astrophysical information from NASA GCN circulars using an LLM via DeepSeek.

Project description

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

From PyPI (recommended)

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_Rr 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.

Project details


Download files

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

Source Distribution

gcn_circular_llm-0.4.0.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

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

gcn_circular_llm-0.4.0-py3-none-any.whl (22.1 kB view details)

Uploaded Python 3

File details

Details for the file gcn_circular_llm-0.4.0.tar.gz.

File metadata

  • Download URL: gcn_circular_llm-0.4.0.tar.gz
  • Upload date:
  • Size: 21.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for gcn_circular_llm-0.4.0.tar.gz
Algorithm Hash digest
SHA256 4c76891447a9652923a39f7da68cf7df9e9c544528e70520a1dafe5c2ea5d812
MD5 657afc4414e29b0d7b9585f210ac9339
BLAKE2b-256 d45a79085f24abc45d8812bef7d84ea9093e9e7c4b21e909390eb8506319d309

See more details on using hashes here.

File details

Details for the file gcn_circular_llm-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for gcn_circular_llm-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 59546c4a4eb68596a5c835dfcfa2e2ad1cdf24961871c100f51b2d41178f6982
MD5 4720099d228d710a3f14d4ac2286c045
BLAKE2b-256 b9f11888a300dad3e25c962d84528852a2f7ad61be1d877b3b0d5298d96abf78

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page