morseframes 0.1.0a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. morseframes-0.1.0a1/.github/workflows/ci.yml +71 -0
  2. morseframes-0.1.0a1/.github/workflows/publish.yml +115 -0
  3. morseframes-0.1.0a1/.gitignore +34 -0
  4. morseframes-0.1.0a1/.readthedocs.yaml +13 -0
  5. morseframes-0.1.0a1/CHANGELOG.md +31 -0
  6. morseframes-0.1.0a1/CITATION.cff +21 -0
  7. morseframes-0.1.0a1/CMakeLists.txt +188 -0
  8. morseframes-0.1.0a1/CONTRIBUTING.md +81 -0
  9. morseframes-0.1.0a1/LICENSE +22 -0
  10. morseframes-0.1.0a1/PKG-INFO +213 -0
  11. morseframes-0.1.0a1/README.md +160 -0
  12. morseframes-0.1.0a1/benchmarks/benchmark_gudhi_view.cpp +938 -0
  13. morseframes-0.1.0a1/docs/api.rst +11 -0
  14. morseframes-0.1.0a1/docs/benchmark_reproduction.md +321 -0
  15. morseframes-0.1.0a1/docs/benchmark_summary.md +135 -0
  16. morseframes-0.1.0a1/docs/conf.py +54 -0
  17. morseframes-0.1.0a1/docs/cpp_complex_view_api.md +91 -0
  18. morseframes-0.1.0a1/docs/gudhi_contribution_design_note.md +328 -0
  19. morseframes-0.1.0a1/docs/gudhi_upstream_patch_map.md +416 -0
  20. morseframes-0.1.0a1/docs/index.rst +45 -0
  21. morseframes-0.1.0a1/docs/inspecting_morse_data.rst +199 -0
  22. morseframes-0.1.0a1/docs/minimal_examples.rst +125 -0
  23. morseframes-0.1.0a1/docs/native_gudhi_large_lean_r30_table.tex +35 -0
  24. morseframes-0.1.0a1/docs/native_gudhi_overhead_summary_table.tex +20 -0
  25. morseframes-0.1.0a1/docs/native_gudhi_stage_profile_quick_table.tex +24 -0
  26. morseframes-0.1.0a1/docs/native_gudhi_view_default_r30_table.tex +35 -0
  27. morseframes-0.1.0a1/docs/native_gudhi_view_quick_table.tex +25 -0
  28. morseframes-0.1.0a1/docs/phase0_conventions.md +79 -0
  29. morseframes-0.1.0a1/docs/plotly_morse_square_demo.html +18 -0
  30. morseframes-0.1.0a1/docs/plotting_demo.rst +19 -0
  31. morseframes-0.1.0a1/docs/profile_metric_fair_validation_table.tex +36 -0
  32. morseframes-0.1.0a1/docs/profile_selector_decision_summary_table.tex +28 -0
  33. morseframes-0.1.0a1/docs/project_overview.rst +89 -0
  34. morseframes-0.1.0a1/docs/python_api.md +295 -0
  35. morseframes-0.1.0a1/docs/python_prime_field_tutorial.md +167 -0
  36. morseframes-0.1.0a1/docs/quickstart.rst +66 -0
  37. morseframes-0.1.0a1/docs/requirements.txt +3 -0
  38. morseframes-0.1.0a1/docs/selector_feature_diagnostic_table.tex +19 -0
  39. morseframes-0.1.0a1/docs/strategies.md +251 -0
  40. morseframes-0.1.0a1/docs/synthetic_scale_table.tex +30 -0
  41. morseframes-0.1.0a1/examples/example_barcode.cpp +137 -0
  42. morseframes-0.1.0a1/examples/example_morse_persistence_from_simplex_tree.cpp +86 -0
  43. morseframes-0.1.0a1/examples/gudhi_simplex_tree_morse.cpp +82 -0
  44. morseframes-0.1.0a1/include/gudhi/Morse_persistence/complex_view.h +53 -0
  45. morseframes-0.1.0a1/include/gudhi/Morse_persistence/diagram.h +57 -0
  46. morseframes-0.1.0a1/include/gudhi/Morse_persistence/morse_sequence.h +34 -0
  47. morseframes-0.1.0a1/include/gudhi/Morse_persistence/persistence_reducer.h +177 -0
  48. morseframes-0.1.0a1/include/gudhi/Morse_persistence/reference_map.h +125 -0
  49. morseframes-0.1.0a1/include/gudhi/Morse_persistence/strategy.h +100 -0
  50. morseframes-0.1.0a1/include/gudhi/Morse_persistence.h +29 -0
  51. morseframes-0.1.0a1/include/morseframes/annotation.hpp +366 -0
  52. morseframes-0.1.0a1/include/morseframes/complex_view.hpp +101 -0
  53. morseframes-0.1.0a1/include/morseframes/coreference_persistence.hpp +690 -0
  54. morseframes-0.1.0a1/include/morseframes/debug_checks.hpp +124 -0
  55. morseframes-0.1.0a1/include/morseframes/field_annotation_store.hpp +349 -0
  56. morseframes-0.1.0a1/include/morseframes/field_arithmetic.hpp +70 -0
  57. morseframes-0.1.0a1/include/morseframes/filtered_complex.hpp +244 -0
  58. morseframes-0.1.0a1/include/morseframes/instrumentation.hpp +173 -0
  59. morseframes-0.1.0a1/include/morseframes/inverse_annotation_store.hpp +354 -0
  60. morseframes-0.1.0a1/include/morseframes/morse_reference_api.hpp +171 -0
  61. morseframes-0.1.0a1/include/morseframes/morse_sequence.hpp +1400 -0
  62. morseframes-0.1.0a1/include/morseframes/reference_persistence.hpp +1601 -0
  63. morseframes-0.1.0a1/include/morseframes/simplex_tree_builder.hpp +1250 -0
  64. morseframes-0.1.0a1/include/morseframes/simplex_tree_morse.hpp +58 -0
  65. morseframes-0.1.0a1/include/morseframes/standard_persistence.hpp +271 -0
  66. morseframes-0.1.0a1/include/morseframes/working_sets.hpp +50 -0
  67. morseframes-0.1.0a1/pyproject.toml +51 -0
  68. morseframes-0.1.0a1/python/examples/plotly_morse_square_demo.py +68 -0
  69. morseframes-0.1.0a1/python/examples/prime_field_tutorial.py +134 -0
  70. morseframes-0.1.0a1/python/examples/quickstart.py +35 -0
  71. morseframes-0.1.0a1/python/morseframes/__init__.py +5172 -0
  72. morseframes-0.1.0a1/python/morseframes/_core_bindings.cpp +1437 -0
  73. morseframes-0.1.0a1/python/morseframes/plotting.py +1330 -0
  74. morseframes-0.1.0a1/python/tests/test_benchmark_tool.py +1466 -0
  75. morseframes-0.1.0a1/python/tests/test_package_metadata.py +15 -0
  76. morseframes-0.1.0a1/python/tests/test_plotting.py +70 -0
  77. morseframes-0.1.0a1/python/tests/test_python_api.py +1143 -0
  78. morseframes-0.1.0a1/tests/test_gudhi_simplex_tree_view.cpp +574 -0
  79. morseframes-0.1.0a1/tests/test_morse_reference.cpp +1004 -0
  80. morseframes-0.1.0a1/tools/analyze_selector_features.py +534 -0
  81. morseframes-0.1.0a1/tools/benchmark_persistence.py +2458 -0
  82. morseframes-0.1.0a1/tools/benchmark_prime_field_overhead.py +354 -0
  83. morseframes-0.1.0a1/tools/calibrate_profile_gate.py +275 -0
  84. morseframes-0.1.0a1/tools/compare_profile_gates.py +307 -0
  85. morseframes-0.1.0a1/tools/render_benchmark_summary.py +268 -0
  86. morseframes-0.1.0a1/tools/render_native_gudhi_stage_profile.py +334 -0
  87. morseframes-0.1.0a1/tools/render_native_gudhi_view_table.py +284 -0
  88. morseframes-0.1.0a1/tools/render_synthetic_scale_table.py +274 -0
  89. morseframes-0.1.0a1/tools/run_fair_profile_validation.py +1086 -0
  90. morseframes-0.1.0a1/tools/summarize_selector_decisions.py +516 -0
  91. morseframes-0.1.0a1/tools/validate_with_gudhi.py +90 -0
@@ -0,0 +1,71 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ env:
8
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
9
+
10
+ jobs:
11
+ test:
12
+ name: C++ and Python (${{ matrix.os }}, Python ${{ matrix.python-version }})
13
+ runs-on: ${{ matrix.os }}
14
+ timeout-minutes: 20
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ os: [ubuntu-latest, macos-latest]
19
+ python-version: ["3.11"]
20
+
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+
24
+ - uses: actions/setup-python@v5
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+
28
+ - name: Upgrade pip
29
+ run: python -m pip install --upgrade pip
30
+
31
+ - name: Configure C++
32
+ run: cmake -S . -B build -DMORSEFRAMES_BUILD_GUDHI_TOOLS=OFF
33
+
34
+ - name: Build C++
35
+ run: cmake --build build --parallel
36
+
37
+ - name: Test C++
38
+ run: ctest --test-dir build --output-on-failure --timeout 120
39
+
40
+ - name: Install Python package
41
+ run: python -m pip install -e .
42
+
43
+ - name: Smoke-test native Python package
44
+ run: python -c "import morseframes as mf; print(mf.__version__, mf.cpp_backend_available()); assert mf.cpp_backend_available()"
45
+
46
+ - name: Test pure-Python fallback
47
+ run: MORSEFRAMES_DISABLE_CPP_BACKEND=1 python -m unittest discover -s python/tests -p "test_*.py"
48
+
49
+ - name: Run Python quickstart
50
+ run: python python/examples/quickstart.py
51
+
52
+ docs:
53
+ name: Documentation
54
+ runs-on: ubuntu-latest
55
+ timeout-minutes: 10
56
+
57
+ steps:
58
+ - uses: actions/checkout@v4
59
+
60
+ - uses: actions/setup-python@v5
61
+ with:
62
+ python-version: "3.12"
63
+
64
+ - name: Install documentation dependencies
65
+ run: python -m pip install -r docs/requirements.txt
66
+
67
+ - name: Check generated benchmark summary
68
+ run: python tools/render_benchmark_summary.py --check
69
+
70
+ - name: Build documentation
71
+ run: MORSEFRAMES_DISABLE_CPP_BACKEND=1 python -m sphinx -W --keep-going -b html docs docs/_build/html
@@ -0,0 +1,115 @@
1
+ name: Publish Python Package
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ repository:
7
+ description: "Package registry to publish to"
8
+ required: true
9
+ default: testpypi
10
+ type: choice
11
+ options:
12
+ - testpypi
13
+ - pypi
14
+ release:
15
+ types: [published]
16
+
17
+ permissions:
18
+ contents: read
19
+
20
+ env:
21
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
22
+ CIBW_BUILD: "cp310-* cp311-* cp312-*"
23
+ CIBW_SKIP: "*-musllinux_*"
24
+ CIBW_TEST_COMMAND: >-
25
+ python -c "import morseframes as mf;
26
+ assert mf.__version__ == '0.1.0a1';
27
+ assert mf.cpp_backend_available();
28
+ print(mf.__version__, mf.cpp_backend_available())"
29
+
30
+ jobs:
31
+ sdist:
32
+ name: Source distribution
33
+ runs-on: ubuntu-latest
34
+
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+
38
+ - uses: actions/setup-python@v5
39
+ with:
40
+ python-version: "3.12"
41
+
42
+ - name: Build source distribution
43
+ run: |
44
+ python -m pip install --upgrade pip build
45
+ python -m build --sdist --outdir dist
46
+
47
+ - uses: actions/upload-artifact@v4
48
+ with:
49
+ name: sdist
50
+ path: dist/*.tar.gz
51
+
52
+ wheels:
53
+ name: Wheels (${{ matrix.os }})
54
+ runs-on: ${{ matrix.os }}
55
+ strategy:
56
+ fail-fast: false
57
+ matrix:
58
+ os: [ubuntu-latest, macos-latest]
59
+
60
+ steps:
61
+ - uses: actions/checkout@v4
62
+
63
+ - uses: actions/setup-python@v5
64
+ with:
65
+ python-version: "3.12"
66
+
67
+ - uses: pypa/cibuildwheel@v4.1.0
68
+ with:
69
+ output-dir: wheelhouse
70
+
71
+ - uses: actions/upload-artifact@v4
72
+ with:
73
+ name: wheels-${{ matrix.os }}
74
+ path: wheelhouse/*.whl
75
+
76
+ publish-testpypi:
77
+ name: Publish to TestPyPI
78
+ if: github.event_name == 'workflow_dispatch' && inputs.repository == 'testpypi'
79
+ needs: [sdist, wheels]
80
+ runs-on: ubuntu-latest
81
+ environment: testpypi
82
+ permissions:
83
+ contents: read
84
+ id-token: write
85
+
86
+ steps:
87
+ - uses: actions/download-artifact@v4
88
+ with:
89
+ path: dist
90
+ merge-multiple: true
91
+
92
+ - uses: pypa/gh-action-pypi-publish@v1.14.0
93
+ with:
94
+ packages-dir: dist
95
+ repository-url: https://test.pypi.org/legacy/
96
+
97
+ publish-pypi:
98
+ name: Publish to PyPI
99
+ if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.repository == 'pypi')
100
+ needs: [sdist, wheels]
101
+ runs-on: ubuntu-latest
102
+ environment: pypi
103
+ permissions:
104
+ contents: read
105
+ id-token: write
106
+
107
+ steps:
108
+ - uses: actions/download-artifact@v4
109
+ with:
110
+ path: dist
111
+ merge-multiple: true
112
+
113
+ - uses: pypa/gh-action-pypi-publish@v1.14.0
114
+ with:
115
+ packages-dir: dist
@@ -0,0 +1,34 @@
1
+ build/
2
+ build-*/
3
+ cmake-build-*/
4
+ CMakeFiles/
5
+ CMakeCache.txt
6
+ CTestTestfile.cmake
7
+ CMakeInit.txt
8
+ Makefile
9
+ build.ninja
10
+ .ninja_deps
11
+ .ninja_log
12
+ .cmake/
13
+ .skbuild-info.json
14
+ cmake_install.cmake
15
+
16
+ __pycache__/
17
+ *.py[cod]
18
+ *.so
19
+ *.dylib
20
+ *.a
21
+ *.o
22
+ *.egg-info/
23
+ dist/
24
+ .pytest_cache/
25
+
26
+ *.aux
27
+ *.log
28
+ *.out
29
+ *.toc
30
+ docs/*_prose.tex
31
+ docs/experiments_morse_persistence*.pdf
32
+ docs/_build/
33
+
34
+ .DS_Store
@@ -0,0 +1,13 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-24.04
5
+ tools:
6
+ python: "3.12"
7
+
8
+ sphinx:
9
+ configuration: docs/conf.py
10
+
11
+ python:
12
+ install:
13
+ - requirements: docs/requirements.txt
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ All notable changes to MorseFrames are recorded here.
4
+
5
+ ## 0.1.0a1 - 2026-06-20
6
+
7
+ Initial public alpha release.
8
+
9
+ ### Added
10
+
11
+ - Header-only C++ core for filtered simplicial complexes.
12
+ - Python interface with pure-Python fallback and optional nanobind backend.
13
+ - Morse sequence strategies: saturated, F-Min, F-Max, same-level reduction,
14
+ plateau-greedy, and flooding variants.
15
+ - Reference and coreference map construction.
16
+ - Morse-reference and Morse-coreference persistence over `Z_2` and prime
17
+ fields `F_p`.
18
+ - Simplex-tree-like builder for constructing complexes.
19
+ - Experimental GUDHI-facing adapter for `Simplex_tree`.
20
+ - Plotly demonstration for inspecting Morse critical data on a triangulated
21
+ square.
22
+ - Reproducible benchmark scripts and generated public benchmark table
23
+ fragments.
24
+ - Read the Docs documentation, including overview, quickstart, minimal
25
+ examples, and Morse-data inspection guide.
26
+ - GitHub Actions CI for C++, Python, and documentation builds.
27
+
28
+ ### Notes
29
+
30
+ - This is research software. Public APIs are useful for experiments, but may
31
+ still evolve while the paper and GUDHI integration mature.
@@ -0,0 +1,21 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use MorseFrames in academic work, please cite it using this metadata."
3
+ type: software
4
+ title: "MorseFrames"
5
+ authors:
6
+ - family-names: Najman
7
+ given-names: Laurent
8
+ abstract: >-
9
+ Experimental C++ and Python software for Morse sequences, reference and
10
+ coreference maps, Morse complexes, and Morse-based persistent homology.
11
+ version: "0.1.0a1"
12
+ date-released: "2026-06-20"
13
+ license: MIT
14
+ repository-code: "https://github.com/lnajman/morseframes"
15
+ url: "https://morseframes.readthedocs.io/"
16
+ keywords:
17
+ - persistent homology
18
+ - discrete Morse theory
19
+ - Morse sequence
20
+ - computational topology
21
+ - simplicial complex
@@ -0,0 +1,188 @@
1
+ cmake_minimum_required(VERSION 3.16)
2
+
3
+ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND NOT CMAKE_OSX_ARCHITECTURES)
4
+ set(_MORSEFRAMES_PYTHON_FOR_ARCH "")
5
+ if(DEFINED Python_EXECUTABLE)
6
+ set(_MORSEFRAMES_PYTHON_FOR_ARCH "${Python_EXECUTABLE}")
7
+ elseif(DEFINED PYTHON_EXECUTABLE)
8
+ set(_MORSEFRAMES_PYTHON_FOR_ARCH "${PYTHON_EXECUTABLE}")
9
+ endif()
10
+
11
+ if(_MORSEFRAMES_PYTHON_FOR_ARCH)
12
+ execute_process(
13
+ COMMAND "${_MORSEFRAMES_PYTHON_FOR_ARCH}" -c
14
+ "import platform; print(platform.machine())"
15
+ OUTPUT_VARIABLE _MORSEFRAMES_PYTHON_ARCH
16
+ RESULT_VARIABLE _MORSEFRAMES_PYTHON_ARCH_RESULT
17
+ OUTPUT_STRIP_TRAILING_WHITESPACE
18
+ )
19
+ if(_MORSEFRAMES_PYTHON_ARCH_RESULT EQUAL 0
20
+ AND (_MORSEFRAMES_PYTHON_ARCH STREQUAL "arm64"
21
+ OR _MORSEFRAMES_PYTHON_ARCH STREQUAL "x86_64"))
22
+ set(CMAKE_OSX_ARCHITECTURES "${_MORSEFRAMES_PYTHON_ARCH}"
23
+ CACHE STRING "Build architectures for macOS" FORCE)
24
+ endif()
25
+ endif()
26
+ endif()
27
+
28
+ project(morseframes LANGUAGES CXX)
29
+
30
+ set(CMAKE_CXX_STANDARD 17)
31
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
32
+ set(CMAKE_CXX_EXTENSIONS OFF)
33
+
34
+ if(DEFINED SKBUILD)
35
+ set(MORSEFRAMES_DEFAULT_BUILD_PYTHON ON)
36
+ set(MORSEFRAMES_DEFAULT_BUILD_TESTS OFF)
37
+ set(MORSEFRAMES_DEFAULT_BUILD_EXAMPLES OFF)
38
+ set(MORSEFRAMES_DEFAULT_BUILD_GUDHI_TOOLS OFF)
39
+ else()
40
+ set(MORSEFRAMES_DEFAULT_BUILD_PYTHON OFF)
41
+ set(MORSEFRAMES_DEFAULT_BUILD_TESTS ON)
42
+ set(MORSEFRAMES_DEFAULT_BUILD_EXAMPLES ON)
43
+ set(MORSEFRAMES_DEFAULT_BUILD_GUDHI_TOOLS ON)
44
+ endif()
45
+
46
+ option(MORSEFRAMES_BUILD_PYTHON
47
+ "Build nanobind Python extension"
48
+ ${MORSEFRAMES_DEFAULT_BUILD_PYTHON})
49
+ option(MORSEFRAMES_BUILD_TESTS
50
+ "Build MorseFrames C++ tests"
51
+ ${MORSEFRAMES_DEFAULT_BUILD_TESTS})
52
+ option(MORSEFRAMES_BUILD_EXAMPLES
53
+ "Build MorseFrames C++ examples"
54
+ ${MORSEFRAMES_DEFAULT_BUILD_EXAMPLES})
55
+ option(MORSEFRAMES_BUILD_GUDHI_TOOLS
56
+ "Build optional GUDHI Simplex_tree integration tests and benchmark when headers are available"
57
+ ${MORSEFRAMES_DEFAULT_BUILD_GUDHI_TOOLS})
58
+ set(MORSEFRAMES_GUDHI_INCLUDE_DIR "" CACHE PATH
59
+ "Optional path to a GUDHI include directory containing gudhi/Simplex_tree.h")
60
+ set(MORSEFRAMES_BOOST_INCLUDE_DIR "" CACHE PATH
61
+ "Optional path to a Boost include directory needed by GUDHI headers")
62
+
63
+ if(MORSEFRAMES_BUILD_GUDHI_TOOLS)
64
+ if(NOT MORSEFRAMES_GUDHI_INCLUDE_DIR)
65
+ find_path(MORSEFRAMES_GUDHI_INCLUDE_DIR
66
+ NAMES gudhi/Simplex_tree.h
67
+ HINTS
68
+ ENV GUDHI_ROOT
69
+ ENV GUDHI_DIR
70
+ PATH_SUFFIXES include
71
+ DOC "Path to a GUDHI include directory containing gudhi/Simplex_tree.h")
72
+ endif()
73
+
74
+ if(NOT MORSEFRAMES_BOOST_INCLUDE_DIR)
75
+ find_path(MORSEFRAMES_BOOST_INCLUDE_DIR
76
+ NAMES boost/core/empty_value.hpp
77
+ HINTS
78
+ ENV BOOST_ROOT
79
+ ENV Boost_ROOT
80
+ ENV CONDA_PREFIX
81
+ PATH_SUFFIXES include
82
+ DOC "Path to a Boost include directory needed by GUDHI headers")
83
+ endif()
84
+ endif()
85
+
86
+ add_library(morseframes INTERFACE)
87
+ target_include_directories(morseframes INTERFACE
88
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
89
+ )
90
+
91
+ if(MORSEFRAMES_BUILD_TESTS)
92
+ add_executable(morseframes_tests
93
+ tests/test_morse_reference.cpp
94
+ )
95
+ target_link_libraries(morseframes_tests PRIVATE morseframes)
96
+ endif()
97
+
98
+ if(MORSEFRAMES_BUILD_EXAMPLES)
99
+ add_executable(morseframes_example_barcode
100
+ examples/example_barcode.cpp
101
+ )
102
+ target_link_libraries(morseframes_example_barcode PRIVATE morseframes)
103
+ endif()
104
+
105
+ if(MORSEFRAMES_BUILD_GUDHI_TOOLS
106
+ AND MORSEFRAMES_GUDHI_INCLUDE_DIR
107
+ AND EXISTS "${MORSEFRAMES_GUDHI_INCLUDE_DIR}/gudhi/Simplex_tree.h"
108
+ AND MORSEFRAMES_BOOST_INCLUDE_DIR
109
+ AND EXISTS "${MORSEFRAMES_BOOST_INCLUDE_DIR}/boost/core/empty_value.hpp")
110
+ add_executable(morseframes_gudhi_simplex_tree_view_tests
111
+ tests/test_gudhi_simplex_tree_view.cpp
112
+ )
113
+ target_link_libraries(morseframes_gudhi_simplex_tree_view_tests PRIVATE morseframes)
114
+ target_include_directories(morseframes_gudhi_simplex_tree_view_tests PRIVATE
115
+ "${MORSEFRAMES_GUDHI_INCLUDE_DIR}"
116
+ "${MORSEFRAMES_BOOST_INCLUDE_DIR}"
117
+ )
118
+
119
+ add_executable(morseframes_benchmark_gudhi_view
120
+ benchmarks/benchmark_gudhi_view.cpp
121
+ )
122
+ target_link_libraries(morseframes_benchmark_gudhi_view PRIVATE morseframes)
123
+ target_include_directories(morseframes_benchmark_gudhi_view PRIVATE
124
+ "${MORSEFRAMES_GUDHI_INCLUDE_DIR}"
125
+ "${MORSEFRAMES_BOOST_INCLUDE_DIR}"
126
+ )
127
+
128
+ add_executable(morseframes_gudhi_simplex_tree_example
129
+ examples/gudhi_simplex_tree_morse.cpp
130
+ )
131
+ target_link_libraries(morseframes_gudhi_simplex_tree_example PRIVATE morseframes)
132
+ target_include_directories(morseframes_gudhi_simplex_tree_example PRIVATE
133
+ "${MORSEFRAMES_GUDHI_INCLUDE_DIR}"
134
+ "${MORSEFRAMES_BOOST_INCLUDE_DIR}"
135
+ )
136
+
137
+ add_executable(morseframes_gudhi_style_simplex_tree_example
138
+ examples/example_morse_persistence_from_simplex_tree.cpp
139
+ )
140
+ target_link_libraries(morseframes_gudhi_style_simplex_tree_example PRIVATE morseframes)
141
+ target_include_directories(morseframes_gudhi_style_simplex_tree_example PRIVATE
142
+ "${MORSEFRAMES_GUDHI_INCLUDE_DIR}"
143
+ "${MORSEFRAMES_BOOST_INCLUDE_DIR}"
144
+ )
145
+ elseif(MORSEFRAMES_BUILD_GUDHI_TOOLS
146
+ AND MORSEFRAMES_GUDHI_INCLUDE_DIR
147
+ AND EXISTS "${MORSEFRAMES_GUDHI_INCLUDE_DIR}/gudhi/Simplex_tree.h")
148
+ message(STATUS
149
+ "Skipping GUDHI Simplex_tree tools because Boost headers were not found. "
150
+ "Set MORSEFRAMES_BOOST_INCLUDE_DIR or BOOST_ROOT to enable them.")
151
+ elseif(MORSEFRAMES_BUILD_GUDHI_TOOLS)
152
+ message(STATUS
153
+ "Skipping GUDHI Simplex_tree tools because GUDHI headers were not found. "
154
+ "Set MORSEFRAMES_GUDHI_INCLUDE_DIR or GUDHI_ROOT to enable them.")
155
+ endif()
156
+
157
+ if(MORSEFRAMES_BUILD_PYTHON)
158
+ find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
159
+ execute_process(
160
+ COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
161
+ OUTPUT_STRIP_TRAILING_WHITESPACE
162
+ OUTPUT_VARIABLE nanobind_ROOT
163
+ )
164
+ find_package(nanobind CONFIG REQUIRED)
165
+
166
+ nanobind_add_module(_morse_core
167
+ python/morseframes/_core_bindings.cpp
168
+ )
169
+ target_link_libraries(_morse_core PRIVATE morseframes)
170
+ set_target_properties(_morse_core PROPERTIES
171
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/python/morseframes"
172
+ )
173
+ if(DEFINED SKBUILD)
174
+ install(TARGETS _morse_core
175
+ LIBRARY DESTINATION morseframes
176
+ RUNTIME DESTINATION morseframes
177
+ )
178
+ endif()
179
+ endif()
180
+
181
+ enable_testing()
182
+ if(TARGET morseframes_tests)
183
+ add_test(NAME morseframes_tests COMMAND morseframes_tests)
184
+ endif()
185
+ if(TARGET morseframes_gudhi_simplex_tree_view_tests)
186
+ add_test(NAME morseframes_gudhi_simplex_tree_view_tests
187
+ COMMAND morseframes_gudhi_simplex_tree_view_tests)
188
+ endif()
@@ -0,0 +1,81 @@
1
+ # Contributing
2
+
3
+ MorseFrames is research software. Contributions are welcome, especially small
4
+ tests, documentation fixes, reproducibility improvements, and focused bug
5
+ reports.
6
+
7
+ ## Development Setup
8
+
9
+ From the repository root, build and test the C++ core:
10
+
11
+ ```sh
12
+ cmake -S . -B build -DMORSEFRAMES_BUILD_GUDHI_TOOLS=OFF
13
+ cmake --build build --parallel
14
+ ctest --test-dir build --output-on-failure
15
+ ```
16
+
17
+ Install the Python package in editable mode:
18
+
19
+ ```sh
20
+ python3 -m pip install -e ".[dev]"
21
+ python3 -c "import morseframes as mf; print(mf.__version__, mf.cpp_backend_available())"
22
+ ```
23
+
24
+ Run the pure-Python fallback tests:
25
+
26
+ ```sh
27
+ MORSEFRAMES_DISABLE_CPP_BACKEND=1 python3 -m unittest discover -s python/tests -p "test_*.py"
28
+ ```
29
+
30
+ Run the quickstart example:
31
+
32
+ ```sh
33
+ python3 python/examples/quickstart.py
34
+ ```
35
+
36
+ ## Documentation
37
+
38
+ Install the documentation dependencies and build the Sphinx site:
39
+
40
+ ```sh
41
+ python3 -m pip install -r docs/requirements.txt
42
+ MORSEFRAMES_DISABLE_CPP_BACKEND=1 python3 -m sphinx -W --keep-going -b html docs docs/_build/html
43
+ ```
44
+
45
+ The public documentation is hosted at:
46
+
47
+ <https://morseframes.readthedocs.io/>
48
+
49
+ ## Optional GUDHI Tools
50
+
51
+ The GUDHI-facing examples, tests, and benchmarks are enabled when GUDHI and
52
+ Boost headers are available:
53
+
54
+ ```sh
55
+ cmake -S . -B build \
56
+ -DMORSEFRAMES_GUDHI_INCLUDE_DIR=/path/to/gudhi/include \
57
+ -DMORSEFRAMES_BOOST_INCLUDE_DIR=/path/to/boost/include
58
+ ```
59
+
60
+ ## Benchmarks
61
+
62
+ Benchmark and table-generation scripts live in `tools/`. The public
63
+ reproduction instructions are in:
64
+
65
+ ```text
66
+ docs/benchmark_reproduction.md
67
+ ```
68
+
69
+ Use benchmark results as comparative signals rather than absolute machine
70
+ independent timings. When changing algorithms or reducers, prefer reporting
71
+ ratios, dataset metadata, and repeated-run summaries.
72
+
73
+ ## Pull Request Checklist
74
+
75
+ - Keep changes focused.
76
+ - Add or update tests when behavior changes.
77
+ - Run the C++ tests, Python fallback tests, and documentation build when
78
+ touching the corresponding surface.
79
+ - Keep generated scratch files out of commits.
80
+ - Do not commit private manuscript drafts or private discussion notes to this
81
+ public repository.
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Laurent Najman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+