MultiPyVu 3.5.4__tar.gz → 3.8.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.
- {multipyvu-3.5.4 → multipyvu-3.8.0}/LICENSE +20 -20
- {multipyvu-3.5.4/src/MultiPyVu.egg-info → multipyvu-3.8.0}/PKG-INFO +39 -38
- {multipyvu-3.5.4 → multipyvu-3.8.0}/README.md +36 -12
- {multipyvu-3.5.4 → multipyvu-3.8.0}/pyproject.toml +11 -4
- multipyvu-3.8.0/setup.py +27 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/CommandChamber.py +35 -32
- multipyvu-3.5.4/src/MultiPyVu/Command_factory.py → multipyvu-3.8.0/src/MultiPyVu/CommandFactory.py +103 -3
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/CommandField.py +175 -94
- multipyvu-3.8.0/src/MultiPyVu/CommandFieldSetPoints.py +398 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/CommandMultiVu.py +27 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/CommandRotator.py +42 -36
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/CommandSdo.py +18 -5
- multipyvu-3.8.0/src/MultiPyVu/CommandTempSetPoints.py +257 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/CommandTemperature.py +130 -58
- multipyvu-3.8.0/src/MultiPyVu/CommandVectorMagnet.py +780 -0
- multipyvu-3.8.0/src/MultiPyVu/CommandWaitFor.py +851 -0
- multipyvu-3.8.0/src/MultiPyVu/ICommand.py +522 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/IEventManager.py +42 -42
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/IServer.py +68 -68
- multipyvu-3.8.0/src/MultiPyVu/MultiVuClient.py +849 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuClient_base.py +562 -521
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuDataFile/MultiVuDataFile.py +4 -0
- multipyvu-3.8.0/src/MultiPyVu/MultiVuDataFile/__version.py +2 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuDataFile/is_pathname_valid.py +3 -3
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuServer.py +405 -388
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/ParseInputs.py +14 -14
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/SocketMessage.py +16 -2
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/SocketMessageClient.py +526 -503
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/SocketMessageServer.py +912 -867
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/__init__.py +1 -1
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/__main__.py +3 -4
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/__version.py +1 -1
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/exceptions.py +1 -3
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/generate_sdo_objects.py +6 -2
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/gui/Controller.py +208 -246
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/gui/IController.py +132 -132
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/gui/IView.py +97 -83
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/gui/ViewFactory.py +26 -26
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/gui/ViewTk.py +687 -532
- multipyvu-3.8.0/src/MultiPyVu/gui/font_loader.py +204 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/instrument.py +62 -6
- multipyvu-3.8.0/src/MultiPyVu/logging_config.py +111 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/project_vars.py +13 -4
- multipyvu-3.8.0/src/MultiPyVu/scripts/helper_scripts.py +28 -0
- multipyvu-3.8.0/src/MultiPyVu/scripts/helper_scripts_client.py +54 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0/src/MultiPyVu.egg-info}/PKG-INFO +39 -38
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu.egg-info/SOURCES.txt +6 -2
- multipyvu-3.5.4/setup.py +0 -61
- multipyvu-3.5.4/src/MultiPyVu/CommandWaitFor.py +0 -507
- multipyvu-3.5.4/src/MultiPyVu/ICommand.py +0 -322
- multipyvu-3.5.4/src/MultiPyVu/MultiVuClient.py +0 -513
- multipyvu-3.5.4/src/MultiPyVu/MultiVuDataFile/__version.py +0 -2
- multipyvu-3.5.4/src/MultiPyVu/logging_config.py +0 -76
- multipyvu-3.5.4/src/MultiPyVu/scripts/helper_scripts.py +0 -118
- multipyvu-3.5.4/src/MultiPyVu/scripts/whats_my_ip_address.cmd +0 -21
- {multipyvu-3.5.4 → multipyvu-3.8.0}/setup.cfg +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/BRT.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuDataFile/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/check_windows_esc.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/font/Play-Bold.ttf +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/font/Play-Regular.ttf +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/font/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/gui/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/images/Q.png +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/images/QD_logo.jpg +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/images/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/logging_config.yaml +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/scripts/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu/sdo_object.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu.egg-info/dependency_links.txt +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu.egg-info/requires.txt +0 -0
- {multipyvu-3.5.4 → multipyvu-3.8.0}/src/MultiPyVu.egg-info/top_level.txt +0 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License (MIT)
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2023 Quantum Design, Inc
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1
|
+
MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Quantum Design, Inc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
@@ -1,41 +1,20 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MultiPyVu
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.8.0
|
|
4
4
|
Summary: Control MultiVu using Python
|
|
5
5
|
Author-email: Damon D Jackson <djackson@qdusa.com>
|
|
6
6
|
Maintainer-email: "Quantum Design, Inc." <apps@qdusa.com>
|
|
7
|
-
License: MIT
|
|
8
|
-
|
|
9
|
-
Copyright (c) 2023 Quantum Design, Inc
|
|
10
|
-
|
|
11
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
-
in the Software without restriction, including without limitation the rights
|
|
14
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
-
furnished to do so, subject to the following conditions:
|
|
17
|
-
|
|
18
|
-
The above copyright notice and this permission notice shall be included in all
|
|
19
|
-
copies or substantial portions of the Software.
|
|
20
|
-
|
|
21
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
-
SOFTWARE.
|
|
7
|
+
License-Expression: MIT
|
|
28
8
|
Project-URL: Quantum Design, https://qdusa.com
|
|
29
9
|
Project-URL: Pharos, https://www.qdusa.com/register/account/login
|
|
30
10
|
Keywords: Quantum Design,QD,MultiVu,PPMS,DynaCool,MPMS3,VersaLab,OptiCool
|
|
31
11
|
Classifier: Programming Language :: Python :: 3
|
|
32
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
33
12
|
Classifier: Operating System :: OS Independent
|
|
34
13
|
Classifier: Intended Audience :: Science/Research
|
|
35
14
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
36
15
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
37
16
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
38
|
-
Requires-Python: >=3.
|
|
17
|
+
Requires-Python: >=3.7
|
|
39
18
|
Description-Content-Type: text/markdown
|
|
40
19
|
License-File: LICENSE
|
|
41
20
|
Requires-Dist: pandas
|
|
@@ -43,9 +22,7 @@ Requires-Dist: pywin32>=300; platform_system == "Windows"
|
|
|
43
22
|
Requires-Dist: pillow
|
|
44
23
|
Requires-Dist: pyyaml
|
|
45
24
|
Dynamic: license-file
|
|
46
|
-
Dynamic: requires-dist
|
|
47
25
|
Dynamic: requires-python
|
|
48
|
-
Dynamic: summary
|
|
49
26
|
|
|
50
27
|

|
|
51
28
|
# MultiPyVu
|
|
@@ -82,13 +59,13 @@ The components of MultiPyVu enable access to the set and read the temperature, f
|
|
|
82
59
|
|
|
83
60
|
### Module Requirements<a class="anchor" id="requirements"></a>
|
|
84
61
|
MultiPyVu uses the following modules:
|
|
85
|
-
- python version 3.
|
|
62
|
+
- python version 3.7 or higher
|
|
86
63
|
- pywin32 - version 300 or higher.
|
|
87
64
|
- pandas - data read back from a *.dat* file is a Pandas Dataframe
|
|
88
65
|
- pillow - supports server gui
|
|
89
66
|
- pyyaml - supports logging
|
|
90
67
|
|
|
91
|
-
|
|
68
|
+
To find which version of Python is used on the local computer, from a command prompt type:
|
|
92
69
|
```
|
|
93
70
|
python --version
|
|
94
71
|
```
|
|
@@ -109,13 +86,13 @@ Remote Connection\example_MVDataFile_VISA.py | Simple example showing how to rou
|
|
|
109
86
|
Data Processing\example_save_open_dat.py | Script showing how to save and read a MultiVu *.dat* file into a Pandas DataFrame, then plot with matplotlib.
|
|
110
87
|
Measuring\example_stabilize.py | Measures the temperature while stabilizing at each temperature.
|
|
111
88
|
Measuring\example_sweep.py | Measures the temperature while sweeping the temperature.
|
|
112
|
-
|
|
89
|
+
Measuring\example_get_setpoints.py | Shows how to get the temperature and magnetic field setpoints.
|
|
90
|
+
Options\example_aux_therm.py | Gets the temperature of the auxiliary thermometer from the OptiCool.
|
|
113
91
|
Options\example_resistivity_option.py | Demonstrates how to set up the BRT module bridges for resistivity measurements and how to save the data.
|
|
114
92
|
Options\example_horizontal_rotator.py | Demonstrates how to move the horizontal rotator to a new position.
|
|
115
|
-
UsefulBatchFiles\
|
|
116
|
-
UsefulBatchFiles\show_process_with_port.cmd | Shows that active processes are running and what port is being used. By default, this looks for processes running on port 5000. To query a different port number, append it to the command line arguments. ```$ show_processes_with_port.cmd 4567```
|
|
93
|
+
UsefulBatchFiles\show_processes_with_port.cmd | Shows that active processes are running and what port is being used. By default, this looks for processes running on port 27183. To query a different port number, append it to the command line arguments. ```$ show_processes_with_port.cmd 45678```
|
|
117
94
|
UsefulBatchFiles\RunServer.cmd | This runs the server GUI.
|
|
118
|
-
UsefulBatchFiles\kill_process.cmd | This ends the processes with the specified PID (which can be identified using
|
|
95
|
+
UsefulBatchFiles\kill_process.cmd | This ends the processes with the specified PID (which can be identified using show_processes_with_port.cmd). Run using ```$ kill_process.cmd 13579```
|
|
119
96
|
|
|
120
97
|
### Getting Started<a class="anchor" id="getting-started"></a>
|
|
121
98
|
Once the MultiPyVu module has been installed, be sure that the MultiVu executable is running on the PC connected to the cryostat before starting the server. For testing purposes, you can use MultiVu in simulation mode on an office computer, or run mpv.Server with the -s flag which runs the python code in scaffolding that mimics MultiVu. This is especially helpful for developing a script on a computer that does not have MultiVu running (Mac, Linux, or any PC without MultiVu). When running MultiVu and MultiPyVu, be sure that they are running under the same permissions.
|
|
@@ -181,7 +158,7 @@ with mpv.Client('127.0.0.1') as client:
|
|
|
181
158
|
# do post-processing once the client has been closed
|
|
182
159
|
```
|
|
183
160
|
|
|
184
|
-
If the host or port are not default values (localhost and
|
|
161
|
+
If the host or port are not default values (localhost and 27183, respectively), then these parameters must be specified when instantiating MultiPyVu.Client().
|
|
185
162
|
|
|
186
163
|
Alternatively, one can start a connection to the server using:
|
|
187
164
|
```python
|
|
@@ -191,7 +168,7 @@ client.open()
|
|
|
191
168
|
client.close_client()
|
|
192
169
|
# do post-processing once the client has been closed
|
|
193
170
|
```
|
|
194
|
-
Using the above method could end up with the server hung up because errors need to be correctly accounted for. It is safer to use the Client as a context manager using a with-block.
|
|
171
|
+
Using the above method could end up with the server hung up because errors need to be correctly accounted for. It is safer to use the Client as a context manager using a with-block. In addition, a client object can only connect to the server once. For a second connection, one must instantiate a new client instance.
|
|
195
172
|
|
|
196
173
|
The client can also close the server directly using:
|
|
197
174
|
```python
|
|
@@ -239,6 +216,10 @@ The <enum_options> mode is set using the client.temperature.approach_mode enum,
|
|
|
239
216
|
```python
|
|
240
217
|
temperature, status = client.get_temperature()
|
|
241
218
|
```
|
|
219
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
220
|
+
```python
|
|
221
|
+
temperature, rate, approach = client.get_temperature_setpoints()
|
|
222
|
+
```
|
|
242
223
|
|
|
243
224
|
**Field**<a class="anchor" id="field"></a>
|
|
244
225
|
```python
|
|
@@ -260,6 +241,10 @@ The field and status are read back using:
|
|
|
260
241
|
```python
|
|
261
242
|
field, status = client.get_field()
|
|
262
243
|
```
|
|
244
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
245
|
+
```python
|
|
246
|
+
field, rate, approach, driven = client.get_field_setpoints()
|
|
247
|
+
```
|
|
263
248
|
|
|
264
249
|
**Chamber**<a class="anchor" id="chamber"></a>
|
|
265
250
|
```python
|
|
@@ -325,7 +310,7 @@ For DynaCool, VersaLab, and PPMS customers with the horizontal rotator option, M
|
|
|
325
310
|
Once configured, the following commands are simple to use:
|
|
326
311
|
```python
|
|
327
312
|
position = 374.5
|
|
328
|
-
rate_deg_per_sec =
|
|
313
|
+
rate_deg_per_sec = 30.0
|
|
329
314
|
client.set_position(position, rate_deg_per_sec)
|
|
330
315
|
pos, status = client.get_position()
|
|
331
316
|
```
|
|
@@ -400,7 +385,7 @@ The server status can be queried from the command line. First, we can see if th
|
|
|
400
385
|
```cmd
|
|
401
386
|
$ python -m MultiPyVu -running
|
|
402
387
|
```
|
|
403
|
-
By default, this queries the server at IP address = localhost and port =
|
|
388
|
+
By default, this queries the server at IP address = localhost and port = 27183. To query a different address, use the *-ip=* or *-p=* flags.
|
|
404
389
|
|
|
405
390
|
Similarly, in order to get the server status at a specific ip address, use:
|
|
406
391
|
```cmd
|
|
@@ -439,8 +424,8 @@ with mpv.Server(flags=['-s', 'DYNACOOL']) as server:
|
|
|
439
424
|
|
|
440
425
|
### Troubleshooting<a class="anchor" id="troubleshooting"></a>
|
|
441
426
|
Typical connection issues are due to:
|
|
442
|
-
- Firewall. You might need to allow connections on port
|
|
443
|
-
- Port conflict. If port
|
|
427
|
+
- Firewall. You might need to allow connections on port 27183 (the default port number) in your firewall. Windows Firewall may cause issues depending upon your network settings. If the server is open and a connection fails disabling Firewalls temporarily may be your best option to troubleshoot. If your computers are on the same domain disabling the Domain Firewall may be sufficient.
|
|
428
|
+
- Port conflict. If port 27183 is in use, a different number can be specified when instantiating MultiPyVu.Server() and MultiPyVu.Client().
|
|
444
429
|
```python
|
|
445
430
|
server = mpv.Server(port=6000)
|
|
446
431
|
client = mpv.Client(port=6000)
|
|
@@ -449,6 +434,22 @@ client = mpv.Client(port=6000)
|
|
|
449
434
|
- A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
|
|
450
435
|
|
|
451
436
|
## Changelog<a class="anchor" id="changelog"></a>
|
|
437
|
+
**3.8.0**
|
|
438
|
+
- September 2026
|
|
439
|
+
- Add support for the OptiCool Vector magnet
|
|
440
|
+
- Improvements to the GUI for a better look on MacOS.
|
|
441
|
+
- Improvements to wait_for() command.
|
|
442
|
+
|
|
443
|
+
**3.7.0**
|
|
444
|
+
- September 2025
|
|
445
|
+
- Point MultiPyVuDataFile to version 00.05.00, which ignores blank lines when importing .dat files into a Pandas Dataframe.
|
|
446
|
+
|
|
447
|
+
**3.6.1**
|
|
448
|
+
- August 2025
|
|
449
|
+
- Add commands to get the temperature and field setpoints.
|
|
450
|
+
- Remove dependencies on the distutils module.
|
|
451
|
+
- Minimum python version 3.7
|
|
452
|
+
|
|
452
453
|
**3.5.4**
|
|
453
454
|
- June 2025
|
|
454
455
|
- Add the horizontal rotator option for DynaCool, VersaLab, and PPMS.
|
|
@@ -33,13 +33,13 @@ The components of MultiPyVu enable access to the set and read the temperature, f
|
|
|
33
33
|
|
|
34
34
|
### Module Requirements<a class="anchor" id="requirements"></a>
|
|
35
35
|
MultiPyVu uses the following modules:
|
|
36
|
-
- python version 3.
|
|
36
|
+
- python version 3.7 or higher
|
|
37
37
|
- pywin32 - version 300 or higher.
|
|
38
38
|
- pandas - data read back from a *.dat* file is a Pandas Dataframe
|
|
39
39
|
- pillow - supports server gui
|
|
40
40
|
- pyyaml - supports logging
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
To find which version of Python is used on the local computer, from a command prompt type:
|
|
43
43
|
```
|
|
44
44
|
python --version
|
|
45
45
|
```
|
|
@@ -60,13 +60,13 @@ Remote Connection\example_MVDataFile_VISA.py | Simple example showing how to rou
|
|
|
60
60
|
Data Processing\example_save_open_dat.py | Script showing how to save and read a MultiVu *.dat* file into a Pandas DataFrame, then plot with matplotlib.
|
|
61
61
|
Measuring\example_stabilize.py | Measures the temperature while stabilizing at each temperature.
|
|
62
62
|
Measuring\example_sweep.py | Measures the temperature while sweeping the temperature.
|
|
63
|
-
|
|
63
|
+
Measuring\example_get_setpoints.py | Shows how to get the temperature and magnetic field setpoints.
|
|
64
|
+
Options\example_aux_therm.py | Gets the temperature of the auxiliary thermometer from the OptiCool.
|
|
64
65
|
Options\example_resistivity_option.py | Demonstrates how to set up the BRT module bridges for resistivity measurements and how to save the data.
|
|
65
66
|
Options\example_horizontal_rotator.py | Demonstrates how to move the horizontal rotator to a new position.
|
|
66
|
-
UsefulBatchFiles\
|
|
67
|
-
UsefulBatchFiles\show_process_with_port.cmd | Shows that active processes are running and what port is being used. By default, this looks for processes running on port 5000. To query a different port number, append it to the command line arguments. ```$ show_processes_with_port.cmd 4567```
|
|
67
|
+
UsefulBatchFiles\show_processes_with_port.cmd | Shows that active processes are running and what port is being used. By default, this looks for processes running on port 27183. To query a different port number, append it to the command line arguments. ```$ show_processes_with_port.cmd 45678```
|
|
68
68
|
UsefulBatchFiles\RunServer.cmd | This runs the server GUI.
|
|
69
|
-
UsefulBatchFiles\kill_process.cmd | This ends the processes with the specified PID (which can be identified using
|
|
69
|
+
UsefulBatchFiles\kill_process.cmd | This ends the processes with the specified PID (which can be identified using show_processes_with_port.cmd). Run using ```$ kill_process.cmd 13579```
|
|
70
70
|
|
|
71
71
|
### Getting Started<a class="anchor" id="getting-started"></a>
|
|
72
72
|
Once the MultiPyVu module has been installed, be sure that the MultiVu executable is running on the PC connected to the cryostat before starting the server. For testing purposes, you can use MultiVu in simulation mode on an office computer, or run mpv.Server with the -s flag which runs the python code in scaffolding that mimics MultiVu. This is especially helpful for developing a script on a computer that does not have MultiVu running (Mac, Linux, or any PC without MultiVu). When running MultiVu and MultiPyVu, be sure that they are running under the same permissions.
|
|
@@ -132,7 +132,7 @@ with mpv.Client('127.0.0.1') as client:
|
|
|
132
132
|
# do post-processing once the client has been closed
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
If the host or port are not default values (localhost and
|
|
135
|
+
If the host or port are not default values (localhost and 27183, respectively), then these parameters must be specified when instantiating MultiPyVu.Client().
|
|
136
136
|
|
|
137
137
|
Alternatively, one can start a connection to the server using:
|
|
138
138
|
```python
|
|
@@ -142,7 +142,7 @@ client.open()
|
|
|
142
142
|
client.close_client()
|
|
143
143
|
# do post-processing once the client has been closed
|
|
144
144
|
```
|
|
145
|
-
Using the above method could end up with the server hung up because errors need to be correctly accounted for. It is safer to use the Client as a context manager using a with-block.
|
|
145
|
+
Using the above method could end up with the server hung up because errors need to be correctly accounted for. It is safer to use the Client as a context manager using a with-block. In addition, a client object can only connect to the server once. For a second connection, one must instantiate a new client instance.
|
|
146
146
|
|
|
147
147
|
The client can also close the server directly using:
|
|
148
148
|
```python
|
|
@@ -190,6 +190,10 @@ The <enum_options> mode is set using the client.temperature.approach_mode enum,
|
|
|
190
190
|
```python
|
|
191
191
|
temperature, status = client.get_temperature()
|
|
192
192
|
```
|
|
193
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
194
|
+
```python
|
|
195
|
+
temperature, rate, approach = client.get_temperature_setpoints()
|
|
196
|
+
```
|
|
193
197
|
|
|
194
198
|
**Field**<a class="anchor" id="field"></a>
|
|
195
199
|
```python
|
|
@@ -211,6 +215,10 @@ The field and status are read back using:
|
|
|
211
215
|
```python
|
|
212
216
|
field, status = client.get_field()
|
|
213
217
|
```
|
|
218
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
219
|
+
```python
|
|
220
|
+
field, rate, approach, driven = client.get_field_setpoints()
|
|
221
|
+
```
|
|
214
222
|
|
|
215
223
|
**Chamber**<a class="anchor" id="chamber"></a>
|
|
216
224
|
```python
|
|
@@ -276,7 +284,7 @@ For DynaCool, VersaLab, and PPMS customers with the horizontal rotator option, M
|
|
|
276
284
|
Once configured, the following commands are simple to use:
|
|
277
285
|
```python
|
|
278
286
|
position = 374.5
|
|
279
|
-
rate_deg_per_sec =
|
|
287
|
+
rate_deg_per_sec = 30.0
|
|
280
288
|
client.set_position(position, rate_deg_per_sec)
|
|
281
289
|
pos, status = client.get_position()
|
|
282
290
|
```
|
|
@@ -351,7 +359,7 @@ The server status can be queried from the command line. First, we can see if th
|
|
|
351
359
|
```cmd
|
|
352
360
|
$ python -m MultiPyVu -running
|
|
353
361
|
```
|
|
354
|
-
By default, this queries the server at IP address = localhost and port =
|
|
362
|
+
By default, this queries the server at IP address = localhost and port = 27183. To query a different address, use the *-ip=* or *-p=* flags.
|
|
355
363
|
|
|
356
364
|
Similarly, in order to get the server status at a specific ip address, use:
|
|
357
365
|
```cmd
|
|
@@ -390,8 +398,8 @@ with mpv.Server(flags=['-s', 'DYNACOOL']) as server:
|
|
|
390
398
|
|
|
391
399
|
### Troubleshooting<a class="anchor" id="troubleshooting"></a>
|
|
392
400
|
Typical connection issues are due to:
|
|
393
|
-
- Firewall. You might need to allow connections on port
|
|
394
|
-
- Port conflict. If port
|
|
401
|
+
- Firewall. You might need to allow connections on port 27183 (the default port number) in your firewall. Windows Firewall may cause issues depending upon your network settings. If the server is open and a connection fails disabling Firewalls temporarily may be your best option to troubleshoot. If your computers are on the same domain disabling the Domain Firewall may be sufficient.
|
|
402
|
+
- Port conflict. If port 27183 is in use, a different number can be specified when instantiating MultiPyVu.Server() and MultiPyVu.Client().
|
|
395
403
|
```python
|
|
396
404
|
server = mpv.Server(port=6000)
|
|
397
405
|
client = mpv.Client(port=6000)
|
|
@@ -400,6 +408,22 @@ client = mpv.Client(port=6000)
|
|
|
400
408
|
- A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
|
|
401
409
|
|
|
402
410
|
## Changelog<a class="anchor" id="changelog"></a>
|
|
411
|
+
**3.8.0**
|
|
412
|
+
- September 2026
|
|
413
|
+
- Add support for the OptiCool Vector magnet
|
|
414
|
+
- Improvements to the GUI for a better look on MacOS.
|
|
415
|
+
- Improvements to wait_for() command.
|
|
416
|
+
|
|
417
|
+
**3.7.0**
|
|
418
|
+
- September 2025
|
|
419
|
+
- Point MultiPyVuDataFile to version 00.05.00, which ignores blank lines when importing .dat files into a Pandas Dataframe.
|
|
420
|
+
|
|
421
|
+
**3.6.1**
|
|
422
|
+
- August 2025
|
|
423
|
+
- Add commands to get the temperature and field setpoints.
|
|
424
|
+
- Remove dependencies on the distutils module.
|
|
425
|
+
- Minimum python version 3.7
|
|
426
|
+
|
|
403
427
|
**3.5.4**
|
|
404
428
|
- June 2025
|
|
405
429
|
- Add the horizontal rotator option for DynaCool, VersaLab, and PPMS.
|
|
@@ -6,19 +6,23 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
name = "MultiPyVu"
|
|
7
7
|
dynamic = [
|
|
8
8
|
"version",
|
|
9
|
-
"description",
|
|
10
9
|
"requires-python",
|
|
11
|
-
"dependencies",
|
|
12
10
|
]
|
|
13
11
|
authors = [{name = "Damon D Jackson", email = "djackson@qdusa.com"}]
|
|
14
12
|
maintainers = [
|
|
15
13
|
{ name = "Quantum Design, Inc.", email = "apps@qdusa.com" },
|
|
16
14
|
]
|
|
17
15
|
readme = "README.md"
|
|
18
|
-
|
|
16
|
+
description = "Control MultiVu using Python"
|
|
17
|
+
dependencies = [
|
|
18
|
+
"pandas",
|
|
19
|
+
"pywin32>=300; platform_system=='Windows'",
|
|
20
|
+
"pillow",
|
|
21
|
+
"pyyaml",
|
|
22
|
+
]
|
|
23
|
+
license = "MIT"
|
|
19
24
|
classifiers = [
|
|
20
25
|
"Programming Language :: Python :: 3",
|
|
21
|
-
"License :: OSI Approved :: MIT License",
|
|
22
26
|
"Operating System :: OS Independent",
|
|
23
27
|
"Intended Audience :: Science/Research",
|
|
24
28
|
"Topic :: Scientific/Engineering :: Physics",
|
|
@@ -39,3 +43,6 @@ keywords = [
|
|
|
39
43
|
[project.urls]
|
|
40
44
|
"Quantum Design" = "https://qdusa.com"
|
|
41
45
|
"Pharos" = "https://www.qdusa.com/register/account/login"
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.dynamic]
|
|
48
|
+
version = {attr = "MultiPyVu.__version.__version__"}
|
multipyvu-3.8.0/setup.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""A setuptools based setup module.
|
|
2
|
+
|
|
3
|
+
See:
|
|
4
|
+
https://packaging.python.org/guides/distributing-packages-using-setuptools/
|
|
5
|
+
https://github.com/pypa/sampleproject
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# Always prefer setuptools over distutils
|
|
9
|
+
from setuptools import find_packages, setup
|
|
10
|
+
|
|
11
|
+
# name, version, description, license, dependencies, and readme are
|
|
12
|
+
# configured in pyproject.toml. Only the settings without a pyproject.toml
|
|
13
|
+
# equivalent (package discovery/layout and non-Python package data) live here.
|
|
14
|
+
setup(
|
|
15
|
+
package_dir={"": "src"},
|
|
16
|
+
packages=find_packages(where="src"),
|
|
17
|
+
package_data={"MultiPyVu": [
|
|
18
|
+
"images/*.jpg",
|
|
19
|
+
"images/*.png",
|
|
20
|
+
"font/*.ttf",
|
|
21
|
+
"scripts/*",
|
|
22
|
+
"MultiVuDataFile/*.py",
|
|
23
|
+
"logging_config.yaml"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
python_requires=">=3.7",
|
|
27
|
+
)
|
|
@@ -13,7 +13,7 @@ from typing import Dict, List, Tuple, Union
|
|
|
13
13
|
|
|
14
14
|
from .exceptions import MultiPyVuError
|
|
15
15
|
from .ICommand import (ICommand, ICommandImp, ICommandObserverSim,
|
|
16
|
-
ISimulateChange
|
|
16
|
+
ISimulateChange)
|
|
17
17
|
from .IEventManager import IObserver
|
|
18
18
|
|
|
19
19
|
|
|
@@ -90,7 +90,7 @@ class CommandChamberBase(ICommand):
|
|
|
90
90
|
|
|
91
91
|
def convert_result(self, response: Dict[str, str]) -> Tuple:
|
|
92
92
|
"""
|
|
93
|
-
Converts the CommandMultiVu response from
|
|
93
|
+
Converts the CommandMultiVu response from get_state_server()
|
|
94
94
|
to something usable for the user.
|
|
95
95
|
|
|
96
96
|
Parameters:
|
|
@@ -131,7 +131,7 @@ class CommandChamberBase(ICommand):
|
|
|
131
131
|
raise NotImplementedError
|
|
132
132
|
|
|
133
133
|
@abstractmethod
|
|
134
|
-
def _set_state_imp(self, mode:
|
|
134
|
+
def _set_state_imp(self, mode: modeEnum) -> Union[str, int]:
|
|
135
135
|
raise NotImplementedError
|
|
136
136
|
|
|
137
137
|
def set_state_server(self, arg_string) -> Union[str, int]:
|
|
@@ -148,8 +148,8 @@ class CommandChamberBase(ICommand):
|
|
|
148
148
|
for m in modeEnum:
|
|
149
149
|
err_msg += f'\n\t{m.value}: {m.name}'
|
|
150
150
|
raise MultiPyVuError(err_msg)
|
|
151
|
-
self.state = set_mode
|
|
152
|
-
return self._set_state_imp(
|
|
151
|
+
self.state = modeEnum(set_mode)
|
|
152
|
+
return self._set_state_imp(self.state)
|
|
153
153
|
|
|
154
154
|
def state_code_dict(self):
|
|
155
155
|
return STATE_DICT
|
|
@@ -195,7 +195,7 @@ class CommandChamberImp(ICommandImp, CommandChamberBase):
|
|
|
195
195
|
if self.instrument_name == 'OPTICOOL':
|
|
196
196
|
err_msg = 'get_chamber() is not available for the OptiCool'
|
|
197
197
|
raise MultiPyVuError(err_msg)
|
|
198
|
-
|
|
198
|
+
can_error = self._mvu.GetChamber(state_variant)
|
|
199
199
|
# On 6/10/25, I found that the PPMS was returning something greater
|
|
200
200
|
# than 1 with the GetTemperature() command. After talking with Mark,
|
|
201
201
|
# I have decided to only check for a value greater than 1 for all
|
|
@@ -206,7 +206,7 @@ class CommandChamberImp(ICommandImp, CommandChamberBase):
|
|
|
206
206
|
|
|
207
207
|
return 0.0, self.state
|
|
208
208
|
|
|
209
|
-
def _set_state_imp(self, mode:
|
|
209
|
+
def _set_state_imp(self, mode: modeEnum) -> Union[str, int]:
|
|
210
210
|
can_error = self._mvu.SetChamber(mode)
|
|
211
211
|
self.set_point = mode
|
|
212
212
|
|
|
@@ -216,7 +216,7 @@ class CommandChamberImp(ICommandImp, CommandChamberBase):
|
|
|
216
216
|
else:
|
|
217
217
|
# returning this string makes CommandMultiVu_base happy
|
|
218
218
|
return 'Call was successful'
|
|
219
|
-
elif can_error >
|
|
219
|
+
elif can_error > 1:
|
|
220
220
|
raise MultiPyVuError('Error when calling SetChamber()')
|
|
221
221
|
return can_error
|
|
222
222
|
|
|
@@ -266,15 +266,22 @@ class CommandChamberImp(ICommandImp, CommandChamberBase):
|
|
|
266
266
|
#
|
|
267
267
|
############################
|
|
268
268
|
|
|
269
|
-
@catch_thread_error
|
|
270
269
|
class SimulateChamberChange(ISimulateChange):
|
|
271
|
-
# class variables
|
|
270
|
+
# These are class variables, not instance variables, so that the
|
|
271
|
+
# simulated instrument keeps its condition from one change
|
|
272
|
+
# thread to the next. See ISimulateChange for the reasoning.
|
|
272
273
|
_stop_flag: bool = False
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
274
|
+
_state_dict = STATE_DICT
|
|
275
|
+
# The starting values come from the Command*Base class so that
|
|
276
|
+
# the scaffolding and the real implementation begin in the
|
|
277
|
+
# same place.
|
|
278
|
+
_current_val: float = CommandChamberBase._current_val
|
|
279
|
+
_state: int = CommandChamberBase._state
|
|
280
|
+
_set_point: float = CommandChamberBase._set_point
|
|
281
|
+
# The chamber has no rate, and the flavor is set by
|
|
282
|
+
# CommandChamberSim._set_state_imp() before the thread runs.
|
|
283
|
+
_rate: float = 0.0
|
|
284
|
+
_flavor: str = ''
|
|
278
285
|
_observers: List[IObserver] = []
|
|
279
286
|
|
|
280
287
|
def __init__(self):
|
|
@@ -282,11 +289,11 @@ class SimulateChamberChange(ISimulateChange):
|
|
|
282
289
|
|
|
283
290
|
@property
|
|
284
291
|
def current_val(self):
|
|
285
|
-
return SimulateChamberChange.
|
|
292
|
+
return SimulateChamberChange._current_val
|
|
286
293
|
|
|
287
294
|
@current_val.setter
|
|
288
295
|
def current_val(self, new):
|
|
289
|
-
SimulateChamberChange.
|
|
296
|
+
SimulateChamberChange._current_val = new
|
|
290
297
|
|
|
291
298
|
@property
|
|
292
299
|
def set_point(self):
|
|
@@ -323,20 +330,20 @@ class SimulateChamberChange(ISimulateChange):
|
|
|
323
330
|
if self.stop_requested():
|
|
324
331
|
return
|
|
325
332
|
if self.set_point == modeEnum.seal.value:
|
|
326
|
-
self.state =
|
|
333
|
+
self.state = 1
|
|
327
334
|
elif self.set_point == modeEnum.purge_seal.value:
|
|
328
|
-
self.state =
|
|
335
|
+
self.state = 1
|
|
329
336
|
elif self.set_point == modeEnum.vent_seal.value:
|
|
330
|
-
self.state =
|
|
337
|
+
self.state = 2
|
|
331
338
|
elif self.set_point == modeEnum.high_vacuum.value:
|
|
332
|
-
self.state =
|
|
339
|
+
self.state = 7
|
|
333
340
|
elif self.set_point == modeEnum.pump_continuous.value:
|
|
334
|
-
self.state =
|
|
341
|
+
self.state = 8
|
|
335
342
|
elif self.set_point == modeEnum.vent_continuous.value:
|
|
336
343
|
if self.flavor == 'PPMS':
|
|
337
|
-
self.state =
|
|
344
|
+
self.state = 5
|
|
338
345
|
else:
|
|
339
|
-
self.state =
|
|
346
|
+
self.state = 9
|
|
340
347
|
else:
|
|
341
348
|
msg = f'{self.set_point} is an invalid mode'
|
|
342
349
|
raise ValueError(msg)
|
|
@@ -401,13 +408,12 @@ class CommandChamberSim(CommandChamberBase,
|
|
|
401
408
|
raise MultiPyVuError(err_msg)
|
|
402
409
|
return 0.0, self.state
|
|
403
410
|
|
|
404
|
-
def _set_state_imp(self, mode:
|
|
405
|
-
self.change_thread = self.get_sim_instance()
|
|
406
|
-
state_string = STATE_DICT[self.state]
|
|
411
|
+
def _set_state_imp(self, mode: modeEnum) -> Union[str, int]:
|
|
412
|
+
self.change_thread: SimulateChamberChange = self.get_sim_instance()
|
|
407
413
|
self.change_thread.set_params('',
|
|
408
414
|
mode,
|
|
409
415
|
0.0,
|
|
410
|
-
|
|
416
|
+
self.state,
|
|
411
417
|
)
|
|
412
418
|
self.change_thread.flavor = self.instrument_name
|
|
413
419
|
self.change_thread.subscribe(self)
|
|
@@ -422,7 +428,4 @@ class CommandChamberSim(CommandChamberBase,
|
|
|
422
428
|
return error
|
|
423
429
|
|
|
424
430
|
def update(self, value, state):
|
|
425
|
-
|
|
426
|
-
if state_str == state:
|
|
427
|
-
self.state = state_number
|
|
428
|
-
break
|
|
431
|
+
self.state = state
|