Update app.py
Browse files
app.py
CHANGED
@@ -10,7 +10,7 @@ from docx.shared import Inches, Pt
|
|
10 |
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
|
11 |
import os
|
12 |
|
13 |
-
def generar_tabla(n_filas, concentracion_inicial, unidad_medida):
|
14 |
valores_base = [1.00, 0.80, 0.60, 0.40, 0.20, 0.10, 0.05]
|
15 |
|
16 |
if n_filas <= 7:
|
@@ -34,19 +34,27 @@ def generar_tabla(n_filas, concentracion_inicial, unidad_medida):
|
|
34 |
nombre_columna = f"Soluci贸n de in贸culo ({concentracion_inicial} {unidad_medida})"
|
35 |
df["Factor de Diluci贸n"] = df[nombre_columna].apply(lambda x: round(1 / x, 2))
|
36 |
df[f"Concentraci贸n Predicha ({unidad_medida})"] = df["Factor de Diluci贸n"].apply(
|
37 |
-
lambda x: round(concentracion_inicial / x,
|
38 |
)
|
39 |
|
40 |
df[f"Concentraci贸n Real ({unidad_medida})"] = None
|
41 |
|
42 |
return df
|
43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
def generar_datos_sinteticos(df, desviacion_std):
|
45 |
col_predicha = [col for col in df.columns if 'Predicha' in col][0]
|
46 |
col_real = [col for col in df.columns if 'Real' in col][0]
|
47 |
|
48 |
# Generar datos sint茅ticos
|
49 |
-
valores_predichos = df[col_predicha].values
|
50 |
datos_sinteticos = valores_predichos + np.random.normal(0, desviacion_std, size=len(valores_predichos))
|
51 |
datos_sinteticos = np.maximum(0, datos_sinteticos) # Asegurar que no haya valores negativos
|
52 |
datos_sinteticos = np.round(datos_sinteticos, 2)
|
@@ -60,8 +68,8 @@ def generar_graficos(df_valid):
|
|
60 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
61 |
|
62 |
# Calcular regresi贸n lineal
|
63 |
-
slope, intercept, r_value, p_value, std_err = stats.linregress(df_valid[col_predicha], df_valid[col_real])
|
64 |
-
df_valid['Ajuste Lineal'] = intercept + slope * df_valid[col_predicha]
|
65 |
|
66 |
# Configurar estilos
|
67 |
sns.set(style="whitegrid")
|
@@ -92,9 +100,11 @@ def generar_graficos(df_valid):
|
|
92 |
)
|
93 |
|
94 |
# L铆nea ideal
|
|
|
|
|
95 |
ax1.plot(
|
96 |
-
[
|
97 |
-
[
|
98 |
color='red',
|
99 |
linestyle='--',
|
100 |
label='Ideal'
|
@@ -118,7 +128,7 @@ def generar_graficos(df_valid):
|
|
118 |
ax1.legend(loc='lower right', fontsize=10)
|
119 |
|
120 |
# Gr谩fico de residuos
|
121 |
-
residuos = df_valid[col_real] - df_valid['Ajuste Lineal']
|
122 |
sns.scatterplot(
|
123 |
data=df_valid,
|
124 |
x=col_predicha,
|
@@ -163,7 +173,7 @@ def evaluar_calidad_calibracion(df_valid, r_squared, rmse, cv_percent):
|
|
163 |
if cv_percent > 15:
|
164 |
evaluacion["recomendaciones"].append("- La variabilidad es alta. Revise el procedimiento de diluci贸n")
|
165 |
|
166 |
-
if rmse > 0.1 * df_valid[df_valid.columns[-1]].mean():
|
167 |
evaluacion["recomendaciones"].append("- El error de predicci贸n es significativo. Verifique la t茅cnica de medici贸n")
|
168 |
|
169 |
return evaluacion
|
@@ -173,6 +183,10 @@ def generar_informe_completo(df_valid):
|
|
173 |
col_predicha = [col for col in df_valid.columns if 'Predicha' in col][0]
|
174 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
175 |
|
|
|
|
|
|
|
|
|
176 |
# Calcular estad铆sticas
|
177 |
slope, intercept, r_value, p_value, std_err = stats.linregress(df_valid[col_predicha], df_valid[col_real])
|
178 |
r_squared = r_value ** 2
|
@@ -372,10 +386,6 @@ def cargar_ejemplo_od():
|
|
372 |
df[f"Concentraci贸n Real (OD)"] = valores_reales
|
373 |
return 1.0, "OD", 7, df
|
374 |
|
375 |
-
def actualizar_tabla_evento(n_filas, concentracion, unidad):
|
376 |
-
df = generar_tabla(n_filas, concentracion, unidad)
|
377 |
-
return df
|
378 |
-
|
379 |
def limpiar_datos():
|
380 |
df = generar_tabla(7, 2000000, "UFC")
|
381 |
return (
|
@@ -390,7 +400,9 @@ def limpiar_datos():
|
|
390 |
|
391 |
def generar_datos_sinteticos_evento(df):
|
392 |
df = df.copy()
|
393 |
-
|
|
|
|
|
394 |
df = generar_datos_sinteticos(df, desviacion_std)
|
395 |
return df
|
396 |
|
@@ -420,10 +432,18 @@ with gr.Blocks(theme=gr.themes.Soft()) as interfaz:
|
|
420 |
step=1,
|
421 |
label="N煤mero de filas"
|
422 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
423 |
|
424 |
with gr.Row():
|
425 |
calcular_btn = gr.Button("馃攧 Calcular", variant="primary")
|
426 |
limpiar_btn = gr.Button("馃棏 Limpiar Datos", variant="secondary")
|
|
|
427 |
|
428 |
with gr.Row():
|
429 |
ejemplo_ufc_btn = gr.Button("馃搵 Cargar Ejemplo UFC", variant="secondary")
|
@@ -443,14 +463,13 @@ with gr.Blocks(theme=gr.themes.Soft()) as interfaz:
|
|
443 |
with gr.Tab("馃搳 An谩lisis y Reporte"):
|
444 |
estado_output = gr.Textbox(label="Estado", interactive=False)
|
445 |
graficos_output = gr.Plot(label="Gr谩ficos de An谩lisis")
|
446 |
-
informe_output = gr.Markdown(elem_id="informe_output")
|
447 |
|
448 |
with gr.Row():
|
449 |
copiar_btn = gr.Button("馃搵 Copiar Informe", variant="secondary")
|
450 |
exportar_word_btn = gr.Button("馃捑 Exportar Informe Word", variant="primary")
|
451 |
exportar_latex_btn = gr.Button("馃捑 Exportar Informe LaTeX", variant="primary")
|
452 |
|
453 |
-
# Agregar componentes gr.File para los archivos exportados
|
454 |
exportar_word_file = gr.File(label="Informe en Word")
|
455 |
exportar_latex_file = gr.File(label="Informe en LaTeX")
|
456 |
|
@@ -490,26 +509,43 @@ with gr.Blocks(theme=gr.themes.Soft()) as interfaz:
|
|
490 |
outputs=tabla_output
|
491 |
)
|
492 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
493 |
# Actualizar tabla al cambiar los par谩metros
|
|
|
|
|
|
|
|
|
494 |
concentracion_input.change(
|
495 |
fn=actualizar_tabla_evento,
|
496 |
-
inputs=[filas_slider, concentracion_input, unidad_input],
|
497 |
outputs=tabla_output
|
498 |
)
|
499 |
|
500 |
unidad_input.change(
|
501 |
fn=actualizar_tabla_evento,
|
502 |
-
inputs=[filas_slider, concentracion_input, unidad_input],
|
503 |
outputs=tabla_output
|
504 |
)
|
505 |
|
506 |
filas_slider.change(
|
507 |
fn=actualizar_tabla_evento,
|
508 |
-
inputs=[filas_slider, concentracion_input, unidad_input],
|
|
|
|
|
|
|
|
|
|
|
|
|
509 |
outputs=tabla_output
|
510 |
)
|
511 |
|
512 |
-
# Evento de copiar informe utilizando JavaScript
|
513 |
copiar_btn.click(
|
514 |
None,
|
515 |
[],
|
@@ -532,13 +568,13 @@ with gr.Blocks(theme=gr.themes.Soft()) as interfaz:
|
|
532 |
exportar_word_btn.click(
|
533 |
fn=exportar_word,
|
534 |
inputs=[tabla_output, informe_output],
|
535 |
-
outputs=exportar_word_file
|
536 |
)
|
537 |
|
538 |
exportar_latex_btn.click(
|
539 |
fn=exportar_latex,
|
540 |
inputs=[tabla_output, informe_output],
|
541 |
-
outputs=exportar_latex_file
|
542 |
)
|
543 |
|
544 |
# Inicializar la interfaz con el ejemplo base
|
|
|
10 |
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
|
11 |
import os
|
12 |
|
13 |
+
def generar_tabla(n_filas, concentracion_inicial, unidad_medida, decimales_predicha=0):
|
14 |
valores_base = [1.00, 0.80, 0.60, 0.40, 0.20, 0.10, 0.05]
|
15 |
|
16 |
if n_filas <= 7:
|
|
|
34 |
nombre_columna = f"Soluci贸n de in贸culo ({concentracion_inicial} {unidad_medida})"
|
35 |
df["Factor de Diluci贸n"] = df[nombre_columna].apply(lambda x: round(1 / x, 2))
|
36 |
df[f"Concentraci贸n Predicha ({unidad_medida})"] = df["Factor de Diluci贸n"].apply(
|
37 |
+
lambda x: round(concentracion_inicial / x, decimales_predicha)
|
38 |
)
|
39 |
|
40 |
df[f"Concentraci贸n Real ({unidad_medida})"] = None
|
41 |
|
42 |
return df
|
43 |
|
44 |
+
def ajustar_decimales_evento(df, decimales):
|
45 |
+
df = df.copy()
|
46 |
+
# Identificar la columna de Concentraci贸n Predicha
|
47 |
+
col_predicha = [col for col in df.columns if 'Concentraci贸n Predicha' in col][0]
|
48 |
+
# Redondear la columna al n煤mero de decimales especificado
|
49 |
+
df[col_predicha] = df[col_predicha].apply(lambda x: round(float(x), decimales))
|
50 |
+
return df
|
51 |
+
|
52 |
def generar_datos_sinteticos(df, desviacion_std):
|
53 |
col_predicha = [col for col in df.columns if 'Predicha' in col][0]
|
54 |
col_real = [col for col in df.columns if 'Real' in col][0]
|
55 |
|
56 |
# Generar datos sint茅ticos
|
57 |
+
valores_predichos = df[col_predicha].astype(float).values
|
58 |
datos_sinteticos = valores_predichos + np.random.normal(0, desviacion_std, size=len(valores_predichos))
|
59 |
datos_sinteticos = np.maximum(0, datos_sinteticos) # Asegurar que no haya valores negativos
|
60 |
datos_sinteticos = np.round(datos_sinteticos, 2)
|
|
|
68 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
69 |
|
70 |
# Calcular regresi贸n lineal
|
71 |
+
slope, intercept, r_value, p_value, std_err = stats.linregress(df_valid[col_predicha].astype(float), df_valid[col_real].astype(float))
|
72 |
+
df_valid['Ajuste Lineal'] = intercept + slope * df_valid[col_predicha].astype(float)
|
73 |
|
74 |
# Configurar estilos
|
75 |
sns.set(style="whitegrid")
|
|
|
100 |
)
|
101 |
|
102 |
# L铆nea ideal
|
103 |
+
min_predicha = df_valid[col_predicha].astype(float).min()
|
104 |
+
max_predicha = df_valid[col_predicha].astype(float).max()
|
105 |
ax1.plot(
|
106 |
+
[min_predicha, max_predicha],
|
107 |
+
[min_predicha, max_predicha],
|
108 |
color='red',
|
109 |
linestyle='--',
|
110 |
label='Ideal'
|
|
|
128 |
ax1.legend(loc='lower right', fontsize=10)
|
129 |
|
130 |
# Gr谩fico de residuos
|
131 |
+
residuos = df_valid[col_real].astype(float) - df_valid['Ajuste Lineal']
|
132 |
sns.scatterplot(
|
133 |
data=df_valid,
|
134 |
x=col_predicha,
|
|
|
173 |
if cv_percent > 15:
|
174 |
evaluacion["recomendaciones"].append("- La variabilidad es alta. Revise el procedimiento de diluci贸n")
|
175 |
|
176 |
+
if rmse > 0.1 * df_valid[df_valid.columns[-1]].astype(float).mean():
|
177 |
evaluacion["recomendaciones"].append("- El error de predicci贸n es significativo. Verifique la t茅cnica de medici贸n")
|
178 |
|
179 |
return evaluacion
|
|
|
183 |
col_predicha = [col for col in df_valid.columns if 'Predicha' in col][0]
|
184 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
185 |
|
186 |
+
# Convertir a num茅rico
|
187 |
+
df_valid[col_predicha] = df_valid[col_predicha].astype(float)
|
188 |
+
df_valid[col_real] = df_valid[col_real].astype(float)
|
189 |
+
|
190 |
# Calcular estad铆sticas
|
191 |
slope, intercept, r_value, p_value, std_err = stats.linregress(df_valid[col_predicha], df_valid[col_real])
|
192 |
r_squared = r_value ** 2
|
|
|
386 |
df[f"Concentraci贸n Real (OD)"] = valores_reales
|
387 |
return 1.0, "OD", 7, df
|
388 |
|
|
|
|
|
|
|
|
|
389 |
def limpiar_datos():
|
390 |
df = generar_tabla(7, 2000000, "UFC")
|
391 |
return (
|
|
|
400 |
|
401 |
def generar_datos_sinteticos_evento(df):
|
402 |
df = df.copy()
|
403 |
+
col_predicha = [col for col in df.columns if 'Predicha' in col][0]
|
404 |
+
df[col_predicha] = pd.to_numeric(df[col_predicha], errors='coerce')
|
405 |
+
desviacion_std = 0.05 * df[col_predicha].mean() # 5% de la media como desviaci贸n est谩ndar
|
406 |
df = generar_datos_sinteticos(df, desviacion_std)
|
407 |
return df
|
408 |
|
|
|
432 |
step=1,
|
433 |
label="N煤mero de filas"
|
434 |
)
|
435 |
+
decimales_slider = gr.Slider(
|
436 |
+
minimum=0,
|
437 |
+
maximum=5,
|
438 |
+
value=0,
|
439 |
+
step=1,
|
440 |
+
label="N煤mero de Decimales"
|
441 |
+
)
|
442 |
|
443 |
with gr.Row():
|
444 |
calcular_btn = gr.Button("馃攧 Calcular", variant="primary")
|
445 |
limpiar_btn = gr.Button("馃棏 Limpiar Datos", variant="secondary")
|
446 |
+
ajustar_decimales_btn = gr.Button("馃洜 Ajustar Decimales", variant="secondary")
|
447 |
|
448 |
with gr.Row():
|
449 |
ejemplo_ufc_btn = gr.Button("馃搵 Cargar Ejemplo UFC", variant="secondary")
|
|
|
463 |
with gr.Tab("馃搳 An谩lisis y Reporte"):
|
464 |
estado_output = gr.Textbox(label="Estado", interactive=False)
|
465 |
graficos_output = gr.Plot(label="Gr谩ficos de An谩lisis")
|
466 |
+
informe_output = gr.Markdown(elem_id="informe_output")
|
467 |
|
468 |
with gr.Row():
|
469 |
copiar_btn = gr.Button("馃搵 Copiar Informe", variant="secondary")
|
470 |
exportar_word_btn = gr.Button("馃捑 Exportar Informe Word", variant="primary")
|
471 |
exportar_latex_btn = gr.Button("馃捑 Exportar Informe LaTeX", variant="primary")
|
472 |
|
|
|
473 |
exportar_word_file = gr.File(label="Informe en Word")
|
474 |
exportar_latex_file = gr.File(label="Informe en LaTeX")
|
475 |
|
|
|
509 |
outputs=tabla_output
|
510 |
)
|
511 |
|
512 |
+
# Evento al presionar el bot贸n Ajustar Decimales
|
513 |
+
ajustar_decimales_btn.click(
|
514 |
+
fn=ajustar_decimales_evento,
|
515 |
+
inputs=[tabla_output, decimales_slider],
|
516 |
+
outputs=tabla_output
|
517 |
+
)
|
518 |
+
|
519 |
# Actualizar tabla al cambiar los par谩metros
|
520 |
+
def actualizar_tabla_evento(n_filas, concentracion, unidad, decimales):
|
521 |
+
df = generar_tabla(n_filas, concentracion, unidad, decimales)
|
522 |
+
return df
|
523 |
+
|
524 |
concentracion_input.change(
|
525 |
fn=actualizar_tabla_evento,
|
526 |
+
inputs=[filas_slider, concentracion_input, unidad_input, decimales_slider],
|
527 |
outputs=tabla_output
|
528 |
)
|
529 |
|
530 |
unidad_input.change(
|
531 |
fn=actualizar_tabla_evento,
|
532 |
+
inputs=[filas_slider, concentracion_input, unidad_input, decimales_slider],
|
533 |
outputs=tabla_output
|
534 |
)
|
535 |
|
536 |
filas_slider.change(
|
537 |
fn=actualizar_tabla_evento,
|
538 |
+
inputs=[filas_slider, concentracion_input, unidad_input, decimales_slider],
|
539 |
+
outputs=tabla_output
|
540 |
+
)
|
541 |
+
|
542 |
+
decimales_slider.change(
|
543 |
+
fn=actualizar_tabla_evento,
|
544 |
+
inputs=[filas_slider, concentracion_input, unidad_input, decimales_slider],
|
545 |
outputs=tabla_output
|
546 |
)
|
547 |
|
548 |
+
# Evento de copiar informe utilizando JavaScript
|
549 |
copiar_btn.click(
|
550 |
None,
|
551 |
[],
|
|
|
568 |
exportar_word_btn.click(
|
569 |
fn=exportar_word,
|
570 |
inputs=[tabla_output, informe_output],
|
571 |
+
outputs=exportar_word_file
|
572 |
)
|
573 |
|
574 |
exportar_latex_btn.click(
|
575 |
fn=exportar_latex,
|
576 |
inputs=[tabla_output, informe_output],
|
577 |
+
outputs=exportar_latex_file
|
578 |
)
|
579 |
|
580 |
# Inicializar la interfaz con el ejemplo base
|