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.
- qinstrument-0.4.0/LICENSE.md +17 -0
- qinstrument-0.4.0/PKG-INFO +176 -0
- qinstrument-0.4.0/QInstrument.egg-info/PKG-INFO +176 -0
- qinstrument-0.4.0/QInstrument.egg-info/SOURCES.txt +134 -0
- qinstrument-0.4.0/QInstrument.egg-info/dependency_links.txt +1 -0
- qinstrument-0.4.0/QInstrument.egg-info/requires.txt +14 -0
- qinstrument-0.4.0/QInstrument.egg-info/top_level.txt +1 -0
- qinstrument-0.4.0/README.md +125 -0
- qinstrument-0.4.0/__init__.py +7 -0
- qinstrument-0.4.0/instruments/DS345/DS345Widget.ui +562 -0
- qinstrument-0.4.0/instruments/DS345/__init__.py +11 -0
- qinstrument-0.4.0/instruments/DS345/fake.py +21 -0
- qinstrument-0.4.0/instruments/DS345/instrument.py +294 -0
- qinstrument-0.4.0/instruments/DS345/widget.py +19 -0
- qinstrument-0.4.0/instruments/IPGLaser/IPGLaserWidget.ui +95 -0
- qinstrument-0.4.0/instruments/IPGLaser/Ipglaser.py +182 -0
- qinstrument-0.4.0/instruments/IPGLaser/__init__.py +11 -0
- qinstrument-0.4.0/instruments/IPGLaser/fake.py +20 -0
- qinstrument-0.4.0/instruments/IPGLaser/icons/amber-led-off.png +0 -0
- qinstrument-0.4.0/instruments/IPGLaser/icons/amber-led-on.png +0 -0
- qinstrument-0.4.0/instruments/IPGLaser/icons/green-led-off.png +0 -0
- qinstrument-0.4.0/instruments/IPGLaser/icons/green-led-on.png +0 -0
- qinstrument-0.4.0/instruments/IPGLaser/icons/red-led-off.png +0 -0
- qinstrument-0.4.0/instruments/IPGLaser/icons/red-led-on.png +0 -0
- qinstrument-0.4.0/instruments/IPGLaser/instrument.py +121 -0
- qinstrument-0.4.0/instruments/IPGLaser/widget.py +35 -0
- qinstrument-0.4.0/instruments/Opus/OpusWidget.ui +382 -0
- qinstrument-0.4.0/instruments/Opus/__init__.py +11 -0
- qinstrument-0.4.0/instruments/Opus/instrument.py +125 -0
- qinstrument-0.4.0/instruments/Opus/widget.py +89 -0
- qinstrument-0.4.0/instruments/PiezoDrive/PDUS210Widget.ui +359 -0
- qinstrument-0.4.0/instruments/PiezoDrive/__init__.py +11 -0
- qinstrument-0.4.0/instruments/PiezoDrive/instrument.py +128 -0
- qinstrument-0.4.0/instruments/PiezoDrive/widget.py +43 -0
- qinstrument-0.4.0/instruments/Proscan/ProscanWidget.ui +573 -0
- qinstrument-0.4.0/instruments/Proscan/__init__.py +11 -0
- qinstrument-0.4.0/instruments/Proscan/instrument.py +265 -0
- qinstrument-0.4.0/instruments/Proscan/widget.py +65 -0
- qinstrument-0.4.0/instruments/SR830/SR830Widget.ui +775 -0
- qinstrument-0.4.0/instruments/SR830/__init__.py +11 -0
- qinstrument-0.4.0/instruments/SR830/fake.py +45 -0
- qinstrument-0.4.0/instruments/SR830/instrument.py +187 -0
- qinstrument-0.4.0/instruments/SR830/widget.py +19 -0
- qinstrument-0.4.0/instruments/SR844/QFakeSR844.py +8 -0
- qinstrument-0.4.0/instruments/SR844/QSR844.py +7 -0
- qinstrument-0.4.0/instruments/SR844/QSR844Widget.py +28 -0
- qinstrument-0.4.0/instruments/SR844/SR844Widget.ui +584 -0
- qinstrument-0.4.0/instruments/SR844/__init__.py +11 -0
- qinstrument-0.4.0/instruments/SR844/fake.py +45 -0
- qinstrument-0.4.0/instruments/SR844/instrument.py +208 -0
- qinstrument-0.4.0/instruments/SR844/widget.py +19 -0
- qinstrument-0.4.0/instruments/TDS1000/__init__.py +11 -0
- qinstrument-0.4.0/instruments/TDS1000/instrument.py +60 -0
- qinstrument-0.4.0/instruments/__init__.py +10 -0
- qinstrument-0.4.0/lib/Configure.py +130 -0
- qinstrument-0.4.0/lib/QAbstractInstrument.py +285 -0
- qinstrument-0.4.0/lib/QFakeInstrument.py +92 -0
- qinstrument-0.4.0/lib/QInstrumentWidget.py +340 -0
- qinstrument-0.4.0/lib/QSerialInstrument.py +188 -0
- qinstrument-0.4.0/lib/QSerialInterface.py +294 -0
- qinstrument-0.4.0/lib/QThreadedInstrumentWidget.py +20 -0
- qinstrument-0.4.0/lib/__init__.py +20 -0
- qinstrument-0.4.0/lib/threadedInstrument.py +24 -0
- qinstrument-0.4.0/pyproject.toml +73 -0
- qinstrument-0.4.0/setup.cfg +4 -0
- qinstrument-0.4.0/tests/test_QAbstractInstrument.py +204 -0
- qinstrument-0.4.0/tests/test_QFakeInstrument.py +144 -0
- qinstrument-0.4.0/tests/test_QInstrumentWidget.py +114 -0
- qinstrument-0.4.0/tests/test_QSerialInterface.py +271 -0
- qinstrument-0.4.0/widgets/QJoystick.py +118 -0
- qinstrument-0.4.0/widgets/QLedWidget.py +158 -0
- qinstrument-0.4.0/widgets/QRotaryEncoder.py +86 -0
- qinstrument-0.4.0/widgets/QRotaryEncoderSpinBox.py +155 -0
- qinstrument-0.4.0/widgets/QRotaryEncoderSpinBox.ui +171 -0
- 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
|
+
[](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
|
+
[](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 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
QInstrument
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# QInstrument
|
|
2
|
+
|
|
3
|
+
[](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.
|