File size: 12,317 Bytes
3f7e7e6 d3d8124 3f7e7e6 d3d8124 3f7e7e6 29fefec 3f7e7e6 d3d8124 3f7e7e6 d3d8124 3f7e7e6 d3d8124 3f7e7e6 d3d8124 3f7e7e6 227fa34 |
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# UI.py
import gradio as gr
import numpy as np # Necesario para np.inf en los valores por defecto de los l铆mites
def create_interface(process_function_for_button):
"""
Crea la interfaz de usuario completa para el modelado de bioprocesos.
Conecta el bot贸n de submit a la 'process_function_for_button' proporcionada.
"""
# Usar un tema est谩ndar de Gradio para mayor compatibilidad.
# theme='gradio/soft' es una buena opci贸n. Puedes cambiarlo si tienes un tema personalizado que funcione.
with gr.Blocks(theme='gradio/soft') as demo:
gr.Markdown("# Modelado de Bioprocesos con Ecuaciones Personalizadas y An谩lisis por IA")
gr.Markdown(
"Sube un archivo Excel con columnas 'Tiempo', 'Biomasa', 'Sustrato', 'Producto'. "
"Ingresa tus propias ecuaciones (usando 't' para tiempo y 'X_val' para X(t) en ecuaciones de S/P), "
"los nombres de sus par谩metros, y sus l铆mites. El sistema ajustar谩 los modelos y un LLM analizar谩 los resultados."
)
with gr.Row():
with gr.Column(scale=2):
gr.Markdown("### 1. Carga de Datos y Configuraci贸n General del Gr谩fico")
file_input = gr.File(label="Subir archivo Excel (.xlsx)", file_types=[".xlsx"])
show_legend_ui = gr.Checkbox(label="Mostrar leyenda en gr谩ficos", value=True)
show_params_ui = gr.Checkbox(label="Mostrar par谩metros ajustados en gr谩ficos", value=True)
legend_position_ui = gr.Dropdown(
label="Posici贸n de la leyenda",
choices=['best', 'upper right', 'upper left', 'lower right', 'lower left', 'center left', 'center right', 'lower center', 'upper center', 'center'],
value='best', # String value, esto est谩 bien
type="value"
)
with gr.Column(scale=1):
gr.Markdown("### 2. Conteo de Ecuaciones a Probar")
gr.Markdown("Define cu谩ntas ecuaciones diferentes quieres probar para cada componente (1 a 3).")
# Usar floats para gr.Number, Gradio los maneja bien incluso con precision=0
biomass_eq_count_ui = gr.Number(label="Ecuaciones de Biomasa:", value=1.0, minimum=1.0, maximum=3.0, step=1.0, precision=0)
substrate_eq_count_ui = gr.Number(label="Ecuaciones de Sustrato:", value=1.0, minimum=1.0, maximum=3.0, step=1.0, precision=0)
product_eq_count_ui = gr.Number(label="Ecuaciones de Producto:", value=1.0, minimum=1.0, maximum=3.0, step=1.0, precision=0)
# --- Secci贸n de Biomasa ---
with gr.Accordion("3. Definici贸n de Modelos de Biomasa", open=True):
gr.Markdown("Ingresa la ecuaci贸n (ej: `Xm*(1 - exp(-um*(t - t_lag)))`), los nombres de los par谩metros (ej: `Xm, um, t_lag`), y los l铆mites de los par谩metros (ej: `(0, np.inf), (0, 5), (0, 100)`). Usa `t` como la variable de tiempo.")
with gr.Row():
with gr.Column(): # Columna 1 para Biomasa (siempre visible)
biomass_eq1_ui = gr.Textbox(label="Ecuaci贸n de Biomasa 1", value="Xm * (1 - exp(-um * (t - t_lag)))", lines=2)
biomass_param1_ui = gr.Textbox(label="Par谩metros Biomasa 1", value="Xm, um, t_lag")
biomass_bound1_ui = gr.Textbox(label="L铆mites Biomasa 1", value="(0, np.inf), (0, np.inf), (0, np.inf)")
# Columna 2 para Biomasa
biomass_col2_container = gr.Column(visible=False)
with biomass_col2_container:
biomass_eq2_ui = gr.Textbox(label="Ecuaci贸n de Biomasa 2", value="X0 * exp(um * t)", lines=2) # Ejemplo: Crecimiento exponencial
biomass_param2_ui = gr.Textbox(label="Par谩metros Biomasa 2", value="X0, um")
biomass_bound2_ui = gr.Textbox(label="L铆mites Biomasa 2", value="(0, np.inf), (0, np.inf)")
# Columna 3 para Biomasa
biomass_col3_container = gr.Column(visible=False)
with biomass_col3_container:
biomass_eq3_ui = gr.Textbox(label="Ecuaci贸n de Biomasa 3", lines=2, value="", placeholder="Ej: (X0 * Xm * exp(um * t)) / (Xm - X0 + X0 * exp(um * t))") # Log铆stica
biomass_param3_ui = gr.Textbox(label="Par谩metros Biomasa 3", value="", placeholder="X0, Xm, um")
biomass_bound3_ui = gr.Textbox(label="L铆mites Biomasa 3", value="", placeholder="(0,np.inf),(0,np.inf),(0,np.inf)")
# --- Secci贸n de Sustrato ---
with gr.Accordion("4. Definici贸n de Modelos de Sustrato", open=True):
gr.Markdown("Para Sustrato/Producto, si tu ecuaci贸n depende de la concentraci贸n de biomasa X(t) calculada por un modelo de biomasa, usa `X_val` en tu ecuaci贸n. Ejemplo: `S0 - (X_val / YXS)`.")
with gr.Row():
with gr.Column():
substrate_eq1_ui = gr.Textbox(label="Ecuaci贸n de Sustrato 1", value="S0 - (X_val / YXS) - mS * t", lines=2)
substrate_param1_ui = gr.Textbox(label="Par谩metros Sustrato 1", value="S0, YXS, mS")
substrate_bound1_ui = gr.Textbox(label="L铆mites Sustrato 1", value="(0, np.inf), (1e-9, np.inf), (0, np.inf)") # YXS > 0
substrate_col2_container = gr.Column(visible=False)
with substrate_col2_container:
substrate_eq2_ui = gr.Textbox(label="Ecuaci贸n de Sustrato 2", lines=2, value="")
substrate_param2_ui = gr.Textbox(label="Par谩metros Sustrato 2", value="")
substrate_bound2_ui = gr.Textbox(label="L铆mites Sustrato 2", value="")
substrate_col3_container = gr.Column(visible=False)
with substrate_col3_container:
substrate_eq3_ui = gr.Textbox(label="Ecuaci贸n de Sustrato 3", lines=2, value="")
substrate_param3_ui = gr.Textbox(label="Par谩metros Sustrato 3", value="")
substrate_bound3_ui = gr.Textbox(label="L铆mites Sustrato 3", value="")
# --- Secci贸n de Producto ---
with gr.Accordion("5. Definici贸n de Modelos de Producto", open=True):
gr.Markdown("Similar a Sustrato, usa `X_val` para la dependencia de la biomasa X(t).")
with gr.Row():
with gr.Column():
product_eq1_ui = gr.Textbox(label="Ecuaci贸n de Producto 1", value="P0 + YPX * X_val + mP * t", lines=2)
product_param1_ui = gr.Textbox(label="Par谩metros Producto 1", value="P0, YPX, mP")
product_bound1_ui = gr.Textbox(label="L铆mites Producto 1", value="(0, np.inf), (0, np.inf), (0, np.inf)")
product_col2_container = gr.Column(visible=False)
with product_col2_container:
product_eq2_ui = gr.Textbox(label="Ecuaci贸n de Producto 2", lines=2, value="")
product_param2_ui = gr.Textbox(label="Par谩metros Producto 2", value="")
product_bound2_ui = gr.Textbox(label="L铆mites Producto 2", value="")
product_col3_container = gr.Column(visible=False)
with product_col3_container:
product_eq3_ui = gr.Textbox(label="Ecuaci贸n de Producto 3", lines=2, value="")
product_param3_ui = gr.Textbox(label="Par谩metros Producto 3", value="")
product_bound3_ui = gr.Textbox(label="L铆mites Producto 3", value="")
# L贸gica para mostrar/ocultar campos de ecuaci贸n din谩micamente
def update_eq_visibility(count_value):
try:
# El valor de gr.Number puede ser None si el usuario lo borra
if count_value is None:
count = 0 # O 1, dependiendo de c贸mo quieras manejarlo. 0 ocultar谩 todo.
else:
count = int(float(count_value)) # Convertir a float primero, luego a int
except ValueError:
count = 0 # Si la conversi贸n falla, asumir 0
# gr.update es la forma can贸nica de actualizar propiedades
return gr.update(visible=count >= 2), gr.update(visible=count >= 3)
# Conectar eventos .change() de los contadores a la funci贸n de visibilidad
biomass_eq_count_ui.change(fn=update_eq_visibility, inputs=biomass_eq_count_ui, outputs=[biomass_col2_container, biomass_col3_container])
substrate_eq_count_ui.change(fn=update_eq_visibility, inputs=substrate_eq_count_ui, outputs=[substrate_col2_container, substrate_col3_container])
product_eq_count_ui.change(fn=update_eq_visibility, inputs=product_eq_count_ui, outputs=[product_col2_container, product_col3_container])
# Bot贸n de env铆o
submit_button = gr.Button("Procesar y Analizar Modelos", variant="primary", scale=1, elem_id="submit_button_main")
# Salidas
gr.Markdown("## Resultados del An谩lisis y Modelado")
with gr.Row():
# Para la imagen, type="pil" es bueno si tu funci贸n devuelve un objeto PIL.Image
image_output = gr.Image(label="Gr谩fico Generado de Ajustes", type="pil", scale=2, show_download_button=True, height=750)
with gr.Column(scale=3):
analysis_output = gr.Markdown(label="An谩lisis del Modelo por IA")
# Lista de todos los inputs para el bot贸n de submit
all_inputs_for_button = [
file_input,
biomass_eq1_ui, biomass_eq2_ui, biomass_eq3_ui,
biomass_param1_ui, biomass_param2_ui, biomass_param3_ui,
biomass_bound1_ui, biomass_bound2_ui, biomass_bound3_ui,
substrate_eq1_ui, substrate_eq2_ui, substrate_eq3_ui,
substrate_param1_ui, substrate_param2_ui, substrate_param3_ui,
substrate_bound1_ui, substrate_bound2_ui, substrate_bound3_ui,
product_eq1_ui, product_eq2_ui, product_eq3_ui,
product_param1_ui, product_param2_ui, product_param3_ui,
product_bound1_ui, product_bound2_ui, product_bound3_ui,
legend_position_ui,
show_legend_ui,
show_params_ui,
biomass_eq_count_ui,
substrate_eq_count_ui,
product_eq_count_ui
]
outputs_for_button = [image_output, analysis_output]
# Conexi贸n del bot贸n DENTRO del contexto de Blocks
submit_button.click(
fn=process_function_for_button, # Usa la funci贸n pasada como argumento
inputs=all_inputs_for_button,
outputs=outputs_for_button,
# api_name="process_data" # Opcional, para nombrar el endpoint de la API
)
# Inicializar visibilidad usando demo.load para que se aplique al cargar la UI
def set_initial_visibility_on_load_wrapper(b_c_val, s_c_val, p_c_val):
# Obtener los valores iniciales de los gr.Number components y aplicar la l贸gica de visibilidad.
# Los valores de los Number inputs pueden ser float, convertirlos a int.
b_c_int = int(float(b_c_val)) if b_c_val is not None else 0
s_c_int = int(float(s_c_val)) if s_c_val is not None else 0
p_c_int = int(float(p_c_val)) if p_c_val is not None else 0
b_vis2_upd, b_vis3_upd = update_eq_visibility(b_c_int)
s_vis2_upd, s_vis3_upd = update_eq_visibility(s_c_int)
p_vis2_upd, p_vis3_upd = update_eq_visibility(p_c_int)
# Devolver los resultados de gr.update para cada componente de salida del demo.load
return b_vis2_upd, b_vis3_upd, s_vis2_upd, s_vis3_upd, p_vis2_upd, p_vis3_upd
demo.load(
fn=set_initial_visibility_on_load_wrapper,
inputs=[biomass_eq_count_ui, substrate_eq_count_ui, product_eq_count_ui],
outputs=[
biomass_col2_container, biomass_col3_container,
substrate_col2_container, substrate_col3_container,
product_col2_container, product_col3_container
]
)
return demo |