Update app.py
Browse files
app.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import numpy as np
|
2 |
import pandas as pd
|
3 |
import statsmodels.formula.api as smf
|
4 |
import statsmodels.api as sm
|
@@ -97,7 +97,11 @@ class RSM_BoxBehnken:
|
|
97 |
return
|
98 |
|
99 |
def objective_function(x):
|
100 |
-
return -self.model_simplified.predict(pd.DataFrame({
|
|
|
|
|
|
|
|
|
101 |
|
102 |
bounds = [(-1, 1), (-1, 1), (-1, 1)]
|
103 |
x0 = [0, 0, 0]
|
@@ -115,7 +119,7 @@ class RSM_BoxBehnken:
|
|
115 |
optimization_table = pd.DataFrame({
|
116 |
'Variable': [self.x1_name, self.x2_name, self.x3_name],
|
117 |
'Nivel Óptimo (Natural)': optimal_levels_natural,
|
118 |
-
'Nivel Óptimo (Codificado)': self.optimal_levels
|
119 |
})
|
120 |
|
121 |
return optimization_table.round(3) # Redondear a 3 decimales
|
@@ -508,7 +512,7 @@ class RSM_BoxBehnken:
|
|
508 |
img_bytes = fig.to_image(format="png")
|
509 |
zip_file.writestr(f'Grafico_{idx}.png', img_bytes)
|
510 |
zip_buffer.seek(0)
|
511 |
-
return zip_buffer
|
512 |
|
513 |
def save_fig_to_bytes(self, fig):
|
514 |
"""
|
@@ -568,7 +572,7 @@ def load_data(x1_name, x2_name, x3_name, y_name, x1_levels_str, x2_levels_str, x
|
|
568 |
|
569 |
def fit_and_optimize_model():
|
570 |
if 'rsm' not in globals():
|
571 |
-
return None, None, None, None, None, None,
|
572 |
|
573 |
# Ajustar modelos y optimizar
|
574 |
model_completo, pareto_completo = rsm.fit_model()
|
@@ -597,31 +601,19 @@ def fit_and_optimize_model():
|
|
597 |
contribution_table,
|
598 |
anova_table,
|
599 |
rsm.all_figures, # Devuelve todas las figuras generadas
|
600 |
-
gr.
|
601 |
)
|
602 |
|
603 |
-
def generate_rsm_plot(
|
604 |
-
if
|
605 |
-
return None, "
|
606 |
|
607 |
-
|
608 |
-
|
609 |
-
# Se puede mejorar la lógica si es necesario
|
610 |
-
selected_fig = None
|
611 |
-
for idx, fig in enumerate(all_figures):
|
612 |
-
title = fig.layout.title.text
|
613 |
-
if fixed_variable in title and f"fijo en {fixed_level:.3f}" in title:
|
614 |
-
selected_fig = fig
|
615 |
-
current_index = idx
|
616 |
-
break
|
617 |
|
618 |
-
|
619 |
-
selected_fig = all_figures[0]
|
620 |
-
current_index = 0
|
621 |
-
|
622 |
-
return selected_fig, None, current_index
|
623 |
|
624 |
-
def navigate_plot(direction, current_index, total_plots):
|
625 |
"""
|
626 |
Navega entre los gráficos.
|
627 |
|
@@ -629,17 +621,25 @@ def navigate_plot(direction, current_index, total_plots):
|
|
629 |
direction (str): 'left' o 'right'.
|
630 |
current_index (int): Índice actual.
|
631 |
total_plots (int): Total de gráficos.
|
|
|
632 |
|
633 |
Returns:
|
634 |
-
|
635 |
"""
|
|
|
|
|
|
|
636 |
if direction == 'left':
|
637 |
new_index = (current_index - 1) % total_plots
|
638 |
elif direction == 'right':
|
639 |
new_index = (current_index + 1) % total_plots
|
640 |
else:
|
641 |
new_index = current_index
|
642 |
-
|
|
|
|
|
|
|
|
|
643 |
|
644 |
def download_current_plot(all_figures, current_index):
|
645 |
"""
|
@@ -650,13 +650,13 @@ def download_current_plot(all_figures, current_index):
|
|
650 |
current_index (int): Índice de la figura actual.
|
651 |
|
652 |
Returns:
|
653 |
-
|
654 |
"""
|
655 |
if not all_figures:
|
656 |
-
return None
|
657 |
fig = all_figures[current_index]
|
658 |
img_bytes = rsm.save_fig_to_bytes(fig)
|
659 |
-
return img_bytes
|
660 |
|
661 |
def download_all_plots_zip(all_figures):
|
662 |
"""
|
@@ -666,22 +666,23 @@ def download_all_plots_zip(all_figures):
|
|
666 |
all_figures (list): Lista de figuras.
|
667 |
|
668 |
Returns:
|
669 |
-
|
670 |
"""
|
671 |
zip_bytes = rsm.save_figures_to_zip()
|
672 |
if zip_bytes:
|
673 |
-
|
674 |
-
|
|
|
675 |
|
676 |
def download_all_tables_excel():
|
677 |
"""
|
678 |
Descarga todas las tablas en un archivo Excel con múltiples hojas.
|
679 |
|
680 |
Returns:
|
681 |
-
|
682 |
"""
|
683 |
if 'rsm' not in globals():
|
684 |
-
return None
|
685 |
|
686 |
tables = rsm.get_all_tables()
|
687 |
excel_buffer = io.BytesIO()
|
@@ -689,7 +690,8 @@ def download_all_tables_excel():
|
|
689 |
for sheet_name, table in tables.items():
|
690 |
table.to_excel(writer, sheet_name=sheet_name, index=False)
|
691 |
excel_buffer.seek(0)
|
692 |
-
|
|
|
693 |
|
694 |
# --- Crear la interfaz de Gradio ---
|
695 |
|
@@ -744,7 +746,7 @@ with gr.Blocks() as demo:
|
|
744 |
contribution_table_output = gr.Dataframe(label="Tabla de % de Contribución", interactive=False)
|
745 |
anova_table_output = gr.Dataframe(label="Tabla ANOVA Detallada", interactive=False)
|
746 |
gr.Markdown("## Descargar Todas las Tablas")
|
747 |
-
download_excel_button = gr.DownloadButton("Descargar Tablas en Excel"
|
748 |
|
749 |
with gr.Column():
|
750 |
gr.Markdown("## Generar Gráficos de Superficie de Respuesta")
|
@@ -757,8 +759,9 @@ with gr.Blocks() as demo:
|
|
757 |
rsm_plot_output = gr.Plot()
|
758 |
plot_info = gr.Textbox(label="Información del Gráfico", value="Gráfico 1 de 9", interactive=False)
|
759 |
with gr.Row():
|
760 |
-
download_plot_button = gr.DownloadButton("Descargar Gráfico Actual (PNG)"
|
761 |
-
download_all_plots_button = gr.DownloadButton("Descargar Todos los Gráficos (ZIP)"
|
|
|
762 |
|
763 |
load_button.click(
|
764 |
load_data,
|
@@ -780,78 +783,75 @@ with gr.Blocks() as demo:
|
|
780 |
contribution_table_output,
|
781 |
anova_table_output,
|
782 |
gr.State(), # all_figures
|
783 |
-
gr.
|
784 |
]
|
785 |
)
|
786 |
|
787 |
plot_button.click(
|
788 |
-
lambda: (None, 0), #
|
789 |
inputs=[],
|
790 |
-
outputs=[rsm_plot_output,
|
791 |
)
|
792 |
|
793 |
# Navegación de gráficos
|
794 |
-
with gr.Row():
|
795 |
-
left_button.click(
|
796 |
-
navigate_plot,
|
797 |
-
inputs=["left", gr.State(), gr.State()],
|
798 |
-
outputs=gr.State()
|
799 |
-
)
|
800 |
-
right_button.click(
|
801 |
-
navigate_plot,
|
802 |
-
inputs=["right", gr.State(), gr.State()],
|
803 |
-
outputs=gr.State()
|
804 |
-
)
|
805 |
-
|
806 |
-
# Funciones para manejar la navegación y actualización de gráficos
|
807 |
-
def update_plot(direction, current_index, total_plots, all_figures):
|
808 |
-
if not all_figures:
|
809 |
-
return None, "No hay gráficos disponibles.", current_index
|
810 |
-
|
811 |
-
if direction == "left":
|
812 |
-
new_index = (current_index - 1) % total_plots
|
813 |
-
elif direction == "right":
|
814 |
-
new_index = (current_index + 1) % total_plots
|
815 |
-
else:
|
816 |
-
new_index = current_index
|
817 |
-
|
818 |
-
selected_fig = all_figures[new_index]
|
819 |
-
plot_info_text = f"Gráfico {new_index + 1} de {total_plots}"
|
820 |
-
|
821 |
-
return selected_fig, plot_info_text, new_index
|
822 |
-
|
823 |
-
# Actualizar gráficos al navegar
|
824 |
left_button.click(
|
825 |
-
|
826 |
-
inputs=["left",
|
827 |
-
outputs=[rsm_plot_output, plot_info,
|
828 |
)
|
829 |
-
|
830 |
right_button.click(
|
831 |
-
|
832 |
-
inputs=["right",
|
833 |
-
outputs=[rsm_plot_output, plot_info,
|
834 |
)
|
835 |
|
|
|
|
|
|
|
|
|
836 |
# Descargar gráfico actual
|
837 |
download_plot_button.click(
|
838 |
download_current_plot,
|
839 |
-
inputs=[
|
840 |
-
outputs=download_plot_button
|
841 |
)
|
842 |
|
843 |
# Descargar todos los gráficos en ZIP
|
844 |
download_all_plots_button.click(
|
845 |
download_all_plots_zip,
|
846 |
-
inputs=[
|
847 |
-
outputs=download_all_plots_button
|
848 |
)
|
849 |
|
850 |
# Descargar todas las tablas en Excel
|
851 |
download_excel_button.click(
|
852 |
download_all_tables_excel,
|
853 |
inputs=[],
|
854 |
-
outputs=download_excel_button
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
855 |
)
|
856 |
|
857 |
# Ejemplo de uso
|
@@ -867,5 +867,5 @@ with gr.Blocks() as demo:
|
|
867 |
8. Descarga el gráfico actual en PNG o descarga todos los gráficos en un ZIP.
|
868 |
9. Descarga todas las tablas en un archivo Excel con el botón correspondiente.
|
869 |
""")
|
870 |
-
|
871 |
demo.launch()
|
|
|
1 |
+
import numpy as np
|
2 |
import pandas as pd
|
3 |
import statsmodels.formula.api as smf
|
4 |
import statsmodels.api as sm
|
|
|
97 |
return
|
98 |
|
99 |
def objective_function(x):
|
100 |
+
return -self.model_simplified.predict(pd.DataFrame({
|
101 |
+
self.x1_name: [x[0]],
|
102 |
+
self.x2_name: [x[1]],
|
103 |
+
self.x3_name: [x[2]]
|
104 |
+
})).values[0]
|
105 |
|
106 |
bounds = [(-1, 1), (-1, 1), (-1, 1)]
|
107 |
x0 = [0, 0, 0]
|
|
|
119 |
optimization_table = pd.DataFrame({
|
120 |
'Variable': [self.x1_name, self.x2_name, self.x3_name],
|
121 |
'Nivel Óptimo (Natural)': optimal_levels_natural,
|
122 |
+
'Nivel Óptimo (Codificado)': self.optimal_levels
|
123 |
})
|
124 |
|
125 |
return optimization_table.round(3) # Redondear a 3 decimales
|
|
|
512 |
img_bytes = fig.to_image(format="png")
|
513 |
zip_file.writestr(f'Grafico_{idx}.png', img_bytes)
|
514 |
zip_buffer.seek(0)
|
515 |
+
return zip_buffer.getvalue()
|
516 |
|
517 |
def save_fig_to_bytes(self, fig):
|
518 |
"""
|
|
|
572 |
|
573 |
def fit_and_optimize_model():
|
574 |
if 'rsm' not in globals():
|
575 |
+
return None, None, None, None, None, None, None, None, None, gr.State(), gr.State()
|
576 |
|
577 |
# Ajustar modelos y optimizar
|
578 |
model_completo, pareto_completo = rsm.fit_model()
|
|
|
601 |
contribution_table,
|
602 |
anova_table,
|
603 |
rsm.all_figures, # Devuelve todas las figuras generadas
|
604 |
+
gr.State() # Inicializa el índice actual
|
605 |
)
|
606 |
|
607 |
+
def generate_rsm_plot(all_figures, current_index):
|
608 |
+
if not all_figures:
|
609 |
+
return None, "No hay gráficos disponibles.", current_index
|
610 |
|
611 |
+
selected_fig = all_figures[current_index]
|
612 |
+
plot_info_text = f"Gráfico {current_index + 1} de {len(all_figures)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
613 |
|
614 |
+
return selected_fig, plot_info_text, current_index
|
|
|
|
|
|
|
|
|
615 |
|
616 |
+
def navigate_plot(direction, current_index, total_plots, all_figures):
|
617 |
"""
|
618 |
Navega entre los gráficos.
|
619 |
|
|
|
621 |
direction (str): 'left' o 'right'.
|
622 |
current_index (int): Índice actual.
|
623 |
total_plots (int): Total de gráficos.
|
624 |
+
all_figures (list): Lista de todas las figuras.
|
625 |
|
626 |
Returns:
|
627 |
+
tuple: (gr.Figure, str, int)
|
628 |
"""
|
629 |
+
if not all_figures:
|
630 |
+
return None, "No hay gráficos disponibles.", current_index
|
631 |
+
|
632 |
if direction == 'left':
|
633 |
new_index = (current_index - 1) % total_plots
|
634 |
elif direction == 'right':
|
635 |
new_index = (current_index + 1) % total_plots
|
636 |
else:
|
637 |
new_index = current_index
|
638 |
+
|
639 |
+
selected_fig = all_figures[new_index]
|
640 |
+
plot_info_text = f"Gráfico {new_index + 1} de {total_plots}"
|
641 |
+
|
642 |
+
return selected_fig, plot_info_text, new_index
|
643 |
|
644 |
def download_current_plot(all_figures, current_index):
|
645 |
"""
|
|
|
650 |
current_index (int): Índice de la figura actual.
|
651 |
|
652 |
Returns:
|
653 |
+
tuple: (bytes, str)
|
654 |
"""
|
655 |
if not all_figures:
|
656 |
+
return None, "grafico_actual.png"
|
657 |
fig = all_figures[current_index]
|
658 |
img_bytes = rsm.save_fig_to_bytes(fig)
|
659 |
+
return img_bytes, f"Grafico_RSM_{current_index + 1}.png"
|
660 |
|
661 |
def download_all_plots_zip(all_figures):
|
662 |
"""
|
|
|
666 |
all_figures (list): Lista de figuras.
|
667 |
|
668 |
Returns:
|
669 |
+
tuple: (bytes, str)
|
670 |
"""
|
671 |
zip_bytes = rsm.save_figures_to_zip()
|
672 |
if zip_bytes:
|
673 |
+
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
674 |
+
return zip_bytes, f"Graficos_RSM_{timestamp}.zip"
|
675 |
+
return None, "Graficos_RSM.zip"
|
676 |
|
677 |
def download_all_tables_excel():
|
678 |
"""
|
679 |
Descarga todas las tablas en un archivo Excel con múltiples hojas.
|
680 |
|
681 |
Returns:
|
682 |
+
tuple: (bytes, str)
|
683 |
"""
|
684 |
if 'rsm' not in globals():
|
685 |
+
return None, "Tablas_RSM.xlsx"
|
686 |
|
687 |
tables = rsm.get_all_tables()
|
688 |
excel_buffer = io.BytesIO()
|
|
|
690 |
for sheet_name, table in tables.items():
|
691 |
table.to_excel(writer, sheet_name=sheet_name, index=False)
|
692 |
excel_buffer.seek(0)
|
693 |
+
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
694 |
+
return excel_buffer.getvalue(), f"Tablas_RSM_{timestamp}.xlsx"
|
695 |
|
696 |
# --- Crear la interfaz de Gradio ---
|
697 |
|
|
|
746 |
contribution_table_output = gr.Dataframe(label="Tabla de % de Contribución", interactive=False)
|
747 |
anova_table_output = gr.Dataframe(label="Tabla ANOVA Detallada", interactive=False)
|
748 |
gr.Markdown("## Descargar Todas las Tablas")
|
749 |
+
download_excel_button = gr.DownloadButton("Descargar Tablas en Excel")
|
750 |
|
751 |
with gr.Column():
|
752 |
gr.Markdown("## Generar Gráficos de Superficie de Respuesta")
|
|
|
759 |
rsm_plot_output = gr.Plot()
|
760 |
plot_info = gr.Textbox(label="Información del Gráfico", value="Gráfico 1 de 9", interactive=False)
|
761 |
with gr.Row():
|
762 |
+
download_plot_button = gr.DownloadButton("Descargar Gráfico Actual (PNG)")
|
763 |
+
download_all_plots_button = gr.DownloadButton("Descargar Todos los Gráficos (ZIP)")
|
764 |
+
current_index_state = gr.State(0) # Estado para el índice actual
|
765 |
|
766 |
load_button.click(
|
767 |
load_data,
|
|
|
783 |
contribution_table_output,
|
784 |
anova_table_output,
|
785 |
gr.State(), # all_figures
|
786 |
+
gr.State() # current_index (reset)
|
787 |
]
|
788 |
)
|
789 |
|
790 |
plot_button.click(
|
791 |
+
lambda: (None, "Gráfico 1 de 9", 0), # Inicializar plot y índice
|
792 |
inputs=[],
|
793 |
+
outputs=[rsm_plot_output, plot_info, current_index_state]
|
794 |
)
|
795 |
|
796 |
# Navegación de gráficos
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
797 |
left_button.click(
|
798 |
+
navigate_plot,
|
799 |
+
inputs=["left", current_index_state, gr.Number(value=9), gr.State()],
|
800 |
+
outputs=[rsm_plot_output, plot_info, current_index_state]
|
801 |
)
|
|
|
802 |
right_button.click(
|
803 |
+
navigate_plot,
|
804 |
+
inputs=["right", current_index_state, gr.Number(value=9), gr.State()],
|
805 |
+
outputs=[rsm_plot_output, plot_info, current_index_state]
|
806 |
)
|
807 |
|
808 |
+
# Función para actualizar y mostrar el gráfico actual
|
809 |
+
def update_plot(direction, current_index, total_plots, all_figures):
|
810 |
+
return navigate_plot(direction, current_index, int(total_plots), all_figures)
|
811 |
+
|
812 |
# Descargar gráfico actual
|
813 |
download_plot_button.click(
|
814 |
download_current_plot,
|
815 |
+
inputs=[gr.State(), current_index_state],
|
816 |
+
outputs=[download_plot_button]
|
817 |
)
|
818 |
|
819 |
# Descargar todos los gráficos en ZIP
|
820 |
download_all_plots_button.click(
|
821 |
download_all_plots_zip,
|
822 |
+
inputs=[gr.State()],
|
823 |
+
outputs=[download_all_plots_button]
|
824 |
)
|
825 |
|
826 |
# Descargar todas las tablas en Excel
|
827 |
download_excel_button.click(
|
828 |
download_all_tables_excel,
|
829 |
inputs=[],
|
830 |
+
outputs=[download_excel_button]
|
831 |
+
)
|
832 |
+
|
833 |
+
# Mostrar el primer gráfico después de generar todos
|
834 |
+
def show_first_plot(all_figures):
|
835 |
+
if not all_figures:
|
836 |
+
return None, "No hay gráficos disponibles.", 0
|
837 |
+
return all_figures[0], "Gráfico 1 de 9", 0
|
838 |
+
|
839 |
+
plot_button.click(
|
840 |
+
lambda: (None, "Gráfico 1 de 9", 0), # Placeholder para reiniciar el índice
|
841 |
+
inputs=[],
|
842 |
+
outputs=[rsm_plot_output, plot_info, current_index_state]
|
843 |
+
)
|
844 |
+
|
845 |
+
# Actualizar gráficos al navegar
|
846 |
+
left_button.click(
|
847 |
+
update_plot,
|
848 |
+
inputs=["left", current_index_state, gr.Number(value=9), gr.State()],
|
849 |
+
outputs=[rsm_plot_output, plot_info, current_index_state]
|
850 |
+
)
|
851 |
+
right_button.click(
|
852 |
+
update_plot,
|
853 |
+
inputs=["right", current_index_state, gr.Number(value=9), gr.State()],
|
854 |
+
outputs=[rsm_plot_output, plot_info, current_index_state]
|
855 |
)
|
856 |
|
857 |
# Ejemplo de uso
|
|
|
867 |
8. Descarga el gráfico actual en PNG o descarga todos los gráficos en un ZIP.
|
868 |
9. Descarga todas las tablas en un archivo Excel con el botón correspondiente.
|
869 |
""")
|
870 |
+
|
871 |
demo.launch()
|