QuLab 2.0.1__cp310-cp310-macosx_11_0_x86_64.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 (82) hide show
  1. QuLab-2.0.1.dist-info/LICENSE +21 -0
  2. QuLab-2.0.1.dist-info/METADATA +95 -0
  3. QuLab-2.0.1.dist-info/RECORD +82 -0
  4. QuLab-2.0.1.dist-info/WHEEL +5 -0
  5. QuLab-2.0.1.dist-info/entry_points.txt +2 -0
  6. QuLab-2.0.1.dist-info/top_level.txt +1 -0
  7. qulab/__init__.py +1 -0
  8. qulab/__main__.py +24 -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 +4 -0
  21. qulab/scan/base.py +548 -0
  22. qulab/scan/dataset.py +0 -0
  23. qulab/scan/expression.py +472 -0
  24. qulab/scan/optimize.py +0 -0
  25. qulab/scan/scanner.py +270 -0
  26. qulab/scan/transforms.py +16 -0
  27. qulab/scan/utils.py +37 -0
  28. qulab/storage/__init__.py +0 -0
  29. qulab/storage/__main__.py +51 -0
  30. qulab/storage/backend/__init__.py +0 -0
  31. qulab/storage/backend/redis.py +204 -0
  32. qulab/storage/base_dataset.py +352 -0
  33. qulab/storage/chunk.py +60 -0
  34. qulab/storage/dataset.py +127 -0
  35. qulab/storage/file.py +273 -0
  36. qulab/storage/models/__init__.py +22 -0
  37. qulab/storage/models/base.py +4 -0
  38. qulab/storage/models/config.py +28 -0
  39. qulab/storage/models/file.py +89 -0
  40. qulab/storage/models/ipy.py +58 -0
  41. qulab/storage/models/models.py +88 -0
  42. qulab/storage/models/record.py +161 -0
  43. qulab/storage/models/report.py +22 -0
  44. qulab/storage/models/tag.py +93 -0
  45. qulab/storage/storage.py +95 -0
  46. qulab/sys/__init__.py +0 -0
  47. qulab/sys/chat.py +688 -0
  48. qulab/sys/device/__init__.py +3 -0
  49. qulab/sys/device/basedevice.py +221 -0
  50. qulab/sys/device/loader.py +86 -0
  51. qulab/sys/device/utils.py +46 -0
  52. qulab/sys/drivers/FakeInstrument.py +52 -0
  53. qulab/sys/drivers/__init__.py +0 -0
  54. qulab/sys/ipy_events.py +125 -0
  55. qulab/sys/net/__init__.py +0 -0
  56. qulab/sys/net/bencoder.py +205 -0
  57. qulab/sys/net/cli.py +169 -0
  58. qulab/sys/net/dhcp.py +543 -0
  59. qulab/sys/net/dhcpd.py +176 -0
  60. qulab/sys/net/kad.py +1142 -0
  61. qulab/sys/net/kcp.py +192 -0
  62. qulab/sys/net/nginx.py +192 -0
  63. qulab/sys/progress.py +190 -0
  64. qulab/sys/rpc/__init__.py +0 -0
  65. qulab/sys/rpc/client.py +0 -0
  66. qulab/sys/rpc/exceptions.py +96 -0
  67. qulab/sys/rpc/msgpack.py +1052 -0
  68. qulab/sys/rpc/msgpack.pyi +41 -0
  69. qulab/sys/rpc/rpc.py +412 -0
  70. qulab/sys/rpc/serialize.py +139 -0
  71. qulab/sys/rpc/server.py +29 -0
  72. qulab/sys/rpc/socket.py +29 -0
  73. qulab/sys/rpc/utils.py +25 -0
  74. qulab/sys/rpc/worker.py +0 -0
  75. qulab/version.py +1 -0
  76. qulab/visualization/__init__.py +188 -0
  77. qulab/visualization/__main__.py +71 -0
  78. qulab/visualization/_autoplot.py +457 -0
  79. qulab/visualization/plot_layout.py +408 -0
  80. qulab/visualization/plot_seq.py +90 -0
  81. qulab/visualization/qdat.py +152 -0
  82. 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,95 @@
1
+ Metadata-Version: 2.1
2
+ Name: QuLab
3
+ Version: 2.0.1
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: matplotlib >=3.7.2
34
+ Requires-Dist: numpy >=1.13.3
35
+ Requires-Dist: ply >=3.11
36
+ Requires-Dist: scipy >=1.0.0
37
+
38
+ # QuLab
39
+ [![View build status](https://travis-ci.org/feihoo87/QuLab.svg?branch=master)](https://travis-ci.org/feihoo87/QuLab)
40
+ [![Coverage Status](https://coveralls.io/repos/github/feihoo87/QuLab/badge.svg)](https://coveralls.io/github/feihoo87/QuLab)
41
+ [![Updates](https://pyup.io/repos/github/feihoo87/QuLab/shield.svg)](https://pyup.io/repos/github/feihoo87/QuLab/)
42
+ [![Docs Status](https://readthedocs.org/projects/qulab/badge/?version=latest)](http://qulab.readthedocs.org)
43
+ [![PyPI version](https://badge.fury.io/py/QuLab.svg)](https://badge.fury.io/py/QuLab)
44
+ [![](https://img.shields.io/badge/python-3.6%2C%203.7-brightgreen.svg)]()
45
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3352232.svg)](https://doi.org/10.5281/zenodo.3352232)
46
+
47
+ **Documentation can be found at [qulab.readthedocs.org](https://qulab.readthedocs.org/).**
48
+
49
+ ## Installation
50
+ We encourage installing QuLab via the pip tool (a python package manager):
51
+ ```bash
52
+ python -m pip install QuLab
53
+ ```
54
+
55
+ To install from the latest source, you need to clone the GitHub repository on your machine.
56
+ ```bash
57
+ git clone https://github.com/feihoo87/QuLab.git
58
+ ```
59
+
60
+ Then dependencies and QuLab can be installed in this way:
61
+ ```bash
62
+ cd QuLab
63
+ python -m pip install -e .
64
+ ```
65
+
66
+ ## Usage
67
+
68
+
69
+ ## Running Tests
70
+ To run tests:
71
+
72
+ ```
73
+ python -m pip install -r requirements-dev.txt
74
+ python -m pytest
75
+ ```
76
+
77
+ ## Attribution
78
+ 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:
79
+ ```
80
+ @misc{xu_huikai_2019_3352232,
81
+ author = {Xu, Huikai},
82
+ title = {QuLab},
83
+ month = aug,
84
+ year = 2019,
85
+ doi = {10.5281/zenodo.3352232},
86
+ url = {https://doi.org/10.5281/zenodo.3352232}
87
+ }
88
+ ```
89
+
90
+ ## Reporting Issues
91
+ Please report all issues [on github](https://github.com/feihoo87/QuLab/issues).
92
+
93
+ ## License
94
+
95
+ [MIT](https://opensource.org/licenses/MIT)
@@ -0,0 +1,82 @@
1
+ qulab/__init__.py,sha256=8zLGg-DfQhnDl2Ky0n-zXpN-8e-g7iR0AcaI4l4Vvpk,32
2
+ qulab/__main__.py,sha256=HnWr_0eErzaJUkjeTpeR7-l5FASfYK-h0VtqQI-eVoc,371
3
+ qulab/fun.cpython-310-darwin.so,sha256=-fPL-Qi5PVXRqQ9-rUlYIGLeDU5OqNUB-n_AzZSb4M8,78416
4
+ qulab/version.py,sha256=pMl7p0vBanIg04EfboBE80RyG_KP7M0m9V3-qTl0YLQ,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=yT_L9Rdr9lwxds-uq-sC_lhnTQxJgIkSzQkiX9PYmug,216
16
+ qulab/scan/base.py,sha256=SAmv-QRPHcN_FlfKeMykbBatm5Qo5DS76PFt5h2xtWY,17143
17
+ qulab/scan/dataset.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ qulab/scan/expression.py,sha256=J0F7jFyCkMKcHieT5ok6alivjrnHXPqQ0Xil5czGDuI,14781
19
+ qulab/scan/optimize.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ qulab/scan/scanner.py,sha256=H5wXarVeJab6pNVfLEWB6jCmpeIdpUu6igR9vlaQ-wc,7802
21
+ qulab/scan/transforms.py,sha256=ReUuG57B_1GEgOwZZaxYbOTappG7yY9ERvagc2v48Pg,252
22
+ qulab/scan/utils.py,sha256=2bj7ggTNTK5LXwBDi8w7IzFqFjchoE6EhgSASC0fpDQ,1024
23
+ qulab/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ qulab/storage/__main__.py,sha256=3emxxRry8BB0m8hUZvJ_oBqkPy7ksV7flHB_KEDXZuI,1692
25
+ qulab/storage/base_dataset.py,sha256=4aKhqBNdZfdlm_z1Qy5dv0HrvgpvMdy8pbyfua8uE-4,11865
26
+ qulab/storage/chunk.py,sha256=dtck2Pem7OYYX3TYlnWwfqrgXSmkLhi0nN_ElbuS-c8,1701
27
+ qulab/storage/dataset.py,sha256=Q9asJxNwYNcmu7sSqsAdAntYIre9b4dGIiFnt1O-KI4,4655
28
+ qulab/storage/file.py,sha256=KAaXFI1SKdcCVWjopVqYaWU4WZgZU9Oh2epdqH1ADPw,8343
29
+ qulab/storage/storage.py,sha256=qRyR-5zRRx84DfsifozlYKMRj8bykwRyF7TW8oyFmwk,2561
30
+ qulab/storage/backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ qulab/storage/backend/redis.py,sha256=hNaPP0V1BSWbUcx4AxOhEXiR83c_BZqeVzeOYkb8-zM,5202
32
+ qulab/storage/models/__init__.py,sha256=DkKzQF7tYd1WL1gGPuCThBcGfpnCuZ_PTLrqV3M_EJ0,586
33
+ qulab/storage/models/base.py,sha256=QLXiTRCPcg28BCFxBHexAxdNLjh2ONkzgNavoFOBW9s,114
34
+ qulab/storage/models/config.py,sha256=Mxk0-YcK0WgA-7-2oIuDMAeBaUECzj-3_oPvgF7gYtE,689
35
+ qulab/storage/models/file.py,sha256=1Rypz1QSco6drBCiR_BS6Oy0ifOapBIeNEm0uDqqxBk,2716
36
+ qulab/storage/models/ipy.py,sha256=uYBeqWsOxxCWUsDpnwhxugh6C9OuH92OrChlLj0gddk,1574
37
+ qulab/storage/models/models.py,sha256=JUqtvk8ywulkcFL38WfTviuVOcdvSGakZYJS7jAPNig,2879
38
+ qulab/storage/models/record.py,sha256=L0k531bGF9JN-GLv3hG87tB7k0kuSBkEeC9vi6_qywE,4970
39
+ qulab/storage/models/report.py,sha256=j9ByrVoue-rwaXcnfTzVOSf1xDJdlZJq666agF0AZRY,798
40
+ qulab/storage/models/tag.py,sha256=c3cTxpJUoG9L6xyDvVuagYVhB32amzbkBOmVeRIZ5Zo,2339
41
+ qulab/sys/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
+ qulab/sys/chat.py,sha256=DlFLP_gbVyL8fDUyad6Xu8sjQCZJauLIvF31mj5BtMs,22449
43
+ qulab/sys/ipy_events.py,sha256=qvsqs7-CYQ-P4WtSe9UUZZ0tC88XxPMd9DM4LJALgEk,2889
44
+ qulab/sys/progress.py,sha256=Tk1B96_1QrlI4yU0cyZlf2wVsF238DjQGqXJVG2j4t0,5350
45
+ qulab/sys/device/__init__.py,sha256=bDqJrYQJx8YR4u_CYvJPpIBr6whP7pVnxnROTHk_yhA,149
46
+ qulab/sys/device/basedevice.py,sha256=iqyX2SQLb7aRWNE5Uj2yHkFOLqVrX2I1N-xubTDB5tQ,6423
47
+ qulab/sys/device/loader.py,sha256=AL0rNF4UZ-CUHoF8FNtT_ZGLwySvz7SDPsKALaJS8po,2501
48
+ qulab/sys/device/utils.py,sha256=H9TvMqHZABhFdIah4uT0x9FvQ6ZPwbvw-wCnWTy4rfo,1564
49
+ qulab/sys/drivers/FakeInstrument.py,sha256=kwIXN-dHmvGYBinmcCLxUQKm0ENiJpsMwgQIYNLDS2k,1867
50
+ qulab/sys/drivers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
+ qulab/sys/net/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ qulab/sys/net/bencoder.py,sha256=p85DtmVy3cna3Da07boau77el2Cnym5-mKGF4xCJSy4,4959
53
+ qulab/sys/net/cli.py,sha256=dm-JxbgZgFH2P_5Zu3kSrLzy2U_VRLswkvE1d3xGp0w,5690
54
+ qulab/sys/net/dhcp.py,sha256=gT5ehyvwW3y8E5u_DnYRd5I0KaddonmQJFVhlIS2yxM,23509
55
+ qulab/sys/net/dhcpd.py,sha256=pNC47i-hu8HTzCrKU0PatL3AbgEqe1ovmpLPwNoZLa8,5322
56
+ qulab/sys/net/kad.py,sha256=gGYb9cXbAdbYhubQdCRqOGigllBy0kSUp4z3_f3AWz0,38981
57
+ qulab/sys/net/kcp.py,sha256=oFyiosQ1o0qeVA9hODIYEZtJj4HN1aNLGVP6vbxouMs,5761
58
+ qulab/sys/net/nginx.py,sha256=QAQthr_Dux7xRpgqeY6BVxxre4dg0WJITztSk8Fn-jU,4964
59
+ qulab/sys/rpc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
+ qulab/sys/rpc/client.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ qulab/sys/rpc/exceptions.py,sha256=djK44hYVMixF2Y-lAXDGHlyyCmYGw7EJjB3I0ttejok,2567
62
+ qulab/sys/rpc/msgpack.py,sha256=s9mbPIkQktO1FiSAuE6ymM_1w8rIERA0gMm5GQkT7z8,35327
63
+ qulab/sys/rpc/msgpack.pyi,sha256=3dJgISPCTEBo65VaoGjcFkdLijPx6zJtKqcZiS9bcaE,1274
64
+ qulab/sys/rpc/rpc.py,sha256=9ZwzC79FgmbHXbO1Gjg4z0wZgHLDziTwVuS2aZpLJAk,11979
65
+ qulab/sys/rpc/serialize.py,sha256=0SR1me02mao2JwWR3rdjUIcOzh1m1JFb7fLEaw_q-pE,3355
66
+ qulab/sys/rpc/server.py,sha256=e3R0gwOHpLEkSp7Tb43FMSDvqSG-pjrkskdISKQRseE,713
67
+ qulab/sys/rpc/socket.py,sha256=e3R0gwOHpLEkSp7Tb43FMSDvqSG-pjrkskdISKQRseE,713
68
+ qulab/sys/rpc/utils.py,sha256=6YGFOkY7o09lkA_I1FIP9_1Up3k2F1KOkftvu0_8lxo,594
69
+ qulab/sys/rpc/worker.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
+ qulab/visualization/__init__.py,sha256=26cuHt3QIJXUb3VaMxlJx3IQTOUVJFKlYBZr7WMP53M,6129
71
+ qulab/visualization/__main__.py,sha256=9zKK3yZFy0leU40ou6BpRC1Fsetfc1gjjFzIZYIwP6Y,1639
72
+ qulab/visualization/_autoplot.py,sha256=p4jzsJFgtOhnU0iuZJvjTT2ar6fvGd9VmxBr5dx1JC8,13777
73
+ qulab/visualization/plot_layout.py,sha256=clNw9QjE_kVNpIIx2Ob4YhAz2fucPGMuzkoIrOJo_Y8,13533
74
+ qulab/visualization/plot_seq.py,sha256=lphYF4VhkEdc_wWr1kFBwrx2yujkyFPFaJ3pjr61awI,2693
75
+ qulab/visualization/qdat.py,sha256=ZeevBYWkzbww4xZnsjHhw7wRorJCBzbG0iEu-XQB4EA,5735
76
+ qulab/visualization/widgets.py,sha256=6KkiTyQ8J-ei70LbPQZAK35wjktY47w2IveOa682ftA,3180
77
+ QuLab-2.0.1.dist-info/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
78
+ QuLab-2.0.1.dist-info/METADATA,sha256=9lh5a31NtQa3tADAUrr94sSw38Mzza_1BSzEkHJVtPY,3385
79
+ QuLab-2.0.1.dist-info/WHEEL,sha256=v2akoWUNGxyk4Dpga8gpYszagodl-xQddd16moZ4Utw,111
80
+ QuLab-2.0.1.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
81
+ QuLab-2.0.1.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
82
+ QuLab-2.0.1.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_11_0_x86_64
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,24 @@
1
+ import click
2
+
3
+ from .monitor.__main__ import main as monitor
4
+ from .sys.net.cli import dht
5
+ from .visualization.__main__ import plot
6
+
7
+
8
+ @click.group()
9
+ def main():
10
+ pass
11
+
12
+
13
+ @main.command()
14
+ def hello():
15
+ """Print hello world."""
16
+ click.echo('hello, world')
17
+
18
+
19
+ main.add_command(monitor)
20
+ main.add_command(plot)
21
+ main.add_command(dht)
22
+
23
+ if __name__ == '__main__':
24
+ 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()