Real-time atmospheric risk index API
AtmoIndex computes rolling 30-day hazard indices for any geographic location, providing risk scores (0-100) for hurricanes, tornadoes, floods, and wildfires. It also implements intelligent alert logic with day-1/day-3/day-7 thresholds and reminders based on severity and location changes.
- Multi-hazard scoring: Hurricane, tornado, flood, wildfire, plus composite score
- Rolling 30-day window: Historical (past 30d) + forecast (16d forward, extrapolated to 30d)
- Smart alerts: Initial alerts, severity changes (≥10 delta), location changes, and sudden spikes (≥25 delta)
- Flexible caching: Redis for production, in-memory fallback for development
- Clean architecture: Weather adapter design allows easy swap to NOAA/NWS/NHC/SPC
Each hazard uses weather data proxies to compute 0-100 risk scores:
- Flood: Precipitation-based (100mm → ~100 score)
- Hurricane: Wind gust-based (12 m/s → 0, 26 m/s → 100)
- Tornado: Gust delta + raw gust (crude proxy; future: CAPE/SRH)
- Wildfire: Dryness (7-day precip), heat (tmax), wind (wspd)
- Composite: Average of all four hazards
The /v1/watch endpoint tracks risk over time and generates alerts:
- D7 (day 7): "Storm to watch" - Early warning for high risk (score ≥ 70)
- D3 (day 3): "Storm we're watching" - Medium-term alert
- D1 (day 1): "Storm imminent" or "Sudden spike" (day1 - day2 ≥ 25)
Reminders are sent when:
- Location changes: Geohash bucket changes (6-char hash)
- Severity changes: Any hazard score changes by ≥10 points
- Risk clears: All hazards drop below 70 threshold
Alert types: [INIT], [LOC], [SEV], [SPIKE], [CLEAR]
# Create virtual environment
python3.11 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -e .
# Install dev dependencies (for tests)
pip install -e ".[dev]"
# Run server (in-memory mode)
uvicorn atmoindex.app.main:app --host 0.0.0.0 --port 8080 --reload
# Or use make
make dev
make run# Copy environment template
cp .env.example .env
# Start services
docker compose up -d
# View logs
docker compose logs -f api
# Stop services
docker compose down# Run all tests
pytest -q
# Or use make
make test
# With coverage
pytest --cov=atmoindex --cov-report=htmlCompute hazard index for a location.
Parameters:
lat(float): Latitude, -90 to 90lon(float): Longitude, -180 to 180
Response:
{
"input": {"lat": 25.7617, "lon": -80.1918},
"day1": {
"date": "2024-01-15",
"hurr": 45,
"torn": 32,
"flood": 67,
"fire": 12,
"comp": 39
},
"day3": { "date": "2024-01-17", "hurr": 52, ... },
"day7": { "date": "2024-01-21", "hurr": 61, ... },
"meta": {
"src": "open-meteo",
"past_days": 30,
"fwd_days": 16,
"extrapolated": true
}
}Compute index and check for alerts.
Body:
{
"lat": 25.7617,
"lon": -80.1918
}Response:
{
"input": {"lat": 25.7617, "lon": -80.1918},
"alerts": [
"[INIT] D7 storm to watch: FLOOD=82, HURR=75",
"[SEV] D3 severity: HURR:70->84"
],
"day1": { ... },
"day3": { ... },
"day7": { ... },
"meta": { ... }
}Health check endpoint.
Response:
{
"status": "ok",
"cache": "redis"
}curl "http://localhost:8080/v1/index?lat=25.7617&lon=-80.1918"curl -X POST "http://localhost:8080/v1/watch" \
-H "Content-Type: application/json" \
-d '{"lat": 25.7617, "lon": -80.1918}'curl -s "http://localhost:8080/v1/index?lat=25.7617&lon=-80.1918" | jq .Environment variables (optional):
REDIS_URL: Redis connection URL (e.g.,redis://localhost:6379/0)- If not set, uses in-memory cache
PORT: Server port (default: 8080)
Current scoring uses simplified weather data proxies:
- Tornado risk doesn't use CAPE (Convective Available Potential Energy) or storm-relative helicity
- Hurricane risk is wind-based only; doesn't account for pressure or storm structure
- Wildfire risk is a basic combination of dry/hot/windy conditions
- Forecast limited to 16 days: Open-Meteo provides 16-day forecasts; days 17-30 repeat day-16 values (marked in metadata)
- No real-time storm tracking: Doesn't integrate live hurricane tracks or tornado warnings
- No spatial extent: Point-based only; doesn't account for storm size or affected area
- Integrate NOAA/NWS/NHC/SPC data sources
- Add CAPE/SRH for better tornado scoring
- Polygon overlap detection for affected areas
- Slack/email webhook notifications
- Historical risk database for trends
- Mobile app integration
- Multi-location watchlist management
atmoindex/
├── app/
│ ├── main.py # FastAPI routes + app factory
│ ├── models.py # Pydantic schemas
│ ├── deps.py # Settings + cache (Redis/in-mem)
│ ├── svc_met.py # Weather adapter (Open-Meteo)
│ ├── svc_score.py # Hazard scoring functions
│ ├── svc_alert.py # Alert logic + watchlist
│ └── utils.py # Helpers (clamp, geohash, etc.)
└── tests/
├── test_index.py # /v1/index tests
├── test_watch.py # /v1/watch alert tests
└── test_score.py # Scoring unit tests
Contributions welcome! Please:
- Fork the repo
- Create a feature branch
- Add tests for new functionality
- Ensure
pytestpasses - Submit a PR
MIT License - see LICENSE file for details.
For issues or questions:
- Open an issue on GitHub
- Check existing issues for known problems
- Review the API docs above
Built with FastAPI, httpx, and Pydantic. Weather data from Open-Meteo.