Skip to content

Commit 7a295f4

Browse files
authored
Merge pull request #129 from lucasimi/develop
Develop
2 parents c7af7f9 + 62d1892 commit 7a295f4

32 files changed

+1236
-549
lines changed

.github/workflows/bench.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: bench
2+
3+
on:
4+
push:
5+
branches:
6+
- develop
7+
- main
8+
9+
jobs:
10+
test-job:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Check out repository code
14+
uses: actions/checkout@v2
15+
- name: Install Python
16+
uses: actions/setup-python@v4
17+
with:
18+
python-version: '3.10'
19+
- name: Install dependencies
20+
run: |
21+
python -m pip install -e .[dev]
22+
- name: Run benchmarks
23+
run: |
24+
python -m unittest discover -s tests -p 'test_bench_*.py'

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
python -m pip install -e .[dev]
2222
- name: Run tests and code coverage
2323
run: |
24-
coverage run --source=src -m unittest discover -s tests
24+
coverage run --source=src -m unittest discover -s tests -p 'test_unit_*.py'
2525
coverage report -m
2626
- name: Upload coverage reports to Codecov
2727
uses: codecov/codecov-action@v3

.gitignore

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
**/__pycache__
22
**/*.pyc
3+
**/*.pyo
34
**/*.csv
45
**/*.egg-info
56
**/.ipynb_checkpoints
67
**/*.log
78
**/docs/build
89
**/*.ipynb
910

11+
**/*.c
12+
**/*.cpp
13+
**/*.so
14+
**/*.pyd
15+
**/*.dll
16+
**/*.dylib
17+
1018
.coverage
1119
.vscode
1220
.idea
13-
dist
21+
dist/
22+
build/

app/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ streamlit==1.34.0
22
numpy>=1.25.2
33
scikit-learn>=1.5.0
44
pandas>=2.1.0
5-
tda-mapper==0.6.0
5+
tda-mapper==0.7.0

app/streamlit_app.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from tdamapper.cover import CubicalCover, BallCover, TrivialCover
2020
from tdamapper.clustering import TrivialClustering, FailSafeClustering
2121
from tdamapper.plot import MapperLayoutInteractive
22+
from tdamapper.utils.metrics import minkowski
2223

2324

2425
MAX_NODES = 1000
@@ -182,7 +183,7 @@ def set_mapper_fig(self, dim, seed, color_feat, agg, cmap, title):
182183

183184

184185
def lp_metric(p):
185-
return lambda x, y: np.linalg.norm(x - y, ord=p)
186+
return minkowski(p)
186187

187188

188189
def fix_data(data):
@@ -634,11 +635,11 @@ def mapper_draw_section(color_feat):
634635
seed = _mapper_seed()
635636
cmap = _mapper_cmap()
636637
agg, agg_name = _mapper_aggregation()
637-
mapper_plot = st.session_state[S_RESULTS].mapper_plot
638+
mapper_graph = st.session_state[S_RESULTS].mapper_graph
638639
update_button = st.button(
639640
'🖌️ Draw',
640641
use_container_width=True,
641-
disabled=mapper_plot is None)
642+
disabled=mapper_graph is None)
642643
mapper_fig_outdated = st.session_state[S_RESULTS].mapper_fig_outdated
643644
auto_rendering = st.session_state[S_RESULTS].auto_rendering
644645
title = f'{agg_name} of {color_feat}'

docs/source/tdamapper.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ tdamapper.clustering
3333
:undoc-members:
3434
:show-inheritance:
3535

36+
tdamapper.utils.metrics
37+
-----------------------
38+
39+
.. automodule:: tdamapper.utils.metrics
40+
:members:
41+
:undoc-members:
42+
:show-inheritance:
43+
44+
tdamapper.utils.vptree
45+
-----------------------
46+
47+
.. automodule:: tdamapper.utils.vptree
48+
:members:
49+
:undoc-members:
50+
:show-inheritance:
51+
3652
tdamapper.plot
3753
--------------
3854

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
[build-system]
2-
requires = ["setuptools>=42", "wheel"]
2+
requires = ["setuptools>=42", "wheel", "Cython"]
33
build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "tda-mapper"
7-
version = "0.6.0"
7+
version = "0.7.0"
88
description = "A simple and efficient Python implementation of Mapper algorithm for Topological Data Analysis"
99
readme = "README.md"
1010
authors = [{ name = "Luca Simi", email = "lucasimi90@gmail.com" }]

setup.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from setuptools import setup
2+
from setuptools.extension import Extension
3+
from Cython.Build import cythonize
4+
5+
6+
setup(
7+
ext_modules=cythonize([
8+
Extension(
9+
"tdamapper.utils._metrics",
10+
["src/tdamapper/utils/_metrics.pyx"])
11+
]))

src/tdamapper/cover.py

Lines changed: 118 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,50 @@ class BallCover(ProximityCover):
7575
Cover algorithm based on `ball proximity function` implemented as
7676
:class:`tdamapper.proximity.BallProximity`.
7777
78-
:param radius: The radius of the open balls, must be positive.
78+
:param radius: The radius of the open balls. Must be a positive value.
7979
:type radius: float
80-
:param metric: The (pseudo-)metric function that defines the distance
81-
between points, must be symmetric, positive, and satisfy the
82-
triangle-inequality, i.e.
83-
:math:`metric(x, z) \leq metric(x, y) + metric(y, z)` for every x, y, z
84-
in the dataset.
85-
:type metric: Callable
86-
:param flat: A flag that indicates whether to use a flat or a hierarchical
87-
vantage point tree, defaults to False.
88-
:type flat: bool, optional
80+
:param metric: The metric used to define the distance between points.
81+
Accepts any value compatible with `tdamapper.utils.metrics.get_metric`.
82+
Defaults to 'euclidean'.
83+
:type metric: str or callable
84+
:param metric_params: Additional parameters for the metric function, to be
85+
passed to `tdamapper.utils.metrics.get_metric`. Defaults to None.
86+
:type metric_params: dict, optional
87+
:param kind: Specifies whether to use a flat or a hierarchical vantage
88+
point tree. Acceptable values are 'flat' or 'hierarchical'. Defaults
89+
to 'flat'.
90+
:type kind: str
91+
:param leaf_capacity: The maximum number of points in a leaf node of the
92+
vantage point tree. Must be a positive value. Defaults to 1.
93+
:type leaf_capacity: int
94+
:param leaf_radius: The radius of the leaf nodes. If not specified, it
95+
defaults to the value of `radius`. Must be a positive value. Defaults
96+
to None.
97+
:type leaf_radius: float, optional
98+
:param pivoting: The method used for pivoting in the vantage point tree.
99+
Acceptable values are None, 'random', or 'furthest'. Defaults to None.
100+
:type pivoting: str or callable, optional
89101
"""
90102

91-
def __init__(self, radius, metric, flat=True):
92-
prox = BallProximity(radius=radius, metric=metric, flat=flat)
103+
def __init__(
104+
self,
105+
radius,
106+
metric='euclidean',
107+
metric_params=None,
108+
kind='flat',
109+
leaf_capacity=1,
110+
leaf_radius=None,
111+
pivoting=None,
112+
):
113+
prox = BallProximity(
114+
radius=radius,
115+
metric=metric,
116+
metric_params=metric_params,
117+
kind=kind,
118+
leaf_capacity=leaf_capacity,
119+
leaf_radius=leaf_radius,
120+
pivoting=pivoting,
121+
)
93122
super().__init__(proximity=prox)
94123

95124

@@ -101,19 +130,48 @@ class KNNCover(ProximityCover):
101130
:param neighbors: The number of neighbors to use for the KNN Proximity
102131
function, must be positive and less than the length of the dataset.
103132
:type neighbors: int
104-
:param metric: The (pseudo-)metric function that defines the distance
105-
between points, must be symmetric, positive, and satisfy the
106-
triangle-inequality, i.e.
107-
:math:`metric(x, z) \leq metric(x, y) + metric(y, z)` for every x, y, z
108-
in the dataset.
109-
:type metric: Callable
110-
:param flat: A flag that indicates whether to use a flat or a hierarchical
111-
vantage point tree, defaults to False.
112-
:type flat: bool, optional
133+
:param metric: The metric used to define the distance between points.
134+
Accepts any value compatible with `tdamapper.utils.metrics.get_metric`.
135+
Defaults to 'euclidean'.
136+
:type metric: str or callable
137+
:param metric_params: Additional parameters for the metric function, to be
138+
passed to `tdamapper.utils.metrics.get_metric`. Defaults to None.
139+
:type metric_params: dict, optional
140+
:param kind: Specifies whether to use a flat or a hierarchical vantage
141+
point tree. Acceptable values are 'flat' or 'hierarchical'. Defaults
142+
to 'flat'.
143+
:type kind: str
144+
:param leaf_capacity: The maximum number of points in a leaf node of the
145+
vantage point tree. If not specified, it defaults to the value of
146+
`neighbors`. Must be a positive value. Defaults to None.
147+
:type leaf_capacity: int, optional
148+
:param leaf_radius: The radius of the leaf nodes. Must be a positive value.
149+
Defaults to 0.0.
150+
:type leaf_radius: float
151+
:param pivoting: The method used for pivoting in the vantage point tree.
152+
Acceptable values are None, 'random', or 'furthest'. Defaults to None.
153+
:type pivoting: str or callable, optional
113154
"""
114155

115-
def __init__(self, neighbors, metric, flat=True):
116-
prox = KNNProximity(neighbors=neighbors, metric=metric, flat=flat)
156+
def __init__(
157+
self,
158+
neighbors,
159+
metric='euclidean',
160+
metric_params=None,
161+
kind='flat',
162+
leaf_capacity=None,
163+
leaf_radius=0.0,
164+
pivoting=None,
165+
):
166+
prox = KNNProximity(
167+
neighbors=neighbors,
168+
metric=metric,
169+
metric_params=metric_params,
170+
kind=kind,
171+
leaf_capacity=leaf_capacity,
172+
leaf_radius=leaf_radius,
173+
pivoting=pivoting,
174+
)
117175
super().__init__(proximity=prox)
118176

119177

@@ -122,22 +180,52 @@ class CubicalCover(ProximityCover):
122180
Cover algorithm based on the `cubical proximity function` implemented as
123181
:class:`tdamapper.proximity.CubicalProximity`.
124182
125-
:param n_intervals: The number of intervals to use for each dimension, must
126-
be positive and less than or equal to the length of the dataset.
183+
:param n_intervals: The number of intervals to use for each dimension.
184+
Must be positive and less than or equal to the length of the dataset.
127185
:type n_intervals: int
128186
:param overlap_frac: The fraction of overlap between adjacent intervals on
129187
each dimension, must be in the range (0.0, 1.0).
130188
:type overlap_frac: float
131-
:param flat: A flag that indicates whether to use a flat or a hierarchical
132-
vantage point tree, defaults to False.
133-
:type flat: bool, optional
189+
:param metric: The metric used to define the distance between points.
190+
Accepts any value compatible with `tdamapper.utils.metrics.get_metric`.
191+
Defaults to 'euclidean'.
192+
:type metric: str or callable
193+
:param metric_params: Additional parameters for the metric function, to be
194+
passed to `tdamapper.utils.metrics.get_metric`. Defaults to None.
195+
:type metric_params: dict, optional
196+
:param kind: Specifies whether to use a flat or a hierarchical vantage
197+
point tree. Acceptable values are 'flat' or 'hierarchical'. Defaults
198+
to 'flat'.
199+
:type kind: str
200+
:param leaf_capacity: The maximum number of points in a leaf node of the
201+
vantage point tree. Must be a positive value. Defaults to 1.
202+
:type leaf_capacity: int
203+
:param leaf_radius: The radius of the leaf nodes. If not specified, it
204+
defaults to the value of `radius`. Must be a positive value. Defaults
205+
to None.
206+
:type leaf_radius: float, optional
207+
:param pivoting: The method used for pivoting in the vantage point tree.
208+
Acceptable values are None, 'random', or 'furthest'. Defaults to None.
209+
:type pivoting: str or callable, optional
134210
"""
135211

136-
def __init__(self, n_intervals, overlap_frac, flat=True):
212+
def __init__(
213+
self,
214+
n_intervals,
215+
overlap_frac,
216+
kind='flat',
217+
leaf_capacity=1,
218+
leaf_radius=None,
219+
pivoting=None,
220+
):
137221
prox = CubicalProximity(
138222
n_intervals=n_intervals,
139223
overlap_frac=overlap_frac,
140-
flat=flat)
224+
kind=kind,
225+
leaf_capacity=leaf_capacity,
226+
leaf_radius=leaf_radius,
227+
pivoting=pivoting,
228+
)
141229
super().__init__(proximity=prox)
142230

143231

0 commit comments

Comments
 (0)