def test_fvtk_functions(): # Create a renderer r = fvtk.ren() # Create 2 lines with 2 different colors lines = [np.random.rand(10, 3), np.random.rand(20, 3)] colors = np.random.rand(2, 3) c = fvtk.line(lines, colors) fvtk.add(r, c) # create streamtubes of the same lines and shift them a bit c2 = fvtk.streamtube(lines, colors) c2.SetPosition(2, 0, 0) fvtk.add(r, c2) # Create a volume and return a volumetric actor using volumetric rendering vol = 100 * np.random.rand(100, 100, 100) vol = vol.astype('uint8') r = fvtk.ren() v = fvtk.volume(vol) fvtk.add(r, v) # Remove all objects fvtk.rm_all(r) # Put some text l = fvtk.label(r, text='Yes Men') fvtk.add(r, l) # Slice the volume fvtk.add(r, fvtk.slicer(vol, plane_i=[50])) # Change the position of the active camera fvtk.camera(r, pos=(0.6, 0, 0), verbose=False)
def show_odfs_with_map(odf, sphere, map): ren = fvtk.ren() sfu = fvtk.sphere_funcs(odf[:, None, :], sphere, norm=True) sfu.RotateX(-90) sfu.SetPosition(5, 5, 1) sfu.SetScale(0.435) slice = fvtk.slicer(map, plane_i=None, plane_j=[0]) slice.RotateX(-90) fvtk.add(ren, slice) fvtk.add(ren, sfu) fvtk.show(ren)
def test_fvtk_functions(): # This tests will fail if any of the given actors changed inputs or do # not exist # Create a renderer r = fvtk.ren() # Create 2 lines with 2 different colors lines = [np.random.rand(10, 3), np.random.rand(20, 3)] colors = np.random.rand(2, 3) c = fvtk.line(lines, colors) fvtk.add(r, c) # create streamtubes of the same lines and shift them a bit c2 = fvtk.streamtube(lines, colors) c2.SetPosition(2, 0, 0) fvtk.add(r, c2) # Create a volume and return a volumetric actor using volumetric rendering vol = 100 * np.random.rand(100, 100, 100) vol = vol.astype('uint8') r = fvtk.ren() v = fvtk.volume(vol) fvtk.add(r, v) # Remove all objects fvtk.rm_all(r) # Put some text l = fvtk.label(r, text='Yes Men') fvtk.add(r, l) # Slice the volume slicer = fvtk.slicer(vol) slicer.display(50, None, None) fvtk.add(r, slicer) # Change the position of the active camera fvtk.camera(r, pos=(0.6, 0, 0), verbose=False) fvtk.clear(r) # Peak directions p = fvtk.peaks(np.random.rand(3, 3, 3, 5, 3)) fvtk.add(r, p) p2 = fvtk.peaks(np.random.rand(3, 3, 3, 5, 3), np.random.rand(3, 3, 3, 5), colors=(0, 1, 0)) fvtk.add(r, p2)
def test_fvtk_functions(): # This tests will fail if any of the given actors changed inputs or do # not exist # Create a renderer r = fvtk.ren() # Create 2 lines with 2 different colors lines = [np.random.rand(10, 3), np.random.rand(20, 3)] colors = np.random.rand(2, 3) c = fvtk.line(lines, colors) fvtk.add(r, c) # create streamtubes of the same lines and shift them a bit c2 = fvtk.streamtube(lines, colors) c2.SetPosition(2, 0, 0) fvtk.add(r, c2) # Create a volume and return a volumetric actor using volumetric rendering vol = 100 * np.random.rand(100, 100, 100) vol = vol.astype('uint8') r = fvtk.ren() v = fvtk.volume(vol) fvtk.add(r, v) # Remove all objects fvtk.rm_all(r) # Put some text l = fvtk.label(r, text='Yes Men') fvtk.add(r, l) # Slice the volume slicer = fvtk.slicer(vol) slicer.display(50, None, None) fvtk.add(r, slicer) # Change the position of the active camera fvtk.camera(r, pos=(0.6, 0, 0), verbose=False) fvtk.clear(r) # Peak directions p = fvtk.peaks(np.random.rand(3, 3, 3, 5, 3)) fvtk.add(r, p) p2 = fvtk.peaks(np.random.rand(3, 3, 3, 5, 3), np.random.rand(3, 3, 3, 5), colors=(0, 1, 0)) fvtk.add(r, p2)
def show_odfs_with_map2(odf, sphere, map, w, fpng): ren = fvtk.ren() sfu = fvtk.sphere_funcs(odf, sphere, norm=True) #sfu.RotateX(-90) sfu.SetPosition(w, w, 1) sfu.SetScale(0.435) sli = fvtk.slicer(map, plane_i=None, plane_k=[0], outline=False) #sli.RotateX(-90) fvtk.add(ren, sli) fvtk.add(ren, sfu) #fvtk.add(ren, fvtk.axes((20, 20, 20))) #fvtk.show(ren) fvtk.record(ren, n_frames=1, out_path=fpng, magnification=2, size=(900, 900))
def createVtkPng(source, anatomical, roi): import vtk from dipy.viz.colormap import line_colors from dipy.viz import fvtk target = source.replace(".trk",".png") roiImage= nibabel.load(roi) anatomicalImage = nibabel.load(anatomical) sourceImage = [s[0] for s in nibabel.trackvis.read(source, points_space='voxel')[0]] try: sourceActor = fvtk.streamtube(sourceImage, line_colors(sourceImage)) roiActor = fvtk.contour(roiImage.get_data(), levels=[1], colors=[(1., 1., 0.)], opacities=[1.]) anatomicalActor = fvtk.slicer(anatomicalImage.get_data(), voxsz=(1.0, 1.0, 1.0), plane_i=None, plane_j=None, plane_k=[65], outline=False) except ValueError: return False sourceActor.RotateX(-70) sourceActor.RotateY(2.5) sourceActor.RotateZ(185) roiActor.RotateX(-70) roiActor.RotateY(2.5) roiActor.RotateZ(185) anatomicalActor.RotateX(-70) anatomicalActor.RotateY(2.5) anatomicalActor.RotateZ(185) ren = fvtk.ren() fvtk.add(ren, sourceActor) fvtk.add(ren, roiActor) fvtk.add(ren, anatomicalActor) fvtk.record(ren, out_path=target, size=(1200, 1200), n_frames=1, verbose=True, cam_pos=(90.03, 118.33, 700.59)) return target
def record_slice(fname, data, k, show=False): ren = fvtk.ren() fvtk.add(ren, fvtk.slicer(data, plane_k=[k])) if show: fvtk.show(ren) fvtk.record(ren, out_path=fname, size=(600, 600))
above and all the streamlines that pass though that ROI. The ROI is the yellow region near the center of the axial image. """ from dipy.viz import fvtk from dipy.viz.colormap import line_colors # Make display objects color = line_colors(cc_streamlines) cc_streamlines_actor = fvtk.line(cc_streamlines, line_colors(cc_streamlines)) cc_ROI_actor = fvtk.contour(cc_slice, levels=[1], colors=[(1., 1., 0.)], opacities=[1.]) vol_actor = fvtk.slicer(t1_data) vol_actor.display(40, None, None) vol_actor2 = vol_actor.copy() vol_actor2.display(None, None, 35) # Add display objects to canvas r = fvtk.ren() fvtk.add(r, vol_actor) fvtk.add(r, vol_actor2) fvtk.add(r, cc_streamlines_actor) fvtk.add(r, cc_ROI_actor) # Save figures fvtk.record(r, n_frames=1,
colored by LFBC, and the fibers after the cleaning procedure via RFBC thresholding. """ # Visualize the results from dipy.viz import fvtk, actor # Create renderer ren = fvtk.ren() # Original lines colored by LFBC lineactor = actor.line(fbc_sl_orig, clrs_orig, linewidth=0.2) fvtk.add(ren, lineactor) # Horizontal (axial) slice of T1 data vol_actor1 = fvtk.slicer(t1_data, affine=affine) vol_actor1.display(None, None, 20) fvtk.add(ren, vol_actor1) # Vertical (sagittal) slice of T1 data vol_actor2 = fvtk.slicer(t1_data, affine=affine) vol_actor2.display(35, None, None) fvtk.add(ren, vol_actor2) # Show original fibers fvtk.camera(ren, pos=(-264, 285, 155), focal=(0, -14, 9), viewup=(0, 0, 1), verbose=False) fvtk.record(ren, n_frames=1, out_path='OR_before.png', size=(900, 900)) # Show thresholded fibers fvtk.rm(ren, lineactor)
colored by LFBC, and the fibers after the cleaning procedure via RFBC thresholding. """ # Visualize the results from dipy.viz import fvtk, actor # Create renderer ren = fvtk.ren() # Original lines colored by LFBC lineactor = actor.line(fbc_sl_orig, clrs_orig, linewidth=0.2) fvtk.add(ren, lineactor) # Horizontal (axial) slice of T1 data vol_actor1 = fvtk.slicer(t1_data, affine=affine) vol_actor1.display(None, None, 20) fvtk.add(ren, vol_actor1) # Vertical (sagittal) slice of T1 data vol_actor2 = fvtk.slicer(t1_data, affine=affine) vol_actor2.display(35, None, None) fvtk.add(ren, vol_actor2) # Show original fibers fvtk.camera(ren, pos=(-264, 285, 155), focal=(0, -14, 9), viewup=(0, 0, 1), verbose=False) fvtk.record(ren, n_frames=1, out_path='OR_before.png', size=(900, 900)) # Show thresholded fibers fvtk.rm(ren, lineactor)
""" We can use some of dipy's visualization tools to display the ROI we targeted above and all the streamlines that pass though that ROI. The ROI is the yellow region near the center of the axial image. """ from dipy.viz import fvtk from dipy.viz.colormap import line_colors # Make display objects color = line_colors(cc_streamlines) cc_streamlines_actor = fvtk.line(cc_streamlines, line_colors(cc_streamlines)) cc_ROI_actor = fvtk.contour(cc_slice, levels=[1], colors=[(1., 1., 0.)], opacities=[1.]) vol_actor = fvtk.slicer(t1_data) vol_actor.display(40, None, None) vol_actor2 = vol_actor.copy() vol_actor2.display(None, None, 35) # Add display objects to canvas r = fvtk.ren() fvtk.add(r, vol_actor) fvtk.add(r, vol_actor2) fvtk.add(r, cc_streamlines_actor) fvtk.add(r, cc_ROI_actor) # Save figures fvtk.record(r, n_frames=1, out_path='corpuscallosum_axial.png', size=(800, 800))
""" from dipy.viz import fvtk from dipy.viz.colormap import line_colors # Make display objects color = line_colors(cc_streamlines) cc_streamlines_actor = fvtk.line(cc_streamlines, line_colors(cc_streamlines)) cc_ROI_actor = fvtk.contour(cc_slice, levels=[1], colors=[(1., 1., 0.)], opacities=[1.]) vol_actor = fvtk.slicer(t1_data, voxsz=(1.0, 1.0, 1.0), plane_i=[40], plane_j=None, plane_k=[35], outline=False) # Add display objects to canvas r = fvtk.ren() fvtk.add(r, vol_actor) fvtk.add(r, cc_streamlines_actor) fvtk.add(r, cc_ROI_actor) # Save figures fvtk.record(r, n_frames=1, out_path='corpuscallosum_axial.png', size=(800, 800)) fvtk.camera(r, [-1, 0, 0], [0, 0, 0], viewup=[0, 0, 1])
""" Let's visualize the initial candidate group of streamlines in 3D, relative to the anatomical structure of this brain: """ from dipy.viz.colormap import line_colors from dipy.viz import fvtk candidate_streamlines_actor = fvtk.streamtube(candidate_sl, line_colors(candidate_sl)) cc_ROI_actor = fvtk.contour(cc_slice, levels=[1], colors=[(1., 1., 0.)], opacities=[1.]) vol_actor = fvtk.slicer(t1_data, voxsz=(1.0, 1.0, 1.0), plane_i=[40], plane_j=None, plane_k=[35], outline=False) # Add display objects to canvas ren = fvtk.ren() fvtk.add(ren, candidate_streamlines_actor) fvtk.add(ren, cc_ROI_actor) fvtk.add(ren, vol_actor) fvtk.record(ren, n_frames=1, out_path='life_candidates.png', size=(800, 800)) """ .. figure:: life_candidates.png :align: center **Candidate connectome before life optimization**
fodf_spheres.SetPosition(15, 15, 1) fodf_spheres.SetScale(0.78) fvtk.add(ren, fodf_spheres) """ Additionally, we can visualize the ODFs together with a GFA slice """ from dipy.reconst.odf import gfa GFA = gfa(csd_odf) fvtk.add(ren, fvtk.slicer(GFA, plane_k=[0])) print('Saving illustration as csd_odfs.png') fvtk.record(ren, out_path='csd_odfs.png', size=(600, 600)) """ .. figure:: csd_odfs.png :align: center **CSD ODFs**. .. [Tournier2007] J-D. Tournier, F. Calamante and A. Connelly, "Robust determination of the fibre orientation distribution in diffusion MRI: Non-negativity constrained super-resolved spherical deconvolution", Neuroimage, vol. 35, no. 4, pp. 1459-1472, 2007. .. include:: ../links_names.inc """
def life(dwifile, bvecsfile, bvalsfile, tractogramfile, outdir, display_tracks=False, verbose=0): """ Linear fascicle evaluation (LiFE) Evaluating the results of tractography algorithms is one of the biggest challenges for diffusion MRI. One proposal for evaluation of tractography results is to use a forward model that predicts the signal from each of a set of streamlines, and then fit a linear model to these simultaneous prediction. Parameters ---------- dwifile: str the path to the diffusion dataset. bvecsfile: str the path to the diffusion b-vectors. bvalsfile: str the path to the diffusion b-values. tractogramfile: str the path to the tractogram. outdir: str the destination folder. display_tracks: bool, default False if True render the tracks. verbose: int, default 0 the verbosity level. Returns ------- life_weights_file: str a file containing the fiber track weights. life_weights_snap: str a snap with the distrubution of weights. spatial_error_file: str the model root mean square error. tracks_snap: str a snap with the tracks. """ # Load diffusion data and tractogram bvecs = numpy.loadtxt(bvecsfile) bvals = numpy.loadtxt(bvalsfile) gtab = gradient_table(bvals, bvecs) im = nibabel.load(dwifile) data = im.get_data() trk = nibabel.streamlines.load(tractogramfile) if verbose > 0: print("[info] Diffusion shape: {0}".format(data.shape)) print("[info] Number of tracks: {0}".format(len(trk.streamlines))) # Express the tractogram in voxel coordiantes inv_affine = numpy.linalg.inv(trk.affine) trk = [ numpy.dot( numpy.concatenate( ( streamline, numpy.ones( (len(streamline), 1) ) ), axis=1 ), inv_affine) for streamline in trk.streamlines] trk = [track[..., :3] for track in trk] # Create a viewer tracks_snap = None if display_tracks: nb_tracks = len(trk) if nb_tracks < 5000: downsampling = 1 else: downsampling = nb_tracks // 5000 tracks_snap = os.path.join(outdir, "tracks.png") streamlines_actor = fvtk.line(trk[::downsampling], line_colors(trk[::downsampling])) vol_actor = fvtk.slicer(data[..., 0]) vol_actor.display(data.shape[0] // 2, None, None) ren = fvtk.ren() fvtk.add(ren, streamlines_actor) fvtk.add(ren, vol_actor) fvtk.record(ren, n_frames=1, out_path=tracks_snap, size=(800, 800)) if verbose > 1: fvtk.show(ren) # Fit the Life model and save the associated weights fiber_model = dpilife.FiberModel(gtab) fiber_fit = fiber_model.fit(data, trk, affine=numpy.eye(4)) life_weights = fiber_fit.beta life_weights_file = os.path.join(outdir, "life_weights.txt") numpy.savetxt(life_weights_file, life_weights) life_weights_snap = os.path.join(outdir, "life_weights.png") fig, ax = plt.subplots(1) ax.hist(life_weights, bins=100, histtype="step") ax.set_xlabel("Fiber weights") ax.set_ylabel("# Fibers") fig.savefig(life_weights_snap) # Invert the model and predict back either the data that was used to fit # the model: compute the prediction error of the diffusion-weighted data # and calculate the root of the mean squared error. model_predict = fiber_fit.predict() model_error = model_predict - fiber_fit.data model_rmse = numpy.sqrt(numpy.mean(model_error[:, 10:] ** 2, -1)) data_rmse = numpy.ones(data.shape[:3]) * numpy.nan data_rmse[fiber_fit.vox_coords[:, 0], fiber_fit.vox_coords[:, 1], fiber_fit.vox_coords[:, 2]] = model_rmse model_error_file = os.path.join(outdir, "model_rmse.nii.gz") error_im = nibabel.Nifti1Image(data_rmse, im.affine) nibabel.save(error_im, model_error_file) # As a baseline against which we can compare, we assume that the weight # for each streamline is equal to zero. This produces the naive prediction # of the mean of the signal in each voxel. life_weights_baseline = numpy.zeros(life_weights.shape[0]) pred_weighted = numpy.reshape( opt.spdot(fiber_fit.life_matrix, life_weights_baseline), (fiber_fit.vox_coords.shape[0], numpy.sum(~gtab.b0s_mask))) mean_pred = numpy.empty( (fiber_fit.vox_coords.shape[0], gtab.bvals.shape[0])) S0 = fiber_fit.b0_signal # Since the fitting is done in the demeaned S/S0 domain, we need to add # back the mean and then multiply by S0 in every voxels. mean_pred[..., gtab.b0s_mask] = S0[:, None] mean_pred[..., ~gtab.b0s_mask] = ( (pred_weighted + fiber_fit.mean_signal[:, None]) * S0[:, None]) mean_error = mean_pred - fiber_fit.data mean_rmse = numpy.sqrt(numpy.mean(mean_error ** 2, -1)) data_rmse = numpy.ones(data.shape[:3]) * numpy.nan data_rmse[fiber_fit.vox_coords[:, 0], fiber_fit.vox_coords[:, 1], fiber_fit.vox_coords[:, 2]] = mean_rmse mean_error_file = os.path.join(outdir, "mean_rmse.nii.gz") error_im = nibabel.Nifti1Image(data_rmse, im.affine) nibabel.save(error_im, mean_error_file) # Compute the improvment array data_rmse = numpy.ones(data.shape[:3]) * numpy.nan data_rmse[fiber_fit.vox_coords[:, 0], fiber_fit.vox_coords[:, 1], fiber_fit.vox_coords[:, 2]] = mean_rmse - model_rmse improvment_error_file = os.path.join(outdir, "improvment_rmse.nii.gz") error_im = nibabel.Nifti1Image(data_rmse, im.affine) nibabel.save(error_im, improvment_error_file) return (life_weights_file, life_weights_snap, model_error_file, mean_error_file, improvment_error_file, tracks_snap)