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.
- qcodespp/__init__.py +77 -0
- qcodespp/actions.py +237 -0
- qcodespp/data/__init__.py +0 -0
- qcodespp/data/data_array.py +555 -0
- qcodespp/data/data_set.py +926 -0
- qcodespp/data/format.py +338 -0
- qcodespp/data/gnuplot_format.py +425 -0
- qcodespp/data/hdf5_format.py +537 -0
- qcodespp/data/hdf5_format_hickle.py +63 -0
- qcodespp/data/io.py +241 -0
- qcodespp/data/location.py +171 -0
- qcodespp/instrument_drivers/Keysight/Keysight_34450A.py +9 -0
- qcodespp/instrument_drivers/Keysight/__init__.py +0 -0
- qcodespp/instrument_drivers/Keysight/private/Keysight_344xxA.py +456 -0
- qcodespp/instrument_drivers/Keysight/private/__init__.py +0 -0
- qcodespp/instrument_drivers/Lakeshore/Model_340.py +483 -0
- qcodespp/instrument_drivers/Lakeshore/__init__.py +0 -0
- qcodespp/instrument_drivers/QDevil/159fit_params_high_latest.json +386 -0
- qcodespp/instrument_drivers/QDevil/159fit_params_low_latest.json +386 -0
- qcodespp/instrument_drivers/QDevil/QDAC2.py +3229 -0
- qcodespp/instrument_drivers/QDevil/QDAC2_Array.py +300 -0
- qcodespp/instrument_drivers/QDevil/QSwitch_elab.py +652 -0
- qcodespp/instrument_drivers/QDevil/__init__.py +0 -0
- qcodespp/instrument_drivers/ZI/ZIHF2LI.py +415 -0
- qcodespp/instrument_drivers/ZI/ZIMFLI.py +764 -0
- qcodespp/instrument_drivers/ZI/ZIMFLI_sync.py +108 -0
- qcodespp/instrument_drivers/ZI/ZIUHFLI.py +2179 -0
- qcodespp/instrument_drivers/ZI/__init__.py +1 -0
- qcodespp/instrument_drivers/__init__.py +0 -0
- qcodespp/instrument_drivers/cryogenic/CryogenicSMS120C.py +599 -0
- qcodespp/instrument_drivers/cryogenic/__init__.py +0 -0
- qcodespp/instrument_drivers/instrument_mocks.py +379 -0
- qcodespp/instrument_drivers/multiplexer_instrument.py +287 -0
- qcodespp/instrument_drivers/national_instruments/PXI_4461.py +451 -0
- qcodespp/instrument_drivers/national_instruments/PXI_4462.py +290 -0
- qcodespp/instrument_drivers/national_instruments/PXI_6259.py +436 -0
- qcodespp/instrument_drivers/national_instruments/PXI_6733.py +230 -0
- qcodespp/instrument_drivers/national_instruments/PXI_6733_e.py +243 -0
- qcodespp/instrument_drivers/national_instruments/__init__.py +0 -0
- qcodespp/instrument_drivers/oxford/__init__.py +0 -0
- qcodespp/instrument_drivers/oxford/mercuryiPS_serial.py +658 -0
- qcodespp/instrument_drivers/oxford/triton.py +434 -0
- qcodespp/instrument_drivers/tektronix/Keithley_2000_Scan.py +65 -0
- qcodespp/instrument_drivers/tektronix/Keithley_2182a.py +190 -0
- qcodespp/instrument_drivers/tektronix/Keithley_2400.py +158 -0
- qcodespp/instrument_drivers/tektronix/Keithley_2450.py +242 -0
- qcodespp/instrument_drivers/tektronix/Keithley_2700.py +397 -0
- qcodespp/instrument_drivers/tektronix/Keithley_6500.py +161 -0
- qcodespp/instrument_drivers/tektronix/__init__.py +0 -0
- qcodespp/instrument_drivers/yokogawa/GS200.py +513 -0
- qcodespp/instrument_drivers/yokogawa/__init__.py +0 -0
- qcodespp/loops.py +1342 -0
- qcodespp/measure.py +310 -0
- qcodespp/parameters.py +311 -0
- qcodespp/plotting/RemotePlot.py +469 -0
- qcodespp/plotting/RemotePlotClient.py +367 -0
- qcodespp/plotting/RemoteQtPlotWidgets.py +871 -0
- qcodespp/plotting/__init__.py +0 -0
- qcodespp/plotting/analysis_tools.py +195 -0
- qcodespp/plotting/colors.py +135 -0
- qcodespp/plotting/offline/__init__.py +0 -0
- qcodespp/plotting/offline/datatypes.py +999 -0
- qcodespp/plotting/offline/design.py +906 -0
- qcodespp/plotting/offline/design.ui +1578 -0
- qcodespp/plotting/offline/editor.py +2966 -0
- qcodespp/plotting/offline/filters.py +561 -0
- qcodespp/plotting/offline/fits.py +1171 -0
- qcodespp/plotting/offline/helpers.py +288 -0
- qcodespp/plotting/offline/iconGadget.png +0 -0
- qcodespp/plotting/offline/main.py +55 -0
- qcodespp/plotting/offline/popupwindows.py +1848 -0
- qcodespp/plotting/offline/qcodes_pp_extension.py +328 -0
- qcodespp/plotting/offline/sidebars.py +1108 -0
- qcodespp/station.py +290 -0
- qcodespp/utils/__init__.py +0 -0
- qcodespp/utils/helpers.py +618 -0
- qcodespp/utils/visa_helpers.py +61 -0
- qcodespp/version.py +12 -0
- qcodespp-0.1.0.dist-info/METADATA +91 -0
- qcodespp-0.1.0.dist-info/RECORD +82 -0
- qcodespp-0.1.0.dist-info/WHEEL +4 -0
- 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
|