Satintel / app /main.py
Vedant Jigarbhai Mehta
Deploy FastAPI backend with satellite data for HF Spaces
9e6e107
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.routes import auth, users, satellite, analytics, maps, action_plan, data, health, analysis, green_gap, time_machine
app = FastAPI(
title="Satellite Environmental Intelligence Platform",
description="AETRIX 2026 β€” PS-4: Satellite data analytics for smart cities",
version="1.0.0",
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=False,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(health.router, prefix="/api/v1", tags=["Health"])
app.include_router(auth.router, prefix="/api/v1/auth", tags=["Auth"])
app.include_router(users.router, prefix="/api/v1/users", tags=["Users"])
app.include_router(satellite.router, prefix="/api/v1/satellite", tags=["Satellite"])
app.include_router(analytics.router, prefix="/api/v1/analytics", tags=["Analytics"])
app.include_router(maps.router, prefix="/api/v1/maps", tags=["Maps"])
app.include_router(action_plan.router, prefix="/api/v1/action-plan", tags=["Action Plan"])
app.include_router(data.router, prefix="/api/v1/data", tags=["Data"])
app.include_router(analysis.router, prefix="/api/v1/analysis", tags=["Specialized Analysis"])
app.include_router(green_gap.router, prefix="/api/v1/green-gap", tags=["Green Gap Analysis"])
app.include_router(time_machine.router, prefix="/api/v1/time-machine", tags=["Time Machine"])
@app.on_event("startup")
async def startup():
# Create PostGIS tables if database is configured
try:
from app.models.db_models import create_tables, get_engine
engine = get_engine()
if engine:
await create_tables()
print("PostgreSQL + PostGIS connected, tables ready")
else:
print("No DATABASE_URL configured β€” using in-memory fallback")
except Exception as e:
print(f"Database setup skipped: {e} β€” using in-memory fallback")
print("Satellite Environmental Intelligence Platform started")
# ── Warm up ALL caches in background thread ──────────────
import threading
threading.Thread(target=_warmup_caches, daemon=True).start()
def _warmup_caches():
"""Pre-load all data + run ML models for all 14 cities at startup."""
import time
start = time.time()
try:
from app.utils.cities import CITIES
from app.services import satellite_service, ml_service
params = ["LST", "NDVI", "NO2", "SO2", "CO", "O3", "AEROSOL", "SOIL_MOISTURE"]
ml_params = ["LST", "NDVI", "NO2", "SOIL_MOISTURE"]
city_keys = list(CITIES.keys())
print(f"[WARMUP] Pre-loading data for {len(city_keys)} cities...")
for i, city_key in enumerate(city_keys):
# Load + harmonize all parameters (populates _raw_cache and _data_cache)
for param in params:
try:
satellite_service._load_data(param, city_key)
except Exception:
pass
# Pre-compute heatmap data
for param in params:
try:
satellite_service.get_heatmap_data(param, city_key)
except Exception:
pass
# Pre-compute timeseries
for param in params:
try:
satellite_service.get_timeseries(param, city_key)
except Exception:
pass
# Run ML models (populates _ml_cache)
for param in ml_params:
try:
ml_service.detect_anomalies(param, city_key)
except Exception:
pass
try:
ml_service.find_hotspots(param, city_key)
except Exception:
pass
# Pre-compute city summary (uses cached ML results)
try:
ml_service.get_city_summary(city_key)
except Exception:
pass
print(f"[WARMUP] {city_key} done ({i+1}/{len(city_keys)})")
# Record sync timestamp
try:
from app.services import cache_service
cache_service.set_last_synced()
except Exception:
pass
elapsed = round(time.time() - start, 1)
print(f"[WARMUP] All {len(city_keys)} cities cached in {elapsed}s β€” ready for instant responses")
except Exception as e:
print(f"[WARMUP] Cache warmup error: {e}")
@app.on_event("shutdown")
async def shutdown():
print("Shutting down...")