mg-pso-gui 0.1.12__py3-none-any.whl → 0.1.40__py3-none-any.whl

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