feat(np_utils): add non-convex ray marching and label interface thickness - #145
Conversation
…ness Adds np_raymarch_until_background and np_label_interface_thickness to np_utils, max_distance_ray_cast_non_convex to poi_fun/ray_casting, and NII.label_interface_thickness as the mm-aware wrapper. The existing max_distance_ray_cast_convex bisects, which assumes the region is convex: on a mask with an interior gap it reports the far outer wall instead of the near edge of the gap. The new marcher takes fixed trilinear-interpolated steps, so concave and multi-lobed structures are handled correctly. A test pins the difference - on the same mask the bisection returns 34.5 where the marcher correctly stops at 14.5. np_label_interface_thickness measures how thick one structure is where it meets another, by marching inward along the surface normal from every interface voxel. Changes from the source implementation: - the RegularGridInterpolator is built once and reused across rays, instead of being rebuilt over the whole volume for every boundary voxel - distances are returned in mm when a zoom is given, rather than voxels - max_count_component is a parameter instead of being hardcoded to 2 - fixed a crash when max_steps was None and only max_distance was set: the fallback assigned a float to range() 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_dilate_msk |
121.81 ±0.54 | 120.22 ±0.27 | -1.3% | 0.001 |
poi_calc_centroids_nocrop |
4.30 ±0.03 | 4.34 ±0.03 | +0.9% | 0.027 |
nii_erode_msk |
6.05 ±0.12 | 6.01 ±0.04 | -0.7% | 0.236 |
nii_fill_holes |
4.56 ±0.03 | 4.59 ±0.03 | +0.7% | 0.053 |
nii_load_img |
11.62 ±0.09 | 11.69 ±1.85 | +0.6% | 0.249 |
… 31 more measurements
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_save |
11.40 ±0.08 | 11.46 ±0.04 | +0.5% | 0.261 |
nii_filter_connected_components |
4.19 ±0.02 | 4.17 ±0.03 | -0.5% | 0.087 |
nii_rescale_seg |
3.02 ±0.01 | 3.04 ±0.03 | +0.4% | 0.412 |
nii_resample_from_to |
41.48 ±0.10 | 41.62 ±0.27 | +0.3% | 0.276 |
nii_rescale |
39.74 ±0.16 | 39.83 ±0.13 | +0.2% | 0.148 |
poi_calc_poi_from_subreg_vert |
11.35 ±0.10 | 11.33 ±0.08 | -0.1% | 0.964 |
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.03 ±0.00 | 0.04 ±0.00 | +19.5% (noise) | 0.003 |
nii_pad_to |
0.49 ±0.02 | 0.53 ±0.03 | +7.6% (noise) | 0.150 |
nii_set_dtype |
0.35 ±0.02 | 0.37 ±0.03 | +6.3% (noise) | 0.201 |
poi_to_global |
0.15 ±0.02 | 0.16 ±0.01 | +5.1% (noise) | 0.980 |
poi_save |
0.36 ±0.02 | 0.34 ±0.01 | -5.0% (noise) | 0.519 |
nii_apply_crop |
0.49 ±0.03 | 0.51 ±0.03 | +3.5% (noise) | 0.763 |
poi_rescale |
0.17 ±0.01 | 0.17 ±0.01 | +2.8% (noise) | 0.637 |
poi_local_to_global_arr |
0.24 ±0.00 | 0.23 ±0.00 | -2.7% (noise) | 0.005 |
nii_reorient |
0.62 ±0.03 | 0.64 ±0.03 | +2.4% (noise) | 0.348 |
nii_compute_crop |
0.27 ±0.02 | 0.28 ±0.02 | +2.1% (noise) | 0.658 |
nii_map_labels |
0.77 ±0.02 | 0.78 ±0.02 | +2.0% (noise) | 0.208 |
poi_calc_centroids |
2.41 ±0.42 | 2.36 ±0.03 | -2.0% (noise) | 0.184 |
poi_resample_from_to |
0.53 ±0.01 | 0.53 ±0.02 | -1.3% (noise) | 0.902 |
poi_reorient |
0.32 ±0.01 | 0.32 ±0.03 | +1.2% (noise) | 0.593 |
nii_extract_label |
0.29 ±0.01 | 0.30 ±0.01 | +1.1% (noise) | 0.932 |
nii_get_connected_components |
1.97 ±0.04 | 1.95 ±0.02 | -0.9% (noise) | 0.215 |
nii_unique |
0.57 ±0.00 | 0.57 ±0.01 | +0.9% (noise) | 0.326 |
nii_volumes |
1.90 ±0.01 | 1.88 ±0.02 | -0.8% (noise) | 0.079 |
poi_load |
0.86 ±0.02 | 0.86 ±0.02 | -0.5% (noise) | 0.551 |
nii_center_of_masses |
1.79 ±0.01 | 1.78 ±0.01 | -0.4% (noise) | 0.420 |
nii_load_seg |
2.60 ±0.03 | 2.61 ±0.02 | +0.4% (noise) | 0.796 |
poi_map_labels |
0.14 ±0.01 | 0.14 ±0.01 | -0.0% (noise) | 0.799 |
ct_2d — shape (73, 47, 1)
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_dilate_msk |
14.08 ±0.10 | 13.81 ±0.04 | -1.9% | 0.001 |
nii_resample_from_to |
7.06 ±0.03 | 7.07 ±0.12 | +0.2% | 0.714 |
nii_rescale |
5.34 ±0.04 | 5.35 ±0.05 | +0.1% | 0.303 |
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_get_array |
0.02 ±0.00 | 0.01 ±0.00 | -17.8% (noise) | 0.227 |
nii_center_of_masses |
0.21 ±0.02 | 0.18 ±0.01 | -12.6% (noise) | 0.026 |
nii_unique |
0.12 ±0.01 | 0.11 ±0.01 | -7.8% (noise) | 0.234 |
poi_to_global |
0.23 ±0.01 | 0.22 ±0.01 | -5.9% (noise) | 0.313 |
poi_save |
0.46 ±0.02 | 0.48 ±0.03 | +5.0% (noise) | 0.560 |
nii_map_labels |
0.46 ±0.01 | 0.44 ±0.02 | -3.9% (noise) | 0.520 |
nii_get_connected_components |
0.61 ±0.03 | 0.59 ±0.01 | -2.9% (noise) | 0.410 |
nii_apply_crop |
0.63 ±0.03 | 0.61 ±0.01 | -2.7% (noise) | 0.121 |
nii_extract_label |
0.40 ±0.02 | 0.39 ±0.02 | -2.2% (noise) | 0.726 |
nii_volumes |
0.26 ±0.01 | 0.27 ±0.01 | +2.1% (noise) | 0.724 |
nii_set_dtype |
0.38 ±0.02 | 0.37 ±0.01 | -1.9% (noise) | 0.132 |
poi_map_labels |
0.19 ±0.01 | 0.19 ±0.01 | +1.8% (noise) | 0.879 |
nii_load_img |
1.40 ±0.02 | 1.37 ±0.01 | -1.8% (noise) | 0.118 |
poi_local_to_global_arr |
0.27 ±0.01 | 0.27 ±0.00 | -1.7% (noise) | 0.575 |
poi_resample_from_to |
0.69 ±0.02 | 0.68 ±0.01 | -1.5% (noise) | 0.092 |
poi_reorient |
0.43 ±0.02 | 0.42 ±0.01 | -1.3% (noise) | 0.300 |
nii_rescale_seg |
0.72 ±0.02 | 0.71 ±0.01 | -1.3% (noise) | 0.518 |
poi_calc_centroids_nocrop |
1.03 ±0.01 | 1.02 ±0.03 | -1.2% (noise) | 0.699 |
nii_fill_holes |
0.77 ±0.02 | 0.76 ±0.02 | -1.1% (noise) | 0.446 |
poi_rescale |
0.24 ±0.01 | 0.24 ±0.01 | -1.0% (noise) | 0.658 |
poi_load |
0.97 ±0.01 | 0.97 ±0.01 | -0.9% (noise) | 0.229 |
nii_save |
1.28 ±0.02 | 1.27 ±0.02 | -0.7% (noise) | 0.998 |
nii_erode_msk |
0.89 ±0.04 | 0.88 ±0.02 | -0.6% (noise) | 0.584 |
nii_reorient |
0.74 ±0.02 | 0.73 ±0.02 | -0.4% (noise) | 0.502 |
poi_calc_centroids |
0.84 ±0.02 | 0.83 ±0.02 | -0.3% (noise) | 0.444 |
nii_pad_to |
0.52 ±0.04 | 0.52 ±0.01 | +0.3% (noise) | 0.392 |
nii_filter_connected_components |
0.77 ±0.02 | 0.77 ±0.00 | +0.2% (noise) | 0.455 |
nii_load_seg |
1.51 ±0.01 | 1.52 ±0.02 | +0.2% (noise) | 0.721 |
nii_compute_crop |
0.13 ±0.01 | 0.13 ±0.00 | -0.1% (noise) | 0.875 |
mri_3d — shape (68, 52, 67)
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_dilate_msk |
158.45 ±0.74 | 154.88 ±0.32 | -2.3% | 0.000 |
poi_calc_centroids_nocrop |
9.01 ±0.04 | 8.92 ±0.05 | -1.1% | 0.024 |
nii_filter_connected_components |
4.55 ±0.02 | 4.51 ±0.04 | -0.8% | 0.082 |
nii_erode_msk |
7.54 ±0.09 | 7.49 ±0.04 | -0.6% | 0.168 |
nii_save |
9.42 ±0.03 | 9.45 ±0.08 | +0.4% | 0.810 |
… 31 more measurements
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
poi_calc_poi_from_subreg_vert |
10.73 ±0.08 | 10.69 ±0.06 | -0.4% | 0.909 |
nii_rescale |
37.48 ±0.28 | 37.56 ±0.13 | +0.2% | 0.671 |
nii_resample_from_to |
39.27 ±0.27 | 39.19 ±0.07 | -0.2% | 0.723 |
nii_rescale_seg |
3.03 ±0.02 | 3.03 ±0.03 | +0.0% | 0.971 |
nii_load_img |
9.40 ±0.05 | 9.40 ±0.03 | -0.0% | 0.493 |
nii_fill_holes |
5.45 ±0.07 | 5.45 ±0.01 | +0.0% | 0.637 |
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.05 ±0.01 | +37.1% (noise) | 0.003 |
poi_to_global |
0.26 ±0.01 | 0.25 ±0.01 | -4.2% (noise) | 0.468 |
poi_rescale |
0.28 ±0.00 | 0.28 ±0.01 | +3.2% (noise) | 0.156 |
poi_map_labels |
0.24 ±0.01 | 0.23 ±0.00 | -3.0% (noise) | 0.042 |
nii_pad_to |
0.66 ±0.01 | 0.68 ±0.02 | +2.6% (noise) | 0.375 |
poi_save |
0.53 ±0.01 | 0.54 ±0.02 | +2.5% (noise) | 0.506 |
nii_set_dtype |
0.47 ±0.01 | 0.46 ±0.01 | -1.9% (noise) | 0.124 |
nii_load_seg |
2.77 ±0.05 | 2.72 ±0.06 | -1.7% (noise) | 0.235 |
nii_compute_crop |
0.33 ±0.01 | 0.34 ±0.01 | +1.7% (noise) | 0.880 |
nii_extract_label |
0.42 ±0.01 | 0.41 ±0.02 | -1.3% (noise) | 0.726 |
poi_load |
2.07 ±0.02 | 2.10 ±0.01 | +1.2% (noise) | 0.033 |
nii_apply_crop |
0.66 ±0.01 | 0.66 ±0.01 | -1.0% (noise) | 0.295 |
poi_local_to_global_arr |
0.28 ±0.01 | 0.28 ±0.01 | -0.5% (noise) | 0.712 |
nii_reorient |
0.78 ±0.02 | 0.78 ±0.02 | +0.4% (noise) | 0.453 |
poi_resample_from_to |
0.71 ±0.02 | 0.71 ±0.01 | +0.3% (noise) | 0.541 |
nii_unique |
0.59 ±0.02 | 0.59 ±0.01 | +0.2% (noise) | 0.589 |
poi_calc_centroids |
2.76 ±0.02 | 2.77 ±0.02 | +0.2% (noise) | 0.630 |
poi_reorient |
0.44 ±0.01 | 0.44 ±0.02 | -0.2% (noise) | 0.590 |
nii_center_of_masses |
2.05 ±0.01 | 2.05 ±0.03 | +0.2% (noise) | 0.669 |
nii_volumes |
2.00 ±0.01 | 2.00 ±0.01 | +0.1% (noise) | 0.658 |
nii_get_connected_components |
2.01 ±0.01 | 2.01 ±0.02 | +0.1% (noise) | 0.733 |
nii_map_labels |
0.96 ±0.01 | 0.96 ±0.02 | +0.0% (noise) | 0.935 |
mri_2d — shape (68, 52, 1)
| Measurement | baseline ms (median ±½·range) | head ms (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_dilate_msk |
18.72 ±0.09 | 18.19 ±0.05 | -2.8% | 0.000 |
nii_rescale |
5.44 ±0.11 | 5.36 ±0.03 | -1.6% | 0.395 |
nii_resample_from_to |
7.16 ±0.11 | 7.12 ±0.05 | -0.5% | 0.195 |
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_set_dtype |
0.38 ±0.01 | 0.41 ±0.02 | +8.7% (noise) | 0.011 |
nii_get_array |
0.01 ±0.00 | 0.02 ±0.00 | +6.4% (noise) | 0.340 |
poi_rescale |
0.28 ±0.01 | 0.26 ±0.02 | -4.7% (noise) | 0.325 |
poi_resample_from_to |
0.69 ±0.01 | 0.72 ±0.13 | +3.6% (noise) | 0.189 |
nii_get_connected_components |
0.60 ±0.02 | 0.58 ±0.03 | -3.4% (noise) | 0.938 |
poi_load |
1.84 ±0.02 | 1.90 ±0.03 | +3.2% (noise) | 0.002 |
poi_map_labels |
0.23 ±0.01 | 0.23 ±0.01 | -3.0% (noise) | 0.477 |
poi_reorient |
0.46 ±0.01 | 0.44 ±0.02 | -3.0% (noise) | 0.064 |
nii_erode_msk |
1.14 ±0.02 | 1.11 ±0.01 | -2.8% (noise) | 0.072 |
nii_unique |
0.12 ±0.00 | 0.12 ±0.01 | +2.4% (noise) | 0.658 |
nii_compute_crop |
0.13 ±0.01 | 0.13 ±0.01 | +2.2% (noise) | 0.547 |
nii_filter_connected_components |
0.81 ±0.03 | 0.80 ±0.02 | -2.0% (noise) | 0.738 |
nii_load_seg |
1.54 ±0.02 | 1.51 ±0.01 | -1.9% (noise) | 0.036 |
poi_calc_centroids |
1.05 ±0.02 | 1.07 ±0.05 | +1.7% (noise) | 0.134 |
nii_pad_to |
0.51 ±0.02 | 0.52 ±0.02 | +1.4% (noise) | 0.944 |
poi_calc_centroids_nocrop |
1.27 ±0.02 | 1.25 ±0.01 | -1.4% (noise) | 0.158 |
nii_apply_crop |
0.62 ±0.02 | 0.61 ±0.01 | -1.3% (noise) | 0.389 |
nii_fill_holes |
0.97 ±0.02 | 0.96 ±0.02 | -1.3% (noise) | 0.320 |
nii_extract_label |
0.38 ±0.01 | 0.38 ±0.02 | -1.2% (noise) | 0.758 |
nii_rescale_seg |
0.70 ±0.02 | 0.70 ±0.02 | -1.2% (noise) | 0.928 |
nii_load_img |
1.40 ±0.04 | 1.38 ±0.03 | -1.1% (noise) | 0.423 |
poi_save |
0.51 ±0.02 | 0.52 ±0.01 | +1.1% (noise) | 0.598 |
nii_volumes |
0.44 ±0.01 | 0.43 ±0.01 | -1.1% (noise) | 0.298 |
nii_map_labels |
0.45 ±0.03 | 0.45 ±0.02 | +0.9% (noise) | 0.423 |
nii_reorient |
0.74 ±0.01 | 0.75 ±0.02 | +0.8% (noise) | 0.302 |
poi_local_to_global_arr |
0.27 ±0.01 | 0.27 ±0.01 | +0.6% (noise) | 0.502 |
nii_save |
1.28 ±0.01 | 1.27 ±0.02 | -0.5% (noise) | 0.890 |
nii_center_of_masses |
0.37 ±0.01 | 0.37 ±0.01 | +0.1% (noise) | 0.571 |
poi_to_global |
0.26 ±0.02 | 0.26 ±0.01 | +0.0% (noise) | 0.414 |
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 0171e70 vs head 0171e70 · 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.53 ±0.00 | 3.58 ±0.00 | +1.4% | — |
nii_rescale_seg |
5.95 ±0.00 | 5.88 ±0.00 | -1.1% | — |
nii_rescale |
6.13 ±0.00 | 6.07 ±0.00 | -1.0% | — |
nii_resample_from_to |
6.26 ±0.00 | 6.20 ±0.00 | -1.0% | — |
nii_load_seg |
5.91 ±0.00 | 5.96 ±0.00 | +0.9% | — |
… 31 more measurements
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_dilate_msk |
5.85 ±0.00 | 5.87 ±0.00 | +0.3% | — |
nii_erode_msk |
5.87 ±0.00 | 5.88 ±0.00 | +0.3% | — |
nii_save |
3.71 ±0.00 | 3.71 ±0.00 | +0.0% | — |
nii_set_dtype |
5.18 ±0.00 | 5.18 ±0.00 | +0.0% | — |
nii_reorient |
5.80 ±0.00 | 5.80 ±0.00 | +0.0% | — |
nii_apply_crop |
5.80 ±0.00 | 5.80 ±0.00 | +0.0% | — |
nii_pad_to |
5.36 ±0.00 | 5.36 ±0.00 | +0.0% | — |
nii_volumes |
3.52 ±0.00 | 3.52 ±0.00 | +0.0% | — |
nii_center_of_masses |
3.27 ±0.00 | 3.27 ±0.00 | +0.0% | — |
nii_extract_label |
5.30 ±0.00 | 5.30 ±0.00 | +0.0% | — |
nii_map_labels |
5.43 ±0.00 | 5.43 ±0.00 | +0.0% | — |
nii_fill_holes |
6.22 ±0.00 | 6.22 ±0.00 | +0.0% | — |
nii_get_connected_components |
6.55 ±0.00 | 6.55 ±0.00 | +0.0% | — |
nii_filter_connected_components |
6.80 ±0.00 | 6.80 ±0.00 | +0.0% | — |
poi_calc_centroids |
5.99 ±0.00 | 5.99 ±0.00 | +0.0% | — |
poi_calc_centroids_nocrop |
5.86 ±0.00 | 5.86 ±0.00 | +0.0% | — |
poi_reorient |
3.83 ±0.00 | 3.83 ±0.00 | +0.0% | — |
poi_to_global |
3.08 ±0.00 | 3.08 ±0.00 | +0.0% | — |
poi_resample_from_to |
5.18 ±0.00 | 5.18 ±0.00 | +0.0% | — |
poi_calc_poi_from_subreg_vert |
7.05 ±0.00 | 7.05 ±0.00 | +0.0% | 0.178 |
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 |
1.65 ±0.00 | 1.65 ±0.00 | +0.0% (noise) | — |
nii_compute_crop |
2.90 ±0.00 | 2.90 ±0.00 | +0.0% (noise) | — |
nii_unique |
2.96 ±0.00 | 2.96 ±0.00 | +0.0% (noise) | — |
poi_rescale |
2.61 ±0.00 | 2.61 ±0.00 | +0.0% (noise) | — |
poi_local_to_global_arr |
2.96 ±0.00 | 2.96 ±0.00 | +0.0% (noise) | — |
poi_save |
1.40 ±0.00 | 1.40 ±0.00 | +0.0% (noise) | — |
poi_map_labels |
1.77 ±0.00 | 1.77 ±0.00 | +0.0% (noise) | — |
poi_load |
1.61 ±0.00 | 1.61 ±0.00 | +0.0% (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.52 ±0.00 | +1.5% | — |
nii_rescale_seg |
5.88 ±0.00 | 5.82 ±0.00 | -1.1% | — |
nii_rescale |
6.07 ±0.00 | 6.01 ±0.00 | -1.0% | — |
nii_resample_from_to |
6.20 ±0.00 | 6.13 ±0.00 | -1.0% | — |
nii_load_seg |
5.85 ±0.00 | 5.90 ±0.00 | +0.9% | — |
… 30 more measurements
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_dilate_msk |
5.79 ±0.00 | 5.80 ±0.00 | +0.3% | — |
nii_erode_msk |
5.80 ±0.00 | 5.82 ±0.00 | +0.3% | — |
nii_save |
3.65 ±0.00 | 3.65 ±0.00 | +0.0% | — |
nii_set_dtype |
5.12 ±0.00 | 5.12 ±0.00 | +0.0% | — |
nii_reorient |
5.74 ±0.00 | 5.74 ±0.00 | +0.0% | — |
nii_apply_crop |
5.74 ±0.00 | 5.74 ±0.00 | +0.0% | — |
nii_pad_to |
5.30 ±0.00 | 5.30 ±0.00 | +0.0% | — |
nii_volumes |
3.46 ±0.00 | 3.46 ±0.00 | +0.0% | — |
nii_center_of_masses |
3.21 ±0.00 | 3.21 ±0.00 | +0.0% | — |
nii_extract_label |
5.24 ±0.00 | 5.24 ±0.00 | +0.0% | — |
nii_map_labels |
5.37 ±0.00 | 5.37 ±0.00 | +0.0% | — |
nii_fill_holes |
6.16 ±0.00 | 6.16 ±0.00 | +0.0% | — |
nii_get_connected_components |
6.49 ±0.00 | 6.49 ±0.00 | +0.0% | — |
nii_filter_connected_components |
6.74 ±0.00 | 6.74 ±0.00 | +0.0% | — |
poi_calc_centroids |
5.93 ±0.00 | 5.93 ±0.00 | +0.0% | 0.374 |
poi_calc_centroids_nocrop |
5.86 ±0.00 | 5.86 ±0.00 | +0.0% | — |
poi_reorient |
3.77 ±0.00 | 3.77 ±0.00 | +0.0% | — |
poi_to_global |
3.02 ±0.00 | 3.02 ±0.00 | +0.0% | — |
poi_resample_from_to |
5.11 ±0.00 | 5.11 ±0.00 | +0.0% | — |
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% | — |
nii_get_array |
1.59 ±0.00 | 1.59 ±0.00 | +0.0% (noise) | — |
nii_compute_crop |
2.84 ±0.00 | 2.84 ±0.00 | +0.0% (noise) | — |
nii_unique |
2.90 ±0.00 | 2.90 ±0.00 | +0.0% (noise) | — |
poi_rescale |
2.54 ±0.00 | 2.54 ±0.00 | +0.0% (noise) | — |
poi_local_to_global_arr |
2.89 ±0.00 | 2.89 ±0.00 | +0.0% (noise) | — |
poi_save |
1.34 ±0.00 | 1.34 ±0.00 | +0.0% (noise) | — |
poi_map_labels |
1.71 ±0.00 | 1.71 ±0.00 | +0.0% (noise) | — |
poi_load |
1.55 ±0.00 | 1.55 ±0.00 | +0.0% (noise) | — |
mri_3d — shape (68, 52, 67)
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_load_img |
3.53 ±0.00 | 3.58 ±0.00 | +1.4% | — |
nii_rescale_seg |
5.88 ±0.00 | 5.82 ±0.00 | -1.1% | — |
nii_rescale |
6.07 ±0.00 | 6.01 ±0.00 | -1.0% | — |
nii_resample_from_to |
6.20 ±0.00 | 6.13 ±0.00 | -1.0% | — |
nii_load_seg |
5.85 ±0.00 | 5.90 ±0.00 | +0.9% | — |
… 31 more measurements
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_dilate_msk |
5.79 ±0.00 | 5.80 ±0.00 | +0.3% | — |
nii_erode_msk |
5.80 ±0.00 | 5.82 ±0.00 | +0.3% | — |
nii_save |
3.65 ±0.00 | 3.65 ±0.00 | +0.0% | — |
nii_set_dtype |
5.18 ±0.00 | 5.18 ±0.00 | +0.0% | — |
nii_reorient |
5.74 ±0.00 | 5.74 ±0.00 | +0.0% | — |
nii_apply_crop |
5.74 ±0.00 | 5.74 ±0.00 | +0.0% | — |
nii_pad_to |
5.30 ±0.00 | 5.30 ±0.00 | +0.0% | — |
nii_volumes |
3.46 ±0.00 | 3.46 ±0.00 | +0.0% | — |
nii_center_of_masses |
3.21 ±0.00 | 3.21 ±0.00 | +0.0% | — |
nii_extract_label |
5.24 ±0.00 | 5.24 ±0.00 | +0.0% | — |
nii_map_labels |
5.37 ±0.00 | 5.37 ±0.00 | +0.0% | — |
nii_fill_holes |
6.16 ±0.00 | 6.16 ±0.00 | +0.0% | — |
nii_get_connected_components |
6.49 ±0.00 | 6.49 ±0.00 | +0.0% | — |
nii_filter_connected_components |
6.74 ±0.00 | 6.74 ±0.00 | +0.0% | — |
poi_calc_centroids |
5.93 ±0.00 | 5.93 ±0.00 | +0.0% | — |
poi_calc_centroids_nocrop |
5.80 ±0.00 | 5.80 ±0.00 | +0.0% | — |
poi_reorient |
3.77 ±0.00 | 3.77 ±0.00 | +0.0% | — |
poi_to_global |
3.02 ±0.00 | 3.02 ±0.00 | +0.0% | — |
poi_resample_from_to |
5.11 ±0.00 | 5.11 ±0.00 | +0.0% | — |
poi_calc_poi_from_subreg_vert |
7.05 ±0.00 | 7.05 ±0.00 | +0.0% | — |
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 |
1.59 ±0.00 | 1.59 ±0.00 | +0.0% (noise) | — |
nii_compute_crop |
2.84 ±0.00 | 2.84 ±0.00 | +0.0% (noise) | — |
nii_unique |
2.90 ±0.00 | 2.90 ±0.00 | +0.0% (noise) | — |
poi_rescale |
2.54 ±0.00 | 2.54 ±0.00 | +0.0% (noise) | — |
poi_local_to_global_arr |
2.89 ±0.00 | 2.89 ±0.00 | +0.0% (noise) | — |
poi_save |
1.40 ±0.00 | 1.40 ±0.00 | +0.0% (noise) | — |
poi_map_labels |
1.71 ±0.00 | 1.71 ±0.00 | +0.0% (noise) | — |
poi_load |
1.55 ±0.00 | 1.55 ±0.00 | +0.0% (noise) | — |
mri_2d — shape (68, 52, 1)
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_load_img |
3.53 ±0.00 | 3.58 ±0.00 | +1.4% | — |
nii_rescale_seg |
5.88 ±0.00 | 5.82 ±0.00 | -1.1% | — |
nii_rescale |
6.07 ±0.00 | 6.01 ±0.00 | -1.0% | — |
nii_resample_from_to |
6.20 ±0.00 | 6.13 ±0.00 | -1.0% | — |
nii_load_seg |
5.85 ±0.00 | 5.90 ±0.00 | +0.9% | — |
… 30 more measurements
| Measurement | baseline MiB (median ±½·range) | head MiB (median ±½·range) | Δ % | p |
|---|---|---|---|---|
nii_dilate_msk |
5.79 ±0.00 | 5.80 ±0.00 | +0.3% | — |
nii_erode_msk |
5.80 ±0.00 | 5.82 ±0.00 | +0.3% | — |
nii_save |
3.65 ±0.00 | 3.65 ±0.00 | +0.0% | — |
nii_set_dtype |
5.18 ±0.00 | 5.18 ±0.00 | +0.0% | — |
nii_reorient |
5.74 ±0.00 | 5.74 ±0.00 | +0.0% | — |
nii_apply_crop |
5.74 ±0.00 | 5.74 ±0.00 | +0.0% | — |
nii_pad_to |
5.30 ±0.00 | 5.30 ±0.00 | +0.0% | — |
nii_volumes |
3.46 ±0.00 | 3.46 ±0.00 | +0.0% | — |
nii_center_of_masses |
3.21 ±0.00 | 3.21 ±0.00 | +0.0% | — |
nii_extract_label |
5.24 ±0.00 | 5.24 ±0.00 | +0.0% | — |
nii_map_labels |
5.37 ±0.00 | 5.37 ±0.00 | +0.0% | — |
nii_fill_holes |
6.16 ±0.00 | 6.16 ±0.00 | +0.0% | — |
nii_get_connected_components |
6.49 ±0.00 | 6.49 ±0.00 | +0.0% | — |
nii_filter_connected_components |
6.74 ±0.00 | 6.74 ±0.00 | +0.0% | — |
poi_calc_centroids |
5.93 ±0.00 | 5.93 ±0.00 | +0.0% | — |
poi_calc_centroids_nocrop |
5.86 ±0.00 | 5.86 ±0.00 | +0.0% | — |
poi_reorient |
3.77 ±0.00 | 3.77 ±0.00 | +0.0% | — |
poi_to_global |
3.02 ±0.00 | 3.02 ±0.00 | +0.0% | — |
poi_resample_from_to |
5.11 ±0.00 | 5.11 ±0.00 | +0.0% | — |
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% | — |
nii_get_array |
1.59 ±0.00 | 1.59 ±0.00 | +0.0% (noise) | — |
nii_compute_crop |
2.84 ±0.00 | 2.84 ±0.00 | +0.0% (noise) | — |
nii_unique |
2.90 ±0.00 | 2.90 ±0.00 | +0.0% (noise) | — |
poi_rescale |
2.54 ±0.00 | 2.54 ±0.00 | +0.0% (noise) | — |
poi_local_to_global_arr |
2.89 ±0.00 | 2.89 ±0.00 | +0.0% (noise) | — |
poi_save |
1.40 ±0.00 | 1.40 ±0.00 | +0.0% (noise) | — |
poi_map_labels |
1.71 ±0.00 | 1.71 ±0.00 | +0.0% (noise) | — |
poi_load |
1.55 ±0.00 | 1.55 ±0.00 | +0.0% (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 B3 from the cross-repo survey.
What
np_utilsnp_raymarch_until_background(arr, start, direction, …)— fixed-step, trilinear-interpolated march until the mask drops below a threshold, withmax_steps/max_distanceguards. Accepts a prebuiltinterpolatorfor marching many rays through one mask.np_label_interface_thickness(arr, label, other_label, zoom=…)— how thicklabelis where it meetsother_label, measured by marching inward along the surface normal from every interface voxel.poi_fun/ray_castingmax_distance_ray_cast_non_convex(region: NII, …)— NII wrapper, default stepmin(zoom)/16.NIIlabel_interface_thickness(label, other_label, …)— returns millimetres viazoom.Why this is a real gap
max_distance_ray_cast_convexbisects, which silently assumes convexity. On a mask with an interior gap it reports the far outer wall rather than the near edge of the gap:[5,35)with a hole at[15,20), ray from x=6 along +xmax_distance_ray_cast_convex(existing)max_distance_ray_cast_non_convex(new)Both numbers are asserted in the tests, so the distinction stays pinned.
Changes from the source implementation
RegularGridInterpolatorover the whole volume inside the per-boundary-voxel function, so cost scaled asO(n_boundary × volume). It is now built once innp_label_interface_thicknessand passed in.zoomis given, rather than voxels.max_count_componentis a parameter instead of hardcoded to 2.max_steps=Noneand onlymax_distancewas set, the fallback assigned1e8(a float) torange(), raisingTypeError. Now covered by a test.A note on what the number means
Thickness is measured from the interface voxel's center to the 0.5 isosurface, so an 8-voxel slab reads ≈8.5, not 8.0. The half-voxel is inherent to interpolating a binary mask, and the tests assert the value with that offset rather than papering over it.
Verification
unit_tests/test_nputils.pyandunit_tests/test_nii_extended.py: exit point on a slab; stopping at an interior gap; the convex-bisection contrast;Noneon step and distance limits; missing-limit assertion; leaving the volume; known slab thickness and its zero variance; zoom scaling; no-contact empty result;max_count_componentfiltering (with a fixture where the second component genuinely touches the reference, so the parameter is actually exercised); and NII/array-level agreement.ruff checkclean.🤖 Generated with Claude Code