qcodespp 0.1.0__py3-none-any.whl

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 (82) hide show
  1. qcodespp/__init__.py +77 -0
  2. qcodespp/actions.py +237 -0
  3. qcodespp/data/__init__.py +0 -0
  4. qcodespp/data/data_array.py +555 -0
  5. qcodespp/data/data_set.py +926 -0
  6. qcodespp/data/format.py +338 -0
  7. qcodespp/data/gnuplot_format.py +425 -0
  8. qcodespp/data/hdf5_format.py +537 -0
  9. qcodespp/data/hdf5_format_hickle.py +63 -0
  10. qcodespp/data/io.py +241 -0
  11. qcodespp/data/location.py +171 -0
  12. qcodespp/instrument_drivers/Keysight/Keysight_34450A.py +9 -0
  13. qcodespp/instrument_drivers/Keysight/__init__.py +0 -0
  14. qcodespp/instrument_drivers/Keysight/private/Keysight_344xxA.py +456 -0
  15. qcodespp/instrument_drivers/Keysight/private/__init__.py +0 -0
  16. qcodespp/instrument_drivers/Lakeshore/Model_340.py +483 -0
  17. qcodespp/instrument_drivers/Lakeshore/__init__.py +0 -0
  18. qcodespp/instrument_drivers/QDevil/159fit_params_high_latest.json +386 -0
  19. qcodespp/instrument_drivers/QDevil/159fit_params_low_latest.json +386 -0
  20. qcodespp/instrument_drivers/QDevil/QDAC2.py +3229 -0
  21. qcodespp/instrument_drivers/QDevil/QDAC2_Array.py +300 -0
  22. qcodespp/instrument_drivers/QDevil/QSwitch_elab.py +652 -0
  23. qcodespp/instrument_drivers/QDevil/__init__.py +0 -0
  24. qcodespp/instrument_drivers/ZI/ZIHF2LI.py +415 -0
  25. qcodespp/instrument_drivers/ZI/ZIMFLI.py +764 -0
  26. qcodespp/instrument_drivers/ZI/ZIMFLI_sync.py +108 -0
  27. qcodespp/instrument_drivers/ZI/ZIUHFLI.py +2179 -0
  28. qcodespp/instrument_drivers/ZI/__init__.py +1 -0
  29. qcodespp/instrument_drivers/__init__.py +0 -0
  30. qcodespp/instrument_drivers/cryogenic/CryogenicSMS120C.py +599 -0
  31. qcodespp/instrument_drivers/cryogenic/__init__.py +0 -0
  32. qcodespp/instrument_drivers/instrument_mocks.py +379 -0
  33. qcodespp/instrument_drivers/multiplexer_instrument.py +287 -0
  34. qcodespp/instrument_drivers/national_instruments/PXI_4461.py +451 -0
  35. qcodespp/instrument_drivers/national_instruments/PXI_4462.py +290 -0
  36. qcodespp/instrument_drivers/national_instruments/PXI_6259.py +436 -0
  37. qcodespp/instrument_drivers/national_instruments/PXI_6733.py +230 -0
  38. qcodespp/instrument_drivers/national_instruments/PXI_6733_e.py +243 -0
  39. qcodespp/instrument_drivers/national_instruments/__init__.py +0 -0
  40. qcodespp/instrument_drivers/oxford/__init__.py +0 -0
  41. qcodespp/instrument_drivers/oxford/mercuryiPS_serial.py +658 -0
  42. qcodespp/instrument_drivers/oxford/triton.py +434 -0
  43. qcodespp/instrument_drivers/tektronix/Keithley_2000_Scan.py +65 -0
  44. qcodespp/instrument_drivers/tektronix/Keithley_2182a.py +190 -0
  45. qcodespp/instrument_drivers/tektronix/Keithley_2400.py +158 -0
  46. qcodespp/instrument_drivers/tektronix/Keithley_2450.py +242 -0
  47. qcodespp/instrument_drivers/tektronix/Keithley_2700.py +397 -0
  48. qcodespp/instrument_drivers/tektronix/Keithley_6500.py +161 -0
  49. qcodespp/instrument_drivers/tektronix/__init__.py +0 -0
  50. qcodespp/instrument_drivers/yokogawa/GS200.py +513 -0
  51. qcodespp/instrument_drivers/yokogawa/__init__.py +0 -0
  52. qcodespp/loops.py +1342 -0
  53. qcodespp/measure.py +310 -0
  54. qcodespp/parameters.py +311 -0
  55. qcodespp/plotting/RemotePlot.py +469 -0
  56. qcodespp/plotting/RemotePlotClient.py +367 -0
  57. qcodespp/plotting/RemoteQtPlotWidgets.py +871 -0
  58. qcodespp/plotting/__init__.py +0 -0
  59. qcodespp/plotting/analysis_tools.py +195 -0
  60. qcodespp/plotting/colors.py +135 -0
  61. qcodespp/plotting/offline/__init__.py +0 -0
  62. qcodespp/plotting/offline/datatypes.py +999 -0
  63. qcodespp/plotting/offline/design.py +906 -0
  64. qcodespp/plotting/offline/design.ui +1578 -0
  65. qcodespp/plotting/offline/editor.py +2966 -0
  66. qcodespp/plotting/offline/filters.py +561 -0
  67. qcodespp/plotting/offline/fits.py +1171 -0
  68. qcodespp/plotting/offline/helpers.py +288 -0
  69. qcodespp/plotting/offline/iconGadget.png +0 -0
  70. qcodespp/plotting/offline/main.py +55 -0
  71. qcodespp/plotting/offline/popupwindows.py +1848 -0
  72. qcodespp/plotting/offline/qcodes_pp_extension.py +328 -0
  73. qcodespp/plotting/offline/sidebars.py +1108 -0
  74. qcodespp/station.py +290 -0
  75. qcodespp/utils/__init__.py +0 -0
  76. qcodespp/utils/helpers.py +618 -0
  77. qcodespp/utils/visa_helpers.py +61 -0
  78. qcodespp/version.py +12 -0
  79. qcodespp-0.1.0.dist-info/METADATA +91 -0
  80. qcodespp-0.1.0.dist-info/RECORD +82 -0
  81. qcodespp-0.1.0.dist-info/WHEEL +4 -0
  82. qcodespp-0.1.0.dist-info/licenses/LICENSE +21 -0
qcodespp/station.py ADDED
@@ -0,0 +1,290 @@
1
+ """Station objects - collect all the equipment you use to do an experiment."""
2
+ from typing import List, Sequence, Any
3
+
4
+ import time
5
+
6
+ from qcodes.metadatable import MetadatableWithName
7
+
8
+ from qcodespp.parameters import Parameter
9
+ from qcodes.parameters import ParameterBase , ElapsedTimeParameter
10
+
11
+ from qcodes import Station as QStation
12
+ from qcodes import Instrument
13
+ from qcodespp.actions import _actions_snapshot
14
+ from numpy import mean
15
+
16
+ '''
17
+ This code wraps the QCoDeS Station class and adds some functionality to it.
18
+ It allows for the automatic addition of instruments and parameters to the station,
19
+ and underlies the data acquisition. In qcodesplusplus there is no separate measurement
20
+ context, since all measurements should be done in the context of a station anyway.
21
+ Doing it like this forces the user to only measure parameters in the station,
22
+ without the need for a separate measurement context.
23
+ '''
24
+
25
+ class Station(QStation):
26
+ """
27
+ A representation of the physical measurement setup/station.
28
+
29
+ This class is a wrapper around the QCoDeS Station class, adding functionality
30
+ for automatic addition of instruments and parameters, and providing a
31
+ measurement method that can be used to measure parameters in the station.
32
+
33
+ Args:
34
+ components: List of Instruments, Parameters, or other components to add to the station.
35
+
36
+ add_variables: Automatically adds previously defined Instruments and Parameters to the station.
37
+ Typically, add_variables=globals() to look through all previously defined variables.
38
+
39
+ config_file: Path to YAML files to load the station config from.
40
+ - If only one yaml file needed to be loaded, it should be passed
41
+ as a string, e.g., '~/station.yaml'
42
+ - If more than one yaml file needed, they should be supplied as
43
+ a sequence of strings, e.g. ['~/station1.yaml', '~/station2.yaml']
44
+
45
+ use_monitor: Should the QCoDeS monitor be activated for this station.
46
+
47
+ default: Is this station the default?
48
+
49
+ update_snapshot: Immediately update the snapshot of each component as it is added to the Station.
50
+
51
+ inc_timer: Include a timer parameter in the station and the default measurement.
52
+
53
+ """
54
+
55
+ def __init__(
56
+ self,
57
+ *components: MetadatableWithName,
58
+ add_variables: Any=None,
59
+ config_file: str | Sequence[str] | None = None,
60
+ use_monitor: bool | None = None,
61
+ default: bool = True,
62
+ update_snapshot: bool = True,
63
+ inc_timer: bool = True,
64
+ **kwargs: Any,
65
+ ) -> None:
66
+
67
+ super().__init__(*components, config_file,use_monitor,default,update_snapshot,**kwargs)
68
+
69
+ # when a new station is defined, store it in a class variable
70
+ # so it becomes the globally accessible default station.
71
+ # You can still have multiple stations defined, but to use
72
+ # other than the default one you must specify it explicitly.
73
+ # If for some reason you want this new Station NOT to be the
74
+ # default, just specify default=False
75
+ if default:
76
+ Station.default = self
77
+
78
+ self.components: dict[str, MetadatableWithName] = {}
79
+ for item in components:
80
+ self.add_component(item, update_snapshot=update_snapshot)
81
+
82
+ self.use_monitor = use_monitor
83
+
84
+ self._added_methods: list[str] = []
85
+ self._monitor_parameters: list[Parameter] = []
86
+
87
+ if config_file is None:
88
+ self.config_file = []
89
+ elif isinstance(config_file, str):
90
+ self.config_file = [
91
+ config_file,
92
+ ]
93
+ else:
94
+ self.config_file = list(config_file)
95
+
96
+ self.load_config_files(*self.config_file)
97
+
98
+ if inc_timer==True:
99
+ timer=ElapsedTimeParameter(name='timer')
100
+ self.add_component(timer, update_snapshot=update_snapshot)
101
+
102
+ self.default_measurement = [] # type: List
103
+
104
+ if add_variables is not None:
105
+ self.auto_add(add_variables)
106
+
107
+ def auto_add(self,variables,add_instruments: bool=True,add_parameters: bool=True,update_snapshot: bool=True):
108
+ """
109
+ Automatically add previously defined instruments and parameters to the station. Usually, auto_add=globals().
110
+
111
+ Args:
112
+ variables: Dictionary of variables to check for Instruments and Parameters. e.g. globals(), locals(), etc.
113
+
114
+ add_instruments: If True, add Instruments to the station.
115
+
116
+ add_parameters: If True, add Parameters to the station.
117
+
118
+ update_snapshot: If True, update the snapshot of each component as it is added to the Station.
119
+ """
120
+ print('Automatically adding components to Station...')
121
+ for variable in variables.values():
122
+ if add_instruments and isinstance(variable,Instrument) and variable not in self.components.values():
123
+ self.add_component(variable,update_snapshot=update_snapshot)
124
+ elif add_parameters and isinstance(variable,ParameterBase) and variable not in self.components.values():
125
+ self.add_component(variable,update_snapshot=update_snapshot)
126
+
127
+ if add_instruments:
128
+ inststring='Instruments in station:'
129
+ for component in self.components.values():
130
+ if isinstance(component,Instrument):
131
+ inststring+=f' {component.name},'
132
+ print(inststring[:-1])
133
+
134
+ if add_parameters and 'parameters' in self.snapshot_base():
135
+ paramstring='Parameters in station:'
136
+ for component in self.components.values():
137
+ if isinstance(component,ParameterBase):
138
+ paramstring+=f' {component.full_name},'
139
+ print(paramstring[:-1])
140
+
141
+ def snapshot_base(self, update: bool=False,
142
+ params_to_skip_update: Sequence[str]=None) -> dict:
143
+ """
144
+ State of the station as a JSON-compatible dict.
145
+
146
+ Note: in the station contains an instrument that has already been
147
+ closed, not only will it not be snapshotted, it will also be removed
148
+ from the station during the execution of this function.
149
+
150
+ Args:
151
+ update (bool): If True, update the state by querying the
152
+ all the children: f.ex. instruments, parameters, components, etc.
153
+ If False, just use the latest values in memory.
154
+
155
+ Returns:
156
+ dict: base snapshot
157
+ """
158
+ snap = {
159
+ 'instruments': {},
160
+ 'parameters': {},
161
+ 'components': {},
162
+ 'default_measurement': _actions_snapshot(
163
+ self.default_measurement, update)
164
+ }
165
+
166
+ components_to_remove = []
167
+
168
+ for name, itm in self.components.items():
169
+ if isinstance(itm, Instrument):
170
+ # instruments can be closed during the lifetime of the
171
+ # station object, hence this 'if' allows to avoid
172
+ # snapshotting instruments that are already closed
173
+ if Instrument.is_valid(itm):
174
+ snap['instruments'][name] = itm.snapshot(update=update)
175
+ else:
176
+ components_to_remove.append(name)
177
+ elif isinstance(itm, (Parameter
178
+ )):
179
+ snap['parameters'][name] = itm.snapshot(update=update)
180
+ else:
181
+ snap['components'][name] = itm.snapshot(update=update)
182
+
183
+ for c in components_to_remove:
184
+ self.remove_component(c)
185
+
186
+ return snap
187
+
188
+ def set_measurement(self, *actions, check_in_station=True):
189
+ """
190
+ Save a set of ``*actions``` as the default measurement for this Station.
191
+
192
+ These actions will be executed by default by a Loop if this is the
193
+ default Station, and any measurements among them can be done once
194
+ by .measure
195
+
196
+ Args:
197
+ *actions: parameters to set as default measurement
198
+ """
199
+ # Validate now so the user gets an error message ASAP
200
+ # and so we don't accept `Loop` as an action here, where
201
+ # it would cause infinite recursion.
202
+ # We need to import Loop inside here to avoid circular import
203
+ from .loops import Loop
204
+ Loop.validate_actions(*actions)
205
+
206
+ if check_in_station:
207
+ for action in actions:
208
+ if hasattr(action,'get') and action not in self.components.values():
209
+ if hasattr(action, 'instrument') and action.instrument not in self.components.values():
210
+ raise ValueError(f'Could not find {action.full_name} nor a possible parent instrument in the specified Station. '
211
+ 'Please add the parameter and/or instrument to the Station before measuring to avoid loss of metadata.')
212
+ elif hasattr(action, 'instrument') and action.instrument and action.instrument not in self.components.values():
213
+ raise ValueError(f'{action.full_name} belongs to the instrument {action.instrument.name}, but this instrument '
214
+ 'is not in the specified Station. '
215
+ 'Please add this instrument to the Station before measuring to avoid loss of metadata.')
216
+
217
+ self.default_measurement = actions
218
+
219
+ if 'timer' in self.components:
220
+ self.default_measurement = self.default_measurement + (self.components['timer'],)
221
+
222
+ def communication_time(self,measurement_num=5, return_average=True):
223
+ """
224
+ Estimate how long it takes to communicate with the instruments in the station.
225
+
226
+ Args:
227
+ measurement_num: Number of measurements to take to estimate the communication time.
228
+ Default is 1, but can be set to a higher number for more accurate estimates.
229
+ return_average: Whether to return the average of the measurements or the entire list.
230
+ Returns:
231
+ Either the average communication time or the list of communication times for each measurement.
232
+ """
233
+ commtimes=[]
234
+ for i in range(measurement_num):
235
+ starttime=time.time()
236
+ self.measurement()
237
+ endtime=time.time()
238
+ commtimes.append(endtime-starttime)
239
+ if return_average:
240
+ return mean(commtimes)
241
+ else:
242
+ return commtimes
243
+
244
+ def measurement(self, *actions):
245
+ """
246
+ Measure the default measurement, or parameters in actions.
247
+
248
+ Args:
249
+ *actions: parameters to mesure
250
+ """
251
+ if not actions:
252
+ actions = self.default_measurement
253
+
254
+ out = []
255
+
256
+ # this is a stripped down, uncompiled version of how
257
+ # ActiveLoop handles a set of actions
258
+ # callables (including Wait) return nothing, but can
259
+ # change system state.
260
+ for action in actions:
261
+ if hasattr(action, 'get'):
262
+ out.append(action.get())
263
+ elif callable(action):
264
+ action()
265
+
266
+ return out
267
+
268
+ def measure(self,*actions,timer=None):
269
+ """
270
+ Pass the default measurement to a loop after previously setting it with set_measurement.
271
+
272
+ Example:
273
+ station.set_measurement(param1, param2)
274
+ loop = Loop(instrument.parameter.sweep(1, 10, 1),delay=0.1).each(*station.measure())
275
+ """
276
+
277
+ if not actions:
278
+ actions = self.default_measurement
279
+ if timer==False:
280
+ actions=tuple(action for action in actions if action.name!='timer')
281
+ return actions
282
+
283
+ # station['someitem'] and station.someitem are both
284
+ # shortcuts to station.components['someitem']
285
+ # (assuming 'someitem' doesn't have another meaning in Station)
286
+ def __getitem__(self, key):
287
+ """Shortcut to components dict."""
288
+ return self.components[key]
289
+
290
+ delegate_attr_dicts = ['components']
File without changes