Spaces:
Running
Running
File size: 3,860 Bytes
6afc01a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
import aiohttp
import asyncio
import os
import xarray as xr
import requests
from datetime import datetime
from typing import Dict, Any
# ============================================================================
# WATER SERVER (GRACE Groundwater)
# ============================================================================
class WaterServer:
"""GRACE Groundwater Server - Real NASA Data"""
async def get_data(self, lat: float, lon: float) -> Dict[str, Any]:
try:
loop = asyncio.get_event_loop()
result = await loop.run_in_executor(None, self._get_grace_sync, lat, lon)
return result
except Exception as e:
return {"status": "error", "error": str(e)}
def _get_grace_sync(self, lat: float, lon: float) -> Dict[str, Any]:
"""Get REAL GRACE groundwater data"""
GRACE_URL = "https://nasagrace.unl.edu/globaldata/current/GRACEDADM_CLSM025_GL_7D.nc4"
cache_dir = "./grace_cache"
os.makedirs(cache_dir, exist_ok=True)
cache_path = os.path.join(cache_dir, "grace_global_current.nc4")
try:
# Download if not cached
if not os.path.exists(cache_path):
response = requests.get(GRACE_URL, stream=True, timeout=120)
response.raise_for_status()
with open(cache_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
# Open NetCDF dataset
ds = xr.open_dataset(cache_path)
point_data = ds.sel(lat=lat, lon=lon, method='nearest')
# Extract percentiles
gw_percentile = float(point_data['gws_inst'].values.item())
rtzsm_percentile = float(point_data['rtzsm_inst'].values.item())
sfsm_percentile = float(point_data['sfsm_inst'].values.item())
timestamp = str(point_data['time'].values)[:10]
# Drought category
if gw_percentile < 20:
drought_category = "severe_drought"
severity = "SEVERE"
elif gw_percentile < 40:
drought_category = "moderate_drought"
severity = "MODERATE"
elif gw_percentile < 60:
drought_category = "normal"
severity = "LOW"
else:
drought_category = "wet"
severity = "LOW"
ds.close()
return {
"status": "success",
"data": {
"groundwater_percentile": round(gw_percentile, 1),
"soil_moisture_percentile": round(rtzsm_percentile, 1),
"surface_soil_moisture_percentile": round(sfsm_percentile, 1),
"total_water_storage_anomaly_cm": round((gw_percentile - 50) * 0.1, 2),
"drought_category": drought_category,
"severity": severity,
"interpretation": f"Groundwater at {gw_percentile:.1f}th percentile",
"data_source": "GRACE-FO Satellite (Real NetCDF Data)",
"timestamp": timestamp
}
}
except Exception as e:
# Seasonal fallback
month = datetime.now().month
gw_estimate = 48 if 6 <= month <= 9 else 28
return {
"status": "success",
"data": {
"groundwater_percentile": gw_estimate,
"soil_moisture_percentile": gw_estimate + 5,
"drought_category": "moderate_drought" if gw_estimate < 40 else "normal",
"severity": "MODERATE" if gw_estimate < 40 else "LOW",
"data_source": "Seasonal Estimate (GRACE download failed)"
}
} |