ivoryos 1.4.0__tar.gz → 1.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ivoryos might be problematic. Click here for more details.

Files changed (112) hide show
  1. {ivoryos-1.4.0 → ivoryos-1.4.1}/PKG-INFO +5 -4
  2. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/optimizer/ax_optimizer.py +3 -0
  3. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/optimizer/base_optimizer.py +4 -0
  4. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/optimizer/baybe_optimizer.py +3 -0
  5. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/optimizer/nimo_optimizer.py +9 -0
  6. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/execute.py +49 -20
  7. ivoryos-1.4.1/ivoryos/routes/execute/templates/components/logging_panel.html +56 -0
  8. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/form.py +10 -7
  9. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/script_runner.py +5 -4
  10. ivoryos-1.4.1/ivoryos/version.py +1 -0
  11. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos.egg-info/PKG-INFO +5 -4
  12. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos.egg-info/requires.txt +5 -4
  13. {ivoryos-1.4.0 → ivoryos-1.4.1}/pyproject.toml +3 -2
  14. ivoryos-1.4.0/ivoryos/routes/execute/templates/components/logging_panel.html +0 -31
  15. ivoryos-1.4.0/ivoryos/version.py +0 -1
  16. {ivoryos-1.4.0 → ivoryos-1.4.1}/LICENSE +0 -0
  17. {ivoryos-1.4.0 → ivoryos-1.4.1}/README.md +0 -0
  18. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/__init__.py +0 -0
  19. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/app.py +0 -0
  20. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/config.py +0 -0
  21. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/optimizer/registry.py +0 -0
  22. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/__init__.py +0 -0
  23. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/api/api.py +0 -0
  24. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/auth/__init__.py +0 -0
  25. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/auth/auth.py +0 -0
  26. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/auth/templates/login.html +0 -0
  27. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/auth/templates/signup.html +0 -0
  28. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/control/__init__.py +0 -0
  29. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/control/control.py +0 -0
  30. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/control/control_file.py +0 -0
  31. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/control/control_new_device.py +0 -0
  32. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/control/templates/controllers.html +0 -0
  33. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/control/templates/controllers_new.html +0 -0
  34. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/control/utils.py +0 -0
  35. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/data/__init__.py +0 -0
  36. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/data/data.py +0 -0
  37. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/data/templates/components/step_card.html +0 -0
  38. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/data/templates/workflow_database.html +0 -0
  39. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/data/templates/workflow_view.html +0 -0
  40. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/__init__.py +0 -0
  41. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/design.py +0 -0
  42. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/design_file.py +0 -0
  43. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/design_step.py +0 -0
  44. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/action_form.html +0 -0
  45. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/actions_panel.html +0 -0
  46. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/autofill_toggle.html +0 -0
  47. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/canvas.html +0 -0
  48. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/canvas_footer.html +0 -0
  49. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/canvas_header.html +0 -0
  50. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/canvas_main.html +0 -0
  51. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/deck_selector.html +0 -0
  52. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/edit_action_form.html +0 -0
  53. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/instruments_panel.html +0 -0
  54. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/modals/drop_modal.html +0 -0
  55. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/modals/json_modal.html +0 -0
  56. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/modals/new_script_modal.html +0 -0
  57. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/modals/rename_modal.html +0 -0
  58. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/modals/saveas_modal.html +0 -0
  59. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/modals.html +0 -0
  60. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/python_code_overlay.html +0 -0
  61. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/sidebar.html +0 -0
  62. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/components/text_to_code_panel.html +0 -0
  63. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/design/templates/experiment_builder.html +0 -0
  64. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/__init__.py +0 -0
  65. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/execute_file.py +0 -0
  66. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/templates/components/error_modal.html +0 -0
  67. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/templates/components/progress_panel.html +0 -0
  68. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/templates/components/run_panel.html +0 -0
  69. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/templates/components/run_tabs.html +0 -0
  70. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/templates/components/tab_bayesian.html +0 -0
  71. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/templates/components/tab_configuration.html +0 -0
  72. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/templates/components/tab_repeat.html +0 -0
  73. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/execute/templates/experiment_run.html +0 -0
  74. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/library/__init__.py +0 -0
  75. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/library/library.py +0 -0
  76. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/library/templates/library.html +0 -0
  77. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/main/__init__.py +0 -0
  78. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/main/main.py +0 -0
  79. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/main/templates/help.html +0 -0
  80. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/routes/main/templates/home.html +0 -0
  81. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/server.py +0 -0
  82. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/socket_handlers.py +0 -0
  83. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/favicon.ico +0 -0
  84. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/gui_annotation/Slide1.png +0 -0
  85. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/gui_annotation/Slide2.PNG +0 -0
  86. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/js/action_handlers.js +0 -0
  87. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/js/db_delete.js +0 -0
  88. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/js/overlay.js +0 -0
  89. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/js/script_metadata.js +0 -0
  90. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/js/socket_handler.js +0 -0
  91. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/js/sortable_card.js +0 -0
  92. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/js/sortable_design.js +0 -0
  93. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/js/ui_state.js +0 -0
  94. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/logo.webp +0 -0
  95. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/static/style.css +0 -0
  96. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/templates/base.html +0 -0
  97. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/__init__.py +0 -0
  98. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/bo_campaign.py +0 -0
  99. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/client_proxy.py +0 -0
  100. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/db_models.py +0 -0
  101. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/decorators.py +0 -0
  102. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/global_config.py +0 -0
  103. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/llm_agent.py +0 -0
  104. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/nest_script.py +0 -0
  105. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/py_to_json.py +0 -0
  106. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/serilize.py +0 -0
  107. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/task_runner.py +0 -0
  108. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos/utils/utils.py +0 -0
  109. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos.egg-info/SOURCES.txt +0 -0
  110. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos.egg-info/dependency_links.txt +0 -0
  111. {ivoryos-1.4.0 → ivoryos-1.4.1}/ivoryos.egg-info/top_level.txt +0 -0
  112. {ivoryos-1.4.0 → ivoryos-1.4.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ivoryos
3
- Version: 1.4.0
3
+ Version: 1.4.1
4
4
  Summary: an open-source Python package enabling Self-Driving Labs (SDLs) interoperability
5
5
  Author-email: Ivory Zhang <ivoryzhang@chem.ubc.ca>
6
6
  License: MIT
@@ -25,9 +25,10 @@ Provides-Extra: optimizer-baybe
25
25
  Requires-Dist: baybe; extra == "optimizer-baybe"
26
26
  Provides-Extra: optimizer-nimo
27
27
  Requires-Dist: nimo; extra == "optimizer-nimo"
28
- Provides-Extra: optimizer
29
- Requires-Dist: ax-platform>=1.1.2; extra == "optimizer"
30
- Requires-Dist: baybe>=0.14.0; extra == "optimizer"
28
+ Provides-Extra: optimizers
29
+ Requires-Dist: ax-platform>=1.1.2; extra == "optimizers"
30
+ Requires-Dist: baybe>=0.14.0; extra == "optimizers"
31
+ Requires-Dist: nimo; extra == "optimizers"
31
32
  Provides-Extra: doc
32
33
  Requires-Dist: sphinx; extra == "doc"
33
34
  Requires-Dist: sphinx-rtd-theme; extra == "doc"
@@ -126,6 +126,9 @@ class AxOptimizer(OptimizerBase):
126
126
  raw_data=obj_only_result
127
127
  )
128
128
 
129
+ def get_plots(self, plot_type):
130
+ return None
131
+
129
132
  @staticmethod
130
133
  def get_schema():
131
134
  return {
@@ -48,6 +48,10 @@ class OptimizerBase(ABC):
48
48
  def append_existing_data(self, existing_data):
49
49
  pass
50
50
 
51
+ @abstractmethod
52
+ def get_plots(self, plot_type):
53
+ pass
54
+
51
55
  @staticmethod
52
56
  def _create_discrete_search_space(range_with_step=None, value_type ="float"):
53
57
  if range_with_step is None:
@@ -153,6 +153,9 @@ class BaybeOptimizer(OptimizerBase):
153
153
  recommender=step_2_recommender
154
154
  )
155
155
 
156
+ def get_plots(self, plot_type):
157
+ return None
158
+
156
159
  @staticmethod
157
160
  def get_schema():
158
161
  """
@@ -1,4 +1,5 @@
1
1
  ### ivoryos/optimizers/nimo_optimizer.py
2
+ import glob
2
3
  import itertools
3
4
  import os
4
5
 
@@ -122,6 +123,14 @@ class NIMOOptimizer(OptimizerBase):
122
123
  # TODO, history is part of the candidate file, we probably won't need this
123
124
  pass
124
125
 
126
+ def get_plots(self, plot_type):
127
+ import nimo
128
+ nimo.visualization.plot_phase_diagram.plot(input_file=self.candidates,
129
+ fig_folder=os.path.join(self.datapath, "nimo_data"))
130
+ files = sorted(glob.glob(os.path.join(os.path.join(self.datapath, "nimo_data"), "phase_diagram_*.png")))
131
+ if not files:
132
+ return None
133
+ return files[-1]
125
134
 
126
135
  @staticmethod
127
136
  def get_schema():
@@ -3,7 +3,7 @@ import os
3
3
  import time
4
4
 
5
5
  from flask import Blueprint, redirect, url_for, flash, jsonify, request, render_template, session, \
6
- current_app, g
6
+ current_app, g, send_file
7
7
  from flask_login import login_required
8
8
 
9
9
  from ivoryos.routes.execute.execute_file import files
@@ -185,26 +185,39 @@ def run_bo():
185
185
  """
186
186
  script = utils.get_script_file()
187
187
  run_name = script.name if script.name else "untitled"
188
- payload = request.form.to_dict()
189
- repeat = payload.pop("repeat", None)
190
- optimizer_type = payload.pop("optimizer_type", None)
191
- existing_data = payload.pop("existing_data", None)
192
- batch_mode = payload.pop("batch_mode", None)
193
- batch_size = payload.pop("batch_size", 1)
194
-
195
- # Get constraint expressions (new single-line input)
196
- constraint_exprs = request.form.getlist("constraint_expr")
197
- constraints = [expr.strip() for expr in constraint_exprs if expr.strip()]
198
-
199
- # Remove constraint_expr entries from payload before parsing parameters
200
- for key in list(payload.keys()):
201
- if key.startswith("constraint_expr"):
202
- payload.pop(key, None)
203
-
204
- parameters, objectives, steps = parse_optimization_form(payload)
205
- try:
188
+
189
+ if request.accept_mimetypes.best_match(['application/json', 'text/html']) == 'application/json':
190
+ payload_json = request.get_json()
191
+ objectives = payload_json.pop("objectives", None)
192
+ parameters = payload_json.pop("parameters", None)
193
+ steps = payload_json.pop("steps", None)
194
+ constraints = payload_json.pop("parameter_constraints", None)
195
+ repeat = payload_json.pop("repeat", None)
196
+ batch_size = payload_json.pop("batch_size", None)
197
+ optimizer_type = payload_json.pop("optimizer_type", None)
198
+ existing_data = payload_json.pop("existing_data", None)
199
+
200
+ else:
201
+ payload = request.form.to_dict()
202
+ repeat = payload.pop("repeat", None)
203
+ optimizer_type = payload.pop("optimizer_type", None)
204
+ existing_data = payload.pop("existing_data", None)
205
+ batch_mode = payload.pop("batch_mode", None)
206
+ batch_size = payload.pop("batch_size", 1)
207
+
208
+ # Get constraint expressions (new single-line input)
209
+ constraint_exprs = request.form.getlist("constraint_expr")
210
+ constraints = [expr.strip() for expr in constraint_exprs if expr.strip()]
211
+
212
+ # Remove constraint_expr entries from payload before parsing parameters
213
+ for key in list(payload.keys()):
214
+ if key.startswith("constraint_expr"):
215
+ payload.pop(key, None)
216
+
217
+ parameters, objectives, steps = parse_optimization_form(payload)
206
218
 
207
219
  # if True:
220
+ try:
208
221
  datapath = current_app.config["DATA_FOLDER"]
209
222
  run_name = script.validate_function_name(run_name)
210
223
  Optimizer = global_config.optimizers.get(optimizer_type, None)
@@ -213,10 +226,11 @@ def run_bo():
213
226
  optimizer = Optimizer(experiment_name=run_name, parameter_space=parameters, objective_config=objectives,
214
227
  parameter_constraints = constraints,
215
228
  optimizer_config=steps, datapath=datapath)
229
+ current_app.config["LAST_OPTIMIZER"] = optimizer
216
230
  runner.run_script(script=script, run_name=run_name, optimizer=optimizer,
217
231
  logger=g.logger, socketio=g.socketio, repeat_count=repeat,
218
232
  output_path=datapath, compiled=False, history=existing_data,
219
- current_app=current_app._get_current_object(), batch_mode=batch_mode, batch_size=int(batch_size),
233
+ current_app=current_app._get_current_object(), batch_size=int(batch_size),
220
234
  objectives=objectives
221
235
  )
222
236
 
@@ -227,6 +241,21 @@ def run_bo():
227
241
  flash(e.__str__())
228
242
  return redirect(url_for("execute.experiment_run"))
229
243
 
244
+ @execute.route("/executions/latest_plot")
245
+ @login_required
246
+ def get_optimizer_plot():
247
+
248
+ optimizer = current_app.config.get("LAST_OPTIMIZER")
249
+ if optimizer is not None:
250
+ # the placeholder is for showing different plots
251
+ latest_file = optimizer.get_plots('placeholder')
252
+ # print(latest_file)
253
+ if files:
254
+ return send_file(latest_file, mimetype="image/png")
255
+ # print("No plots found")
256
+ return jsonify({"error": "No plots found"}), 404
257
+
258
+
230
259
 
231
260
 
232
261
  @execute.route("/executions/status", methods=["GET"])
@@ -0,0 +1,56 @@
1
+ {# Logging panel component for experiment run #}
2
+ <div class="col-lg-6 col-sm-12 logging-panel">
3
+ <div class="d-flex justify-content-between align-items-center">
4
+ <h5>Progress:</h5>
5
+ <div class="d-flex gap-2 ms-auto">
6
+ <button id="pause-resume" class="btn btn-info text-white">
7
+ {% if pause_status %}
8
+ <i class="bi bi-play-circle"></i>
9
+ {% else %}
10
+ <i class="bi bi-pause-circle"></i>
11
+ {% endif %}
12
+ </button>
13
+ <button id="abort-current" class="btn btn-danger text-white">
14
+ <i class="bi bi-stop-circle"></i>
15
+ </button>
16
+ <button id="abort-pending" class="btn btn-warning text-white">
17
+ <i class="bi bi-hourglass-split"></i>
18
+ </button>
19
+ </div>
20
+ </div>
21
+ <small class="text-muted mt-2">
22
+ <strong>Note:</strong> The current step cannot be paused or stopped until it completes.
23
+ </small>
24
+ <div class="progress my-3">
25
+ <div id="progress-bar-inner" class="progress-bar progress-bar-striped progress-bar-animated"></div>
26
+ </div>
27
+ <!-- Tabs -->
28
+ <ul class="nav nav-tabs" id="logPlotTabs" role="tablist">
29
+ <li class="nav-item" role="presentation">
30
+ <button class="nav-link active" id="log-tab" data-bs-toggle="tab" data-bs-target="#log" type="button" role="tab">Log</button>
31
+ </li>
32
+ <li class="nav-item" role="presentation">
33
+ <button class="nav-link" id="plot-tab" data-bs-toggle="tab" data-bs-target="#plot" type="button" role="tab">Optimizer Plot</button>
34
+ </li>
35
+ </ul>
36
+ <div class="tab-content mt-3" id="logPlotTabsContent">
37
+ <div class="tab-pane fade show active" id="log" role="tabpanel">
38
+ <div id="logging-panel" class="border p-2 bg-light" style="max-height: 400px; overflow-y: auto;"></div>
39
+ </div>
40
+ <div class="tab-pane fade" id="plot" role="tabpanel">
41
+ <button class="btn btn-success mb-2" onclick="showPlot()">Refresh Plot</button>
42
+ <small class="text-muted d-block mt-1" id="plot-info">This function is only available for NIMO optimizers.</small>
43
+ <br>
44
+ <img id="optimizerPlot" src="" class="img-fluid rounded shadow-sm d-block mx-auto" style="max-width:100%; display:none;">
45
+ </div>
46
+
47
+ </div>
48
+
49
+ </div>
50
+ <script>
51
+ function showPlot() {
52
+ const img = document.getElementById('optimizerPlot');
53
+ img.src = "{{ url_for('execute.get_optimizer_plot') }}";
54
+ img.style.display = 'block';
55
+ }
56
+ </script>
@@ -350,13 +350,16 @@ def create_form_from_module(sdl_module, autofill: bool = False, script=None, des
350
350
  """
351
351
  method_forms = {}
352
352
  for attr_name in dir(sdl_module):
353
- method = getattr(sdl_module, attr_name)
354
- if inspect.ismethod(method) and not attr_name.startswith('_'):
355
- signature = inspect.signature(method)
356
- docstring = inspect.getdoc(method)
357
- attr = dict(signature=signature, docstring=docstring)
358
- form_class = create_add_form(attr, attr_name, autofill, script, design)
359
- method_forms[attr_name] = form_class()
353
+ try:
354
+ method = getattr(sdl_module, attr_name)
355
+ if inspect.ismethod(method) and not attr_name.startswith('_'):
356
+ signature = inspect.signature(method)
357
+ docstring = inspect.getdoc(method)
358
+ attr = dict(signature=signature, docstring=docstring)
359
+ form_class = create_add_form(attr, attr_name, autofill, script, design)
360
+ method_forms[attr_name] = form_class()
361
+ except Exception as e:
362
+ print(f"Error creating form for {attr_name}: {e}")
360
363
  return method_forms
361
364
 
362
365
 
@@ -534,12 +534,12 @@ class ScriptRunner:
534
534
 
535
535
  async def _execute_repeat_batched(self, step: Dict, contexts: List[Dict[str, Any]], phase_id, step_index, section_name):
536
536
  """Execute repeat block for multiple samples."""
537
- times = step["args"].get("times", 1)
537
+ times = step["args"].get("statement", 1)
538
538
 
539
539
  for i in range(times):
540
540
  # Add repeat index to all contexts
541
- for context in contexts:
542
- context["repeat_index"] = i
541
+ # for context in contexts:
542
+ # context["repeat_index"] = i
543
543
 
544
544
  await self._execute_steps_batched(step["repeat_block"], contexts, phase_id=phase_id, step_index=step_index, section_name=section_name)
545
545
 
@@ -594,7 +594,8 @@ class ScriptRunner:
594
594
  db.session.add(step_db)
595
595
  db.session.flush()
596
596
  try:
597
- self.socketio.emit('execution', {'section': f"{section_name}-{step_index}"})
597
+ # print(f"step {section_name}-{step_index}")
598
+ self.socketio.emit('execution', {'section': f"{section_name}-{step_index-1}"})
598
599
  if action == "wait":
599
600
  duration = float(substituted_args["statement"])
600
601
  self.safe_sleep(duration)
@@ -0,0 +1 @@
1
+ __version__ = "1.4.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ivoryos
3
- Version: 1.4.0
3
+ Version: 1.4.1
4
4
  Summary: an open-source Python package enabling Self-Driving Labs (SDLs) interoperability
5
5
  Author-email: Ivory Zhang <ivoryzhang@chem.ubc.ca>
6
6
  License: MIT
@@ -25,9 +25,10 @@ Provides-Extra: optimizer-baybe
25
25
  Requires-Dist: baybe; extra == "optimizer-baybe"
26
26
  Provides-Extra: optimizer-nimo
27
27
  Requires-Dist: nimo; extra == "optimizer-nimo"
28
- Provides-Extra: optimizer
29
- Requires-Dist: ax-platform>=1.1.2; extra == "optimizer"
30
- Requires-Dist: baybe>=0.14.0; extra == "optimizer"
28
+ Provides-Extra: optimizers
29
+ Requires-Dist: ax-platform>=1.1.2; extra == "optimizers"
30
+ Requires-Dist: baybe>=0.14.0; extra == "optimizers"
31
+ Requires-Dist: nimo; extra == "optimizers"
31
32
  Provides-Extra: doc
32
33
  Requires-Dist: sphinx; extra == "doc"
33
34
  Requires-Dist: sphinx-rtd-theme; extra == "doc"
@@ -20,10 +20,6 @@ sphinx
20
20
  sphinx-rtd-theme
21
21
  sphinxcontrib-httpdomain
22
22
 
23
- [optimizer]
24
- ax-platform>=1.1.2
25
- baybe>=0.14.0
26
-
27
23
  [optimizer-ax]
28
24
  ax-platform
29
25
 
@@ -32,3 +28,8 @@ baybe
32
28
 
33
29
  [optimizer-nimo]
34
30
  nimo
31
+
32
+ [optimizers]
33
+ ax-platform>=1.1.2
34
+ baybe>=0.14.0
35
+ nimo
@@ -30,9 +30,10 @@ dependencies = [
30
30
  optimizer-ax = ["ax-platform"]
31
31
  optimizer-baybe = ["baybe"]
32
32
  optimizer-nimo = ["nimo"]
33
- optimizer = [
33
+ optimizers = [
34
34
  "ax-platform>=1.1.2",
35
- "baybe>=0.14.0"
35
+ "baybe>=0.14.0",
36
+ "nimo"
36
37
  ]
37
38
  doc = [
38
39
  "sphinx",
@@ -1,31 +0,0 @@
1
- {# Logging panel component for experiment run #}
2
- <div class="col-lg-6 col-sm-12 logging-panel">
3
- <p>
4
- <div class="p d-flex justify-content-between align-items-center">
5
- <h5>Progress:</h5>
6
- <div class="d-flex gap-2 ms-auto">
7
- <button id="pause-resume" class="btn btn-info text-white" data-bs-toggle="tooltip" title="Pause execution">
8
- {% if pause_status %}
9
- <i class="bi bi-play-circle"></i>
10
- {% else %}
11
- <i class="bi bi-pause-circle"></i>
12
- {% endif %}
13
- </button>
14
- <button id="abort-current" class="btn btn-danger text-white" data-bs-toggle="tooltip" title="Stop execution after current step">
15
- <i class="bi bi-stop-circle"></i>
16
- </button>
17
- <button id="abort-pending" class="btn btn-warning text-white" data-bs-toggle="tooltip" title="Stop execution after current iteration">
18
- <i class="bi bi-hourglass-split"></i>
19
- </button>
20
- </div>
21
- </div>
22
- <div class="text-muted mt-2">
23
- <small><strong>Note:</strong> The current step cannot be paused or stopped until it completes. </small>
24
- </div>
25
-
26
- <div class="progress" role="progressbar" aria-label="Animated striped example" aria-valuenow="10" aria-valuemin="0" aria-valuemax="100">
27
- <div id="progress-bar-inner" class="progress-bar progress-bar-striped progress-bar-animated"></div>
28
- </div>
29
- <p><h5>Log:</h5></p>
30
- <div id="logging-panel"></div>
31
- </div>
@@ -1 +0,0 @@
1
- __version__ = "1.4.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes