mg-pso-gui 0.1.13__py3-none-any.whl → 0.2.75__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. {mg_pso_gui-0.1.13.dist-info → mg_pso_gui-0.2.75.dist-info}/METADATA +10 -11
  2. mg_pso_gui-0.2.75.dist-info/RECORD +76 -0
  3. {mg_pso_gui-0.1.13.dist-info → mg_pso_gui-0.2.75.dist-info}/WHEEL +1 -1
  4. mgpsogui/gui/General/ParameterView.py +110 -0
  5. mgpsogui/gui/General/__init__.py +0 -0
  6. mgpsogui/gui/HomePage.py +565 -513
  7. mgpsogui/gui/OptionManager.py +333 -145
  8. mgpsogui/gui/OptionManager_backup.py +443 -0
  9. mgpsogui/gui/PlatformTab/PlatformTab.py +15 -6
  10. mgpsogui/gui/RunTab/OptimalParameterView.py +47 -0
  11. mgpsogui/gui/RunTab/RunTab.py +89 -35
  12. mgpsogui/gui/SetupTab/BoundsEditorWindow.py +1 -1
  13. mgpsogui/gui/SetupTab/BoundsList.py +97 -34
  14. mgpsogui/gui/SetupTab/CustomFunctionEditorWindow.py +74 -0
  15. mgpsogui/gui/SetupTab/CustomFunctionMetrics.py +156 -0
  16. mgpsogui/gui/SetupTab/FunctionsList.py +60 -6
  17. mgpsogui/gui/SetupTab/{StaticParameterView.py → ListEditor.py} +27 -16
  18. mgpsogui/gui/SetupTab/ListParametersView.py +7 -6
  19. mgpsogui/gui/SetupTab/{CalibrationParametersView.py → OverrideParameterMetrics.py} +35 -9
  20. mgpsogui/gui/SetupTab/OverrideParameterWindow.py +40 -0
  21. mgpsogui/gui/SetupTab/SetupTab.py +31 -11
  22. mgpsogui/gui/SetupTab/StepView.py +93 -22
  23. mgpsogui/gui/VisualizeTab/MatrixEditor.py +68 -0
  24. mgpsogui/gui/VisualizeTab/SideBar.py +399 -0
  25. mgpsogui/gui/VisualizeTab/VisualizeTab.py +76 -11
  26. mgpsogui/gui/defaults/__init__.py +0 -0
  27. mgpsogui/gui/defaults/optimization.json +176 -0
  28. mgpsogui/gui/defaults/sampling.json +111 -0
  29. mgpsogui/gui/defaults/sensitivity.json +20 -0
  30. mgpsogui/gui/images/plus.png +0 -0
  31. mgpsogui/gui/images/test.png +0 -0
  32. mgpsogui/util/GraphGenerator.py +747 -42
  33. mgpsogui/util/PSORunner.py +608 -116
  34. mgpsogui/util/debug.py +559 -0
  35. mgpsogui/util/helpers.py +95 -0
  36. mgpsogui/util/recosu/__init__.py +2 -1
  37. mgpsogui/util/recosu/pso/csip_access.py +2 -35
  38. mgpsogui/util/recosu/pso/pso.py +55 -59
  39. mgpsogui/util/recosu/sampling/__init__.py +16 -0
  40. mgpsogui/util/recosu/sampling/halton/__init__.py +0 -0
  41. mgpsogui/util/recosu/sampling/halton/halton.py +45 -0
  42. mgpsogui/util/recosu/sampling/halton/prime.py +82 -0
  43. mgpsogui/util/recosu/sampling/random/__init__.py +0 -0
  44. mgpsogui/util/recosu/sampling/random/random_sampler.py +34 -0
  45. mgpsogui/util/recosu/sampling/sample_trace_writer.py +47 -0
  46. mgpsogui/util/recosu/sampling/sampler_task.py +75 -0
  47. mgpsogui/util/recosu/sampling/sampling.py +99 -0
  48. mgpsogui/util/sampler_test_driver.py +129 -0
  49. mg_pso_gui-0.1.13.dist-info/RECORD +0 -50
  50. mgpsogui/gui/images/IGOW 4 Logo.png +0 -0
  51. {mg_pso_gui-0.1.13.dist-info → mg_pso_gui-0.2.75.dist-info}/entry_points.txt +0 -0
  52. {mg_pso_gui-0.1.13.dist-info → mg_pso_gui-0.2.75.dist-info}/top_level.txt +0 -0
mgpsogui/gui/HomePage.py CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/local/bin/python3.9
1
+ #!/usr/local/bin/python3.10
2
2
 
3
3
  import os
4
4
  import time
@@ -13,12 +13,14 @@ import requests
13
13
  import tkinter as tk
14
14
  import tkinter.messagebox
15
15
  import customtkinter
16
+ from customtkinter import ThemeManager
16
17
  import json
17
18
  import os
18
19
  from PIL import Image, ImageTk
19
20
  import traceback
20
21
  from multiprocessing import Process
21
22
  from multiprocessing import Queue
23
+
22
24
  import re
23
25
  import pandas as pd
24
26
  import numpy as np
@@ -30,6 +32,8 @@ from queue import Empty
30
32
 
31
33
  from ..util import PSORunner
32
34
  from ..util import GraphGenerator
35
+ from ..util.CTkToolTip import CTkToolTip as ctt
36
+ from ..util import helpers as hp
33
37
 
34
38
  import subprocess
35
39
  import plotly.express as px
@@ -47,526 +51,574 @@ from .VisualizeTab import VisualizeTab as vt
47
51
 
48
52
  from ..util.CTkToolTip import CTkToolTip as ctt
49
53
 
50
- customtkinter.set_appearance_mode("Dark") # Modes: "System" (standard), "Dark", "Light"
54
+ customtkinter.set_appearance_mode("System") # Modes: "System" (standard), "Dark", "Light"
51
55
  customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
52
56
 
53
57
  results_queue = Queue()
54
58
  stdout_queue = Queue()
55
59
  stderr_queue = Queue()
56
- cosu_queue = Queue()
57
60
 
58
61
  class App(customtkinter.CTk):
59
- def __init__(self):
60
- super().__init__()
61
-
62
- self.option_manager = om.OptionManager()
63
-
64
- self.running_config = None
65
- self.selected_graph_name = None
66
-
67
- self.train_process = None
68
- self.minikube_process = None
69
- self.data_x = [0]
70
- self.data_y = [0]
71
-
72
- self.image_width = 1280
73
- self.image_height = 720
74
-
75
- # configure window
76
- self.title("CSIP PSO")
77
- self.geometry(f"{1920}x{1080}")
78
-
79
- # configure grid layout (4x4)
80
- self.grid_columnconfigure(0, weight=1)
81
- self.grid_rowconfigure(1, weight=1)
82
-
83
- header_padding_x = (5, 5)
84
- header_padding_y = (10, 10)
85
-
86
- self.sidebar_frame = customtkinter.CTkFrame(self, width=140, corner_radius=0)
87
- self.sidebar_frame.grid(row=0, column=0, sticky="nsew")
88
- self.sidebar_frame.grid_columnconfigure(4, weight=1)
89
- self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="CSIP PSO", font=customtkinter.CTkFont(size=20, weight="bold"))
90
- self.logo_label.grid(row=0, column=0, padx=(20, 10), pady=header_padding_y)
91
- self.save_button = customtkinter.CTkButton(self.sidebar_frame, text="Save", width=60, command=self.save_project)
92
- self.save_button.grid(row=0, column=1, padx=header_padding_x, pady=header_padding_y)
93
- self.load_button = customtkinter.CTkButton(self.sidebar_frame, text="Load", width=60, command=self.load_project)
94
- self.load_button.grid(row=0, column=2, padx=header_padding_x, pady=header_padding_y)
95
-
96
- # 4 is service URL
97
- self.service_label = customtkinter.CTkLabel(self.sidebar_frame, text="Service:", anchor="w")
98
- self.service_label.grid(row=0, column=3, padx=(80, 5), pady=header_padding_y)
99
- self.service_url = customtkinter.CTkEntry(self.sidebar_frame, textvariable=self.option_manager.get_arguments()['url'])
100
- self.service_url.grid(row=0, column=4, columnspan=1, padx=header_padding_x, pady=header_padding_y, sticky="nsew")
101
- refresh_image = customtkinter.CTkImage(Image.open(os.path.join("./images", "refresh.png")), size=(20, 20))
102
- self.refresh_button = customtkinter.CTkButton(self.sidebar_frame, text=None, width=30, image=refresh_image, command=self.load)
103
- self.refresh_button.grid(row=0, column=5, padx=(5, 80), pady=header_padding_y)
104
-
105
- self.scaling_label = customtkinter.CTkLabel(self.sidebar_frame, text="Scale:", anchor="w")
106
- self.scaling_label.grid(row=0, column=6, padx=header_padding_x, pady=header_padding_y)
107
- self.scaling_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["50%", "75%", "100%", "125%", "150%", "175%", "200%"], width=60,
108
- command=self.change_scaling_event)
109
- self.scaling_optionemenu.grid(row=0, column=7, padx=header_padding_x, pady=header_padding_y)
110
- self.scaling_optionemenu.set("100%")
111
-
112
- expand_image = customtkinter.CTkImage(Image.open(os.path.join("./images", "expand.png")), size=(20, 20))
113
- self.new_window = customtkinter.CTkButton(self.sidebar_frame, text=None, width=30, image=expand_image, command=self.new_window)
114
- self.new_window.grid(row=0, column=8, padx=(5, 20), pady=header_padding_y)
115
-
116
- self.tabview = customtkinter.CTkTabview(self, bg_color="transparent", fg_color="transparent")
117
- self.tabview.grid(row=1, column=0, padx=(0, 0), pady=(10, 10), sticky="nsew")
118
- tab1 = "Platform"
119
- tab2 = "Setup"
120
- tab3 = "Logs"
121
- tab4 = "Results"
122
- #tab5 = "Results"
123
-
124
- self.tabview.add(tab1)
125
- self.tabview.add(tab2)
126
- self.tabview.add(tab4)
127
- self.tabview.add(tab3)
128
- #self.tabview.add(tab5)
129
-
130
- #self.tabview.configure(state="disabled")
131
-
132
- pt.create_tab(self, self.tabview.tab(tab1))
133
- st.create_tab(self, self.tabview.tab(tab2))
134
- rt.create_tab(self, self.tabview.tab(tab3))
135
- vt.create_tab(self, self.tabview.tab(tab4))
136
-
137
- self.footer_frame = customtkinter.CTkFrame(self, corner_radius=0)
138
- self.footer_frame.grid(row=2, column=0, sticky="nsew")
139
- self.footer_frame.grid_columnconfigure(4, weight=1)
140
-
141
- self.footer_progress_label = customtkinter.CTkLabel(self.footer_frame, text="Stopped", width=150, font=customtkinter.CTkFont(size=16, weight="bold"), anchor="w")
142
- self.footer_progress_label.grid(row=0, column=0, padx=(20, 5), pady=header_padding_y)
143
-
144
- self.footer_progress_bar = customtkinter.CTkProgressBar(self.footer_frame)
145
- self.footer_progress_bar.grid(row=0, column=4, padx=(50, 100), pady=header_padding_y, sticky="ew")
146
- self.footer_progress_bar.set(0)
147
-
148
- play_image = customtkinter.CTkImage(Image.open(os.path.join("./images", "play.png")), size=(20, 20))
149
- self.new_window = customtkinter.CTkButton(self.footer_frame, text=None, width=30, image=play_image, command=self.run)
150
- self.new_window.grid(row=0, column=7, padx=(5, 5), pady=header_padding_y)
151
-
152
- stop_image = customtkinter.CTkImage(Image.open(os.path.join("./images", "stop.png")), size=(20, 20))
153
- self.new_window = customtkinter.CTkButton(self.footer_frame, text=None, width=30, image=stop_image, command=self.stop)
154
- self.new_window.grid(row=0, column=8, padx=(5, 20), pady=header_padding_y)
155
-
156
- def _resize_image(self, event):
157
- self.graph_label.update_idletasks()
158
- new_width = self.graph_label.winfo_width()
159
- new_height = self.graph_label.winfo_height()
160
-
161
- alt_width = new_height * 1.77778
162
- alt_height = new_width / 1.77778
163
-
164
- if (new_width < new_height):
165
- new_height = alt_height
166
- else:
167
- new_width = alt_width
168
-
169
- self.image_width = new_width
170
- self.image_height = new_height
171
-
172
- self.graph_image = customtkinter.CTkImage(self.graph_image_obj, size=(new_width, new_height))
173
- self.graph_label.configure(image=self.graph_image)
174
- self.graph_label.update_idletasks()
175
-
176
- def callback_test(self, *args):
177
- print("callback_test called")
178
-
179
- def update_graph(self, value):
180
- selected_graph = self.graph_selector_value.get()
181
- info = self.option_manager.get_project_data()
182
- folder = os.path.join(info['path'], info['name'])
183
-
184
- if not os.path.exists(folder):
185
- os.makedirs(folder)
186
-
187
- if (selected_graph == "Best Cost Stacked"):
188
- self.selected_graph_name = "best_cost_stacked"
189
- image_path = os.path.join(folder, self.selected_graph_name + ".png")
190
- if not os.path.exists(image_path):
191
- image_path = os.path.join("./images", "up.png")
192
- self.graph_image_obj = Image.open(image_path)
193
- self.graph_image = customtkinter.CTkImage(self.graph_image_obj, size=(self.image_width, self.image_height))
194
- self.graph_label.configure(image=self.graph_image)
195
- elif (selected_graph == "Best Cost by Round"):
196
- self.selected_graph_name = "best_cost_by_round"
197
- image_path = os.path.join(folder, self.selected_graph_name + ".png")
198
- if not os.path.exists(image_path):
199
- image_path = os.path.join("./images", "up.png")
200
- self.graph_image_obj = Image.open(image_path)
201
- self.graph_image = customtkinter.CTkImage(self.graph_image_obj, size=(self.image_width, self.image_height))
202
- self.graph_label.configure(image=self.graph_image)
203
- elif (selected_graph == "Iteration Table"):
204
- self.selected_graph_name = "table"
205
- image_path = os.path.join(folder, self.selected_graph_name + ".png")
206
- if not os.path.exists(image_path):
207
- image_path = os.path.join("./images", "up.png")
208
- self.graph_image_obj = Image.open(image_path)
209
- self.graph_image = customtkinter.CTkImage(self.graph_image_obj, size=(self.image_width, self.image_height))
210
- self.graph_label.configure(image=self.graph_image)
211
- elif (selected_graph == "Calibrated Parameters"):
212
- self.selected_graph_name = "calibrated_params_by_round"
213
- image_path = os.path.join(folder, self.selected_graph_name + ".png")
214
- if not os.path.exists(image_path):
215
- image_path = os.path.join("./images", "up.png")
216
- self.graph_image_obj = Image.open(image_path)
217
- self.graph_image = customtkinter.CTkImage(self.graph_image_obj, size=(self.image_width, self.image_height))
218
- self.graph_label.configure(image=self.graph_image)
219
-
220
- def save_project(self):
221
- metrics = self.option_manager.get_metrics()
222
- filename = asksaveasfilename(filetypes=[("JSON", "*.json")], initialfile="config", defaultextension="json", title="Save Project")
223
-
224
- try:
225
-
226
- # Convert metrics to json and save to file with proper spacing
227
- with open(filename, "w") as f:
228
- f.write(json.dumps(metrics, indent=4))
229
-
230
- self.save_button.configure(text="Saved!")
231
- self.after(3000, lambda: self.save_button.configure(text="Save"))
232
- except Exception as e:
233
- self.save_button.configure(text="Error!")
234
- print(e)
235
- self.after(3000, lambda: self.save_button.configure(text="Save"))
236
-
237
- def new_window(self):
238
- # Shell out and run ./main.py
239
- subprocess.Popen(["python3", "../mgpsogui.py"])
240
-
241
- def load_project(self):
242
-
243
- filename = askopenfilename(filetypes=[("JSON", "*.json")], title="Open Project", multiple=False)
244
- print(filename)
245
-
246
- try:
247
-
248
- # Load config.json and convert to metrics
249
- with open(filename, "r") as f:
250
- metrics = json.loads(f.read())
251
-
252
- self.option_manager.set_path(filename)
253
-
254
- if "arguments" in metrics:
255
- metrics["arguments"]["calibration_parameters"] = metrics["calibration_parameters"]
256
-
257
- if "service_parameters" in metrics:
258
- self.option_manager.set_service_parameters(metrics["service_parameters"])
259
- self.tabview.configure(state="enabled")
260
-
261
- print(metrics)
262
-
263
- self.option_manager.clear()
264
- self.option_manager.add_arguments(metrics["arguments"])
265
- self.option_manager.add_steps(metrics["steps"])
266
-
267
- self.steps_frame.clear()
268
- self.steps_frame.render()
269
-
270
- self.static_param_frame.clear()
271
- self.static_param_frame.render()
272
-
273
- self.calib_param_frame.clear()
274
- self.calib_param_frame.render()
275
-
276
- self.load_button.configure(text="Loaded!")
277
- self.after(3000, lambda: self.load_button.configure(text="Load"))
278
-
279
- except Exception as e:
280
- print(e)
281
- self.load_button.configure(text="Error!")
282
- self.after(3000, lambda: self.load_button.configure(text="Load"))
283
-
284
- def change_appearance_mode_event(self, new_appearance_mode: str):
285
- customtkinter.set_appearance_mode(new_appearance_mode)
286
-
287
- def change_scaling_event(self, new_scaling: str):
288
- new_scaling_float = int(new_scaling.replace("%", "")) / 100
289
- customtkinter.set_widget_scaling(new_scaling_float)
290
-
291
- def change_scaling_event(self, new_scaling: str):
292
- new_scaling_float = int(new_scaling.replace("%", "")) / 100
293
- customtkinter.set_widget_scaling(new_scaling_float)
294
-
295
- def make_request(self):
296
- service_url = self.service_url.get()
297
- try:
298
- response = requests.get(service_url)
299
-
300
- response_json = json.loads(response.text)
301
- status = response.status_code
302
-
303
- self.option_manager.set_service_parameters(response_json)
304
-
305
- self.service_status.delete('0.0', tk.END)
306
- self.service_status.insert(text=str(status), index='0.0')
307
- self.service_name.delete('0.0', tk.END)
308
- self.service_name.insert(text=str(response_json["metainfo"]["name"]), index='0.0')
309
- self.service_description.delete('0.0', tk.END)
310
- self.service_description.insert(text=str(response_json["metainfo"]["description"]), index='0.0')
311
- self.service_details.delete('0.0', tk.END)
312
- self.service_details.insert(text=json.dumps(response_json, indent=4), index='0.0')
313
-
314
- self.refresh_button.configure(fg_color="green")
315
- except Exception as e:
316
- self.refresh_button.configure(fg_color="red")
317
-
318
-
319
- def load(self):
320
- # Make HTTP request to service_url and save the result to bounds.json
321
-
322
- self.default_button_color = self.refresh_button.cget("fg_color")
323
-
324
- self.refresh_button.configure(fg_color="gray")
325
-
326
- self.after(10, self.make_request)
327
- self.after(3000, lambda: self.refresh_button.configure(fg_color=self.default_button_color))
328
-
329
- def run(self):
330
- metrics = self.option_manager.get_metrics()
331
- self.running_config = metrics
332
-
333
- #self.progress_bar.configure(mode="indeterminnate")
334
- #self.progress_bar.start()
335
- self.footer_progress_bar.configure(mode="indeterminnate")
336
- self.footer_progress_bar.start()
337
-
338
- self.data_x = [0]
339
- self.data_y = [0]
340
-
341
- self.progress_message_middle.configure(text="Calibration starting...")
342
- self.footer_progress_label.configure(text="Starting...")
343
-
344
- self.textbox.insert("0.0", "Starting calibration...\n\n")
345
- self.textbox.insert("0.0", "Calibration Parameters:\n")
346
- self.textbox.insert("0.0", json.dumps(metrics, indent=4) + "\n\n")
347
- try:
348
- info = self.option_manager.get_project_data()
349
- folder = os.path.join(info['path'], info['name'])
350
-
351
- self.train_process = Process(target=PSORunner.run_process, args=(stdout_queue, stderr_queue, results_queue, cosu_queue, metrics, folder))
352
- self.train_process.daemon = True
353
- self.train_process.start()
354
- self.after(1000, self.watch_loop)
355
- self.string_cache = ""
356
- self.data_cache = ""
357
-
358
- except Exception as e:
359
- self.textbox.insert("0.0", "An exception occurred!\n Exception: " + str(e) + "\n\n")
360
- self.textbox.insert("0.0", "Stack trace:\n")
361
- self.textbox.insert("0.0", traceback.format_exc())
362
- self.textbox.insert("0.0", "\n\n")
363
- self.textbox.insert("0.0", "Calibration failed!")
364
- self.progress_message_left.configure(text="")
365
- self.progress_message_middle.configure(text="Calibration failed! See error log below.")
366
- self.progress_message_right.configure(text="")
367
- self.footer_progress_label.configure(text="Failed")
368
- #self.progress_bar.stop()
369
- self.footer_progress_bar.stop()
370
- #self.progress_bar.configure(mode="determinate")
371
- self.footer_progress_bar.configure(mode="determinate")
372
- #self.progress_bar.set(0)
373
- self.footer_progress_bar.set(0)
374
-
375
- def stop(self):
376
- print("Stopping...")
377
- self.train_process.terminate()
378
-
379
- info = self.option_manager.get_project_data()
380
- folder = os.path.join(info['path'], info['name'])
381
-
382
- if not os.path.exists(folder):
383
- os.makedirs(folder)
384
-
385
- # Stop the process
386
- if (os.path.exists(os.path.join(folder, 'output.txt'))):
387
- os.remove(os.path.join(folder, 'output.txt'))
388
-
389
- if (os.path.exists(os.path.join(folder, 'error.txt'))):
390
- os.remove(os.path.join(folder, 'error.txt'))
391
-
392
- self.textbox.insert("0.0", "\nCalibration terminated!\n")
393
- #self.progress_bar.stop()
394
- self.footer_progress_bar.stop()
395
- #self.progress_bar.configure(mode="determinate")
396
- self.footer_progress_bar.configure(mode="determinate")
397
- #self.progress_bar.set(0)
398
- self.footer_progress_bar.set(0)
399
- self.progress_message_left.configure(text="")
400
- self.progress_message_middle.configure(text="Calibration stopped!")
401
- self.footer_progress_label.configure(text="Stopped")
402
- self.progress_message_right.configure(text="")
403
-
404
- def watch_loop(self):
405
- # Check if file exists:
406
-
407
- info = self.option_manager.get_project_data()
408
- folder = os.path.join(info['path'], info['name'])
409
-
410
- if not os.path.exists(folder):
411
- os.makedirs(folder)
412
-
413
- while True:
414
- try:
415
- stdout_line = stdout_queue.get_nowait()
416
-
417
- print("# " + stdout_line, flush=True)
418
- with open(os.path.join(folder, 'output.txt'), 'a') as f:
419
- f.write(stdout_line)
420
-
421
- except Empty:
422
- break
423
-
424
- while True:
425
- try:
426
- stderr_line = stderr_queue.get_nowait()
427
-
428
- print("? " + stderr_line, flush=True)
429
- with open(os.path.join(folder, 'error.txt'), 'a') as f:
430
- f.write(stderr_line)
431
-
432
- except Empty:
433
- break
434
-
435
- while True:
436
- try:
437
- cosu_line = cosu_queue.get_nowait()
438
-
439
- print("COSU " + cosu_line, flush=True)
440
- except Empty:
441
- break
442
-
443
- if (os.path.exists(os.path.join(folder, 'output.txt'))):
444
- with open(os.path.join(folder, 'output.txt'), 'r') as f:
445
- lines = f.readlines()
446
- lines_string = "".join(lines)
447
-
448
- new_characters = lines_string.replace(self.string_cache, "")
449
- # Update the textbox with characters not in self.string_cache
450
- self.textbox.insert('0.0', new_characters)
451
- self.string_cache = lines_string
452
- print(new_characters, end="")
453
-
454
- try:
455
- with open(os.path.join(folder, "output.txt"), "r") as f:
456
- text = f.read()
457
-
458
- calibrated_params_pattern = r"calibrated params: ({.*?})"
459
- best_particle_values_pattern = r"best particle values: (\[.*?\])"
460
- progress_pattern = r"Progress - best_round_cost:(.*?), rel_round_tol:(.*?), rtol:(.*?)\n"
461
-
462
- calibrated_params = re.findall(calibrated_params_pattern, text)
463
- best_particle_values = re.findall(best_particle_values_pattern, text)
464
- progress_values = re.findall(progress_pattern, text)
465
-
466
- for index, pp in enumerate(best_particle_values):
467
- pp = pp.strip()
468
- pp = pp.replace('[ ', '[')
469
- pp = pp.replace(' ', ',')
470
- pp = pp.replace(' ', ',')
471
- best_particle_values[index] = pp
472
-
473
- calibrated_params = [ast.literal_eval(i) for i in calibrated_params]
474
- best_particle_values = [ast.literal_eval(i) for i in best_particle_values]
475
- progress_values = [tuple(map(float, i)) for i in progress_values]
476
-
477
- print("Current params: " + str(calibrated_params), flush=True)
478
-
479
- GraphGenerator.calibrated_params_by_round(self.running_config['steps'], calibrated_params, self.option_manager)
480
- self.update_graph("")
481
- except Exception as e:
482
- # Print stack trace
483
- traceback.print_exc()
484
-
485
- print(e)
486
-
487
- if (os.path.exists(os.path.join(folder, 'error.txt'))):
488
- with open(os.path.join(folder, 'error.txt'), 'r') as f:
489
- lines = f.readlines()
490
- lines_string = "".join(lines)
491
- self.data_cache = lines_string
492
-
493
- pattern = r'(\d+)%\|.*\|(\d+)/(\d+)(?:,\sbest_cost=(\d+\.\d+))?' # The magic of AI
494
- matches = re.findall(pattern, self.data_cache)
495
- filtered_matches = [match for match in matches if match[3] != '']
496
- matches = filtered_matches
497
-
498
- if len(matches) > 0:
499
- df = pd.DataFrame(matches, columns=['percent', 'completed_rounds', 'total_rounds', 'best_cost'], dtype=float)
500
- df = df[df['best_cost'] != '']
501
- df = df.dropna()
502
- df = df.drop_duplicates()
503
- df['round_step'] = (df['completed_rounds'].diff() < 0).cumsum()
504
- df = df.drop_duplicates(subset=['completed_rounds', 'round_step'])
505
-
506
- GraphGenerator.best_cost_stacked(self.running_config['steps'], df, self.option_manager)
507
- GraphGenerator.best_cost_by_round(self.running_config['steps'], df, self.option_manager)
508
- GraphGenerator.table(self.running_config['steps'], df, self.option_manager)
509
- self.update_graph("")
510
-
511
- match = matches[-1]
512
- percent = int(match[0])
513
- completed_rounds = int(match[1])
514
- total_rounds = int(match[2])
515
- best_cost = float(match[3]) if match[3] else None
516
-
517
- if (percent > 0):
518
- #self.progress_bar.stop()
519
- self.footer_progress_bar.stop()
520
- #self.progress_bar.configure(mode="determinate")
521
- self.footer_progress_bar.configure(mode="determinate")
522
- #self.progress_bar.set(percent/100)
523
- self.footer_progress_bar.set(percent/100)
524
- self.progress_message_left.configure(text="Percent Complete: " + str(percent) + "%")
525
- self.progress_message_middle.configure(text=str(completed_rounds) + "/" + str(total_rounds))
526
- self.footer_progress_label.configure(text=str(completed_rounds) + "/" + str(total_rounds))
527
- self.progress_message_right.configure(text="Best Cost: " + str(best_cost))
528
- else:
529
- #self.progress_bar.configure(mode="indeterminate")
530
- self.footer_progress_bar.configure(mode="indeterminate")
531
- #self.progress_bar.start()
532
- self.footer_progress_bar.start()
533
- self.progress_message_left.configure(text="")
534
- self.progress_message_middle.configure(text="Starting new round...")
535
- self.footer_progress_label.configure(text="Next round...")
536
- self.progress_message_right.configure(text="")
537
-
538
-
539
-
540
- if self.train_process.is_alive():
541
- self.after(1000, self.watch_loop)
542
- else:
543
- # Check if queue is empty
544
- """
545
- if (self.process_queue.empty()):
546
- print("PROCESS FINISHED BUT WE GOT NO OBJECTS :(")
547
- self.footer_progress_label.configure(text="Failed")
548
- else:
549
- self.final_results = self.process_queue.get()
550
- print("PROCESS FINISHED WE GOT THINGS")
551
- print(self.final_results)
552
- self.footer_progress_label.configure(text="Finished")
553
- """
554
-
555
- #self.progress_bar.stop()
556
- self.footer_progress_bar.stop()
557
- #self.progress_bar.configure(mode="indeterminate")
558
- self.footer_progress_bar.configure(mode="indeterminate")
559
- #self.progress_bar.start()
560
- self.footer_progress_bar.start()
561
- self.progress_message_left.configure(text="")
562
- self.progress_message_middle.configure(text="Calibration finished!")
563
- self.progress_message_right.configure(text="")
564
- self.textbox.insert("0.0", "\nCalibration finished!\n")
62
+ def __init__(self):
63
+ super().__init__()
64
+
65
+ self.option_manager = om.OptionManager()
66
+
67
+ # self.graph_selector_value = tk.StringVar()
68
+ # self.graph_selector_value.set("Best Cost Stacked")
69
+
70
+ # self.graph_theme_value = tk.StringVar()
71
+ # self.graph_theme_value.set("Dark")
72
+
73
+ # self.selected_csv = tk.StringVar()
74
+ # self.selected_csv.set("No files found...")
75
+ self.open_file = "None"
76
+ self.csv_data = None
77
+
78
+ # self.selected_csv2 = tk.StringVar()
79
+ # self.selected_csv2.set("No files found...")
80
+ self.open_file2 = "None"
81
+ self.csv_data2 = None
82
+
83
+ # self.selected_x = tk.StringVar()
84
+ # self.selected_x.set("time")
85
+
86
+ # self.selected_y1 = tk.StringVar()
87
+ # self.selected_y1.set("NONE")
88
+
89
+ # self.selected_y2 = tk.StringVar()
90
+ # self.selected_y2.set("NONE")
91
+
92
+ # self.figure_style = tk.StringVar()
93
+ # self.figure_style.set("Scatter")
94
+
95
+ # self.matrix_values = []
96
+ # self.matrix_values.append(tk.StringVar())
97
+ # self.matrix_values[0].set("NONE")
98
+
99
+ self.running_config = None
100
+ self.selected_graph_name = None
101
+
102
+ self.train_process = None
103
+ self.minikube_process = None
104
+ self.data_x = [0]
105
+ self.data_y = [0]
106
+
107
+ self.image_scale = 1
108
+ self.image_width = 1280
109
+ self.image_height = 720
110
+ self.progress_data = None
111
+ self.calibration_data = None
112
+ self.testing = False
113
+
114
+ # configure window
115
+ self.title("COSU Manager")
116
+ self.geometry(f"{1920}x{1080}")
117
+
118
+ # configure grid layout (4x4)
119
+ self.grid_columnconfigure(0, weight=1)
120
+ self.grid_rowconfigure(1, weight=1)
121
+
122
+ header_padding_x = (5, 5)
123
+ header_padding_y = (10, 10)
124
+
125
+ self.sidebar_frame = customtkinter.CTkFrame(self, width=140, corner_radius=0)
126
+ self.sidebar_frame.grid(row=0, column=0, sticky="nsew")
127
+ self.sidebar_frame.grid_columnconfigure(4, weight=1)
128
+ self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="COSU Manager", font=customtkinter.CTkFont(size=20, weight="bold"))
129
+ self.logo_label.grid(row=0, column=0, padx=(20, 10), pady=header_padding_y)
130
+ self.save_button = customtkinter.CTkButton(self.sidebar_frame, text="Save", width=60, command=self.save_project)
131
+ self.save_button.grid(row=0, column=1, padx=header_padding_x, pady=header_padding_y)
132
+ self.load_button = customtkinter.CTkButton(self.sidebar_frame, text="Load", width=60, command=self.load_project)
133
+ self.load_button.grid(row=0, column=2, padx=header_padding_x, pady=header_padding_y)
134
+
135
+ # 4 is service URL
136
+ self.service_label = customtkinter.CTkLabel(self.sidebar_frame, text="Service:", anchor="w")
137
+ self.service_label.grid(row=0, column=3, padx=(80, 5), pady=header_padding_y)
138
+ self.service_url = customtkinter.CTkEntry(self.sidebar_frame, textvariable=self.option_manager.get("url"))
139
+ self.service_url.grid(row=0, column=4, columnspan=1, padx=header_padding_x, pady=header_padding_y, sticky="nsew")
140
+ refresh_image = customtkinter.CTkImage(Image.open(os.path.join("./images", "refresh.png")), size=(20, 20))
141
+ self.refresh_button = customtkinter.CTkButton(self.sidebar_frame, text=None, width=30, image=refresh_image, command=self.load)
142
+ ctt(self.refresh_button, delay=0.1, alpha=0.95, message="Connect to Service")
143
+ self.refresh_button.grid(row=0, column=5, padx=header_padding_x, pady=header_padding_y)
144
+
145
+ self.algorithm_optionmenu = customtkinter.CTkOptionMenu(self.sidebar_frame, variable=self.option_manager.get_mode_sv(), values=self.option_manager.get_service_modes(), width=50, command=self.refresh_step_view)
146
+ self.algorithm_optionmenu.grid(row=0, column=6, padx=(5, 80), pady=header_padding_y)
147
+
148
+ self.scaling_label = customtkinter.CTkLabel(self.sidebar_frame, text="Scale:", anchor="w")
149
+ self.scaling_label.grid(row=0, column=7, padx=header_padding_x, pady=header_padding_y)
150
+ self.scaling_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["50%", "75%", "100%", "125%", "150%", "175%", "200%"], width=60,
151
+ command=self.change_scaling_event)
152
+ self.scaling_optionemenu.grid(row=0, column=8, padx=(5, 20), pady=header_padding_y)
153
+ self.scaling_optionemenu.set("100%")
154
+
155
+ expand_image = customtkinter.CTkImage(Image.open(os.path.join("./images", "expand.png")), size=(20, 20))
156
+ #self.new_window = customtkinter.CTkButton(self.sidebar_frame, text=None, width=30, image=expand_image, command=self.open_new_window)
157
+ #ctt(self.new_window, delay=0.1, alpha=0.95, message="Open New Window")
158
+ #self.new_window.grid(row=0, column=9, padx=(5, 20), pady=header_padding_y)
159
+
160
+ self.tabview = customtkinter.CTkTabview(self, bg_color="transparent", fg_color="transparent")
161
+ self.tabview.grid(row=1, column=0, padx=(0, 0), pady=(10, 10), sticky="nsew")
162
+ tab1 = "Platform"
163
+ tab2 = "Setup"
164
+ tab3 = "Project"
165
+ tab4 = "Results"
166
+
167
+ self.tabview.add(tab1)
168
+ self.tabview.add(tab2)
169
+ self.tabview.add(tab4)
170
+ self.tabview.add(tab3)
171
+
172
+ pt.create_tab(self, self.tabview.tab(tab1))
173
+ st.create_tab(self, self.tabview.tab(tab2))
174
+ rt.create_tab(self, self.tabview.tab(tab3))
175
+ vt.create_tab(self, self.tabview.tab(tab4))
176
+
177
+ self.footer_frame = customtkinter.CTkFrame(self, corner_radius=0)
178
+ self.footer_frame.grid(row=2, column=0, sticky="nsew")
179
+ self.footer_frame.grid_columnconfigure(4, weight=1)
180
+
181
+ self.footer_progress_label = customtkinter.CTkLabel(self.footer_frame, text="Stopped", width=150, font=customtkinter.CTkFont(size=16, weight="bold"), anchor="w")
182
+ self.footer_progress_label.grid(row=0, column=0, padx=(20, 5), pady=header_padding_y)
183
+
184
+ self.footer_progress_bar = customtkinter.CTkProgressBar(self.footer_frame)
185
+ self.footer_progress_bar.grid(row=0, column=4, padx=(50, 100), pady=header_padding_y, sticky="ew")
186
+ self.footer_progress_bar.set(0)
187
+
188
+ play_image = customtkinter.CTkImage(Image.open(os.path.join("./images", "play.png")), size=(20, 20))
189
+ self.run_button = customtkinter.CTkButton(self.footer_frame, text=None, width=30, image=play_image, command=self.run)
190
+ ctt(self.run_button, delay=0.1, alpha=0.95, message="Start Job")
191
+ self.run_button.grid(row=0, column=7, padx=(20, 5), pady=header_padding_y)
192
+
193
+ test_image = customtkinter.CTkImage(Image.open(os.path.join("./images", "test.png")), size=(20, 20))
194
+ self.test_button = customtkinter.CTkButton(self.footer_frame, text=None, width=30, image=test_image, command=self.run_test)
195
+ ctt(self.test_button, delay=0.1, alpha=0.95, message="Start Testing")
196
+ self.test_button.grid(row=0, column=8, padx=(5, 5), pady=header_padding_y)
197
+
198
+ stop_image = customtkinter.CTkImage(Image.open(os.path.join("./images", "stop.png")), size=(20, 20))
199
+ self.stop_button = customtkinter.CTkButton(self.footer_frame, text=None, width=30, image=stop_image, command=self.stop)
200
+ ctt(self.stop_button, delay=0.1, alpha=0.95, message="Stop")
201
+ self.stop_button.grid(row=0, column=9, padx=(5, 20), pady=header_padding_y)
202
+
203
+ download_image = customtkinter.CTkImage(Image.open(os.path.join("./images", "down.png")), size=(20, 20))
204
+ self.download_button = customtkinter.CTkButton(self.footer_frame, text=None, width=30, image=download_image, command=self.stop)
205
+ ctt(self.download_button, delay=0.1, alpha=0.95, message="Download Results")
206
+ self.download_button.grid(row=0, column=10, padx=(5, 20), pady=header_padding_y)
207
+
208
+ self.refresh_step_view(0)
209
+ self.after(1000, self.running_loop)
210
+
211
+ def update_graph(self, value):
212
+ self.vis_sidebar.refresh()
213
+ GraphGenerator.generate_graphs(self)
214
+
215
+ def save_project(self):
216
+ filename = asksaveasfilename(filetypes=[("JSON", "*.json")], initialfile="config", defaultextension="json", title="Save Project")
217
+
218
+ try:
219
+ self.option_manager.set_path(filename)
220
+ self.option_manager.save_project(filename)
221
+
222
+ folder = self.option_manager.get_project_folder()
223
+ if not os.path.exists(folder):
224
+ os.makedirs(folder)
225
+
226
+ if not os.path.exists(os.path.join(folder, "results")):
227
+ os.makedirs(os.path.join(folder, "results"))
228
+
229
+ self.save_button.configure(text="Saved!")
230
+ self.after(3000, lambda: self.save_button.configure(text="Save"))
231
+ except Exception as e:
232
+ self.save_button.configure(text="Error!")
233
+ print(e)
234
+ self.after(3000, lambda: self.save_button.configure(text="Save"))
235
+
236
+ def refresh_step_view(self, value):
237
+ mode = self.option_manager.get_mode()
238
+ self.service_url.configure(textvariable=self.option_manager.get("url"))
239
+ self.graph_theme.configure(variable=self.option_manager.get("graph_theme"))
240
+
241
+ # Limit graph selection based on mode
242
+ self.graph_selector.configure(variable=self.option_manager.get("selected_graph"))
243
+ graph_types = []
244
+ if mode == "Optimization":
245
+ graph_types = ["Best Cost Stacked", "Best Cost by Round", "Custom CSV", "Compare CSV"]
246
+ elif mode == "Sensitivity Analysis":
247
+ graph_types = ["Custom CSV", "Compare CSV"]
248
+ elif mode == "Sampling: Halton" or mode == "Sampling Random":
249
+ graph_types = ["Sampling CSV", "Matrix Editor"]
250
+ self.graph_selector.configure(values=graph_types)
251
+ selected_graph = self.option_manager.get("selected_graph").get()
252
+ if selected_graph not in graph_types:
253
+ self.option_manager.get("selected_graph").set(graph_types[0])
254
+
255
+
256
+ if mode == "Optimization":
257
+ self.test_button.configure(state="normal")
258
+ self.test_button.configure(fg_color=get_color("CTkButton"))
259
+ self.download_button.configure(state="normal")
260
+ self.download_button.configure(fg_color=get_color("CTkButton"))
261
+ else:
262
+ self.test_button.configure(state="disabled")
263
+ self.test_button.configure(fg_color="gray")
264
+ self.download_button.configure(state="disabled")
265
+ self.download_button.configure(fg_color="gray")
266
+
267
+ self.vis_sidebar.clear()
268
+ self.vis_sidebar.render()
269
+
270
+ self.steps_frame.clear()
271
+ self.steps_frame.render()
272
+
273
+ self.static_param_frame.clear()
274
+ self.static_param_frame.render()
275
+
276
+ self.calib_param_frame.clear()
277
+ self.calib_param_frame.render()
278
+
279
+ self.service_param_frame.clear()
280
+ self.service_param_frame.render()
281
+
282
+ self.optimal_param_frame.clear()
283
+ self.optimal_param_frame.render()
284
+
285
+ self.project_name_label.configure(text=self.option_manager.get_project_data()["name"])
286
+ self.project_path_label.configure(text=self.option_manager.get_project_data()["path"])
287
+
288
+ def open_new_window(self):
289
+ # Shell out and run ./main.py
290
+ subprocess.Popen(["python3", "../mgpsogui.py"])
291
+
292
+ def load_project(self):
293
+
294
+ filename = askopenfilename(filetypes=[("JSON", "*.json")], title="Open Project", multiple=False)
295
+ print(filename)
296
+
297
+ try:
298
+
299
+ self.option_manager.load_project(filename)
300
+ self.option_manager.set_path(filename)
301
+
302
+ folder = self.option_manager.get_project_folder()
303
+ if not os.path.exists(folder):
304
+ os.makedirs(folder)
305
+
306
+ if not os.path.exists(os.path.join(folder, "results")):
307
+ os.makedirs(os.path.join(folder, "results"))
308
+
309
+ self.refresh_step_view(0)
310
+
311
+ self.load_button.configure(text="Loaded!")
312
+ self.after(3000, lambda: self.load_button.configure(text="Load"))
313
+
314
+ self.load()
315
+
316
+ except Exception as e:
317
+ print(e)
318
+ # Print stack trace
319
+ traceback.print_exc()
320
+
321
+
322
+ self.load_button.configure(text="Error!")
323
+ self.after(3000, lambda: self.load_button.configure(text="Load"))
324
+
325
+ def change_appearance_mode_event(self, new_appearance_mode: str):
326
+ customtkinter.set_appearance_mode(new_appearance_mode)
327
+
328
+ def change_scaling_event(self, new_scaling: str):
329
+ new_scaling_float = int(new_scaling.replace("%", "")) / 100
330
+ customtkinter.set_widget_scaling(new_scaling_float)
331
+
332
+ def change_scaling_event(self, new_scaling: str):
333
+ new_scaling_float = int(new_scaling.replace("%", "")) / 100
334
+ customtkinter.set_widget_scaling(new_scaling_float)
335
+
336
+ def make_request(self):
337
+ service_url = self.service_url.get()
338
+ try:
339
+ response = requests.get(service_url, timeout=5)
340
+
341
+ response_json = json.loads(response.text)
342
+ status = response.status_code
343
+
344
+ self.option_manager.set_data("service_request_data", response_json)
345
+
346
+ self.service_status.delete('0.0', tk.END)
347
+ self.service_status.insert(text=str(status), index='0.0')
348
+ self.service_name.delete('0.0', tk.END)
349
+ self.service_name.insert(text=str(response_json["metainfo"]["name"]), index='0.0')
350
+ self.service_description.delete('0.0', tk.END)
351
+ self.service_description.insert(text=str(response_json["metainfo"]["description"]), index='0.0')
352
+ self.service_details.delete('0.0', tk.END)
353
+ self.service_details.insert(text=json.dumps(response_json, indent=4), index='0.0')
354
+
355
+ self.refresh_button.configure(fg_color="green")
356
+ except Exception as e:
357
+ self.refresh_button.configure(fg_color="red")
358
+ self.after(1000, lambda: self.refresh_button.configure(fg_color=get_color("CTkButton")))
359
+
360
+ self.refresh_step_view(0)
361
+
362
+
363
+ def load(self):
364
+ # Make HTTP request to service_url and save the result to bounds.json
365
+
366
+ self.refresh_button.configure(fg_color="gray")
367
+
368
+ self.after(10, self.make_request)
369
+ self.after(3000, lambda: self.refresh_button.configure(fg_color=get_color("CTkButton")))
370
+
371
+ def run_test(self):
372
+ self.testing = True
373
+ self.run()
374
+
375
+ def run(self):
376
+
377
+ data = self.option_manager.get_all_data()
378
+ mode = self.option_manager.get_mode()
379
+ data = data[mode]
380
+
381
+ self.running_config = data
382
+
383
+ #if self.testing:
384
+ # steps = metrics['steps']
385
+ # for step in steps:
386
+ # for param in step['param']:
387
+ # param['default_value'] = param['optimal_value']
388
+ self.testing = False
389
+
390
+ self.progress_data = None
391
+ self.calibration_data = None
392
+
393
+ #self.progress_bar.configure(mode="indeterminnate")
394
+ #self.progress_bar.start()
395
+ self.footer_progress_bar.configure(mode="indeterminnate")
396
+ self.footer_progress_bar.start()
397
+
398
+ self.data_x = [0]
399
+ self.data_y = [0]
400
+
401
+ #self.progress_message_middle.configure(text="Job starting...")
402
+ self.footer_progress_label.configure(text="Starting...")
403
+
404
+ self.textbox.insert("0.0", "Starting job...\n\n")
405
+ self.textbox.insert("0.0", "Job Parameters:\n")
406
+ self.textbox.insert("0.0", json.dumps(data, indent=4) + "\n\n")
407
+ try:
408
+ folder = self.option_manager.get_project_folder()
409
+
410
+ self.train_process = Process(target=PSORunner.run_process, args=(stdout_queue, stderr_queue, results_queue, data, folder, mode))
411
+ self.train_process.daemon = True
412
+ self.train_process.start()
413
+ self.after(1000, self.watch_loop)
414
+ self.string_cache = ""
415
+ self.data_cache = ""
416
+
417
+ except Exception as e:
418
+ self.textbox.insert("0.0", "An exception occurred!\n Exception: " + str(e) + "\n\n")
419
+ self.textbox.insert("0.0", "Stack trace:\n")
420
+ self.textbox.insert("0.0", traceback.format_exc())
421
+ self.textbox.insert("0.0", "\n\n")
422
+ self.textbox.insert("0.0", "Job failed!")
423
+ #self.progress_message_left.configure(text="")
424
+ #self.progress_message_middle.configure(text="Job failed! See error log below.")
425
+ #self.progress_message_right.configure(text="")
426
+ self.footer_progress_label.configure(text="Failed")
427
+ #self.progress_bar.stop()
428
+ self.footer_progress_bar.stop()
429
+ #self.progress_bar.configure(mode="determinate")
430
+ self.footer_progress_bar.configure(mode="determinate")
431
+ #self.progress_bar.set(0)
432
+ self.footer_progress_bar.set(0)
433
+
434
+
435
+ def stop(self):
436
+ print("Stopping...")
437
+ self.train_process.terminate()
438
+
439
+ folder = self.option_manager.get_project_folder()
440
+
441
+ if not os.path.exists(folder):
442
+ os.makedirs(folder)
443
+
444
+ # Stop the process
445
+ #if (os.path.exists(os.path.join(folder, 'output.txt'))):
446
+ # os.remove(os.path.join(folder, 'output.txt'))
447
+
448
+ #if (os.path.exists(os.path.join(folder, 'error.txt'))):
449
+ # os.remove(os.path.join(folder, 'error.txt'))
450
+
451
+ self.textbox.insert("0.0", "Job terminated!\n")
452
+ #self.progress_bar.stop()
453
+ self.footer_progress_bar.stop()
454
+ #self.progress_bar.configure(mode="determinate")
455
+ self.footer_progress_bar.configure(mode="determinate")
456
+ #self.progress_bar.set(0)
457
+ self.footer_progress_bar.set(0)
458
+ #self.progress_message_left.configure(text="")
459
+ #self.progress_message_middle.configure(text="Job stopped!")
460
+ self.footer_progress_label.configure(text="Stopped")
461
+ #self.progress_message_right.configure(text="")
462
+
463
+ def running_loop(self):
464
+ try:
465
+ active_tab = self.tabview.get()
466
+ if (active_tab == "Results"):
467
+ GraphGenerator.generate_graphs(self)
468
+ finally:
469
+ self.after(1000, self.running_loop)
470
+
471
+ def watch_loop(self):
472
+ print("Watch loop running...")
473
+
474
+ folder = self.option_manager.get_project_folder()
475
+
476
+ if not os.path.exists(folder):
477
+ os.makedirs(folder)
478
+
479
+ while True:
480
+ try:
481
+ stdout_line = stdout_queue.get_nowait()
482
+
483
+ print("# " + stdout_line, flush=True)
484
+ with open(os.path.join(folder, 'output.txt'), 'a') as f:
485
+ f.write(stdout_line)
486
+ except Empty:
487
+ break
488
+
489
+ while True:
490
+ try:
491
+ stderr_line = stderr_queue.get_nowait()
492
+ print("? " + stderr_line, flush=True)
493
+ with open(os.path.join(folder, 'error.txt'), 'a') as f:
494
+ f.write(stderr_line)
495
+
496
+ except Empty:
497
+ break
498
+
499
+ while True:
500
+ try:
501
+ trace = results_queue.get_nowait()
502
+
503
+ print("TRACE " + str(trace), flush=True)
504
+
505
+ final_results = hp.extract_final_round_values(trace)
506
+ print("Final results: " + str(final_results), flush=True)
507
+
508
+ all_steps = self.option_manager.get_steps()
509
+ data = final_results["data"]
510
+ index = 0
511
+ for step in data:
512
+ for param in step.keys():
513
+ value = step[param]
514
+ target_step = all_steps[index]
515
+ for target_param in target_step['parameter_objects']:
516
+ if target_param['name'].get() == param:
517
+ target_param['optimal_value'].set(value)
518
+ index += 1
519
+ print("Applied optimal values")
520
+ except Empty:
521
+ break
522
+ except Exception as e:
523
+ print("Some error happened when getting the trace!")
524
+ print(e)
525
+
526
+ # Write output to textbox
527
+ if (os.path.exists(os.path.join(folder, 'output.txt'))):
528
+ with open(os.path.join(folder, 'output.txt'), 'r') as f:
529
+ lines = f.readlines()
530
+ lines_string = "".join(lines)
531
+
532
+ new_characters = lines_string.replace(self.string_cache, "")
533
+ # Update the textbox with characters not in self.string_cache
534
+ self.textbox.insert('0.0', new_characters)
535
+ self.string_cache = lines_string
536
+ print(new_characters, end="")
537
+
538
+ try:
539
+ # REPLACE THIS WITH READING THE STEP TRACE JSON for PSO
540
+ with open(os.path.join(folder, "output.txt"), "r") as f:
541
+ text = f.read()
542
+
543
+ calibrated_params_pattern = r"calibrated params: ({.*?})"
544
+ best_particle_values_pattern = r"best particle values: (\[.*?\])"
545
+ progress_pattern = r"Progress - best_round_cost:(.*?), rel_round_tol:(.*?), rtol:(.*?)\n"
546
+
547
+ calibrated_params = re.findall(calibrated_params_pattern, text)
548
+ best_particle_values = re.findall(best_particle_values_pattern, text)
549
+ progress_values = re.findall(progress_pattern, text)
550
+
551
+ for index, pp in enumerate(best_particle_values):
552
+ pp = pp.strip()
553
+ pp = pp.replace('[ ', '[')
554
+ pp = pp.replace(' ', ',')
555
+ pp = pp.replace(' ', ',')
556
+ best_particle_values[index] = pp
557
+
558
+ calibrated_params = [ast.literal_eval(i) for i in calibrated_params]
559
+ best_particle_values = [ast.literal_eval(i) for i in best_particle_values]
560
+ progress_values = [tuple(map(float, i)) for i in progress_values]
561
+ self.calibration_data = calibrated_params
562
+
563
+ except Exception as e:
564
+ traceback.print_exc()
565
+ print(e)
566
+
567
+ # Parse data into interface
568
+ mode = self.option_manager.get_mode()
569
+ if mode == "Optimization":
570
+ if (os.path.exists(os.path.join(folder, 'error.txt'))):
571
+ data = hp.parse_pso_error(os.path.join(folder, 'error.txt'), len(self.option_manager.get_steps()))
572
+ print(data)
573
+ self.progress_data = data["data"]
574
+ self.footer_progress_bar.stop()
575
+ self.footer_progress_bar.configure(mode="determinate")
576
+ self.footer_progress_bar.set(data["percent"]/100)
577
+ self.footer_progress_label.configure(text="Round: " + str(data["round"]) + " - Step: " + str(data["step"]))
578
+ else:
579
+ if (os.path.exists(os.path.join(folder, 'output.txt'))):
580
+ data = hp.parse_sampling_output(os.path.join(folder, 'output.txt'))
581
+ print(data)
582
+ self.footer_progress_bar.stop()
583
+ self.footer_progress_bar.configure(mode="determinate")
584
+ self.footer_progress_bar.set(data["percent"]/100)
585
+ self.footer_progress_label.configure(text=str(round(data["percent"])) + "%")
586
+
587
+
588
+
589
+ if self.train_process.is_alive():
590
+ self.after(1000, self.watch_loop)
591
+ else:
592
+ #self.progress_bar.stop()
593
+ self.footer_progress_bar.stop()
594
+ #self.progress_bar.configure(mode="indeterminate")
595
+ self.footer_progress_bar.configure(mode="indeterminate")
596
+ #self.progress_bar.start()
597
+ self.footer_progress_bar.start()
598
+ #self.progress_message_left.configure(text="")
599
+ #self.progress_message_middle.configure(text="Job finished!")
600
+ #self.progress_message_right.configure(text="")
601
+ self.textbox.insert("0.0", "\nJob finished!\n")
602
+
603
+ # IF "./crash.txt" exists write it to the textbox
604
+ if (os.path.exists(os.path.join(folder, 'crash.txt'))):
605
+ with open(os.path.join(folder, 'crash.txt'), 'r') as f:
606
+ lines = f.readlines()
607
+ lines_string = "".join(lines)
608
+ print("CRASH OCCURRED!")
609
+ print(lines_string)
610
+ self.textbox.insert('0.0', lines_string)
611
+ self.textbox.insert('0.0', "CRASH OCCURRED!\n")
612
+ # Delete the file
613
+ os.remove(os.path.join(folder, 'crash.txt'))
614
+
615
+ def get_color(class_name, property = "fg_color"):
616
+ return ThemeManager.theme[class_name][property]
565
617
 
566
618
  def start():
567
- app = App()
568
- app.mainloop()
619
+ app = App()
620
+ app.mainloop()
569
621
 
570
622
  if __name__ == "__main__":
571
- app = App()
572
- app.mainloop()
623
+ app = App()
624
+ app.mainloop()