Update app.py
Browse files
app.py
CHANGED
@@ -69,7 +69,7 @@ class RSM_BoxBehnken:
|
|
69 |
Ajusta el modelo de segundo orden a los datos, eliminando términos no significativos.
|
70 |
"""
|
71 |
formula = f'{self.y_name} ~ {self.x1_name} + {self.x2_name} + ' \
|
72 |
-
f'I({self.x1_name}**2) + I({self.x2_name}**2) + I({self.x3_name}**2)'
|
73 |
self.model_simplified = smf.ols(formula, data=self.data).fit()
|
74 |
print("\nModelo Simplificado:")
|
75 |
print(self.model_simplified.summary())
|
@@ -121,7 +121,7 @@ class RSM_BoxBehnken:
|
|
121 |
|
122 |
# Determinar las variables que varían y sus niveles naturales
|
123 |
varying_variables = [var for var in [self.x1_name, self.x2_name, self.x3_name] if var != fixed_variable]
|
124 |
-
|
125 |
# Establecer los niveles naturales para las variables que varían
|
126 |
x_natural_levels = self.get_levels(varying_variables[0])
|
127 |
y_natural_levels = self.get_levels(varying_variables[1])
|
@@ -224,10 +224,10 @@ class RSM_BoxBehnken:
|
|
224 |
Puedes personalizar este método según tus necesidades.
|
225 |
"""
|
226 |
units = {
|
227 |
-
'
|
228 |
-
'
|
229 |
-
'
|
230 |
-
'
|
231 |
}
|
232 |
return units.get(variable_name, '')
|
233 |
|
@@ -242,11 +242,11 @@ class RSM_BoxBehnken:
|
|
242 |
|
243 |
self.all_figures = [] # Resetear la lista de figuras
|
244 |
|
245 |
-
# Niveles naturales para graficar
|
246 |
levels_to_plot_natural = {
|
247 |
-
self.x1_name: self.
|
248 |
-
self.x2_name: self.
|
249 |
-
self.x3_name: self.
|
250 |
}
|
251 |
|
252 |
# Generar y almacenar gráficos individuales
|
@@ -361,7 +361,7 @@ class RSM_BoxBehnken:
|
|
361 |
'Suma de Cuadrados': [],
|
362 |
'% Contribución': []
|
363 |
})
|
364 |
-
|
365 |
# Calcular porcentaje de contribución para cada factor
|
366 |
for index, row in anova_table.iterrows():
|
367 |
if index != 'Residual':
|
@@ -372,7 +372,7 @@ class RSM_BoxBehnken:
|
|
372 |
factor_name = f'{self.x2_name}^2'
|
373 |
elif factor_name == f'I({self.x3_name} ** 2)':
|
374 |
factor_name = f'{self.x3_name}^2'
|
375 |
-
|
376 |
ss_factor = row['sum_sq']
|
377 |
contribution_percentage = (ss_factor / ss_total) * 100
|
378 |
|
@@ -433,7 +433,7 @@ class RSM_BoxBehnken:
|
|
433 |
# 10. Cuadrados medios
|
434 |
ms_regression = ss_regression / df_regression
|
435 |
ms_residual = ss_residual / df_residual
|
436 |
-
ms_lack_of_fit =
|
437 |
ms_pure_error = ss_pure_error / df_pure_error if not np.isnan(ss_pure_error) else np.nan
|
438 |
|
439 |
# 11. Estadístico F y valor p para la falta de ajuste
|
@@ -449,7 +449,7 @@ class RSM_BoxBehnken:
|
|
449 |
'F': [np.nan, np.nan, f_lack_of_fit, np.nan, np.nan],
|
450 |
'Valor p': [np.nan, np.nan, p_lack_of_fit, np.nan, np.nan]
|
451 |
})
|
452 |
-
|
453 |
# Calcular la suma de cuadrados y grados de libertad para la curvatura
|
454 |
ss_curvature = anova_reduced['sum_sq'][f'I({self.x1_name} ** 2)'] + anova_reduced['sum_sq'][f'I({self.x2_name} ** 2)'] + anova_reduced['sum_sq'][f'I({self.x3_name} ** 2)']
|
455 |
df_curvature = 3
|
@@ -459,7 +459,7 @@ class RSM_BoxBehnken:
|
|
459 |
|
460 |
# Reorganizar las filas para que la curvatura aparezca después de la regresión
|
461 |
detailed_anova_table = detailed_anova_table.reindex([0, 5, 1, 2, 3, 4])
|
462 |
-
|
463 |
# Resetear el índice para que sea consecutivo
|
464 |
detailed_anova_table = detailed_anova_table.reset_index(drop=True)
|
465 |
|
@@ -554,7 +554,7 @@ class RSM_BoxBehnken:
|
|
554 |
font.size = Pt(12)
|
555 |
|
556 |
# Título del informe
|
557 |
-
titulo = doc.add_heading('Informe de Optimización de Producción de
|
558 |
titulo.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
559 |
|
560 |
doc.add_paragraph(f"Fecha: {datetime.now().strftime('%d/%m/%Y %H:%M')}").alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
@@ -595,37 +595,48 @@ class RSM_BoxBehnken:
|
|
595 |
|
596 |
# --- Funciones para la Interfaz de Gradio ---
|
597 |
|
598 |
-
def load_data(
|
599 |
"""
|
600 |
Carga los datos del diseño Box-Behnken desde cajas de texto y crea la instancia de RSM_BoxBehnken.
|
601 |
"""
|
602 |
try:
|
603 |
-
#
|
604 |
-
|
605 |
-
|
606 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
607 |
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
|
|
|
|
613 |
|
614 |
-
# Validar que el DataFrame tenga las columnas correctas
|
615 |
-
if not all(col in data.columns for col in column_names):
|
616 |
-
raise ValueError("El formato de los datos no es correcto.")
|
617 |
|
618 |
# Crear la instancia de RSM_BoxBehnken
|
619 |
global rsm
|
620 |
rsm = RSM_BoxBehnken(data, x1_name, x2_name, x3_name, y_name, x1_levels, x2_levels, x3_levels)
|
621 |
|
622 |
-
return data.round(3),
|
623 |
-
|
624 |
except Exception as e:
|
625 |
# Mostrar mensaje de error
|
626 |
error_message = f"Error al cargar los datos: {str(e)}"
|
627 |
print(error_message)
|
628 |
-
return None,
|
|
|
629 |
|
630 |
def fit_and_optimize_model():
|
631 |
if 'rsm' not in globals():
|
@@ -639,14 +650,14 @@ def fit_and_optimize_model():
|
|
639 |
prediction_table = rsm.generate_prediction_table()
|
640 |
contribution_table = rsm.calculate_contribution_percentage()
|
641 |
anova_table = rsm.calculate_detailed_anova()
|
642 |
-
|
643 |
-
# Generar todas las figuras
|
644 |
rsm.generate_all_plots()
|
645 |
-
|
646 |
# Formatear la ecuación para que se vea mejor en Markdown
|
647 |
equation_formatted = equation.replace(" + ", "<br>+ ").replace(" ** ", "^").replace("*", " × ")
|
648 |
equation_formatted = f"### Ecuación del Modelo Simplificado:<br>{equation_formatted}"
|
649 |
-
|
650 |
# Guardar las tablas en Excel temporal
|
651 |
excel_path = rsm.save_tables_to_excel()
|
652 |
|
@@ -658,7 +669,7 @@ def fit_and_optimize_model():
|
|
658 |
pareto_completo,
|
659 |
model_simplificado.summary().as_html(),
|
660 |
pareto_simplificado,
|
661 |
-
|
662 |
optimization_table,
|
663 |
prediction_table,
|
664 |
contribution_table,
|
@@ -680,17 +691,17 @@ def navigate_plot(direction, current_index, all_figures):
|
|
680 |
"""
|
681 |
if not all_figures:
|
682 |
return None, "No hay gráficos disponibles.", current_index
|
683 |
-
|
684 |
if direction == 'left':
|
685 |
new_index = (current_index - 1) % len(all_figures)
|
686 |
elif direction == 'right':
|
687 |
new_index = (current_index + 1) % len(all_figures)
|
688 |
else:
|
689 |
new_index = current_index
|
690 |
-
|
691 |
selected_fig = all_figures[new_index]
|
692 |
plot_info_text = f"Gráfico {new_index + 1} de {len(all_figures)}"
|
693 |
-
|
694 |
return selected_fig, plot_info_text, new_index
|
695 |
|
696 |
def download_current_plot(all_figures, current_index):
|
@@ -702,12 +713,12 @@ def download_current_plot(all_figures, current_index):
|
|
702 |
fig = all_figures[current_index]
|
703 |
img_bytes = rsm.save_fig_to_bytes(fig)
|
704 |
filename = f"Grafico_RSM_{current_index + 1}.png"
|
705 |
-
|
706 |
# Crear un archivo temporal
|
707 |
with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as temp_file:
|
708 |
temp_file.write(img_bytes)
|
709 |
temp_path = temp_file.name
|
710 |
-
|
711 |
return temp_path # Retornar solo la ruta
|
712 |
|
713 |
def download_all_plots_zip():
|
@@ -749,39 +760,19 @@ def exportar_word(rsm_instance, tables_dict):
|
|
749 |
|
750 |
def create_gradio_interface():
|
751 |
with gr.Blocks() as demo:
|
752 |
-
gr.Markdown("# Optimización de la
|
753 |
-
|
754 |
with gr.Row():
|
755 |
with gr.Column():
|
756 |
-
gr.Markdown("## Configuración del
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
x1_levels_input = gr.Textbox(label="Niveles de X1 (separados por comas)", value="1, 3.5, 5.5")
|
762 |
-
x2_levels_input = gr.Textbox(label="Niveles de X2 (separados por comas)", value="0.03, 0.2, 0.3")
|
763 |
-
x3_levels_input = gr.Textbox(label="Niveles de X3 (separados por comas)", value="0.4, 0.65, 0.9")
|
764 |
-
data_input = gr.Textbox(label="Datos del Experimento (formato CSV)", lines=10, value="""1,-1,-1,0,166.594
|
765 |
-
2,1,-1,0,177.557
|
766 |
-
3,-1,1,0,127.261
|
767 |
-
4,1,1,0,147.573
|
768 |
-
5,-1,0,-1,188.883
|
769 |
-
6,1,0,-1,224.527
|
770 |
-
7,-1,0,1,190.238
|
771 |
-
8,1,0,1,226.483
|
772 |
-
9,0,-1,-1,195.550
|
773 |
-
10,0,1,-1,149.493
|
774 |
-
11,0,-1,1,187.683
|
775 |
-
12,0,1,1,148.621
|
776 |
-
13,0,0,0,278.951
|
777 |
-
14,0,0,0,297.238
|
778 |
-
15,0,0,0,280.896""")
|
779 |
-
load_button = gr.Button("Cargar Datos")
|
780 |
-
|
781 |
with gr.Column():
|
782 |
gr.Markdown("## Datos Cargados")
|
783 |
data_output = gr.Dataframe(label="Tabla de Datos", interactive=False)
|
784 |
-
|
785 |
# Sección de análisis visible solo después de cargar los datos
|
786 |
with gr.Row(visible=False) as analysis_row:
|
787 |
with gr.Column():
|
@@ -801,11 +792,11 @@ def create_gradio_interface():
|
|
801 |
gr.Markdown("## Descargar Todas las Tablas")
|
802 |
download_excel_button = gr.DownloadButton("Descargar Tablas en Excel")
|
803 |
download_word_button = gr.DownloadButton("Descargar Tablas en Word")
|
804 |
-
|
805 |
with gr.Column():
|
806 |
gr.Markdown("## Generar Gráficos de Superficie de Respuesta")
|
807 |
-
fixed_variable_input = gr.Dropdown(label="Variable Fija", choices=["
|
808 |
-
fixed_level_input = gr.Slider(label="Nivel de Variable Fija", minimum
|
809 |
plot_button = gr.Button("Generar Gráficos")
|
810 |
with gr.Row():
|
811 |
left_button = gr.Button("<")
|
@@ -817,14 +808,14 @@ def create_gradio_interface():
|
|
817 |
download_all_plots_button = gr.DownloadButton("Descargar Todos los Gráficos (ZIP)")
|
818 |
current_index_state = gr.State(0) # Estado para el índice actual
|
819 |
all_figures_state = gr.State([]) # Estado para todas las figuras
|
820 |
-
|
821 |
-
# Cargar datos
|
822 |
load_button.click(
|
823 |
load_data,
|
824 |
-
inputs=[
|
825 |
-
outputs=[data_output,
|
826 |
)
|
827 |
-
|
828 |
# Ajustar modelo y optimizar
|
829 |
fit_button.click(
|
830 |
fit_and_optimize_model,
|
@@ -843,7 +834,7 @@ def create_gradio_interface():
|
|
843 |
download_excel_button # Ruta del Excel de tablas
|
844 |
]
|
845 |
)
|
846 |
-
|
847 |
# Generar y mostrar los gráficos
|
848 |
plot_button.click(
|
849 |
lambda fixed_var, fixed_lvl: (
|
@@ -855,7 +846,7 @@ def create_gradio_interface():
|
|
855 |
inputs=[fixed_variable_input, fixed_level_input],
|
856 |
outputs=[rsm_plot_output, plot_info, current_index_state, all_figures_state]
|
857 |
)
|
858 |
-
|
859 |
# Navegación de gráficos
|
860 |
left_button.click(
|
861 |
lambda current_index, all_figures: navigate_plot('left', current_index, all_figures),
|
@@ -867,46 +858,43 @@ def create_gradio_interface():
|
|
867 |
inputs=[current_index_state, all_figures_state],
|
868 |
outputs=[rsm_plot_output, plot_info, current_index_state]
|
869 |
)
|
870 |
-
|
871 |
# Descargar gráfico actual
|
872 |
download_plot_button.click(
|
873 |
download_current_plot,
|
874 |
inputs=[all_figures_state, current_index_state],
|
875 |
outputs=download_plot_button
|
876 |
)
|
877 |
-
|
878 |
# Descargar todos los gráficos en ZIP
|
879 |
download_all_plots_button.click(
|
880 |
download_all_plots_zip,
|
881 |
inputs=[],
|
882 |
outputs=download_all_plots_button
|
883 |
)
|
884 |
-
|
885 |
# Descargar todas las tablas en Excel y Word
|
886 |
download_excel_button.click(
|
887 |
fn=lambda: download_all_tables_excel(),
|
888 |
inputs=[],
|
889 |
outputs=download_excel_button
|
890 |
)
|
891 |
-
|
892 |
download_word_button.click(
|
893 |
fn=lambda: exportar_word(rsm, rsm.get_all_tables()),
|
894 |
inputs=[],
|
895 |
outputs=download_word_button
|
896 |
)
|
897 |
-
|
898 |
# Ejemplo de uso
|
899 |
-
gr.Markdown("##
|
900 |
gr.Markdown("""
|
901 |
-
1.
|
902 |
-
2.
|
903 |
-
3.
|
904 |
-
4.
|
905 |
-
5.
|
906 |
-
6.
|
907 |
-
7. Navega entre los gráficos usando los botones '<' y '>'.
|
908 |
-
8. Descarga el gráfico actual en PNG o descarga todos los gráficos en un ZIP.
|
909 |
-
9. Descarga todas las tablas en un archivo Excel o Word con los botones correspondientes.
|
910 |
""")
|
911 |
|
912 |
return demo
|
@@ -918,4 +906,4 @@ def main():
|
|
918 |
interface.launch(share=True)
|
919 |
|
920 |
if __name__ == "__main__":
|
921 |
-
main()
|
|
|
69 |
Ajusta el modelo de segundo orden a los datos, eliminando términos no significativos.
|
70 |
"""
|
71 |
formula = f'{self.y_name} ~ {self.x1_name} + {self.x2_name} + ' \
|
72 |
+
f'I({self.x1_name}**2) + I({self.x2_name}**2) + I({self.x3_name}**2)' # Adjusted formula to include x3^2
|
73 |
self.model_simplified = smf.ols(formula, data=self.data).fit()
|
74 |
print("\nModelo Simplificado:")
|
75 |
print(self.model_simplified.summary())
|
|
|
121 |
|
122 |
# Determinar las variables que varían y sus niveles naturales
|
123 |
varying_variables = [var for var in [self.x1_name, self.x2_name, self.x3_name] if var != fixed_variable]
|
124 |
+
|
125 |
# Establecer los niveles naturales para las variables que varían
|
126 |
x_natural_levels = self.get_levels(varying_variables[0])
|
127 |
y_natural_levels = self.get_levels(varying_variables[1])
|
|
|
224 |
Puedes personalizar este método según tus necesidades.
|
225 |
"""
|
226 |
units = {
|
227 |
+
'Glucosa_g_L': 'g/L',
|
228 |
+
'Proteina_Pescado_g_L': 'g/L',
|
229 |
+
'Sulfato_Manganeso_g_L': 'g/L',
|
230 |
+
'Abs_600nm': '' # No units for Absorbance
|
231 |
}
|
232 |
return units.get(variable_name, '')
|
233 |
|
|
|
242 |
|
243 |
self.all_figures = [] # Resetear la lista de figuras
|
244 |
|
245 |
+
# Niveles naturales para graficar - Using levels from the data context, not Box-Behnken design levels.
|
246 |
levels_to_plot_natural = {
|
247 |
+
self.x1_name: sorted(list(set(self.data[self.x1_name]))), # Using unique values from data
|
248 |
+
self.x2_name: sorted(list(set(self.data[self.x2_name]))), # Using unique values from data
|
249 |
+
self.x3_name: sorted(list(set(self.data[self.x3_name]))) # Using unique values from data
|
250 |
}
|
251 |
|
252 |
# Generar y almacenar gráficos individuales
|
|
|
361 |
'Suma de Cuadrados': [],
|
362 |
'% Contribución': []
|
363 |
})
|
364 |
+
|
365 |
# Calcular porcentaje de contribución para cada factor
|
366 |
for index, row in anova_table.iterrows():
|
367 |
if index != 'Residual':
|
|
|
372 |
factor_name = f'{self.x2_name}^2'
|
373 |
elif factor_name == f'I({self.x3_name} ** 2)':
|
374 |
factor_name = f'{self.x3_name}^2'
|
375 |
+
|
376 |
ss_factor = row['sum_sq']
|
377 |
contribution_percentage = (ss_factor / ss_total) * 100
|
378 |
|
|
|
433 |
# 10. Cuadrados medios
|
434 |
ms_regression = ss_regression / df_regression
|
435 |
ms_residual = ss_residual / df_residual
|
436 |
+
ms_lack_of_fit = ms_lack_of_fit / df_lack_of_fit if not np.isnan(ss_lack_of_fit) else np.nan
|
437 |
ms_pure_error = ss_pure_error / df_pure_error if not np.isnan(ss_pure_error) else np.nan
|
438 |
|
439 |
# 11. Estadístico F y valor p para la falta de ajuste
|
|
|
449 |
'F': [np.nan, np.nan, f_lack_of_fit, np.nan, np.nan],
|
450 |
'Valor p': [np.nan, np.nan, p_lack_of_fit, np.nan, np.nan]
|
451 |
})
|
452 |
+
|
453 |
# Calcular la suma de cuadrados y grados de libertad para la curvatura
|
454 |
ss_curvature = anova_reduced['sum_sq'][f'I({self.x1_name} ** 2)'] + anova_reduced['sum_sq'][f'I({self.x2_name} ** 2)'] + anova_reduced['sum_sq'][f'I({self.x3_name} ** 2)']
|
455 |
df_curvature = 3
|
|
|
459 |
|
460 |
# Reorganizar las filas para que la curvatura aparezca después de la regresión
|
461 |
detailed_anova_table = detailed_anova_table.reindex([0, 5, 1, 2, 3, 4])
|
462 |
+
|
463 |
# Resetear el índice para que sea consecutivo
|
464 |
detailed_anova_table = detailed_anova_table.reset_index(drop=True)
|
465 |
|
|
|
554 |
font.size = Pt(12)
|
555 |
|
556 |
# Título del informe
|
557 |
+
titulo = doc.add_heading('Informe de Optimización de Producción de Absorbancia', 0) # Changed Title
|
558 |
titulo.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
559 |
|
560 |
doc.add_paragraph(f"Fecha: {datetime.now().strftime('%d/%m/%Y %H:%M')}").alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
|
|
595 |
|
596 |
# --- Funciones para la Interfaz de Gradio ---
|
597 |
|
598 |
+
def load_data(data_str): # Modified load_data to only take data_str
|
599 |
"""
|
600 |
Carga los datos del diseño Box-Behnken desde cajas de texto y crea la instancia de RSM_BoxBehnken.
|
601 |
"""
|
602 |
try:
|
603 |
+
# Use the data dictionary directly
|
604 |
+
data_dict = {
|
605 |
+
'Tratamiento': ['T1', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'T8', 'T9', 'T10', 'T11', 'T12', 'T13', 'T14', 'T15'] * 3,
|
606 |
+
'Tiempo_fermentacion_h': [16] * 15 + [23] * 15 + [40] * 15,
|
607 |
+
'pH': [6.02, 5.39, 6.27, 4.82, 6.25, 4.87, 4.76, 4.68, 4.64, 6.35, 4.67, 6.43, 4.58, 4.60, 6.96,
|
608 |
+
5.17, 5.95, 6.90, 5.50, 5.08, 4.95, 5.41, 5.52, 4.98, 7.10, 5.36, 6.91, 5.21, 4.66, 7.10,
|
609 |
+
5.42, 5.60, 7.36, 5.36, 4.66, 4.93, 5.18, 5.26, 4.92, 7.28, 5.26, 6.84, 5.19, 4.58, 7.07],
|
610 |
+
'Abs_600nm': [1.576, 1.474, 1.293, 1.446, 1.537, 1.415, 1.481, 1.419, 1.321, 1.224, 1.459, 0.345, 1.279, 1.181, 0.662,
|
611 |
+
1.760, 1.690, 1.485, 1.658, 1.728, 1.594, 1.673, 1.607, 1.531, 1.424, 1.595, 0.344, 1.477, 1.257, 0.660,
|
612 |
+
1.932, 1.780, 1.689, 1.876, 1.885, 1.824, 1.913, 1.810, 1.852, 1.694, 1.831, 0.347, 1.752, 1.367, 0.656],
|
613 |
+
'Glucosa_g_L': [5,10,0,5,10,5,10,5,10,0,5,0,5,5,0] * 3,
|
614 |
+
'Proteina_Pescado_g_L': [1.4,1.4,3.2,3.2,3.2,3.2,3.2,5,5,5,5,0,5,5,0] * 3,
|
615 |
+
'Sulfato_Manganeso_g_L': [0.75,0.5,0.75,0.5,0.75,0.5,0.75,0.5,0.25,0.75,0.5,0.25,0.5,0.25,0.5] * 3
|
616 |
+
}
|
617 |
+
data = pd.DataFrame(data_dict)
|
618 |
|
619 |
+
x1_name = "Glucosa_g_L"
|
620 |
+
x2_name = "Proteina_Pescado_g_L"
|
621 |
+
x3_name = "Sulfato_Manganeso_g_L"
|
622 |
+
y_name = "Abs_600nm"
|
623 |
+
x1_levels = sorted(list(set(data[x1_name]))) # Levels from data
|
624 |
+
x2_levels = sorted(list(set(data[x2_name]))) # Levels from data
|
625 |
+
x3_levels = sorted(list(set(data[x3_name]))) # Levels from data
|
626 |
|
|
|
|
|
|
|
627 |
|
628 |
# Crear la instancia de RSM_BoxBehnken
|
629 |
global rsm
|
630 |
rsm = RSM_BoxBehnken(data, x1_name, x2_name, x3_name, y_name, x1_levels, x2_levels, x3_levels)
|
631 |
|
632 |
+
return data.round(3), gr.update(visible=True) # Removed other outputs, only return data_output and analysis_row
|
633 |
+
|
634 |
except Exception as e:
|
635 |
# Mostrar mensaje de error
|
636 |
error_message = f"Error al cargar los datos: {str(e)}"
|
637 |
print(error_message)
|
638 |
+
return None, gr.update(visible=False) # Removed other outputs, only return data_output and analysis_row
|
639 |
+
|
640 |
|
641 |
def fit_and_optimize_model():
|
642 |
if 'rsm' not in globals():
|
|
|
650 |
prediction_table = rsm.generate_prediction_table()
|
651 |
contribution_table = rsm.calculate_contribution_percentage()
|
652 |
anova_table = rsm.calculate_detailed_anova()
|
653 |
+
|
654 |
+
# Generar todas las figuras and store them in rsm.all_figures
|
655 |
rsm.generate_all_plots()
|
656 |
+
|
657 |
# Formatear la ecuación para que se vea mejor en Markdown
|
658 |
equation_formatted = equation.replace(" + ", "<br>+ ").replace(" ** ", "^").replace("*", " × ")
|
659 |
equation_formatted = f"### Ecuación del Modelo Simplificado:<br>{equation_formatted}"
|
660 |
+
|
661 |
# Guardar las tablas en Excel temporal
|
662 |
excel_path = rsm.save_tables_to_excel()
|
663 |
|
|
|
669 |
pareto_completo,
|
670 |
model_simplificado.summary().as_html(),
|
671 |
pareto_simplificado,
|
672 |
+
equation_output,
|
673 |
optimization_table,
|
674 |
prediction_table,
|
675 |
contribution_table,
|
|
|
691 |
"""
|
692 |
if not all_figures:
|
693 |
return None, "No hay gráficos disponibles.", current_index
|
694 |
+
|
695 |
if direction == 'left':
|
696 |
new_index = (current_index - 1) % len(all_figures)
|
697 |
elif direction == 'right':
|
698 |
new_index = (current_index + 1) % len(all_figures)
|
699 |
else:
|
700 |
new_index = current_index
|
701 |
+
|
702 |
selected_fig = all_figures[new_index]
|
703 |
plot_info_text = f"Gráfico {new_index + 1} de {len(all_figures)}"
|
704 |
+
|
705 |
return selected_fig, plot_info_text, new_index
|
706 |
|
707 |
def download_current_plot(all_figures, current_index):
|
|
|
713 |
fig = all_figures[current_index]
|
714 |
img_bytes = rsm.save_fig_to_bytes(fig)
|
715 |
filename = f"Grafico_RSM_{current_index + 1}.png"
|
716 |
+
|
717 |
# Crear un archivo temporal
|
718 |
with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as temp_file:
|
719 |
temp_file.write(img_bytes)
|
720 |
temp_path = temp_file.name
|
721 |
+
|
722 |
return temp_path # Retornar solo la ruta
|
723 |
|
724 |
def download_all_plots_zip():
|
|
|
760 |
|
761 |
def create_gradio_interface():
|
762 |
with gr.Blocks() as demo:
|
763 |
+
gr.Markdown("# Optimización de la Absorbancia usando RSM") # Changed Title
|
764 |
+
|
765 |
with gr.Row():
|
766 |
with gr.Column():
|
767 |
+
gr.Markdown("## Configuración del Análisis") # Changed Section Title
|
768 |
+
# Removed input boxes for variable names and levels
|
769 |
+
data_input = gr.Textbox(label="Datos del Experimento (formato CSV - Ignored, Data is Hardcoded)", lines=5, interactive=False, value="Data is pre-loaded, ignore input.") # Adjusted Textbox
|
770 |
+
load_button = gr.Button("Cargar Datos") # Keep load button for triggering data load but input is ignored
|
771 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
772 |
with gr.Column():
|
773 |
gr.Markdown("## Datos Cargados")
|
774 |
data_output = gr.Dataframe(label="Tabla de Datos", interactive=False)
|
775 |
+
|
776 |
# Sección de análisis visible solo después de cargar los datos
|
777 |
with gr.Row(visible=False) as analysis_row:
|
778 |
with gr.Column():
|
|
|
792 |
gr.Markdown("## Descargar Todas las Tablas")
|
793 |
download_excel_button = gr.DownloadButton("Descargar Tablas en Excel")
|
794 |
download_word_button = gr.DownloadButton("Descargar Tablas en Word")
|
795 |
+
|
796 |
with gr.Column():
|
797 |
gr.Markdown("## Generar Gráficos de Superficie de Respuesta")
|
798 |
+
fixed_variable_input = gr.Dropdown(label="Variable Fija", choices=["Glucosa_g_L", "Proteina_Pescado_g_L", "Sulfato_Manganeso_g_L"], value="Glucosa_g_L") # Updated choices
|
799 |
+
fixed_level_input = gr.Slider(label="Nivel de Variable Fija (Natural Units)", minimum=0, maximum=10, step=0.1, value=5.0) # Updated Slider
|
800 |
plot_button = gr.Button("Generar Gráficos")
|
801 |
with gr.Row():
|
802 |
left_button = gr.Button("<")
|
|
|
808 |
download_all_plots_button = gr.DownloadButton("Descargar Todos los Gráficos (ZIP)")
|
809 |
current_index_state = gr.State(0) # Estado para el índice actual
|
810 |
all_figures_state = gr.State([]) # Estado para todas las figuras
|
811 |
+
|
812 |
+
# Cargar datos - Modified load_button click to only take data_input (which is ignored)
|
813 |
load_button.click(
|
814 |
load_data,
|
815 |
+
inputs=[data_input], # Only data_input is now input
|
816 |
+
outputs=[data_output, analysis_row] # Removed other outputs, only return data_output and analysis_row
|
817 |
)
|
818 |
+
|
819 |
# Ajustar modelo y optimizar
|
820 |
fit_button.click(
|
821 |
fit_and_optimize_model,
|
|
|
834 |
download_excel_button # Ruta del Excel de tablas
|
835 |
]
|
836 |
)
|
837 |
+
|
838 |
# Generar y mostrar los gráficos
|
839 |
plot_button.click(
|
840 |
lambda fixed_var, fixed_lvl: (
|
|
|
846 |
inputs=[fixed_variable_input, fixed_level_input],
|
847 |
outputs=[rsm_plot_output, plot_info, current_index_state, all_figures_state]
|
848 |
)
|
849 |
+
|
850 |
# Navegación de gráficos
|
851 |
left_button.click(
|
852 |
lambda current_index, all_figures: navigate_plot('left', current_index, all_figures),
|
|
|
858 |
inputs=[current_index_state, all_figures_state],
|
859 |
outputs=[rsm_plot_output, plot_info, current_index_state]
|
860 |
)
|
861 |
+
|
862 |
# Descargar gráfico actual
|
863 |
download_plot_button.click(
|
864 |
download_current_plot,
|
865 |
inputs=[all_figures_state, current_index_state],
|
866 |
outputs=download_plot_button
|
867 |
)
|
868 |
+
|
869 |
# Descargar todos los gráficos en ZIP
|
870 |
download_all_plots_button.click(
|
871 |
download_all_plots_zip,
|
872 |
inputs=[],
|
873 |
outputs=download_all_plots_button
|
874 |
)
|
875 |
+
|
876 |
# Descargar todas las tablas en Excel y Word
|
877 |
download_excel_button.click(
|
878 |
fn=lambda: download_all_tables_excel(),
|
879 |
inputs=[],
|
880 |
outputs=download_excel_button
|
881 |
)
|
882 |
+
|
883 |
download_word_button.click(
|
884 |
fn=lambda: exportar_word(rsm, rsm.get_all_tables()),
|
885 |
inputs=[],
|
886 |
outputs=download_word_button
|
887 |
)
|
888 |
+
|
889 |
# Ejemplo de uso
|
890 |
+
gr.Markdown("## Instrucciones:") # Shortened Instructions
|
891 |
gr.Markdown("""
|
892 |
+
1. Click 'Cargar Datos' para usar los datos precargados.
|
893 |
+
2. Click 'Ajustar Modelo y Optimizar'.
|
894 |
+
3. Select 'Variable Fija' and 'Nivel de Variable Fija'.
|
895 |
+
4. Click 'Generar Gráficos'.
|
896 |
+
5. Navigate plots with '<' and '>'.
|
897 |
+
6. Download plots and tables as needed.
|
|
|
|
|
|
|
898 |
""")
|
899 |
|
900 |
return demo
|
|
|
906 |
interface.launch(share=True)
|
907 |
|
908 |
if __name__ == "__main__":
|
909 |
+
main()
|