QuLab 2.11.6__tar.gz → 2.11.7__tar.gz

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 (115) hide show
  1. {qulab-2.11.6 → qulab-2.11.7}/PKG-INFO +1 -1
  2. {qulab-2.11.6 → qulab-2.11.7}/QuLab.egg-info/PKG-INFO +1 -1
  3. qulab-2.11.7/qulab/version.py +1 -0
  4. {qulab-2.11.6 → qulab-2.11.7}/qulab/visualization/plot_layout.py +179 -51
  5. {qulab-2.11.6 → qulab-2.11.7}/qulab/visualization/rot3d.py +28 -2
  6. qulab-2.11.6/qulab/version.py +0 -1
  7. {qulab-2.11.6 → qulab-2.11.7}/LICENSE +0 -0
  8. {qulab-2.11.6 → qulab-2.11.7}/MANIFEST.in +0 -0
  9. {qulab-2.11.6 → qulab-2.11.7}/QuLab.egg-info/SOURCES.txt +0 -0
  10. {qulab-2.11.6 → qulab-2.11.7}/QuLab.egg-info/dependency_links.txt +0 -0
  11. {qulab-2.11.6 → qulab-2.11.7}/QuLab.egg-info/entry_points.txt +0 -0
  12. {qulab-2.11.6 → qulab-2.11.7}/QuLab.egg-info/requires.txt +0 -0
  13. {qulab-2.11.6 → qulab-2.11.7}/QuLab.egg-info/top_level.txt +0 -0
  14. {qulab-2.11.6 → qulab-2.11.7}/README.md +0 -0
  15. {qulab-2.11.6 → qulab-2.11.7}/pyproject.toml +0 -0
  16. {qulab-2.11.6 → qulab-2.11.7}/qulab/__init__.py +0 -0
  17. {qulab-2.11.6 → qulab-2.11.7}/qulab/__main__.py +0 -0
  18. {qulab-2.11.6 → qulab-2.11.7}/qulab/cli/__init__.py +0 -0
  19. {qulab-2.11.6 → qulab-2.11.7}/qulab/cli/commands.py +0 -0
  20. {qulab-2.11.6 → qulab-2.11.7}/qulab/cli/config.py +0 -0
  21. {qulab-2.11.6 → qulab-2.11.7}/qulab/cli/decorators.py +0 -0
  22. {qulab-2.11.6 → qulab-2.11.7}/qulab/executor/__init__.py +0 -0
  23. {qulab-2.11.6 → qulab-2.11.7}/qulab/executor/analyze.py +0 -0
  24. {qulab-2.11.6 → qulab-2.11.7}/qulab/executor/cli.py +0 -0
  25. {qulab-2.11.6 → qulab-2.11.7}/qulab/executor/load.py +0 -0
  26. {qulab-2.11.6 → qulab-2.11.7}/qulab/executor/registry.py +0 -0
  27. {qulab-2.11.6 → qulab-2.11.7}/qulab/executor/schedule.py +0 -0
  28. {qulab-2.11.6 → qulab-2.11.7}/qulab/executor/storage.py +0 -0
  29. {qulab-2.11.6 → qulab-2.11.7}/qulab/executor/template.py +0 -0
  30. {qulab-2.11.6 → qulab-2.11.7}/qulab/executor/utils.py +0 -0
  31. {qulab-2.11.6 → qulab-2.11.7}/qulab/monitor/__init__.py +0 -0
  32. {qulab-2.11.6 → qulab-2.11.7}/qulab/monitor/__main__.py +0 -0
  33. {qulab-2.11.6 → qulab-2.11.7}/qulab/monitor/config.py +0 -0
  34. {qulab-2.11.6 → qulab-2.11.7}/qulab/monitor/dataset.py +0 -0
  35. {qulab-2.11.6 → qulab-2.11.7}/qulab/monitor/event_queue.py +0 -0
  36. {qulab-2.11.6 → qulab-2.11.7}/qulab/monitor/mainwindow.py +0 -0
  37. {qulab-2.11.6 → qulab-2.11.7}/qulab/monitor/monitor.py +0 -0
  38. {qulab-2.11.6 → qulab-2.11.7}/qulab/monitor/ploter.py +0 -0
  39. {qulab-2.11.6 → qulab-2.11.7}/qulab/monitor/qt_compat.py +0 -0
  40. {qulab-2.11.6 → qulab-2.11.7}/qulab/monitor/toolbar.py +0 -0
  41. {qulab-2.11.6 → qulab-2.11.7}/qulab/scan/__init__.py +0 -0
  42. {qulab-2.11.6 → qulab-2.11.7}/qulab/scan/curd.py +0 -0
  43. {qulab-2.11.6 → qulab-2.11.7}/qulab/scan/models.py +0 -0
  44. {qulab-2.11.6 → qulab-2.11.7}/qulab/scan/optimize.py +0 -0
  45. {qulab-2.11.6 → qulab-2.11.7}/qulab/scan/query.py +0 -0
  46. {qulab-2.11.6 → qulab-2.11.7}/qulab/scan/record.py +0 -0
  47. {qulab-2.11.6 → qulab-2.11.7}/qulab/scan/scan.py +0 -0
  48. {qulab-2.11.6 → qulab-2.11.7}/qulab/scan/server.py +0 -0
  49. {qulab-2.11.6 → qulab-2.11.7}/qulab/scan/space.py +0 -0
  50. {qulab-2.11.6 → qulab-2.11.7}/qulab/scan/utils.py +0 -0
  51. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/__init__.py +0 -0
  52. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/__main__.py +0 -0
  53. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/backend/__init__.py +0 -0
  54. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/backend/redis.py +0 -0
  55. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/base_dataset.py +0 -0
  56. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/chunk.py +0 -0
  57. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/dataset.py +0 -0
  58. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/file.py +0 -0
  59. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/models/__init__.py +0 -0
  60. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/models/base.py +0 -0
  61. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/models/config.py +0 -0
  62. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/models/file.py +0 -0
  63. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/models/ipy.py +0 -0
  64. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/models/models.py +0 -0
  65. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/models/record.py +0 -0
  66. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/models/report.py +0 -0
  67. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/models/tag.py +0 -0
  68. {qulab-2.11.6 → qulab-2.11.7}/qulab/storage/storage.py +0 -0
  69. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/__init__.py +0 -0
  70. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/chat.py +0 -0
  71. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/device/__init__.py +0 -0
  72. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/device/basedevice.py +0 -0
  73. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/device/loader.py +0 -0
  74. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/device/utils.py +0 -0
  75. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/drivers/FakeInstrument.py +0 -0
  76. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/drivers/__init__.py +0 -0
  77. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/ipy_events.py +0 -0
  78. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/net/__init__.py +0 -0
  79. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/net/bencoder.py +0 -0
  80. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/net/cli.py +0 -0
  81. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/net/dhcp.py +0 -0
  82. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/net/dhcpd.py +0 -0
  83. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/net/kad.py +0 -0
  84. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/net/kcp.py +0 -0
  85. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/net/nginx.py +0 -0
  86. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/progress.py +0 -0
  87. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/__init__.py +0 -0
  88. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/client.py +0 -0
  89. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/exceptions.py +0 -0
  90. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/msgpack.py +0 -0
  91. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/msgpack.pyi +0 -0
  92. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/router.py +0 -0
  93. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/rpc.py +0 -0
  94. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/serialize.py +0 -0
  95. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/server.py +0 -0
  96. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/socket.py +0 -0
  97. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/utils.py +0 -0
  98. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/worker.py +0 -0
  99. {qulab-2.11.6 → qulab-2.11.7}/qulab/sys/rpc/zmq_socket.py +0 -0
  100. {qulab-2.11.6 → qulab-2.11.7}/qulab/tools/__init__.py +0 -0
  101. {qulab-2.11.6 → qulab-2.11.7}/qulab/tools/connection_helper.py +0 -0
  102. {qulab-2.11.6 → qulab-2.11.7}/qulab/typing.py +0 -0
  103. {qulab-2.11.6 → qulab-2.11.7}/qulab/utils.py +0 -0
  104. {qulab-2.11.6 → qulab-2.11.7}/qulab/visualization/__init__.py +0 -0
  105. {qulab-2.11.6 → qulab-2.11.7}/qulab/visualization/__main__.py +0 -0
  106. {qulab-2.11.6 → qulab-2.11.7}/qulab/visualization/_autoplot.py +0 -0
  107. {qulab-2.11.6 → qulab-2.11.7}/qulab/visualization/plot_circ.py +0 -0
  108. {qulab-2.11.6 → qulab-2.11.7}/qulab/visualization/plot_seq.py +0 -0
  109. {qulab-2.11.6 → qulab-2.11.7}/qulab/visualization/qdat.py +0 -0
  110. {qulab-2.11.6 → qulab-2.11.7}/qulab/visualization/widgets.py +0 -0
  111. {qulab-2.11.6 → qulab-2.11.7}/setup.cfg +0 -0
  112. {qulab-2.11.6 → qulab-2.11.7}/setup.py +0 -0
  113. {qulab-2.11.6 → qulab-2.11.7}/src/qulab.h +0 -0
  114. {qulab-2.11.6 → qulab-2.11.7}/tests/test_kad.py +0 -0
  115. {qulab-2.11.6 → qulab-2.11.7}/tests/test_scan.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: QuLab
3
- Version: 2.11.6
3
+ Version: 2.11.7
4
4
  Summary: contral instruments and manage data
5
5
  Author-email: feihoo87 <feihoo87@gmail.com>
6
6
  Maintainer-email: feihoo87 <feihoo87@gmail.com>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: QuLab
3
- Version: 2.11.6
3
+ Version: 2.11.7
4
4
  Summary: contral instruments and manage data
5
5
  Author-email: feihoo87 <feihoo87@gmail.com>
6
6
  Maintainer-email: feihoo87 <feihoo87@gmail.com>
@@ -0,0 +1 @@
1
+ __version__ = "2.11.7"
@@ -6,6 +6,8 @@ import numpy as np
6
6
  from matplotlib import cm
7
7
  from matplotlib.colors import Normalize
8
8
 
9
+ from .rot3d import projection, rot_round
10
+
9
11
  layout_example = {
10
12
  'qubits': {
11
13
  'Q0': {
@@ -152,7 +154,7 @@ def circle_path(pos, r, n=40):
152
154
  return xx, yy
153
155
 
154
156
 
155
- def circle_link_path(pos1, pos2, r1, r2, width, n=20):
157
+ def circle_link_path(pos1, pos2, r1, r2, width, n=2):
156
158
  width = min(2 * max(r1, r2), width)
157
159
 
158
160
  x1, y1 = pos1
@@ -204,59 +206,185 @@ def circle_half_directed_link_path(pos1, pos2, r1, r2, width, n=20):
204
206
  xx2[:-1]]), np.hstack([yy2[-1], yy1, a.imag, yy2[:-1]])
205
207
 
206
208
 
207
- def draw(layout, ax=None, qubit_cbar=True, coupler_cbar=True, origin='upper'):
209
+ def project(pos, camera=(0, 0, 100), rotation=None):
210
+ if rotation is None:
211
+ rotation = {
212
+ 'axis': (0, 0, 1),
213
+ 'angle': 0,
214
+ 'center': (0, 0, 0),
215
+ }
216
+ x0, y0, z0 = camera
217
+ if len(pos) == 2:
218
+ x, y, z = [*pos, 0]
219
+ else:
220
+ x, y, z = pos
221
+ x, y, z = rot_round(x, y, z, rotation['axis'], rotation['angle'],
222
+ rotation['center'])
223
+ x, y, d = projection(x - x0, y - y0, z, d0=z0)
224
+ return x + x0, y + y0
225
+
226
+
227
+ def _draw_qubit(ax, qubit, pos):
228
+ path = circle_path(pos, qubit.get('radius', 0.5))
229
+ plot_range(ax,
230
+ path,
231
+ qubit.get('text', ''),
232
+ qubit.get('color', None),
233
+ lw=qubit.get('lw', 0.5),
234
+ fontsize=qubit.get('fontsize', 9),
235
+ rotation=qubit.get('text_rotation', 0),
236
+ text_color=qubit.get('text_color', 'k'),
237
+ bounder_color=qubit.get('bounder_color', 'k'))
238
+
239
+
240
+ def _draw_coupler(ax, coupler, layout, q1, q2, pos1, pos2):
241
+ r1 = layout['qubits'][q1].get('radius', 0.5)
242
+ r2 = layout['qubits'][q2].get('radius', 0.5)
243
+ width = coupler.get('width', 0.5)
244
+ lw = coupler.get('lw', 0.5)
245
+
246
+ text_rotation = 180 * np.arctan2(pos2[1] - pos1[1],
247
+ pos2[0] - pos1[0]) / np.pi
248
+
249
+ path = circle_link_path(pos1, pos2, r1, r2, width)
250
+ plot_range(ax,
251
+ path,
252
+ coupler.get('text', ''),
253
+ color=coupler.get('color', None),
254
+ lw=0,
255
+ fontsize=coupler.get('fontsize', 9),
256
+ rotation=coupler.get('text_rotation', text_rotation),
257
+ text_color=coupler.get('text_color', 'k'))
258
+ if lw > 0:
259
+ x, y = circle_link_path(pos1, pos2, r1, r2, width, n=2)
260
+ ax.plot(x[:2], y[:2], lw=lw, color=coupler.get('bounder_color', 'k'))
261
+ ax.plot(x[2:], y[2:], lw=lw, color=coupler.get('bounder_color', 'k'))
262
+
263
+
264
+ def get_range(layout):
265
+ coods = []
266
+ for q in layout['qubits']:
267
+ pos = layout['qubits'][q]['pos']
268
+ if len(pos) == 2:
269
+ x, y, z = [*pos, 0]
270
+ else:
271
+ x, y, z = pos
272
+ coods.append([x, y, z])
273
+ coods = np.array(coods)
274
+
275
+ center = coods.mean(axis=0)
276
+ radius = np.max(np.sqrt(np.sum((coods - center)**2, axis=1)))
277
+
278
+ return center, radius
279
+
280
+
281
+ def sorted_by_distance(layout, camera, rotation):
282
+ qubits = []
283
+ camera = np.array(camera)
284
+ for q in layout['qubits']:
285
+ pos = layout['qubits'][q]['pos']
286
+ if len(pos) == 2:
287
+ x, y, z = [*pos, 0]
288
+ else:
289
+ x, y, z = pos
290
+ x, y, z = rot_round(x, y, z, rotation['axis'], rotation['angle'],
291
+ rotation['center'])
292
+ d = np.sqrt(np.sum((np.array([x, y, z]) - camera)**2))
293
+ qubits.append((d, q))
294
+ qubits = sorted(qubits, key=lambda x: x[0])
295
+
296
+ plot_order = []
297
+ for _, q in reversed(qubits):
298
+ for c in layout['qubits'][q]['couplers']:
299
+ if ('C', c) not in plot_order:
300
+ plot_order.append(('C', c))
301
+ plot_order.append(('Q', q))
302
+ return plot_order
303
+
304
+
305
+ def draw(layout,
306
+ ax=None,
307
+ qubit_cbar=True,
308
+ coupler_cbar=True,
309
+ origin='upper',
310
+ camera=None,
311
+ rotation=None):
312
+ """
313
+ Draw a layout with qubits and couplers.
314
+
315
+ Parameters
316
+ ----------
317
+ layout: dict
318
+ A dictionary containing the layout of the qubits and couplers.
319
+ The dictionary should have the following structure:
320
+ {
321
+ 'qubits': {
322
+ 'Q0': {'pos': (x, y), 'radius': r, 'text': 'Q0'},
323
+ ...
324
+ },
325
+ 'couplers': {
326
+ 'C0': {'qubits': ['Q0', 'Q1'], 'width': w, 'text': 'C0'},
327
+ ...
328
+ }
329
+ }
330
+ ax: matplotlib.axes.Axes
331
+ The axes on which to draw the layout. If None, the current axes will be used.
332
+ qubit_cbar: bool
333
+ Whether to draw a colorbar for the qubits.
334
+ coupler_cbar: bool
335
+ Whether to draw a colorbar for the couplers.
336
+ origin: str
337
+ The origin of the layout. If 'upper', the y-coordinates will be inverted.
338
+ camera: tuple
339
+ The position of the camera in 3D space. Default is (0, 0, 1).
340
+ rotation: dict
341
+ The rotation of the layout. The dictionary should have the following structure:
342
+ {
343
+ 'axis': (x, y, z),
344
+ 'angle': angle,
345
+ 'center': (x, y, z)
346
+ }
347
+ If None, no rotation will be applied.
348
+ """
208
349
  if ax is None:
209
350
  ax = plt.gca()
210
351
 
211
- for qubit in layout['qubits'].values():
212
- pos = qubit['pos']
213
- if origin == 'upper':
214
- pos = pos[0], -pos[1]
215
- path = circle_path(pos, qubit.get('radius', 0.5))
216
- plot_range(ax,
217
- path,
218
- qubit.get('text', ''),
219
- qubit.get('color', None),
220
- lw=qubit.get('lw', 0.5),
221
- fontsize=qubit.get('fontsize', 9),
222
- rotation=qubit.get('rotation', 0),
223
- text_color=qubit.get('text_color', 'k'),
224
- bounder_color=qubit.get('bounder_color', 'k'))
225
-
226
- for coupler in layout['couplers'].values():
227
- q1, q2 = coupler['qubits']
228
- pos1 = layout['qubits'][q1]['pos']
229
- pos2 = layout['qubits'][q2]['pos']
230
- if origin == 'upper':
231
- pos1 = pos1[0], -pos1[1]
232
- pos2 = pos2[0], -pos2[1]
233
- r1 = layout['qubits'][q1].get('radius', 0.5)
234
- r2 = layout['qubits'][q2].get('radius', 0.5)
235
- width = coupler.get('width', 0.5)
236
- lw = coupler.get('lw', 0.5)
237
-
238
- rotation = 180 * np.arctan2(pos2[1] - pos1[1],
239
- pos2[0] - pos1[0]) / np.pi
240
-
241
- path = circle_link_path(pos1, pos2, r1, r2, width)
242
- plot_range(ax,
243
- path,
244
- coupler.get('text', ''),
245
- color=coupler.get('color', None),
246
- lw=0,
247
- fontsize=coupler.get('fontsize', 9),
248
- rotation=coupler.get('rotation', rotation),
249
- text_color=coupler.get('text_color', 'k'))
250
- if lw > 0:
251
- x, y = circle_link_path(pos1, pos2, r1, r2, width, n=2)
252
- ax.plot(x[:2],
253
- y[:2],
254
- lw=lw,
255
- color=coupler.get('bounder_color', 'k'))
256
- ax.plot(x[2:],
257
- y[2:],
258
- lw=lw,
259
- color=coupler.get('bounder_color', 'k'))
352
+ center, radius = get_range(layout)
353
+
354
+ if rotation is None:
355
+ rotation = {
356
+ 'axis': (0, 0, 1),
357
+ 'angle': 0,
358
+ }
359
+ if 'center' not in rotation:
360
+ rotation['center'] = center
361
+ if camera is None:
362
+ camera = (center[0], center[1], center[2] + radius * 5)
363
+
364
+ plot_order = sorted_by_distance(layout, camera, rotation)
365
+
366
+ if origin == 'upper':
367
+ camera = [camera[0], -camera[1], camera[2]]
368
+ for kind, name in plot_order:
369
+ if kind == 'Q':
370
+ pos = layout['qubits'][name]['pos']
371
+ if origin == 'upper':
372
+ pos = [pos[0], -pos[1], *pos[2:]]
373
+ pos = project(pos, camera, rotation)
374
+ _draw_qubit(ax, layout['qubits'][name], pos)
375
+ elif kind == 'C':
376
+ coupler = layout['couplers'][name]
377
+ q1, q2 = coupler['qubits']
378
+ pos1 = layout['qubits'][q1]['pos']
379
+ pos2 = layout['qubits'][q2]['pos']
380
+ if origin == 'upper':
381
+ pos1 = [pos1[0], -pos1[1], *pos1[2:]]
382
+ pos2 = [pos2[0], -pos2[1], *pos2[2:]]
383
+ pos1 = project(pos1, camera, rotation)
384
+ pos2 = project(pos2, camera, rotation)
385
+ _draw_coupler(ax, coupler, layout, q1, q2, pos1, pos2)
386
+ else:
387
+ pass
260
388
 
261
389
  ax.axis('equal')
262
390
  ax.set_axis_off()
@@ -14,10 +14,36 @@ def _rot(theta, v):
14
14
 
15
15
 
16
16
  def rot_round(x, y, z, v=[0, 0, 1], theta=0, c=[0, 0, 0]):
17
+ """
18
+ Rotate a point (x, y, z) around a vector v by an angle theta
19
+
20
+ Parameters
21
+ ----------
22
+ x, y, z: coordinates of the point to be rotated
23
+ v: vector to rotate around
24
+ theta: angle to rotate by (in radians)
25
+ c: center of rotation
26
+
27
+ Returns
28
+ -------
29
+ ret: rotated coordinates
30
+ """
17
31
  ret = (np.array([x, y, z]).T - np.array(c)) @ _rot(theta, v) + np.array(c)
18
32
  return ret.T
19
33
 
20
34
 
21
- def projection(x, y, z, y0=1):
35
+ def projection(x, y, z, d0=1):
36
+ """
37
+ Project a point (x, y, z) onto a plane at z = 0
38
+
39
+ Parameters
40
+ ----------
41
+ x, y, z: coordinates of the point to be projected
42
+ d0: distance from the camera to the plane
43
+
44
+ Returns
45
+ -------
46
+ ret: projected coordinates
47
+ """
22
48
  d = np.sqrt(x**2 + y**2 + z**2)
23
- return x * y0 / y, z * y0 / y, d
49
+ return x * d0 / (d0 - z), y * d0 / (d0 - z), d
@@ -1 +0,0 @@
1
- __version__ = "2.11.6"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes