multimodars 0.4.0__tar.gz → 0.4.2__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.4.0 → multimodars-0.4.2}/CHANGELOG.md +17 -3
- {multimodars-0.4.0 → multimodars-0.4.2}/Cargo.lock +1 -1
- {multimodars-0.4.0 → multimodars-0.4.2}/Cargo.toml +2 -2
- {multimodars-0.4.0 → multimodars-0.4.2}/PKG-INFO +1 -1
- {multimodars-0.4.0 → multimodars-0.4.2}/src/ccta/adjust_mesh/label_coronary.rs +5 -6
- {multimodars-0.4.0 → multimodars-0.4.2}/src/ccta/adjust_mesh/scale_coronary.rs +10 -12
- multimodars-0.4.2/src/ccta/adjust_mesh.rs +12 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/ccta/binding/ccta_py.rs +28 -178
- {multimodars-0.4.0 → multimodars-0.4.2}/src/ccta/discretizing/projecting.rs +2 -3
- {multimodars-0.4.0 → multimodars-0.4.2}/src/ccta/discretizing/resampling.rs +2 -4
- {multimodars-0.4.0 → multimodars-0.4.2}/src/ccta/discretizing/utils.rs +2 -2
- multimodars-0.4.2/src/ccta/discretizing/vessel_tree.rs +82 -0
- multimodars-0.4.0/src/ccta/discretizing/mod.rs → multimodars-0.4.2/src/ccta/discretizing.rs +3 -6
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/binding/align.rs +3 -3
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/binding/entry.rs +111 -67
- multimodars-0.4.0/src/intravascular/binding/mod.rs → multimodars-0.4.2/src/intravascular/binding/functions.rs +3 -7
- multimodars-0.4.2/src/intravascular/binding.rs +8 -0
- multimodars-0.4.0/src/intravascular/centerline_align/mod.rs → multimodars-0.4.2/src/intravascular/centerline_align/align.rs +17 -17
- multimodars-0.4.2/src/intravascular/centerline_align.rs +5 -0
- multimodars-0.4.0/src/intravascular/io/mod.rs → multimodars-0.4.2/src/intravascular/io/build.rs +4 -21
- multimodars-0.4.2/src/intravascular/io/geometry.rs +6 -0
- multimodars-0.4.2/src/intravascular/io/input.rs +7 -0
- multimodars-0.4.2/src/intravascular/io.rs +7 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/processing/align_between.rs +1 -17
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/processing/align_within.rs +4 -4
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/processing/postprocessing.rs +3 -3
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/processing/preprocessing.rs +7 -7
- multimodars-0.4.0/src/intravascular/to_object/mod.rs → multimodars-0.4.2/src/intravascular/to_object/process.rs +4 -8
- multimodars-0.4.2/src/intravascular/to_object.rs +6 -0
- multimodars-0.4.2/src/lib.rs +88 -0
- multimodars-0.4.2/src/types/binding/py_centerline.rs +287 -0
- multimodars-0.4.2/src/types/binding/py_centerline_point.rs +83 -0
- multimodars-0.4.2/src/types/binding/py_contour.rs +432 -0
- multimodars-0.4.2/src/types/binding/py_contour_point.rs +129 -0
- multimodars-0.4.2/src/types/binding/py_discretized_vessel_tree.rs +157 -0
- multimodars-0.4.2/src/types/binding/py_frame.rs +201 -0
- multimodars-0.4.2/src/types/binding/py_geometry.rs +468 -0
- multimodars-0.4.2/src/types/binding/py_geometry_pair.rs +226 -0
- multimodars-0.4.2/src/types/binding/py_input_data.rs +258 -0
- multimodars-0.4.2/src/types/binding/py_record.rs +87 -0
- multimodars-0.4.2/src/types/binding.rs +21 -0
- multimodars-0.4.0/src/intravascular/io/input.rs → multimodars-0.4.2/src/types/native/centerline.rs +6 -433
- multimodars-0.4.2/src/types/native/centerline_point.rs +22 -0
- multimodars-0.4.2/src/types/native/contour.rs +963 -0
- multimodars-0.4.2/src/types/native/contour_point.rs +227 -0
- multimodars-0.4.0/src/ccta/discretizing/vessel_tree.rs → multimodars-0.4.2/src/types/native/discretized_tree.rs +7 -105
- multimodars-0.4.2/src/types/native/frame.rs +845 -0
- multimodars-0.4.2/src/types/native/geometry.rs +1234 -0
- multimodars-0.4.2/src/types/native/geometry_pair.rs +20 -0
- multimodars-0.4.2/src/types/native/input_data.rs +218 -0
- multimodars-0.4.2/src/types/native/record.rs +31 -0
- multimodars-0.4.2/src/types/native.rs +21 -0
- multimodars-0.4.2/src/types.rs +2 -0
- multimodars-0.4.0/src/ccta/adjust_mesh/mod.rs +0 -40
- multimodars-0.4.0/src/intravascular/binding/classes.rs +0 -2144
- multimodars-0.4.0/src/intravascular/io/geometry.rs +0 -3071
- multimodars-0.4.0/src/lib.rs +0 -83
- {multimodars-0.4.0 → multimodars-0.4.2}/.gitattributes +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/.github/workflows/CI.yml +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/.gitignore +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/.pre-commit-config.yaml +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/.readthedocs.yaml +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/CITATION.cff +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/CONTRIBUTING.md +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/LICENSE +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/README.md +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/ROADMAP.MD +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/benchmarks/BENCHMARK_PLAN.md +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/benchmarks/benchmark_bruteforce_stepsize.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/benchmarks/benchmark_cpu_scaling.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/benchmarks/results/bruteforce_stepsize.png +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/benchmarks/results/cpu_scaling.png +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/idealized_geometry/branch_diastolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/idealized_geometry/branch_systolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/idealized_geometry/calcium_diastolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/idealized_geometry/calcium_systolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/idealized_geometry/diastolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/idealized_geometry/diastolic_reference_points.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/idealized_geometry/eem_diastolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/idealized_geometry/eem_systolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/idealized_geometry/systolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/idealized_geometry/systolic_reference_points.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_full/branch_diastolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_full/branch_systolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_full/calcium_diastolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_full/calcium_systolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_full/diastolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_full/diastolic_reference_points.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_full/eem_diastolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_full/eem_systolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_full/systolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_full/systolic_reference_points.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_rest/combined_sorted_manual.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_rest/diastolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_rest/diastolic_reference_points.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_rest/systolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_rest/systolic_reference_points.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_stress/combined_sorted_manual.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_stress/diastolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_stress/diastolic_reference_points.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_stress/systolic_contours.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/data/fixtures/ivus_stress/systolic_reference_points.csv +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/media/coronary_artery_disease.jpg +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/media/dynamic_lumen_changes.png +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/media/multimoda-rs.jpg +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/__init__.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/_converters.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/_processing.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/ccta/__init__.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/ccta/debug_plots.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/ccta/discretization_map.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/ccta/fixing_functions.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/ccta/labeling.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/ccta/manipulating.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/io/__init__.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/io/read_geometrical.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/io/write_geometries.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/multimodars.pyi +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/multimodars/py.typed +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/paper/REVIEWER1.md +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/paper/REVIEWER2.md +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/paper/bibliography.bib +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/paper/figures/Figure1.jpg +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/paper/figures/Figure2.jpg +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/paper/figures/Figure3.png +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/paper/figures/Figure4.jpg +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/paper/paper.md +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/pyproject.toml +0 -0
- /multimodars-0.4.0/src/ccta/binding/mod.rs → /multimodars-0.4.2/src/ccta/binding.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/ccta/discretizing/plan.md +0 -0
- /multimodars-0.4.0/src/ccta/mod.rs → /multimodars-0.4.2/src/ccta.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/centerline_align/align_algorithms.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/centerline_align/preprocessing.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/io/integrity_check.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/io/output.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/processing/process_utils.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/processing/wall.rs +0 -0
- /multimodars-0.4.0/src/intravascular/processing/mod.rs → /multimodars-0.4.2/src/intravascular/processing.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/to_object/interpolation.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/to_object/texture.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/to_object/write_mtl.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/utils/general_utils.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/src/intravascular/utils/test_utils.rs +0 -0
- /multimodars-0.4.0/src/intravascular/utils/mod.rs → /multimodars-0.4.2/src/intravascular/utils.rs +0 -0
- /multimodars-0.4.0/src/intravascular/mod.rs → /multimodars-0.4.2/src/intravascular.rs +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/tests/conftest.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/tests/test_ccta.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/tests/test_converters.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/tests/test_core.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/tests/test_intravascular.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/tests/test_wrappers.py +0 -0
- {multimodars-0.4.0 → multimodars-0.4.2}/tests/tests_todo.md +0 -0
|
@@ -3,11 +3,26 @@
|
|
|
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.4.2] - 2026-06-04
|
|
7
|
+
Large internal refactor to improve readability and decouple modules. No behaviour change.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- All native types and Python bindings extracted from scattered files into a unified `src/types/native/` and
|
|
11
|
+
`src/types/binding/` module.
|
|
12
|
+
- Several large files split into focused submodules (`binding/classes.rs` removed, `io/geometry.rs`, `centerline_align.rs`, `to_object.rs` split).
|
|
13
|
+
- `Point3D` trait added and shared across `ContourPoint`, `CenterlinePoint`, and `(f64, f64, f64)`, simplified some functions with this.
|
|
14
|
+
|
|
15
|
+
## [0.4.1] - 2026-06-02
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Rust `use` declarations now follow the idiomatic convention of importing the parent module for
|
|
19
|
+
functions (e.g. `use crate::ccta::discretizing;` -> `discretizing::discretize_vessel_rs(...)`)
|
|
20
|
+
and importing types/structs/enums directly. No behaviour change; purely internal style cleanup
|
|
21
|
+
across 14 source files.
|
|
22
|
+
|
|
6
23
|
## [0.4.0] - 2026-05-25
|
|
7
|
-
This version introduces backwards compatibility breaking changes.
|
|
8
24
|
|
|
9
25
|
### Added
|
|
10
|
-
|
|
11
26
|
**Vessel-tree discretization pipeline**
|
|
12
27
|
|
|
13
28
|
- `prepare_centerlines(rca_cl, lca_cl, results_dict, branch_sigma, control_plot)`: one-call
|
|
@@ -47,7 +62,6 @@ the style of `label_geometry`'s control plot and working correctly in all enviro
|
|
|
47
62
|
- `plot_results_key`, `compare_centerline_scaling`: migrated from Plotly to trimesh.
|
|
48
63
|
|
|
49
64
|
### Changed
|
|
50
|
-
|
|
51
65
|
**Alignment reference point naming** (`align_three_point`, `align_combined`, `align_manual`)
|
|
52
66
|
|
|
53
67
|
The three landmark parameters have been renamed for anatomical clarity:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "multimodars"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.2"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
license = "MIT"
|
|
6
6
|
readme = "README.md"
|
|
@@ -15,7 +15,7 @@ csv = "1.4.0"
|
|
|
15
15
|
serde = { version = "1.0.228", features = ["derive"]}
|
|
16
16
|
image = "0.25.10"
|
|
17
17
|
nalgebra = "0.35.0"
|
|
18
|
-
toml = "1.1.2
|
|
18
|
+
toml = "1.1.2"
|
|
19
19
|
rayon = "1.12.0"
|
|
20
20
|
crossbeam = "0.8.4"
|
|
21
21
|
anyhow = "1.0.102"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
use
|
|
2
|
-
use crate::intravascular::io::input::{Centerline, CenterlinePoint};
|
|
1
|
+
use crate::types::native::{Centerline, CenterlinePoint};
|
|
3
2
|
use rayon::prelude::*;
|
|
4
3
|
use std::collections::HashSet;
|
|
5
4
|
|
|
@@ -178,9 +177,9 @@ pub fn remove_occluded_points_ray_triangle_rust(
|
|
|
178
177
|
}
|
|
179
178
|
|
|
180
179
|
fn point_to_triangle_distance(point: &(f64, f64, f64), triangle: &Triangle) -> f64 {
|
|
181
|
-
let dist_v0 = calculate_squared_distance(point, &triangle.v0);
|
|
182
|
-
let dist_v1 = calculate_squared_distance(point, &triangle.v1);
|
|
183
|
-
let dist_v2 = calculate_squared_distance(point, &triangle.v2);
|
|
180
|
+
let dist_v0 = super::calculate_squared_distance(point, &triangle.v0);
|
|
181
|
+
let dist_v1 = super::calculate_squared_distance(point, &triangle.v1);
|
|
182
|
+
let dist_v2 = super::calculate_squared_distance(point, &triangle.v2);
|
|
184
183
|
|
|
185
184
|
dist_v0.min(dist_v1).min(dist_v2)
|
|
186
185
|
}
|
|
@@ -299,7 +298,7 @@ fn find_points_inside_of_sphere(sphere: &BoundingSphere, point: &(f64, f64, f64)
|
|
|
299
298
|
#[cfg(test)]
|
|
300
299
|
mod test_find_cl_bounded_points {
|
|
301
300
|
use super::*;
|
|
302
|
-
use crate::
|
|
301
|
+
use crate::types::native::ContourPoint;
|
|
303
302
|
|
|
304
303
|
#[test]
|
|
305
304
|
fn test_find_points_simple_geometry() {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
use
|
|
2
|
-
use crate::intravascular::io::geometry::Frame;
|
|
3
|
-
use crate::intravascular::io::input::{Centerline, CenterlinePoint};
|
|
1
|
+
use crate::types::native::{Centerline, CenterlinePoint, Frame};
|
|
4
2
|
use rayon::prelude::*;
|
|
5
3
|
use std::collections::HashSet;
|
|
6
4
|
|
|
@@ -17,8 +15,8 @@ pub fn centerline_based_wall_diameter_optimization(
|
|
|
17
15
|
|
|
18
16
|
// find closest centerline point
|
|
19
17
|
let closest_cl = match centerline.points.iter().min_by(|a, b| {
|
|
20
|
-
let dist_a = calculate_squared_distance(*a, ref_point_coronary);
|
|
21
|
-
let dist_b = calculate_squared_distance(*b, ref_point_coronary);
|
|
18
|
+
let dist_a = super::calculate_squared_distance(*a, ref_point_coronary);
|
|
19
|
+
let dist_b = super::calculate_squared_distance(*b, ref_point_coronary);
|
|
22
20
|
dist_a
|
|
23
21
|
.partial_cmp(&dist_b)
|
|
24
22
|
.unwrap_or(std::cmp::Ordering::Equal)
|
|
@@ -28,8 +26,8 @@ pub fn centerline_based_wall_diameter_optimization(
|
|
|
28
26
|
};
|
|
29
27
|
|
|
30
28
|
let closest_aortic: &Point3D = match aortic_points.iter().min_by(|a, b| {
|
|
31
|
-
let dist_a = calculate_squared_distance(*a, ref_point_coronary);
|
|
32
|
-
let dist_b = calculate_squared_distance(*b, ref_point_coronary);
|
|
29
|
+
let dist_a = super::calculate_squared_distance(*a, ref_point_coronary);
|
|
30
|
+
let dist_b = super::calculate_squared_distance(*b, ref_point_coronary);
|
|
33
31
|
dist_a
|
|
34
32
|
.partial_cmp(&dist_b)
|
|
35
33
|
.unwrap_or(std::cmp::Ordering::Equal)
|
|
@@ -150,7 +148,7 @@ fn find_region_points(
|
|
|
150
148
|
.map(|(i, a_pt)| {
|
|
151
149
|
let min_sq = reference_points
|
|
152
150
|
.iter()
|
|
153
|
-
.map(|r_pt| calculate_squared_distance(a_pt, r_pt))
|
|
151
|
+
.map(|r_pt| super::calculate_squared_distance(a_pt, r_pt))
|
|
154
152
|
.fold(f64::INFINITY, |m, v| if v < m { v } else { m });
|
|
155
153
|
(i, min_sq)
|
|
156
154
|
})
|
|
@@ -199,7 +197,7 @@ fn symmetric_nn_distance(a: &[Point3D], b: &[Point3D]) -> f64 {
|
|
|
199
197
|
.par_iter()
|
|
200
198
|
.map(|pa| {
|
|
201
199
|
b.iter()
|
|
202
|
-
.map(|pb| calculate_squared_distance(pa, pb))
|
|
200
|
+
.map(|pb| super::calculate_squared_distance(pa, pb))
|
|
203
201
|
.fold(f64::INFINITY, |m, v| if v < m { v } else { m })
|
|
204
202
|
})
|
|
205
203
|
.sum();
|
|
@@ -210,7 +208,7 @@ fn symmetric_nn_distance(a: &[Point3D], b: &[Point3D]) -> f64 {
|
|
|
210
208
|
.par_iter()
|
|
211
209
|
.map(|pb| {
|
|
212
210
|
a.iter()
|
|
213
|
-
.map(|pa| calculate_squared_distance(pb, pa))
|
|
211
|
+
.map(|pa| super::calculate_squared_distance(pb, pa))
|
|
214
212
|
.fold(f64::INFINITY, |m, v| if v < m { v } else { m })
|
|
215
213
|
})
|
|
216
214
|
.sum();
|
|
@@ -265,7 +263,7 @@ fn find_closest_centerline_point_optimized(
|
|
|
265
263
|
let mut closest_point = ¢erline.points[0];
|
|
266
264
|
|
|
267
265
|
for centerline_point in ¢erline.points {
|
|
268
|
-
let distance_squared = calculate_squared_distance(&point, centerline_point);
|
|
266
|
+
let distance_squared = super::calculate_squared_distance(&point, centerline_point);
|
|
269
267
|
if distance_squared < min_distance_squared {
|
|
270
268
|
min_distance_squared = distance_squared;
|
|
271
269
|
closest_point = centerline_point;
|
|
@@ -419,7 +417,7 @@ pub fn clean_up_non_section_points(
|
|
|
419
417
|
|
|
420
418
|
#[cfg(test)]
|
|
421
419
|
mod tests {
|
|
422
|
-
use crate::
|
|
420
|
+
use crate::types::native::{CenterlinePoint, ContourPoint};
|
|
423
421
|
use nalgebra::Vector3;
|
|
424
422
|
|
|
425
423
|
use super::*;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
pub mod label_coronary;
|
|
2
|
+
pub mod scale_coronary;
|
|
3
|
+
use crate::types::native::Point3D;
|
|
4
|
+
|
|
5
|
+
/// Squared Euclidean distance between any two [`Point3D`] values.
|
|
6
|
+
/// Use the squared form to avoid a `sqrt` when only ordering matters.
|
|
7
|
+
pub(super) fn calculate_squared_distance<A: Point3D, B: Point3D>(a: &A, b: &B) -> f64 {
|
|
8
|
+
let dx = a.x() - b.x();
|
|
9
|
+
let dy = a.y() - b.y();
|
|
10
|
+
let dz = a.z() - b.z();
|
|
11
|
+
dx * dx + dy * dy + dz * dz
|
|
12
|
+
}
|
|
@@ -1,177 +1,16 @@
|
|
|
1
|
-
// src/ccta/binding/
|
|
1
|
+
// src/ccta/binding/ccta_py.rs
|
|
2
2
|
use std::collections::{HashMap, HashSet};
|
|
3
3
|
|
|
4
|
-
use crate::ccta::adjust_mesh::label_coronary
|
|
5
|
-
use crate::ccta::adjust_mesh::label_coronary::
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
use crate::
|
|
9
|
-
|
|
10
|
-
centerline_based_diameter_optimization, centerline_based_wall_diameter_optimization,
|
|
11
|
-
clean_up_non_section_points, find_points_by_cl_region_rs,
|
|
12
|
-
};
|
|
13
|
-
use crate::ccta::discretizing::discretize_vessel_rs;
|
|
14
|
-
use crate::ccta::discretizing::vessel_tree::DiscretizedVesselTree;
|
|
15
|
-
use crate::intravascular::binding::classes::{PyCenterline, PyContour, PyFrame};
|
|
4
|
+
use crate::ccta::adjust_mesh::label_coronary;
|
|
5
|
+
use crate::ccta::adjust_mesh::label_coronary::Triangle;
|
|
6
|
+
use crate::ccta::adjust_mesh::scale_coronary;
|
|
7
|
+
use crate::ccta::discretizing;
|
|
8
|
+
use crate::types::binding::{PyCenterline, PyContour, PyDiscretizedVesselTree, PyFrame};
|
|
9
|
+
use crate::types::native::DiscretizedVesselTree;
|
|
16
10
|
use pyo3::prelude::*;
|
|
17
11
|
|
|
18
12
|
type Point3D = (f64, f64, f64);
|
|
19
13
|
type TriangleTuple = (Point3D, Point3D, Point3D);
|
|
20
|
-
/// (main_ref, clock_ref, counter_clock_ref) — all three as plain xyz tuples.
|
|
21
|
-
type RefTriplet = (Point3D, Point3D, Point3D);
|
|
22
|
-
|
|
23
|
-
// ─── PyDiscretizedVesselTree ──────────────────────────────────────────────────
|
|
24
|
-
|
|
25
|
-
/// Fully discretized coronary vessel tree (aorta + RCA + LCA + side branches).
|
|
26
|
-
///
|
|
27
|
-
/// Attributes
|
|
28
|
-
/// ----------
|
|
29
|
-
/// discretized_aorta : list of PyContour
|
|
30
|
-
/// Cross-sectional contours along the aortic centerline.
|
|
31
|
-
/// discretized_rca_main : list of PyContour
|
|
32
|
-
/// Cross-sectional contours along the RCA main vessel.
|
|
33
|
-
/// discretized_lca_main : list of PyContour
|
|
34
|
-
/// Cross-sectional contours along the LCA main vessel.
|
|
35
|
-
/// rca_branches : list of list of PyContour
|
|
36
|
-
/// Per-side-branch contour lists for the RCA. ``rca_branches[i]``
|
|
37
|
-
/// corresponds to RCA branch_id ``i + 1``.
|
|
38
|
-
/// lca_branches : list of list of PyContour
|
|
39
|
-
/// Per-side-branch contour lists for the LCA.
|
|
40
|
-
/// rca_references : list of tuple
|
|
41
|
-
/// Orientation triplets ``(main_ref, clock_ref, counter_clock_ref)`` along
|
|
42
|
-
/// the RCA, sorted proximal → distal. Each element is a 3-tuple of
|
|
43
|
-
/// ``(x, y, z)`` coordinate tuples.
|
|
44
|
-
/// lca_references : list of tuple
|
|
45
|
-
/// Same structure for the LCA.
|
|
46
|
-
/// ao_rca : tuple of float
|
|
47
|
-
/// Centroid ``(x, y, z)`` of the aorta slice closest to the RCA ostium.
|
|
48
|
-
/// ao_lca : tuple of float
|
|
49
|
-
/// Centroid ``(x, y, z)`` of the aorta slice closest to the LCA ostium.
|
|
50
|
-
#[pyclass(skip_from_py_object)]
|
|
51
|
-
#[derive(Debug, Clone)]
|
|
52
|
-
pub struct PyDiscretizedVesselTree {
|
|
53
|
-
#[pyo3(get, set)]
|
|
54
|
-
pub discretized_aorta: Vec<PyContour>,
|
|
55
|
-
#[pyo3(get, set)]
|
|
56
|
-
pub discretized_rca_main: Vec<PyContour>,
|
|
57
|
-
#[pyo3(get, set)]
|
|
58
|
-
pub discretized_lca_main: Vec<PyContour>,
|
|
59
|
-
#[pyo3(get, set)]
|
|
60
|
-
pub rca_branches: Vec<Vec<PyContour>>,
|
|
61
|
-
#[pyo3(get, set)]
|
|
62
|
-
pub lca_branches: Vec<Vec<PyContour>>,
|
|
63
|
-
#[pyo3(get)]
|
|
64
|
-
pub rca_references: Vec<RefTriplet>,
|
|
65
|
-
#[pyo3(get)]
|
|
66
|
-
pub lca_references: Vec<RefTriplet>,
|
|
67
|
-
#[pyo3(get, set)]
|
|
68
|
-
pub ao_rca: Point3D,
|
|
69
|
-
#[pyo3(get, set)]
|
|
70
|
-
pub ao_lca: Point3D,
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
#[pymethods]
|
|
74
|
-
impl PyDiscretizedVesselTree {
|
|
75
|
-
fn __repr__(&self) -> String {
|
|
76
|
-
format!(
|
|
77
|
-
"DiscretizedVesselTree(ao={}, rca_main={}, lca_main={}, rca_branches={}, lca_branches={}, rca_refs={}, lca_refs={})",
|
|
78
|
-
self.discretized_aorta.len(),
|
|
79
|
-
self.discretized_rca_main.len(),
|
|
80
|
-
self.discretized_lca_main.len(),
|
|
81
|
-
self.rca_branches.len(),
|
|
82
|
-
self.lca_branches.len(),
|
|
83
|
-
self.rca_references.len(),
|
|
84
|
-
self.lca_references.len(),
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/// Recompute orientation reference triplets and aortic ostium centroids
|
|
89
|
-
/// from the current contour data.
|
|
90
|
-
///
|
|
91
|
-
/// Call this after replacing contours (e.g. with B-spline fits) so that
|
|
92
|
-
/// ``rca_references``, ``lca_references``, ``ao_rca``, and ``ao_lca``
|
|
93
|
-
/// reflect the updated geometry.
|
|
94
|
-
pub fn calculate_ref_pts(&mut self) -> PyResult<()> {
|
|
95
|
-
let convert =
|
|
96
|
-
|contours: &[PyContour]| -> PyResult<Vec<crate::intravascular::io::geometry::Contour>> {
|
|
97
|
-
contours.iter().map(|c| c.to_rust_contour()).collect()
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
let rust_aorta = convert(&self.discretized_aorta)?;
|
|
101
|
-
let rust_rca = convert(&self.discretized_rca_main)?;
|
|
102
|
-
let rust_lca = convert(&self.discretized_lca_main)?;
|
|
103
|
-
let rust_rca_branches: PyResult<Vec<Vec<_>>> =
|
|
104
|
-
self.rca_branches.iter().map(|b| convert(b)).collect();
|
|
105
|
-
let rust_lca_branches: PyResult<Vec<Vec<_>>> =
|
|
106
|
-
self.lca_branches.iter().map(|b| convert(b)).collect();
|
|
107
|
-
|
|
108
|
-
let tree = DiscretizedVesselTree {
|
|
109
|
-
discretized_aorta: rust_aorta,
|
|
110
|
-
discretized_rca_main: rust_rca,
|
|
111
|
-
discretized_lca_main: rust_lca,
|
|
112
|
-
rca_branches: rust_rca_branches?,
|
|
113
|
-
lca_branches: rust_lca_branches?,
|
|
114
|
-
spacing: 1.0,
|
|
115
|
-
rca_references: vec![],
|
|
116
|
-
lca_references: vec![],
|
|
117
|
-
ao_rca: (0.0, 0.0, 0.0),
|
|
118
|
-
ao_lca: (0.0, 0.0, 0.0),
|
|
119
|
-
pts_cusp_rcc: None,
|
|
120
|
-
pts_cusp_lcc: None,
|
|
121
|
-
pts_cusp_acc: None,
|
|
122
|
-
index_stj_slice: None,
|
|
123
|
-
index_aa: None,
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
let updated = tree.calculate_ref_pts();
|
|
127
|
-
self.rca_references = updated
|
|
128
|
-
.rca_references
|
|
129
|
-
.into_iter()
|
|
130
|
-
.map(|r| (r.main_ref, r.clock_ref, r.counter_clock_ref))
|
|
131
|
-
.collect();
|
|
132
|
-
self.lca_references = updated
|
|
133
|
-
.lca_references
|
|
134
|
-
.into_iter()
|
|
135
|
-
.map(|r| (r.main_ref, r.clock_ref, r.counter_clock_ref))
|
|
136
|
-
.collect();
|
|
137
|
-
self.ao_rca = updated.ao_rca;
|
|
138
|
-
self.ao_lca = updated.ao_lca;
|
|
139
|
-
|
|
140
|
-
Ok(())
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
impl From<DiscretizedVesselTree> for PyDiscretizedVesselTree {
|
|
145
|
-
fn from(t: DiscretizedVesselTree) -> Self {
|
|
146
|
-
Self {
|
|
147
|
-
discretized_aorta: t.discretized_aorta.iter().map(PyContour::from).collect(),
|
|
148
|
-
discretized_rca_main: t.discretized_rca_main.iter().map(PyContour::from).collect(),
|
|
149
|
-
discretized_lca_main: t.discretized_lca_main.iter().map(PyContour::from).collect(),
|
|
150
|
-
rca_branches: t
|
|
151
|
-
.rca_branches
|
|
152
|
-
.iter()
|
|
153
|
-
.map(|b| b.iter().map(PyContour::from).collect())
|
|
154
|
-
.collect(),
|
|
155
|
-
lca_branches: t
|
|
156
|
-
.lca_branches
|
|
157
|
-
.iter()
|
|
158
|
-
.map(|b| b.iter().map(PyContour::from).collect())
|
|
159
|
-
.collect(),
|
|
160
|
-
rca_references: t
|
|
161
|
-
.rca_references
|
|
162
|
-
.into_iter()
|
|
163
|
-
.map(|r| (r.main_ref, r.clock_ref, r.counter_clock_ref))
|
|
164
|
-
.collect(),
|
|
165
|
-
lca_references: t
|
|
166
|
-
.lca_references
|
|
167
|
-
.into_iter()
|
|
168
|
-
.map(|r| (r.main_ref, r.clock_ref, r.counter_clock_ref))
|
|
169
|
-
.collect(),
|
|
170
|
-
ao_rca: t.ao_rca,
|
|
171
|
-
ao_lca: t.ao_lca,
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
14
|
|
|
176
15
|
/// Find points bounded by spheres along a coronary vessel centerline.
|
|
177
16
|
///
|
|
@@ -211,7 +50,8 @@ pub fn find_centerline_bounded_points_simple(
|
|
|
211
50
|
let rust_centerline = centerline.to_rust_centerline();
|
|
212
51
|
|
|
213
52
|
// Call Rust function directly - no complex conversions needed
|
|
214
|
-
let result_points =
|
|
53
|
+
let result_points =
|
|
54
|
+
label_coronary::find_centerline_bounded_points(rust_centerline, &points, radius);
|
|
215
55
|
|
|
216
56
|
Ok(result_points)
|
|
217
57
|
}
|
|
@@ -257,7 +97,7 @@ pub fn remove_occluded_points_ray_triangle(
|
|
|
257
97
|
.map(|(v0, v1, v2)| Triangle::new(v0, v1, v2))
|
|
258
98
|
.collect();
|
|
259
99
|
|
|
260
|
-
let result = remove_occluded_points_ray_triangle_rust(
|
|
100
|
+
let result = label_coronary::remove_occluded_points_ray_triangle_rust(
|
|
261
101
|
&rust_centerline_coronary,
|
|
262
102
|
&rust_centerline_aorta,
|
|
263
103
|
range_coronary,
|
|
@@ -291,8 +131,11 @@ pub fn adjust_diameter_centerline_morphing_simple(
|
|
|
291
131
|
) -> PyResult<Vec<Point3D>> {
|
|
292
132
|
let rust_centerline = centerline.to_rust_centerline();
|
|
293
133
|
|
|
294
|
-
let result_points =
|
|
295
|
-
|
|
134
|
+
let result_points = scale_coronary::centerline_based_diameter_morphing(
|
|
135
|
+
&rust_centerline,
|
|
136
|
+
&points,
|
|
137
|
+
diameter_adjustment_mm,
|
|
138
|
+
);
|
|
296
139
|
|
|
297
140
|
Ok(result_points)
|
|
298
141
|
}
|
|
@@ -332,7 +175,8 @@ pub fn find_points_by_cl_region(
|
|
|
332
175
|
.map(|f| f.to_rust_frame())
|
|
333
176
|
.collect::<Result<_, _>>()?;
|
|
334
177
|
|
|
335
|
-
let result_points =
|
|
178
|
+
let result_points =
|
|
179
|
+
scale_coronary::find_points_by_cl_region_rs(&rust_centerline, &rust_frames, &points);
|
|
336
180
|
|
|
337
181
|
Ok(result_points)
|
|
338
182
|
}
|
|
@@ -367,7 +211,7 @@ pub fn clean_outlier_points(
|
|
|
367
211
|
neighborhood_radius: f64,
|
|
368
212
|
min_neigbor_ratio: f64,
|
|
369
213
|
) -> PyResult<(Vec<Point3D>, Vec<Point3D>)> {
|
|
370
|
-
let result_points = clean_up_non_section_points(
|
|
214
|
+
let result_points = scale_coronary::clean_up_non_section_points(
|
|
371
215
|
points_to_cleanup,
|
|
372
216
|
reference_points,
|
|
373
217
|
neighborhood_radius,
|
|
@@ -414,7 +258,7 @@ pub fn find_proximal_distal_scaling(
|
|
|
414
258
|
distal_reference: Vec<Point3D>,
|
|
415
259
|
) -> PyResult<(f64, f64)> {
|
|
416
260
|
let rust_centerline = centerline.to_rust_centerline();
|
|
417
|
-
let (prox_dist, distal_dist) = centerline_based_diameter_optimization(
|
|
261
|
+
let (prox_dist, distal_dist) = scale_coronary::centerline_based_diameter_optimization(
|
|
418
262
|
&anomalous_points,
|
|
419
263
|
n_proximal,
|
|
420
264
|
n_distal,
|
|
@@ -451,7 +295,7 @@ pub fn find_aortic_scaling(
|
|
|
451
295
|
centerline: PyCenterline,
|
|
452
296
|
) -> PyResult<f64> {
|
|
453
297
|
let rust_centerline = centerline.to_rust_centerline();
|
|
454
|
-
let dist = centerline_based_aortic_diameter_optimization(
|
|
298
|
+
let dist = scale_coronary::centerline_based_aortic_diameter_optimization(
|
|
455
299
|
&intramural_points,
|
|
456
300
|
&reference_points,
|
|
457
301
|
&rust_centerline,
|
|
@@ -490,7 +334,7 @@ pub fn find_aortic_wall_scaling(
|
|
|
490
334
|
aortic_pts: Vec<Point3D>,
|
|
491
335
|
) -> PyResult<f64> {
|
|
492
336
|
let rust_centerline = cl_aorta.to_rust_centerline();
|
|
493
|
-
let dist = centerline_based_wall_diameter_optimization(
|
|
337
|
+
let dist = scale_coronary::centerline_based_wall_diameter_optimization(
|
|
494
338
|
&rust_centerline,
|
|
495
339
|
&ref_pt_coronary,
|
|
496
340
|
&aortic_pts,
|
|
@@ -586,7 +430,13 @@ pub fn discretize_vessel(
|
|
|
586
430
|
n_points: usize,
|
|
587
431
|
) -> PyResult<Vec<PyContour>> {
|
|
588
432
|
let rust_centerline = centerline.to_rust_centerline();
|
|
589
|
-
let contours = discretize_vessel_rs(
|
|
433
|
+
let contours = discretizing::discretize_vessel_rs(
|
|
434
|
+
&rust_centerline,
|
|
435
|
+
&points,
|
|
436
|
+
branch_id,
|
|
437
|
+
step_size,
|
|
438
|
+
n_points,
|
|
439
|
+
);
|
|
590
440
|
Ok(contours.iter().map(PyContour::from).collect())
|
|
591
441
|
}
|
|
592
442
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
use crate::
|
|
2
|
-
use crate::intravascular::io::input::{Centerline, CenterlinePoint, ContourPoint};
|
|
1
|
+
use crate::types::native::{Centerline, CenterlinePoint, Contour, ContourPoint, ContourType};
|
|
3
2
|
use nalgebra::Vector3;
|
|
4
3
|
|
|
5
4
|
/// Walks branch `branch_id` at uniform arc-length steps of `step_size`, assigns each mesh point
|
|
@@ -206,7 +205,7 @@ fn interpolate_branch_at_s(
|
|
|
206
205
|
#[cfg(test)]
|
|
207
206
|
mod tests {
|
|
208
207
|
use super::*;
|
|
209
|
-
use crate::
|
|
208
|
+
use crate::types::native::{Centerline, CenterlinePoint, ContourPoint};
|
|
210
209
|
use nalgebra::Vector3;
|
|
211
210
|
|
|
212
211
|
fn cp(idx: u32, x: f64, y: f64, z: f64) -> ContourPoint {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
use crate::
|
|
2
|
-
use crate::intravascular::io::input::ContourPoint;
|
|
1
|
+
use crate::types::native::{Contour, ContourPoint};
|
|
3
2
|
use nalgebra::Vector3;
|
|
4
3
|
|
|
5
4
|
/// Filters and resamples raw projected slices from `walk_centerline_slices`:
|
|
@@ -230,8 +229,7 @@ fn catmull_rom(
|
|
|
230
229
|
#[cfg(test)]
|
|
231
230
|
mod tests {
|
|
232
231
|
use super::*;
|
|
233
|
-
use crate::
|
|
234
|
-
use crate::intravascular::io::input::ContourPoint;
|
|
232
|
+
use crate::types::native::{Contour, ContourPoint, ContourType};
|
|
235
233
|
|
|
236
234
|
fn make_point(x: f64, y: f64, z: f64) -> ContourPoint {
|
|
237
235
|
ContourPoint {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
use crate::
|
|
1
|
+
use crate::types::native::{Centerline, CenterlinePoint, ContourPoint};
|
|
2
2
|
use nalgebra::Vector3;
|
|
3
3
|
|
|
4
4
|
/// Smooths centerline positions with a Gaussian kernel (per branch) and recomputes normals.
|
|
@@ -149,7 +149,7 @@ pub fn smooth_centerline(centerline: &Centerline, sigma: f64) -> Centerline {
|
|
|
149
149
|
#[cfg(test)]
|
|
150
150
|
mod tests {
|
|
151
151
|
use super::*;
|
|
152
|
-
use crate::
|
|
152
|
+
use crate::types::native::ContourPoint;
|
|
153
153
|
|
|
154
154
|
fn make_centerline(pts: &[(f64, f64, f64)]) -> Centerline {
|
|
155
155
|
let contour_pts: Vec<ContourPoint> = pts
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
use crate::types::native::{Centerline, Contour, DiscretizedVesselTree};
|
|
2
|
+
use anyhow::Result;
|
|
3
|
+
|
|
4
|
+
impl DiscretizedVesselTree {
|
|
5
|
+
/// Discretize the full vessel tree from pre-labelled point sets.
|
|
6
|
+
///
|
|
7
|
+
/// Smooths all three centerlines with a Gaussian (σ = 2.5 points) before
|
|
8
|
+
/// discretizing, then processes:
|
|
9
|
+
/// - aorta (branch 0)
|
|
10
|
+
/// - RCA main vessel (`branch_id_rca`, usually 0)
|
|
11
|
+
/// - LCA main vessel (`branch_id_lca`, usually 0)
|
|
12
|
+
/// - every RCA side branch: `side_branches_rca[i]` → branch_id `i + 1`
|
|
13
|
+
/// - every LCA side branch: `side_branches_lca[i]` → branch_id `i + 1`
|
|
14
|
+
///
|
|
15
|
+
/// `side_branches_rca` / `side_branches_lca` come from `label_branches` results:
|
|
16
|
+
/// `results["rca_points_side_1"]`, `results["rca_points_side_2"]`, …, in order.
|
|
17
|
+
pub fn from_results_dict(
|
|
18
|
+
ao_cl: &Centerline,
|
|
19
|
+
rca_cl: &Centerline,
|
|
20
|
+
lca_cl: &Centerline,
|
|
21
|
+
points_ao: &[(f64, f64, f64)],
|
|
22
|
+
points_rca_main: &[(f64, f64, f64)],
|
|
23
|
+
points_lca_main: &[(f64, f64, f64)],
|
|
24
|
+
side_branches_rca: Vec<Vec<(f64, f64, f64)>>,
|
|
25
|
+
side_branches_lca: Vec<Vec<(f64, f64, f64)>>,
|
|
26
|
+
branch_id_rca: u32,
|
|
27
|
+
branch_id_lca: u32,
|
|
28
|
+
step_size: f64,
|
|
29
|
+
n_points: usize,
|
|
30
|
+
) -> Result<DiscretizedVesselTree> {
|
|
31
|
+
let discretized_aorta =
|
|
32
|
+
super::discretize_vessel_rs(ao_cl, points_ao, 0, step_size, n_points);
|
|
33
|
+
let discretized_rca_main = super::discretize_vessel_rs(
|
|
34
|
+
rca_cl,
|
|
35
|
+
points_rca_main,
|
|
36
|
+
branch_id_rca,
|
|
37
|
+
step_size,
|
|
38
|
+
n_points,
|
|
39
|
+
);
|
|
40
|
+
let discretized_lca_main = super::discretize_vessel_rs(
|
|
41
|
+
lca_cl,
|
|
42
|
+
points_lca_main,
|
|
43
|
+
branch_id_lca,
|
|
44
|
+
step_size,
|
|
45
|
+
n_points,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
let rca_branches: Vec<Vec<Contour>> = side_branches_rca
|
|
49
|
+
.iter()
|
|
50
|
+
.enumerate()
|
|
51
|
+
.map(|(i, pts)| {
|
|
52
|
+
super::discretize_vessel_rs(rca_cl, pts, (i + 1) as u32, step_size, n_points)
|
|
53
|
+
})
|
|
54
|
+
.collect();
|
|
55
|
+
|
|
56
|
+
let lca_branches: Vec<Vec<Contour>> = side_branches_lca
|
|
57
|
+
.iter()
|
|
58
|
+
.enumerate()
|
|
59
|
+
.map(|(i, pts)| {
|
|
60
|
+
super::discretize_vessel_rs(lca_cl, pts, (i + 1) as u32, step_size, n_points)
|
|
61
|
+
})
|
|
62
|
+
.collect();
|
|
63
|
+
|
|
64
|
+
Ok(DiscretizedVesselTree {
|
|
65
|
+
discretized_aorta,
|
|
66
|
+
discretized_rca_main,
|
|
67
|
+
discretized_lca_main,
|
|
68
|
+
spacing: step_size,
|
|
69
|
+
rca_branches,
|
|
70
|
+
lca_branches,
|
|
71
|
+
rca_references: vec![],
|
|
72
|
+
lca_references: vec![],
|
|
73
|
+
ao_lca: (0.0, 0.0, 0.0),
|
|
74
|
+
ao_rca: (0.0, 0.0, 0.0),
|
|
75
|
+
pts_cusp_rcc: None,
|
|
76
|
+
pts_cusp_lcc: None,
|
|
77
|
+
pts_cusp_acc: None,
|
|
78
|
+
index_stj_slice: None,
|
|
79
|
+
index_aa: None,
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -3,10 +3,7 @@ pub mod resampling;
|
|
|
3
3
|
mod utils;
|
|
4
4
|
pub mod vessel_tree;
|
|
5
5
|
|
|
6
|
-
use crate::
|
|
7
|
-
use crate::ccta::discretizing::resampling::create_uniform_contours;
|
|
8
|
-
use crate::intravascular::io::geometry::Contour;
|
|
9
|
-
use crate::intravascular::io::input::Centerline;
|
|
6
|
+
use crate::types::native::{Centerline, Contour};
|
|
10
7
|
|
|
11
8
|
/// Walk `branch_id` of `centerline` at uniform `step_size` intervals, project the supplied
|
|
12
9
|
/// mesh `points` onto each perpendicular cross-section, filter incomplete slices, and
|
|
@@ -21,6 +18,6 @@ pub fn discretize_vessel_rs(
|
|
|
21
18
|
const SMOOTH_SIGMA: f64 = 2.5;
|
|
22
19
|
|
|
23
20
|
let cl_smooth = utils::smooth_centerline(centerline, SMOOTH_SIGMA);
|
|
24
|
-
let raw = walk_centerline_slices(&cl_smooth, points, branch_id, step_size);
|
|
25
|
-
create_uniform_contours(raw, n_points)
|
|
21
|
+
let raw = projecting::walk_centerline_slices(&cl_smooth, points, branch_id, step_size);
|
|
22
|
+
resampling::create_uniform_contours(raw, n_points)
|
|
26
23
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
use crate::intravascular::{
|
|
2
|
-
|
|
3
|
-
centerline_align::{align_combined_rs, align_manual_rs, align_three_point_rs},
|
|
1
|
+
use crate::intravascular::centerline_align::{
|
|
2
|
+
align_combined_rs, align_manual_rs, align_three_point_rs,
|
|
4
3
|
};
|
|
4
|
+
use crate::types::binding::{PyCenterline, PyContourType, PyGeometry, PyGeometryPair};
|
|
5
5
|
use pyo3::prelude::*;
|
|
6
6
|
|
|
7
7
|
/// Align a geometry (or geometry pair) to the centerline using three reference points.
|