mg-pso-gui 0.0.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- mg-pso-gui/BoundsEditorWindow.py +74 -0
- mg-pso-gui/BoundsList.py +263 -0
- mg-pso-gui/CTkToolTip/__init__.py +11 -0
- mg-pso-gui/CTkToolTip/ctk_tooltip.py +187 -0
- mg-pso-gui/CalibrationParametersView.py +61 -0
- mg-pso-gui/FunctionsList.py +83 -0
- mg-pso-gui/GraphGenerator.py +215 -0
- mg-pso-gui/ListParametersView.py +173 -0
- mg-pso-gui/OptionManager.py +259 -0
- mg-pso-gui/PSORunner.py +68 -0
- mg-pso-gui/StaticParameterView.py +61 -0
- mg-pso-gui/StepView.py +118 -0
- mg-pso-gui/__init__.py +1 -0
- mg-pso-gui/main.py +485 -0
- mg_pso_gui-0.0.1.dist-info/LICENSE +21 -0
- mg_pso_gui-0.0.1.dist-info/METADATA +23 -0
- mg_pso_gui-0.0.1.dist-info/RECORD +19 -0
- mg_pso_gui-0.0.1.dist-info/WHEEL +5 -0
- mg_pso_gui-0.0.1.dist-info/top_level.txt +1 -0
mg-pso-gui/main.py
ADDED
@@ -0,0 +1,485 @@
|
|
1
|
+
#!/usr/local/bin/python3.9
|
2
|
+
|
3
|
+
import tkinter as tk
|
4
|
+
import tkinter.messagebox
|
5
|
+
import customtkinter
|
6
|
+
import StepView as sv
|
7
|
+
import StaticParameterView as spv
|
8
|
+
import CalibrationParametersView as cpv
|
9
|
+
import OptionManager as om
|
10
|
+
import json
|
11
|
+
import os
|
12
|
+
import PSORunner
|
13
|
+
from PIL import Image
|
14
|
+
import traceback
|
15
|
+
from multiprocessing import Process
|
16
|
+
from multiprocessing import Queue
|
17
|
+
import re
|
18
|
+
from CTkToolTip import *
|
19
|
+
import requests
|
20
|
+
import pandas as pd
|
21
|
+
import numpy as np
|
22
|
+
import ast
|
23
|
+
|
24
|
+
import GraphGenerator
|
25
|
+
|
26
|
+
import subprocess
|
27
|
+
import plotly.express as px
|
28
|
+
import plotly.graph_objs as go
|
29
|
+
|
30
|
+
from tkinter.filedialog import askopenfilename
|
31
|
+
from tkinter.filedialog import asksaveasfilename
|
32
|
+
|
33
|
+
customtkinter.set_appearance_mode("System") # Modes: "System" (standard), "Dark", "Light"
|
34
|
+
customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
|
35
|
+
|
36
|
+
class App(customtkinter.CTk):
|
37
|
+
def __init__(self):
|
38
|
+
super().__init__()
|
39
|
+
|
40
|
+
self.option_manager = om.OptionManager()
|
41
|
+
#self.option_manager.add_arguments(args)
|
42
|
+
#self.option_manager.add_steps(steps)
|
43
|
+
|
44
|
+
self.running_config = None
|
45
|
+
self.selected_graph_name = None
|
46
|
+
|
47
|
+
self.process = None
|
48
|
+
self.process_queue = None
|
49
|
+
self.data_x = [0]
|
50
|
+
self.data_y = [0]
|
51
|
+
|
52
|
+
# configure window
|
53
|
+
self.title("CSIP PSO")
|
54
|
+
self.geometry(f"{1920}x{1080}")
|
55
|
+
|
56
|
+
# configure grid layout (4x4)
|
57
|
+
self.grid_columnconfigure(1, weight=8)
|
58
|
+
self.grid_columnconfigure(2, weight=1)
|
59
|
+
self.grid_rowconfigure((1), weight=1)
|
60
|
+
self.grid_rowconfigure((0), weight=4)
|
61
|
+
|
62
|
+
# create sidebar frame with widgets
|
63
|
+
self.sidebar_frame = customtkinter.CTkFrame(self, width=140, corner_radius=0)
|
64
|
+
self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew")
|
65
|
+
self.sidebar_frame.grid_rowconfigure(4, weight=1)
|
66
|
+
self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="CSIP PSO", font=customtkinter.CTkFont(size=20, weight="bold"))
|
67
|
+
self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 20))
|
68
|
+
self.save_button = customtkinter.CTkButton(self.sidebar_frame, text="Save", command=self.save_project)
|
69
|
+
self.save_button.grid(row=1, column=0, padx=20, pady=(10, 10))
|
70
|
+
self.load_button = customtkinter.CTkButton(self.sidebar_frame, text="Load", command=self.load_project)
|
71
|
+
self.load_button.grid(row=2, column=0, padx=20, pady=(10, 10))
|
72
|
+
|
73
|
+
self.new_window = customtkinter.CTkButton(self.sidebar_frame, text="New Window", command=self.new_window)
|
74
|
+
self.new_window.grid(row=6, column=0, padx=20, pady=(10, 10))
|
75
|
+
|
76
|
+
self.scaling_label = customtkinter.CTkLabel(self.sidebar_frame, text="Scale:", anchor="w")
|
77
|
+
self.scaling_label.grid(row=7, column=0, padx=20, pady=(10, 0))
|
78
|
+
self.scaling_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["50%", "75%", "100%", "150%", "200%"],
|
79
|
+
command=self.change_scaling_event)
|
80
|
+
self.scaling_optionemenu.grid(row=8, column=0, padx=20, pady=(10, 20))
|
81
|
+
self.scaling_optionemenu.set("100%")
|
82
|
+
|
83
|
+
self.tabview = customtkinter.CTkTabview(self)
|
84
|
+
self.tabview.grid(row=0, column=1, columnspan=2, rowspan=2, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
85
|
+
tab1 = "Platform"
|
86
|
+
tab2 = "Setup"
|
87
|
+
tab3 = "Run"
|
88
|
+
tab4 = "Visualize"
|
89
|
+
|
90
|
+
self.tabview.add(tab1)
|
91
|
+
self.tabview.add(tab2)
|
92
|
+
self.tabview.add(tab3)
|
93
|
+
self.tabview.add(tab4)
|
94
|
+
|
95
|
+
self.tabview.tab(tab1).grid_columnconfigure(0, weight=1)
|
96
|
+
self.tabview.tab(tab1).grid_rowconfigure(0, weight=1)
|
97
|
+
self.tabview.tab(tab1).grid_rowconfigure(1, weight=1)
|
98
|
+
self.tabview.tab(tab1).grid_rowconfigure(2, weight=200)
|
99
|
+
|
100
|
+
self.service_url = customtkinter.CTkEntry(self.tabview.tab(tab1), textvariable=self.option_manager.get_arguments()['url'])
|
101
|
+
self.service_url.grid(row=0, column=0, columnspan=1, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
102
|
+
|
103
|
+
self.load_parameters = customtkinter.CTkButton(self.tabview.tab(tab1), text="Connect", command=self.load)
|
104
|
+
self.load_parameters.grid(row=0, column=1, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
105
|
+
|
106
|
+
self.service_status = customtkinter.CTkLabel(self.tabview.tab(tab1), text="Service Status: Unknown")
|
107
|
+
self.service_status.grid(row=1, column=0, columnspan=2, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
108
|
+
|
109
|
+
self.service_name = customtkinter.CTkLabel(self.tabview.tab(tab1), text="")
|
110
|
+
self.service_name.grid(row=2, column=0, columnspan=2, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
111
|
+
|
112
|
+
self.service_description = customtkinter.CTkLabel(self.tabview.tab(tab1), text="")
|
113
|
+
self.service_description.grid(row=3, column=0, columnspan=2, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
114
|
+
|
115
|
+
self.tabview.tab(tab2).grid_columnconfigure(0, weight=8)
|
116
|
+
self.tabview.tab(tab2).grid_columnconfigure(1, weight=1)
|
117
|
+
self.tabview.tab(tab2).grid_rowconfigure(0, weight=1)
|
118
|
+
self.tabview.tab(tab2).grid_rowconfigure(1, weight=1)
|
119
|
+
|
120
|
+
self.steps_frame = sv.StepView(self.tabview.tab(tab2), label_text="Steps Editor", option_manager=self.option_manager)
|
121
|
+
self.steps_frame.grid(row=0, rowspan=2, column=0, padx=(10, 10), pady=(10, 10), sticky="nsew")
|
122
|
+
self.steps_frame.grid_columnconfigure(0, weight=1)
|
123
|
+
self.steps_frame.grid_rowconfigure(0, weight=1)
|
124
|
+
|
125
|
+
self.static_param_frame = spv.StaticParameterView(self.tabview.tab(tab2), label_text="Static Parameters", option_manager=self.option_manager)
|
126
|
+
self.static_param_frame.grid(row=0, column=1, padx=(10, 10), pady=(10, 10), sticky="nsew")
|
127
|
+
self.static_param_frame.grid_columnconfigure(0, weight=1)
|
128
|
+
self.static_param_frame.grid_rowconfigure(0, weight=1)
|
129
|
+
|
130
|
+
self.calib_param_frame = cpv.CalibrationParametersView(self.tabview.tab(tab2), label_text="Calibration Parameters", option_manager=self.option_manager)
|
131
|
+
self.calib_param_frame.grid(row=1, column=1, padx=(10, 10), pady=(10, 10), sticky="nsew")
|
132
|
+
self.calib_param_frame.grid_columnconfigure(0, weight=1)
|
133
|
+
self.calib_param_frame.grid_rowconfigure(0, weight=1)
|
134
|
+
|
135
|
+
# URL
|
136
|
+
|
137
|
+
self.tabview.tab(tab3).grid_columnconfigure(0, weight=1)
|
138
|
+
self.tabview.tab(tab3).grid_rowconfigure(0, weight=1)
|
139
|
+
self.tabview.tab(tab3).grid_rowconfigure(1, weight=1)
|
140
|
+
self.tabview.tab(tab3).grid_rowconfigure(2, weight=200)
|
141
|
+
self.url = customtkinter.CTkEntry(self.tabview.tab(tab3), textvariable=self.option_manager.get_arguments()['url'])
|
142
|
+
self.url.grid(row=0, column=0, columnspan=1, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
143
|
+
|
144
|
+
self.run_button = customtkinter.CTkButton(self.tabview.tab(tab3), text="Run", command=self.run)
|
145
|
+
self.run_button.grid(row=0, column=1, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
146
|
+
CTkToolTip(self.run_button, delay=0.5, message="Start calibration...")
|
147
|
+
|
148
|
+
|
149
|
+
self.stop_button = customtkinter.CTkButton(self.tabview.tab(tab3), text="Stop", command=self.stop)
|
150
|
+
self.stop_button.grid(row=0, column=2, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
151
|
+
CTkToolTip(self.stop_button, delay=0.5, message="Stop calibration...")
|
152
|
+
|
153
|
+
self.progress_container = customtkinter.CTkFrame(self.tabview.tab(tab3))
|
154
|
+
self.progress_container.grid_columnconfigure(0, weight=1)
|
155
|
+
self.progress_container.grid_columnconfigure(1, weight=1)
|
156
|
+
self.progress_container.grid_columnconfigure(2, weight=1)
|
157
|
+
self.progress_container.grid(row=1, column=0, columnspan=3, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
158
|
+
|
159
|
+
fig = px.scatter(x=self.data_x, y=self.data_y)
|
160
|
+
fig.write_image("./best_cost_stacked.png")
|
161
|
+
fig.write_image("./best_cost_by_round.png")
|
162
|
+
fig.write_image("./table.png")
|
163
|
+
fig.write_image("./calibrated_params_by_round.png")
|
164
|
+
|
165
|
+
# Add progress bar to progress container
|
166
|
+
self.progress_message_left = customtkinter.CTkLabel(self.progress_container, text="")
|
167
|
+
self.progress_message_left.grid(row=0, column=0, padx=(10, 10), pady=(10, 10), sticky="w")
|
168
|
+
|
169
|
+
self.progress_message_middle = customtkinter.CTkLabel(self.progress_container, text="Calibration not running...")
|
170
|
+
self.progress_message_middle.grid(row=0, column=1, padx=(10, 10), pady=(10, 10), sticky="ew")
|
171
|
+
|
172
|
+
self.progress_message_right = customtkinter.CTkLabel(self.progress_container, text="")
|
173
|
+
self.progress_message_right.grid(row=0, column=2, padx=(10, 10), pady=(10, 10), sticky="e")
|
174
|
+
|
175
|
+
self.progress_bar = customtkinter.CTkProgressBar(self.progress_container)
|
176
|
+
self.progress_bar.grid(row=1, column=0, columnspan=3, padx=(10, 10), pady=(10, 10), sticky="ew")
|
177
|
+
self.progress_bar.set(0)
|
178
|
+
CTkToolTip(self.progress_bar, delay=0.5, message="Current calibration progress")
|
179
|
+
|
180
|
+
self.textbox = customtkinter.CTkTextbox(self.tabview.tab(tab3))
|
181
|
+
self.textbox.grid(row=2, column=0, columnspan=3, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
182
|
+
self.textbox.insert("0.0", "Welcome to the CSIP PSO Calibration Tool!\n\nUse the Calibration tab to define steps and calibration parameters. Use this tab to run and observe calibration progress. Once finished, use the Visualization tab to generate figures and graphs.")
|
183
|
+
|
184
|
+
self.tabview.tab(tab4).grid_columnconfigure(1, weight=10)
|
185
|
+
self.tabview.tab(tab4).grid_columnconfigure(0, weight=1)
|
186
|
+
self.tabview.tab(tab4).grid_columnconfigure(2, weight=1)
|
187
|
+
self.tabview.tab(tab4).grid_rowconfigure(1, weight=1)
|
188
|
+
|
189
|
+
self.graph_selector_value = tk.StringVar()
|
190
|
+
self.graph_selector_value.set("Best Cost Stacked")
|
191
|
+
self.graph_selector = customtkinter.CTkOptionMenu(self.tabview.tab(tab4), values=["Best Cost Stacked", "Best Cost by Round", "Calibrated Parameters", "Table"], variable=self.graph_selector_value, command=self.update_graph)
|
192
|
+
self.graph_selector.grid(row=0, column=0, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
193
|
+
|
194
|
+
# Add a button to call open_graph_in_browser
|
195
|
+
self.graph_button = customtkinter.CTkButton(self.tabview.tab(tab4), text="Open Graph in Browser", command=self.open_graph_in_browser)
|
196
|
+
self.graph_button.grid(row=0, column=2, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
197
|
+
#CTkToolTip(self.graph_button, delay=0.5, message="Open graph in browser...")
|
198
|
+
|
199
|
+
|
200
|
+
self.graph_image = customtkinter.CTkImage(Image.open(os.path.join(".", "best_cost_stacked.png")), size=(700, 500))
|
201
|
+
self.graph_label = customtkinter.CTkLabel(self.tabview.tab(tab4), text=None, image=self.graph_image)
|
202
|
+
self.graph_label.grid(row=1, column=0, columnspan=3, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
203
|
+
|
204
|
+
def callback_test(self, *args):
|
205
|
+
print("callback_test called")
|
206
|
+
|
207
|
+
def run(self):
|
208
|
+
metrics = self.option_manager.get_metrics()
|
209
|
+
self.running_config = metrics
|
210
|
+
|
211
|
+
self.progress_bar.configure(mode="indeterminnate")
|
212
|
+
self.progress_bar.start()
|
213
|
+
|
214
|
+
self.data_x = [0]
|
215
|
+
self.data_y = [0]
|
216
|
+
|
217
|
+
self.progress_message_middle.configure(text="Calibration starting...")
|
218
|
+
|
219
|
+
self.textbox.insert("0.0", "Starting calibration...\n\n")
|
220
|
+
self.textbox.insert("0.0", "Calibration Parameters:\n")
|
221
|
+
self.textbox.insert("0.0", json.dumps(metrics, indent=4) + "\n\n")
|
222
|
+
try:
|
223
|
+
self.process_queue = Queue()
|
224
|
+
self.process = Process(target=PSORunner.run_process, args=(metrics, self.process_queue))
|
225
|
+
self.process.daemon = True
|
226
|
+
self.process.start()
|
227
|
+
self.after(1000, self.watch_loop)
|
228
|
+
self.string_cache = ""
|
229
|
+
self.data_cache = ""
|
230
|
+
|
231
|
+
except Exception as e:
|
232
|
+
self.textbox.insert("0.0", "An exception occurred!\n Exception: " + str(e) + "\n\n")
|
233
|
+
self.textbox.insert("0.0", "Stack trace:\n")
|
234
|
+
self.textbox.insert("0.0", traceback.format_exc())
|
235
|
+
self.textbox.insert("0.0", "\n\n")
|
236
|
+
self.textbox.insert("0.0", "Calibration failed!")
|
237
|
+
self.progress_message_left.configure(text="")
|
238
|
+
self.progress_message_middle.configure(text="Calibration failed! See error log below.")
|
239
|
+
self.progress_message_right.configure(text="")
|
240
|
+
self.progress_bar.stop()
|
241
|
+
self.progress_bar.configure(mode="determinate")
|
242
|
+
self.progress_bar.set(0)
|
243
|
+
|
244
|
+
def update_graph(self, value):
|
245
|
+
selected_graph = self.graph_selector_value.get()
|
246
|
+
if (selected_graph == "Best Cost Stacked"):
|
247
|
+
self.selected_graph_name = "best_cost_stacked"
|
248
|
+
self.graph_image = customtkinter.CTkImage(Image.open(os.path.join(".", self.selected_graph_name + ".png")), size=(1280, 720))
|
249
|
+
self.graph_label.configure(image=self.graph_image)
|
250
|
+
elif (selected_graph == "Best Cost by Round"):
|
251
|
+
self.selected_graph_name = "best_cost_by_round"
|
252
|
+
self.graph_image = customtkinter.CTkImage(Image.open(os.path.join(".", self.selected_graph_name + ".png")), size=(1280, 720))
|
253
|
+
self.graph_label.configure(image=self.graph_image)
|
254
|
+
elif (selected_graph == "Table"):
|
255
|
+
self.selected_graph_name = "table"
|
256
|
+
self.graph_image = customtkinter.CTkImage(Image.open(os.path.join(".", self.selected_graph_name + ".png")), size=(1280, 720))
|
257
|
+
self.graph_label.configure(image=self.graph_image)
|
258
|
+
elif (selected_graph == "Calibrated Parameters"):
|
259
|
+
self.selected_graph_name = "calibrated_params_by_round"
|
260
|
+
self.graph_image = customtkinter.CTkImage(Image.open(os.path.join(".", self.selected_graph_name + ".png")), size=(1280, 720))
|
261
|
+
self.graph_label.configure(image=self.graph_image)
|
262
|
+
|
263
|
+
def save_project(self):
|
264
|
+
metrics = self.option_manager.get_metrics()
|
265
|
+
filename = asksaveasfilename(filetypes=[("JSON", "*.json")], initialfile="config", defaultextension="json", title="Save Project")
|
266
|
+
|
267
|
+
try:
|
268
|
+
|
269
|
+
# Convert metrics to json and save to file with proper spacing
|
270
|
+
with open(filename, "w") as f:
|
271
|
+
f.write(json.dumps(metrics, indent=4))
|
272
|
+
|
273
|
+
self.save_button.configure(text="Saved!")
|
274
|
+
self.after(3000, lambda: self.save_button.configure(text="Save"))
|
275
|
+
except Exception as e:
|
276
|
+
self.save_button.configure(text="Error!")
|
277
|
+
print(e)
|
278
|
+
self.after(3000, lambda: self.save_button.configure(text="Save"))
|
279
|
+
|
280
|
+
def new_window(self):
|
281
|
+
# Shell out and run ./main.py
|
282
|
+
subprocess.Popen(["python3", "main.py"])
|
283
|
+
|
284
|
+
def load_project(self):
|
285
|
+
|
286
|
+
filename = askopenfilename(filetypes=[("JSON", "*.json")], title="Open Project", multiple=False)
|
287
|
+
print(filename)
|
288
|
+
|
289
|
+
try:
|
290
|
+
|
291
|
+
# Load config.json and convert to metrics
|
292
|
+
with open(filename, "r") as f:
|
293
|
+
metrics = json.loads(f.read())
|
294
|
+
|
295
|
+
metrics["arguments"]["calibration_parameters"] = metrics["calibration_parameters"]
|
296
|
+
|
297
|
+
print(metrics)
|
298
|
+
|
299
|
+
self.option_manager.clear()
|
300
|
+
self.option_manager.add_arguments(metrics["arguments"])
|
301
|
+
self.option_manager.add_steps(metrics["steps"])
|
302
|
+
|
303
|
+
self.steps_frame.clear()
|
304
|
+
self.steps_frame.render()
|
305
|
+
|
306
|
+
self.static_param_frame.clear()
|
307
|
+
self.static_param_frame.render()
|
308
|
+
|
309
|
+
self.calib_param_frame.clear()
|
310
|
+
self.calib_param_frame.render()
|
311
|
+
|
312
|
+
self.load_button.configure(text="Loaded!")
|
313
|
+
self.after(3000, lambda: self.load_button.configure(text="Load"))
|
314
|
+
|
315
|
+
except Exception as e:
|
316
|
+
print(e)
|
317
|
+
self.load_button.configure(text="Error!")
|
318
|
+
self.after(3000, lambda: self.load_button.configure(text="Load"))
|
319
|
+
|
320
|
+
|
321
|
+
def load(self):
|
322
|
+
# Make HTTP request to service_url and save the result to bounds.json
|
323
|
+
self.load_parameters.configure(text="Loading...")
|
324
|
+
self.after(10, self.make_request)
|
325
|
+
self.after(3000, lambda: self.load_parameters.configure(text="Connect"))
|
326
|
+
|
327
|
+
def make_request(self):
|
328
|
+
service_url = self.service_url.get()
|
329
|
+
response = requests.get(service_url)
|
330
|
+
with open("bounds.json", "w") as f:
|
331
|
+
f.write(response.text)
|
332
|
+
|
333
|
+
response_json = json.loads(response.text)
|
334
|
+
status = response.status_code
|
335
|
+
|
336
|
+
self.service_status.configure(text="Service Status: " + str(status))
|
337
|
+
self.service_name.configure(text=response_json["metainfo"]["name"])
|
338
|
+
self.service_description.configure(text=response_json["metainfo"]["description"])
|
339
|
+
|
340
|
+
|
341
|
+
self.load_parameters.configure(text="Loaded!")
|
342
|
+
|
343
|
+
def watch_loop(self):
|
344
|
+
# Check if file exists:
|
345
|
+
if (os.path.exists('./output.txt')):
|
346
|
+
with open('./output.txt', 'r') as f:
|
347
|
+
lines = f.readlines()
|
348
|
+
lines_string = "".join(lines)
|
349
|
+
|
350
|
+
new_characters = lines_string.replace(self.string_cache, "")
|
351
|
+
# Update the textbox with characters not in self.string_cache
|
352
|
+
self.textbox.insert('0.0', new_characters)
|
353
|
+
self.string_cache = lines_string
|
354
|
+
print(new_characters, end="")
|
355
|
+
|
356
|
+
try:
|
357
|
+
with open("output.txt", "r") as f:
|
358
|
+
text = f.read()
|
359
|
+
|
360
|
+
calibrated_params_pattern = r"calibrated params: ({.*?})"
|
361
|
+
best_particle_values_pattern = r"best particle values: (\[.*?\])"
|
362
|
+
progress_pattern = r"Progress - best_round_cost:(.*?), rel_round_tol:(.*?), rtol:(.*?)\n"
|
363
|
+
|
364
|
+
calibrated_params = re.findall(calibrated_params_pattern, text)
|
365
|
+
best_particle_values = re.findall(best_particle_values_pattern, text)
|
366
|
+
progress_values = re.findall(progress_pattern, text)
|
367
|
+
|
368
|
+
for index, pp in enumerate(best_particle_values):
|
369
|
+
pp = pp.strip()
|
370
|
+
pp = pp.replace('[ ', '[')
|
371
|
+
pp = pp.replace(' ', ',')
|
372
|
+
pp = pp.replace(' ', ',')
|
373
|
+
best_particle_values[index] = pp
|
374
|
+
|
375
|
+
calibrated_params = [ast.literal_eval(i) for i in calibrated_params]
|
376
|
+
best_particle_values = [ast.literal_eval(i) for i in best_particle_values]
|
377
|
+
progress_values = [tuple(map(float, i)) for i in progress_values]
|
378
|
+
|
379
|
+
print(calibrated_params)
|
380
|
+
|
381
|
+
GraphGenerator.calibrated_params_by_round(self.running_config['steps'], calibrated_params)
|
382
|
+
self.update_graph("")
|
383
|
+
except Exception as e:
|
384
|
+
# Print stack trace
|
385
|
+
traceback.print_exc()
|
386
|
+
|
387
|
+
print(e)
|
388
|
+
|
389
|
+
if (os.path.exists('./error.txt')):
|
390
|
+
with open('./error.txt', 'r') as f:
|
391
|
+
lines = f.readlines()
|
392
|
+
lines_string = "".join(lines)
|
393
|
+
self.data_cache = lines_string
|
394
|
+
|
395
|
+
pattern = r'(\d+)%\|.*\|(\d+)/(\d+)(?:,\sbest_cost=(\d+\.\d+))?' # The magic of AI
|
396
|
+
matches = re.findall(pattern, self.data_cache)
|
397
|
+
filtered_matches = [match for match in matches if match[3] != '']
|
398
|
+
matches = filtered_matches
|
399
|
+
|
400
|
+
if len(matches) > 0:
|
401
|
+
df = pd.DataFrame(matches, columns=['percent', 'completed_rounds', 'total_rounds', 'best_cost'], dtype=float)
|
402
|
+
df = df[df['best_cost'] != '']
|
403
|
+
df = df.dropna()
|
404
|
+
df = df.drop_duplicates()
|
405
|
+
df['round_step'] = (df['completed_rounds'].diff() < 0).cumsum()
|
406
|
+
df = df.drop_duplicates(subset=['completed_rounds', 'round_step'])
|
407
|
+
|
408
|
+
GraphGenerator.best_cost_stacked(self.running_config['steps'], df)
|
409
|
+
GraphGenerator.best_cost_by_round(self.running_config['steps'], df)
|
410
|
+
GraphGenerator.table(self.running_config['steps'], df)
|
411
|
+
self.update_graph("")
|
412
|
+
|
413
|
+
match = matches[-1]
|
414
|
+
percent = int(match[0])
|
415
|
+
completed_rounds = int(match[1])
|
416
|
+
total_rounds = int(match[2])
|
417
|
+
best_cost = float(match[3]) if match[3] else None
|
418
|
+
|
419
|
+
if (percent > 0):
|
420
|
+
self.progress_bar.stop()
|
421
|
+
self.progress_bar.configure(mode="determinate")
|
422
|
+
self.progress_bar.set(percent/100)
|
423
|
+
self.progress_message_left.configure(text="Percent Complete: " + str(percent) + "%")
|
424
|
+
self.progress_message_middle.configure(text=str(completed_rounds) + "/" + str(total_rounds))
|
425
|
+
self.progress_message_right.configure(text="Best Cost: " + str(best_cost))
|
426
|
+
else:
|
427
|
+
self.progress_bar.configure(mode="indeterminate")
|
428
|
+
self.progress_bar.start()
|
429
|
+
self.progress_message_left.configure(text="")
|
430
|
+
self.progress_message_middle.configure(text="Starting new round...")
|
431
|
+
self.progress_message_right.configure(text="")
|
432
|
+
|
433
|
+
|
434
|
+
|
435
|
+
if self.process.is_alive():
|
436
|
+
self.after(1000, self.watch_loop)
|
437
|
+
else:
|
438
|
+
self.textbox.insert("0.0", "\nCalibration finished!\n")
|
439
|
+
|
440
|
+
def open_graph_in_browser(self):
|
441
|
+
# Shell out to the terminal and run "open ./example.html"
|
442
|
+
subprocess.run(["open", "./" + self.selected_graph_name + ".html"])
|
443
|
+
|
444
|
+
def stop(self):
|
445
|
+
# Stop the process
|
446
|
+
if (os.path.exists('output.txt')):
|
447
|
+
os.remove('output.txt')
|
448
|
+
|
449
|
+
if (os.path.exists('error.txt')):
|
450
|
+
os.remove('error.txt')
|
451
|
+
|
452
|
+
self.textbox.insert("0.0", "\nCalibration terminated!\n")
|
453
|
+
self.process.terminate()
|
454
|
+
self.progress_bar.stop()
|
455
|
+
self.progress_bar.configure(mode="determinate")
|
456
|
+
self.progress_bar.set(0)
|
457
|
+
self.progress_message_left.configure(text="")
|
458
|
+
self.progress_message_middle.configure(text="Calibration stopped!")
|
459
|
+
self.progress_message_right.configure(text="")
|
460
|
+
|
461
|
+
def open_input_dialog_event(self):
|
462
|
+
dialog = customtkinter.CTkInputDialog(text="Type in a number:", title="CTkInputDialog")
|
463
|
+
print("CTkInputDialog:", dialog.get_input())
|
464
|
+
|
465
|
+
def change_appearance_mode_event(self, new_appearance_mode: str):
|
466
|
+
customtkinter.set_appearance_mode(new_appearance_mode)
|
467
|
+
|
468
|
+
def change_scaling_event(self, new_scaling: str):
|
469
|
+
new_scaling_float = int(new_scaling.replace("%", "")) / 100
|
470
|
+
customtkinter.set_widget_scaling(new_scaling_float)
|
471
|
+
|
472
|
+
def sidebar_button_event(self):
|
473
|
+
print("sidebar_button click")
|
474
|
+
|
475
|
+
def change_scaling_event(self, new_scaling: str):
|
476
|
+
new_scaling_float = int(new_scaling.replace("%", "")) / 100
|
477
|
+
customtkinter.set_widget_scaling(new_scaling_float)
|
478
|
+
|
479
|
+
def start():
|
480
|
+
app = App()
|
481
|
+
app.mainloop()
|
482
|
+
|
483
|
+
if __name__ == "__main__":
|
484
|
+
app = App()
|
485
|
+
app.mainloop()
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 Robert Cordingly
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: mg-pso-gui
|
3
|
+
Version: 0.0.1
|
4
|
+
Summary: GUI for MG-PSO
|
5
|
+
Author: Robert Cordingly
|
6
|
+
Author-email: <rcording@uw.ed>
|
7
|
+
Keywords: python,muti-group,pso,particle,swarm,optimization,gui
|
8
|
+
Classifier: Development Status :: 1 - Planning
|
9
|
+
Classifier: Intended Audience :: Developers
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
11
|
+
Classifier: Operating System :: Unix
|
12
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
14
|
+
Description-Content-Type: text/markdown
|
15
|
+
License-File: LICENSE
|
16
|
+
Requires-Dist: pandas
|
17
|
+
Requires-Dist: numpy
|
18
|
+
Requires-Dist: requests
|
19
|
+
Requires-Dist: tkinter
|
20
|
+
Requires-Dist: customtkinter
|
21
|
+
Requires-Dist: plotly
|
22
|
+
|
23
|
+
GUI for MG-PSO
|
@@ -0,0 +1,19 @@
|
|
1
|
+
mg-pso-gui/BoundsEditorWindow.py,sha256=ftWRn47diOpV7rVrqvDO1Ezv58zqHP-UHxg2ztB3XWY,2843
|
2
|
+
mg-pso-gui/BoundsList.py,sha256=AunP0LRoa1QYg2N_ZVzYKzanxhEdTLprLUCP9pZ80fE,12054
|
3
|
+
mg-pso-gui/CalibrationParametersView.py,sha256=ppVBHG3nphku9-P6Z8az-HTpgk8vHxnj-A5m80BZTgA,2784
|
4
|
+
mg-pso-gui/FunctionsList.py,sha256=bTH_OeWqwXdJLKOLEclqrJ-wAZ4pNGPP-oCf5eOqQjo,3822
|
5
|
+
mg-pso-gui/GraphGenerator.py,sha256=m4BgERnjQ-x3f9odka0tIkeike4PH9K8oHhB_ATIyd4,6792
|
6
|
+
mg-pso-gui/ListParametersView.py,sha256=74-HnSBSdBh8TTLIeuNZxR2_yzP7YsHygbht8PZUrO0,6945
|
7
|
+
mg-pso-gui/OptionManager.py,sha256=lvh-1dwrc0Tu1P0Z3wVJ8ClZUdwCGGBM3B6cDN6YH8w,10518
|
8
|
+
mg-pso-gui/PSORunner.py,sha256=s1mcDE27tTvlxg6fU7yVGVSc_5cTnVT6KOY_Y67RXUI,2681
|
9
|
+
mg-pso-gui/StaticParameterView.py,sha256=iEG-UpBBlAJabZo3MG768oLqOROjUPc23tKOSd47IUc,2739
|
10
|
+
mg-pso-gui/StepView.py,sha256=8okZPvzPuXMs34QmK33CRi-x6BCVaU9T_a2MF9loOvo,5516
|
11
|
+
mg-pso-gui/__init__.py,sha256=Mr6KgaQze4Jm7LA5hlcYKFW4xP7mG7IhWR13iAWWFF8,22
|
12
|
+
mg-pso-gui/main.py,sha256=5XX3E5puPYQbi8vST4Ewr1-tI_ctL52zqwYGchEZAs4,23747
|
13
|
+
mg-pso-gui/CTkToolTip/__init__.py,sha256=G1jxV55hGtGgwyC1sR-uUUdasDdh0XZgcI-aILgGYA0,225
|
14
|
+
mg-pso-gui/CTkToolTip/ctk_tooltip.py,sha256=SZMovpQIGvdpDRbqCKl9SHs92DrFCO2MOYL2ifolvOE,6329
|
15
|
+
mg_pso_gui-0.0.1.dist-info/LICENSE,sha256=4KnEaagdIWvLuRbEpwrDrlvLJsMYum5DUlu_GNoR-S8,1073
|
16
|
+
mg_pso_gui-0.0.1.dist-info/METADATA,sha256=rMau6hGQPH6D7yZgBtOuHjyT4yoVa6deJubOONSpNUU,697
|
17
|
+
mg_pso_gui-0.0.1.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
18
|
+
mg_pso_gui-0.0.1.dist-info/top_level.txt,sha256=WH9ongsyYdvguFzybSgb5607x00ewNbcnNUdoqgjvyc,11
|
19
|
+
mg_pso_gui-0.0.1.dist-info/RECORD,,
|
@@ -0,0 +1 @@
|
|
1
|
+
mg-pso-gui
|