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
@@ -0,0 +1,338 @@
1
+ from collections import namedtuple
2
+ from traceback import format_exc
3
+ from operator import attrgetter
4
+ import logging
5
+ from datetime import datetime
6
+
7
+ log = logging.getLogger(__name__)
8
+
9
+ class Formatter:
10
+ """
11
+ Data file formatters
12
+
13
+ Formatters translate between DataSetPPs and data files.
14
+
15
+ Each Formatter is expected to implement writing methods:
16
+
17
+ - ``write``: to write the ``DataArrays``
18
+ - ``write_metadata``: to write the metadata structure
19
+
20
+ Optionally, if this Formatter keeps the data file(s) open
21
+ between write calls, it may implement:
22
+
23
+ - ``close_file``: to perform any final cleanup and release the
24
+ file and any other resources.
25
+
26
+ and reading methods:
27
+
28
+ - ``read`` or ``read_one_file`` to reconstruct the ``DataArrays``, either
29
+ all at once (``read``) or one file at a time, supplied by the base class
30
+ ``read`` method that loops over all data files at the correct location.
31
+
32
+ - ``read_metadata``: to reload saved metadata. If a subclass overrides
33
+ ``read``, this method should call ``read_metadata``, but keep it also
34
+ as a separate method because it occasionally gets called independently.
35
+
36
+ All of these methods accept a ``data_set`` argument, which should be a
37
+ ``DataSetPP`` object. Even if you are loading a new data set from disk, this
38
+ object should already have attributes:
39
+
40
+ - io: an IO manager (see qcodes.data.io)
41
+ location: a string, like a file path, that identifies the DataSetPP and
42
+ tells the IO manager where to store it
43
+ - arrays: a dict of ``{array_id:DataArray}`` to read into.
44
+
45
+ - read will create entries that don't yet exist.
46
+ - write will write ALL DataArrays in the DataSetPP, using
47
+ last_saved_index and modified_range, as well as whether or not
48
+ it found the specified file, to determine how much to write.
49
+ """
50
+ ArrayGroup = namedtuple('ArrayGroup', 'shape set_arrays data name')
51
+
52
+ def write(self, data_set, io_manager, location, write_metadata=True,
53
+ force_write=False, only_complete=True):
54
+ """
55
+ Write the DataSetPP to storage.
56
+
57
+ Subclasses must override this method.
58
+
59
+ It is up to the Formatter to decide when to overwrite completely,
60
+ and when to just append or otherwise update the file(s).
61
+
62
+ Args:
63
+ data_set (DataSetPP): the data we are writing.
64
+ io_manager (io_manager): base physical location to write to.
65
+ location (str): the file location within the io_manager.
66
+ write_metadata (bool): if True, then the metadata is written to disk
67
+ force_write (bool): if True, then the data is written to disk
68
+ only_complete (bool): Used only by the gnuplot formatter's
69
+ overridden version of this method
70
+ """
71
+ raise NotImplementedError
72
+
73
+ def read(self, data_set, include_metadata=True):
74
+ """
75
+ Read the entire ``DataSetPP``.
76
+
77
+ Find all files matching ``data_set.location`` (using io_manager.list)
78
+ and call ``read_one_file`` on each. Subclasses may either override
79
+ this method (if they use only one file or want to do their own
80
+ searching) or override ``read_one_file`` to use the search and
81
+ initialization functionality defined here.
82
+
83
+ Args:
84
+ data_set (DataSetPP): the data to read into. Should already have
85
+ attributes ``io`` (an io manager), ``location`` (string),
86
+ and ``arrays`` (dict of ``{array_id: array}``, can be empty
87
+ or can already have some or all of the arrays present, they
88
+ expect to be overwritten)
89
+ """
90
+ io_manager = data_set.io
91
+ location = data_set.location
92
+
93
+ data_files = io_manager.list(location)
94
+ if not data_files:
95
+ raise IOError('no data found at ' + location)
96
+
97
+ # in case the DataArrays exist but haven't been initialized
98
+ for array in data_set.arrays.values():
99
+ if array.ndarray is None:
100
+ array.init_data()
101
+
102
+ if include_metadata==True:
103
+ self.read_metadata(data_set)
104
+
105
+ ids_read = set()
106
+ for fn in data_files:
107
+ with io_manager.open(fn, 'r') as f:
108
+ try:
109
+ self.read_one_file(data_set, f, ids_read)
110
+ except ValueError:
111
+ log.warning('error reading file ' + fn)
112
+ log.warning(format_exc())
113
+
114
+ def write_metadata(self, data_set, io_manager, location, read_first=True):
115
+ """
116
+ Write the metadata for this DataSetPP to storage.
117
+
118
+ Subclasses must override this method.
119
+
120
+ Args:
121
+ data_set (DataSetPP): the data we are writing.
122
+ io_manager (io_manager): base physical location to write to.
123
+ location (str): the file location within the io_manager.
124
+ read_first (bool, optional): whether to first look for previously
125
+ saved metadata that may contain more information than the local
126
+ copy.
127
+ """
128
+ raise NotImplementedError
129
+
130
+ def read_metadata(self, data_set):
131
+ """
132
+ Read the metadata from this DataSetPP from storage.
133
+
134
+ Subclasses must override this method.
135
+
136
+ Args:
137
+ data_set (DataSetPP): the data to read metadata into
138
+ """
139
+ raise NotImplementedError
140
+
141
+ def read_one_file(self, data_set, f, ids_read):
142
+ """
143
+ Read data from a single file into a ``DataSetPP``.
144
+
145
+ Formatter subclasses that break a DataSetPP into multiple data files may
146
+ choose to override either this method, which handles one file at a
147
+ time, or ``read`` which finds matching files on its own.
148
+
149
+ Args:
150
+ data_set (DataSetPP): the data we are reading into.
151
+
152
+ f (file-like): a file-like object to read from, as provided by
153
+ ``io_manager.open``.
154
+
155
+ ids_read (set): ``array_ids`` that we have already read.
156
+ When you read an array, check that it's not in this set (except
157
+ setpoints, which can be in several files with different inner
158
+ loops) then add it to the set so other files know it should not
159
+ be read again.
160
+
161
+ Raises:
162
+ ValueError: if a duplicate array_id of measured data is found
163
+ """
164
+ raise NotImplementedError
165
+
166
+ def match_save_range(self, group, file_exists, only_complete=True, force_rewrite=False):
167
+ """
168
+ Find the save range that will joins all changes in an array group.
169
+
170
+ Matches all full-sized arrays: the data arrays plus the inner loop
171
+ setpoint array.
172
+
173
+ Note: if an outer loop has changed values (without the inner
174
+ loop or measured data changing) we won't notice it here. We assume
175
+ that before an iteration of the inner loop starts, the outer loop
176
+ setpoint gets set and then does not change later.
177
+
178
+ Args:
179
+ group (Formatter.ArrayGroup): a ``namedtuple`` containing the
180
+ arrays that go together in one file, as tuple ``group.data``.
181
+
182
+ file_exists (bool): Does this file already exist? If True, and
183
+ all arrays in the group agree on ``last_saved_index``, we
184
+ assume the file has been written up to this index and we can
185
+ append to it. Otherwise we will set the returned range to start
186
+ from zero (so if the file does exist, it gets completely
187
+ overwritten).
188
+
189
+ only_complete (bool): Should we write all available new data,
190
+ or only complete rows? If True, we write only the range of
191
+ array indices which all arrays in the group list as modified,
192
+ so that future writes will be able to do a clean append to
193
+ the data file as more data arrives.
194
+ Default True.
195
+
196
+ Returns:
197
+ Tuple(int, int): the first and last raveled indices that should
198
+ be saved. Returns None if:
199
+ * no data is present
200
+ * no new data can be found
201
+ """
202
+ inner_setpoint = group.set_arrays[-1]
203
+ full_dim_data = (inner_setpoint, ) + group.data
204
+
205
+ # always return None if there are no modifications,
206
+ # even if there are last_saved_index inconsistencies
207
+ # so we don't do extra writing just to reshape the file
208
+ for array in full_dim_data:
209
+ if array.modified_range:
210
+ break
211
+ else:
212
+ return None
213
+
214
+ last_saved_index = inner_setpoint.last_saved_index
215
+
216
+ if last_saved_index is None or not file_exists:
217
+ if last_saved_index is None and file_exists:
218
+ log.warning(f"{datetime.now().replace(microsecond=0)}: Inconsistent file information. "
219
+ "last_save_index is None but file exists. "
220
+ "Will overwrite")
221
+ if last_saved_index is not None and not file_exists:
222
+ log.warning(f"{datetime.now().replace(microsecond=0)}: Inconsistent file information. "
223
+ "last_save_index is not None but file does not "
224
+ "exist. Will rewrite from scratch")
225
+ return self._match_save_range_whole_file(
226
+ full_dim_data, only_complete)
227
+
228
+ if force_rewrite:
229
+ #log.warning("Writing to primary data file skipped: Will rewrite primary file from scratch")
230
+ return self._match_save_range_whole_file(
231
+ full_dim_data, only_complete)
232
+
233
+ # force overwrite if inconsistent last_saved_index
234
+ for array in group.data:
235
+ if array.last_saved_index != last_saved_index:
236
+ return self._match_save_range_whole_file(
237
+ full_dim_data, only_complete)
238
+
239
+ return self._match_save_range_incremental(
240
+ full_dim_data, last_saved_index, only_complete)
241
+
242
+ @staticmethod
243
+ def _match_save_range_whole_file(arrays, only_complete):
244
+ max_save = None
245
+ agg = (min if only_complete else max)
246
+ for array in arrays:
247
+ array_max = array.last_saved_index
248
+ if array_max is None:
249
+ array_max = -1
250
+ mr = array.modified_range
251
+ if mr:
252
+ array_max = max(array_max, mr[1])
253
+ max_save = (array_max if max_save is None else
254
+ agg(max_save, array_max))
255
+
256
+ if max_save >= 0:
257
+ return (0, max_save)
258
+ else:
259
+ return None
260
+
261
+ @staticmethod
262
+ def _match_save_range_incremental(arrays, last_saved_index, only_complete):
263
+ mod_ranges = []
264
+ for array in arrays:
265
+ mr = array.modified_range
266
+ if not mr:
267
+ if only_complete:
268
+ return None
269
+ else:
270
+ continue
271
+ mod_ranges.append(mr)
272
+
273
+ mod_range = mod_ranges[0]
274
+ agg = (min if only_complete else max)
275
+ for mr in mod_ranges[1:]:
276
+ mod_range = (min(mod_range[0], mr[0]),
277
+ agg(mod_range[1], mr[1]))
278
+
279
+ if last_saved_index >= mod_range[1]:
280
+ return (0, last_saved_index)
281
+ elif last_saved_index >= mod_range[0]:
282
+ return (0, mod_range[1])
283
+ else:
284
+ return (last_saved_index + 1, mod_range[1])
285
+
286
+ def group_arrays(self, arrays):
287
+ """
288
+ Find the sets of arrays which share all the same setpoint arrays.
289
+
290
+ Some Formatters use this grouping to determine which arrays to save
291
+ together in one file.
292
+
293
+ Args:
294
+ arrays (Dict[DataArray]): all the arrays in a DataSetPP
295
+
296
+ Returns:
297
+ List[Formatter.ArrayGroup]: namedtuples giving:
298
+
299
+ - shape (Tuple[int]): dimensions as in numpy
300
+ - set_arrays (Tuple[DataArray]): the setpoints of this group
301
+ - data (Tuple[DataArray]): measured arrays in this group
302
+ - name (str): a unique name of this group, obtained by joining
303
+ the setpoint array ids.
304
+ """
305
+
306
+ set_array_sets = tuple(set(array.set_arrays
307
+ for array in arrays.values()))
308
+ all_set_arrays = set()
309
+ for set_array_set in set_array_sets:
310
+ all_set_arrays.update(set_array_set)
311
+
312
+ grouped_data = [[] for _ in set_array_sets]
313
+
314
+ for array in arrays.values():
315
+ i = set_array_sets.index(array.set_arrays)
316
+ if array not in all_set_arrays: # array.set_arrays[-1] != array:
317
+ # don't include the setpoint array itself in the data
318
+ grouped_data[i].append(array)
319
+
320
+ out = []
321
+ id_getter = attrgetter('array_id')
322
+ for set_arrays, data in zip(set_array_sets, grouped_data):
323
+ leni = len(set_arrays)
324
+ if not data and any(1 for other_set_arrays in set_array_sets if
325
+ len(other_set_arrays) > leni and
326
+ other_set_arrays[:leni] == set_arrays):
327
+ # this is an outer loop that doesn't have any data of its own,
328
+ # so skip it.
329
+ # Inner-loop setpoints with no data is weird (we set values
330
+ # but didn't measure anything there?) but we should keep it.
331
+ continue
332
+
333
+ group_name = '_'.join(sai.array_id for sai in set_arrays)
334
+ out.append(self.ArrayGroup(shape=set_arrays[-1].shape,
335
+ set_arrays=set_arrays,
336
+ data=tuple(sorted(data, key=id_getter)),
337
+ name=group_name))
338
+ return out