ivoryos 1.0.0__py3-none-any.whl → 1.0.3__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.

Potentially problematic release.


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

@@ -26,8 +26,8 @@
26
26
  </h2>
27
27
  <div id="runpanel" class="accordion-collapse collapse show">
28
28
  <div class="accordion-body">
29
- {% if script['script'] or script['prep'] or script['cleanup'] %}
30
- <div class="row">
29
+ <div class="row">
30
+ {% if script['script'] or script['prep'] or script['cleanup'] %}
31
31
  <div class="col-lg-6 col-sm-12" id="run-panel" style="{{ 'display: none;' if pause_status else '' }}">
32
32
  <ul class="nav nav-tabs" id="myTabs" role="tablist">
33
33
  <li class="nav-item" role="presentation">
@@ -127,129 +127,62 @@
127
127
  </form>
128
128
  {% endif %}
129
129
  </div>
130
-
131
- {# <div class="tab-pane fade " id="tab3" role="tabpanel" aria-labelledby="tab3-tab">#}
132
- {# <form role="form" method='POST' name="bo" action="{{ url_for('design.experiment_run')}}">#}
133
- {# <div class="form-group">#}
134
- {# <p><h5>Parameters:</h5><p>#}
135
- {# {% for config in config_list %}#}
136
- {# <div class="row g-3 align-items-center">#}
137
- {# <div class="col-lg-3 col-sm-6 ">#}
138
- {# {{config}}:#}
139
- {# </div>#}
140
- {# <div class="col-auto">#}
141
- {# <label class="col-form-label" for="{{config}}_type">Type</label>#}
142
- {# </div>#}
143
- {# <div class="col-auto">#}
144
- {# <select class="form-select" id="{{config}}_type" name="{{config}}_type">#}
145
- {# <option selected value="range">range</option>#}
146
- {# <option value="choice">choice</option>#}
147
- {# <option value="fixed">fixed</option>#}
148
- {# </select>#}
149
- {# </div>#}
150
- {# <div class="col-auto">#}
151
- {# <label class="" for="{{config}}_value">Values</label>#}
152
- {# </div>#}
153
- {# <div class="col-auto">#}
154
- {# <input type="text" class="form-control" id="{{config}}_value" name="{{config}}_value" placeholder="1, 2, 3">#}
155
- {# </div>#}
156
- {# <div class="col-auto">#}
157
- {# <input type="text" class="form-control" id="{{config}}_value_max" style="display: none;" placeholder="1, 2, 3">#}
158
- {# </div>#}
159
- {# </div>#}
160
- {# {% endfor %}#}
161
- {# <p><h5>Objective:</h5><p>#}
162
- {# {% for objective in return_list %}#}
163
- {# <div class="row gy-2 gx-3 align-items-center input-group">#}
164
- {# <div class="col-3">#}
165
- {# {{objective}}:#}
166
- {# </div>#}
167
- {# <div class="col-auto">#}
168
- {# <label class="" for="{{objective}}_min">Minimize</label>#}
169
- {# </div>#}
170
- {# <div class="col-auto">#}
171
- {# <select class="form-select" id="{{objective}}_min" name="{{objective}}_min">#}
172
- {# <option selected>minimize</option>#}
173
- {# <option>maximize</option>#}
174
- {# <option>none</option>#}
175
- {# </select>#}
176
- {# </div>#}
177
- {# <div class="col-auto">#}
178
- {# <label class="" for="{{objective}}_threshold">Threshold</label>#}
179
- {# </div>#}
180
- {# <div class="col-auto">#}
181
- {# <input type="text" class="form-control" id="{{objective}}_threshold" name="{{objective}}_threshold" placeholder="None">#}
182
- {# </div>#}
183
- {# </div>#}
184
- {# {% endfor %}#}
185
- {# <p><h5>Budget:</h5></p>#}
186
- {# <div class="input-group mb-3">#}
187
- {# <label class="input-group-text" for="repeat">Max iteration </label>#}
188
- {# <input class="form-control" type="number" id="repeat" name="repeat" min="1" max="1000" value="25">#}
189
- {# </div>#}
190
- {# {% if not no_deck_warning%}#}
191
- {# <div class="input-group mb-3">#}
192
- {# <button class="form-control" type="submit" name="bo">Run</button>#}
193
- {# </div>#}
194
- {# {% endif %}#}
195
- {# </div>#}
196
- {# </form>#}
197
- {# </div>#}
198
- <div class="tab-pane fade" id="tab3" role="tabpanel" aria-labelledby="tab3-tab">
199
- <form method="POST" name="bo" action="{{ url_for('design.experiment_run') }}">
200
- <div class="container py-2">
201
130
 
202
- <!-- Parameters -->
203
- <h6 class="fw-bold mt-2 mb-1">Parameters</h6>
204
- {% for config in config_list %}
205
- <div class="row align-items-center mb-2">
206
- <div class="col-3 col-form-label-sm">
207
- {{ config }}:
208
- </div>
209
- <div class="col-6">
210
- <select class="form-select form-select-sm" id="{{config}}_type" name="{{config}}_type">
211
- <option selected value="range">range</option>
212
- <option value="choice">choice</option>
213
- <option value="fixed">fixed</option>
214
- </select>
215
- </div>
216
- <div class="col-3">
217
- <input type="text" class="form-control form-control-sm" id="{{config}}_value" name="{{config}}_value" placeholder="1, 2, 3">
218
- </div>
219
- </div>
220
- {% endfor %}
131
+ <div class="tab-pane fade" id="tab3" role="tabpanel" aria-labelledby="tab3-tab">
132
+ <form method="POST" name="bo" action="{{ url_for('design.experiment_run') }}">
133
+ <div class="container py-2">
221
134
 
222
- <!-- Objective -->
223
- <h6 class="fw-bold mt-3 mb-1">Objectives</h6>
224
- {% for objective in return_list %}
225
- <div class="row align-items-center mb-2">
226
- <div class="col-3 col-form-label-sm">
227
- {{ objective }}:
228
- </div>
229
- <div class="col-6">
230
- <select class="form-select form-select-sm" id="{{objective}}_min" name="{{objective}}_min">
231
- <option selected>minimize</option>
232
- <option>maximize</option>
233
- <option>none</option>
234
- </select>
235
- </div>
236
- </div>
237
- {% endfor %}
135
+ <!-- Parameters -->
136
+ <h6 class="fw-bold mt-2 mb-1">Parameters</h6>
137
+ {% for config in config_list %}
138
+ <div class="row align-items-center mb-2">
139
+ <div class="col-3 col-form-label-sm">
140
+ {{ config }}:
141
+ </div>
142
+ <div class="col-6">
143
+ <select class="form-select form-select-sm" id="{{config}}_type" name="{{config}}_type">
144
+ <option selected value="range">range</option>
145
+ <option value="choice">choice</option>
146
+ <option value="fixed">fixed</option>
147
+ </select>
148
+ </div>
149
+ <div class="col-3">
150
+ <input type="text" class="form-control form-control-sm" id="{{config}}_value" name="{{config}}_value" placeholder="1, 2, 3">
151
+ </div>
152
+ </div>
153
+ {% endfor %}
238
154
 
239
- <h6 class="fw-bold mt-3 mb-1">Budget</h6>
155
+ <!-- Objective -->
156
+ <h6 class="fw-bold mt-3 mb-1">Objectives</h6>
157
+ {% for objective in return_list %}
158
+ <div class="row align-items-center mb-2">
159
+ <div class="col-3 col-form-label-sm">
160
+ {{ objective }}:
161
+ </div>
162
+ <div class="col-6">
163
+ <select class="form-select form-select-sm" id="{{objective}}_min" name="{{objective}}_min">
164
+ <option selected>minimize</option>
165
+ <option>maximize</option>
166
+ <option>none</option>
167
+ </select>
168
+ </div>
169
+ </div>
170
+ {% endfor %}
240
171
 
241
- <div class="input-group mb-3">
242
- <label class="input-group-text" for="repeat">Max iteration </label>
243
- <input class="form-control" type="number" id="repeat" name="repeat" min="1" max="1000" value="25">
244
- </div>
245
- {% if not no_deck_warning%}
246
- <div class="input-group mb-3">
247
- <button class="form-control" type="submit" name="bo">Run</button>
248
- </div>
249
- {% endif %}
250
- </div>
251
- </form>
252
- </div>
172
+ <h6 class="fw-bold mt-3 mb-1">Budget</h6>
173
+
174
+ <div class="input-group mb-3">
175
+ <label class="input-group-text" for="repeat">Max iteration </label>
176
+ <input class="form-control" type="number" id="repeat" name="repeat" min="1" max="1000" value="25">
177
+ </div>
178
+ {% if not no_deck_warning%}
179
+ <div class="input-group mb-3">
180
+ <button class="form-control" type="submit" name="bo">Run</button>
181
+ </div>
182
+ {% endif %}
183
+ </div>
184
+ </form>
185
+ </div>
253
186
 
254
187
 
255
188
  <div class="tab-pane fade {{ 'show active' if config_list and config_list|count<=5 else '' }}" id="tab4" role="tabpanel" aria-labelledby="tab4-tab">
@@ -278,6 +211,12 @@
278
211
  </div>
279
212
  </div>
280
213
  </div>
214
+ {% else %}
215
+ <div class="col-lg-6 col-sm-12" id="placeholder-panel">
216
+
217
+ </div>
218
+ {% endif %}
219
+
281
220
  <div class="col-lg-6 col-sm-12" id="code-panel" style="{{ '' if pause_status else 'display: none;'}}">
282
221
  <p>
283
222
  <h5>Progress:</h5>
@@ -299,7 +238,7 @@
299
238
  {% endif %}
300
239
  {% if "cleanup" in line_collection.keys() %}
301
240
  {% set stype = "cleanup" %}
302
- <h6>Experiment:</h6>
241
+ <h6>Cleanup:</h6>
303
242
  {% for code in line_collection["cleanup"] %}
304
243
  <pre style="margin: 0; padding: 0; line-height: 1;"><code class="python" id="{{ stype }}-{{ loop.index0 }}" >{{code}}</code></pre>
305
244
  {% endfor %}
@@ -337,7 +276,7 @@
337
276
  <div id="logging-panel"></div>
338
277
  </div>
339
278
  </div>
340
- {% endif %}
279
+
341
280
  </div>
342
281
  </div>
343
282
  </div>
@@ -10,21 +10,26 @@ document.addEventListener("DOMContentLoaded", function() {
10
10
  var progressBar = document.getElementById('progress-bar-inner');
11
11
  progressBar.style.width = progress + '%';
12
12
  progressBar.setAttribute('aria-valuenow', progress);
13
+ const runPanel = document.getElementById("run-panel");
14
+ const codePanel = document.getElementById("code-panel");
13
15
  if (progress === 1) {
14
- document.getElementById("run-panel").style.display = "none";
15
- document.getElementById("code-panel").style.display = "block";
16
-
17
- // Optional: Scroll to the code panel
18
- document.getElementById("code-panel").scrollIntoView({ behavior: "smooth" });
16
+ if (runPanel) runPanel.style.display = "none";
17
+ if (codePanel) {
18
+ codePanel.style.display = "block";
19
+ codePanel.scrollIntoView({ behavior: "smooth" });
20
+ }
21
+ progressBar.classList.remove('bg-success');
22
+ progressBar.classList.remove('bg-danger');
23
+ progressBar.classList.add('progress-bar-animated');
19
24
  }
20
25
  if (progress === 100) {
21
26
  // Remove animation and set green color when 100% is reached
22
27
  progressBar.classList.remove('progress-bar-animated');
23
28
  progressBar.classList.add('bg-success'); // Bootstrap class for green color
24
29
  setTimeout(() => {
25
- document.getElementById("code-panel").style.display = "none";
26
- document.getElementById("run-panel").style.display = "block";
27
- }, 1000); // Small delay to let users see the completion
30
+ if (runPanel) runPanel.style.display = "block";
31
+ if (codePanel) codePanel.style.display = "none";
32
+ }, 1000); // Small delay to let users see the completion
28
33
  }
29
34
  });
30
35
 
@@ -0,0 +1,87 @@
1
+ from ivoryos.utils.utils import install_and_import
2
+
3
+
4
+ def ax_init_form(data, arg_types):
5
+ """
6
+ create Ax campaign from the web form input
7
+ :param data:
8
+ """
9
+ install_and_import("ax", "ax-platform")
10
+ parameter, objectives = ax_wrapper(data, arg_types)
11
+ from ax.service.ax_client import AxClient
12
+ ax_client = AxClient()
13
+ ax_client.create_experiment(parameter, objectives=objectives)
14
+ return ax_client
15
+
16
+
17
+ def ax_wrapper(data: dict, arg_types: list):
18
+ """
19
+ Ax platform wrapper function for creating optimization campaign parameters and objective from the web form input
20
+ :param data: e.g.,
21
+ {
22
+ "param_1_type": "range", "param_1_value": [1,2],
23
+ "param_2_type": "range", "param_2_value": [1,2],
24
+ "obj_1_min": True,
25
+ "obj_2_min": True
26
+ }
27
+ :return: the optimization campaign parameters
28
+ parameter=[
29
+ {"name": "param_1", "type": "range", "bounds": [1,2]},
30
+ {"name": "param_1", "type": "range", "bounds": [1,2]}
31
+ ]
32
+ objectives=[
33
+ {"name": "obj_1", "min": True, "threshold": None},
34
+ {"name": "obj_2", "min": True, "threshold": None},
35
+ ]
36
+ """
37
+ from ax.service.utils.instantiation import ObjectiveProperties
38
+ parameter = []
39
+ objectives = {}
40
+ # Iterate through the webui_data dictionary
41
+ for key, value in data.items():
42
+ # Check if the key corresponds to a parameter type
43
+ if "_type" in key:
44
+ param_name = key.split("_type")[0]
45
+ param_type = value
46
+ param_value = data[f"{param_name}_value"].split(",")
47
+ try:
48
+ values = [float(v) for v in param_value]
49
+ except Exception:
50
+ values = param_value
51
+ if param_type == "range":
52
+ param = {"name": param_name, "type": param_type, "bounds": values}
53
+ if param_type == "choice":
54
+ param = {"name": param_name, "type": param_type, "values": values}
55
+ if param_type == "fixed":
56
+ param = {"name": param_name, "type": param_type, "value": values[0]}
57
+ _type = arg_types[param_name] if arg_types[param_name] in ["str", "bool", "int"] else "float"
58
+ param.update({"value_type": _type})
59
+ parameter.append(param)
60
+ elif key.endswith("_min"):
61
+ if not value == 'none':
62
+ obj_name = key.split("_min")[0]
63
+ is_min = True if value == "minimize" else False
64
+
65
+ threshold = None if f"{obj_name}_threshold" not in data else data[f"{obj_name}_threshold"]
66
+ properties = ObjectiveProperties(minimize=is_min)
67
+ objectives[obj_name] = properties
68
+
69
+ return parameter, objectives
70
+
71
+
72
+ def ax_init_opc(bo_args):
73
+ install_and_import("ax", "ax-platform")
74
+ from ax.service.ax_client import AxClient
75
+ from ax.service.utils.instantiation import ObjectiveProperties
76
+
77
+ ax_client = AxClient()
78
+ objectives = bo_args.get("objectives")
79
+ objectives_formatted = {}
80
+ for obj in objectives:
81
+ obj_name = obj.get("name")
82
+ minimize = obj.get("minimize")
83
+ objectives_formatted[obj_name] = ObjectiveProperties(minimize=minimize)
84
+ bo_args["objectives"] = objectives_formatted
85
+ ax_client.create_experiment(**bo_args)
86
+
87
+ return ax_client
@@ -8,7 +8,7 @@ import os
8
8
 
9
9
  # Function to create class and methods dynamically
10
10
  def create_function(url, class_name, functions):
11
- class_template = f'class {class_name.capitalize()}:\n url = "{url}ivoryos/backend_control/deck.{class_name}"\n'
11
+ class_template = f'class {class_name.capitalize()}:\n url = "{url}ivoryos/api/control/deck.{class_name}"\n'
12
12
 
13
13
  for function_name, details in functions.items():
14
14
  signature = details['signature']
@@ -48,7 +48,8 @@ class Script(db.Model):
48
48
 
49
49
  def __init__(self, name=None, deck=None, status=None, script_dict: dict = None, id_order: dict = None,
50
50
  time_created=None, last_modified=None, editing_type=None, author: str = None,
51
- registered:bool=False,
51
+ # registered:bool=False,
52
+ python_script: str = None
52
53
  ):
53
54
  if script_dict is None:
54
55
  script_dict = {"prep": [], "script": [], "cleanup": []}
@@ -76,6 +77,7 @@ class Script(db.Model):
76
77
  self.id_order = id_order
77
78
  self.editing_type = editing_type
78
79
  self.author = author
80
+ self.python_script = python_script
79
81
  # self.r = registered
80
82
 
81
83
  def as_dict(self):
@@ -412,12 +414,13 @@ class Script(db.Model):
412
414
  """
413
415
  line_collection = {}
414
416
  for stype, func_str in exec_str_collection.items():
415
- module = ast.parse(func_str)
416
- func_def = next(node for node in module.body if isinstance(node, ast.FunctionDef))
417
+ if func_str:
418
+ module = ast.parse(func_str)
419
+ func_def = next(node for node in module.body if isinstance(node, ast.FunctionDef))
417
420
 
418
- # Extract function body as source lines
419
- line_collection[stype] = [ast.unparse(node) for node in func_def.body if not isinstance(node, ast.Return)]
420
- # print(line_collection[stype])
421
+ # Extract function body as source lines
422
+ line_collection[stype] = [ast.unparse(node) for node in func_def.body if not isinstance(node, ast.Return)]
423
+ # print(line_collection[stype])
421
424
  return line_collection
422
425
 
423
426
  def compile(self, script_path=None):
@@ -670,7 +673,24 @@ class WorkflowStep(db.Model):
670
673
  run_error = db.Column(db.Boolean, default=False)
671
674
 
672
675
  def as_dict(self):
673
- dict = self.__dict__
676
+ dict = self.__dict__.copy()
677
+ dict.pop('_sa_instance_state', None)
678
+ return dict
679
+
680
+
681
+ class SingleStep(db.Model):
682
+ __tablename__ = 'single_steps'
683
+
684
+ id = db.Column(db.Integer, primary_key=True)
685
+ method_name = db.Column(db.String(128), nullable=False)
686
+ kwargs = db.Column(JSONType, nullable=False)
687
+ start_time = db.Column(db.DateTime)
688
+ end_time = db.Column(db.DateTime)
689
+ run_error = db.Column(db.String(128))
690
+ output = db.Column(JSONType)
691
+
692
+ def as_dict(self):
693
+ dict = self.__dict__.copy()
674
694
  dict.pop('_sa_instance_state', None)
675
695
  return dict
676
696
 
@@ -1,4 +1,4 @@
1
- # from ivoryos.utils.script_runner import ScriptRunner
1
+ import threading
2
2
 
3
3
 
4
4
  class GlobalConfig:
@@ -13,7 +13,8 @@ class GlobalConfig:
13
13
  cls._instance._defined_variables = {}
14
14
  cls._instance._api_variables = set()
15
15
  cls._instance._deck_snapshot = {}
16
- cls._instance._runner = None
16
+ cls._instance._runner_lock = threading.Lock()
17
+ cls._instance._runner_status = None
17
18
  return cls._instance
18
19
 
19
20
  @property
@@ -70,9 +71,17 @@ class GlobalConfig:
70
71
  self._api_variables = value
71
72
 
72
73
  @property
73
- def runner(self):
74
- return self._runner
74
+ def runner_lock(self):
75
+ return self._runner_lock
75
76
 
76
- @runner.setter
77
- def runner(self, value):
78
- self._runner = value
77
+ @runner_lock.setter
78
+ def runner_lock(self, value):
79
+ self._runner_lock = value
80
+
81
+ @property
82
+ def runner_status(self):
83
+ return self._runner_status
84
+
85
+ @runner_status.setter
86
+ def runner_status(self, value):
87
+ self._runner_status = value