mg-pso-gui 0.1.13__tar.gz → 0.1.14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/PKG-INFO +1 -1
  2. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mg_pso_gui.egg-info/PKG-INFO +1 -1
  3. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mg_pso_gui.egg-info/SOURCES.txt +1 -0
  4. mg-pso-gui-0.1.14/mgpsogui/gui/HomePage.py +611 -0
  5. mg-pso-gui-0.1.14/mgpsogui/trace.json +472 -0
  6. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/recosu/pso/csip_access.py +1 -33
  7. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/recosu/pso/pso.py +0 -48
  8. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/setup.py +1 -1
  9. mg-pso-gui-0.1.13/mgpsogui/gui/HomePage.py +0 -572
  10. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mg_pso_gui.egg-info/dependency_links.txt +0 -0
  11. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mg_pso_gui.egg-info/entry_points.txt +0 -0
  12. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mg_pso_gui.egg-info/requires.txt +0 -0
  13. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mg_pso_gui.egg-info/top_level.txt +0 -0
  14. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/__init__.py +0 -0
  15. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/OptionManager.py +0 -0
  16. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/PlatformTab/PlatformTab.py +0 -0
  17. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/PlatformTab/__init__.py +0 -0
  18. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/RunTab/RunTab.py +0 -0
  19. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/RunTab/__init__.py +0 -0
  20. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/SetupTab/BoundsEditorWindow.py +0 -0
  21. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/SetupTab/BoundsList.py +0 -0
  22. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/SetupTab/CalibrationParametersView.py +0 -0
  23. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/SetupTab/FunctionsList.py +0 -0
  24. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/SetupTab/ListParametersView.py +0 -0
  25. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/SetupTab/SetupTab.py +0 -0
  26. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/SetupTab/StaticParameterView.py +0 -0
  27. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/SetupTab/StepView.py +0 -0
  28. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/SetupTab/__init__.py +0 -0
  29. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/VisualizeTab/VisualizeTab.py +0 -0
  30. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/VisualizeTab/__init__.py +0 -0
  31. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/__init__.py +0 -0
  32. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/images/IGOW 4 Logo.png +0 -0
  33. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/images/collapse.png +0 -0
  34. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/images/down.png +0 -0
  35. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/images/expand.png +0 -0
  36. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/images/play.png +0 -0
  37. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/images/refresh.png +0 -0
  38. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/images/refresh_hd.png +0 -0
  39. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/images/stop.png +0 -0
  40. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/images/trash.png +0 -0
  41. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/gui/images/up.png +0 -0
  42. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/mgpsogui.py +0 -0
  43. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/start.yaml +0 -0
  44. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/CTkToolTip/__init__.py +0 -0
  45. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/CTkToolTip/ctk_tooltip.py +0 -0
  46. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/GraphGenerator.py +0 -0
  47. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/PSORunner.py +0 -0
  48. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/__init__.py +0 -0
  49. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/recosu/__init__.py +0 -0
  50. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/recosu/pso/__init__.py +0 -0
  51. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/recosu/utils/__init__.py +0 -0
  52. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/recosu/utils/plot/__init__.py +0 -0
  53. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/recosu/utils/plot/cost_steps.py +0 -0
  54. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/recosu/utils/trace_writer.py +0 -0
  55. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/mgpsogui/util/recosu/utils/utils.py +0 -0
  56. {mg-pso-gui-0.1.13 → mg-pso-gui-0.1.14}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mg-pso-gui
3
- Version: 0.1.13
3
+ Version: 0.1.14
4
4
  Summary: GUI for MG-PSO
5
5
  Author: Robert Cordingly
6
6
  Author-email: <rcording@uw.ed>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mg-pso-gui
3
- Version: 0.1.13
3
+ Version: 0.1.14
4
4
  Summary: GUI for MG-PSO
5
5
  Author: Robert Cordingly
6
6
  Author-email: <rcording@uw.ed>
@@ -8,6 +8,7 @@ mg_pso_gui.egg-info/top_level.txt
8
8
  mgpsogui/__init__.py
9
9
  mgpsogui/mgpsogui.py
10
10
  mgpsogui/start.yaml
11
+ mgpsogui/trace.json
11
12
  mgpsogui/gui/HomePage.py
12
13
  mgpsogui/gui/OptionManager.py
13
14
  mgpsogui/gui/__init__.py
@@ -0,0 +1,611 @@
1
+ #!/usr/local/bin/python3.9
2
+
3
+ import os
4
+ import time
5
+ dir_path = os.path.dirname(os.path.realpath(__file__))
6
+ os.chdir(dir_path)
7
+ print(dir_path)
8
+
9
+ # minikube kubectl -- create -f ../start.yaml ; sleep 60 ; minikube service pf8087-csu-csip-oms -n csip
10
+
11
+ import requests
12
+
13
+ import tkinter as tk
14
+ import tkinter.messagebox
15
+ import customtkinter
16
+ import json
17
+ import os
18
+ from PIL import Image, ImageTk
19
+ import traceback
20
+ from multiprocessing import Process
21
+ from multiprocessing import Queue
22
+ import re
23
+ import pandas as pd
24
+ import numpy as np
25
+ import ast
26
+ import platform
27
+ import time
28
+
29
+ from queue import Empty
30
+
31
+ from ..util import PSORunner
32
+ from ..util import GraphGenerator
33
+
34
+ import subprocess
35
+ import plotly.express as px
36
+ import plotly.graph_objs as go
37
+
38
+ from tkinter.filedialog import askopenfilename
39
+ from tkinter.filedialog import asksaveasfilename
40
+
41
+ from . import OptionManager as om
42
+
43
+ from .SetupTab import SetupTab as st
44
+ from .PlatformTab import PlatformTab as pt
45
+ from .RunTab import RunTab as rt
46
+ from .VisualizeTab import VisualizeTab as vt
47
+
48
+ from ..util.CTkToolTip import CTkToolTip as ctt
49
+
50
+ customtkinter.set_appearance_mode("Dark") # Modes: "System" (standard), "Dark", "Light"
51
+ customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
52
+
53
+ results_queue = Queue()
54
+ stdout_queue = Queue()
55
+ stderr_queue = Queue()
56
+ cosu_queue = Queue()
57
+
58
+ 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")
565
+
566
+ def get_results(self):
567
+ request: Client = Client()
568
+ for name, value in parameters.items():
569
+ # if parameter name has a / in it assume that is a file based parameter and therefore value needs to be an array
570
+ if "/" in name and type(value) is not list:
571
+ request.add_data(name, [value])
572
+ else:
573
+ request.add_data(name, value)
574
+
575
+ conf = {
576
+ 'service_timeout': 60.0 # (sec)
577
+ }
578
+ files: List[str] = [] #optional list of filenames
579
+
580
+ #Synchronous Call
581
+ result: Client = request.execute(CSIP_ENDPOINT, files=files, sync=True, conf=conf)
582
+
583
+ #Asynchronous Call
584
+ tsamp: float = 0
585
+ def callback(c: Client, progress: str):
586
+ tsamp2: float = time.time()
587
+ print('Halton Update {} - {} - {}'.format(halton_id, c.get_status(), tsamp2 - tsamp))
588
+
589
+
590
+ tsamp = time.time()
591
+ result: Client = request.execute_async(
592
+ CSIP_ENDPOINT,
593
+ files=files,
594
+ callback=callback,
595
+ first_poll=poll_time,
596
+ next_poll=poll_time,
597
+ conf=conf
598
+ )
599
+ # After recieving response
600
+ if result.is_finished():
601
+ print(result)
602
+ else:
603
+ print(result)
604
+
605
+ def start():
606
+ app = App()
607
+ app.mainloop()
608
+
609
+ if __name__ == "__main__":
610
+ app = App()
611
+ app.mainloop()