morphomatics 4.0__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.
- morphomatics/__init__.py +13 -0
- morphomatics/geom/__init__.py +16 -0
- morphomatics/geom/bezier_spline.py +361 -0
- morphomatics/geom/misc.py +104 -0
- morphomatics/geom/surface.py +208 -0
- morphomatics/graph/__init__.py +13 -0
- morphomatics/graph/operators.py +124 -0
- morphomatics/manifold/__init__.py +46 -0
- morphomatics/manifold/bezierfold.py +500 -0
- morphomatics/manifold/connection.py +105 -0
- morphomatics/manifold/cubic_bezierfold.py +305 -0
- morphomatics/manifold/differential_coords.py +197 -0
- morphomatics/manifold/discrete_ops.py +56 -0
- morphomatics/manifold/euclidean.py +213 -0
- morphomatics/manifold/fundamental_coords.py +440 -0
- morphomatics/manifold/gl_p_coords.py +149 -0
- morphomatics/manifold/gl_p_n.py +201 -0
- morphomatics/manifold/grassmann.py +174 -0
- morphomatics/manifold/hyperbolic_space.py +271 -0
- morphomatics/manifold/kendall.py +269 -0
- morphomatics/manifold/lie_group.py +102 -0
- morphomatics/manifold/manifold.py +162 -0
- morphomatics/manifold/manopt_wrapper.py +185 -0
- morphomatics/manifold/metric.py +110 -0
- morphomatics/manifold/point_distribution_model.py +143 -0
- morphomatics/manifold/power_manifold.py +413 -0
- morphomatics/manifold/product_manifold.py +381 -0
- morphomatics/manifold/se_3.py +419 -0
- morphomatics/manifold/shape_space.py +57 -0
- morphomatics/manifold/so_3.py +494 -0
- morphomatics/manifold/spd.py +524 -0
- morphomatics/manifold/sphere.py +241 -0
- morphomatics/manifold/tangent_bundle.py +337 -0
- morphomatics/manifold/util.py +126 -0
- morphomatics/nn/__init__.py +15 -0
- morphomatics/nn/flow_layers.py +219 -0
- morphomatics/nn/tangent_layers.py +176 -0
- morphomatics/nn/train.py +202 -0
- morphomatics/nn/wFM_layers.py +152 -0
- morphomatics/opt/__init__.py +14 -0
- morphomatics/opt/riemannian_newton_raphson.py +65 -0
- morphomatics/opt/riemannian_steepest_descent.py +61 -0
- morphomatics/stats/__init__.py +18 -0
- morphomatics/stats/biinvariant_statistics.py +190 -0
- morphomatics/stats/exponential_barycenter.py +78 -0
- morphomatics/stats/geometric_median.py +89 -0
- morphomatics/stats/principal_geodesic_analysis.py +135 -0
- morphomatics/stats/riemannian_regression.py +317 -0
- morphomatics/stats/statistical_shape_model.py +99 -0
- morphomatics-4.0.dist-info/LICENSE +9 -0
- morphomatics-4.0.dist-info/METADATA +55 -0
- morphomatics-4.0.dist-info/RECORD +54 -0
- morphomatics-4.0.dist-info/WHEEL +5 -0
- morphomatics-4.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
################################################################################
|
|
2
|
+
# #
|
|
3
|
+
# This file is part of the Morphomatics library #
|
|
4
|
+
# see https://github.com/morphomatics/morphomatics #
|
|
5
|
+
# #
|
|
6
|
+
# Copyright (C) 2024 Zuse Institute Berlin #
|
|
7
|
+
# #
|
|
8
|
+
# Morphomatics is distributed under the terms of the MIT License. #
|
|
9
|
+
# see $MORPHOMATICS/LICENSE #
|
|
10
|
+
# #
|
|
11
|
+
################################################################################
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
from scipy import sparse
|
|
16
|
+
|
|
17
|
+
from .misc import memoize, gradient_matrix_ambient
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Surface(object):
|
|
22
|
+
""" Triangular surface geom. """
|
|
23
|
+
|
|
24
|
+
def __init__(self, v, f):
|
|
25
|
+
"""
|
|
26
|
+
:arg v: #v-by-dim array of vertex coordinate
|
|
27
|
+
:arg f: #f-by-3 array of triangles (each given as indices into \a v)
|
|
28
|
+
"""
|
|
29
|
+
# cache for memoization
|
|
30
|
+
self._cache_v = dict()
|
|
31
|
+
self._cache_f = dict()
|
|
32
|
+
|
|
33
|
+
self.v = np.asarray(v).astype(np.double, copy=False)
|
|
34
|
+
self.f = np.asarray(f)
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def v(self):
|
|
38
|
+
return self.__v
|
|
39
|
+
|
|
40
|
+
@v.setter
|
|
41
|
+
def v(self, v):
|
|
42
|
+
self.__v = v
|
|
43
|
+
self._cache_v.clear()
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def f(self):
|
|
47
|
+
return self.__f
|
|
48
|
+
|
|
49
|
+
@f.setter
|
|
50
|
+
def f(self, f):
|
|
51
|
+
self.__f = f
|
|
52
|
+
self._cache_v.clear()
|
|
53
|
+
self._cache_f.clear()
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
@memoize('_cache_v')
|
|
57
|
+
def grad(self):
|
|
58
|
+
""" Gradient of a scalar function defined on piecewise linear elements
|
|
59
|
+
(see: geom.misc.gradient_matrix_ambient) """
|
|
60
|
+
return gradient_matrix_ambient(self.v, self.f)
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
@memoize('_cache_v')
|
|
64
|
+
def div(self):
|
|
65
|
+
"""Divergence operator"""
|
|
66
|
+
mass = self.face_areas
|
|
67
|
+
d = self.grad.shape[0] / len(mass) # ambient dim.
|
|
68
|
+
return self.grad.T @ sparse.diags(np.repeat(mass, d), 0)
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
@memoize('_cache_v')
|
|
72
|
+
def face_areas(self):
|
|
73
|
+
"""Area of triangles."""
|
|
74
|
+
# Compute cross-product of edges
|
|
75
|
+
ppts = self.v[self.f]
|
|
76
|
+
nnfnorms = np.cross(ppts[:, 1] - ppts[:, 0],
|
|
77
|
+
ppts[:, 2] - ppts[:, 0])
|
|
78
|
+
# Compute vector length
|
|
79
|
+
return np.sqrt((nnfnorms ** 2).sum(-1)) / 2
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
@memoize('_cache_f')
|
|
83
|
+
def inner_edges(self):
|
|
84
|
+
"""
|
|
85
|
+
Extract inner edges of an oriented, triangle surface.
|
|
86
|
+
:return: sparse matrix with inner edge ids as entries (indexed by resp. faces).
|
|
87
|
+
"""
|
|
88
|
+
m = len(self.f)
|
|
89
|
+
n = self.f.max() + 1
|
|
90
|
+
|
|
91
|
+
e1 = sparse.coo_matrix((np.ones(m), (self.f[:, 0], self.f[:, 1])), (n, n))
|
|
92
|
+
e2 = sparse.coo_matrix((np.ones(m), (self.f[:, 1], self.f[:, 2])), (n, n))
|
|
93
|
+
e3 = sparse.coo_matrix((np.ones(m), (self.f[:, 2], self.f[:, 0])), (n, n))
|
|
94
|
+
D = (e1 + e2 + e3).tocsr()
|
|
95
|
+
|
|
96
|
+
# boundary edges as sparse matrix
|
|
97
|
+
E = (D - D.T).tocsr()
|
|
98
|
+
# inner edges as sparse matrix
|
|
99
|
+
F = 0.5*(D + D.T - np.absolute(D - D.T))
|
|
100
|
+
F.eliminate_zeros()
|
|
101
|
+
|
|
102
|
+
off = 1
|
|
103
|
+
f1 = sparse.coo_matrix((np.arange(off, m+off), (self.f[:, 0], self.f[:, 1])), (n, n)).tocsr()
|
|
104
|
+
f2 = sparse.coo_matrix((np.arange(off, m+off), (self.f[:, 1], self.f[:, 2])), (n, n)).tocsr()
|
|
105
|
+
f3 = sparse.coo_matrix((np.arange(off, m+off), (self.f[:, 2], self.f[:, 0])), (n, n)).tocsr()
|
|
106
|
+
|
|
107
|
+
ff = f1 +f2 +f3
|
|
108
|
+
|
|
109
|
+
FF = F.multiply(ff)
|
|
110
|
+
FFU = sparse.triu(FF).tocsr()
|
|
111
|
+
|
|
112
|
+
edgesI = FFU.tocoo().row
|
|
113
|
+
edgesJ = FFU.tocoo().col
|
|
114
|
+
|
|
115
|
+
edgeTriI = np.reshape(np.asarray(FF[edgesI[:], edgesJ[:]]), edgesI.shape[0]) - 1
|
|
116
|
+
edgeTriJ = np.reshape(np.asarray(FF[edgesJ[:], edgesI[:]]), edgesJ.shape[0]) - 1
|
|
117
|
+
|
|
118
|
+
# k-th (inner) edge, s.t. FFU(edgesI[k], edgesJ[k]) -> FFU(edgesJ[k], edgesI[k])
|
|
119
|
+
tris2InnerEdgeId = sparse.coo_matrix((np.arange(1, FFU.getnnz()+1), (edgeTriI[:], edgeTriJ[:])), (m, m))
|
|
120
|
+
tris2InnerEdgeId = tris2InnerEdgeId + tris2InnerEdgeId.T
|
|
121
|
+
tris2InnerEdgeId.data = tris2InnerEdgeId.data -1
|
|
122
|
+
|
|
123
|
+
return tris2InnerEdgeId.tocsr()
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
@memoize('_cache_v')
|
|
127
|
+
def edge_areas(self):
|
|
128
|
+
inner_edge = sparse.triu(self.inner_edges)
|
|
129
|
+
areas=np.zeros(inner_edge.data.shape[0])
|
|
130
|
+
areas[inner_edge.data[:]] = 1.0/3.0 * ( self.face_areas[inner_edge.row[:]] + self.face_areas[inner_edge.col[:]] )
|
|
131
|
+
return areas
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
@memoize('_cache_f')
|
|
135
|
+
def neighbors(self):
|
|
136
|
+
"""
|
|
137
|
+
Provides information on face neighbors.
|
|
138
|
+
:return: idx_1, idx_2, idx_3, n_1, n_2, n_3,
|
|
139
|
+
where idx_1, idx_2, idx_3 are boolean index arrays for faces with at least one (idx_1), at least two (idx_2) and three (idx_3) neighbors;
|
|
140
|
+
where n_1, n_2, n_3 are n x k array storing the respective neighbors per face for all faces with at least one (n_1), at least two (n_2)
|
|
141
|
+
and three (n_3) neighbors.
|
|
142
|
+
"""
|
|
143
|
+
# neighbors per face
|
|
144
|
+
neighs = np.asarray(np.split(self.inner_edges.indices, self.inner_edges.indptr[1:-1]), dtype=object)
|
|
145
|
+
nNeighs = np.asarray(list(map(np.shape, neighs))).ravel()
|
|
146
|
+
|
|
147
|
+
idx_1 = (nNeighs == 1)
|
|
148
|
+
idx_2 = (nNeighs == 2)
|
|
149
|
+
idx_3 = (nNeighs == 3)
|
|
150
|
+
|
|
151
|
+
neigh_pad = np.zeros((neighs.shape[0], 3)).astype(int)
|
|
152
|
+
|
|
153
|
+
if np.count_nonzero(idx_1):
|
|
154
|
+
neigh_pad[idx_1, 0:1] = np.asarray(list(neighs[idx_1]))
|
|
155
|
+
if np.count_nonzero(idx_2):
|
|
156
|
+
neigh_pad[idx_2, 0:2] = np.asarray(list(neighs[idx_2]))
|
|
157
|
+
if np.count_nonzero(idx_3):
|
|
158
|
+
neigh_pad[idx_3, 0:3] = np.asarray(list(neighs[idx_3]))
|
|
159
|
+
|
|
160
|
+
idx_1 = (nNeighs > 0)
|
|
161
|
+
idx_2 = (nNeighs > 1)
|
|
162
|
+
idx_3 = (nNeighs > 2)
|
|
163
|
+
|
|
164
|
+
n_1 = neigh_pad[idx_1]
|
|
165
|
+
n_2 = neigh_pad[idx_2]
|
|
166
|
+
n_3 = neigh_pad[idx_3]
|
|
167
|
+
|
|
168
|
+
return idx_1, idx_2, idx_3, n_1, n_2, n_3
|
|
169
|
+
|
|
170
|
+
def copy(self):
|
|
171
|
+
"""
|
|
172
|
+
:return: copy of this surface
|
|
173
|
+
"""
|
|
174
|
+
return Surface(self.v.copy(), self.f.copy())
|
|
175
|
+
|
|
176
|
+
def boundary(self):
|
|
177
|
+
"""
|
|
178
|
+
Extract boundary curves of an oriented, triangle surface.
|
|
179
|
+
:return: List of boundary curves (list of vertex indices).
|
|
180
|
+
"""
|
|
181
|
+
m = len(self.f)
|
|
182
|
+
n = self.f.max() + 1
|
|
183
|
+
# boundary edges as sparse matrix
|
|
184
|
+
e1 = sparse.coo_matrix((np.ones(m), (self.f[:, 0], self.f[:, 1])), (n, n))
|
|
185
|
+
e2 = sparse.coo_matrix((np.ones(m), (self.f[:, 1], self.f[:, 2])), (n, n))
|
|
186
|
+
e3 = sparse.coo_matrix((np.ones(m), (self.f[:, 2], self.f[:, 0])), (n, n))
|
|
187
|
+
E = (e1 - e1.T + e2 - e2.T + e3 - e3.T).tocsr()
|
|
188
|
+
E.sort_indices()
|
|
189
|
+
|
|
190
|
+
if E.nnz == 0:
|
|
191
|
+
return None
|
|
192
|
+
|
|
193
|
+
# extract boundary curves
|
|
194
|
+
boundaries = []
|
|
195
|
+
|
|
196
|
+
nnz = E.getnnz(1)
|
|
197
|
+
for i in range(n):
|
|
198
|
+
if nnz[i] == 0: continue
|
|
199
|
+
# new boundary curve
|
|
200
|
+
bnd = [i]
|
|
201
|
+
while True:
|
|
202
|
+
j = (E.getrow(bnd[-1]) > 0).indices[0]
|
|
203
|
+
nnz[j] = 0 # mark as part of a processed bnd. curve
|
|
204
|
+
if j == i: break
|
|
205
|
+
bnd.append(j)
|
|
206
|
+
boundaries.append(bnd)
|
|
207
|
+
|
|
208
|
+
return boundaries
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
################################################################################
|
|
2
|
+
# #
|
|
3
|
+
# This file is part of the Morphomatics library #
|
|
4
|
+
# see https://github.com/morphomatics/morphomatics #
|
|
5
|
+
# #
|
|
6
|
+
# Copyright (C) 2024 Zuse Institute Berlin #
|
|
7
|
+
# #
|
|
8
|
+
# Morphomatics is distributed under the terms of the MIT License. #
|
|
9
|
+
# see $MORPHOMATICS/LICENSE #
|
|
10
|
+
# #
|
|
11
|
+
################################################################################
|
|
12
|
+
|
|
13
|
+
from .operators import mfdg_laplace, mfdg_gradient, max_pooling, mean_pooling, in_degree_centrality, out_degree_centrality
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
################################################################################
|
|
2
|
+
# #
|
|
3
|
+
# This file is part of the Morphomatics library #
|
|
4
|
+
# see https://github.com/morphomatics/morphomatics #
|
|
5
|
+
# #
|
|
6
|
+
# Copyright (C) 2024 Zuse Institute Berlin #
|
|
7
|
+
# #
|
|
8
|
+
# Morphomatics is distributed under the terms of the MIT License. #
|
|
9
|
+
# see $MORPHOMATICS/LICENSE #
|
|
10
|
+
# #
|
|
11
|
+
################################################################################
|
|
12
|
+
|
|
13
|
+
import jax
|
|
14
|
+
from jax import tree_util as tree
|
|
15
|
+
import jax.numpy as jnp
|
|
16
|
+
import jraph
|
|
17
|
+
|
|
18
|
+
from morphomatics.manifold import Manifold
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def mfdg_gradient(M: Manifold, graph: jraph.GraphsTuple) -> jnp.array:
|
|
22
|
+
"""Given a graph with manifold-valued features returns the gradient as defined in https://arxiv.org/abs/1702.05293
|
|
23
|
+
|
|
24
|
+
:param M: feature manifold
|
|
25
|
+
:param graph: M-valued graph
|
|
26
|
+
:return: edge gradients
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
# gradients on directed edges are stored along first axis (orderd given by graph.senders/receivers)
|
|
30
|
+
logs = jax.vmap(M.connec.log)(graph.nodes[graph.senders], graph.nodes[graph.receivers])
|
|
31
|
+
|
|
32
|
+
return vec_times_kd(jnp.sqrt(graph.edges), logs)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def mfdg_laplace(M: Manifold, graph: jraph.GraphsTuple) -> jnp.array:
|
|
36
|
+
"""Given a graph with manifold-valued features returns the isotropic graph 2-Laplacian as defined in
|
|
37
|
+
https://arxiv.org/abs/1702.05293
|
|
38
|
+
|
|
39
|
+
:param M: feature manifold
|
|
40
|
+
:param graph: M-valued graph
|
|
41
|
+
:return: Laplace vectors at node feature
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
# multiply negative gradients with corresponding square root edge weights
|
|
45
|
+
weighted_gradients = vec_times_kd(jnp.sqrt(graph.edges), -mfdg_gradient(M, graph))
|
|
46
|
+
|
|
47
|
+
return jax.ops.segment_sum(weighted_gradients, graph.senders, num_segments=len(graph.nodes)) # already ordered
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def max_pooling(G: jraph.GraphsTuple, z: jnp.ndarray) -> jnp.array:
|
|
51
|
+
"""Graph-wise max pooling of features z over graph G.
|
|
52
|
+
|
|
53
|
+
:param G: graph
|
|
54
|
+
:param z: scalar graph features
|
|
55
|
+
:return: max value for each graph in the batch
|
|
56
|
+
"""
|
|
57
|
+
sum_n_node = tree.tree_leaves(G.nodes)[0].shape[0]
|
|
58
|
+
n_graph = G.n_node.shape[0]
|
|
59
|
+
graph_idx = jnp.arange(n_graph)
|
|
60
|
+
|
|
61
|
+
node_gr_idx = jnp.repeat(
|
|
62
|
+
graph_idx, G.n_node, axis=0, total_repeat_length=sum_n_node)
|
|
63
|
+
|
|
64
|
+
# return constant (not -inf) for graphs without edges as these can appear through batching
|
|
65
|
+
return jraph.segment_max_or_constant(z, node_gr_idx, n_graph, indices_are_sorted=True)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def mean_pooling(G: jraph.GraphsTuple, z: jnp.ndarray) -> jnp.array:
|
|
69
|
+
"""Graph-wise mean pooling of features z over graph G.
|
|
70
|
+
|
|
71
|
+
:param G: graph
|
|
72
|
+
:param z: scalar graph features
|
|
73
|
+
:return: mean value for each graph in the batch
|
|
74
|
+
"""
|
|
75
|
+
sum_n_node = tree.tree_leaves(G.nodes)[0].shape[0]
|
|
76
|
+
n_graph = G.n_node.shape[0]
|
|
77
|
+
graph_idx = jnp.arange(n_graph)
|
|
78
|
+
|
|
79
|
+
node_gr_idx = jnp.repeat(
|
|
80
|
+
graph_idx, G.n_node, axis=0, total_repeat_length=sum_n_node)
|
|
81
|
+
|
|
82
|
+
return jax.ops.segment_sum(z, node_gr_idx, n_graph, indices_are_sorted=True) / jnp.clip(G.n_node, 1).reshape((n_graph,) + (1,)*(z.ndim-1))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def in_degree_centrality(G: jraph.GraphsTuple) -> float:
|
|
86
|
+
""" Normalized in-degree centrality
|
|
87
|
+
|
|
88
|
+
"""
|
|
89
|
+
def f(n: int):
|
|
90
|
+
return jnp.count_nonzero(G.receivers == n)
|
|
91
|
+
|
|
92
|
+
d = jax.vmap(f)(jnp.arange(G.n_node[0]))
|
|
93
|
+
|
|
94
|
+
return d / jnp.max(d)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def out_degree_centrality(G: jraph.GraphsTuple) -> float:
|
|
98
|
+
""" Normalized out-degree centrality
|
|
99
|
+
|
|
100
|
+
"""
|
|
101
|
+
def f(n: int):
|
|
102
|
+
return jnp.count_nonzero(G.senders == n)
|
|
103
|
+
|
|
104
|
+
d = jax.vmap(f)(jnp.arange(G.n_node[0]))
|
|
105
|
+
|
|
106
|
+
return d / jnp.max(d)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def atleast_kd(array, k) -> jnp.array:
|
|
110
|
+
"""Make array at least k-dimensional"""
|
|
111
|
+
array = jnp.asarray(array)
|
|
112
|
+
new_shape = array.shape + (1,) * (k - array.ndim)
|
|
113
|
+
return array.reshape(new_shape)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def vec_times_kd(vec: jnp.array, tensor: jnp.array) -> jnp.array:
|
|
117
|
+
"""Multiply the i-th slice (along first axis) of a tensor with the i-th element of a given vector
|
|
118
|
+
|
|
119
|
+
The vector can be 2-dimensional as long as one of the dimensions is of size one, i.e, it is a proper vector.
|
|
120
|
+
|
|
121
|
+
Attention: non-jitable with asserts
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
return atleast_kd(vec, len(tensor.shape)) * tensor
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
################################################################################
|
|
2
|
+
# #
|
|
3
|
+
# This file is part of the Morphomatics library #
|
|
4
|
+
# see https://github.com/morphomatics/morphomatics #
|
|
5
|
+
# #
|
|
6
|
+
# Copyright (C) 2024 Zuse Institute Berlin #
|
|
7
|
+
# #
|
|
8
|
+
# Morphomatics is distributed under the terms of the MIT License. #
|
|
9
|
+
# see $MORPHOMATICS/LICENSE #
|
|
10
|
+
# #
|
|
11
|
+
################################################################################
|
|
12
|
+
|
|
13
|
+
# Abstract classes for manifolds
|
|
14
|
+
from .lie_group import LieGroup
|
|
15
|
+
from .connection import Connection
|
|
16
|
+
from .metric import Metric
|
|
17
|
+
from .manifold import Manifold
|
|
18
|
+
|
|
19
|
+
from. power_manifold import PowerManifold
|
|
20
|
+
from. product_manifold import ProductManifold
|
|
21
|
+
|
|
22
|
+
# Standard manifolds
|
|
23
|
+
from .euclidean import Euclidean
|
|
24
|
+
from .gl_p_n import GLpn
|
|
25
|
+
from .so_3 import SO3
|
|
26
|
+
from .se_3 import SE3
|
|
27
|
+
from .spd import SPD
|
|
28
|
+
from .sphere import Sphere
|
|
29
|
+
from .hyperbolic_space import HyperbolicSpace
|
|
30
|
+
from .grassmann import Grassmann
|
|
31
|
+
from .tangent_bundle import TangentBundle
|
|
32
|
+
|
|
33
|
+
# PyManopt Wrapper for manifolds
|
|
34
|
+
from .manopt_wrapper import ManoptWrap
|
|
35
|
+
|
|
36
|
+
# Shape spaces
|
|
37
|
+
from .shape_space import ShapeSpace
|
|
38
|
+
from .fundamental_coords import FundamentalCoords
|
|
39
|
+
from .differential_coords import DifferentialCoords
|
|
40
|
+
from .point_distribution_model import PointDistributionModel
|
|
41
|
+
from .gl_p_coords import GLpCoords
|
|
42
|
+
from .kendall import Kendall
|
|
43
|
+
|
|
44
|
+
# Space of shape trajectories
|
|
45
|
+
from .bezierfold import Bezierfold
|
|
46
|
+
from .cubic_bezierfold import CubicBezierfold
|