# UI.py import gradio as gr # La importación de process_and_plot ya no es necesaria aquí, # la función de procesamiento se pasará como argumento a create_interface. def create_interface(process_function_for_button): """ Esta función crea la interfaz de usuario y la devuelve. Conecta el botón de submit a la 'process_function_for_button' proporcionada. """ with gr.Blocks(theme='upsatwal/mlsc_tiet') as demo: # O usa gr.themes.Soft() o tu theme preferido gr.Markdown("# Modelado de Bioprocesos con Ecuaciones Personalizadas y Análisis por IA") with gr.Row(): with gr.Column(scale=2): gr.Markdown("### Carga de Datos y Configuración General") 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' ) with gr.Column(scale=1): gr.Markdown("### Conteo de Ecuaciones a Probar") biomass_eq_count_ui = gr.Number(label="Biomasa (1-3)", value=1, minimum=1, maximum=3, precision=0, step=1) substrate_eq_count_ui = gr.Number(label="Sustrato (1-3)", value=1, minimum=1, maximum=3, precision=0, step=1) product_eq_count_ui = gr.Number(label="Producto (1-3)", value=1, minimum=1, maximum=3, precision=0, step=1) # --- Sección de Biomasa --- with gr.Accordion("Ecuaciones y Parámetros de Biomasa", open=True): with gr.Row(): with gr.Column(): biomass_eq1_ui = gr.Textbox(label="Ecuación de Biomasa 1", value="Xm * (1 - exp(-um * (t - t_lag)))", lines=2, placeholder="Ej: Xm * (1 - exp(-um * (t - t_lag)))") biomass_param1_ui = gr.Textbox(label="Parámetros Biomasa 1", value="Xm, um, t_lag", info="Nombres de parámetros, coma sep. Use 't' para tiempo. 'X_val' para X(t) en S/P.") biomass_bound1_ui = gr.Textbox(label="Límites Biomasa 1", value="(0, np.inf), (0, np.inf), (0, np.inf)", info="Formato: (low,high) para cada param. Use np.inf.") # Columna 2 para Biomasa (inicialmente oculta) biomass_col2 = gr.Column(visible=False) with biomass_col2: biomass_eq2_ui = gr.Textbox(label="Ecuación de Biomasa 2", value="X0 * exp(um * t)", lines=2) 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 (inicialmente oculta) biomass_col3 = gr.Column(visible=False) with biomass_col3: biomass_eq3_ui = gr.Textbox(label="Ecuación de Biomasa 3", lines=2) biomass_param3_ui = gr.Textbox(label="Parámetros Biomasa 3") biomass_bound3_ui = gr.Textbox(label="Límites Biomasa 3") # --- Sección de Sustrato --- with gr.Accordion("Ecuaciones y Parámetros de Sustrato", open=True): gr.Markdown("Para ecuaciones de Sustrato y Producto que dependen de la biomasa X(t), usa la variable `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 no debe ser cero substrate_col2 = gr.Column(visible=False) with substrate_col2: substrate_eq2_ui = gr.Textbox(label="Ecuación de Sustrato 2", lines=2) substrate_param2_ui = gr.Textbox(label="Parámetros Sustrato 2") substrate_bound2_ui = gr.Textbox(label="Límites Sustrato 2") substrate_col3 = gr.Column(visible=False) with substrate_col3: substrate_eq3_ui = gr.Textbox(label="Ecuación de Sustrato 3", lines=2) substrate_param3_ui = gr.Textbox(label="Parámetros Sustrato 3") substrate_bound3_ui = gr.Textbox(label="Límites Sustrato 3") # --- Sección de Producto --- with gr.Accordion("Ecuaciones y Parámetros de Producto", open=True): 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 = gr.Column(visible=False) with product_col2: product_eq2_ui = gr.Textbox(label="Ecuación de Producto 2", lines=2) product_param2_ui = gr.Textbox(label="Parámetros Producto 2") product_bound2_ui = gr.Textbox(label="Límites Producto 2") product_col3 = gr.Column(visible=False) with product_col3: product_eq3_ui = gr.Textbox(label="Ecuación de Producto 3", lines=2) product_param3_ui = gr.Textbox(label="Parámetros Producto 3") product_bound3_ui = gr.Textbox(label="Límites Producto 3") # Lógica para mostrar/ocultar campos de ecuación dinámicamente # La función `update_visibility` devuelve una tupla de diccionarios para Gradio def update_visibility_fn(count): return gr.Column(visible=count >= 2), gr.Column(visible=count >= 3) biomass_eq_count_ui.change(fn=update_visibility_fn, inputs=biomass_eq_count_ui, outputs=[biomass_col2, biomass_col3]) substrate_eq_count_ui.change(fn=update_visibility_fn, inputs=substrate_eq_count_ui, outputs=[substrate_col2, substrate_col3]) product_eq_count_ui.change(fn=update_visibility_fn, inputs=product_eq_count_ui, outputs=[product_col2, product_col3]) submit_button = gr.Button("Procesar y Analizar", variant="primary", scale=1) gr.Markdown("## Resultados del Análisis") with gr.Row(): image_output = gr.Image(label="Gráfico Generado", type="pil", width=600, height=900, scale=2, show_download_button=True) 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 ) # Inicializar la visibilidad correctamente al cargar la demo # para los campos de ecuación 2 y 3. def initial_visibility_setup(val_b, val_s, val_p): return ( update_visibility_fn(val_b)[0], update_visibility_fn(val_b)[1], update_visibility_fn(val_s)[0], update_visibility_fn(val_s)[1], update_visibility_fn(val_p)[0], update_visibility_fn(val_p)[1] ) demo.load( fn=initial_visibility_setup, inputs=[biomass_eq_count_ui, substrate_eq_count_ui, product_eq_count_ui], outputs=[ biomass_col2, biomass_col3, substrate_col2, substrate_col3, product_col2, product_col3 ] ) return demo