def test_deform_streamlines(): # Create Random deformation field deformation_field = np.random.randn(200, 200, 200, 3) # Specify stream2grid and grid2world stream2grid = np.array([[np.random.randn(1)[0], 0, 0, 0], [0, np.random.randn(1)[0], 0, 0], [0, 0, np.random.randn(1)[0], 0], [0, 0, 0, 1]]) grid2world = np.array([[np.random.randn(1)[0], 0, 0, 0], [0, np.random.randn(1)[0], 0, 0], [0, 0, np.random.randn(1)[0], 0], [0, 0, 0, 1]]) stream2world = np.dot(stream2grid, grid2world) # Deform streamlines (let two grid spaces be the same for simplicity) new_streamlines = deform_streamlines(streamlines, deformation_field, stream2grid, grid2world, stream2grid, grid2world) # Interpolate displacements onto original streamlines streamlines_in_grid = transform_streamlines(streamlines, stream2grid) disps = values_from_volume(deformation_field, streamlines_in_grid) # Put new_streamlines into world space new_streamlines_world = transform_streamlines(new_streamlines, stream2world) # Subtract disps from new_streamlines in world space orig_streamlines_world = list(np.subtract(new_streamlines_world, disps)) # Put orig_streamlines_world into voxmm orig_streamlines = transform_streamlines(orig_streamlines_world, np.linalg.inv(stream2world)) # All close because of floating pt inprecision for o, s in zip(orig_streamlines, streamlines): assert_allclose(s, o, rtol=1e-10, atol=0)
""" origin_affine[2][3] = origin_affine[2][3] / vox_size """ But when scaling the z-offset, we are also implicitly scaling the y-offset as well (by 1/2).Thus we need to correct for this by only scaling the y by the square of the voxel size (1/4, and not 1/2): """ origin_affine[1][3] = origin_affine[1][3] / vox_size**2 # Apply the deformation and correct for the extents mni_streamlines = deform_streamlines(sft.streamlines, deform_field=mapping.get_forward_field(), stream_to_current_grid=target_isocenter, current_grid_to_world=origin_affine, stream_to_ref_grid=target_isocenter, ref_grid_to_world=np.eye(4)) """ We display the original streamlines and the registered streamlines: """ from dipy.viz import has_fury def show_template_bundles(bundles, show=True, fname=None): renderer = window.Renderer() template_actor = actor.slicer(static) renderer.add(template_actor)
def register_save(inputpathdir, target_path, subject, outputpath, figspath, params, registration_types, applydirs, verbose): anat_path = get_anat(inputpathdir, subject) #myanat = load_nifti(anat_path) myanat = nib.load(anat_path) anat_data = np.squeeze(myanat.get_data()[..., 0]) anat_affine = myanat.affine anat_hdr = myanat.header vox_size = myanat.header.get_zooms()[0] #mynifti = load_nifti("/Volumes/Data/Badea/Lab/19abb14/N57437_nii4D.nii") #anat_data = np.squeeze(myanat[0])[..., 0] #anat_affine = myanat[1] #hdr = myanat.header mytarget = nib.load(target_path) target_data = np.squeeze(mytarget.get_data()[..., 0]) target_affine = mytarget.affine identity = np.eye(4) affine_map = AffineMap(identity, target_data.shape, target_affine, anat_data.shape, anat_affine) resampled = affine_map.transform(anat_data) """ regtools.overlay_slices(target_data, resampled, None, 0, "target_data", "anat_data", figspath + "resampled_0.png") regtools.overlay_slices(target_data, resampled, None, 1, "target_data", "anat_data", figspath + "resampled_1.png") regtools.overlay_slices(target_data, resampled, None, 2, "target_data", "anat_data", figspath + "resampled_2.png") """ c_of_mass = transform_centers_of_mass(target_data, target_affine, anat_data, anat_affine) apply_niftis = [] apply_trks = [] if inputpathdir in applydirs: applyfiles = [anat_path] else: applyfiles = [] for applydir in applydirs: apply_niftis.extend(get_niftis(applydir, subject)) apply_trks.extend(get_trks(applydir, subject)) if "center_mass" in registration_types: if apply_trks: metric = CCMetric(3) level_iters = [10, 10, 5] sdr = SymmetricDiffeomorphicRegistration(metric, level_iters) mapping = sdr.optimize(target_data, anat_data, target_affine, anat_affine, c_of_mass.affine) for apply_nifti in apply_niftis: fname = os.path.basename(apply_nifti).split(".")[0] fpath = outputpath + fname + "_centermass.nii" applynii = nib.load(apply_nifti) apply_data = applynii.get_data() apply_affine = applynii.affine apply_hdr = myanat.header if len(np.shape(apply_data)) == 4: transformed_all = c_of_mass.transform(apply_data, apply4D=True) transformed = transformed_all[:, :, :, 0] else: transformed_all = c_of_mass.transform(apply_data) transformed = transformed_all save_nifti(fpath, transformed_all, apply_affine, hdr=apply_hdr) if figspath is not None: regtools.overlay_slices(target_data, transformed, None, 0, "target_data", "Transformed", figspath + fname + "_centermass_1.png") regtools.overlay_slices(target_data, transformed, None, 1, "target_data", "Transformed", figspath + fname + "_centermass_2.png") regtools.overlay_slices(target_data, transformed, None, 2, "target_data", "Transformed", figspath + fname + "_centermass_3.png") if verbose: print("Saved the file at " + fpath) #mapping = sdr.optimize(target_data, anat_data, target_affine, anat_affine, # c_of_mass.affine) #warped_moving = mapping.transform(anat_data) for apply_trk in apply_trks: fname = os.path.basename(apply_trk).split(".")[0] fpath = outputpath + fname + "_centermass.trk" sft = load_tractogram(apply_trk, 'same') target_isocenter = np.diag( np.array([-vox_size, vox_size, vox_size, 1])) origin_affine = affine_map.affine.copy() origin_affine[0][3] = -origin_affine[0][3] origin_affine[1][3] = -origin_affine[1][3] origin_affine[2][3] = origin_affine[2][3] / vox_size origin_affine[1][3] = origin_affine[1][3] / vox_size**2 # Apply the deformation and correct for the extents mni_streamlines = deform_streamlines( sft.streamlines, deform_field=mapping.get_forward_field(), stream_to_current_grid=target_isocenter, current_grid_to_world=origin_affine, stream_to_ref_grid=target_isocenter, ref_grid_to_world=np.eye(4)) if has_fury: show_template_bundles(mni_streamlines, anat_data, show=False, fname=figspath + fname + '_streamlines_centermass.png') sft = StatefulTractogram(mni_streamlines, myanat, Space.RASMM) save_tractogram(sft, fpath, bbox_valid_check=False) if verbose: print("Saved the file at " + fpath) metric = MutualInformationMetric(params.nbins, params.sampling_prop) if "AffineRegistration" in registration_types: affreg = AffineRegistration(metric=metric, level_iters=params.level_iters, sigmas=params.sigmas, factors=params.factors) transform = TranslationTransform3D() params0 = None starting_affine = c_of_mass.affine translation = affreg.optimize(target_data, anat_data, transform, params0, target_affine, anat_affine, starting_affine=starting_affine) if apply_trks: metric = CCMetric(3) level_iters = [10, 10, 5] sdr = SymmetricDiffeomorphicRegistration(metric, level_iters) mapping = sdr.optimize(target_data, anat_data, target_affine, anat_affine, translation.affine) for apply_nifti in apply_niftis: fname = os.path.basename(apply_nifti).split(".")[0] fpath = outputpath + fname + "_affinereg.nii" applynii = nib.load(apply_nifti) apply_data = applynii.get_data() apply_affine = applynii.affine apply_hdr = myanat.header if len(np.shape(apply_data)) == 4: transformed_all = translation.transform(apply_data, apply4D=True) transformed = transformed_all[:, :, :, 0] else: transformed_all = translation.transform(apply_data) transformed = transformed_all save_nifti(fpath, transformed_all, anat_affine, hdr=anat_hdr) if figspath is not None: regtools.overlay_slices(target_data, transformed, None, 0, "target_data", "Transformed", figspath + fname + "_affinereg_1.png") regtools.overlay_slices(target_data, transformed, None, 1, "target_data", "Transformed", figspath + fname + "_affinereg_2.png") regtools.overlay_slices(target_data, transformed, None, 2, "target_data", "Transformed", figspath + fname + "_affinereg_3.png") if verbose: print("Saved the file at " + fpath) for apply_trk in apply_trks: fname = os.path.basename(apply_trk).split(".")[0] fpath = outputpath + fname + "_affinereg.trk" sft = load_tractogram(apply_trk, 'same') target_isocenter = np.diag( np.array([-vox_size, vox_size, vox_size, 1])) origin_affine = affine_map.affine.copy() origin_affine[0][3] = -origin_affine[0][3] origin_affine[1][3] = -origin_affine[1][3] origin_affine[2][3] = origin_affine[2][3] / vox_size origin_affine[1][3] = origin_affine[1][3] / vox_size**2 # Apply the deformation and correct for the extents mni_streamlines = deform_streamlines( sft.streamlines, deform_field=mapping.get_forward_field(), stream_to_current_grid=target_isocenter, current_grid_to_world=origin_affine, stream_to_ref_grid=target_isocenter, ref_grid_to_world=np.eye(4)) if has_fury: show_template_bundles(mni_streamlines, anat_data, show=False, fname=figspath + fname + '_streamlines_affinereg.png') sft = StatefulTractogram(mni_streamlines, myanat, Space.RASMM) save_tractogram(sft, fpath, bbox_valid_check=False) if verbose: print("Saved the file at " + fpath) if "RigidTransform3D" in registration_types: transform = RigidTransform3D() params0 = None if 'translation' not in locals(): affreg = AffineRegistration(metric=metric, level_iters=params.level_iters, sigmas=params.sigmas, factors=params.factors) translation = affreg.optimize(target_data, anat_data, transform, params0, target_affine, anat_affine, starting_affine=c_of_mass.affine) starting_affine = translation.affine rigid = affreg.optimize(target_data, anat_data, transform, params0, target_affine, anat_affine, starting_affine=starting_affine) transformed = rigid.transform(anat_data) if apply_trks: metric = CCMetric(3) level_iters = [10, 10, 5] sdr = SymmetricDiffeomorphicRegistration(metric, level_iters) mapping = sdr.optimize(target_data, anat_data, target_affine, anat_affine, rigid.affine) for apply_nifti in apply_niftis: fname = os.path.basename(apply_nifti).split(".")[0] fpath = outputpath + fname + "_rigidtransf3d.nii" applynii = nib.load(apply_nifti) apply_data = applynii.get_data() apply_affine = applynii.affine apply_hdr = myanat.header if len(np.shape(apply_data)) == 4: transformed_all = rigid.transform(apply_data, apply4D=True) transformed = transformed_all[:, :, :, 0] else: transformed_all = rigid.transform(apply_data) transformed = transformed_all save_nifti(fpath, transformed_all, anat_affine, hdr=anat_hdr) if figspath is not None: regtools.overlay_slices( target_data, transformed, None, 0, "target_data", "Transformed", figspath + fname + "_rigidtransf3d_1.png") regtools.overlay_slices( target_data, transformed, None, 1, "target_data", "Transformed", figspath + fname + "_rigidtransf3d_2.png") regtools.overlay_slices( target_data, transformed, None, 2, "target_data", "Transformed", figspath + fname + "_rigidtransf3d_3.png") if verbose: print("Saved the file at " + fpath) for apply_trk in apply_trks: fname = os.path.basename(apply_trk).split(".")[0] fpath = outputpath + fname + "_rigidtransf3d.trk" sft = load_tractogram(apply_trk, 'same') target_isocenter = np.diag( np.array([-vox_size, vox_size, vox_size, 1])) origin_affine = affine_map.affine.copy() origin_affine[0][3] = -origin_affine[0][3] origin_affine[1][3] = -origin_affine[1][3] origin_affine[2][3] = origin_affine[2][3] / vox_size origin_affine[1][3] = origin_affine[1][3] / vox_size**2 # Apply the deformation and correct for the extents mni_streamlines = deform_streamlines( sft.streamlines, deform_field=mapping.get_forward_field(), stream_to_current_grid=target_isocenter, current_grid_to_world=origin_affine, stream_to_ref_grid=target_isocenter, ref_grid_to_world=np.eye(4)) if has_fury: show_template_bundles(mni_streamlines, anat_data, show=False, fname=figspath + fname + '_rigidtransf3d.png') sft = StatefulTractogram(mni_streamlines, myanat, Space.RASMM) save_tractogram(sft, fpath, bbox_valid_check=False) if verbose: print("Saved the file at " + fpath) if "AffineTransform3D" in registration_types: transform = AffineTransform3D() params0 = None starting_affine = rigid.affine affine = affreg.optimize(target_data, anat_data, transform, params0, target_affine, anat_affine, starting_affine=starting_affine) transformed = affine.transform(anat_data) if apply_trks: metric = CCMetric(3) level_iters = [10, 10, 5] sdr = SymmetricDiffeomorphicRegistration(metric, level_iters) mapping = sdr.optimize(target_data, anat_data, target_affine, anat_affine, affine.affine) for apply_nifti in apply_niftis: fname = os.path.basename(apply_nifti).split(".")[0] fpath = outputpath + fname + "_affinetransf3d.nii" applynii = nib.load(apply_nifti) apply_data = applynii.get_data() apply_affine = applynii.affine apply_hdr = myanat.header if len(np.shape(apply_data)) == 4: transformed_all = affine.transform(apply_data, apply4D=True) transformed = transformed_all[:, :, :, 0] else: transformed_all = affine.transform(apply_data) transformed = transformed_all save_nifti(fpath, transformed_all, anat_affine, hdr=anat_hdr) if figspath is not None: regtools.overlay_slices( target_data, transformed, None, 0, "target_data", "Transformed", figspath + fname + "_affinetransf3d_1.png") regtools.overlay_slices( target_data, transformed, None, 1, "target_data", "Transformed", figspath + fname + "_affinetransf3d_2.png") regtools.overlay_slices( target_data, transformed, None, 2, "target_data", "Transformed", figspath + fname + "_affinetransf3d_3.png") if verbose: print("Saved the file at " + fpath) for apply_trk in apply_trks: fname = os.path.basename(apply_trk).split(".")[0] fpath = outputpath + fname + "_affinetransf3d.trk" sft = load_tractogram(apply_trk, 'same') target_isocenter = np.diag( np.array([-vox_size, vox_size, vox_size, 1])) origin_affine = affine_map.affine.copy() origin_affine[0][3] = -origin_affine[0][3] origin_affine[1][3] = -origin_affine[1][3] origin_affine[2][3] = origin_affine[2][3] / vox_size origin_affine[1][3] = origin_affine[1][3] / vox_size**2 # Apply the deformation and correct for the extents mni_streamlines = deform_streamlines( sft.streamlines, deform_field=mapping.get_forward_field(), stream_to_current_grid=target_isocenter, current_grid_to_world=origin_affine, stream_to_ref_grid=target_isocenter, ref_grid_to_world=np.eye(4)) if has_fury: show_template_bundles(mni_streamlines, anat_data, show=False, fname=figspath + fname + '_streamlines_affinetransf3d.png') sft = StatefulTractogram(mni_streamlines, myanat, Space.RASMM) save_tractogram(sft, fpath, bbox_valid_check=False) if verbose: print("Saved the file at " + fpath)
affine_mat_path = os.path.join(path_transforms, f'{subj}_affine.txt') affine_mat_s = read_affine_txt(affine_mat_path) affine_mat = np.eye(4) affine_mat[:3, :3] = affine_mat_s #streamlines_postrigid, header_postrigid = unload_trk(trk_preprocess_postrigid) streamlines_postrigidaffine = transform_streamlines(streamlines_postrigid, np.linalg.inv(affine_mat)) if (not os.path.exists(trk_preprocess_postrigid_affine) or overwrite) and save_temp_files: save_trk_header(filepath=trk_preprocess_postrigid_affine, streamlines=streamlines_postrigidaffine, header=header, affine=np.eye(4), verbose=verbose) #streamlines_postrigidaffine, header_postrigidaffine = unload_trk(trk_preprocess_postrigid_affine) warp, affine, vox_size, header_warp, ref_info = extract_nii_info(runno_to_MDT) warp = warp[:,:,:,0,:] vox_size = tuple(np.linalg.eigvals(affine[:3,:3])) vox_size = vox_size[0] target_isocenter = np.diag(np.array([-vox_size, vox_size, vox_size, 1])) streamlines_post_warp = deform_streamlines( streamlines_postrigidaffine, deform_field=warp, stream_to_current_grid=target_isocenter, current_grid_to_world=np.eye(4), stream_to_ref_grid=target_isocenter, ref_grid_to_world=np.eye(4)) if (not os.path.exists(trk_MDT_space) or overwrite): save_trk_header(filepath=trk_MDT_space, streamlines=streamlines_post_warp, header=header, affine=np.eye(4), verbose=verbose) else: print(f'{trk_MDT_space} already exists')
def direct_streamline_norm(streams, fa_path, outdir: Path): """Applys the Symmetric Diffeomorphic Registration (SyN) Algorithm onto the streamlines to the atlas space defined by .../atlases/reference_brains/FSL_HCP1065_FA_2mm.nii.gz Parameters ---------- streams : str Path to streamlines.trk file to be transformed fa_path : str Path to subject's FA tensor image outdir : Path Output directory location. Returns ------- ArraySequence Transformed streamlines str Path to tractogram streamline file: streamlines_dsn.trk """ atlas_dir = m2g_bids.get_atlas_dir() template_path = atlas_dir + "/atlases/reference_brains/FSL_HCP1065_FA_2mm.nii.gz" # Run SyN and normalize streamlines fa_img = nib.load(fa_path) vox_size = fa_img.get_header().get_zooms()[0] template_img = nib.load(template_path) # SyN FA->Template mapping, affine_map = reg_utils.wm_syn(template_path, fa_path, str(outdir / "tmp")) streamlines = load_trk(streams, reference="same") # Warp streamlines adjusted_affine = affine_map.affine.copy() adjusted_affine[1][3] = -adjusted_affine[1][3] / vox_size**2 mni_streamlines = deform_streamlines( streamlines.streamlines, deform_field=mapping.get_forward_field()[-1:], stream_to_current_grid=template_img.affine, current_grid_to_world=adjusted_affine, stream_to_ref_grid=template_img.affine, ref_grid_to_world=np.eye(4), ) # Save streamlines hdr = fa_img.header trk_affine = np.eye(4) trk_hdr = nib.streamlines.trk.TrkFile.create_empty_header() trk_hdr["hdr_size"] = 1000 trk_hdr["dimensions"] = hdr["dim"][1:4].astype("float32") trk_hdr["voxel_sizes"] = hdr["pixdim"][1:4] trk_hdr["voxel_to_rasmm"] = trk_affine trk_hdr["voxel_order"] = "RAS" trk_hdr["pad2"] = "RAS" trk_hdr["image_orientation_patient"] = np.array( [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]).astype("float32") trk_hdr["endianness"] = "<" trk_hdr["_offset_data"] = 1000 trk_hdr["nb_streamlines"] = len(mni_streamlines) tractogram = nib.streamlines.Tractogram(mni_streamlines, affine_to_rasmm=trk_affine) trkfile = nib.streamlines.trk.TrkFile(tractogram, header=trk_hdr) streams_mni = streams.split(".trk")[0] + "_dsn.trk" nib.streamlines.save(trkfile, streams_mni) return mni_streamlines, streams_mni