| import numpy as np |
| import gradio as gr |
| import joblib |
| import tensorflow as tf |
| import pandas as pd |
|
|
| MODEL_PATH = "./NN_12_feat.keras" |
| SCALER_PATH = "./scaler.pkl" |
|
|
| |
| model = tf.keras.models.load_model(MODEL_PATH) |
| scaler = joblib.load(SCALER_PATH) |
|
|
| |
|
|
| FEATURE_NAMES = ['Angular Width (deg)', |
| 'MPA (deg)', |
| 'Linear Speed (km/s)', |
| '2nd ord. Final Linear Speed (km/s)', |
| 'Mass (g)', |
| 'Bx (nT)', |
| 'Bz (nT)', |
| 'Proton Temperature (K)', |
| 'Flow Speed (km/s)', |
| 'Flow Longitude (deg)', |
| 'Alpha to Proton Ratio', |
| 'Plasma Pressure (nPa)'] |
|
|
| |
| |
| '''RANGES = { |
| name: {"min": 0.0, "max": 1.0, "step": 0.01, "value": 0.5} |
| for name in FEATURE_NAMES |
| }''' |
|
|
| RANGES = { |
| "Angular Width (deg)": { |
| "min": 0, "max": 360, "step": 1, "value": 180, "unit": "deg" |
| }, |
| "MPA (deg)": { |
| "min": 0, "max": 360, "step": 1, "value": 180, "unit": "deg" |
| }, |
| "Linear Speed (km/s)": { |
| "min": 100, "max": 3000, "step": 10, "value": 800, "unit": "km/s" |
| }, |
| "2nd ord. Final Linear Speed (km/s)": { |
| "min": 100, "max": 3000, "step": 10, "value": 800, "unit": "km/s" |
| }, |
| "Mass (g)": { |
| "min": 1e12, "max": 1e17, "step": 1e12, "value": 5e14, "unit": "g" |
| }, |
| "Bx (nT)": { |
| "min": -20, "max": 20, "step": 0.5, "value": 0, "unit": "nT" |
| }, |
| "Bz (nT)": { |
| "min": -40, "max": 20, "step": 0.5, "value": -10, "unit": "nT" |
| }, |
| "Proton Temperature (K)": { |
| "min": 1e3, "max": 2e6, "step": 1e3, "value": 1e5, "unit": "K" |
| }, |
| "Flow Speed (km/s)": { |
| "min": 100, "max": 1000, "step": 10, "value": 500, "unit": "km/s" |
| }, |
| "Flow Longitude (deg)": { |
| "min": -10, "max": 10, "step": 1, "value": 0, "unit": "deg" |
| }, |
| "Alpha to Proton Ratio": { |
| "min": 0, "max": 10, "step": 0.005, "value": 0.02, "unit": "" |
| }, |
| "Plasma Pressure (nPa)": { |
| "min": 0, "max": 20, "step": 0.1, "value": 2, "unit": "nPa" |
| } |
| } |
|
|
| |
| THRESH_FAST = 24 |
| THRESH_MED = 48 |
|
|
| def _predict_from_vector(x_raw: np.ndarray) -> float: |
| """x_raw: shape (12,) sin escalar""" |
| x_scaled = scaler.transform(x_raw.reshape(1, -1)) |
| y = model.predict(x_scaled, verbose=0).reshape(-1)[0] |
| return float(y) |
|
|
| def predict(*inputs): |
| x = np.array(inputs, dtype=float) |
|
|
| y = _predict_from_vector(x) |
|
|
| |
| if y <= THRESH_FAST: |
| label = "Rápida" |
| msg = f"🟢 Predicción **rápida**: **{y:.2f} h** (≤ {THRESH_FAST} h)." |
| elif y <= THRESH_MED: |
| label = "Intermedia" |
| msg = f"🟠 Predicción **intermedia**: **{y:.2f} h** (entre {THRESH_FAST} y {THRESH_MED} h)." |
| else: |
| label = "Lenta" |
| msg = f"🔴 Predicción **lenta**: **{y:.2f} h** (> {THRESH_MED} h)." |
|
|
| table = [[FEATURE_NAMES[i], float(x[i])] for i in range(len(FEATURE_NAMES))] |
| |
|
|
| return y, table, msg |
| ''' |
| def what_if(feature_idx, *inputs): |
| x0 = np.array(inputs, dtype=float) |
| fname = FEATURE_NAMES[int(feature_idx)] |
| r = RANGES[fname] |
| |
| xs = np.linspace(r["min"], r["max"], 60) |
| ys = [] |
| for v in xs: |
| x = x0.copy() |
| x[int(feature_idx)] = v |
| ys.append(_predict_from_vector(x)) |
| |
| data = [{"x": float(a), "y": float(b)} for a, b in zip(xs, ys)] |
| title = f"Curva what-if variando: **{fname}**" |
| return data, title''' |
|
|
| def what_if(feature_idx, *inputs): |
| x0 = np.array(inputs, dtype=float) |
|
|
| idx = int(feature_idx) |
| fname = FEATURE_NAMES[idx] |
| r = RANGES[fname] |
|
|
| xs = np.linspace(r["min"], r["max"], 60) |
| ys = [] |
| for v in xs: |
| x = x0.copy() |
| x[idx] = v |
| ys.append(_predict_from_vector(x)) |
|
|
| df = pd.DataFrame({"x": xs.astype(float), "y": np.array(ys, dtype=float)}) |
|
|
| title = f"Curva what-if variando: **{fname}**" |
| return df, title |
|
|
| with gr.Blocks() as demo: |
| gr.Markdown( |
| "## Predicción del tiempo de propagación de una CME\n" |
| "Ingresá los 12 atributos.\n" |
| "Se puede explorar la sensibilidad de cada atributo mediante **what-if**." |
| ) |
|
|
| with gr.Row(): |
| with gr.Column(scale=2): |
| inputs = [] |
| for name in FEATURE_NAMES: |
| r = RANGES[name] |
| inputs.append( |
| gr.Slider( |
| minimum=r["min"], maximum=r["max"], step=r["step"], |
| value=r["value"], |
| label=name |
| ) |
| ) |
| btn = gr.Button("Predecir") |
|
|
| with gr.Column(scale=1): |
| out_value = gr.Number(label="Tiempo de propagación predicho (h)", precision=2) |
| out_table = gr.Dataframe(headers=["Atributo", "Valor"], interactive=False, row_count=12, col_count=2) |
| out_text = gr.Markdown() |
|
|
| btn.click(predict, inputs=inputs, outputs=[out_value, out_table, out_text]) |
|
|
| gr.Markdown("### What-if (sensibilidad)") |
| with gr.Row(): |
| feature_pick = gr.Dropdown( |
| choices=[(f"{i} — {FEATURE_NAMES[i]}", i) for i in range(len(FEATURE_NAMES))], |
| value=0, |
| label="Elegí el atributo a variar" |
| ) |
| whatif_btn = gr.Button("Generar curva") |
|
|
| plot = gr.LinePlot( |
| x="x", y="y", |
| title="Predicción vs valor del atributo", |
| x_title="Valor del atributo", |
| y_title="Tiempo de propagación (h)", |
| height=350 |
| ) |
| plot_title = gr.Markdown() |
|
|
| whatif_btn.click( |
| what_if, |
| inputs=[feature_pick] + inputs, |
| outputs=[plot, plot_title] |
| ) |
|
|
| demo.launch() |