Source code for AFQ.recognition.roi

import numpy as np
from dipy.core.interpolation import interpolate_scalar_3d


[docs] def _interp_arr_with_affine(roi, arr, affine): inv_affine = np.linalg.inv(affine) lin_T = inv_affine[:3, :3].T offset = inv_affine[:3, 3] arr_xformd = np.dot(arr, lin_T) + offset return np.array(interpolate_scalar_3d(roi, arr_xformd)[0])
[docs] def check_sls_with_inclusion(sls, include_rois, include_roi_tols): inc_results = np.zeros(len(sls), dtype=tuple) for jj, sl in enumerate(sls): closest = np.zeros(len(include_rois), dtype=np.int32) dists = np.zeros(len(include_rois), dtype=np.float32) sl = np.asarray(sl) valid = True for ii, roi in enumerate(include_rois): dist = _interp_arr_with_affine(roi.get_fdata(), sl, roi.affine) closest[ii] = np.argmin(dist) dists[ii] = dist[closest[ii]] if dist[closest[ii]] > include_roi_tols[ii]: # Too far from one of them: inc_results[jj] = (False, [], []) valid = False break # Checked all the ROIs and it was close to all of them if valid: inc_results[jj] = (True, closest, dists) return inc_results
[docs] def check_sl_with_exclusion(sl, exclude_rois, exclude_roi_tols): """Helper function to check that a streamline is not too close to a list of exclusion ROIs. """ for ii, roi in enumerate(exclude_rois): # if any part of the streamline is near any exclusion ROI, # return False if np.any( _interp_arr_with_affine(roi.get_fdata(), sl, roi.affine) <= exclude_roi_tols[ii] ): return False # Either there are no exclusion ROIs, or you are not close to any: return True
[docs] def clean_by_endpoints(fgarray, target, target_idx, tol=0, flip_sls=None): """ Clean a collection of streamlines based on an endpoint ROI. Filters down to only include items that have their start or end points close to the targets. Parameters ---------- fgarray : ndarray of shape (N, M, 3) Where N is number of streamlines, M is number of nodes. Assumed to be in RASMM space. target: Nifti1Image Nifti1Image containing a distance transform of the ROI. target_idx: int. Index within each streamline to check if within the target region. Typically 0 for startpoint ROIs or -1 for endpoint ROIs. If using flip_sls, this becomes (len(sl) - this_idx - 1) % len(sl) tol : int, optional A distance tolerance (in units that the coordinates of the streamlines are represented in). Default: 0, which means that the endpoint is exactly in the coordinate of the target ROI. flip_sls : 1d array, optional Length is len(streamlines), whether to flip the streamline. Yields ------- boolean array of streamlines that survive cleaning. """ if not isinstance(fgarray, np.ndarray): raise ValueError( ( "fgarray must be a numpy ndarray, you can resample " "your streamlines using resample_tg in AFQ.recognition.utils" ) ) n_sls, n_nodes, _ = fgarray.shape # handle target_idx negative values as wrapping around effective_idx = target_idx if target_idx >= 0 else (n_nodes + target_idx) indices = np.full(n_sls, effective_idx) if flip_sls is not None: flipped_indices = n_nodes - 1 - effective_idx indices = np.where(flip_sls.astype(bool), flipped_indices, indices) distances = _interp_arr_with_affine( target.get_fdata(), fgarray[np.arange(n_sls), indices], target.affine ) return distances <= tol