Add aerosol pipeline
Browse files- app.py +125 -0
- requirements.txt +14 -0
app.py
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
app.py — Gradio Space para HuggingFace.
|
| 3 |
+
Solo UI: llama via HTTP al api_server.py que corre en el droplet AMD.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import os
|
| 7 |
+
import base64
|
| 8 |
+
import io
|
| 9 |
+
import requests
|
| 10 |
+
import gradio as gr
|
| 11 |
+
from PIL import Image
|
| 12 |
+
|
| 13 |
+
API_URL = os.environ.get("API_URL", "http://localhost:7860")
|
| 14 |
+
|
| 15 |
+
VARIABLES = [
|
| 16 |
+
"Optical_Depth_Land_And_Ocean",
|
| 17 |
+
"Image_Optical_Depth_Land_And_Ocean",
|
| 18 |
+
"Angstrom_Exponent_1_Ocean",
|
| 19 |
+
"Mass_Concentration_Land",
|
| 20 |
+
]
|
| 21 |
+
|
| 22 |
+
def run_download(concept_id, bbox_w, bbox_s, bbox_e, bbox_n,
|
| 23 |
+
date_start, date_end, n_granules, hdf_dir):
|
| 24 |
+
try:
|
| 25 |
+
r = requests.post(f"{API_URL}/download", json={
|
| 26 |
+
"concept_id": concept_id,
|
| 27 |
+
"bbox_west": bbox_w, "bbox_south": bbox_s,
|
| 28 |
+
"bbox_east": bbox_e, "bbox_north": bbox_n,
|
| 29 |
+
"date_start": date_start, "date_end": date_end,
|
| 30 |
+
"n_granules": int(n_granules),
|
| 31 |
+
"hdf_dir": hdf_dir,
|
| 32 |
+
}, timeout=300)
|
| 33 |
+
return r.json().get("log", "Sin respuesta")
|
| 34 |
+
except Exception as e:
|
| 35 |
+
return f"Error: {e}"
|
| 36 |
+
|
| 37 |
+
def run_pipeline(hdf_dir, output_dir, plots_dir, db_url, variable):
|
| 38 |
+
try:
|
| 39 |
+
r = requests.post(f"{API_URL}/pipeline", json={
|
| 40 |
+
"hdf_dir": hdf_dir,
|
| 41 |
+
"output_dir": output_dir,
|
| 42 |
+
"plots_dir": plots_dir,
|
| 43 |
+
"db_url": db_url,
|
| 44 |
+
"variable": variable,
|
| 45 |
+
}, timeout=600)
|
| 46 |
+
data = r.json()
|
| 47 |
+
images = []
|
| 48 |
+
for img in data.get("images", []):
|
| 49 |
+
raw = base64.b64decode(img["b64"])
|
| 50 |
+
images.append(Image.open(io.BytesIO(raw)))
|
| 51 |
+
status = (
|
| 52 |
+
f"Pipeline completado\n"
|
| 53 |
+
f"Filas cargadas: {data.get('rows_loaded', 0):,}\n"
|
| 54 |
+
f"Graficas: {data.get('plots_count', 0)}"
|
| 55 |
+
)
|
| 56 |
+
return status, images
|
| 57 |
+
except Exception as e:
|
| 58 |
+
return f"Error: {e}", []
|
| 59 |
+
|
| 60 |
+
def run_full(concept_id, bbox_w, bbox_s, bbox_e, bbox_n,
|
| 61 |
+
date_start, date_end, n_granules,
|
| 62 |
+
hdf_dir, output_dir, plots_dir, db_url, variable):
|
| 63 |
+
dl_log = run_download(concept_id, bbox_w, bbox_s, bbox_e, bbox_n,
|
| 64 |
+
date_start, date_end, n_granules, hdf_dir)
|
| 65 |
+
status, images = run_pipeline(hdf_dir, output_dir, plots_dir, db_url, variable)
|
| 66 |
+
return dl_log + "\n\n" + status, images
|
| 67 |
+
|
| 68 |
+
with gr.Blocks(title="AMD MI300X Aerosol Pipeline") as demo:
|
| 69 |
+
gr.Markdown("# AMD MI300X Aerosol Pipeline Demo\nDescarga datos MODIS y genera visualizaciones de aerosoles con agentes LangGraph en AMD MI300X.")
|
| 70 |
+
|
| 71 |
+
with gr.Tabs():
|
| 72 |
+
with gr.TabItem("1 Descarga"):
|
| 73 |
+
with gr.Row():
|
| 74 |
+
ci1 = gr.Textbox(label="Concept ID", value="C1443528505-LAADS")
|
| 75 |
+
ng1 = gr.Slider(1, 20, value=5, step=1, label="N granules")
|
| 76 |
+
with gr.Row():
|
| 77 |
+
bw1 = gr.Number(label="Lon W", value=-10)
|
| 78 |
+
bs1 = gr.Number(label="Lat S", value=20)
|
| 79 |
+
be1 = gr.Number(label="Lon E", value=10)
|
| 80 |
+
bn1 = gr.Number(label="Lat N", value=50)
|
| 81 |
+
with gr.Row():
|
| 82 |
+
ds1 = gr.Textbox(label="Fecha inicio", value="2003-07-04")
|
| 83 |
+
de1 = gr.Textbox(label="Fecha fin", value="2003-07-05")
|
| 84 |
+
hd1 = gr.Textbox(label="HDF dir", value="/tmp/earthdata")
|
| 85 |
+
btn1 = gr.Button("Descargar", variant="primary")
|
| 86 |
+
out1 = gr.Textbox(label="Log", lines=10)
|
| 87 |
+
btn1.click(run_download, [ci1,bw1,bs1,be1,bn1,ds1,de1,ng1,hd1], out1)
|
| 88 |
+
|
| 89 |
+
with gr.TabItem("2 Pipeline"):
|
| 90 |
+
hd2 = gr.Textbox(label="HDF dir", value="/tmp/earthdata")
|
| 91 |
+
od2 = gr.Textbox(label="CSV dir", value="/tmp/aerosol_csv")
|
| 92 |
+
pd2 = gr.Textbox(label="Plots dir", value="/tmp/aerosol_plots")
|
| 93 |
+
db2 = gr.Textbox(label="DB URL", value="", type="password")
|
| 94 |
+
va2 = gr.Dropdown(VARIABLES, label="Variable", value=VARIABLES[0])
|
| 95 |
+
btn2 = gr.Button("Ejecutar pipeline", variant="primary")
|
| 96 |
+
st2 = gr.Textbox(label="Estado", lines=5)
|
| 97 |
+
gl2 = gr.Gallery(label="Graficas", columns=3, height=500)
|
| 98 |
+
btn2.click(run_pipeline, [hd2,od2,pd2,db2,va2], [st2,gl2])
|
| 99 |
+
|
| 100 |
+
with gr.TabItem("3 Flujo completo"):
|
| 101 |
+
with gr.Row():
|
| 102 |
+
ci3 = gr.Textbox(label="Concept ID", value="C1443528505-LAADS")
|
| 103 |
+
ng3 = gr.Slider(1, 20, value=5, step=1, label="N granules")
|
| 104 |
+
with gr.Row():
|
| 105 |
+
bw3 = gr.Number(label="Lon W", value=-10)
|
| 106 |
+
bs3 = gr.Number(label="Lat S", value=20)
|
| 107 |
+
be3 = gr.Number(label="Lon E", value=10)
|
| 108 |
+
bn3 = gr.Number(label="Lat N", value=50)
|
| 109 |
+
with gr.Row():
|
| 110 |
+
ds3 = gr.Textbox(label="Fecha inicio", value="2003-07-04")
|
| 111 |
+
de3 = gr.Textbox(label="Fecha fin", value="2003-07-05")
|
| 112 |
+
hd3 = gr.Textbox(label="HDF dir", value="/tmp/earthdata")
|
| 113 |
+
od3 = gr.Textbox(label="CSV dir", value="/tmp/aerosol_csv")
|
| 114 |
+
pd3 = gr.Textbox(label="Plots dir", value="/tmp/aerosol_plots")
|
| 115 |
+
db3 = gr.Textbox(label="DB URL", value="", type="password")
|
| 116 |
+
va3 = gr.Dropdown(VARIABLES, label="Variable", value=VARIABLES[0])
|
| 117 |
+
btn3 = gr.Button("Ejecutar todo", variant="primary")
|
| 118 |
+
lg3 = gr.Textbox(label="Log", lines=12)
|
| 119 |
+
im3 = gr.Gallery(label="Graficas", columns=3, height=500)
|
| 120 |
+
btn3.click(run_full, [ci3,bw3,bs3,be3,bn3,ds3,de3,ng3,hd3,od3,pd3,db3,va3], [lg3,im3])
|
| 121 |
+
|
| 122 |
+
gr.Markdown("---\nPowered by AMD MI300X | vLLM | LangGraph | NASA EarthData | MODIS MYD04_3K")
|
| 123 |
+
|
| 124 |
+
if __name__ == "__main__":
|
| 125 |
+
demo.launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
openai>=1.0.0
|
| 2 |
+
langgraph>=0.2.0
|
| 3 |
+
langchain>=0.3.0
|
| 4 |
+
langchain-openai>=0.2.0
|
| 5 |
+
langchain-mcp-adapters>=0.1.0
|
| 6 |
+
mcp>=1.0.0
|
| 7 |
+
earthaccess>=0.9.0
|
| 8 |
+
pyhdf>=0.11.0
|
| 9 |
+
numpy>=1.26.0
|
| 10 |
+
pandas>=2.2.0
|
| 11 |
+
matplotlib>=3.9.0
|
| 12 |
+
psycopg2-binary>=2.9.0
|
| 13 |
+
python-dotenv>=1.0.0
|
| 14 |
+
tqdm>=4.66.0
|