normi 0.1.0__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.
- normi-0.1.0/LICENSE +21 -0
- normi-0.1.0/MANIFEST.in +1 -0
- normi-0.1.0/PKG-INFO +167 -0
- normi-0.1.0/README.md +104 -0
- normi-0.1.0/extra-requirements.txt +14 -0
- normi-0.1.0/setup.cfg +44 -0
- normi-0.1.0/setup.py +113 -0
- normi-0.1.0/src/normi/__init__.py +11 -0
- normi-0.1.0/src/normi/__main__.py +130 -0
- normi-0.1.0/src/normi/_estimators.py +459 -0
- normi-0.1.0/src/normi/_typing.py +97 -0
- normi-0.1.0/src/normi/_utils.py +62 -0
- normi-0.1.0/src/normi.egg-info/PKG-INFO +167 -0
- normi-0.1.0/src/normi.egg-info/SOURCES.txt +19 -0
- normi-0.1.0/src/normi.egg-info/dependency_links.txt +1 -0
- normi-0.1.0/src/normi.egg-info/entry_points.txt +2 -0
- normi-0.1.0/src/normi.egg-info/requires.txt +41 -0
- normi-0.1.0/src/normi.egg-info/top_level.txt +1 -0
- normi-0.1.0/tests/test__estimators.py +164 -0
- normi-0.1.0/tests/test__utils.py +38 -0
normi-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Biomolecular Dynamics
|
|
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.
|
normi-0.1.0/MANIFEST.in
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include extra-requirements.txt
|
normi-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: normi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Estimator for Normalized Mutual Information
|
|
5
|
+
Home-page: https://github.com/moldyn/NorMI
|
|
6
|
+
Author: braniii
|
|
7
|
+
License: MIT License
|
|
8
|
+
Project-URL: Documentation, https://moldyn.github.io/NorMI
|
|
9
|
+
Project-URL: Source Code, https://github.com/moldyn/NorMI
|
|
10
|
+
Project-URL: Changelog, https://moldyn.github.io/NorMI/changelog
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/moldyn/NorMI/issues
|
|
12
|
+
Keywords: normalized mutual information,mutual information,Kraskov Estimator,KSG Estimator
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Natural Language :: English
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: numpy>=1.21.0
|
|
29
|
+
Requires-Dist: scipy
|
|
30
|
+
Requires-Dist: click>=8.0.0
|
|
31
|
+
Requires-Dist: beartype>=0.10.4
|
|
32
|
+
Requires-Dist: tqdm
|
|
33
|
+
Requires-Dist: scikit-learn>=1.0.0
|
|
34
|
+
Requires-Dist: typing_extensions>=3.9.0; python_version < "3.9"
|
|
35
|
+
Provides-Extra: testing
|
|
36
|
+
Requires-Dist: pytest-cov; extra == "testing"
|
|
37
|
+
Requires-Dist: pytest-rerunfailures; extra == "testing"
|
|
38
|
+
Requires-Dist: flake8; extra == "testing"
|
|
39
|
+
Requires-Dist: pytest; extra == "testing"
|
|
40
|
+
Provides-Extra: coding
|
|
41
|
+
Requires-Dist: wemake-python-styleguide; extra == "coding"
|
|
42
|
+
Provides-Extra: docs
|
|
43
|
+
Requires-Dist: mkdocs-click; extra == "docs"
|
|
44
|
+
Requires-Dist: mkdocstrings; extra == "docs"
|
|
45
|
+
Requires-Dist: mkdocs-section-index; extra == "docs"
|
|
46
|
+
Requires-Dist: mkdocs-gen-files; extra == "docs"
|
|
47
|
+
Requires-Dist: mkdocs-literate-nav; extra == "docs"
|
|
48
|
+
Requires-Dist: mkdocstrings-python; extra == "docs"
|
|
49
|
+
Requires-Dist: mkdocs-material; extra == "docs"
|
|
50
|
+
Provides-Extra: all
|
|
51
|
+
Requires-Dist: mkdocs-click; extra == "all"
|
|
52
|
+
Requires-Dist: pytest-rerunfailures; extra == "all"
|
|
53
|
+
Requires-Dist: flake8; extra == "all"
|
|
54
|
+
Requires-Dist: pytest-cov; extra == "all"
|
|
55
|
+
Requires-Dist: pytest; extra == "all"
|
|
56
|
+
Requires-Dist: mkdocstrings; extra == "all"
|
|
57
|
+
Requires-Dist: wemake-python-styleguide; extra == "all"
|
|
58
|
+
Requires-Dist: mkdocs-section-index; extra == "all"
|
|
59
|
+
Requires-Dist: mkdocs-gen-files; extra == "all"
|
|
60
|
+
Requires-Dist: mkdocs-literate-nav; extra == "all"
|
|
61
|
+
Requires-Dist: mkdocstrings-python; extra == "all"
|
|
62
|
+
Requires-Dist: mkdocs-material; extra == "all"
|
|
63
|
+
|
|
64
|
+
<div align="center">
|
|
65
|
+
<!--
|
|
66
|
+
|
|
67
|
+
<img class="lightmode" style="width: 400px;" src="https://github.com/moldyn/normi/blob/main/docs/logo_large_light.svg?raw=true#gh-light-mode-only" />
|
|
68
|
+
-->
|
|
69
|
+
|
|
70
|
+
<p>
|
|
71
|
+
<a href="https://github.com/wemake-services/wemake-python-styleguide" alt="wemake-python-styleguide">
|
|
72
|
+
<img src="https://img.shields.io/badge/style-wemake-000000.svg" /></a>
|
|
73
|
+
<a href="https://beartype.rtfd.io" alt="bear-ified">
|
|
74
|
+
<img src="https://raw.githubusercontent.com/beartype/beartype-assets/main/badge/bear-ified.svg" /></a>
|
|
75
|
+
<a href="https://pypi.org/project/normi" alt="PyPI">
|
|
76
|
+
<img src="https://img.shields.io/pypi/v/normi" /></a>
|
|
77
|
+
<a href="https://anaconda.org/conda-forge/normi" alt="conda version">
|
|
78
|
+
<img src="https://img.shields.io/conda/vn/conda-forge/normi" /></a>
|
|
79
|
+
<a href="https://pepy.tech/project/normi" alt="Downloads">
|
|
80
|
+
<img src="https://static.pepy.tech/badge/normi" /></a>
|
|
81
|
+
<a href="https://github.com/moldyn/normi/actions/workflows/pytest.yml" alt="GitHub Workflow Status">
|
|
82
|
+
<img src="https://img.shields.io/github/actions/workflow/status/moldyn/normi/pytest.yml?branch=main"></a>
|
|
83
|
+
<a href="https://codecov.io/gh/moldyn/normi" alt="Code coverage">
|
|
84
|
+
<img src="https://codecov.io/gh/moldyn/normi/branch/main/graph/badge.svg?token=KNWDAUXIGI" /></a>
|
|
85
|
+
<a href="https://github.com/moldyn/normi/actions/workflows/codeql.yml" alt="CodeQL">
|
|
86
|
+
<img src="https://github.com/moldyn/normi/actions/workflows/codeql.yml/badge.svg?branch=main" /></a>
|
|
87
|
+
<a href="https://img.shields.io/pypi/pyversions/normi" alt="PyPI - Python Version">
|
|
88
|
+
<img src="https://img.shields.io/pypi/pyversions/normi" /></a>
|
|
89
|
+
<a href="https://moldyn.github.io/normi" alt="Docs">
|
|
90
|
+
<img src="https://img.shields.io/badge/MkDocs-Documentation-brightgreen" /></a>
|
|
91
|
+
<a href="https://github.com/moldyn/normi/blob/main/LICENSE" alt="License">
|
|
92
|
+
<img src="https://img.shields.io/github/license/moldyn/normi" /></a>
|
|
93
|
+
</p>
|
|
94
|
+
|
|
95
|
+
<p>
|
|
96
|
+
<a href="https://moldyn.github.io/normi">Docs</a> •
|
|
97
|
+
<a href="#features">Features</a> •
|
|
98
|
+
<a href="#installation">Installation</a> •
|
|
99
|
+
<a href="#usage">Usage</a> •
|
|
100
|
+
<a href="https://moldyn.github.io/normi/faq">FAQ</a>
|
|
101
|
+
</p>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
# NorMI: Nonparametric Normalized Mutual Information Estimator Based on $k$-NN Statistics
|
|
105
|
+
This software provides an extension to the Kraskov-Estimator to allow normalizing the mutual information.
|
|
106
|
+
|
|
107
|
+
The method will be published soon as:
|
|
108
|
+
> **Adaptive Entropy-Based Normalization for (High-Dimensional) Mutual Information**
|
|
109
|
+
> D. Nagel, G. Diez, and G. Stock,
|
|
110
|
+
|
|
111
|
+
If you use this software package, please cite the above mentioned paper.
|
|
112
|
+
|
|
113
|
+
## Features
|
|
114
|
+
- Intuitive usage via [module](#module---inside-a-python-script) and via [CI](#ci---usage-directly-from-the-command-line)
|
|
115
|
+
- Sklearn-style API for fast integration into your Python workflow
|
|
116
|
+
- No magic, only a single parameter which can be optimized via cross-validation
|
|
117
|
+
- Extensive [documentation](https://moldyn.github.io/normi) and detailed discussion in publication
|
|
118
|
+
|
|
119
|
+
## Installation
|
|
120
|
+
<!--
|
|
121
|
+
The package is called `normi` and is available via [PyPI](https://pypi.org/project/normi) or [conda](https://anaconda.org/conda-forge/normi). To install it, simply call:
|
|
122
|
+
```bash
|
|
123
|
+
python3 -m pip install --upgrade normi
|
|
124
|
+
```
|
|
125
|
+
or
|
|
126
|
+
```
|
|
127
|
+
conda install -c conda-forge normi
|
|
128
|
+
```
|
|
129
|
+
or for the latest dev version
|
|
130
|
+
-->
|
|
131
|
+
The package is not yet published and only available directly from github
|
|
132
|
+
```bash
|
|
133
|
+
# via ssh key
|
|
134
|
+
python3 -m pip install git+ssh://git@github.com/moldyn/normi.git
|
|
135
|
+
|
|
136
|
+
# or via password-based login
|
|
137
|
+
python3 -m pip install git+https://github.com/moldyn/normi.git
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Shell Completion
|
|
141
|
+
Using the `bash`, `zsh` or `fish` shell click provides an easy way to provide shell completion, checkout the [docs](https://click.palletsprojects.com/en/8.0.x/shell-completion).
|
|
142
|
+
In the case of bash you need to add following line to your `~/.bashrc`
|
|
143
|
+
```bash
|
|
144
|
+
eval "$(_NORMALIZED_MI_COMPLETE=bash_source normi)"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Usage
|
|
148
|
+
In general one can call the module directly by its entry point `$ normi` or by calling the module `$ python -m normi`. The latter method is preferred to ensure using the desired python environment. For enabling the shell completion, the entry point needs to be used.
|
|
149
|
+
|
|
150
|
+
### CI - Usage Directly from the Command Line
|
|
151
|
+
The module brings a rich CI using [click](https://click.palletsprojects.com).
|
|
152
|
+
Each module and submodule contains a detailed help, which can be accessed by
|
|
153
|
+
...
|
|
154
|
+
|
|
155
|
+
tba
|
|
156
|
+
|
|
157
|
+
### Module - Inside a Python Script
|
|
158
|
+
```python
|
|
159
|
+
from normi import NormalizedMI
|
|
160
|
+
|
|
161
|
+
# Load file
|
|
162
|
+
# X is np.ndarray of shape (n_samples, n_features)
|
|
163
|
+
|
|
164
|
+
nmi = NormalizedMI()
|
|
165
|
+
nmi.fit(X)
|
|
166
|
+
...
|
|
167
|
+
```
|
normi-0.1.0/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<!--
|
|
3
|
+
<img class="darkmode" style="width: 400px;" src="https://github.com/moldyn/normi/blob/main/docs/logo_large_dark.svg?raw=true#gh-dark-mode-only" />
|
|
4
|
+
<img class="lightmode" style="width: 400px;" src="https://github.com/moldyn/normi/blob/main/docs/logo_large_light.svg?raw=true#gh-light-mode-only" />
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
<p>
|
|
8
|
+
<a href="https://github.com/wemake-services/wemake-python-styleguide" alt="wemake-python-styleguide">
|
|
9
|
+
<img src="https://img.shields.io/badge/style-wemake-000000.svg" /></a>
|
|
10
|
+
<a href="https://beartype.rtfd.io" alt="bear-ified">
|
|
11
|
+
<img src="https://raw.githubusercontent.com/beartype/beartype-assets/main/badge/bear-ified.svg" /></a>
|
|
12
|
+
<a href="https://pypi.org/project/normi" alt="PyPI">
|
|
13
|
+
<img src="https://img.shields.io/pypi/v/normi" /></a>
|
|
14
|
+
<a href="https://anaconda.org/conda-forge/normi" alt="conda version">
|
|
15
|
+
<img src="https://img.shields.io/conda/vn/conda-forge/normi" /></a>
|
|
16
|
+
<a href="https://pepy.tech/project/normi" alt="Downloads">
|
|
17
|
+
<img src="https://static.pepy.tech/badge/normi" /></a>
|
|
18
|
+
<a href="https://github.com/moldyn/normi/actions/workflows/pytest.yml" alt="GitHub Workflow Status">
|
|
19
|
+
<img src="https://img.shields.io/github/actions/workflow/status/moldyn/normi/pytest.yml?branch=main"></a>
|
|
20
|
+
<a href="https://codecov.io/gh/moldyn/normi" alt="Code coverage">
|
|
21
|
+
<img src="https://codecov.io/gh/moldyn/normi/branch/main/graph/badge.svg?token=KNWDAUXIGI" /></a>
|
|
22
|
+
<a href="https://github.com/moldyn/normi/actions/workflows/codeql.yml" alt="CodeQL">
|
|
23
|
+
<img src="https://github.com/moldyn/normi/actions/workflows/codeql.yml/badge.svg?branch=main" /></a>
|
|
24
|
+
<a href="https://img.shields.io/pypi/pyversions/normi" alt="PyPI - Python Version">
|
|
25
|
+
<img src="https://img.shields.io/pypi/pyversions/normi" /></a>
|
|
26
|
+
<a href="https://moldyn.github.io/normi" alt="Docs">
|
|
27
|
+
<img src="https://img.shields.io/badge/MkDocs-Documentation-brightgreen" /></a>
|
|
28
|
+
<a href="https://github.com/moldyn/normi/blob/main/LICENSE" alt="License">
|
|
29
|
+
<img src="https://img.shields.io/github/license/moldyn/normi" /></a>
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
<p>
|
|
33
|
+
<a href="https://moldyn.github.io/normi">Docs</a> •
|
|
34
|
+
<a href="#features">Features</a> •
|
|
35
|
+
<a href="#installation">Installation</a> •
|
|
36
|
+
<a href="#usage">Usage</a> •
|
|
37
|
+
<a href="https://moldyn.github.io/normi/faq">FAQ</a>
|
|
38
|
+
</p>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
# NorMI: Nonparametric Normalized Mutual Information Estimator Based on $k$-NN Statistics
|
|
42
|
+
This software provides an extension to the Kraskov-Estimator to allow normalizing the mutual information.
|
|
43
|
+
|
|
44
|
+
The method will be published soon as:
|
|
45
|
+
> **Adaptive Entropy-Based Normalization for (High-Dimensional) Mutual Information**
|
|
46
|
+
> D. Nagel, G. Diez, and G. Stock,
|
|
47
|
+
|
|
48
|
+
If you use this software package, please cite the above mentioned paper.
|
|
49
|
+
|
|
50
|
+
## Features
|
|
51
|
+
- Intuitive usage via [module](#module---inside-a-python-script) and via [CI](#ci---usage-directly-from-the-command-line)
|
|
52
|
+
- Sklearn-style API for fast integration into your Python workflow
|
|
53
|
+
- No magic, only a single parameter which can be optimized via cross-validation
|
|
54
|
+
- Extensive [documentation](https://moldyn.github.io/normi) and detailed discussion in publication
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
<!--
|
|
58
|
+
The package is called `normi` and is available via [PyPI](https://pypi.org/project/normi) or [conda](https://anaconda.org/conda-forge/normi). To install it, simply call:
|
|
59
|
+
```bash
|
|
60
|
+
python3 -m pip install --upgrade normi
|
|
61
|
+
```
|
|
62
|
+
or
|
|
63
|
+
```
|
|
64
|
+
conda install -c conda-forge normi
|
|
65
|
+
```
|
|
66
|
+
or for the latest dev version
|
|
67
|
+
-->
|
|
68
|
+
The package is not yet published and only available directly from github
|
|
69
|
+
```bash
|
|
70
|
+
# via ssh key
|
|
71
|
+
python3 -m pip install git+ssh://git@github.com/moldyn/normi.git
|
|
72
|
+
|
|
73
|
+
# or via password-based login
|
|
74
|
+
python3 -m pip install git+https://github.com/moldyn/normi.git
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Shell Completion
|
|
78
|
+
Using the `bash`, `zsh` or `fish` shell click provides an easy way to provide shell completion, checkout the [docs](https://click.palletsprojects.com/en/8.0.x/shell-completion).
|
|
79
|
+
In the case of bash you need to add following line to your `~/.bashrc`
|
|
80
|
+
```bash
|
|
81
|
+
eval "$(_NORMALIZED_MI_COMPLETE=bash_source normi)"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Usage
|
|
85
|
+
In general one can call the module directly by its entry point `$ normi` or by calling the module `$ python -m normi`. The latter method is preferred to ensure using the desired python environment. For enabling the shell completion, the entry point needs to be used.
|
|
86
|
+
|
|
87
|
+
### CI - Usage Directly from the Command Line
|
|
88
|
+
The module brings a rich CI using [click](https://click.palletsprojects.com).
|
|
89
|
+
Each module and submodule contains a detailed help, which can be accessed by
|
|
90
|
+
...
|
|
91
|
+
|
|
92
|
+
tba
|
|
93
|
+
|
|
94
|
+
### Module - Inside a Python Script
|
|
95
|
+
```python
|
|
96
|
+
from normi import NormalizedMI
|
|
97
|
+
|
|
98
|
+
# Load file
|
|
99
|
+
# X is np.ndarray of shape (n_samples, n_features)
|
|
100
|
+
|
|
101
|
+
nmi = NormalizedMI()
|
|
102
|
+
nmi.fit(X)
|
|
103
|
+
...
|
|
104
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Extra requirements
|
|
2
|
+
# package[version_required]: tag1, tag2, ...
|
|
3
|
+
flake8: testing
|
|
4
|
+
wemake-python-styleguide: coding
|
|
5
|
+
pytest: testing
|
|
6
|
+
pytest-cov: testing
|
|
7
|
+
pytest-rerunfailures: testing
|
|
8
|
+
mkdocs-material: docs
|
|
9
|
+
mkdocstrings: docs
|
|
10
|
+
mkdocstrings-python: docs
|
|
11
|
+
mkdocs-literate-nav: docs
|
|
12
|
+
mkdocs-gen-files: docs
|
|
13
|
+
mkdocs-section-index: docs
|
|
14
|
+
mkdocs-click: docs
|
normi-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[tool:pytest]
|
|
2
|
+
addopts =
|
|
3
|
+
--strict-markers
|
|
4
|
+
--doctest-modules
|
|
5
|
+
--reruns 5
|
|
6
|
+
--reruns-delay 1
|
|
7
|
+
--cov-report=term-missing
|
|
8
|
+
--cov=src/normi tests/
|
|
9
|
+
|
|
10
|
+
[flake8]
|
|
11
|
+
format = wemake
|
|
12
|
+
show-source = True
|
|
13
|
+
statistics = True
|
|
14
|
+
doctests = True
|
|
15
|
+
max-complexity = 10
|
|
16
|
+
count = True
|
|
17
|
+
dictionaries = en_US, python, technical
|
|
18
|
+
spellcheck-targets = comments
|
|
19
|
+
rst-roles = class, func, ref
|
|
20
|
+
rst-directives = todo
|
|
21
|
+
ignore =
|
|
22
|
+
S101, C101, N, DAR401, DAR402, W504,
|
|
23
|
+
WPS306, WPS352, WPS120, WPS111, WPS305, WPS326, WPS115
|
|
24
|
+
exclude = .git, src/*/__pycache__, docs, build, dist
|
|
25
|
+
per-file-ignores =
|
|
26
|
+
src/*/__init__.py:F401, F403, D104, D400, E501
|
|
27
|
+
setup.py:D100
|
|
28
|
+
tests/*.py:WPS, DAR101, DAR201
|
|
29
|
+
|
|
30
|
+
[isort]
|
|
31
|
+
include_trailing_comma = true
|
|
32
|
+
multi_line_output = 3
|
|
33
|
+
line_length = 79
|
|
34
|
+
skip = src/*/__init__.py
|
|
35
|
+
|
|
36
|
+
[darglint]
|
|
37
|
+
strictness = short
|
|
38
|
+
docstring_style = numpy
|
|
39
|
+
ignore_regex = ^_(.*)
|
|
40
|
+
|
|
41
|
+
[egg_info]
|
|
42
|
+
tag_build =
|
|
43
|
+
tag_date = 0
|
|
44
|
+
|
normi-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import pathlib
|
|
3
|
+
import sys
|
|
4
|
+
from collections import defaultdict
|
|
5
|
+
|
|
6
|
+
import setuptools
|
|
7
|
+
|
|
8
|
+
# check for python version
|
|
9
|
+
if sys.version_info < (3, 8):
|
|
10
|
+
raise SystemExit('Python 3.8+ is required!')
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_extra_requirements(path, add_all=True):
|
|
14
|
+
"""Parse extra-requirements file."""
|
|
15
|
+
with open(path) as depfile:
|
|
16
|
+
extra_deps = defaultdict(set)
|
|
17
|
+
for line in depfile:
|
|
18
|
+
if not line.startswith('#'):
|
|
19
|
+
if ':' not in line:
|
|
20
|
+
raise ValueError(
|
|
21
|
+
f'Dependency in {path} not correct formatted: {line}',
|
|
22
|
+
)
|
|
23
|
+
dep, tags = line.split(':')
|
|
24
|
+
tags = {tag.strip() for tag in tags.split(',')}
|
|
25
|
+
for tag in tags:
|
|
26
|
+
extra_deps[tag].add(dep)
|
|
27
|
+
|
|
28
|
+
# add tag `all` at the end
|
|
29
|
+
if add_all:
|
|
30
|
+
extra_deps['all'] = {
|
|
31
|
+
tag for tags in extra_deps.values() for tag in tags
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return extra_deps
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def remove_gh_dark_mode_only_tags(text, tag='#gh-dark-mode-only'):
|
|
38
|
+
"""Remove recursively all """
|
|
39
|
+
idx = text.find(tag)
|
|
40
|
+
if idx < 0:
|
|
41
|
+
return text
|
|
42
|
+
|
|
43
|
+
idx_tag_end = text.find('>', idx)
|
|
44
|
+
idx_tag_start = text.rfind('<', 0, idx)
|
|
45
|
+
return remove_gh_dark_mode_only_tags(
|
|
46
|
+
text[:idx_tag_start] + text[idx_tag_end + 1:], tag,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# The directory containing this file
|
|
51
|
+
HERE = pathlib.Path(__file__).parent
|
|
52
|
+
|
|
53
|
+
# The text of the README file
|
|
54
|
+
README = remove_gh_dark_mode_only_tags(
|
|
55
|
+
(HERE / 'README.md').read_text(),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# This call to setup() does all the work
|
|
59
|
+
setuptools.setup(
|
|
60
|
+
name='normi',
|
|
61
|
+
version='0.1.0',
|
|
62
|
+
description='Estimator for Normalized Mutual Information',
|
|
63
|
+
long_description=README,
|
|
64
|
+
long_description_content_type='text/markdown',
|
|
65
|
+
keywords=[
|
|
66
|
+
'normalized mutual information',
|
|
67
|
+
'mutual information',
|
|
68
|
+
'Kraskov Estimator',
|
|
69
|
+
'KSG Estimator',
|
|
70
|
+
],
|
|
71
|
+
author='braniii',
|
|
72
|
+
url='https://github.com/moldyn/NorMI',
|
|
73
|
+
license='MIT License',
|
|
74
|
+
classifiers=[
|
|
75
|
+
'License :: OSI Approved :: MIT License',
|
|
76
|
+
'Intended Audience :: Science/Research',
|
|
77
|
+
'Natural Language :: English',
|
|
78
|
+
'Programming Language :: Python :: 3',
|
|
79
|
+
'Programming Language :: Python :: 3.8',
|
|
80
|
+
'Programming Language :: Python :: 3.9',
|
|
81
|
+
'Programming Language :: Python :: 3.10',
|
|
82
|
+
'Programming Language :: Python :: 3.11',
|
|
83
|
+
'Topic :: Scientific/Engineering :: Bio-Informatics',
|
|
84
|
+
'Topic :: Scientific/Engineering :: Information Analysis',
|
|
85
|
+
'Topic :: Scientific/Engineering :: Physics',
|
|
86
|
+
'Topic :: Software Development :: Libraries :: Python Modules',
|
|
87
|
+
],
|
|
88
|
+
project_urls={
|
|
89
|
+
'Documentation': 'https://moldyn.github.io/NorMI',
|
|
90
|
+
'Source Code': 'https://github.com/moldyn/NorMI',
|
|
91
|
+
'Changelog': 'https://moldyn.github.io/NorMI/changelog',
|
|
92
|
+
'Bug Tracker': 'https://github.com/moldyn/NorMI/issues',
|
|
93
|
+
},
|
|
94
|
+
package_dir={'': 'src'},
|
|
95
|
+
packages=setuptools.find_packages(where='src'),
|
|
96
|
+
include_package_data=True,
|
|
97
|
+
python_requires='>=3.8',
|
|
98
|
+
entry_points={
|
|
99
|
+
'console_scripts': [
|
|
100
|
+
'normi = normi.__main__:main',
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
install_requires=[
|
|
104
|
+
'numpy>=1.21.0',
|
|
105
|
+
'scipy',
|
|
106
|
+
'click>=8.0.0',
|
|
107
|
+
'beartype>=0.10.4',
|
|
108
|
+
'tqdm',
|
|
109
|
+
'scikit-learn>=1.0.0',
|
|
110
|
+
'typing_extensions>=3.9.0;python_version<"3.9"',
|
|
111
|
+
],
|
|
112
|
+
extras_require=get_extra_requirements('extra-requirements.txt'),
|
|
113
|
+
)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""Normalized mutual information"""
|
|
3
|
+
__all__ = ['NormalizedMI']
|
|
4
|
+
|
|
5
|
+
NORMS = {'joint', 'geometric', 'arithmetic', 'min', 'max'}
|
|
6
|
+
INVMEASURES = {'radius', 'volume', 'kraskov'}
|
|
7
|
+
|
|
8
|
+
from ._estimators import NormalizedMI
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
__version__ = '0.1.0'
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""CLI of normalized-mi.
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
Copyright (c) 2023, Daniel Nagel
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
import click
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from normi import INVMEASURES, NORMS, NormalizedMI, __version__
|
|
12
|
+
from normi._utils import savetxt
|
|
13
|
+
|
|
14
|
+
# setup matplotlibs rcParam
|
|
15
|
+
|
|
16
|
+
PRECISION = ['half', 'single', 'double']
|
|
17
|
+
PRECISION_TO_DTYPE = {
|
|
18
|
+
'half': np.float16,
|
|
19
|
+
'single': np.float32,
|
|
20
|
+
'double': np.float64,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
HELP_STR = f"""Normalized MI v{__version__}
|
|
24
|
+
|
|
25
|
+
\b
|
|
26
|
+
Estimating the normalized mutual information based on k-nn statistics.
|
|
27
|
+
Copyright (c) 2023, Daniel Nagel
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@click.command(
|
|
32
|
+
help='Estimating NMI matrix of coordinates.',
|
|
33
|
+
no_args_is_help=True,
|
|
34
|
+
)
|
|
35
|
+
@click.option(
|
|
36
|
+
'-i',
|
|
37
|
+
'--input',
|
|
38
|
+
'input_file',
|
|
39
|
+
required=True,
|
|
40
|
+
type=click.Path(exists=True),
|
|
41
|
+
help=(
|
|
42
|
+
'Path to input file. Needs to be of shape (n_samples, n_features).'
|
|
43
|
+
' All command lines need to start with "#". By default np.float16'
|
|
44
|
+
' is used for the datatype.'
|
|
45
|
+
),
|
|
46
|
+
)
|
|
47
|
+
@click.option(
|
|
48
|
+
'-o',
|
|
49
|
+
'--output',
|
|
50
|
+
'output_basename',
|
|
51
|
+
required=True,
|
|
52
|
+
type=click.Path(),
|
|
53
|
+
help=(
|
|
54
|
+
'Path to output basename. Will be a matrix of shape (n_features, '
|
|
55
|
+
'n_features).'
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
@click.option(
|
|
59
|
+
'--norm',
|
|
60
|
+
default='joint',
|
|
61
|
+
show_default=True,
|
|
62
|
+
type=click.Choice(NORMS, case_sensitive=False),
|
|
63
|
+
help='Normalization method of the mutual information.',
|
|
64
|
+
)
|
|
65
|
+
@click.option(
|
|
66
|
+
'--inv-measure',
|
|
67
|
+
default='radius',
|
|
68
|
+
show_default=True,
|
|
69
|
+
type=click.Choice(INVMEASURES, case_sensitive=False),
|
|
70
|
+
help='Invariant measure to rescale the entropies.',
|
|
71
|
+
)
|
|
72
|
+
@click.option(
|
|
73
|
+
'--n-dims',
|
|
74
|
+
default=1,
|
|
75
|
+
show_default=True,
|
|
76
|
+
type=click.IntRange(min=1),
|
|
77
|
+
help=(
|
|
78
|
+
'Dimension of each feature. Assumes the first nth colums belong to the'
|
|
79
|
+
' first feature.'
|
|
80
|
+
),
|
|
81
|
+
)
|
|
82
|
+
@click.option(
|
|
83
|
+
'--precision',
|
|
84
|
+
default='single',
|
|
85
|
+
show_default=True,
|
|
86
|
+
type=click.Choice(PRECISION, case_sensitive=True),
|
|
87
|
+
help=(
|
|
88
|
+
'Precision used for calculation. Lower precision reduces memory '
|
|
89
|
+
'impact but may lead to overflow errors.'
|
|
90
|
+
),
|
|
91
|
+
)
|
|
92
|
+
@click.option(
|
|
93
|
+
'-v',
|
|
94
|
+
'--verbose',
|
|
95
|
+
is_flag=True,
|
|
96
|
+
help='Activate verbose mode.',
|
|
97
|
+
)
|
|
98
|
+
def main(
|
|
99
|
+
input_file, output_basename, norm, inv_measure, n_dims, precision, verbose,
|
|
100
|
+
):
|
|
101
|
+
# load file
|
|
102
|
+
if verbose:
|
|
103
|
+
click.echo(f'\nNormalized MI\n~~~ Load file: {input_file}')
|
|
104
|
+
features = np.loadtxt(input_file, dtype=PRECISION_TO_DTYPE[precision])
|
|
105
|
+
|
|
106
|
+
if verbose:
|
|
107
|
+
click.echo('~~~ Initialize class')
|
|
108
|
+
nmi = NormalizedMI(
|
|
109
|
+
normalize_method=norm,
|
|
110
|
+
invariant_measure=inv_measure,
|
|
111
|
+
verbose=verbose,
|
|
112
|
+
n_dims=n_dims,
|
|
113
|
+
)
|
|
114
|
+
if verbose:
|
|
115
|
+
click.echo('~~~ Fit class')
|
|
116
|
+
nmi.fit(features)
|
|
117
|
+
|
|
118
|
+
# save results
|
|
119
|
+
if verbose:
|
|
120
|
+
click.echo(f'~~~ Save files: {output_basename}.nmi/.mi/.hxy/.hx/.hy')
|
|
121
|
+
kwargs = {'fmt': '%.5f'}
|
|
122
|
+
savetxt(f'{output_basename}.nmi', nmi.nmi_, **kwargs)
|
|
123
|
+
savetxt(f'{output_basename}.mi', nmi.mi_, **kwargs)
|
|
124
|
+
savetxt(f'{output_basename}.hx', nmi.hx_, **kwargs)
|
|
125
|
+
savetxt(f'{output_basename}.hy', nmi.hy_, **kwargs)
|
|
126
|
+
savetxt(f'{output_basename}.hxy', nmi.hxy_, **kwargs)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
if __name__ == '__main__':
|
|
130
|
+
main()
|