{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# How to use [ReMatching](https://arxiv.org/abs/2305.09274]) to compute a functional map?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import geomstats.backend as gs\n", "from geomfum.dataset import NotebooksDataset\n", "from geomfum.refine import ZoomOut\n", "from geomfum.shape import TriangleMesh\n", "from geomfum.shape.hierarchical import HierarchicalMesh" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Load meshes](00_load_mesh_from_file.ipynb)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO: Data has already been downloaded... using cached file ('C:\\Users\\giuli\\.geomfum\\data\\cat-00.off').\n", "INFO: Data has already been downloaded... using cached file ('C:\\Users\\giuli\\.geomfum\\data\\lion-00.off').\n" ] }, { "data": { "text/plain": [ "((7207, 14410), (5000, 9996))" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dataset = NotebooksDataset()\n", "\n", "mesh_a = TriangleMesh.from_file(dataset.get_filename(\"cat-00\"))\n", "mesh_b = TriangleMesh.from_file(dataset.get_filename(\"lion-00\"))\n", "\n", "(mesh_a.n_vertices, mesh_a.n_faces), (mesh_b.n_vertices, mesh_b.n_faces)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create [hierarchical meshes](./11_hierarchical_mesh.ipynb)." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "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.)\n", " return TriangleMesh(gs.asarray(rlow.vertices), gs.asarray(rlow.triangles))\n" ] }, { "data": { "text/plain": [ "((1004, 2004), (1021, 2038))" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "hmesh_a = HierarchicalMesh.from_registry(mesh_a, min_n_samples=1000)\n", "hmesh_b = HierarchicalMesh.from_registry(mesh_b, min_n_samples=1000)\n", "\n", "(\n", " (hmesh_a.low.n_vertices, hmesh_a.low.n_faces),\n", " (hmesh_b.low.n_vertices, hmesh_b.low.n_faces),\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Set Laplace eigenbasis](./02_mesh_laplacian_spectrum.ipynb) for each low-resolution mesh." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "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.)\n", " return _torch.sparse_csc_tensor(ccol_indices, row_indices, values, size=array.shape)\n" ] } ], "source": [ "hmesh_a.low.laplacian.find_spectrum(spectrum_size=10, set_as_basis=True)\n", "hmesh_b.low.laplacian.find_spectrum(spectrum_size=10, set_as_basis=True)\n", "\n", "hmesh_a.low.basis.use_k = 6\n", "hmesh_b.low.basis.use_k = 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Extend the basis for the high-resolution meshes." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(torch.Size([7207, 10]), torch.Size([5000, 10]))" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "hmesh_a.extend_basis(set_as_basis=True)\n", "hmesh_b.extend_basis(set_as_basis=True)\n", "\n", "(\n", " hmesh_a.high.basis.vecs.shape,\n", " hmesh_b.high.basis.vecs.shape,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Assume we have a [valid functional map](./07_functional_map.ipynb) $C$ between `hmesh_a.low` and `hmesh_b.low` (which for demonstration purposes, we instantiate randomly)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "torch.Size([5, 6])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fmap_matrix = gs.random.uniform(\n", " size=(\n", " hmesh_b.low.basis.spectrum_size,\n", " hmesh_a.low.basis.spectrum_size,\n", " )\n", ")\n", "\n", "fmap_matrix.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, this functional map can be seamlessly used with the high-resolution meshes. For example, we can [upsample it with ZoomOut](./15_refine_functional_map.ipynb)." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "torch.Size([7, 10])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "upsampler = ZoomOut(nit=2, step=(2, 1))\n", "\n", "upsampled_fmap_matrix = upsampler(\n", " fmap_matrix,\n", " hmesh_a.high.basis,\n", " hmesh_b.high.basis,\n", ")\n", "\n", "upsampled_fmap_matrix.shape" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([[-1.7216, 1.6309, -1.0569, ..., 2.6765, -1.0474, -0.7150],\n", " [-1.7216, 1.7008, -0.8650, ..., 2.8492, -1.4360, -0.5147],\n", " [-1.7216, 1.6956, -0.8413, ..., 2.8793, -1.4352, -0.8264],\n", " ...,\n", " [-1.7216, 5.0574, 6.8286, ..., -3.7746, 6.3645, -0.2106],\n", " [-1.7216, 5.0638, 6.8446, ..., -3.8109, 6.4590, -0.2137],\n", " [-1.7216, 1.6375, -1.0054, ..., 2.7148, -1.1002, -1.0103]])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "hmesh_a.high.basis.vecs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NB: `mesh_a` and `hmesh_a.high` are the same object, so it is indiferent which one to use." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Further reading\n", "\n", "* [How to compute a functional map?](./functional_map.ipynb)\n", "\n", "* [How to refine a functional map?](./15_refine_functional_map.ipynb)" ] } ], "metadata": { "kernelspec": { "display_name": "VENV", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.8" }, "requires": [ "rematching" ] }, "nbformat": 4, "nbformat_minor": 2 }