MultiPyVu 3.3.0__tar.gz → 3.6.1__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.3.0/src/MultiPyVu.egg-info → multipyvu-3.6.1}/PKG-INFO +69 -51
- {multipyvu-3.3.0 → multipyvu-3.6.1}/README.md +61 -26
- {multipyvu-3.3.0 → multipyvu-3.6.1}/pyproject.toml +1 -2
- {multipyvu-3.3.0 → multipyvu-3.6.1}/setup.py +5 -5
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/BRT.py +25 -16
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/CommandChamber.py +14 -10
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/CommandField.py +76 -62
- multipyvu-3.6.1/src/MultiPyVu/CommandFieldSetPoints.py +288 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/CommandMultiVu.py +1 -1
- multipyvu-3.6.1/src/MultiPyVu/CommandRotator.py +566 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/CommandSdo.py +17 -13
- multipyvu-3.6.1/src/MultiPyVu/CommandTempSetPoints.py +248 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/CommandTemperature.py +31 -26
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/CommandWaitFor.py +75 -9
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/Command_factory.py +90 -3
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/ICommand.py +33 -31
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuClient.py +116 -10
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuClient_base.py +201 -88
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuDataFile/MultiVuDataFile.py +5 -6
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuServer.py +14 -14
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/SocketMessage.py +175 -159
- multipyvu-3.6.1/src/MultiPyVu/SocketMessageClient.py +510 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/SocketMessageServer.py +388 -208
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/__version.py +1 -1
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/exceptions.py +1 -1
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/instrument.py +3 -3
- multipyvu-3.6.1/src/MultiPyVu/logging_config.py +76 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/project_vars.py +9 -2
- {multipyvu-3.3.0 → multipyvu-3.6.1/src/MultiPyVu.egg-info}/PKG-INFO +69 -51
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu.egg-info/SOURCES.txt +3 -0
- multipyvu-3.3.0/src/MultiPyVu/SocketMessageClient.py +0 -290
- multipyvu-3.3.0/src/MultiPyVu/logging_config.py +0 -72
- {multipyvu-3.3.0 → multipyvu-3.6.1}/LICENSE +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/setup.cfg +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/IEventManager.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/IServer.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuDataFile/__init__.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuDataFile/__version.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuDataFile/is_pathname_valid.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/ParseInputs.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/__init__.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/__main__.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/check_windows_esc.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/font/Play-Bold.ttf +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/font/Play-Regular.ttf +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/font/__init__.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/generate_sdo_objects.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/gui/Controller.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/gui/IController.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/gui/IView.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/gui/ViewFactory.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/gui/ViewTk.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/gui/__init__.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/images/Q.png +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/images/QD_logo.jpg +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/images/__init__.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/logging_config.yaml +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/scripts/__init__.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/scripts/helper_scripts.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/scripts/whats_my_ip_address.cmd +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu/sdo_object.py +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu.egg-info/dependency_links.txt +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu.egg-info/requires.txt +0 -0
- {multipyvu-3.3.0 → multipyvu-3.6.1}/src/MultiPyVu.egg-info/top_level.txt +0 -0
|
@@ -1,47 +1,30 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: MultiPyVu
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.6.1
|
|
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
|
|
42
21
|
Requires-Dist: pywin32>=300; platform_system == "Windows"
|
|
43
22
|
Requires-Dist: pillow
|
|
44
23
|
Requires-Dist: pyyaml
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
Dynamic: requires-dist
|
|
26
|
+
Dynamic: requires-python
|
|
27
|
+
Dynamic: summary
|
|
45
28
|
|
|
46
29
|

|
|
47
30
|
# MultiPyVu
|
|
@@ -60,6 +43,7 @@ Requires-Dist: pyyaml
|
|
|
60
43
|
* [is_steady()](#is_steady)
|
|
61
44
|
* [get_aux_temperature()](#aux_therm)
|
|
62
45
|
* [resistivity option](#brt)
|
|
46
|
+
* [horizontal rotator option](#rotator)
|
|
63
47
|
* [Saving & Opening a MultiVu Data File](#save)
|
|
64
48
|
* [Querying the Server Status](#server_status)
|
|
65
49
|
* [Testing the Server Using Scaffolding](#scaffolding)
|
|
@@ -77,13 +61,13 @@ The components of MultiPyVu enable access to the set and read the temperature, f
|
|
|
77
61
|
|
|
78
62
|
### Module Requirements<a class="anchor" id="requirements"></a>
|
|
79
63
|
MultiPyVu uses the following modules:
|
|
80
|
-
- python version 3.
|
|
64
|
+
- python version 3.7 or higher
|
|
81
65
|
- pywin32 - version 300 or higher.
|
|
82
66
|
- pandas - data read back from a *.dat* file is a Pandas Dataframe
|
|
83
67
|
- pillow - supports server gui
|
|
84
68
|
- pyyaml - supports logging
|
|
85
69
|
|
|
86
|
-
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.
|
|
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:
|
|
87
71
|
```
|
|
88
72
|
python --version
|
|
89
73
|
```
|
|
@@ -104,8 +88,10 @@ Remote Connection\example_MVDataFile_VISA.py | Simple example showing how to rou
|
|
|
104
88
|
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.
|
|
105
89
|
Measuring\example_stabilize.py | Measures the temperature while stabilizing at each temperature.
|
|
106
90
|
Measuring\example_sweep.py | Measures the temperature while sweeping the temperature.
|
|
107
|
-
|
|
91
|
+
Measuring\example_get_setpoints.py | Shows how to get the temperature and magnetic field setpoints.
|
|
92
|
+
Options\example_aux_therm.py | Gets the temperature of the auxiliary thermometer from the OptiCool.
|
|
108
93
|
Options\example_resistivity_option.py | Demonstrates how to set up the BRT module bridges for resistivity measurements and how to save the data.
|
|
94
|
+
Options\example_horizontal_rotator.py | Demonstrates how to move the horizontal rotator to a new position.
|
|
109
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```.
|
|
110
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```
|
|
111
97
|
UsefulBatchFiles\RunServer.cmd | This runs the server GUI.
|
|
@@ -138,22 +124,23 @@ $ python -m MultiPyVu -get_ip
|
|
|
138
124
|
On the client PC, update the 'host' variable of the 'example_Remote-Client.py' script *with the same server PC IPV4 address* and run it. The script will report the present temperature and field value/status a few times to show the connection is functioning.
|
|
139
125
|
|
|
140
126
|
**Next Steps:**
|
|
141
|
-
It may sometimes be desirable to combine the sample environment parameters (temperature, field) with readings from a user's own instrumentation into a single *.dat* file which can be plotted in MultiVu. This functionality, accomplished using the MultiPyVu.DataFile module, is demonstrated using PyVISA to communicate with a VISA-compatible instrument in the 'example_MvDataFile_VISA.py' example. Note that for this routine to execute properly, the correct instrument bus/address and query string need to be updated in the script.
|
|
127
|
+
It may sometimes be desirable to combine the sample environment parameters (temperature, field) with readings from a user's own instrumentation into a single *.dat* file which can be plotted in MultiVu. This functionality, accomplished using the MultiPyVu.DataFile module, is demonstrated using PyVISA to communicate with a VISA-compatible instrument in the 'Remote Connection/example_MvDataFile_VISA.py' example. Note that for this routine to execute properly, the correct instrument bus/address and query string need to be updated in the script.
|
|
142
128
|
|
|
143
129
|
For further information on the detailed operation of the components of the module, see the following sections.
|
|
144
130
|
|
|
145
131
|
### Using MultiPyVu.Server() and MultiPyVu.Client()<a class="anchor" id="using"></a>
|
|
146
|
-
To start the server on localhost, open MultiVu, and
|
|
132
|
+
To start the server on localhost, open MultiVu, and type:
|
|
147
133
|
```cmd
|
|
148
|
-
$ python
|
|
134
|
+
$ python -m MultiPyVu
|
|
149
135
|
```
|
|
150
|
-
|
|
136
|
+
One can also use the example script _run_server.py_, go to a command prompt and type:
|
|
151
137
|
```cmd
|
|
152
|
-
$ python
|
|
138
|
+
$ python run_server.py
|
|
153
139
|
```
|
|
140
|
+
|
|
154
141
|
As mentioned above, if the client and the server are running on the same computer as MultiVu, then one can use example_local.py as a guide to set up the whole script in one file.
|
|
155
142
|
|
|
156
|
-
There are a list of
|
|
143
|
+
There are a list of flags to specify settings. These can be found by typing -h, which brings up help information:
|
|
157
144
|
```cmd
|
|
158
145
|
$ python -m MultiPyVu -h
|
|
159
146
|
```
|
|
@@ -170,8 +157,8 @@ Both the Server and the Client are context managers, which means to write a scri
|
|
|
170
157
|
import MultiPyVu as mpv
|
|
171
158
|
|
|
172
159
|
with mpv.Client('127.0.0.1') as client:
|
|
173
|
-
|
|
174
|
-
|
|
160
|
+
# put scripting commands here
|
|
161
|
+
# do post-processing once the client has been closed
|
|
175
162
|
```
|
|
176
163
|
|
|
177
164
|
If the host or port are not default values (localhost and 5000, respectively), then these parameters must be specified when instantiating MultiPyVu.Client().
|
|
@@ -180,16 +167,11 @@ Alternatively, one can start a connection to the server using:
|
|
|
180
167
|
```python
|
|
181
168
|
client = mpv.Client(host='127.0.0.1')
|
|
182
169
|
client.open()
|
|
183
|
-
|
|
170
|
+
# put scripting commands here
|
|
184
171
|
client.close_client()
|
|
185
|
-
|
|
186
|
-
```
|
|
187
|
-
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.
|
|
188
|
-
|
|
189
|
-
If needed, one can turn off socket timeouts so that the client will wait indefinitely for a response from the server. To do this, set the time in seconds using the 'socket_timeout' keyword when instantiating the client, or set the time to *None* to turn off the timeout. By default, the timeout is set to one second.
|
|
190
|
-
```python
|
|
191
|
-
client = mpv.Client(socket_timeout=None)
|
|
172
|
+
# do post-processing once the client has been closed
|
|
192
173
|
```
|
|
174
|
+
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.
|
|
193
175
|
|
|
194
176
|
The client can also close the server directly using:
|
|
195
177
|
```python
|
|
@@ -197,14 +179,14 @@ client.close_server()
|
|
|
197
179
|
```
|
|
198
180
|
instead of client.close_client(). Note that once this is called, the server will need to be reopened. Also, this can not be accessed from within a with-block.
|
|
199
181
|
|
|
200
|
-
If the client and server are being run on the same computer, then
|
|
182
|
+
If the client and server are being run on the same computer, then a single script can control them both.
|
|
201
183
|
```python
|
|
202
184
|
import MultiPyVu as mpv
|
|
203
185
|
|
|
204
186
|
with mpv.Server() as server:
|
|
205
187
|
with mpv.Client() as client:
|
|
206
|
-
|
|
207
|
-
|
|
188
|
+
# put scripting commands here
|
|
189
|
+
# do post-processing now that the client and server have been closed
|
|
208
190
|
```
|
|
209
191
|
|
|
210
192
|
This is convenient as it does not require running two different scripts.
|
|
@@ -237,6 +219,10 @@ The <enum_options> mode is set using the client.temperature.approach_mode enum,
|
|
|
237
219
|
```python
|
|
238
220
|
temperature, status = client.get_temperature()
|
|
239
221
|
```
|
|
222
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
223
|
+
```python
|
|
224
|
+
temperature, rate, approach = client.get_temperature_setpoints()
|
|
225
|
+
```
|
|
240
226
|
|
|
241
227
|
**Field**<a class="anchor" id="field"></a>
|
|
242
228
|
```python
|
|
@@ -258,6 +244,10 @@ The field and status are read back using:
|
|
|
258
244
|
```python
|
|
259
245
|
field, status = client.get_field()
|
|
260
246
|
```
|
|
247
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
248
|
+
```python
|
|
249
|
+
field, rate, approach, driven = client.get_field_setpoints()
|
|
250
|
+
```
|
|
261
251
|
|
|
262
252
|
**Chamber**<a class="anchor" id="chamber"></a>
|
|
263
253
|
```python
|
|
@@ -271,9 +261,9 @@ chamber = client.get_chamber()
|
|
|
271
261
|
Note that this command is not used by the OptiCool.
|
|
272
262
|
|
|
273
263
|
**Wait For**<a class="anchor" id="waitfor"></a>
|
|
274
|
-
When a setting on a cryostat is configured, it will take time to reach the new set point. If desired, one can wait for the setting to become stable using the .wait_for(delay, timeout, bitmask) command. A delay will set the time in seconds after the setting is stable, which can be useful to make sure a sample has time to thermalize; timeout is the seconds until the command will give up; bitmask tells the system which settings need to be stable. This can be set using the
|
|
264
|
+
When a setting on a cryostat is configured, it will take time to reach the new set point. If desired, one can wait for the setting to become stable using the .wait_for(delay, timeout, bitmask) command. A delay will set the time in seconds after the setting is stable, which can be useful to make sure a sample has time to thermalize; timeout is the seconds until the command will give up; bitmask tells the system which settings need to be stable. This can be set using the waitfor handle, and multiple parameters are combined using bit-wise or. In the example below, the wait_for command will wait at least 90 seconds for the temperature, field, and chamber to stabilize, and will then immediately go on to the next command.
|
|
275
265
|
```python
|
|
276
|
-
client.wait_for(0, 90, client.temperature.waitfor | client.field.waitfor|
|
|
266
|
+
client.wait_for(0, 90, client.temperature.waitfor | client.field.waitfor |
|
|
277
267
|
client.chamber.waitfor)
|
|
278
268
|
```
|
|
279
269
|
|
|
@@ -316,6 +306,18 @@ client.resistivity.get_resistance(bridge_number)
|
|
|
316
306
|
client.resistivity.get_current(bridge_number)
|
|
317
307
|
```
|
|
318
308
|
|
|
309
|
+
**Horizontal Rotator Option**<a class="anchor" id="rotator"></a>
|
|
310
|
+
|
|
311
|
+
For DynaCool, VersaLab, and PPMS customers with the horizontal rotator option, MultiPyVu can be used to adjust the rotator position. The option must be configured before using MultiPyVu. Note that the rate_deg_per_sec is ignored for the PPMS.
|
|
312
|
+
|
|
313
|
+
Once configured, the following commands are simple to use:
|
|
314
|
+
```python
|
|
315
|
+
position = 374.5
|
|
316
|
+
rate_deg_per_sec = 100.0
|
|
317
|
+
client.set_position(position, rate_deg_per_sec)
|
|
318
|
+
pos, status = client.get_position()
|
|
319
|
+
```
|
|
320
|
+
|
|
319
321
|
### Saving & Opening a MultiVu Data File<a class="anchor" id="save"></a>
|
|
320
322
|
The MultiPyVu.Client class can be used in conjunction with 3rd party tools in order to expand the capabilities of measurements from a Quantum Design cryostat. One can set up a VISA connection to a voltmeter, for example, and then collect information while controlling the cryostat temperature, field, and chamber status. This data can be collected into a MultiVu data file using MultiPyVu.DataFile. One can also use this to read a data file into a Pandas DataFrame.
|
|
321
323
|
|
|
@@ -419,8 +421,8 @@ import MultiPyVu as mpv
|
|
|
419
421
|
|
|
420
422
|
with mpv.Server(flags=['-s', 'DYNACOOL']) as server:
|
|
421
423
|
with mpv.Client() as client:
|
|
422
|
-
|
|
423
|
-
|
|
424
|
+
# put scripting commands here
|
|
425
|
+
# do post-processing now that the client and server have been closed
|
|
424
426
|
```
|
|
425
427
|
|
|
426
428
|
### Troubleshooting<a class="anchor" id="troubleshooting"></a>
|
|
@@ -435,6 +437,22 @@ client = mpv.Client(port=6000)
|
|
|
435
437
|
- A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
|
|
436
438
|
|
|
437
439
|
## Changelog<a class="anchor" id="changelog"></a>
|
|
440
|
+
**3.6.1**
|
|
441
|
+
- August 2025
|
|
442
|
+
- Add commands to get the temperature and field setpoints.
|
|
443
|
+
- Remove dependencies on the distutils module.
|
|
444
|
+
- Minimum python version 3.7
|
|
445
|
+
|
|
446
|
+
**3.5.4**
|
|
447
|
+
- June 2025
|
|
448
|
+
- Add the horizontal rotator option for DynaCool, VersaLab, and PPMS.
|
|
449
|
+
|
|
450
|
+
**3.4.0**
|
|
451
|
+
- May 2025
|
|
452
|
+
- Minimum python version now 3.9.
|
|
453
|
+
- Implemented socket handshaking to improve the reliability of the socket
|
|
454
|
+
communications.
|
|
455
|
+
|
|
438
456
|
**3.3.0**
|
|
439
457
|
- April 2025
|
|
440
458
|
- Bugfix which didn't allow this to be run on Mac or Linux platforms.
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* [is_steady()](#is_steady)
|
|
16
16
|
* [get_aux_temperature()](#aux_therm)
|
|
17
17
|
* [resistivity option](#brt)
|
|
18
|
+
* [horizontal rotator option](#rotator)
|
|
18
19
|
* [Saving & Opening a MultiVu Data File](#save)
|
|
19
20
|
* [Querying the Server Status](#server_status)
|
|
20
21
|
* [Testing the Server Using Scaffolding](#scaffolding)
|
|
@@ -32,13 +33,13 @@ The components of MultiPyVu enable access to the set and read the temperature, f
|
|
|
32
33
|
|
|
33
34
|
### Module Requirements<a class="anchor" id="requirements"></a>
|
|
34
35
|
MultiPyVu uses the following modules:
|
|
35
|
-
- python version 3.
|
|
36
|
+
- python version 3.7 or higher
|
|
36
37
|
- pywin32 - version 300 or higher.
|
|
37
38
|
- pandas - data read back from a *.dat* file is a Pandas Dataframe
|
|
38
39
|
- pillow - supports server gui
|
|
39
40
|
- pyyaml - supports logging
|
|
40
41
|
|
|
41
|
-
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.
|
|
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
43
|
```
|
|
43
44
|
python --version
|
|
44
45
|
```
|
|
@@ -59,8 +60,10 @@ Remote Connection\example_MVDataFile_VISA.py | Simple example showing how to rou
|
|
|
59
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.
|
|
60
61
|
Measuring\example_stabilize.py | Measures the temperature while stabilizing at each temperature.
|
|
61
62
|
Measuring\example_sweep.py | Measures the temperature while sweeping the temperature.
|
|
62
|
-
|
|
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.
|
|
63
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
|
+
Options\example_horizontal_rotator.py | Demonstrates how to move the horizontal rotator to a new position.
|
|
64
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```.
|
|
65
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```
|
|
66
69
|
UsefulBatchFiles\RunServer.cmd | This runs the server GUI.
|
|
@@ -93,22 +96,23 @@ $ python -m MultiPyVu -get_ip
|
|
|
93
96
|
On the client PC, update the 'host' variable of the 'example_Remote-Client.py' script *with the same server PC IPV4 address* and run it. The script will report the present temperature and field value/status a few times to show the connection is functioning.
|
|
94
97
|
|
|
95
98
|
**Next Steps:**
|
|
96
|
-
It may sometimes be desirable to combine the sample environment parameters (temperature, field) with readings from a user's own instrumentation into a single *.dat* file which can be plotted in MultiVu. This functionality, accomplished using the MultiPyVu.DataFile module, is demonstrated using PyVISA to communicate with a VISA-compatible instrument in the 'example_MvDataFile_VISA.py' example. Note that for this routine to execute properly, the correct instrument bus/address and query string need to be updated in the script.
|
|
99
|
+
It may sometimes be desirable to combine the sample environment parameters (temperature, field) with readings from a user's own instrumentation into a single *.dat* file which can be plotted in MultiVu. This functionality, accomplished using the MultiPyVu.DataFile module, is demonstrated using PyVISA to communicate with a VISA-compatible instrument in the 'Remote Connection/example_MvDataFile_VISA.py' example. Note that for this routine to execute properly, the correct instrument bus/address and query string need to be updated in the script.
|
|
97
100
|
|
|
98
101
|
For further information on the detailed operation of the components of the module, see the following sections.
|
|
99
102
|
|
|
100
103
|
### Using MultiPyVu.Server() and MultiPyVu.Client()<a class="anchor" id="using"></a>
|
|
101
|
-
To start the server on localhost, open MultiVu, and
|
|
104
|
+
To start the server on localhost, open MultiVu, and type:
|
|
102
105
|
```cmd
|
|
103
|
-
$ python
|
|
106
|
+
$ python -m MultiPyVu
|
|
104
107
|
```
|
|
105
|
-
|
|
108
|
+
One can also use the example script _run_server.py_, go to a command prompt and type:
|
|
106
109
|
```cmd
|
|
107
|
-
$ python
|
|
110
|
+
$ python run_server.py
|
|
108
111
|
```
|
|
112
|
+
|
|
109
113
|
As mentioned above, if the client and the server are running on the same computer as MultiVu, then one can use example_local.py as a guide to set up the whole script in one file.
|
|
110
114
|
|
|
111
|
-
There are a list of
|
|
115
|
+
There are a list of flags to specify settings. These can be found by typing -h, which brings up help information:
|
|
112
116
|
```cmd
|
|
113
117
|
$ python -m MultiPyVu -h
|
|
114
118
|
```
|
|
@@ -125,8 +129,8 @@ Both the Server and the Client are context managers, which means to write a scri
|
|
|
125
129
|
import MultiPyVu as mpv
|
|
126
130
|
|
|
127
131
|
with mpv.Client('127.0.0.1') as client:
|
|
128
|
-
|
|
129
|
-
|
|
132
|
+
# put scripting commands here
|
|
133
|
+
# do post-processing once the client has been closed
|
|
130
134
|
```
|
|
131
135
|
|
|
132
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,16 +139,11 @@ Alternatively, one can start a connection to the server using:
|
|
|
135
139
|
```python
|
|
136
140
|
client = mpv.Client(host='127.0.0.1')
|
|
137
141
|
client.open()
|
|
138
|
-
|
|
142
|
+
# put scripting commands here
|
|
139
143
|
client.close_client()
|
|
140
|
-
|
|
141
|
-
```
|
|
142
|
-
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.
|
|
143
|
-
|
|
144
|
-
If needed, one can turn off socket timeouts so that the client will wait indefinitely for a response from the server. To do this, set the time in seconds using the 'socket_timeout' keyword when instantiating the client, or set the time to *None* to turn off the timeout. By default, the timeout is set to one second.
|
|
145
|
-
```python
|
|
146
|
-
client = mpv.Client(socket_timeout=None)
|
|
144
|
+
# do post-processing once the client has been closed
|
|
147
145
|
```
|
|
146
|
+
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.
|
|
148
147
|
|
|
149
148
|
The client can also close the server directly using:
|
|
150
149
|
```python
|
|
@@ -152,14 +151,14 @@ client.close_server()
|
|
|
152
151
|
```
|
|
153
152
|
instead of client.close_client(). Note that once this is called, the server will need to be reopened. Also, this can not be accessed from within a with-block.
|
|
154
153
|
|
|
155
|
-
If the client and server are being run on the same computer, then
|
|
154
|
+
If the client and server are being run on the same computer, then a single script can control them both.
|
|
156
155
|
```python
|
|
157
156
|
import MultiPyVu as mpv
|
|
158
157
|
|
|
159
158
|
with mpv.Server() as server:
|
|
160
159
|
with mpv.Client() as client:
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
# put scripting commands here
|
|
161
|
+
# do post-processing now that the client and server have been closed
|
|
163
162
|
```
|
|
164
163
|
|
|
165
164
|
This is convenient as it does not require running two different scripts.
|
|
@@ -192,6 +191,10 @@ The <enum_options> mode is set using the client.temperature.approach_mode enum,
|
|
|
192
191
|
```python
|
|
193
192
|
temperature, status = client.get_temperature()
|
|
194
193
|
```
|
|
194
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
195
|
+
```python
|
|
196
|
+
temperature, rate, approach = client.get_temperature_setpoints()
|
|
197
|
+
```
|
|
195
198
|
|
|
196
199
|
**Field**<a class="anchor" id="field"></a>
|
|
197
200
|
```python
|
|
@@ -213,6 +216,10 @@ The field and status are read back using:
|
|
|
213
216
|
```python
|
|
214
217
|
field, status = client.get_field()
|
|
215
218
|
```
|
|
219
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
220
|
+
```python
|
|
221
|
+
field, rate, approach, driven = client.get_field_setpoints()
|
|
222
|
+
```
|
|
216
223
|
|
|
217
224
|
**Chamber**<a class="anchor" id="chamber"></a>
|
|
218
225
|
```python
|
|
@@ -226,9 +233,9 @@ chamber = client.get_chamber()
|
|
|
226
233
|
Note that this command is not used by the OptiCool.
|
|
227
234
|
|
|
228
235
|
**Wait For**<a class="anchor" id="waitfor"></a>
|
|
229
|
-
When a setting on a cryostat is configured, it will take time to reach the new set point. If desired, one can wait for the setting to become stable using the .wait_for(delay, timeout, bitmask) command. A delay will set the time in seconds after the setting is stable, which can be useful to make sure a sample has time to thermalize; timeout is the seconds until the command will give up; bitmask tells the system which settings need to be stable. This can be set using the
|
|
236
|
+
When a setting on a cryostat is configured, it will take time to reach the new set point. If desired, one can wait for the setting to become stable using the .wait_for(delay, timeout, bitmask) command. A delay will set the time in seconds after the setting is stable, which can be useful to make sure a sample has time to thermalize; timeout is the seconds until the command will give up; bitmask tells the system which settings need to be stable. This can be set using the waitfor handle, and multiple parameters are combined using bit-wise or. In the example below, the wait_for command will wait at least 90 seconds for the temperature, field, and chamber to stabilize, and will then immediately go on to the next command.
|
|
230
237
|
```python
|
|
231
|
-
client.wait_for(0, 90, client.temperature.waitfor | client.field.waitfor|
|
|
238
|
+
client.wait_for(0, 90, client.temperature.waitfor | client.field.waitfor |
|
|
232
239
|
client.chamber.waitfor)
|
|
233
240
|
```
|
|
234
241
|
|
|
@@ -271,6 +278,18 @@ client.resistivity.get_resistance(bridge_number)
|
|
|
271
278
|
client.resistivity.get_current(bridge_number)
|
|
272
279
|
```
|
|
273
280
|
|
|
281
|
+
**Horizontal Rotator Option**<a class="anchor" id="rotator"></a>
|
|
282
|
+
|
|
283
|
+
For DynaCool, VersaLab, and PPMS customers with the horizontal rotator option, MultiPyVu can be used to adjust the rotator position. The option must be configured before using MultiPyVu. Note that the rate_deg_per_sec is ignored for the PPMS.
|
|
284
|
+
|
|
285
|
+
Once configured, the following commands are simple to use:
|
|
286
|
+
```python
|
|
287
|
+
position = 374.5
|
|
288
|
+
rate_deg_per_sec = 100.0
|
|
289
|
+
client.set_position(position, rate_deg_per_sec)
|
|
290
|
+
pos, status = client.get_position()
|
|
291
|
+
```
|
|
292
|
+
|
|
274
293
|
### Saving & Opening a MultiVu Data File<a class="anchor" id="save"></a>
|
|
275
294
|
The MultiPyVu.Client class can be used in conjunction with 3rd party tools in order to expand the capabilities of measurements from a Quantum Design cryostat. One can set up a VISA connection to a voltmeter, for example, and then collect information while controlling the cryostat temperature, field, and chamber status. This data can be collected into a MultiVu data file using MultiPyVu.DataFile. One can also use this to read a data file into a Pandas DataFrame.
|
|
276
295
|
|
|
@@ -374,8 +393,8 @@ import MultiPyVu as mpv
|
|
|
374
393
|
|
|
375
394
|
with mpv.Server(flags=['-s', 'DYNACOOL']) as server:
|
|
376
395
|
with mpv.Client() as client:
|
|
377
|
-
|
|
378
|
-
|
|
396
|
+
# put scripting commands here
|
|
397
|
+
# do post-processing now that the client and server have been closed
|
|
379
398
|
```
|
|
380
399
|
|
|
381
400
|
### Troubleshooting<a class="anchor" id="troubleshooting"></a>
|
|
@@ -390,6 +409,22 @@ client = mpv.Client(port=6000)
|
|
|
390
409
|
- A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
|
|
391
410
|
|
|
392
411
|
## Changelog<a class="anchor" id="changelog"></a>
|
|
412
|
+
**3.6.1**
|
|
413
|
+
- August 2025
|
|
414
|
+
- Add commands to get the temperature and field setpoints.
|
|
415
|
+
- Remove dependencies on the distutils module.
|
|
416
|
+
- Minimum python version 3.7
|
|
417
|
+
|
|
418
|
+
**3.5.4**
|
|
419
|
+
- June 2025
|
|
420
|
+
- Add the horizontal rotator option for DynaCool, VersaLab, and PPMS.
|
|
421
|
+
|
|
422
|
+
**3.4.0**
|
|
423
|
+
- May 2025
|
|
424
|
+
- Minimum python version now 3.9.
|
|
425
|
+
- Implemented socket handshaking to improve the reliability of the socket
|
|
426
|
+
communications.
|
|
427
|
+
|
|
393
428
|
**3.3.0**
|
|
394
429
|
- April 2025
|
|
395
430
|
- Bugfix which didn't allow this to be run on Mac or Linux platforms.
|
|
@@ -15,10 +15,9 @@ maintainers = [
|
|
|
15
15
|
{ name = "Quantum Design, Inc.", email = "apps@qdusa.com" },
|
|
16
16
|
]
|
|
17
17
|
readme = "README.md"
|
|
18
|
-
license =
|
|
18
|
+
license = "MIT"
|
|
19
19
|
classifiers = [
|
|
20
20
|
"Programming Language :: Python :: 3",
|
|
21
|
-
"License :: OSI Approved :: MIT License",
|
|
22
21
|
"Operating System :: OS Independent",
|
|
23
22
|
"Intended Audience :: Science/Research",
|
|
24
23
|
"Topic :: Scientific/Engineering :: Physics",
|
|
@@ -5,12 +5,12 @@ https://packaging.python.org/guides/distributing-packages-using-setuptools/
|
|
|
5
5
|
https://github.com/pypa/sampleproject
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
# Always prefer setuptools over distutils
|
|
9
|
-
from setuptools import setup, find_packages
|
|
10
|
-
import pathlib
|
|
11
8
|
import codecs
|
|
12
9
|
import os.path
|
|
10
|
+
import pathlib
|
|
13
11
|
|
|
12
|
+
# Always prefer setuptools over distutils
|
|
13
|
+
from setuptools import find_packages, setup
|
|
14
14
|
|
|
15
15
|
here = pathlib.Path(__file__).parent.resolve()
|
|
16
16
|
|
|
@@ -51,11 +51,11 @@ setup(
|
|
|
51
51
|
"logging_config.yaml"
|
|
52
52
|
]
|
|
53
53
|
},
|
|
54
|
-
python_requires=">=3.
|
|
54
|
+
python_requires=">=3.7",
|
|
55
55
|
install_requires=[
|
|
56
56
|
"pandas",
|
|
57
57
|
"pywin32>=300; platform_system=='Windows'",
|
|
58
58
|
"pillow",
|
|
59
|
-
"pyyaml"
|
|
59
|
+
"pyyaml"
|
|
60
60
|
],
|
|
61
61
|
)
|
|
@@ -20,6 +20,23 @@ class Brt():
|
|
|
20
20
|
self.client = client
|
|
21
21
|
self.stabilize_time = 5
|
|
22
22
|
|
|
23
|
+
def _make_bridge_number_error(self, bridge_number: int) -> str:
|
|
24
|
+
"""
|
|
25
|
+
This creates a simple error message saying that the
|
|
26
|
+
selected bridge number is out of range
|
|
27
|
+
|
|
28
|
+
Arguments:
|
|
29
|
+
bridge_number
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
error message
|
|
33
|
+
"""
|
|
34
|
+
msg = 'bridge_number must be 1, 2, or 3 '
|
|
35
|
+
# Note that python version 3.7 does not allow formatting
|
|
36
|
+
# strings using {bridge_number = }
|
|
37
|
+
msg += f'(bridge_number = {bridge_number})'
|
|
38
|
+
return msg
|
|
39
|
+
|
|
23
40
|
def bridge_setup(self,
|
|
24
41
|
bridge_number: int,
|
|
25
42
|
channel_on: bool,
|
|
@@ -74,8 +91,7 @@ class Brt():
|
|
|
74
91
|
|
|
75
92
|
sdo = enable_sdo.get(bridge_number, None)
|
|
76
93
|
if sdo is None:
|
|
77
|
-
|
|
78
|
-
raise ValueError(msg)
|
|
94
|
+
raise ValueError(self._make_bridge_number_error(bridge_number))
|
|
79
95
|
self.client._set_sdo(sdo, int(enable))
|
|
80
96
|
# Pause to let the SDO go through. The pause time is
|
|
81
97
|
# somewhat arbitrary.
|
|
@@ -113,8 +129,7 @@ class Brt():
|
|
|
113
129
|
|
|
114
130
|
sdo = const_current_sdo.get(bridge_number, None)
|
|
115
131
|
if sdo is None:
|
|
116
|
-
|
|
117
|
-
raise ValueError(msg)
|
|
132
|
+
raise ValueError(self._make_bridge_number_error(bridge_number))
|
|
118
133
|
self.client._set_sdo(sdo, int(const_current))
|
|
119
134
|
for timeout in range(0, 4):
|
|
120
135
|
time.sleep(0.6)
|
|
@@ -149,8 +164,7 @@ class Brt():
|
|
|
149
164
|
|
|
150
165
|
sdo = resistance.get(bridge_number, None)
|
|
151
166
|
if sdo is None:
|
|
152
|
-
|
|
153
|
-
raise ValueError(msg)
|
|
167
|
+
raise ValueError(self._make_bridge_number_error(bridge_number))
|
|
154
168
|
res, status = self.client._get_sdo(sdo)
|
|
155
169
|
return float(res), status
|
|
156
170
|
|
|
@@ -181,8 +195,7 @@ class Brt():
|
|
|
181
195
|
|
|
182
196
|
sdo = current.get(bridge_number, None)
|
|
183
197
|
if sdo is None:
|
|
184
|
-
|
|
185
|
-
raise ValueError(msg)
|
|
198
|
+
raise ValueError(self._make_bridge_number_error(bridge_number))
|
|
186
199
|
res, status = self.client._get_sdo(sdo)
|
|
187
200
|
return float(res), status
|
|
188
201
|
|
|
@@ -222,8 +235,7 @@ class Brt():
|
|
|
222
235
|
|
|
223
236
|
sdo = current_sdo.get(bridge_number, None)
|
|
224
237
|
if sdo is None:
|
|
225
|
-
|
|
226
|
-
raise ValueError(msg)
|
|
238
|
+
raise ValueError(self._make_bridge_number_error(bridge_number))
|
|
227
239
|
self.client._set_sdo(sdo, current_uA)
|
|
228
240
|
# Put in constant current mode
|
|
229
241
|
self._constant_current(bridge_number, True)
|
|
@@ -265,8 +277,7 @@ class Brt():
|
|
|
265
277
|
|
|
266
278
|
sdo = current_sdo.get(bridge_number, None)
|
|
267
279
|
if sdo is None:
|
|
268
|
-
|
|
269
|
-
raise ValueError(msg)
|
|
280
|
+
raise ValueError(self._make_bridge_number_error(bridge_number))
|
|
270
281
|
self.client._set_sdo(sdo, current_uA)
|
|
271
282
|
|
|
272
283
|
def power_limit(self, bridge_number: int, power_uW: float) -> None:
|
|
@@ -306,8 +317,7 @@ class Brt():
|
|
|
306
317
|
|
|
307
318
|
sdo = current_sdo.get(bridge_number, None)
|
|
308
319
|
if sdo is None:
|
|
309
|
-
|
|
310
|
-
raise ValueError(msg)
|
|
320
|
+
raise ValueError(self._make_bridge_number_error(bridge_number))
|
|
311
321
|
self.client._set_sdo(sdo, power_uW)
|
|
312
322
|
|
|
313
323
|
def voltage_limit(self, bridge_number: int, voltage_mV: float) -> None:
|
|
@@ -347,8 +357,7 @@ class Brt():
|
|
|
347
357
|
|
|
348
358
|
sdo = current_sdo.get(bridge_number, None)
|
|
349
359
|
if sdo is None:
|
|
350
|
-
|
|
351
|
-
raise ValueError(msg)
|
|
360
|
+
raise ValueError(self._make_bridge_number_error(bridge_number))
|
|
352
361
|
self.client._set_sdo(sdo, voltage_mV)
|
|
353
362
|
|
|
354
363
|
# This works, but is not used for the resistivity option, so currently commented out
|