QuLab 2.0.2__cp310-cp310-macosx_10_9_universal2.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 (84) hide show
  1. QuLab-2.0.2.dist-info/LICENSE +21 -0
  2. QuLab-2.0.2.dist-info/METADATA +98 -0
  3. QuLab-2.0.2.dist-info/RECORD +84 -0
  4. QuLab-2.0.2.dist-info/WHEEL +5 -0
  5. QuLab-2.0.2.dist-info/entry_points.txt +2 -0
  6. QuLab-2.0.2.dist-info/top_level.txt +1 -0
  7. qulab/__init__.py +1 -0
  8. qulab/__main__.py +26 -0
  9. qulab/fun.cpython-310-darwin.so +0 -0
  10. qulab/monitor/__init__.py +1 -0
  11. qulab/monitor/__main__.py +8 -0
  12. qulab/monitor/config.py +41 -0
  13. qulab/monitor/dataset.py +77 -0
  14. qulab/monitor/event_queue.py +54 -0
  15. qulab/monitor/mainwindow.py +234 -0
  16. qulab/monitor/monitor.py +93 -0
  17. qulab/monitor/ploter.py +123 -0
  18. qulab/monitor/qt_compat.py +16 -0
  19. qulab/monitor/toolbar.py +265 -0
  20. qulab/scan/__init__.py +3 -0
  21. qulab/scan/curd.py +144 -0
  22. qulab/scan/expression.py +505 -0
  23. qulab/scan/models.py +540 -0
  24. qulab/scan/optimize.py +69 -0
  25. qulab/scan/query_record.py +361 -0
  26. qulab/scan/recorder.py +447 -0
  27. qulab/scan/scan.py +701 -0
  28. qulab/scan/utils.py +37 -0
  29. qulab/storage/__init__.py +0 -0
  30. qulab/storage/__main__.py +51 -0
  31. qulab/storage/backend/__init__.py +0 -0
  32. qulab/storage/backend/redis.py +204 -0
  33. qulab/storage/base_dataset.py +352 -0
  34. qulab/storage/chunk.py +60 -0
  35. qulab/storage/dataset.py +127 -0
  36. qulab/storage/file.py +273 -0
  37. qulab/storage/models/__init__.py +22 -0
  38. qulab/storage/models/base.py +4 -0
  39. qulab/storage/models/config.py +28 -0
  40. qulab/storage/models/file.py +89 -0
  41. qulab/storage/models/ipy.py +58 -0
  42. qulab/storage/models/models.py +88 -0
  43. qulab/storage/models/record.py +161 -0
  44. qulab/storage/models/report.py +22 -0
  45. qulab/storage/models/tag.py +93 -0
  46. qulab/storage/storage.py +95 -0
  47. qulab/sys/__init__.py +0 -0
  48. qulab/sys/chat.py +688 -0
  49. qulab/sys/device/__init__.py +3 -0
  50. qulab/sys/device/basedevice.py +221 -0
  51. qulab/sys/device/loader.py +86 -0
  52. qulab/sys/device/utils.py +46 -0
  53. qulab/sys/drivers/FakeInstrument.py +52 -0
  54. qulab/sys/drivers/__init__.py +0 -0
  55. qulab/sys/ipy_events.py +125 -0
  56. qulab/sys/net/__init__.py +0 -0
  57. qulab/sys/net/bencoder.py +205 -0
  58. qulab/sys/net/cli.py +169 -0
  59. qulab/sys/net/dhcp.py +543 -0
  60. qulab/sys/net/dhcpd.py +176 -0
  61. qulab/sys/net/kad.py +1142 -0
  62. qulab/sys/net/kcp.py +192 -0
  63. qulab/sys/net/nginx.py +192 -0
  64. qulab/sys/progress.py +190 -0
  65. qulab/sys/rpc/__init__.py +0 -0
  66. qulab/sys/rpc/client.py +0 -0
  67. qulab/sys/rpc/exceptions.py +96 -0
  68. qulab/sys/rpc/msgpack.py +1052 -0
  69. qulab/sys/rpc/msgpack.pyi +41 -0
  70. qulab/sys/rpc/rpc.py +412 -0
  71. qulab/sys/rpc/serialize.py +139 -0
  72. qulab/sys/rpc/server.py +29 -0
  73. qulab/sys/rpc/socket.py +29 -0
  74. qulab/sys/rpc/utils.py +25 -0
  75. qulab/sys/rpc/worker.py +0 -0
  76. qulab/sys/rpc/zmq_socket.py +209 -0
  77. qulab/version.py +1 -0
  78. qulab/visualization/__init__.py +188 -0
  79. qulab/visualization/__main__.py +71 -0
  80. qulab/visualization/_autoplot.py +463 -0
  81. qulab/visualization/plot_layout.py +408 -0
  82. qulab/visualization/plot_seq.py +90 -0
  83. qulab/visualization/qdat.py +152 -0
  84. qulab/visualization/widgets.py +86 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 feihoo87
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.1
2
+ Name: QuLab
3
+ Version: 2.0.2
4
+ Summary: contral instruments and manage data
5
+ Author-email: feihoo87 <feihoo87@gmail.com>
6
+ Maintainer-email: feihoo87 <feihoo87@gmail.com>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/feihoo87/QuLab
9
+ Project-URL: Bug Reports, https://github.com/feihoo87/QuLab/issues
10
+ Project-URL: Source, https://github.com/feihoo87/QuLab/
11
+ Keywords: experiment,laboratory
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Operating System :: MacOS :: MacOS X
19
+ Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
20
+ Classifier: Programming Language :: Python
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: blinker >=1.4
28
+ Requires-Dist: click >=7.1.2
29
+ Requires-Dist: dill >=0.3.6
30
+ Requires-Dist: GitPython >=3.1.14
31
+ Requires-Dist: ipython >=7.4.0
32
+ Requires-Dist: ipywidgets >=7.4.2
33
+ Requires-Dist: loguru >=0.7.2
34
+ Requires-Dist: matplotlib >=3.7.2
35
+ Requires-Dist: numpy >=1.13.3
36
+ Requires-Dist: ply >=3.11
37
+ Requires-Dist: pyzmq >=25.1.0
38
+ Requires-Dist: scipy >=1.0.0
39
+ Requires-Dist: watchdog >=4.0.0
40
+
41
+ # QuLab
42
+ [![View build status](https://travis-ci.org/feihoo87/QuLab.svg?branch=master)](https://travis-ci.org/feihoo87/QuLab)
43
+ [![Coverage Status](https://coveralls.io/repos/github/feihoo87/QuLab/badge.svg)](https://coveralls.io/github/feihoo87/QuLab)
44
+ [![Updates](https://pyup.io/repos/github/feihoo87/QuLab/shield.svg)](https://pyup.io/repos/github/feihoo87/QuLab/)
45
+ [![Docs Status](https://readthedocs.org/projects/qulab/badge/?version=latest)](http://qulab.readthedocs.org)
46
+ [![PyPI version](https://badge.fury.io/py/QuLab.svg)](https://badge.fury.io/py/QuLab)
47
+ [![](https://img.shields.io/badge/python-3.6%2C%203.7-brightgreen.svg)]()
48
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3352232.svg)](https://doi.org/10.5281/zenodo.3352232)
49
+
50
+ **Documentation can be found at [qulab.readthedocs.org](https://qulab.readthedocs.org/).**
51
+
52
+ ## Installation
53
+ We encourage installing QuLab via the pip tool (a python package manager):
54
+ ```bash
55
+ python -m pip install QuLab
56
+ ```
57
+
58
+ To install from the latest source, you need to clone the GitHub repository on your machine.
59
+ ```bash
60
+ git clone https://github.com/feihoo87/QuLab.git
61
+ ```
62
+
63
+ Then dependencies and QuLab can be installed in this way:
64
+ ```bash
65
+ cd QuLab
66
+ python -m pip install -e .
67
+ ```
68
+
69
+ ## Usage
70
+
71
+
72
+ ## Running Tests
73
+ To run tests:
74
+
75
+ ```
76
+ python -m pip install -r requirements-dev.txt
77
+ python -m pytest
78
+ ```
79
+
80
+ ## Attribution
81
+ If you make use of this code, please consider citing the Zenodo DOI [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3352232.svg)](https://doi.org/10.5281/zenodo.3352232) as a software citation:
82
+ ```
83
+ @misc{xu_huikai_2019_3352232,
84
+ author = {Xu, Huikai},
85
+ title = {QuLab},
86
+ month = aug,
87
+ year = 2019,
88
+ doi = {10.5281/zenodo.3352232},
89
+ url = {https://doi.org/10.5281/zenodo.3352232}
90
+ }
91
+ ```
92
+
93
+ ## Reporting Issues
94
+ Please report all issues [on github](https://github.com/feihoo87/QuLab/issues).
95
+
96
+ ## License
97
+
98
+ [MIT](https://opensource.org/licenses/MIT)
@@ -0,0 +1,84 @@
1
+ qulab/__init__.py,sha256=8zLGg-DfQhnDl2Ky0n-zXpN-8e-g7iR0AcaI4l4Vvpk,32
2
+ qulab/__main__.py,sha256=h84t4vjTH6Gu7SrBhudkzvbqfH1oNudDtM11LIY1h4Q,430
3
+ qulab/fun.cpython-310-darwin.so,sha256=0z1iTDlNIT1TovOPS1xdhj0zPGtRhhj8KNVLIMz70yk,159632
4
+ qulab/version.py,sha256=xARS6PXiulA1Bog5UZUM6hqQfydeRzKLyWtOyUBL-Ss,21
5
+ qulab/monitor/__init__.py,sha256=nTHelnDpxRS_fl_B38TsN0njgq8eVTEz9IAnN3NbDlM,42
6
+ qulab/monitor/__main__.py,sha256=w3yUcqq195LzSnXTkQcuC1RSFRhy4oQ_PEBmucXguME,97
7
+ qulab/monitor/config.py,sha256=fQ5JcsMApKc1UwANEnIvbDQZl8uYW0tle92SaYtX9lI,744
8
+ qulab/monitor/dataset.py,sha256=C4wZU-XqYHY1ysvUGSF5958M_GANrXW-f1SHnruHJno,2455
9
+ qulab/monitor/event_queue.py,sha256=o66jOTKJmJibt-bhYFjk5p_rExxu-hdoR_BfR8PMN3I,1823
10
+ qulab/monitor/mainwindow.py,sha256=Bme7YKg2LQSpRH6cg8rcFhdnxUU_d_F4b6TIvPVAbx4,7799
11
+ qulab/monitor/monitor.py,sha256=7E4bnTsO6qC85fs2ONrccGHfaYKv7SW74mtXzv6QjVc,2305
12
+ qulab/monitor/ploter.py,sha256=CbiIjmohgtwDDTVeGzhXEGVo3XjytMdhLwU9VUkg9vo,3601
13
+ qulab/monitor/qt_compat.py,sha256=OK71_JSO_iyXjRIKHANmaK4Lx4bILUzmXI-mwKg3QeI,788
14
+ qulab/monitor/toolbar.py,sha256=WEag6cxAtEsOLL14XvM7pSE56EA3MO188_JuprNjdBs,7948
15
+ qulab/scan/__init__.py,sha256=BflmtNkyV72f4jqkeXoO_gi7kf8CHyk-AmKHjNXwe1A,124
16
+ qulab/scan/curd.py,sha256=ntpK62ArZiF2mrDDewcw227VMR1E_8no0yLJSrgdgng,4518
17
+ qulab/scan/expression.py,sha256=-aTYbjFQNI1mwOcoSBztqhKfGJpu_n4a1QnWro_xnTU,15694
18
+ qulab/scan/models.py,sha256=S8Q9hC8nOzxyoNB10EYg-miDKqoNMnjyAECjD-TuORw,17117
19
+ qulab/scan/optimize.py,sha256=vErjRTCtn2MwMF5Xyhs1P4gHF2IFHv_EqxsUvH_4y7k,2287
20
+ qulab/scan/query_record.py,sha256=ed40efBQxtkwUxZHT0zB9SYlMxgNUFqOtCiseOCeBe0,11521
21
+ qulab/scan/recorder.py,sha256=jIkFY-Mirvkpyvh-8nKFiTqrLbGAgp9h9kBX25q_RIs,15402
22
+ qulab/scan/scan.py,sha256=hWKDSosn7_eOAiiA548vdBRYu34OvvWPEtfXLk7fxcY,23030
23
+ qulab/scan/utils.py,sha256=2bj7ggTNTK5LXwBDi8w7IzFqFjchoE6EhgSASC0fpDQ,1024
24
+ qulab/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ qulab/storage/__main__.py,sha256=3emxxRry8BB0m8hUZvJ_oBqkPy7ksV7flHB_KEDXZuI,1692
26
+ qulab/storage/base_dataset.py,sha256=4aKhqBNdZfdlm_z1Qy5dv0HrvgpvMdy8pbyfua8uE-4,11865
27
+ qulab/storage/chunk.py,sha256=dtck2Pem7OYYX3TYlnWwfqrgXSmkLhi0nN_ElbuS-c8,1701
28
+ qulab/storage/dataset.py,sha256=Q9asJxNwYNcmu7sSqsAdAntYIre9b4dGIiFnt1O-KI4,4655
29
+ qulab/storage/file.py,sha256=KAaXFI1SKdcCVWjopVqYaWU4WZgZU9Oh2epdqH1ADPw,8343
30
+ qulab/storage/storage.py,sha256=qRyR-5zRRx84DfsifozlYKMRj8bykwRyF7TW8oyFmwk,2561
31
+ qulab/storage/backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ qulab/storage/backend/redis.py,sha256=hNaPP0V1BSWbUcx4AxOhEXiR83c_BZqeVzeOYkb8-zM,5202
33
+ qulab/storage/models/__init__.py,sha256=DkKzQF7tYd1WL1gGPuCThBcGfpnCuZ_PTLrqV3M_EJ0,586
34
+ qulab/storage/models/base.py,sha256=QLXiTRCPcg28BCFxBHexAxdNLjh2ONkzgNavoFOBW9s,114
35
+ qulab/storage/models/config.py,sha256=Mxk0-YcK0WgA-7-2oIuDMAeBaUECzj-3_oPvgF7gYtE,689
36
+ qulab/storage/models/file.py,sha256=1Rypz1QSco6drBCiR_BS6Oy0ifOapBIeNEm0uDqqxBk,2716
37
+ qulab/storage/models/ipy.py,sha256=uYBeqWsOxxCWUsDpnwhxugh6C9OuH92OrChlLj0gddk,1574
38
+ qulab/storage/models/models.py,sha256=JUqtvk8ywulkcFL38WfTviuVOcdvSGakZYJS7jAPNig,2879
39
+ qulab/storage/models/record.py,sha256=L0k531bGF9JN-GLv3hG87tB7k0kuSBkEeC9vi6_qywE,4970
40
+ qulab/storage/models/report.py,sha256=j9ByrVoue-rwaXcnfTzVOSf1xDJdlZJq666agF0AZRY,798
41
+ qulab/storage/models/tag.py,sha256=c3cTxpJUoG9L6xyDvVuagYVhB32amzbkBOmVeRIZ5Zo,2339
42
+ qulab/sys/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ qulab/sys/chat.py,sha256=DlFLP_gbVyL8fDUyad6Xu8sjQCZJauLIvF31mj5BtMs,22449
44
+ qulab/sys/ipy_events.py,sha256=qvsqs7-CYQ-P4WtSe9UUZZ0tC88XxPMd9DM4LJALgEk,2889
45
+ qulab/sys/progress.py,sha256=Tk1B96_1QrlI4yU0cyZlf2wVsF238DjQGqXJVG2j4t0,5350
46
+ qulab/sys/device/__init__.py,sha256=bDqJrYQJx8YR4u_CYvJPpIBr6whP7pVnxnROTHk_yhA,149
47
+ qulab/sys/device/basedevice.py,sha256=iqyX2SQLb7aRWNE5Uj2yHkFOLqVrX2I1N-xubTDB5tQ,6423
48
+ qulab/sys/device/loader.py,sha256=AL0rNF4UZ-CUHoF8FNtT_ZGLwySvz7SDPsKALaJS8po,2501
49
+ qulab/sys/device/utils.py,sha256=H9TvMqHZABhFdIah4uT0x9FvQ6ZPwbvw-wCnWTy4rfo,1564
50
+ qulab/sys/drivers/FakeInstrument.py,sha256=kwIXN-dHmvGYBinmcCLxUQKm0ENiJpsMwgQIYNLDS2k,1867
51
+ qulab/sys/drivers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ qulab/sys/net/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
+ qulab/sys/net/bencoder.py,sha256=p85DtmVy3cna3Da07boau77el2Cnym5-mKGF4xCJSy4,4959
54
+ qulab/sys/net/cli.py,sha256=dm-JxbgZgFH2P_5Zu3kSrLzy2U_VRLswkvE1d3xGp0w,5690
55
+ qulab/sys/net/dhcp.py,sha256=gT5ehyvwW3y8E5u_DnYRd5I0KaddonmQJFVhlIS2yxM,23509
56
+ qulab/sys/net/dhcpd.py,sha256=pNC47i-hu8HTzCrKU0PatL3AbgEqe1ovmpLPwNoZLa8,5322
57
+ qulab/sys/net/kad.py,sha256=gGYb9cXbAdbYhubQdCRqOGigllBy0kSUp4z3_f3AWz0,38981
58
+ qulab/sys/net/kcp.py,sha256=oFyiosQ1o0qeVA9hODIYEZtJj4HN1aNLGVP6vbxouMs,5761
59
+ qulab/sys/net/nginx.py,sha256=QAQthr_Dux7xRpgqeY6BVxxre4dg0WJITztSk8Fn-jU,4964
60
+ qulab/sys/rpc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ qulab/sys/rpc/client.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
+ qulab/sys/rpc/exceptions.py,sha256=djK44hYVMixF2Y-lAXDGHlyyCmYGw7EJjB3I0ttejok,2567
63
+ qulab/sys/rpc/msgpack.py,sha256=s9mbPIkQktO1FiSAuE6ymM_1w8rIERA0gMm5GQkT7z8,35327
64
+ qulab/sys/rpc/msgpack.pyi,sha256=3dJgISPCTEBo65VaoGjcFkdLijPx6zJtKqcZiS9bcaE,1274
65
+ qulab/sys/rpc/rpc.py,sha256=9ZwzC79FgmbHXbO1Gjg4z0wZgHLDziTwVuS2aZpLJAk,11979
66
+ qulab/sys/rpc/serialize.py,sha256=0SR1me02mao2JwWR3rdjUIcOzh1m1JFb7fLEaw_q-pE,3355
67
+ qulab/sys/rpc/server.py,sha256=e3R0gwOHpLEkSp7Tb43FMSDvqSG-pjrkskdISKQRseE,713
68
+ qulab/sys/rpc/socket.py,sha256=e3R0gwOHpLEkSp7Tb43FMSDvqSG-pjrkskdISKQRseE,713
69
+ qulab/sys/rpc/utils.py,sha256=6YGFOkY7o09lkA_I1FIP9_1Up3k2F1KOkftvu0_8lxo,594
70
+ qulab/sys/rpc/worker.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
+ qulab/sys/rpc/zmq_socket.py,sha256=fuW86N7O1X-TmFO0ona7GC47jsg5mLp7kBcO42kpCKk,7926
72
+ qulab/visualization/__init__.py,sha256=26cuHt3QIJXUb3VaMxlJx3IQTOUVJFKlYBZr7WMP53M,6129
73
+ qulab/visualization/__main__.py,sha256=9zKK3yZFy0leU40ou6BpRC1Fsetfc1gjjFzIZYIwP6Y,1639
74
+ qulab/visualization/_autoplot.py,sha256=jddg40dX48Wd8G6NLFA_Kf7z1QxdrZBDS99Xx2GLMqs,14099
75
+ qulab/visualization/plot_layout.py,sha256=clNw9QjE_kVNpIIx2Ob4YhAz2fucPGMuzkoIrOJo_Y8,13533
76
+ qulab/visualization/plot_seq.py,sha256=lphYF4VhkEdc_wWr1kFBwrx2yujkyFPFaJ3pjr61awI,2693
77
+ qulab/visualization/qdat.py,sha256=ZeevBYWkzbww4xZnsjHhw7wRorJCBzbG0iEu-XQB4EA,5735
78
+ qulab/visualization/widgets.py,sha256=6KkiTyQ8J-ei70LbPQZAK35wjktY47w2IveOa682ftA,3180
79
+ QuLab-2.0.2.dist-info/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
80
+ QuLab-2.0.2.dist-info/METADATA,sha256=cIK74-RBs-jNnttEcwVdgMtNd4WAh7OmcVn2ShZBIt4,3477
81
+ QuLab-2.0.2.dist-info/WHEEL,sha256=r7U64H7df5k5VoE41bE2otJ6YmrMps4wUd2_S2hHvHQ,115
82
+ QuLab-2.0.2.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
83
+ QuLab-2.0.2.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
84
+ QuLab-2.0.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.43.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp310-cp310-macosx_10_9_universal2
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ qulab = qulab.__main__:main
@@ -0,0 +1 @@
1
+ qulab
qulab/__init__.py ADDED
@@ -0,0 +1 @@
1
+ from .version import __version__
qulab/__main__.py ADDED
@@ -0,0 +1,26 @@
1
+ import click
2
+
3
+ from .monitor.__main__ import main as monitor
4
+ from .scan.recorder import record
5
+ from .sys.net.cli import dht
6
+ from .visualization.__main__ import plot
7
+
8
+
9
+ @click.group()
10
+ def main():
11
+ pass
12
+
13
+
14
+ @main.command()
15
+ def hello():
16
+ """Print hello world."""
17
+ click.echo('hello, world')
18
+
19
+
20
+ main.add_command(monitor)
21
+ main.add_command(plot)
22
+ main.add_command(dht)
23
+ main.add_command(record)
24
+
25
+ if __name__ == '__main__':
26
+ main()
Binary file
@@ -0,0 +1 @@
1
+ from .monitor import Monitor, get_monitor
@@ -0,0 +1,8 @@
1
+ import click
2
+
3
+ from .monitor import Monitor
4
+
5
+
6
+ @click.command(name='monitor')
7
+ def main():
8
+ pass
@@ -0,0 +1,41 @@
1
+ import numpy as np
2
+
3
+ style = '''
4
+ QWidget {
5
+ font: medium Ubuntu;
6
+ background-color: #011F2F;
7
+ font-size: 16px;
8
+ font-size: 16px;
9
+ color:#FFFFFF;
10
+ }
11
+ '''
12
+ #
13
+ Nroll = 6
14
+
15
+ # Format of the data.
16
+ forms = {
17
+ "mag": lambda w, ang: np.abs(w),
18
+ "phase": lambda w, ang: np.angle(w),
19
+ "real": lambda w, ang: np.real(w),
20
+ "imag": lambda w, ang: np.imag(w),
21
+ "rot": lambda w, ang: np.real(np.exp(1j * ang) * np.array(w))
22
+ }
23
+ form_keys = list(forms.keys())
24
+ #
25
+ COL_SEL = (0, 0, 0)
26
+ COL_UNSEL = (6, 6, 8)
27
+ #
28
+
29
+ defualt_colors = [
30
+ (200, 0, 0),
31
+ (55, 100, 180),
32
+ (40, 80, 150),
33
+ (30, 50, 110),
34
+ (25, 40, 70),
35
+ (25, 30, 50),
36
+ ]
37
+
38
+ widths = [3, 2, 2, 2, 1, 1]
39
+ SymSize = [5, 0, 0, 0, 0, 0]
40
+ ridx = list(range(Nroll))
41
+ ridx.reverse()
@@ -0,0 +1,77 @@
1
+ from collections import defaultdict, deque
2
+
3
+ from .config import Nroll
4
+
5
+ PAUSE_TIME = 1
6
+
7
+ Number = int | float | complex
8
+
9
+
10
+ def remove_duplicates(input_list: list[str]) -> list[str]:
11
+ """
12
+ Remove duplicates from a list of strings, keeping the order of the elements.
13
+ """
14
+ return list(dict.fromkeys(input_list))
15
+
16
+
17
+ class Dataset():
18
+
19
+ def __init__(self):
20
+ self.column_names = []
21
+ self.box = deque(maxlen=Nroll)
22
+ self.dirty = True
23
+
24
+ def clear(self):
25
+ self.box.clear()
26
+
27
+ def clear_history(self):
28
+ o = self.box.popleft()
29
+ self.box.clear()
30
+ self.box.appendleft(o)
31
+
32
+ def set_column_names(self, column_names: list[str]):
33
+ column_names = remove_duplicates(column_names)
34
+ if column_names != self.column_names:
35
+ self.clear()
36
+ self.column_names = column_names
37
+
38
+ def get_data(self, step: int, xname: str,
39
+ yname: str) -> tuple[list[Number], list[Number]]:
40
+ try:
41
+ b = self.box[step]
42
+ except IndexError:
43
+ return [], []
44
+ return b[xname], b[yname]
45
+
46
+ def append(self, dataframe: list[Number] | list[list[Number]]):
47
+ if not dataframe:
48
+ return
49
+ try:
50
+ iter(dataframe[0]) # test if dataframe is a list of list
51
+ self._append_traces(dataframe)
52
+ except TypeError:
53
+ self._append_points(dataframe)
54
+
55
+ def roll(self):
56
+ self.box.appendleft(defaultdict(list))
57
+
58
+ def _append_points(self, points: list[Number]):
59
+ self.dirty = True
60
+ assert (len(points) == len(
61
+ self.column_names)), (f"-PointDataBox\n"
62
+ f"-ap\n"
63
+ f"-Length Must be same\n"
64
+ f"the column_names : {self.column_names}\n"
65
+ f"given data : {points}")
66
+ for name, p in zip(self.column_names, points):
67
+ self.box[0][name].append(p)
68
+
69
+ def _append_traces(self, traces: list[list[Number]]):
70
+ self.dirty = True
71
+ assert (len(traces) == len(
72
+ self.column_names)), (f"-TraceDataBox\n"
73
+ f"-at\n"
74
+ f"-Length Must be same\n"
75
+ f"the column_names : {self.column_names}\n"
76
+ f"given data : {traces}")
77
+ self.box.appendleft(dict(zip(self.column_names, traces)))
@@ -0,0 +1,54 @@
1
+ import warnings
2
+ from multiprocessing import Queue
3
+
4
+ from .dataset import Dataset
5
+ from .toolbar import ToolBar
6
+
7
+
8
+ class EventQueue():
9
+
10
+ def __init__(self, queue: Queue, toolbar: ToolBar, point_dataset: Dataset,
11
+ trace_dataset: Dataset):
12
+ self.toolbar = toolbar
13
+ self.queue = queue
14
+ self.point_dataset = point_dataset
15
+ self.trace_dataset = trace_dataset
16
+
17
+ def flush(self):
18
+ while (not self.queue.empty()):
19
+ words = self.queue.get()
20
+ try:
21
+ assert (isinstance(
22
+ words, tuple)), "QueueHandler - fifo Content must be tuple"
23
+ assert (
24
+ len(words) == 2
25
+ ), "QueueHandler -the tuple must be like (\"command_type\" , \"DATA\")"
26
+ cmd, data = words
27
+ assert (isinstance(
28
+ cmd, str)), "QueueHandler - the command should be a string"
29
+ except AssertionError as e:
30
+ warnings.warn(e.args[0])
31
+ continue
32
+
33
+ self.handle(cmd, data)
34
+
35
+ def handle(self, cmd, data):
36
+ match cmd:
37
+ case "PN":
38
+ self.point_dataset.set_column_names(data)
39
+ self.toolbar.refresh_comb()
40
+ case "TN":
41
+ self.trace_dataset.set_column_names(data)
42
+ self.toolbar.refresh_comb()
43
+ case "PD":
44
+ self.point_dataset.append(data)
45
+ case "TD":
46
+ self.trace_dataset.append(data)
47
+ case "ROLL":
48
+ self.point_dataset.roll()
49
+ case "PXY":
50
+ self.toolbar.set_point_text(data)
51
+ case "TXY":
52
+ self.toolbar.set_trace_text(data)
53
+ case _:
54
+ warnings.warn(f"QueueHandler - unknown command : {cmd}")
@@ -0,0 +1,234 @@
1
+ from multiprocessing import Queue
2
+ from typing import Literal
3
+
4
+ from .config import forms, ridx, style
5
+ from .dataset import Dataset
6
+ from .event_queue import EventQueue
7
+ from .ploter import PlotWidget
8
+ from .qt_compat import (BottomDockWidgetArea, QtCore, QtWidgets,
9
+ ScrollBarAlwaysOff, ScrollBarAlwaysOn,
10
+ TopDockWidgetArea)
11
+ from .toolbar import ToolBar
12
+
13
+
14
+ class MainWindow(QtWidgets.QMainWindow):
15
+
16
+ def __init__(self,
17
+ queue: Queue,
18
+ ncols=3,
19
+ plot_minimum_height=350,
20
+ plot_colors: list[tuple[int, int, int]] | None = None):
21
+ super().__init__()
22
+ self.ncols = ncols
23
+ self.need_reshuffled = False
24
+ self.plot_minimum_height = plot_minimum_height
25
+ self.plot_widgets: list[PlotWidget] = []
26
+ self.plot_colors = plot_colors
27
+ self.toolbar = ToolBar()
28
+ self.trace_data_box = Dataset()
29
+ self.point_data_box = Dataset()
30
+ self.queue = EventQueue(queue, self.toolbar, self.point_data_box,
31
+ self.trace_data_box)
32
+
33
+ self.init_ui()
34
+
35
+ self.timer = QtCore.QTimer()
36
+ self.timer.timeout.connect(self.update)
37
+ self.timer.start(250)
38
+
39
+ def init_ui(self):
40
+ self.setStyleSheet(style)
41
+ self.setMinimumHeight(500)
42
+ self.setMinimumWidth(700)
43
+ self.scroll = QtWidgets.QScrollArea(
44
+ ) # Scroll Area which contains the widgets, set as the centralWidget
45
+ self.widget = QtWidgets.QWidget(
46
+ ) # Widget that contains the collection of Vertical Box
47
+ self.layout = QtWidgets.QGridLayout()
48
+ self.widget.setLayout(self.layout)
49
+
50
+ #Scroll Area Properties
51
+ #self.setCorner(Qt.TopSection, Qt.TopDockWidgetArea);
52
+ self.scroll.setVerticalScrollBarPolicy(ScrollBarAlwaysOn)
53
+ self.scroll.setHorizontalScrollBarPolicy(ScrollBarAlwaysOff)
54
+ self.scroll.setWidgetResizable(True)
55
+ self.scroll.setWidget(self.widget)
56
+ self.setCentralWidget(self.scroll)
57
+
58
+ self.dock = QtWidgets.QDockWidget(self)
59
+ self.dock.setAllowedAreas(TopDockWidgetArea | BottomDockWidgetArea)
60
+ self.addDockWidget(TopDockWidgetArea, self.dock)
61
+ self.dock.setFloating(False)
62
+ self.dock.setWidget(self.toolbar)
63
+ self.dock.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable)
64
+ #self.tabifyDockWidget(self.dock,None);
65
+ #self.addDockWidget(self.dock);
66
+ #self.setStatusBar(self.toolbar);
67
+ #self.layout.addWidget(self.toolbar , 0 , 0 , 1, self.ncol);
68
+
69
+ self.setWindowTitle('Scroll multi view')
70
+ self.show()
71
+ self.toolbar.set_mainwindow(self)
72
+ self.toolbar.pb.setChecked(True)
73
+
74
+ @property
75
+ def mode(self) -> Literal["P", "T"]:
76
+ return self.toolbar.mode
77
+
78
+ @property
79
+ def dataset(self) -> Dataset:
80
+ return {"P": self.point_data_box, "T": self.trace_data_box}[self.mode]
81
+
82
+ def set_ncols(self, x: int):
83
+ x = max(1, min(10, int(x)))
84
+ if (x != self.ncols):
85
+ self.need_reshuffled = True
86
+ self.ncols = x
87
+
88
+ def add_subplot(self):
89
+ n = len(self.plot_widgets)
90
+ pw = PlotWidget(self.plot_minimum_height, self.plot_colors)
91
+ self.plot_widgets.append(pw)
92
+ grid_row = n // self.ncols
93
+ grid_col = n % self.ncols
94
+ self.layout.addWidget(pw, grid_row + 1, grid_col)
95
+ return pw
96
+
97
+ def create_subplots(self, xy_pairs):
98
+ for xn, yn in xy_pairs:
99
+ pw = self.add_subplot()
100
+ pw.set_X_label(xn)
101
+ pw.set_Y_label(yn)
102
+ self.do_link()
103
+ self.all_enable_auto_range()
104
+
105
+ def clear_subplots(self):
106
+ for i in range(len(self.plot_widgets)):
107
+ self.layout.removeWidget(self.plot_widgets[i])
108
+ self.plot_widgets[i].setParent(None)
109
+ self.plot_widgets.clear()
110
+
111
+ def remove_plot(self, w: PlotWidget):
112
+ w.setParent(None)
113
+ self.plot_widgets.remove(w)
114
+ self.reshuffle()
115
+
116
+ def drop_last_plot(self, i_=-1):
117
+ # delete the one
118
+ i = int(i_)
119
+ if (i < len(self.plot_widgets)):
120
+ w = self.plot_widgets[i]
121
+ w.setParent(None)
122
+ del w
123
+ del self.plot_widgets[i]
124
+ self.reshuffle()
125
+
126
+ def reshuffle(self):
127
+ for idx, widget in enumerate(self.plot_widgets):
128
+ widget.setParent(None)
129
+ grid_row = idx // self.ncols
130
+ grid_col = idx % self.ncols
131
+ self.layout.addWidget(widget, grid_row + 1, grid_col)
132
+
133
+ def keyPressEvent(self, ev):
134
+ #print(ev.text());
135
+ tx = ev.text()
136
+ if (tx in ['_', '-']):
137
+ self.set_ncols(self.ncols - 1)
138
+ elif (tx in ['=', '+']):
139
+ self.set_ncols(self.ncols + 1)
140
+
141
+ def mouse_click(self):
142
+ pass
143
+
144
+ def do_link(self):
145
+ """
146
+ link the plot
147
+
148
+ share the same x or y axis
149
+ """
150
+ same_X = {}
151
+ xy_pairs = self.toolbar.xypairs
152
+ for idx, xyn in enumerate(xy_pairs):
153
+ xn, yn = xyn
154
+ if xn not in same_X:
155
+ same_X[xn] = []
156
+ same_X[xn].append(idx)
157
+
158
+ sharex, sharey = self.toolbar.sharexy()
159
+
160
+ s_A = not (sharex and sharey)
161
+ for x, yidxs in same_X.items():
162
+ pre_yidx = -1
163
+ for yidx in yidxs:
164
+ if (-1 != pre_yidx):
165
+ if (s_A):
166
+ self.plot_widgets[pre_yidx].plotItem.vb.setXLink(None)
167
+ self.plot_widgets[pre_yidx].plotItem.vb.setYLink(None)
168
+
169
+ if sharex:
170
+ self.plot_widgets[pre_yidx].plotItem.vb.setXLink(
171
+ self.plot_widgets[yidx].plotItem.vb)
172
+
173
+ if sharey:
174
+ self.plot_widgets[pre_yidx].plotItem.vb.setYLink(
175
+ self.plot_widgets[yidx].plotItem.vb)
176
+ pre_yidx = yidx
177
+
178
+ def all_auto_range(self):
179
+ for pw in self.plot_widgets:
180
+ pw.auto_range()
181
+
182
+ def all_enable_auto_range(self):
183
+ for pw in self.plot_widgets:
184
+ pw.enable_auto_range()
185
+
186
+ def update(self):
187
+ # update the queue
188
+ self.queue.flush()
189
+
190
+ rescale = False
191
+
192
+ # setup the xyfm
193
+ if (self.toolbar.xypairs_dirty):
194
+ self.clear_subplots()
195
+ self.create_subplots(self.toolbar.xypairs)
196
+ self.toolbar.xypairs_dirty = False
197
+ rescale = True
198
+
199
+ if (self.toolbar.link_dirty):
200
+ self.do_link()
201
+ self.toolbar.link_dirty = False
202
+
203
+ if (self.need_reshuffled):
204
+ self.need_reshuffled = False
205
+ self.reshuffle()
206
+
207
+ # checking the log space
208
+ if (self.toolbar.xyfm_dirty):
209
+ for pw in self.plot_widgets:
210
+ pw.plotItem.ctrl.logXCheck.setChecked(self.toolbar.lx)
211
+ pw.plotItem.ctrl.logYCheck.setChecked(self.toolbar.ly)
212
+
213
+ #update the plot
214
+ # if clear is set then do the clear :
215
+ if (self.toolbar.CR_flag):
216
+ self.toolbar.CR_flag = False
217
+ self.dataset.clear_history()
218
+ self.dataset.dirty = True
219
+
220
+ if (self.dataset.dirty or self.toolbar.xyfm_dirty or rescale):
221
+ self.dataset.dirty = False
222
+ self.xyfm_dirty = False
223
+ for pw in self.plot_widgets:
224
+
225
+ fx = forms[self.toolbar.fx]
226
+ fy = forms[self.toolbar.fy]
227
+ for i in ridx:
228
+ x, y = self.dataset.get_data(i, pw.xname, pw.yname)
229
+ l = min(len(x), len(y))
230
+ x, y = fx(x[:l], 0), fy(y[:l], 0)
231
+ pw.set_data(i, x, y)
232
+ pw.update()
233
+ if rescale:
234
+ pw.auto_range()