mg-pso-gui 0.1.40__py3-none-any.whl → 0.2.75__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- {mg_pso_gui-0.1.40.dist-info → mg_pso_gui-0.2.75.dist-info}/METADATA +10 -11
- mg_pso_gui-0.2.75.dist-info/RECORD +76 -0
- {mg_pso_gui-0.1.40.dist-info → mg_pso_gui-0.2.75.dist-info}/WHEEL +1 -1
- mgpsogui/gui/General/ParameterView.py +110 -0
- mgpsogui/gui/General/__init__.py +0 -0
- mgpsogui/gui/HomePage.py +234 -238
- mgpsogui/gui/OptionManager.py +333 -145
- mgpsogui/gui/OptionManager_backup.py +443 -0
- mgpsogui/gui/PlatformTab/PlatformTab.py +15 -6
- mgpsogui/gui/RunTab/OptimalParameterView.py +47 -0
- mgpsogui/gui/RunTab/RunTab.py +90 -17
- mgpsogui/gui/SetupTab/BoundsEditorWindow.py +1 -1
- mgpsogui/gui/SetupTab/BoundsList.py +97 -34
- mgpsogui/gui/SetupTab/CustomFunctionEditorWindow.py +74 -0
- mgpsogui/gui/SetupTab/CustomFunctionMetrics.py +156 -0
- mgpsogui/gui/SetupTab/FunctionsList.py +60 -6
- mgpsogui/gui/SetupTab/{StaticParameterView.py → ListEditor.py} +27 -16
- mgpsogui/gui/SetupTab/ListParametersView.py +7 -6
- mgpsogui/gui/SetupTab/{CalibrationParametersView.py → OverrideParameterMetrics.py} +35 -9
- mgpsogui/gui/SetupTab/OverrideParameterWindow.py +40 -0
- mgpsogui/gui/SetupTab/SetupTab.py +31 -11
- mgpsogui/gui/SetupTab/StepView.py +93 -22
- mgpsogui/gui/VisualizeTab/MatrixEditor.py +68 -0
- mgpsogui/gui/VisualizeTab/SideBar.py +316 -25
- mgpsogui/gui/VisualizeTab/VisualizeTab.py +69 -8
- mgpsogui/gui/defaults/__init__.py +0 -0
- mgpsogui/gui/defaults/optimization.json +176 -0
- mgpsogui/gui/defaults/sampling.json +111 -0
- mgpsogui/gui/defaults/sensitivity.json +20 -0
- mgpsogui/gui/images/plus.png +0 -0
- mgpsogui/util/GraphGenerator.py +721 -50
- mgpsogui/util/PSORunner.py +615 -86
- mgpsogui/util/debug.py +559 -0
- mgpsogui/util/helpers.py +95 -0
- mgpsogui/util/recosu/__init__.py +2 -1
- mgpsogui/util/recosu/pso/pso.py +55 -11
- mgpsogui/util/recosu/sampling/__init__.py +16 -0
- mgpsogui/util/recosu/sampling/halton/__init__.py +0 -0
- mgpsogui/util/recosu/sampling/halton/halton.py +45 -0
- mgpsogui/util/recosu/sampling/halton/prime.py +82 -0
- mgpsogui/util/recosu/sampling/random/__init__.py +0 -0
- mgpsogui/util/recosu/sampling/random/random_sampler.py +34 -0
- mgpsogui/util/recosu/sampling/sample_trace_writer.py +47 -0
- mgpsogui/util/recosu/sampling/sampler_task.py +75 -0
- mgpsogui/util/recosu/sampling/sampling.py +99 -0
- mgpsogui/util/sampler_test_driver.py +129 -0
- mg_pso_gui-0.1.40.dist-info/RECORD +0 -52
- mgpsogui/gui/images/IGOW 4 Logo.png +0 -0
- {mg_pso_gui-0.1.40.dist-info → mg_pso_gui-0.2.75.dist-info}/entry_points.txt +0 -0
- {mg_pso_gui-0.1.40.dist-info → mg_pso_gui-0.2.75.dist-info}/top_level.txt +0 -0
mgpsogui/gui/RunTab/RunTab.py
CHANGED
@@ -8,35 +8,108 @@ import re
|
|
8
8
|
import ast
|
9
9
|
import pandas as pd
|
10
10
|
import numpy as np
|
11
|
+
import os
|
12
|
+
import platform
|
13
|
+
import subprocess
|
11
14
|
|
12
15
|
from ...util import PSORunner
|
13
16
|
from ...util import GraphGenerator
|
14
17
|
from ...util.CTkToolTip import CTkToolTip as ctt
|
18
|
+
import customtkinter
|
19
|
+
|
20
|
+
from . import OptimalParameterView as opv
|
15
21
|
|
16
22
|
def create_tab(self, tab):
|
17
23
|
|
18
24
|
# URL
|
19
25
|
tab.grid_columnconfigure(0, weight=1)
|
20
|
-
tab.
|
21
|
-
tab.
|
22
|
-
|
23
|
-
|
24
|
-
self.progress_container.
|
25
|
-
self.progress_container.grid_columnconfigure(
|
26
|
-
self.progress_container.grid_columnconfigure(
|
27
|
-
self.progress_container.
|
26
|
+
tab.grid_columnconfigure(1, weight=5)
|
27
|
+
tab.grid_columnconfigure(2, weight=1)
|
28
|
+
tab.grid_rowconfigure(0, weight=200)
|
29
|
+
|
30
|
+
#self.progress_container = customtkinter.CTkFrame(tab)
|
31
|
+
#self.progress_container.grid_columnconfigure(0, weight=1)
|
32
|
+
#self.progress_container.grid_columnconfigure(1, weight=1)
|
33
|
+
#self.progress_container.grid_columnconfigure(2, weight=1)
|
34
|
+
#self.progress_container.grid(row=0, column=0, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
28
35
|
|
29
36
|
# Add progress bar to progress container
|
30
|
-
self.progress_message_left = customtkinter.CTkLabel(self.progress_container, text="")
|
31
|
-
self.progress_message_left.grid(row=0, column=0, padx=(10, 10), pady=(10, 10), sticky="w")
|
37
|
+
#self.progress_message_left = customtkinter.CTkLabel(self.progress_container, text="")
|
38
|
+
#self.progress_message_left.grid(row=0, column=0, padx=(10, 10), pady=(10, 10), sticky="w")
|
32
39
|
|
33
|
-
self.progress_message_middle = customtkinter.CTkLabel(self.progress_container, text="Calibration not running...")
|
34
|
-
self.progress_message_middle.grid(row=0, column=1, padx=(10, 10), pady=(10, 10), sticky="ew")
|
40
|
+
#self.progress_message_middle = customtkinter.CTkLabel(self.progress_container, text="Calibration not running...")
|
41
|
+
#self.progress_message_middle.grid(row=0, column=1, padx=(10, 10), pady=(10, 10), sticky="ew")
|
35
42
|
|
36
|
-
self.progress_message_right = customtkinter.CTkLabel(self.progress_container, text="")
|
37
|
-
self.progress_message_right.grid(row=0, column=2, padx=(10, 10), pady=(10, 10), sticky="e")
|
43
|
+
#self.progress_message_right = customtkinter.CTkLabel(self.progress_container, text="")
|
44
|
+
#self.progress_message_right.grid(row=0, column=2, padx=(10, 10), pady=(10, 10), sticky="e")
|
38
45
|
|
46
|
+
self.optimal_param_frame = opv.OptimalParameterView(tab, option_manager=self.option_manager, label_text="Optimal Parameters")
|
47
|
+
self.optimal_param_frame.grid(row=0, column=0, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
48
|
+
self.optimal_param_frame.grid_columnconfigure(0, weight=1)
|
49
|
+
self.optimal_param_frame.grid_rowconfigure(0, weight=1)
|
50
|
+
|
39
51
|
self.textbox = customtkinter.CTkTextbox(tab)
|
40
|
-
self.textbox.grid(row=
|
41
|
-
self.textbox.insert("0.0", "Welcome to the CSIP PSO Calibration Tool!\n\nUse the Setup tab to define steps and calibration parameters. Use this tab to view logs and
|
42
|
-
|
52
|
+
self.textbox.grid(row=0, column=1, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
53
|
+
self.textbox.insert("0.0", "Welcome to the CSIP PSO Calibration Tool!\n\nUse the Setup tab to define steps and calibration parameters. Use this tab to view logs and manage your Project. Once finished, use the Results tab to generate figures and graphs.")
|
54
|
+
|
55
|
+
self.project_editor = customtkinter.CTkScrollableFrame(tab, label_text="Project Editor")
|
56
|
+
self.project_editor.grid(row=0, column=2, padx=(20, 20), pady=(20, 20), sticky="nsew")
|
57
|
+
self.project_editor.grid_columnconfigure(0, weight=1)
|
58
|
+
self.project_editor.grid_rowconfigure(0, weight=1)
|
59
|
+
|
60
|
+
customtkinter.CTkLabel(self.project_editor, text="Copy Data to Current Mode:").grid(row=0, column=0, padx=(20, 20), pady=(5, 10), sticky="ew")
|
61
|
+
|
62
|
+
def copy_sense():
|
63
|
+
self.option_manager.copy_list("Sensitivity Analysis")
|
64
|
+
self.refresh_step_view(0)
|
65
|
+
|
66
|
+
def copy_halton():
|
67
|
+
self.option_manager.copy_list("Sampling: Halton")
|
68
|
+
self.refresh_step_view(0)
|
69
|
+
|
70
|
+
def copy_random():
|
71
|
+
self.option_manager.copy_list("Sampling: Random")
|
72
|
+
self.refresh_step_view(0)
|
73
|
+
|
74
|
+
def copy_optim():
|
75
|
+
self.option_manager.copy_list("Optimization")
|
76
|
+
self.refresh_step_view(0)
|
77
|
+
|
78
|
+
def open_project_folder():
|
79
|
+
# Open the file in the default program
|
80
|
+
folder = self.option_manager.get_project_folder()
|
81
|
+
|
82
|
+
if not os.path.exists(folder):
|
83
|
+
os.makedirs(folder)
|
84
|
+
|
85
|
+
if platform.system() == "Windows":
|
86
|
+
os.startfile(folder)
|
87
|
+
elif platform.system() == "Darwin":
|
88
|
+
subprocess.Popen(["open", folder])
|
89
|
+
else:
|
90
|
+
subprocess.Popen(["xdg-open", folder])
|
91
|
+
|
92
|
+
self.halton_copy = customtkinter.CTkButton(self.project_editor, text="From Sampling: Halton", command=copy_halton)
|
93
|
+
self.halton_copy.grid(row=1, column=0, padx=(20, 20), pady=(5, 10), sticky="ew")
|
94
|
+
|
95
|
+
self.random_copy = customtkinter.CTkButton(self.project_editor, text="From Sampling: Random", command=copy_random)
|
96
|
+
self.random_copy.grid(row=2, column=0, padx=(20, 20), pady=(5, 10), sticky="ew")
|
97
|
+
|
98
|
+
self.analysis_copy = customtkinter.CTkButton(self.project_editor, text="From Sensitivity Analysis", command=copy_sense)
|
99
|
+
self.analysis_copy.grid(row=3, column=0, padx=(20, 20), pady=(5, 10), sticky="ew")
|
100
|
+
|
101
|
+
self.optimization_copy = customtkinter.CTkButton(self.project_editor, text="From Optimization", command=copy_optim)
|
102
|
+
self.optimization_copy.grid(row=4, column=0, padx=(20, 20), pady=(5, 10), sticky="ew")
|
103
|
+
|
104
|
+
customtkinter.CTkLabel(self.project_editor, text="Project Management:").grid(row=5, column=0, padx=(20, 20), pady=(5, 10), sticky="ew")
|
105
|
+
|
106
|
+
self.open_folder = customtkinter.CTkButton(self.project_editor, text="Open Project Folder", command=open_project_folder)
|
107
|
+
self.open_folder.grid(row=6, column=0, padx=(20, 20), pady=(5, 10), sticky="ew")
|
108
|
+
|
109
|
+
customtkinter.CTkLabel(self.project_editor, text="Project Name:").grid(row=7, column=0, padx=(20, 20), pady=(10, 5), sticky="ew")
|
110
|
+
self.project_name_label = customtkinter.CTkLabel(self.project_editor, text=self.option_manager.get_project_data()["name"])
|
111
|
+
self.project_name_label.grid(row=8, column=0, padx=(20, 20), pady=(5, 10), sticky="ew")
|
112
|
+
|
113
|
+
customtkinter.CTkLabel(self.project_editor, text="Project Path:").grid(row=9, column=0, padx=(20, 20), pady=(10, 5), sticky="ew")
|
114
|
+
self.project_path_label = customtkinter.CTkLabel(self.project_editor, text=self.option_manager.get_project_data()["path"])
|
115
|
+
self.project_path_label.grid(row=10, column=0, padx=(20, 20), pady=(5, 10), sticky="ew")
|
@@ -54,7 +54,7 @@ class BoundsEditorWindow(CTkInputDialog):
|
|
54
54
|
hover_color=self._button_hover_color,
|
55
55
|
text_color=self._button_text_color,
|
56
56
|
text='Cancel',
|
57
|
-
command=self.
|
57
|
+
command=self._cancel_event)
|
58
58
|
self._cancel_button.grid(row=2, column=1, columnspan=1, padx=(10, 20), pady=(0, 20), sticky="ew")
|
59
59
|
|
60
60
|
def _ok_event(self, event=None):
|
@@ -13,6 +13,8 @@ import json
|
|
13
13
|
import PIL
|
14
14
|
from PIL import Image
|
15
15
|
import os
|
16
|
+
import pandas as pd
|
17
|
+
from tkinter.filedialog import askopenfilename
|
16
18
|
|
17
19
|
class BoundsList(CTkFrame):
|
18
20
|
def __init__(self, *args,
|
@@ -21,20 +23,8 @@ class BoundsList(CTkFrame):
|
|
21
23
|
**kwargs):
|
22
24
|
super().__init__(*args, **kwargs)
|
23
25
|
|
24
|
-
self.optParams = []
|
25
26
|
self.option_manager = option_manager
|
26
27
|
|
27
|
-
details = self.option_manager.get_service_parameters()
|
28
|
-
self.paramMap = {}
|
29
|
-
if "parameter" in details:
|
30
|
-
for param in details["parameter"]:
|
31
|
-
self.paramMap[param["name"]] = param
|
32
|
-
if "min" in param:
|
33
|
-
self.optParams.append(param["name"])
|
34
|
-
|
35
|
-
self.optParams.sort()
|
36
|
-
|
37
|
-
|
38
28
|
self.edit_mode = False
|
39
29
|
self.tooltip_list = []
|
40
30
|
|
@@ -62,6 +52,34 @@ class BoundsList(CTkFrame):
|
|
62
52
|
index = 0
|
63
53
|
|
64
54
|
self.tooltip_list = []
|
55
|
+
|
56
|
+
mode = self.option_manager.get_mode()
|
57
|
+
|
58
|
+
# Load bound parameters depending on the mode
|
59
|
+
self.optParams = []
|
60
|
+
if mode == "Optimization" or mode == "Sampling: Halton" or mode == "Sampling: Random":
|
61
|
+
details = self.option_manager.serialize_data(self.option_manager.get("service_request_data"))
|
62
|
+
self.paramMap = {}
|
63
|
+
if "parameter" in details:
|
64
|
+
for param in details["parameter"]:
|
65
|
+
self.paramMap[param["name"]] = param
|
66
|
+
if "min" in param:
|
67
|
+
self.optParams.append(param["name"])
|
68
|
+
|
69
|
+
self.optParams.sort()
|
70
|
+
elif mode == "Sensitivity Analysis":
|
71
|
+
file_path = self.option_manager.get("sensitivity_analysis_path").get()
|
72
|
+
folder = self.option_manager.get_project_folder()
|
73
|
+
file_path = os.path.join(folder, "results", file_path)
|
74
|
+
if os.path.exists(file_path):
|
75
|
+
try:
|
76
|
+
df = pd.read_csv(file_path)
|
77
|
+
self.optParams = df.columns.tolist()
|
78
|
+
except Exception as e:
|
79
|
+
print(f"Error loading CSV file: {e}")
|
80
|
+
else:
|
81
|
+
print(f"File does not exist: {file_path}")
|
82
|
+
|
65
83
|
|
66
84
|
self.containerFrame = CTkFrame(self, fg_color="transparent")
|
67
85
|
self.containerFrame.grid(row=0, column=0, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
@@ -71,12 +89,16 @@ class BoundsList(CTkFrame):
|
|
71
89
|
|
72
90
|
CTkLabel(self.containerFrame, text="Type:").grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
73
91
|
CTkLabel(self.containerFrame, text="Name:").grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
74
|
-
|
75
|
-
|
76
|
-
|
92
|
+
|
93
|
+
if mode != "Sensitivity Analysis":
|
94
|
+
CTkLabel(self.containerFrame, text="Bounds:").grid(row=row, column=2, columnspan=2, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
95
|
+
|
96
|
+
if mode == "Optimization":
|
97
|
+
CTkLabel(self.containerFrame, text="Default:").grid(row=row, column=4, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
98
|
+
CTkLabel(self.containerFrame, text="Strategy:").grid(row=row, column=5, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
77
99
|
row += 1
|
78
100
|
|
79
|
-
bounds = self.option_manager.get_steps()[self.step_index]["
|
101
|
+
bounds = self.option_manager.get_steps()[self.step_index]["parameter_objects"]
|
80
102
|
|
81
103
|
for bound in bounds:
|
82
104
|
tt1 = None
|
@@ -112,34 +134,53 @@ class BoundsList(CTkFrame):
|
|
112
134
|
bb.grid(row=row, column=2, padx=(5, 5), pady=(5, 5), sticky="new")
|
113
135
|
ctt(bb, delay=0.1, alpha=0.95, message="Delete this bound...")
|
114
136
|
else:
|
137
|
+
|
138
|
+
if mode == "Sensitivity Analysis":
|
139
|
+
row += 1
|
140
|
+
index += 1
|
141
|
+
continue
|
142
|
+
|
115
143
|
bounds_min = CTkEntry(self.containerFrame)
|
116
144
|
vcmd = (self.register(self.validate_number), '%P', cc, bounds_min)
|
117
145
|
bounds_min.grid(row=row, column=2, padx=(5, 5), pady=(5, 5), sticky="new")
|
118
|
-
bounds_min.configure(textvariable=bound["
|
146
|
+
bounds_min.configure(textvariable=bound["min_bound"], validate='all', validatecommand=vcmd)
|
119
147
|
self.validate_number(bounds_min.get(), cc, bounds_min)
|
120
148
|
|
121
149
|
bounds_max = CTkEntry(self.containerFrame)
|
122
150
|
vcmd = (self.register(self.validate_number), '%P', cc, bounds_max)
|
123
151
|
bounds_max.grid(row=row, column=3, padx=(5, 5), pady=(5, 5), sticky="new")
|
124
|
-
bounds_max.configure(textvariable=bound["
|
152
|
+
bounds_max.configure(textvariable=bound["max_bound"], validate='all', validatecommand=vcmd)
|
125
153
|
self.validate_number(bounds_max.get(), cc, bounds_max)
|
126
154
|
tt2 = ctt(bounds_max, delay=0.1, alpha=0.95, message="...")
|
127
155
|
|
128
|
-
default_value = CTkEntry(self.containerFrame)
|
129
|
-
default_value.grid(row=row, column=4, padx=(5, 5), pady=(5, 5), sticky="new")
|
130
|
-
default_value.configure(textvariable=bound["default_value"])
|
131
|
-
|
132
|
-
|
133
156
|
if (bound_type == "list"):
|
134
157
|
def button_click_event(bound_index):
|
135
|
-
|
136
|
-
print("Number:", dialog.get_input())
|
158
|
+
BEW(title="Edit List Bound", step_index=self.step_index, bound_index=bound_index, option_manager=self.option_manager)
|
137
159
|
|
138
160
|
open_window = lambda event=None, bound_index=index: (button_click_event(bound_index))
|
139
161
|
expand_image = CTkImage(Image.open(os.path.join("./images", "expand.png")), size=(20, 20))
|
140
162
|
button = CTkButton(self.containerFrame, width=30, text=None, image=expand_image, command=open_window)
|
141
163
|
button.grid(row=row, column=6, padx=(5, 5), pady=(5, 5), sticky="new")
|
142
164
|
|
165
|
+
if mode == "Sampling: Random" or mode == "Sampling: Halton":
|
166
|
+
|
167
|
+
tt1 = ctt(bounds_min, delay=0.1, alpha=0.95, message="...")
|
168
|
+
tt2 = ctt(bounds_max, delay=0.1, alpha=0.95, message="...")
|
169
|
+
if cc is not None:
|
170
|
+
tt3 = ctt(cc, delay=0.1, alpha=0.95, message="...")
|
171
|
+
|
172
|
+
self.tooltip_list.append([tt3, tt1, tt2])
|
173
|
+
|
174
|
+
self.update_tooltips(index)
|
175
|
+
|
176
|
+
row += 1
|
177
|
+
index += 1
|
178
|
+
continue
|
179
|
+
|
180
|
+
default_value = CTkEntry(self.containerFrame)
|
181
|
+
default_value.grid(row=row, column=4, padx=(5, 5), pady=(5, 5), sticky="new")
|
182
|
+
default_value.configure(textvariable=bound["default_value"])
|
183
|
+
|
143
184
|
calibration_strat = CTkOptionMenu(self.containerFrame, dynamic_resizing=False, values=['none', 'mean', 'single'], variable=bound["calibration_strategy"])
|
144
185
|
calibration_strat.grid(row=row, column=5, padx=(5, 5), pady=(5, 5), sticky="new")
|
145
186
|
|
@@ -161,26 +202,48 @@ class BoundsList(CTkFrame):
|
|
161
202
|
CTkButton(self.containerFrame, text="Exit", command=self.toggle_edit_mode).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="new")
|
162
203
|
else:
|
163
204
|
CTkButton(self.containerFrame, text="Edit", command=self.toggle_edit_mode).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="new")
|
164
|
-
|
165
|
-
|
166
|
-
|
205
|
+
|
206
|
+
CTkButton(self.containerFrame, text="Add Bound", command=add_func).grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="new")
|
207
|
+
|
208
|
+
def import_csv():
|
209
|
+
filename = askopenfilename(filetypes=[("CSV", "*.csv")], title="Open Bound CSV", multiple=False)
|
210
|
+
print(filename)
|
211
|
+
|
212
|
+
# Open CSV file
|
213
|
+
if filename is not None and filename != "":
|
214
|
+
df = pd.read_csv(filename)
|
215
|
+
for _, row in df.iterrows():
|
216
|
+
if "name" not in row:
|
217
|
+
continue
|
218
|
+
name = row["name"] if "name" in row else "name"
|
219
|
+
type_ = row["type"] if "type" in row else "custom"
|
220
|
+
min_bound = row["min_bound"] if "min_bound" in row else 0
|
221
|
+
max_bound = row["max_bound"] if "max_bound" in row else 1
|
222
|
+
default_value = row["default_value"] if "default_value" in row else 1
|
223
|
+
calibration_strategy = row["calibration_strategy"] if "calibration_strategy" in row else "none"
|
224
|
+
self.option_manager.add_bound(step_index=self.step_index, name=name, min=min_bound, max=max_bound, type=type_, default_value=default_value, calibration_strategy=calibration_strategy)
|
225
|
+
|
226
|
+
self.clear()
|
227
|
+
self.render()
|
228
|
+
|
229
|
+
CTkButton(self.containerFrame, text="Import CSV", command=import_csv).grid(row=row, column=2, padx=(5, 5), pady=(5, 5), sticky="new")
|
167
230
|
|
168
231
|
def update_type(self, index, option):
|
169
232
|
value = option.get()
|
170
|
-
self.option_manager.get_steps()[self.step_index]["
|
233
|
+
self.option_manager.get_steps()[self.step_index]["parameter_objects"][index]["type"].set(value)
|
171
234
|
self.refresh()
|
172
235
|
|
173
236
|
def update_values(self, index):
|
174
|
-
name = self.option_manager.get_steps()[self.step_index]["
|
237
|
+
name = self.option_manager.get_steps()[self.step_index]["parameter_objects"][index]["name"].get()
|
175
238
|
if name in self.paramMap:
|
176
239
|
obj = self.paramMap[name]
|
177
|
-
self.option_manager.get_steps()[self.step_index]["
|
178
|
-
self.option_manager.get_steps()[self.step_index]["
|
240
|
+
self.option_manager.get_steps()[self.step_index]["parameter_objects"][index]["min_bound"].set(obj["softmin"])
|
241
|
+
self.option_manager.get_steps()[self.step_index]["parameter_objects"][index]["max_bound"].set(obj["softmax"])
|
179
242
|
|
180
243
|
def update_tooltips(self, index):
|
181
244
|
try:
|
182
|
-
name = self.option_manager.get_steps()[self.step_index]["
|
183
|
-
bound_type = self.option_manager.get_steps()[self.step_index]["
|
245
|
+
name = self.option_manager.get_steps()[self.step_index]["parameter_objects"][index]["name"].get()
|
246
|
+
bound_type = self.option_manager.get_steps()[self.step_index]["parameter_objects"][index]["type"].get()
|
184
247
|
|
185
248
|
tooltips = self.tooltip_list[index]
|
186
249
|
t3 = tooltips[0]
|
@@ -0,0 +1,74 @@
|
|
1
|
+
from typing import Union, Tuple, Optional
|
2
|
+
|
3
|
+
from customtkinter import CTkLabel
|
4
|
+
from customtkinter import CTkButton
|
5
|
+
from customtkinter import CTkEntry
|
6
|
+
from customtkinter import CTkInputDialog
|
7
|
+
from .CustomFunctionMetrics import CustomFunctionsMetricsView as ListView
|
8
|
+
|
9
|
+
class CustomFunctionEditorWindow(CTkInputDialog):
|
10
|
+
"""
|
11
|
+
Dialog with extra window, message, entry widget, cancel and ok button.
|
12
|
+
For detailed information check out the documentation.
|
13
|
+
"""
|
14
|
+
|
15
|
+
def __init__(self, *args,
|
16
|
+
step_index: 0,
|
17
|
+
function_index: 0,
|
18
|
+
option_manager: None,
|
19
|
+
**kwargs):
|
20
|
+
super().__init__(*args, **kwargs)
|
21
|
+
|
22
|
+
self.geometry("400x800")
|
23
|
+
|
24
|
+
self.step_index = step_index
|
25
|
+
self.function_index = function_index
|
26
|
+
self.option_manager = option_manager
|
27
|
+
self.bounds = None
|
28
|
+
|
29
|
+
def _create_widgets(self):
|
30
|
+
|
31
|
+
self.grid_columnconfigure((0, 1), weight=1)
|
32
|
+
self.rowconfigure(0, weight=1)
|
33
|
+
|
34
|
+
self.bounds = ListView(
|
35
|
+
self, step_index=self.step_index, function_index=self.function_index, option_manager=self.option_manager)
|
36
|
+
self.bounds.grid(row=0, column=0, columnspan=2, padx=(10, 10),
|
37
|
+
pady=(10, 10), sticky="nsew")
|
38
|
+
self.bounds.grid_columnconfigure(0, weight=1)
|
39
|
+
|
40
|
+
self._ok_button = CTkButton(master=self,
|
41
|
+
width=100,
|
42
|
+
border_width=0,
|
43
|
+
fg_color=self._button_fg_color,
|
44
|
+
hover_color=self._button_hover_color,
|
45
|
+
text_color=self._button_text_color,
|
46
|
+
text='Save',
|
47
|
+
command=self._ok_event)
|
48
|
+
self._ok_button.grid(row=2, column=0, columnspan=1, padx=(20, 10), pady=(0, 20), sticky="ew")
|
49
|
+
|
50
|
+
self._cancel_button = CTkButton(master=self,
|
51
|
+
width=100,
|
52
|
+
border_width=0,
|
53
|
+
fg_color=self._button_fg_color,
|
54
|
+
hover_color=self._button_hover_color,
|
55
|
+
text_color=self._button_text_color,
|
56
|
+
text='Cancel',
|
57
|
+
command=self._cancel_event)
|
58
|
+
self._cancel_button.grid(row=2, column=1, columnspan=1, padx=(10, 20), pady=(0, 20), sticky="ew")
|
59
|
+
|
60
|
+
def _ok_event(self, event=None):
|
61
|
+
# Save values in bounds editor...
|
62
|
+
|
63
|
+
self.bounds.push_to_option_manager()
|
64
|
+
|
65
|
+
self.grab_release()
|
66
|
+
self.destroy()
|
67
|
+
|
68
|
+
def _on_closing(self):
|
69
|
+
self.grab_release()
|
70
|
+
self.destroy()
|
71
|
+
|
72
|
+
def _cancel_event(self):
|
73
|
+
self.grab_release()
|
74
|
+
self.destroy()
|
@@ -0,0 +1,156 @@
|
|
1
|
+
from customtkinter import CTkScrollableFrame
|
2
|
+
from customtkinter import CTkFrame
|
3
|
+
from customtkinter import CTkLabel
|
4
|
+
from customtkinter import CTkButton
|
5
|
+
from customtkinter import CTkEntry
|
6
|
+
from customtkinter import CTkOptionMenu
|
7
|
+
import tkinter as tk
|
8
|
+
import subprocess
|
9
|
+
import platform
|
10
|
+
import os
|
11
|
+
|
12
|
+
global option_manager
|
13
|
+
|
14
|
+
class CustomFunctionsMetricsView(CTkScrollableFrame):
|
15
|
+
def __init__(self, *args,
|
16
|
+
option_manager: None,
|
17
|
+
step_index: 0,
|
18
|
+
function_index: 0,
|
19
|
+
**kwargs):
|
20
|
+
super().__init__(*args, **kwargs)
|
21
|
+
|
22
|
+
self.option_manager = option_manager
|
23
|
+
self.step_index = step_index
|
24
|
+
self.functions_index = function_index
|
25
|
+
self.key_values = []
|
26
|
+
|
27
|
+
self.edit_mode = False
|
28
|
+
|
29
|
+
self.columns = ["absdiff",
|
30
|
+
"absdifflog",
|
31
|
+
"ave",
|
32
|
+
"bias",
|
33
|
+
"fhf",
|
34
|
+
"ioa",
|
35
|
+
"ioa2",
|
36
|
+
"kge",
|
37
|
+
"kge09",
|
38
|
+
"mns",
|
39
|
+
"mse",
|
40
|
+
"ns",
|
41
|
+
"ns2log",
|
42
|
+
"nslog1p",
|
43
|
+
"nslog2",
|
44
|
+
"pbias",
|
45
|
+
"pmcc",
|
46
|
+
"rmse",
|
47
|
+
"trmse"]
|
48
|
+
|
49
|
+
self.positive_best = {"absdiff": True,
|
50
|
+
"absdifflog": True,
|
51
|
+
"ave": True,
|
52
|
+
"bias": True,
|
53
|
+
"fhf": True,
|
54
|
+
"ioa": True,
|
55
|
+
"ioa2": True,
|
56
|
+
"kge": True,
|
57
|
+
"kge09": True,
|
58
|
+
"mns": True,
|
59
|
+
"mse": True,
|
60
|
+
"ns": False,
|
61
|
+
"ns2log": True,
|
62
|
+
"nslog1p": True,
|
63
|
+
"nslog2": True,
|
64
|
+
"pbias": True,
|
65
|
+
"pmcc": True,
|
66
|
+
"rmse": True,
|
67
|
+
"trmse": True}
|
68
|
+
|
69
|
+
equation = self.option_manager.get_steps()[self.step_index]["objective_functions"][self.functions_index]["custom_function"].get()
|
70
|
+
|
71
|
+
# Example equation (0 * (1 - ns)) + (bias * 0) + (pbias * 0) + (absdiff * 0)
|
72
|
+
try:
|
73
|
+
if equation != "":
|
74
|
+
equation = equation.replace("1 - ", "")
|
75
|
+
equation = equation.replace("(", "")
|
76
|
+
equation = equation.replace(")", "")
|
77
|
+
equation = equation.replace(" ", "")
|
78
|
+
pairs = equation.split("+")
|
79
|
+
for pair in pairs:
|
80
|
+
key, value = pair.split("*")
|
81
|
+
self.add_key(key, value)
|
82
|
+
except Exception as e:
|
83
|
+
self.key_values = []
|
84
|
+
|
85
|
+
self.render()
|
86
|
+
|
87
|
+
def clear(self):
|
88
|
+
self.containerFrame.destroy()
|
89
|
+
|
90
|
+
def toggle_edit_mode(self):
|
91
|
+
self.clear()
|
92
|
+
self.edit_mode = not self.edit_mode
|
93
|
+
self.render()
|
94
|
+
|
95
|
+
def add_key(self, key="ns", value="0"):
|
96
|
+
obj = {"name": tk.StringVar(), "value": tk.StringVar()}
|
97
|
+
obj['name'].set(key)
|
98
|
+
obj['value'].set(value)
|
99
|
+
self.key_values.append(obj)
|
100
|
+
|
101
|
+
def remove_key(self, index):
|
102
|
+
self.key_values.pop(index)
|
103
|
+
|
104
|
+
def render(self):
|
105
|
+
row = 0
|
106
|
+
index = 0
|
107
|
+
|
108
|
+
self.containerFrame = CTkFrame(self)
|
109
|
+
self.containerFrame.grid(row=0, column=0, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
110
|
+
self.containerFrame.grid_columnconfigure((0, 1), weight=1)
|
111
|
+
|
112
|
+
CTkLabel(self.containerFrame, text="Objective:").grid(row=row, column=0, columnspan=1, padx=5, pady=5, sticky="")
|
113
|
+
CTkLabel(self.containerFrame, text="Weight:").grid(row=row, column=1, columnspan=1, padx=5, pady=5, sticky="")
|
114
|
+
row += 1
|
115
|
+
|
116
|
+
for key_value_pair in self.key_values:
|
117
|
+
CTkOptionMenu(self.containerFrame, values=self.columns, variable=self.key_values[index]["name"]).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="ew")
|
118
|
+
|
119
|
+
|
120
|
+
if self.edit_mode:
|
121
|
+
return_func = lambda index=index: (self.clear(), self.remove_key(index), self.render())
|
122
|
+
CTkButton(self.containerFrame, text="Remove", command=return_func).grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="ew")
|
123
|
+
else:
|
124
|
+
bb = CTkEntry(self.containerFrame)
|
125
|
+
bb.grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="ew")
|
126
|
+
bb.configure(textvariable=self.key_values[index]["value"])
|
127
|
+
row += 1
|
128
|
+
index += 1
|
129
|
+
|
130
|
+
if self.edit_mode:
|
131
|
+
CTkButton(self.containerFrame, text="Exit", command=self.toggle_edit_mode).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="ew")
|
132
|
+
else:
|
133
|
+
CTkButton(self.containerFrame, text="Edit", command=self.toggle_edit_mode).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="ew")
|
134
|
+
|
135
|
+
add_key_func = lambda: (self.clear(), self.add_key(), self.render())
|
136
|
+
CTkButton(self.containerFrame, text="Add", command=add_key_func).grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="ew")
|
137
|
+
|
138
|
+
row += 1
|
139
|
+
|
140
|
+
def push_to_option_manager(self):
|
141
|
+
equation = ""
|
142
|
+
|
143
|
+
for key_value in self.key_values:
|
144
|
+
name = key_value["name"].get()
|
145
|
+
weight = key_value["value"].get()
|
146
|
+
|
147
|
+
positiveBest = self.positive_best[name]
|
148
|
+
|
149
|
+
if positiveBest:
|
150
|
+
equation += f"({name} * {weight}) + "
|
151
|
+
else:
|
152
|
+
equation += f"((1 - {name}) * {weight}) + "
|
153
|
+
|
154
|
+
equation = equation[:-3] # Remove the last " + "
|
155
|
+
|
156
|
+
self.option_manager.get_steps()[self.step_index]["objective_functions"][self.functions_index]["custom_function"].set(equation)
|