qcodes 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 (128) hide show
  1. qcodes/__init__.py +65 -0
  2. qcodes/actions.py +207 -0
  3. qcodes/config/__init__.py +2 -0
  4. qcodes/config/config.py +396 -0
  5. qcodes/config/qcodesrc.json +11 -0
  6. qcodes/config/qcodesrc_schema.json +55 -0
  7. qcodes/data/__init__.py +0 -0
  8. qcodes/data/data_array.py +520 -0
  9. qcodes/data/data_set.py +803 -0
  10. qcodes/data/format.py +309 -0
  11. qcodes/data/gnuplot_format.py +366 -0
  12. qcodes/data/hdf5_format.py +385 -0
  13. qcodes/data/io.py +266 -0
  14. qcodes/data/location.py +166 -0
  15. qcodes/data/manager.py +163 -0
  16. qcodes/instrument/__init__.py +0 -0
  17. qcodes/instrument/base.py +630 -0
  18. qcodes/instrument/function.py +134 -0
  19. qcodes/instrument/ip.py +236 -0
  20. qcodes/instrument/metaclass.py +45 -0
  21. qcodes/instrument/mock.py +278 -0
  22. qcodes/instrument/parameter.py +1001 -0
  23. qcodes/instrument/remote.py +529 -0
  24. qcodes/instrument/server.py +189 -0
  25. qcodes/instrument/sweep_values.py +286 -0
  26. qcodes/instrument/visa.py +198 -0
  27. qcodes/instrument_drivers/AlazarTech/ATS.py +1001 -0
  28. qcodes/instrument_drivers/AlazarTech/ATS9870.py +266 -0
  29. qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py +143 -0
  30. qcodes/instrument_drivers/AlazarTech/__init__.py +0 -0
  31. qcodes/instrument_drivers/QuTech/IVVI.py +390 -0
  32. qcodes/instrument_drivers/QuTech/__init__.py +0 -0
  33. qcodes/instrument_drivers/__init__.py +0 -0
  34. qcodes/instrument_drivers/agilent/Agilent_34400A.py +155 -0
  35. qcodes/instrument_drivers/agilent/E8527D.py +79 -0
  36. qcodes/instrument_drivers/agilent/HP33210A.py +104 -0
  37. qcodes/instrument_drivers/agilent/__init__.py +0 -0
  38. qcodes/instrument_drivers/agilent/test_suite.py +96 -0
  39. qcodes/instrument_drivers/ithaco/Ithaco_1211.py +110 -0
  40. qcodes/instrument_drivers/ithaco/__init__.py +0 -0
  41. qcodes/instrument_drivers/oxford/__init__.py +0 -0
  42. qcodes/instrument_drivers/oxford/mercuryiPS.py +358 -0
  43. qcodes/instrument_drivers/oxford/triton.py +227 -0
  44. qcodes/instrument_drivers/rigol/DG4000.py +591 -0
  45. qcodes/instrument_drivers/rigol/__init__.py +0 -0
  46. qcodes/instrument_drivers/rohde_schwarz/SGS100A.py +99 -0
  47. qcodes/instrument_drivers/rohde_schwarz/ZNB20.py +154 -0
  48. qcodes/instrument_drivers/rohde_schwarz/__init__.py +0 -0
  49. qcodes/instrument_drivers/signal_hound/USB_SA124B.py +567 -0
  50. qcodes/instrument_drivers/signal_hound/__init__.py +0 -0
  51. qcodes/instrument_drivers/stanford_research/SR560.py +116 -0
  52. qcodes/instrument_drivers/stanford_research/SR830.py +314 -0
  53. qcodes/instrument_drivers/stanford_research/SR865.py +305 -0
  54. qcodes/instrument_drivers/stanford_research/__init__.py +0 -0
  55. qcodes/instrument_drivers/tektronix/AWG5014.py +1228 -0
  56. qcodes/instrument_drivers/tektronix/AWG520.py +659 -0
  57. qcodes/instrument_drivers/tektronix/Keithley_2000.py +195 -0
  58. qcodes/instrument_drivers/tektronix/Keithley_2600.py +83 -0
  59. qcodes/instrument_drivers/tektronix/Keithley_2700.py +395 -0
  60. qcodes/instrument_drivers/tektronix/__init__.py +0 -0
  61. qcodes/instrument_drivers/test.py +94 -0
  62. qcodes/instrument_drivers/weinschel/Weinschel_8320.py +21 -0
  63. qcodes/instrument_drivers/weinschel/__init__.py +0 -0
  64. qcodes/instrument_drivers/weinschel/test_suite.py +27 -0
  65. qcodes/loops.py +1009 -0
  66. qcodes/measure.py +155 -0
  67. qcodes/plots/__init__.py +0 -0
  68. qcodes/plots/base.py +280 -0
  69. qcodes/plots/colors.py +135 -0
  70. qcodes/plots/pyqtgraph.py +384 -0
  71. qcodes/plots/qcmatplotlib.py +206 -0
  72. qcodes/process/__init__.py +0 -0
  73. qcodes/process/helpers.py +60 -0
  74. qcodes/process/qcodes_process.py +72 -0
  75. qcodes/process/server.py +395 -0
  76. qcodes/process/stream_queue.py +152 -0
  77. qcodes/station.py +178 -0
  78. qcodes/test.py +119 -0
  79. qcodes/tests/__init__.py +0 -0
  80. qcodes/tests/common.py +7 -0
  81. qcodes/tests/data_mocks.py +173 -0
  82. qcodes/tests/instrument_mocks.py +327 -0
  83. qcodes/tests/py35_syntax.py +13 -0
  84. qcodes/tests/test_combined_par.py +156 -0
  85. qcodes/tests/test_command.py +120 -0
  86. qcodes/tests/test_config.py +222 -0
  87. qcodes/tests/test_data.py +668 -0
  88. qcodes/tests/test_deferred_operations.py +105 -0
  89. qcodes/tests/test_driver_testcase.py +58 -0
  90. qcodes/tests/test_format.py +414 -0
  91. qcodes/tests/test_hdf5formatter.py +333 -0
  92. qcodes/tests/test_helpers.py +630 -0
  93. qcodes/tests/test_instrument.py +981 -0
  94. qcodes/tests/test_instrument_server.py +156 -0
  95. qcodes/tests/test_json.py +48 -0
  96. qcodes/tests/test_location_provider.py +109 -0
  97. qcodes/tests/test_loop.py +825 -0
  98. qcodes/tests/test_measure.py +49 -0
  99. qcodes/tests/test_metadata.py +49 -0
  100. qcodes/tests/test_multiprocessing.py +471 -0
  101. qcodes/tests/test_nested_attrs.py +100 -0
  102. qcodes/tests/test_parameter.py +151 -0
  103. qcodes/tests/test_plots.py +44 -0
  104. qcodes/tests/test_sweep_values.py +159 -0
  105. qcodes/tests/test_validators.py +482 -0
  106. qcodes/tests/test_visa.py +184 -0
  107. qcodes/utils/__init__.py +0 -0
  108. qcodes/utils/command.py +176 -0
  109. qcodes/utils/deferred_operations.py +276 -0
  110. qcodes/utils/helpers.py +417 -0
  111. qcodes/utils/metadata.py +42 -0
  112. qcodes/utils/nested_attrs.py +177 -0
  113. qcodes/utils/reload_code.py +98 -0
  114. qcodes/utils/threading.py +72 -0
  115. qcodes/utils/timing.py +89 -0
  116. qcodes/utils/validators.py +393 -0
  117. qcodes/version.py +1 -0
  118. qcodes/widgets/__init__.py +0 -0
  119. qcodes/widgets/display.py +47 -0
  120. qcodes/widgets/widgets.css +77 -0
  121. qcodes/widgets/widgets.js +237 -0
  122. qcodes/widgets/widgets.py +215 -0
  123. qcodes-0.1.0.dist-info/DESCRIPTION.rst +165 -0
  124. qcodes-0.1.0.dist-info/METADATA +194 -0
  125. qcodes-0.1.0.dist-info/RECORD +128 -0
  126. qcodes-0.1.0.dist-info/WHEEL +5 -0
  127. qcodes-0.1.0.dist-info/metadata.json +1 -0
  128. qcodes-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,668 @@
1
+ from unittest import TestCase
2
+ from unittest.mock import patch
3
+ import numpy as np
4
+ import os
5
+ import pickle
6
+ import logging
7
+
8
+ from qcodes.data.data_array import DataArray
9
+ from qcodes.data.manager import get_data_manager, NoData
10
+ from qcodes.data.io import DiskIO
11
+ from qcodes.data.data_set import load_data, new_data, DataMode, DataSet
12
+ from qcodes.process.helpers import kill_processes
13
+ from qcodes.utils.helpers import LogCapture
14
+ from qcodes import active_children
15
+
16
+ from .data_mocks import (MockDataManager, MockFormatter, MatchIO,
17
+ MockLive, MockArray, DataSet2D, DataSet1D,
18
+ DataSetCombined, RecordingMockFormatter)
19
+ from .common import strip_qc
20
+
21
+
22
+ class TestDataArray(TestCase):
23
+
24
+ def test_attributes(self):
25
+ pname = 'Betty Sue'
26
+ plabel = 'The best apple pie this side of Wenatchee'
27
+ pfullname = 'bert'
28
+
29
+ class MockParam:
30
+ name = pname
31
+ label = plabel
32
+
33
+ def __init__(self, full_name=None):
34
+ self.full_name = full_name
35
+
36
+ name = 'Oscar'
37
+ label = 'The grouch. GRR!'
38
+ fullname = 'ernie'
39
+ array_id = 24601
40
+ set_arrays = ('awesomeness', 'chocolate content')
41
+ shape = 'Ginornous'
42
+ action_indices = (1, 2, 3, 4, 5)
43
+
44
+ p_data = DataArray(parameter=MockParam(pfullname), name=name,
45
+ label=label, full_name=fullname)
46
+ p_data2 = DataArray(parameter=MockParam(pfullname))
47
+
48
+ # explicitly given name and label override parameter vals
49
+ self.assertEqual(p_data.name, name)
50
+ self.assertEqual(p_data.label, label)
51
+ self.assertEqual(p_data.full_name, fullname)
52
+ self.assertEqual(p_data2.name, pname)
53
+ self.assertEqual(p_data2.label, plabel)
54
+ self.assertEqual(p_data2.full_name, pfullname)
55
+ # test default values
56
+ self.assertIsNone(p_data.array_id)
57
+ self.assertEqual(p_data.shape, ())
58
+ self.assertEqual(p_data.action_indices, ())
59
+ self.assertEqual(p_data.set_arrays, ())
60
+ self.assertIsNone(p_data.ndarray)
61
+
62
+ np_data = DataArray(name=name, label=label, array_id=array_id,
63
+ set_arrays=set_arrays, shape=shape,
64
+ action_indices=action_indices)
65
+ self.assertEqual(np_data.name, name)
66
+ self.assertEqual(np_data.label, label)
67
+ # no full name or parameter - use name
68
+ self.assertEqual(np_data.full_name, name)
69
+ # test simple assignments
70
+ self.assertEqual(np_data.array_id, array_id)
71
+ self.assertEqual(np_data.set_arrays, set_arrays)
72
+ self.assertEqual(np_data.shape, shape)
73
+ self.assertEqual(np_data.action_indices, action_indices)
74
+
75
+ name_data = DataArray(name=name)
76
+ self.assertEqual(name_data.label, name)
77
+
78
+ blank_data = DataArray()
79
+ self.assertIsNone(blank_data.name)
80
+
81
+ def test_preset_data(self):
82
+ onetwothree = [
83
+ # lists and tuples work
84
+ [1.0, 2.0, 3.0],
85
+ (1.0, 2.0, 3.0),
86
+
87
+ # iterators get automatically cast to floats
88
+ (i + 1 for i in range(3)),
89
+ map(float, range(1, 4)),
90
+
91
+ # and of course numpy arrays themselves work
92
+ np.array([1.0, 2.0, 3.0]),
93
+ ]
94
+
95
+ expected123 = [1.0, 2.0, 3.0]
96
+
97
+ for item in onetwothree:
98
+ data = DataArray(preset_data=item)
99
+ self.assertEqual(data.ndarray.tolist(), expected123)
100
+ self.assertEqual(data.shape, (3, ))
101
+
102
+ # you can re-initialize a DataArray with the same shape data,
103
+ # but not with a different shape
104
+ list456 = [4, 5, 6]
105
+ data.init_data(data=list456)
106
+ self.assertEqual(data.ndarray.tolist(), list456)
107
+ with self.assertRaises(ValueError):
108
+ data.init_data([1, 2])
109
+ self.assertEqual(data.ndarray.tolist(), list456)
110
+ self.assertEqual(data.shape, (3, ))
111
+
112
+ # you can call init_data again with no data, and nothing changes
113
+ data.init_data()
114
+ self.assertEqual(data.ndarray.tolist(), list456)
115
+ self.assertEqual(data.shape, (3, ))
116
+
117
+ # multidimensional works too
118
+ list2d = [[1, 2], [3, 4]]
119
+ data2 = DataArray(preset_data=list2d)
120
+ self.assertEqual(data2.ndarray.tolist(), list2d)
121
+ self.assertEqual(data2.shape, (2, 2))
122
+
123
+ def test_init_data_error(self):
124
+ data = DataArray(preset_data=[1, 2])
125
+ data.shape = (3, )
126
+
127
+ # not sure when this would happen... but if you call init_data
128
+ # and it notices an inconsistency between shape and the actual
129
+ # data that's already there, it raises an error
130
+ with self.assertRaises(ValueError):
131
+ data.init_data()
132
+
133
+ def test_clear(self):
134
+ nan = float('nan')
135
+ data = DataArray(preset_data=[1, 2])
136
+ data.clear()
137
+ # sometimes it's annoying that nan != nan
138
+ self.assertEqual(repr(data.ndarray.tolist()), repr([nan, nan]))
139
+
140
+ def test_edit_and_mark(self):
141
+ data = DataArray(preset_data=[[1, 2], [3, 4]])
142
+ self.assertEqual(data[0].tolist(), [1, 2])
143
+ self.assertEqual(data[0, 1], 2)
144
+
145
+ data.modified_range = None
146
+ self.assertIsNone(data.last_saved_index)
147
+
148
+ self.assertEqual(len(data), 2)
149
+ data[0] = np.array([5, 6])
150
+ data[1, 0] = 7
151
+ self.assertEqual(data.ndarray.tolist(), [[5, 6], [7, 4]])
152
+
153
+ self.assertEqual(data.modified_range, (0, 2))
154
+
155
+ # as if we saved the first two points... the third should still
156
+ # show as modified
157
+ data.mark_saved(1)
158
+ self.assertEqual(data.last_saved_index, 1)
159
+ self.assertEqual(data.modified_range, (2, 2))
160
+
161
+ # now we save the third point... no modifications left.
162
+ data.mark_saved(2)
163
+ self.assertEqual(data.last_saved_index, 2)
164
+ self.assertEqual(data.modified_range, None)
165
+
166
+ data.clear_save()
167
+ self.assertEqual(data.last_saved_index, None)
168
+ self.assertEqual(data.modified_range, (0, 2))
169
+
170
+ def test_edit_and_mark_slice(self):
171
+ data = DataArray(preset_data=[[1] * 5] * 6)
172
+
173
+ self.assertEqual(data.shape, (6, 5))
174
+ data.modified_range = None
175
+
176
+ data[:4:2, 2:] = 2
177
+ self.assertEqual(data.tolist(), [
178
+ [1, 1, 2, 2, 2],
179
+ [1, 1, 1, 1, 1],
180
+ [1, 1, 2, 2, 2],
181
+ [1, 1, 1, 1, 1],
182
+ [1, 1, 1, 1, 1],
183
+ [1, 1, 1, 1, 1]
184
+ ])
185
+ self.assertEqual(data.modified_range, (2, 14))
186
+
187
+ def test_repr(self):
188
+ array2d = [[1, 2], [3, 4]]
189
+ arrayrepr = repr(np.array(array2d))
190
+ array_id = (3, 4)
191
+ data = DataArray(preset_data=array2d)
192
+
193
+ self.assertEqual(repr(data), 'DataArray[2,2]:\n' + arrayrepr)
194
+
195
+ data.array_id = array_id
196
+ self.assertEqual(repr(data), 'DataArray[2,2]: ' + str(array_id) +
197
+ '\n' + arrayrepr)
198
+
199
+ def test_nest_empty(self):
200
+ data = DataArray()
201
+
202
+ self.assertEqual(data.shape, ())
203
+
204
+ mock_set_array = 'not really an array but we don\'t check'
205
+ mock_set_array2 = 'another one'
206
+
207
+ data.nest(2, action_index=44, set_array=mock_set_array)
208
+ data.nest(3, action_index=66, set_array=mock_set_array2)
209
+
210
+ # the array doesn't exist until you initialize it
211
+ self.assertIsNone(data.ndarray)
212
+
213
+ # but other attributes are set
214
+ self.assertEqual(data.shape, (3, 2))
215
+ self.assertEqual(data.action_indices, (66, 44))
216
+ self.assertEqual(data.set_arrays, (mock_set_array2, mock_set_array))
217
+
218
+ data.init_data()
219
+ self.assertEqual(data.ndarray.shape, (3, 2))
220
+
221
+ # after initializing data, you can't nest anymore because this isn't
222
+ # a preset array
223
+ with self.assertRaises(RuntimeError):
224
+ data.nest(4)
225
+
226
+ def test_nest_preset(self):
227
+ data = DataArray(preset_data=[1, 2])
228
+ data.nest(3)
229
+ self.assertEqual(data.shape, (3, 2))
230
+ self.assertEqual(data.ndarray.tolist(), [[1, 2]] * 3)
231
+ self.assertEqual(data.action_indices, ())
232
+ self.assertEqual(data.set_arrays, (data,))
233
+
234
+ # test that the modified range gets correctly set to
235
+ # (0, 2*3-1 = 5)
236
+ self.assertEqual(data.modified_range, (0, 5))
237
+
238
+ # you need a set array for all but the inner nesting
239
+ with self.assertRaises(TypeError):
240
+ data.nest(4)
241
+
242
+ def test_data_set_property(self):
243
+ data = DataArray(preset_data=[1, 2])
244
+ self.assertIsNone(data.data_set)
245
+
246
+ mock_data_set = 'pretend this is a DataSet, we don\'t check type'
247
+ mock_data_set2 = 'you can only assign to another after first clearing'
248
+ data.data_set = mock_data_set
249
+ self.assertEqual(data.data_set, mock_data_set)
250
+
251
+ with self.assertRaises(RuntimeError):
252
+ data.data_set = mock_data_set2
253
+
254
+ data.data_set = None
255
+ self.assertIsNone(data.data_set)
256
+ data.data_set = mock_data_set2
257
+ self.assertEqual(data.data_set, mock_data_set2)
258
+
259
+ def test_fraction_complete(self):
260
+ data = DataArray(shape=(5, 10))
261
+ self.assertIsNone(data.ndarray)
262
+ self.assertEqual(data.fraction_complete(), 0.0)
263
+
264
+ data.init_data()
265
+ self.assertEqual(data.fraction_complete(), 0.0)
266
+
267
+ # index = 1 * 10 + 7 - add 1 (for index 0) and you get 18
268
+ # each index is 2% of the total, so this is 36%
269
+ data[1, 7] = 1
270
+ self.assertEqual(data.fraction_complete(), 18/50)
271
+
272
+ # add a last_saved_index but modified_range is still bigger
273
+ data.mark_saved(13)
274
+ self.assertEqual(data.fraction_complete(), 18/50)
275
+
276
+ # now last_saved_index wins
277
+ data.mark_saved(19)
278
+ self.assertEqual(data.fraction_complete(), 20/50)
279
+
280
+ # now pretend we get more info from syncing
281
+ data.synced_index = 22
282
+ self.assertEqual(data.fraction_complete(), 23/50)
283
+
284
+
285
+ class TestLoadData(TestCase):
286
+
287
+ def setUp(self):
288
+ kill_processes()
289
+
290
+ def test_no_live_data(self):
291
+ # live data with no DataManager at all
292
+ with self.assertRaises(RuntimeError):
293
+ load_data()
294
+ self.assertEqual(len(active_children()), 0)
295
+
296
+ # now make a DataManager and try again
297
+ get_data_manager()
298
+ self.assertEqual(len(active_children()), 1)
299
+ # same result but different code path
300
+ with self.assertRaises(RuntimeError):
301
+ load_data()
302
+
303
+ def test_no_saved_data(self):
304
+ with self.assertRaises(IOError):
305
+ load_data('_no/such/file_')
306
+
307
+ def test_load_false(self):
308
+ with self.assertRaises(ValueError):
309
+ load_data(False)
310
+
311
+ def test_get_live(self):
312
+ loc = 'live from New York!'
313
+
314
+ class MockLive:
315
+ pass
316
+
317
+ live_data = MockLive()
318
+
319
+ dm = MockDataManager()
320
+ dm.location = loc
321
+ dm.live_data = live_data
322
+
323
+ data = load_data(data_manager=dm, location=loc)
324
+ self.assertEqual(data, live_data)
325
+
326
+ for nd in (None, NoData()):
327
+ dm.live_data = nd
328
+ with self.assertRaises(RuntimeError):
329
+ load_data(data_manager=dm, location=loc)
330
+ with self.assertRaises(RuntimeError):
331
+ load_data(data_manager=dm)
332
+
333
+ def test_get_read(self):
334
+ dm = MockDataManager()
335
+ dm.location = 'somewhere else'
336
+
337
+ data = load_data(formatter=MockFormatter(), data_manager=dm,
338
+ location='here!')
339
+ self.assertEqual(data.has_read_data, True)
340
+ self.assertEqual(data.has_read_metadata, True)
341
+
342
+
343
+ class TestDataSetMetaData(TestCase):
344
+
345
+ def test_snapshot(self):
346
+ data = new_data(location=False)
347
+ expected_snap = {
348
+ '__class__': 'qcodes.data.data_set.DataSet',
349
+ 'location': False,
350
+ 'arrays': {},
351
+ 'formatter': 'qcodes.data.gnuplot_format.GNUPlotFormat',
352
+ }
353
+ snap = strip_qc(data.snapshot())
354
+
355
+ # handle io separately so we don't need to figure out our path
356
+ self.assertIn('DiskIO', snap['io'])
357
+ del snap['io']
358
+ self.assertEqual(snap, expected_snap)
359
+
360
+ # even though we removed io from the snapshot, it's still in .metadata
361
+ self.assertIn('io', data.metadata)
362
+
363
+ # then do the same transformations to metadata to check it too
364
+ del data.metadata['io']
365
+ strip_qc(data.metadata)
366
+ self.assertEqual(data.metadata, expected_snap)
367
+
368
+ # location is False so read_metadata should be a noop
369
+ data.metadata = {'food': 'Fried chicken'}
370
+ data.read_metadata()
371
+ self.assertEqual(data.metadata, {'food': 'Fried chicken'})
372
+
373
+ # snapshot should never delete things from metadata, only add or update
374
+ data.metadata['location'] = 'Idaho'
375
+ snap = strip_qc(data.snapshot())
376
+ expected_snap['food'] = 'Fried chicken'
377
+ del snap['io']
378
+ self.assertEqual(snap, expected_snap)
379
+
380
+
381
+ class TestNewData(TestCase):
382
+
383
+ @classmethod
384
+ def setUpClass(cls):
385
+ kill_processes()
386
+ cls.original_lp = DataSet.location_provider
387
+
388
+ @classmethod
389
+ def tearDownClass(cls):
390
+ DataSet.location_provider = cls.original_lp
391
+
392
+ def test_overwrite(self):
393
+ io = MatchIO([1])
394
+
395
+ with self.assertRaises(FileExistsError):
396
+ new_data(location='somewhere', io=io, data_manager=False)
397
+
398
+ data = new_data(location='somewhere', io=io, overwrite=True,
399
+ data_manager=False)
400
+ self.assertEqual(data.location, 'somewhere')
401
+
402
+ def test_mode_error(self):
403
+ with self.assertRaises(ValueError):
404
+ new_data(mode=DataMode.PUSH_TO_SERVER, data_manager=False)
405
+
406
+ def test_location_functions(self):
407
+ def my_location(io, record):
408
+ return 'data/{}'.format((record or {}).get('name') or 'LOOP!')
409
+
410
+ def my_location2(io, record):
411
+ name = (record or {}).get('name') or 'loop?'
412
+ return 'data/{}/folder'.format(name)
413
+
414
+ DataSet.location_provider = my_location
415
+
416
+ self.assertEqual(new_data(data_manager=False).location, 'data/LOOP!')
417
+ self.assertEqual(new_data(data_manager=False, name='cheese').location,
418
+ 'data/cheese')
419
+
420
+ data = new_data(data_manager=False, location=my_location2)
421
+ self.assertEqual(data.location, 'data/loop?/folder')
422
+ data = new_data(data_manager=False, location=my_location2,
423
+ name='iceCream')
424
+ self.assertEqual(data.location, 'data/iceCream/folder')
425
+
426
+
427
+ class TestDataSet(TestCase):
428
+
429
+ def tearDown(self):
430
+ kill_processes()
431
+
432
+ def test_constructor_errors(self):
433
+ # no location - only allowed with load_data
434
+ with self.assertRaises(ValueError):
435
+ DataSet()
436
+ # wrong type
437
+ with self.assertRaises(ValueError):
438
+ DataSet(location=42)
439
+
440
+ # OK to have location=False, but wrong mode
441
+ with self.assertRaises(ValueError):
442
+ DataSet(location=False, mode='happy')
443
+
444
+ @patch('qcodes.data.data_set.get_data_manager')
445
+ def test_from_server(self, gdm_mock):
446
+ mock_dm = MockDataManager()
447
+ gdm_mock.return_value = mock_dm
448
+ mock_dm.location = 'Mars'
449
+ mock_dm.live_data = MockLive()
450
+
451
+ # wrong location or False location - converts to local
452
+ data = DataSet(location='Jupiter', data_manager=True, mode=DataMode.PULL_FROM_SERVER)
453
+ self.assertEqual(data.mode, DataMode.LOCAL)
454
+
455
+ data = DataSet(location=False, data_manager=True, mode=DataMode.PULL_FROM_SERVER)
456
+ self.assertEqual(data.mode, DataMode.LOCAL)
457
+
458
+ # location matching server - stays in server mode
459
+ data = DataSet(location='Mars', data_manager=True, mode=DataMode.PULL_FROM_SERVER,
460
+ formatter=MockFormatter())
461
+ self.assertEqual(data.mode, DataMode.PULL_FROM_SERVER)
462
+ self.assertEqual(data.arrays, MockLive.arrays)
463
+
464
+ # cannot write except in LOCAL mode
465
+ with self.assertRaises(RuntimeError):
466
+ data.write()
467
+
468
+ # cannot finalize in PULL_FROM_SERVER mode
469
+ with self.assertRaises(RuntimeError):
470
+ data.finalize()
471
+
472
+ # now test when the server says it's not there anymore
473
+ mock_dm.location = 'Saturn'
474
+ data.sync()
475
+ self.assertEqual(data.mode, DataMode.LOCAL)
476
+ self.assertEqual(data.has_read_data, True)
477
+
478
+ # now it's LOCAL so we *can* write.
479
+ data.write()
480
+ self.assertEqual(data.has_written_data, True)
481
+
482
+ # location=False: write, read and sync are noops.
483
+ data.has_read_data = False
484
+ data.has_written_data = False
485
+ data.location = False
486
+ data.write()
487
+ data.read()
488
+ data.sync()
489
+ self.assertEqual(data.has_read_data, False)
490
+ self.assertEqual(data.has_written_data, False)
491
+
492
+ @patch('qcodes.data.data_set.get_data_manager')
493
+ def test_to_server(self, gdm_mock):
494
+ mock_dm = MockDataManager()
495
+ mock_dm.needs_restart = True
496
+ gdm_mock.return_value = mock_dm
497
+
498
+ data = DataSet(location='Venus', data_manager=True, mode=DataMode.PUSH_TO_SERVER)
499
+ self.assertEqual(mock_dm.needs_restart, False, data)
500
+ self.assertEqual(mock_dm.data_set, data)
501
+ self.assertEqual(data.data_manager, mock_dm)
502
+ self.assertEqual(data.mode, DataMode.PUSH_TO_SERVER)
503
+
504
+ # cannot write except in LOCAL mode
505
+ with self.assertRaises(RuntimeError):
506
+ data.write()
507
+
508
+ # now do what the DataServer does with this DataSet: init_on_server
509
+ # fails until there is an array
510
+ with self.assertRaises(RuntimeError):
511
+ data.init_on_server()
512
+
513
+ data.add_array(MockArray())
514
+ data.init_on_server()
515
+ self.assertEqual(data.noise.ready, True)
516
+
517
+ # we can only add a given array_id once
518
+ with self.assertRaises(ValueError):
519
+ data.add_array(MockArray())
520
+
521
+ def test_write_copy(self):
522
+ data = DataSet1D(location=False)
523
+ mockbase = os.path.abspath('some_folder')
524
+ data.io = DiskIO(mockbase)
525
+
526
+ mr = (2, 3)
527
+ mr_full = (0, 4)
528
+ lsi = 1
529
+ data.x_set.modified_range = mr
530
+ data.y.modified_range = mr
531
+ data.x_set.last_saved_index = lsi
532
+ data.y.last_saved_index = lsi
533
+
534
+ with self.assertRaises(TypeError):
535
+ data.write_copy()
536
+
537
+ with self.assertRaises(TypeError):
538
+ data.write_copy(path='some/path', io_manager=DiskIO('.'))
539
+
540
+ with self.assertRaises(TypeError):
541
+ data.write_copy(path='some/path', location='something/else')
542
+
543
+ data.formatter = RecordingMockFormatter()
544
+ data.write_copy(path='/some/abs/path')
545
+ self.assertEqual(data.formatter.write_calls,
546
+ [(None, '/some/abs/path')])
547
+ self.assertEqual(data.formatter.write_metadata_calls,
548
+ [(None, '/some/abs/path', False)])
549
+ # check that the formatter gets called as if nothing has been saved
550
+ self.assertEqual(data.formatter.modified_ranges,
551
+ [{'x_set': mr_full, 'y': mr_full}])
552
+ self.assertEqual(data.formatter.last_saved_indices,
553
+ [{'x_set': None, 'y': None}])
554
+ # but the dataset afterward has its original mods back
555
+ self.assertEqual(data.x_set.modified_range, mr)
556
+ self.assertEqual(data.y.modified_range, mr)
557
+ self.assertEqual(data.x_set.last_saved_index, lsi)
558
+ self.assertEqual(data.y.last_saved_index, lsi)
559
+
560
+ # recreate the formatter to clear the calls attributes
561
+ data.formatter = RecordingMockFormatter()
562
+ data.write_copy(location='some/rel/path')
563
+ self.assertEqual(data.formatter.write_calls,
564
+ [(mockbase, 'some/rel/path')])
565
+ self.assertEqual(data.formatter.write_metadata_calls,
566
+ [(mockbase, 'some/rel/path', False)])
567
+
568
+ mockbase2 = os.path.abspath('some/other/folder')
569
+ io2 = DiskIO(mockbase2)
570
+
571
+ with self.assertRaises(ValueError):
572
+ # if location=False we need to specify it in write_copy
573
+ data.write_copy(io_manager=io2)
574
+
575
+ data.location = 'yet/another/path'
576
+ data.formatter = RecordingMockFormatter()
577
+ data.write_copy(io_manager=io2)
578
+ self.assertEqual(data.formatter.write_calls,
579
+ [(mockbase2, 'yet/another/path')])
580
+ self.assertEqual(data.formatter.write_metadata_calls,
581
+ [(mockbase2, 'yet/another/path', False)])
582
+
583
+ def test_pickle_dataset(self):
584
+ # Test pickling of DataSet object
585
+ # If the data_manager is set to None, then the object should pickle.
586
+ m = DataSet2D()
587
+ pickle.dumps(m)
588
+
589
+ def test_fraction_complete(self):
590
+ empty_data = new_data(arrays=(), location=False)
591
+ self.assertEqual(empty_data.fraction_complete(), 0.0)
592
+
593
+ data = DataSetCombined(location=False)
594
+ self.assertEqual(data.fraction_complete(), 1.0)
595
+
596
+ # alter only the measured arrays, check that only these are used
597
+ # to calculate fraction_complete
598
+ data.y1.modified_range = (0, 0) # 1 of 2
599
+ data.y2.modified_range = (0, 0) # 1 of 2
600
+ data.z1.modified_range = (0, 2) # 3 of 6
601
+ data.z2.modified_range = (0, 2) # 3 of 6
602
+ self.assertEqual(data.fraction_complete(), 0.5)
603
+
604
+ # mark more things complete using last_saved_index and synced_index
605
+ data.y1.last_saved_index = 1 # 2 of 2
606
+ data.z1.synced_index = 5 # 6 of 6
607
+ self.assertEqual(data.fraction_complete(), 0.75)
608
+
609
+ def mock_sync(self):
610
+ # import pdb; pdb.set_trace()
611
+ i = self.sync_index
612
+ self.syncing_array[i] = i
613
+ self.sync_index = i + 1
614
+ return self.sync_index < self.syncing_array.size
615
+
616
+ def failing_func(self):
617
+ raise RuntimeError('it is called failing_func for a reason!')
618
+
619
+ def logging_func(self):
620
+ logging.info('background at index {}'.format(self.sync_index))
621
+
622
+ def test_complete(self):
623
+ array = DataArray(name='y', shape=(5,))
624
+ array.init_data()
625
+ data = new_data(arrays=(array,), location=False)
626
+ self.syncing_array = array
627
+ self.sync_index = 0
628
+ data.sync = self.mock_sync
629
+ bf = DataSet.background_functions
630
+ bf['fail'] = self.failing_func
631
+ bf['log'] = self.logging_func
632
+
633
+ with LogCapture() as logs:
634
+ # grab info and warnings but not debug messages
635
+ logging.getLogger().setLevel(logging.INFO)
636
+ data.complete(delay=0.001)
637
+
638
+ logs = logs.value
639
+
640
+ expected_logs = [
641
+ 'waiting for DataSet <False> to complete',
642
+ 'DataSet: 0% complete',
643
+ 'RuntimeError: it is called failing_func for a reason!',
644
+ 'background at index 1',
645
+ 'DataSet: 20% complete',
646
+ 'RuntimeError: it is called failing_func for a reason!',
647
+ 'background function fail failed twice in a row, removing it',
648
+ 'background at index 2',
649
+ 'DataSet: 40% complete',
650
+ 'background at index 3',
651
+ 'DataSet: 60% complete',
652
+ 'background at index 4',
653
+ 'DataSet: 80% complete',
654
+ 'background at index 5',
655
+ 'DataSet <False> is complete'
656
+ ]
657
+
658
+ log_index = 0
659
+ for line in expected_logs:
660
+ self.assertIn(line, logs, logs)
661
+ try:
662
+ log_index_new = logs.index(line, log_index)
663
+ except ValueError:
664
+ raise ValueError('line {} not found after {} in: \n {}'.format(
665
+ line, log_index, logs))
666
+ self.assertTrue(log_index_new >= log_index, logs)
667
+ log_index = log_index_new + len(line) + 1 # +1 for \n
668
+ self.assertEqual(log_index, len(logs), logs)