• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

feihoo87 / waveforms / 7442221979

08 Jan 2024 01:47AM UTC coverage: 33.345% (-0.05%) from 33.393%
7442221979

push

github

feihoo87
update

0 of 15 new or added lines in 1 file covered. (0.0%)

24 existing lines in 2 files now uncovered.

2795 of 8382 relevant lines covered (33.35%)

2.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/waveforms/visualization/plot_layout.py
1
import functools
×
2
import operator
×
3

4
import matplotlib.pyplot as plt
×
5
import numpy as np
×
6
from matplotlib import cm
×
7
from matplotlib.colors import Normalize
×
8

9
layout_example = {
×
10
    'qubits': {
11
        'Q0': {
12
            'pos': (0, 1)
13
        },
14
        'Q1': {
15
            'pos': (1, 0)
16
        },
17
        'Q2': {
18
            'pos': (0, -1)
19
        },
20
        'Q3': {
21
            'pos': (-1, 0)
22
        }
23
    },
24
    'couplers': {
25
        'C0': {
26
            'qubits': ['Q0', 'Q1'],
27
        },
28
        'C1': {
29
            'qubits': ['Q1', 'Q2'],
30
        },
31
        'C2': {
32
            'qubits': ['Q2', 'Q3'],
33
        },
34
        'C3': {
35
            'qubits': ['Q0', 'Q3'],
36
        }
37
    }
38
}
39

40

41
def complete_layout(layout):
×
42
    for c in layout['couplers']:
×
43
        qubits = layout['couplers'][c]['qubits']
×
44
        for q in qubits:
×
45
            if q not in layout['qubits']:
×
46
                raise ValueError('qubit {} not found'.format(q))
×
47
            if 'couplers' not in layout['qubits'][q]:
×
48
                layout['qubits'][q]['couplers'] = []
×
49
            if c not in layout['qubits'][q]['couplers']:
×
50
                layout['qubits'][q]['couplers'].append(c)
×
51
    return layout
×
52

53

54
def get_shared_coupler(layout, q1, q2):
×
55
    for c in layout['qubits'][q1]['couplers']:
×
56
        if q2 in layout['couplers'][c]['qubits']:
×
57
            return c
×
58
    return None
×
59

60

61
def get_neighbours(layout,
×
62
                   qubit_or_coupler,
63
                   distance=1,
64
                   type='qubit',
65
                   inrange=False):
66

67
    def _qubits(couplers):
×
68
        ret = set()
×
69
        for c in couplers:
×
70
            ret = ret | set(layout['couplers'][c]['qubits'])
×
71
        return ret
×
72

73
    def _couplers(qubits):
×
74
        ret = set()
×
75
        for q in qubits:
×
76
            ret = ret | set(layout['qubits'][q]['couplers'])
×
77
        return ret
×
78

79
    couplers = []
×
80
    neighbors = []
×
81

82
    if qubit_or_coupler in layout['qubits']:
×
83
        couplers.append(set(layout['qubits'][qubit_or_coupler]['couplers']))
×
84
        neighbors.append(_qubits(couplers[0]) - {qubit_or_coupler})
×
85
    elif qubit_or_coupler in layout['couplers']:
×
86
        if type == 'coupler':
×
87
            distance += 1
×
88
        neighbors.append(set(layout['couplers'][qubit_or_coupler]['qubits']))
×
89
        couplers.append({qubit_or_coupler})
×
90
    else:
91
        raise ValueError(f'qubit or coupler {qubit_or_coupler!r} not found')
×
92
    distance -= 1
×
93

94
    while distance > 0:
×
95
        couplers.append(_couplers(neighbors[-1]) - couplers[-1])
×
96
        neighbors.append(_qubits(couplers[-1]) - neighbors[-1])
×
97
        distance -= 1
×
98

99
    if type == 'qubit':
×
100
        if inrange:
×
101
            return list(functools.reduce(operator.or_, neighbors, set()))
×
102
        else:
103
            return list(neighbors[-1])
×
104
    elif type == 'coupler':
×
105
        if inrange:
×
106
            if qubit_or_coupler in couplers[0]:
×
107
                couplers = couplers[1:]
×
108
            return list(functools.reduce(operator.or_, couplers, set()))
×
109
        else:
110
            return list(couplers[-1])
×
111
    else:
112
        raise ValueError("type must be 'qubit' or 'coupler'")
×
113

114

115
def plot_range(ax,
×
116
               path,
117
               text='',
118
               color=None,
119
               text_color='k',
120
               bounder_color='k',
121
               lw=0.5,
122
               fontsize=9):
123
    x, y = path
×
124
    center = x.mean(), y.mean()
×
125

126
    if color:
×
127
        ax.fill(x, y, color=color, lw=0)
×
128

129
    if lw is not None and lw > 0:
×
130
        ax.plot(np.hstack([x, [x[0]]]),
×
131
                np.hstack([y, [y[0]]]),
132
                color=bounder_color,
133
                lw=lw)
134

135
    if text:
×
136
        ax.text(center[0],
×
137
                center[1],
138
                text,
139
                ha='center',
140
                va='center',
141
                color=text_color,
142
                fontsize=fontsize)
143

144

145
def circle_path(pos, r, n=40):
×
146
    x, y = pos
×
147
    t = 2 * np.pi * np.linspace(0, 1, n, endpoint=False)
×
148
    xx = r * np.cos(t) + x
×
149
    yy = r * np.sin(t) + y
×
150
    return xx, yy
×
151

152

153
def circle_link_path(pos1, pos2, r1, r2, width, n=20):
×
154
    width = min(2 * max(r1, r2), width)
×
155

156
    x1, y1 = pos1
×
157
    x2, y2 = pos2
×
158

159
    phi = np.arctan2(y2 - y1, x2 - x1)
×
160

161
    theta1 = np.arcsin(width / 2 / r1)
×
162
    theta2 = np.arcsin(width / 2 / r2)
×
163

164
    t = np.linspace(-theta1, theta1, n) + phi
×
165
    xx1 = r1 * np.cos(t) + x1
×
166
    yy1 = r1 * np.sin(t) + y1
×
167

168
    t = np.linspace(-theta2, theta2, n) + phi + np.pi
×
169
    xx2 = r2 * np.cos(t) + x2
×
170
    yy2 = r2 * np.sin(t) + y2
×
171

172
    return np.hstack([xx2[-1], xx1,
×
173
                      xx2[:-1]]), np.hstack([yy2[-1], yy1, yy2[:-1]])
174

175

176
def circle_half_directed_link_path(pos1, pos2, r1, r2, width, n=20):
×
177
    width = min(max(r1, r2), width)
×
178

179
    x1, y1 = pos1
×
180
    x2, y2 = pos2
×
181

182
    phi = np.arctan2(y2 - y1, x2 - x1)
×
183

184
    theta1 = np.arcsin(width / r1)
×
185
    theta2 = np.arcsin(width / r2)
×
186

187
    t = np.linspace(0.2 * theta1, theta1, n) + phi
×
188
    xx1 = r1 * np.cos(t) + x1
×
189
    yy1 = r1 * np.sin(t) + y1
×
190

191
    t = np.linspace(-theta2, -0.2 * theta2, n) + phi + np.pi
×
192
    xx2 = r2 * np.cos(t) + x2
×
193
    yy2 = r2 * np.sin(t) + y2
×
194

195
    v = (xx2[0] - xx1[-1]) + 1j * (yy2[0] - yy1[-1])
×
196
    c = (xx2[0] + xx1[-1]) / 2 + 1j * (yy2[0] + yy1[-1]) / 2
×
197

198
    a = np.array([1 / 6, 1 / 12]) + 1j * np.array([0, 0.4 * width / np.abs(v)])
×
199
    a = a * v + c
×
200

201
    return np.hstack([xx2[-1], xx1, a.real,
×
202
                      xx2[:-1]]), np.hstack([yy2[-1], yy1, a.imag, yy2[:-1]])
203

204

205
def draw(layout, ax=None, qubit_cbar=True, coupler_cbar=True, origin='upper'):
×
206
    if ax is None:
×
207
        ax = plt.gca()
×
208

209
    for qubit in layout['qubits'].values():
×
210
        pos = qubit['pos']
×
211
        if origin == 'upper':
×
212
            pos = pos[0], -pos[1]
×
213
        path = circle_path(pos, qubit.get('radius', 0.5))
×
214
        plot_range(ax,
×
215
                   path,
216
                   qubit.get('text', ''),
217
                   qubit.get('color', None),
218
                   lw=qubit.get('lw', 0.5),
219
                   fontsize=qubit.get('fontsize', 9),
220
                   text_color=qubit.get('text_color', 'k'),
221
                   bounder_color=qubit.get('bounder_color', 'k'))
222

223
    for coupler in layout['couplers'].values():
×
224
        q1, q2 = coupler['qubits']
×
225
        pos1 = layout['qubits'][q1]['pos']
×
226
        pos2 = layout['qubits'][q2]['pos']
×
227
        if origin == 'upper':
×
228
            pos1 = pos1[0], -pos1[1]
×
229
            pos2 = pos2[0], -pos2[1]
×
230
        r1 = layout['qubits'][q1].get('radius', 0.5)
×
231
        r2 = layout['qubits'][q2].get('radius', 0.5)
×
232
        width = coupler.get('width', 0.5)
×
233
        lw = coupler.get('lw', 0.5)
×
234

235
        path = circle_link_path(pos1, pos2, r1, r2, width)
×
236
        plot_range(ax,
×
237
                   path,
238
                   coupler.get('text', ''),
239
                   color=coupler.get('color', None),
240
                   lw=0,
241
                   fontsize=coupler.get('fontsize', 9),
242
                   text_color=coupler.get('text_color', 'k'))
243
        if lw > 0:
×
244
            x, y = circle_link_path(pos1, pos2, r1, r2, width, n=2)
×
245
            ax.plot(x[:2],
×
246
                    y[:2],
247
                    lw=lw,
248
                    color=coupler.get('bounder_color', 'k'))
249
            ax.plot(x[2:],
×
250
                    y[2:],
251
                    lw=lw,
252
                    color=coupler.get('bounder_color', 'k'))
253

254
    ax.axis('equal')
×
255
    ax.set_axis_off()
×
256

257
    if qubit_cbar and layout['__colorbar__']['qubit']['norm'] is not None:
×
258
        cbar = plt.colorbar(cm.ScalarMappable(
×
259
            norm=layout['__colorbar__']['qubit']['norm'],
260
            cmap=layout['__colorbar__']['qubit']['cmap']),
261
                            ax=ax,
262
                            location='bottom',
263
                            orientation='horizontal',
264
                            pad=0.01,
265
                            shrink=0.5)
266
        cbar.set_label(layout['__colorbar__']['qubit']['label'])
×
267
    if coupler_cbar and layout['__colorbar__']['coupler']['norm'] is not None:
×
268
        cbar = plt.colorbar(cm.ScalarMappable(
×
269
            norm=layout['__colorbar__']['coupler']['norm'],
270
            cmap=layout['__colorbar__']['coupler']['cmap']),
271
                            ax=ax,
272
                            location='bottom',
273
                            orientation='horizontal',
274
                            pad=0.01,
275
                            shrink=0.5)
276
        cbar.set_label(layout['__colorbar__']['coupler']['label'])
×
277

278

279
def get_norm(params, elms, vmin=None, vmax=None):
×
280
    data = []
×
281
    for elm in elms:
×
282
        if elm in params:
×
283
            if isinstance(params[elm], (int, float)):
×
284
                data.append(params[elm])
×
285
            elif 'value' in params[elm] and params[elm]['value'] is not None:
×
286
                data.append(params[elm]['value'])
×
287
    if data:
×
288
        if vmin is None:
×
289
            vmin = min(data)
×
290
        if vmax is None:
×
291
            vmax = max(data)
×
292
        return Normalize(vmin=vmin, vmax=vmax)
×
293
    else:
294
        return None
×
295

296

297
def fill_layout(layout,
×
298
                params,
299
                qubit_size=0.5,
300
                coupler_size=0.5,
301
                qubit_fontsize=9,
302
                coupler_fontsize=9,
303
                qubit_color=None,
304
                coupler_color=None,
305
                qubit_cmap='hot',
306
                qubit_vmax=None,
307
                qubit_vmin=None,
308
                qubit_norm=None,
309
                coupler_cmap='binary',
310
                coupler_vmax=None,
311
                coupler_vmin=None,
312
                coupler_norm=None,
313
                bounder_color='k',
314
                lw=0.5):
315

UNCOV
316
    qubit_cmap = plt.get_cmap(qubit_cmap)
×
317
    coupler_cmap = plt.get_cmap(coupler_cmap)
×
318

UNCOV
319
    if qubit_norm is None:
×
UNCOV
320
        qubit_norm = get_norm(params,
×
321
                              layout['qubits'].keys(),
322
                              vmin=qubit_vmin,
323
                              vmax=qubit_vmax)
UNCOV
324
    if coupler_norm is None:
×
325
        coupler_norm = get_norm(params,
×
326
                                layout['couplers'].keys(),
327
                                vmin=coupler_vmin,
328
                                vmax=coupler_vmax)
UNCOV
329
    layout['__colorbar__'] = {
×
330
        'coupler': {
331
            'cmap': coupler_cmap,
332
            'norm': coupler_norm,
333
            'label': ''
334
        },
335
        'qubit': {
336
            'cmap': qubit_cmap,
337
            'norm': qubit_norm,
338
            'label': ''
339
        }
340
    }
341

342
    for qubit in layout['qubits']:
×
343
        layout['qubits'][qubit]['radius'] = qubit_size
×
344
        layout['qubits'][qubit]['fontsize'] = qubit_fontsize
×
345
        if qubit in params:
×
346
            layout['qubits'][qubit]['lw'] = 0
×
347
            if not isinstance(params[qubit], dict):
×
UNCOV
348
                params[qubit] = {'value': params[qubit]}
×
349
            if 'color' in params[qubit]:
×
UNCOV
350
                layout['qubits'][qubit]['color'] = params[qubit]['color']
×
UNCOV
351
            elif 'value' in params[qubit] and params[qubit][
×
352
                    'value'] is not None:
353
                layout['qubits'][qubit]['color'] = qubit_cmap(
×
354
                    qubit_norm(params[qubit]['value']))
355
            else:
UNCOV
356
                layout['qubits'][qubit]['color'] = qubit_color
×
357
                if qubit_color is None:
×
UNCOV
358
                    layout['qubits'][qubit]['lw'] = lw
×
359
            layout['qubits'][qubit]['radius'] = params[qubit].get(
×
360
                'radius', qubit_size)
UNCOV
361
            layout['qubits'][qubit]['fontsize'] = params[qubit].get(
×
362
                'fontsize', qubit_fontsize)
363
            layout['qubits'][qubit]['text'] = params[qubit].get('text', '')
×
364
            layout['qubits'][qubit]['text_color'] = params[qubit].get(
×
365
                'text_color', 'k')
366
        else:
367
            layout['qubits'][qubit]['color'] = qubit_color
×
368
            if qubit_color is None:
×
UNCOV
369
                layout['qubits'][qubit]['lw'] = lw
×
370
            else:
371
                layout['qubits'][qubit]['lw'] = 0
×
372
            layout['qubits'][qubit]['bounder_color'] = bounder_color
×
373

374
    for coupler in layout['couplers']:
×
375
        layout['couplers'][coupler]['width'] = coupler_size
×
376
        layout['couplers'][coupler]['fontsize'] = coupler_fontsize
×
377
        layout['couplers'][coupler]['bounder_color'] = bounder_color
×
378
        if coupler in params:
×
379
            layout['couplers'][coupler]['lw'] = 0
×
380
            if not isinstance(params[coupler], dict):
×
UNCOV
381
                params[coupler] = {'value': params[coupler]}
×
382
            if 'color' in params[coupler]:
×
UNCOV
383
                layout['couplers'][coupler]['color'] = params[coupler]['color']
×
UNCOV
384
            elif 'value' in params[coupler] and params[coupler][
×
385
                    'value'] is not None:
386
                layout['couplers'][coupler]['color'] = coupler_cmap(
×
387
                    coupler_norm(params[coupler]['value']))
388
            else:
UNCOV
389
                layout['couplers'][coupler]['color'] = coupler_color
×
390
                if coupler_color is None:
×
UNCOV
391
                    layout['couplers'][qubit]['lw'] = lw
×
392
            layout['couplers'][coupler]['width'] = params[coupler].get(
×
393
                'width', coupler_size)
394
            layout['couplers'][coupler]['fontsize'] = params[coupler].get(
×
395
                'fontsize', coupler_fontsize)
UNCOV
396
            layout['couplers'][coupler]['text'] = params[coupler].get(
×
397
                'text', '')
398
            layout['couplers'][coupler]['text_color'] = params[coupler].get(
×
399
                'text_color', 'k')
400
        else:
401
            layout['couplers'][coupler]['color'] = coupler_color
×
402
            if coupler_color is None:
×
UNCOV
403
                layout['couplers'][coupler]['lw'] = lw
×
404
            else:
UNCOV
405
                layout['couplers'][coupler]['lw'] = 0
×
UNCOV
406
            layout['couplers'][coupler]['bounder_color'] = bounder_color
×
407

UNCOV
408
    return layout
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc