feat(core): add point-search, boundary-normal and vertebra-angle helpers - #141
Conversation
Upstreams three helpers that sibling repos had each re-implemented locally, and removes the duplicate vector helpers that already existed inside TPTBox. np_utils: - np_index / np_find_closest_point_index: row lookup and nearest-point search over an (N, D) point array. The nearest-point search tries an exact match first for integer (voxel) arrays, then falls back to scipy's cdist. - np_compute_boundary_normals: per-voxel surface normals where one label touches another, via a 6-connectivity contact test and the Sobel gradient of a Gaussian-smoothed mask. Complements np_compute_surface, which has no normals, and calculate_pca_normal_np, which returns a single axis for a whole segmentation. - np_unit_vector / np_angle_between: canonical implementations. angles.py and ray_casting.py both carried their own copy; both now alias these, and angles.py keeps its historic public names. poi_fun.vertebra_direction: - get_vert_direction_angles: angle between each of a vertebra's P/I/R direction vectors and the corresponding global axis. Useful as a QC signal for direction landmarks that are not orthonormal. Four existing call sites now use the shared point search instead of hand-rolling cdist/argmin: pixel_based_point_finder (get_nearest_neighbor and the point-set projection loop) and endplates (two norm(axis=1) distance computations). All four were verified equivalent to their previous behaviour over randomized inputs. Note on the source material: the upstream fast_cdist was documented as "much faster than scipy.cdist" but benchmarks 2-6x slower, since scipy's is compiled C while the einsum form materialises the difference array. Only its exact-match fast path was adopted, on top of cdist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Benchmark comparisonSpeed (wall time per call)baseline Showing the 5 most-changed measurements per case; the rest are collapsed. Rows with a baseline below 3 ms are tagged
|
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_save |
11.85 ±0.09 | 11.50 ±0.05 | -2.9% | 0.001 |
nii_filter_connected_components |
4.32 ±0.04 | 4.21 ±0.05 | -2.6% | 0.017 |
nii_fill_holes |
4.69 ±0.07 | 4.79 ±0.08 | +2.1% | 0.171 |
nii_load_img |
11.98 ±0.09 | 11.73 ±0.18 | -2.1% | 0.204 |
poi_calc_centroids_nocrop |
4.44 ±0.03 | 4.36 ±0.29 | -1.6% | 0.603 |
… 31 more measurements
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_rescale_seg |
3.14 ±0.05 | 3.10 ±0.03 | -1.2% | 0.051 |
nii_erode_msk |
6.12 ±0.07 | 6.20 ±0.10 | +1.2% | 0.258 |
nii_dilate_msk |
119.28 ±0.22 | 118.24 ±0.48 | -0.9% | 0.009 |
nii_resample_from_to |
41.95 ±0.20 | 41.63 ±0.17 | -0.8% | 0.011 |
poi_calc_poi_from_subreg_vert |
11.61 ±0.07 | 11.52 ±0.03 | -0.7% | 0.076 |
nii_rescale |
40.02 ±0.10 | 39.77 ±0.17 | -0.6% | 0.028 |
metric_voxels |
250463.00 ±0.00 | 250463.00 ±0.00 | +0.0% | — |
metric_labels |
3.00 ±0.00 | 3.00 ±0.00 | +0.0% | — |
metric_foreground_pct |
14.51 ±0.00 | 14.51 ±0.00 | +0.0% | — |
nii_get_array |
0.06 ±0.00 | 0.03 ±0.00 | -49.8% (noise) | 0.000 |
nii_set_dtype |
0.54 ±0.04 | 0.39 ±0.04 | -27.5% (noise) | 0.000 |
poi_reorient |
0.42 ±0.03 | 0.32 ±0.01 | -23.2% (noise) | 0.001 |
nii_reorient |
0.87 ±0.05 | 0.69 ±0.03 | -20.5% (noise) | 0.000 |
nii_pad_to |
0.69 ±0.02 | 0.56 ±0.02 | -17.8% (noise) | 0.000 |
nii_extract_label |
0.43 ±0.03 | 0.36 ±0.05 | -17.1% (noise) | 0.172 |
nii_apply_crop |
0.64 ±0.04 | 0.54 ±0.02 | -14.7% (noise) | 0.004 |
poi_map_labels |
0.17 ±0.02 | 0.15 ±0.01 | -14.5% (noise) | 0.010 |
nii_load_seg |
2.98 ±0.06 | 2.67 ±0.01 | -10.4% (noise) | 0.000 |
poi_save |
0.42 ±0.03 | 0.39 ±0.01 | -8.1% (noise) | 0.029 |
poi_rescale |
0.20 ±0.03 | 0.19 ±0.01 | -6.7% (noise) | 0.147 |
poi_local_to_global_arr |
0.26 ±0.00 | 0.25 ±0.01 | -5.4% (noise) | 0.002 |
poi_to_global |
0.19 ±0.01 | 0.18 ±0.03 | -4.8% (noise) | 0.992 |
poi_resample_from_to |
0.57 ±0.01 | 0.54 ±0.01 | -4.3% (noise) | 0.004 |
nii_map_labels |
0.84 ±0.01 | 0.87 ±0.08 | +4.0% (noise) | 0.276 |
nii_unique |
0.62 ±0.03 | 0.60 ±0.02 | -3.5% (noise) | 0.086 |
nii_get_connected_components |
2.09 ±0.02 | 2.02 ±0.04 | -3.3% (noise) | 0.020 |
nii_center_of_masses |
1.86 ±0.01 | 1.81 ±0.01 | -2.8% (noise) | 0.000 |
nii_compute_crop |
0.32 ±0.02 | 0.31 ±0.01 | -2.3% (noise) | 0.736 |
poi_calc_centroids |
2.47 ±0.02 | 2.42 ±0.04 | -1.7% (noise) | 0.036 |
poi_load |
0.86 ±0.02 | 0.87 ±0.01 | +0.8% (noise) | 0.506 |
nii_volumes |
1.91 ±0.03 | 1.91 ±0.01 | -0.3% (noise) | 0.309 |
ct_2d — shape (73, 47, 1)
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_rescale |
5.56 ±0.16 | 5.34 ±0.04 | -4.0% | 0.094 |
nii_resample_from_to |
7.42 ±0.17 | 7.13 ±0.12 | -3.9% | 0.029 |
nii_dilate_msk |
13.72 ±0.06 | 13.79 ±0.04 | +0.5% | 0.104 |
metric_voxels |
3431.00 ±0.00 | 3431.00 ±0.00 | +0.0% | — |
metric_labels |
3.00 ±0.00 | 3.00 ±0.00 | +0.0% | — |
… 30 more measurements
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
metric_foreground_pct |
37.60 ±0.00 | 37.60 ±0.00 | +0.0% | — |
nii_compute_crop |
0.17 ±0.01 | 0.15 ±0.01 | -12.8% (noise) | 0.105 |
poi_map_labels |
0.24 ±0.01 | 0.22 ±0.01 | -7.7% (noise) | 0.006 |
poi_resample_from_to |
0.76 ±0.03 | 0.71 ±0.03 | -7.0% (noise) | 0.018 |
poi_local_to_global_arr |
0.31 ±0.01 | 0.29 ±0.00 | -6.6% (noise) | 0.007 |
nii_fill_holes |
0.85 ±0.04 | 0.90 ±0.02 | +6.3% (noise) | 0.045 |
nii_set_dtype |
0.44 ±0.01 | 0.46 ±0.01 | +6.0% (noise) | 0.003 |
nii_get_connected_components |
0.71 ±0.04 | 0.75 ±0.04 | +5.6% (noise) | 0.077 |
nii_volumes |
0.31 ±0.01 | 0.29 ±0.01 | -5.5% (noise) | 0.054 |
nii_center_of_masses |
0.23 ±0.01 | 0.24 ±0.02 | +4.7% (noise) | 0.359 |
poi_to_global |
0.27 ±0.01 | 0.26 ±0.01 | -4.3% (noise) | 0.626 |
nii_erode_msk |
0.92 ±0.02 | 0.96 ±0.03 | +4.2% (noise) | 0.041 |
nii_load_seg |
1.73 ±0.09 | 1.66 ±0.02 | -3.8% (noise) | 0.425 |
nii_unique |
0.15 ±0.01 | 0.14 ±0.01 | -3.5% (noise) | 0.242 |
nii_pad_to |
0.58 ±0.03 | 0.60 ±0.03 | +3.0% (noise) | 0.178 |
nii_get_array |
0.02 ±0.00 | 0.02 ±0.00 | -2.6% (noise) | 0.276 |
nii_map_labels |
0.54 ±0.01 | 0.52 ±0.02 | -2.4% (noise) | 0.090 |
poi_reorient |
0.47 ±0.01 | 0.48 ±0.01 | +2.4% (noise) | 0.192 |
nii_filter_connected_components |
0.87 ±0.02 | 0.89 ±0.02 | +2.4% (noise) | 0.014 |
nii_reorient |
0.84 ±0.03 | 0.82 ±0.01 | -1.8% (noise) | 0.114 |
poi_save |
0.55 ±0.01 | 0.54 ±0.02 | -1.7% (noise) | 0.119 |
nii_rescale_seg |
0.82 ±0.02 | 0.80 ±0.01 | -1.6% (noise) | 0.260 |
nii_extract_label |
0.45 ±0.03 | 0.46 ±0.02 | +1.5% (noise) | 0.725 |
nii_save |
1.42 ±0.05 | 1.40 ±0.02 | -1.4% (noise) | 0.198 |
nii_apply_crop |
0.72 ±0.02 | 0.71 ±0.02 | -1.2% (noise) | 0.458 |
poi_load |
1.01 ±0.02 | 1.00 ±0.02 | -0.8% (noise) | 0.069 |
poi_calc_centroids_nocrop |
1.13 ±0.02 | 1.12 ±0.01 | -0.8% (noise) | 0.389 |
nii_load_img |
1.50 ±0.05 | 1.49 ±0.04 | -0.6% (noise) | 0.562 |
poi_calc_centroids |
0.95 ±0.03 | 0.94 ±0.04 | -0.2% (noise) | 0.760 |
poi_rescale |
0.29 ±0.01 | 0.29 ±0.01 | -0.2% (noise) | 0.183 |
mri_3d — shape (68, 52, 67)
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_filter_connected_components |
4.75 ±0.06 | 4.61 ±0.02 | -3.0% | 0.003 |
nii_load_img |
9.72 ±0.06 | 9.55 ±0.05 | -1.8% | 0.003 |
nii_fill_holes |
5.64 ±0.02 | 5.54 ±0.04 | -1.7% | 0.004 |
nii_erode_msk |
7.74 ±0.05 | 7.61 ±0.15 | -1.6% | 0.737 |
poi_calc_centroids_nocrop |
9.05 ±0.07 | 9.16 ±0.08 | +1.2% | 0.547 |
… 31 more measurements
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_save |
9.64 ±0.08 | 9.56 ±0.04 | -0.9% | 0.017 |
nii_resample_from_to |
39.38 ±0.34 | 39.06 ±0.19 | -0.8% | 0.057 |
nii_dilate_msk |
153.89 ±0.57 | 152.97 ±0.46 | -0.6% | 0.033 |
nii_rescale_seg |
3.14 ±0.07 | 3.12 ±0.01 | -0.6% | 0.130 |
nii_rescale |
37.43 ±0.13 | 37.34 ±0.18 | -0.2% | 0.757 |
poi_calc_poi_from_subreg_vert |
10.90 ±0.03 | 10.90 ±0.07 | -0.0% | 0.595 |
metric_voxels |
236912.00 ±0.00 | 236912.00 ±0.00 | +0.0% | — |
metric_labels |
8.00 ±0.00 | 8.00 ±0.00 | +0.0% | — |
metric_foreground_pct |
18.21 ±0.00 | 18.21 ±0.00 | +0.0% | — |
nii_get_array |
0.04 ±0.00 | 0.06 ±0.00 | +35.5% (noise) | 0.000 |
nii_set_dtype |
0.53 ±0.02 | 0.59 ±0.05 | +12.1% (noise) | 0.041 |
poi_to_global |
0.29 ±0.02 | 0.31 ±0.01 | +6.7% (noise) | 0.032 |
nii_extract_label |
0.54 ±0.05 | 0.51 ±0.02 | -6.1% (noise) | 0.053 |
nii_get_connected_components |
2.22 ±0.07 | 2.10 ±0.03 | -5.5% (noise) | 0.011 |
poi_rescale |
0.33 ±0.01 | 0.31 ±0.02 | -5.3% (noise) | 0.145 |
nii_pad_to |
0.81 ±0.03 | 0.77 ±0.01 | -5.0% (noise) | 0.071 |
poi_resample_from_to |
0.77 ±0.02 | 0.81 ±0.02 | +4.8% (noise) | 0.007 |
nii_load_seg |
2.98 ±0.10 | 2.84 ±0.02 | -4.4% (noise) | 0.055 |
poi_save |
0.57 ±0.02 | 0.60 ±0.01 | +4.4% (noise) | 0.082 |
poi_reorient |
0.53 ±0.03 | 0.52 ±0.01 | -3.3% (noise) | 0.436 |
nii_unique |
0.66 ±0.01 | 0.64 ±0.01 | -3.0% (noise) | 0.037 |
poi_map_labels |
0.26 ±0.01 | 0.26 ±0.00 | +2.7% (noise) | 0.307 |
nii_reorient |
0.88 ±0.06 | 0.90 ±0.02 | +2.2% (noise) | 0.537 |
poi_calc_centroids |
2.93 ±0.03 | 2.89 ±0.04 | -1.5% (noise) | 0.057 |
poi_local_to_global_arr |
0.29 ±0.01 | 0.29 ±0.01 | +1.5% (noise) | 0.244 |
nii_map_labels |
1.05 ±0.02 | 1.03 ±0.02 | -1.5% (noise) | 0.052 |
poi_load |
2.10 ±0.04 | 2.12 ±0.03 | +1.0% (noise) | 0.842 |
nii_apply_crop |
0.77 ±0.02 | 0.76 ±0.02 | -0.5% (noise) | 0.273 |
nii_center_of_masses |
2.10 ±0.02 | 2.10 ±0.02 | -0.2% (noise) | 0.578 |
nii_volumes |
2.04 ±0.02 | 2.05 ±0.02 | +0.1% (noise) | 0.284 |
nii_compute_crop |
0.37 ±0.01 | 0.37 ±0.01 | +0.0% (noise) | 0.360 |
mri_2d — shape (68, 52, 1)
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_rescale |
5.81 ±0.07 | 5.41 ±0.05 | -6.8% | 0.000 |
nii_resample_from_to |
7.35 ±0.19 | 7.21 ±0.12 | -2.0% | 0.258 |
nii_dilate_msk |
18.27 ±0.06 | 18.16 ±0.17 | -0.6% | 0.876 |
metric_voxels |
3536.00 ±0.00 | 3536.00 ±0.00 | +0.0% | — |
metric_labels |
7.00 ±0.00 | 7.00 ±0.00 | +0.0% | — |
… 30 more measurements
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
metric_foreground_pct |
50.17 ±0.00 | 50.17 ±0.00 | +0.0% | — |
nii_rescale_seg |
0.86 ±0.04 | 0.79 ±0.01 | -8.6% (noise) | 0.005 |
poi_to_global |
0.32 ±0.01 | 0.29 ±0.02 | -8.2% (noise) | 0.024 |
nii_center_of_masses |
0.44 ±0.01 | 0.40 ±0.01 | -8.1% (noise) | 0.001 |
poi_rescale |
0.33 ±0.03 | 0.30 ±0.01 | -7.1% (noise) | 0.170 |
nii_erode_msk |
1.28 ±0.04 | 1.20 ±0.03 | -6.8% (noise) | 0.006 |
nii_reorient |
0.90 ±0.03 | 0.84 ±0.01 | -6.7% (noise) | 0.003 |
poi_calc_centroids_nocrop |
1.45 ±0.03 | 1.35 ±0.04 | -6.5% (noise) | 0.017 |
nii_unique |
0.15 ±0.01 | 0.14 ±0.01 | -5.2% (noise) | 0.177 |
nii_get_array |
0.02 ±0.00 | 0.02 ±0.00 | -4.7% (noise) | 0.533 |
nii_fill_holes |
1.09 ±0.02 | 1.04 ±0.04 | -4.6% (noise) | 0.085 |
poi_reorient |
0.53 ±0.01 | 0.51 ±0.02 | -4.4% (noise) | 0.043 |
nii_set_dtype |
0.46 ±0.04 | 0.44 ±0.02 | -4.2% (noise) | 0.480 |
nii_extract_label |
0.46 ±0.02 | 0.44 ±0.01 | -4.2% (noise) | 0.050 |
nii_compute_crop |
0.17 ±0.02 | 0.17 ±0.01 | -3.8% (noise) | 0.907 |
nii_pad_to |
0.62 ±0.02 | 0.60 ±0.02 | -3.6% (noise) | 0.487 |
nii_volumes |
0.49 ±0.01 | 0.47 ±0.01 | -3.6% (noise) | 0.048 |
nii_load_img |
1.46 ±0.03 | 1.51 ±0.11 | +3.3% (noise) | 0.284 |
poi_save |
0.60 ±0.02 | 0.62 ±0.02 | +2.6% (noise) | 0.322 |
poi_local_to_global_arr |
0.30 ±0.01 | 0.30 ±0.03 | +2.6% (noise) | 0.313 |
nii_save |
1.41 ±0.02 | 1.39 ±0.02 | -1.7% (noise) | 0.315 |
poi_load |
1.91 ±0.02 | 1.88 ±0.01 | -1.1% (noise) | 0.073 |
nii_get_connected_components |
0.69 ±0.03 | 0.68 ±0.03 | -1.1% (noise) | 0.495 |
poi_calc_centroids |
1.15 ±0.03 | 1.14 ±0.01 | -1.0% (noise) | 0.835 |
nii_filter_connected_components |
0.90 ±0.02 | 0.89 ±0.00 | -0.9% (noise) | 0.066 |
nii_map_labels |
0.55 ±0.04 | 0.55 ±0.04 | -0.9% (noise) | 0.626 |
nii_apply_crop |
0.72 ±0.02 | 0.72 ±0.03 | -0.9% (noise) | 0.841 |
poi_map_labels |
0.26 ±0.01 | 0.26 ±0.01 | +0.4% (noise) | 0.583 |
poi_resample_from_to |
0.79 ±0.01 | 0.79 ±0.01 | -0.4% (noise) | 0.514 |
nii_load_seg |
1.65 ±0.06 | 1.64 ±0.02 | -0.1% (noise) | 0.887 |
Gate: a measurement fails when the baseline is ≥ 1 ms, the median grows by ≥ 50%, and Welch's t-test gives p < 0.05. metric_* rows are context only.
Memory (peak RSS growth per call)
baseline 439b142 vs head 439b142 · python 3.11.16 · 5 repeats + 1 warmup · sampler proc-status, isolation fork · measurement floor ≈ 0.90 MiB
Showing the 5 most-changed measurements per case; the rest are collapsed. Rows with a baseline below 3 MiB are tagged (noise) — runner jitter on those swamps any real change.
ct_3d — shape (73, 47, 73)
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_load_img |
3.52 ±0.00 | 3.57 ±0.00 | +1.4% | — |
poi_resample_from_to |
5.18 ±0.00 | 5.14 ±0.00 | -0.8% | — |
nii_set_dtype |
5.18 ±0.00 | 5.15 ±0.00 | -0.7% | — |
nii_apply_crop |
5.81 ±0.00 | 5.77 ±0.00 | -0.7% | — |
poi_calc_centroids_nocrop |
5.87 ±0.00 | 5.83 ±0.00 | -0.7% | — |
… 31 more measurements
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_extract_label |
5.31 ±0.00 | 5.27 ±0.00 | -0.7% | — |
nii_pad_to |
5.37 ±0.00 | 5.33 ±0.00 | -0.7% | — |
poi_calc_centroids |
6.00 ±0.00 | 5.96 ±0.00 | -0.7% | — |
nii_map_labels |
5.43 ±0.00 | 5.40 ±0.00 | -0.6% | — |
nii_resample_from_to |
6.20 ±0.00 | 6.16 ±0.00 | -0.6% | — |
nii_fill_holes |
6.23 ±0.00 | 6.19 ±0.00 | -0.6% | — |
nii_reorient |
5.81 ±0.00 | 5.77 ±0.00 | -0.6% | — |
nii_rescale_seg |
5.89 ±0.00 | 5.85 ±0.00 | -0.6% | — |
nii_rescale |
6.07 ±0.00 | 6.04 ±0.00 | -0.6% | — |
nii_filter_connected_components |
6.81 ±0.00 | 6.77 ±0.00 | -0.6% | — |
poi_calc_poi_from_subreg_vert |
7.06 ±0.00 | 7.02 ±0.00 | -0.6% | 0.000 |
nii_get_connected_components |
6.56 ±0.00 | 6.52 ±0.00 | -0.5% | — |
poi_to_global |
3.08 ±0.00 | 3.07 ±0.00 | -0.5% | — |
nii_dilate_msk |
5.86 ±0.00 | 5.84 ±0.00 | -0.5% | — |
nii_erode_msk |
5.88 ±0.00 | 5.85 ±0.00 | -0.5% | — |
nii_load_seg |
5.91 ±0.00 | 5.94 ±0.00 | +0.5% | — |
poi_reorient |
3.83 ±0.00 | 3.82 ±0.00 | -0.4% | — |
nii_center_of_masses |
3.27 ±0.00 | 3.26 ±0.00 | -0.4% | — |
nii_volumes |
3.52 ±0.00 | 3.51 ±0.00 | -0.3% | — |
nii_save |
3.71 ±0.00 | 3.70 ±0.00 | -0.3% | — |
metric_voxels |
250463.00 ±0.00 | 250463.00 ±0.00 | +0.0% | — |
metric_labels |
3.00 ±0.00 | 3.00 ±0.00 | +0.0% | — |
metric_foreground_pct |
14.51 ±0.00 | 14.51 ±0.00 | +0.0% | — |
poi_rescale |
2.61 ±0.00 | 2.59 ±0.00 | -0.6% (noise) | — |
poi_local_to_global_arr |
2.96 ±0.00 | 2.94 ±0.00 | -0.5% (noise) | — |
nii_get_array |
1.64 ±0.00 | 1.65 ±0.00 | +0.5% (noise) | — |
nii_compute_crop |
2.89 ±0.00 | 2.88 ±0.00 | -0.4% (noise) | — |
nii_unique |
2.96 ±0.00 | 2.95 ±0.00 | -0.4% (noise) | — |
poi_save |
1.40 ±0.00 | 1.41 ±0.00 | +0.3% (noise) | — |
poi_load |
1.61 ±0.00 | 1.62 ±0.00 | +0.2% (noise) | — |
poi_map_labels |
1.77 ±0.00 | 1.78 ±0.00 | +0.2% (noise) | — |
ct_2d — shape (73, 47, 1)
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_load_img |
3.46 ±0.00 | 3.51 ±0.00 | +1.4% | — |
poi_resample_from_to |
5.12 ±0.00 | 5.08 ±0.00 | -0.8% | — |
nii_set_dtype |
5.12 ±0.00 | 5.08 ±0.00 | -0.8% | — |
nii_extract_label |
5.25 ±0.00 | 5.21 ±0.00 | -0.7% | — |
nii_pad_to |
5.30 ±0.00 | 5.27 ±0.00 | -0.7% | — |
… 30 more measurements
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_map_labels |
5.37 ±0.00 | 5.33 ±0.00 | -0.7% | — |
nii_fill_holes |
6.16 ±0.00 | 6.12 ±0.00 | -0.7% | — |
nii_reorient |
5.75 ±0.00 | 5.71 ±0.00 | -0.7% | — |
nii_apply_crop |
5.75 ±0.00 | 5.71 ±0.00 | -0.7% | — |
nii_rescale_seg |
5.82 ±0.00 | 5.79 ±0.00 | -0.7% | — |
poi_calc_centroids_nocrop |
5.87 ±0.00 | 5.83 ±0.00 | -0.7% | — |
poi_calc_centroids |
5.93 ±0.00 | 5.89 ±0.00 | -0.7% | 0.000 |
nii_rescale |
6.01 ±0.00 | 5.97 ±0.00 | -0.6% | — |
nii_resample_from_to |
6.14 ±0.00 | 6.10 ±0.00 | -0.6% | — |
nii_get_connected_components |
6.50 ±0.00 | 6.46 ±0.00 | -0.6% | — |
nii_filter_connected_components |
6.75 ±0.00 | 6.71 ±0.00 | -0.6% | — |
nii_dilate_msk |
5.80 ±0.00 | 5.77 ±0.00 | -0.5% | — |
nii_erode_msk |
5.82 ±0.00 | 5.79 ±0.00 | -0.5% | — |
poi_to_global |
3.02 ±0.00 | 3.00 ±0.00 | -0.5% | — |
nii_center_of_masses |
3.21 ±0.00 | 3.19 ±0.00 | -0.5% | — |
nii_volumes |
3.46 ±0.00 | 3.44 ±0.00 | -0.5% | — |
nii_save |
3.64 ±0.00 | 3.63 ±0.00 | -0.4% | — |
poi_reorient |
3.77 ±0.00 | 3.75 ±0.00 | -0.4% | — |
nii_load_seg |
5.85 ±0.00 | 5.88 ±0.00 | +0.4% | — |
metric_voxels |
3431.00 ±0.00 | 3431.00 ±0.00 | +0.0% | — |
metric_labels |
3.00 ±0.00 | 3.00 ±0.00 | +0.0% | — |
metric_foreground_pct |
37.60 ±0.00 | 37.60 ±0.00 | +0.0% | — |
poi_rescale |
2.54 ±0.00 | 2.52 ±0.00 | -0.6% (noise) | — |
nii_compute_crop |
2.83 ±0.00 | 2.82 ±0.00 | -0.6% (noise) | — |
poi_local_to_global_arr |
2.89 ±0.00 | 2.88 ±0.00 | -0.5% (noise) | — |
nii_unique |
2.89 ±0.00 | 2.88 ±0.00 | -0.5% (noise) | — |
poi_save |
1.34 ±0.00 | 1.34 ±0.00 | +0.3% (noise) | — |
poi_load |
1.55 ±0.00 | 1.55 ±0.00 | +0.3% (noise) | — |
nii_get_array |
1.58 ±0.00 | 1.59 ±0.00 | +0.2% (noise) | — |
poi_map_labels |
1.71 ±0.00 | 1.71 ±0.00 | +0.2% (noise) | — |
mri_3d — shape (68, 52, 67)
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_load_img |
3.52 ±0.00 | 3.57 ±0.00 | +1.3% | — |
poi_resample_from_to |
5.12 ±0.00 | 5.08 ±0.00 | -0.8% | — |
nii_set_dtype |
5.18 ±0.00 | 5.14 ±0.00 | -0.8% | — |
nii_extract_label |
5.25 ±0.00 | 5.21 ±0.00 | -0.7% | — |
nii_pad_to |
5.30 ±0.00 | 5.27 ±0.00 | -0.7% | — |
… 31 more measurements
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_map_labels |
5.37 ±0.00 | 5.33 ±0.00 | -0.7% | — |
nii_fill_holes |
6.16 ±0.00 | 6.12 ±0.00 | -0.7% | — |
nii_reorient |
5.75 ±0.00 | 5.71 ±0.00 | -0.7% | — |
nii_apply_crop |
5.75 ±0.00 | 5.71 ±0.00 | -0.7% | — |
poi_calc_centroids_nocrop |
5.80 ±0.00 | 5.77 ±0.00 | -0.7% | — |
nii_rescale_seg |
5.82 ±0.00 | 5.79 ±0.00 | -0.7% | — |
poi_calc_centroids |
5.93 ±0.00 | 5.89 ±0.00 | -0.7% | — |
nii_rescale |
6.01 ±0.00 | 5.97 ±0.00 | -0.6% | — |
nii_resample_from_to |
6.14 ±0.00 | 6.10 ±0.00 | -0.6% | — |
nii_get_connected_components |
6.50 ±0.00 | 6.46 ±0.00 | -0.6% | — |
nii_filter_connected_components |
6.75 ±0.00 | 6.71 ±0.00 | -0.6% | — |
poi_calc_poi_from_subreg_vert |
7.05 ±0.00 | 7.02 ±0.00 | -0.6% | — |
nii_dilate_msk |
5.80 ±0.00 | 5.77 ±0.00 | -0.5% | — |
nii_erode_msk |
5.82 ±0.00 | 5.79 ±0.00 | -0.5% | — |
poi_to_global |
3.02 ±0.00 | 3.00 ±0.00 | -0.5% | — |
nii_center_of_masses |
3.21 ±0.00 | 3.19 ±0.00 | -0.5% | — |
nii_volumes |
3.46 ±0.00 | 3.44 ±0.00 | -0.5% | — |
nii_save |
3.64 ±0.00 | 3.63 ±0.00 | -0.4% | — |
poi_reorient |
3.77 ±0.00 | 3.75 ±0.00 | -0.4% | — |
nii_load_seg |
5.85 ±0.00 | 5.88 ±0.00 | +0.4% | — |
metric_voxels |
236912.00 ±0.00 | 236912.00 ±0.00 | +0.0% | — |
metric_labels |
8.00 ±0.00 | 8.00 ±0.00 | +0.0% | — |
metric_foreground_pct |
18.21 ±0.00 | 18.21 ±0.00 | +0.0% | — |
poi_rescale |
2.54 ±0.00 | 2.52 ±0.00 | -0.6% (noise) | — |
nii_compute_crop |
2.83 ±0.00 | 2.82 ±0.00 | -0.6% (noise) | — |
poi_local_to_global_arr |
2.89 ±0.00 | 2.88 ±0.00 | -0.5% (noise) | — |
nii_unique |
2.89 ±0.00 | 2.88 ±0.00 | -0.5% (noise) | — |
poi_save |
1.40 ±0.00 | 1.40 ±0.00 | +0.3% (noise) | — |
poi_load |
1.55 ±0.00 | 1.55 ±0.00 | +0.3% (noise) | — |
nii_get_array |
1.58 ±0.00 | 1.59 ±0.00 | +0.2% (noise) | — |
poi_map_labels |
1.71 ±0.00 | 1.71 ±0.00 | +0.2% (noise) | — |
mri_2d — shape (68, 52, 1)
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_load_img |
3.52 ±0.00 | 3.57 ±0.00 | +1.3% | — |
poi_resample_from_to |
5.12 ±0.00 | 5.08 ±0.00 | -0.8% | — |
nii_set_dtype |
5.18 ±0.00 | 5.14 ±0.00 | -0.8% | — |
nii_extract_label |
5.25 ±0.00 | 5.21 ±0.00 | -0.7% | — |
nii_pad_to |
5.30 ±0.00 | 5.27 ±0.00 | -0.7% | — |
… 30 more measurements
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_map_labels |
5.37 ±0.00 | 5.33 ±0.00 | -0.7% | — |
nii_fill_holes |
6.16 ±0.00 | 6.12 ±0.00 | -0.7% | — |
nii_reorient |
5.75 ±0.00 | 5.71 ±0.00 | -0.7% | — |
nii_apply_crop |
5.75 ±0.00 | 5.71 ±0.00 | -0.7% | — |
nii_rescale_seg |
5.82 ±0.00 | 5.79 ±0.00 | -0.7% | — |
poi_calc_centroids_nocrop |
5.87 ±0.00 | 5.83 ±0.00 | -0.7% | — |
poi_calc_centroids |
5.93 ±0.00 | 5.89 ±0.00 | -0.7% | — |
nii_rescale |
6.01 ±0.00 | 5.97 ±0.00 | -0.6% | — |
nii_resample_from_to |
6.14 ±0.00 | 6.10 ±0.00 | -0.6% | — |
nii_get_connected_components |
6.50 ±0.00 | 6.46 ±0.00 | -0.6% | — |
nii_filter_connected_components |
6.75 ±0.00 | 6.71 ±0.00 | -0.6% | — |
nii_dilate_msk |
5.80 ±0.00 | 5.77 ±0.00 | -0.5% | — |
nii_erode_msk |
5.82 ±0.00 | 5.79 ±0.00 | -0.5% | — |
poi_to_global |
3.02 ±0.00 | 3.00 ±0.00 | -0.5% | — |
nii_center_of_masses |
3.21 ±0.00 | 3.19 ±0.00 | -0.5% | — |
nii_volumes |
3.46 ±0.00 | 3.44 ±0.00 | -0.5% | — |
nii_save |
3.64 ±0.00 | 3.63 ±0.00 | -0.4% | — |
poi_reorient |
3.77 ±0.00 | 3.75 ±0.00 | -0.4% | — |
nii_load_seg |
5.85 ±0.00 | 5.88 ±0.00 | +0.4% | — |
metric_voxels |
3536.00 ±0.00 | 3536.00 ±0.00 | +0.0% | — |
metric_labels |
7.00 ±0.00 | 7.00 ±0.00 | +0.0% | — |
metric_foreground_pct |
50.17 ±0.00 | 50.17 ±0.00 | +0.0% | — |
poi_rescale |
2.54 ±0.00 | 2.52 ±0.00 | -0.6% (noise) | — |
nii_compute_crop |
2.83 ±0.00 | 2.82 ±0.00 | -0.6% (noise) | — |
poi_local_to_global_arr |
2.89 ±0.00 | 2.88 ±0.00 | -0.5% (noise) | — |
nii_unique |
2.89 ±0.00 | 2.88 ±0.00 | -0.5% (noise) | — |
poi_save |
1.40 ±0.00 | 1.40 ±0.00 | +0.3% (noise) | — |
poi_load |
1.55 ±0.00 | 1.55 ±0.00 | +0.3% (noise) | — |
nii_get_array |
1.58 ±0.00 | 1.59 ±0.00 | +0.2% (noise) | — |
poi_map_labels |
1.71 ±0.00 | 1.71 ±0.00 | +0.2% (noise) | — |
Gate: a measurement fails when the baseline is ≥ 1 MiB, the median grows by ≥ 50%, and Welch's t-test gives p < 0.05. metric_* rows are context only.
Upstreams three helpers found in sibling repos under
ongoing_projects/hendrik/, where each had been re-implemented locally several times over, and consolidates the vector helpers that were already duplicated inside TPTBox.What's added
np_utilsnp_index— row indices of an(N, D)point array that exactly equal a given point.np_find_closest_point_index— nearest-point search. For integer (voxel) arrays it tries an exact match first, which is the common case when the query already sits on the grid, then falls back to a distance search.np_compute_boundary_normals— per-voxel surface normals where one label touches another: 6-connectivity contact test, then the Sobel gradient of a Gaussian-smoothed mask.np_compute_surfacehas no normals, andcalculate_pca_normal_npreturns a single principal axis for a whole segmentation, so this filled a real gap.np_unit_vector/np_angle_between— canonical implementations.spine/spinestats/angles.pyandcore/poi_fun/ray_casting.pyeach carried their own copy; both now alias these.angles.pykeeps exportingunit_vector/angle_betweenunder their historic names, so nothing downstream breaks.core/poi_fun/vertebra_directionget_vert_direction_angles— angle between each of a vertebra's Posterior/Inferior/Right direction vectors and the corresponding global axis. A healthy frame stays near-orthogonal; an implausibly large angle flags direction landmarks that are wrong.What's refactored
Four sites hand-rolled
cdist/argminand now use the shared search:pixel_based_point_finder.py(get_nearest_neighbor)cdist(p.T, locs)+.argmin()pixel_based_point_finder.py(point-set projection loop)cdist_to_point+np.argminendplates.py×2np.linalg.norm(… , axis=1)Also removed a dead commented-out duplicate in
endplates.py.cdist_to_pointitself is unchanged — it was already optimal.Notes on the source material
Two things did not survive review, and are worth recording:
fast_cdistwas not ported. Its upstream comment claims it is "much faster than scipy.cdist". It is 2–6× slower — scipy's is compiled C, while the einsum form materialises the(N, 3)difference array. Benchmarked at n=1k→1M across float and int dtypes. Only its exact-match fast path was adopted, reimplemented on top ofcdist.[-1, 0, 0]with label 1 at low x) and documented accordingly.A fourth candidate — a topological hole fill — was dropped entirely:
np_fill_holesis already backed byfill_voids(compiled C++) and matches 6-connectedbinary_fill_holeson both a sealed and a leaky shell. The candidate was a torchconv3dloop iterated to fixpoint.Similarly, only the angle triple from the vertebra-orientation candidate is new. Its
R,corpus_comandrel_to_corpusare alreadyget_vert_direction_matrix, a POI lookup, andget_vert_direction_PIRrespectively — confirmed identical over 50 random orthonormal frames rather than assumed.Verification
ruff checkclean; the flake8 CI gate (E9,F63,F7,F82) reports 0.unit_tests/test_nputils.pyandunit_tests/test_poi_ops.py, covering exact/multiple/no-hit lookup, brute-force agreement of the nearest-point search on int and float clouds, unit-length and direction of the normals, non-touching and diagonal-only-contact edge cases, and radian/degree consistency of the angle triple.get_nearest_neighbor's oldnp.expand_dimspath accepted.🤖 Generated with Claude Code