mbapy 0.7.2__tar.gz → 0.7.4__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 (98) hide show
  1. {mbapy-0.7.2/mbapy.egg-info → mbapy-0.7.4}/PKG-INFO +39 -12
  2. mbapy-0.7.4/README.md +155 -0
  3. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/__version__.py +3 -3
  4. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/base.py +40 -23
  5. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/bio/peptide.py +3 -3
  6. mbapy-0.7.4/mbapy/plot.py +264 -0
  7. mbapy-0.7.2/mbapy/plot.py → mbapy-0.7.4/mbapy/plot_utils/bar_utils.py +44 -212
  8. mbapy-0.7.4/mbapy/plot_utils/scatter_utils.py +231 -0
  9. mbapy-0.7.4/mbapy/sci_utils/__init__.py +0 -0
  10. mbapy-0.7.4/mbapy/scripts/_script_utils_.py +57 -0
  11. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/duitang.py +3 -3
  12. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/extract-dir.py +19 -10
  13. mbapy-0.7.4/mbapy/scripts/hplc.py +449 -0
  14. mbapy-0.7.4/mbapy/scripts/mass.py +446 -0
  15. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/peptide.py +120 -61
  16. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/stats/reg.py +14 -10
  17. mbapy-0.7.4/mbapy/storage/mbapy-cli-scripts-list.json +92 -0
  18. mbapy-0.7.4/mbapy/web_utils/__init__.py +0 -0
  19. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/web_utils/request.py +2 -1
  20. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/web_utils/spider.py +82 -41
  21. mbapy-0.7.4/mbapy/web_utils/task.py +471 -0
  22. {mbapy-0.7.2 → mbapy-0.7.4/mbapy.egg-info}/PKG-INFO +39 -12
  23. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy.egg-info/SOURCES.txt +4 -0
  24. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy.egg-info/requires.txt +4 -0
  25. {mbapy-0.7.2 → mbapy-0.7.4}/requirements.json +6 -2
  26. {mbapy-0.7.2 → mbapy-0.7.4}/setup.py +2 -2
  27. mbapy-0.7.2/README.md +0 -128
  28. mbapy-0.7.2/mbapy/scripts/_script_utils_.py +0 -18
  29. mbapy-0.7.2/mbapy/scripts/hplc.py +0 -173
  30. mbapy-0.7.2/mbapy/scripts/mass.py +0 -278
  31. mbapy-0.7.2/mbapy/storage/mbapy-cli-scripts-list.json +0 -87
  32. mbapy-0.7.2/mbapy/web_utils/task.py +0 -314
  33. {mbapy-0.7.2 → mbapy-0.7.4}/LICENSE +0 -0
  34. {mbapy-0.7.2 → mbapy-0.7.4}/MANIFEST.in +0 -0
  35. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/__init__.py +0 -0
  36. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/bio/__init__.py +0 -0
  37. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/__init__.py +0 -0
  38. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/arch/CL/__init__.py +0 -0
  39. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/arch/CL/builder.py +0 -0
  40. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/arch/CL/trainer.py +0 -0
  41. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/arch/CLIP/__init__.py +0 -0
  42. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/arch/CLIP/builder.py +0 -0
  43. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/arch/CLIP/trainer.py +0 -0
  44. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/arch/__init__.py +0 -0
  45. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/bb.py +0 -0
  46. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/data.py +0 -0
  47. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/hyper_search.py +0 -0
  48. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/loss.py +0 -0
  49. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/m.py +0 -0
  50. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/optim.py +0 -0
  51. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/paper/__init__.py +0 -0
  52. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/paper/bb.py +0 -0
  53. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/dl_torch/utils.py +0 -0
  54. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/file.py +0 -0
  55. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/file_utils/__init__.py +0 -0
  56. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/file_utils/image.py +0 -0
  57. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/file_utils/video.py +0 -0
  58. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/game.py +0 -0
  59. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/paper.py +0 -0
  60. {mbapy-0.7.2/mbapy/sci_utils → mbapy-0.7.4/mbapy/plot_utils}/__init__.py +0 -0
  61. /mbapy-0.7.2/mbapy/web_utils/__init__.py → /mbapy-0.7.4/mbapy/plot_utils/line_utils.py +0 -0
  62. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/sci_utils/paper_download.py +0 -0
  63. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/sci_utils/paper_parse.py +0 -0
  64. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/sci_utils/paper_search.py +0 -0
  65. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/__init__.py +0 -0
  66. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/__main__.py +0 -0
  67. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/_main_.py +0 -0
  68. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/avif.py +0 -0
  69. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/cluster.py +0 -0
  70. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/cnipa.py +0 -0
  71. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/cp.py +0 -0
  72. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/extract_paper.py +0 -0
  73. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/file-size.py +0 -0
  74. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/mv.py +0 -0
  75. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/reviz.py +0 -0
  76. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/rm.py +0 -0
  77. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/scihub.py +0 -0
  78. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/scihub_selenium.py +0 -0
  79. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/splash_img.py +0 -0
  80. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/scripts/video.py +0 -0
  81. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/stats/__init__.py +0 -0
  82. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/stats/cluster.py +0 -0
  83. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/stats/df.py +0 -0
  84. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/stats/geography.py +0 -0
  85. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/stats/test.py +0 -0
  86. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/storage/libsci.dll +0 -0
  87. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/storage/libsci.so +0 -0
  88. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/storage/libstats.dll +0 -0
  89. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/storage/libstats.so +0 -0
  90. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/web.py +0 -0
  91. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy/web_utils/parse.py +0 -0
  92. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy.egg-info/dependency_links.txt +0 -0
  93. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy.egg-info/entry_points.txt +0 -0
  94. {mbapy-0.7.2 → mbapy-0.7.4}/mbapy.egg-info/top_level.txt +0 -0
  95. {mbapy-0.7.2 → mbapy-0.7.4}/setup.cfg +0 -0
  96. {mbapy-0.7.2 → mbapy-0.7.4}/test/test_base.py +0 -0
  97. {mbapy-0.7.2 → mbapy-0.7.4}/test/test_game.py +0 -0
  98. {mbapy-0.7.2 → mbapy-0.7.4}/test/test_web.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mbapy
3
- Version: 0.7.2
3
+ Version: 0.7.4
4
4
  Summary: MyBA in Python
5
5
  Home-page: https://github.com/BHM-Bob/BA_PY
6
6
  Author: BHM-Bob G
@@ -10,24 +10,49 @@ Description: <!--
10
10
  * @Author: BHM-Bob 2262029386@qq.com
11
11
  * @Date: 2022-10-19 22:16:22
12
12
  * @LastEditors: BHM-Bob 2262029386@qq.com
13
- * @LastEditTime: 2024-04-04 19:36:44
13
+ * @LastEditTime: 2024-04-30 10:19:58
14
14
  * @Description:
15
15
  -->
16
- # BA_PY: Optimize Your Workflow with Python!
17
- [![Downloads](https://static.pepy.tech/badge/mbapy)](https://pepy.tech/project/mbapy) ![PyPI - Downloads](https://img.shields.io/pypi/dm/mbapy) ![GitHub all releases](https://img.shields.io/github/downloads/BHM-Bob/BA_PY/total?label=GitHub%20all%20releases%20downloads)
18
16
 
19
- ![GitHub repo size](https://img.shields.io/github/repo-size/BHM-Bob/BA_PY) ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/BHM-Bob/BA_PY) [![GitHub Commit Activity](https://img.shields.io/github/commit-activity/m/BHM-Bob/BA_PY)](https://github.com/BHM-Bob/BA_PY/pulse)
17
+ <h1 style="text-align:center;">BA_PY: Optimize Your Workflow with Python!</h1>
18
+
19
+ <p style="text-align:center;">
20
+ <img src="https://static.pepy.tech/badge/mbapy" alt="Downloads" style="display:inline-block; margin-left:auto; margin-right:auto;" />
21
+ <img src="https://img.shields.io/pypi/dm/mbapy" alt="Downloads" style="display:inline-block; margin-left:auto; margin-right:auto;" />
22
+ <img src="https://img.shields.io/github/downloads/BHM-Bob/BA_PY/total?label=GitHub%20all%20releases%20downloads" alt="Downloads" style="display:inline-block; margin-left:auto; margin-right:auto;" />
23
+ </p>
24
+
25
+ <p style="text-align:center;">
26
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://img.shields.io/github/repo-size/BHM-Bob/BA_PY" alt="repo size" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
27
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://img.shields.io/github/languages/code-size/BHM-Bob/BA_PY" alt="code size" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
28
+ <a href="https://github.com/BHM-Bob/BA_PY/releases"><img src="https://img.shields.io/github/v/release/BHM-Bob/BA_PY?label=GitHub%20Release" alt="GitHub release (latest by date)" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
29
+ <a href="https://github.com/BHM-Bob/BA_PY/releases"><img src="https://img.shields.io/github/commit-activity/m/BHM-Bob/BA_PY" alt="GitHub Commit Activity" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
30
+ <a><img src="https://img.shields.io/github/last-commit/BHM-Bob/BA_PY?label=GitHub%20Last%20Commit" alt="GitHub last commit" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
31
+ </p>
32
+
33
+ <p style="text-align:center;">
34
+ <a href="https://pypi.org/project/mbapy/"><img src="https://img.shields.io/pypi/status/mbapy?label=PyPI%20Status" alt="PyPI Status" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
35
+ <a href="https://pypi.org/project/mbapy/"><img src="https://img.shields.io/pypi/v/mbapy?label=PyPI%20Release" alt="PyPI" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
36
+ <a href="https://pypi.org/project/mbapy/"><img src="https://img.shields.io/pypi/pyversions/mbapy" alt="python versions" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
37
+ </p>
38
+
39
+ <p style="text-align:center;">
40
+ <img alt="GitHub language count" src="https://img.shields.io/github/languages/count/BHM-Bob/BA_PY">
41
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://img.shields.io/readthedocs/ba-py" alt="docs" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
42
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://img.shields.io/github/license/BHM-Bob/BA_PY" alt="license" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
43
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://codeium.com/badges/main" alt="codeium" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
44
+ </p>
45
+
46
+ <p style="text-align:center;">
47
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://camo.githubusercontent.com/c292429e232884db22e86c2ea2ea7695bc49dc4ae13344003a95879eeb7425d8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f57696e646f77732d3030373844363f7374796c653d666f722d7468652d6261646765266c6f676f3d77696e646f7773266c6f676f436f6c6f723d7768697465" alt="windows" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
48
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://camo.githubusercontent.com/7eefb2ba052806d8a9ce69863c2eeb3b03cd5935ead7bd2e9245ae2e705a1adf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c696e75782d4643433632343f7374796c653d666f722d7468652d6261646765266c6f676f3d6c696e7578266c6f676f436f6c6f723d626c61636b" alt="linux" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
49
+ </p>
20
50
 
21
- ![PyPI - Status](https://img.shields.io/pypi/status/mbapy?label=PyPI%20Status) ![PyPI](https://img.shields.io/pypi/v/mbapy) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/mbapy)
22
-
23
- ![Read the Docs](https://img.shields.io/readthedocs/ba-py) ![GitHub](https://img.shields.io/github/license/BHM-Bob/BA_PY) [![built with Codeium](https://codeium.com/badges/main)](https://codeium.com)
24
-
25
- ![platform - WINDOWS](https://camo.githubusercontent.com/c292429e232884db22e86c2ea2ea7695bc49dc4ae13344003a95879eeb7425d8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f57696e646f77732d3030373844363f7374796c653d666f722d7468652d6261646765266c6f676f3d77696e646f7773266c6f676f436f6c6f723d7768697465) ![platform - LINUX](https://camo.githubusercontent.com/7eefb2ba052806d8a9ce69863c2eeb3b03cd5935ead7bd2e9245ae2e705a1adf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c696e75782d4643433632343f7374796c653d666f722d7468652d6261646765266c6f676f3d6c696e7578266c6f676f436f6c6f723d626c61636b)
26
51
 
27
52
  mbapy is a Python package that includes a collection of useful Python scripts as sub-modules, and it's goal is *Basic for All in Python*.
28
53
  mbapy primarily focus on data works, including data-retrieval, data-management, data-visualization, data-analysis and data-computation. It is built for both python-users and command-line-users.
29
54
 
30
- ## get start
55
+ <h2 style="text-align:center;">Get start</h2>
31
56
 
32
57
  #### install
33
58
  Now, mbapy only support pypi install:
@@ -58,10 +83,12 @@ Description: <!--
58
83
  - open source at:
59
84
  1. [github: https://github.com/BHM-Bob/BA_PY](https://github.com/BHM-Bob/BA_PY)
60
85
  2. [gitee: https://gitee.com/BHM-Bob/BA_PY](https://gitee.com/BHM-Bob/BA_PY)
86
+ 3. [SourceForge: https://sourceforge.net/projects/ba-py/](https://sourceforge.net/projects/ba-py/)
61
87
  - docs at: [read the docs: https://ba-py.rtfd.io](https://ba-py.readthedocs.io/en/latest/)
62
88
  - PyPI: [https://pypi.org/project/mbapy/](https://pypi.org/project/mbapy/)
63
89
 
64
- # contain
90
+ <h2 style="text-align:center;">Contents</h2>
91
+
65
92
  ## mbapy python package
66
93
  #### \_\_version\_\_
67
94
  *some version info*
mbapy-0.7.4/README.md ADDED
@@ -0,0 +1,155 @@
1
+ <!--
2
+ * @Author: BHM-Bob 2262029386@qq.com
3
+ * @Date: 2022-10-19 22:16:22
4
+ * @LastEditors: BHM-Bob 2262029386@qq.com
5
+ * @LastEditTime: 2024-04-30 10:19:58
6
+ * @Description:
7
+ -->
8
+
9
+ <h1 style="text-align:center;">BA_PY: Optimize Your Workflow with Python!</h1>
10
+
11
+ <p style="text-align:center;">
12
+ <img src="https://static.pepy.tech/badge/mbapy" alt="Downloads" style="display:inline-block; margin-left:auto; margin-right:auto;" />
13
+ <img src="https://img.shields.io/pypi/dm/mbapy" alt="Downloads" style="display:inline-block; margin-left:auto; margin-right:auto;" />
14
+ <img src="https://img.shields.io/github/downloads/BHM-Bob/BA_PY/total?label=GitHub%20all%20releases%20downloads" alt="Downloads" style="display:inline-block; margin-left:auto; margin-right:auto;" />
15
+ </p>
16
+
17
+ <p style="text-align:center;">
18
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://img.shields.io/github/repo-size/BHM-Bob/BA_PY" alt="repo size" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
19
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://img.shields.io/github/languages/code-size/BHM-Bob/BA_PY" alt="code size" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
20
+ <a href="https://github.com/BHM-Bob/BA_PY/releases"><img src="https://img.shields.io/github/v/release/BHM-Bob/BA_PY?label=GitHub%20Release" alt="GitHub release (latest by date)" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
21
+ <a href="https://github.com/BHM-Bob/BA_PY/releases"><img src="https://img.shields.io/github/commit-activity/m/BHM-Bob/BA_PY" alt="GitHub Commit Activity" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
22
+ <a><img src="https://img.shields.io/github/last-commit/BHM-Bob/BA_PY?label=GitHub%20Last%20Commit" alt="GitHub last commit" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
23
+ </p>
24
+
25
+ <p style="text-align:center;">
26
+ <a href="https://pypi.org/project/mbapy/"><img src="https://img.shields.io/pypi/status/mbapy?label=PyPI%20Status" alt="PyPI Status" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
27
+ <a href="https://pypi.org/project/mbapy/"><img src="https://img.shields.io/pypi/v/mbapy?label=PyPI%20Release" alt="PyPI" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
28
+ <a href="https://pypi.org/project/mbapy/"><img src="https://img.shields.io/pypi/pyversions/mbapy" alt="python versions" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
29
+ </p>
30
+
31
+ <p style="text-align:center;">
32
+ <img alt="GitHub language count" src="https://img.shields.io/github/languages/count/BHM-Bob/BA_PY">
33
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://img.shields.io/readthedocs/ba-py" alt="docs" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
34
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://img.shields.io/github/license/BHM-Bob/BA_PY" alt="license" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
35
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://codeium.com/badges/main" alt="codeium" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
36
+ </p>
37
+
38
+ <p style="text-align:center;">
39
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://camo.githubusercontent.com/c292429e232884db22e86c2ea2ea7695bc49dc4ae13344003a95879eeb7425d8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f57696e646f77732d3030373844363f7374796c653d666f722d7468652d6261646765266c6f676f3d77696e646f7773266c6f676f436f6c6f723d7768697465" alt="windows" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
40
+ <a href="https://github.com/BHM-Bob/BA_PY/"><img src="https://camo.githubusercontent.com/7eefb2ba052806d8a9ce69863c2eeb3b03cd5935ead7bd2e9245ae2e705a1adf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c696e75782d4643433632343f7374796c653d666f722d7468652d6261646765266c6f676f3d6c696e7578266c6f676f436f6c6f723d626c61636b" alt="linux" style="display:inline-block; margin-left:auto; margin-right:auto;" /></a>
41
+ </p>
42
+
43
+
44
+ mbapy is a Python package that includes a collection of useful Python scripts as sub-modules, and it's goal is *Basic for All in Python*.
45
+ mbapy primarily focus on data works, including data-retrieval, data-management, data-visualization, data-analysis and data-computation. It is built for both python-users and command-line-users.
46
+
47
+ <h2 style="text-align:center;">Get start</h2>
48
+
49
+ #### install
50
+ Now, mbapy only support pypi install:
51
+ ```
52
+ pip install mbapy
53
+ ```
54
+
55
+ mbapy is a multi-funtional package, and it does not require every third-party packages to make every sub-module work. However, it provides some requriements option to install more specified requirements to make some sub-modules work:
56
+ 1. bio: some packages for biology(sci).
57
+ install as `pip install mbapy[bio]`
58
+ 2. game: some packages for game(pygame).
59
+ install as `pip install mbapy[game]`
60
+ 3. full: full requirements to make almost every sub-module in mbapy work(except dl_torch).
61
+ install as `pip install mbapy[full]`
62
+
63
+ If you find the latest release version has some problems, you can try install the up-to-date version on github or gitee:
64
+ ```
65
+ pip install git+https://github.com/BHM-Bob/BA_PY.git
66
+ ```
67
+ ```
68
+ pip install git+https://gitee.com/BHM-Bob/BA_PY.git
69
+ ```
70
+
71
+ #### docs
72
+ The documentation for mbapy can be found on [read the docs](https://ba-py.readthedocs.io/en/latest/) or just in the `docs` folder.
73
+
74
+ #### web sites
75
+ - open source at:
76
+ 1. [github: https://github.com/BHM-Bob/BA_PY](https://github.com/BHM-Bob/BA_PY)
77
+ 2. [gitee: https://gitee.com/BHM-Bob/BA_PY](https://gitee.com/BHM-Bob/BA_PY)
78
+ 3. [SourceForge: https://sourceforge.net/projects/ba-py/](https://sourceforge.net/projects/ba-py/)
79
+ - docs at: [read the docs: https://ba-py.rtfd.io](https://ba-py.readthedocs.io/en/latest/)
80
+ - PyPI: [https://pypi.org/project/mbapy/](https://pypi.org/project/mbapy/)
81
+
82
+ <h2 style="text-align:center;">Contents</h2>
83
+
84
+ ## mbapy python package
85
+ #### \_\_version\_\_
86
+ *some version info*
87
+
88
+ #### base
89
+ *some utils for easier coding*
90
+
91
+ #### file
92
+ ##### image
93
+ *imgae utils*, including reading, saving and process a image into a feature tensor via pytorch.
94
+ ##### video
95
+ *video utils*, including extract frames or unique frames from a video.
96
+
97
+ #### plot
98
+ *pandas.dataFrame utils for plot and some simple plot based on plt*
99
+
100
+ #### web
101
+ *utils for web-crawler*
102
+ ##### request
103
+ *get a web hyml page or a selenium browser warpper for easier usage*.
104
+ ##### parse
105
+ *utils for parsing html*
106
+ ##### task
107
+ *small task manager*
108
+ ##### spider
109
+ *a light-weight web spider architecture*
110
+
111
+ #### stats
112
+ ##### cluster
113
+ *BAKmeans, KOptim, KBayesian from KMeans, and a func for many cluster*
114
+ ##### df
115
+ *pandas.dataFrame utils for stats*
116
+ ##### reg
117
+ *regression*
118
+ ##### test
119
+ *some test func(using scipy and mostly give a support for mbapy-style data input)*
120
+
121
+ #### dl-torch
122
+ *pytorch utils for deeplearning*
123
+ ##### bb
124
+ *basic blocks : tiny network structures*
125
+ ##### data
126
+ *utils for dataset loading*
127
+ ##### loss
128
+ *some loss function*
129
+ ##### m
130
+ *model : deeplearning model constructed with basic blocks*
131
+ ##### utils
132
+ *deeplearning training utils*
133
+ ##### optim
134
+ *learning rate scheduler*
135
+
136
+ #### paper
137
+ *sci-paper utils, contains paper searching, downloading and parsing*
138
+ ##### paper_search
139
+ *search papers via pubmed, baidu xueshu, wos*
140
+ ##### paper_download
141
+ *download papers via scihub*
142
+ ##### paper_parse
143
+ *parse paper from a pdf file into a dict of each sections*
144
+
145
+ #### scripts
146
+ *some useful scripts for command user*
147
+ launch by `python -m mbapy.scripts.XXX` or `mbapy-cli XXX`.
148
+
149
+ ## examples
150
+ #### web/crawler
151
+ 1. chaoxin ppt multi threads downloader (jpg->pdf)
152
+ 2. wujin search http://www.basechem.org
153
+ 3. chemSub search http://chemsub.online.fr
154
+ 4. cnipa https://pss-system.cponline.cnipa.gov.cn/seniorSearch
155
+
@@ -2,15 +2,15 @@
2
2
  Author: BHM-Bob 2262029386@qq.com
3
3
  Date: 2022-11-01 22:16:49
4
4
  LastEditors: BHM-Bob 2262029386@qq.com
5
- LastEditTime: 2024-04-21 21:06:53
5
+ LastEditTime: 2024-05-10 21:06:00
6
6
  Description:
7
7
  '''
8
8
 
9
9
  __title__ = "mbapy"
10
10
  __description__ = "MyBA in Python"
11
11
  __url__ = "https://github.com/BHM-Bob/BA_PY"
12
- __version__ = "0.7.2"
13
- __build__ = "20240421_0"
12
+ __version__ = "0.7.4"
13
+ __build__ = "20240510_0"
14
14
  __author__ = "BHM-Bob G"
15
15
  __author_email__ = "bhmfly@foxmail.com"
16
16
  __license__ = "MIT"
@@ -2,7 +2,7 @@
2
2
  Author: BHM-Bob 2262029386@qq.com
3
3
  Date: 2022-10-19 22:46:30
4
4
  LastEditors: BHM-Bob 2262029386@qq.com
5
- LastEditTime: 2024-03-01 10:09:58
5
+ LastEditTime: 2024-04-25 22:58:26
6
6
  Description:
7
7
  '''
8
8
  import ctypes
@@ -356,6 +356,10 @@ def parameter_checker(*arg_checkers, raise_err = True, **kwarg_checkers):
356
356
 
357
357
  Returns:
358
358
  A decorated function that performs argument validity checks before executing the original function.
359
+
360
+ Notes:
361
+ - If all checkers get passed, the original function is executed.
362
+ - If any checker fails, the function returns None or raises a ValueError, depending on the value of `raise_err`.
359
363
 
360
364
  Example usage:
361
365
  >>> @check_arguments(path = check_parameters_path, head = check_parameters_len)
@@ -366,32 +370,39 @@ def parameter_checker(*arg_checkers, raise_err = True, **kwarg_checkers):
366
370
  def decorator(func):
367
371
  @wraps(func)
368
372
  def wrapper(*args, **kwargs):
369
- # info string
370
373
  info_string = f"Parameter checker for {func.__code__.co_name} : Invalid value for argument "
374
+ def check_arg(checker, arg_name: str, arg_value):
375
+ if not checker(arg_value):
376
+ if raise_err:
377
+ raise ValueError(info_string+arg_name)
378
+ else:
379
+ return put_err(info_string+arg_name, False)
380
+ return True
381
+ # args_name will exclude *args and **kwargs with name of args and kwargs
382
+ args_name = list(func.__code__.co_varnames)[:func.__code__.co_argcount+
383
+ func.__code__.co_kwonlyargcount]
371
384
  # check positional arguments
372
- for i, arg_check in enumerate(arg_checkers):
385
+ for i, arg_checker in enumerate(arg_checkers):
373
386
  if i < len(args):
374
- arg = args[i]
375
- if not arg_check(arg):
376
- arg_name = func.__code__.co_varnames[i]
377
- if raise_err:
378
- raise ValueError(info_string+arg_name)
379
- else:
380
- # directly return a none value, skip the err pop
381
- return put_err(info_string+arg_name, None)
387
+ if not check_arg(arg_checker, args_name[i], args[i]):
388
+ return None
382
389
  # check keyword arguments
383
390
  for arg_name, kwarg_checker in kwarg_checkers.items():
384
- # pass the rigth arg name
385
- if arg_name in func.__code__.co_varnames:
391
+ # if passed the rigth arg name
392
+ if arg_name in args_name:
386
393
  # get the index of the argument
387
- idx = func.__code__.co_varnames.index(arg_name)
388
- # get the argument through the index if passed positionally
389
- arg = args[idx] if idx < len(args) else kwargs[arg_name]
390
- if not kwarg_checker(arg):
391
- if raise_err:
392
- raise ValueError(info_string+arg_name)
393
- else:
394
- return put_err(info_string+arg_name, None)
394
+ idx = args_name.index(arg_name)
395
+ # get arg value
396
+ if idx < len(args):
397
+ arg_value = args[idx]
398
+ elif arg_name in kwargs:
399
+ arg_value = kwargs[arg_name]
400
+ elif func.__defaults__ and idx-len(args) < len(func.__defaults__):
401
+ arg_value = func.__defaults__[idx-len(args)]
402
+ else:
403
+ raise TypeError(f'{func.__code__.co_name}() minssing required argument')
404
+ if not check_arg(kwarg_checker, arg_name, arg_value):
405
+ return None
395
406
  return func(*args, **kwargs)
396
407
  return wrapper
397
408
  return decorator
@@ -681,5 +692,11 @@ __all__ = [
681
692
 
682
693
  if __name__ == '__main__':
683
694
  # dev code
684
- # set_default_kwargs
685
- d = set_default_kwargs({'a':1}, discard_extra=True, eps = 0.5, min_samples = 3)
695
+ class Test:
696
+ @parameter_checker(b = lambda b: b in ['b', 'B'], raise_err=False)
697
+ def __init__(self, a, b: str = 'b', *args, **kwargs) -> None:
698
+ print(a, b)
699
+
700
+ Test('A')
701
+ Test('A', 'A', e = 'E')
702
+ Test('A', 'B', 10)
@@ -309,6 +309,8 @@ class Peptide:
309
309
  parts[-1] = parts[-1] + C_pg
310
310
  # generate AAs
311
311
  self.AAs = [AnimoAcid(part, aa_repr_w) for part in parts]
312
+ else:
313
+ self.AAs = []
312
314
 
313
315
  def flatten(self, inplace: bool = False):
314
316
  """
@@ -323,9 +325,7 @@ class Peptide:
323
325
  seq.append(aa)
324
326
  if inplace:
325
327
  self.AAs = seq
326
- return self
327
- else:
328
- return seq
328
+ return seq
329
329
 
330
330
  def repr(self, repr_w: int = 3, include_pg: bool = True,
331
331
  include_dash: bool = True):
@@ -0,0 +1,264 @@
1
+ from itertools import chain, combinations
2
+ from typing import Callable, Dict, List, Tuple, Union, Optional
3
+
4
+ import matplotlib.patches as patches
5
+ import matplotlib.pyplot as plt
6
+ import matplotlib.ticker as ticker
7
+ import numpy as np
8
+ import pandas as pd
9
+ import seaborn as sns
10
+ import statsmodels.api as sm
11
+
12
+ if __name__ == '__main__':
13
+ # dev mode
14
+ import mbapy.stats.test as mst
15
+ from mbapy.stats.df import (get_df_data, pro_bar_data, pro_bar_data_R,
16
+ sort_df_factors)
17
+ from mbapy.stats.test import p_value_to_stars
18
+ # Assembly of functions
19
+ from mbapy.plot_utils.bar_utils import AxisLable, pro_bar_data, plot_bar, plot_positional_hue
20
+ from mbapy.plot_utils.line_utils import *
21
+ from mbapy.plot_utils.scatter_utils import plot_reg, plot_scatter, add_scatter_legend
22
+ else:
23
+ # release mode
24
+ from .stats import test as mst
25
+ from .stats.df import (get_df_data, pro_bar_data, pro_bar_data_R,
26
+ sort_df_factors)
27
+ from .stats.test import p_value_to_stars
28
+ # Assembly of functions
29
+ from .plot_utils.bar_utils import AxisLable, pro_bar_data, plot_bar, plot_positional_hue
30
+ from .plot_utils.line_utils import *
31
+ from .plot_utils.scatter_utils import plot_reg, plot_scatter, add_scatter_legend
32
+
33
+ # plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文
34
+ plt.rcParams["font.family"] = 'Times New Roman'
35
+ plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
36
+ colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
37
+
38
+ def rgb2hex(r, g, b):
39
+ return '#'+('{:02X}' * 3).format(r, g, b)
40
+ def hex2rgb(hex:str):
41
+ return [int(hex[i:i+2], 16) for i in (1, 3, 5)]
42
+ def rgbs2hexs(rgbs:List[Tuple[float]]):
43
+ """
44
+ Takes a list of RGB tuples and converts them to a list of hexadecimal color codes.
45
+ Each RGB tuple must contain three floats between 0 and 1 representing the red, green, and blue
46
+ components of the color. Returns a list of hexadecimal color codes as strings.
47
+ """
48
+ return list(map(lambda x : rgb2hex(*[int(x[i]*255) for i in range(3)]),
49
+ rgbs))
50
+
51
+ def get_palette(n:int = 10, mode:Union[None, str] = None, return_n = True) -> List[str]:
52
+ """get a seq of hex colors
53
+ Parameters
54
+ ----------
55
+ n: how many colors required
56
+ mode: kind of colors
57
+ - hls : [default] sns.color_palette('hls', n)
58
+ - green : sum 5 grenns
59
+ - pair : plt.get_cmap('tab20')
60
+ - others : plt.get_cmap(mode)
61
+ """
62
+ assert n >= 1, 'n < 1'
63
+ ret = None
64
+ if mode == 'hls':
65
+ ret = rgbs2hexs(sns.color_palette('hls', n))
66
+ elif n <= 5 and mode == 'green':
67
+ ret = ['#80ab1c', '#405535', '#99b69b', '#92e4ce', '#72cb87'][0:n]
68
+ elif n <= 9:
69
+ ret = rgbs2hexs(plt.get_cmap('Set1').colors)
70
+ elif n <= 12:
71
+ ret = rgbs2hexs(plt.get_cmap('Set3').colors)
72
+ elif n <= 20 and mode == 'pair':
73
+ ret = rgbs2hexs(plt.get_cmap('tab20').colors)
74
+ else:
75
+ ret = rgbs2hexs(plt.get_cmap(mode).colors)
76
+ if return_n and ret is not None:
77
+ ret = ret[:n]
78
+ return ret
79
+
80
+
81
+ def calcu_swarm_pos(x: float, y: np.ndarray, width: float, d: Optional[float] = None):
82
+ """
83
+ This function calculates the x-coordinates for the data points in a swarm plot.
84
+ The x-coordinates are calculated based on the given x-coordinate, y-coordinates,
85
+ and width of the swarm. If d is not None, it will be used as the distance between
86
+ the data points. Otherwise, it will be calculated based on the number of data points.
87
+
88
+ Parameters:
89
+ - x: the x-coordinate of the center of the swarm.
90
+ - y: the y-coordinates of the data points.
91
+ - width: the width of the swarm.
92
+ - d: the distance between the data points. If None, it will be calculated based on the number of data points.
93
+
94
+ Returns:
95
+ - A numpy array of x-coordinates for the data points.
96
+ """
97
+ def _calcu_arithmetic(x, n, w, d):
98
+ if isinstance(d, float) or isinstance(d, int):
99
+ a0 = x - (n-1)*d/2
100
+ return np.linspace(a0, a0+d*(n-1), n)
101
+ if n == 1:
102
+ return x
103
+ else:
104
+ a0, d = x-w/2, w/(n-1)
105
+ return np.linspace(a0, a0+d*(n-1), n)
106
+ ret = np.zeros(len(y))
107
+ for y_u in np.unique(y):
108
+ y_idx = np.where(y == y_u)[0]
109
+ ret[y_idx] = _calcu_arithmetic(x, len(y_idx), width, d)
110
+ return ret
111
+
112
+ def qqplot(tags:List[str], df:pd.DataFrame, figsize = (12, 6), nrows = 1, ncols = 1, **kwargs):
113
+ """
114
+ Generate a QQ-plot for each column in the given DataFrame.
115
+
116
+ Parameters:
117
+ tags (List[str]): A list of column names to generate QQ-plots for.
118
+ df (pd.DataFrame): The DataFrame containing the data.
119
+ figsize (tuple, optional): The size of the figure. Defaults to (12, 6).
120
+ nrows (int, optional): The number of rows in the figure grid. Defaults to 1.
121
+ ncols (int, optional): The number of columns in the figure grid. Defaults to 1.
122
+ **kwargs: Additional keyword arguments including xlim, ylim, title, tick_size, and label_size.
123
+
124
+ Returns:
125
+ None
126
+ """
127
+ axs = []
128
+ fig = plt.figure(figsize = (12, 6))
129
+ for fig_idx in range(1, ncols*nrows+1):
130
+ axs.append(fig.add_subplot(nrows, ncols, fig_idx))
131
+ if 'xlim' in kwargs:
132
+ axs[-1].set_xlim(kwargs['xlim'])
133
+ if 'ylim' in kwargs:
134
+ axs[-1].set_ylim(kwargs['ylim'])
135
+ sm.qqplot(np.array(df[tags[fig_idx-1]]), fit=True, line="45", ax=axs[-1])
136
+ axs[-1].set_title(tags[fig_idx-1]+' - QQPlot', fontdict={'fontsize':15})
137
+ if 'title' in kwargs:
138
+ axs[-1].set_ylim(kwargs['title'][fig_idx-1])
139
+ if 'tick_size' in kwargs:
140
+ axs[-1].tick_params(labelsize = kwargs['tick_size'])
141
+ if 'label_size' in kwargs:
142
+ axs[-1].set_xlabel('Theoretical Quantiles', fontsize = kwargs['label_size'])
143
+ axs[-1].set_ylabel('Sample Quantiles', fontsize = kwargs['label_size'])
144
+ return axs
145
+
146
+ def save_show(path:str, dpi = 300, bbox_inches = 'tight', show: bool = True):
147
+ """
148
+ Saves the current matplotlib figure to a file at the specified path and displays the figure.
149
+
150
+ Parameters:
151
+ - path (str): The path where the figure will be saved.
152
+ - dpi (int, optional): The resolution of the saved figure in dots per inch. Default is 300.
153
+ - bbox_inches (str or Bbox, optional): The portion of the figure to save. Default is 'tight'.
154
+ - show (bool, optional): Whether to show the figure after saving. Default is True.
155
+ """
156
+ plt.tight_layout()
157
+ plt.gcf().savefig(path, dpi=dpi, bbox_inches = bbox_inches)
158
+ if show:
159
+ plt.show()
160
+
161
+ def plot_stats_star(x1: float, x2: float, h: float, endpoint: float, p_value: float,
162
+ ax = plt, p2star: Callable[[float], str] = p_value_to_stars):
163
+ """
164
+ Params
165
+ - x1: The x-coordinate of the left endpoint.
166
+ - x2: The x-coordinate of the right endpoint.
167
+ - h: The y-coordinate of the horizontal line.
168
+ - endpoint: The height of the endpoint.
169
+ - p_value: The p-value of the difference.
170
+ - ax: The `Axes` instance to plot on. Default is `plt`.
171
+ - p2star: A function that converts a p-value to a string of stars. Default is `p_value_to_stars`.
172
+
173
+ Returns:
174
+ None
175
+ """
176
+ ax.plot([x1, x2], [h, h], color='black')
177
+ ax.plot([x1, x1], [h, h-endpoint], color='black')
178
+ ax.plot([x2, x2], [h, h-endpoint], color='black')
179
+ ax.text((x1+x2)/2, h, p2star(p_value), ha='center')
180
+
181
+ def plot_turkey(means, std_errs, tukey_results, min_star = 1):
182
+ """
183
+ Plot a bar chart showing the means of different groups along with the standard errors.
184
+
185
+ Parameters:
186
+ - means: A list of mean values for each group.
187
+ - std_errs: A list of standard errors for each group.
188
+ - tukey_results: The Tukey's test results object.
189
+
190
+ Returns:
191
+ The current `Axes` instance.
192
+
193
+ This function plots a bar chart using the given mean values and standard errors. It also marks the groups with significant differences based on the Tukey's test results.
194
+ For each combination of groups, the function checks if the corresponding Tukey's test result indicates a significant difference. If so, it plots a horizontal line at the maximum height, vertical lines at the endpoints, and places a text label with stars indicating the p-value of the difference.
195
+ """
196
+ x = np.arange(len(means))
197
+ plt.bar(x, means, yerr=std_errs, capsize=5)
198
+
199
+ combins = np.array(list(combinations(range(len(means)), 2)))
200
+ height = max(means) + max(std_errs)
201
+ min_height = 0.05 * height
202
+ endpoint_height = [height - 0.05 * min_height, height + 0.05 * min_height]
203
+ for i, combination in enumerate(combins):
204
+ if tukey_results.reject[i] \
205
+ and len(p_value_to_stars(tukey_results.pvalues[i])) >= min_star:
206
+ plt.plot(combination, [height, height], color='black')
207
+ plt.plot([combination[0], combination[0]], endpoint_height, color='black')
208
+ plt.plot([combination[1], combination[1]], endpoint_height, color='black')
209
+ plt.text(np.mean(combination), height,
210
+ p_value_to_stars(tukey_results.pvalues[i]), ha='center')
211
+ height += min_height
212
+
213
+ plt.xticks(x, tukey_results.groupsunique)
214
+ return plt.gca()
215
+
216
+
217
+ __all__ = [
218
+ 'AxisLable',
219
+ 'pro_bar_data',
220
+ 'plot_bar',
221
+ 'plot_positional_hue',
222
+
223
+ 'plot_reg',
224
+ 'plot_scatter',
225
+ 'add_scatter_legend',
226
+
227
+ 'rgb2hex',
228
+ 'hex2rgb',
229
+ 'rgbs2hexs',
230
+ 'get_palette',
231
+ 'calcu_swarm_pos',
232
+ 'qqplot',
233
+ 'save_show',
234
+ 'plot_stats_star',
235
+ 'plot_turkey'
236
+ ]
237
+
238
+
239
+ if __name__ == '__main__':
240
+ # dev code
241
+ df = pd.read_excel('./data/plot.xlsx', sheet_name='MWM')
242
+ df['Animal Type'] = df['Animal Type'].astype('str')
243
+ model = mst.multicomp_turkeyHSD({'Animal Type':[]}, 'Duration', df)
244
+ result = mst.turkey_to_table(model)
245
+ print(result)
246
+ # sub_df = get_df_data({'Animal Type':[]}, ['Duration'], df)
247
+ sub_df = pro_bar_data(['Animal Type'], ['Duration'], df)
248
+ # test err
249
+ cols = get_palette(n = 4, mode = 'hls')
250
+ plot_bar(['Animal Type'], ['Duration'], df, err = sub_df['Duration_SE'], jitter = True,
251
+ edgecolor = [cols], linewidth = 5, colors = ['white'], jitter_kwargs = {'size': 10, 'alpha': 1, 'color': [cols]})
252
+ plt.show()
253
+ plot_turkey(sub_df['Duration'], sub_df['Duration_SE'], model)
254
+ plt.show()
255
+
256
+ df = pd.DataFrame({'Month': [5, 5, 6, 6, 7, 7, 8, 8, 9, 9],
257
+ 'Ozone': [23.61538, 22.22445, 29.44444, 18.20790, 59.11538, 31.63584, 59.96154, 39.68121, 31.44828, 24.14182]})
258
+ model = mst.multicomp_turkeyHSD({'Month':[]}, 'Ozone', df)
259
+ result = mst.turkey_to_table(model)
260
+ print(result)
261
+ sub_df = pro_bar_data(['Month'], ['Ozone'], df)
262
+ plot_turkey(sub_df['Ozone'], sub_df['Ozone_SE'], model)
263
+ plt.show()
264
+