File size: 8,869 Bytes
d3d8124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# UI.py
import gradio as gr
# La importación de process_and_plot se maneja por modal_app.py
# from interface import process_and_plot

def create_interface():
    """
    Esta función crea la interfaz de usuario y la devuelve para que pueda ser lanzada
    desde app.py utilizando demo.launch().
    """
    
    with gr.Blocks(theme='upsatwal/mlsc_tiet') as demo: # Puede que necesites un theme diferente o default
    # with gr.Blocks(theme=gr.themes.Soft()) as demo: # Alternativa más común
        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")
                biomass_eq_count_ui = gr.Number(label="Número de ecuaciones de Biomasa a probar (1-3)", value=1, minimum=1, maximum=3, precision=0, step=1)
                substrate_eq_count_ui = gr.Number(label="Número de ecuaciones de Sustrato a probar (1-3)", value=1, minimum=1, maximum=3, precision=0, step=1)
                product_eq_count_ui = gr.Number(label="Número de ecuaciones de Producto a probar (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 (ej: Xm * (1 - exp(-um * t)))", value="Xm * (1 - exp(-um * t))", lines=2) # Modelo de Moser simplificado
                    biomass_param1_ui = gr.Textbox(label="Parámetros Biomasa 1 (coma sep., ej: Xm, um, Ks)", value="Xm, um, t_lag", info="Use 't' para tiempo. Use 'Ks' o 't_lag' para fases de retardo si es necesario.")
                    biomass_bound1_ui = gr.Textbox(label="Límites Biomasa 1 (ej: (0,inf),(0,5),(-10,10))", value="(0, inf), (0, inf), (0, inf)", info="Formato: (low,high) para cada param. Use np.inf.")
                with gr.Column(visible=False) as biomass_col2: # Inicialmente oculto
                    biomass_eq2_ui = gr.Textbox(label="Ecuación de Biomasa 2", value="X0 * exp(um * t)", lines=2) # Crecimiento exponencial simple
                    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, inf), (0, inf)")
                with gr.Column(visible=False) as biomass_col3: # Inicialmente oculto
                    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, usa `X_val` para representar la concentración de biomasa calculada X(t). Ejemplo: `S0 - (1/YXS) * (X_val - X0_biomass)`")
            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) # Luedeking-Piret simplificado
                    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, inf), (0.01, inf), (0, inf)")
                with gr.Column(visible=False) as 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")
                with gr.Column(visible=False) as 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) # Luedeking-Piret simplificado
                    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, inf), (0, inf), (0, inf)")
                with gr.Column(visible=False) as 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")
                with gr.Column(visible=False) as 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
        def update_visibility(count, c2, c3):
            return gr.Column(visible=count >= 2), gr.Column(visible=count >= 3)

        biomass_eq_count_ui.change(fn=lambda x: update_visibility(x, biomass_col2, biomass_col3), inputs=biomass_eq_count_ui, outputs=[biomass_col2, biomass_col3])
        substrate_eq_count_ui.change(fn=lambda x: update_visibility(x, substrate_col2, substrate_col3), inputs=substrate_eq_count_ui, outputs=[substrate_col2, substrate_col3])
        product_eq_count_ui.change(fn=lambda x: update_visibility(x, product_col2, product_col3), 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) # Ajusta escala si es necesario
            with gr.Column(scale=3): # Más espacio para el análisis
                analysis_output = gr.Markdown(label="Análisis del Modelo por IA") # Usar Markdown para mejor formato
        
        # Lista de todos los inputs para el botón de submit
        all_inputs = [
            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
        ]
        # La conexión se hace en modal_app.py al inyectar la función de `interface`
        # El atributo `fn` del botón se establecerá allí.
        demo.load(fn=lambda: (gr.Column(visible=False), gr.Column(visible=False)), outputs=[biomass_col2, biomass_col3])
        demo.load(fn=lambda: (gr.Column(visible=False), gr.Column(visible=False)), outputs=[substrate_col2, substrate_col3])
        demo.load(fn=lambda: (gr.Column(visible=False), gr.Column(visible=False)), outputs=[product_col2, product_col3])

    return demo, all_inputs, [image_output, analysis_output], submit_button # Devolver también inputs, outputs y botón