apsbits 1.0.0rc2__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.
Files changed (44) hide show
  1. apsbits/__init__.py +18 -0
  2. apsbits/_version.py +21 -0
  3. apsbits/core/__init__.py +11 -0
  4. apsbits/core/best_effort_init.py +38 -0
  5. apsbits/core/catalog_init.py +29 -0
  6. apsbits/core/run_engine_init.py +71 -0
  7. apsbits/demo_instrument/README.md +1 -0
  8. apsbits/demo_instrument/__init__.py +3 -0
  9. apsbits/demo_instrument/callbacks/__init__.py +1 -0
  10. apsbits/demo_instrument/callbacks/nexus_data_file_writer.py +60 -0
  11. apsbits/demo_instrument/callbacks/spec_data_file_writer.py +93 -0
  12. apsbits/demo_instrument/configs/__init__.py +1 -0
  13. apsbits/demo_instrument/configs/devices.yml +52 -0
  14. apsbits/demo_instrument/configs/devices_aps_only.yml +6 -0
  15. apsbits/demo_instrument/configs/iconfig.yml +81 -0
  16. apsbits/demo_instrument/configs/logging.yml +41 -0
  17. apsbits/demo_instrument/devices/__init__.py +1 -0
  18. apsbits/demo_instrument/plans/__init__.py +8 -0
  19. apsbits/demo_instrument/plans/dm_plans.py +111 -0
  20. apsbits/demo_instrument/plans/sim_plans.py +69 -0
  21. apsbits/demo_instrument/startup.py +63 -0
  22. apsbits/tests/__init__.py +1 -0
  23. apsbits/tests/conftest.py +32 -0
  24. apsbits/tests/test_device_factories.py +44 -0
  25. apsbits/tests/test_general.py +83 -0
  26. apsbits/tests/test_stored_dict.py +139 -0
  27. apsbits/utils/__init__.py +1 -0
  28. apsbits/utils/aps_functions.py +67 -0
  29. apsbits/utils/config_loaders.py +61 -0
  30. apsbits/utils/context_aware.py +187 -0
  31. apsbits/utils/controls_setup.py +113 -0
  32. apsbits/utils/create_new_instrument.py +144 -0
  33. apsbits/utils/helper_functions.py +113 -0
  34. apsbits/utils/logging_setup.py +211 -0
  35. apsbits/utils/make_devices_yaml.py +127 -0
  36. apsbits/utils/metadata.py +101 -0
  37. apsbits/utils/sim_creator.py +199 -0
  38. apsbits/utils/stored_dict.py +192 -0
  39. apsbits-1.0.0rc2.dist-info/LICENSE +48 -0
  40. apsbits-1.0.0rc2.dist-info/METADATA +349 -0
  41. apsbits-1.0.0rc2.dist-info/RECORD +44 -0
  42. apsbits-1.0.0rc2.dist-info/WHEEL +5 -0
  43. apsbits-1.0.0rc2.dist-info/entry_points.txt +2 -0
  44. apsbits-1.0.0rc2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,192 @@
1
+ """
2
+ Storage-backed Dictionary
3
+ =========================
4
+
5
+ A dictionary that writes its contents to YAML file.
6
+
7
+ Replaces ``bluesky.utils.PersistentDict``.
8
+
9
+ * Contents must be JSON serializable.
10
+ * Contents stored in a single human-readable YAML file.
11
+ * Sync to disk shortly after dictionary is updated.
12
+
13
+ .. autosummary::
14
+
15
+ ~StoredDict
16
+ """
17
+
18
+ __all__ = ["StoredDict"]
19
+
20
+ import collections.abc
21
+ import datetime
22
+ import inspect
23
+ import json
24
+ import logging
25
+ import pathlib
26
+ import threading
27
+ import time
28
+
29
+ import yaml
30
+
31
+ logger = logging.getLogger(__name__)
32
+ logger.bsdev(__file__)
33
+
34
+
35
+ class StoredDict(collections.abc.MutableMapping):
36
+ """
37
+ Dictionary that syncs to storage.
38
+
39
+ .. autosummary::
40
+
41
+ ~flush
42
+ ~popitem
43
+ ~reload
44
+
45
+ .. rubric:: Static methods
46
+
47
+ All support for the YAML format is implemented in the static methods.
48
+
49
+ .. autosummary::
50
+
51
+ ~dump
52
+ ~load
53
+
54
+ ----
55
+ """
56
+
57
+ def __init__(self, file, delay=5, title=None, serializable=True):
58
+ """
59
+ StoredDict : Dictionary that syncs to storage
60
+
61
+ PARAMETERS
62
+
63
+ file : str or pathlib.Path
64
+ Name of file to store dictionary contents.
65
+ delay : number
66
+ Time delay (s) since last dictionary update to write to storage.
67
+ Default: 5 seconds.
68
+ title : str or None
69
+ Comment to write at top of file.
70
+ Default: "Written by StoredDict."
71
+ serializable : bool
72
+ If True, validate new dictionary entries are JSON serializable.
73
+ """
74
+ self._file = pathlib.Path(file)
75
+ self._delay = max(0, delay)
76
+ self._title = title or f"Written by {self.__class__.__name__}."
77
+ self.test_serializable = serializable
78
+
79
+ self.sync_in_progress = False
80
+ self._sync_deadline = time.time()
81
+ self._sync_key = f"sync_agent_{id(self):x}"
82
+ self._sync_loop_period = 0.005
83
+
84
+ self._cache = {}
85
+ self.reload()
86
+
87
+ def __delitem__(self, key):
88
+ """Delete dictionary value by key."""
89
+ del self._cache[key]
90
+
91
+ def __getitem__(self, key):
92
+ """Get dictionary value by key."""
93
+ return self._cache[key]
94
+
95
+ def __iter__(self):
96
+ """Iterate over the dictionary keys."""
97
+ yield from self._cache
98
+
99
+ def __len__(self):
100
+ """Number of keys in the dictionary."""
101
+ return len(self._cache)
102
+
103
+ def __repr__(self):
104
+ """representation of this object."""
105
+ return f"<{self.__class__.__name__} {dict(self)!r}>"
106
+
107
+ def __setitem__(self, key, value):
108
+ """Write to the dictionary."""
109
+ outermost_frame = inspect.getouterframes(inspect.currentframe())[-1]
110
+ if "sphinx-build" in outermost_frame.filename:
111
+ # Seems that Sphinx is building the documentation.
112
+ # Ignore all the objects it tries to add.
113
+ return
114
+
115
+ if self.test_serializable:
116
+ json.dumps({key: value})
117
+
118
+ self._cache[key] = value # Store the new (or revised) content.
119
+
120
+ # Reset the deadline.
121
+ self._sync_deadline = time.time() + self._delay
122
+ logger.debug("new sync deadline in %f s.", self._delay)
123
+
124
+ if not self.sync_in_progress:
125
+ # Start the sync_agent (thread).
126
+ self._delayed_sync_to_storage()
127
+
128
+ def _delayed_sync_to_storage(self):
129
+ """
130
+ Sync the metadata to storage.
131
+
132
+ Start a time-delay thread. New writes to the metadata dictionary will
133
+ extend the deadline. Sync once the deadline is reached.
134
+ """
135
+
136
+ def sync_agent():
137
+ """Threaded task."""
138
+ logger.debug("Starting sync_agent...")
139
+ self.sync_in_progress = True
140
+ while time.time() < self._sync_deadline:
141
+ time.sleep(self._sync_loop_period)
142
+ logger.debug("Sync waiting period ended")
143
+ self.sync_in_progress = False
144
+
145
+ StoredDict.dump(self._file, self._cache, title=self._title)
146
+
147
+ thred = threading.Thread(target=sync_agent)
148
+ thred.start()
149
+
150
+ def flush(self):
151
+ """Force a write of the dictionary to disk"""
152
+ logger.debug("flush()")
153
+ if not self.sync_in_progress:
154
+ StoredDict.dump(self._file, self._cache, title=self._title)
155
+ self._sync_deadline = time.time()
156
+ self.sync_in_progress = False
157
+
158
+ def popitem(self):
159
+ """
160
+ Remove and return a (key, value) pair as a 2-tuple.
161
+
162
+ Pairs are returned in LIFO (last-in, first-out) order.
163
+ Raises KeyError if the dict is empty.
164
+ """
165
+ return self._cache.popitem()
166
+
167
+ def reload(self):
168
+ """Read dictionary from storage."""
169
+ logger.debug("reload()")
170
+ self._cache = StoredDict.load(self._file)
171
+
172
+ @staticmethod
173
+ def dump(file, contents, title=None):
174
+ """Write dictionary to YAML file."""
175
+ logger.debug("_dump(): file='%s', contents=%r, title=%r", file, contents, title)
176
+ with open(file, "w") as f:
177
+ if isinstance(title, str) and len(title) > 0:
178
+ f.write(f"# {title}\n")
179
+ f.write(f"# Dictionary contents written: {datetime.datetime.now()}\n\n")
180
+ f.write(yaml.dump(contents, indent=2))
181
+
182
+ @staticmethod
183
+ def load(file):
184
+ """Read dictionary from YAML file."""
185
+ from .config_loaders import load_config_yaml
186
+
187
+ file = pathlib.Path(file)
188
+ logger.debug("_load('%s')", file)
189
+ md = None
190
+ if file.exists():
191
+ md = load_config_yaml(file)
192
+ return md or {} # In case file is empty.
@@ -0,0 +1,48 @@
1
+ Copyright (c) 2023-2025, UChicago Argonne, LLC
2
+
3
+ All Rights Reserved
4
+
5
+ BITS
6
+
7
+ BCDA, Advanced Photon Source, Argonne National Laboratory
8
+
9
+
10
+ OPEN SOURCE LICENSE
11
+
12
+ Redistribution and use in source and binary forms, with or without
13
+ modification, are permitted provided that the following conditions are met:
14
+
15
+ 1. Redistributions of source code must retain the above copyright notice,
16
+ this list of conditions and the following disclaimer. Software changes,
17
+ modifications, or derivative works, should be noted with comments and
18
+ the author and organization's name.
19
+
20
+ 2. Redistributions in binary form must reproduce the above copyright notice,
21
+ this list of conditions and the following disclaimer in the documentation
22
+ and/or other materials provided with the distribution.
23
+
24
+ 3. Neither the names of UChicago Argonne, LLC or the Department of Energy
25
+ nor the names of its contributors may be used to endorse or promote
26
+ products derived from this software without specific prior written
27
+ permission.
28
+
29
+ 4. The software and the end-user documentation included with the
30
+ redistribution, if any, must include the following acknowledgment:
31
+
32
+ "This product includes software produced by UChicago Argonne, LLC
33
+ under Contract No. DE-AC02-06CH11357 with the Department of Energy."
34
+
35
+ ****************************************************************************
36
+
37
+ DISCLAIMER
38
+
39
+ THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND.
40
+
41
+ Neither the United States GOVERNMENT, nor the United States Department
42
+ of Energy, NOR uchicago argonne, LLC, nor any of their employees, makes
43
+ any warranty, express or implied, or assumes any legal liability or
44
+ responsibility for the accuracy, completeness, or usefulness of any
45
+ information, data, apparatus, product, or process disclosed, or
46
+ represents that its use would not infringe privately owned rights.
47
+
48
+ ****************************************************************************
@@ -0,0 +1,349 @@
1
+ Metadata-Version: 2.2
2
+ Name: apsbits
3
+ Version: 1.0.0rc2
4
+ Summary: Model of a Bluesky Data Acquisition Instrument in console, notebook, & queueserver.
5
+ Author-email: Eric Codrea <ecodrea@anl.gov>, Pete Jemian <prjemian+instrument@gmail.com>, Rafael Vescovi <rvescovi@anl.gov>
6
+ Maintainer-email: Eric Codrea <ecodrea@anl.gov>, Pete Jemian <prjemian+instrument@gmail.com>, Rafael Vescovi <rvescovi@anl.gov>
7
+ License: Copyright (c) 2023-2025, UChicago Argonne, LLC
8
+
9
+ All Rights Reserved
10
+
11
+ BITS
12
+
13
+ BCDA, Advanced Photon Source, Argonne National Laboratory
14
+
15
+
16
+ OPEN SOURCE LICENSE
17
+
18
+ Redistribution and use in source and binary forms, with or without
19
+ modification, are permitted provided that the following conditions are met:
20
+
21
+ 1. Redistributions of source code must retain the above copyright notice,
22
+ this list of conditions and the following disclaimer. Software changes,
23
+ modifications, or derivative works, should be noted with comments and
24
+ the author and organization's name.
25
+
26
+ 2. Redistributions in binary form must reproduce the above copyright notice,
27
+ this list of conditions and the following disclaimer in the documentation
28
+ and/or other materials provided with the distribution.
29
+
30
+ 3. Neither the names of UChicago Argonne, LLC or the Department of Energy
31
+ nor the names of its contributors may be used to endorse or promote
32
+ products derived from this software without specific prior written
33
+ permission.
34
+
35
+ 4. The software and the end-user documentation included with the
36
+ redistribution, if any, must include the following acknowledgment:
37
+
38
+ "This product includes software produced by UChicago Argonne, LLC
39
+ under Contract No. DE-AC02-06CH11357 with the Department of Energy."
40
+
41
+ ****************************************************************************
42
+
43
+ DISCLAIMER
44
+
45
+ THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND.
46
+
47
+ Neither the United States GOVERNMENT, nor the United States Department
48
+ of Energy, NOR uchicago argonne, LLC, nor any of their employees, makes
49
+ any warranty, express or implied, or assumes any legal liability or
50
+ responsibility for the accuracy, completeness, or usefulness of any
51
+ information, data, apparatus, product, or process disclosed, or
52
+ represents that its use would not infringe privately owned rights.
53
+
54
+ ****************************************************************************
55
+
56
+ Project-URL: Homepage, https://BCDA-APS.github.io/APSBITS/
57
+ Project-URL: Bug Tracker, https://github.com/BCDA-APS/APSBITS/issues
58
+ Keywords: bluesky,queueserver
59
+ Classifier: Development Status :: 6 - Mature
60
+ Classifier: Environment :: Console
61
+ Classifier: Intended Audience :: Developers
62
+ Classifier: License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
63
+ Classifier: License :: Freely Distributable
64
+ Classifier: License :: Public Domain
65
+ Classifier: Programming Language :: Python
66
+ Classifier: Programming Language :: Python :: 3
67
+ Classifier: Topic :: Utilities
68
+ Requires-Python: >=3.11
69
+ Description-Content-Type: text/markdown
70
+ License-File: LICENSE
71
+ Requires-Dist: apstools>=1.7.2
72
+ Requires-Dist: bluesky-queueserver-api
73
+ Requires-Dist: bluesky-queueserver
74
+ Requires-Dist: bluesky-widgets
75
+ Requires-Dist: bluesky
76
+ Requires-Dist: caproto
77
+ Requires-Dist: databroker==1.2.5
78
+ Requires-Dist: guarneri
79
+ Requires-Dist: ipython
80
+ Requires-Dist: jupyterlab
81
+ Requires-Dist: ophyd-registry
82
+ Requires-Dist: ophyd
83
+ Requires-Dist: PyQt5>5.15
84
+ Requires-Dist: pyRestTable
85
+ Requires-Dist: pysumreg
86
+ Requires-Dist: qtpy
87
+ Requires-Dist: toml
88
+ Provides-Extra: dev
89
+ Requires-Dist: build; extra == "dev"
90
+ Requires-Dist: isort; extra == "dev"
91
+ Requires-Dist: mypy; extra == "dev"
92
+ Requires-Dist: pre-commit; extra == "dev"
93
+ Requires-Dist: pytest; extra == "dev"
94
+ Requires-Dist: ruff; extra == "dev"
95
+ Provides-Extra: doc
96
+ Requires-Dist: babel; extra == "doc"
97
+ Requires-Dist: ipykernel; extra == "doc"
98
+ Requires-Dist: jinja2; extra == "doc"
99
+ Requires-Dist: markupsafe; extra == "doc"
100
+ Requires-Dist: myst_parser; extra == "doc"
101
+ Requires-Dist: nbsphinx; extra == "doc"
102
+ Requires-Dist: pydata-sphinx-theme; extra == "doc"
103
+ Requires-Dist: pygments-ipython-console; extra == "doc"
104
+ Requires-Dist: pygments; extra == "doc"
105
+ Requires-Dist: sphinx-design; extra == "doc"
106
+ Requires-Dist: sphinx-tabs; extra == "doc"
107
+ Requires-Dist: sphinx; extra == "doc"
108
+ Provides-Extra: all
109
+ Requires-Dist: apsbits[dev,doc]; extra == "all"
110
+
111
+ # APSBITS: Template Package for Bluesky Instruments
112
+
113
+ | PyPI | Coverage |
114
+ | --- | --- |
115
+ [![PyPi](https://img.shields.io/pypi/v/apsbits.svg)](https://pypi.python.org/pypi/apsbits) | [![Coverage Status](https://coveralls.io/repos/github/BCDA-APS/BITS/badge.svg)](https://coveralls.io/github/BCDA-APS/BITS) |
116
+
117
+ BITS: **B**luesky **I**nstrument **T**emplate**S**
118
+
119
+ Template of a Bluesky Data Acquisition Instrument in console, notebook, &
120
+ queueserver.
121
+
122
+ ## Create repository from this template.
123
+
124
+
125
+
126
+ https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template
127
+
128
+ Creating a repository from a template
129
+ On GitHub, navigate to the main page of the repository.
130
+
131
+ Above the file list, click Use this template.
132
+
133
+ Select Create a new repository.
134
+
135
+ ![Screenshot of the "Use this template" button and the dropdown menu expanded to show the "Open in a codespace" option.
136
+ ](docs/resources/use-this-template-button.webp)
137
+
138
+ Alternatively, you can open the template in a codespace and publish your work to a new repository later. For more information, see Creating a codespace from a template.
139
+
140
+ Use the Owner dropdown menu to select the account you want to own the repository.
141
+
142
+ Screenshot of the owner menu for a new GitHub repository. The menu shows two options, octocat and github.
143
+ Type a name for your repository, and an optional description.
144
+
145
+ ![Image 2](docs/resources/create-repo-from-template.webp)
146
+
147
+
148
+ Screenshot of a the first step in creating a repository. The "Repository name" field contains the text "hello-world" and is outlined in orange.
149
+ Choose a repository visibility. For more information, see About repositories.
150
+
151
+ ![Image 3](docs/resources/create-repository-owner.webp)
152
+
153
+ Optionally, to include the directory structure and files from all branches in the template, and not just the default branch, select Include all branches.
154
+
155
+ Optionally, if the personal account or organization in which you're creating uses any GitHub Apps from GitHub Marketplace, select any apps you'd like to use in the repository.
156
+
157
+ Click Create repository from template.
158
+
159
+ ## Installing your own BITS instrument
160
+
161
+ ```bash
162
+ export ENV_NAME=BITS_env
163
+
164
+ conda create -y -n $ENV_NAME python=3.11 pyepics
165
+ conda activate $ENV_NAME
166
+ pip install -e ."[all]"
167
+ ```
168
+
169
+
170
+ ## Edit your instrument
171
+
172
+
173
+
174
+ ## IPython console Start
175
+
176
+ To start the bluesky instrument session in a ipython execute the next command in a terminal:
177
+
178
+ ```bash
179
+ ipython
180
+ ```
181
+
182
+ ## Jupyter Notebook Start
183
+ Start JupyterLab, a Jupyter notebook server, or a notebook, VSCode.
184
+
185
+ ## Starting the BITS Package
186
+
187
+ ```py
188
+ from instrument.startup import *
189
+ RE(make_devices()) # create all the ophyd-style control devices
190
+ ```
191
+
192
+ ## Run Sim Plan Demo
193
+
194
+ To run some simulated plans that ensure the installation worked as expected
195
+ please run the next commands inside an ipython session or a jupyter notebook
196
+ after starting the data acquisition:
197
+
198
+ ```py
199
+ RE(sim_print_plan())
200
+ RE(sim_count_plan())
201
+ RE(sim_rel_scan_plan())
202
+ ```
203
+
204
+ See this [example](./docs/source/demo.ipynb).
205
+
206
+ ## Configuration files
207
+
208
+ The files that can be configured to adhere to your preferences are:
209
+
210
+ - `configs/iconfig.yml` - configuration for data collection
211
+ - `configs/logging.yml` - configuration for session logging to console and/or files
212
+ - `qserver/qs-config.yml` - contains all configuration of the QS host process. See the [documentation](https://blueskyproject.io/bluesky-queueserver/manager_config.html) for more details of the configuration.
213
+
214
+ ## queueserver
215
+
216
+ The queueserver has a host process that manages a RunEngine. Client sessions
217
+ will interact with that host process.
218
+
219
+ ### Run a queueserver host process
220
+
221
+ Use the queueserver host management script to start the QS host process. The
222
+ `restart` option stops the server (if it is running) and then starts it. This is
223
+ the usual way to (re)start the QS host process. Using `restart`, the process
224
+ runs in the background.
225
+
226
+ ```bash
227
+ ./qserver/qs_host.sh restart
228
+ ```
229
+
230
+ ### Run a queueserver client GUI
231
+
232
+ To run the gui client for the queueserver you can use the next command inside the terminal:
233
+
234
+ ```bash
235
+ queue-monitor &
236
+ ```
237
+
238
+ ### Shell script explained
239
+
240
+ A [shell script](./qserver/qs_host.sh) is used to start the QS host process. Below
241
+ are all the command options, and what they do.
242
+
243
+ ```bash
244
+ (bstest) $ ./qserver/qs_host.sh help
245
+ Usage: qs_host.sh {start|stop|restart|status|checkup|console|run} [NAME]
246
+
247
+ COMMANDS
248
+ console attach to process console if process is running in screen
249
+ checkup check that process is running, restart if not
250
+ restart restart process
251
+ run run process in console (not screen)
252
+ start start process
253
+ status report if process is running
254
+ stop stop process
255
+
256
+ OPTIONAL TERMS
257
+ NAME name of process (default: bluesky_queueserver-)
258
+ ```
259
+
260
+ Alternatively, run the QS host's startup command directly within the `./qserver/`
261
+ subdirectory.
262
+
263
+ ```bash
264
+ cd ./qserver
265
+ start-re-manager --config=./qs-config.yml
266
+ ```
267
+
268
+ ## Testing
269
+
270
+ Use this command to run the test suite locally:
271
+
272
+ ```bash
273
+ pytest -vvv --lf ./src
274
+ ```
275
+
276
+ ## Documentation
277
+
278
+ <details>
279
+ <summary>prerequisite</summary>
280
+
281
+ To build the documentation locally, install [`pandoc`](https://pandoc.org/) in
282
+ your conda environment:
283
+
284
+ ```bash
285
+ conda install conda-forge::pandoc
286
+ ```
287
+
288
+ </details>
289
+
290
+ Use this command to build the documentation locally:
291
+
292
+ ```bash
293
+ make -C docs clean html
294
+ ```
295
+
296
+ Once the documentation builds, view the HTML pages using your web browser:
297
+
298
+ ```bash
299
+ BROWSER ./docs/build/html/index.html &
300
+ ```
301
+
302
+ ### Adding to the documentation source
303
+
304
+ The documentation source is located in files and directories under
305
+ `./docs/source`. Various examples are provided.
306
+
307
+ Documentation can be added in these formats:
308
+ [`.rst`](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html)
309
+ (reStructured text), [`.md`](https://en.wikipedia.org/wiki/Markdown) (markdown),
310
+ and [`.ipynb`](https://jupyter.org/) (Jupyter notebook). For more information,
311
+ see the [Sphinx](https://www.sphinx-doc.org/) documentation.
312
+
313
+ ## Warnings
314
+
315
+ ### Bluesky Queueserver
316
+
317
+ The QS host process writes files into the `qserver/` directory. This directory can be
318
+ relocated. However, it should not be moved into the instrument package since
319
+ that might be installed into a read-only directory.
320
+
321
+ ## How-To Guides
322
+ ### How to use the template
323
+
324
+ Consider renaming this `instrument` package to be more clear that is specific to *this*
325
+ instrument. This will be the name by which it is `pip` installed and also used with
326
+ `import`. Let's use an example instrument package name `my_instrument` below to show which parts are edited.
327
+
328
+ 1) Click on use as template button
329
+ 2) Adjust the following parameters in the following files:
330
+ - `pyproject.toml`
331
+ - `[project]` `name =` *example: `my_instrument`*
332
+ - `[project.urls]` *change URLs for your repo*
333
+ - `[tool.setuptools]` `package-dir = {"instrument" = "src/instrument"}` *example: `{"my_instrument" = "src/instrument"}`*
334
+ - `src/instrument/init.py`
335
+ - `__package__ = "instrument"` *example: `"my_instrument"`*
336
+ - `src/instrument/configs/iconfig.yml`
337
+ - `DATABROKER_CATALOG:` *change from `temp` to your catalog's name*
338
+ - `beamline_id:` *one word beamline name (such as known by APS scheduling system)*
339
+ - `instrument_name:` *descriptive name of your beamline*
340
+ - `DM_SETUP_FILE:` *Path to DM bash setup file, comment out if you do not have*
341
+ - `BEC:` *adjust for your preferences*
342
+ - `qserver/qs-config.yml`
343
+ - `startup_module: instrument.startup` *example: `my_instrument.startup`*
344
+ - `docs/source/conf.py`
345
+ - `import instrument` *example `import my_instrument`*
346
+ - `project = "instrument"` *example: `"my_instrument"`*
347
+ - `version = instrument.__version__` *example: `my_instrument.__version__`*
348
+
349
+ - [APS Data Management Plans](./docs/source/guides/dm.md)
@@ -0,0 +1,44 @@
1
+ apsbits/__init__.py,sha256=aC6iFpu22_zSzmQDjkrd3FcthCgjoD1SUiZ-7j_TwuY,442
2
+ apsbits/_version.py,sha256=M6t-LPFvXIty3cmb1PuSyyBXUrQKwdDeD11Ht_y2eKY,521
3
+ apsbits/core/__init__.py,sha256=CmmaJwx5aAUf2d-svOMw9paMlKnCSz_xvEPBAW8e5nA,266
4
+ apsbits/core/best_effort_init.py,sha256=FJ53pcywdhsTloDXbxsbV9eMLyNxWjm7pFKjLS7Mnv8,938
5
+ apsbits/core/catalog_init.py,sha256=rhvTgnTN0cGUCWqF2zwq22MrCq5jKbvQ2EHMLG4t6yQ,588
6
+ apsbits/core/run_engine_init.py,sha256=gXWGj25mAy6acRiK0tA7yR1lGqF7Fhg2fZn9fwp0wZ4,2070
7
+ apsbits/demo_instrument/README.md,sha256=fLZWnARxJxOZSwrb1eIN4UtRpxrLgKeApU5xJ5jGNWs,19
8
+ apsbits/demo_instrument/__init__.py,sha256=FvRPlH1kNyvOzRV6K-ELCQgGYBzUEsrU--yr29x8Zx4,69
9
+ apsbits/demo_instrument/startup.py,sha256=cbgiVKXr8h_UH4xtXhnIwy1USYy6sOAPKOEcgc4q6Nw,2272
10
+ apsbits/demo_instrument/callbacks/__init__.py,sha256=UlYegbF9GbziD1UzgscoGo9T5aFPvs-upwXxPQmBEjY,35
11
+ apsbits/demo_instrument/callbacks/nexus_data_file_writer.py,sha256=3pwLL7E8tzKrmSRQ9iTLJUpdZss-x1l9t0qT1Wn8ihQ,1519
12
+ apsbits/demo_instrument/callbacks/spec_data_file_writer.py,sha256=D58A-Th7sSJasAmkFNg_Ab3v3TUjOf9uKw_9HK_Ne9M,2641
13
+ apsbits/demo_instrument/configs/__init__.py,sha256=mhZO8bz7uexqBJx0PrILGQM6ssHPbCx8fld7EtRy6so,46
14
+ apsbits/demo_instrument/configs/devices.yml,sha256=sbAyUSqCF2CeCp_KKmCBEuOj3gT1h8OP_eR5uqROby0,1305
15
+ apsbits/demo_instrument/configs/devices_aps_only.yml,sha256=XR9ZB-RaVpG-rghDSYKL8A16wETuOi7mzlx7U8LBCTg,136
16
+ apsbits/demo_instrument/configs/iconfig.yml,sha256=YAz2FCv6VlvBEz9n-u7KymF9n-tfrSW4JWiyDjK_NFo,2271
17
+ apsbits/demo_instrument/configs/logging.yml,sha256=ydODRE8cUqzZvI7xxTB9jT6hEQci8jKrshF8mwRV9fo,836
18
+ apsbits/demo_instrument/devices/__init__.py,sha256=3nhJy2BDR_nelXjxWw5_1Ppg7zStO6v2vJNpvO06IYU,27
19
+ apsbits/demo_instrument/plans/__init__.py,sha256=Qjo7AYRIReo-x5i9rkpiYs86F5C8adDchn_Ghe-Qn1A,356
20
+ apsbits/demo_instrument/plans/dm_plans.py,sha256=SeZMKQeQGlQ-abpv3Ccfe9BgQDHMxFQq0pEgsiZCeb4,3445
21
+ apsbits/demo_instrument/plans/sim_plans.py,sha256=er9Dekkh9ob6t-GBR0tb2EIBdgr3JqRdIfr2xTi_l-Y,1963
22
+ apsbits/tests/__init__.py,sha256=ZqbT_R0daJUQAawNOy472d-DOwwYxmZQKuZp3jivZDM,48
23
+ apsbits/tests/conftest.py,sha256=mEErfrzLO_27WIergnHD5gC8iYLf7R_TRQPKhJ8UJbM,868
24
+ apsbits/tests/test_device_factories.py,sha256=Uoq3V6zugCLCqNagln81N3d7dk_e8bTAsH5ZwEKpVrI,1364
25
+ apsbits/tests/test_general.py,sha256=KoGchanPPOg8E1n7KhJxLuclKCgoDgxr0s11Wj7ySrM,2646
26
+ apsbits/tests/test_stored_dict.py,sha256=BmJAXnQFtkqdXloiMdzUXDxZ1SH-wwNyQmgmWOyhQkI,4248
27
+ apsbits/utils/__init__.py,sha256=2ZlHuOIAtb-kEBwQoabNVWD5QOVtDBORgdy1BzI8NS8,45
28
+ apsbits/utils/aps_functions.py,sha256=o4ZQ0GCdftpCRJnVcjKrx5WnQNV0gwnA_oXS8rBhGN0,2135
29
+ apsbits/utils/config_loaders.py,sha256=ZVUu0WgfxAwgy8ICULhjNNhg3xsowUeD6kZFIEQYjnY,1712
30
+ apsbits/utils/context_aware.py,sha256=Aepj9Zxctc1hZg7Uv-rltObFHGLFEHySTa4pE1SiY-k,5627
31
+ apsbits/utils/controls_setup.py,sha256=HA4P2NNohEOfK_MUkELuxjoMAC8UPjHX52PmbzF5dNM,3395
32
+ apsbits/utils/create_new_instrument.py,sha256=DQddRosANfvfmndftNW52Z_Xi0_9Y3HnD7XYS-bHvxA,4546
33
+ apsbits/utils/helper_functions.py,sha256=KUbTdRIkhIeEtAOxiqKTzV4fv97bn6HEpcPvly3XOAw,3126
34
+ apsbits/utils/logging_setup.py,sha256=lDThArGcwq9v0ClRJs__thQG13xITx7-pQbmxdR6FsU,7034
35
+ apsbits/utils/make_devices_yaml.py,sha256=x9qp_bRMo4p0HdKHYFhZlVEcCoQrTl8-srwCnrCfefg,3614
36
+ apsbits/utils/metadata.py,sha256=aiEVHFK13Zu1XCbFALrfFxIJzDHtmPEAj9xO5QAKs9g,2629
37
+ apsbits/utils/sim_creator.py,sha256=OUs0vS0shaEQRJZVRS9j9TE496YjGr8zqKQzZJl1DYE,5275
38
+ apsbits/utils/stored_dict.py,sha256=ACqlB81YSMjHITBb0bAX5BMp_hPGOGPLiueQdsqjDAw,5530
39
+ apsbits-1.0.0rc2.dist-info/LICENSE,sha256=VRL4rXRDmRe62o4ci_VPKWl_z8_96c-U6DUqelNBgI0,1927
40
+ apsbits-1.0.0rc2.dist-info/METADATA,sha256=KxfP9_A5b3mCZfs5-602bYJYbztrnJz3M_Sa-u7G3dQ,12544
41
+ apsbits-1.0.0rc2.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
42
+ apsbits-1.0.0rc2.dist-info/entry_points.txt,sha256=iLl4F8OZNqN7wb-wmKSBY8_LDK7B2CnGWbPMNIt8QEA,73
43
+ apsbits-1.0.0rc2.dist-info/top_level.txt,sha256=K0KyAyPka1k4prJJFWALbX0gcUL3i4kiflTvSeM_6O4,8
44
+ apsbits-1.0.0rc2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (76.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ create-bits = apsbits.utils.create_new_instrument:main
@@ -0,0 +1 @@
1
+ apsbits