Notebook source code: notebooks/how_to/15_refine_functional_map.ipynb
Run it yourself on binder Binder badge

How to refine a functional map?#

 In [ ]:
import geomstats.backend as gs

from geomfum.dataset import NotebooksDataset
from geomfum.refine import (
    FastSinkhornFilters,
    IcpRefiner,
    ZoomOut,
)
from geomfum.shape import TriangleMesh

Load meshes.

 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_b.n_vertices
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, 5000)

Set Laplace eigenbasis for each mesh.

 In [3]:
mesh_a.laplacian.find_spectrum(spectrum_size=10, set_as_basis=True)
mesh_b.laplacian.find_spectrum(spectrum_size=10, set_as_basis=True)

mesh_a.basis.use_k = 6
mesh_b.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)

Assume we have a valid functional map \(C\) between mesh_a and mesh_b (which for demonstration purposes, we instantiate randomly).

 In [4]:
fmap_matrix = gs.random.uniform(
    size=(mesh_b.basis.spectrum_size, mesh_a.basis.spectrum_size)
)

fmap_matrix.shape
 Out [4]:
torch.Size([5, 6])

Refine functional map using ICP algorithm (see OCSBG2012).

 In [5]:
icp = IcpRefiner(nit=10, atol=1e-4)

icp_fmap_matrix = icp(fmap_matrix, mesh_a.basis, mesh_b.basis)

icp_fmap_matrix.shape
 Out [5]:
torch.Size([5, 6])

Refine functional map using ZoomOut (see MRRSWO2019).

 In [6]:
zoomout = ZoomOut(nit=2, step=(2, 1))

zoomout_fmap_matrix_ = zoomout(fmap_matrix, mesh_a.basis, mesh_b.basis)

zoomout_fmap_matrix_.shape
 Out [6]:
torch.Size([7, 10])

Refine functional map using fast Sinkhorn filters (see PRMWO2021).

 In [7]:
fast_sinkhorn_filters = FastSinkhornFilters(nit=2, step=(2, 1))

fast_sinkhorn_filters_fmap_matrix_ = fast_sinkhorn_filters(
    fmap_matrix, mesh_a.basis, mesh_b.basis
)

fast_sinkhorn_filters_fmap_matrix_.shape
 Out [7]:
torch.Size([7, 10])

Pointwise and functional converters can be easily controlled through p2p_from_fm_converter and fm_from_p2p_converter (sensible defaults are used.)

Further reading#