C2MV commited on
Commit
db80485
1 Parent(s): 975c61e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -198
app.py CHANGED
@@ -3,6 +3,10 @@ os.system('pip install gradio seaborn scipy scikit-learn openpyxl networkx pydan
3
 
4
  from pydantic import BaseModel, ConfigDict
5
 
 
 
 
 
6
  import numpy as np
7
  import networkx as nx
8
  import matplotlib.pyplot as plt
@@ -12,7 +16,6 @@ from sklearn.preprocessing import PolynomialFeatures
12
  from sklearn.metrics import r2_score
13
  from itertools import combinations
14
  import tempfile
15
- import pandas as pd
16
 
17
  # Clase para el modelo de regresión
18
  class RegressionModel:
@@ -29,7 +32,7 @@ class RegressionModel:
29
  X_poly = self.poly.transform(X)
30
  return self.model.predict(X_poly)
31
 
32
- def r2_score_calc(self, X, y):
33
  y_pred = self.predict(X)
34
  return r2_score(y, y_pred)
35
 
@@ -68,8 +71,8 @@ class ExperimentalDesign:
68
  self.model_variable1.fit(X, self.variable1_values)
69
  self.model_variable2.fit(X, self.variable2_values)
70
 
71
- self.r2_variable1 = self.model_variable1.r2_score_calc(X, self.variable1_values)
72
- self.r2_variable2 = self.model_variable2.r2_score_calc(X, self.variable2_values)
73
 
74
  # Clase para el análisis de teoría de grafos
75
  class GraphTheoryAnalysis:
@@ -81,48 +84,16 @@ class GraphTheoryAnalysis:
81
  def set_matrices_and_values(self):
82
  self.all_factors = list(self.experiment.factor_values.keys())
83
 
84
- def build_graph(self, level=2, r2_threshold=0.5):
85
- """
86
- Construye el grafo basado en el nivel de combinación.
87
-
88
- Args:
89
- level (int): Nivel de combinación (2 o 3).
90
- r2_threshold (float): Umbral de R² para incluir una interacción.
91
- """
92
- if level not in [2, 3]:
93
- raise ValueError("Nivel de combinación no soportado. Debe ser 2 o 3.")
94
-
95
- self.graph.clear() # Limpiar grafo existente
96
-
97
- if level >= 2:
98
- # Construir interacciones de nivel 2
99
- for pair in combinations(self.all_factors, 2):
100
- self.experiment.set_active_factors(list(pair))
101
- self.experiment.fit_models()
102
- r2 = (self.experiment.r2_variable1 + self.experiment.r2_variable2) / 2
103
- if r2 >= r2_threshold:
104
- self.graph.add_edge(pair[0], pair[1], weight=r2)
105
-
106
- if level == 3:
107
- # Calcular R² acumulado por factor
108
- factor_r2 = {}
109
- for factor in self.all_factors:
110
- edges = [data['weight'] for u, v, data in self.graph.edges(data=True) if u == factor or v == factor]
111
- factor_r2[factor] = sum(edges) / len(edges) if edges else 0
112
-
113
- # Seleccionar los 3 factores con mayor R²
114
- top_factors = sorted(factor_r2, key=factor_r2.get, reverse=True)[:3]
115
 
116
- # Limpiar el grafo para incluir solo las interacciones entre los 3 factores
117
- self.graph.clear()
118
-
119
- # Añadir interacciones entre los 3 factores seleccionados
120
- for pair in combinations(top_factors, 2):
121
  self.experiment.set_active_factors(list(pair))
122
  self.experiment.fit_models()
123
  r2 = (self.experiment.r2_variable1 + self.experiment.r2_variable2) / 2
124
- if r2 >= r2_threshold:
125
- self.graph.add_edge(pair[0], pair[1], weight=r2)
126
 
127
  def visualize_graph(self, style='Style 1'):
128
  pos = nx.spring_layout(self.graph)
@@ -154,12 +125,9 @@ class GraphTheoryAnalysis:
154
  nx.draw_networkx_labels(self.graph, pos, font_size=font_size)
155
 
156
  edge_weights = [self.graph[u][v]['weight'] for u, v in self.graph.edges()]
157
- # Normalizar el ancho de las líneas para mejor visualización
158
- max_weight = max(edge_weights) if edge_weights else 1
159
- normalized_weights = [weight / max_weight * 5 for weight in edge_weights]
160
- nx.draw_networkx_edges(self.graph, pos, width=normalized_weights, edge_color=edge_color)
161
 
162
- edge_labels = { (u, v): f"{d['weight']:.2f}" for u, v, d in self.graph.edges(data=True) }
163
  nx.draw_networkx_edge_labels(self.graph, pos, edge_labels=edge_labels, font_size=font_size)
164
 
165
  plt.title(f"Grafo de relaciones entre factores basado en R² ({style})")
@@ -173,38 +141,8 @@ class GraphTheoryAnalysis:
173
 
174
  return temp_file.name
175
 
176
- # Función para generar el diseño Box-Behnken para 3 factores
177
- def generate_box_behnken(factors):
178
- # Box-Behnken design for 3 factors
179
- bb_design_3f = [
180
- [-1, -1, 0],
181
- [ 1, -1, 0],
182
- [-1, 1, 0],
183
- [ 1, 1, 0],
184
- [-1, 0, -1],
185
- [ 1, 0, -1],
186
- [-1, 0, 1],
187
- [ 1, 0, 1],
188
- [ 0, -1, -1],
189
- [ 0, 1, -1],
190
- [ 0, -1, 1],
191
- [ 0, 1, 1]
192
- ]
193
- design = []
194
- for row in bb_design_3f:
195
- design.append(dict(zip(factors, row)))
196
- return design
197
-
198
  # Definición de la interfaz de Gradio
199
  def analyze_design(level, pb_design, bb_design, variable1_values, variable2_values, style):
200
- # Validar y convertir matrices de diseño a numpy arrays
201
- try:
202
- pb_design_np = np.array(pb_design, dtype=float)
203
- bb_design_np = np.array(bb_design, dtype=float)
204
- except ValueError:
205
- return "Error: Asegúrate de que las matrices de diseño contienen solo números.", None, None
206
-
207
- # Inicializar diseño experimental
208
  experiment = ExperimentalDesign(regression_degree=2)
209
  optimizer = GraphTheoryAnalysis(experiment)
210
 
@@ -215,85 +153,14 @@ def analyze_design(level, pb_design, bb_design, variable1_values, variable2_valu
215
  'X4': [0.05, 0.5]
216
  }
217
 
218
- experiment.set_design(pb_design_np, bb_design_np)
219
  experiment.set_factors(factor_values)
220
- experiment.set_dependent_variables(np.array(variable1_values, dtype=float), np.array(variable2_values, dtype=float))
221
 
222
  optimizer.set_matrices_and_values()
223
- optimizer.build_graph(level=level, r2_threshold=0.5) # Ajusta el umbral según tus necesidades
224
  graph_image_path = optimizer.visualize_graph(style=style)
225
-
226
- if level == 3:
227
- # Identificar los 3 factores más activos basados en R²
228
- factor_r2 = {}
229
- for factor in experiment.factor_values.keys():
230
- # Filtrar las aristas que contienen el factor
231
- edges = [data['weight'] for u, v, data in optimizer.graph.edges(data=True) if u == factor or v == factor]
232
- factor_r2[factor] = sum(edges) / len(edges) if edges else 0
233
-
234
- # Seleccionar los 3 factores con mayor R²
235
- top_factors = sorted(factor_r2, key=factor_r2.get, reverse=True)[:3]
236
-
237
- # Generar diseño Box-Behnken para los 3 factores
238
- bb_design_3f = generate_box_behnken(top_factors)
239
-
240
- # Simular datos de respuesta (puedes ajustar esta parte según tus necesidades)
241
- # Aquí, simplemente generamos valores aleatorios para las respuestas
242
- np.random.seed(42) # Para reproducibilidad
243
- simulated_response1 = np.random.uniform(0.1, 1.0, len(bb_design_3f))
244
- simulated_response2 = np.random.uniform(0.1, 1.0, len(bb_design_3f))
245
-
246
- # Crear dataframe de resultados
247
- bb_results = []
248
- for i, design in enumerate(bb_design_3f):
249
- row = design.copy()
250
- row['Response 1'] = round(simulated_response1[i], 3)
251
- row['Response 2'] = round(simulated_response2[i], 3)
252
- bb_results.append(row)
253
-
254
- # Convertir bb_design_used a DataFrame para mostrar
255
- bb_design_used = bb_design_3f
256
- headers = top_factors + ['Response 1', 'Response 2']
257
-
258
- # Crear DataFrame para la matriz Box-Behnken usada
259
- df_bb_used = pd.DataFrame(bb_design_used)
260
- # Agregar respuestas al DataFrame
261
- df_bb_used[['Response 1', 'Response 2']] = pd.DataFrame(bb_results)[['Response 1', 'Response 2']]
262
-
263
- elif level == 2:
264
- # Usar el diseño Box-Behnken ingresado por el usuario para 4 factores
265
- bb_design_used = []
266
- for row in bb_design:
267
- design_row = { 'X1': row[0], 'X2': row[1], 'X3': row[2], 'X4': row[3] }
268
- bb_design_used.append(design_row)
269
-
270
- # Simular datos de respuesta (puedes ajustar esta parte según tus necesidades)
271
- # Aquí, simplemente generamos valores aleatorios para las respuestas
272
- np.random.seed(42) # Para reproducibilidad
273
- simulated_response1 = np.random.uniform(0.1, 1.0, len(bb_design_used))
274
- simulated_response2 = np.random.uniform(0.1, 1.0, len(bb_design_used))
275
-
276
- # Crear dataframe de resultados
277
- bb_results = []
278
- for i, design in enumerate(bb_design_used):
279
- row = design.copy()
280
- row['Response 1'] = round(simulated_response1[i], 3)
281
- row['Response 2'] = round(simulated_response2[i], 3)
282
- bb_results.append(row)
283
-
284
- headers = ['X1', 'X2', 'X3', 'X4', 'Response 1', 'Response 2']
285
-
286
- # Crear DataFrame para la matriz Box-Behnken usada
287
- df_bb_used = pd.DataFrame(bb_design_used)
288
- # Agregar respuestas al DataFrame
289
- df_bb_used[['Response 1', 'Response 2']] = pd.DataFrame(bb_results)[['Response 1', 'Response 2']]
290
- else:
291
- return "Error: Nivel de combinación inválido. Debe ser 2 o 3.", None, None
292
-
293
- # Crear DataFrame para los datos simulados
294
- df_simulated = df_bb_used.copy()
295
-
296
- return graph_image_path, df_bb_used, df_simulated
297
 
298
  # Matriz Plackett-Burman (por defecto)
299
  default_pb_design = [
@@ -307,7 +174,7 @@ default_pb_design = [
307
  [-1, -1, -1, -1]
308
  ]
309
 
310
- # Matriz Box-Behnken (por defecto) para 4 factores
311
  default_bb_design = [
312
  [-1, -1, 0, 0],
313
  [1, -1, 0, 0],
@@ -344,52 +211,16 @@ default_variable2_values = [0.362, 0.856, 0.177, 0.261, 0.946, 0.695, 0.892, 0.0
344
  interface = gr.Interface(
345
  fn=analyze_design,
346
  inputs=[
347
- gr.Slider(2, 3, step=1, label="Nivel de Combinación (2 o 3)", value=3),
348
- gr.Dataframe(
349
- headers=["X1", "X2", "X3", "X4"],
350
- value=default_pb_design,
351
- label="Matriz 1 (Plackett-Burman)",
352
- datatype=["number"]*4,
353
- row_count=(8, "fixed"),
354
- col_count=(4, "fixed")
355
- ),
356
- gr.Dataframe(
357
- headers=["X1", "X2", "X3", "X4"],
358
- value=default_bb_design,
359
- label="Matriz 2 (Box-Behnken)",
360
- datatype=["number"]*4,
361
- row_count=(25, "fixed"),
362
- col_count=(4, "fixed")
363
- ),
364
- gr.Dataframe(
365
- headers=["Variable 1"],
366
- value=[[val] for val in default_variable1_values],
367
- label="Valores de Variable 1",
368
- datatype=["number"],
369
- row_count=(8, "fixed"),
370
- col_count=(1, "fixed")
371
- ),
372
- gr.Dataframe(
373
- headers=["Variable 2"],
374
- value=[[val] for val in default_variable2_values],
375
- label="Valores de Variable 2",
376
- datatype=["number"],
377
- row_count=(8, "fixed"),
378
- col_count=(1, "fixed")
379
- ),
380
- gr.Dropdown(
381
- ["Style 1", "Style 2", "Style 3", "Style 4"],
382
- label="Estilo del Grafo",
383
- value="Style 1"
384
- )
385
- ],
386
- outputs=[
387
- gr.Image(label="Grafo de Relaciones entre Factores"),
388
- gr.Dataframe(label="Matriz Box-Behnken Usada"),
389
- gr.Dataframe(label="Datos Simulados para Box-Behnken")
390
  ],
391
- title="Análisis de Teoría de Grafos para Diseño Experimental",
392
- description="Analiza y visualiza las relaciones entre factores en un diseño experimental usando teoría de grafos. Además, genera y presenta datos simulados para un diseño Box-Behnken de 3 factores."
 
393
  )
394
 
395
  # Ejecutar la interfaz
 
3
 
4
  from pydantic import BaseModel, ConfigDict
5
 
6
+ class YourModel(BaseModel):
7
+ class Config:
8
+ arbitrary_types_allowed = True
9
+
10
  import numpy as np
11
  import networkx as nx
12
  import matplotlib.pyplot as plt
 
16
  from sklearn.metrics import r2_score
17
  from itertools import combinations
18
  import tempfile
 
19
 
20
  # Clase para el modelo de regresión
21
  class RegressionModel:
 
32
  X_poly = self.poly.transform(X)
33
  return self.model.predict(X_poly)
34
 
35
+ def r2_score(self, X, y):
36
  y_pred = self.predict(X)
37
  return r2_score(y, y_pred)
38
 
 
71
  self.model_variable1.fit(X, self.variable1_values)
72
  self.model_variable2.fit(X, self.variable2_values)
73
 
74
+ self.r2_variable1 = self.model_variable1.r2_score(X, self.variable1_values)
75
+ self.r2_variable2 = self.model_variable2.r2_score(X, self.variable2_values)
76
 
77
  # Clase para el análisis de teoría de grafos
78
  class GraphTheoryAnalysis:
 
84
  def set_matrices_and_values(self):
85
  self.all_factors = list(self.experiment.factor_values.keys())
86
 
87
+ def build_graph(self, level=3):
88
+ if level > len(self.all_factors):
89
+ level = len(self.all_factors) # Ajustar el nivel al número de factores disponibles
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
+ for pair in combinations(self.all_factors, level):
92
+ if len(pair) >= 2: # Asegurarse de que hay suficientes elementos para formar un par
 
 
 
93
  self.experiment.set_active_factors(list(pair))
94
  self.experiment.fit_models()
95
  r2 = (self.experiment.r2_variable1 + self.experiment.r2_variable2) / 2
96
+ self.graph.add_edge(pair[0], pair[1], weight=r2)
 
97
 
98
  def visualize_graph(self, style='Style 1'):
99
  pos = nx.spring_layout(self.graph)
 
125
  nx.draw_networkx_labels(self.graph, pos, font_size=font_size)
126
 
127
  edge_weights = [self.graph[u][v]['weight'] for u, v in self.graph.edges()]
128
+ nx.draw_networkx_edges(self.graph, pos, width=edge_weights, edge_color=edge_color)
 
 
 
129
 
130
+ edge_labels = nx.get_edge_attributes(self.graph, 'weight')
131
  nx.draw_networkx_edge_labels(self.graph, pos, edge_labels=edge_labels, font_size=font_size)
132
 
133
  plt.title(f"Grafo de relaciones entre factores basado en R² ({style})")
 
141
 
142
  return temp_file.name
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  # Definición de la interfaz de Gradio
145
  def analyze_design(level, pb_design, bb_design, variable1_values, variable2_values, style):
 
 
 
 
 
 
 
 
146
  experiment = ExperimentalDesign(regression_degree=2)
147
  optimizer = GraphTheoryAnalysis(experiment)
148
 
 
153
  'X4': [0.05, 0.5]
154
  }
155
 
156
+ experiment.set_design(np.array(pb_design), np.array(bb_design))
157
  experiment.set_factors(factor_values)
158
+ experiment.set_dependent_variables(np.array(variable1_values), np.array(variable2_values))
159
 
160
  optimizer.set_matrices_and_values()
161
+ optimizer.build_graph(level=level)
162
  graph_image_path = optimizer.visualize_graph(style=style)
163
+ return graph_image_path, bb_design
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
 
165
  # Matriz Plackett-Burman (por defecto)
166
  default_pb_design = [
 
174
  [-1, -1, -1, -1]
175
  ]
176
 
177
+ # Matriz Box-Behnken (por defecto)
178
  default_bb_design = [
179
  [-1, -1, 0, 0],
180
  [1, -1, 0, 0],
 
211
  interface = gr.Interface(
212
  fn=analyze_design,
213
  inputs=[
214
+ gr.Slider(1, 4, step=1, label="Level of Combination (1 to 4)"),
215
+ gr.Dataframe(headers=["X1", "X2", "X3", "X4"], value=default_pb_design, label="Matrix 1 (Plackett-Burman)"),
216
+ gr.Dataframe(headers=["X1", "X2", "X3", "X4"], value=default_bb_design, label="Matrix 2 (Box-Behnken)"),
217
+ gr.Dataframe(headers=["Variable 1"], value=[[val] for val in default_variable1_values], label="Variable 1 Values"),
218
+ gr.Dataframe(headers=["Variable 2"], value=[[val] for val in default_variable2_values], label="Variable 2 Values"),
219
+ gr.Dropdown(["Style 1", "Style 2", "Style 3", "Style 4"], label="Graph Style", value="Style 1")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  ],
221
+ outputs=["image", "dataframe"],
222
+ title="Graph Theory Analysis for Experimental Design",
223
+ description="Analyze and visualize the relationships between factors in an experimental design using graph theory."
224
  )
225
 
226
  # Ejecutar la interfaz