ivoryos 1.2.0b1__py3-none-any.whl → 1.2.2__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 (82) hide show
  1. ivoryos/__init__.py +22 -1
  2. ivoryos/config.py +1 -0
  3. ivoryos/optimizer/ax_optimizer.py +164 -0
  4. ivoryos/optimizer/base_optimizer.py +65 -0
  5. ivoryos/optimizer/baybe_optimizer.py +183 -0
  6. ivoryos/optimizer/registry.py +9 -0
  7. ivoryos/routes/auth/auth.py +3 -1
  8. ivoryos/routes/data/data.py +2 -0
  9. ivoryos/routes/design/design.py +4 -4
  10. ivoryos/routes/library/library.py +4 -4
  11. ivoryos/utils/script_runner.py +1 -1
  12. ivoryos/utils/serilize.py +4 -6
  13. ivoryos/utils/utils.py +2 -1
  14. ivoryos/version.py +1 -1
  15. {ivoryos-1.2.0b1.dist-info → ivoryos-1.2.2.dist-info}/METADATA +60 -35
  16. ivoryos-1.2.2.dist-info/RECORD +47 -0
  17. {ivoryos-1.2.0b1.dist-info → ivoryos-1.2.2.dist-info}/WHEEL +1 -1
  18. {ivoryos-1.2.0b1.dist-info → ivoryos-1.2.2.dist-info}/top_level.txt +0 -1
  19. ivoryos/routes/auth/templates/login.html +0 -25
  20. ivoryos/routes/auth/templates/signup.html +0 -32
  21. ivoryos/routes/control/templates/controllers.html +0 -166
  22. ivoryos/routes/control/templates/controllers_new.html +0 -112
  23. ivoryos/routes/data/templates/components/step_card.html +0 -13
  24. ivoryos/routes/data/templates/workflow_database.html +0 -109
  25. ivoryos/routes/data/templates/workflow_view.html +0 -130
  26. ivoryos/routes/design/templates/components/action_form.html +0 -53
  27. ivoryos/routes/design/templates/components/actions_panel.html +0 -25
  28. ivoryos/routes/design/templates/components/autofill_toggle.html +0 -10
  29. ivoryos/routes/design/templates/components/canvas.html +0 -5
  30. ivoryos/routes/design/templates/components/canvas_footer.html +0 -9
  31. ivoryos/routes/design/templates/components/canvas_header.html +0 -75
  32. ivoryos/routes/design/templates/components/canvas_main.html +0 -34
  33. ivoryos/routes/design/templates/components/deck_selector.html +0 -10
  34. ivoryos/routes/design/templates/components/edit_action_form.html +0 -38
  35. ivoryos/routes/design/templates/components/instruments_panel.html +0 -66
  36. ivoryos/routes/design/templates/components/modals/drop_modal.html +0 -17
  37. ivoryos/routes/design/templates/components/modals/json_modal.html +0 -22
  38. ivoryos/routes/design/templates/components/modals/new_script_modal.html +0 -17
  39. ivoryos/routes/design/templates/components/modals/rename_modal.html +0 -23
  40. ivoryos/routes/design/templates/components/modals/saveas_modal.html +0 -27
  41. ivoryos/routes/design/templates/components/modals.html +0 -6
  42. ivoryos/routes/design/templates/components/python_code_overlay.html +0 -39
  43. ivoryos/routes/design/templates/components/sidebar.html +0 -15
  44. ivoryos/routes/design/templates/components/text_to_code_panel.html +0 -20
  45. ivoryos/routes/design/templates/experiment_builder.html +0 -41
  46. ivoryos/routes/execute/templates/components/error_modal.html +0 -20
  47. ivoryos/routes/execute/templates/components/logging_panel.html +0 -31
  48. ivoryos/routes/execute/templates/components/progress_panel.html +0 -27
  49. ivoryos/routes/execute/templates/components/run_panel.html +0 -9
  50. ivoryos/routes/execute/templates/components/run_tabs.html +0 -17
  51. ivoryos/routes/execute/templates/components/tab_bayesian.html +0 -399
  52. ivoryos/routes/execute/templates/components/tab_configuration.html +0 -98
  53. ivoryos/routes/execute/templates/components/tab_repeat.html +0 -14
  54. ivoryos/routes/execute/templates/experiment_run.html +0 -294
  55. ivoryos/routes/library/templates/library.html +0 -91
  56. ivoryos/routes/main/templates/help.html +0 -141
  57. ivoryos/routes/main/templates/home.html +0 -103
  58. ivoryos/static/favicon.ico +0 -0
  59. ivoryos/static/gui_annotation/Slide1.png +0 -0
  60. ivoryos/static/gui_annotation/Slide2.PNG +0 -0
  61. ivoryos/static/js/action_handlers.js +0 -213
  62. ivoryos/static/js/db_delete.js +0 -23
  63. ivoryos/static/js/overlay.js +0 -12
  64. ivoryos/static/js/script_metadata.js +0 -39
  65. ivoryos/static/js/socket_handler.js +0 -125
  66. ivoryos/static/js/sortable_card.js +0 -24
  67. ivoryos/static/js/sortable_design.js +0 -138
  68. ivoryos/static/js/ui_state.js +0 -113
  69. ivoryos/static/logo.webp +0 -0
  70. ivoryos/static/style.css +0 -211
  71. ivoryos/templates/base.html +0 -157
  72. ivoryos-1.2.0b1.dist-info/RECORD +0 -105
  73. tests/__init__.py +0 -0
  74. tests/conftest.py +0 -133
  75. tests/integration/__init__.py +0 -0
  76. tests/integration/test_route_auth.py +0 -80
  77. tests/integration/test_route_control.py +0 -94
  78. tests/integration/test_route_database.py +0 -61
  79. tests/integration/test_route_design.py +0 -36
  80. tests/integration/test_route_main.py +0 -35
  81. tests/integration/test_sockets.py +0 -26
  82. {ivoryos-1.2.0b1.dist-info → ivoryos-1.2.2.dist-info/licenses}/LICENSE +0 -0
@@ -1,11 +1,11 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: ivoryos
3
- Version: 1.2.0b1
3
+ Version: 1.2.2
4
4
  Summary: an open-source Python package enabling Self-Driving Labs (SDLs) interoperability
5
- Home-page: https://gitlab.com/heingroup/ivoryos
6
- Author: Ivory Zhang
7
- Author-email: ivoryzhang@chem.ubc.ca
5
+ Author-email: Ivory Zhang <ivoryzhang@chem.ubc.ca>
8
6
  License: MIT
7
+ Project-URL: Homepage, https://gitlab.com/heingroup/ivoryos
8
+ Requires-Python: >=3.7
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
11
  Requires-Dist: bcrypt
@@ -17,6 +17,10 @@ Requires-Dist: Flask-WTF
17
17
  Requires-Dist: SQLAlchemy-Utils
18
18
  Requires-Dist: python-dotenv
19
19
  Requires-Dist: astor; python_version < "3.9"
20
+ Provides-Extra: optimizer
21
+ Requires-Dist: ax-platform; extra == "optimizer"
22
+ Requires-Dist: baybe; extra == "optimizer"
23
+ Dynamic: license-file
20
24
 
21
25
  [![Documentation Status](https://readthedocs.org/projects/ivoryos/badge/?version=latest)](https://ivoryos.readthedocs.io/en/latest/?badge=latest)
22
26
  [![PyPI version](https://img.shields.io/pypi/v/ivoryos)](https://pypi.org/project/ivoryos/)
@@ -48,7 +52,7 @@ With the least modification of the current workflow, user can design, manage and
48
52
  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
53
 
50
54
  ### Python Version
51
- Python >=3.10 for best compatibility. Python >=3.7 without Ax.
55
+ Python >=3.10 for the best compatibility. Python >=3.7 without Ax.
52
56
  ### Python dependencies
53
57
  This software is compatible with the latest versions of all dependencies.
54
58
  - bcrypt~=4.0
@@ -59,7 +63,9 @@ This software is compatible with the latest versions of all dependencies.
59
63
  - SQLAlchemy-Utils~=0.41
60
64
  - Flask-WTF~=1.2
61
65
  - python-dotenv==1.0.1
62
- - ax-platform (optional ~=0.4 for Python>=3.9)
66
+ - ax-platform (optional 1.0 for Python>=3.10)
67
+ - baybe (optional)
68
+
63
69
 
64
70
  ## Installation
65
71
  ```bash
@@ -83,43 +89,60 @@ import ivoryos
83
89
  ivoryos.run(__name__)
84
90
  ```
85
91
  ### Login
86
- Create an account and login (local database)
92
+ Create an account and login (local database with bcrypt password)
87
93
  ### Features
88
- - **Direct control**: direct function calling _Device_ tab
89
- - **Workflow design and iteration**:
90
- - **Design**: add function to canvas in _Design_ tab. click `Compile and Run` button to go to the execution page
91
- - **Execution**: configure iteration methods and parameters in _Compile/Run_ tab.
92
- - **Database**: manage workflows in _Library_ tab.
93
- - **Info page**: additional info in _About_ tab.
94
+ - **Direct control**: direct function calling _Devices_ tab
95
+ - **Workflows**:
96
+ - **Design Editor**: drag/add function to canvas in _Design_ tab. click `Compile and Run` button to go to the execution configuration page
97
+ - **Execution Config**: configure iteration methods and parameters in _Compile/Run_ tab.
98
+ - **Design Library**: manage workflow scripts in _Library_ tab.
99
+ - **Workflow Data**: Execution records are in _Data_ tab.
94
100
 
95
101
  [//]: # (![Discord]&#40;https://img.shields.io/discord/1313641159356059770&#41;)
96
102
 
97
103
  [//]: # (![PyPI - Downloads]&#40;https://img.shields.io/pypi/dm/ivoryos&#41;)
98
104
 
99
105
 
100
- ### Additional settings (not actively maintained)
101
- #### AI assistant
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.
106
+ ### Additional settings
107
+ [//]: # (#### AI assistant)
103
108
 
104
- #### Enable LLMs with [OpenAI API](https://github.com/openai/openai-python)
105
- 1. Create a `.env` file for `OPENAI_API_KEY`
106
- ```
107
- OPENAI_API_KEY="Your API Key"
108
- ```
109
- 2. In your SDL script, define model, you can use any GPT models.
109
+ [//]: # (To streamline the experimental design on SDLs, we also integrate Large Language Models &#40;LLMs&#41; to interpret the inspected functions and generate code according to task descriptions.)
110
110
 
111
- ```python
112
- ivoryos.run(__name__, model="gpt-3.5-turbo")
113
- ```
111
+ [//]: # ()
112
+ [//]: # (#### Enable LLMs with [OpenAI API]&#40;https://github.com/openai/openai-python&#41;)
114
113
 
115
- #### Enable local LLMs with [Ollama](https://ollama.com/)
116
- 1. Download Ollama.
117
- 2. pull models from Ollama
118
- 3. In your SDL script, define LLM server and model, you can use any models available on Ollama.
114
+ [//]: # (1. Create a `.env` file for `OPENAI_API_KEY`)
119
115
 
120
- ```python
121
- ivoryos.run(__name__, llm_server="localhost", model="llama3.1")
122
- ```
116
+ [//]: # (```)
117
+
118
+ [//]: # (OPENAI_API_KEY="Your API Key")
119
+
120
+ [//]: # (```)
121
+
122
+ [//]: # (2. In your SDL script, define model, you can use any GPT models.)
123
+
124
+ [//]: # ()
125
+ [//]: # (```python)
126
+
127
+ [//]: # (ivoryos.run&#40;__name__, model="gpt-3.5-turbo"&#41;)
128
+
129
+ [//]: # (```)
130
+
131
+ [//]: # ()
132
+ [//]: # (#### Enable local LLMs with [Ollama]&#40;https://ollama.com/&#41;)
133
+
134
+ [//]: # (1. Download Ollama.)
135
+
136
+ [//]: # (2. pull models from Ollama)
137
+
138
+ [//]: # (3. In your SDL script, define LLM server and model, you can use any models available on Ollama.)
139
+
140
+ [//]: # ()
141
+ [//]: # (```python)
142
+
143
+ [//]: # (ivoryos.run&#40;__name__, llm_server="localhost", model="llama3.1"&#41;)
144
+
145
+ [//]: # (```)
123
146
 
124
147
  #### Add additional logger(s)
125
148
  ```python
@@ -144,7 +167,7 @@ ivoryos.run(__name__)
144
167
 
145
168
  * Running on all addresses (0.0.0.0)
146
169
  * Running on http://127.0.0.1:8000
147
- * Running on http://xxx.xx.xx.xxx:8000
170
+ * Running on http://0.0.0.0:8000
148
171
 
149
172
  ### Deck function and web form
150
173
  ![](https://gitlab.com/heingroup/ivoryos/raw/main/docs/source/_static/demo.gif)
@@ -172,6 +195,8 @@ When you run the application for the first time, it will automatically create th
172
195
  - [x] dropdown input ✅
173
196
  - [x] show line number option ✅
174
197
  - [ ] snapshot version control
198
+ - [ ] optimizer-agnostic
199
+ - [ ] check batch-config file compatibility
175
200
 
176
201
  ## Citing
177
202
 
@@ -212,4 +237,4 @@ For an additional perspective related to the development of the tool, please see
212
237
  ## Authors and Acknowledgement
213
238
  Ivory Zhang, Lucy Hao
214
239
 
215
- Authors acknowledge all former and current Hein Lab members for their valuable suggestions.
240
+ Authors acknowledge Telescope Innovations, Hein Lab members for their valuable suggestions and contributions.
@@ -0,0 +1,47 @@
1
+ ivoryos/__init__.py,sha256=x4PnDTbhx1ZTugfuclGQ03GO3yidAfiUFU7vuGyKD8M,9830
2
+ ivoryos/config.py,sha256=y3RxNjiIola9tK7jg-mHM8EzLMwiLwOzoisXkDvj0gA,2174
3
+ ivoryos/socket_handlers.py,sha256=VWVWiIdm4jYAutwGu6R0t1nK5MuMyOCL0xAnFn06jWQ,1302
4
+ ivoryos/version.py,sha256=uuf4VNtTNA93fMhoAur9YafzaKJFnczY-H1SSCSuRVQ,22
5
+ ivoryos/optimizer/ax_optimizer.py,sha256=PoSu8hrDFFpqyhRBnaSMswIUsDfEX6sPWt8NEZ_sobs,7112
6
+ ivoryos/optimizer/base_optimizer.py,sha256=JTbUharZKn0t8_BDbAFuwZIbT1VOnX1Xuog1pJuU8hY,1992
7
+ ivoryos/optimizer/baybe_optimizer.py,sha256=EdrrRiYO-IOx610cPXiQhH4qG8knUP0uiZ0YoyaGIU8,7954
8
+ ivoryos/optimizer/registry.py,sha256=lr0cqdI2iEjw227ZPRpVkvsdYdddjeJJRzawDv77cEc,219
9
+ ivoryos/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ ivoryos/routes/api/api.py,sha256=X_aZMB_nCxW41pqZpJOiEEwGmlqLqJUArruevuy41v0,2284
11
+ ivoryos/routes/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ ivoryos/routes/auth/auth.py,sha256=CqoP9cM8BuXVGHGujX7-0sNAOdWILU9amyBrObOD6Ss,3283
13
+ ivoryos/routes/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ ivoryos/routes/control/control.py,sha256=Vmy3GRZz8EbKmV9qslR8gsaYaYzb5HQTpukp42HfMow,5236
15
+ ivoryos/routes/control/control_file.py,sha256=NIAzwhswvpl3u0mansy1ku-rPDybS5hVbmbnymOikWk,1548
16
+ ivoryos/routes/control/control_new_device.py,sha256=mfJKg5JAOagIpUKbp2b5nRwvd2V3bzT3M0zIhIsEaFM,5456
17
+ ivoryos/routes/control/utils.py,sha256=at11wA5HPAZN4BfMaymj1GKEvRTrqi4Wg6cTqUZJDjU,1155
18
+ ivoryos/routes/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ ivoryos/routes/data/data.py,sha256=AoqCaIAK0f9hstF1pxlJFeK_J-wKbMfXWGNDUbaBFFk,4218
20
+ ivoryos/routes/design/__init__.py,sha256=zS3HXKaw0ALL5n6t_W1rUz5Uj5_tTQ-Y1VMXyzewvR0,113
21
+ ivoryos/routes/design/design.py,sha256=F5X0Wa1sXSdolQ8w87wQBv6bN7jMwCnQ4jX8r4SkO24,17763
22
+ ivoryos/routes/design/design_file.py,sha256=m4yku8fkpLUs4XvLJBqR5V-kyaGKbGB6ZoRxGbjEU5Q,2140
23
+ ivoryos/routes/design/design_step.py,sha256=l8U3-FuXmap__sYm51AueKdbTaLCFaKjAz-j02b4g-E,5200
24
+ ivoryos/routes/execute/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ ivoryos/routes/execute/execute.py,sha256=hFnCvzO1OzR0XckCRzHfP_RZV70DtbH_p7kw1YhIe3o,12250
26
+ ivoryos/routes/execute/execute_file.py,sha256=TelWYV295p4ZPhkUDJSVxfYROfVaKodEmDPTS2plQHI,2816
27
+ ivoryos/routes/library/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ ivoryos/routes/library/library.py,sha256=ZruIoaa06GlqpvJ383PSDEFdlPJFl2E2YI0H8aK7Hc0,5477
29
+ ivoryos/routes/main/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ ivoryos/routes/main/main.py,sha256=1AcSouCocHWjlpEED-ECn5OFiu0-3u0N-0st5RtKCVY,952
31
+ ivoryos/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ ivoryos/utils/bo_campaign.py,sha256=Fil-zT7JexL_p9XqyWByjAk42XB1R9XUKN8CdV5bi6c,9714
33
+ ivoryos/utils/client_proxy.py,sha256=0OT2xTMkqh_2ybgCxMV_71ZVUThWwrsnAhTIBY5vDR8,2095
34
+ ivoryos/utils/db_models.py,sha256=baE4LJcSGUj10Tj6imfINXi4JQX_4oLv_kb9bd0rp-M,27920
35
+ ivoryos/utils/form.py,sha256=eIk1N77Ynxc4Omww5ZYlmpOIJfQPWto2qfiU6nzIIeQ,21755
36
+ ivoryos/utils/global_config.py,sha256=zNO9GYhGn7El3msWoxJIm3S4Mzb3VMh2i5ZEsVtvb2Q,2463
37
+ ivoryos/utils/llm_agent.py,sha256=-lVCkjPlpLues9sNTmaT7bT4sdhWvV2DiojNwzB2Lcw,6422
38
+ ivoryos/utils/py_to_json.py,sha256=fyqjaxDHPh-sahgT6IHSn34ktwf6y51_x1qvhbNlH-U,7314
39
+ ivoryos/utils/script_runner.py,sha256=g3_pLYcu6gF9sPjhW9WRlwMH7ScDpz_MqMJzxNayfyg,16725
40
+ ivoryos/utils/serilize.py,sha256=lkBhkz8r2bLmz2_xOb0c4ptSSOqjIu6krj5YYK4Nvj8,6784
41
+ ivoryos/utils/task_runner.py,sha256=cDIcmDaqYh0vXoYaL_kO877pluAo2tyfsHl9OgZqJJE,3029
42
+ ivoryos/utils/utils.py,sha256=-WiU0_brszB9yDsiQepf_7SzNgPTSpul2RSKDOY3pqo,13921
43
+ ivoryos-1.2.2.dist-info/licenses/LICENSE,sha256=p2c8S8i-8YqMpZCJnadLz1-ofxnRMILzz6NCMIypRag,1084
44
+ ivoryos-1.2.2.dist-info/METADATA,sha256=vvueQx-kWo57d7AvBCDtUp28Ot_DBmgeTaZ6HVNS3ec,9416
45
+ ivoryos-1.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
46
+ ivoryos-1.2.2.dist-info/top_level.txt,sha256=FRIWWdiEvRKqw-XfF_UK3XV0CrnNb6EmVbEgjaVazRM,8
47
+ ivoryos-1.2.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.45.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,25 +0,0 @@
1
- {% extends 'base.html' %}
2
- {% block title %}IvoryOS | Login{% endblock %}
3
-
4
-
5
- {% block body %}
6
- <div class= "login">
7
- <div class="bg-white rounded shadow-sm flex-fill">
8
- <div class="p-4" style="align-items: center">
9
- <h5>Log in</h5>
10
- <form role="form" method='POST' name="login" action="{{ url_for('auth.login') }}">
11
- <div class="input-group mb-3">
12
- <label class="input-group-text" for="username">Username</label>
13
- <input class="form-control" type="text" id="username" name="username">
14
- </div>
15
- <div class="input-group mb-3">
16
- <label class="input-group-text" for="password">Password</label>
17
- <input class="form-control" type="password" id="password" name="password">
18
- </div>
19
- <button type="submit" class="btn btn-secondary" name="login" style="width: 100%;">login</button>
20
- </form>
21
- <p class="message">Not registered? <a href="{{ url_for('auth.signup') }}">Create a new account</a>
22
- </div>
23
- </div>
24
- </div>
25
- {% endblock %}
@@ -1,32 +0,0 @@
1
- {% extends 'base.html' %}
2
- {% block title %}IvoryOS | Signup{% endblock %}
3
-
4
-
5
- {% block body %}
6
- <div class= "login">
7
- <div class="bg-white rounded shadow-sm flex-fill">
8
- <div class="p-4" style="align: center">
9
- <h5>Create a new account</h5>
10
- <form role="form" method='POST' name="signup" action="{{ url_for('auth.signup') }}">
11
-
12
- <div class="input-group mb-3">
13
- <label class="input-group-text" for="username">Username</label>
14
- <input class="form-control" type="text" id="username" name="username" required>
15
- </div>
16
- <div class="input-group mb-3">
17
- <label class="input-group-text" for="password">Password</label>
18
- <input class="form-control" type="password" id="password" name="password" required>
19
- </div>
20
- {# <div class="input-group mb-3">#}
21
- {# <label class="input-group-text" for="confirm_password">Confirm Password</label>#}
22
- {# <input class="form-control" type="confirm_password" id="confirm_password" name="confirm_password">#}
23
- {# </div>#}
24
-
25
- <button type="submit" class="btn btn-secondary" name="login" style="width: 100%;">Sign up</button>
26
- </form>
27
- <p class="message" >Already registered? <a href="{{ url_for('auth.login') }}">Sign In</a></p>
28
- </div>
29
- </div>
30
- </div>
31
-
32
- {% endblock %}
@@ -1,166 +0,0 @@
1
- {% extends 'base.html' %}
2
- {% block title %}IvoryOS | Controllers {% endblock %}
3
-
4
- {% block body %}
5
- <div id="overlay" class="overlay">
6
- <div>
7
- <h3 id="overlay-text"></h3>
8
- <div class="spinner-border" role="status"></div>
9
- </div>
10
- </div>
11
- <div class="container-fluid">
12
- <div class="row">
13
- <!-- Sidebar: Instruments -->
14
- <nav class="col-md-3 col-lg-2 d-md-block bg-light sidebar py-3" style="height: 100vh; overflow-y: auto; position: sticky; top: 0;">
15
- <div class="sidebar-sticky">
16
- <!-- Deck Instruments -->
17
- <div class="mb-4">
18
- <div class="list-group">
19
- {% for inst in defined_variables %}
20
- <a class="list-group-item list-group-item-action d-flex align-items-center {% if instrument == inst %}active bg-primary text-white border-0{% else %}bg-light{% endif %}"
21
- href="{{ url_for('control.deck_controllers') }}?instrument={{ inst }}"
22
- style="border-radius: 0.5rem; margin-bottom: 0.5rem; transition: background 0.2s;">
23
- <span class="flex-grow-1">{{ inst | format_name }}</span>
24
- {% if instrument == inst %}
25
- <span class="ms-auto">&gt;</span>
26
- {% endif %}
27
- </a>
28
- {% endfor %}
29
- </div>
30
- </div>
31
-
32
-
33
-
34
- <!-- Temp Instruments -->
35
- {% if temp_variables %}
36
- <div class="mb-4">
37
- <h6 class="fw-bold text-secondary mb-2" style="letter-spacing: 1px;">Temp Instruments</h6>
38
- <div class="list-group">
39
- {% for inst in temp_variables %}
40
- <a class="list-group-item list-group-item-action d-flex align-items-center {% if instrument == inst %}active bg-warning text-dark border-0{% else %}bg-light{% endif %}"
41
- href="{{ url_for('control.deck_controllers') }}?instrument={{ inst }}"
42
- style="border-radius: 0.5rem; margin-bottom: 0.5rem; transition: background 0.2s;">
43
- <span class="flex-grow-1">{{ inst | format_name }}</span>
44
- {% if instrument == inst %}
45
- <span class="ms-auto">&gt;</span>
46
- {% endif %}
47
- </a>
48
- {% endfor %}
49
- </div>
50
- </div>
51
- {% endif %}
52
- <!-- Action Buttons -->
53
- <div class="mb-4">
54
- <a href="{{ url_for('control.file.download_proxy', filetype='proxy') }}" class="btn btn-outline-primary w-100 mb-2">
55
- Download proxy
56
- </a>
57
- <a href="{{ url_for('control.temp.new_controller') }}" class="btn btn-outline-success w-100">
58
- New connection
59
- </a>
60
- </div>
61
- </div>
62
- </nav>
63
-
64
- <!-- Main: Method Cards -->
65
- <main class="col-md-9 ms-sm-auto col-lg-10 px-md-4" style="height: 100vh; overflow-y: auto;">
66
- {% if instrument%}
67
- {# <h2 class="text-secondary">{{ instrument }} controller</h2>#}
68
- <div class="grid-container" id="sortable-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 1rem; width: 100%;">
69
- {% set hidden = session.get('hidden_functions', {}) %}
70
- {% set hidden_instrument = hidden.get(instrument, []) %}
71
- {% for function, form in forms.items() %}
72
- {% if function not in hidden_instrument %}
73
- <div class="card" id="{{function}}" style="margin: 0;">
74
- <div class="bg-white rounded shadow-sm h-100">
75
- <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>
76
- <a href="{{ url_for('control.hide_function', instrument=instrument, function=function) }}"
77
- data-method="patch" data-payload='{"hidden":true}' class="toggle-visibility">
78
- <i style="float: right;" class="bi bi-eye-slash-fill text-muted" title="Hide function"></i>
79
- </a>
80
- <div class="form-control" style="border: none">
81
- <form role="form" method='POST' name="{{function}}" id="{{function}}" action="{{ url_for('control.deck_controllers') }}?instrument={{ instrument }}">
82
- <div class="form-group">
83
- {{ form.hidden_tag() }}
84
- {% for field in form %}
85
- {% if field.type not in ['CSRFTokenField', 'HiddenField'] %}
86
- <div class="input-group mb-3">
87
- <label class="input-group-text">{{ field.label.text | format_name }}</label>
88
- {% if field.type == "SubmitField" %}
89
- {{ field(class="btn btn-dark") }}
90
- {% elif field.type == "BooleanField" %}
91
- {{ field(class="form-check-input") }}
92
- {% else %}
93
- {{ field(class="form-control") }}
94
- {% endif %}
95
- </div>
96
- {% endif %}
97
- {% endfor %}
98
- </div>
99
- <div class="input-group mb-3">
100
- <button type="submit" name="{{ function }}" id="{{ function }}" class="form-control" style="background-color: #a5cece;">
101
- {{ function | format_name }}
102
- </button>
103
- </div>
104
- </form>
105
- </div>
106
- </div>
107
- </div>
108
- {% endif %}
109
- {% endfor %}
110
- </div>
111
- <!-- Hidden functions accordion -->
112
- <div class="accordion accordion-flush" id="accordionActions" >
113
- <div class="accordion-item">
114
- <h4 class="accordion-header">
115
- <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#hidden">
116
- Hidden functions
117
- </button>
118
- </h4>
119
- </div>
120
- <div id="hidden" class="accordion-collapse collapse" data-bs-parent="#accordionActions">
121
- <div class="accordion-body">
122
- {% for function in hidden_instrument %}
123
- <div>
124
- {{ function }}
125
- <a href="{{ url_for('control.hide_function', instrument=instrument, function=function) }}"
126
- data-method="patch" data-payload='{"hidden":false}' class="toggle-visibility">
127
- <i class="bi bi-eye-fill text-success" title="Show function"></i>
128
- </a>
129
- </div>
130
- {% endfor %}
131
- </div>
132
- </div>
133
- </div>
134
- <script>
135
-
136
- document.querySelectorAll('.toggle-visibility').forEach(el => {
137
- el.addEventListener('click', e => {
138
- e.preventDefault();
139
- const url = el.getAttribute('href');
140
- const payload = JSON.parse(el.getAttribute('data-payload') || '{}');
141
- fetch(url, {
142
- method: 'PATCH',
143
- headers: {
144
- 'Content-Type': 'application/json'
145
- },
146
- body: JSON.stringify(payload)
147
- }).then(response => {
148
- if (response.ok) {
149
- location.reload(); // or update the DOM directly
150
- }
151
- });
152
- });
153
- });
154
-
155
- const saveOrderUrl = `{{ url_for('control.save_order', instrument=instrument) }}`;
156
- const buttonIds = {{ session['card_order'][instrument] | tojson }};
157
- </script>
158
- <script src="{{ url_for('static', filename='js/sortable_card.js') }}"></script>
159
- <script src="{{ url_for('static', filename='js/overlay.js') }}"></script>
160
- {% else %}
161
- <div class="alert alert-info mt-4">Select an instrument to view its methods.</div>
162
- {% endif %}
163
- </main>
164
- </div>
165
- </div>
166
- {% endblock %}
@@ -1,112 +0,0 @@
1
- {% extends 'base.html' %}
2
- {% block title %}IvoryOS | New devices{% endblock %}
3
-
4
- {% block body %}
5
- <div class="row">
6
- <!-- Available Python API -->
7
- <div class="col-xl-4 col-lg-4 col-md-6 mb-4">
8
- <div class="card shadow-sm mb-4">
9
- <div class="card-header">
10
- <h5 class="mb-0">Available Python API</h5>
11
- </div>
12
- <div class="card-body">
13
- {% for instrument in api_variables %}
14
- <div class="card mb-2">
15
- <div class="card-body p-2">
16
- <a href="{{ url_for('control.temp.new_controller', instrument=instrument) }}" class="text-dark stretched-link">{{ instrument }}</a>
17
- </div>
18
- </div>
19
- {% endfor %}
20
- <div class="card mt-3">
21
- <div class="card-body p-2">
22
- <a data-bs-toggle="modal" href="#importAPI" class="stretched-link">
23
- <i class="bi bi-folder-plus"></i> Import API
24
- </a>
25
- </div>
26
- </div>
27
- </div>
28
- </div>
29
- </div>
30
-
31
- <!-- Connecting Device -->
32
- <div class="col-xl-5 col-lg-5 col-md-6 mb-4">
33
- {% if device %}
34
- {# {{ device }}#}
35
- <div class="card shadow-sm mb-4">
36
- <div class="card-header">
37
- <h5 class="mb-0">Connecting</h5>
38
- </div>
39
- <div class="card-body">
40
- <form role="form" method="POST" name="init" action="{{ url_for('control.temp.new_controller', instrument=instrument) }}">
41
- <div class="mb-3">
42
- <label class="form-label" for="device_name">Name this device</label>
43
- <input class="form-control" type="text" id="device_name" name="device_name" aria-describedby="nameHelpBlock" placeholder="e.g. {{device.__name__}}_1">
44
- <div id="nameHelpBlock" class="form-text">
45
- Name your instrument, avoid names that are defined on the right
46
- </div>
47
- </div>
48
- {% for arg in device.__init__.__annotations__ %}
49
- {% if not arg == "return" %}
50
- <div class="mb-3">
51
- <label class="form-label" for="{{arg}}">{{arg}}</label>
52
- <input class="form-control" type="text" id="{{arg}}" name="{{arg}}"
53
- placeholder="{{device.__init__.__annotations__[arg].__name__}}"
54
- value="{{args.parameters[arg].default if not args.parameters[arg].default.__name__ == '_empty' else ''}}">
55
- {% if device.__init__.__annotations__[arg].__module__ is not in ["builtins", "typing"] %}
56
- <a role="button" href="{{ url_for('control.temp.new_controller', instrument=device.__init__.__annotations__[arg].__name__) }}" class="btn btn-secondary btn-sm mt-2">Initialize {{device.__init__.__annotations__[arg].__name__}} first</a>
57
- {% endif %}
58
- </div>
59
- {% endif %}
60
- {% endfor %}
61
- <button type="submit" class="btn btn-dark">Connect</button>
62
- </form>
63
- </div>
64
- </div>
65
- {% endif %}
66
- </div>
67
-
68
- <!-- Defined Instruments -->
69
- <div class="col-xl-3 col-lg-3 col-md-6 mb-4">
70
- <div class="card shadow-sm mb-4">
71
- <div class="card-header">
72
- <h5 class="mb-0">Defined Instruments</h5>
73
- </div>
74
- <div class="card-body">
75
- {% if defined_variables %}
76
- <ul class="list-group">
77
- {% for instrument in defined_variables %}
78
- <li class="list-group-item">{{ instrument }}</li>
79
- {% endfor %}
80
- </ul>
81
- {% else %}
82
- <span class="text-muted">No instruments defined.</span>
83
- {% endif %}
84
- </div>
85
- </div>
86
- </div>
87
- </div>
88
-
89
- <!-- Import API Modal -->
90
- <div class="modal fade" id="importAPI" tabindex="-1" aria-labelledby="importModal" aria-hidden="true">
91
- <div class="modal-dialog">
92
- <div class="modal-content">
93
- <div class="modal-header">
94
- <h1 class="modal-title fs-5" id="importModal">Import API by file path</h1>
95
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
96
- </div>
97
- <form method="POST" action="{{ url_for('control.temp.import_api') }}" enctype="multipart/form-data">
98
- <div class="modal-body">
99
- <div class="mb-3">
100
- <label class="form-label" for="filepath">File Path:</label>
101
- <input type="text" class="form-control" name="filepath" id="filepath">
102
- </div>
103
- </div>
104
- <div class="modal-footer">
105
- <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
106
- <button type="submit" class="btn btn-primary">Save</button>
107
- </div>
108
- </form>
109
- </div>
110
- </div>
111
- </div>
112
- {% endblock %}
@@ -1,13 +0,0 @@
1
- <div class="card mb-2 {{ 'border-danger text-danger bg-light' if step.run_error else 'border-secondary' }}">
2
- <div class="card-body p-2">
3
- <strong>{{ step.method_name | format_name }}</strong>
4
- <small class="text-muted">
5
- <i class="fas fa-play-circle me-1"></i> Start: {{ step.start_time.strftime('%H:%M:%S') if step.start_time else 'N/A' }}
6
- <i class="fas fa-stop-circle ms-2 me-1"></i> End: {{ step.end_time.strftime('%H:%M:%S') if step.end_time else 'N/A' }}
7
- <!-- {% if step.run_error %}
8
- <i class="fas fa-stop-circle ms-2 me-1"></i> Error: {{ step.run_error if step.run_error else 'N/A' }}
9
- {% endif %} -->
10
- </small>
11
- <!-- <small>Error: {{ step.run_error }}</small> -->
12
- </div>
13
- </div>