def viz_dimer_positions(positions, size=5, cmap_name="tab20c", color_feature_name=None): import ipyvolume as ipv # Only show visible dimers selected_dimers = positions[positions['visible'] is True] x, y, z = selected_dimers[['x', 'y', 'z']].values.astype('float').T if color_feature_name: # TODO: that code should be much simpler... cmap = matplotlib.cm.get_cmap(cmap_name) categories = selected_dimers[color_feature_name].unique() color_indices = cmap([i / len(categories) for i in categories]) color = np.zeros((len(selected_dimers[color_feature_name]), 4)) for color_index in enumerate(categories): color[selected_dimers[color_feature_name] == categories[color_index]] = color_indices[color_index] else: color = '#e4191b' ipv.figure(height=800, width=1000) ipv.scatter(x, y, z, size=size, marker='sphere', color=color) ipv.squarelim() ipv.show()
def viz_dimer_positions_ipv(positions, size=5, cmap_name="tab20c", color_feature_name=None): try: import ipyvolume as ipv except ImportError: mess = "YOu need to install the ipyvolume library. " mess += "Please follow the official instructions at https://github.com/maartenbreddels/ipyvolume." raise ImportError(mess) # Only show visible dimers selected_dimers = positions[positions["visible"]] x, y, z = selected_dimers[["x", "y", "z"]].values.astype("float").T if color_feature_name: # TODO: that code should be much simpler... cmap = matplotlib.cm.get_cmap(cmap_name) categories = selected_dimers[color_feature_name].unique() color_indices = cmap([i / len(categories) for i in categories]) color = np.zeros((len(selected_dimers[color_feature_name]), 4)) for color_index, _ in enumerate(categories): mask = selected_dimers[color_feature_name] == categories[ color_index] color[mask] = color_indices[color_index] else: color = "#e4191b" ipv.figure(height=800, width=1000) ipv.scatter(x, y, z, size=size, marker="sphere", color=color) ipv.squarelim() ipv.show()
def brain(draw=True, show=True, fiducial=True, flat=True, inflated=True, subject='S1', interval=1000, uv=True, color=None): import ipyvolume as ipv try: import cortex except: warnings.warn("it seems pycortex is not installed, which is needed for this example") raise xlist, ylist, zlist = [], [], [] polys_list = [] def add(pts, polys): xlist.append(pts[:,0]) ylist.append(pts[:,1]) zlist.append(pts[:,2]) polys_list.append(polys) def n(x): return (x - x.min()) / x.ptp() if fiducial or color is True: pts, polys = cortex.db.get_surf('S1', 'fiducial', merge=True) x, y, z = pts.T r = n(x) g = n(y) b = n(z) if color is True: color = np.array([r,g,b]).T.copy() else: color = None if fiducial: add(pts, polys) else: if color is False: color = None if inflated: add(*cortex.db.get_surf('S1', 'inflated', merge=True, nudge=True)) u = v = None if flat or uv: pts, polys = cortex.db.get_surf('S1', 'flat', merge=True, nudge=True) x, y, z = pts.T u = n(x) v = n(y) if flat: add(pts, polys) polys_list.sort(key=lambda x: len(x)) polys = polys_list[0] if draw: if color is None: mesh = ipv.plot_trisurf(xlist, ylist, zlist, polys, u=u, v=v) else: mesh = ipv.plot_trisurf(xlist, ylist, zlist, polys, color=color, u=u, v=v) if show: if len(x) > 1: ipv.animation_control(mesh, interval=interval) ipv.squarelim() ipv.show() return mesh else: return xlist, ylist, zlist, polys
def plot_group_brain_activation(self, radius=12.5, freq_range=(40, 200), clim=None, cmap='RdBu_r'): """ Plots brain surface based on the mean activity across the group. Uses ipyvolume to plot Parameters ---------- radius: float Maximum distance between an electrode and a vertex to be counted as data for that vertex freq_range: list 2 element list defining minimum and maximum frequncies to average. clim: float Maximum/minumum value of the colormap. Will be centered at zero. If not given, will use the maximum absolute value of the data. cmap: str matplotlib colormap to use Returns ------- left hemisphere and right hemisphere activation maps """ # load brain mesh l_coords, l_faces, r_coords, r_faces = self.load_brain_mesh() # compute mean activation l_vert_mean, r_vert_mean = self.compute_surface_map(radius, freq_range) # define colormap range if clim is None: clim = np.max([np.nanmax(np.abs(l_vert_mean)), np.nanmax(np.abs(r_vert_mean))]) c_norm = plt.Normalize(vmin=-clim, vmax=clim) c_mappable = cmx.ScalarMappable(norm=c_norm, cmap=plt.get_cmap(cmap)) # compute surface colors for left valid_l_inds = ~np.isnan(l_vert_mean) l_colors = np.full((l_vert_mean.shape[0], 4), 0.) l_colors[valid_l_inds] = c_mappable.to_rgba(l_vert_mean[valid_l_inds]) # and right valid_r_inds = ~np.isnan(r_vert_mean) r_colors = np.full((r_vert_mean.shape[0], 4), 0.) r_colors[valid_r_inds] = c_mappable.to_rgba(r_vert_mean[valid_r_inds]) # plot it! fig = p3.figure(width=800, height=800, lighting=True) brain_l = p3.plot_trisurf(l_coords[:, 0], l_coords[:, 1], l_coords[:, 2], triangles=l_faces, color=l_colors) brain_r = p3.plot_trisurf(r_coords[:, 0], r_coords[:, 1], r_coords[:, 2], triangles=r_faces, color=r_colors) # turn off axis and make square ipv.squarelim() ipv.style.box_off() ipv.style.axes_off() p3.show() return fig
def plot_group_brain_activation(self, radius=12.5, freq_range=(40, 200), clim=None, cmap='RdBu_r', n_perms=100, min_n=5, res_key='t-stat'): """ Plots brain surface based on the mean activity across the group. Uses ipyvolume to plot Parameters ---------- radius: float Maximum distance between an electrode and a vertex to be counted as data for that vertex freq_range: list 2 element list defining minimum and maximum frequncies to average. clim: float Maximum/minumum value of the colormap. Will be centered at zero. If not given, will use the maximum absolute value of the data. cmap: str matplotlib colormap to use n_perms: int Number of permutations to do when computing our t-statistic significance thresholds min_n: int Vertices with less than this number of subjects will be plotted in gray, regardless of the significance val res_key: str Column name of dataframe to use as the metric Returns ------- left hemisphere and right hemisphere activation maps """ # load brain mesh l_coords, l_faces, r_coords, r_faces = self.load_brain_mesh() # compute mean activation. First get vertex x subject arrays l_vert_vals, r_vert_vals = self.compute_surface_map(radius, freq_range, res_key) # we will actually be plotting t-statistics, so compute those l_ts, l_ps = ttest_1samp(l_vert_vals, 0, axis=1, nan_policy='omit') r_ts, r_ps = ttest_1samp(r_vert_vals, 0, axis=1, nan_policy='omit') # not let's compute our significance thresholds via non-parametric permutation procedure sig_thresh = self.compute_permute_dist_par(l_vert_vals, r_vert_vals, n_perms=n_perms) # define colormap range if clim is None: clim = np.max([np.nanmax(np.abs(l_ts)), np.nanmax(np.abs(r_ts))]) c_norm = plt.Normalize(vmin=-clim, vmax=clim) c_mappable = cmx.ScalarMappable(norm=c_norm, cmap=plt.get_cmap(cmap)) # compute surface colors for left valid_l_inds = ~np.isnan(l_ts) & (np.sum(np.isnan(l_vert_vals), axis=1) >= min_n) l_colors = np.full((l_ts.shape[0], 4), 0.) l_colors[valid_l_inds] = c_mappable.to_rgba(l_ts[valid_l_inds]) # and right valid_r_inds = ~np.isnan(r_ts) & (np.sum(np.isnan(r_vert_vals), axis=1) >= min_n) r_colors = np.full((r_ts.shape[0], 4), 0.) r_colors[valid_r_inds] = c_mappable.to_rgba(r_ts[valid_r_inds]) # lastly, mask out vertices that do not meet our significance thresh sig_l = (l_ts < sig_thresh[0]) | (l_ts > sig_thresh[1]) sig_r = (r_ts < sig_thresh[0]) | (r_ts > sig_thresh[1]) l_colors[~sig_l] = [.7, .7, .7, 0.] r_colors[~sig_r] = [.7, .7, .7, 0.] # plot it! fig = p3.figure(width=800, height=800, lighting=True) brain_l = p3.plot_trisurf(l_coords[:, 0], l_coords[:, 1], l_coords[:, 2], triangles=l_faces, color=l_colors) brain_r = p3.plot_trisurf(r_coords[:, 0], r_coords[:, 1], r_coords[:, 2], triangles=r_faces, color=r_colors) # turn off axis and make square ipv.squarelim() ipv.style.box_off() ipv.style.axes_off() p3.show() return fig
def plot_group_brain_activation(self, radius=12.5, freq_range=(40, 200), clim=None, cmap='RdBu_r', n_perms=100, min_n=5): """ Plots brain surface based on the mean activity across the group. Uses ipyvolume to plot Parameters ---------- radius: float Maximum distance between an electrode and a vertex to be counted as data for that vertex freq_range: list 2 element list defining minimum and maximum frequncies to average. clim: float Maximum/minumum value of the colormap. Will be centered at zero. If not given, will use the maximum absolute value of the data. cmap: str matplotlib colormap to use n_perms: int Number of permutations to do when computing our t-statistic significance thresholds min_n: int Vertices with less than this number of subjects will be plotted in gray, regardless of the significance val Returns ------- left hemisphere and right hemisphere activation maps """ # load brain mesh l_coords, l_faces, r_coords, r_faces = self.load_brain_mesh() # compute mean activation. First get vertex x subject arrays l_vert_vals, r_vert_vals = self.compute_surface_map(radius, freq_range) # we will actually be plotting t-statistics, so compute those l_ts, l_ps = ttest_1samp(l_vert_vals, 0, axis=1, nan_policy='omit') r_ts, r_ps = ttest_1samp(r_vert_vals, 0, axis=1, nan_policy='omit') # not let's compute our significance thresholds via non-parametric permutation procedure sig_thresh = self.compute_permute_dist_par(l_vert_vals, r_vert_vals, n_perms=n_perms) # define colormap range if clim is None: clim = np.max([np.nanmax(np.abs(l_ts)), np.nanmax(np.abs(r_ts))]) c_norm = plt.Normalize(vmin=-clim, vmax=clim) c_mappable = cmx.ScalarMappable(norm=c_norm, cmap=plt.get_cmap(cmap)) # compute surface colors for left valid_l_inds = ~np.isnan(l_ts) & (np.sum(np.isnan(l_vert_vals), axis=1) >= min_n) l_colors = np.full((l_ts.shape[0], 4), 0.) l_colors[valid_l_inds] = c_mappable.to_rgba(l_ts[valid_l_inds]) # and right valid_r_inds = ~np.isnan(r_ts) & (np.sum(np.isnan(r_vert_vals), axis=1) >= min_n) r_colors = np.full((r_ts.shape[0], 4), 0.) r_colors[valid_r_inds] = c_mappable.to_rgba(r_ts[valid_r_inds]) # lastly, mask out vertices that do not meet our significance thresh sig_l = (l_ts < sig_thresh[0]) | (l_ts > sig_thresh[1]) sig_r = (r_ts < sig_thresh[0]) | (r_ts > sig_thresh[1]) l_colors[~sig_l] = [.7, .7, .7, 0.] r_colors[~sig_r] = [.7, .7, .7, 0.] # plot it! fig = p3.figure(width=800, height=800, lighting=True) brain_l = p3.plot_trisurf(l_coords[:, 0], l_coords[:, 1], l_coords[:, 2], triangles=l_faces, color=l_colors) brain_r = p3.plot_trisurf(r_coords[:, 0], r_coords[:, 1], r_coords[:, 2], triangles=r_faces, color=r_colors) # turn off axis and make square ipv.squarelim() ipv.style.box_off() ipv.style.axes_off() p3.show() return fig
def __init__(self, subject_id, hemi, surf, title=None, cortex='classic', alpha=1.0, size=800, background='black', foreground=None, figure=None, subjects_dir=None, views=['lateral'], offset=True, show_toolbar=False, offscreen=False, interaction=None, units='mm'): # surf = surface if cortex != 'classic': raise ValueError('Options for parameter "cortex" ' + 'is not yet supported.') if figure is not None: raise ValueError('figure parameter is not supported yet.') if interaction is not None: raise ValueError('"interaction" parameter is not supported.') self._foreground = foreground self._hemi = hemi self._units = units self._title = title self._subject_id = subject_id self._views = views # for now only one color bar can be added # since it is the same for all figures self._colorbar_added = False # array of data used by TimeViewer self._data = {} # load geometry for one or both hemispheres as necessary offset = None if (not offset or hemi != 'both') else 0.0 if hemi in ('both', 'split'): self._hemis = ('lh', 'rh') elif hemi in ('lh', 'rh'): self._hemis = (hemi, ) else: raise ValueError('hemi has to be either "lh", "rh", "split", ' + 'or "both"') if isinstance(size, int): fig_w = size fig_h = size else: fig_w, fig_h = size self.geo = {} self._figures = [[] for v in views] self._hemi_meshes = {} self._overlays = {} for h in self._hemis: # Initialize a Surface object as the geometry geo = Surface(subject_id, h, surf, subjects_dir, offset, units=self._units) # Load in the geometry and curvature geo.load_geometry() geo.load_curvature() self.geo[h] = geo for ri, v in enumerate(views): fig = ipv.figure(width=fig_w, height=fig_h, lighting=True) fig.animation = 0 self._figures[ri].append(fig) ipv.style.box_off() ipv.style.axes_off() ipv.style.background_color(background) ipv.view(views_dict[v].azim, views_dict[v].elev) for ci, h in enumerate(self._hemis): if ci == 1 and hemi == 'split': # create a separate figure for right hemisphere fig = ipv.figure(width=fig_w, height=fig_h, lighting=True) fig.animation = 0 self._figures[ri].append(fig) ipv.style.box_off() ipv.style.axes_off() ipv.style.background_color(background) ipv.view(views_dict[v].azim, views_dict[v].elev) hemi_mesh = self._plot_hemi_mesh(self.geo[h].coords, self.geo[h].faces, self.geo[h].grey_curv) self._hemi_meshes[h + '_' + v] = hemi_mesh ipv.squarelim() self._add_title()
def plot_brain(brain, surface='dots', nodes=True, node_colors=False, node_groups=None, surface_color=None, node_color='red', network=None, dot_size=0.1, dot_color='gray', min_fibers=10, max_fibers=500, lowest_cmap_color=0.2, highest_cmap_color=0.7, cmap='rocket', background='light'): import ipyvolume as ipv if surface_color is None: if surface == 'dots': surface_color = 'gray' elif surface == 'full': surface_color = 'orange' if isinstance(node_colors, bool) and node_colors: node_colors = ['red', 'green', 'blue', 'violet', 'yellow'] if node_colors and node_groups is None: node_groups = brain['nodes']['label'] fig = ipv.figure() # plot surface x, y, z = [brain['surface'][key] for key in list('xyz')] if surface == 'dots': ipv.scatter(x, y, z, marker='box', color=dot_color, size=dot_size) elif surface == 'full': ipv.plot_trisurf(x, y, z, triangles=brain['surface']['tri'], color=surface_color) # plot nodes if nodes: xyz = brain['nodes']['xyz'] if node_colors: for label_idx, color in zip(np.unique(node_groups), node_colors): mask = node_groups == label_idx ipv.scatter(xyz[mask, 0], xyz[mask, 1], xyz[mask, 2], marker='sphere', color=color, size=1.5) else: ipv.scatter(xyz[:, 0], xyz[:, 1], xyz[:, 2], marker='sphere', color=node_color, size=1.5) # plot connections if network is not None: x, y, z = brain['nodes']['xyz'].T scaling = highest_cmap_color - lowest_cmap_color min_fibers_log = np.log(min_fibers) max_fibers_log = np.log(max_fibers) if hasattr(plt.cm, cmap): cmp = getattr(plt.cm, cmap) else: import seaborn as sns cmp = getattr(sns.cm, cmap) with fig.hold_sync(): for ii in range(89): for jj in range(ii, 90): if network[ii, jj] > min_fibers: float_color = (min( np.log((network[ii, jj] - min_fibers)) / (max_fibers_log - min_fibers_log), 1.) * scaling + lowest_cmap_color) line_color = cmp(float_color) ipv.plot(x[[ii, jj]], y[[ii, jj]], z[[ii, jj]], color=line_color[:3]) ipv.squarelim() ipv.style.use([background, 'minimal']) ipv.show() return fig
def plot_brain_mesh(rh_vertices=None, lh_vertices=None, rh_faces=None, lh_faces=None, rh_color='grey', lh_color='grey', fig_size=(500, 500), azimuth=90, elevation=90): """Function for plotting triangular format Freesurfer surface of the brain. Parameters ---------- rh_vertices : numpy.array, optional Array of right hemisphere vertex (x, y, z) coordinates, of size number_of_vertices x 3. Default is None. lh_vertices : numpy.array, optional Array of left hemisphere vertex (x, y, z) coordinates, of size number_of_vertices x 3. Default is None. rh_faces : numpy.array, optional Array defining right hemisphere mesh triangles, of size number_of_faces x 3. Default is None. lh_faces : numpy.array, optional Array defining mesh triangles, of size number_of_faces x 3. Default is None. rh_color : str | numpy.array, optional Color for each point/vertex/symbol of the right hemisphere, can be string format, examples for red:’red’, ‘#f00’, ‘#ff0000’ or ‘rgb(1,0,0), or rgb array of shape (N, 3). Default value is 'grey'. lh_color : str | numpy.array, optional Color for each point/vertex/symbol of the left hemisphere, can be string format, examples for red:’red’, ‘#f00’, ‘#ff0000’ or ‘rgb(1,0,0), or rgb array of shape (N, 3). Default value is 'grey'. fig_size : (int, int), optional Width and height of the figure. Default is (500, 500). azimuth : int, optional Angle of rotation about the z-axis (pointing up) in degrees. Default is 90. elevation : int, optional Vertical rotation where 90 means ‘up’, -90 means ‘down’, in degrees. Default is 90. Returns ------- fig : ipyvolume.Figure Ipyvolume object presenting the figure. rh_mesh : ipyvolume.Mesh Ipyvolume object presenting the built mesh for right hemisphere. lh_mesh : ipyvolume.Mesh Ipyvolume object presenting the built mesh for right hemisphere. """ rh_mesh = None lh_mesh = None fig = ipv.figure(width=fig_size[0], height=fig_size[1], lighting=True) if (rh_vertices is not None) and (rh_faces is not None): rh_mesh = plot_hemisphere_mesh(rh_vertices, rh_faces, rh_color) if (lh_vertices is not None) and (lh_faces is not None): lh_mesh = plot_hemisphere_mesh(lh_vertices, lh_faces, lh_color) style.use('minimal') ipv.view(azimuth, elevation) ipv.squarelim() ipv.show() return fig, rh_mesh, lh_mesh