Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
9674fd8
Refactor vectorized ECT calculation for efficiency
yemeen Jan 13, 2025
a563150
Merge branch 'main' of https://github.com/MunchLab/ect into vectorize…
yemeen Jan 13, 2025
ccfca93
Add optimized numba parallel threshold computation
yemeen Jan 13, 2025
6e7403b
Merge branch 'main' of https://github.com/MunchLab/ect into vectorize…
yemeen Jan 15, 2025
5efffe5
Merge branch 'benchmarks' of https://github.com/MunchLab/ect into vec…
yemeen Jan 15, 2025
14fa662
Merge branch 'benchmarks' of https://github.com/MunchLab/ect into vec…
yemeen Jan 15, 2025
e513518
Update method names and variables to follow snake_case and remove
yemeen Jan 15, 2025
7b19993
Merge branch 'main' of https://github.com/MunchLab/ect into vectorize…
yemeen Jan 21, 2025
68a5226
Refactor graph embedding calculations for efficiency
yemeen Jan 21, 2025
4277039
Add class for managing ECT direction vectors
yemeen Jan 22, 2025
5b6bcad
Start 3d mods to embed
yemeen Jan 24, 2025
01e419a
Refactor EmbeddedGraph class for better structure
yemeen Jan 28, 2025
7bed36c
Add EmbeddedGraph class with coordinate transformation methods
yemeen Jan 29, 2025
3173d43
Update node management and coordinate validation
yemeen Feb 4, 2025
0255211
Remove unnecessary function create_example_cw
yemeen Feb 4, 2025
a5a67e0
Update direction sampling strategy and ECT calculation
yemeen Feb 8, 2025
13cc6a6
Start separating into ECTResults class and fix ECT not working for CWs
yemeen Feb 11, 2025
1de92dc
add smooth function to ECTResult
yemeen Mar 10, 2025
db2f70f
Update graph operations and ECC calculation
yemeen Mar 11, 2025
085506f
fix tests to work with new structure, add directions and results test…
yemeen Mar 13, 2025
0995f82
start sklearn estimator implement
yemeen Mar 13, 2025
4f06b08
Refactor ECT class with simpler initialization, fix test failures,
yemeen Mar 30, 2025
8a74d1e
add new tutorials
yemeen Mar 30, 2025
b0209f2
run make clean
yemeen Mar 30, 2025
2c5302a
Refactor ECT class methods for better readability
yemeen Mar 30, 2025
ff6e42a
make html
yemeen Mar 30, 2025
3f309b0
Merge main: Resolve conflicts favoring rewritten code
yemeen Mar 30, 2025
d035e04
rebuild docs
yemeen Mar 30, 2025
931fc5c
Update required Python version to >=3.10
yemeen Mar 30, 2025
b71f237
Update Python versions in workflow matrix
yemeen Mar 30, 2025
fd2088c
rework threshold logic and fix tutorials
yemeen Apr 7, 2025
3e2705e
add to the graph tutorial displaying custom directions and thresholds
yemeen Apr 7, 2025
9670cc7
fix matisse tutorial
yemeen Apr 7, 2025
e68a370
remove old tutorials
yemeen Apr 7, 2025
5366040
fix tests for new bounding radius logic
yemeen Apr 7, 2025
6c74f09
Update autopep8 directory path in Makefile
yemeen Apr 7, 2025
20d7253
improve tutorial with directions and threshold property of ECTResult
yemeen Apr 7, 2025
4eb89c3
remove unused imports
yemeen Apr 7, 2025
6320eae
add docs, fix cw tutorial error, make clean
yemeen Apr 8, 2025
5b43f64
Update tests for creating faces
yemeen Apr 8, 2025
e3ce61b
Fixed up docs stuff
lizliz Apr 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.10", "3.11"]

steps:
- uses: actions/checkout@v4
Expand Down
79 changes: 79 additions & 0 deletions Extra_Notebooks/Mesh.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1 0\n",
"4 5\n",
"9 8\n",
"10 1\n"
]
}
],
"source": [
"from CGAL.CGAL_Kernel import Point_2\n",
"from CGAL.CGAL_Triangulation_2 import Triangulation_2\n",
"from CGAL.CGAL_Triangulation_2 import Triangulation_2_Vertex_circulator\n",
"from CGAL.CGAL_Triangulation_2 import Triangulation_2_Vertex_handle\n",
"\n",
"points=[]\n",
"points.append( Point_2(1,0) )\n",
"points.append( Point_2(3,2) )\n",
"points.append( Point_2(4,5) )\n",
"points.append( Point_2(9,8) )\n",
"points.append( Point_2(7,4) )\n",
"points.append( Point_2(5,2) )\n",
"points.append( Point_2(6,3) )\n",
"points.append( Point_2(10,1) )\n",
" \n",
"t=Triangulation_2()\n",
"t.insert(points)\n",
"\n",
"vc = t.incident_vertices(t.infinite_vertex())\n",
"\n",
"if vc.hasNext():\n",
" done = vc.next();\n",
" iter=Triangulation_2_Vertex_handle()\n",
" while(1):\n",
" iter=vc.next()\n",
" print (iter.point())\n",
" if iter == done:\n",
" break\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"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.7"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
1,891 changes: 1,891 additions & 0 deletions Extra_Notebooks/Playing_with_Spirals.ipynb

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ reqs:

clean:
# Running autopep8
@autopep8 -r --in-place ect/
@autopep8 -r --in-place src/ect/

tests:
# Running unittests
Expand Down Expand Up @@ -41,4 +41,9 @@ all:
@make html

# Running unittests
@make tests
@make tests



develop:
pip install -e .
13 changes: 7 additions & 6 deletions benchmarks/benchmark_cw.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Benchmarks for CW complex computations"""
import numpy as np
import time
from ect import ECT, EmbeddedCW, create_example_cw
from ect import ECT
from ect.utils.examples import create_example_cw
import json
from pathlib import Path

Expand All @@ -11,9 +12,9 @@ def benchmark_cw_ect(num_runs=5):
results = {}

configs = [
(8, 10), # Small
(36, 36), # Medium
(360, 360), # Large
(8, 10),
(36, 36),
(360, 360),
]

for num_dir, num_thresh in configs:
Expand All @@ -26,7 +27,7 @@ def benchmark_cw_ect(num_runs=5):
start_time = time.time()

myect = ECT(num_dirs=num_dir, num_thresh=num_thresh)
myect.calculateECT(K)
myect.calculate(K)

execution_time = time.time() - start_time
times.append(execution_time)
Expand All @@ -45,7 +46,7 @@ def benchmark_cw_ect(num_runs=5):
print("Running CW complex benchmarks...")
results = benchmark_cw_ect()

# Save results

output_dir = Path("benchmark_results")
output_dir.mkdir(exist_ok=True)

Expand Down
33 changes: 10 additions & 23 deletions benchmarks/benchmark_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,20 @@ def benchmark_graph_ect(num_runs=5):
"""Benchmark ECT computation on graphs"""
results = {}

# Warmup run to trigger JIT compilation
warmup_shape = create_test_shape(100, 1)
G_warmup = EmbeddedGraph()
G_warmup.add_cycle(warmup_shape)
myect = ECT(num_dirs=360, num_thresh=360)
myect.calculate(G_warmup) # Warmup run

configs = [
(100, 1),
(1000, 1),
(100, 3),
(1000, 3),
(10000, 3),
(100000, 5),
]

for points, complexity in configs:
Expand All @@ -41,7 +49,7 @@ def benchmark_graph_ect(num_runs=5):
for _ in range(num_runs):
start_time = time.time()
myect = ECT(num_dirs=360, num_thresh=360)
myect.calculateECT(G)
myect.calculate(G)
times.append(time.time() - start_time)

results[f'points_{points}_complexity_{complexity}'] = {
Expand All @@ -50,30 +58,9 @@ def benchmark_graph_ect(num_runs=5):
'min_time': float(np.min(times)),
'max_time': float(np.max(times))
}
print(results)

return results


def benchmark_g_omega(num_runs=5):
"""Benchmark g_omega computation"""
results = {}

sizes = [100, 500, 1000]
for size in sizes:
shape = create_test_shape(size)
G = EmbeddedGraph()
G.add_cycle(shape)

times = []
for _ in range(num_runs):
start_time = time.time()
for theta in np.linspace(0, 2*np.pi, 360):
G.g_omega(theta)
times.append(time.time() - start_time)

results[f'size_{size}'] = {
'mean_time': float(np.mean(times)),
'std_time': float(np.std(times))
}

return results
5 changes: 2 additions & 3 deletions benchmarks/run_benchmarks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import time
from pathlib import Path
import json
from benchmark_graph import benchmark_graph_ect, benchmark_g_omega
from benchmark_graph import benchmark_graph_ect
from benchmark_cw import benchmark_cw_ect
import platform

Expand All @@ -26,8 +26,7 @@ def run_all_benchmarks(num_runs=5):
print("\nRunning CW complex benchmarks...")
results['benchmarks']['cw_ect'] = benchmark_cw_ect(num_runs=num_runs)

print("\nRunning g_omega benchmarks...")
results['benchmarks']['g_omega'] = benchmark_g_omega(num_runs=num_runs)


return results

Expand Down
389 changes: 389 additions & 0 deletions doc_source/notebooks/Matisse/example_matisse.ipynb

Large diffs are not rendered by default.

381 changes: 0 additions & 381 deletions doc_source/notebooks/Tutorial-ECT_for_CW_Complexes.ipynb

This file was deleted.

623 changes: 0 additions & 623 deletions doc_source/notebooks/Tutorial-ECT_for_embedded_graphs.ipynb

This file was deleted.

374 changes: 374 additions & 0 deletions doc_source/notebooks/tutorial_cw.ipynb

Large diffs are not rendered by default.

74 changes: 74 additions & 0 deletions doc_source/notebooks/tutorial_cw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# %% [markdown]
# # Tutorial: ECT for CW complexes
#
# This tutorial walks you through how to build a CW complex with the `EmbeddedCW` class, and then use the `ECT` class to compute the Euler characteristic transform

# %%
from ect import ECT, EmbeddedCW
from ect.utils.examples import create_example_cw
import numpy as np

# %% [markdown]
# The CW complex is the same as the `EmbeddedGraph` class with that additional ability to add faces. Faces are added by passing in a list of vertices. Note that we are generally assuming that these vertices follow around an empty region (as in, no other vertex is in the interior) in the graph bounded by the vertices, and further that all edges are already included in the graph. However the class does not yet check for this so you need to be careful!

# %%
K = EmbeddedCW()

# Add vertices with coordinates
K.add_node("A", [0, 0])
K.add_node("B", [1, 0])
K.add_node("C", [1, 1])
K.add_node("D", [0, 1])

# Add edges to form a square
K.add_edges_from([("A", "B"), ("B", "C"), ("C", "D"), ("D", "A")])

# Add the square face
K.add_face(["A", "B", "C", "D"])

K.center_coordinates()
K.plot()

# %% [markdown]
# Just to have something a bit more interesting, let's make a more complicated example that's built into the class.

# %%
K = create_example_cw()
K.plot(bounding_circle=True)


# %% [markdown]
# As with the `EmbeddedGraph` class, we can initialize the `ECT` class by deciding how many directions and how many thresholds to use.

# %%
ect = ECT(num_dirs=100, num_thresh=80)

# %% [markdown]
# Then we can compute the ECC for a single direction. In this case, the $x$-axis will be computed for the `num_thresh=80` stopping points in the interval $[-1.2r,1.2r]$ where $r$ is the minimum bounding radius for the input complex.

# %%
result = ect.calculate(K, theta=0)
result.plot()

# %% [markdown]
# But of course it's easier to see this in a plot. This command calculates the ECC and immediately plots it.

# %%
# Set bounding radius to control threshold range
radius = K.get_bounding_radius()
ect.set_bounding_radius(1.2 * radius)

# %% [markdown]
# Similarly, we can compute the ECT and return the matrix. We make sure to internally set the bounding radius to use to control the $y$ axis of the plot.

# %%
result = ect.calculate(K)
result.plot()

# %% [markdown]
# We can also look at the Smooth ECT:

# %%
# Calculate SECT and plot
smooth = result.smooth()
smooth.plot()
791 changes: 791 additions & 0 deletions doc_source/notebooks/tutorial_graph.ipynb

Large diffs are not rendered by default.

Loading