multimodars 0.2.3__tar.gz → 0.3.0__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.
- {multimodars-0.2.3 → multimodars-0.3.0}/.github/workflows/CI.yml +1 -1
- multimodars-0.3.0/.pre-commit-config.yaml +52 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/CHANGELOG.md +55 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/Cargo.lock +1 -27
- {multimodars-0.2.3 → multimodars-0.3.0}/Cargo.toml +1 -2
- {multimodars-0.2.3 → multimodars-0.3.0}/PKG-INFO +7 -2
- multimodars-0.3.0/ROADMAP.MD +90 -0
- multimodars-0.3.0/docs/api/adjust_ccta.rst +9 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/conf.py +4 -10
- multimodars-0.3.0/docs/figures/dataprep.jpg +0 -0
- multimodars-0.3.0/docs/index.rst +82 -0
- multimodars-0.3.0/docs/tutorial_ccta.rst +485 -0
- multimodars-0.3.0/docs/tutorial_intravascular.rst +621 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/multimodars/__init__.py +50 -2
- {multimodars-0.2.3 → multimodars-0.3.0}/multimodars/_converters.py +82 -6
- multimodars-0.3.0/multimodars/_processing.py +1426 -0
- multimodars-0.3.0/multimodars/ccta/__init__.py +466 -0
- multimodars-0.3.0/multimodars/ccta/debug_plots.py +207 -0
- multimodars-0.3.0/multimodars/ccta/fixing_functions.py +239 -0
- multimodars-0.3.0/multimodars/ccta/labeling.py +561 -0
- multimodars-0.3.0/multimodars/ccta/manipulating.py +977 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/multimodars/multimodars.pyi +184 -169
- {multimodars-0.2.3 → multimodars-0.3.0}/pyproject.toml +9 -2
- {multimodars-0.2.3 → multimodars-0.3.0}/src/ccta/adjust_mesh/label_coronary.rs +1 -3
- {multimodars-0.2.3 → multimodars-0.3.0}/src/ccta/adjust_mesh/scale_coronary.rs +97 -42
- {multimodars-0.2.3 → multimodars-0.3.0}/src/ccta/binding/ccta_py.rs +114 -23
- {multimodars-0.2.3 → multimodars-0.3.0}/src/ccta/mod.rs +0 -1
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/binding/align.rs +6 -6
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/binding/classes.rs +85 -10
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/binding/entry.rs +186 -195
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/binding/mod.rs +256 -319
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/centerline_align/align_algorithms.rs +1 -1
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/centerline_align/mod.rs +13 -13
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/io/geometry.rs +91 -26
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/io/input.rs +10 -13
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/io/integrity_check.rs +18 -21
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/io/mod.rs +2 -5
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/io/output.rs +1 -1
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/processing/align_between.rs +16 -11
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/processing/align_within.rs +18 -20
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/processing/postprocessing.rs +3 -9
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/processing/preprocessing.rs +55 -22
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/processing/process_utils.rs +2 -4
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/processing/wall.rs +11 -19
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/to_object/interpolation.rs +8 -8
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/to_object/mod.rs +2 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/to_object/texture.rs +1 -1
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/to_object/write_mtl.rs +5 -5
- multimodars-0.2.3/src/intravascular/utils/utils.rs → multimodars-0.3.0/src/intravascular/utils/general_utils.rs +4 -4
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/utils/mod.rs +1 -1
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/utils/test_utils.rs +11 -11
- {multimodars-0.2.3 → multimodars-0.3.0}/src/lib.rs +5 -2
- multimodars-0.3.0/tests/test_ccta.py +657 -0
- multimodars-0.2.3/.pre-commit-config.yaml +0 -38
- multimodars-0.2.3/ROADMAP.MD +0 -63
- multimodars-0.2.3/docs/api/adjust_ccta.rst +0 -9
- multimodars-0.2.3/docs/index.rst +0 -69
- multimodars-0.2.3/docs/tutorial_ccta.rst +0 -163
- multimodars-0.2.3/docs/tutorial_intravascular.rst +0 -391
- multimodars-0.2.3/multimodars/ccta/__init__.py +0 -1
- multimodars-0.2.3/multimodars/ccta/adjust_ccta.py +0 -1007
- multimodars-0.2.3/src/ccta/io/input.rs +0 -220
- multimodars-0.2.3/src/ccta/io/mod.rs +0 -1
- {multimodars-0.2.3 → multimodars-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/.github/workflows/draft-pdf.yml +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/.gitignore +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/.readthedocs.yaml +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/CONTRIBUTING.md +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/LICENSE +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/README.md +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/idealized_geometry/branch_diastolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/idealized_geometry/branch_systolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/idealized_geometry/calcium_diastolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/idealized_geometry/calcium_systolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/idealized_geometry/diastolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/idealized_geometry/diastolic_reference_points.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/idealized_geometry/eem_diastolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/idealized_geometry/eem_systolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/idealized_geometry/systolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/idealized_geometry/systolic_reference_points.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_full/branch_diastolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_full/branch_systolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_full/calcium_diastolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_full/calcium_systolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_full/diastolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_full/diastolic_reference_points.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_full/eem_diastolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_full/eem_systolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_full/systolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_full/systolic_reference_points.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_rest/combined_sorted_manual.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_rest/diastolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_rest/diastolic_reference_points.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_rest/systolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_rest/systolic_reference_points.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_stress/combined_sorted_manual.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_stress/diastolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_stress/diastolic_reference_points.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_stress/systolic_contours.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/data/fixtures/ivus_stress/systolic_reference_points.csv +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/Makefile +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/_static/.gitkeep +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/centerline.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/classes/PyCenterline.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/classes/PyCenterlinePoint.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/classes/PyContour.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/classes/PyContourPoint.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/classes/PyFrame.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/classes/PyGeometry.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/classes/PyGeometryPair.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/classes/PyInputData.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/classes/PyRecord.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/classes/index.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/converters_and_wrappers.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/core.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/index.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/processing.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/api/utilities.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/build.sh +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/changelog.md +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/figures/Alignment3p.png +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/figures/animation_stress_induced_systolic_deformation.gif +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/figures/anomalous_labeling.jpg +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/figures/initial_labeling.jpg +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/figures/scaling.jpg +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/installation.rst +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/docs/make.bat +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/media/coronary_artery_disease.jpg +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/media/dynamic_lumen_changes.png +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/media/multimoda-rs.jpg +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/multimodars/io/__init__.py +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/multimodars/io/read_geometrical.py +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/multimodars/io/write_geometries.py +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/multimodars/py.typed +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/paper/REVIEWER1.md +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/paper/bibliography.bib +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/paper/figures/Figure1.jpg +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/paper/figures/Figure2.jpg +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/paper/figures/Figure3.png +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/paper/figures/Figure4.jpg +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/paper/paper.md +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/src/ccta/adjust_mesh/mod.rs +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/src/ccta/binding/mod.rs +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/centerline_align/preprocessing.rs +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/mod.rs +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/src/intravascular/processing/mod.rs +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/tests/conftest.py +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/tests/test_converters.py +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/tests/test_core.py +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/tests/test_wrappers.py +0 -0
- {multimodars-0.2.3 → multimodars-0.3.0}/tests/tests_todo.md +0 -0
|
@@ -226,7 +226,7 @@ jobs:
|
|
|
226
226
|
name: Release
|
|
227
227
|
runs-on: ubuntu-latest
|
|
228
228
|
if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
|
|
229
|
-
needs: [linux, musllinux, windows, macos, sdist]
|
|
229
|
+
needs: [linux, musllinux, windows, macos, sdist, python-compat]
|
|
230
230
|
permissions:
|
|
231
231
|
id-token: write
|
|
232
232
|
contents: write
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: local
|
|
3
|
+
hooks:
|
|
4
|
+
# - id: pytest
|
|
5
|
+
# name: Run pytest
|
|
6
|
+
# entry: pytest
|
|
7
|
+
# language: system
|
|
8
|
+
# types: [python]
|
|
9
|
+
# pass_filenames: false
|
|
10
|
+
|
|
11
|
+
- id: rust-fmt
|
|
12
|
+
name: Rust format
|
|
13
|
+
entry: cargo fmt --all
|
|
14
|
+
language: system
|
|
15
|
+
types: [rust]
|
|
16
|
+
pass_filenames: false
|
|
17
|
+
|
|
18
|
+
- id: rust-clippy
|
|
19
|
+
name: Rust clippy
|
|
20
|
+
entry: cargo clippy --all-targets --all-features -- -D warnings
|
|
21
|
+
language: system
|
|
22
|
+
types: [rust]
|
|
23
|
+
pass_filenames: false
|
|
24
|
+
|
|
25
|
+
# - id: rust-test
|
|
26
|
+
# name: Rust unit tests
|
|
27
|
+
# entry: cargo test --lib # --quiet
|
|
28
|
+
# language: system
|
|
29
|
+
# types: [rust]
|
|
30
|
+
# pass_filenames: false
|
|
31
|
+
|
|
32
|
+
- id: python-black
|
|
33
|
+
name: Black formatting
|
|
34
|
+
entry: black
|
|
35
|
+
language: system
|
|
36
|
+
types: [python]
|
|
37
|
+
require_serial: true
|
|
38
|
+
args: [--quiet, --target-version, py312]
|
|
39
|
+
|
|
40
|
+
- id: python-ruff
|
|
41
|
+
name: Ruff linting
|
|
42
|
+
entry: ruff check
|
|
43
|
+
language: system
|
|
44
|
+
types: [python]
|
|
45
|
+
args: [--fix]
|
|
46
|
+
|
|
47
|
+
- id: python-mypy
|
|
48
|
+
name: Mypy type checking
|
|
49
|
+
entry: mypy multimodars --ignore-missing-imports
|
|
50
|
+
language: system
|
|
51
|
+
types: [python]
|
|
52
|
+
pass_filenames: false
|
|
@@ -3,6 +3,61 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
This project adheres to [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [0.3.0] - 2026-04-30
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- `stitch_ccta_to_intravascular()`: fuses an aligned intravascular `PyGeometry` with a CCTA
|
|
10
|
+
trimesh by triangulating a patch between the open boundary ring of the CCTA mesh and the
|
|
11
|
+
proximal/distal contour of the intravascular geometry. Supports two boundary-ring alignment
|
|
12
|
+
modes (`"nearest_iv"` and `"highest_z"`) for proximal and distal ends independently.
|
|
13
|
+
- `fix_and_remesh_stitched_mesh()`: repairs the stitched surface (non-manifold edges/vertices,
|
|
14
|
+
open holes) and applies isotropic remeshing via `pymeshlab`. Requires the optional
|
|
15
|
+
`multimodars[meshlab]` extra.
|
|
16
|
+
- `manual_hole_fill()`: flat-fills remaining open holes in a trimesh after automatic repair.
|
|
17
|
+
- `remove_labeled_points_from_mesh()`: deletes one or more labeled vertex regions from the mesh, remaps faces, and returns the open boundary ring as `"boundary_points"` for downstream stitching.
|
|
18
|
+
- `keep_labeled_points_from_mesh()`: retains only the vertices of a specified labeled region,
|
|
19
|
+
discarding all others.
|
|
20
|
+
- `sync_results_to_mesh()`: refreshes all coordinate lists in the results dictionary after
|
|
21
|
+
`scale_region_centerline_morphing()` moves vertices, keeping labels consistent with the
|
|
22
|
+
updated mesh.
|
|
23
|
+
- `find_aortic_wall_scaling()`: computes the optimal radial scaling factor for the aortic wall
|
|
24
|
+
region by minimising the distance to the first intravascular frame whose lumen elliptic ratio
|
|
25
|
+
drops below 1.3 (transition from intramural to free-segment lumen).
|
|
26
|
+
- `export_section_stl()`: exports the full mesh or a labeled sub-region (`"all"`, `"aorta"`,
|
|
27
|
+
`"rca"`, `"lca"`) as an STL file.
|
|
28
|
+
- `plot_results_key()`: opens an interactive 3-D trimesh scene visualising selected labeled
|
|
29
|
+
regions with colour coding (yellow = aorta, blue = RCA, green = LCA, red = removed/intramural,
|
|
30
|
+
cyan = proximal, magenta = distal, orange = anomalous).
|
|
31
|
+
- Tests for all new CCTA functions.
|
|
32
|
+
- `mypy` added to pre-commit hooks for static type checking.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
- Rust-side CCTA STL reader (`src/ccta/io/input.rs`) removed; mesh I/O is now handled
|
|
36
|
+
entirely via Python `trimesh`, eliminating the `stl_io` dependency.
|
|
37
|
+
- `pymeshlab` and `pyglet` are now optional dependencies; the core package installs without
|
|
38
|
+
them. Install extras with `pip install 'multimodars[meshlab]'`.
|
|
39
|
+
- Debug-plot helpers moved to a dedicated `ccta.debug_plots` module.
|
|
40
|
+
- CCTA Python module refactored into focused sub-modules (`labeling`, `manipulating`,
|
|
41
|
+
`fixing_functions`, `debug_plots`).
|
|
42
|
+
- Parameter order updated in several CCTA API calls for consistency.
|
|
43
|
+
- `diastole` argument removed from functions where it was not used.
|
|
44
|
+
- Labeling of aorta boundary points improved to avoid incorrect assignment at mesh edges.
|
|
45
|
+
- Type stubs updated and extended to cover all new public functions.
|
|
46
|
+
- Clippy lints applied across the Rust codebase (non-breaking).
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
- 3-D area and elliptic ratio calculation corrected for non-planar contours.
|
|
50
|
+
- Mesh face normals corrected after stitching to ensure consistent outward orientation.
|
|
51
|
+
|
|
52
|
+
### Documentation
|
|
53
|
+
- CCTA tutorial completely rewritten to cover the full stitching workflow:
|
|
54
|
+
`remove_labeled_points_from_mesh` → `stitch_ccta_to_intravascular` →
|
|
55
|
+
`fix_and_remesh_stitched_mesh` → Taubin smoothing → `export_section_stl` → re-labeling.
|
|
56
|
+
- Intravascular tutorial reviewed and completed: section numbering corrected (1–7),
|
|
57
|
+
CSV-vs-numpy workflow note added, column descriptions with units added to data tables,
|
|
58
|
+
Sphinx cross-references added throughout, `translate()` tuple-argument bug fixed.
|
|
59
|
+
|
|
60
|
+
|
|
6
61
|
## [0.2.3] - 2026-03-06
|
|
7
62
|
|
|
8
63
|
### Added
|
|
@@ -161,12 +161,6 @@ version = "1.23.1"
|
|
|
161
161
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
162
162
|
checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422"
|
|
163
163
|
|
|
164
|
-
[[package]]
|
|
165
|
-
name = "byteorder"
|
|
166
|
-
version = "1.5.0"
|
|
167
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
168
|
-
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|
169
|
-
|
|
170
164
|
[[package]]
|
|
171
165
|
name = "byteorder-lite"
|
|
172
166
|
version = "0.1.0"
|
|
@@ -390,15 +384,6 @@ dependencies = [
|
|
|
390
384
|
"miniz_oxide",
|
|
391
385
|
]
|
|
392
386
|
|
|
393
|
-
[[package]]
|
|
394
|
-
name = "float-cmp"
|
|
395
|
-
version = "0.10.0"
|
|
396
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
397
|
-
checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8"
|
|
398
|
-
dependencies = [
|
|
399
|
-
"num-traits",
|
|
400
|
-
]
|
|
401
|
-
|
|
402
387
|
[[package]]
|
|
403
388
|
name = "getrandom"
|
|
404
389
|
version = "0.3.4"
|
|
@@ -726,7 +711,7 @@ dependencies = [
|
|
|
726
711
|
|
|
727
712
|
[[package]]
|
|
728
713
|
name = "multimodars"
|
|
729
|
-
version = "0.
|
|
714
|
+
version = "0.3.0"
|
|
730
715
|
dependencies = [
|
|
731
716
|
"anyhow",
|
|
732
717
|
"approx",
|
|
@@ -737,7 +722,6 @@ dependencies = [
|
|
|
737
722
|
"pyo3",
|
|
738
723
|
"rayon",
|
|
739
724
|
"serde",
|
|
740
|
-
"stl_io",
|
|
741
725
|
"toml",
|
|
742
726
|
]
|
|
743
727
|
|
|
@@ -1255,16 +1239,6 @@ version = "1.2.1"
|
|
|
1255
1239
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1256
1240
|
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
|
1257
1241
|
|
|
1258
|
-
[[package]]
|
|
1259
|
-
name = "stl_io"
|
|
1260
|
-
version = "0.10.0"
|
|
1261
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1262
|
-
checksum = "da63e75b86345156b191c021b3ce2a13b973941ecdb8c70d6f00cbbfe0076ed7"
|
|
1263
|
-
dependencies = [
|
|
1264
|
-
"byteorder",
|
|
1265
|
-
"float-cmp",
|
|
1266
|
-
]
|
|
1267
|
-
|
|
1268
1242
|
[[package]]
|
|
1269
1243
|
name = "syn"
|
|
1270
1244
|
version = "2.0.104"
|
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: multimodars
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
7
7
|
Classifier: License :: OSI Approved :: MIT License
|
|
8
8
|
Requires-Dist: numpy>=2.0.0,<3.0.0
|
|
9
9
|
Requires-Dist: trimesh>=4.8.0
|
|
10
|
-
Requires-Dist:
|
|
10
|
+
Requires-Dist: scipy>=1.15.0
|
|
11
11
|
Requires-Dist: sphinx>=8.0,<9.0 ; extra == 'docs'
|
|
12
12
|
Requires-Dist: sphinx-rtd-theme ; extra == 'docs'
|
|
13
13
|
Requires-Dist: sphinx-autodoc-typehints ; extra == 'docs'
|
|
14
14
|
Requires-Dist: myst-parser ; extra == 'docs'
|
|
15
15
|
Requires-Dist: maturin>=1.7,<2.0 ; extra == 'docs'
|
|
16
16
|
Requires-Dist: furo ; extra == 'docs'
|
|
17
|
+
Requires-Dist: pymeshlab>=2023.12 ; extra == 'meshlab'
|
|
17
18
|
Requires-Dist: pytest>=9.0.2 ; extra == 'test'
|
|
18
19
|
Requires-Dist: pytest-cov ; extra == 'test'
|
|
19
20
|
Requires-Dist: ruff ; extra == 'test'
|
|
20
21
|
Requires-Dist: black ; extra == 'test'
|
|
22
|
+
Requires-Dist: mypy ; extra == 'test'
|
|
23
|
+
Requires-Dist: pyglet<2 ; extra == 'viz'
|
|
21
24
|
Provides-Extra: docs
|
|
25
|
+
Provides-Extra: meshlab
|
|
22
26
|
Provides-Extra: test
|
|
27
|
+
Provides-Extra: viz
|
|
23
28
|
License-File: LICENSE
|
|
24
29
|
Summary: A Rust-powered cardiac multi-image modality fusion package
|
|
25
30
|
Author: Anselm W. Stark
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Python package that has one purpose: Combining any intravascular image modality with CCTA meshes.
|
|
2
|
+
|
|
3
|
+
# Centerline alignment module
|
|
4
|
+
(- [] Create Centerline directly from mesh) (v1.0.0)
|
|
5
|
+
|
|
6
|
+
# Mesh combination (v0.3.0)
|
|
7
|
+
- [] Write a more stable function to find intramural points on aorta (for now works with excluded RCA points)
|
|
8
|
+
- [] fix centerline resampling
|
|
9
|
+
- [] Create an aortic and coronary wall with a consistent connection
|
|
10
|
+
|
|
11
|
+
# CCTA clinical assessment (v0.4.0)
|
|
12
|
+
- [] automatically find the required reference points for alignment
|
|
13
|
+
- [] automatically assess lumen area, minor-, major axis, mla, intramural length etc. from the CCTA mesh.
|
|
14
|
+
- [] return hausdorff distances per point between aligned ivus mesh and ccta mesh.
|
|
15
|
+
- [] function to automatically assign wall thickness to ccta and combined ivus/ccta mesh
|
|
16
|
+
- [] helper function to automatically export only certain points on mesh (e.g. RCA or LCA)
|
|
17
|
+
- [] function to combine anomalous section only with the distal part
|
|
18
|
+
|
|
19
|
+
# Miscellaneous
|
|
20
|
+
- [] Improve print statements in the whole package
|
|
21
|
+
|
|
22
|
+
# Prepublish checklist (JOSS review feedback — open until resolved):
|
|
23
|
+
|
|
24
|
+
## Data & archival
|
|
25
|
+
- [] Upload example data (`examples.zip`) to a persistent archive (Zenodo or similar) with a DOI.
|
|
26
|
+
Upload the source code snapshot there as well, either in the same record or a separate one linked from the paper.
|
|
27
|
+
Leave open until the DOI is minted and cited in the paper/README.
|
|
28
|
+
- [] Clarify whether the sample data (repo + examples.zip) is real human data or synthetic data.
|
|
29
|
+
If real, add a statement on ethical approval / data-use conformity per JOSS policy
|
|
30
|
+
(https://joss.readthedocs.io/en/latest/policies.html#joss-policies).
|
|
31
|
+
|
|
32
|
+
## Dependencies / packaging
|
|
33
|
+
- [] Add `scipy` as an explicit runtime dependency in `pyproject.toml` (required by `mm.label_geometry()`).
|
|
34
|
+
- [] Convert `optional-dependencies` groups that are not user-facing extras (docs, test, dev)
|
|
35
|
+
to PEP 735 `dependency-groups` so they are not shipped with the package on PyPI.
|
|
36
|
+
Move notebook runtime deps (`trimesh`, `plotly`, `scipy`, `nbformat`, `ipykernel`) into a
|
|
37
|
+
`[dependency-groups.dev]` group so `uv` installs them automatically during development.
|
|
38
|
+
|
|
39
|
+
## Examples / notebooks
|
|
40
|
+
- [] Include the `examples/` folder (with data) directly in the repository so users can clone
|
|
41
|
+
and run without a separate download, and so CI can execute the notebooks as tests.
|
|
42
|
+
- [] Fix `ivus_to_centerline.ipynb`: create `output/` and `output/unprocessed/` directories
|
|
43
|
+
on-the-fly with `os.makedirs(..., exist_ok=True)` so the notebook does not error on a fresh clone.
|
|
44
|
+
- [] Add a unit test that runs the example notebook end-to-end (e.g. using `nbmake` or `pytest-notebook`)
|
|
45
|
+
so regressions are caught automatically.
|
|
46
|
+
|
|
47
|
+
## Performance claim
|
|
48
|
+
- [] Provide reproducible code + sample data for the performance claim in the paper (lines 102-104):
|
|
49
|
+
"Empirical performance on a 16-core CPU: an OCT pullback with 280 frames and a rotation search range
|
|
50
|
+
of ±3° (final accuracy 0.01°) saw alignment time reduced from 150 s to 18 s with the optimized
|
|
51
|
+
multiscale search."
|
|
52
|
+
Add a benchmark script or notebook to `examples/` so the claim can be independently reproduced.
|
|
53
|
+
|
|
54
|
+
## Documentation — Tutorial Intravascular
|
|
55
|
+
- [x] Section "1. Workflow csv files": add column descriptions with units after the data table,
|
|
56
|
+
and add header names to the first data table — done (frame_index, x (mm), y (mm), z (mm)
|
|
57
|
+
headers present; "Column descriptions:" bullet block added).
|
|
58
|
+
- [x] Section "1. Workflow csv files": add `:func:` / `:class:` Sphinx cross-references —
|
|
59
|
+
done throughout section 2 and the rest of the tutorial.
|
|
60
|
+
- [x] Section "3. Workflow numpy arrays": explain how CSV and numpy workflows differ — done via
|
|
61
|
+
`.. note:: **CSV vs. numpy workflow** …` block at the top of section 3.
|
|
62
|
+
- [x] Fix section numbering — done: sections run 1–7 with no duplicates.
|
|
63
|
+
- [x] Section "6. Utility functions / to_array": clarify Returns block — done with prose
|
|
64
|
+
descriptions and typed bullet list per return type; `:func:` cross-reference present.
|
|
65
|
+
- [x] Fix `translate((0.0, 1.0, 2.0))` tuple bug — done: all three call-sites use positional
|
|
66
|
+
args `translate(0.0, 1.0, 2.0)`.
|
|
67
|
+
- [] Fix remaining undefined variables in tutorial snippets (reviewer: "cannot be run due to
|
|
68
|
+
undefined variables"):
|
|
69
|
+
- `stress` (section 6, to_array snippet, line ~392) — only defined if the user followed the
|
|
70
|
+
`from_file_full` path; breaks on the `singlepair` path. Change to `rest` or add a note.
|
|
71
|
+
- `cl_resampled` (section 6, to_array snippet, line ~394) — variable returned in section 4
|
|
72
|
+
is named `resampled_cl`; rename to match.
|
|
73
|
+
- `results["rca_points"]` (section 4, align_combined code block, line ~358) — `results` is
|
|
74
|
+
never defined in this tutorial. Add an inline comment: `# from mm.label_geometry() — see
|
|
75
|
+
CCTA tutorial` and a placeholder assignment above the block.
|
|
76
|
+
- `geometry` (section 5, to_obj code block, line ~374) — undefined at that point; replace
|
|
77
|
+
with `aligned` (returned from align_combined in section 4).
|
|
78
|
+
|
|
79
|
+
## Documentation — general
|
|
80
|
+
- [] Consider converting tutorials to Jupyter notebooks rendered via `nbsphinx` or `myst-nb`
|
|
81
|
+
so outputs are visible, results are verifiable, and documentation build failures reveal
|
|
82
|
+
broken code early. (Non-blocking suggestion from reviewer crnh / richardkoehler.)
|
|
83
|
+
- [] Cite the case-report paper in the Research impact statement (it is cited elsewhere but
|
|
84
|
+
not in that section).
|
|
85
|
+
|
|
86
|
+
## CI / quality
|
|
87
|
+
- [] Integrate coverage measurement (`pytest-cov`) and upload reports to Coveralls or Codecov.
|
|
88
|
+
- [] Add a coverage status badge to the README.
|
|
89
|
+
- [] Add `mypy` to pre-commit hooks.
|
|
90
|
+
- [] Add `scipy` to pre-commit / lint hooks.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Adjust CCTA
|
|
2
|
+
===========
|
|
3
|
+
|
|
4
|
+
.. autofunction:: multimodars.ccta.labeling.label_geometry
|
|
5
|
+
.. autofunction:: multimodars.ccta.labeling.label_anomalous_region
|
|
6
|
+
.. autofunction:: multimodars.ccta.manipulating.scale_region_centerline_morphing
|
|
7
|
+
.. autofunction:: multimodars.ccta.manipulating.find_distal_and_proximal_scaling
|
|
8
|
+
.. autofunction:: multimodars.ccta.manipulating.find_aorta_scaling
|
|
9
|
+
.. autofunction:: multimodars.ccta.debug_plots.compare_centerline_scaling
|
|
@@ -3,12 +3,13 @@ import sys
|
|
|
3
3
|
import re
|
|
4
4
|
|
|
5
5
|
try:
|
|
6
|
-
import multimodars
|
|
6
|
+
import multimodars # noqa: F401
|
|
7
7
|
except ImportError:
|
|
8
8
|
from unittest.mock import MagicMock
|
|
9
9
|
|
|
10
10
|
sys.modules["multimodars"] = MagicMock()
|
|
11
11
|
|
|
12
|
+
|
|
12
13
|
# Get the version from Cargo.toml
|
|
13
14
|
def get_version():
|
|
14
15
|
with open(os.path.join("..", "Cargo.toml"), "r") as f:
|
|
@@ -19,6 +20,7 @@ def get_version():
|
|
|
19
20
|
return match.group(1)
|
|
20
21
|
return "0.0.0"
|
|
21
22
|
|
|
23
|
+
|
|
22
24
|
# Add project to path
|
|
23
25
|
sys.path.insert(0, os.path.abspath(".."))
|
|
24
26
|
sys.path.insert(0, os.path.abspath("../src"))
|
|
@@ -62,12 +64,4 @@ autodoc_default_options = {
|
|
|
62
64
|
"special-members": "__init__",
|
|
63
65
|
}
|
|
64
66
|
autodoc_typehints = "description"
|
|
65
|
-
|
|
66
|
-
# Workaround for PyO3 modules
|
|
67
|
-
try:
|
|
68
|
-
import multimodars
|
|
69
|
-
except ImportError:
|
|
70
|
-
from unittest.mock import MagicMock
|
|
71
|
-
|
|
72
|
-
sys.modules["multimodars"] = MagicMock()
|
|
73
|
-
print("Warning: multimodars module not found, using mocks for documentation")
|
|
67
|
+
numfig = True
|
|
Binary file
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
.. multimodars documentation master file, created by
|
|
2
|
+
sphinx-quickstart on Wed Jul 23 22:38:42 2025.
|
|
3
|
+
You can adapt this file completely to your liking, but it should at least
|
|
4
|
+
contain the root `toctree` directive.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Welcome to multimodars documentation!
|
|
8
|
+
=====================================
|
|
9
|
+
|
|
10
|
+
*multimodars: A Rust-powered cardiac multi-image modality fusion package.*
|
|
11
|
+
|
|
12
|
+
.. warning::
|
|
13
|
+
|
|
14
|
+
Not intended for clinical use.
|
|
15
|
+
|
|
16
|
+
This package aims to combine different cardiac imaging modalities to combined 3D models. A particular focus is on the fusion of intravascular
|
|
17
|
+
imaging (either intravascular ultrasound [IVUS] or optical coherence tomography [OCT]) with a 3D geometry created from computed coronary tomography angiography (CCTA).
|
|
18
|
+
|
|
19
|
+
The main functionalities are organized into two major categories:
|
|
20
|
+
|
|
21
|
+
1. **Intravascular Alignment**: This category addresses the co-registration of intravascular frames through translation and rotation to minimize the distance between adjacent frames.
|
|
22
|
+
This approach is particularly useful for correcting misalignments introduced by cardiac motion during intravascular image acquisition. It further encompasses the alignment of
|
|
23
|
+
separate intravascular pullbacks (e.g., acquired under rest and stress conditions) as well as the co-registration of systolic and diastolic frames within the same pullback.
|
|
24
|
+
|
|
25
|
+
2. **CCTA-Intravascular Fusion**: This category covers the fusion of intravascular frames with a three-dimensional geometry reconstructed from coronary computed tomography angiography (CCTA).
|
|
26
|
+
This is particularly valuable for generating high-resolution three-dimensional models of coronary arteries by combining the high spatial resolution of intravascular imaging with the
|
|
27
|
+
three-dimensional geometry provided by CCTA. Functionalities in this category include the anatomical labeling of CCTA geometries based on centerlines, the registration of intravascular
|
|
28
|
+
frames onto a centerline, and the subsequent fusion of the resulting geometry with the CCTA reconstruction.
|
|
29
|
+
|
|
30
|
+
Intravascular image data are accepted either as CSV files following the output format of
|
|
31
|
+
`AIVUS <https://github.com/AI-in-Cardiovascular-Medicine/AIVUS-CAA>`_, an open-source tool for automated intravascular ultrasound analysis,
|
|
32
|
+
or directly as NumPy arrays, affording greater flexibility for integration with custom pipelines.
|
|
33
|
+
|
|
34
|
+
Table of Contents
|
|
35
|
+
-----------------
|
|
36
|
+
|
|
37
|
+
.. toctree::
|
|
38
|
+
:hidden:
|
|
39
|
+
|
|
40
|
+
Home <self>
|
|
41
|
+
|
|
42
|
+
.. toctree::
|
|
43
|
+
:maxdepth: 2
|
|
44
|
+
|
|
45
|
+
installation
|
|
46
|
+
Intravascular Alignment Tutorial <tutorial_intravascular>
|
|
47
|
+
CCTA Intravascular Fusion Tutorial <tutorial_ccta>
|
|
48
|
+
api/index
|
|
49
|
+
changelog
|
|
50
|
+
|
|
51
|
+
License
|
|
52
|
+
-------
|
|
53
|
+
|
|
54
|
+
This package is covered by the open source `MIT License <https://github.com/yungselm/multimoda-rs/blob/main/LICENSE>`_.
|
|
55
|
+
|
|
56
|
+
Developers
|
|
57
|
+
----------
|
|
58
|
+
|
|
59
|
+
- `Anselm Stark <https://github.com/yugnselm>`_:sup:`1,2`
|
|
60
|
+
- `Marc Ilic <https://github.com/cicram>`_:sup:`1,2`
|
|
61
|
+
- `Ali Mokthari <https://github.com/alimokh91>`_:sup:`1,2`
|
|
62
|
+
- `Pooya Mohammadi Kazaj <https://github.com/pooya-mohammadi>`_:sup:`1,2`
|
|
63
|
+
- `Isaac Shiri <https://github.com/Isaacshiri>`_:sup:`1`
|
|
64
|
+
|
|
65
|
+
:sup:`1`\ Department of Cardiology, Inselspital, Bern University Hospital, University of Bern, Switzerland
|
|
66
|
+
:sup:`2`\ Graduate School for Cellular and Biomedical Sciences, University of Bern, Bern, Switzerland
|
|
67
|
+
|
|
68
|
+
Contributing
|
|
69
|
+
------------
|
|
70
|
+
We'd welcome your contributions to multimodars. Please read the
|
|
71
|
+
`contributing guidelines <https://github.com/yungselm/multimoda-rs/blob/main/CONTRIBUTING.md>`_ on how to contribute to ``multimodars``.
|
|
72
|
+
|
|
73
|
+
Changelog
|
|
74
|
+
---------
|
|
75
|
+
|
|
76
|
+
* :doc:`changelog`
|
|
77
|
+
|
|
78
|
+
Indices and tables
|
|
79
|
+
==================
|
|
80
|
+
|
|
81
|
+
* :ref:`genindex`
|
|
82
|
+
* :ref:`search`
|