mogutda 0.4.3__py3-none-any.whl

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.
mogutda/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+
2
+ from .utils import *
3
+ from .abssimcomplex import SimplicialComplex
4
+ from .alphacomplex import AlphaComplex
5
+ from .vrcomplex import VietorisRipsComplex
@@ -0,0 +1,131 @@
1
+
2
+ from itertools import combinations
3
+ import warnings
4
+
5
+ import numpy as np
6
+ from scipy.sparse import dok_matrix
7
+ from scipy.sparse.linalg import aslinearoperator
8
+ from scipy.linalg.interpolative import estimate_rank
9
+ import networkx as nx
10
+ import matplotlib.pyplot as plt
11
+
12
+ from .utils import faces
13
+
14
+
15
+ class SimplicialComplex:
16
+ def __init__(self, simplices=[]):
17
+ self.import_simplices(simplices=simplices)
18
+
19
+ def import_simplices(self, simplices=[]):
20
+ # self.simplices = list(map(lambda simplex: tuple(sorted(simplex)), simplices))
21
+ self.simplices = [tuple(sorted(simplex)) for simplex in simplices]
22
+ self.face_set = faces(self.simplices)
23
+
24
+ def n_faces(self, n):
25
+ # return list(filter(lambda face: len(face) == n + 1, self.face_set))
26
+ return [face for face in self.face_set if len(face) == n+1]
27
+
28
+ def boundary_operator(self, i):
29
+ source_simplices = self.n_faces(i)
30
+ target_simplices = self.n_faces(i - 1)
31
+
32
+ if len(target_simplices) == 0:
33
+ S = dok_matrix((1, len(source_simplices)), dtype=np.float64)
34
+ S[0, 0:len(source_simplices)] = 1
35
+ else:
36
+ source_simplices_dict = {
37
+ source_simplices[j]: j for j in range(len(source_simplices))
38
+ }
39
+ target_simplices_dict = {
40
+ target_simplices[i]: i for i in range(len(target_simplices))
41
+ }
42
+
43
+ S = dok_matrix(
44
+ (len(target_simplices), len(source_simplices)), dtype=np.float64
45
+ )
46
+ for source_simplex in source_simplices:
47
+ for a in range(len(source_simplex)):
48
+ target_simplex = source_simplex[:a] + source_simplex[(a + 1) :]
49
+ i = target_simplices_dict[target_simplex]
50
+ j = source_simplices_dict[source_simplex]
51
+ S[i, j] = -1 if a % 2 == 1 else 1 # S[i, j] = (-1)**a
52
+ return S
53
+
54
+ def betti_number(self, i, eps=None):
55
+ boundop_i = self.boundary_operator(i)
56
+ boundop_ip1 = self.boundary_operator(i + 1)
57
+
58
+ if i == 0:
59
+ boundop_i_rank = 0
60
+ else:
61
+ if eps is None:
62
+ try:
63
+ boundop_i_rank = np.linalg.matrix_rank(boundop_i.toarray())
64
+ except (np.linalg.LinAlgError, ValueError):
65
+ boundop_i_rank = boundop_i.shape[1]
66
+ else:
67
+ boundop_i_rank = estimate_rank(aslinearoperator(boundop_i), eps)
68
+
69
+ if eps is None:
70
+ try:
71
+ boundop_ip1_rank = np.linalg.matrix_rank(boundop_ip1.toarray())
72
+ except (np.linalg.LinAlgError, ValueError):
73
+ boundop_ip1_rank = boundop_ip1.shape[1]
74
+ else:
75
+ boundop_ip1_rank = estimate_rank(aslinearoperator(boundop_ip1), eps)
76
+
77
+ return (boundop_i.shape[1] - boundop_i_rank) - boundop_ip1_rank
78
+
79
+ def euler_characteristics(self):
80
+ max_n = max(map(len, self.simplices))
81
+ return sum(
82
+ [(-1 if a % 2 == 1 else 1) * self.betti_number(a) for a in range(max_n)]
83
+ )
84
+
85
+ def generate_graph(self, simplices=None):
86
+ """ Generate edges and vertices in sets """
87
+ if len(self.simplices) == 0 and simplices is None:
88
+ raise Exception("No simplices to create a graph from. Please specify one.")
89
+ elif simplices is not None:
90
+ self.import_simplices(simplices=simplices)
91
+
92
+ vertices = set()
93
+ edges = set()
94
+
95
+ for simplex in self.simplices:
96
+ for vertex1, vertex2 in combinations(simplex, 2):
97
+ vertices.add(vertex1)
98
+ vertices.add(vertex2)
99
+ edges.add(tuple(sorted([vertex1, vertex2])))
100
+ return vertices, edges
101
+
102
+ def draw(self, vertex_labels=True, edge_labels=False):
103
+ """ Draw the Simplicial Complex """
104
+ vertices, edges = self.generate_graph()
105
+
106
+ if len(vertices) + len(edges) > 1000:
107
+ warnings.warn(
108
+ "The number of elements to draw exceeds 100. To still draw the plot, call the function with override_100_limit = True. "
109
+ )
110
+ else:
111
+ G = nx.Graph()
112
+ for vertex in vertices:
113
+ G.add_node(vertex)
114
+ for edge in edges:
115
+ G.add_edge(edge[0], edge[1])
116
+ pos = nx.spring_layout(G)
117
+
118
+ nx.draw(G, pos)
119
+
120
+ labels = {}
121
+ if vertex_labels is True:
122
+ for vertex in vertices:
123
+ labels[vertex] = str(vertex)
124
+ nx.draw_networkx_labels(G, pos, labels, font_size=16)
125
+
126
+ if edge_labels is True:
127
+ edge_labels = {}
128
+ for edge in edges:
129
+ edge_labels[edge] = "{}:{}".format(edge[0], edge[1])
130
+ nx.draw_networkx_edge_labels(G, pos, edge_labels, font_size=3)
131
+ plt.plot()
@@ -0,0 +1,71 @@
1
+
2
+ from scipy.spatial import Delaunay, distance
3
+
4
+ from .abssimcomplex import SimplicialComplex
5
+ from .utils import facesiter, get_allpoints
6
+
7
+
8
+ def calculate_distmatrix(points, labels, distfcn):
9
+ return {
10
+ (labels[i], labels[j]): distfcn(points[i], points[j])
11
+ for i in range(len(labels)) for j in range(len(labels))
12
+ }
13
+
14
+
15
+ def contain_detachededges(simplex, distdict, epsilon):
16
+ if len(simplex) == 2:
17
+ return distdict[simplex[0], simplex[1]] > 2*epsilon
18
+ else:
19
+ for face in facesiter(simplex):
20
+ contained = contain_detachededges(face, distdict, epsilon)
21
+ if contained:
22
+ return True
23
+ return False
24
+
25
+
26
+ class AlphaComplex(SimplicialComplex):
27
+ def __init__(
28
+ self,
29
+ points,
30
+ epsilon,
31
+ labels=None,
32
+ distfcn=distance.euclidean
33
+ ):
34
+ super(AlphaComplex, self).__init__()
35
+ self.pts = points
36
+ self.labels = (range(len(self.pts))
37
+ if (labels is None or len(labels) != len(self.pts))
38
+ else labels)
39
+ self.epsilon = epsilon
40
+ self.distfcn = distfcn
41
+ self.import_simplices(
42
+ self.construct_simplices(self.pts, self.labels, self.epsilon, self.distfcn)
43
+ )
44
+
45
+ def construct_simplices(self, points, labels, epsilon, distfcn):
46
+ distdict = calculate_distmatrix(points, labels, distfcn)
47
+
48
+ delaunayobj = Delaunay(points)
49
+
50
+ simplices = []
51
+ for simplexnda in delaunayobj.simplices:
52
+ simplex = tuple(simplexnda)
53
+
54
+ detached = [contain_detachededges(face, distdict, epsilon) for face in facesiter(simplex)]
55
+
56
+ if True in detached and len(simplex) > 2:
57
+ simplices += [
58
+ face
59
+ for face, notkeep in zip(facesiter(simplex), detached)
60
+ if not notkeep
61
+ ]
62
+ else:
63
+ simplices.append(simplex)
64
+ # simplices = map(lambda simplex: tuple(sorted(simplex)), simplices)
65
+ simplices = [tuple(sorted(simplex)) for simplex in simplices]
66
+ simplices = list(set(simplices))
67
+
68
+ allpts = get_allpoints(simplices)
69
+ simplices += [(point,) for point in (set(labels)-allpts)]
70
+
71
+ return simplices
mogutda/utils.py ADDED
@@ -0,0 +1,27 @@
1
+
2
+ from itertools import combinations
3
+
4
+
5
+ def facesiter(simplex):
6
+ for i in range(len(simplex)):
7
+ yield simplex[:i] + simplex[(i + 1):]
8
+
9
+
10
+ def flattening_simplex(simplices):
11
+ for simplex in simplices:
12
+ for point in simplex:
13
+ yield point
14
+
15
+
16
+ def get_allpoints(simplices):
17
+ return set(flattening_simplex(simplices))
18
+
19
+
20
+ def faces(simplices):
21
+ faceset = set()
22
+ for simplex in simplices:
23
+ numnodes = len(simplex)
24
+ for r in range(numnodes, 0, -1):
25
+ for face in combinations(simplex, r):
26
+ faceset.add(tuple(sorted(face)))
27
+ return faceset
mogutda/vrcomplex.py ADDED
@@ -0,0 +1,38 @@
1
+
2
+ from itertools import product
3
+
4
+ import networkx as nx
5
+ from scipy.spatial import distance
6
+
7
+ from .abssimcomplex import SimplicialComplex
8
+
9
+
10
+ class VietorisRipsComplex(SimplicialComplex):
11
+ def __init__(
12
+ self,
13
+ points,
14
+ epsilon,
15
+ labels=None,
16
+ distfcn=distance.euclidean
17
+ ):
18
+ super(VietorisRipsComplex, self).__init__()
19
+ self.pts = points
20
+ self.labels = (list(range(len(self.pts)))
21
+ if labels is None or len(labels) != len(self.pts)
22
+ else labels)
23
+ self.epsilon = epsilon
24
+ self.distfcn = distfcn
25
+ self.network = self.construct_network(
26
+ self.pts, self.labels, self.epsilon, self.distfcn
27
+ )
28
+ self.import_simplices(map(tuple, nx.find_cliques(self.network)))
29
+
30
+ def construct_network(self, points, labels, epsilon, distfcn):
31
+ g = nx.Graph()
32
+ g.add_nodes_from(labels)
33
+ for pair in product(zip(points, labels), zip(points, labels)):
34
+ if pair[0][1] != pair[1][1]:
35
+ dist = distfcn(pair[0][0], pair[1][0])
36
+ if dist < epsilon:
37
+ g.add_edge(pair[0][1], pair[1][1])
38
+ return g
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 Kwan Yuet Stephen Ho
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,182 @@
1
+ Metadata-Version: 2.1
2
+ Name: mogutda
3
+ Version: 0.4.3
4
+ Summary: Topological Data Analysis in Python
5
+ Author-email: Kwan Yuet Stephen Ho <stephenhky@yahoo.com.hk>
6
+ License: MIT
7
+ Project-URL: Documentation, https://mogutda.readthedocs.io
8
+ Project-URL: Repository, https://github.com/stephenhky/MoguTDA
9
+ Project-URL: Issues, https://github.com/stephenhky/MoguTDA/issues
10
+ Keywords: mogutda,numerical methods,topology,data,algebraic topology
11
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
12
+ Classifier: Topic :: Scientific/Engineering :: Physics
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Intended Audience :: Developers
20
+ Classifier: Intended Audience :: Education
21
+ Classifier: Intended Audience :: Information Technology
22
+ Classifier: Intended Audience :: Science/Research
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: numpy>=1.16.0
27
+ Requires-Dist: scipy>=1.10.0
28
+ Requires-Dist: networkx>=2.0
29
+ Requires-Dist: matplotlib>=3.3.0
30
+ Provides-Extra: test
31
+ Requires-Dist: unittest; extra == "test"
32
+
33
+ # `mogutda`: Topological Data Analysis in Python
34
+
35
+ [![CircleCI](https://circleci.com/gh/stephenhky/MoguTDA.svg?style=svg)](https://circleci.com/gh/stephenhky/MoguTDA.svg)
36
+ [![GitHub release](https://img.shields.io/github/release/stephenhky/MoguTDA.svg?maxAge=3600)](https://github.com/stephenhky/MoguTDA/releases)
37
+ [![Documentation Status](https://readthedocs.org/projects/mogutda/badge/?version=latest)](https://mogutda.readthedocs.io/en/latest/?badge=latest)
38
+ [![Updates](https://pyup.io/repos/github/stephenhky/MoguTDA/shield.svg)](https://pyup.io/repos/github/stephenhky/MoguTDA/)
39
+ [![Python 3](https://pyup.io/repos/github/stephenhky/MoguTDA/python-3-shield.svg)](https://pyup.io/repos/github/stephenhky/MoguTDA/)
40
+ [![pypi](https://img.shields.io/pypi/v/mogutda.svg?maxAge=3600)](https://pypi.org/project/mogutda/)
41
+ [![download](https://img.shields.io/pypi/dm/mogutda.svg?maxAge=2592000&label=installs&color=%2327B1FF)](https://pypi.org/project/mogutda/)
42
+ [![stars](https://img.shields.io/github/stars/stephenhky/MoguTDA.svg?style=social&label=Star&maxAge=60)](https://github.com/stephenhky/MoguTDA)
43
+
44
+
45
+ ## Introduction
46
+
47
+ `mogutda` contains Python codes that demonstrate the numerical calculation
48
+ of algebraic topology in an application to topological data analysis
49
+ (TDA). Its core code is the numerical methods concerning implicial complex,
50
+ and the estimation of homology and Betti numbers.
51
+
52
+ Topological data analysis aims at studying the shapes of the data, and
53
+ draw some insights from them. A lot of machine learning algorithms deal
54
+ with distances, which are extremely useful, but they miss the
55
+ information the data may carry from their geometry.
56
+
57
+ ## History
58
+
59
+ The codes in this package were developed as a demonstration of a few posts of my blog.
60
+ It was not designed to be a Python package but a pedagogical collection of codes.
61
+ (See: [PyTDA](https://github.com/stephenhky/PyTDA).)
62
+ However, the codes and the blog posts have been unexpectedly popular. Therefore,
63
+ I modularized the code into the package [`mogu`](https://pypi.org/project/mogu/).
64
+ (or corresponding repository: [MoguNumerics](https://github.com/stephenhky/MoguNumerics))
65
+ However, `mogu` is simply a collection of unrelated numerical routines with a lot of
66
+ dependencies, but the part of TDA can be quite independent.
67
+
68
+ In order to provide other researchers and developers an independent package, which is compact (without
69
+ unecessary alternative packages to load), and efficient, I decided to modularize
70
+ the codes of TDA separately, and name this package `mogutda`.
71
+
72
+ ## Prerequisite
73
+
74
+ It runs under Python 3.8, 3.9, 3.10, and 3.11.
75
+
76
+ ## Simple Tutorial: Simplicial Complex
77
+
78
+ You can install by:
79
+
80
+ ```
81
+ pip install mogutda
82
+ ```
83
+
84
+ To establish a simplicial complex for a torus, type
85
+
86
+ ```
87
+ import numpy as np
88
+ from mogutda import SimplicialComplex
89
+
90
+ torus_sc = [(1,2,4), (4,2,5), (2,3,5), (3,5,6), (5,6,1), (1,6,2), (6,7,2), (7,3,2),
91
+ (1,3,4), (3,4,6), (4,6,7), (4,5,7), (5,7,1), (7,3,1)]
92
+ torus_c = SimplicialComplex(simplices=torus_sc)
93
+ ```
94
+
95
+ To retrieve its Betti numbers, type:
96
+
97
+ ```
98
+ print(torus_c.betti_number(0)) # print 1
99
+ print(torus_c.betti_number(1)) # print 2
100
+ print(torus_c.betti_number(2)) # print 1
101
+ ```
102
+
103
+ ## Demo Codes and Blog Entries
104
+
105
+ Codes in this repository are demo codes for a few entries of my blog,
106
+ [Everything about Data Analytics](https://datawarrior.wordpress.com/),
107
+ and the corresponding entries are:
108
+
109
+ * [Starting the Journey of Topological Data Analysis (TDA)](https://datawarrior.wordpress.com/2015/08/03/tda-1-starting-the-journey-of-topological-data-analysis-tda/) (August 3, 2015)
110
+ * [Constructing Connectivities](https://datawarrior.wordpress.com/2015/09/14/tda-2-constructing-connectivities/) (September 14, 2015)
111
+ * [Homology and Betti Numbers](https://datawarrior.wordpress.com/2015/11/03/tda-3-homology-and-betti-numbers/) (November 3, 2015)
112
+ * [Topology in Physics and Computing](https://datawarrior.wordpress.com/2015/11/10/mathanalytics-6-topology-in-physics-and-computing/) (November 10, 2015)
113
+ * [Persistence](https://datawarrior.wordpress.com/2015/12/20/tda-4-persistence/) (December 20, 2015)
114
+ * [Topological Phases](https://datawarrior.wordpress.com/2016/10/06/topological-phases/) (October 6, 2016)
115
+ * [moguTDA: Python package for Simplicial Complex](https://datawarrior.wordpress.com/2018/07/02/mogutda-python-package-for-simplicial-complex/) (July 2, 2018)
116
+
117
+ ## Wolfram Demonstration
118
+ Richard Hennigan put a nice Wolfram Demonstration online explaining what
119
+ the simplicial complexes are, and how homologies are defined:
120
+
121
+ * [Simplicial Homology of the Alpha Complex](http://demonstrations.wolfram.com/SimplicialHomologyOfTheAlphaComplex/)
122
+
123
+ ## News
124
+
125
+ * 09/19/2024: `mogutda` 0.4.3 released.
126
+ * 07/16/2024: `mogutsa` 0.4.2 released.
127
+ * 11/23/2023: `mogutda` 0.4.1 released.
128
+ * 08/18/2023: `mogutda` 0.4.0 released.
129
+ * 06/20/2023: `mogutda` 0.3.5 released.
130
+ * 09/09/2022: `mogutda` 0.3.4 released.
131
+ * 07/15/2021: `mogutda` 0.3.3 released.
132
+ * 04/10/2021: `mogutda` 0.3.2 released.
133
+ * 11/28/2020: `mogutda` 0.3.1 released.
134
+ * 08/16/2020: `mogutda` 0.3.0 released.
135
+ * 04/28/2020: `mogutda` 0.2.1 released.
136
+ * 01/16/2020: `mogutda` 0.2.0 released.
137
+ * 02/20/2019: `mogutda` 0.1.5 released.
138
+ * 12/31/2018: `mogutda` 0.1.4 released.
139
+ * 07/18/2018: `mogutda` 0.1.3 released.
140
+ * 07/02/2018: `mogutda` 0.1.2 released.
141
+ * 06/13/2018: `mogutda` 0.1.1 released.
142
+ * 06/11/2018: `mogutda` 0.1.0 released.
143
+
144
+ ## Other TDA Packages
145
+
146
+ It is recommended that for real application, you should use the following packages
147
+ for efficiency, because my codes serve the pedagogical purpose only.
148
+
149
+ ### C++
150
+ * [Dionysus](http://www.mrzv.org/software/dionysus/)
151
+ * [PHAT](https://bitbucket.org/phat-code/phat)
152
+
153
+ ### Python
154
+ * [Dionysus](http://www.mrzv.org/software/dionysus/python/overview.html)
155
+
156
+ ### R
157
+ * [TDA](https://cran.r-project.org/web/packages/TDA/index.html) (article: [\[arXiv\]](http://arxiv.org/abs/1411.1830))
158
+
159
+ ## Contributions
160
+
161
+ If you want to contribute, feel free to fork the repository, and submit
162
+ a pull request whenever you are ready.
163
+
164
+ If you spot any bugs or issues, go to the [Issue](https://github.com/stephenhky/MoguTDA) page.
165
+
166
+ I may not approve pull request immediately if your suggested change is big.
167
+ If you want to incorporate something big, please discuss with me first.
168
+
169
+ ## References
170
+ * Afra J. Zomorodian. *Topology for Computing* (New York, NY: Cambridge University Press, 2009). [\[Amazon\]](https://www.amazon.com/Computing-Cambridge-Monographs-Computational-Mathematics/dp/0521136091)
171
+ * Afra J. Zomorodian. "Topological Data Analysis," *Proceedings of Symposia in Applied Mathematics* (2011). [\[link\]](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.261.1298)
172
+ * Afra Zomorodian, Gunnar Carlsson, “Computing Persistent Homology,” *Discrete Comput. Geom.* 33, 249-274 (2005). [\[pdf\]](http://geometry.stanford.edu/papers/zc-cph-05/zc-cph-05.pdf)
173
+ * Gunnar Carlsson, “Topology and Data”, *Bull. Amer. Math. Soc.* 46, 255-308 (2009). [\[link\]](http://www.ams.org/journals/bull/2009-46-02/S0273-0979-09-01249-X/)
174
+ * Jeffrey Ray, Marcello Trovati, "A Survey of Topological Data Analysis (TDA) Methods Implemented in Python," in *Advances in Intelligent Networking and Collaborative Systems*, Springer (2018).
175
+ * P. Y. Lum, G. Singh, A. Lehman, T. Ishkanov, M. Vejdemo-Johansson, M. Alagappan, J. Carlsson, G. Carlsson, “Extracting insights from the shape of complex data using topology”, *Sci. Rep.* 3, 1236 (2013). [\[link\]](http://www.nature.com/srep/2013/130207/srep01236/full/srep01236.html)
176
+ * Robert Ghrist, “Barcodes: The persistent topology of data,” *Bull. Amer. Math. Soc.* 45, 1-15 (2008). [\[pdf\]](http://www.ams.org/journals/bull/2008-45-01/S0273-0979-07-01191-3/S0273-0979-07-01191-3.pdf)
177
+
178
+ ## Links
179
+
180
+ * PyPI: [https://pypi.org/project/mogutda/](https://pypi.org/project/mogutda/)
181
+ * Documentation: [https://mogutda.readthedocs.io/](https://mogutda.readthedocs.io/)
182
+ * Bug Reports: [https://github.com/stephenhky/MoguTDA/issues](https://github.com/stephenhky/MoguTDA/issues)
@@ -0,0 +1,10 @@
1
+ mogutda/__init__.py,sha256=vKhNOC6bE6kRNh-dAEb0GWnmvbpf75TFLHadBLd3Bno,149
2
+ mogutda/abssimcomplex.py,sha256=3_E5SbQMf1kBXtS4vwRGLV5sin-Slv64URbnCfUaJEo,4857
3
+ mogutda/alphacomplex.py,sha256=eBGv-ZgcfAJnVCaMKfBQ-PV-Mk7gK34yYM13dWj-tTc,2293
4
+ mogutda/utils.py,sha256=1KDTfo8ClLueGPLXn-l1rxWTfLqxsjtDMsX0nQGK89E,606
5
+ mogutda/vrcomplex.py,sha256=0FE9h4yRbf1DgdQtYvfm-J5j7oeO0JlZPmp0L06le24,1220
6
+ mogutda-0.4.3.dist-info/LICENSE,sha256=3paJBNa5qA0n3pWiu0x3NMUOpzN_ypGIWKQ3YImmz_o,1063
7
+ mogutda-0.4.3.dist-info/METADATA,sha256=npkQgBI5dewlRCx2Wg-yRrJ4eQacovAno6ps8B3_AR8,9279
8
+ mogutda-0.4.3.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
9
+ mogutda-0.4.3.dist-info/top_level.txt,sha256=K_S8S2ArTcepp_xCda5D_91jTHd04raVcOt7dX6vmHw,8
10
+ mogutda-0.4.3.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ mogutda