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/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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.41.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ mg-pso-gui