Skip to content

Commit

Permalink
Added basic example notebook.
Browse files Browse the repository at this point in the history
  • Loading branch information
ErnstRoell committed Jul 1, 2024
1 parent 1a228bb commit e60377c
Show file tree
Hide file tree
Showing 2 changed files with 391 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ of a vector given an index vector.

## Usage

For example usage, we provide the `example.ipynb` file and the code therein reproduces the
For example usage, we provide the `notebooks/example.ipynb` file and the code therein reproduces the
ECT of the gif of this readme.
The code is provided on an as is basis. You are cordially invited to both contribute and
provide feedback. Do not hesitate to contact us.
Expand Down
390 changes: 390 additions & 0 deletions notebooks/example.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,390 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import torch \n",
"import torch_geometric\n",
"from torch_geometric.data import Data"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import matplotlib_inline"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# Basic dataset with three points,three edges and one face.\n",
"points_coordinates = torch.tensor([[0.5, 0.0], [-0.5, 0.0], [0.5, 0.5]])\n",
"edge_index=torch.tensor([[0, 1, 2], [1, 2, 0]], dtype=torch.long)\n",
"face_index=torch.tensor([[0], [1], [2]], dtype=torch.long)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"# We pick a direction between 0 and 2*pi\n",
"theta = torch.tensor(0.0) \n",
"xi = torch.tensor([torch.sin(theta),torch.cos(theta)])"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([0.0000, 0.0000, 0.5000])\n"
]
}
],
"source": [
"# Next we compute the node heights as the inner product of the vertex coordinates \n",
"# and the direction.\n",
"node_heigth = points_coordinates @ xi \n",
"print(node_heigth)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([0.0000, 0.5000, 0.5000])"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# The \"height\" of each edge is defined as the maximum of the node heights of the \n",
"# vertices it is spanned by. Since the edge indices are given as tuples, we lookup the \n",
"# edge height tuples in the node heights vector (indexing is the same) and \n",
"# compute the column-wise maximum. \n",
"\n",
"edge_height_tuples = node_heigth[edge_index]\n",
"edge_height = edge_height_tuples.max(dim=0)[0]\n",
"edge_height"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([0.5000])"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# For the face heights we perform the same computation.\n",
"face_height_tuples = node_heigth[face_index]\n",
"face_height = face_height_tuples.max(dim=0)[0]\n",
"face_height"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# The two critical points are 0 and 1/2 and these are the places the ect changes. \n",
"# Below zero the ecc is zero, between 0 and 1/2 it is 2-1 = 1 (2 points 1 edges)\n",
"# and above 1/2 it is 3-3+1=1. \n",
"# We find these numbers by counting all the points edges and faces below a certain\n",
"# value. "
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([[0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [1., 1., 0.],\n",
" [1., 1., 0.],\n",
" [1., 1., 0.],\n",
" [1., 1., 0.],\n",
" [1., 1., 0.],\n",
" [1., 1., 0.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.]])\n"
]
}
],
"source": [
"# Instead of counting points, we assign each element an indicator function that \n",
"# zero below the critical point and 1 above it. \n",
"# To do so, we translate the indicator function for each point, edge and face. \n",
"\n",
"# Discretize interval in 25 steps\n",
"interval = torch.linspace(-1,1,25).view(-1,1)\n",
"\n",
"translated_nodes = interval - node_heigth \n",
"ecc_points = torch.heaviside(translated_nodes,values=torch.tensor([1.0]))\n",
"print(ecc_points)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"# Note that the 0 is at index 13 and 1/2 is at index 20. Indeed this is where \n",
"# the curves change value. \n",
"\n",
"# We do the same for the faces and edges."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([[0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.]])\n"
]
}
],
"source": [
"\n",
"\n",
"# Discretize interval in 25 steps\n",
"interval = torch.linspace(-1,1,25).view(-1,1)\n",
"\n",
"translated_edges = interval - edge_height \n",
"ecc_edges = torch.heaviside(translated_edges,values=torch.tensor([1.0]))\n",
"print(ecc_edges)"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([[0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 0., 0.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.],\n",
" [1., 1., 1.]])\n"
]
}
],
"source": [
"# Discretize interval in 25 steps\n",
"interval = torch.linspace(-1,1,25).view(-1,1)\n",
"\n",
"translated_edges = interval - edge_height \n",
"ecc_edges = torch.heaviside(translated_edges,values=torch.tensor([1.0]))\n",
"print(ecc_edges)"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tensor([[0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [0.],\n",
" [1.],\n",
" [1.],\n",
" [1.],\n",
" [1.],\n",
" [1.],\n",
" [1.],\n",
" [1.]])\n"
]
}
],
"source": [
"# Discretize interval in 25 steps\n",
"interval = torch.linspace(-1,1,25).view(-1,1)\n",
"\n",
"translated_faces = interval - face_height \n",
"ecc_faces = torch.heaviside(translated_faces,values=torch.tensor([1.0]))\n",
"print(ecc_faces)"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 1.,\n",
" 1., 1., 1., 1., 1., 1., 1.])"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# The ect along this direction is then computed by first computing the sum of\n",
"# columns in each of the three matrices and then by computing the \n",
"# alternating sum of the three matrices.\n",
"\n",
"ecc = ecc_points.sum(axis=1) - ecc_edges.sum(axis=1) + ecc_faces.sum(axis=1) \n",
"ecc"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# We can indeed verify that at index 13 the value changes from 0 to 1 (which is)\n",
"# the origin in our coordinate system."
]
}
],
"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.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

0 comments on commit e60377c

Please sign in to comment.