Skip to content

Commit eca7996

Browse files
committed
ENH: Fix Bland-Altman plot salient data identification
Fix Bland-Altman plot salient data identification: - Fix the indices of the rightmost/closest to mean zero different salient points: the previous implementation was not keeping `top_n` points, and was returning all percentile count points. - The mask corresponding to the rightmost/closest to mean zero different salient points was not, in reality, a (boolean) mask; instead, it contained the indices of the salient points at issue. These turned out to be correctly computed, and hence when indexing the BA plot data array, the plot matched what was expected. This error went unnoticed in commit b2f544b because only the mask is used to highlight the salient data. Add a test that ensures that the returned data dimensionality is the one expected.
1 parent 1cef030 commit eca7996

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

src/nifreeze/analysis/measure_agreement.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,18 +258,20 @@ def identify_bland_altman_salient_data(
258258
# Sort indices by descending mean (rightmost values first)
259259
right_sort_mean = remaining_idx[np.argsort(mean[remaining_idx])[::-1]]
260260

261-
# Take top percentile of the rightmost points
261+
# Take a percentile of the rightmost points
262262
top_p_count = int(percentile * len(right_sort_mean))
263263
top_p_sorted = right_sort_mean[:top_p_count]
264264

265265
# Get absolute difference from mean_diff (closeness to zero mean difference)
266266
diff_distance = np.abs(diff[top_p_sorted] - mean_diff)
267267

268268
# Sort rightmost points by closeness to zero diff
269-
upper_idx = np.argsort(diff_distance)
269+
top_p_idx = np.argsort(diff_distance)
270270

271271
# Take top_n of them
272-
right_mask = right_sort_mean[upper_idx[:top_n]]
272+
upper_idx = top_p_sorted[top_p_idx][:top_n]
273+
right_mask = np.zeros_like(reliability_mask, dtype=bool)
274+
right_mask[upper_idx] = True
273275

274276
return {
275277
BASalientEntity.RELIABILITY_INDICES.value: reliability_idx,

test/test_analysis.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
import pytest
2727

2828
from nifreeze.analysis.measure_agreement import (
29+
BASalientEntity,
2930
compute_bland_altman_features,
3031
compute_z_score,
32+
identify_bland_altman_salient_data,
3133
)
3234

3335

@@ -105,3 +107,23 @@ def test_compute_bland_altman_features(request):
105107
assert loa_lower < loa_upper
106108
assert np.isscalar(ci_mean)
107109
assert np.isscalar(ci_loa)
110+
111+
112+
def test_identify_bland_altman_salient_data():
113+
_data1 = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
114+
_data2 = np.array([1.1, 2.1, 1.1, 2.7, 3.4, 5.1, 2.2, 6.3, 7.6, 8.2])
115+
116+
ci = 0.95
117+
top_n = 2
118+
119+
# Generate measurements
120+
percentile = 0.75
121+
salient_data = identify_bland_altman_salient_data(_data1, _data2, ci, top_n, percentile=percentile)
122+
123+
assert len(salient_data[BASalientEntity.RELIABILITY_MASK.value]) == len(_data1)
124+
125+
assert len(salient_data[BASalientEntity.LEFT_INDICES.value]) == top_n
126+
assert len(salient_data[BASalientEntity.LEFT_MASK.value]) == len(_data1)
127+
128+
assert len(salient_data[BASalientEntity.RIGHT_INDICES.value]) == top_n
129+
assert len(salient_data[BASalientEntity.RIGHT_MASK.value]) == len(_data1)

0 commit comments

Comments
 (0)