Update app.py
Browse files
app.py
CHANGED
@@ -80,23 +80,42 @@ class GraphTheoryAnalysis:
|
|
80 |
def set_matrices_and_values(self):
|
81 |
self.all_factors = list(self.experiment.factor_values.keys())
|
82 |
|
83 |
-
def build_graph(self, level=
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
|
101 |
def visualize_graph(self, style='Style 1'):
|
102 |
pos = nx.spring_layout(self.graph)
|
@@ -194,55 +213,80 @@ def analyze_design(level, pb_design, bb_design, variable1_values, variable2_valu
|
|
194 |
experiment.set_dependent_variables(np.array(variable1_values, dtype=float), np.array(variable2_values, dtype=float))
|
195 |
|
196 |
optimizer.set_matrices_and_values()
|
197 |
-
optimizer.build_graph(level=level)
|
198 |
graph_image_path = optimizer.visualize_graph(style=style)
|
199 |
|
200 |
-
# Identificar los 3 factores más activos basados en R²
|
201 |
-
factor_r2 = {}
|
202 |
-
for factor in experiment.factor_values.keys():
|
203 |
-
# Filtrar las aristas que contienen el factor
|
204 |
-
edges = [data['weight'] for u, v, data in optimizer.graph.edges(data=True) if u == factor or v == factor]
|
205 |
-
factor_r2[factor] = sum(edges) / len(edges) if edges else 0
|
206 |
-
|
207 |
-
# Seleccionar los 3 factores con mayor R²
|
208 |
-
top_factors = sorted(factor_r2, key=factor_r2.get, reverse=True)[:3]
|
209 |
-
|
210 |
-
# Generar diseño Box-Behnken para los 3 factores
|
211 |
-
bb_design_3f = generate_box_behnken(top_factors)
|
212 |
-
|
213 |
-
# Simular datos de respuesta (puedes ajustar esta parte según tus necesidades)
|
214 |
-
# Aquí, simplemente generamos valores aleatorios para las respuestas
|
215 |
-
np.random.seed(42) # Para reproducibilidad
|
216 |
-
simulated_response1 = np.random.uniform(0.1, 1.0, len(bb_design_3f))
|
217 |
-
simulated_response2 = np.random.uniform(0.1, 1.0, len(bb_design_3f))
|
218 |
-
|
219 |
-
# Crear dataframe de resultados
|
220 |
-
bb_results = []
|
221 |
-
for i, design in enumerate(bb_design_3f):
|
222 |
-
row = design.copy()
|
223 |
-
row['Response 1'] = round(simulated_response1[i], 3)
|
224 |
-
row['Response 2'] = round(simulated_response2[i], 3)
|
225 |
-
bb_results.append(row)
|
226 |
-
|
227 |
-
# Convertir bb_design_used a DataFrame para mostrar
|
228 |
if level == 3:
|
229 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
230 |
bb_design_used = bb_design_3f
|
231 |
headers = top_factors + ['Response 1', 'Response 2']
|
232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
# Usar el diseño Box-Behnken ingresado por el usuario para 4 factores
|
234 |
bb_design_used = []
|
235 |
for row in bb_design:
|
236 |
design_row = { 'X1': row[0], 'X2': row[1], 'X3': row[2], 'X4': row[3] }
|
237 |
bb_design_used.append(design_row)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
238 |
headers = ['X1', 'X2', 'X3', 'X4', 'Response 1', 'Response 2']
|
239 |
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
|
|
|
|
|
|
|
|
|
|
244 |
|
245 |
-
return graph_image_path, df_bb_used,
|
246 |
|
247 |
# Matriz Plackett-Burman (por defecto)
|
248 |
default_pb_design = [
|
|
|
80 |
def set_matrices_and_values(self):
|
81 |
self.all_factors = list(self.experiment.factor_values.keys())
|
82 |
|
83 |
+
def build_graph(self, level=2, r2_threshold=0.5):
|
84 |
+
"""
|
85 |
+
Construye el grafo basado en el nivel de combinación.
|
86 |
+
|
87 |
+
Args:
|
88 |
+
level (int): Nivel de combinación (2 o 3).
|
89 |
+
r2_threshold (float): Umbral de R² para incluir una interacción.
|
90 |
+
"""
|
91 |
+
self.graph.clear() # Limpiar grafo existente
|
92 |
+
|
93 |
+
if level == 2:
|
94 |
+
# Considerar todas las combinaciones de 2 factores
|
95 |
+
for pair in combinations(self.all_factors, 2):
|
96 |
+
self.experiment.set_active_factors(list(pair))
|
97 |
+
self.experiment.fit_models()
|
98 |
+
r2 = (self.experiment.r2_variable1 + self.experiment.r2_variable2) / 2
|
99 |
+
if r2 >= r2_threshold:
|
100 |
+
self.graph.add_edge(pair[0], pair[1], weight=r2)
|
101 |
+
elif level == 3:
|
102 |
+
# Identificar los 3 factores más relevantes
|
103 |
+
factor_r2 = {}
|
104 |
+
for factor in self.all_factors:
|
105 |
+
edges = [data['weight'] for u, v, data in self.graph.edges(data=True) if u == factor or v == factor]
|
106 |
+
factor_r2[factor] = sum(edges) / len(edges) if edges else 0
|
107 |
+
|
108 |
+
top_factors = sorted(factor_r2, key=factor_r2.get, reverse=True)[:3]
|
109 |
+
|
110 |
+
# Añadir únicamente las interacciones entre los 3 factores seleccionados
|
111 |
+
for pair in combinations(top_factors, 2):
|
112 |
+
self.experiment.set_active_factors(list(pair))
|
113 |
+
self.experiment.fit_models()
|
114 |
+
r2 = (self.experiment.r2_variable1 + self.experiment.r2_variable2) / 2
|
115 |
+
if r2 >= r2_threshold:
|
116 |
+
self.graph.add_edge(pair[0], pair[1], weight=r2)
|
117 |
+
else:
|
118 |
+
raise ValueError("Nivel de combinación no soportado. Debe ser 2 o 3.")
|
119 |
|
120 |
def visualize_graph(self, style='Style 1'):
|
121 |
pos = nx.spring_layout(self.graph)
|
|
|
213 |
experiment.set_dependent_variables(np.array(variable1_values, dtype=float), np.array(variable2_values, dtype=float))
|
214 |
|
215 |
optimizer.set_matrices_and_values()
|
216 |
+
optimizer.build_graph(level=level, r2_threshold=0.5) # Ajusta el umbral según tus necesidades
|
217 |
graph_image_path = optimizer.visualize_graph(style=style)
|
218 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
if level == 3:
|
220 |
+
# Identificar los 3 factores más activos basados en R²
|
221 |
+
factor_r2 = {}
|
222 |
+
for factor in experiment.factor_values.keys():
|
223 |
+
# Filtrar las aristas que contienen el factor
|
224 |
+
edges = [data['weight'] for u, v, data in optimizer.graph.edges(data=True) if u == factor or v == factor]
|
225 |
+
factor_r2[factor] = sum(edges) / len(edges) if edges else 0
|
226 |
+
|
227 |
+
# Seleccionar los 3 factores con mayor R²
|
228 |
+
top_factors = sorted(factor_r2, key=factor_r2.get, reverse=True)[:3]
|
229 |
+
|
230 |
+
# Generar diseño Box-Behnken para los 3 factores
|
231 |
+
bb_design_3f = generate_box_behnken(top_factors)
|
232 |
+
|
233 |
+
# Simular datos de respuesta (puedes ajustar esta parte según tus necesidades)
|
234 |
+
# Aquí, simplemente generamos valores aleatorios para las respuestas
|
235 |
+
np.random.seed(42) # Para reproducibilidad
|
236 |
+
simulated_response1 = np.random.uniform(0.1, 1.0, len(bb_design_3f))
|
237 |
+
simulated_response2 = np.random.uniform(0.1, 1.0, len(bb_design_3f))
|
238 |
+
|
239 |
+
# Crear dataframe de resultados
|
240 |
+
bb_results = []
|
241 |
+
for i, design in enumerate(bb_design_3f):
|
242 |
+
row = design.copy()
|
243 |
+
row['Response 1'] = round(simulated_response1[i], 3)
|
244 |
+
row['Response 2'] = round(simulated_response2[i], 3)
|
245 |
+
bb_results.append(row)
|
246 |
+
|
247 |
+
# Convertir bb_design_used a DataFrame para mostrar
|
248 |
bb_design_used = bb_design_3f
|
249 |
headers = top_factors + ['Response 1', 'Response 2']
|
250 |
+
|
251 |
+
# Crear DataFrame para la matriz Box-Behnken usada
|
252 |
+
df_bb_used = pd.DataFrame(bb_design_used)
|
253 |
+
# Agregar respuestas al DataFrame
|
254 |
+
df_bb_used[['Response 1', 'Response 2']] = pd.DataFrame(bb_results)[['Response 1', 'Response 2']]
|
255 |
+
|
256 |
+
elif level == 2:
|
257 |
# Usar el diseño Box-Behnken ingresado por el usuario para 4 factores
|
258 |
bb_design_used = []
|
259 |
for row in bb_design:
|
260 |
design_row = { 'X1': row[0], 'X2': row[1], 'X3': row[2], 'X4': row[3] }
|
261 |
bb_design_used.append(design_row)
|
262 |
+
|
263 |
+
# Simular datos de respuesta (puedes ajustar esta parte según tus necesidades)
|
264 |
+
# Aquí, simplemente generamos valores aleatorios para las respuestas
|
265 |
+
np.random.seed(42) # Para reproducibilidad
|
266 |
+
simulated_response1 = np.random.uniform(0.1, 1.0, len(bb_design_used))
|
267 |
+
simulated_response2 = np.random.uniform(0.1, 1.0, len(bb_design_used))
|
268 |
+
|
269 |
+
# Crear dataframe de resultados
|
270 |
+
bb_results = []
|
271 |
+
for i, design in enumerate(bb_design_used):
|
272 |
+
row = design.copy()
|
273 |
+
row['Response 1'] = round(simulated_response1[i], 3)
|
274 |
+
row['Response 2'] = round(simulated_response2[i], 3)
|
275 |
+
bb_results.append(row)
|
276 |
+
|
277 |
headers = ['X1', 'X2', 'X3', 'X4', 'Response 1', 'Response 2']
|
278 |
|
279 |
+
# Crear DataFrame para la matriz Box-Behnken usada
|
280 |
+
df_bb_used = pd.DataFrame(bb_design_used)
|
281 |
+
# Agregar respuestas al DataFrame
|
282 |
+
df_bb_used[['Response 1', 'Response 2']] = pd.DataFrame(bb_results)[['Response 1', 'Response 2']]
|
283 |
+
else:
|
284 |
+
return "Error: Nivel de combinación inválido. Debe ser 2 o 3.", None, None
|
285 |
+
|
286 |
+
# Crear DataFrame para los datos simulados
|
287 |
+
df_simulated = df_bb_used.copy()
|
288 |
|
289 |
+
return graph_image_path, df_bb_used, df_simulated
|
290 |
|
291 |
# Matriz Plackett-Burman (por defecto)
|
292 |
default_pb_design = [
|