-
Notifications
You must be signed in to change notification settings - Fork 0
API Reference
MitraSETI exposes a REST API via FastAPI. The interactive Swagger UI documentation is available at http://localhost:8000/docs when the server is running.
uvicorn api.main:app --host 0.0.0.0 --port 8000System health check. Returns GPU status, loaded models, disk space, and overall readiness.
Response:
{
"status": "healthy",
"gpu_available": true,
"gpu_device": "mps",
"model_loaded": true,
"ood_calibrated": true,
"disk_free_gb": 142.3,
"rust_core_available": true
}Example:
curl http://localhost:8000/healthUpload and process a .fil or .h5 file through the full pipeline (de-Doppler search, RFI filtering, ML classification, OOD detection, catalog cross-reference).
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
file |
file | Yes | Filterbank file (.fil or .h5) |
source_name |
string | No | Source name (e.g., "Voyager-1") |
ra |
float | No | Right ascension in degrees |
dec |
float | No | Declination in degrees |
Response:
{
"observation_id": 1,
"file": "voyager1.h5",
"source_name": "Voyager-1",
"total_signals": 847,
"candidates_found": 1,
"rfi_rejected": 824,
"processing_time_ms": 60,
"candidates": [
{
"id": 1,
"frequency_hz": 8419921066.0,
"drift_rate": 0.3928,
"snr": 245.7,
"classification": "narrowband_drifting",
"confidence": 0.982,
"rfi_score": 0.05,
"ood_score": 0.12,
"is_anomaly": false
}
]
}Example:
curl -X POST http://localhost:8000/process \
-F "file=@data/voyager1.h5" \
-F "source_name=Voyager-1" \
-F "ra=286.86" \
-F "dec=12.17"List detected signals with optional filters. Returns paginated results ordered by SNR (descending).
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
min_snr |
float | — | Minimum SNR filter |
max_snr |
float | — | Maximum SNR filter |
min_drift |
float | — | Minimum drift rate (Hz/s) |
max_drift |
float | — | Maximum drift rate (Hz/s) |
classification |
string | — | Filter by signal class (e.g., "narrowband_drifting") |
is_candidate |
bool | — | Filter to candidates only |
observation_id |
int | — | Filter by observation |
limit |
int | 100 | Maximum results to return |
offset |
int | 0 | Pagination offset |
Response:
{
"signals": [
{
"id": 1,
"frequency_hz": 8419921066.0,
"drift_rate": 0.3928,
"snr": 245.7,
"rfi_score": 0.05,
"classification": "narrowband_drifting",
"confidence": 0.982,
"is_candidate": true,
"is_verified": false,
"observation_id": 1,
"detected_at": "2025-01-15T08:00:32",
"ra": 286.86,
"dec": 12.17,
"bandwidth_hz": 2.8,
"notes": null
}
],
"total": 847,
"limit": 100,
"offset": 0
}Examples:
# All signals with SNR > 20
curl "http://localhost:8000/signals?min_snr=20"
# Only candidates
curl "http://localhost:8000/signals?is_candidate=true"
# Narrowband drifting signals from a specific observation
curl "http://localhost:8000/signals?classification=narrowband_drifting&observation_id=1"
# Paginate through results
curl "http://localhost:8000/signals?limit=50&offset=50"Retrieve a single signal by its ID.
Response:
{
"id": 1,
"frequency_hz": 8419921066.0,
"drift_rate": 0.3928,
"snr": 245.7,
"rfi_score": 0.05,
"classification": "narrowband_drifting",
"confidence": 0.982,
"is_candidate": true,
"is_verified": false,
"observation_id": 1,
"detected_at": "2025-01-15T08:00:32",
"image_path": null,
"ra": 286.86,
"dec": 12.17,
"bandwidth_hz": 2.8,
"notes": null
}Example:
curl http://localhost:8000/signals/1Update a signal's classification, verification status, or notes. Used by researchers to manually review and annotate signals.
Request Body:
{
"classification": "candidate_et",
"is_verified": true,
"notes": "Confirmed drifting signal at Voyager-1 carrier frequency"
}All fields are optional — only provided fields are updated.
Response:
Returns the updated signal object.
Example:
curl -X PATCH http://localhost:8000/signals/1 \
-H "Content-Type: application/json" \
-d '{"is_verified": true, "notes": "Confirmed Voyager-1 carrier"}'List signals promoted to ET candidate status, ordered by SNR (descending). This is a convenience endpoint equivalent to GET /signals?is_candidate=true.
Response:
{
"candidates": [
{
"id": 1,
"signal_id": 1,
"observation_id": 1,
"frequency_hz": 8419921066.0,
"drift_rate": 0.3928,
"snr": 245.7,
"classification": "narrowband_drifting",
"confidence": 0.982,
"catalog_matches": [
{
"catalog": "SIMBAD",
"source_name": "Voyager 1",
"distance_arcmin": 0.02
}
],
"astrolens_match": null,
"notes": null,
"created_at": "2025-01-15T08:00:32"
}
],
"total": 1
}Example:
curl http://localhost:8000/candidatesAggregate processing statistics across all observations.
Response:
{
"total_observations": 48,
"total_signals": 89432,
"total_candidates": 15,
"total_rfi_rejected": 87210,
"avg_processing_time_ms": 320,
"avg_signals_per_observation": 1863,
"candidate_rate": 0.017,
"rfi_rate": 0.975,
"classifications": {
"narrowband_drifting": 142,
"narrowband_stationary": 1823,
"broadband": 234,
"pulsed": 12,
"chirp": 3,
"rfi_terrestrial": 45210,
"rfi_satellite": 42000,
"noise": 8,
"candidate_et": 0
}
}Example:
curl http://localhost:8000/statsCross-reference sky coordinates against SIMBAD, NVSS, FIRST, and ATNF Pulsar catalogs. Results are cached for 24 hours.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ra |
float | Yes | Right ascension in degrees |
dec |
float | Yes | Declination in degrees |
radius_arcmin |
float | No (default: 5.0) | Search radius in arcminutes |
Response:
{
"ra": 286.86,
"dec": 12.17,
"radius_arcmin": 5.0,
"matches": [
{
"catalog": "SIMBAD",
"source_name": "Voyager 1",
"ra": 286.862,
"dec": 12.171,
"distance_arcmin": 0.02,
"flux_density": null,
"spectral_type": "Spacecraft",
"notes": "NASA deep space probe"
},
{
"catalog": "NVSS",
"source_name": "NVSS J190726+121015",
"ra": 286.86,
"dec": 12.17,
"distance_arcmin": 1.3,
"flux_density": 12.4,
"spectral_type": null,
"notes": "1.4 GHz continuum source"
}
],
"is_known_source": true,
"closest_match": {
"catalog": "SIMBAD",
"source_name": "Voyager 1",
"distance_arcmin": 0.02
}
}Example:
curl "http://localhost:8000/catalog/crossref?ra=286.86&dec=12.17&radius_arcmin=5"Check for AstroLens optical anomalies near a radio position. Requires AstroLens artifacts to be available.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ra |
float | Yes | Right ascension in degrees |
dec |
float | Yes | Declination in degrees |
radius_arcmin |
float | No (default: 2.0) | Search radius in arcminutes |
Response:
{
"ra": 286.86,
"dec": 12.17,
"radius_arcmin": 2.0,
"anomalies_found": 0,
"matches": []
}Example:
curl "http://localhost:8000/astrolens/crossref?ra=286.86&dec=12.17"WebSocket endpoint for real-time signal updates during processing. Clients receive JSON messages as signals are detected and classified.
Message Types:
{
"type": "signal_detected",
"data": {
"frequency_hz": 8419921066.0,
"drift_rate": 0.3928,
"snr": 245.7,
"classification": "narrowband_drifting",
"confidence": 0.982
}
}{
"type": "processing_complete",
"data": {
"file": "voyager1.h5",
"total_signals": 847,
"candidates": 1,
"processing_time_ms": 60
}
}{
"type": "candidate_found",
"data": {
"id": 1,
"frequency_hz": 8419921066.0,
"drift_rate": 0.3928,
"snr": 245.7,
"classification": "narrowband_drifting"
}
}Example (Python):
import asyncio
import websockets
import json
async def listen():
async with websockets.connect("ws://localhost:8000/ws/live") as ws:
async for message in ws:
data = json.loads(message)
if data["type"] == "candidate_found":
print(f"Candidate: {data['data']['frequency_hz']} Hz, "
f"SNR {data['data']['snr']}")
asyncio.run(listen())Example (JavaScript):
const ws = new WebSocket("ws://localhost:8000/ws/live");
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === "candidate_found") {
console.log(`Candidate: ${data.data.frequency_hz} Hz, SNR ${data.data.snr}`);
}
};All endpoints return standard HTTP error codes with JSON bodies:
{
"detail": "Signal with id 999 not found"
}| Code | Meaning |
|---|---|
| 400 | Bad request (invalid parameters) |
| 404 | Resource not found |
| 422 | Validation error (missing required fields) |
| 500 | Internal server error |
CORS is enabled for all origins by default, allowing browser-based clients to connect from any domain. Configure allowed origins in api/main.py for production deployments.