def glyph_dot(centers, colors, radius=100): if np.array(colors).ndim == 1: colors = np.tile(colors, (len(centers), 1)) vtk_pnt = numpy_to_vtk_points(centers) pnt_polydata = vtk.vtkPolyData() pnt_polydata.SetPoints(vtk_pnt) vertex_filter = vtk.vtkVertexGlyphFilter() vertex_filter.SetInputData(pnt_polydata) vertex_filter.Update() polydata = vtk.vtkPolyData() polydata.ShallowCopy(vertex_filter.GetOutput()) mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(polydata) mapper.SetScalarModeToUsePointFieldData() pnt_actor = vtk.vtkActor() pnt_actor.SetMapper(mapper) pnt_actor.GetProperty().SetPointSize(radius) cols = numpy_to_vtk_colors(255 * np.ascontiguousarray(colors)) cols.SetName('colors') polydata.GetPointData().AddArray(cols) mapper.SelectColorArray('colors') return pnt_actor
def run(self, input_files, cluster=False, cluster_thr=15., random_colors=False, length_gt=0, length_lt=1000, clusters_gt=0, clusters_lt=10**8, native_coords=False, stealth=False, emergency_header='icbm_2009a', bg_color=(0, 0, 0), disable_order_transparency=False, buan=False, buan_thr=0.5, buan_highlight=(1, 0, 0), out_dir='', out_stealth_png='tmp.png'): """ Interactive medical visualization - Invert the Horizon! Interact with any number of .trk, .tck or .dpy tractograms and anatomy files .nii or .nii.gz. Cluster streamlines on loading. Parameters ---------- input_files : variable string cluster : bool, optional Enable QuickBundlesX clustering. cluster_thr : float, optional Distance threshold used for clustering. Default value 15.0 for small animal brains you may need to use something smaller such as 2.0. The distance is in mm. For this parameter to be active ``cluster`` should be enabled. random_colors : bool, optional Given multiple tractograms have been included then each tractogram will be shown with different color. length_gt : float, optional Clusters with average length greater than ``length_gt`` amount in mm will be shown. length_lt : float, optional Clusters with average length less than ``length_lt`` amount in mm will be shown. clusters_gt : int, optional Clusters with size greater than ``clusters_gt`` will be shown. clusters_lt : int, optional Clusters with size less than ``clusters_gt`` will be shown. native_coords : bool, optional Show results in native coordinates. stealth : bool, optional Do not use interactive mode just save figure. emergency_header : str, optional If no anatomy reference is provided an emergency header is provided. Current options 'icbm_2009a' and 'icbm_2009c'. bg_color : variable float, optional Define the background color of the scene. Colors can be defined with 1 or 3 values and should be between [0-1]. disable_order_transparency : bool, optional Use depth peeling to sort transparent objects. If True also enables anti-aliasing. buan : bool, optional Enables BUAN framework visualization. buan_thr : float, optional Uses the threshold value to highlight segments on the bundle which have pvalues less than this threshold. buan_highlight : variable float, optional Define the bundle highlight area color. Colors can be defined with 1 or 3 values and should be between [0-1]. For example, a value of (1, 0, 0) would mean the red color. out_dir : str, optional Output directory. (default current directory) out_stealth_png : str, optional Filename of saved picture. References ---------- .. [Horizon_ISMRM19] Garyfallidis E., M-A. Cote, B.Q. Chandio, S. Fadnavis, J. Guaje, R. Aggarwal, E. St-Onge, K.S. Juneja, S. Koudoro, D. Reagan, DIPY Horizon: fast, modular, unified and adaptive visualization, Proceedings of: International Society of Magnetic Resonance in Medicine (ISMRM), Montreal, Canada, 2019. """ verbose = True tractograms = [] images = [] pams = [] numpy_files = [] interactive = not stealth world_coords = not native_coords bundle_colors = None mni_2009a = {} mni_2009a['affine'] = np.array([[1., 0., 0., -98.], [0., 1., 0., -134.], [0., 0., 1., -72.], [0., 0., 0., 1.]]) mni_2009a['dims'] = (197, 233, 189) mni_2009a['vox_size'] = (1., 1., 1.) mni_2009a['vox_space'] = 'RAS' mni_2009c = {} mni_2009c['affine'] = np.array([[1., 0., 0., -96.], [0., 1., 0., -132.], [0., 0., 1., -78.], [0., 0., 0., 1.]]) mni_2009c['dims'] = (193, 229, 193) mni_2009c['vox_size'] = (1., 1., 1.) mni_2009c['vox_space'] = 'RAS' if emergency_header == 'icbm_2009a': hdr = mni_2009c else: hdr = mni_2009c emergency_ref = create_nifti_header(hdr['affine'], hdr['dims'], hdr['vox_size']) io_it = self.get_io_iterator() for input_output in io_it: fname = input_output[0] if verbose: print('Loading file ...') print(fname) print('\n') fl = fname.lower() ends = fl.endswith if ends('.trk'): sft = load_tractogram(fname, 'same', bbox_valid_check=False) tractograms.append(sft) if ends('.dpy') or ends('.tck'): sft = load_tractogram(fname, emergency_ref) tractograms.append(sft) if ends('.nii.gz') or ends('.nii'): data, affine = load_nifti(fname) images.append((data, affine)) if verbose: print('Affine to RAS') np.set_printoptions(3, suppress=True) print(affine) np.set_printoptions() if ends(".pam5"): pam = load_peaks(fname) pams.append(pam) if verbose: print('Peak_dirs shape') print(pam.peak_dirs.shape) if ends(".npy"): data = np.load(fname) numpy_files.append(data) if verbose: print('numpy array length') print(len(data)) if buan: bundle_colors = [] for i in range(len(numpy_files)): n = len(numpy_files[i]) pvalues = numpy_files[i] bundle = tractograms[i].streamlines indx = assignment_map(bundle, bundle, n) ind = np.array(indx) nb_lines = len(bundle) lines_range = range(nb_lines) points_per_line = [len(bundle[i]) for i in lines_range] points_per_line = np.array(points_per_line, np.intp) cols_arr = line_colors(bundle) colors_mapper = np.repeat(lines_range, points_per_line, axis=0) vtk_colors = numpy_to_vtk_colors(255 * cols_arr[colors_mapper]) colors = numpy_support.vtk_to_numpy(vtk_colors) colors = (colors - np.min(colors)) / np.ptp(colors) for i in range(n): if pvalues[i] < buan_thr: colors[ind == i] = buan_highlight bundle_colors.append(colors) if len(bg_color) == 1: bg_color *= 3 elif len(bg_color) != 3: raise ValueError('You need 3 values to set up backgound color. ' 'e.g --bg_color 0.5 0.5 0.5') order_transparent = not disable_order_transparency horizon(tractograms=tractograms, images=images, pams=pams, cluster=cluster, cluster_thr=cluster_thr, random_colors=random_colors, bg_color=bg_color, order_transparent=order_transparent, length_gt=length_gt, length_lt=length_lt, clusters_gt=clusters_gt, clusters_lt=clusters_lt, world_coords=world_coords, interactive=interactive, buan=buan, buan_colors=bundle_colors, out_png=pjoin(out_dir, out_stealth_png))
def _peaks_colors_from_points(points, colors=None, points_per_line=2): """ Returns a VTK scalar array containing colors information for each one of the peaks according to the policy defined by the parameter colors. Parameters ---------- points : (N, 3) array or ndarray points coordinates array. colors : None or string ('rgb_standard') or tuple (3D or 4D) or array/ndarray (N, 3 or 4) or array/ndarray (K, 3 or 4) or array/ndarray(N, ) or array/ndarray (K, ) If None a standard orientation colormap is used for every line. If one tuple of color is used. Then all streamlines will have the same color. If an array (N, 3 or 4) is given, where N is equal to the number of points. Then every point is colored with a different RGB(A) color. If an array (K, 3 or 4) is given, where K is equal to the number of lines. Then every line is colored with a different RGB(A) color. If an array (N, ) is given, where N is the number of points then these are considered as the values to be used by the colormap. If an array (K,) is given, where K is the number of lines then these are considered as the values to be used by the colormap. points_per_line : int (1 or 2), optional number of points per peak direction. Returns ------- color_array : vtkDataArray vtk scalar array with name 'colors'. colors_are_scalars : bool indicates whether or not the colors are scalars to be interpreted by a colormap. global_opacity : float returns 1 if the colors array doesn't contain opacity otherwise -1. """ num_pnts = len(points) num_lines = num_pnts // points_per_line colors_are_scalars = False global_opacity = 1 if colors is None or colors == 'rgb_standard': # Automatic RGB colors colors = np.asarray((0, 0, 0)) color_array = numpy_to_vtk_colors(np.tile(255 * colors, (num_pnts, 1))) elif type(colors) is tuple: global_opacity = 1 if len(colors) == 3 else -1 colors = np.asarray(colors) color_array = numpy_to_vtk_colors(np.tile(255 * colors, (num_pnts, 1))) else: colors = np.asarray(colors) if len(colors) == num_lines: pnts_colors = np.repeat(colors, points_per_line, axis=0) if colors.ndim == 1: # Scalar per line color_array = numpy_support.numpy_to_vtk(pnts_colors, deep=True) colors_are_scalars = True elif colors.ndim == 2: # RGB(A) color per line global_opacity = 1 if colors.shape[1] == 3 else -1 color_array = numpy_to_vtk_colors(255 * pnts_colors) elif len(colors) == num_pnts: if colors.ndim == 1: # Scalar per point color_array = numpy_support.numpy_to_vtk(colors, deep=True) colors_are_scalars = True elif colors.ndim == 2: # RGB(A) color per point global_opacity = 1 if colors.shape[1] == 3 else -1 color_array = numpy_to_vtk_colors(255 * colors) color_array.SetName('colors') return color_array, colors_are_scalars, global_opacity
def sphere(centers, colors, radii=1., theta=16, phi=16, vertices=None, faces=None): """Visualize one or many spheres with different colors and radii Parameters ---------- centers : ndarray, shape (N, 3) colors : ndarray (N,3) or (N, 4) or tuple (3,) or tuple (4,) RGB or RGBA (for opacity) R, G, B and A should be at the range [0, 1] radii : float or ndarray, shape (N,) theta : int phi : int vertices : ndarray, shape (N, 3) faces : ndarray, shape (M, 3) If faces is None then a sphere is created based on theta and phi angles If not then a sphere is created with the provided vertices and faces. Returns ------- vtkActor Examples -------- >>> from fury import window, actor >>> scene = window.Scene() >>> centers = np.random.rand(5, 3) >>> sphere_actor = actor.sphere(centers, window.colors.coral) >>> scene.add(sphere_actor) >>> # window.show(scene) """ if np.array(colors).ndim == 1: colors = np.tile(colors, (len(centers), 1)) if isinstance(radii, (float, int)): radii = radii * np.ones(len(centers), dtype='f8') pts = numpy_to_vtk_points(np.ascontiguousarray(centers)) cols = numpy_to_vtk_colors(255 * np.ascontiguousarray(colors)) cols.SetName('colors') radii_fa = numpy_support.numpy_to_vtk(np.ascontiguousarray( radii.astype('f8')), deep=0) radii_fa.SetName('rad') polydata_centers = vtk.vtkPolyData() polydata_sphere = vtk.vtkPolyData() if faces is None: src = vtk.vtkSphereSource() src.SetRadius(1) src.SetThetaResolution(theta) src.SetPhiResolution(phi) else: set_polydata_vertices(polydata_sphere, vertices) set_polydata_triangles(polydata_sphere, faces) polydata_centers.SetPoints(pts) polydata_centers.GetPointData().AddArray(radii_fa) polydata_centers.GetPointData().SetActiveScalars('rad') polydata_centers.GetPointData().AddArray(cols) glyph = vtk.vtkGlyph3D() if faces is None: glyph.SetSourceConnection(src.GetOutputPort()) else: glyph.SetSourceData(polydata_sphere) glyph.SetInputData(polydata_centers) glyph.Update() mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(glyph.GetOutput()) mapper.SetScalarModeToUsePointFieldData() mapper.SelectColorArray('colors') actor = vtk.vtkActor() actor.SetMapper(mapper) return actor
def rectangle2(centers, colors, use_vertices=False, size=(2, 2)): """Visualize one or many spheres with different colors and radii Parameters ---------- centers : ndarray, shape (N, 3) colors : ndarray (N,3) or (N, 4) or tuple (3,) or tuple (4,) RGB or RGBA (for opacity) R, G, B and A should be at the range [0, 1] """ if np.array(colors).ndim == 1: colors = np.tile(colors, (len(centers), 1)) pts = numpy_to_vtk_points(np.ascontiguousarray(centers)) cols = numpy_to_vtk_colors(255 * np.ascontiguousarray(colors)) cols.SetName('colors') polydata_centers = vtk.vtkPolyData() polydata_centers.SetPoints(pts) polydata_centers.GetPointData().AddArray(cols) print("NB pts: ", polydata_centers.GetNumberOfPoints()) print("NB arrays: ", polydata_centers.GetPointData().GetNumberOfArrays()) for i in range(polydata_centers.GetPointData().GetNumberOfArrays()): print("Array {0}: {1}".format( i, polydata_centers.GetPointData().GetArrayName(i))) for i in range(polydata_centers.GetCellData().GetNumberOfArrays()): print("Cell {0}: {1}".format( i, polydata_centers.GetCellData().GetArrayName(i))) print("Array pts: {}".format( polydata_centers.GetPoints().GetData().GetName())) glyph = vtk.vtkGlyph3D() if use_vertices: scale = 1 my_polydata = vtk.vtkPolyData() my_vertices = np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 1.0, 0.0], [1.0, 0.0, 0.0]]) my_vertices -= np.array([0.5, 0.5, 0]) my_vertices = scale * my_vertices my_triangles = np.array([[0, 1, 2], [2, 3, 0]], dtype='i8') set_polydata_vertices(my_polydata, my_vertices) set_polydata_triangles(my_polydata, my_triangles) glyph.SetSourceData(my_polydata) else: src = vtk.vtkPlaneSource() src.SetXResolution(size[0]) src.SetYResolution(size[1]) glyph.SetSourceConnection(src.GetOutputPort()) glyph.SetInputData(polydata_centers) glyph.Update() mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(glyph.GetOutput()) mapper.SetScalarModeToUsePointFieldData() mapper.SelectColorArray('colors') actor = vtk.vtkActor() actor.SetMapper(mapper) return actor