tmapper-py 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.
- tmapper_py-0.1.0/LICENSE +28 -0
- tmapper_py-0.1.0/PKG-INFO +108 -0
- tmapper_py-0.1.0/README.md +66 -0
- tmapper_py-0.1.0/pyproject.toml +72 -0
- tmapper_py-0.1.0/setup.cfg +4 -0
- tmapper_py-0.1.0/src/tmapper/__init__.py +63 -0
- tmapper_py-0.1.0/src/tmapper/_shortest_path.py +22 -0
- tmapper_py-0.1.0/src/tmapper/app/__init__.py +10 -0
- tmapper_py-0.1.0/src/tmapper/app/launcher.py +35 -0
- tmapper_py-0.1.0/src/tmapper/app/streamlit_app.py +1240 -0
- tmapper_py-0.1.0/src/tmapper/cknngraph.py +73 -0
- tmapper_py-0.1.0/src/tmapper/cycle_cluster.py +111 -0
- tmapper_py-0.1.0/src/tmapper/cycle_cluster_conn.py +112 -0
- tmapper_py-0.1.0/src/tmapper/cycle_count.py +150 -0
- tmapper_py-0.1.0/src/tmapper/cycle_count2p.py +72 -0
- tmapper_py-0.1.0/src/tmapper/cycle_cutter.py +47 -0
- tmapper_py-0.1.0/src/tmapper/cycle_overlap.py +71 -0
- tmapper_py-0.1.0/src/tmapper/cycle_path_decomp.py +104 -0
- tmapper_py-0.1.0/src/tmapper/cycles_to_paths.py +40 -0
- tmapper_py-0.1.0/src/tmapper/filtergraph.py +107 -0
- tmapper_py-0.1.0/src/tmapper/graph_utils.py +283 -0
- tmapper_py-0.1.0/src/tmapper/knngraph.py +61 -0
- tmapper_py-0.1.0/src/tmapper/labeling.py +45 -0
- tmapper_py-0.1.0/src/tmapper/modularity.py +74 -0
- tmapper_py-0.1.0/src/tmapper/path_traffic.py +35 -0
- tmapper_py-0.1.0/src/tmapper/plotting.py +463 -0
- tmapper_py-0.1.0/src/tmapper/sample_data.py +19 -0
- tmapper_py-0.1.0/src/tmapper/sampledata/EL_temp.csv +57710 -0
- tmapper_py-0.1.0/src/tmapper/tcm_distance.py +63 -0
- tmapper_py-0.1.0/src/tmapper/tknndigraph.py +190 -0
- tmapper_py-0.1.0/src/tmapper_py.egg-info/PKG-INFO +108 -0
- tmapper_py-0.1.0/src/tmapper_py.egg-info/SOURCES.txt +44 -0
- tmapper_py-0.1.0/src/tmapper_py.egg-info/dependency_links.txt +1 -0
- tmapper_py-0.1.0/src/tmapper_py.egg-info/entry_points.txt +2 -0
- tmapper_py-0.1.0/src/tmapper_py.egg-info/requires.txt +23 -0
- tmapper_py-0.1.0/src/tmapper_py.egg-info/top_level.txt +1 -0
- tmapper_py-0.1.0/tests/test_app.py +940 -0
- tmapper_py-0.1.0/tests/test_core_pipeline.py +224 -0
- tmapper_py-0.1.0/tests/test_cycle_cluster.py +45 -0
- tmapper_py-0.1.0/tests/test_cycle_count.py +54 -0
- tmapper_py-0.1.0/tests/test_cycle_path_decomp.py +87 -0
- tmapper_py-0.1.0/tests/test_graph_utils.py +181 -0
- tmapper_py-0.1.0/tests/test_knngraph.py +68 -0
- tmapper_py-0.1.0/tests/test_modularity.py +61 -0
- tmapper_py-0.1.0/tests/test_path_traffic.py +21 -0
- tmapper_py-0.1.0/tests/test_visualization.py +187 -0
tmapper_py-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Multiscale Complex Systems Lab
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tmapper-py
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python port of Temporal Mapper 2 -- build attractor transition networks from time-series data
|
|
5
|
+
Author: Mengsen Zhang
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/Multiscale-Complex-Systems-Lab/tmapper-py
|
|
8
|
+
Project-URL: MATLAB original, https://github.com/Multiscale-Complex-Systems-Lab/tmapper2
|
|
9
|
+
Keywords: temporal mapper,topological data analysis,mapper,dynamical systems,time series,attractor,recurrence
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: numpy>=1.24
|
|
23
|
+
Requires-Dist: scipy>=1.10
|
|
24
|
+
Requires-Dist: networkx>=3.0
|
|
25
|
+
Provides-Extra: plot
|
|
26
|
+
Requires-Dist: matplotlib>=3.7; extra == "plot"
|
|
27
|
+
Requires-Dist: python-igraph>=1.0; extra == "plot"
|
|
28
|
+
Requires-Dist: pyvis>=0.3; extra == "plot"
|
|
29
|
+
Provides-Extra: app
|
|
30
|
+
Requires-Dist: streamlit>=1.30; extra == "app"
|
|
31
|
+
Requires-Dist: pandas>=1.5; extra == "app"
|
|
32
|
+
Requires-Dist: matplotlib>=3.7; extra == "app"
|
|
33
|
+
Requires-Dist: python-igraph>=1.0; extra == "app"
|
|
34
|
+
Requires-Dist: pyvis>=0.3; extra == "app"
|
|
35
|
+
Provides-Extra: test
|
|
36
|
+
Requires-Dist: pytest>=7.0; extra == "test"
|
|
37
|
+
Requires-Dist: pandas>=1.5; extra == "test"
|
|
38
|
+
Provides-Extra: docs
|
|
39
|
+
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
|
|
40
|
+
Requires-Dist: mkdocstrings[python]>=0.25; extra == "docs"
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
|
|
43
|
+
# tmapper (Python)
|
|
44
|
+
|
|
45
|
+
A Python port of [Temporal Mapper 2](https://github.com/Multiscale-Complex-Systems-Lab/tmapper2), a toolbox for building **attractor transition networks** from time-series data.
|
|
46
|
+
|
|
47
|
+
**Status: feature-complete port.** Both the core two-step pipeline (`tknndigraph` + `filtergraph` + plotting) and the secondary cycle/path analysis toolkit (cycle counting/clustering, path decomposition, traffic, modularity) are ported and tested. `tknngraph.m` (a legacy, unused MATLAB function) was intentionally not ported.
|
|
48
|
+
|
|
49
|
+
For the full background, citation, and the original MATLAB implementation, see [tmapper2](https://github.com/Multiscale-Complex-Systems-Lab/tmapper2).
|
|
50
|
+
|
|
51
|
+
**Documentation, quickstart, and full API reference:** https://multiscale-complex-systems-lab.github.io/tmapper-py/
|
|
52
|
+
|
|
53
|
+
## What's included
|
|
54
|
+
|
|
55
|
+
- **Core pipeline**: `tknndigraph`, `filtergraph`, `find_node_label`, `tcm_distance`, `plot_tmgraph`, `plot_tmgraph_tcm`, `plot_tmgraph_interactive` (draggable/zoomable/hoverable HTML via pyvis, no MATLAB equivalent)
|
|
56
|
+
- **Standalone graph builders**: `knngraph`, `cknngraph`
|
|
57
|
+
- **Graph/data utilities**: `node_size`, `node_measure`, `normalize_geodesic`, `normalize_tcm`, `members_to_tidx`, `subgraph_from_members`, `sym_dyn_to_digraph`, `digraph_to_graph`, `find_blocks`
|
|
58
|
+
- **Cycle/path analysis toolkit**: `cycle_count` (Giscard/Kriege/Wilson combinatorial-sieve counter, third-party algorithm carrying its own BSD license -- see `cycle_count.py`), `cycle_count2p`, `reorg_cycles`, `cycle_path_overlap`, `cycle_cluster`, `cycle_cluster_conn`, `cycle_cutter`, `cycles_to_paths`, `cycle_path_decomp`, `path_traffic`, `qasym`, `cal_mod`
|
|
59
|
+
- **Interactive app**: `tmapper-app`, a browser front end for the whole pipeline -- see below
|
|
60
|
+
|
|
61
|
+
All ported functions were cross-checked node-for-node and edge-for-edge against real MATLAB output on deterministic test graphs (see the test suite for the same hand-derived oracle values used in the MATLAB toolbox's own `tests/`).
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install tmapper-py # library
|
|
67
|
+
pip install "tmapper-py[app]" # library + the interactive app
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
(The distribution is `tmapper-py` -- `tmapper` alone isn't available on PyPI,
|
|
71
|
+
see [Installation](https://multiscale-complex-systems-lab.github.io/tmapper-py/installation/).
|
|
72
|
+
Everything imports as `import tmapper` either way.)
|
|
73
|
+
|
|
74
|
+
For development, from a clone:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git clone https://github.com/Multiscale-Complex-Systems-Lab/tmapper-py.git
|
|
78
|
+
cd tmapper-py
|
|
79
|
+
pip install -e ".[app,test]"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Interactive app
|
|
83
|
+
|
|
84
|
+
Prefer point-and-click? `tmapper-app` runs the same pipeline in your browser -- load data, pick variables, turn the parameters, and explore the network without writing any code:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install "tmapper-py[app]"
|
|
88
|
+
tmapper-app
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
It handles missing data and downsampling for you (dropping incomplete rows before an anti-aliasing lowpass), exports both figures and analysis-ready data (interactive HTML, PNGs, a per-timepoint `timeline.csv`, GraphML, and a provenance JSON), and shows a runnable script reproducing the current build.
|
|
92
|
+
|
|
93
|
+
See the [Interactive App guide](https://multiscale-complex-systems-lab.github.io/tmapper-py/app/) for a full walkthrough.
|
|
94
|
+
|
|
95
|
+
## Running tests
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pytest
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Notes for users porting workflows from MATLAB
|
|
102
|
+
|
|
103
|
+
- Node labels are 0-indexed (Pythonic), unlike the MATLAB original's 1-indexed convention.
|
|
104
|
+
- If you z-score your data before calling `tknndigraph` (as `tmapper_demo.m` does), note that MATLAB's `zscore` divides by the sample standard deviation (`N-1`), while `scipy.stats.zscore` defaults to the population standard deviation (`N`). Pass `ddof=1` to `scipy.stats.zscore` to match MATLAB's convention -- otherwise results can subtly diverge near k-NN/threshold boundaries. (Verified: with `ddof=1`, the Python and MATLAB pipelines produce identical output down to floating-point precision on the sample dataset.)
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
BSD 3-Clause License -- see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# tmapper (Python)
|
|
2
|
+
|
|
3
|
+
A Python port of [Temporal Mapper 2](https://github.com/Multiscale-Complex-Systems-Lab/tmapper2), a toolbox for building **attractor transition networks** from time-series data.
|
|
4
|
+
|
|
5
|
+
**Status: feature-complete port.** Both the core two-step pipeline (`tknndigraph` + `filtergraph` + plotting) and the secondary cycle/path analysis toolkit (cycle counting/clustering, path decomposition, traffic, modularity) are ported and tested. `tknngraph.m` (a legacy, unused MATLAB function) was intentionally not ported.
|
|
6
|
+
|
|
7
|
+
For the full background, citation, and the original MATLAB implementation, see [tmapper2](https://github.com/Multiscale-Complex-Systems-Lab/tmapper2).
|
|
8
|
+
|
|
9
|
+
**Documentation, quickstart, and full API reference:** https://multiscale-complex-systems-lab.github.io/tmapper-py/
|
|
10
|
+
|
|
11
|
+
## What's included
|
|
12
|
+
|
|
13
|
+
- **Core pipeline**: `tknndigraph`, `filtergraph`, `find_node_label`, `tcm_distance`, `plot_tmgraph`, `plot_tmgraph_tcm`, `plot_tmgraph_interactive` (draggable/zoomable/hoverable HTML via pyvis, no MATLAB equivalent)
|
|
14
|
+
- **Standalone graph builders**: `knngraph`, `cknngraph`
|
|
15
|
+
- **Graph/data utilities**: `node_size`, `node_measure`, `normalize_geodesic`, `normalize_tcm`, `members_to_tidx`, `subgraph_from_members`, `sym_dyn_to_digraph`, `digraph_to_graph`, `find_blocks`
|
|
16
|
+
- **Cycle/path analysis toolkit**: `cycle_count` (Giscard/Kriege/Wilson combinatorial-sieve counter, third-party algorithm carrying its own BSD license -- see `cycle_count.py`), `cycle_count2p`, `reorg_cycles`, `cycle_path_overlap`, `cycle_cluster`, `cycle_cluster_conn`, `cycle_cutter`, `cycles_to_paths`, `cycle_path_decomp`, `path_traffic`, `qasym`, `cal_mod`
|
|
17
|
+
- **Interactive app**: `tmapper-app`, a browser front end for the whole pipeline -- see below
|
|
18
|
+
|
|
19
|
+
All ported functions were cross-checked node-for-node and edge-for-edge against real MATLAB output on deterministic test graphs (see the test suite for the same hand-derived oracle values used in the MATLAB toolbox's own `tests/`).
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install tmapper-py # library
|
|
25
|
+
pip install "tmapper-py[app]" # library + the interactive app
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
(The distribution is `tmapper-py` -- `tmapper` alone isn't available on PyPI,
|
|
29
|
+
see [Installation](https://multiscale-complex-systems-lab.github.io/tmapper-py/installation/).
|
|
30
|
+
Everything imports as `import tmapper` either way.)
|
|
31
|
+
|
|
32
|
+
For development, from a clone:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/Multiscale-Complex-Systems-Lab/tmapper-py.git
|
|
36
|
+
cd tmapper-py
|
|
37
|
+
pip install -e ".[app,test]"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Interactive app
|
|
41
|
+
|
|
42
|
+
Prefer point-and-click? `tmapper-app` runs the same pipeline in your browser -- load data, pick variables, turn the parameters, and explore the network without writing any code:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install "tmapper-py[app]"
|
|
46
|
+
tmapper-app
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
It handles missing data and downsampling for you (dropping incomplete rows before an anti-aliasing lowpass), exports both figures and analysis-ready data (interactive HTML, PNGs, a per-timepoint `timeline.csv`, GraphML, and a provenance JSON), and shows a runnable script reproducing the current build.
|
|
50
|
+
|
|
51
|
+
See the [Interactive App guide](https://multiscale-complex-systems-lab.github.io/tmapper-py/app/) for a full walkthrough.
|
|
52
|
+
|
|
53
|
+
## Running tests
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pytest
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Notes for users porting workflows from MATLAB
|
|
60
|
+
|
|
61
|
+
- Node labels are 0-indexed (Pythonic), unlike the MATLAB original's 1-indexed convention.
|
|
62
|
+
- If you z-score your data before calling `tknndigraph` (as `tmapper_demo.m` does), note that MATLAB's `zscore` divides by the sample standard deviation (`N-1`), while `scipy.stats.zscore` defaults to the population standard deviation (`N`). Pass `ddof=1` to `scipy.stats.zscore` to match MATLAB's convention -- otherwise results can subtly diverge near k-NN/threshold boundaries. (Verified: with `ddof=1`, the Python and MATLAB pipelines produce identical output down to floating-point precision on the sample dataset.)
|
|
63
|
+
|
|
64
|
+
## License
|
|
65
|
+
|
|
66
|
+
BSD 3-Clause License -- see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
# Distribution name on PyPI, not the importable module (that's still
|
|
7
|
+
# `tmapper`, see [tool.setuptools.packages.find] below). Plain "tmapper" is
|
|
8
|
+
# blocked there by PyPI's anti-typosquatting check: it's a 1-character edit
|
|
9
|
+
# from the existing "mapper" package (a similarly-themed topological data
|
|
10
|
+
# analysis tool), which is exactly the pattern that check exists to catch.
|
|
11
|
+
name = "tmapper-py"
|
|
12
|
+
version = "0.1.0"
|
|
13
|
+
description = "Python port of Temporal Mapper 2 -- build attractor transition networks from time-series data"
|
|
14
|
+
readme = "README.md"
|
|
15
|
+
requires-python = ">=3.10"
|
|
16
|
+
# SPDX string + license-files: the `{ file = ... }` table form is
|
|
17
|
+
# deprecated and stops working on setuptools >= 77.
|
|
18
|
+
license = "BSD-3-Clause"
|
|
19
|
+
license-files = ["LICENSE"]
|
|
20
|
+
authors = [{ name = "Mengsen Zhang" }]
|
|
21
|
+
keywords = [
|
|
22
|
+
"temporal mapper", "topological data analysis", "mapper",
|
|
23
|
+
"dynamical systems", "time series", "attractor", "recurrence",
|
|
24
|
+
]
|
|
25
|
+
classifiers = [
|
|
26
|
+
"Development Status :: 4 - Beta",
|
|
27
|
+
"Intended Audience :: Science/Research",
|
|
28
|
+
"Operating System :: OS Independent",
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Programming Language :: Python :: 3.10",
|
|
31
|
+
"Programming Language :: Python :: 3.11",
|
|
32
|
+
"Programming Language :: Python :: 3.12",
|
|
33
|
+
"Topic :: Scientific/Engineering :: Information Analysis",
|
|
34
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
35
|
+
]
|
|
36
|
+
dependencies = [
|
|
37
|
+
"numpy>=1.24",
|
|
38
|
+
"scipy>=1.10",
|
|
39
|
+
"networkx>=3.0",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.optional-dependencies]
|
|
43
|
+
plot = ["matplotlib>=3.7", "python-igraph>=1.0", "pyvis>=0.3"]
|
|
44
|
+
# pandas is declared explicitly rather than leaned on as a streamlit
|
|
45
|
+
# transitive dependency: the app imports it directly, so it is a real
|
|
46
|
+
# requirement of ours. The core library stays pandas-free.
|
|
47
|
+
app = [
|
|
48
|
+
"streamlit>=1.30",
|
|
49
|
+
"pandas>=1.5",
|
|
50
|
+
"matplotlib>=3.7",
|
|
51
|
+
"python-igraph>=1.0",
|
|
52
|
+
"pyvis>=0.3",
|
|
53
|
+
]
|
|
54
|
+
# the app tests drive the app, so they need its dependencies too
|
|
55
|
+
test = ["pytest>=7.0", "pandas>=1.5"]
|
|
56
|
+
docs = ["mkdocs-material>=9.5", "mkdocstrings[python]>=0.25"]
|
|
57
|
+
|
|
58
|
+
[project.scripts]
|
|
59
|
+
# `pip install "tmapper-py[app]"` then just `tmapper-app`
|
|
60
|
+
tmapper-app = "tmapper.app.launcher:main"
|
|
61
|
+
|
|
62
|
+
[project.urls]
|
|
63
|
+
Homepage = "https://github.com/Multiscale-Complex-Systems-Lab/tmapper-py"
|
|
64
|
+
"MATLAB original" = "https://github.com/Multiscale-Complex-Systems-Lab/tmapper2"
|
|
65
|
+
|
|
66
|
+
[tool.setuptools.packages.find]
|
|
67
|
+
where = ["src"]
|
|
68
|
+
|
|
69
|
+
[tool.setuptools.package-data]
|
|
70
|
+
# the bundled sample dataset, so the app's "Try sample data" button and the
|
|
71
|
+
# Quickstart work from a pip install and not only from a clone
|
|
72
|
+
tmapper = ["sampledata/*.csv"]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from .sample_data import sample_data_path
|
|
2
|
+
from .tknndigraph import tknndigraph
|
|
3
|
+
from .filtergraph import filtergraph
|
|
4
|
+
from .labeling import find_node_label
|
|
5
|
+
from .tcm_distance import tcm_distance
|
|
6
|
+
from .plotting import plot_tmgraph, plot_tmgraph_tcm, plot_tmgraph_interactive
|
|
7
|
+
from .knngraph import knngraph
|
|
8
|
+
from .cknngraph import cknngraph
|
|
9
|
+
from .cycle_count import cycle_count
|
|
10
|
+
from .cycle_count2p import cycle_count2p, reorg_cycles
|
|
11
|
+
from .cycle_overlap import cycle_path_overlap
|
|
12
|
+
from .cycle_cluster import cycle_cluster
|
|
13
|
+
from .cycle_cluster_conn import cycle_cluster_conn
|
|
14
|
+
from .cycle_cutter import cycle_cutter
|
|
15
|
+
from .cycles_to_paths import cycles_to_paths
|
|
16
|
+
from .cycle_path_decomp import cycle_path_decomp
|
|
17
|
+
from .path_traffic import path_traffic
|
|
18
|
+
from .modularity import qasym, cal_mod
|
|
19
|
+
from .graph_utils import (
|
|
20
|
+
node_size,
|
|
21
|
+
node_measure,
|
|
22
|
+
normalize_geodesic,
|
|
23
|
+
normalize_tcm,
|
|
24
|
+
members_to_tidx,
|
|
25
|
+
subgraph_from_members,
|
|
26
|
+
sym_dyn_to_digraph,
|
|
27
|
+
digraph_to_graph,
|
|
28
|
+
find_blocks,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"sample_data_path",
|
|
33
|
+
"tknndigraph",
|
|
34
|
+
"filtergraph",
|
|
35
|
+
"find_node_label",
|
|
36
|
+
"tcm_distance",
|
|
37
|
+
"plot_tmgraph",
|
|
38
|
+
"plot_tmgraph_tcm",
|
|
39
|
+
"plot_tmgraph_interactive",
|
|
40
|
+
"knngraph",
|
|
41
|
+
"cknngraph",
|
|
42
|
+
"cycle_count",
|
|
43
|
+
"cycle_count2p",
|
|
44
|
+
"reorg_cycles",
|
|
45
|
+
"cycle_path_overlap",
|
|
46
|
+
"cycle_cluster",
|
|
47
|
+
"cycle_cluster_conn",
|
|
48
|
+
"cycle_cutter",
|
|
49
|
+
"cycles_to_paths",
|
|
50
|
+
"cycle_path_decomp",
|
|
51
|
+
"path_traffic",
|
|
52
|
+
"qasym",
|
|
53
|
+
"cal_mod",
|
|
54
|
+
"node_size",
|
|
55
|
+
"node_measure",
|
|
56
|
+
"normalize_geodesic",
|
|
57
|
+
"normalize_tcm",
|
|
58
|
+
"members_to_tidx",
|
|
59
|
+
"subgraph_from_members",
|
|
60
|
+
"sym_dyn_to_digraph",
|
|
61
|
+
"digraph_to_graph",
|
|
62
|
+
"find_blocks",
|
|
63
|
+
]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Shared all-pairs shortest-path helper.
|
|
2
|
+
|
|
3
|
+
Uses scipy's compiled Dijkstra (via ``scipy.sparse.csgraph.shortest_path``)
|
|
4
|
+
instead of networkx's ``floyd_warshall_numpy``. The latter is O(n^3) with
|
|
5
|
+
substantial per-iteration numpy overhead and becomes the dominant cost at
|
|
6
|
+
realistic graph sizes (a few thousand nodes); our graphs are sparse (a
|
|
7
|
+
handful of edges per node from the k-NN construction), where Dijkstra from
|
|
8
|
+
every source is asymptotically and practically much faster.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import networkx as nx
|
|
12
|
+
from scipy.sparse.csgraph import shortest_path
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def all_pairs_distance(g, nodelist, weight="weight"):
|
|
16
|
+
"""All-pairs shortest-path distance matrix for ``g``, ordered by
|
|
17
|
+
``nodelist``. ``weight=None`` treats every edge as weight 1 (hop
|
|
18
|
+
count); ``weight="weight"`` (default) uses ``g``'s edge weights.
|
|
19
|
+
Unreachable pairs are ``inf``, matching ``nx.floyd_warshall_numpy``.
|
|
20
|
+
"""
|
|
21
|
+
adj = nx.to_scipy_sparse_array(g, nodelist=nodelist, weight=weight, dtype=float)
|
|
22
|
+
return shortest_path(adj, method="auto", directed=True)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""The interactive Streamlit app, and its launcher.
|
|
2
|
+
|
|
3
|
+
Lives inside the package so that ``pip install "tmapper[app]"`` ships it --
|
|
4
|
+
otherwise the app would only be runnable from a clone of the repository,
|
|
5
|
+
which is exactly the friction it exists to remove.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .launcher import main
|
|
9
|
+
|
|
10
|
+
__all__ = ["main"]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Console-script entry point: ``tmapper-app``.
|
|
2
|
+
|
|
3
|
+
A Streamlit app is a *script Streamlit runs*, not a program you import and
|
|
4
|
+
call, so this hands the app file to Streamlit's own CLI rather than
|
|
5
|
+
executing it directly -- running it as a plain script would just print
|
|
6
|
+
Streamlit's "missing ScriptRunContext" warnings and do nothing useful.
|
|
7
|
+
|
|
8
|
+
Any extra arguments are passed straight through, so the usual Streamlit
|
|
9
|
+
options still work::
|
|
10
|
+
|
|
11
|
+
tmapper-app --server.port 8600 --server.address 0.0.0.0
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import sys
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
APP_FILE = Path(__file__).resolve().parent / "streamlit_app.py"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def main(argv=None):
|
|
21
|
+
try:
|
|
22
|
+
from streamlit.web import cli as stcli
|
|
23
|
+
except ImportError: # pragma: no cover - depends on install extras
|
|
24
|
+
raise SystemExit(
|
|
25
|
+
"The interactive app needs Streamlit, which is not installed.\n"
|
|
26
|
+
"Install it with: pip install 'tmapper[app]'"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
args = sys.argv[1:] if argv is None else list(argv)
|
|
30
|
+
sys.argv = ["streamlit", "run", str(APP_FILE), *args]
|
|
31
|
+
return stcli.main()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if __name__ == "__main__": # pragma: no cover
|
|
35
|
+
sys.exit(main())
|