ivoryos 1.3.5__tar.gz → 1.3.6__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 (109) hide show
  1. {ivoryos-1.3.5 → ivoryos-1.3.6}/PKG-INFO +5 -2
  2. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/optimizer/ax_optimizer.py +3 -3
  3. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/optimizer/base_optimizer.py +2 -1
  4. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/optimizer/registry.py +3 -1
  5. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/design.py +7 -1
  6. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/design_step.py +7 -3
  7. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/edit_action_form.html +2 -0
  8. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/server.py +5 -1
  9. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/js/action_handlers.js +28 -11
  10. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/bo_campaign.py +1 -1
  11. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/db_models.py +14 -5
  12. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/form.py +8 -4
  13. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/script_runner.py +1 -1
  14. ivoryos-1.3.6/ivoryos/version.py +1 -0
  15. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos.egg-info/PKG-INFO +5 -2
  16. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos.egg-info/requires.txt +5 -1
  17. {ivoryos-1.3.5 → ivoryos-1.3.6}/pyproject.toml +3 -1
  18. ivoryos-1.3.5/ivoryos/version.py +0 -1
  19. {ivoryos-1.3.5 → ivoryos-1.3.6}/LICENSE +0 -0
  20. {ivoryos-1.3.5 → ivoryos-1.3.6}/README.md +0 -0
  21. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/__init__.py +0 -0
  22. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/app.py +0 -0
  23. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/config.py +0 -0
  24. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/optimizer/baybe_optimizer.py +0 -0
  25. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/__init__.py +0 -0
  26. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/api/api.py +0 -0
  27. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/auth/__init__.py +0 -0
  28. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/auth/auth.py +0 -0
  29. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/auth/templates/login.html +0 -0
  30. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/auth/templates/signup.html +0 -0
  31. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/control/__init__.py +0 -0
  32. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/control/control.py +0 -0
  33. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/control/control_file.py +0 -0
  34. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/control/control_new_device.py +0 -0
  35. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/control/templates/controllers.html +0 -0
  36. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/control/templates/controllers_new.html +0 -0
  37. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/control/utils.py +0 -0
  38. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/data/__init__.py +0 -0
  39. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/data/data.py +0 -0
  40. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/data/templates/components/step_card.html +0 -0
  41. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/data/templates/workflow_database.html +0 -0
  42. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/data/templates/workflow_view.html +0 -0
  43. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/__init__.py +0 -0
  44. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/design_file.py +0 -0
  45. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/action_form.html +0 -0
  46. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/actions_panel.html +0 -0
  47. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/autofill_toggle.html +0 -0
  48. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/canvas.html +0 -0
  49. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/canvas_footer.html +0 -0
  50. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/canvas_header.html +0 -0
  51. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/canvas_main.html +0 -0
  52. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/deck_selector.html +0 -0
  53. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/instruments_panel.html +0 -0
  54. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/modals/drop_modal.html +0 -0
  55. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/modals/json_modal.html +0 -0
  56. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/modals/new_script_modal.html +0 -0
  57. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/modals/rename_modal.html +0 -0
  58. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/modals/saveas_modal.html +0 -0
  59. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/modals.html +0 -0
  60. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/python_code_overlay.html +0 -0
  61. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/sidebar.html +0 -0
  62. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/components/text_to_code_panel.html +0 -0
  63. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/design/templates/experiment_builder.html +0 -0
  64. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/__init__.py +0 -0
  65. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/execute.py +0 -0
  66. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/execute_file.py +0 -0
  67. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/templates/components/error_modal.html +0 -0
  68. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/templates/components/logging_panel.html +0 -0
  69. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/templates/components/progress_panel.html +0 -0
  70. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/templates/components/run_panel.html +0 -0
  71. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/templates/components/run_tabs.html +0 -0
  72. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/templates/components/tab_bayesian.html +0 -0
  73. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/templates/components/tab_configuration.html +0 -0
  74. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/templates/components/tab_repeat.html +0 -0
  75. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/execute/templates/experiment_run.html +0 -0
  76. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/library/__init__.py +0 -0
  77. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/library/library.py +0 -0
  78. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/library/templates/library.html +0 -0
  79. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/main/__init__.py +0 -0
  80. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/main/main.py +0 -0
  81. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/main/templates/help.html +0 -0
  82. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/routes/main/templates/home.html +0 -0
  83. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/socket_handlers.py +0 -0
  84. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/favicon.ico +0 -0
  85. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/gui_annotation/Slide1.png +0 -0
  86. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/gui_annotation/Slide2.PNG +0 -0
  87. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/js/db_delete.js +0 -0
  88. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/js/overlay.js +0 -0
  89. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/js/script_metadata.js +0 -0
  90. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/js/socket_handler.js +0 -0
  91. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/js/sortable_card.js +0 -0
  92. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/js/sortable_design.js +0 -0
  93. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/js/ui_state.js +0 -0
  94. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/logo.webp +0 -0
  95. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/static/style.css +0 -0
  96. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/templates/base.html +0 -0
  97. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/__init__.py +0 -0
  98. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/client_proxy.py +0 -0
  99. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/decorators.py +0 -0
  100. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/global_config.py +0 -0
  101. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/llm_agent.py +0 -0
  102. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/py_to_json.py +0 -0
  103. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/serilize.py +0 -0
  104. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/task_runner.py +0 -0
  105. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos/utils/utils.py +0 -0
  106. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos.egg-info/SOURCES.txt +0 -0
  107. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos.egg-info/dependency_links.txt +0 -0
  108. {ivoryos-1.3.5 → ivoryos-1.3.6}/ivoryos.egg-info/top_level.txt +0 -0
  109. {ivoryos-1.3.5 → ivoryos-1.3.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ivoryos
3
- Version: 1.3.5
3
+ Version: 1.3.6
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
@@ -9,6 +9,7 @@ Requires-Python: >=3.7
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
11
  Requires-Dist: bcrypt
12
+ Requires-Dist: Flask[async]
12
13
  Requires-Dist: Flask-Login
13
14
  Requires-Dist: Flask-Session
14
15
  Requires-Dist: Flask-SocketIO
@@ -21,8 +22,10 @@ Provides-Extra: optimizer-ax
21
22
  Requires-Dist: ax-platform; extra == "optimizer-ax"
22
23
  Provides-Extra: optimizer-baybe
23
24
  Requires-Dist: baybe; extra == "optimizer-baybe"
25
+ Provides-Extra: optimizer-nimo
26
+ Requires-Dist: nimo; extra == "optimizer-nimo"
24
27
  Provides-Extra: optimizer
25
- Requires-Dist: ax-platform; extra == "optimizer"
28
+ Requires-Dist: ax-platform>=1.1.2; extra == "optimizer"
26
29
  Requires-Dist: baybe; extra == "optimizer"
27
30
  Provides-Extra: doc
28
31
  Requires-Dist: sphinx; extra == "doc"
@@ -30,7 +30,7 @@ class AxOptimizer(OptimizerBase):
30
30
  @staticmethod
31
31
  def _create_generator_mapping():
32
32
  """Create a mapping from string values to Generator enum members."""
33
- from ax.modelbridge import Generators
33
+ from ax.adapter import Generators
34
34
  return {member.value: member for member in Generators}
35
35
 
36
36
  def _convert_parameter_to_ax_format(self, parameter_space):
@@ -96,8 +96,8 @@ class AxOptimizer(OptimizerBase):
96
96
  step_2 = optimizer_config.get("step_2", {})
97
97
  step_1_generator = step_1.get("model", "Sobol")
98
98
  step_2_generator = step_2.get("model", "BOTorch")
99
- generator_1 = GenerationStep(model=generators.get(step_1_generator), num_trials=step_1.get("num_samples", 5))
100
- generator_2 = GenerationStep(model=generators.get(step_2_generator), num_trials=step_2.get("num_samples", -1))
99
+ generator_1 = GenerationStep(generator=generators.get(step_1_generator), num_trials=step_1.get("num_samples", 5))
100
+ generator_2 = GenerationStep(generator=generators.get(step_2_generator), num_trials=step_2.get("num_samples", -1))
101
101
  return GenerationStrategy(steps=[generator_1, generator_2])
102
102
 
103
103
  def suggest(self, n=1):
@@ -5,7 +5,7 @@ from abc import ABC, abstractmethod
5
5
 
6
6
 
7
7
  class OptimizerBase(ABC):
8
- def __init__(self, experiment_name:str, parameter_space: list, objective_config: dict, optimizer_config: dict):
8
+ def __init__(self, experiment_name:str, parameter_space: list, objective_config: dict, optimizer_config: dict, datapath:str=None):
9
9
  """
10
10
  :param experiment_name: arbitrary name
11
11
  :param parameter_space: list of parameter names
@@ -29,6 +29,7 @@ class OptimizerBase(ABC):
29
29
  self.parameter_space = parameter_space
30
30
  self.objective_config = objective_config
31
31
  self.optimizer_config = optimizer_config
32
+ self.datapath = datapath
32
33
 
33
34
  @abstractmethod
34
35
  def suggest(self, n=1):
@@ -2,8 +2,10 @@
2
2
 
3
3
  from ivoryos.optimizer.ax_optimizer import AxOptimizer
4
4
  from ivoryos.optimizer.baybe_optimizer import BaybeOptimizer
5
+ from ivoryos.optimizer.nimo_optimizer import NIMOOptimizer
5
6
 
6
7
  OPTIMIZER_REGISTRY = {
7
8
  "ax": AxOptimizer,
8
- "baybe": BaybeOptimizer
9
+ "baybe": BaybeOptimizer,
10
+ "nimo": NIMOOptimizer,
9
11
  }
@@ -385,7 +385,13 @@ def methods_handler(instrument: str = ''):
385
385
  success = False
386
386
  msg = [f"{field}: {', '.join(messages)}" for field, messages in form.errors.items()]
387
387
  utils.post_script_file(script)
388
- exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
388
+ #TODO
389
+ try:
390
+ exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
391
+ except Exception as e:
392
+ exec_string = {}
393
+ msg = f"Compilation failed: {str(e)}"
394
+ # exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
389
395
  session['python_code'] = exec_string
390
396
  design_buttons = {stype: create_action_button(script, stype) for stype in script.stypes}
391
397
  html = render_template("components/canvas_main.html", script=script, buttons_dict=design_buttons)
@@ -23,12 +23,16 @@ def get_step(uuid: int):
23
23
  """
24
24
  script = utils.get_script_file()
25
25
  action = script.find_by_uuid(uuid)
26
- if request.method == 'GET':
27
- # forms = create_form_from_action(action, script=script)
26
+ if action is None:
27
+ return jsonify({"warning": "Step not found, please refresh the page."}), 404
28
+
29
+ elif request.method == 'GET':
30
+ forms = create_form_from_action(action, script=script)
28
31
  # session['edit_action'] = action
29
32
  return render_template("components/edit_action_form.html",
30
33
  action=action,
31
- forms=create_form_from_action(action, script=script))
34
+ forms=forms)
35
+
32
36
 
33
37
 
34
38
  @steps.post("/draft/steps/<int:uuid>")
@@ -6,6 +6,7 @@
6
6
  <i class="bi bi-arrow-return-left"></i>
7
7
  </a>
8
8
  </div>
9
+ {% if action %}
9
10
  <h5> {{ action['action'] | format_name }} </h5>
10
11
  <form role="form" method='POST' name="{{instrument}}"
11
12
  action="{{ url_for('design.design_steps.get_step', uuid=action['uuid']) }}"
@@ -36,3 +37,4 @@
36
37
  <button type="submit" class="btn btn-primary">Save</button>
37
38
  <button type="button" class="btn btn-primary" id="back">Back</button>
38
39
  </form>
40
+ {% endif %}
@@ -50,6 +50,7 @@ def run(module=None, host="0.0.0.0", port=None, debug=None, llm_server=None, mod
50
50
  blueprint_plugins: Union[list, Blueprint] = [],
51
51
  exclude_names: list = [],
52
52
  notification_handler=None,
53
+ optimizer_registry: dict = None,
53
54
  ):
54
55
  """
55
56
  Start ivoryOS app server.
@@ -91,7 +92,10 @@ def run(module=None, host="0.0.0.0", port=None, debug=None, llm_server=None, mod
91
92
  app.config["LOGGERS_PATH"] = logger_output_name or app.config["LOGGERS_PATH"] # default.log
92
93
  logger_path = os.path.join(app.config["OUTPUT_FOLDER"], app.config["LOGGERS_PATH"])
93
94
  dummy_deck_path = os.path.join(app.config["OUTPUT_FOLDER"], app.config["DUMMY_DECK"])
94
- global_config.optimizers = OPTIMIZER_REGISTRY
95
+ if optimizer_registry:
96
+ global_config.optimizers = optimizer_registry
97
+ else:
98
+ global_config.optimizers = OPTIMIZER_REGISTRY
95
99
  if module:
96
100
  app.config["MODULE"] = module
97
101
  app.config["OFF_LINE"] = False
@@ -172,33 +172,50 @@ function editAction(uuid) {
172
172
  return;
173
173
  }
174
174
 
175
- // Save current state before fetching new content
176
175
  previousHtmlState = document.getElementById('instrument-panel').innerHTML;
177
176
 
178
177
  fetch(scriptStepUrl.replace('0', uuid), {
179
- method: 'GET',
178
+ method: 'GET', // no need for Content-Type on GET
180
179
  headers: {
181
180
  'Content-Type': 'application/json'
182
181
  }
183
182
  })
184
- .then(response => response.text())
183
+ .then(response => {
184
+ if (!response.ok) {
185
+ return response.json().then(err => {
186
+ if (err.warning) {
187
+ alert(err.warning); // <-- should fire now
188
+ }
189
+ // restore panel so user isn't stuck
190
+ if (previousHtmlState) {
191
+ document.getElementById('instrument-panel').innerHTML = previousHtmlState;
192
+ previousHtmlState = null;
193
+ }
194
+ throw new Error("Step fetch failed: " + response.status);
195
+ });
196
+ }
197
+ return response.text();
198
+ })
185
199
  .then(html => {
186
200
  document.getElementById('instrument-panel').innerHTML = html;
187
201
 
188
- // Add click handler for back button
189
- document.getElementById('back').addEventListener('click', function(e) {
190
- e.preventDefault();
191
- if (previousHtmlState) {
192
- document.getElementById('instrument-panel').innerHTML = previousHtmlState;
193
- previousHtmlState = null; // Clear the stored state
194
- }
195
- });
202
+ const backButton = document.getElementById('back');
203
+ if (backButton) {
204
+ backButton.addEventListener('click', function(e) {
205
+ e.preventDefault();
206
+ if (previousHtmlState) {
207
+ document.getElementById('instrument-panel').innerHTML = previousHtmlState;
208
+ previousHtmlState = null;
209
+ }
210
+ });
211
+ }
196
212
  })
197
213
  .catch(error => console.error('Error:', error));
198
214
  }
199
215
 
200
216
 
201
217
 
218
+
202
219
  function deleteAction(uuid) {
203
220
  if (!uuid) {
204
221
  console.error('Invalid UUID');
@@ -209,7 +209,7 @@ def parse_optimization_form(form_data: Dict[str, str]):
209
209
  parameter["bounds"] = bounds
210
210
 
211
211
  elif value == "choice":
212
- choices_field = f"{param_name}_choices"
212
+ choices_field = f"{param_name}_value"
213
213
  if choices_field in form_data and form_data[choices_field]:
214
214
  # Split choices by comma and clean whitespace
215
215
  choices = [choice.strip() for choice in form_data[choices_field].split(',')]
@@ -644,12 +644,21 @@ class Script(db.Model):
644
644
  args_str = args_str.replace(f"'#{args[arg][1:]}'", args[arg][1:])
645
645
  elif isinstance(args[arg], dict):
646
646
  # print(args[arg])
647
- variables = self.get_variables()
647
+ if not args[arg]:
648
+ continue
649
+ # Extract the variable name (first key in the dict)
648
650
  value = next(iter(args[arg]))
649
- if value not in variables:
650
- raise ValueError(f"Variable ({value}) is not defined.")
651
- args_str = args_str.replace(f"{args[arg]}", next(iter(args[arg])))
652
- # elif self._is_variable(arg):
651
+ var_type = args[arg].get(value)
652
+
653
+ # Only process if it's a function_output variable reference
654
+ if var_type == "function_output":
655
+ variables = self.get_variables()
656
+ if value not in variables:
657
+ raise ValueError(f"Variable ({value}) is not defined.")
658
+ # Replace the dict string representation with just the variable name
659
+ args_str = args_str.replace(f"{args[arg]}", value)
660
+
661
+ # elif self._is_variable(arg):
653
662
  # print("is variable")
654
663
  # args_str = args_str.replace(f"'{args[arg]}'", args[arg])
655
664
  return args_str
@@ -405,7 +405,7 @@ def create_form_from_action(action: dict, script=None, design=True):
405
405
  for name, param_type in arg_types.items():
406
406
  # formatted_param_name = format_name(name)
407
407
  value = args.get(name, "")
408
- if type(value) is dict:
408
+ if type(value) is dict and value:
409
409
  value = next(iter(value))
410
410
  field_kwargs = {
411
411
  "label": name,
@@ -556,9 +556,13 @@ def _action_button(action: dict, variables: dict):
556
556
  arg_list = []
557
557
  for k, v in action['args'].items():
558
558
  if isinstance(v, dict):
559
- value = next(iter(v)) # Extract the first key if it's a dict
560
- # show warning color for variable calling when there is no definition
561
- style = "background-color: khaki" if value not in variables.keys() else ""
559
+ if not v:
560
+ value = v # Keep the original value if not a dict
561
+ else:
562
+ value = next(iter(v)) # Extract the first key if it's a dict
563
+ # show warning color for variable calling when there is no definition
564
+
565
+ style = "background-color: khaki" if v.get(value) == "function_output" and value not in variables.keys() else ""
562
566
  else:
563
567
  value = v # Keep the original value if not a dict
564
568
  arg_list.append(f"{k} = {value}") # Format the key-value pair
@@ -198,7 +198,7 @@ class ScriptRunner:
198
198
 
199
199
 
200
200
  else:
201
- print("just exec synchronously")
201
+ # print("just exec synchronously")
202
202
  exec(line, exec_globals, exec_locals)
203
203
  exec_globals.update(exec_locals)
204
204
  # return locals_dict
@@ -0,0 +1 @@
1
+ __version__ = "1.3.6"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ivoryos
3
- Version: 1.3.5
3
+ Version: 1.3.6
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
@@ -9,6 +9,7 @@ Requires-Python: >=3.7
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
11
  Requires-Dist: bcrypt
12
+ Requires-Dist: Flask[async]
12
13
  Requires-Dist: Flask-Login
13
14
  Requires-Dist: Flask-Session
14
15
  Requires-Dist: Flask-SocketIO
@@ -21,8 +22,10 @@ Provides-Extra: optimizer-ax
21
22
  Requires-Dist: ax-platform; extra == "optimizer-ax"
22
23
  Provides-Extra: optimizer-baybe
23
24
  Requires-Dist: baybe; extra == "optimizer-baybe"
25
+ Provides-Extra: optimizer-nimo
26
+ Requires-Dist: nimo; extra == "optimizer-nimo"
24
27
  Provides-Extra: optimizer
25
- Requires-Dist: ax-platform; extra == "optimizer"
28
+ Requires-Dist: ax-platform>=1.1.2; extra == "optimizer"
26
29
  Requires-Dist: baybe; extra == "optimizer"
27
30
  Provides-Extra: doc
28
31
  Requires-Dist: sphinx; extra == "doc"
@@ -1,4 +1,5 @@
1
1
  bcrypt
2
+ Flask[async]
2
3
  Flask-Login
3
4
  Flask-Session
4
5
  Flask-SocketIO
@@ -19,7 +20,7 @@ sphinx-rtd-theme
19
20
  sphinxcontrib-httpdomain
20
21
 
21
22
  [optimizer]
22
- ax-platform
23
+ ax-platform>=1.1.2
23
24
  baybe
24
25
 
25
26
  [optimizer-ax]
@@ -27,3 +28,6 @@ ax-platform
27
28
 
28
29
  [optimizer-baybe]
29
30
  baybe
31
+
32
+ [optimizer-nimo]
33
+ nimo
@@ -14,6 +14,7 @@ authors = [
14
14
  ]
15
15
  dependencies = [
16
16
  "bcrypt",
17
+ "Flask[async]",
17
18
  "Flask-Login",
18
19
  "Flask-Session",
19
20
  "Flask-SocketIO",
@@ -27,8 +28,9 @@ dependencies = [
27
28
  [project.optional-dependencies]
28
29
  optimizer-ax = ["ax-platform"]
29
30
  optimizer-baybe = ["baybe"]
31
+ optimizer-nimo = ["nimo"]
30
32
  optimizer = [
31
- "ax-platform",
33
+ "ax-platform>=1.1.2",
32
34
  "baybe"
33
35
  ]
34
36
  doc = [
@@ -1 +0,0 @@
1
- __version__ = "1.3.5"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes