Skip to content

Commit 68fc0a8

Browse files
authored
Merge branch 'labscript-suite:master' into master
2 parents be0970a + 4b0722f commit 68fc0a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+2427
-174
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,4 @@ conda_packages/
159159
docs/html/
160160
docs/source/_build/
161161
docs/source/components.rst
162+
docs/source/devices/_apidoc

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ The following devices have been implemented in the _labscript suite_:<sup>†</s
4747
* [NovaTech DDS9m](http://www.novatechsales.com/PDF_files/dds9mds_lr.pdf) 170MHz Four Channel Direct Digital Synthesized Signal Generator (see [blog post](http://labscriptsuite.org/blog/tag/novatech-dds9m/))
4848
* [OpalKelly XEM3001](https://opalkelly.com/products/xem3001/) FPGA Boards used by the Cicero control system (PR [#50](https://bitbucket-archive.labscriptsuite.org/#!/labscript_suite/labscript_devices/pull-requests/50))
4949
* [PineBlaster](http://labscriptsuite.org/hardware/pineblaster) Open-source Digital Pattern Generator
50+
* [PrawnBlaster](https://github.com/labscript-suite/prawnblaster/) Open-source pseudoclock based on the $4 Raspberry Pi Pico
5051
* [SpinCore](https://www.spincore.com/products/#pulsegeneration) Programmable Pulse Generators and Direct Digital Synthesis
5152
* [PulseBlasterDDS-II-300-AWG](http://www.spincore.com/products/PulseBlasterDDS-II-300/)
5253
* [PulseBlasterESR-PRO](https://www.spincore.com/products/PulseBlasterESR-PRO/)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{%- macro automodule(modname, options) -%}
2+
.. automodule:: {{ modname }}
3+
{%- for option in options %}
4+
:{{ option }}:
5+
{%- endfor %}
6+
{%- endmacro %}
7+
8+
{%- macro toctree(docnames) -%}
9+
.. toctree::
10+
:maxdepth: {{ maxdepth }}
11+
{% for docname in docnames %}
12+
{{ docname }}
13+
{%- endfor %}
14+
{%- endmacro %}
15+
16+
{%- macro autosummary(submodules) -%}
17+
.. autosummary::
18+
{% for submodule in submodules %}
19+
{{submodule}}
20+
{%- endfor %}
21+
{%- endmacro %}
22+
23+
{%- macro autosum(pkgname) -%}
24+
.. autosummary::
25+
26+
{{pkgname}}
27+
{%- endmacro %}
28+
29+
{%- if is_namespace %}
30+
{{- [pkgname, "namespace"] | join(" ") | e | heading }}
31+
{% else %}
32+
{# {{- [pkgname, ""] | join(" ") | e | heading }} #}
33+
{% endif %}
34+
35+
{%- if submodules %}
36+
{{ autosummary(submodules) }}
37+
{% if separatemodules %}
38+
{{ toctree(submodules) }}
39+
{% else %}
40+
{%- for submodule in submodules %}
41+
{% if show_headings %}
42+
{{- [submodule, ""] | join(" ") | e | heading(2) }}
43+
{% endif %}
44+
{{ automodule(submodule, automodule_options) }}
45+
{% endfor %}
46+
{%- endif %}
47+
{%- endif %}

docs/source/adding_devices.rst

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
How to Add a Device
2+
===================
3+
4+
Adding a **labscript-device** involves implementing interfaces for your hardware to different protions of the **labscript-suite**. Namely, you must provide
5+
6+
* A `labscript_device` that takes **labscript** high-level commands and turns them into instructions that are saved to the shot h5 file.
7+
* A `BLACS_worker` that handles communication with the hardware, in particular interpreting the instructions from the shot h5 file into the necessary hardware commands to configure the device.
8+
* A `BLACS_tab` which provides a graphical interface to control the instrument via **BLACS**
9+
10+
Though not strictly required, you should also consider providing a `runviewer_parser`, which can read the h5 instructions and produce the appropriate shot timings that would occur. This interface is only used in **runviewer**.
11+
12+
General Strategy
13+
~~~~~~~~~~~~~~~~
14+
15+
As a general rule, it is best to model new hardware implementations off of a currently implemented device that has similar functionality.
16+
If the functionality is similar enough, it may even be possible to simply sub-class the currently implemented device, which is likely preferrable.
17+
18+
Barring the above simple solution, one must work from scratch.
19+
It is best to begin by determining the **labscript** device class to inherit from: `Psuedoclock`, `Device`, `IntermediateDevice`.
20+
The first is for implementing Psuedoclock devices, the second is for generic devices that are not hardware timed by a pseudoclock, and the last is for hardware timed device that are connected to another device controlled via labscript.
21+
22+
The `labscript_device` implements general configuration parameters, many of which are passed to the `BLACS_worker`.
23+
It also implements the `generate_code` method which converts **labscript** high-level instructions and saves them to the h5 file.
24+
25+
The `BLACS_tab` defines the GUI widgets that control the device.
26+
This typically takes the form of using standard widgets provided by **labscript** for controlling **labscript** output primitives (ie `AnalogOut`, `DigitalOut`,`DDS`, etc).
27+
This configuration is done in the `initialiseGUI` method.
28+
This also links directly to the appropriate BLACS workers.
29+
30+
The `BLACS_worker` handles communication with the hardware itself and often represents the bulk of the work required to implement a new labscript device.
31+
In general, it should provide five different methods:
32+
33+
* `init`: This method initialised communications with the device. Not to be confused with the standard python class `__init__` method.
34+
* `program_manual`: This method allows for user control of the device via the `BLACS_tab`, setting outputs to the values set in the `BLACS_tab` widgets.
35+
* `check_remote_values`: This method reads the current settings of the device, updating the `BLACS_tab` widgets to reflect these values.
36+
* `transition_to_buffered`: This method transitions the device to buffered shot mode, reading the shot h5 file and taking the saved instructions from `labscript_device.generate_code` and sending the appropriate commands to the hardware.
37+
* `transition_to_manual`: This method transitions the device from buffered to manual mode. It does any necessary configuration to take the device out of buffered mode and is used to read an measurements and save them to the shot h5 file as results.
38+
39+
The `runviewer_parser` takes shot h5 files, reads the saved instructions, and allows you to view them in **runviewer** in order to visualise experiment timing.
40+
41+
Code Organization
42+
~~~~~~~~~~~~~~~~~
43+
44+
There are currently two supported file organization styles for a labscript-device.
45+
46+
The old style has the `labscript_device`, `BLACS_tab`, `BLACS_worker`, and `runviewer_parser` all in the same file, which typically has the same name as the `labscript_device` class name.
47+
48+
The new style allows for arbitrary code organization, but typically has a folder named after the `labscript_device` with each device component in a different file (ie `labscript_devices.py`, `BLACS_workers.py`, etc).
49+
With this style, the folder requires an `__init__.py` file (which can be empty) as well as a `register_classes.py` file.
50+
This file imports :obj:`<labscript-utils:labscript_utils.device_registry>` via
51+
52+
.. code-block:: python
53+
54+
from labscript_devices import register_classes
55+
56+
This function informs **labscript** where to find the necessary classes during import. An example for the `NI_DAQmx` device is
57+
58+
.. code-block:: python
59+
60+
register_classes(
61+
'NI_DAQmx',
62+
BLACS_tab='labscript_devices.NI_DAQmx.blacs_tabs.NI_DAQmxTab',
63+
runviewer_parser='labscript_devices.NI_DAQmx.runviewer_parsers.NI_DAQmxParser',
64+
)
65+
66+
Contributions to **labscript-devices**
67+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
68+
69+
If you decide to implement a labscript-device for controlling new hardware, we highly encourage you to consider making a pull-request to the **labscript-devices** repository in order to add your work to the **labscript-suite**.
70+
Increasing the list of supported devices is an important way for the **labscript-suite** to continue to grow, allowing new users to more quickly get up and running with hardware they may already have.

docs/source/conf.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
# ones.
4040
extensions = [
4141
"sphinx.ext.autodoc",
42+
"sphinx.ext.autosummary",
4243
"sphinx.ext.autosectionlabel",
4344
"sphinx.ext.intersphinx",
4445
"sphinx.ext.napoleon",
@@ -49,6 +50,8 @@
4950
]
5051

5152
autodoc_typehints = 'description'
53+
autoclass_content = 'both' # options: 'both', 'class', 'init'
54+
autodoc_mock_imports = ['PyDAQmx']
5255

5356
# Prefix each autosectionlabel with the name of the document it is in and a colon
5457
autosectionlabel_prefix_document = True
@@ -169,6 +172,13 @@
169172
else:
170173
todo_include_todos = True
171174

175+
# -- Options for PDF output --------------------------------------------------
176+
177+
latex_elements = {
178+
# make entire document landscape
179+
'geometry': '\\usepackage[landscape]{geometry}',
180+
}
181+
172182
# -- Options for HTML output -------------------------------------------------
173183

174184
# The theme to use for HTML and HTML Help pages. See the documentation for
@@ -223,3 +233,64 @@ def setup(app):
223233
img_path=img_path
224234
)
225235
)
236+
237+
# hook to run apidoc before building
238+
app.connect('builder-inited', run_apidoc)
239+
# hooks to test docstring coverage
240+
app.connect('autodoc-process-docstring', doc_coverage)
241+
app.connect('build-finished', doc_report)
242+
243+
244+
def run_apidoc(_):
245+
"""Runs apidoc with our desired parameters to generate the NI_DAQmx models docs.
246+
"""
247+
from sphinx.ext.apidoc import main
248+
if os.environ.get('READTHEDOCS'):
249+
rel_path = '../..'
250+
else:
251+
rel_path = '..'
252+
daq_models_path = os.path.join(os.path.abspath(rel_path),
253+
'labscript_devices')
254+
out_path = os.path.join(os.path.dirname(Path(__file__)),
255+
'devices', '_apidoc', 'models')
256+
templates_path = os.path.join(os.path.dirname(Path(__file__)),
257+
'_templates', 'models')
258+
main(['-TMf', '-s', 'inc',
259+
'-t', templates_path,
260+
'-o', out_path, daq_models_path])
261+
262+
263+
members_to_watch = ['module', 'class', 'function', 'exception', 'method', 'attribute']
264+
doc_count = 0
265+
undoc_count = 0
266+
undoc_objects = []
267+
undoc_print_objects = False
268+
269+
270+
def doc_coverage(app, what, name, obj, options, lines):
271+
global doc_count
272+
global undoc_count
273+
global undoc_objects
274+
275+
if (what in members_to_watch and len(lines) == 0):
276+
# blank docstring detected
277+
undoc_count += 1
278+
undoc_objects.append(name)
279+
else:
280+
doc_count += 1
281+
282+
283+
def doc_report(app, exception):
284+
global doc_count
285+
global undoc_count
286+
global undoc_objects
287+
# print out report of documentation coverage
288+
total_docs = undoc_count + doc_count
289+
if total_docs != 0:
290+
print(f'\nAPI Doc coverage of {doc_count/total_docs:.1%}')
291+
if undoc_print_objects or os.environ.get('READTHEDOCS'):
292+
print('\nItems lacking documentation')
293+
print('===========================')
294+
print(*undoc_objects, sep='\n')
295+
else:
296+
print('No docs counted, run \'make clean\' then rebuild to get the count.')

docs/source/devices.rst

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
Devices
2+
=========
3+
4+
Here is a list of all the currently supported devices.
5+
6+
7+
Pseudoclocks
8+
~~~~~~~~~~~~
9+
10+
Pseudoclocks provide the timing backbone of the labscript_suite.
11+
These devices produce hardware-timed clocklines that trigger other device outputs and acquisitions.
12+
Many pseudoclock devices also include other types of outputs, including digital voltage and DDS frequency synthesizers.
13+
14+
.. toctree::
15+
:maxdepth: 2
16+
17+
devices/pulseblaster
18+
devices/pulseblaster_no_dds
19+
devices/opalkellyXEM3001
20+
devices/pineblaster
21+
devices/prawnblaster
22+
devices/rfblaster
23+
24+
NI DAQS
25+
~~~~~~~~~~~~
26+
27+
The NI_DAQmx device provides a generic interface for National Instruments data acquisition hardware.
28+
This includes digital and analog voltage I/O. These input/outputs can be either static or hardware-timed dynamically changing variables.
29+
30+
.. toctree::
31+
:maxdepth: 2
32+
33+
devices/ni_daqs
34+
35+
Cameras
36+
~~~~~~~~~~~~
37+
38+
The camera devices provide interfaces for using various scientific cameras to acquire hardware-timed images during an experiment.
39+
They are organized by the programming API the underlies the communication to the device.
40+
The "master" camera class which provides the core functionality and from which the others derive is the IMAQdx class.
41+
42+
.. toctree::
43+
:maxdepth: 2
44+
45+
devices/IMAQdx
46+
devices/pylon
47+
devices/flycapture2
48+
devices/spinnaker
49+
devices/andorsolis
50+
51+
52+
Frequency Sources
53+
~~~~~~~~~~~~~~~~~
54+
55+
These devices cover various frequency sources that provide either hardware-timed frequency, amplitude, or phase updates or static frequency outputs.
56+
57+
.. toctree::
58+
:maxdepth: 2
59+
60+
devices/novatechDDS9m
61+
devices/phasematrixquicksyn
62+
63+
64+
Miscellaneous
65+
~~~~~~~~~~~~~~~
66+
67+
These devices cover other types of devices.
68+
69+
.. toctree::
70+
:maxdepth: 2
71+
72+
devices/alazartechboard
73+
devices/lightcrafterdmd
74+
devices/tekscope
75+
devices/zaberstagecontroller
76+
77+
78+
Other
79+
~~~~~~~~~~~~~~
80+
81+
These devices provide dummy instruments for prototyping and testing purposes of the rest of the labscript_suite as well as the FunctionRunner device which can run arbitrary code post-shot.
82+
83+
.. toctree::
84+
:maxdepth: 2
85+
86+
devices/functionrunner
87+
devices/dummypseudoclock
88+
devices/dummyintermediate
89+
devices/testdevice
90+

docs/source/devices/IMAQdx.rst

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
IMAQdx Cameras
2+
==============
3+
4+
Overview
5+
~~~~~~~~
6+
7+
The "master" camera device from which all others derive.
8+
9+
.. autosummary::
10+
labscript_devices.IMAQdxCamera.labscript_devices
11+
labscript_devices.IMAQdxCamera.blacs_tabs
12+
labscript_devices.IMAQdxCamera.blacs_workers
13+
14+
Installation
15+
~~~~~~~~~~~~
16+
17+
18+
Usage
19+
~~~~~
20+
21+
22+
Detailed Documentation
23+
~~~~~~~~~~~~~~~~~~~~~~
24+
25+
.. automodule:: labscript_devices.IMAQdxCamera
26+
:members:
27+
:undoc-members:
28+
:show-inheritance:
29+
:private-members:
30+
31+
.. automodule:: labscript_devices.IMAQdxCamera.labscript_devices
32+
:members:
33+
:undoc-members:
34+
:show-inheritance:
35+
:private-members:
36+
37+
.. automodule:: labscript_devices.IMAQdxCamera.blacs_tabs
38+
:members:
39+
:undoc-members:
40+
:show-inheritance:
41+
:private-members:
42+
43+
.. automodule:: labscript_devices.IMAQdxCamera.blacs_workers
44+
:members:
45+
:undoc-members:
46+
:show-inheritance:
47+
:private-members:
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Alazar Tech Board
2+
=================
3+
4+
A labscript device class for data acquisition boards made by Alazar Technologies Inc (ATS).
5+
6+
Installation
7+
~~~~~~~~~~~~
8+
9+
This device requires the atsapi.py wrapper. It should be installed into site-packages or
10+
kept in the local directory.
11+
12+
It also uses the tqdm progress bar, which is not a standard dependency for the labscript-suite.
13+
14+
Detailed Documentation
15+
~~~~~~~~~~~~~~~~~~~~~~
16+
17+
.. automodule:: labscript_devices.AlazarTechBoard
18+
:members:
19+
:undoc-members:
20+
:show-inheritance:
21+
:member-order: bysource
22+
:private-members:

0 commit comments

Comments
 (0)