MultiPyVu 3.6.1__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.
Files changed (70) hide show
  1. {multipyvu-3.6.1 → multipyvu-3.8.0}/LICENSE +20 -20
  2. {multipyvu-3.6.1/src/MultiPyVu.egg-info → multipyvu-3.8.0}/PKG-INFO +19 -12
  3. {multipyvu-3.6.1 → multipyvu-3.8.0}/README.md +18 -9
  4. {multipyvu-3.6.1 → multipyvu-3.8.0}/pyproject.toml +10 -2
  5. multipyvu-3.8.0/setup.py +27 -0
  6. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/CommandChamber.py +26 -23
  7. multipyvu-3.6.1/src/MultiPyVu/Command_factory.py → multipyvu-3.8.0/src/MultiPyVu/CommandFactory.py +50 -9
  8. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/CommandField.py +130 -59
  9. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/CommandFieldSetPoints.py +139 -29
  10. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/CommandMultiVu.py +27 -0
  11. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/CommandRotator.py +28 -21
  12. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/CommandSdo.py +15 -2
  13. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/CommandTempSetPoints.py +17 -8
  14. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/CommandTemperature.py +116 -47
  15. multipyvu-3.8.0/src/MultiPyVu/CommandVectorMagnet.py +780 -0
  16. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/CommandWaitFor.py +346 -68
  17. multipyvu-3.8.0/src/MultiPyVu/ICommand.py +522 -0
  18. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/IEventManager.py +42 -42
  19. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/IServer.py +68 -68
  20. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuClient.py +849 -559
  21. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuClient_base.py +562 -532
  22. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuDataFile/MultiVuDataFile.py +4 -0
  23. multipyvu-3.8.0/src/MultiPyVu/MultiVuDataFile/__version.py +2 -0
  24. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuDataFile/is_pathname_valid.py +3 -3
  25. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuServer.py +405 -388
  26. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/ParseInputs.py +14 -14
  27. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/SocketMessage.py +16 -1
  28. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/SocketMessageClient.py +526 -510
  29. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/SocketMessageServer.py +912 -867
  30. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/__init__.py +1 -1
  31. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/__main__.py +3 -4
  32. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/__version.py +1 -1
  33. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/exceptions.py +0 -2
  34. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/generate_sdo_objects.py +6 -2
  35. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/gui/Controller.py +208 -246
  36. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/gui/IController.py +132 -132
  37. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/gui/IView.py +97 -83
  38. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/gui/ViewFactory.py +26 -26
  39. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/gui/ViewTk.py +687 -532
  40. multipyvu-3.8.0/src/MultiPyVu/gui/font_loader.py +204 -0
  41. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/instrument.py +62 -6
  42. multipyvu-3.8.0/src/MultiPyVu/logging_config.py +111 -0
  43. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/project_vars.py +11 -2
  44. multipyvu-3.8.0/src/MultiPyVu/scripts/helper_scripts.py +28 -0
  45. multipyvu-3.8.0/src/MultiPyVu/scripts/helper_scripts_client.py +54 -0
  46. {multipyvu-3.6.1 → multipyvu-3.8.0/src/MultiPyVu.egg-info}/PKG-INFO +19 -12
  47. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu.egg-info/SOURCES.txt +4 -2
  48. multipyvu-3.6.1/setup.py +0 -61
  49. multipyvu-3.6.1/src/MultiPyVu/ICommand.py +0 -324
  50. multipyvu-3.6.1/src/MultiPyVu/MultiVuDataFile/__version.py +0 -2
  51. multipyvu-3.6.1/src/MultiPyVu/logging_config.py +0 -76
  52. multipyvu-3.6.1/src/MultiPyVu/scripts/helper_scripts.py +0 -118
  53. multipyvu-3.6.1/src/MultiPyVu/scripts/whats_my_ip_address.cmd +0 -21
  54. {multipyvu-3.6.1 → multipyvu-3.8.0}/setup.cfg +0 -0
  55. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/BRT.py +0 -0
  56. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/MultiVuDataFile/__init__.py +0 -0
  57. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/check_windows_esc.py +0 -0
  58. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/font/Play-Bold.ttf +0 -0
  59. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/font/Play-Regular.ttf +0 -0
  60. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/font/__init__.py +0 -0
  61. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/gui/__init__.py +0 -0
  62. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/images/Q.png +0 -0
  63. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/images/QD_logo.jpg +0 -0
  64. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/images/__init__.py +0 -0
  65. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/logging_config.yaml +0 -0
  66. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/scripts/__init__.py +0 -0
  67. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu/sdo_object.py +0 -0
  68. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu.egg-info/dependency_links.txt +0 -0
  69. {multipyvu-3.6.1 → multipyvu-3.8.0}/src/MultiPyVu.egg-info/requires.txt +0 -0
  70. {multipyvu-3.6.1 → 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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MultiPyVu
3
- Version: 3.6.1
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>
@@ -22,9 +22,7 @@ Requires-Dist: pywin32>=300; platform_system == "Windows"
22
22
  Requires-Dist: pillow
23
23
  Requires-Dist: pyyaml
24
24
  Dynamic: license-file
25
- Dynamic: requires-dist
26
25
  Dynamic: requires-python
27
- Dynamic: summary
28
26
 
29
27
  ![qd_logo](https://qdusa.com/images/QD_logo.png)
30
28
  # MultiPyVu
@@ -67,7 +65,7 @@ MultiPyVu uses the following modules:
67
65
  - pillow - supports server gui
68
66
  - pyyaml - supports logging
69
67
 
70
- For the Python 3 distribution Quantum Design recommends [Anaconda](https://www.anaconda.com/products/individual) as it includes most modules needed for this server and other packages useful for scientific computing. To find which version of Python is used, from a command prompt type:
68
+ To find which version of Python is used on the local computer, from a command prompt type:
71
69
  ```
72
70
  python --version
73
71
  ```
@@ -92,10 +90,9 @@ Measuring\example_get_setpoints.py | Shows how to get the temperature and magnet
92
90
  Options\example_aux_therm.py | Gets the temperature of the auxiliary thermometer from the OptiCool.
93
91
  Options\example_resistivity_option.py | Demonstrates how to set up the BRT module bridges for resistivity measurements and how to save the data.
94
92
  Options\example_horizontal_rotator.py | Demonstrates how to move the horizontal rotator to a new position.
95
- UsefulBatchFiles\whats_my_ip_address.cmd | This batch file script prints out the IP address for the computer, providing an easy way to get the server IP address needed for remote operation. Alternatively, the gui can be used to get the IP address by calling ```python -m MultiPyVu```.
96
- 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```
97
94
  UsefulBatchFiles\RunServer.cmd | This runs the server GUI.
98
- UsefulBatchFiles\kill_process.cmd | This ends the processes with the specified PID (which can be identified using show_process_with_port.cmd). Run using ```$ kill_process.cmd 13579```
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```
99
96
 
100
97
  ### Getting Started<a class="anchor" id="getting-started"></a>
101
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.
@@ -161,7 +158,7 @@ with mpv.Client('127.0.0.1') as client:
161
158
  # do post-processing once the client has been closed
162
159
  ```
163
160
 
164
- If the host or port are not default values (localhost and 5000, respectively), then these parameters must be specified when instantiating MultiPyVu.Client().
161
+ If the host or port are not default values (localhost and 27183, respectively), then these parameters must be specified when instantiating MultiPyVu.Client().
165
162
 
166
163
  Alternatively, one can start a connection to the server using:
167
164
  ```python
@@ -313,7 +310,7 @@ For DynaCool, VersaLab, and PPMS customers with the horizontal rotator option, M
313
310
  Once configured, the following commands are simple to use:
314
311
  ```python
315
312
  position = 374.5
316
- rate_deg_per_sec = 100.0
313
+ rate_deg_per_sec = 30.0
317
314
  client.set_position(position, rate_deg_per_sec)
318
315
  pos, status = client.get_position()
319
316
  ```
@@ -388,7 +385,7 @@ The server status can be queried from the command line. First, we can see if th
388
385
  ```cmd
389
386
  $ python -m MultiPyVu -running
390
387
  ```
391
- By default, this queries the server at IP address = localhost and port = 5000. To query a different address, use the *-ip=* or *-p=* flags.
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.
392
389
 
393
390
  Similarly, in order to get the server status at a specific ip address, use:
394
391
  ```cmd
@@ -427,8 +424,8 @@ with mpv.Server(flags=['-s', 'DYNACOOL']) as server:
427
424
 
428
425
  ### Troubleshooting<a class="anchor" id="troubleshooting"></a>
429
426
  Typical connection issues are due to:
430
- - Firewall. You might need to allow connections on port 5000 (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.
431
- - Port conflict. If port 5000 is in use, a different number can be specified when instantiating MultiPyVu.Server() and MultiPyVu.Client().
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().
432
429
  ```python
433
430
  server = mpv.Server(port=6000)
434
431
  client = mpv.Client(port=6000)
@@ -437,6 +434,16 @@ client = mpv.Client(port=6000)
437
434
  - A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
438
435
 
439
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
+
440
447
  **3.6.1**
441
448
  - August 2025
442
449
  - Add commands to get the temperature and field setpoints.
@@ -39,7 +39,7 @@ MultiPyVu uses the following modules:
39
39
  - pillow - supports server gui
40
40
  - pyyaml - supports logging
41
41
 
42
- For the Python 3 distribution Quantum Design recommends [Anaconda](https://www.anaconda.com/products/individual) as it includes most modules needed for this server and other packages useful for scientific computing. To find which version of Python is used, from a command prompt type:
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
  ```
@@ -64,10 +64,9 @@ Measuring\example_get_setpoints.py | Shows how to get the temperature and magnet
64
64
  Options\example_aux_therm.py | Gets the temperature of the auxiliary thermometer from the OptiCool.
65
65
  Options\example_resistivity_option.py | Demonstrates how to set up the BRT module bridges for resistivity measurements and how to save the data.
66
66
  Options\example_horizontal_rotator.py | Demonstrates how to move the horizontal rotator to a new position.
67
- UsefulBatchFiles\whats_my_ip_address.cmd | This batch file script prints out the IP address for the computer, providing an easy way to get the server IP address needed for remote operation. Alternatively, the gui can be used to get the IP address by calling ```python -m MultiPyVu```.
68
- 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```
69
68
  UsefulBatchFiles\RunServer.cmd | This runs the server GUI.
70
- UsefulBatchFiles\kill_process.cmd | This ends the processes with the specified PID (which can be identified using show_process_with_port.cmd). Run using ```$ kill_process.cmd 13579```
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```
71
70
 
72
71
  ### Getting Started<a class="anchor" id="getting-started"></a>
73
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.
@@ -133,7 +132,7 @@ with mpv.Client('127.0.0.1') as client:
133
132
  # do post-processing once the client has been closed
134
133
  ```
135
134
 
136
- If the host or port are not default values (localhost and 5000, respectively), then these parameters must be specified when instantiating MultiPyVu.Client().
135
+ If the host or port are not default values (localhost and 27183, respectively), then these parameters must be specified when instantiating MultiPyVu.Client().
137
136
 
138
137
  Alternatively, one can start a connection to the server using:
139
138
  ```python
@@ -285,7 +284,7 @@ For DynaCool, VersaLab, and PPMS customers with the horizontal rotator option, M
285
284
  Once configured, the following commands are simple to use:
286
285
  ```python
287
286
  position = 374.5
288
- rate_deg_per_sec = 100.0
287
+ rate_deg_per_sec = 30.0
289
288
  client.set_position(position, rate_deg_per_sec)
290
289
  pos, status = client.get_position()
291
290
  ```
@@ -360,7 +359,7 @@ The server status can be queried from the command line. First, we can see if th
360
359
  ```cmd
361
360
  $ python -m MultiPyVu -running
362
361
  ```
363
- By default, this queries the server at IP address = localhost and port = 5000. To query a different address, use the *-ip=* or *-p=* flags.
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.
364
363
 
365
364
  Similarly, in order to get the server status at a specific ip address, use:
366
365
  ```cmd
@@ -399,8 +398,8 @@ with mpv.Server(flags=['-s', 'DYNACOOL']) as server:
399
398
 
400
399
  ### Troubleshooting<a class="anchor" id="troubleshooting"></a>
401
400
  Typical connection issues are due to:
402
- - Firewall. You might need to allow connections on port 5000 (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.
403
- - Port conflict. If port 5000 is in use, a different number can be specified when instantiating MultiPyVu.Server() and MultiPyVu.Client().
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().
404
403
  ```python
405
404
  server = mpv.Server(port=6000)
406
405
  client = mpv.Client(port=6000)
@@ -409,6 +408,16 @@ client = mpv.Client(port=6000)
409
408
  - A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
410
409
 
411
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
+
412
421
  **3.6.1**
413
422
  - August 2025
414
423
  - Add commands to get the temperature and field setpoints.
@@ -6,15 +6,20 @@ 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"
16
+ description = "Control MultiVu using Python"
17
+ dependencies = [
18
+ "pandas",
19
+ "pywin32>=300; platform_system=='Windows'",
20
+ "pillow",
21
+ "pyyaml",
22
+ ]
18
23
  license = "MIT"
19
24
  classifiers = [
20
25
  "Programming Language :: Python :: 3",
@@ -38,3 +43,6 @@ keywords = [
38
43
  [project.urls]
39
44
  "Quantum Design" = "https://qdusa.com"
40
45
  "Pharos" = "https://www.qdusa.com/register/account/login"
46
+
47
+ [tool.setuptools.dynamic]
48
+ version = {attr = "MultiPyVu.__version.__version__"}
@@ -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, catch_thread_error)
16
+ ISimulateChange)
17
17
  from .IEventManager import IObserver
18
18
 
19
19
 
@@ -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
- _val: float
274
- _state: str
275
- _set_point: float
276
- _rate: float
277
- _flavor: str
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._val
292
+ return SimulateChamberChange._current_val
286
293
 
287
294
  @current_val.setter
288
295
  def current_val(self, new):
289
- SimulateChamberChange._val = new
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 = STATE_DICT[1]
333
+ self.state = 1
327
334
  elif self.set_point == modeEnum.purge_seal.value:
328
- self.state = STATE_DICT[1]
335
+ self.state = 1
329
336
  elif self.set_point == modeEnum.vent_seal.value:
330
- self.state = STATE_DICT[2]
337
+ self.state = 2
331
338
  elif self.set_point == modeEnum.high_vacuum.value:
332
- self.state = STATE_DICT[7]
339
+ self.state = 7
333
340
  elif self.set_point == modeEnum.pump_continuous.value:
334
- self.state = STATE_DICT[8]
341
+ self.state = 8
335
342
  elif self.set_point == modeEnum.vent_continuous.value:
336
343
  if self.flavor == 'PPMS':
337
- self.state = STATE_DICT[5]
344
+ self.state = 5
338
345
  else:
339
- self.state = STATE_DICT[9]
346
+ self.state = 9
340
347
  else:
341
348
  msg = f'{self.set_point} is an invalid mode'
342
349
  raise ValueError(msg)
@@ -403,11 +410,10 @@ class CommandChamberSim(CommandChamberBase,
403
410
 
404
411
  def _set_state_imp(self, mode: modeEnum) -> Union[str, int]:
405
412
  self.change_thread: SimulateChamberChange = self.get_sim_instance()
406
- state_string = STATE_DICT[self.state]
407
413
  self.change_thread.set_params('',
408
414
  mode,
409
415
  0.0,
410
- state_string,
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
- for state_number, state_str in STATE_DICT.items():
426
- if state_str == state:
427
- self.state = state_number
428
- break
431
+ self.state = state
@@ -1,6 +1,5 @@
1
1
  """
2
- Command_factory.py is used to instantiate the 'real' or
3
- simulated ICommand classes.
2
+ CommandFactory.py is used to instantiate the ICommand classes.
4
3
  """
5
4
 
6
5
  from typing import Union
@@ -8,6 +7,7 @@ from typing import Union
8
7
  from . import CommandChamber as chamber
9
8
  from . import CommandField as field
10
9
  from . import CommandFieldSetPoints as field_setpoints
10
+ from . import CommandVectorMagnet as vector_cartesian
11
11
  from . import CommandRotator as rotator
12
12
  from . import CommandSdo as sdo
13
13
  from . import CommandTemperature as temperature
@@ -38,9 +38,17 @@ def create_command_mv(mvu_flavor,
38
38
  cmd_dict = {'TEMP': create_command_temp(mvu_flavor, win32_dispatch),
39
39
  'TEMP_SETPOINTS': create_command_temp_setpoints(mvu_flavor,
40
40
  win32_dispatch),
41
+ 'FIELD': create_command_field(mvu_flavor, win32_dispatch),
42
+ 'FIELD_SETPOINTS_X': create_command_field_setpoints(mvu_flavor,
43
+ win32_dispatch,
44
+ 'X'),
45
+ 'FIELD_SETPOINTS_Y': create_command_field_setpoints(mvu_flavor,
46
+ win32_dispatch,
47
+ 'Y'),
41
48
  'FIELD_SETPOINTS': create_command_field_setpoints(mvu_flavor,
42
49
  win32_dispatch),
43
- 'FIELD': create_command_field(mvu_flavor, win32_dispatch),
50
+ 'VECTOR_CART': create_command_vector(mvu_flavor, win32_dispatch, True),
51
+ 'VECTOR_SPHERE': create_command_vector(mvu_flavor, win32_dispatch, False),
44
52
  'CHAMBER': create_command_chamber(mvu_flavor, win32_dispatch),
45
53
  'SDO': create_command_sdo(win32_dispatch),
46
54
  'WAITFOR': create_command_wait_for(mvu_flavor, win32_dispatch),
@@ -92,11 +100,11 @@ def create_command_temp_setpoints(
92
100
  The name of the MultiVu flavor (the instrument name)
93
101
  win32_dispatch (optional): win32com.client.CDispatch or None
94
102
  This is the object used to communicate with MultiVu.
95
- Default is None, which will load CommandTemperatureSim
103
+ Default is None, which will load CommandTempSetPointsSim.
96
104
 
97
105
  Returns:
98
106
  --------
99
- CommandTemperature object
107
+ CommandTempSetPoints object
100
108
  """
101
109
  if win32_dispatch:
102
110
  return temp_setpoints.CommandTempSetpointsImp(mvu_flavor, win32_dispatch)
@@ -130,9 +138,42 @@ def create_command_field(
130
138
  return field.CommandFieldSim(mvu_flavor)
131
139
 
132
140
 
141
+ def create_command_vector(
142
+ mvu_flavor: str = '',
143
+ win32_dispatch=None,
144
+ cartesian_coordinates=True,
145
+ ) -> Union[vector_cartesian.CommandVectorImp,
146
+ vector_cartesian.CommandVectorSim]:
147
+ """
148
+ Create a CommandVector object
149
+
150
+ Parameters:
151
+ -----------
152
+ mvu_flavor: str
153
+ The name of the MultiVu flavor (the instrument name)
154
+ win32_dispatch (optional): win32com.client.CDispatch or None
155
+ This is the object used to communicate with MultiVu.
156
+ Default is None, which will load CommandVectorSim
157
+ cartesian_coordinates (optional): If true (false), instantiate
158
+ the magnet in cartesian (spherical) coordinates.
159
+
160
+ Returns:
161
+ --------
162
+ CommandVector object
163
+ """
164
+ if win32_dispatch:
165
+ return vector_cartesian.CommandVectorImp(win32_dispatch,
166
+ mvu_flavor,
167
+ cartesian_coordinates)
168
+ else:
169
+ return vector_cartesian.CommandVectorSim(mvu_flavor,
170
+ cartesian_coordinates)
171
+
172
+
133
173
  def create_command_field_setpoints(
134
174
  mvu_flavor: str = '',
135
175
  win32_dispatch=None,
176
+ axis: str = 'Z',
136
177
  ) -> Union[field_setpoints.CommandFieldSetPointsSim,
137
178
  field_setpoints.CommandFieldSetPointsImp]:
138
179
  """
@@ -144,16 +185,16 @@ def create_command_field_setpoints(
144
185
  The name of the MultiVu flavor (the instrument name)
145
186
  win32_dispatch (optional): win32com.client.CDispatch or None
146
187
  This is the object used to communicate with MultiVu.
147
- Default is None, which will load CommandTemperatureSim
188
+ Default is None, which will load CommandFieldSetPointsSim
148
189
 
149
190
  Returns:
150
191
  --------
151
- CommandTemperature object
192
+ CommandFieldSetPoints object
152
193
  """
153
194
  if win32_dispatch:
154
- return field_setpoints.CommandFieldSetPointsImp(mvu_flavor, win32_dispatch)
195
+ return field_setpoints.CommandFieldSetPointsImp(mvu_flavor, win32_dispatch, axis)
155
196
  else:
156
- return field_setpoints.CommandFieldSetPointsSim(mvu_flavor)
197
+ return field_setpoints.CommandFieldSetPointsSim(mvu_flavor, axis)
157
198
 
158
199
 
159
200
  def create_command_chamber(