alchemist-nrel 0.2.1__py3-none-any.whl → 0.3.0__py3-none-any.whl
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.
- alchemist_core/__init__.py +14 -7
- alchemist_core/acquisition/botorch_acquisition.py +14 -6
- alchemist_core/audit_log.py +594 -0
- alchemist_core/data/experiment_manager.py +69 -5
- alchemist_core/models/botorch_model.py +6 -4
- alchemist_core/models/sklearn_model.py +44 -6
- alchemist_core/session.py +600 -8
- alchemist_core/utils/doe.py +200 -0
- {alchemist_nrel-0.2.1.dist-info → alchemist_nrel-0.3.0.dist-info}/METADATA +57 -40
- alchemist_nrel-0.3.0.dist-info/RECORD +66 -0
- {alchemist_nrel-0.2.1.dist-info → alchemist_nrel-0.3.0.dist-info}/entry_points.txt +1 -0
- {alchemist_nrel-0.2.1.dist-info → alchemist_nrel-0.3.0.dist-info}/top_level.txt +1 -0
- api/main.py +19 -3
- api/models/requests.py +71 -0
- api/models/responses.py +144 -0
- api/routers/experiments.py +117 -5
- api/routers/sessions.py +329 -10
- api/routers/visualizations.py +10 -5
- api/services/session_store.py +210 -54
- api/static/NEW_ICON.ico +0 -0
- api/static/NEW_ICON.png +0 -0
- api/static/NEW_LOGO_DARK.png +0 -0
- api/static/NEW_LOGO_LIGHT.png +0 -0
- api/static/assets/api-vcoXEqyq.js +1 -0
- api/static/assets/index-C0_glioA.js +4084 -0
- api/static/assets/index-CB4V1LI5.css +1 -0
- api/static/index.html +14 -0
- api/static/vite.svg +1 -0
- run_api.py +55 -0
- ui/gpr_panel.py +7 -2
- ui/notifications.py +197 -10
- ui/ui.py +1117 -68
- ui/variables_setup.py +47 -2
- ui/visualizations.py +60 -3
- alchemist_nrel-0.2.1.dist-info/RECORD +0 -54
- {alchemist_nrel-0.2.1.dist-info → alchemist_nrel-0.3.0.dist-info}/WHEEL +0 -0
- {alchemist_nrel-0.2.1.dist-info → alchemist_nrel-0.3.0.dist-info}/licenses/LICENSE +0 -0
ui/variables_setup.py
CHANGED
|
@@ -2,6 +2,7 @@ import customtkinter as ctk
|
|
|
2
2
|
from customtkinter import filedialog
|
|
3
3
|
import json, csv, os
|
|
4
4
|
from skopt.space import Real, Integer, Categorical
|
|
5
|
+
from alchemist_core.data.search_space import SearchSpace
|
|
5
6
|
from tkinter import StringVar
|
|
6
7
|
import tkinter.messagebox as messagebox
|
|
7
8
|
from tksheet import Sheet # requires tksheet package
|
|
@@ -427,7 +428,52 @@ class SpaceSetupWindow(ctk.CTkToplevel):
|
|
|
427
428
|
|
|
428
429
|
# Update the main UI if it has the necessary methods
|
|
429
430
|
if hasattr(self.master, 'search_space'):
|
|
431
|
+
# Store the skopt-compatible dimensions for legacy UI code
|
|
430
432
|
self.master.search_space = self.search_space
|
|
433
|
+
# Always create/update the SearchSpace manager on the master so the
|
|
434
|
+
# OptimizationSession and ExperimentManager get a consistent object.
|
|
435
|
+
try:
|
|
436
|
+
ss = SearchSpace().from_dict(self.master.variable_space_data)
|
|
437
|
+
self.master.search_space_manager = ss
|
|
438
|
+
# Keep the skopt-compatible reference too
|
|
439
|
+
try:
|
|
440
|
+
self.master.search_space = ss.to_skopt()
|
|
441
|
+
except Exception:
|
|
442
|
+
self.master.search_space = ss
|
|
443
|
+
# Ensure experiment manager is updated
|
|
444
|
+
if hasattr(self.master, 'experiment_manager'):
|
|
445
|
+
try:
|
|
446
|
+
self.master.experiment_manager.set_search_space(ss)
|
|
447
|
+
except Exception:
|
|
448
|
+
pass
|
|
449
|
+
# If there's an active OptimizationSession, update it as well
|
|
450
|
+
if hasattr(self.master, 'session') and self.master.session is not None:
|
|
451
|
+
try:
|
|
452
|
+
self.master.session.search_space = ss
|
|
453
|
+
self.master.session.experiment_manager.set_search_space(ss)
|
|
454
|
+
# emit an event so other UI components can react
|
|
455
|
+
try:
|
|
456
|
+
self.master.session.events.emit('search_space_loaded', {'source': 'ui'})
|
|
457
|
+
except Exception:
|
|
458
|
+
pass
|
|
459
|
+
except Exception:
|
|
460
|
+
pass
|
|
461
|
+
except Exception:
|
|
462
|
+
pass
|
|
463
|
+
|
|
464
|
+
# Let the main app know the search space changed so it can sync to session
|
|
465
|
+
if hasattr(self.master, '_sync_data_to_session'):
|
|
466
|
+
try:
|
|
467
|
+
self.master._sync_data_to_session()
|
|
468
|
+
except Exception:
|
|
469
|
+
pass
|
|
470
|
+
|
|
471
|
+
if hasattr(self.master, '_update_ui_state'):
|
|
472
|
+
try:
|
|
473
|
+
self.master._update_ui_state()
|
|
474
|
+
except Exception:
|
|
475
|
+
pass
|
|
476
|
+
|
|
431
477
|
if hasattr(self.master, 'update_variables_display'):
|
|
432
478
|
self.master.update_variables_display()
|
|
433
479
|
elif hasattr(self.master, 'var_sheet'):
|
|
@@ -469,8 +515,7 @@ class SpaceSetupWindow(ctk.CTkToplevel):
|
|
|
469
515
|
self.master.load_exp_button.configure(state='normal')
|
|
470
516
|
if hasattr(self.master, 'gen_template_button'):
|
|
471
517
|
self.master.gen_template_button.configure(state='normal')
|
|
472
|
-
|
|
473
|
-
self.master.cluster_switch.configure(state='normal')
|
|
518
|
+
# Clustering UI removed; no cluster_switch configuration needed
|
|
474
519
|
|
|
475
520
|
except Exception as e:
|
|
476
521
|
print(f"Error updating main UI variables: {e}")
|
ui/visualizations.py
CHANGED
|
@@ -93,11 +93,53 @@ class Visualizations:
|
|
|
93
93
|
def initialize_figure(self):
|
|
94
94
|
"""Initialize the Matplotlib figure and axes."""
|
|
95
95
|
if self.fig is None or self.ax is None:
|
|
96
|
-
|
|
96
|
+
# Use current rcParam DPI when creating the figure so text sizes
|
|
97
|
+
# are consistent with the active window's DPI settings.
|
|
98
|
+
dpi = plt.rcParams.get('figure.dpi', 100)
|
|
99
|
+
self.fig, self.ax = plt.subplots(figsize=(6, 4), dpi=dpi)
|
|
97
100
|
|
|
98
101
|
def open_window(self):
|
|
99
102
|
"""Open the visualization window."""
|
|
100
|
-
|
|
103
|
+
# Probe DPI from the parent window (avoids creating a new Tk root).
|
|
104
|
+
try:
|
|
105
|
+
dpi = int(self.parent.winfo_fpixels('1i'))
|
|
106
|
+
except Exception:
|
|
107
|
+
dpi = plt.rcParams.get('figure.dpi', 100)
|
|
108
|
+
|
|
109
|
+
# Apply DPI to matplotlib runtime settings so text and markers scale correctly
|
|
110
|
+
plt.rcParams['figure.dpi'] = dpi
|
|
111
|
+
|
|
112
|
+
# Cap font sizes to avoid oversized rendering on HiDPI displays
|
|
113
|
+
try:
|
|
114
|
+
fs = plt.rcParams.get('font.size', 10)
|
|
115
|
+
if fs > 14:
|
|
116
|
+
plt.rcParams['font.size'] = 10
|
|
117
|
+
if plt.rcParams.get('xtick.labelsize', 10) > 12:
|
|
118
|
+
plt.rcParams['xtick.labelsize'] = 8
|
|
119
|
+
if plt.rcParams.get('ytick.labelsize', 10) > 12:
|
|
120
|
+
plt.rcParams['ytick.labelsize'] = 8
|
|
121
|
+
except Exception:
|
|
122
|
+
pass
|
|
123
|
+
|
|
124
|
+
self.initialize_figure() # Ensure the figure is initialized with corrected DPI
|
|
125
|
+
# Enforce additional rcParams to keep the figure compact and fonts reasonable
|
|
126
|
+
try:
|
|
127
|
+
plt.rcParams['axes.titlesize'] = min(12, plt.rcParams.get('axes.titlesize', 12))
|
|
128
|
+
plt.rcParams['axes.labelsize'] = min(10, plt.rcParams.get('axes.labelsize', 10))
|
|
129
|
+
plt.rcParams['legend.fontsize'] = min(9, plt.rcParams.get('legend.fontsize', 9))
|
|
130
|
+
plt.rcParams['xtick.labelsize'] = min(9, plt.rcParams.get('xtick.labelsize', 9))
|
|
131
|
+
plt.rcParams['ytick.labelsize'] = min(9, plt.rcParams.get('ytick.labelsize', 9))
|
|
132
|
+
plt.rcParams['lines.markersize'] = min(6, plt.rcParams.get('lines.markersize', 6))
|
|
133
|
+
except Exception:
|
|
134
|
+
pass
|
|
135
|
+
|
|
136
|
+
# Ensure the figure uses a compact size (in inches) and the detected DPI.
|
|
137
|
+
try:
|
|
138
|
+
# Prefer a slightly smaller figure to avoid huge white margins
|
|
139
|
+
self.fig.set_size_inches(5, 4, forward=True)
|
|
140
|
+
self.fig.set_dpi(dpi)
|
|
141
|
+
except Exception:
|
|
142
|
+
pass
|
|
101
143
|
|
|
102
144
|
if self.search_space is None:
|
|
103
145
|
print("Error: Search space is not defined.")
|
|
@@ -122,6 +164,15 @@ class Visualizations:
|
|
|
122
164
|
visualization_window.focus_force()
|
|
123
165
|
visualization_window.grab_set()
|
|
124
166
|
|
|
167
|
+
# Fix macOS Retina scaling by probing the new window's DPI and applying it
|
|
168
|
+
try:
|
|
169
|
+
dpi = int(visualization_window.winfo_fpixels('1i'))
|
|
170
|
+
except Exception:
|
|
171
|
+
dpi = plt.rcParams.get('figure.dpi', 100)
|
|
172
|
+
|
|
173
|
+
# Apply DPI to matplotlib runtime settings so text and markers scale correctly
|
|
174
|
+
plt.rcParams['figure.dpi'] = dpi
|
|
175
|
+
|
|
125
176
|
# Top control frame for other visualizations (metrics, parity, hyperparameters)
|
|
126
177
|
# Use two rows to avoid crowding
|
|
127
178
|
control_container = ctk.CTkFrame(visualization_window)
|
|
@@ -191,8 +242,14 @@ class Visualizations:
|
|
|
191
242
|
self.plot_frame = ctk.CTkFrame(main_container, height=450)
|
|
192
243
|
self.plot_frame.pack(side="left", fill='both', expand=True, padx=5, pady=5)
|
|
193
244
|
self.canvas = FigureCanvasTkAgg(self.fig, master=self.plot_frame)
|
|
245
|
+
# Draw and tighten layout before packing to reduce excess margins
|
|
246
|
+
try:
|
|
247
|
+
self.fig.tight_layout(pad=0.6)
|
|
248
|
+
except Exception:
|
|
249
|
+
pass
|
|
194
250
|
self.canvas.draw()
|
|
195
|
-
|
|
251
|
+
# Use smaller padding so the canvas doesn't create excess whitespace
|
|
252
|
+
self.canvas.get_tk_widget().pack(fill='both', expand=True, padx=2, pady=2)
|
|
196
253
|
self.metrics_toolbar = NavigationToolbar2Tk(self.canvas, self.plot_frame)
|
|
197
254
|
self.metrics_toolbar.config(background='#2E2E2E')
|
|
198
255
|
self.metrics_toolbar._message_label.config(background='#2E2E2E')
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
main.py,sha256=3sAO2QZxxibs4WRT82i2w6KVBBFmYEMNUoGiMYFowOw,126
|
|
2
|
-
alchemist_core/__init__.py,sha256=YA4a1INzAl6iuumPEXGGrorX9weogVN20b-w-UbB9bY,1813
|
|
3
|
-
alchemist_core/config.py,sha256=Sk5eM1okktO5bUMlMPv9yzF2fpuiyGr9LUtlCWIBDc8,3366
|
|
4
|
-
alchemist_core/events.py,sha256=ty9nRzfZGHzk6b09dALIwrMY_5PYSv0wMaw94JLDjSk,6717
|
|
5
|
-
alchemist_core/session.py,sha256=bZTpa5vatg3w4zSg6qaXDQbpV-WrGwaRqD_sNc4Qas8,23889
|
|
6
|
-
alchemist_core/acquisition/__init__.py,sha256=3CYGI24OTBS66ETrlGFyHCNpfS6DBMP41MZDhvjFEzg,32
|
|
7
|
-
alchemist_core/acquisition/base_acquisition.py,sha256=s51vGx0b0Nt91lSCiVwYP9IClugVg2VJ21dn2n_4LIs,483
|
|
8
|
-
alchemist_core/acquisition/botorch_acquisition.py,sha256=9ofyetj6gyBzO_3y8Y50EfCxP6BiHKYXTGIHT3fx6eY,30947
|
|
9
|
-
alchemist_core/acquisition/skopt_acquisition.py,sha256=YRdANqgiN3GWd4sn16oruN6jVnI4RLmvLhBMUfYyLp4,13115
|
|
10
|
-
alchemist_core/data/__init__.py,sha256=wgEb03x0RzVCi0uJXOzEKXkbA2oNHom5EgSB3tKgl1E,256
|
|
11
|
-
alchemist_core/data/experiment_manager.py,sha256=kS63mVmuTNxhI3A9io52VKGcZOcgcTIyJqrzUQuZgkw,5910
|
|
12
|
-
alchemist_core/data/search_space.py,sha256=oA9YEF3JRWpRklHzSo_Uxlmfy7bHwZfLZFDf4_nl4ew,6230
|
|
13
|
-
alchemist_core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
alchemist_core/models/ax_model.py,sha256=Fnu19Et376WxLXpApZSalIbWHQE9OQnMk41_PW69XnQ,6040
|
|
15
|
-
alchemist_core/models/base_model.py,sha256=gIpC2eoTZcp4ozI0Rctcxt_4bLhgaE6ALYCzvuIrMZw,3145
|
|
16
|
-
alchemist_core/models/botorch_model.py,sha256=t-zqLRpCIGwSeIyveqJTjr8MQ9zWecnJIueaWg3Geck,42026
|
|
17
|
-
alchemist_core/models/sklearn_model.py,sha256=ID0anz8BNGKDMpQlLlzKuyey1CvaJQkf0C79Q_S3tGo,34735
|
|
18
|
-
alchemist_core/utils/__init__.py,sha256=oQsvUqukRng8GgiZSPMM-xmB-Lv46XveJzYQr2MdkOc,99
|
|
19
|
-
alchemist_nrel-0.2.1.dist-info/licenses/LICENSE,sha256=wdIWWEj59ztfQViDuT_9wG3L1K8afUpRSygimXw36wY,1511
|
|
20
|
-
api/__init__.py,sha256=ODc6pq4OSImgK4xvhX_zMhqUjIc7JvLfqxKF_-Ubw7g,49
|
|
21
|
-
api/dependencies.py,sha256=sF1YYjnFRaw7nj7Y7URKLF2Ek-EfaXqjOyV1Zbktz2g,1090
|
|
22
|
-
api/example_client.py,sha256=aZMNuJmt00hpNEkijn5RnVEV7ZPfKzwQxucSasTrrdw,6645
|
|
23
|
-
api/main.py,sha256=Y2oPwxPK_jfOMNkT9qLQnM6lNzaM9sdJhOybJVFf8UM,3403
|
|
24
|
-
api/middleware/__init__.py,sha256=WM4JEg3DibymvEvQ6hx_FJkv8lKLjHD48qNouSORGxA,313
|
|
25
|
-
api/middleware/error_handlers.py,sha256=k5hNo6W5QDjGRHUY8Le-t7ubWkwSZBFpsTKcEF0nweI,4545
|
|
26
|
-
api/models/__init__.py,sha256=YFtp8989mH9Zjzvd8W6pXklQJXTf8zWj4I2YWnLegDQ,1204
|
|
27
|
-
api/models/requests.py,sha256=wy8KCgf3cwJ2Yz2wEzQjCqkUT6x0VHQHFTQDVMfbUMU,7213
|
|
28
|
-
api/models/responses.py,sha256=c_okZVP0A8MF7aH199Bl6zjoJgede9lBrH5i8R8oPXc,8445
|
|
29
|
-
api/routers/__init__.py,sha256=Mhg62NdA6iaPy-L5HLVp_dd9aUHmJ72KtMSRyO2kusA,180
|
|
30
|
-
api/routers/acquisition.py,sha256=7c9ifuCFeDj8osWRHgCjAwbXjhd3iEBlVLW23FOAZXI,5710
|
|
31
|
-
api/routers/experiments.py,sha256=q7Y1y5-pIIu0hRZAQKTpllL3AGstjbCP-dUqYAnQ-hI,4946
|
|
32
|
-
api/routers/models.py,sha256=32Ln0MtlnCEjfN3Q6Io_EBwwwGoJXb73UbQEMIcVGjI,3651
|
|
33
|
-
api/routers/sessions.py,sha256=k4gJe8qgb-8INT04_buYAfZIfMGBxfOOxn5tcXfr6LI,4523
|
|
34
|
-
api/routers/variables.py,sha256=TiByX1ITabBDdTSMGAPa1lGd0LBipNgDfmPsbvTEAdE,10108
|
|
35
|
-
api/routers/visualizations.py,sha256=qP__NhhflNKEAEcLV0c_WMQvofoNWSORMXbEMQCuVgI,23783
|
|
36
|
-
api/services/__init__.py,sha256=0jw0tkL-8CtChv5ytdXRFeIz1OTVz7Vw1UaaDo86PQs,106
|
|
37
|
-
api/services/session_store.py,sha256=Jot2S75Qrqaw_dbfNbeJt5rwlu25abexP4BMMCIgfdE,9605
|
|
38
|
-
ui/__init__.py,sha256=H4kWlVey7KKf3iPQi74zuM7FSOg5Gh-ii3UwSTuIp8A,1203
|
|
39
|
-
ui/acquisition_panel.py,sha256=zF-mQDrs-Y7sf2GXYF-bPlO9UXZMTzYRMDN-Wn5FyWw,39647
|
|
40
|
-
ui/custom_widgets.py,sha256=UXNv4DiTw3tFC0VaN1Qtcf_-9umX34uDn46-cEA6cs0,3812
|
|
41
|
-
ui/experiment_logger.py,sha256=dP3IGaQ31sURyz7awd_VrZBWaKLH2xXEeRalWZpvVcQ,8366
|
|
42
|
-
ui/gpr_panel.py,sha256=cXZbYndkZ7E6GowkorYqBHVStpxEKDVJv8S-ZPzGGRQ,26230
|
|
43
|
-
ui/notifications.py,sha256=evVd9r7OMqaZyx2WWXFnL-moIjrDFmRoMKrX9hvKB_g,28003
|
|
44
|
-
ui/pool_viz.py,sha256=RwjggEfRSSEe-4nGjxc-I-1e5_aH64DgypT_YoubLIU,8765
|
|
45
|
-
ui/ui.py,sha256=tJZoiBRACjY07NPrDdqYJc8we1Ze4fqnxJVUCHVkFZ8,54945
|
|
46
|
-
ui/ui_utils.py,sha256=yud2-9LvT4XBcjTyfwUX5tYGNZRlAUVlu2YpcNY1HKA,658
|
|
47
|
-
ui/utils.py,sha256=m19YFFkEUAY46YSj6S5RBmfUFjIWOk7F8CB4oKDRRZw,1078
|
|
48
|
-
ui/variables_setup.py,sha256=4pu91MNRZlsK-DwRNd7U619wKDdSknI5Cf744o5Lxqo,21673
|
|
49
|
-
ui/visualizations.py,sha256=X3Arl1k2UoQK2DCQ8YBnoJ4fscvinAlPJ1hInYkKvGo,67686
|
|
50
|
-
alchemist_nrel-0.2.1.dist-info/METADATA,sha256=AAMdcL8KyjGcyjH9Ci2pqJOLenJSZ29b_CDigeK99Ak,6892
|
|
51
|
-
alchemist_nrel-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
52
|
-
alchemist_nrel-0.2.1.dist-info/entry_points.txt,sha256=zTuR1EjHMjeeAtUOACu0njiTCBMoaCobFqLlQ7IPYs8,40
|
|
53
|
-
alchemist_nrel-0.2.1.dist-info/top_level.txt,sha256=dwh-oxj7H6oAGYchcUDyfiu9UxxzCn4hUDx1oeM2k-8,27
|
|
54
|
-
alchemist_nrel-0.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|