Methodology
How ASTRO-SCAN is engineered. Principles, sources, and decisions.
1. Project context
ASTRO-SCAN is an independent space observation platform engineered solo from Tlemcen, Algeria. It started as a personal sandbox for real-time astronomy and grew into a distributed system covering live spacecraft tracking, space weather, situational awareness, family safety telemetry, and astrophysical observation. Every component is deployed in production on a Hetzner VPS in Hillsboro, Oregon.
The platform is built without external funding, without a team, and without proprietary data. All sources are public APIs from government agencies and open scientific networks.
2. Engineering principles
3. Data sources
All data displayed comes from one of the following public sources. Each source is cached server-side to respect upstream rate limits.
| Domain | Source | License |
|---|---|---|
| ISS orbit (TLE) | AMSAT nasabare.txt | Public |
| Geomagnetic Kp / F10.7 / X-Ray | NOAA SWPC | US Gov public domain |
| Space weather alerts | NOAA SWPC Alerts | US Gov public domain |
| Global earthquakes (24h) | USGS Earthquake Hazards | US Gov public domain |
| Aircraft state vectors | OpenSky Network | CC-BY 4.0 (research) |
| Astronomy picture of the day | NASA APOD | Public |
| Earth imagery | NASA Blue Marble / Black Marble (GIBS) | Public |
| GeoIP country resolution | MaxMind GeoLite2 (local) | CC-BY-SA 4.0 |
4. Derived signals
Some indicators are not directly streamed. They are computed in real time from live inputs. Every formula is documented, auditable, and deterministic. The Global Threat Index displayed in Situational Awareness is computed as follows:
threat_index =
0.35 * normalize(noaa_kp, 0, 9) // Geomagnetic storm
+ 0.20 * normalize(log10(xray_wm2), -8, -3) // Solar flare X-ray
+ 0.25 * seismic_score // USGS 24h aggregate
+ 0.10 * air_traffic_density // OpenSky saturation
+ 0.10 * min(48, tle_age_hours) / 48 * 100 // Data freshness
The seismic sub-score is the estimated shaking intensity at the observatory (Tlemcen), not a count of global earthquakes. A former magnitude-weighted world count made a distant M7 saturate the term to 100 even when nothing was felt on site; it is replaced (SG-A0012) by a site-local intensity. For each event, the Modified Mercalli Intensity (MMI) expected at the observatory is computed with the USGS « Did You Feel It » attenuation relation (Bakun and colleagues), active-crust version:
MMI = 5.07 + 1.09 * M - 3.69 * log10(D_hypo) D_hypo = sqrt(surface_distance_km^2 + depth_km^2) // hypocentral, conservative MMI < 1 -> 0 (not felt) ; MMI bounded to [0, 12] seismic_score = max(MMI over 24h) / 12 * 100 // explicit linear scale -> [0, 100]
Estimated intensity, never measured. The hypocentral
distance is chosen because it is conservative (it never over-estimates intensity)
and reduces to the epicentral distance for a shallow event. The linear
MMI / 12 scale is used because MMI is already an ordinal intensity
scale [0–12]; a linear map preserves its meaning and stays auditable
(MMI 12 total destruction → 100, MMI 0 not felt → 0). A
distant M7 that is not felt contributes 0; a nearby M3.5 that is felt contributes.
Events without usable coordinates or depth are excluded from the calculation and
counted separately (excluded_no_coords), never guessed.
Honesty — known limits. This relation is
calibrated for the Western United States (shallow active crust)
and applied to the Mediterranean for lack of a regionally calibrated relation
— the USGS itself notes these relations have regional dependencies and
encourages operators to develop their own. It ignores site effects
(soil amplification). Its uncertainty is on the order of 0.8 MMI unit.
Observatory coordinates come from the single source of truth
(app/constants/observatory.py), never hardcoded.
5. Stack
- Backend: Python 3.12, Flask (main app), FastAPI (Situational Awareness microservice), httpx, asyncio, uvloop, gunicorn, uvicorn.
- Frontend: vanilla JavaScript (no framework bloat), CesiumJS for 3D globes, Chart.js for time-series, WebSocket for real-time telemetry.
- Astronomy: Skyfield (SGP4 propagation), Astropy (ephemerides), N2YO (ISS pass predictions).
- Infrastructure: Hetzner VPS Hillsboro Oregon US-West, nginx (TLS via Porkbun DNS-01), systemd with hardening, Redis (caching facade).
- Quality: pytest smoke + unit + coverage on Python 3.11 + 3.12, GitHub Actions CI on every push, semantic versioning with descriptive tags.
6. Versioning and operations
Releases follow semantic versioning. The current major release is
v2.7.0-mission-control-live, which adds the Situational
Awareness module. Each release tag carries a descriptive suffix so the
git log itself reads as an engineering narrative.
Production deployment is reproducible from the GitHub repository: clone, install dependencies, set environment variables, enable systemd units. The repository at github.com/za1974ria/astroscan is the single source of truth. CI runs on every push.
7. What this platform is not
ASTRO-SCAN is not a research instrument. It is not a substitute for ESA Space Safety Programme assets, NOAA real-time alerts, or USGS seismic monitoring. It is an aggregator and visualizer. Operational decisions should always be made against the upstream sources directly, which are listed and linked in this document.