diff --git a/scilpy/tractograms/streamline_operations.py b/scilpy/tractograms/streamline_operations.py index feefa276e..d79d5ae52 100644 --- a/scilpy/tractograms/streamline_operations.py +++ b/scilpy/tractograms/streamline_operations.py @@ -224,6 +224,8 @@ def cut_invalid_streamlines(sft, epsilon=0.001): ---------- sft: StatefulTractogram The sft to remove invalid points from. + epsilon: float + Error allowed when verifying the bounding box. Returns ------- @@ -243,7 +245,7 @@ def cut_invalid_streamlines(sft, epsilon=0.001): sft.to_corner() copy_sft = copy.deepcopy(sft) - indices_to_remove, _ = copy_sft.remove_invalid_streamlines() + indices_to_cut, _ = copy_sft.remove_invalid_streamlines() new_streamlines = [] new_data_per_point = {} @@ -255,21 +257,27 @@ def cut_invalid_streamlines(sft, epsilon=0.001): cutting_counter = 0 for ind in range(len(sft.streamlines)): - # No reason to try to cut if all points are within the volume - if ind in indices_to_remove: - best_pos = [0, 0] - cur_pos = [0, 0] + if ind in indices_to_cut: + # This streamline was detected as invalid + + best_pos = [0, 0] # First and last valid points of longest segment + cur_pos = [0, 0] # First and last valid points of current segment for pos, point in enumerate(sft.streamlines[ind]): if (point < epsilon).any() or \ (point >= sft.dimensions - epsilon).any(): + # The coordinate is < 0 or > box. Starting new segment cur_pos = [pos+1, pos+1] - if cur_pos[1] - cur_pos[0] > best_pos[1] - best_pos[0]: + elif cur_pos[1] - cur_pos[0] > best_pos[1] - best_pos[0]: + # We found a longer good segment. best_pos = cur_pos + + # Ready to check next point. cur_pos[1] += 1 + # Appending the longest segment to the list of streamlines if not best_pos == [0, 0]: new_streamlines.append( - sft.streamlines[ind][best_pos[0]:best_pos[1]-1]) + sft.streamlines[ind][best_pos[0]:best_pos[1]]) cutting_counter += 1 for key in sft.data_per_streamline.keys(): new_data_per_streamline[key].append( @@ -279,8 +287,9 @@ def cut_invalid_streamlines(sft, epsilon=0.001): sft.data_per_point[key][ind][ best_pos[0]:best_pos[1]-1]) else: - logging.warning('Streamlines entirely out of the volume.') + logging.warning('Streamline entirely out of the volume.') else: + # No reason to try to cut if all points are within the volume new_streamlines.append(sft.streamlines[ind]) for key in sft.data_per_streamline.keys(): new_data_per_streamline[key].append( diff --git a/scilpy/tractograms/tests/test_streamline_operations.py b/scilpy/tractograms/tests/test_streamline_operations.py index ab82144b2..1d500cee4 100644 --- a/scilpy/tractograms/tests/test_streamline_operations.py +++ b/scilpy/tractograms/tests/test_streamline_operations.py @@ -19,7 +19,7 @@ smooth_line_gaussian, smooth_line_spline, parallel_transport_streamline, get_angles, get_streamlines_as_linspaces, - compress_sft) + compress_sft, cut_invalid_streamlines) from scilpy.tractograms.tractogram_operations import concatenate_sft @@ -83,8 +83,21 @@ def test_compress_sft(): def test_cut_invalid_streamlines(): - # toDo - pass + sft = load_tractogram(in_long_sft, in_ref) + sft.to_vox() + + cut, nb = cut_invalid_streamlines(sft) + assert len(cut) == len(sft) + assert nb == 0 + + # Faking an invalid streamline. Currently, volume is 64x64x3 + sft.streamlines[0][-1, :] = [65.0, 65.0, 2.0] + cut, nb = cut_invalid_streamlines(sft) + assert len(cut) == len(sft) + assert np.all([len(sc) <= len(s) for s, sc in + zip(sft.streamlines, cut.streamlines)]) + assert len(cut.streamlines[0]) == len(sft.streamlines[0]) - 1 + assert nb == 1 def test_filter_streamlines_by_length():