MultiPyVu 2.1.2__tar.gz → 2.2.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 (53) hide show
  1. {MultiPyVu-2.1.2/src/MultiPyVu.egg-info → MultiPyVu-2.2.0}/PKG-INFO +14 -13
  2. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/README.md +13 -9
  3. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/setup.py +0 -3
  4. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandChamber.py +23 -14
  5. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandField.py +15 -6
  6. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandMultiVu_base.py +2 -6
  7. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandTemperature.py +20 -9
  8. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/Command_factory.py +4 -3
  9. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuClient_base.py +2 -0
  10. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuServer.py +10 -2
  11. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/__version.py +1 -1
  12. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/instrument.py +33 -35
  13. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0/src/MultiPyVu.egg-info}/PKG-INFO +14 -13
  14. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu.egg-info/SOURCES.txt +0 -1
  15. MultiPyVu-2.1.2/src/MultiPyVu.egg-info/requires.txt +0 -3
  16. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/LICENSE +0 -0
  17. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/pyproject.toml +0 -0
  18. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/setup.cfg +0 -0
  19. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/BRT.py +0 -0
  20. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandMultiVu_imp.py +0 -0
  21. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandMultiVu_sim.py +0 -0
  22. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandSdo.py +0 -0
  23. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/Controller.py +0 -0
  24. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/ICommand.py +0 -0
  25. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/IController.py +0 -0
  26. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/IView.py +0 -0
  27. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuClient.py +0 -0
  28. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuDataFile/MultiVuDataFile.py +0 -0
  29. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuDataFile/__init__.py +0 -0
  30. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuDataFile/__version.py +0 -0
  31. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuDataFile/is_pathname_valid.py +0 -0
  32. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/ParseInputs.py +0 -0
  33. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/ServerEventManager.py +0 -0
  34. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/SocketMessage.py +0 -0
  35. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/SocketMessageClient.py +0 -0
  36. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/SocketMessageServer.py +0 -0
  37. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/ViewFactory.py +0 -0
  38. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/ViewTk.py +0 -0
  39. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/__init__.py +0 -0
  40. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/__main__.py +0 -0
  41. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/create_logger.py +0 -0
  42. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/exceptions.py +0 -0
  43. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/font/Play-Bold.ttf +0 -0
  44. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/font/Play-Regular.ttf +0 -0
  45. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/generate_sdo_objects.py +0 -0
  46. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/images/Q.png +0 -0
  47. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/images/QD_logo.jpg +0 -0
  48. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/project_vars.py +0 -0
  49. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/scripts/whats_my_ip_address.cmd +0 -0
  50. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu/sdo_object.py +0 -0
  51. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu.egg-info/dependency_links.txt +0 -0
  52. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiPyVu.egg-info/top_level.txt +0 -0
  53. {MultiPyVu-2.1.2 → MultiPyVu-2.2.0}/src/MultiVuDataFile/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: MultiPyVu
3
- Version: 2.1.2
3
+ Version: 2.2.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>
@@ -38,9 +38,6 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
38
38
  Requires-Python: >=3.8
39
39
  Description-Content-Type: text/markdown
40
40
  License-File: LICENSE
41
- Requires-Dist: pandas
42
- Requires-Dist: pywin32>=300
43
- Requires-Dist: pillow
44
41
 
45
42
  ![qd_logo](https://qdusa.com/images/QD_logo.png)
46
43
  # MultiPyVu
@@ -90,13 +87,13 @@ pip install update MultiPyVu
90
87
  Several examples have been uploaded to [Quantum Design's Pharos database](https://www.qdusa.com/pharos/view.php?fDocumentId=4339) as well as [GitHub](https://github.com/qdusa/MultiPyVu/tree/master/PharosExamples/). These examples demonstrate various capabilities of the module, and serve as templates upon which users can add their own code to integrate external hardware operations with the environmental controls of the Quantum Design instrument.
91
88
  | Filename | Description|
92
89
  -----|-----
93
- example_Local.py | A simple script which starts the server, then the client, on the PC running MultiVu. It relays instrument parameters and status to demonstrate communication, serving as a minimum working example useful for testing basic functionality.
94
- example_Remote-Server.py | For remote operation; this script must be running on the on the control PC along with the MultiVu executable.
95
- example_Remote-Client.py | For remote operation; this script runs on a separate PC and relays instrument parameters and status to demonstration communication.
96
- example_Command-Demos.py | Utilizes most functions of the module, setting temperature/field/chamber operations, reading back the values and status of those parameters, and waiting for stability conditions to be met. As-written, it runs in local mode.
97
- example_MVDataFile-VISA.py | Simple example showing how to route environmental parameters and data from external instruments into a single MultiVu-readable *.dat* file. As-written, it runs in local mode.
90
+ example_local.py | A simple script which starts the server, then the client, on the PC running MultiVu. It relays instrument parameters and status to demonstrate communication, serving as a minimum working example useful for testing basic functionality.
91
+ example_remote_server.py | For remote operation; this script must be running on the on the control PC along with the MultiVu executable.
92
+ example_remote_client.py | For remote operation; this script runs on a separate PC and relays instrument parameters and status to demonstration communication.
93
+ example_command_demos.py | Utilizes most functions of the module, setting temperature/field/chamber operations, reading back the values and status of those parameters, and waiting for stability conditions to be met. As-written, it runs in local mode.
94
+ example_MVDataFile_VISA.py | Simple example showing how to route environmental parameters and data from external instruments into a single MultiVu-readable *.dat* file. As-written, it runs in local mode.
98
95
  example_graph_dat.py | Script showing how to read a MultiVu *.dat* file into a Pandas DataFrame.
99
- 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.
96
+ 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```.
100
97
 
101
98
  ### Getting Started<a class="anchor" id="getting-started"></a>
102
99
  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.
@@ -297,8 +294,6 @@ Once configured, MultiPyVu gives access to the following commands:
297
294
  client.resistivity.get_resistance(bridge_number)
298
295
  client.resistivity.get_current(bridge_number)
299
296
  ```
300
- We also support reading back the temperature of the rotator thermometer. This reads off the calibration table of the resistor on the horizontal rotator that is programed onto the SROM of your BRT module. The rotator requires an extra connector that routes the thermometer to channel 1, channel 2 to be the new channel 1 and channel 3 to be the new channel 2. As such this command will only give a meaningful result with the horizontal rotator installed:
301
- ```client.resistivity.get_temperature()```
302
297
 
303
298
  ### Saving & Opening a MultiVu Data File<a class="anchor" id="save"></a>
304
299
  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.
@@ -388,7 +383,13 @@ client = mpv.Client(port=6000)
388
383
  - A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
389
384
 
390
385
  ## Changelog<a class="anchor" id="changelog"></a>
391
- **2.1.0**
386
+ **2.2.0**
387
+ - January 2024
388
+ - Corrected a bug that prevented the Server from recognizing PPMS and MPMS3 MultiVu flavors
389
+ - Log the version number when the Client connects to the Server
390
+ - Remove unwanted warnings when quitting the Server using the esc-key.
391
+
392
+ **2.1.4**
392
393
  - October 2023
393
394
  - Import full module as MultiPyVu. Instead of loading the three sub-modules as:
394
395
  ```python
@@ -46,13 +46,13 @@ pip install update MultiPyVu
46
46
  Several examples have been uploaded to [Quantum Design's Pharos database](https://www.qdusa.com/pharos/view.php?fDocumentId=4339) as well as [GitHub](https://github.com/qdusa/MultiPyVu/tree/master/PharosExamples/). These examples demonstrate various capabilities of the module, and serve as templates upon which users can add their own code to integrate external hardware operations with the environmental controls of the Quantum Design instrument.
47
47
  | Filename | Description|
48
48
  -----|-----
49
- example_Local.py | A simple script which starts the server, then the client, on the PC running MultiVu. It relays instrument parameters and status to demonstrate communication, serving as a minimum working example useful for testing basic functionality.
50
- example_Remote-Server.py | For remote operation; this script must be running on the on the control PC along with the MultiVu executable.
51
- example_Remote-Client.py | For remote operation; this script runs on a separate PC and relays instrument parameters and status to demonstration communication.
52
- example_Command-Demos.py | Utilizes most functions of the module, setting temperature/field/chamber operations, reading back the values and status of those parameters, and waiting for stability conditions to be met. As-written, it runs in local mode.
53
- example_MVDataFile-VISA.py | Simple example showing how to route environmental parameters and data from external instruments into a single MultiVu-readable *.dat* file. As-written, it runs in local mode.
49
+ example_local.py | A simple script which starts the server, then the client, on the PC running MultiVu. It relays instrument parameters and status to demonstrate communication, serving as a minimum working example useful for testing basic functionality.
50
+ example_remote_server.py | For remote operation; this script must be running on the on the control PC along with the MultiVu executable.
51
+ example_remote_client.py | For remote operation; this script runs on a separate PC and relays instrument parameters and status to demonstration communication.
52
+ example_command_demos.py | Utilizes most functions of the module, setting temperature/field/chamber operations, reading back the values and status of those parameters, and waiting for stability conditions to be met. As-written, it runs in local mode.
53
+ example_MVDataFile_VISA.py | Simple example showing how to route environmental parameters and data from external instruments into a single MultiVu-readable *.dat* file. As-written, it runs in local mode.
54
54
  example_graph_dat.py | Script showing how to read a MultiVu *.dat* file into a Pandas DataFrame.
55
- 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.
55
+ 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```.
56
56
 
57
57
  ### Getting Started<a class="anchor" id="getting-started"></a>
58
58
  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.
@@ -253,8 +253,6 @@ Once configured, MultiPyVu gives access to the following commands:
253
253
  client.resistivity.get_resistance(bridge_number)
254
254
  client.resistivity.get_current(bridge_number)
255
255
  ```
256
- We also support reading back the temperature of the rotator thermometer. This reads off the calibration table of the resistor on the horizontal rotator that is programed onto the SROM of your BRT module. The rotator requires an extra connector that routes the thermometer to channel 1, channel 2 to be the new channel 1 and channel 3 to be the new channel 2. As such this command will only give a meaningful result with the horizontal rotator installed:
257
- ```client.resistivity.get_temperature()```
258
256
 
259
257
  ### Saving & Opening a MultiVu Data File<a class="anchor" id="save"></a>
260
258
  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.
@@ -344,7 +342,13 @@ client = mpv.Client(port=6000)
344
342
  - A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
345
343
 
346
344
  ## Changelog<a class="anchor" id="changelog"></a>
347
- **2.1.0**
345
+ **2.2.0**
346
+ - January 2024
347
+ - Corrected a bug that prevented the Server from recognizing PPMS and MPMS3 MultiVu flavors
348
+ - Log the version number when the Client connects to the Server
349
+ - Remove unwanted warnings when quitting the Server using the esc-key.
350
+
351
+ **2.1.4**
348
352
  - October 2023
349
353
  - Import full module as MultiPyVu. Instead of loading the three sub-modules as:
350
354
  ```python
@@ -53,9 +53,6 @@ setup(
53
53
  python_requires=">=3.8",
54
54
  dependencies=[
55
55
  "typing",
56
- "pywin32>=300",
57
- ],
58
- install_requires=[
59
56
  "pandas",
60
57
  "pywin32>=300",
61
58
  "pillow",
@@ -48,7 +48,7 @@ class CommandChamberBase(ICommand):
48
48
  self.instrument_name = instrument_name
49
49
 
50
50
  # State code dictionary
51
- self.__state_dictionary = {
51
+ self._state_dictionary = {
52
52
  0: 'Unknown',
53
53
  1: 'Purged and Sealed',
54
54
  2: 'Vented and Sealed',
@@ -71,22 +71,22 @@ class CommandChamberBase(ICommand):
71
71
  mode_setting: IntEnum,
72
72
  mode_readback):
73
73
  if mode_setting == self.mode.seal:
74
- returnTrue = [self.__state_dictionary[1],
75
- self.__state_dictionary[2],
76
- self.__state_dictionary[3],
74
+ returnTrue = [self._state_dictionary[1],
75
+ self._state_dictionary[2],
76
+ self._state_dictionary[3],
77
77
  ]
78
78
  if mode_readback in returnTrue:
79
79
  return True
80
80
  elif mode_setting == self.mode.purge_seal:
81
- return (mode_readback == self.__state_dictionary[1])
81
+ return (mode_readback == self._state_dictionary[1])
82
82
  elif mode_setting == self.mode.vent_seal:
83
- return (mode_readback == self.__state_dictionary[2])
83
+ return (mode_readback == self._state_dictionary[2])
84
84
  elif mode_setting == self.mode.pump_continuous:
85
- return (mode_readback == self.__state_dictionary[8])
85
+ return (mode_readback == self._state_dictionary[8])
86
86
  elif mode_setting == self.mode.vent_continuous:
87
- return (mode_readback == self.__state_dictionary[9])
87
+ return (mode_readback == self._state_dictionary[9])
88
88
  elif mode_setting == self.mode.high_vacuum:
89
- return (mode_readback == self.__state_dictionary[7])
89
+ return (mode_readback == self._state_dictionary[7])
90
90
 
91
91
  def convert_result(self, response: Dict) -> Tuple:
92
92
  '''
@@ -121,7 +121,10 @@ class CommandChamberBase(ICommand):
121
121
  return f'{mode_as_int}'
122
122
 
123
123
  def convert_state_dictionary(self, status_number):
124
- return self.__state_dictionary[status_number]
124
+ if isinstance(status_number, str):
125
+ return status_number
126
+ else:
127
+ return self._state_dictionary[status_number]
125
128
 
126
129
  @abstractmethod
127
130
  def get_state_server(self, value_variant, state_variant, params=''):
@@ -148,7 +151,7 @@ class CommandChamberBase(ICommand):
148
151
  return self.set_state_server_imp(set_mode)
149
152
 
150
153
  def state_code_dict(self):
151
- return self.__state_dictionary
154
+ return self._state_dictionary
152
155
 
153
156
 
154
157
  ############################
@@ -181,10 +184,16 @@ class CommandChamberImp(CommandChamberBase):
181
184
  return '', return_state
182
185
 
183
186
  def set_state_server_imp(self, mode: int) -> Union[str, int]:
184
- error = self._mvu.SetChamber(mode)
185
- if error > 0:
187
+ can_error = self._mvu.SetChamber(mode)
188
+ if self.instrument_name == 'PPMS':
189
+ if can_error > 1:
190
+ raise MultiPyVuError('Error when calling SetChamber()')
191
+ else:
192
+ # returning this string makes CommandMultiVu_base happy
193
+ return 'Call was successful'
194
+ elif can_error > 0:
186
195
  raise MultiPyVuError('Error when calling SetChamber()')
187
- return error
196
+ return can_error
188
197
 
189
198
 
190
199
  ############################
@@ -58,7 +58,7 @@ class CommandFieldBase(ICommand):
58
58
  self.instrument_name = instrument_name
59
59
 
60
60
  # Field state code dictionary
61
- self.__state_dictionary = {
61
+ self._state_dictionary = {
62
62
  1: 'Stable',
63
63
  2: 'Switch Warming',
64
64
  3: 'Switch Cooling',
@@ -131,7 +131,10 @@ class CommandFieldBase(ICommand):
131
131
  return f'{set_point},{rate_per_sec},{approach.value},{mode}'
132
132
 
133
133
  def convert_state_dictionary(self, status_number):
134
- return self.__state_dictionary[status_number]
134
+ if isinstance(status_number, str):
135
+ return status_number
136
+ else:
137
+ return self._state_dictionary[status_number]
135
138
 
136
139
  @abstractmethod
137
140
  def get_state_server(self, value_variant, state_variant, params=''):
@@ -193,7 +196,7 @@ class CommandFieldBase(ICommand):
193
196
  return error
194
197
 
195
198
  def state_code_dict(self):
196
- return self.__state_dictionary
199
+ return self._state_dictionary
197
200
 
198
201
 
199
202
  ############################
@@ -240,14 +243,20 @@ class CommandFieldImp(CommandFieldBase):
240
243
  set_driven: int
241
244
  ) -> Union[str, int]:
242
245
  try:
243
- error = self._mvu.setField(field,
246
+ can_error = self._mvu.setField(field,
244
247
  set_rate_per_sec,
245
248
  set_approach,
246
249
  set_driven
247
250
  )
248
- if error > 0:
251
+ if self.instrument_name == 'PPMS':
252
+ if can_error > 1:
253
+ raise MultiPyVuError('Error when calling SetField()')
254
+ else:
255
+ # returning this string makes CommandMultiVu_base happy
256
+ return 'Call was successful'
257
+ elif can_error > 0:
249
258
  raise MultiPyVuError('Error when calling SetField()')
250
- return error
259
+ return can_error
251
260
  except AttributeError:
252
261
  # this will raise a pywin_com_error if it is bad
253
262
  return str(self._mvu)
@@ -67,7 +67,7 @@ class CommandMultiVuBase():
67
67
  result_string = result if type(result) == str else f'{result:.4f}'
68
68
  return f'{result_string},{mv_command.units},{code_in_words}'
69
69
 
70
- def set_state(self, command, arg_string) -> str:
70
+ def set_state(self, command, arg_string):
71
71
  '''
72
72
  Sets the state for a given command using the arg_string for parameters
73
73
 
@@ -82,10 +82,6 @@ class CommandMultiVuBase():
82
82
  FIELD: set point, rate, approach, and magnetic state.
83
83
  CHAMBER: mode
84
84
 
85
- Returns:
86
- --------
87
- str: Error message
88
-
89
85
  Raises
90
86
  ------
91
87
  MultiVuExeException
@@ -105,7 +101,7 @@ class CommandMultiVuBase():
105
101
  msg = f'Error when setting the {command} {arg_string}: '
106
102
  msg += f'error = {err}'
107
103
  raise MultiPyVuError(msg)
108
-
104
+
109
105
  if isinstance(err, str):
110
106
  can_error_msg = mv_command.convert_state_dictionary(err)
111
107
  if can_error_msg == 'Call was successful':
@@ -44,7 +44,7 @@ class CommandTemperatureBase(ICommand):
44
44
  super().__init__()
45
45
 
46
46
  # Temperature state code dictionary
47
- self.__state_dictionary = {
47
+ self._state_dictionary = {
48
48
  1: "Stable",
49
49
  2: "Tracking",
50
50
  5: "Near",
@@ -108,10 +108,13 @@ class CommandTemperatureBase(ICommand):
108
108
  return f'{set_point},{rate_per_minute},{approach_mode.value}'
109
109
 
110
110
  def convert_state_dictionary(self, status_number):
111
- return self.__state_dictionary[status_number]
111
+ if isinstance(status_number, str):
112
+ return status_number
113
+ else:
114
+ return self._state_dictionary[status_number]
112
115
 
113
116
  def state_code_dict(self):
114
- return self.__state_dictionary
117
+ return self._state_dictionary
115
118
 
116
119
  @abstractmethod
117
120
  def get_state_server(self, arg_string: str) -> Union[str, int]:
@@ -160,18 +163,20 @@ class CommandTemperatureBase(ICommand):
160
163
  ############################
161
164
 
162
165
  class CommandTemperatureImp(CommandTemperatureBase):
163
- def __init__(self, multivu_win32com):
166
+ def __init__(self, multivu_win32com, instrument_name):
164
167
  '''
165
168
  Parameters:
166
169
  ----------
167
170
  multivu_win32com: Union[win32.dynamic.CDispatch, None]
171
+ mvu_flavor: str
168
172
  '''
169
173
  super().__init__()
170
174
  self._mvu = multivu_win32com
175
+ self.instrument_name = instrument_name
171
176
 
172
177
  def get_state_server(self, value_variant, state_variant, params=''):
173
- error = self._mvu.GetTemperature(value_variant, state_variant)
174
- if error > 0:
178
+ can_error = self._mvu.GetTemperature(value_variant, state_variant)
179
+ if can_error > 0:
175
180
  raise MultiPyVuError('Error when calling GetTemperature()')
176
181
  temperature = value_variant.value
177
182
  return_state = int(state_variant.value)
@@ -184,15 +189,21 @@ class CommandTemperatureImp(CommandTemperatureBase):
184
189
  set_approach: int
185
190
  ) -> Union[str, int]:
186
191
  try:
187
- error = self._mvu.SetTemperature(temperature,
192
+ can_error = self._mvu.SetTemperature(temperature,
188
193
  set_rate_per_min,
189
194
  set_approach)
190
195
  except pywin_com_error:
191
196
  raise MultiPyVuError('No pywin32 connection to MultiVu. Is MultiVu running?')
192
197
  else:
193
- if error > 0:
198
+ if self.instrument_name == 'PPMS':
199
+ if can_error > 1:
200
+ raise MultiPyVuError('Error when calling SetTemperature()')
201
+ else:
202
+ # returning this string makes CommandMultiVu_base happy
203
+ return 'Call was successful'
204
+ elif can_error > 0:
194
205
  raise MultiPyVuError('Error when calling SetTemperature()')
195
- return error
206
+ return can_error
196
207
 
197
208
 
198
209
  ############################
@@ -30,7 +30,7 @@ def create_command_mv(mvu_flavor, win32_dispatch=None):
30
30
  A CommandMultiVu object. If win32_dispatch is None, it returns
31
31
  a simulated object.
32
32
  '''
33
- cmd_dict = {'TEMP': create_command_temp(win32_dispatch),
33
+ cmd_dict = {'TEMP': create_command_temp(win32_dispatch, mvu_flavor),
34
34
  'FIELD': create_command_field(win32_dispatch, mvu_flavor),
35
35
  'CHAMBER': create_command_chamber(win32_dispatch, mvu_flavor),
36
36
  'SDO': create_command_sdo(win32_dispatch),
@@ -42,7 +42,8 @@ def create_command_mv(mvu_flavor, win32_dispatch=None):
42
42
 
43
43
 
44
44
  def create_command_temp(
45
- win32_dispatch=None
45
+ win32_dispatch=None,
46
+ mvu_flavor=''
46
47
  ) -> Union[temperature.CommandTemperatureSim,
47
48
  temperature.CommandTemperatureImp]:
48
49
  '''
@@ -61,7 +62,7 @@ def create_command_temp(
61
62
  if win32_dispatch is None:
62
63
  return temperature.CommandTemperatureSim()
63
64
  else:
64
- return temperature.CommandTemperatureImp(win32_dispatch)
65
+ return temperature.CommandTemperatureImp(win32_dispatch, mvu_flavor)
65
66
 
66
67
 
67
68
  def create_command_field(
@@ -31,6 +31,7 @@ from .exceptions import (MultiPyVuError,
31
31
  ServerCloseError,
32
32
  SocketError
33
33
  )
34
+ from .__version import __version__ as mpv_version
34
35
 
35
36
  if sys.platform == 'win32':
36
37
  import msvcrt # Used to help detect the esc-key
@@ -88,6 +89,7 @@ class ClientBase():
88
89
  self.logger.info(response['result'])
89
90
  self._instr = self._message.instr
90
91
  self.instrument_name = self._message.instr.name
92
+ self.logger.debug(f'MultiPyVu Version: {mpv_version}')
91
93
  return self
92
94
 
93
95
  def __exit__(self, exc_type, exc_value, exc_traceback) -> bool:
@@ -45,6 +45,14 @@ def catch_thread_error(func):
45
45
  def error_handler(*args, **kwargs):
46
46
  try:
47
47
  func(*args, **kwargs)
48
+ # ignore the errors handled in _exit()
49
+ except (
50
+ KeyboardInterrupt,
51
+ MultiPyVuError,
52
+ UserWarning,
53
+ ClientCloseError
54
+ ) as e:
55
+ raise e
48
56
  except BaseException:
49
57
  name = threading.current_thread().name
50
58
  msg = f'Exception in thread \'{name}\' '
@@ -188,8 +196,8 @@ class Server(Subject):
188
196
  def __enter__(self):
189
197
  try:
190
198
  sel = self.config_sock()
191
- except OSError as e:
192
- # invalide connection, so return None
199
+ except OSError:
200
+ # invalid connection, so return None
193
201
  return None
194
202
  quit_keys = "ctrl-c"
195
203
  if sys.platform == 'win32':
@@ -1,2 +1,2 @@
1
1
  # -*- coding: utf-8 -*-
2
- __version__ = "2.1.2"
2
+ __version__ = "2.2.0"
@@ -14,6 +14,7 @@ import time
14
14
  import re
15
15
  import logging
16
16
  from enum import Enum, auto
17
+ from typing import Tuple
17
18
 
18
19
  from .Command_factory import create_command_mv
19
20
  from .project_vars import SERVER_NAME, PYWIN32_VERSION, MIN_PYWIN32_VERSION
@@ -108,14 +109,14 @@ class Instrument():
108
109
  self.multi_vu = None
109
110
  self._connect_to_MultiVu(self.name)
110
111
 
111
- def _get_exe(self, inst: str) -> str:
112
+ def _exe_to_common_name(self, exe_name: str) -> str:
112
113
  '''
113
- Returns the name of the MultiVu exe.
114
+ Returns the common name of the MultiVu flavor.
114
115
 
115
116
  Parameters
116
117
  ----------
117
- inst : str
118
- The name of the MultiVu flavor.
118
+ exe_name : str
119
+ The name of the MultiVu flavor executable.
119
120
 
120
121
  Returns
121
122
  -------
@@ -123,17 +124,18 @@ class Instrument():
123
124
  A string of the specific MultiVu flavor .exe
124
125
 
125
126
  '''
126
- if inst.upper() == InstrumentList.PPMS.name:
127
- name = inst.capitalize() + 'Mvu'
128
- elif inst.upper() == InstrumentList.MPMS3.name:
129
- name = 'SquidVsm'
130
- elif inst.upper() == InstrumentList.VERSALAB.name:
131
- name = 'VersaLab'
132
- elif inst.upper() == InstrumentList.OPTICOOL.name:
133
- name = 'OptiCool'
127
+ if exe_name.capitalize() == 'PpmsMvu.exe'.capitalize():
128
+ name = InstrumentList.PPMS.name
129
+ elif exe_name.capitalize() == 'SquidVsm.exe'.capitalize():
130
+ name = InstrumentList.MPMS3.name
131
+ elif exe_name.capitalize() == 'VersaLab.exe'.capitalize():
132
+ name = InstrumentList.VERSALAB.name
133
+ elif exe_name.capitalize() == 'OptiCool.exe'.capitalize():
134
+ name = InstrumentList.OPTICOOL.name
135
+ elif exe_name.capitalize() == 'DynaCool.exe'.capitalize():
136
+ name = InstrumentList.DYNACOOL.name
134
137
  else:
135
- name = inst.capitalize()
136
- name += '.exe'
138
+ raise ValueError(f'{exe_name} is not a recognized executable name')
137
139
  return name
138
140
 
139
141
  def _get_class_id(self, inst: str) -> str:
@@ -179,29 +181,28 @@ class Instrument():
179
181
  err_msg += 'the MultiVu flavor.'
180
182
  raise MultiPyVuError(err_msg)
181
183
 
182
- detected_name = self.detect_multivu()
183
- if detected_name != instrument_name:
184
+ self.name, self.exe_name = self.detect_multivu()
185
+ if self.name != instrument_name:
184
186
  if instrument_name == '':
185
- msg = f'Found {detected_name} running.'
187
+ msg = f'Found {self.name} running.'
186
188
  self.logger.info(msg)
187
189
  msg = f'MultiPyVu Version: {mpv_version}'
188
190
  self.logger.debug(msg)
189
191
  else:
190
192
  msg = f'User specified {instrument_name}, but detected '
191
- msg += f'{detected_name} running. Either leave out a '
193
+ msg += f'{self.name} running. Either leave out a '
192
194
  msg += 'specific MultiVu flavor and use the detected '
193
195
  msg += 'one, or have the specified flavor match the '
194
196
  msg += 'running instance.'
195
197
  raise ValueError(msg)
196
- self.name = detected_name
197
- self.exe_name = self._get_exe(self.name)
198
198
  self.class_id = self._get_class_id(self.name)
199
199
  self.initialize_multivu_win32com()
200
200
 
201
- def detect_multivu(self) -> str:
201
+ def detect_multivu(self) -> Tuple[str, str]:
202
202
  '''
203
203
  This looks in the file system for a running version of
204
- MultiVu. Once it is found, the function returns the name.
204
+ MultiVu. Once it is found, the function returns the a
205
+ tuple with the common name and the executable name.
205
206
 
206
207
  Raises
207
208
  ------
@@ -211,8 +212,8 @@ class Instrument():
211
212
 
212
213
  Returns
213
214
  -------
214
- string
215
- Returns the common name of the QD instrument.
215
+ tuple[str]
216
+ Returns the (common name, executable name) of the QD instrument.
216
217
 
217
218
  '''
218
219
  # Build a list of enum, instrumentType
@@ -220,6 +221,10 @@ class Instrument():
220
221
  # Remove the last item (called na)
221
222
  instrument_names.pop()
222
223
 
224
+ # declare these variables so that they are available to return
225
+ common_name = ''
226
+ exe_name = ''
227
+
223
228
  # Use WMIC to get the list of running programs with 'multivu'
224
229
  # in their path
225
230
  cmd = 'WMIC PROCESS WHERE "COMMANDLINE like \'%multivu%\'" GET '
@@ -235,15 +240,9 @@ class Instrument():
235
240
  exe_found = re.findall(exe_search, i)
236
241
  if len(exe_found) > 0:
237
242
  name, location, process_id = exe_found[0]
238
- open_mv_dict[name] = (location, process_id)
239
-
240
- # Attempt to match the expected MV executable names with
241
- # the programs in the list and instantiate the instrument
242
- # and add to MultiVu_list.
243
- # MultiVu_list = []
244
- # for instr in instrument_names:
245
- # if instr.name in proc.stdout.upper():
246
- # MultiVu_list.append(instr.name)
243
+ exe_name = name + '.exe'
244
+ common_name = self._exe_to_common_name(exe_name)
245
+ open_mv_dict[common_name] = (location, process_id)
247
246
 
248
247
  # Declare errors if to few or too many are found; for one found,
249
248
  # declare which version is identified
@@ -268,8 +267,7 @@ class Instrument():
268
267
  self.logger.info(msg)
269
268
  else:
270
269
  self.logger.debug(msg)
271
- self.name = name.upper()
272
- return self.name
270
+ return common_name, exe_name
273
271
 
274
272
  def initialize_multivu_win32com(self):
275
273
  '''
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: MultiPyVu
3
- Version: 2.1.2
3
+ Version: 2.2.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>
@@ -38,9 +38,6 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
38
38
  Requires-Python: >=3.8
39
39
  Description-Content-Type: text/markdown
40
40
  License-File: LICENSE
41
- Requires-Dist: pandas
42
- Requires-Dist: pywin32>=300
43
- Requires-Dist: pillow
44
41
 
45
42
  ![qd_logo](https://qdusa.com/images/QD_logo.png)
46
43
  # MultiPyVu
@@ -90,13 +87,13 @@ pip install update MultiPyVu
90
87
  Several examples have been uploaded to [Quantum Design's Pharos database](https://www.qdusa.com/pharos/view.php?fDocumentId=4339) as well as [GitHub](https://github.com/qdusa/MultiPyVu/tree/master/PharosExamples/). These examples demonstrate various capabilities of the module, and serve as templates upon which users can add their own code to integrate external hardware operations with the environmental controls of the Quantum Design instrument.
91
88
  | Filename | Description|
92
89
  -----|-----
93
- example_Local.py | A simple script which starts the server, then the client, on the PC running MultiVu. It relays instrument parameters and status to demonstrate communication, serving as a minimum working example useful for testing basic functionality.
94
- example_Remote-Server.py | For remote operation; this script must be running on the on the control PC along with the MultiVu executable.
95
- example_Remote-Client.py | For remote operation; this script runs on a separate PC and relays instrument parameters and status to demonstration communication.
96
- example_Command-Demos.py | Utilizes most functions of the module, setting temperature/field/chamber operations, reading back the values and status of those parameters, and waiting for stability conditions to be met. As-written, it runs in local mode.
97
- example_MVDataFile-VISA.py | Simple example showing how to route environmental parameters and data from external instruments into a single MultiVu-readable *.dat* file. As-written, it runs in local mode.
90
+ example_local.py | A simple script which starts the server, then the client, on the PC running MultiVu. It relays instrument parameters and status to demonstrate communication, serving as a minimum working example useful for testing basic functionality.
91
+ example_remote_server.py | For remote operation; this script must be running on the on the control PC along with the MultiVu executable.
92
+ example_remote_client.py | For remote operation; this script runs on a separate PC and relays instrument parameters and status to demonstration communication.
93
+ example_command_demos.py | Utilizes most functions of the module, setting temperature/field/chamber operations, reading back the values and status of those parameters, and waiting for stability conditions to be met. As-written, it runs in local mode.
94
+ example_MVDataFile_VISA.py | Simple example showing how to route environmental parameters and data from external instruments into a single MultiVu-readable *.dat* file. As-written, it runs in local mode.
98
95
  example_graph_dat.py | Script showing how to read a MultiVu *.dat* file into a Pandas DataFrame.
99
- 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.
96
+ 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```.
100
97
 
101
98
  ### Getting Started<a class="anchor" id="getting-started"></a>
102
99
  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.
@@ -297,8 +294,6 @@ Once configured, MultiPyVu gives access to the following commands:
297
294
  client.resistivity.get_resistance(bridge_number)
298
295
  client.resistivity.get_current(bridge_number)
299
296
  ```
300
- We also support reading back the temperature of the rotator thermometer. This reads off the calibration table of the resistor on the horizontal rotator that is programed onto the SROM of your BRT module. The rotator requires an extra connector that routes the thermometer to channel 1, channel 2 to be the new channel 1 and channel 3 to be the new channel 2. As such this command will only give a meaningful result with the horizontal rotator installed:
301
- ```client.resistivity.get_temperature()```
302
297
 
303
298
  ### Saving & Opening a MultiVu Data File<a class="anchor" id="save"></a>
304
299
  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.
@@ -388,7 +383,13 @@ client = mpv.Client(port=6000)
388
383
  - A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
389
384
 
390
385
  ## Changelog<a class="anchor" id="changelog"></a>
391
- **2.1.0**
386
+ **2.2.0**
387
+ - January 2024
388
+ - Corrected a bug that prevented the Server from recognizing PPMS and MPMS3 MultiVu flavors
389
+ - Log the version number when the Client connects to the Server
390
+ - Remove unwanted warnings when quitting the Server using the esc-key.
391
+
392
+ **2.1.4**
392
393
  - October 2023
393
394
  - Import full module as MultiPyVu. Instead of loading the three sub-modules as:
394
395
  ```python
@@ -37,7 +37,6 @@ src/MultiPyVu/sdo_object.py
37
37
  src/MultiPyVu.egg-info/PKG-INFO
38
38
  src/MultiPyVu.egg-info/SOURCES.txt
39
39
  src/MultiPyVu.egg-info/dependency_links.txt
40
- src/MultiPyVu.egg-info/requires.txt
41
40
  src/MultiPyVu.egg-info/top_level.txt
42
41
  src/MultiPyVu/MultiVuDataFile/MultiVuDataFile.py
43
42
  src/MultiPyVu/MultiVuDataFile/__init__.py
@@ -1,3 +0,0 @@
1
- pandas
2
- pywin32>=300
3
- pillow
File without changes
File without changes
File without changes