Usage#
This page provides comprehensive usage examples for GeomFuM, referencing our interactive notebook tutorials.
Quick Start#
The best way to learn GeomFuM is through our interactive notebook tutorials. Start with:
Loading Meshes - notebooks/how_to/00_load_mesh_from_file.ipynb
Laplace-Beltrami Operator - notebooks/how_to/01_mesh_laplacian.ipynb
Functional Maps - notebooks/how_to/07_functional_map.ipynb
Basic Usage Examples#
Here are some key code snippets from our tutorials:
Loading and Working with Meshes#
From notebooks/how_to/00_load_mesh_from_file.ipynb:
from geomfum.dataset import NotebooksDataset
from geomfum.shape import TriangleMesh
# Load a mesh
dataset = NotebooksDataset()
mesh = TriangleMesh.from_file(dataset.get_filename("cat-00"))
print(f"Mesh: {mesh.n_vertices} vertices, {mesh.n_faces} faces")
Computing Laplace-Beltrami Spectrum#
From notebooks/how_to/02_mesh_laplacian_spectrum.ipynb:
# Compute eigenfunctions and eigenvalues
mesh.laplacian.find_spectrum(spectrum_size=50, set_as_basis=True)
# Access the basis
eigenfunctions = mesh.basis.vecs
eigenvalues = mesh.basis.vals
print(f"Computed {len(eigenvalues)} eigenfunctions")
Computing Shape Descriptors#
From notebooks/how_to/03_descriptors.ipynb:
from geomfum.descriptor.spectral import HeatKernelSignature, WaveKernelSignature
# Heat Kernel Signature
hks = HeatKernelSignature(n_domain=4)
hks_descriptors = hks(mesh)
# Wave Kernel Signature
wks = WaveKernelSignature(n_domain=3)
wks_descriptors = wks(mesh)
Creating Descriptor Pipelines#
From notebooks/how_to/04_descriptor_pipeline.ipynb:
from geomfum.descriptor.spectral import HeatKernelSignature, LandmarkHeatKernelSignature
from geomfum.descriptor.pipeline import DescriptorPipeline, ArangeSubsampler, L2InnerNormalizer
steps = [
HeatKernelSignature(n_domain=4),
LandmarkHeatKernelSignature(n_domain=4),
ArangeSubsampler(subsample_step=2),
WaveKernelSignature(n_domain=3),
L2InnerNormalizer(),
]
pipeline = DescriptorPipeline(steps)
descriptors = pipeline.apply(mesh)
Computing Functional Maps#
From notebooks/how_to/07_functional_map.ipynb:
from geomfum.functional_map import FactorSum, LBCommutativityEnforcing, SpectralDescriptorPreservation
from geomfum.numerics.optimization import ScipyMinimize
# Set up basis for both meshes
mesh_a.laplacian.find_spectrum(spectrum_size=10, set_as_basis=True)
mesh_b.laplacian.find_spectrum(spectrum_size=10, set_as_basis=True)
# Compute descriptors
descr_a = pipeline.apply(mesh_a)
descr_b = pipeline.apply(mesh_b)
# Create objective function
factors = [
SpectralDescriptorPreservation(
mesh_a.basis.project(descr_a),
mesh_b.basis.project(descr_b),
weight=1.0,
),
LBCommutativityEnforcing.from_bases(
mesh_a.basis, mesh_b.basis, weight=1e-2,
),
]
objective = FactorSum(factors)
# Optimize
optimizer = ScipyMinimize(method="L-BFGS-B")
x0 = gs.zeros((mesh_b.basis.spectrum_size, mesh_a.basis.spectrum_size))
res = optimizer.minimize(objective, x0, fun_jac=objective.gradient)
fmap = res.x.reshape(x0.shape)
Converting to Pointwise Correspondences#
From notebooks/how_to/10_pointwise_from_functional.ipynb:
from geomfum.convert import P2pFromFmConverter
converter = P2pFromFmConverter()
correspondences = converter(fmap, mesh_a, mesh_b)
print(f"Computed {len(correspondences)} correspondences")
Refining Functional Maps#
From notebooks/how_to/15_refine_functional_map.ipynb:
from geomfum.refine import ZoomOutRefiner
# Apply ZoomOut refinement
zoomout = ZoomOutRefiner()
refined_fmap = zoomout(fmap, mesh_a, mesh_b)
# Convert refined map to correspondences
refined_correspondences = converter(refined_fmap, mesh_a, mesh_b)
Advanced Techniques#
Rematching Algorithm#
From notebooks/how_to/13_rematching.ipynb:
from geomfum.shape.hierarchical import HierarchicalMesh
# Apply Rematching
hmesh_a = HierarchicalMesh.from_registry(mesh_a, min_n_samples=1000)
hmesh_a.low.n_vertices, hmesh_a.low.n_faces
Deep Functional Maps#
From notebooks/how_to/14_deep_functional_maps_models.ipynb:
from geomfum.descriptor.learned import FeatureExtractor
from geomfum.forward_functional_map import ForwardFunctionalMap
from geomfum.learning.models import FMNet
functional_map_model = FMNet(
feature_extractor=FeatureExtractor.from_registry(which="diffusionnet"))
with torch.no_grad():
output = functional_map_model(mesh_a, mesh_b, as_dict=True)
fmap12, fmap21 = output["fmap12"], output["fmap21"]
Neural Adjoint Maps#
From notebooks/how_to/18_neural_adjoint_maps.ipynb:
from geomfum.convert import NamFromP2pConverter
mesh_a.basis.use_k = 10
mesh_b.basis.use_k = 10
nam_converter = NamFromP2pConverter(device="cpu")
nam = nam_converter(p2p, mesh_a.basis, mesh_b.basis)
Visualization#
Basic Visualization#
From notebooks/how_to/16_vis_basic.ipynb:
from geomfum.plot import MeshPlotter
plotter = MeshPlotter()
plotter.add_mesh(mesh_a)
plotter.show()
Interactive Learning#
For the best learning experience:
Follow the notebook tutorials in order
Run each cell to see the outputs
Modify parameters to experiment
Try your own data by changing file paths
Use the links at the end of each notebook to navigate
All examples in this page are taken from our actual working notebooks. For complete, runnable examples with outputs and visualizations, see the Notebook Tutorials section.
Next Steps#
Now that you understand the basic usage patterns:
Explore the notebooks - Follow the interactive tutorials
Read the concepts - Understand the theoretical foundations
Check the API - Reference the complete API documentation
Join the community - Visit our Discord server
For questions and issues, visit our GitHub repository.