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 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.
@@ -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()