Notebook source code:
notebooks/how_to/13_rematching.ipynb
Run it yourself on binder
How to use ReMatching to compute a functional map?#
In [ ]:
import geomstats.backend as gs
from geomfum.dataset import NotebooksDataset
from geomfum.refine import ZoomOut
from geomfum.shape import TriangleMesh
from geomfum.shape.hierarchical import HierarchicalMesh
In [2]:
dataset = NotebooksDataset()
mesh_a = TriangleMesh.from_file(dataset.get_filename("cat-00"))
mesh_b = TriangleMesh.from_file(dataset.get_filename("lion-00"))
(mesh_a.n_vertices, mesh_a.n_faces), (mesh_b.n_vertices, mesh_b.n_faces)
INFO: Data has already been downloaded... using cached file ('C:\Users\giuli\.geomfum\data\cat-00.off').
INFO: Data has already been downloaded... using cached file ('C:\Users\giuli\.geomfum\data\lion-00.off').
Out [2]:
((7207, 14410), (5000, 9996))
Create hierarchical meshes.
In [3]:
hmesh_a = HierarchicalMesh.from_registry(mesh_a, min_n_samples=1000)
hmesh_b = HierarchicalMesh.from_registry(mesh_b, min_n_samples=1000)
(
(hmesh_a.low.n_vertices, hmesh_a.low.n_faces),
(hmesh_b.low.n_vertices, hmesh_b.low.n_faces),
)
C:\Users\giuli\OneDrive\Research\geomfum_proj\geomfum\geomfum\wrap\pyrmt.py:69: UserWarning: The given NumPy array is not writable, and PyTorch does not support non-writable tensors. This means writing to this tensor will result in undefined behavior. You may want to copy the array to protect its data or make it writable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at C:\actions-runner\_work\pytorch\pytorch\pytorch\torch\csrc\utils\tensor_numpy.cpp:209.)
return TriangleMesh(gs.asarray(rlow.vertices), gs.asarray(rlow.triangles))
Out [3]:
((1004, 2004), (1021, 2038))
Set Laplace eigenbasis for each low-resolution mesh.
In [4]:
hmesh_a.low.laplacian.find_spectrum(spectrum_size=10, set_as_basis=True)
hmesh_b.low.laplacian.find_spectrum(spectrum_size=10, set_as_basis=True)
hmesh_a.low.basis.use_k = 6
hmesh_b.low.basis.use_k = 5
C:\Users\giuli\OneDrive\Research\geomfum_proj\geomfum\geomfum\_backend\pytorch\sparse.py:22: UserWarning: Sparse CSC tensor support is in beta state. If you miss a functionality in the sparse tensor support, please submit a feature request to https://github.com/pytorch/pytorch/issues. (Triggered internally at C:\actions-runner\_work\pytorch\pytorch\pytorch\aten\src\ATen\SparseCsrTensorImpl.cpp:55.)
return _torch.sparse_csc_tensor(ccol_indices, row_indices, values, size=array.shape)
Extend the basis for the high-resolution meshes.
In [5]:
hmesh_a.extend_basis(set_as_basis=True)
hmesh_b.extend_basis(set_as_basis=True)
(
hmesh_a.high.basis.vecs.shape,
hmesh_b.high.basis.vecs.shape,
)
Out [5]:
(torch.Size([7207, 10]), torch.Size([5000, 10]))
Assume we have a valid functional map \(C\) between hmesh_a.low
and hmesh_b.low
(which for demonstration purposes, we instantiate randomly).
In [6]:
fmap_matrix = gs.random.uniform(
size=(
hmesh_b.low.basis.spectrum_size,
hmesh_a.low.basis.spectrum_size,
)
)
fmap_matrix.shape
Out [6]:
torch.Size([5, 6])
Now, this functional map can be seamlessly used with the high-resolution meshes. For example, we can upsample it with ZoomOut.
In [7]:
upsampler = ZoomOut(nit=2, step=(2, 1))
upsampled_fmap_matrix = upsampler(
fmap_matrix,
hmesh_a.high.basis,
hmesh_b.high.basis,
)
upsampled_fmap_matrix.shape
Out [7]:
torch.Size([7, 10])
In [8]:
hmesh_a.high.basis.vecs
Out [8]:
tensor([[-1.7216, 1.6309, -1.0569, ..., 2.6765, -1.0474, -0.7150],
[-1.7216, 1.7008, -0.8650, ..., 2.8492, -1.4360, -0.5147],
[-1.7216, 1.6956, -0.8413, ..., 2.8793, -1.4352, -0.8264],
...,
[-1.7216, 5.0574, 6.8286, ..., -3.7746, 6.3645, -0.2106],
[-1.7216, 5.0638, 6.8446, ..., -3.8109, 6.4590, -0.2137],
[-1.7216, 1.6375, -1.0054, ..., 2.7148, -1.1002, -1.0103]])
NB: mesh_a
and hmesh_a.high
are the same object, so it is indiferent which one to use.