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
4 changes: 3 additions & 1 deletion .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ jobs:

# Used to host cibuildwheel
- uses: actions/setup-python@v5
with:
python-version: "3.13"

- name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.20.0
run: python -m pip install cibuildwheel==2.22.0

- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse
Expand Down
25 changes: 20 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,24 @@ execute_process(
COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE NB_DIR)
list(APPEND CMAKE_PREFIX_PATH "${NB_DIR}")

find_package(nanobind CONFIG REQUIRED)
find_package(Threads REQUIRED)

if(MSVC)
# Static link of MSVC rt for optimal compatibility
# It avoids to mess with embedded MSVC rt coming from other packages (see PyQT5)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
# Same, enabling LTO (LTGC for MS) give less ABI compatibility, so we dissable it.
# see https://learn.microsoft.com/en-us/cpp/porting/binary-compat-2015-2017?view=msvc-170
# for more details.
nanobind_add_module(pgeof_ext NOMINSIZE STABLE_ABI src/pgeof_ext.cpp)
else()
# we enable LTO on Linux and MacOS.
nanobind_add_module(pgeof_ext NOMINSIZE STABLE_ABI LTO src/pgeof_ext.cpp)
endif()

nanobind_add_module(pgeof_ext NOMINSIZE STABLE_ABI LTO src/pgeof_ext.cpp)
target_link_libraries(pgeof_ext PRIVATE Threads::Threads)

nanobind_add_stub(
pgeof_ext_stub
Expand All @@ -25,10 +40,10 @@ nanobind_add_stub(
DEPENDS pgeof_ext
)

# All lib are headeer only.
# it's faster to include like this than using exported targets
# All lib are header only.
# it's faster to include like this than using exported targets
# (i.e add_subdirectories(...))
target_include_directories(pgeof_ext PRIVATE "include" "third_party/eigen" "third_party/nanoflann/include" "third_party/taskflow")
target_include_directories(pgeof_ext PRIVATE "include" "third_party/eigen" "third_party/nanoflann/include" "third_party/taskflow")

install(TARGETS pgeof_ext LIBRARY DESTINATION pgeof)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pgeof_ext.pyi ${CMAKE_CURRENT_BINARY_DIR}/py.typed DESTINATION pgeof)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pgeof_ext.pyi ${CMAKE_CURRENT_BINARY_DIR}/py.typed DESTINATION pgeof)
82 changes: 42 additions & 40 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
[build-system]
requires = ["scikit-build-core >=0.4.3",
"nanobind == 2.1.0",
"typing_extensions;python_version < '3.11'"
requires = [
"scikit-build-core >=0.4.3",
"nanobind == 2.1.0",
"typing_extensions;python_version < '3.11'",
]
build-backend = "scikit_build_core.build"

[project]
name = "pgeof"
version = "0.3.0"
version = "0.3.2"
readme = "README.md"
description = "Compute the geometric features associated with each point's neighborhood:"
requires-python = ">=3.8,<3.13"
license = {file = "LICENSE"}
requires-python = ">=3.8,<3.14"
license = { file = "LICENSE" }
authors = [
{name = "Loic Landrieu", email = "loic.landrieu@enpc.fr"},
{name = "Damien Robert", email = "damien.robert@uzh.ch"}
{ name = "Loic Landrieu", email = "loic.landrieu@enpc.fr" },
{ name = "Damien Robert", email = "damien.robert@uzh.ch" },
]
keywords = ["point clouds", "features", "3D", "LiDAR"]
classifiers = [
"Development Status :: 3 - Alpha",
"Programming Language :: Python",
"Topic :: Scientific/Engineering"
]
dependencies = [
"numpy >= 1.7, < 2"
"Development Status :: 3 - Alpha",
"Programming Language :: Python",
"Topic :: Scientific/Engineering",
]
dependencies = ["numpy >= 1.7"]

[project.urls]
homepage = "https://github.com/drprojects/point_geometric_features"
Expand All @@ -42,16 +41,16 @@ cmake.build-type = "Release"
# make sdist a lot lighter by removing some useless files from third_party
# ⚠️ be sure to keep copyrights and license file
sdist.exclude = [
"third_party/eigen/bench",
"third_party/eigen/demos",
"third_party/eigen/doc",
"third_party/taskflow/3rd-party",
"third_party/taskflow/benchmarks",
"third_party/taskflow/docs",
"third_party/taskflow/doxygen",
"third_party/taskflow/examples",
"third_party/taskflow/sandbox",
"third_party/taskflow/unittests",
"third_party/eigen/bench",
"third_party/eigen/demos",
"third_party/eigen/doc",
"third_party/taskflow/3rd-party",
"third_party/taskflow/benchmarks",
"third_party/taskflow/docs",
"third_party/taskflow/doxygen",
"third_party/taskflow/examples",
"third_party/taskflow/sandbox",
"third_party/taskflow/unittests",
]

[tool.ruff]
Expand All @@ -61,20 +60,20 @@ line-length = 120
[tool.ruff.lint]
# TODO Add D, PTH, RET, disabled for now as they collides with intial choices
select = ["E", "W", "YTT", "NPY", "PYI", "Q", "F", "B", "I", "SIM", "RUF"]
# TODO: for now we ignore "Line too long error (E501)"
# TODO: for now we ignore "Line too long error (E501)"
# because our comments are too longs
# code formatting will take care of the line length in code anyway
ignore = [
"E501",
# Ignore docstring in public package and module
"D100",
"D104",
# Blank line before class
"D203",
# multiline summary second line
"D213",
# yoda conditions
"SIM300",
"E501",
# Ignore docstring in public package and module
"D100",
"D104",
# Blank line before class
"D203",
# multiline summary second line
"D213",
# yoda conditions
"SIM300",
]

[tool.ruff.lint.isort]
Expand All @@ -86,28 +85,31 @@ legacy_tox_ini = """

[gh-actions]
python =
3.8: py39
3.9: py39
3.10: py310
3.11: py311
3.12: py312
3.13: py313

[testenv]
deps =
pytest >= 7.4
pytest-benchmark ~= 4.0
numpy >= 1.7, < 2
numpy >= 1.7
scipy
jakteristics;platform_system=="Windows" or platform_system=="Linux"
jakteristics;platform_system=="Windows" or platform_system=="Linux"
commands = pytest --basetemp="{envtmpdir}" {posargs}

[testenv:bench]
# globs/wildcards do not work with tox
commands = pytest -s --basetemp="{envtmpdir}" {posargs:tests/bench_knn.py tests/bench_jakteristics.py}
commands = pytest -s --basetemp="{envtmpdir}" {posargs:tests/bench_knn.py tests/bench_jakteristics.py}
"""

[tool.cibuildwheel]
build = "cp3{9,10,11,12}-*"
archs = ["auto64"] # limit to 64bits builds
build = "cp3{8,9,10,11,12,13}-*"
archs = ["auto64"] # limits to 64bits builds
skip = "cp38-macosx_arm64"

# Needed for full C++17 support
[tool.cibuildwheel.macos.environment]
Expand Down
3 changes: 1 addition & 2 deletions tests/bench_jakteristics.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
@pytest.fixture
def random_point_cloud():
rng = np.random.default_rng()
return rng.random(0, 100, size=((1000000, 3)))

return rng.uniform(0.0, 200.0, size=(10000, 3))

@pytest.mark.benchmark(group="feature-computation-jak", disable_gc=True, warmup=True)
def test_bench_jak(benchmark, random_point_cloud):
Expand Down
3 changes: 1 addition & 2 deletions tests/bench_knn.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
@pytest.fixture
def random_point_cloud():
rng = np.random.default_rng()
return rng.random(0, 100, size=((1000000, 3))).astype("float32")

return rng.uniform(0.0, 200.0, size=(1000000, 3)).astype(np.float32)

@pytest.mark.benchmark(group="knn", disable_gc=True, warmup=True)
def test_knn_scipy(benchmark, random_point_cloud):
Expand Down
2 changes: 1 addition & 1 deletion tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
def random_nn(num_points, k):
# Generate a random synthetic point cloud
rng = np.random.default_rng()
xyz = rng.random(size=(num_points, 3))
xyz = rng.uniform(0.0, 200.0, size=(num_points, 3)).astype(np.float32)

# Converting k-nearest neighbors to CSR format
kneigh = KDTree(xyz).query(xyz, k=k, workers=-1)
Expand Down
6 changes: 2 additions & 4 deletions tests/test_pgeof.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
def test_knn():
knn = 10
rng = np.random.default_rng()
xyz = rng.random(size=(1000, 3))
xyz = xyz.astype("float32")
xyz = rng.uniform(0.0, 200.0, size=(1000, 3)).astype(np.float32)
tree = KDTree(xyz)
_, k_legacy = tree.query(xyz, k=knn, workers=-1)
k_new, _ = pgeof.knn_search(xyz, xyz, knn)
Expand All @@ -20,8 +19,7 @@ def test_radius_search():
knn = 10
radius = 0.2
rng = np.random.default_rng()
xyz = rng.random(size=(1000, 3))
xyz = xyz.astype("float32")
xyz = rng.random(size=(1000, 3), dtype=np.float32)
tree = KDTree(xyz)
_, k_legacy = tree.query(xyz, k=knn, distance_upper_bound=radius, workers=-1)
k_legacy[k_legacy == xyz.shape[0]] = -1
Expand Down
2 changes: 1 addition & 1 deletion third_party/eigen
Submodule eigen updated from 287c80 to 314739
2 changes: 1 addition & 1 deletion third_party/taskflow
Submodule taskflow updated 816 files