def test_act_tissue_classifier(): """This tests that the act tissue classifier returns expected tissue types. """ gm = np.random.random((4, 4, 4)) wm = np.random.random((4, 4, 4)) csf = np.random.random((4, 4, 4)) tissue_sum = gm + wm + csf gm /= tissue_sum wm /= tissue_sum csf /= tissue_sum act_tc = ActTissueClassifier(include_map=gm, exclude_map=csf) # test voxel center for ind in ndindex(wm.shape): pts = np.array(ind, dtype='float64') state = act_tc.check_point(pts) if csf[ind] > 0.5: npt.assert_equal(state, TissueTypes.INVALIDPOINT) elif gm[ind] > 0.5: npt.assert_equal(state, TissueTypes.ENDPOINT) else: npt.assert_equal(state, TissueTypes.TRACKPOINT) # test random points in voxel inds = [[0, 1.4, 2.2], [0, 2.3, 2.3], [0, 2.2, 1.3], [0, 0.9, 2.2], [0, 2.8, 1.1], [0, 1.1, 3.3], [0, 2.1, 1.9], [0, 3.1, 3.1], [0, 0.1, 0.1], [0, 0.9, 0.5], [0, 0.9, 0.5], [0, 2.9, 0.1]] for pts in inds: pts = np.array(pts, dtype='float64') state = act_tc.check_point(pts) gm_res = scipy.ndimage.map_coordinates(gm, np.reshape(pts, (3, 1)), order=1, mode='nearest') csf_res = scipy.ndimage.map_coordinates(csf, np.reshape(pts, (3, 1)), order=1, mode='nearest') if csf_res > 0.5: npt.assert_equal(state, TissueTypes.INVALIDPOINT) elif gm_res > 0.5: npt.assert_equal(state, TissueTypes.ENDPOINT) else: npt.assert_equal(state, TissueTypes.TRACKPOINT) # test outside points outside_pts = [[100, 100, 100], [0, -1, 1], [0, 10, 2], [0, 0.5, -0.51], [0, -0.51, 0.1]] for pts in outside_pts: pts = np.array(pts, dtype='float64') state = act_tc.check_point(pts) npt.assert_equal(state, TissueTypes.OUTSIDEIMAGE)
def test_act_tissue_classifier(): """This tests that the act tissue classifier returns expected tissue types. """ gm = np.random.random((4, 4, 4)) wm = np.random.random((4, 4, 4)) csf = np.random.random((4, 4, 4)) tissue_sum = gm + wm + csf gm /= tissue_sum wm /= tissue_sum csf /= tissue_sum act_tc = ActTissueClassifier(include_map=gm, exclude_map=csf) # test voxel center for ind in ndindex(wm.shape): pts = np.array(ind, dtype='float64') state = act_tc.check_point(pts) if csf[ind] > 0.5: npt.assert_equal(state, TissueTypes.INVALIDPOINT) elif gm[ind] > 0.5: npt.assert_equal(state, TissueTypes.ENDPOINT) else: npt.assert_equal(state, TissueTypes.TRACKPOINT) # test random points in voxel inds = [[0, 1.4, 2.2], [0, 2.3, 2.3], [0, 2.2, 1.3], [0, 0.9, 2.2], [0, 2.8, 1.1], [0, 1.1, 3.3], [0, 2.1, 1.9], [0, 3.1, 3.1], [0, 0.1, 0.1], [0, 0.9, 0.5], [0, 0.9, 0.5], [0, 2.9, 0.1]] for pts in inds: pts = np.array(pts, dtype='float64') state = act_tc.check_point(pts) gm_res = scipy.ndimage.map_coordinates( gm, np.reshape(pts, (3, 1)), order=1, mode='nearest') csf_res = scipy.ndimage.map_coordinates( csf, np.reshape(pts, (3, 1)), order=1, mode='nearest') if csf_res > 0.5: npt.assert_equal(state, TissueTypes.INVALIDPOINT) elif gm_res > 0.5: npt.assert_equal(state, TissueTypes.ENDPOINT) else: npt.assert_equal(state, TissueTypes.TRACKPOINT) # test outside points outside_pts = [[100, 100, 100], [0, -1, 1], [0, 10, 2], [0, 0.5, -0.51], [0, -0.51, 0.1]] for pts in outside_pts: pts = np.array(pts, dtype='float64') state = act_tc.check_point(pts) npt.assert_equal(state, TissueTypes.OUTSIDEIMAGE)
def prep_tissues(nodif_B0_mask, gm_in_dwi, vent_csf_in_dwi, wm_in_dwi, tiss_class, cmc_step_size=0.2): try: import cPickle as pickle except ImportError: import _pickle as pickle from dipy.tracking.local import ActTissueClassifier, CmcTissueClassifier, BinaryTissueClassifier # Loads mask and ensures it's a true binary mask mask_img = nib.load(nodif_B0_mask) # Load tissue maps and prepare tissue classifier gm_mask = nib.load(gm_in_dwi) gm_mask_data = gm_mask.get_fdata() wm_mask = nib.load(wm_in_dwi) wm_mask_data = wm_mask.get_fdata() if tiss_class == 'act': vent_csf_in_dwi = nib.load(vent_csf_in_dwi) vent_csf_in_dwi_data = vent_csf_in_dwi.get_fdata() background = np.ones(mask_img.shape) background[(gm_mask_data + wm_mask_data + vent_csf_in_dwi_data) > 0] = 0 include_map = gm_mask_data include_map[background > 0] = 1 exclude_map = vent_csf_in_dwi_data tiss_classifier = ActTissueClassifier(include_map, exclude_map) elif tiss_class == 'bin': wm_in_dwi_data = nib.load(wm_in_dwi).get_fdata().astype('bool') tiss_classifier = BinaryTissueClassifier(wm_in_dwi_data) elif tiss_class == 'cmc': vent_csf_in_dwi = nib.load(vent_csf_in_dwi) vent_csf_in_dwi_data = vent_csf_in_dwi.get_fdata() voxel_size = np.average(wm_mask.get_header()['pixdim'][1:4]) tiss_classifier = CmcTissueClassifier.from_pve(wm_mask_data, gm_mask_data, vent_csf_in_dwi_data, step_size=cmc_step_size, average_voxel_size=voxel_size) else: raise ValueError("%s%s%s" % ('Error: tissuer classification method: ', tiss_class, 'not found')) return tiss_classifier
def test_save_seeds(): tissue = np.array([[2, 1, 1, 2, 1], [2, 2, 1, 1, 2], [1, 1, 1, 1, 1], [1, 1, 1, 2, 2], [0, 1, 1, 1, 2], [0, 1, 1, 0, 2], [1, 0, 1, 1, 1]]) tissue = tissue[None] sphere = HemiSphere.from_sphere(unit_octahedron) pmf_lookup = np.array([[0., 0., 0., ], [0., 0., 1.]]) pmf = pmf_lookup[(tissue > 0).astype("int")] # Create a seeds along x = np.array([0., 0, 0, 0, 0, 0, 0]) y = np.array([0., 1, 2, 3, 4, 5, 6]) z = np.array([1., 1, 1, 0, 1, 1, 1]) seeds = np.column_stack([x, y, z]) # Set up tracking endpoint_mask = tissue == TissueTypes.ENDPOINT invalidpoint_mask = tissue == TissueTypes.INVALIDPOINT tc = ActTissueClassifier(endpoint_mask, invalidpoint_mask) dg = ProbabilisticDirectionGetter.from_pmf(pmf, 60, sphere) # valid streamlines only streamlines_generator = LocalTracking(direction_getter=dg, tissue_classifier=tc, seeds=seeds, affine=np.eye(4), step_size=1., return_all=False, save_seeds=True) streamlines_not_all = iter(streamlines_generator) # Verifiy that seeds are returned by the LocalTracker _, seed = next(streamlines_not_all) npt.assert_equal(seed, seeds[0]) _, seed = next(streamlines_not_all) npt.assert_equal(seed, seeds[1]) # Verifiy that seeds are returned by the PFTTracker also pft_streamlines = ParticleFilteringTracking(direction_getter=dg, tissue_classifier=tc, seeds=seeds, affine=np.eye(4), step_size=1., max_cross=1, return_all=False, save_seeds=True) streamlines = iter(pft_streamlines) _, seed = next(streamlines) npt.assert_equal(seed, seeds[0]) _, seed = next(streamlines) npt.assert_equal(seed, seeds[1])
- 'INVALIDPOINT': ``exclude_map`` > 0.5. """ from dipy.tracking.local import ActTissueClassifier img_pve_csf, img_pve_gm, img_pve_wm = read_stanford_pve_maps() background = np.ones(img_pve_gm.shape) background[(img_pve_gm.get_data() + img_pve_wm.get_data() + img_pve_csf.get_data()) > 0] = 0 include_map = img_pve_gm.get_data() include_map[background > 0] = 1 exclude_map = img_pve_csf.get_data() act_classifier = ActTissueClassifier(include_map, exclude_map) fig = plt.figure() plt.subplot(121) plt.xticks([]) plt.yticks([]) plt.imshow(include_map[:, :, data.shape[2] // 2].T, cmap='gray', origin='lower', interpolation='nearest') plt.subplot(122) plt.xticks([]) plt.yticks([]) plt.imshow(exclude_map[:, :, data.shape[2] // 2].T, cmap='gray', origin='lower',
def main(): parser = _build_args_parser() args = parser.parse_args() if args.isVerbose: logging.basicConfig(level=logging.DEBUG) assert_inputs_exist(parser, [ args.sh_file, args.seed_file, args.map_include_file, args.map_exclude_file ]) assert_outputs_exist(parser, args, [args.output_file]) if not nib.streamlines.is_supported(args.output_file): parser.error('Invalid output streamline file format (must be trk or ' + 'tck): {0}'.format(args.output_file)) if not args.min_length > 0: parser.error('minL must be > 0, {}mm was provided.'.format( args.min_length)) if args.max_length < args.min_length: parser.error( 'maxL must be > than minL, (minL={}mm, maxL={}mm).'.format( args.min_length, args.max_length)) if args.compress: if args.compress < 0.001 or args.compress > 1: logging.warning( 'You are using an error rate of {}.\nWe recommend setting it ' 'between 0.001 and 1.\n0.001 will do almost nothing to the ' 'tracts while 1 will higly compress/linearize the tracts'. format(args.compress)) if args.particles <= 0: parser.error('--particles must be >= 1.') if args.back_tracking <= 0: parser.error('PFT backtracking distance must be > 0.') if args.forward_tracking <= 0: parser.error('PFT forward tracking distance must be > 0.') if args.npv and args.npv <= 0: parser.error('Number of seeds per voxel must be > 0.') if args.nt and args.nt <= 0: parser.error('Total number of seeds must be > 0.') fodf_sh_img = nib.load(args.sh_file) fodf_sh_img = nib.load(args.sh_file) if not np.allclose(np.mean(fodf_sh_img.header.get_zooms()[:3]), fodf_sh_img.header.get_zooms()[0], atol=1.e-3): parser.error( 'SH file is not isotropic. Tracking cannot be ran robustly.') tracking_sphere = HemiSphere.from_sphere(get_sphere('repulsion724')) # Check if sphere is unit, since we couldn't find such check in Dipy. if not np.allclose(np.linalg.norm(tracking_sphere.vertices, axis=1), 1.): raise RuntimeError('Tracking sphere should be unit normed.') sh_basis = args.sh_basis if args.algo == 'det': dgklass = DeterministicMaximumDirectionGetter else: dgklass = ProbabilisticDirectionGetter theta = get_theta(args.theta, args.algo) # Reminder for the future: # pmf_threshold == clip pmf under this # relative_peak_threshold is for initial directions filtering # min_separation_angle is the initial separation angle for peak extraction dg = dgklass.from_shcoeff(fodf_sh_img.get_data().astype(np.double), max_angle=theta, sphere=tracking_sphere, basis_type=sh_basis, pmf_threshold=args.sf_threshold, relative_peak_threshold=args.sf_threshold_init) map_include_img = nib.load(args.map_include_file) map_exclude_img = nib.load(args.map_exclude_file) voxel_size = np.average(map_include_img.get_header()['pixdim'][1:4]) tissue_classifier = None if not args.act: tissue_classifier = CmcTissueClassifier(map_include_img.get_data(), map_exclude_img.get_data(), step_size=args.step_size, average_voxel_size=voxel_size) else: tissue_classifier = ActTissueClassifier(map_include_img.get_data(), map_exclude_img.get_data()) if args.npv: nb_seeds = args.npv seed_per_vox = True elif args.nt: nb_seeds = args.nt seed_per_vox = False else: nb_seeds = 1 seed_per_vox = True voxel_size = fodf_sh_img.header.get_zooms()[0] vox_step_size = args.step_size / voxel_size seed_img = nib.load(args.seed_file) seeds = track_utils.random_seeds_from_mask( seed_img.get_data(), seeds_count=nb_seeds, seed_count_per_voxel=seed_per_vox, random_seed=args.seed) # Note that max steps is used once for the forward pass, and # once for the backwards. This doesn't, in fact, control the real # max length max_steps = int(args.max_length / args.step_size) + 1 pft_streamlines = ParticleFilteringTracking( dg, tissue_classifier, seeds, np.eye(4), max_cross=1, step_size=vox_step_size, maxlen=max_steps, pft_back_tracking_dist=args.back_tracking, pft_front_tracking_dist=args.forward_tracking, particle_count=args.particles, return_all=args.keep_all, random_seed=args.seed) scaled_min_length = args.min_length / voxel_size scaled_max_length = args.max_length / voxel_size filtered_streamlines = ( s for s in pft_streamlines if scaled_min_length <= length(s) <= scaled_max_length) if args.compress: filtered_streamlines = (compress_streamlines(s, args.compress) for s in filtered_streamlines) tractogram = LazyTractogram(lambda: filtered_streamlines, affine_to_rasmm=seed_img.affine) filetype = nib.streamlines.detect_format(args.output_file) header = create_header_from_anat(seed_img, base_filetype=filetype) # Use generator to save the streamlines on-the-fly nib.streamlines.save(tractogram, args.output_file, header=header)
def test_particle_filtering_tractography(): """This tests that the ParticleFilteringTracking produces more streamlines connecting the gray matter than LocalTracking. """ sphere = get_sphere('repulsion100') step_size = 0.2 # Simple tissue masks simple_wm = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0]]) simple_wm = np.dstack([ np.zeros(simple_wm.shape), simple_wm, simple_wm, simple_wm, np.zeros(simple_wm.shape) ]) simple_gm = np.array([[1, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0], [0, 1, 0, 0, 1, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0]]) simple_gm = np.dstack([ np.zeros(simple_gm.shape), simple_gm, simple_gm, simple_gm, np.zeros(simple_gm.shape) ]) simple_csf = np.ones(simple_wm.shape) - simple_wm - simple_gm tc = ActTissueClassifier.from_pve(simple_wm, simple_gm, simple_csf) seeds = seeds_from_mask(simple_wm, density=2) # Random pmf in every voxel shape_img = list(simple_wm.shape) shape_img.extend([sphere.vertices.shape[0]]) np.random.seed(0) # Random number generator initialization pmf = np.random.random(shape_img) # Test that PFT recover equal or more streamlines than localTracking dg = ProbabilisticDirectionGetter.from_pmf(pmf, 60, sphere) local_streamlines_generator = LocalTracking(dg, tc, seeds, np.eye(4), step_size, max_cross=1, return_all=False) local_streamlines = Streamlines(local_streamlines_generator) pft_streamlines_generator = ParticleFilteringTracking( dg, tc, seeds, np.eye(4), step_size, max_cross=1, return_all=False, pft_back_tracking_dist=1, pft_front_tracking_dist=0.5) pft_streamlines = Streamlines(pft_streamlines_generator) npt.assert_(np.array([len(pft_streamlines) > 0])) npt.assert_(np.array([len(pft_streamlines) >= len(local_streamlines)])) # Test that all points are equally spaced for l in [1, 2, 5, 10, 100]: pft_streamlines = ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, max_cross=1, return_all=True, maxlen=l) for s in pft_streamlines: for i in range(len(s) - 1): npt.assert_almost_equal(np.linalg.norm(s[i] - s[i + 1]), step_size) # Test that all points are within the image volume seeds = seeds_from_mask(np.ones(simple_wm.shape), density=1) pft_streamlines_generator = ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, max_cross=1, return_all=True) pft_streamlines = Streamlines(pft_streamlines_generator) for s in pft_streamlines: npt.assert_(np.all((s + 0.5).astype(int) >= 0)) npt.assert_(np.all((s + 0.5).astype(int) < simple_wm.shape)) # Test that the number of streamline return with return_all=True equal the # number of seeds places npt.assert_(np.array([len(pft_streamlines) == len(seeds)])) # Test non WM seed position seeds = [[0, 5, 4], [0, 0, 1], [50, 50, 50]] pft_streamlines_generator = ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, max_cross=1, return_all=True) pft_streamlines = Streamlines(pft_streamlines_generator) npt.assert_equal(len(pft_streamlines[0]), 3) # INVALIDPOINT npt.assert_equal(len(pft_streamlines[1]), 3) # ENDPOINT npt.assert_equal(len(pft_streamlines[2]), 1) # OUTSIDEIMAGE # Test with wrong tissueclassifier type tc_bin = BinaryTissueClassifier(simple_wm) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc_bin, seeds, np.eye(4), step_size)) # Test with invalid back/front tracking distances npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, pft_back_tracking_dist=0, pft_front_tracking_dist=0)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking( dg, tc, seeds, np.eye(4), step_size, pft_back_tracking_dist=-1)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, pft_back_tracking_dist=0, pft_front_tracking_dist=-2)) # Test with invalid affine shape npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(3), step_size)) # Test with invalid maxlen npt.assert_raises( ValueError, lambda: ParticleFilteringTracking( dg, tc, seeds, np.eye(4), step_size, maxlen=0)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking( dg, tc, seeds, np.eye(4), step_size, maxlen=-1)) # Test with invalid particle count npt.assert_raises( ValueError, lambda: ParticleFilteringTracking( dg, tc, seeds, np.eye(4), step_size, particle_count=0)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking( dg, tc, seeds, np.eye(4), step_size, particle_count=-1)) # Test reproducibility tracking_1 = Streamlines( ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, random_seed=0)).data tracking_2 = Streamlines( ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, random_seed=0)).data npt.assert_equal(tracking_1, tracking_2)
def test_stop_conditions(): """This tests that the Local Tracker behaves as expected for the following tissue types. """ # TissueTypes.TRACKPOINT = 1 # TissueTypes.ENDPOINT = 2 # TissueTypes.INVALIDPOINT = 0 tissue = np.array([[2, 1, 1, 2, 1], [2, 2, 1, 1, 2], [1, 1, 1, 1, 1], [1, 1, 1, 2, 2], [0, 1, 1, 1, 2], [0, 1, 1, 0, 2], [1, 0, 1, 1, 1], [2, 1, 2, 0, 0]]) tissue = tissue[None] sphere = HemiSphere.from_sphere(unit_octahedron) pmf_lookup = np.array([[ 0., 0., 0., ], [0., 0., 1.]]) pmf = pmf_lookup[(tissue > 0).astype("int")] # Create a seeds along x = np.array([0., 0, 0, 0, 0, 0, 0, 0]) y = np.array([0., 1, 2, 3, 4, 5, 6, 7]) z = np.array([1., 1, 1, 0, 1, 1, 1, 1]) seeds = np.column_stack([x, y, z]) # Set up tracking endpoint_mask = tissue == TissueTypes.ENDPOINT invalidpoint_mask = tissue == TissueTypes.INVALIDPOINT tc = ActTissueClassifier(endpoint_mask, invalidpoint_mask) dg = ProbabilisticDirectionGetter.from_pmf(pmf, 60, sphere) # valid streamlines only streamlines_generator = LocalTracking(direction_getter=dg, tissue_classifier=tc, seeds=seeds, affine=np.eye(4), step_size=1., return_all=False) streamlines_not_all = iter(streamlines_generator) # all streamlines streamlines_all_generator = LocalTracking(direction_getter=dg, tissue_classifier=tc, seeds=seeds, affine=np.eye(4), step_size=1., return_all=True) streamlines_all = iter(streamlines_all_generator) # Check that the first streamline stops at 1 and 2 (ENDPOINT) y = 0 sl = next(streamlines_not_all) npt.assert_equal(sl[0], [0, y, 1]) npt.assert_equal(sl[-1], [0, y, 2]) npt.assert_equal(len(sl), 2) sl = next(streamlines_all) npt.assert_equal(sl[0], [0, y, 1]) npt.assert_equal(sl[-1], [0, y, 2]) npt.assert_equal(len(sl), 2) # Check that the next streamline stops at 1 and 3 (ENDPOINT) y = 1 sl = next(streamlines_not_all) npt.assert_equal(sl[0], [0, y, 1]) npt.assert_equal(sl[-1], [0, y, 3]) npt.assert_equal(len(sl), 3) sl = next(streamlines_all) npt.assert_equal(sl[0], [0, y, 1]) npt.assert_equal(sl[-1], [0, y, 3]) npt.assert_equal(len(sl), 3) # This streamline should be the same as above. This row does not have # ENDPOINTs, but the streamline should stop at the edge and not include # OUTSIDEIMAGE points. y = 2 sl = next(streamlines_not_all) npt.assert_equal(sl[0], [0, y, 0]) npt.assert_equal(sl[-1], [0, y, 4]) npt.assert_equal(len(sl), 5) sl = next(streamlines_all) npt.assert_equal(sl[0], [0, y, 0]) npt.assert_equal(sl[-1], [0, y, 4]) npt.assert_equal(len(sl), 5) # If we seed on the edge, the first (or last) point in the streamline # should be the seed. y = 3 sl = next(streamlines_not_all) npt.assert_equal(sl[0], seeds[y]) sl = next(streamlines_all) npt.assert_equal(sl[0], seeds[y]) # The last 3 seeds should not produce streamlines, # INVALIDPOINT streamlines are rejected (return_all=False). npt.assert_equal(len(list(streamlines_not_all)), 0) # The last 3 seeds should produce invalid streamlines, # INVALIDPOINT streamlines are kept (return_all=True). # The streamline stops at 1 (INVALIDPOINT) and 3 (ENDPOINT) y = 4 sl = next(streamlines_all) npt.assert_equal(sl[0], [0, y, 1]) npt.assert_equal(sl[-1], [0, y, 3]) npt.assert_equal(len(sl), 3) # The streamline stops at 0 (INVALIDPOINT) and 2 (INVALIDPOINT) y = 5 sl = next(streamlines_all) npt.assert_equal(sl[0], [0, y, 1]) npt.assert_equal(sl[-1], [0, y, 2]) npt.assert_equal(len(sl), 2) # The streamline should contain only one point, the seed point, # because no valid inital direction was returned. y = 6 sl = next(streamlines_all) npt.assert_equal(sl[0], seeds[y]) npt.assert_equal(sl[-1], seeds[y]) npt.assert_equal(len(sl), 1) # The streamline should contain only one point, the seed point, # because no valid neighboring voxel (ENDPOINT) y = 7 sl = next(streamlines_all) npt.assert_equal(sl[0], seeds[y]) npt.assert_equal(sl[-1], seeds[y]) npt.assert_equal(len(sl), 1)
def execution(self, context): sh_coeff_vol = aims.read(self.sh_coefficients.fullPath()) header = sh_coeff_vol.header() #transformation from Aims LPI mm space to RAS mm (reference space) aims_mm_to_ras_mm = np.array(header['transformations'][0]).reshape((4, 4)) voxel_size = np.array(header['voxel_size']) if len(voxel_size) == 4: voxel_size = voxel_size[:-1] scaling = np.concatenate((voxel_size, np.ones(1))) #context.write(voxel_size.shape) scaling_mat = np.diag(scaling) #context.write(scaling_mat.shape, aims_mm_to_ras_mm.shape ) aims_voxel_to_ras_mm = np.dot(aims_mm_to_ras_mm, scaling_mat) affine_tracking = np.eye(4) sh = np.array(sh_coeff_vol, copy=True) sh = sh.astype(np.float64) vol_shape = sh.shape[:-1] if self.sphere is not None: sphere = read_sphere(self.sphere.fullPath()) else: context.write( 'No Projection Sphere provided. Default dipy sphere symmetric 362 is used' ) sphere = get_sphere() dg = DirectionGetter[self.type].from_shcoeff( sh, self.max_angle, sphere, basis_type=None, relative_peak_threshold=self.relative_peak_threshold, min_separation_angle=self.min_separation_angle) #Handling seeds in both deterministic and probabilistic framework s = np.loadtxt(self.seeds.fullPath()) s = s.astype(np.float32) i = np.arange(self.nb_samples) if self.nb_samples <= 1: seeds = s else: seeds = np.zeros((self.nb_samples, ) + s.shape) seeds[i] = s seeds = seeds.reshape((-1, 3)) #put seeds in voxel space context.write(seeds[0]) seeds = nib.affines.apply_affine(np.linalg.inv(scaling_mat), seeds) #building classifier context.write(seeds[0]) if self.constraint == 'Binary': mask_vol = aims.read(self.mask.fullPath()) mask = np.asarray(mask_vol)[..., 0] mask = mask.astype(bool) classifier = BinaryTissueClassifier(mask) elif self.constraint == 'Threshold': scal_vol = aims.read(self.scalar_volume.fullPath()) scal = np.asarray(scal_vol)[..., 0] scal = scal.astype(np.float32) classifier = ThresholdTissueClassifier(scal, self.threshold) else: csf_vol = aims.read(self.csf_pve.fullPath()) grey_vol = aims.read(self.gm_pve.fullPath()) white_vol = aims.read(self.wm_pve.fullPath()) csf = np.array(csf_vol) csf = csf[..., 0] gm = np.array(grey_vol) gm = gm[..., 0] wm = np.array(white_vol) wm = wm[..., 0] #rethreshold volumes due to interpolation (eg values >1) total = (csf + gm + wm).copy() csf[total <= 0] = 0 gm[total <= 0] = 0 wm[total <= 0] = 0 csf[total != 0] = (csf[total != 0]) / (total[total != 0]) wm[total != 0] = (wm[total != 0]) / (total[total != 0]) gm[total != 0] = gm[total != 0] / (total[total != 0]) if self.constraint == 'ACT': classifier = ActTissueClassifier.from_pve(wm_map=wm, gm_map=gm, csf_map=csf) elif self.constraint == 'CMC': classifier = CmcTissueClassifier.from_pve(wm_map=wm, gm_map=gm, csf_map=csf) #Tracking is made in the Aims LPO space (solve shear verification problem, does not work for anisotropic voxels) streamlines_generator = LocalTracking(dg, classifier, seeds, affine_tracking, step_size=self.step_size, max_cross=self.crossing_max, maxlen=self.nb_iter_max, fixedstep=np.float32( self.fixed_step), return_all=self.return_all) #Store Fibers directly in LPI orientation with appropriate transformation save_trk(self.streamlines.fullPath(), streamlines_generator, affine=aims_voxel_to_ras_mm, vox_size=voxel_size, shape=vol_shape) transformManager = getTransformationManager() transformManager.copyReferential(self.sh_coefficients, self.streamlines)
def test_particle_filtering_tractography(): """This tests that the ParticleFilteringTracking produces more streamlines connecting the gray matter than LocalTracking. """ sphere = get_sphere('repulsion100') step_size = 0.2 # Simple tissue masks simple_wm = np.array([[0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0]]) simple_wm = np.dstack([np.zeros(simple_wm.shape), simple_wm, simple_wm, simple_wm, np.zeros(simple_wm.shape)]) simple_gm = np.array([[1, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0], [0, 1, 0, 0, 1, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0]]) simple_gm = np.dstack([np.zeros(simple_gm.shape), simple_gm, simple_gm, simple_gm, np.zeros(simple_gm.shape)]) simple_csf = np.ones(simple_wm.shape) - simple_wm - simple_gm tc = ActTissueClassifier.from_pve(simple_wm, simple_gm, simple_csf) seeds = seeds_from_mask(simple_wm, density=2) # Random pmf in every voxel shape_img = list(simple_wm.shape) shape_img.extend([sphere.vertices.shape[0]]) np.random.seed(0) # Random number generator initialization pmf = np.random.random(shape_img) # Test that PFT recover equal or more streamlines than localTracking dg = ProbabilisticDirectionGetter.from_pmf(pmf, 60, sphere) local_streamlines_generator = LocalTracking(dg, tc, seeds, np.eye(4), step_size, max_cross=1, return_all=False) local_streamlines = Streamlines(local_streamlines_generator) pft_streamlines_generator = ParticleFilteringTracking( dg, tc, seeds, np.eye(4), step_size, max_cross=1, return_all=False, pft_back_tracking_dist=1, pft_front_tracking_dist=0.5) pft_streamlines = Streamlines(pft_streamlines_generator) npt.assert_(np.array([len(pft_streamlines) > 0])) npt.assert_(np.array([len(pft_streamlines) >= len(local_streamlines)])) # Test that all points are equally spaced for l in [1, 2, 5, 10, 100]: pft_streamlines = ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, max_cross=1, return_all=True, maxlen=l) for s in pft_streamlines: for i in range(len(s) - 1): npt.assert_almost_equal(np.linalg.norm(s[i] - s[i + 1]), step_size) # Test that all points are within the image volume seeds = seeds_from_mask(np.ones(simple_wm.shape), density=1) pft_streamlines_generator = ParticleFilteringTracking( dg, tc, seeds, np.eye(4), step_size, max_cross=1, return_all=True) pft_streamlines = Streamlines(pft_streamlines_generator) for s in pft_streamlines: npt.assert_(np.all((s + 0.5).astype(int) >= 0)) npt.assert_(np.all((s + 0.5).astype(int) < simple_wm.shape)) # Test that the number of streamline return with return_all=True equal the # number of seeds places npt.assert_(np.array([len(pft_streamlines) == len(seeds)])) # Test non WM seed position seeds = [[0, 5, 4], [0, 0, 1], [50, 50, 50]] pft_streamlines_generator = ParticleFilteringTracking( dg, tc, seeds, np.eye(4), step_size, max_cross=1, return_all=True) pft_streamlines = Streamlines(pft_streamlines_generator) npt.assert_equal(len(pft_streamlines[0]), 3) # INVALIDPOINT npt.assert_equal(len(pft_streamlines[1]), 3) # ENDPOINT npt.assert_equal(len(pft_streamlines[2]), 1) # OUTSIDEIMAGE # Test with wrong tissueclassifier type tc_bin = BinaryTissueClassifier(simple_wm) npt.assert_raises(ValueError, lambda: ParticleFilteringTracking(dg, tc_bin, seeds, np.eye(4), step_size)) # Test with invalid back/front tracking distances npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, pft_back_tracking_dist=0, pft_front_tracking_dist=0)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, pft_back_tracking_dist=-1)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, pft_back_tracking_dist=0, pft_front_tracking_dist=-2)) # Test with invalid affine shape npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(3), step_size)) # Test with invalid maxlen npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, maxlen=0)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, maxlen=-1)) # Test with invalid particle count npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, particle_count=0)) npt.assert_raises( ValueError, lambda: ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, particle_count=-1)) # Test reproducibility tracking_1 = Streamlines(ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, random_seed=0)).data tracking_2 = Streamlines(ParticleFilteringTracking(dg, tc, seeds, np.eye(4), step_size, random_seed=0)).data npt.assert_equal(tracking_1, tracking_2)
def dwi_dipy_run(dwi_dir, node_size, dir_path, conn_model, parc, atlas_select, network, wm_mask=None): from dipy.reconst.dti import TensorModel, quantize_evecs from dipy.reconst.csdeconv import ConstrainedSphericalDeconvModel, recursive_response from dipy.tracking.local import LocalTracking, ActTissueClassifier from dipy.tracking import utils from dipy.direction import peaks_from_model from dipy.tracking.eudx import EuDX from dipy.data import get_sphere, default_sphere from dipy.core.gradients import gradient_table from dipy.io import read_bvals_bvecs from dipy.tracking.streamline import Streamlines from dipy.direction import ProbabilisticDirectionGetter, ClosestPeakDirectionGetter, BootDirectionGetter from nibabel.streamlines import save as save_trk from nibabel.streamlines import Tractogram ## dwi_dir = '/Users/PSYC-dap3463/Downloads/bedpostx_s002' img_pve_csf = nib.load( '/Users/PSYC-dap3463/Downloads/002_all/tmp/reg_a/t1w_vent_csf_diff_dwi.nii.gz' ) img_pve_wm = nib.load( '/Users/PSYC-dap3463/Downloads/002_all/tmp/reg_a/t1w_wm_in_dwi_bin.nii.gz' ) img_pve_gm = nib.load( '/Users/PSYC-dap3463/Downloads/002_all/tmp/reg_a/t1w_gm_mask_dwi.nii.gz' ) labels_img = nib.load( '/Users/PSYC-dap3463/Downloads/002_all/tmp/reg_a/dwi_aligned_atlas.nii.gz' ) num_total_samples = 10000 tracking_method = 'boot' # Options are 'boot', 'prob', 'peaks', 'closest' procmem = [2, 4] ## if parc is True: node_size = 'parc' dwi_img = "%s%s" % (dwi_dir, '/dwi.nii.gz') nodif_brain_mask_path = "%s%s" % (dwi_dir, '/nodif_brain_mask.nii.gz') bvals = "%s%s" % (dwi_dir, '/bval') bvecs = "%s%s" % (dwi_dir, '/bvec') dwi_img = nib.load(dwi_img) data = dwi_img.get_data() [bvals, bvecs] = read_bvals_bvecs(bvals, bvecs) gtab = gradient_table(bvals, bvecs) gtab.b0_threshold = min(bvals) sphere = get_sphere('symmetric724') # Loads mask and ensures it's a true binary mask mask_img = nib.load(nodif_brain_mask_path) mask = mask_img.get_data() mask = mask > 0 # Fit a basic tensor model first model = TensorModel(gtab) ten = model.fit(data, mask) fa = ten.fa # Tractography if conn_model == 'csd': print('Tracking with csd model...') elif conn_model == 'tensor': print('Tracking with tensor model...') else: raise RuntimeError("%s%s" % (conn_model, ' is not a valid model.')) # Combine seed counts from voxel with seed counts total wm_mask_data = img_pve_wm.get_data() wm_mask_data[0, :, :] = False wm_mask_data[:, 0, :] = False wm_mask_data[:, :, 0] = False seeds = utils.seeds_from_mask(wm_mask_data, density=1, affine=dwi_img.get_affine()) seeds_rnd = utils.random_seeds_from_mask(ten.fa > 0.02, seeds_count=num_total_samples, seed_count_per_voxel=True) seeds_all = np.vstack([seeds, seeds_rnd]) # Load tissue maps and prepare tissue classifier (Anatomically-Constrained Tractography (ACT)) background = np.ones(img_pve_gm.shape) background[(img_pve_gm.get_data() + img_pve_wm.get_data() + img_pve_csf.get_data()) > 0] = 0 include_map = img_pve_gm.get_data() include_map[background > 0] = 1 exclude_map = img_pve_csf.get_data() act_classifier = ActTissueClassifier(include_map, exclude_map) if conn_model == 'tensor': ind = quantize_evecs(ten.evecs, sphere.vertices) streamline_generator = EuDX(a=fa, ind=ind, seeds=seeds_all, odf_vertices=sphere.vertices, a_low=0.05, step_sz=.5) elif conn_model == 'csd': print('Tracking with CSD model...') response = recursive_response( gtab, data, mask=img_pve_wm.get_data().astype('bool'), sh_order=8, peak_thr=0.01, init_fa=0.05, init_trace=0.0021, iter=8, convergence=0.001, parallel=True) csd_model = ConstrainedSphericalDeconvModel(gtab, response) if tracking_method == 'boot': dg = BootDirectionGetter.from_data(data, csd_model, max_angle=30., sphere=default_sphere) elif tracking_method == 'prob': try: print( 'First attempting to build the direction getter directly from the spherical harmonic representation of the FOD...' ) csd_fit = csd_model.fit( data, mask=img_pve_wm.get_data().astype('bool')) dg = ProbabilisticDirectionGetter.from_shcoeff( csd_fit.shm_coeff, max_angle=30., sphere=default_sphere) except: print( 'Sphereical harmonic not available for this model. Using peaks_from_model to represent the ODF of the model on a spherical harmonic basis instead...' ) peaks = peaks_from_model( csd_model, data, default_sphere, .5, 25, mask=img_pve_wm.get_data().astype('bool'), return_sh=True, parallel=True, nbr_processes=procmem[0]) dg = ProbabilisticDirectionGetter.from_shcoeff( peaks.shm_coeff, max_angle=30., sphere=default_sphere) elif tracking_method == 'peaks': dg = peaks_from_model(model=csd_model, data=data, sphere=default_sphere, relative_peak_threshold=.5, min_separation_angle=25, mask=img_pve_wm.get_data().astype('bool'), parallel=True, nbr_processes=procmem[0]) elif tracking_method == 'closest': csd_fit = csd_model.fit(data, mask=img_pve_wm.get_data().astype('bool')) pmf = csd_fit.odf(default_sphere).clip(min=0) dg = ClosestPeakDirectionGetter.from_pmf(pmf, max_angle=30., sphere=default_sphere) streamline_generator = LocalTracking(dg, act_classifier, seeds_all, affine=dwi_img.affine, step_size=0.5) del dg try: del csd_fit except: pass try: del response except: pass try: del csd_model except: pass streamlines = Streamlines(streamline_generator, buffer_size=512) save_trk(Tractogram(streamlines, affine_to_rasmm=dwi_img.affine), 'prob_streamlines.trk') tracks = [sl for sl in streamlines if len(sl) > 1] labels_data = labels_img.get_data().astype('int') labels_affine = labels_img.affine conn_matrix, grouping = utils.connectivity_matrix( tracks, labels_data, affine=labels_affine, return_mapping=True, mapping_as_streamlines=True, symmetric=True) conn_matrix[:3, :] = 0 conn_matrix[:, :3] = 0 return conn_matrix
def prep_tissues(B0_mask, gm_in_dwi, vent_csf_in_dwi, wm_in_dwi, tiss_class, cmc_step_size=0.2): ''' Estimate a tissue classifier for tractography. Parameters ---------- B0_mask : str File path to B0 brain mask. gm_in_dwi : str File path to grey-matter tissue segmentation Nifti1Image. vent_csf_in_dwi : str File path to ventricular CSF tissue segmentation Nifti1Image. wm_in_dwi : str File path to white-matter tissue segmentation Nifti1Image. tiss_class : str Tissue classification method. cmc_step_size : float Step size from CMC tissue classification method. Returns ------- tiss_classifier : obj Tissue classifier object. ''' try: import cPickle as pickle except ImportError: import _pickle as pickle from dipy.tracking.local import ActTissueClassifier, CmcTissueClassifier, BinaryTissueClassifier # Loads mask and ensures it's a true binary mask mask_img = nib.load(B0_mask) # Load tissue maps and prepare tissue classifier gm_mask = nib.load(gm_in_dwi) gm_mask_data = gm_mask.get_fdata() wm_mask = nib.load(wm_in_dwi) wm_mask_data = wm_mask.get_fdata() if tiss_class == 'act': vent_csf_in_dwi = nib.load(vent_csf_in_dwi) vent_csf_in_dwi_data = vent_csf_in_dwi.get_fdata() background = np.ones(mask_img.shape) background[(gm_mask_data + wm_mask_data + vent_csf_in_dwi_data) > 0] = 0 include_map = gm_mask_data include_map[background > 0] = 1 exclude_map = vent_csf_in_dwi_data tiss_classifier = ActTissueClassifier(include_map, exclude_map) elif tiss_class == 'bin': wm_in_dwi_data = nib.load(wm_in_dwi).get_fdata().astype('bool') tiss_classifier = BinaryTissueClassifier(wm_in_dwi_data) elif tiss_class == 'cmc': vent_csf_in_dwi = nib.load(vent_csf_in_dwi) vent_csf_in_dwi_data = vent_csf_in_dwi.get_fdata() voxel_size = np.average(wm_mask.get_header()['pixdim'][1:4]) tiss_classifier = CmcTissueClassifier.from_pve( wm_mask_data, gm_mask_data, vent_csf_in_dwi_data, step_size=cmc_step_size, average_voxel_size=voxel_size) else: B0_mask_data = nib.load(B0_mask).get_fdata().astype('bool') tiss_classifier = BinaryTissueClassifier(B0_mask_data) return tiss_classifier