MultiPyVu 3.5.4__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.5.4/src/MultiPyVu.egg-info → multipyvu-3.6.1}/PKG-INFO +22 -28
- {multipyvu-3.5.4 → multipyvu-3.6.1}/README.md +19 -4
- {multipyvu-3.5.4 → multipyvu-3.6.1}/pyproject.toml +1 -2
- {multipyvu-3.5.4 → multipyvu-3.6.1}/setup.py +2 -2
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/CommandChamber.py +9 -9
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/CommandField.py +53 -43
- multipyvu-3.6.1/src/MultiPyVu/CommandFieldSetPoints.py +288 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/CommandRotator.py +15 -16
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/CommandSdo.py +3 -3
- multipyvu-3.6.1/src/MultiPyVu/CommandTempSetPoints.py +248 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/CommandTemperature.py +26 -23
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/CommandWaitFor.py +75 -9
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/Command_factory.py +60 -1
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/ICommand.py +33 -31
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuClient.py +51 -5
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuClient_base.py +11 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/SocketMessage.py +0 -1
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/SocketMessageClient.py +7 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/SocketMessageServer.py +1 -1
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/__version.py +1 -1
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/exceptions.py +1 -1
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/project_vars.py +2 -2
- {multipyvu-3.5.4 → multipyvu-3.6.1/src/MultiPyVu.egg-info}/PKG-INFO +22 -28
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu.egg-info/SOURCES.txt +2 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/LICENSE +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/setup.cfg +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/BRT.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/CommandMultiVu.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/IEventManager.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/IServer.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuDataFile/MultiVuDataFile.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuDataFile/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuDataFile/__version.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuDataFile/is_pathname_valid.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/MultiVuServer.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/ParseInputs.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/__main__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/check_windows_esc.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/font/Play-Bold.ttf +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/font/Play-Regular.ttf +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/font/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/generate_sdo_objects.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/gui/Controller.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/gui/IController.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/gui/IView.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/gui/ViewFactory.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/gui/ViewTk.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/gui/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/images/Q.png +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/images/QD_logo.jpg +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/images/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/instrument.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/logging_config.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/logging_config.yaml +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/scripts/__init__.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/scripts/helper_scripts.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/scripts/whats_my_ip_address.cmd +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu/sdo_object.py +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu.egg-info/dependency_links.txt +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu.egg-info/requires.txt +0 -0
- {multipyvu-3.5.4 → multipyvu-3.6.1}/src/MultiPyVu.egg-info/top_level.txt +0 -0
|
@@ -1,41 +1,20 @@
|
|
|
1
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
|
|
@@ -82,13 +61,13 @@ The components of MultiPyVu enable access to the set and read the temperature, f
|
|
|
82
61
|
|
|
83
62
|
### Module Requirements<a class="anchor" id="requirements"></a>
|
|
84
63
|
MultiPyVu uses the following modules:
|
|
85
|
-
- python version 3.
|
|
64
|
+
- python version 3.7 or higher
|
|
86
65
|
- pywin32 - version 300 or higher.
|
|
87
66
|
- pandas - data read back from a *.dat* file is a Pandas Dataframe
|
|
88
67
|
- pillow - supports server gui
|
|
89
68
|
- pyyaml - supports logging
|
|
90
69
|
|
|
91
|
-
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:
|
|
92
71
|
```
|
|
93
72
|
python --version
|
|
94
73
|
```
|
|
@@ -109,7 +88,8 @@ Remote Connection\example_MVDataFile_VISA.py | Simple example showing how to rou
|
|
|
109
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.
|
|
110
89
|
Measuring\example_stabilize.py | Measures the temperature while stabilizing at each temperature.
|
|
111
90
|
Measuring\example_sweep.py | Measures the temperature while sweeping the temperature.
|
|
112
|
-
|
|
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.
|
|
113
93
|
Options\example_resistivity_option.py | Demonstrates how to set up the BRT module bridges for resistivity measurements and how to save the data.
|
|
114
94
|
Options\example_horizontal_rotator.py | Demonstrates how to move the horizontal rotator to a new position.
|
|
115
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```.
|
|
@@ -191,7 +171,7 @@ client.open()
|
|
|
191
171
|
client.close_client()
|
|
192
172
|
# do post-processing once the client has been closed
|
|
193
173
|
```
|
|
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.
|
|
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.
|
|
195
175
|
|
|
196
176
|
The client can also close the server directly using:
|
|
197
177
|
```python
|
|
@@ -239,6 +219,10 @@ The <enum_options> mode is set using the client.temperature.approach_mode enum,
|
|
|
239
219
|
```python
|
|
240
220
|
temperature, status = client.get_temperature()
|
|
241
221
|
```
|
|
222
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
223
|
+
```python
|
|
224
|
+
temperature, rate, approach = client.get_temperature_setpoints()
|
|
225
|
+
```
|
|
242
226
|
|
|
243
227
|
**Field**<a class="anchor" id="field"></a>
|
|
244
228
|
```python
|
|
@@ -260,6 +244,10 @@ The field and status are read back using:
|
|
|
260
244
|
```python
|
|
261
245
|
field, status = client.get_field()
|
|
262
246
|
```
|
|
247
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
248
|
+
```python
|
|
249
|
+
field, rate, approach, driven = client.get_field_setpoints()
|
|
250
|
+
```
|
|
263
251
|
|
|
264
252
|
**Chamber**<a class="anchor" id="chamber"></a>
|
|
265
253
|
```python
|
|
@@ -449,6 +437,12 @@ client = mpv.Client(port=6000)
|
|
|
449
437
|
- A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
|
|
450
438
|
|
|
451
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
|
+
|
|
452
446
|
**3.5.4**
|
|
453
447
|
- June 2025
|
|
454
448
|
- 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
|
-
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:
|
|
43
43
|
```
|
|
44
44
|
python --version
|
|
45
45
|
```
|
|
@@ -60,7 +60,8 @@ 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
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```.
|
|
@@ -142,7 +143,7 @@ client.open()
|
|
|
142
143
|
client.close_client()
|
|
143
144
|
# do post-processing once the client has been closed
|
|
144
145
|
```
|
|
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.
|
|
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.
|
|
146
147
|
|
|
147
148
|
The client can also close the server directly using:
|
|
148
149
|
```python
|
|
@@ -190,6 +191,10 @@ The <enum_options> mode is set using the client.temperature.approach_mode enum,
|
|
|
190
191
|
```python
|
|
191
192
|
temperature, status = client.get_temperature()
|
|
192
193
|
```
|
|
194
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
195
|
+
```python
|
|
196
|
+
temperature, rate, approach = client.get_temperature_setpoints()
|
|
197
|
+
```
|
|
193
198
|
|
|
194
199
|
**Field**<a class="anchor" id="field"></a>
|
|
195
200
|
```python
|
|
@@ -211,6 +216,10 @@ The field and status are read back using:
|
|
|
211
216
|
```python
|
|
212
217
|
field, status = client.get_field()
|
|
213
218
|
```
|
|
219
|
+
One can also retrieve the setpoint, rate, and approach mode:
|
|
220
|
+
```python
|
|
221
|
+
field, rate, approach, driven = client.get_field_setpoints()
|
|
222
|
+
```
|
|
214
223
|
|
|
215
224
|
**Chamber**<a class="anchor" id="chamber"></a>
|
|
216
225
|
```python
|
|
@@ -400,6 +409,12 @@ client = mpv.Client(port=6000)
|
|
|
400
409
|
- A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
|
|
401
410
|
|
|
402
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
|
+
|
|
403
418
|
**3.5.4**
|
|
404
419
|
- June 2025
|
|
405
420
|
- Add the horizontal rotator option for DynaCool, VersaLab, and PPMS.
|
|
@@ -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",
|
|
@@ -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
|
|
|
@@ -401,8 +401,8 @@ class CommandChamberSim(CommandChamberBase,
|
|
|
401
401
|
raise MultiPyVuError(err_msg)
|
|
402
402
|
return 0.0, self.state
|
|
403
403
|
|
|
404
|
-
def _set_state_imp(self, mode:
|
|
405
|
-
self.change_thread = self.get_sim_instance()
|
|
404
|
+
def _set_state_imp(self, mode: modeEnum) -> Union[str, int]:
|
|
405
|
+
self.change_thread: SimulateChamberChange = self.get_sim_instance()
|
|
406
406
|
state_string = STATE_DICT[self.state]
|
|
407
407
|
self.change_thread.set_params('',
|
|
408
408
|
mode,
|
|
@@ -15,7 +15,7 @@ from typing import Dict, List, Tuple, Union
|
|
|
15
15
|
from .check_windows_esc import _check_windows_esc
|
|
16
16
|
from .exceptions import MultiPyVuError
|
|
17
17
|
from .ICommand import (ICommand, ICommandImp, ICommandObserverSim,
|
|
18
|
-
ISimulateChange, catch_thread_error)
|
|
18
|
+
ISimulateChange, catch_thread_error, floats_equal)
|
|
19
19
|
from .IEventManager import IObserver
|
|
20
20
|
from .project_vars import CLOCK_TIME
|
|
21
21
|
|
|
@@ -72,12 +72,14 @@ class CommandFieldBase(ICommand):
|
|
|
72
72
|
_current_val: float = 0.0
|
|
73
73
|
_rate: float = 1
|
|
74
74
|
_state: int = 1
|
|
75
|
-
_approach:
|
|
76
|
-
_driven = drivenEnum.driven
|
|
75
|
+
_approach: ApproachEnum = ApproachEnum.no_overshoot
|
|
76
|
+
_driven: drivenEnum = drivenEnum.driven
|
|
77
77
|
|
|
78
78
|
def __init__(self, instrument_name: str):
|
|
79
79
|
super().__init__()
|
|
80
80
|
self.instrument_name = instrument_name
|
|
81
|
+
self.approach_mode = ApproachEnum
|
|
82
|
+
self.drive_mode = drivenEnum
|
|
81
83
|
|
|
82
84
|
self.units = units
|
|
83
85
|
|
|
@@ -114,24 +116,24 @@ class CommandFieldBase(ICommand):
|
|
|
114
116
|
CommandFieldBase._state = new
|
|
115
117
|
|
|
116
118
|
@property
|
|
117
|
-
def
|
|
119
|
+
def approach(self) -> ApproachEnum:
|
|
118
120
|
return CommandFieldBase._approach
|
|
119
121
|
|
|
120
|
-
@
|
|
121
|
-
def
|
|
122
|
+
@approach.setter
|
|
123
|
+
def approach(self, new):
|
|
122
124
|
CommandFieldBase._approach = new
|
|
123
125
|
|
|
124
126
|
@property
|
|
125
|
-
def
|
|
127
|
+
def driven(self) -> drivenEnum:
|
|
126
128
|
return CommandFieldBase._driven
|
|
127
129
|
|
|
128
|
-
@
|
|
129
|
-
def
|
|
130
|
+
@driven.setter
|
|
131
|
+
def driven(self, new: drivenEnum):
|
|
130
132
|
CommandFieldBase._driven = new
|
|
131
133
|
|
|
132
134
|
def convert_result(self, response: Dict[str, str]) -> Tuple[float, str]:
|
|
133
135
|
"""
|
|
134
|
-
Converts the CommandMultiVu response from
|
|
136
|
+
Converts the CommandMultiVu response from get_state_server()
|
|
135
137
|
to something usable for the user.
|
|
136
138
|
|
|
137
139
|
Parameters:
|
|
@@ -193,8 +195,8 @@ class CommandFieldBase(ICommand):
|
|
|
193
195
|
def _set_state_imp(self,
|
|
194
196
|
field: float,
|
|
195
197
|
set_rate_per_sec: float,
|
|
196
|
-
set_approach:
|
|
197
|
-
set_driven:
|
|
198
|
+
set_approach: ApproachEnum,
|
|
199
|
+
set_driven: drivenEnum,
|
|
198
200
|
) -> Union[str, int]:
|
|
199
201
|
raise NotImplementedError
|
|
200
202
|
|
|
@@ -211,26 +213,30 @@ class CommandFieldBase(ICommand):
|
|
|
211
213
|
field = float(field)
|
|
212
214
|
set_rate_per_sec = float(rate)
|
|
213
215
|
set_approach = int(approach)
|
|
214
|
-
|
|
215
|
-
if
|
|
216
|
-
err_msg = f'The approach, {
|
|
217
|
-
err_msg += 'one of the following:'
|
|
216
|
+
set_approach_number = int(approach)
|
|
217
|
+
if set_approach_number > len(ApproachEnum) - 1:
|
|
218
|
+
err_msg = f'The approach, {set_approach_number}, is out of bounds.'
|
|
219
|
+
err_msg += ' Must be one of the following:'
|
|
218
220
|
for mode in ApproachEnum:
|
|
219
|
-
|
|
221
|
+
err_msg += f'\n\t{mode.value}: {mode.name}'
|
|
220
222
|
raise MultiPyVuError(err_msg)
|
|
223
|
+
set_approach = ApproachEnum(set_approach_number)
|
|
221
224
|
|
|
225
|
+
set_driven_number = int(driven)
|
|
222
226
|
if self.instrument_name != 'PPMS':
|
|
227
|
+
set_driven = drivenEnum(set_driven_number)
|
|
223
228
|
if set_driven == drivenEnum.persistent:
|
|
224
229
|
err_msg = f'{self.instrument_name} can only drive the magnet '
|
|
225
230
|
err_msg += 'in driven mode.'
|
|
226
231
|
raise MultiPyVuError(err_msg)
|
|
227
232
|
else:
|
|
228
|
-
if
|
|
229
|
-
err_msg = f'The mode, {
|
|
230
|
-
err_msg += 'one of the following:'
|
|
233
|
+
if set_driven_number > len(drivenEnum) - 1:
|
|
234
|
+
err_msg = f'The driven mode, {set_driven_number}, is out of '
|
|
235
|
+
err_msg += 'bounds. Must be one of the following:'
|
|
231
236
|
for mode in drivenEnum:
|
|
232
237
|
err_msg += f'\n\t{mode.value}: {mode.name}'
|
|
233
238
|
raise MultiPyVuError(err_msg)
|
|
239
|
+
set_driven = drivenEnum(set_driven_number)
|
|
234
240
|
if self.instrument_name == 'VERSALAB':
|
|
235
241
|
if set_approach == ApproachEnum.no_overshoot:
|
|
236
242
|
err_msg = f'{self.instrument_name} does not support the '
|
|
@@ -266,7 +272,10 @@ class CommandFieldImp(ICommandImp, CommandFieldBase):
|
|
|
266
272
|
CommandFieldBase.__init__(self, instrument_name)
|
|
267
273
|
self._mvu = multivu_win32com
|
|
268
274
|
|
|
269
|
-
def get_state_server(self,
|
|
275
|
+
def get_state_server(self,
|
|
276
|
+
value_variant,
|
|
277
|
+
state_variant,
|
|
278
|
+
params='') -> Tuple[float, int]:
|
|
270
279
|
"""
|
|
271
280
|
Retrieves information from MultiVu
|
|
272
281
|
|
|
@@ -297,8 +306,8 @@ class CommandFieldImp(ICommandImp, CommandFieldBase):
|
|
|
297
306
|
def _set_state_imp(self,
|
|
298
307
|
field: float,
|
|
299
308
|
set_rate_per_sec: float,
|
|
300
|
-
set_approach:
|
|
301
|
-
set_driven:
|
|
309
|
+
set_approach: ApproachEnum,
|
|
310
|
+
set_driven: drivenEnum
|
|
302
311
|
) -> Union[str, int]:
|
|
303
312
|
can_error = self._mvu.setField(field,
|
|
304
313
|
set_rate_per_sec,
|
|
@@ -307,17 +316,16 @@ class CommandFieldImp(ICommandImp, CommandFieldBase):
|
|
|
307
316
|
)
|
|
308
317
|
self.set_point = field
|
|
309
318
|
self.rate = set_rate_per_sec
|
|
310
|
-
self.
|
|
311
|
-
self.
|
|
319
|
+
self.approach = set_approach
|
|
320
|
+
self.driven = drivenEnum(set_driven)
|
|
312
321
|
|
|
322
|
+
if can_error > 1:
|
|
323
|
+
raise MultiPyVuError('Error when calling SetField()')
|
|
324
|
+
# It is odd that sometimes a can_error of 1 is okay. So far I have
|
|
325
|
+
# only seen this behavior with a few flavors.
|
|
313
326
|
if self.instrument_name in ('PPMS', 'MPMS3'):
|
|
314
|
-
if can_error > 1:
|
|
315
|
-
raise MultiPyVuError('Error when calling SetField()')
|
|
316
|
-
else:
|
|
317
327
|
# returning this string makes CommandMultiVu_base happy
|
|
318
328
|
return 'Call was successful'
|
|
319
|
-
elif can_error > 0:
|
|
320
|
-
raise MultiPyVuError('Error when calling SetField()')
|
|
321
329
|
return can_error
|
|
322
330
|
|
|
323
331
|
def test(self) -> bool:
|
|
@@ -335,12 +343,12 @@ class CommandFieldImp(ICommandImp, CommandFieldBase):
|
|
|
335
343
|
steady = False
|
|
336
344
|
self._get_values()
|
|
337
345
|
state_name = self.convert_state_dictionary(self.state)
|
|
338
|
-
if state_name
|
|
339
|
-
steady =
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
346
|
+
if state_name in ('Holding (driven)', 'Stable'):
|
|
347
|
+
steady = floats_equal(self.current_val,
|
|
348
|
+
self.set_point,
|
|
349
|
+
accept_pct,
|
|
350
|
+
abs_tol,
|
|
351
|
+
)
|
|
344
352
|
return steady
|
|
345
353
|
|
|
346
354
|
|
|
@@ -434,7 +442,7 @@ class SimulateFieldChange(ISimulateChange):
|
|
|
434
442
|
|
|
435
443
|
# set state to ramping
|
|
436
444
|
start_time = time.time()
|
|
437
|
-
self.state = STATE_DICT[
|
|
445
|
+
self.state = STATE_DICT[6]
|
|
438
446
|
self.notify_observers(self.current_val, self.state)
|
|
439
447
|
|
|
440
448
|
# simulate the ramp
|
|
@@ -500,20 +508,22 @@ class CommandFieldSim(CommandFieldBase,
|
|
|
500
508
|
def _set_state_imp(self,
|
|
501
509
|
field: float,
|
|
502
510
|
set_rate_per_sec: float,
|
|
503
|
-
set_approach:
|
|
504
|
-
set_driven:
|
|
511
|
+
set_approach: ApproachEnum,
|
|
512
|
+
set_driven: drivenEnum
|
|
505
513
|
) -> Union[str, int]:
|
|
506
|
-
self.change_thread = self.get_sim_instance()
|
|
514
|
+
self.change_thread: SimulateFieldChange = self.get_sim_instance()
|
|
507
515
|
state_string = STATE_DICT[self.state]
|
|
508
516
|
self.change_thread.set_params(self.current_val,
|
|
509
517
|
field,
|
|
510
518
|
set_rate_per_sec,
|
|
511
519
|
state_string,
|
|
512
520
|
)
|
|
513
|
-
self.
|
|
521
|
+
self.set_point = field
|
|
522
|
+
self.rate = set_rate_per_sec
|
|
523
|
+
self.approach = set_approach
|
|
514
524
|
self.change_thread.approach = set_approach
|
|
515
|
-
self.
|
|
516
|
-
self.change_thread.driven_mode = self.
|
|
525
|
+
self.driven = set_driven
|
|
526
|
+
self.change_thread.driven_mode = self.driven
|
|
517
527
|
|
|
518
528
|
self.change_thread.subscribe(self)
|
|
519
529
|
self.change_thread.start()
|