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
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import threading
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import zmq
|
|
7
|
+
import json
|
|
8
|
+
from uuid import uuid4
|
|
9
|
+
|
|
10
|
+
from qcodespp.data.data_set import DataSetPP
|
|
11
|
+
from qcodespp.data.data_array import DataArray
|
|
12
|
+
from qcodespp.utils.helpers import NumpyJSONEncoder
|
|
13
|
+
from qcodespp.parameters import Parameter
|
|
14
|
+
|
|
15
|
+
def live_plot(*args,data_set=None, data_items=None):
|
|
16
|
+
"""
|
|
17
|
+
Entry point for live plotting of qcodespp data.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
*args (DataSetPP, DataArray, Parameter, list, tuple): Positional arguments can be:
|
|
21
|
+
- ``DataSetPP``: The dataset to link to the live plot.
|
|
22
|
+
- ``DataArray`` or ``Parameter``: The data items to plot.
|
|
23
|
+
- A list or tuple of ``DataArray`` or ``Parameter`` objects to plot.
|
|
24
|
+
data_set (``DataSetPP``, optional): The ``DataSetPP`` to link to the live plot.
|
|
25
|
+
If not provided, it will try to use the default dataset.
|
|
26
|
+
If no data_set, one can add items to the plot, but the data will not be tracked.
|
|
27
|
+
data_items (Sequence[``DataArray``, ``Parameter``], optional): List of ``DataArray``
|
|
28
|
+
or ``Parameter`` objects to plot. If not provided, nothing will be plotted initially,
|
|
29
|
+
the user can use ``Plot.add()`` later.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
The ``Plot`` instance.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
if data_items is None:
|
|
36
|
+
data_items = []
|
|
37
|
+
|
|
38
|
+
for arg in args:
|
|
39
|
+
if isinstance(arg, DataSetPP):
|
|
40
|
+
data_set = arg
|
|
41
|
+
elif isinstance(arg, (DataArray, Parameter)):
|
|
42
|
+
data_items.append(arg)
|
|
43
|
+
elif isinstance(arg, (list, tuple)):
|
|
44
|
+
data_items.extend(arg)
|
|
45
|
+
|
|
46
|
+
plot = Plot()
|
|
47
|
+
if data_set is None and DataSetPP.default_dataset is not None:
|
|
48
|
+
data_set = DataSetPP.default_dataset
|
|
49
|
+
if data_set:
|
|
50
|
+
data_set.publisher=plot
|
|
51
|
+
if data_items:
|
|
52
|
+
new_items=[]
|
|
53
|
+
for item in data_items:
|
|
54
|
+
if isinstance(item, Parameter) and not data_set:
|
|
55
|
+
raise ValueError('Parameters only accepted to data_items if a data_set is also provided.')
|
|
56
|
+
elif isinstance(item, Parameter):
|
|
57
|
+
for array in data_set.arrays:
|
|
58
|
+
if item.full_name in array:
|
|
59
|
+
new_items.append(data_set.arrays[array])
|
|
60
|
+
elif isinstance(item, DataArray):
|
|
61
|
+
new_items.append(item)
|
|
62
|
+
if not data_set:
|
|
63
|
+
try: # Try ONE more time to link some kind of data set to the plot.
|
|
64
|
+
item.data_set.publisher = plot
|
|
65
|
+
except:
|
|
66
|
+
pass
|
|
67
|
+
else:
|
|
68
|
+
raise TypeError('data_items must be either DataArray or Parameter objects, not %s.' % type(item))
|
|
69
|
+
plot.add_multiple(*new_items)
|
|
70
|
+
|
|
71
|
+
return plot
|
|
72
|
+
|
|
73
|
+
class ControlListener(threading.Thread):
|
|
74
|
+
"""
|
|
75
|
+
ListenToClientTask
|
|
76
|
+
"""
|
|
77
|
+
def __init__(self, client_ready_event=None, port=8876):
|
|
78
|
+
self.client_ready_event = client_ready_event
|
|
79
|
+
self.context = zmq.Context()
|
|
80
|
+
self.socket = self.context.socket(zmq.SUB)
|
|
81
|
+
|
|
82
|
+
self.port = self.socket.bind_to_random_port('tcp://*',
|
|
83
|
+
min_port=port,
|
|
84
|
+
max_port=port+500,
|
|
85
|
+
max_tries=500)
|
|
86
|
+
|
|
87
|
+
self.socket.setsockopt(zmq.SUBSCRIBE, b'')
|
|
88
|
+
|
|
89
|
+
self.poller = zmq.Poller()
|
|
90
|
+
self.poller.register(self.socket, zmq.POLLIN)
|
|
91
|
+
|
|
92
|
+
threading.Thread.__init__(self)
|
|
93
|
+
|
|
94
|
+
self.running = True
|
|
95
|
+
|
|
96
|
+
def run(self):
|
|
97
|
+
while self.running:
|
|
98
|
+
socks = dict(self.poller.poll(1000))
|
|
99
|
+
if socks.get(self.socket) == zmq.POLLIN:
|
|
100
|
+
try:
|
|
101
|
+
msg = self.socket.recv_json()
|
|
102
|
+
ready = msg.get('client_ready', None)
|
|
103
|
+
if ready is True:
|
|
104
|
+
self.client_ready_event.set()
|
|
105
|
+
else:
|
|
106
|
+
pass
|
|
107
|
+
# print(msg)
|
|
108
|
+
except Exception:
|
|
109
|
+
print('ups ups ups')
|
|
110
|
+
|
|
111
|
+
self.socket.close()
|
|
112
|
+
self.context.term()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class Plot():
|
|
116
|
+
"""
|
|
117
|
+
Class to create live plot instances.
|
|
118
|
+
|
|
119
|
+
Most methods of this class should not be called directly; only add(), add_multiple(), clear() and close()
|
|
120
|
+
should be used by the user.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
title (str, optional): Title of the plot window.
|
|
124
|
+
name (str, optional): Name of the plot instance. If not provided, a random UUID will be used.
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
context = zmq.Context()
|
|
128
|
+
socket = context.socket(zmq.PUB)
|
|
129
|
+
|
|
130
|
+
port = 8876
|
|
131
|
+
port = socket.bind_to_random_port('tcp://*',
|
|
132
|
+
min_port=port,
|
|
133
|
+
max_port=port+20,
|
|
134
|
+
max_tries=100)
|
|
135
|
+
encoding = 'utf-8'
|
|
136
|
+
|
|
137
|
+
def __init__(self, title=None, name=None):
|
|
138
|
+
name = name or uuid4().hex
|
|
139
|
+
topic = 'qcodes.plot.'+name
|
|
140
|
+
self.topic = topic
|
|
141
|
+
self.metadata = {}
|
|
142
|
+
self.data_uuid = uuid4().hex
|
|
143
|
+
|
|
144
|
+
self.client_ready_event = threading.Event()
|
|
145
|
+
self.client_ready_event.clear()
|
|
146
|
+
|
|
147
|
+
self.control_task = ControlListener(self.client_ready_event)
|
|
148
|
+
self.control_task.start()
|
|
149
|
+
self.control_port = self.control_task.port
|
|
150
|
+
|
|
151
|
+
self.new_client()
|
|
152
|
+
|
|
153
|
+
ret = self.client_ready_event.wait(30)
|
|
154
|
+
if ret == False:
|
|
155
|
+
print('timeout for plot window.')
|
|
156
|
+
self.client_ready_event.clear()
|
|
157
|
+
|
|
158
|
+
self.set_title(title)
|
|
159
|
+
|
|
160
|
+
def publish(self, data, uuid=None):
|
|
161
|
+
jdata = json.dumps(data, cls=NumpyJSONEncoder)
|
|
162
|
+
uuid = uuid or ''
|
|
163
|
+
self.socket.send_multipart([self.topic.encode(self.encoding),
|
|
164
|
+
uuid.encode(self.encoding),
|
|
165
|
+
jdata.encode(self.encoding)])
|
|
166
|
+
|
|
167
|
+
def publish_data(self, data, uuid, meta, arrays):
|
|
168
|
+
jdata = json.dumps(data)
|
|
169
|
+
uuid = uuid or ''
|
|
170
|
+
jmeta = json.dumps(meta)
|
|
171
|
+
self.socket.send_multipart([self.topic.encode(self.encoding),
|
|
172
|
+
uuid.encode(self.encoding),
|
|
173
|
+
jdata.encode(self.encoding),
|
|
174
|
+
jmeta.encode(self.encoding),
|
|
175
|
+
*arrays])
|
|
176
|
+
|
|
177
|
+
def add_metadata(self, new_metadata, uuid=None):
|
|
178
|
+
data = {'metadata': new_metadata}
|
|
179
|
+
self.publish(data, uuid)
|
|
180
|
+
|
|
181
|
+
def store(self, loop_indices, ids_values, uuid):
|
|
182
|
+
data = {'data': {'values': ids_values,
|
|
183
|
+
'indices': loop_indices}}
|
|
184
|
+
self.publish(data, uuid)
|
|
185
|
+
|
|
186
|
+
def save_metadata(self, metadata, uuid=None):
|
|
187
|
+
self.add_metadata(metadata, uuid)
|
|
188
|
+
|
|
189
|
+
def finalize(self, uuid=None):
|
|
190
|
+
self.publish({'finalize': True}, uuid)
|
|
191
|
+
|
|
192
|
+
def new_client(self, name=None):
|
|
193
|
+
this_dir, this_filename = os.path.split(__file__)
|
|
194
|
+
client = os.path.join(this_dir, 'RemotePlotClient.py')
|
|
195
|
+
args = ['python',
|
|
196
|
+
client,
|
|
197
|
+
self.topic,
|
|
198
|
+
str(self.port),
|
|
199
|
+
str(self.control_port)]
|
|
200
|
+
|
|
201
|
+
print(' '.join(args))
|
|
202
|
+
|
|
203
|
+
DETACHED_PROCESS = 0x00000008
|
|
204
|
+
|
|
205
|
+
subprocess.Popen(args, creationflags=DETACHED_PROCESS)
|
|
206
|
+
|
|
207
|
+
def clear(self):
|
|
208
|
+
self.publish({'clear_plot': True})
|
|
209
|
+
|
|
210
|
+
def add_multiple(self,*z_params):
|
|
211
|
+
"""Add multiple ``DataArray`` s to the ``Plot``.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
*z_params (Sequence [DataArray]): DataArrays to be added to the Plot.
|
|
215
|
+
Each DataArray is added to a separate subplot.
|
|
216
|
+
"""
|
|
217
|
+
for i,z_param in enumerate(z_params):
|
|
218
|
+
self.add(z_param,subplot=i) #title=z_param.full_name,name=z_param.name,
|
|
219
|
+
|
|
220
|
+
def add(self, *args, x=None, y=None, z=None,
|
|
221
|
+
subplot=0, name=None, title=None, position=None,
|
|
222
|
+
relativeto=None, xlabel=None, ylabel=None, zlabel=None,
|
|
223
|
+
xunit=None, yunit=None, zunit=None, silent=True,linecuts=False,
|
|
224
|
+
symbol=None,#color=None, width=None, pen=False, brush=None,
|
|
225
|
+
size=None,# antialias=None,
|
|
226
|
+
**kwargs):
|
|
227
|
+
"""
|
|
228
|
+
Add a trace to the plot.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
*args (DataArray): positional arguments, can be:
|
|
232
|
+
- ``y`` or ``z``: specify just the 1D or 2D data independent parameter, with the setpoint
|
|
233
|
+
axis or axes implied from the DataSetPP setpoints.
|
|
234
|
+
- ``x, y`` or ``x, y, z``: specify all axes of the data.
|
|
235
|
+
x (DataArray, optional): x-axis data.
|
|
236
|
+
y (DataArray, optional): y-axis data.
|
|
237
|
+
z (DataArray, optional): z-axis data.
|
|
238
|
+
subplot (int, optional): Subplot index to add the trace to. Defaults to 0.
|
|
239
|
+
name (str, optional): Name of the trace. If not provided, the name of the DataArray will be used.
|
|
240
|
+
title (str, optional): Title of the trace. If not provided, the name of the DataArray will be used.
|
|
241
|
+
position (str): Position of the subplot in the plot window. Options are 'bottom', 'top', 'left', 'right', 'above', or 'below'.
|
|
242
|
+
relativeto (str, optional): Position relative to which the subplot should be placed.
|
|
243
|
+
xlabel (str, optional): Label for the x-axis. If not provided, the label of the DataArray will be used.
|
|
244
|
+
ylabel (str, optional): Label for the y-axis. If not provided, the label of the DataArray will be used.
|
|
245
|
+
zlabel (str, optional): Label for the z-axis. If not provided, the label of the DataArray will be used.
|
|
246
|
+
xunit (str, optional): Unit for the x-axis. If not provided, the unit of the DataArray will be used.
|
|
247
|
+
yunit (str, optional): Unit for the y-axis. If not provided, the unit of the DataArray will be used.
|
|
248
|
+
zunit (str, optional): Unit for the z-axis. If not provided, the unit of the DataArray will be used.
|
|
249
|
+
silent (bool, optional): If True, do not wait for the client to be ready. Defaults to True.
|
|
250
|
+
linecuts (bool, optional): If True, plot line cuts instead of a 2D image. Defaults to False.
|
|
251
|
+
symbol (str, optional): Symbol to use for the trace. Defaults to None.
|
|
252
|
+
size (int, optional): Size of the symbol. Defaults to None.
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
if x is not None:
|
|
256
|
+
kwargs['x'] = x
|
|
257
|
+
if y is not None:
|
|
258
|
+
kwargs['y'] = y
|
|
259
|
+
if z is not None:
|
|
260
|
+
kwargs['z'] = z
|
|
261
|
+
|
|
262
|
+
kwargs['xlabel'] = xlabel
|
|
263
|
+
kwargs['ylabel'] = ylabel
|
|
264
|
+
kwargs['zlabel'] = zlabel
|
|
265
|
+
kwargs['xunit'] = xunit
|
|
266
|
+
kwargs['yunit'] = yunit
|
|
267
|
+
kwargs['zunit'] = zunit
|
|
268
|
+
kwargs['name'] = name
|
|
269
|
+
|
|
270
|
+
self.expand_trace(args, kwargs)
|
|
271
|
+
|
|
272
|
+
x = kwargs.get('x', None)
|
|
273
|
+
y = kwargs.get('y', None)
|
|
274
|
+
z = kwargs.get('z', None)
|
|
275
|
+
|
|
276
|
+
uuid = None
|
|
277
|
+
|
|
278
|
+
arguments = {'subplot': subplot,
|
|
279
|
+
'title': title,
|
|
280
|
+
'position': position,
|
|
281
|
+
'relativeto': relativeto,
|
|
282
|
+
'linecuts':linecuts,
|
|
283
|
+
'symbol': symbol,
|
|
284
|
+
'size': size}#,
|
|
285
|
+
# 'color': color,
|
|
286
|
+
# 'width': width,
|
|
287
|
+
# 'pen': pen,
|
|
288
|
+
# 'brush': brush,
|
|
289
|
+
# 'size': size,
|
|
290
|
+
# 'antialias': antialias}
|
|
291
|
+
|
|
292
|
+
meta = []
|
|
293
|
+
arrays = []
|
|
294
|
+
|
|
295
|
+
uuid = self.data_uuid
|
|
296
|
+
|
|
297
|
+
snap_name = None
|
|
298
|
+
|
|
299
|
+
for arr_name, arr in zip(['x', 'y', 'z'], [x, y, z]):
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
shape = None
|
|
303
|
+
location = None
|
|
304
|
+
array_id = None
|
|
305
|
+
unit = None
|
|
306
|
+
label = None
|
|
307
|
+
|
|
308
|
+
if arr is not None:
|
|
309
|
+
if isinstance(arr, DataArray):
|
|
310
|
+
snap = arr.snapshot()
|
|
311
|
+
uuid = arr.data_set.uuid
|
|
312
|
+
|
|
313
|
+
location = getattr(arr.data_set, 'location', None)
|
|
314
|
+
label = snap.get('label', None)
|
|
315
|
+
if snap.get('unit',None) is not None:
|
|
316
|
+
unit = snap.get('unit', None)
|
|
317
|
+
elif snap.get('units', None) is not None:
|
|
318
|
+
unit = snap.get('units',None)
|
|
319
|
+
snap_name = snap.get('name', None)
|
|
320
|
+
shape = snap.get('shape', None)
|
|
321
|
+
array_id = arr.array_id
|
|
322
|
+
else:
|
|
323
|
+
array_id = uuid4().hex
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
unit = kwargs.get('%sunit'%arr_name, None) or unit
|
|
327
|
+
label = kwargs.get('%slabel'%arr_name, None) or label
|
|
328
|
+
|
|
329
|
+
arguments['%s_info'%arr_name] = {}
|
|
330
|
+
arguments['%s_info'%arr_name]['location'] = location
|
|
331
|
+
arguments['%s_info'%arr_name]['label'] = label
|
|
332
|
+
arguments['%s_info'%arr_name]['unit'] = unit
|
|
333
|
+
arguments['%s_info'%arr_name]['shape'] = shape
|
|
334
|
+
arguments['%s_info'%arr_name]['name'] = snap_name or name
|
|
335
|
+
arguments['%s_info'%arr_name]['array_id'] = array_id
|
|
336
|
+
arguments['name'] = name or snap_name
|
|
337
|
+
|
|
338
|
+
for arr_name, arr in zip(['x', 'y', 'z'], [x, y, z]):
|
|
339
|
+
if arr is not None:
|
|
340
|
+
if isinstance(arr, DataArray):
|
|
341
|
+
ndarr = arr.ndarray
|
|
342
|
+
if isinstance(arr, np.ndarray):
|
|
343
|
+
ndarr = arr
|
|
344
|
+
else:
|
|
345
|
+
try:
|
|
346
|
+
ndarr = np.array(arr)
|
|
347
|
+
except:
|
|
348
|
+
continue
|
|
349
|
+
|
|
350
|
+
if (~np.isnan(ndarr)).any():
|
|
351
|
+
arrays.append(ndarr)
|
|
352
|
+
arguments['%s_info'%arr_name]['shape'] = ndarr.shape
|
|
353
|
+
arguments['%s_info'%arr_name]['name']
|
|
354
|
+
|
|
355
|
+
meta.append({'array_id': arguments['%s_info'%arr_name]['array_id'],
|
|
356
|
+
'shape': ndarr.shape,
|
|
357
|
+
'dtype': str(ndarr.dtype)})
|
|
358
|
+
|
|
359
|
+
if len(arrays) > 0:
|
|
360
|
+
self.publish_data({'add_plot': arguments},
|
|
361
|
+
uuid, meta, arrays)
|
|
362
|
+
else:
|
|
363
|
+
self.publish({'add_plot': arguments}, uuid)
|
|
364
|
+
|
|
365
|
+
if not silent:
|
|
366
|
+
# self.client_ready_event.clear()
|
|
367
|
+
# return
|
|
368
|
+
ret = self.client_ready_event.wait(30)
|
|
369
|
+
if ret == False:
|
|
370
|
+
print('plot timed out!')
|
|
371
|
+
self.client_ready_event.clear()
|
|
372
|
+
|
|
373
|
+
def expand_trace(self, args, kwargs):
|
|
374
|
+
"""
|
|
375
|
+
Complete the x, y (and possibly z) data definition for a trace.
|
|
376
|
+
|
|
377
|
+
Also modifies kwargs in place so that all the data needed to fully specify the
|
|
378
|
+
trace is present (ie either x and y or x and y and z)
|
|
379
|
+
|
|
380
|
+
Both ``__init__`` (for the first trace) and the ``add`` method support multiple
|
|
381
|
+
ways to specify the data in the trace:
|
|
382
|
+
|
|
383
|
+
As args:
|
|
384
|
+
- ``add(y)`` or ``add(z)`` specify just the main 1D or 2D data, with the setpoint
|
|
385
|
+
axis or axes implied.
|
|
386
|
+
- ``add(x, y)`` or ``add(x, y, z)`` specify all axes of the data.
|
|
387
|
+
And as kwargs:
|
|
388
|
+
- ``add(x=x, y=y, z=z)`` you specify exactly the data you want on each axis.
|
|
389
|
+
Any but the last (y or z) can be omitted, which allows for all of the same
|
|
390
|
+
forms as with args, plus x and z or y and z, with just one axis implied from
|
|
391
|
+
the setpoints of the z data.
|
|
392
|
+
|
|
393
|
+
This method takes any of those forms and converts them into a complete set of
|
|
394
|
+
kwargs, containing all of the explicit or implied data to be used in plotting this trace.
|
|
395
|
+
|
|
396
|
+
Args:
|
|
397
|
+
args (Tuple[DataArray]): positional args, as passed to either ``__init__`` or ``add``
|
|
398
|
+
kwargs (Dict(DataArray]): keyword args, as passed to either ``__init__`` or ``add``.
|
|
399
|
+
kwargs may contain non-data items in keys other than x, y, and z.
|
|
400
|
+
|
|
401
|
+
Raises:
|
|
402
|
+
ValueError: if the shape of the data does not match that of args
|
|
403
|
+
ValueError: if the data is provided twice
|
|
404
|
+
"""
|
|
405
|
+
# TODO(giulioungaretti): replace with an explicit version:
|
|
406
|
+
# return the new kwargs instead of modifying in place
|
|
407
|
+
# TODO this should really be a static method
|
|
408
|
+
if args:
|
|
409
|
+
if hasattr(args[-1][0], '__len__'):
|
|
410
|
+
# 2D (or higher... but ignore this for now)
|
|
411
|
+
# this test works for both numpy arrays and bare sequences
|
|
412
|
+
axletters = 'xyz'
|
|
413
|
+
ndim = 2
|
|
414
|
+
else:
|
|
415
|
+
axletters = 'xy'
|
|
416
|
+
ndim = 1
|
|
417
|
+
|
|
418
|
+
if len(args) not in (1, len(axletters)):
|
|
419
|
+
raise ValueError('{}D data needs 1 or {} unnamed args'.format(
|
|
420
|
+
ndim, len(axletters)))
|
|
421
|
+
|
|
422
|
+
arg_axletters = axletters[-len(args):]
|
|
423
|
+
|
|
424
|
+
for arg, arg_axletters in zip(args, arg_axletters):
|
|
425
|
+
# if arg_axletters in kwargs:
|
|
426
|
+
# raise ValueError(arg_axletters + ' data provided twice')
|
|
427
|
+
kwargs[arg_axletters] = arg
|
|
428
|
+
|
|
429
|
+
# reset axletters, we may or may not have found them above
|
|
430
|
+
axletters = 'xyz' if 'z' in kwargs else 'xy'
|
|
431
|
+
main_data = kwargs.get(axletters[-1], None)
|
|
432
|
+
|
|
433
|
+
if hasattr(main_data, 'set_arrays'):
|
|
434
|
+
num_axes = len(axletters) - 1
|
|
435
|
+
# things will probably fail if we try to plot arrays of the
|
|
436
|
+
# wrong dimension... but we'll give it a shot anyway.
|
|
437
|
+
set_arrays = main_data.set_arrays[-num_axes:]
|
|
438
|
+
# for 2D: y is outer loop, which is earlier in set_arrays,
|
|
439
|
+
# and x is the inner loop... is this the right convention?
|
|
440
|
+
# Merlin: Not in my view, I step on x-axis and do many
|
|
441
|
+
# y-sweeps, thus removed this reversing here.
|
|
442
|
+
set_axletters = axletters[:-1]
|
|
443
|
+
for axletter, set_array in zip(set_axletters, set_arrays):
|
|
444
|
+
if axletter not in kwargs:
|
|
445
|
+
kwargs[axletter] = set_array
|
|
446
|
+
|
|
447
|
+
def set_title(self, title):
|
|
448
|
+
self.publish({'set_title': title})
|
|
449
|
+
|
|
450
|
+
def set_cmap(self, cmap):
|
|
451
|
+
self.publish({'set_cmap': cmap})
|
|
452
|
+
|
|
453
|
+
def save(self, filename=None, subplot=None):
|
|
454
|
+
self.publish({'save_screenshot': {'filename': str(filename), 'subplot': subplot}})
|
|
455
|
+
# print('Should save a screenshot of the plot now')
|
|
456
|
+
|
|
457
|
+
def set_xlabel(self, label, subplot=0):
|
|
458
|
+
print('Should set the x-label of a subplot now')
|
|
459
|
+
|
|
460
|
+
def set_ylabel(self, label, subplot=0):
|
|
461
|
+
print('Should set the y-label of a subplot now')
|
|
462
|
+
|
|
463
|
+
def set_geometry(self, height, width, x0, y0):
|
|
464
|
+
# like other qt takes it:
|
|
465
|
+
print('Should set the geometry of the window now')
|
|
466
|
+
|
|
467
|
+
def close(self):
|
|
468
|
+
self.publish({'close_client': True})
|
|
469
|
+
print('Should close the plot window now')
|