def streamlines_in_mask(sft, target_mask, all_in=False): """ Parameters ---------- sft : StatefulTractogram StatefulTractogram containing the streamlines to segment. target_mask : numpy.ndarray Binary mask in which the streamlines should pass. Returns ------- ids : list Ids of the streamlines passing through the mask. """ sft.to_vox() sft.to_corner() # Copy-Paste from Dipy to get indices if all_in: target_mask = np.array(target_mask, dtype=bool, copy=True) target_mask = np.invert(target_mask) tractogram_mask = compute_tract_counts_map(sft.streamlines, target_mask.shape) tractogram_mask[tractogram_mask > 0] = 1 tmp_mask = tractogram_mask.astype(np.uint8) * target_mask.astype( np.uint8) streamlines_case = _streamlines_in_mask(list(sft.streamlines), tmp_mask, np.eye(3), [0, 0, 0]) return np.where(streamlines_case == [0, 1][False])[0].tolist() else: target_mask = np.array(target_mask, dtype=np.uint8, copy=True) streamlines_case = _streamlines_in_mask(list(sft.streamlines), target_mask, np.eye(3), [0, 0, 0]) return np.where(streamlines_case == [0, 1][True])[0].tolist()
def target_line_based(streamlines, affine, target_mask, include=True): """Filter streamlines based on whether or not they pass through a ROI, using a line-based algorithm. Mostly used as a replacement of `target` for compressed streamlines. This function never returns single-point streamlines, whatever the value of `include`. Parameters ---------- streamlines : iterable A sequence of streamlines. Each streamline should be a (N, 3) array, where N is the length of the streamline. affine : array (4, 4) The mapping between voxel indices and the point space for seeds. The voxel_to_rasmm matrix, typically from a NIFTI file. target_mask : array-like A mask used as a target. Non-zero values are considered to be within the target region. include : bool, default True If True, streamlines passing through `target_mask` are kept. If False, the streamlines not passing through `target_mask` are kept. Returns ------- streamlines : generator A sequence of streamlines that pass through `target_mask`. References ---------- [Bresenham5] Bresenham, Jack Elton. "Algorithm for computer control of a digital plotter", IBM Systems Journal, vol 4, no. 1, 1965. [Houde15] Houde et al. How to avoid biased streamlines-based metrics for streamlines with variable step sizes, ISMRM 2015. See Also -------- dipy.tracking.utils.density_map dipy.tracking.streamline.compress_streamlines """ target_mask = np.array(target_mask, dtype=np.uint8, copy=True) lin_T, offset = _mapping_to_voxel(affine) streamline_index = _streamlines_in_mask(streamlines, target_mask, lin_T, offset) yield # End of initialization for idx in np.where(streamline_index == [0, 1][include])[0]: yield streamlines[idx]
def target_line_based(streamlines, target_mask, affine=None, include=True): # Copy-Paste from Dipy to get indices target_mask = np.array(target_mask, dtype=np.uint8, copy=True) lin_T, offset = _mapping_to_voxel(affine) streamline_index = _streamlines_in_mask( streamlines, target_mask, lin_T, offset) target_indices = [] target_streamlines = [] for idx in np.where(streamline_index == [0, 1][include])[0]: target_indices.append(idx) target_streamlines.append(streamlines[idx]) return target_streamlines, target_indices
def target_line_based(streamlines, target_mask, affine=None, include=True): """Filters streamlines based on whether or not they pass through a ROI, using a line-based algorithm. Mostly used as a replacement of `target` for compressed streamlines. This function never returns single-point streamlines, whatever the value of `include`. Parameters ---------- streamlines : iterable A sequence of streamlines. Each streamline should be a (N, 3) array, where N is the length of the streamline. target_mask : array-like A mask used as a target. Non-zero values are considered to be within the target region. affine : array (4, 4) The affine transform from voxel indices to streamline points. include : bool, default True If True, streamlines passing through `target_mask` are kept. If False, the streamlines not passing through `target_mask` are kept. Returns ------- streamlines : generator A sequence of streamlines that pass through `target_mask`. References ---------- [Bresenham5] Bresenham, Jack Elton. "Algorithm for computer control of a digital plotter", IBM Systems Journal, vol 4, no. 1, 1965. [Houde15] Houde et al. How to avoid biased streamlines-based metrics for streamlines with variable step sizes, ISMRM 2015. See Also -------- dipy.tracking.utils.density_map dipy.tracking.streamline.compress_streamlines """ target_mask = np.array(target_mask, dtype=np.uint8, copy=True) lin_T, offset = _mapping_to_voxel(affine, voxel_size=None) streamline_index = _streamlines_in_mask( streamlines, target_mask, lin_T, offset) yield # End of initialization for idx in np.where(streamline_index == [0, 1][include])[0]: yield streamlines[idx]
def streamlines_in_mask(sft, target_mask): """ Parameters ---------- sft : StatefulTractogram StatefulTractogram containing the streamlines to segment. target_mask : numpy.ndarray Binary mask in which the streamlines should pass. Returns ------- ids : list Ids of the streamlines passing through the mask. """ sft.to_vox() sft.to_corner() # Copy-Paste from Dipy to get indices target_mask = np.array(target_mask, dtype=np.uint8, copy=True) streamlines_case = _streamlines_in_mask(list(sft.streamlines), target_mask, np.eye(3), [-0.5, -0.5, -0.5]) return np.where(streamlines_case == [0, 1][True])[0].tolist()
def _processing_wrapper(args): hdf5_filename = args[0] labels_img = args[1] in_label, out_label = args[2] measures_to_compute = copy.copy(args[3]) if args[4] is not None: similarity_directory = args[4][0] weighted = args[5] include_dps = args[6] min_lesion_vol = args[7] hdf5_file = h5py.File(hdf5_filename, 'r') key = '{}_{}'.format(in_label, out_label) if key not in hdf5_file: return streamlines = reconstruct_streamlines_from_hdf5(hdf5_file, key) if len(streamlines) == 0: return affine, dimensions, voxel_sizes, _ = get_reference_info(labels_img) measures_to_return = {} if not (np.allclose(hdf5_file.attrs['affine'], affine, atol=1e-03) and np.array_equal(hdf5_file.attrs['dimensions'], dimensions)): raise ValueError('Provided hdf5 have incompatible headers.') # Precompute to save one transformation, insert later if 'length' in measures_to_compute: streamlines_copy = list(streamlines) # scil_decompose_connectivity.py requires isotropic voxels mean_length = np.average(length(streamlines_copy))*voxel_sizes[0] # If density is not required, do not compute it # Only required for volume, similarity and any metrics if not ((len(measures_to_compute) == 1 and ('length' in measures_to_compute or 'streamline_count' in measures_to_compute)) or (len(measures_to_compute) == 2 and ('length' in measures_to_compute and 'streamline_count' in measures_to_compute))): density = compute_tract_counts_map(streamlines, dimensions) if 'volume' in measures_to_compute: measures_to_return['volume'] = np.count_nonzero(density) * \ np.prod(voxel_sizes) measures_to_compute.remove('volume') if 'streamline_count' in measures_to_compute: measures_to_return['streamline_count'] = len(streamlines) measures_to_compute.remove('streamline_count') if 'length' in measures_to_compute: measures_to_return['length'] = mean_length measures_to_compute.remove('length') if 'similarity' in measures_to_compute and similarity_directory: density_sim = load_node_nifti(similarity_directory, in_label, out_label, labels_img) if density_sim is None: ba_vox = 0 else: ba_vox = compute_bundle_adjacency_voxel(density, density_sim) measures_to_return['similarity'] = ba_vox measures_to_compute.remove('similarity') for measure in measures_to_compute: # Maps if isinstance(measure, str) and os.path.isdir(measure): map_dirname = measure map_data = load_node_nifti(map_dirname, in_label, out_label, labels_img) measures_to_return[map_dirname] = np.average( map_data[map_data > 0]) elif isinstance(measure, tuple): if not isinstance(measure[0], tuple) \ and os.path.isfile(measure[0]): metric_filename = measure[0] metric_img = measure[1] if not is_header_compatible(metric_img, labels_img): logging.error('{} do not have a compatible header'.format( metric_filename)) raise IOError metric_data = metric_img.get_fdata(dtype=np.float64) if weighted: avg_value = np.average(metric_data, weights=density) else: avg_value = np.average(metric_data[density > 0]) measures_to_return[metric_filename] = avg_value # lesion else: lesion_filename = measure[0][0] computed_lesion_labels = measure[0][1] lesion_img = measure[1] if not is_header_compatible(lesion_img, labels_img): logging.error('{} do not have a compatible header'.format( lesion_filename)) raise IOError voxel_sizes = lesion_img.header.get_zooms()[0:3] lesion_img.set_filename('tmp.nii.gz') lesion_atlas = get_data_as_label(lesion_img) tmp_dict = compute_lesion_stats( density.astype(bool), lesion_atlas, voxel_sizes=voxel_sizes, single_label=True, min_lesion_vol=min_lesion_vol, precomputed_lesion_labels=computed_lesion_labels) tmp_ind = _streamlines_in_mask(list(streamlines), lesion_atlas.astype(np.uint8), np.eye(3), [0, 0, 0]) streamlines_count = len( np.where(tmp_ind == [0, 1][True])[0].tolist()) if tmp_dict: measures_to_return[lesion_filename+'vol'] = \ tmp_dict['lesion_total_volume'] measures_to_return[lesion_filename+'count'] = \ tmp_dict['lesion_count'] measures_to_return[lesion_filename+'sc'] = \ streamlines_count else: measures_to_return[lesion_filename+'vol'] = 0 measures_to_return[lesion_filename+'count'] = 0 measures_to_return[lesion_filename+'sc'] = 0 if include_dps: for dps_key in hdf5_file[key].keys(): if dps_key not in ['data', 'offsets', 'lengths']: out_file = os.path.join(include_dps, dps_key) if 'commit' in dps_key: measures_to_return[out_file] = np.sum( hdf5_file[key][dps_key]) else: measures_to_return[out_file] = np.average( hdf5_file[key][dps_key]) return {(in_label, out_label): measures_to_return}