ivoryos 1.0.9__py3-none-any.whl → 1.2.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.

Potentially problematic release.


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

Files changed (87) hide show
  1. ivoryos/__init__.py +26 -7
  2. ivoryos/routes/api/api.py +56 -0
  3. ivoryos/routes/auth/auth.py +5 -5
  4. ivoryos/routes/control/control.py +77 -372
  5. ivoryos/routes/control/control_file.py +36 -0
  6. ivoryos/routes/control/control_new_device.py +142 -0
  7. ivoryos/routes/control/templates/controllers.html +166 -0
  8. ivoryos/routes/control/templates/controllers_new.html +112 -0
  9. ivoryos/routes/control/utils.py +38 -0
  10. ivoryos/routes/data/data.py +129 -0
  11. ivoryos/routes/data/templates/components/step_card.html +13 -0
  12. ivoryos/routes/{database/templates/database → data/templates}/workflow_database.html +14 -8
  13. ivoryos/routes/{database/templates/database → data/templates}/workflow_view.html +3 -3
  14. ivoryos/routes/design/__init__.py +4 -0
  15. ivoryos/routes/design/design.py +298 -656
  16. ivoryos/routes/design/design_file.py +68 -0
  17. ivoryos/routes/design/design_step.py +145 -0
  18. ivoryos/routes/design/templates/components/action_form.html +53 -0
  19. ivoryos/routes/design/templates/components/actions_panel.html +25 -0
  20. ivoryos/routes/design/templates/components/autofill_toggle.html +10 -0
  21. ivoryos/routes/design/templates/components/canvas.html +5 -0
  22. ivoryos/routes/design/templates/components/canvas_footer.html +9 -0
  23. ivoryos/routes/design/templates/components/canvas_header.html +75 -0
  24. ivoryos/routes/design/templates/components/canvas_main.html +34 -0
  25. ivoryos/routes/design/templates/components/deck_selector.html +10 -0
  26. ivoryos/routes/design/templates/components/edit_action_form.html +38 -0
  27. ivoryos/routes/design/templates/components/instruments_panel.html +66 -0
  28. ivoryos/routes/design/templates/components/modals/drop_modal.html +17 -0
  29. ivoryos/routes/design/templates/components/modals/json_modal.html +22 -0
  30. ivoryos/routes/design/templates/components/modals/new_script_modal.html +17 -0
  31. ivoryos/routes/design/templates/components/modals/rename_modal.html +23 -0
  32. ivoryos/routes/design/templates/components/modals/saveas_modal.html +27 -0
  33. ivoryos/routes/design/templates/components/modals.html +6 -0
  34. ivoryos/routes/design/templates/components/python_code_overlay.html +39 -0
  35. ivoryos/routes/design/templates/components/sidebar.html +15 -0
  36. ivoryos/routes/design/templates/components/text_to_code_panel.html +20 -0
  37. ivoryos/routes/design/templates/experiment_builder.html +41 -0
  38. ivoryos/routes/execute/__init__.py +0 -0
  39. ivoryos/routes/execute/execute.py +317 -0
  40. ivoryos/routes/execute/execute_file.py +78 -0
  41. ivoryos/routes/execute/templates/components/error_modal.html +20 -0
  42. ivoryos/routes/execute/templates/components/logging_panel.html +31 -0
  43. ivoryos/routes/execute/templates/components/progress_panel.html +27 -0
  44. ivoryos/routes/execute/templates/components/run_panel.html +9 -0
  45. ivoryos/routes/execute/templates/components/run_tabs.html +17 -0
  46. ivoryos/routes/execute/templates/components/tab_bayesian.html +398 -0
  47. ivoryos/routes/execute/templates/components/tab_configuration.html +98 -0
  48. ivoryos/routes/execute/templates/components/tab_repeat.html +14 -0
  49. ivoryos/routes/execute/templates/experiment_run.html +294 -0
  50. ivoryos/routes/library/__init__.py +0 -0
  51. ivoryos/routes/library/library.py +159 -0
  52. ivoryos/routes/{database/templates/database/scripts_database.html → library/templates/library.html} +30 -22
  53. ivoryos/routes/main/main.py +1 -1
  54. ivoryos/routes/main/templates/{main/home.html → home.html} +4 -4
  55. ivoryos/socket_handlers.py +52 -0
  56. ivoryos/static/js/action_handlers.js +213 -0
  57. ivoryos/static/js/db_delete.js +23 -0
  58. ivoryos/static/js/script_metadata.js +39 -0
  59. ivoryos/static/js/sortable_design.js +89 -56
  60. ivoryos/static/js/ui_state.js +113 -0
  61. ivoryos/templates/base.html +4 -4
  62. ivoryos/utils/bo_campaign.py +179 -3
  63. ivoryos/utils/db_models.py +14 -5
  64. ivoryos/utils/form.py +5 -9
  65. ivoryos/utils/global_config.py +13 -1
  66. ivoryos/utils/py_to_json.py +225 -0
  67. ivoryos/utils/script_runner.py +49 -7
  68. ivoryos/utils/serilize.py +203 -0
  69. ivoryos/utils/task_runner.py +4 -1
  70. ivoryos/version.py +1 -1
  71. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0.dist-info}/METADATA +5 -8
  72. ivoryos-1.2.0.dist-info/RECORD +105 -0
  73. ivoryos/routes/control/templates/control/controllers.html +0 -78
  74. ivoryos/routes/control/templates/control/controllers_home.html +0 -55
  75. ivoryos/routes/control/templates/control/controllers_new.html +0 -89
  76. ivoryos/routes/database/database.py +0 -306
  77. ivoryos/routes/database/templates/database/step_card.html +0 -7
  78. ivoryos/routes/design/templates/design/experiment_builder.html +0 -521
  79. ivoryos/routes/design/templates/design/experiment_run.html +0 -558
  80. ivoryos-1.0.9.dist-info/RECORD +0 -61
  81. /ivoryos/routes/auth/templates/{auth/login.html → login.html} +0 -0
  82. /ivoryos/routes/auth/templates/{auth/signup.html → signup.html} +0 -0
  83. /ivoryos/routes/{database → data}/__init__.py +0 -0
  84. /ivoryos/routes/main/templates/{main/help.html → help.html} +0 -0
  85. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0.dist-info}/LICENSE +0 -0
  86. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0.dist-info}/WHEEL +0 -0
  87. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,203 @@
1
+ import ast
2
+ import json
3
+ import inspect
4
+ import logging
5
+ from typing import get_type_hints, Union, Optional, get_origin, get_args
6
+ import sys
7
+
8
+ import flask
9
+
10
+ from example.abstract_sdl_example.abstract_balance import AbstractBalance
11
+ from example.abstract_sdl_example.abstract_pump import AbstractPump
12
+
13
+
14
+ class ScriptAnalyzer:
15
+ def __init__(self):
16
+ self.primitive_types = {
17
+ 'int', 'float', 'str', 'bool', 'tuple', 'list'
18
+ }
19
+ self.type_mapping = {
20
+ int: 'int',
21
+ float: 'float',
22
+ str: 'str',
23
+ bool: 'bool',
24
+ tuple: 'tuple',
25
+ list: 'list'
26
+ }
27
+
28
+ def extract_type_from_hint(self, type_hint):
29
+ """Extract primitive types from type hints, handling Union and Optional"""
30
+ if type_hint is None:
31
+ return None
32
+
33
+ # Handle Union types (including Optional which is Union[T, None])
34
+ origin = get_origin(type_hint)
35
+ if origin is Union:
36
+ args = get_args(type_hint)
37
+ types = []
38
+ for arg in args:
39
+ if arg is type(None): # Skip None type
40
+ continue
41
+ if arg in self.type_mapping:
42
+ types.append(self.type_mapping[arg])
43
+ elif hasattr(arg, '__name__') and arg.__name__ in self.primitive_types:
44
+ types.append(arg.__name__)
45
+ else:
46
+ return None # Non-primitive type found
47
+ return types if types else None
48
+
49
+ # Handle direct primitive types
50
+ if type_hint in self.type_mapping:
51
+ return [self.type_mapping[type_hint]]
52
+ elif hasattr(type_hint, '__name__') and type_hint.__name__ in self.primitive_types:
53
+ return [type_hint.__name__]
54
+ else:
55
+ return None # Non-primitive type
56
+
57
+
58
+ def analyze_method(self, method):
59
+ """Analyze a single method and extract its signature"""
60
+ try:
61
+ sig = inspect.signature(method)
62
+ type_hints = get_type_hints(method)
63
+
64
+ parameters = []
65
+ type_hint_warning = False
66
+ user_input_params = []
67
+
68
+ for param_name, param in sig.parameters.items():
69
+ if param_name == 'self':
70
+ continue
71
+
72
+ param_info = {"name": param_name}
73
+
74
+ # Get type hint
75
+ if param_name in type_hints:
76
+ type_list = self.extract_type_from_hint(type_hints[param_name])
77
+ if type_list is None:
78
+ type_hint_warning = True
79
+ user_input_params.append(param_name)
80
+ param_info["type"] = ""
81
+ else:
82
+ param_info["type"] = type_list[0] if len(type_list) == 1 else type_list
83
+ else:
84
+ type_hint_warning = True
85
+ user_input_params.append(param_name)
86
+ param_info["type"] = ""
87
+
88
+ # Get default value
89
+ if param.default != inspect.Parameter.empty:
90
+ param_info["default"] = param.default
91
+
92
+ parameters.append(param_info)
93
+
94
+ # Get docstring
95
+ docstring = inspect.getdoc(method)
96
+
97
+ method_info = {
98
+ "docstring": docstring or "",
99
+ "parameters": parameters
100
+ }
101
+
102
+ return method_info, type_hint_warning
103
+
104
+ except Exception as e:
105
+ print(f"Error analyzing method {method.__name__}: {e}")
106
+ return None
107
+
108
+
109
+ def analyze_module(self, module, exclude_names=[]):
110
+ """Analyze module from sys.modules and extract class instances and methods"""
111
+ exclude_classes = (flask.Blueprint, logging.Logger)
112
+ # Get all variables in the module that are class instances
113
+ included = {}
114
+ excluded = {}
115
+ failed = {}
116
+ included_with_warnings = {}
117
+ for name, obj in vars(module).items():
118
+ if (
119
+ type(obj).__module__ == 'builtins'
120
+ or name[0].isupper()
121
+ or name.startswith("_")
122
+ or isinstance(obj, exclude_classes)
123
+ or name in exclude_names
124
+ or not hasattr(obj, '__class__')
125
+ ):
126
+ excluded[name] = type(obj).__name__
127
+ continue
128
+
129
+ cls = obj.__class__
130
+
131
+ try:
132
+ class_methods, type_hint_warning = self.analyze_class(cls)
133
+ if class_methods:
134
+ if type_hint_warning:
135
+ included_with_warnings[name] = class_methods
136
+ included[name] = class_methods
137
+ except Exception as e:
138
+ failed[name] = str(e)
139
+ continue
140
+ return included, included_with_warnings, failed, excluded
141
+
142
+ def save_to_json(self, data, output_path):
143
+ """Save analysis result to JSON file"""
144
+ with open(output_path, 'w') as f:
145
+ json.dump(data, f, indent=2)
146
+
147
+ def analyze_class(self, cls):
148
+ class_methods = {}
149
+ type_hint_flag = False
150
+ for method_name, method in inspect.getmembers(cls, predicate=callable):
151
+ if method_name.startswith("_") or method_name.isupper():
152
+ continue
153
+ method_info, type_hint_warning = self.analyze_method(method)
154
+ if type_hint_warning:
155
+ type_hint_flag = True
156
+ if method_info:
157
+ class_methods[method_name] = method_info
158
+ return class_methods, type_hint_flag
159
+
160
+ @staticmethod
161
+ def print_deck_snapshot(result, with_warnings, failed):
162
+ print("\nDeck Snapshot:")
163
+ print("Included Classes:")
164
+ for name, methods in result.items():
165
+ print(f" {name}:")
166
+ for method_name, method_info in methods.items():
167
+ print(f" {method_name}: {method_info}")
168
+
169
+ if with_warnings:
170
+ print("\nClasses with Type Hint Warnings:")
171
+ for name, methods in with_warnings.items():
172
+ print(f" {name}:")
173
+ for method_name, method_info in methods.items():
174
+ print(f" {method_name}: {method_info}")
175
+
176
+ if failed:
177
+ print("\nFailed Classes:")
178
+ for name, error in failed.items():
179
+ print(f" {name}: {error}")
180
+
181
+ if __name__ == "__main__":
182
+ balance = AbstractBalance("re")
183
+ pump = AbstractPump("re")
184
+
185
+ _analyzer = ScriptAnalyzer()
186
+ module = sys.modules[__name__]
187
+ try:
188
+
189
+ result, with_warnings, failed, _ = _analyzer.analyze_module(module)
190
+
191
+ output_path = f"analysis.json"
192
+ _analyzer.save_to_json(result, output_path)
193
+
194
+ print(f"\nAnalysis complete! Results saved to: {output_path}")
195
+
196
+
197
+
198
+
199
+ _analyzer.print_deck_snapshot(result, with_warnings, failed)
200
+
201
+ except Exception as e:
202
+ print(f"Error: {e}")
203
+
@@ -72,10 +72,13 @@ class TaskRunner:
72
72
  output = function_executable(**kwargs)
73
73
  step.output = output
74
74
  step.end_time = datetime.now()
75
+ success = True
75
76
  except Exception as e:
76
77
  step.run_error = e.__str__()
77
78
  step.end_time = datetime.now()
79
+ success = False
80
+ output = e.__str__()
78
81
  finally:
79
82
  db.session.commit()
80
83
  self.lock.release()
81
- return output
84
+ return dict(success=success, output=output)
ivoryos/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "1.0.9"
1
+ __version__ = "1.2.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ivoryos
3
- Version: 1.0.9
3
+ Version: 1.2.0
4
4
  Summary: an open-source Python package enabling Self-Driving Labs (SDLs) interoperability
5
5
  Home-page: https://gitlab.com/heingroup/ivoryos
6
6
  Author: Ivory Zhang
@@ -48,7 +48,7 @@ With the least modification of the current workflow, user can design, manage and
48
48
  This software is developed and tested using Windows. This software and its dependencies are compatible across major platforms: Linux, macOS, and Windows. Some dependencies (Flask-SQLAlchemy) may require additional setup.
49
49
 
50
50
  ### Python Version
51
- Python >=3.7 for best compatibility.
51
+ Python >=3.10 for best compatibility. Python >=3.7 without Ax.
52
52
  ### Python dependencies
53
53
  This software is compatible with the latest versions of all dependencies.
54
54
  - bcrypt~=4.0
@@ -59,8 +59,7 @@ This software is compatible with the latest versions of all dependencies.
59
59
  - SQLAlchemy-Utils~=0.41
60
60
  - Flask-WTF~=1.2
61
61
  - python-dotenv==1.0.1
62
- - openai (optional ~=1.53)
63
- - ax-platform (optional ~=0.3 or ~=0.4 for Python>=3.9)
62
+ - ax-platform (optional ~=0.4 for Python>=3.9)
64
63
 
65
64
  ## Installation
66
65
  ```bash
@@ -70,7 +69,7 @@ or
70
69
  ```bash
71
70
  git clone https://gitlab.com/heingroup/ivoryos.git
72
71
  cd ivoryos
73
- pip install -e .
72
+ pip install .
74
73
  ```
75
74
 
76
75
  The installation may take 10 to 30 seconds to install. The installation time may vary and take up to several minutes, depending on the network speed, computer performance, and virtual environment settings.
@@ -98,7 +97,7 @@ Create an account and login (local database)
98
97
  [//]: # (![PyPI - Downloads](https://img.shields.io/pypi/dm/ivoryos))
99
98
 
100
99
 
101
- ### Additional settings
100
+ ### Additional settings (not actively maintained)
102
101
  #### AI assistant
103
102
  To streamline the experimental design on SDLs, we also integrate Large Language Models (LLMs) to interpret the inspected functions and generate code according to task descriptions.
104
103
 
@@ -150,8 +149,6 @@ ivoryos.run(__name__)
150
149
  ### Deck function and web form
151
150
  ![](https://gitlab.com/heingroup/ivoryos/raw/main/docs/source/_static/demo.gif)
152
151
 
153
- ### Text-to-code demo
154
- ![](https://gitlab.com/heingroup/ivoryos/raw/main/docs/source/_static/text-to-code.gif)
155
152
 
156
153
  ### Directory structure
157
154
 
@@ -0,0 +1,105 @@
1
+ ivoryos/__init__.py,sha256=p9m5csEeKgE7VJ_PPf-d50G5Q4A9aN2vRfJRJdi9Z4c,9149
2
+ ivoryos/config.py,sha256=sk4dskm-K_Nv4uaA3QuE6xtew8wL6q3HmIoLgRm7p8U,2153
3
+ ivoryos/socket_handlers.py,sha256=VWVWiIdm4jYAutwGu6R0t1nK5MuMyOCL0xAnFn06jWQ,1302
4
+ ivoryos/version.py,sha256=MpAT5hgNoHnTtG1XRD_GV_A7QrHVU6vJjGSw_8qMGA4,22
5
+ ivoryos/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ ivoryos/routes/api/api.py,sha256=X_aZMB_nCxW41pqZpJOiEEwGmlqLqJUArruevuy41v0,2284
7
+ ivoryos/routes/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ ivoryos/routes/auth/auth.py,sha256=SbtiMc1kFHDXIauvT1o3_8rJ-jVVz2C6hfKeSCmoXSE,3231
9
+ ivoryos/routes/auth/templates/login.html,sha256=WSRrKbdM_oobqSXFRTo-j9UlOgp6sYzS9tm7TqqPULI,1207
10
+ ivoryos/routes/auth/templates/signup.html,sha256=b5LTXtpfTSkSS7X8u1ldwQbbgEFTk6UNMAediA5BwBY,1465
11
+ ivoryos/routes/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ ivoryos/routes/control/control.py,sha256=Vmy3GRZz8EbKmV9qslR8gsaYaYzb5HQTpukp42HfMow,5236
13
+ ivoryos/routes/control/control_file.py,sha256=NIAzwhswvpl3u0mansy1ku-rPDybS5hVbmbnymOikWk,1548
14
+ ivoryos/routes/control/control_new_device.py,sha256=mfJKg5JAOagIpUKbp2b5nRwvd2V3bzT3M0zIhIsEaFM,5456
15
+ ivoryos/routes/control/utils.py,sha256=at11wA5HPAZN4BfMaymj1GKEvRTrqi4Wg6cTqUZJDjU,1155
16
+ ivoryos/routes/control/templates/controllers.html,sha256=tgtTuns8S2Pf6XKeojinQZ1bz112ieRGLPF5-1cElfE,8030
17
+ ivoryos/routes/control/templates/controllers_new.html,sha256=eVeLABT39DWOIYrwWClw7sAD3lCoAGCznygPgFbQoRc,5945
18
+ ivoryos/routes/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ ivoryos/routes/data/data.py,sha256=PhuTNlQptpqBZ_9cVCYN_PbM7LBma5BjvsDlZ5gpPxM,4186
20
+ ivoryos/routes/data/templates/workflow_database.html,sha256=ofvHcovpwmJXo1SFiSrL8I9kLU_3U1UxsJUUrQ2CJUU,4878
21
+ ivoryos/routes/data/templates/workflow_view.html,sha256=72xKreX9WhYx-0n0cFf-CL-fJIWXPCIaTi_Aa8Tq3xg,3651
22
+ ivoryos/routes/data/templates/components/step_card.html,sha256=9lKR4NCgU2v5Nbdv2uaJ-9aKibtiB_2-Y_kyHX6Ka1k,730
23
+ ivoryos/routes/design/__init__.py,sha256=zS3HXKaw0ALL5n6t_W1rUz5Uj5_tTQ-Y1VMXyzewvR0,113
24
+ ivoryos/routes/design/design.py,sha256=9xP6uOro4ZRzvVNJ0oVv9cc27LrQw06lLsxhgYTym9c,17711
25
+ ivoryos/routes/design/design_file.py,sha256=m4yku8fkpLUs4XvLJBqR5V-kyaGKbGB6ZoRxGbjEU5Q,2140
26
+ ivoryos/routes/design/design_step.py,sha256=l8U3-FuXmap__sYm51AueKdbTaLCFaKjAz-j02b4g-E,5200
27
+ ivoryos/routes/design/templates/experiment_builder.html,sha256=hh-d2tOc_40gww5WfUYIf8sM3qBaALZnR8Sx7Ja4tpU,1623
28
+ ivoryos/routes/design/templates/components/action_form.html,sha256=ktnmXVwe2WFLM6Sg_VbBfDrPXrnongSUxjpYhZGamPY,3058
29
+ ivoryos/routes/design/templates/components/actions_panel.html,sha256=jHTR58saTUIZInBdC-vLc1ZTbStLiULeWbupjB4hQzo,977
30
+ ivoryos/routes/design/templates/components/autofill_toggle.html,sha256=CRVQUHoQT7sOSO5-Vax54ImHdT4G_mEgqR5OQkeUwK8,617
31
+ ivoryos/routes/design/templates/components/canvas.html,sha256=bKLCJaG1B36Yy9Vsnz4P5qiX4BPdfaGe9JeQQzu9rsI,268
32
+ ivoryos/routes/design/templates/components/canvas_footer.html,sha256=5VRRacMZbzx0hUej0NPP-PmXM_AtUqduHzDS7a60cQY,435
33
+ ivoryos/routes/design/templates/components/canvas_header.html,sha256=7iIzLDGHX7MnmBbf98nWtLDprbeIgoNV4dJUO1zE4Tc,3598
34
+ ivoryos/routes/design/templates/components/canvas_main.html,sha256=9inYO700zRa09lfQI2NY4FJGGeTh-9rvX4ltjj0LK3k,1432
35
+ ivoryos/routes/design/templates/components/deck_selector.html,sha256=ryTRpljYezo0AzGLCJu_qOMokjjnft3GIxddmNGtBA0,657
36
+ ivoryos/routes/design/templates/components/edit_action_form.html,sha256=Dz7FnnOK4PYptAHNy9_WFCU1RZTSV61-1lNHHOSRJNs,1876
37
+ ivoryos/routes/design/templates/components/instruments_panel.html,sha256=r1jnScVRAknrRPRbAnIVApfnx9f4yavgf9ZlNhNpjW4,3135
38
+ ivoryos/routes/design/templates/components/modals.html,sha256=6Dl8I8oD4ln7kK8C5e92pFVVH5KDte-vVTL0U_6NSTg,306
39
+ ivoryos/routes/design/templates/components/python_code_overlay.html,sha256=GUHgsmUWQf0P1Fbg5W0OJC34TXCUIMQVUkS7KDoauyI,1264
40
+ ivoryos/routes/design/templates/components/sidebar.html,sha256=A6dRo53zIB6QJVrRLJcBZHUNJ3qpYPnR3kWxM8gTkjw,501
41
+ ivoryos/routes/design/templates/components/text_to_code_panel.html,sha256=d-omdXk-PXAR5AyWPr4Rc4pqsebZOiTiMrnz3pPCnUY,1197
42
+ ivoryos/routes/design/templates/components/modals/drop_modal.html,sha256=LPxcycSiBjdQbajYOegjMQEi7ValcaczGoWmW8Sz3Ms,779
43
+ ivoryos/routes/design/templates/components/modals/json_modal.html,sha256=R-SeEdhtuDVbwOWYYH_hCdpul7y4ybCWoNwVIO5j49s,1122
44
+ ivoryos/routes/design/templates/components/modals/new_script_modal.html,sha256=pxZdWWDgI52VsTFzz6pIM9m_dTwR6jARcvCYQ6fV3Lc,937
45
+ ivoryos/routes/design/templates/components/modals/rename_modal.html,sha256=40rLNF9JprdXekB3mv_S3OdqVuQYOe-BZSCgOnIkxJQ,1202
46
+ ivoryos/routes/design/templates/components/modals/saveas_modal.html,sha256=N5PEqUuK3qxDFbtDKFnzHwhLarQLPHiX-XQAdQPL1AU,1555
47
+ ivoryos/routes/execute/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ ivoryos/routes/execute/execute.py,sha256=hFnCvzO1OzR0XckCRzHfP_RZV70DtbH_p7kw1YhIe3o,12250
49
+ ivoryos/routes/execute/execute_file.py,sha256=TelWYV295p4ZPhkUDJSVxfYROfVaKodEmDPTS2plQHI,2816
50
+ ivoryos/routes/execute/templates/experiment_run.html,sha256=D-ek7ISQrIQXy4PH37TnsURihbGNdpCgdTC8w79cwQc,10355
51
+ ivoryos/routes/execute/templates/components/error_modal.html,sha256=5Dmp9V0Ys6781Y-pKn_mc4N9J46c8EwIkjkHX22xCsw,1025
52
+ ivoryos/routes/execute/templates/components/logging_panel.html,sha256=FllozlPd6o7uBd8eflGjRktPV435J3XgiEeLZugoUi0,1623
53
+ ivoryos/routes/execute/templates/components/progress_panel.html,sha256=-nX76aFLxSOiYgI1xMjznC9rDYF-Vb92TmfjXYpBtps,1323
54
+ ivoryos/routes/execute/templates/components/run_panel.html,sha256=CmK-LYJ4K6RonHn6l9eJkqRw0XQizThOugxiXZonSDs,373
55
+ ivoryos/routes/execute/templates/components/run_tabs.html,sha256=u-msoTQPBGvyE_5_UczRtR9bh7zD3EvsgJhT77rTzOI,1145
56
+ ivoryos/routes/execute/templates/components/tab_bayesian.html,sha256=5XTMHZzbGxcCZ2M0LSRqqmVh4qmu0R1MjCkT_FQ0ag0,21314
57
+ ivoryos/routes/execute/templates/components/tab_configuration.html,sha256=JIHsYvwcYQZmJJz503NXnhcceKxd9B3JKFUSvGNWe_0,5131
58
+ ivoryos/routes/execute/templates/components/tab_repeat.html,sha256=X-r7p78tVRrfwmAbhhZGBZbm78C4nTJS6O2A4dvzGEg,760
59
+ ivoryos/routes/library/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
+ ivoryos/routes/library/library.py,sha256=jook_OZRIO1nr3nBxU_X9yrDw5PSLqa0wrInI7GY6sg,5457
61
+ ivoryos/routes/library/templates/library.html,sha256=8pyKTc0TmrSSrwSVAYrh6cuPRHutg_yAA8mqzLFyZIg,3968
62
+ ivoryos/routes/main/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
+ ivoryos/routes/main/main.py,sha256=1AcSouCocHWjlpEED-ECn5OFiu0-3u0N-0st5RtKCVY,952
64
+ ivoryos/routes/main/templates/help.html,sha256=IOktMEsOPk0SCiMBXZ4mpffClERAyX8W82fel71M3M0,9370
65
+ ivoryos/routes/main/templates/home.html,sha256=BDvwkVthxniQ157H6E2hgYHT1Vv1GVBwu6dQejtzwoo,4633
66
+ ivoryos/static/favicon.ico,sha256=RhlrPtfITOkzC9BjP1UB1V5L9Oyp6NwNtWeMcGOnpyc,15406
67
+ ivoryos/static/logo.webp,sha256=lXgfQR-4mHTH83k7VV9iB54-oC2ipe6uZvbwdOnLETc,14974
68
+ ivoryos/static/style.css,sha256=zQVx35A5g6JMJ-K84-6fSKtzXGjp_p5ZVG6KLHPM2IE,4021
69
+ ivoryos/static/gui_annotation/Slide1.png,sha256=Lm4gdOkUF5HIUFaB94tl6koQVkzpitKj43GXV_XYMMc,121727
70
+ ivoryos/static/gui_annotation/Slide2.PNG,sha256=z3wQ9oVgg4JTWVLQGKK_KhtepRHUYP1e05XUWGT2A0I,118761
71
+ ivoryos/static/js/action_handlers.js,sha256=VEDox3gQvg0YXJ6WW6IthOsFqZKmvUGJ8pmQdfzHQFw,5122
72
+ ivoryos/static/js/db_delete.js,sha256=l67fqUaN_FVDaL7v91Hd7LyRbxnqXx9nyjF34-7aewY,561
73
+ ivoryos/static/js/overlay.js,sha256=dPxop19es0E0ZUSY3d_4exIk7CJuQEnlW5uTt5fZfzI,483
74
+ ivoryos/static/js/script_metadata.js,sha256=m8VYZ8OGT2oTx1kXMXq60bKQI9WCbJNkzcFDzLvRuGc,1188
75
+ ivoryos/static/js/socket_handler.js,sha256=2Iyv_3METjhSlSavs_L9FE3PKY4xDEpfzJpd2FywY9o,5300
76
+ ivoryos/static/js/sortable_card.js,sha256=ifmlGe3yy0U_KzMphV4ClRhK2DLOvkELYMlq1vECuac,807
77
+ ivoryos/static/js/sortable_design.js,sha256=QqYyk385JNm6zCgZK_Oa-cJEP1uPtZ_tVz27x4hyx5A,4790
78
+ ivoryos/static/js/ui_state.js,sha256=5EuqwIDndjZTqj9dsAR_IA91iGMcodY_TuQo17LLL1w,3331
79
+ ivoryos/templates/base.html,sha256=SdZswZmfLWehorMsoGkm-FjLFtB1ivLkdUJFbpDRqp4,8519
80
+ ivoryos/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
+ ivoryos/utils/bo_campaign.py,sha256=Fil-zT7JexL_p9XqyWByjAk42XB1R9XUKN8CdV5bi6c,9714
82
+ ivoryos/utils/client_proxy.py,sha256=0OT2xTMkqh_2ybgCxMV_71ZVUThWwrsnAhTIBY5vDR8,2095
83
+ ivoryos/utils/db_models.py,sha256=baE4LJcSGUj10Tj6imfINXi4JQX_4oLv_kb9bd0rp-M,27920
84
+ ivoryos/utils/form.py,sha256=eIk1N77Ynxc4Omww5ZYlmpOIJfQPWto2qfiU6nzIIeQ,21755
85
+ ivoryos/utils/global_config.py,sha256=zNO9GYhGn7El3msWoxJIm3S4Mzb3VMh2i5ZEsVtvb2Q,2463
86
+ ivoryos/utils/llm_agent.py,sha256=-lVCkjPlpLues9sNTmaT7bT4sdhWvV2DiojNwzB2Lcw,6422
87
+ ivoryos/utils/py_to_json.py,sha256=fyqjaxDHPh-sahgT6IHSn34ktwf6y51_x1qvhbNlH-U,7314
88
+ ivoryos/utils/script_runner.py,sha256=W4UL2iMt9bTBlb47pu2kc7SJyL9hlKzdtPudVZ9FvIM,16723
89
+ ivoryos/utils/serilize.py,sha256=Ded3Vbicl4KYN8GJ_gY7HJMuInAeFZEPk5ZtuEtHPns,6933
90
+ ivoryos/utils/task_runner.py,sha256=cDIcmDaqYh0vXoYaL_kO877pluAo2tyfsHl9OgZqJJE,3029
91
+ ivoryos/utils/utils.py,sha256=BzgKIMMb7vyUIwYMhGDsWtwJEy5vNKtEHRJHHSiTSnM,13881
92
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
93
+ tests/conftest.py,sha256=u2sQ6U-Lghyl7et1Oz6J2E5VZ47VINKcjRM_2leAE2s,3627
94
+ tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
+ tests/integration/test_route_auth.py,sha256=l3ZDqr0oiCWS3yYSXGK5yMP6qI2t7Sv5I9zoYTkiyQU,2754
96
+ tests/integration/test_route_control.py,sha256=YYIll84bTUEKiAxFiFSz6LF3fTldPNfCtHs0IR3mSdM,3935
97
+ tests/integration/test_route_database.py,sha256=mS026W_hEuCTMpSkdRWvM-f4MYykK_6nRDJ4K5a7QA0,2342
98
+ tests/integration/test_route_design.py,sha256=PJAvGRiCY6B53Pu1v5vPAVHHsuaqRmRKk2eesSNshLU,1157
99
+ tests/integration/test_route_main.py,sha256=bmuf8Y_9CRWhiLLf4up11ltEd5YCdsLx6I-o26VGDEw,1228
100
+ tests/integration/test_sockets.py,sha256=4ZyFyExm7a-DYzVqpzEONpWeb1a0IT68wyFaQu0rY_Y,925
101
+ ivoryos-1.2.0.dist-info/LICENSE,sha256=p2c8S8i-8YqMpZCJnadLz1-ofxnRMILzz6NCMIypRag,1084
102
+ ivoryos-1.2.0.dist-info/METADATA,sha256=EjG1H1CEgd3eiOshrWhkp2nw8SeoGQ7qB2SZiuxqf9Q,8834
103
+ ivoryos-1.2.0.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
104
+ ivoryos-1.2.0.dist-info/top_level.txt,sha256=mIOiZkdpSwxFJt1R5fsyOff8mNprXHq1nMGNKNULIyE,14
105
+ ivoryos-1.2.0.dist-info/RECORD,,
@@ -1,78 +0,0 @@
1
- {% extends 'base.html' %}
2
- {% block title %}IvoryOS | Controller for {{instrument}}{% endblock %}
3
- {% block body %}
4
- <div id="overlay" class="overlay">
5
- <div>
6
- <h3 id="overlay-text"></h3>
7
- <div class="spinner-border" role="status"></div>
8
- </div>
9
- </div>
10
- <h1>{{instrument}} controller</h1>
11
- {% set hidden = session.get('hidden_functions', {}) %}
12
- <div class="grid-container" id="sortable-grid">
13
- {% for function, form in forms.items() %}
14
-
15
- {% set hidden_instrument = hidden.get(instrument, []) %}
16
- {% if function not in hidden_instrument %}
17
- <div class="card" id="{{function}}">
18
- <div class="bg-white rounded shadow-sm flex-fill">
19
- <i class="bi bi-info-circle ms-2" data-bs-toggle="tooltip" data-bs-placement="top" title='{{ form.hidden_name.description or "Docstring is not available" }}' ></i>
20
- <a style="float: right" aria-label="Close" href="{{ url_for('control.hide_function', instrument=instrument, function=function) }}"><i class="bi bi-eye-slash-fill"></i></a>
21
- <div class="form-control" style="border: none">
22
- <form role="form" method='POST' name="{{function}}" id="{{function}}">
23
- <div class="form-group">
24
- {{ form.hidden_tag() }}
25
- {% for field in form %}
26
- {% if field.type not in ['CSRFTokenField', 'HiddenField'] %}
27
- <div class="input-group mb-3">
28
- <label class="input-group-text">{{ field.label.text }}</label>
29
- {% if field.type == "SubmitField" %}
30
- {{ field(class="btn btn-dark") }}
31
- {% elif field.type == "BooleanField" %}
32
- {{ field(class="form-check-input") }}
33
- {% else %}
34
- {{ field(class="form-control") }}
35
- {% endif %}
36
- </div>
37
- {% endif %}
38
- {% endfor %}
39
- </div>
40
- <div class="input-group mb-3">
41
- <button type="submit" name="{{ function }}" id="{{ function }}" class="form-control" style="background-color: #a5cece;">{{format_name(function)}} </button>
42
-
43
- </div>
44
-
45
- </form>
46
- </div>
47
- </div>
48
- </div>
49
- {% endif %}
50
- {% endfor %}
51
- </div>
52
- <div class="accordion accordion-flush" id="accordionActions" >
53
- <div class="accordion-item">
54
- <h4 class="accordion-header">
55
- <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#hidden">
56
- Hidden functions
57
- </button>
58
- </h4>
59
- </div>
60
- <div id="hidden" class="accordion-collapse collapse" data-bs-parent="#accordionActions">
61
- <div class="accordion-body">
62
- {% set hidden_instrument = hidden.get(instrument, []) %}
63
- {% for function in hidden_instrument %}
64
- <div>
65
- {{ function }} <a href="{{ url_for('control.remove_hidden', instrument=instrument, function=function) }}"><i class="bi bi-eye-fill"></i></a>
66
- </div>
67
- {% endfor %}
68
- </div>
69
- </div>
70
- </div>
71
-
72
- <script>
73
- const saveOrderUrl = `{{ url_for('control.save_order', instrument=instrument) }}`;
74
- const buttonIds = {{ session['card_order'][instrument] | tojson }};
75
- </script>
76
- <script src="{{ url_for('static', filename='js/sortable_card.js') }}"></script>
77
- <script src="{{ url_for('static', filename='js/overlay.js') }}"></script>
78
- {% endblock %}
@@ -1,55 +0,0 @@
1
- {% extends 'base.html' %}
2
- {% block title %}IvoryOS | Devices{% endblock %}
3
- {% block body %}
4
- <div class="row">
5
- {% if defined_variables %}
6
- {% for instrument in defined_variables %}
7
- <div class="col-xl-3 col-lg-4 col-md-6 mb-4 ">
8
- <div class="bg-white rounded shadow-sm position-relative">
9
- {% if deck %}
10
- {# <a href="{{ url_for('control.disconnect', instrument=instrument) }}" class="stretched-link controller-card" style="float: right;color: red; position: relative;">Disconnect <i class="bi bi-x-square"></i></a>#}
11
- <div class="p-4 controller-card">
12
- <h5 class=""><a href="{{ url_for('control.controllers', instrument=instrument) }}" class="text-dark stretched-link">{{instrument.split(".")[1]}}</a></h5>
13
- </div>
14
- {% else %}
15
- <div class="p-4 controller-card">
16
- <h5 class=""><a href="{{ url_for('control.controllers', instrument=instrument) }}" class="text-dark stretched-link">{{instrument}}</a></h5>
17
- </div>
18
- {% endif %}
19
- </div>
20
- </div>
21
- {% endfor %}
22
- <div class="d-flex mb-3">
23
- <a href="{{ url_for('control.download_proxy', filetype='proxy') }}" class="btn btn-outline-primary">
24
- <i class="bi bi-download"></i> Download remote control script
25
- </a>
26
- </div>
27
- {% if not deck %}
28
- <div class="col-xl-3 col-lg-4 col-md-6 mb-4 ">
29
- <div class="bg-white rounded shadow-sm position-relative">
30
- <div class="p-4 controller-card" >
31
- {% if deck %}
32
- {# todo disconnect for imported deck #}
33
- {# <h5> <a href="{{ url_for("disconnect") }}" class="stretched-link" style="color: orangered">Disconnect deck</a></h5>#}
34
- {% else %}
35
- <h5><a href="{{ url_for('control.new_controller') }}" style="color: orange" class="stretched-link">New connection</a></h5>
36
- {% endif %}
37
- </div>
38
- </div>
39
- </div>
40
- {% endif %}
41
- {% else %}
42
- <div class="col-xl-3 col-lg-4 col-md-6 mb-4 ">
43
- <div class="bg-white rounded shadow-sm position-relative">
44
- <div class="p-4 controller-card" >
45
- {% if deck %}
46
- <h5><a data-bs-toggle="modal" href="#importModal" class="stretched-link"><i class="bi bi-folder-plus"></i> Import deck </a></h5>
47
- {% else %}
48
- <h5><a href="{{ url_for('control.new_controller') }}" style="color: orange" class="stretched-link">New connection</a></h5>
49
- {% endif %}
50
- </div>
51
- </div>
52
- </div>
53
- {% endif %}
54
- </div>
55
- {% endblock %}
@@ -1,89 +0,0 @@
1
- {% extends 'base.html' %}
2
- {% block title %}IvoryOS | New devices{% endblock %}
3
-
4
- {% block body %}
5
- <div class="row">
6
- <div class="col-xl-4 col-lg-4 col-md-6 mb-4 ">
7
- <h5>Available Python API</h5>
8
- <hr>
9
- {% for instrument in api_variables %}
10
- <div class="bg-white rounded shadow-sm position-relative">
11
- <h5 class="p-3 controller-card">
12
- <a href="{{ url_for('control.new_controller', instrument=instrument) }}" class="text-dark stretched-link">{{instrument}}</a>
13
- </h5>
14
- </div>
15
- {% endfor %}
16
- <div class="bg-white rounded shadow-sm position-relative">
17
- <h5 class="p-3 controller-card">
18
- <a data-bs-toggle="modal" href="#importAPI" class="stretched-link"><i class="bi bi-folder-plus"></i> Import API</a>
19
- </h5>
20
- </div>
21
- </div>
22
- <div class="col-xl-5 col-lg-5 col-md-6 mb-4 ">
23
- {% if device %}
24
- <h5>Connecting</h5><hr>
25
- <form role="form" method='POST' name="init" action="{{ url_for('control.new_controller', instrument=instrument) }}">
26
- <div class="form-group">
27
- <div class="input-group mb-3">
28
- <span class="input-group-text" >Name this device</span>
29
- <input class="form-control" type="text" id="device_name" name="device_name" aria-labelledby="nameHelpBlock" placeholder="e.g. {{device.__name__}}_1" >
30
- <div id="nameHelpBlock" class="form-text">
31
- Name your instrument, avoid names that are defined on the right
32
- </div>
33
- </div>
34
- {% for arg in device.__init__.__annotations__ %}
35
- {% if not arg == "return" %}
36
- <div class="input-group mb-3">
37
- <span class="input-group-text" >{{arg}}</span>
38
- <input class="form-control" type="text" id="{{arg}}" name="{{arg}}"
39
- placeholder="{{device.__init__.__annotations__[arg].__name__}}"
40
- value="{{args.parameters[arg].default if not args.parameters[arg].default.__name__ == '_empty' else ''}}">
41
- {% if device.__init__.__annotations__[arg].__module__ is not in ["builtins", "typing"] %}
42
- <a role="button" href="{{ url_for('control.new_controller', instrument=device.__init__.__annotations__[arg].__name__) }}" class="btn btn-secondary">initialize {{device.__init__.__annotations__[arg].__name__}} first</a>
43
- {% endif %}
44
- </div>
45
- {% endif %}
46
- {% endfor %}
47
- <button type="submit" class="btn btn-dark">Connect</button>
48
- </div>
49
- </form>
50
- {% endif %}
51
- </div>
52
- <div class="col-xl-3 col-lg-3 col-md-6 mb-4">
53
- <h5>Defined Instruments</h5><hr>
54
- {% if defined_variables %}
55
- <ul class="list-group">
56
- {% for instrument in defined_variables %}
57
- <li class="list-group-item">{{instrument}}</li>
58
- {% endfor %}
59
- </ul>
60
- {% endif %}
61
- </div>
62
- </div>
63
-
64
-
65
- <div class="modal fade" id="importAPI" tabindex="-1" aria-labelledby="importModal" aria-hidden="true" >
66
- <div class="modal-dialog">
67
- <div class="modal-content">
68
- <div class="modal-header">
69
- <h1 class="modal-title fs-5" id="importModal">Import API by file path</h1>
70
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
71
- </div>
72
- <form method="POST" action="{{ url_for('control.import_api') }}" enctype="multipart/form-data">
73
- <div class="modal-body">
74
- <h5>input manually</h5>
75
- <div class="input-group mb-3">
76
- <label class="input-group-text" for="filepath">File Path:</label>
77
- <input type="text" class="form-control" name="filepath" id="filepath">
78
- </div>
79
- <div class="modal-footer">
80
- <button type="button" class="btn btn-secondary" data-bs-dismiss="modal"> Close </button>
81
- <button type="submit" class="btn btn-primary"> Save </button>
82
- </div>
83
- </div>
84
- </form>
85
- </div>
86
- </div>
87
- </div>
88
-
89
- {% endblock %}