Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions .github/workflows/test-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,22 @@ jobs:
- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh

- name: Install Python dependencies
run: |
export PATH="$HOME/.cargo/bin:$PATH"
uv venv
source .venv/bin/activate
uv pip install cython setuptools

- name: Build m4ri library
run: |
export PATH="$HOME/.cargo/bin:$PATH"
source .venv/bin/activate
make build-m4ri

- name: Test package build
run: |
export PATH="$HOME/.cargo/bin:$PATH"
source .venv/bin/activate
make build
echo "✓ Build successful"
21 changes: 19 additions & 2 deletions .github/workflows/test-import.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,30 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive

- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y autoconf automake libtool m4 build-essential

- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh

- name: Create venv and test import
- name: Build m4ri library
run: |
export PATH="$HOME/.cargo/bin:$PATH"
make build-m4ri

- name: Build and install package
run: |
export PATH="$HOME/.cargo/bin:$PATH"
make build
make sync

- name: Test import
run: |
export PATH="$HOME/.cargo/bin:$PATH"
source .venv/bin/activate
uv run python -c "import scloop; print('✓ Import successful')"
python -c "import scloop; print('✓ Import successful')"
6 changes: 6 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include src/scloop/utils/linear_algebra_gf2/libm4ri.a
recursive-include src/scloop/utils/linear_algebra_gf2/include *.h
include src/scloop/utils/linear_algebra_gf2/*.pyx
include src/scloop/data/*.pyx
include src/scloop/data/*.cpp
include src/scloop/data/*.h
11 changes: 8 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,24 @@ M4RI_PREFIX := $(PROJECT_ROOT)/src/scloop/utils/linear_algebra_gf2
build-m4ri:
cd $(M4RI_SRC) && \
autoreconf -i && \
./configure --prefix=$(M4RI_PREFIX) --libdir=$(M4RI_PREFIX) --disable-static --enable-shared --enable-openmp && \
./configure --prefix=$(M4RI_PREFIX) --libdir=$(M4RI_PREFIX) \
--enable-static --disable-shared --enable-openmp \
CFLAGS="-fPIC -O3" && \
$(MAKE) && \
$(MAKE) install

build: build-m4ri
CPLUS_INCLUDE_PATH=$(PROJECT_ROOT)/src/scloop/data uv build
CFLAGS="-I$(M4RI_PREFIX)/include" \
LDFLAGS="-L$(M4RI_PREFIX) -Wl,-rpath,$(M4RI_PREFIX)" \
CPLUS_INCLUDE_PATH=$(PROJECT_ROOT)/src/scloop/data \
uv build

sync:
CPLUS_INCLUDE_PATH=$(PROJECT_ROOT)/src/scloop/data uv sync

clean:
rm -rf dist/ *.egg-info
cd $(M4RI_SRC) && $(MAKE) clean || true
rm -rf $(M4RI_PREFIX)/include $(M4RI_PREFIX)/lib*.so* $(M4RI_PREFIX)/lib*.la $(M4RI_PREFIX)/pkgconfig
rm -rf $(M4RI_PREFIX)/include $(M4RI_PREFIX)/lib*.a $(M4RI_PREFIX)/lib*.so* $(M4RI_PREFIX)/lib*.la $(M4RI_PREFIX)/pkgconfig

rebuild: clean build
36 changes: 23 additions & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
[build-system]
build-backend = "setuptools.build_meta"
requires = [ "cython", "setuptools>74.1" ]

[project]
name = "scloop"
version = "0.1.0"
Expand Down Expand Up @@ -35,18 +31,12 @@ dependencies = [
"umap-learn>=0.5.7",
]

[tool.setuptools]
package-dir = { "" = "src" }
ext-modules = [
{ name = "scloop.data.ripser_lib", sources = [
"./src/scloop/data/ripser_lib.pyx",
"./src/scloop/data/ripser.cpp",
], language = "c++", optional = false },
]

[tool.uv]
package = true

[tool.uv.extra-build-dependencies]
scloop = [ "Cython" ]

[tool.uv.sources]
torch = [
{ index = "pytorch-cu128", marker = "sys_platform == 'linux'" },
Expand All @@ -63,4 +53,24 @@ explicit = true

[tool.ruff]
format.indent-style = "space"
# archive
# [build-system]
# build-backend = "setuptools.build_meta"
# requires = [ "cython", "setuptools>74.1" ]

# [tool.setuptools]
# package-dir = { "" = "src" }
# ext-modules = [
# { name = "scloop.data.ripser_lib", sources = [
# "./src/scloop/data/ripser_lib.pyx",
# "./src/scloop/data/ripser.cpp",
# ], language = "c++", optional = false },
# { name = "scloop.utils.linear_algebra_gf2.m4ri_lib", sources = [
# "./src/scloop/utils/linear_algebra_gf2/m4ri_lib.pyx",
# ], language = "c", optional = false, libraries = ["m4ri"], extra-objects = [
# "./src/scloop/utils/linear_algebra_gf2/libm4ri.a",
# ], include-dirs = [
# "./src/scloop/utils/linear_algebra_gf2/include",
# ] },
# ]
format.quote-style = "double"
25 changes: 25 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from setuptools import setup, Extension
from Cython.Build import cythonize
import os

project_root = os.path.dirname(os.path.abspath(__file__))
m4ri_dir = os.path.join(project_root, "src/scloop/utils/linear_algebra_gf2")

extensions = [
Extension(
"scloop.data.ripser_lib",
sources=["./src/scloop/data/ripser_lib.pyx", "./src/scloop/data/ripser.cpp"],
language="c++",
include_dirs=["./src/scloop/data"],
),
Extension(
"scloop.utils.linear_algebra_gf2.m4ri_lib",
sources=["./src/scloop/utils/linear_algebra_gf2/m4ri_lib.pyx"],
include_dirs=[os.path.join(m4ri_dir, "include")],
extra_objects=[os.path.join(m4ri_dir, "libm4ri.a")],
extra_compile_args=["-fopenmp"],
extra_link_args=["-fopenmp"],
),
]

setup(ext_modules=cythonize(extensions, compiler_directives={"language_level": "3"}))
4 changes: 4 additions & 0 deletions src/scloop/data/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

warnings.filterwarnings("ignore", category=RuntimeWarning)


def subsample(
x: np.ndarray,
n: int,
Expand All @@ -35,6 +36,7 @@ def subsample(
pass
pw_dist = pdist(x)


def edge_idx_encode(i, j, n_vertices, self_edge=True):
if i > j:
i, j = j, i
Expand All @@ -44,6 +46,7 @@ def edge_idx_encode(i, j, n_vertices, self_edge=True):
else:
return i * n_vertices - i * (i + 1) // 2 + (j - i - 1)


def trig_idx_encode(i, j, k, n_vertices, self_edge=True):
i, j, k = sorted([i, j, k])
# // make sure it returns integer
Expand Down Expand Up @@ -299,6 +302,7 @@ def disk_2d_two_holes(r, r1, r2, c1_x, c1_y, c2_x, c2_y, n_points, noise, seed):
y = y[idx_keep] + np.random.normal(0, noise, n_points)
return (x, y)


# # TODO: grid search, adjust radius based on gaussian prior
# # TODO: generate a set of representative loops through custom distance function
# # TODO: pair up loops from two sets though frechet distance and do regression based matching
Expand Down
1 change: 1 addition & 0 deletions src/scloop/utils/linear_algebra_gf2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .m4ri_lib import solve_gf2
Loading