def test_peak_slicer(interactive=False): _peak_dirs = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype='f4') # peak_dirs.shape = (1, 1, 1) + peak_dirs.shape peak_dirs = np.zeros((11, 11, 11, 3, 3)) peak_values = np.random.rand(11, 11, 11, 3) peak_dirs[:, :, :] = _peak_dirs scene = window.Scene() peak_actor = actor.peak_slicer(peak_dirs) scene.add(peak_actor) scene.add(actor.axes((11, 11, 11))) if interactive: window.show(scene) scene.clear() scene.add(peak_actor) scene.add(actor.axes((11, 11, 11))) for k in range(11): peak_actor.display_extent(0, 10, 0, 10, k, k) for j in range(11): peak_actor.display_extent(0, 10, j, j, 0, 10) for i in range(11): peak_actor.display(i, None, None) scene.rm_all() peak_actor = actor.peak_slicer( peak_dirs, peak_values, mask=None, affine=np.diag([3, 2, 1, 1]), colors=None, opacity=0.8, linewidth=3, lod=True, lod_points=10 ** 4, lod_points_size=3) scene.add(peak_actor) scene.add(actor.axes((11, 11, 11))) if interactive: window.show(scene) report = window.analyze_scene(scene) ex = ['vtkLODActor', 'vtkOpenGLActor'] npt.assert_equal(report.actors_classnames, ex) # 6d data data_6d = (255 * np.random.rand(5, 5, 5, 5, 5, 5)) npt.assert_raises(ValueError, actor.peak_slicer, data_6d, data_6d)
def test_peak_slicer(interactive=False): _peak_dirs = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype='f4') # peak_dirs.shape = (1, 1, 1) + peak_dirs.shape peak_dirs = np.zeros((11, 11, 11, 3, 3)) peak_values = np.random.rand(11, 11, 11, 3) peak_dirs[:, :, :] = _peak_dirs renderer = window.Renderer() peak_actor = actor.peak_slicer(peak_dirs) renderer.add(peak_actor) renderer.add(actor.axes((11, 11, 11))) if interactive: window.show(renderer) renderer.clear() renderer.add(peak_actor) renderer.add(actor.axes((11, 11, 11))) for k in range(11): peak_actor.display_extent(0, 10, 0, 10, k, k) for j in range(11): peak_actor.display_extent(0, 10, j, j, 0, 10) for i in range(11): peak_actor.display(i, None, None) renderer.rm_all() peak_actor = actor.peak_slicer( peak_dirs, peak_values, mask=None, affine=np.diag([3, 2, 1, 1]), colors=None, opacity=1, linewidth=3, lod=True, lod_points=10 ** 4, lod_points_size=3) renderer.add(peak_actor) renderer.add(actor.axes((11, 11, 11))) if interactive: window.show(renderer) report = window.analyze_renderer(renderer) ex = ['vtkLODActor', 'vtkOpenGLActor', 'vtkOpenGLActor', 'vtkOpenGLActor'] npt.assert_equal(report.actors_classnames, ex)
def create_peaks_slicer(data, orientation, slice_index, peak_values=None, mask=None, color=None, peaks_width=1.0, symmetric=False): """ Create a peaks slicer actor rendering a slice of the fODF peaks """ # Normalize input data norm = np.linalg.norm(data, axis=-1) data[norm > 0] /= norm[norm > 0].reshape((-1, 1)) # Instantiate peaks slicer peaks_slicer = actor.peak_slicer(data, peaks_values=peak_values, mask=mask, colors=color, linewidth=peaks_width, symmetric=symmetric) set_display_extent(peaks_slicer, orientation, data.shape, slice_index) return peaks_slicer
def create_peaks_slicer(data, orientation, slice_index, peak_values=None, mask=None, color=None, peaks_width=1.0, symmetric=False): """ Create a peaks slicer actor rendering a slice of the fODF peaks Parameters ---------- data : np.ndarray Peaks data. orientation : str Name of the axis to visualize. Choices are axial, coronal and sagittal. slice_index : int Index of the slice to visualize along the chosen orientation. peak_values : np.ndarray, optional Peaks values. Defaults to None. mask : np.ndarray, optional Only the data inside the mask will be displayed. Defaults to None. color : tuple (3,), optional Color used for peaks. If None, a RGB colormap is used. Defaults to None. peaks_width : float, optional Width of peaks segments. Defaults to 1.0. symmetric : bool, optional If True, peaks are drawn for both peaks_dirs and -peaks_dirs. Else, peaks are only drawn for directions given by peaks_dirs. Defaults to False. Returns ------- slicer_actor : actor.peak_slicer Fury object containing the peaks information. """ # Normalize input data norm = np.linalg.norm(data, axis=-1) data[norm > 0] /= norm[norm > 0].reshape((-1, 1)) # Instantiate peaks slicer peaks_slicer = actor.peak_slicer(data, peaks_values=peak_values, mask=mask, colors=color, linewidth=peaks_width, symmetric=symmetric) set_display_extent(peaks_slicer, orientation, data.shape, slice_index) return peaks_slicer
def plot_peak_slice(odf_4d, sphere, background_data, out_file, axis, slicenum, mask_data, tile_size=1200, normalize_peaks=True): from fury import actor, window view_up = [(0., 0., 1.), (0., 0., 1.), (0., -1., 0.)] # Make a slice mask to reduce memory new_shape = list(odf_4d.shape) new_shape[axis] = 1 image_shape = new_shape[:3] midpoint = (new_shape[0] / 2., new_shape[1] / 2., new_shape[2] / 2.) if axis == 0: odf_slice = odf_4d[slicenum, :, :, :].reshape(new_shape) image_slice = background_data[slicenum, :, :].reshape(image_shape) mask_slice = mask_data[slicenum, :, :].reshape(image_shape) camera_dist = max(midpoint[1], midpoint[2]) * np.pi elif axis == 1: odf_slice = odf_4d[:, slicenum, :, :].reshape(new_shape) image_slice = background_data[:, slicenum, :].reshape(image_shape) mask_slice = mask_data[:, slicenum, :].reshape(image_shape) camera_dist = max(midpoint[0], midpoint[2]) * np.pi elif axis == 2: odf_slice = odf_4d[:, :, slicenum, :].reshape(new_shape) image_slice = background_data[:, :, slicenum].reshape(image_shape) mask_slice = mask_data[:, :, slicenum].reshape(image_shape) camera_dist = max(midpoint[0], midpoint[1]) * np.pi position = list(midpoint) position[axis] += camera_dist # Find the actual peaks peak_dirs, peak_values = peaks_from_odfs(odf_slice, sphere, relative_peak_threshold=.1, min_separation_angle=15, mask=mask_slice, normalize_peaks=normalize_peaks, npeaks=3) if normalize_peaks: peak_values = peak_values / peak_values.max() * np.pi peak_actor = actor.peak_slicer(peak_dirs, peak_values, colors=None) image_actor = actor.slicer(image_slice, opacity=0.6, interpolation='nearest') image_size = (tile_size, tile_size) scene = window.Scene() scene.add(image_actor) scene.add(peak_actor) xfov_min, xfov_max = 0, new_shape[0] - 1 yfov_min, yfov_max = 0, new_shape[1] - 1 zfov_min, zfov_max = 0, new_shape[2] - 1 peak_actor.display_extent(xfov_min, xfov_max, yfov_min, yfov_max, zfov_min, zfov_max) image_actor.display_extent(xfov_min, xfov_max, yfov_min, yfov_max, zfov_min, zfov_max) scene.set_camera(focal_point=tuple(midpoint), position=tuple(position), view_up=view_up[axis]) window.record(scene, out_path=out_file, reset_camera=False, size=image_size) scene.clear()
def main(): parser = _build_arg_parser() args = parser.parse_args() required = [args.dwi, args.bval, args.bvec, args.target_template] assert_inputs_exist(parser, required) output_filenames = [] for axis_name in ['sagittal', 'coronal', 'axial']: if args.output_suffix: output_filenames.append(os.path.join(args.output_dir, '{0}_{1}.png'.format( axis_name, args.output_suffix))) else: output_filenames.append(os.path.join(args.output_dir, '{0}.png'.format(axis_name))) assert_outputs_exist(parser, args, output_filenames) if args.output_dir and not os.path.isdir(args.output_dir): os.mkdir(args.output_dir) # Get the relevant slices from the template target_template_img = nib.load(args.target_template) zooms = 1 / float(target_template_img.header.get_zooms()[0]) x_slice = int(target_template_img.shape[0] / 2 + zooms*30) y_slice = int(target_template_img.shape[1] / 2) z_slice = int(target_template_img.shape[2] / 2) slices_choice = (x_slice, y_slice, z_slice) FA, evals, evecs = prepare_data_for_actors(args.dwi, args.bval, args.bvec, args.target_template, slices_choice, shells=args.shells) # Create actors from each dataset for Dipy volume_actor = actor.slicer(FA, affine=nib.load(args.target_template).affine, opacity=0.3, interpolation='nearest') peaks_actor = actor.peak_slicer(evecs, affine=nib.load( args.target_template).affine, peaks_values=evals, colors=None, linewidth=1) # Take a snapshot of each dataset, camera setting are fixed for the # known template, won't work with another. display_slices(volume_actor, slices_choice, output_filenames[0], 'sagittal', view_position=tuple([x for x in (-125, 10, 10)]), focal_point=tuple([x for x in (0, -10, 10)]), peaks_actor=peaks_actor) display_slices(volume_actor, slices_choice, output_filenames[1], 'coronal', view_position=tuple([x for x in (0, 150, 30)]), focal_point=tuple([x for x in (0, 0, 30)]), peaks_actor=peaks_actor) display_slices(volume_actor, slices_choice, output_filenames[2], 'axial', view_position=tuple([x for x in (0, 25, 150)]), focal_point=tuple([x for x in (0, 25, 0)]), peaks_actor=peaks_actor)
def screenshot_fa_peaks(fa, peaks, directory='.'): """ Compute 3 view screenshot with peaks on FA. Parameters ---------- fa : string FA filename. peaks : string Peak filename. directory : string Directory to save the mosaic. Returns ------- name : string Path of the mosaic """ slice_name = ['sagittal', 'coronal', 'axial'] data = nib.load(fa).get_data() evecs_data = nib.load(peaks).get_data() evecs = np.zeros(data.shape + (1, 3)) evecs[:, :, :, 0, :] = evecs_data[...] middle = [data.shape[0] // 2 + 4, data.shape[1] // 2, data.shape[2] // 2] slice_display = [(middle[0], None, None), (None, middle[1], None), (None, None, middle[2])] concat = [] for j, slice_name in enumerate(slice_name): image_name = os.path.basename(str(peaks)).split(".")[0] name = os.path.join(directory, image_name + '.png') slice_actor = actor.slicer(data, interpolation='nearest', opacity=0.3) peak_actor = actor.peak_slicer(evecs, colors=None) peak_actor.GetProperty().SetLineWidth(2.5) slice_actor.display(slice_display[j][0], slice_display[j][1], slice_display[j][2]) peak_actor.display(slice_display[j][0], slice_display[j][1], slice_display[j][2]) renderer = window.ren() renderer.add(slice_actor) renderer.add(peak_actor) center = slice_actor.GetCenter() pos = None viewup = None if slice_name == "sagittal": pos = (center[0] - 350, center[1], center[2]) viewup = (0, 0, -1) elif slice_name == "coronal": pos = (center[0], center[1] + 350, center[2]) viewup = (0, 0, -1) elif slice_name == "axial": pos = (center[0], center[1], center[2] + 350) viewup = (0, -1, 1) camera = renderer.GetActiveCamera() camera.SetViewUp(viewup) camera.SetPosition(pos) camera.SetFocalPoint(center) img = renderer_to_arr(renderer, (1080, 1080)) if len(concat) == 0: concat = img else: concat = np.hstack((concat, img)) imgs_comb = Image.fromarray(concat) imgs_comb.save(name) return name
def render( self, tractogram: Tractogram = None, filename: str = None ): """ Render the streamlines, either directly or through a file Might render from "outside" the environment, like for comet Parameters: ----------- tractogram: Tractogram, optional Object containing the streamlines and seeds path: str, optional If set, save the image at the specified location instead of displaying directly """ from fury import window, actor # Might be rendering from outside the environment if tractogram is None: tractogram = Tractogram( streamlines=self.streamlines[:, :self.length], data_per_streamline={ 'seeds': self.starting_points }) # Reshape peaks for displaying X, Y, Z, M = self.peaks.data.shape peaks = np.reshape(self.peaks.data, (X, Y, Z, 5, M//5)) # Setup scene and actors scene = window.Scene() stream_actor = actor.streamtube(tractogram.streamlines) peak_actor = actor.peak_slicer(peaks, np.ones((X, Y, Z, M)), colors=(0.2, 0.2, 1.), opacity=0.5) dot_actor = actor.dots(tractogram.data_per_streamline['seeds'], color=(1, 1, 1), opacity=1, dot_size=2.5) scene.add(stream_actor) scene.add(peak_actor) scene.add(dot_actor) scene.reset_camera_tight(0.95) # Save or display scene if filename is not None: directory = os.path.dirname(pjoin(self.experiment_path, 'render')) if not os.path.exists(directory): os.makedirs(directory) dest = pjoin(directory, filename) window.snapshot( scene, fname=dest, offscreen=True, size=(800, 800)) else: showm = window.ShowManager(scene, reset_camera=True) showm.initialize() showm.start()