QuLab 2.0.1__cp310-cp310-win_amd64.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.cp310-win_amd64.pyd +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=pprldpRI_kZ3ufoH1JByhi7WIqqwW7MpaRoL0kGchQk,395
3
+ qulab/fun.cp310-win_amd64.pyd,sha256=l5oopTAYLKn4EJwOrkrJqbBOd4ieZjzq1a2nap-3nhU,31232
4
+ qulab/version.py,sha256=pMl7p0vBanIg04EfboBE80RyG_KP7M0m9V3-qTl0YLQ,21
5
+ qulab/monitor/__init__.py,sha256=xEVDkJF8issrsDeLqQmDsvtRmrf-UiViFcGTWuzdlFU,43
6
+ qulab/monitor/__main__.py,sha256=k2H1H5Zf9LLXTDLISJkbikLH-z0f1e5i5i6wXXYPOrE,105
7
+ qulab/monitor/config.py,sha256=y_5StMkdrbZO1ziyKBrvIkB7Jclp9RCPK1QbsOhCxnY,785
8
+ qulab/monitor/dataset.py,sha256=199kx7A08XKDnUN8MUZ7Cl4bWf52M0Mx7jrZLRyTwhw,2532
9
+ qulab/monitor/event_queue.py,sha256=0fj-iP4g6rKaxyom-bL-NoecwPe48V1LlVLoRuGgX_Q,1877
10
+ qulab/monitor/mainwindow.py,sha256=qqw7O9PTTrPjKgZAi7fS14S-fylTK9pzO1tAXtaNNAA,8033
11
+ qulab/monitor/monitor.py,sha256=2AP-hhg1T6-38mieDm5_ONTIXnXYlIrSyOiAOxDKy0I,2398
12
+ qulab/monitor/ploter.py,sha256=dg7W28XTwEbBxHVtdPkFV135OQgoQwTi-NJCZQF-HYU,3724
13
+ qulab/monitor/qt_compat.py,sha256=Eq7zlA4_XstB92NhtAqebtWU_Btw4lcwFO30YxZ-TPE,804
14
+ qulab/monitor/toolbar.py,sha256=HxqG6ywKFyQJM2Q1s7SnhuzjbyeROczAZKwxztD1WJ8,8213
15
+ qulab/scan/__init__.py,sha256=sjw3_wUL8G2AyDKSl9jhvoCbqLGg2DEmloXJHfO067A,220
16
+ qulab/scan/base.py,sha256=4KYjT42qNuIc1axac6Qz4Tkcu9_ZtEpZ1QhxDS17haI,17691
17
+ qulab/scan/dataset.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ qulab/scan/expression.py,sha256=aTHplJPlvuW2R73X6oMcV5Gzeo8NSCre8Q3hE7mkCxI,15253
19
+ qulab/scan/optimize.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ qulab/scan/scanner.py,sha256=PXQwFPkpUIMwoL40FFbXvk693eXxP7YYaHQHAY1Ome4,8072
21
+ qulab/scan/transforms.py,sha256=OWiHE36qKqeOJI-vwo3BOjGi5Ya_xcYU0g7D2DDIGo4,268
22
+ qulab/scan/utils.py,sha256=DHGC-RcGbY7RmMEDvazPkC_nFqlj_N8Cr9spm_CGfuE,1061
23
+ qulab/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ qulab/storage/__main__.py,sha256=6-EjN0waX1yfcMPJXqpIr9UlrIEsSCFApm5G-ZeaPMQ,1742
25
+ qulab/storage/base_dataset.py,sha256=28y3-OZrqJ52p5sbirEpUgjb7hqwLLpd38KU9DCkD24,12217
26
+ qulab/storage/chunk.py,sha256=gfj6EhQbaFbgzRdPZpMc2HV75RIQJ-iQeq_ULQp6g9E,1761
27
+ qulab/storage/dataset.py,sha256=mH5UTI3RbuWqsSnjvmVz1BJ_MoEyYFNhyDD-Ng1P6N8,4782
28
+ qulab/storage/file.py,sha256=HplZpmYu1onC_lb7QuZ5DMRiabW6GU_beaxkixY5KfQ,8616
29
+ qulab/storage/storage.py,sha256=Lb_MVORuwu3DZsXos0M18T10MGDlz4pGWsEseUAib5k,2656
30
+ qulab/storage/backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ qulab/storage/backend/redis.py,sha256=M6nsJc6dWMCjz57-EeCPcMpsuuyV6hUal2fcCr9D9a4,5406
32
+ qulab/storage/models/__init__.py,sha256=4eS_O6ErY8sMCgLt2wEhTHcPvi0ebJGo7smLbvo7YjU,608
33
+ qulab/storage/models/base.py,sha256=nImgJcUGdesnEAcPdF0YzT6td7jeod2CUDsVL7jQkCE,118
34
+ qulab/storage/models/config.py,sha256=I6g5m76ePkDJ9Tr2xB0SAJwDu6jupCQvu1XGIKTPj2g,717
35
+ qulab/storage/models/file.py,sha256=x8h8QbmkhJBZo2REjFFYYbR_SV5OWvZ6Ghpiy1SY2FE,2805
36
+ qulab/storage/models/ipy.py,sha256=ZjflbhUNNjPcRcrXvZung72Y8oGPHWZnJTMoa0x706U,1632
37
+ qulab/storage/models/models.py,sha256=h7nPI0uctftbxe8_cu3WkF59tKS4BuAIGCBmaHsuRBc,2967
38
+ qulab/storage/models/record.py,sha256=F5yu-Sf1aK9pkfCihb2AUU8b5HLlYZAUzrkUkBDpx_4,5131
39
+ qulab/storage/models/report.py,sha256=WO_hahL3VwWn3vn8tFZQ2ffYahV7RllIlAJPFmbVkdA,820
40
+ qulab/storage/models/tag.py,sha256=KPpiEm0SHI613-XLu3NBYE-qeIO9gwuKPw6se2obgPw,2432
41
+ qulab/sys/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
+ qulab/sys/chat.py,sha256=t7wSlREOQ_Ke0pO9bfpkik9wY1qeiTbRF1dial9IbII,23137
43
+ qulab/sys/ipy_events.py,sha256=rGjsApv58_Gwd_TH6ecPnyXK34_ZYZsaX8tk32ozLGY,3014
44
+ qulab/sys/progress.py,sha256=2iYskzRdOC2EM4wtbzm0u1kovjGrF_A0W1kCxbftyzE,5540
45
+ qulab/sys/device/__init__.py,sha256=ZZxPJ9_MHModvghQoZOSWjIdeo3vhg2TJETDdrwQvkU,152
46
+ qulab/sys/device/basedevice.py,sha256=8VOBArKnv_kAq9E4RO-J0Y5-xpqKIdTKozV9w8NK8FY,6644
47
+ qulab/sys/device/loader.py,sha256=G9x78jV5OX9npHvn-Xz05cjjurwn1HPXT5fUlTV4i70,2587
48
+ qulab/sys/device/utils.py,sha256=yQYnpzXy6Z81u5LnE70dWtB7vQ2O-F74s4uD9TY6AHc,1610
49
+ qulab/sys/drivers/FakeInstrument.py,sha256=UBPjolpn8-ueo6-OexbepQL54DQnZrzbSCSiIbEcMak,1919
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=tsMjTG-E_EQokfWrZgJvxO3dTGaM6NOVzPPKsify23A,5164
53
+ qulab/sys/net/cli.py,sha256=B3whPuhwBhlKiFvpdLK-FTv2EYE1U8tYWyUYNq9K5qs,5859
54
+ qulab/sys/net/dhcp.py,sha256=zKd4jQvSc8xYr7PcyR0tLlChpUYBb-WUr7-RzKBnClM,24052
55
+ qulab/sys/net/dhcpd.py,sha256=NB3lVTdk8xkwf4B-v9pOB0ylNj6SbYELGLSPgEQkOak,5498
56
+ qulab/sys/net/kad.py,sha256=uf9bNU2M3JLk6ZH04PDEdrChs4OOkHYoBHYodGIn_WE,40123
57
+ qulab/sys/net/kcp.py,sha256=NUDSkCXAneZoL-KDi_yGNfIdWycSCJRSpH0KL-tvpVQ,5952
58
+ qulab/sys/net/nginx.py,sha256=dxpBmgj-Nw32FR4P3frh1FdENodUUpoICcdKiewYaLY,5156
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=ZXfQYcF9MhUp4tvm7LI6h0jKbF8LUStEOfiW-keoGC0,2663
62
+ qulab/sys/rpc/msgpack.py,sha256=H2ujTA-6q41eQB-HBU0d_3LdGzWqL7EYQfDbPEfu4zQ,36378
63
+ qulab/sys/rpc/msgpack.pyi,sha256=P_tQdQ9L1-Zw6ZR07Eg3Yr-6AhmWCMLbEMFgr5JHke4,1314
64
+ qulab/sys/rpc/rpc.py,sha256=LVqOj7786kU8HrrF4ZVicIDp1aNkafyjBvhz9WJkDfE,12391
65
+ qulab/sys/rpc/serialize.py,sha256=tCrXmdDPw5CacCC2VoY0bbB4qeAGnvPh6UFwfXgVIoA,3494
66
+ qulab/sys/rpc/server.py,sha256=W3bPwe8um1IeR_3HLx-ad6iCcbeuUQcSg11Ze4w6DJg,742
67
+ qulab/sys/rpc/socket.py,sha256=W3bPwe8um1IeR_3HLx-ad6iCcbeuUQcSg11Ze4w6DJg,742
68
+ qulab/sys/rpc/utils.py,sha256=BurIcqh8CS-Hsk1dYP6IiefK4qHivaEqD9_rBY083SA,619
69
+ qulab/sys/rpc/worker.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
+ qulab/visualization/__init__.py,sha256=Bkt9AK5c45d6HFLlT-f8cIppywXziHtJqhDtVxOoKKo,6317
71
+ qulab/visualization/__main__.py,sha256=WduINFl21B-XMsi2rg2cVhIyU11hKKX3zOsjc56QLiQ,1710
72
+ qulab/visualization/_autoplot.py,sha256=JLvyr36wQRUU7i61_TMqcODizWZvTizY5CSGS_ZZsCw,14234
73
+ qulab/visualization/plot_layout.py,sha256=yAnMONOms7_szCdng-8wPpUMPis5UnbaNNzV4KFBgso,13941
74
+ qulab/visualization/plot_seq.py,sha256=h9D0Yl_yO64IwlvBgzMu9EBKr9gg6y8QE55gu2PfTns,2783
75
+ qulab/visualization/qdat.py,sha256=HubXFu4nfcA7iUzghJGle1C86G6221hicLR0b-GqhKQ,5887
76
+ qulab/visualization/widgets.py,sha256=HcYwdhDtLreJiYaZuN3LfofjJmZcLwjMfP5aasebgDo,3266
77
+ QuLab-2.0.1.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
78
+ QuLab-2.0.1.dist-info/METADATA,sha256=NI3Uarm6V21L_ZOfXyn-HEQDCu_l_GNfOCKmE33Wm5c,3480
79
+ QuLab-2.0.1.dist-info/WHEEL,sha256=lO6CqtLHCAi38X3Es1a4R1lAjZFvN010IMRCFo2S7Mc,102
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-win_amd64
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()