BioRAG / UI.py
C2MV's picture
Upload 2 files
3f7e7e6 verified
raw
history blame
12.3 kB
# 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