QInstrument 0.4.0__tar.gz

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 (75) hide show
  1. qinstrument-0.4.0/LICENSE.md +17 -0
  2. qinstrument-0.4.0/PKG-INFO +176 -0
  3. qinstrument-0.4.0/QInstrument.egg-info/PKG-INFO +176 -0
  4. qinstrument-0.4.0/QInstrument.egg-info/SOURCES.txt +134 -0
  5. qinstrument-0.4.0/QInstrument.egg-info/dependency_links.txt +1 -0
  6. qinstrument-0.4.0/QInstrument.egg-info/requires.txt +14 -0
  7. qinstrument-0.4.0/QInstrument.egg-info/top_level.txt +1 -0
  8. qinstrument-0.4.0/README.md +125 -0
  9. qinstrument-0.4.0/__init__.py +7 -0
  10. qinstrument-0.4.0/instruments/DS345/DS345Widget.ui +562 -0
  11. qinstrument-0.4.0/instruments/DS345/__init__.py +11 -0
  12. qinstrument-0.4.0/instruments/DS345/fake.py +21 -0
  13. qinstrument-0.4.0/instruments/DS345/instrument.py +294 -0
  14. qinstrument-0.4.0/instruments/DS345/widget.py +19 -0
  15. qinstrument-0.4.0/instruments/IPGLaser/IPGLaserWidget.ui +95 -0
  16. qinstrument-0.4.0/instruments/IPGLaser/Ipglaser.py +182 -0
  17. qinstrument-0.4.0/instruments/IPGLaser/__init__.py +11 -0
  18. qinstrument-0.4.0/instruments/IPGLaser/fake.py +20 -0
  19. qinstrument-0.4.0/instruments/IPGLaser/icons/amber-led-off.png +0 -0
  20. qinstrument-0.4.0/instruments/IPGLaser/icons/amber-led-on.png +0 -0
  21. qinstrument-0.4.0/instruments/IPGLaser/icons/green-led-off.png +0 -0
  22. qinstrument-0.4.0/instruments/IPGLaser/icons/green-led-on.png +0 -0
  23. qinstrument-0.4.0/instruments/IPGLaser/icons/red-led-off.png +0 -0
  24. qinstrument-0.4.0/instruments/IPGLaser/icons/red-led-on.png +0 -0
  25. qinstrument-0.4.0/instruments/IPGLaser/instrument.py +121 -0
  26. qinstrument-0.4.0/instruments/IPGLaser/widget.py +35 -0
  27. qinstrument-0.4.0/instruments/Opus/OpusWidget.ui +382 -0
  28. qinstrument-0.4.0/instruments/Opus/__init__.py +11 -0
  29. qinstrument-0.4.0/instruments/Opus/instrument.py +125 -0
  30. qinstrument-0.4.0/instruments/Opus/widget.py +89 -0
  31. qinstrument-0.4.0/instruments/PiezoDrive/PDUS210Widget.ui +359 -0
  32. qinstrument-0.4.0/instruments/PiezoDrive/__init__.py +11 -0
  33. qinstrument-0.4.0/instruments/PiezoDrive/instrument.py +128 -0
  34. qinstrument-0.4.0/instruments/PiezoDrive/widget.py +43 -0
  35. qinstrument-0.4.0/instruments/Proscan/ProscanWidget.ui +573 -0
  36. qinstrument-0.4.0/instruments/Proscan/__init__.py +11 -0
  37. qinstrument-0.4.0/instruments/Proscan/instrument.py +265 -0
  38. qinstrument-0.4.0/instruments/Proscan/widget.py +65 -0
  39. qinstrument-0.4.0/instruments/SR830/SR830Widget.ui +775 -0
  40. qinstrument-0.4.0/instruments/SR830/__init__.py +11 -0
  41. qinstrument-0.4.0/instruments/SR830/fake.py +45 -0
  42. qinstrument-0.4.0/instruments/SR830/instrument.py +187 -0
  43. qinstrument-0.4.0/instruments/SR830/widget.py +19 -0
  44. qinstrument-0.4.0/instruments/SR844/QFakeSR844.py +8 -0
  45. qinstrument-0.4.0/instruments/SR844/QSR844.py +7 -0
  46. qinstrument-0.4.0/instruments/SR844/QSR844Widget.py +28 -0
  47. qinstrument-0.4.0/instruments/SR844/SR844Widget.ui +584 -0
  48. qinstrument-0.4.0/instruments/SR844/__init__.py +11 -0
  49. qinstrument-0.4.0/instruments/SR844/fake.py +45 -0
  50. qinstrument-0.4.0/instruments/SR844/instrument.py +208 -0
  51. qinstrument-0.4.0/instruments/SR844/widget.py +19 -0
  52. qinstrument-0.4.0/instruments/TDS1000/__init__.py +11 -0
  53. qinstrument-0.4.0/instruments/TDS1000/instrument.py +60 -0
  54. qinstrument-0.4.0/instruments/__init__.py +10 -0
  55. qinstrument-0.4.0/lib/Configure.py +130 -0
  56. qinstrument-0.4.0/lib/QAbstractInstrument.py +285 -0
  57. qinstrument-0.4.0/lib/QFakeInstrument.py +92 -0
  58. qinstrument-0.4.0/lib/QInstrumentWidget.py +340 -0
  59. qinstrument-0.4.0/lib/QSerialInstrument.py +188 -0
  60. qinstrument-0.4.0/lib/QSerialInterface.py +294 -0
  61. qinstrument-0.4.0/lib/QThreadedInstrumentWidget.py +20 -0
  62. qinstrument-0.4.0/lib/__init__.py +20 -0
  63. qinstrument-0.4.0/lib/threadedInstrument.py +24 -0
  64. qinstrument-0.4.0/pyproject.toml +73 -0
  65. qinstrument-0.4.0/setup.cfg +4 -0
  66. qinstrument-0.4.0/tests/test_QAbstractInstrument.py +204 -0
  67. qinstrument-0.4.0/tests/test_QFakeInstrument.py +144 -0
  68. qinstrument-0.4.0/tests/test_QInstrumentWidget.py +114 -0
  69. qinstrument-0.4.0/tests/test_QSerialInterface.py +271 -0
  70. qinstrument-0.4.0/widgets/QJoystick.py +118 -0
  71. qinstrument-0.4.0/widgets/QLedWidget.py +158 -0
  72. qinstrument-0.4.0/widgets/QRotaryEncoder.py +86 -0
  73. qinstrument-0.4.0/widgets/QRotaryEncoderSpinBox.py +155 -0
  74. qinstrument-0.4.0/widgets/QRotaryEncoderSpinBox.ui +171 -0
  75. qinstrument-0.4.0/widgets/__init__.py +18 -0
@@ -0,0 +1,17 @@
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2022 David G. Grier
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
@@ -0,0 +1,176 @@
1
+ Metadata-Version: 2.4
2
+ Name: QInstrument
3
+ Version: 0.4.0
4
+ Summary: Qt-based framework for controlling scientific instruments over serial ports
5
+ Author-email: "David G. Grier" <david.grier@nyu.edu>
6
+ License: GNU GENERAL PUBLIC LICENSE
7
+ Version 3, 29 June 2007
8
+
9
+ Copyright (C) 2022 David G. Grier
10
+
11
+ This program is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ This program is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU General Public License for more details.
20
+
21
+ You should have received a copy of the GNU General Public License
22
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
23
+
24
+ Project-URL: Homepage, https://github.com/davidgrier/QInstrument
25
+ Project-URL: Repository, https://github.com/davidgrier/QInstrument
26
+ Keywords: scientific instruments,serial port,Qt,laboratory automation
27
+ Classifier: Development Status :: 4 - Beta
28
+ Classifier: Intended Audience :: Science/Research
29
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: Programming Language :: Python :: 3.10
32
+ Classifier: Programming Language :: Python :: 3.11
33
+ Classifier: Programming Language :: Python :: 3.12
34
+ Classifier: Topic :: Scientific/Engineering
35
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
36
+ Requires-Python: >=3.10
37
+ Description-Content-Type: text/markdown
38
+ License-File: LICENSE.md
39
+ Requires-Dist: numpy>=1.20
40
+ Requires-Dist: qtpy>=2.0
41
+ Provides-Extra: plot
42
+ Requires-Dist: matplotlib>=3.5; extra == "plot"
43
+ Provides-Extra: docs
44
+ Requires-Dist: sphinx>=7.0; extra == "docs"
45
+ Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
46
+ Requires-Dist: sphinx-autodoc-typehints>=1.25; extra == "docs"
47
+ Provides-Extra: dev
48
+ Requires-Dist: pytest>=7.0; extra == "dev"
49
+ Requires-Dist: pytest-qt>=4.0; extra == "dev"
50
+ Dynamic: license-file
51
+
52
+ # QInstrument
53
+
54
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
55
+
56
+ A Qt-based framework for controlling scientific instruments over serial ports.
57
+ Instruments are represented as Qt objects with a uniform property system,
58
+ automatic UI binding, and JSON-based configuration persistence.
59
+ Any Qt binding (PyQt5, PyQt6, PySide2, PySide6) is supported via `qtpy`.
60
+
61
+ ## Instruments
62
+
63
+ ### IPG Photonics
64
+ - **YLR Series**: Ytterbium fibre laser
65
+
66
+ ### Laser Quantum
67
+ - **Opus**: Continuous-wave laser
68
+
69
+ ### PiezoDrive
70
+ - **PDUS210**: Piezo transducer driver
71
+
72
+ ### Prior Scientific
73
+ - **Proscan II/III**: Motorised microscope stage controller
74
+
75
+ ### Stanford Research Systems
76
+ - **DS345**: 30 MHz Synthesised Function Generator
77
+ - **SR830**: 100 kHz Digital Lock-in Amplifier
78
+ - **SR844**: 200 MHz RF Lock-in Amplifier
79
+
80
+ ### Tektronix
81
+ - **TDS1000**: Digital oscilloscope
82
+
83
+ ## Installation
84
+
85
+ ```bash
86
+ git clone https://github.com/davidgrier/QInstrument
87
+ cd QInstrument
88
+ python -m venv .qi
89
+ source .qi/bin/activate
90
+ pip install -r requirements.txt
91
+ ```
92
+
93
+ ## Quick start
94
+
95
+ Each instrument widget has a built-in `example()` entry point.
96
+ Run it directly from the command line:
97
+
98
+ ```bash
99
+ python -m QInstrument.instruments.DS345.widget
100
+ ```
101
+
102
+ This finds a connected DS345 and opens its control panel.
103
+ If no instrument is detected it falls back automatically to a simulated
104
+ (fake) device so the UI is always usable.
105
+
106
+ You can also drive the widget from your own application:
107
+
108
+ ```python
109
+ from qtpy.QtWidgets import QApplication
110
+ from QInstrument.instruments.DS345 import QDS345Widget
111
+
112
+ app = QApplication([])
113
+ widget = QDS345Widget()
114
+ widget.show()
115
+ app.exec()
116
+ ```
117
+
118
+ <img src="docs/QDS345Widget.png" width="50%" alt="DS345 Widget">
119
+
120
+ ### Using a simulated instrument
121
+
122
+ When hardware is not available, import the fake class directly:
123
+
124
+ ```python
125
+ from QInstrument.instruments.DS345 import QDS345Widget, QFakeDS345
126
+
127
+ app = QApplication([])
128
+ widget = QDS345Widget(device=QFakeDS345())
129
+ widget.show()
130
+ app.exec()
131
+ ```
132
+
133
+ ## Architecture
134
+
135
+ ```
136
+ QtCore.QObject
137
+ └── QAbstractInstrument # property/method registry, thread-safe get/set, settings I/O
138
+ └── QSerialInstrument # holds QSerialInterface; adds open/find/identify
139
+ └── QXxxInstrument # concrete instrument
140
+
141
+ QtSerialPort.QSerialPort
142
+ └── QSerialInterface # raw serial I/O (owned by QSerialInstrument)
143
+
144
+ QWidget
145
+ └── QInstrumentWidget # loads .ui file, auto-binds widgets to registered properties
146
+ ```
147
+
148
+ Each instrument lives in `instruments/<Name>/` with three files:
149
+
150
+ | File | Purpose |
151
+ |------|---------|
152
+ | `instrument.py` | Serial communication and property registration |
153
+ | `fake.py` | Simulated instrument for UI development without hardware |
154
+ | `widget.py` | Qt widget, `.ui` file binding, `example()` entry point |
155
+
156
+ ## Development
157
+
158
+ Run the test suite:
159
+
160
+ ```bash
161
+ source .qi/bin/activate
162
+ pytest tests/
163
+ ```
164
+
165
+ Tests run automatically before every `git push` via a pre-push hook.
166
+ To install the hook in a fresh clone:
167
+
168
+ ```bash
169
+ cp hooks/pre-push .git/hooks/pre-push # if tracked, else set up manually
170
+ chmod +x .git/hooks/pre-push
171
+ ```
172
+
173
+ ## Acknowledgements
174
+
175
+ Work on this project at New York University is supported by the
176
+ National Science Foundation of the United States under award number DMR-2438983.
@@ -0,0 +1,176 @@
1
+ Metadata-Version: 2.4
2
+ Name: QInstrument
3
+ Version: 0.4.0
4
+ Summary: Qt-based framework for controlling scientific instruments over serial ports
5
+ Author-email: "David G. Grier" <david.grier@nyu.edu>
6
+ License: GNU GENERAL PUBLIC LICENSE
7
+ Version 3, 29 June 2007
8
+
9
+ Copyright (C) 2022 David G. Grier
10
+
11
+ This program is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ This program is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU General Public License for more details.
20
+
21
+ You should have received a copy of the GNU General Public License
22
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
23
+
24
+ Project-URL: Homepage, https://github.com/davidgrier/QInstrument
25
+ Project-URL: Repository, https://github.com/davidgrier/QInstrument
26
+ Keywords: scientific instruments,serial port,Qt,laboratory automation
27
+ Classifier: Development Status :: 4 - Beta
28
+ Classifier: Intended Audience :: Science/Research
29
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: Programming Language :: Python :: 3.10
32
+ Classifier: Programming Language :: Python :: 3.11
33
+ Classifier: Programming Language :: Python :: 3.12
34
+ Classifier: Topic :: Scientific/Engineering
35
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
36
+ Requires-Python: >=3.10
37
+ Description-Content-Type: text/markdown
38
+ License-File: LICENSE.md
39
+ Requires-Dist: numpy>=1.20
40
+ Requires-Dist: qtpy>=2.0
41
+ Provides-Extra: plot
42
+ Requires-Dist: matplotlib>=3.5; extra == "plot"
43
+ Provides-Extra: docs
44
+ Requires-Dist: sphinx>=7.0; extra == "docs"
45
+ Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
46
+ Requires-Dist: sphinx-autodoc-typehints>=1.25; extra == "docs"
47
+ Provides-Extra: dev
48
+ Requires-Dist: pytest>=7.0; extra == "dev"
49
+ Requires-Dist: pytest-qt>=4.0; extra == "dev"
50
+ Dynamic: license-file
51
+
52
+ # QInstrument
53
+
54
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
55
+
56
+ A Qt-based framework for controlling scientific instruments over serial ports.
57
+ Instruments are represented as Qt objects with a uniform property system,
58
+ automatic UI binding, and JSON-based configuration persistence.
59
+ Any Qt binding (PyQt5, PyQt6, PySide2, PySide6) is supported via `qtpy`.
60
+
61
+ ## Instruments
62
+
63
+ ### IPG Photonics
64
+ - **YLR Series**: Ytterbium fibre laser
65
+
66
+ ### Laser Quantum
67
+ - **Opus**: Continuous-wave laser
68
+
69
+ ### PiezoDrive
70
+ - **PDUS210**: Piezo transducer driver
71
+
72
+ ### Prior Scientific
73
+ - **Proscan II/III**: Motorised microscope stage controller
74
+
75
+ ### Stanford Research Systems
76
+ - **DS345**: 30 MHz Synthesised Function Generator
77
+ - **SR830**: 100 kHz Digital Lock-in Amplifier
78
+ - **SR844**: 200 MHz RF Lock-in Amplifier
79
+
80
+ ### Tektronix
81
+ - **TDS1000**: Digital oscilloscope
82
+
83
+ ## Installation
84
+
85
+ ```bash
86
+ git clone https://github.com/davidgrier/QInstrument
87
+ cd QInstrument
88
+ python -m venv .qi
89
+ source .qi/bin/activate
90
+ pip install -r requirements.txt
91
+ ```
92
+
93
+ ## Quick start
94
+
95
+ Each instrument widget has a built-in `example()` entry point.
96
+ Run it directly from the command line:
97
+
98
+ ```bash
99
+ python -m QInstrument.instruments.DS345.widget
100
+ ```
101
+
102
+ This finds a connected DS345 and opens its control panel.
103
+ If no instrument is detected it falls back automatically to a simulated
104
+ (fake) device so the UI is always usable.
105
+
106
+ You can also drive the widget from your own application:
107
+
108
+ ```python
109
+ from qtpy.QtWidgets import QApplication
110
+ from QInstrument.instruments.DS345 import QDS345Widget
111
+
112
+ app = QApplication([])
113
+ widget = QDS345Widget()
114
+ widget.show()
115
+ app.exec()
116
+ ```
117
+
118
+ <img src="docs/QDS345Widget.png" width="50%" alt="DS345 Widget">
119
+
120
+ ### Using a simulated instrument
121
+
122
+ When hardware is not available, import the fake class directly:
123
+
124
+ ```python
125
+ from QInstrument.instruments.DS345 import QDS345Widget, QFakeDS345
126
+
127
+ app = QApplication([])
128
+ widget = QDS345Widget(device=QFakeDS345())
129
+ widget.show()
130
+ app.exec()
131
+ ```
132
+
133
+ ## Architecture
134
+
135
+ ```
136
+ QtCore.QObject
137
+ └── QAbstractInstrument # property/method registry, thread-safe get/set, settings I/O
138
+ └── QSerialInstrument # holds QSerialInterface; adds open/find/identify
139
+ └── QXxxInstrument # concrete instrument
140
+
141
+ QtSerialPort.QSerialPort
142
+ └── QSerialInterface # raw serial I/O (owned by QSerialInstrument)
143
+
144
+ QWidget
145
+ └── QInstrumentWidget # loads .ui file, auto-binds widgets to registered properties
146
+ ```
147
+
148
+ Each instrument lives in `instruments/<Name>/` with three files:
149
+
150
+ | File | Purpose |
151
+ |------|---------|
152
+ | `instrument.py` | Serial communication and property registration |
153
+ | `fake.py` | Simulated instrument for UI development without hardware |
154
+ | `widget.py` | Qt widget, `.ui` file binding, `example()` entry point |
155
+
156
+ ## Development
157
+
158
+ Run the test suite:
159
+
160
+ ```bash
161
+ source .qi/bin/activate
162
+ pytest tests/
163
+ ```
164
+
165
+ Tests run automatically before every `git push` via a pre-push hook.
166
+ To install the hook in a fresh clone:
167
+
168
+ ```bash
169
+ cp hooks/pre-push .git/hooks/pre-push # if tracked, else set up manually
170
+ chmod +x .git/hooks/pre-push
171
+ ```
172
+
173
+ ## Acknowledgements
174
+
175
+ Work on this project at New York University is supported by the
176
+ National Science Foundation of the United States under award number DMR-2438983.
@@ -0,0 +1,134 @@
1
+ LICENSE.md
2
+ README.md
3
+ __init__.py
4
+ pyproject.toml
5
+ ./__init__.py
6
+ ./instruments/__init__.py
7
+ ./instruments/DS345/DS345Widget.ui
8
+ ./instruments/DS345/__init__.py
9
+ ./instruments/DS345/fake.py
10
+ ./instruments/DS345/instrument.py
11
+ ./instruments/DS345/widget.py
12
+ ./instruments/IPGLaser/IPGLaserWidget.ui
13
+ ./instruments/IPGLaser/Ipglaser.py
14
+ ./instruments/IPGLaser/__init__.py
15
+ ./instruments/IPGLaser/fake.py
16
+ ./instruments/IPGLaser/instrument.py
17
+ ./instruments/IPGLaser/widget.py
18
+ ./instruments/IPGLaser/icons/amber-led-off.png
19
+ ./instruments/IPGLaser/icons/amber-led-on.png
20
+ ./instruments/IPGLaser/icons/green-led-off.png
21
+ ./instruments/IPGLaser/icons/green-led-on.png
22
+ ./instruments/IPGLaser/icons/red-led-off.png
23
+ ./instruments/IPGLaser/icons/red-led-on.png
24
+ ./instruments/Opus/OpusWidget.ui
25
+ ./instruments/Opus/__init__.py
26
+ ./instruments/Opus/instrument.py
27
+ ./instruments/Opus/widget.py
28
+ ./instruments/PiezoDrive/PDUS210Widget.ui
29
+ ./instruments/PiezoDrive/__init__.py
30
+ ./instruments/PiezoDrive/instrument.py
31
+ ./instruments/PiezoDrive/widget.py
32
+ ./instruments/Proscan/ProscanWidget.ui
33
+ ./instruments/Proscan/__init__.py
34
+ ./instruments/Proscan/instrument.py
35
+ ./instruments/Proscan/widget.py
36
+ ./instruments/SR830/SR830Widget.ui
37
+ ./instruments/SR830/__init__.py
38
+ ./instruments/SR830/fake.py
39
+ ./instruments/SR830/instrument.py
40
+ ./instruments/SR830/widget.py
41
+ ./instruments/SR844/QFakeSR844.py
42
+ ./instruments/SR844/QSR844.py
43
+ ./instruments/SR844/QSR844Widget.py
44
+ ./instruments/SR844/SR844Widget.ui
45
+ ./instruments/SR844/__init__.py
46
+ ./instruments/SR844/fake.py
47
+ ./instruments/SR844/instrument.py
48
+ ./instruments/SR844/widget.py
49
+ ./instruments/TDS1000/__init__.py
50
+ ./instruments/TDS1000/instrument.py
51
+ ./lib/Configure.py
52
+ ./lib/QAbstractInstrument.py
53
+ ./lib/QFakeInstrument.py
54
+ ./lib/QInstrumentWidget.py
55
+ ./lib/QSerialInstrument.py
56
+ ./lib/QSerialInterface.py
57
+ ./lib/QThreadedInstrumentWidget.py
58
+ ./lib/__init__.py
59
+ ./lib/threadedInstrument.py
60
+ ./widgets/QJoystick.py
61
+ ./widgets/QLedWidget.py
62
+ ./widgets/QRotaryEncoder.py
63
+ ./widgets/QRotaryEncoderSpinBox.py
64
+ ./widgets/QRotaryEncoderSpinBox.ui
65
+ ./widgets/__init__.py
66
+ QInstrument.egg-info/PKG-INFO
67
+ QInstrument.egg-info/SOURCES.txt
68
+ QInstrument.egg-info/dependency_links.txt
69
+ QInstrument.egg-info/requires.txt
70
+ QInstrument.egg-info/top_level.txt
71
+ instruments/__init__.py
72
+ instruments/DS345/DS345Widget.ui
73
+ instruments/DS345/__init__.py
74
+ instruments/DS345/fake.py
75
+ instruments/DS345/instrument.py
76
+ instruments/DS345/widget.py
77
+ instruments/IPGLaser/IPGLaserWidget.ui
78
+ instruments/IPGLaser/Ipglaser.py
79
+ instruments/IPGLaser/__init__.py
80
+ instruments/IPGLaser/fake.py
81
+ instruments/IPGLaser/instrument.py
82
+ instruments/IPGLaser/widget.py
83
+ instruments/IPGLaser/icons/amber-led-off.png
84
+ instruments/IPGLaser/icons/amber-led-on.png
85
+ instruments/IPGLaser/icons/green-led-off.png
86
+ instruments/IPGLaser/icons/green-led-on.png
87
+ instruments/IPGLaser/icons/red-led-off.png
88
+ instruments/IPGLaser/icons/red-led-on.png
89
+ instruments/Opus/OpusWidget.ui
90
+ instruments/Opus/__init__.py
91
+ instruments/Opus/instrument.py
92
+ instruments/Opus/widget.py
93
+ instruments/PiezoDrive/PDUS210Widget.ui
94
+ instruments/PiezoDrive/__init__.py
95
+ instruments/PiezoDrive/instrument.py
96
+ instruments/PiezoDrive/widget.py
97
+ instruments/Proscan/ProscanWidget.ui
98
+ instruments/Proscan/__init__.py
99
+ instruments/Proscan/instrument.py
100
+ instruments/Proscan/widget.py
101
+ instruments/SR830/SR830Widget.ui
102
+ instruments/SR830/__init__.py
103
+ instruments/SR830/fake.py
104
+ instruments/SR830/instrument.py
105
+ instruments/SR830/widget.py
106
+ instruments/SR844/QFakeSR844.py
107
+ instruments/SR844/QSR844.py
108
+ instruments/SR844/QSR844Widget.py
109
+ instruments/SR844/SR844Widget.ui
110
+ instruments/SR844/__init__.py
111
+ instruments/SR844/fake.py
112
+ instruments/SR844/instrument.py
113
+ instruments/SR844/widget.py
114
+ instruments/TDS1000/__init__.py
115
+ instruments/TDS1000/instrument.py
116
+ lib/Configure.py
117
+ lib/QAbstractInstrument.py
118
+ lib/QFakeInstrument.py
119
+ lib/QInstrumentWidget.py
120
+ lib/QSerialInstrument.py
121
+ lib/QSerialInterface.py
122
+ lib/QThreadedInstrumentWidget.py
123
+ lib/__init__.py
124
+ lib/threadedInstrument.py
125
+ tests/test_QAbstractInstrument.py
126
+ tests/test_QFakeInstrument.py
127
+ tests/test_QInstrumentWidget.py
128
+ tests/test_QSerialInterface.py
129
+ widgets/QJoystick.py
130
+ widgets/QLedWidget.py
131
+ widgets/QRotaryEncoder.py
132
+ widgets/QRotaryEncoderSpinBox.py
133
+ widgets/QRotaryEncoderSpinBox.ui
134
+ widgets/__init__.py
@@ -0,0 +1,14 @@
1
+ numpy>=1.20
2
+ qtpy>=2.0
3
+
4
+ [dev]
5
+ pytest>=7.0
6
+ pytest-qt>=4.0
7
+
8
+ [docs]
9
+ sphinx>=7.0
10
+ sphinx-rtd-theme>=2.0
11
+ sphinx-autodoc-typehints>=1.25
12
+
13
+ [plot]
14
+ matplotlib>=3.5
@@ -0,0 +1 @@
1
+ QInstrument
@@ -0,0 +1,125 @@
1
+ # QInstrument
2
+
3
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
4
+
5
+ A Qt-based framework for controlling scientific instruments over serial ports.
6
+ Instruments are represented as Qt objects with a uniform property system,
7
+ automatic UI binding, and JSON-based configuration persistence.
8
+ Any Qt binding (PyQt5, PyQt6, PySide2, PySide6) is supported via `qtpy`.
9
+
10
+ ## Instruments
11
+
12
+ ### IPG Photonics
13
+ - **YLR Series**: Ytterbium fibre laser
14
+
15
+ ### Laser Quantum
16
+ - **Opus**: Continuous-wave laser
17
+
18
+ ### PiezoDrive
19
+ - **PDUS210**: Piezo transducer driver
20
+
21
+ ### Prior Scientific
22
+ - **Proscan II/III**: Motorised microscope stage controller
23
+
24
+ ### Stanford Research Systems
25
+ - **DS345**: 30 MHz Synthesised Function Generator
26
+ - **SR830**: 100 kHz Digital Lock-in Amplifier
27
+ - **SR844**: 200 MHz RF Lock-in Amplifier
28
+
29
+ ### Tektronix
30
+ - **TDS1000**: Digital oscilloscope
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ git clone https://github.com/davidgrier/QInstrument
36
+ cd QInstrument
37
+ python -m venv .qi
38
+ source .qi/bin/activate
39
+ pip install -r requirements.txt
40
+ ```
41
+
42
+ ## Quick start
43
+
44
+ Each instrument widget has a built-in `example()` entry point.
45
+ Run it directly from the command line:
46
+
47
+ ```bash
48
+ python -m QInstrument.instruments.DS345.widget
49
+ ```
50
+
51
+ This finds a connected DS345 and opens its control panel.
52
+ If no instrument is detected it falls back automatically to a simulated
53
+ (fake) device so the UI is always usable.
54
+
55
+ You can also drive the widget from your own application:
56
+
57
+ ```python
58
+ from qtpy.QtWidgets import QApplication
59
+ from QInstrument.instruments.DS345 import QDS345Widget
60
+
61
+ app = QApplication([])
62
+ widget = QDS345Widget()
63
+ widget.show()
64
+ app.exec()
65
+ ```
66
+
67
+ <img src="docs/QDS345Widget.png" width="50%" alt="DS345 Widget">
68
+
69
+ ### Using a simulated instrument
70
+
71
+ When hardware is not available, import the fake class directly:
72
+
73
+ ```python
74
+ from QInstrument.instruments.DS345 import QDS345Widget, QFakeDS345
75
+
76
+ app = QApplication([])
77
+ widget = QDS345Widget(device=QFakeDS345())
78
+ widget.show()
79
+ app.exec()
80
+ ```
81
+
82
+ ## Architecture
83
+
84
+ ```
85
+ QtCore.QObject
86
+ └── QAbstractInstrument # property/method registry, thread-safe get/set, settings I/O
87
+ └── QSerialInstrument # holds QSerialInterface; adds open/find/identify
88
+ └── QXxxInstrument # concrete instrument
89
+
90
+ QtSerialPort.QSerialPort
91
+ └── QSerialInterface # raw serial I/O (owned by QSerialInstrument)
92
+
93
+ QWidget
94
+ └── QInstrumentWidget # loads .ui file, auto-binds widgets to registered properties
95
+ ```
96
+
97
+ Each instrument lives in `instruments/<Name>/` with three files:
98
+
99
+ | File | Purpose |
100
+ |------|---------|
101
+ | `instrument.py` | Serial communication and property registration |
102
+ | `fake.py` | Simulated instrument for UI development without hardware |
103
+ | `widget.py` | Qt widget, `.ui` file binding, `example()` entry point |
104
+
105
+ ## Development
106
+
107
+ Run the test suite:
108
+
109
+ ```bash
110
+ source .qi/bin/activate
111
+ pytest tests/
112
+ ```
113
+
114
+ Tests run automatically before every `git push` via a pre-push hook.
115
+ To install the hook in a fresh clone:
116
+
117
+ ```bash
118
+ cp hooks/pre-push .git/hooks/pre-push # if tracked, else set up manually
119
+ chmod +x .git/hooks/pre-push
120
+ ```
121
+
122
+ ## Acknowledgements
123
+
124
+ Work on this project at New York University is supported by the
125
+ National Science Foundation of the United States under award number DMR-2438983.
@@ -0,0 +1,7 @@
1
+ from importlib.metadata import version, PackageNotFoundError
2
+
3
+ try:
4
+ __version__ = version('QInstrument')
5
+ except PackageNotFoundError:
6
+ # Package is not installed (e.g. running directly from the source tree)
7
+ __version__ = None