def _update_target_position(self, xyz=None): # Check XYZ : sh = xyz.shape assert sh[1] in [2, 3] self._n_sources = sh[0] pos = xyz if sh[1] == 3 else np.c_[xyz, np.full((len(self), ), _z)] self._target_xyz = vispy_array(pos)
def on_timer(*args, **kwargs): if hasattr(brain_obj, 'camera'): brain_obj.camera.azimuth += 1 t = app_timer.elapsed frame = int(np.floor(t * sampling_frequency)) new_data = data[:, frame % data.shape[1]].ravel() source_object._data = vispy_array(new_data) source_object.update() source_object.project_sources(brain_obj) source_object.color_sources()
def _update_position(self, xyz=None): # Check XYZ : sh = xyz.shape assert sh[1] in [2, 3] self._n_sources = sh[0] pos = xyz if sh[1] == 3 else np.c_[xyz, np.full((len(self), ), _z)] self._xyz = vispy_array(pos) # Assign XYZ self._sources._data['a_position'] = self._xyz self.update()
def set_data(self, data, time=None): """Set data to the grid of signals. Parameters ---------- data : array_like Array of data of shape (n_pts,). time : array_like | None Array of time points of shape (n_pts,) """ data = np.asarray(data) assert data.ndim == 1 self._n = len(data) time = np.arange(len(data)) if time is None else np.asarray(time) assert len(time) == len(self) # Transient detection : self.transient = data # self._pos = vispy_array(np.c_[time, data]) self._position_vbo.set_data(self._pos)
def set_data(self, data, index, color='black', lw=2., nbins=10, symbol='disc', size=10., form='line', th=None, norm=None, window=None, overlap=0., baseline=None, clim=None, cmap='viridis', interpolation='gaussian', nperseg=256, noverlap=128): """Set data to the plot. Parameters ---------- data : array_like Raw data vector of shape (N,) index : int | 0 Index of the 3-d array. color : array_like/string/tuple | None Color of the plot. lw : float | None Line width (form='line'). symbol : string | None Marker symbol (form='marker'). size : float | None Marker size (form='marker'). nbins : int | None Number of bins for the histogram (form='histogram') form : {'line', 'marker', 'histogram', 'tf'} Plotting type. th : tuple | None Tuple of floats for line thresholding. norm : int | None Normalization method for (form='tf'). window : tuple | None Averaging window (form='tf'). overlap : float | 0. Overlap between successive windows (form='tf'). baseline : tuple | None Baseline period for the normalization (form='tf'). """ # Update variable : self.form = form self._index = index color = color2vb(color) # Get data index : if data.ndim == 1: idx = slice(None) elif data.ndim in [2, 3]: idx = list(self._navidx[index]) idx.insert(self._axis, slice(None)) idx = tuple(idx) # Convert data to be compatible with VisPy and prepare data : data_c = vispy_array(data[idx]).copy() _data = self._prep._prepare_data(self._sf, data_c, self._time) # Set data : if form in ['line', 'marker', 'psd', 'butterfly']: # line and marker # Get position array : pos = np.c_[self._time, _data] # Send position : if form in ['line', 'psd']: if form == 'psd': fmax = self._sf / 4. f, pxx = welch(_data, self._sf, nperseg=nperseg, noverlap=noverlap) f_sf4 = abs(f - fmax) f_1 = abs(f - 1.) fidx_sf4 = np.where(f_sf4 == f_sf4.min())[0][0] fidx_1 = np.where(f_1 == f_1.min())[0][0] pos = np.c_[f[fidx_1:-fidx_sf4], pxx[fidx_1:-fidx_sf4]] # Threshold : is_th = isinstance(th, (tuple, list, np.ndarray)) col = color2vb(color, length=pos.shape[0]) if is_th: # Build threshold segments : t_min, t_max = self._time.min(), self._time.max() pos_th = np.vstack( ([t_min, th[0]], [t_max, th[0]], [t_min, th[1]], [t_max, th[1]])) self._th.set_data(pos_th, connect='segments', color=color2vb('#ab4642')) # Build line color : col = color2vb(color, length=len(_data)) cond = np.logical_or(_data < th[0], _data > th[1]) col[cond, :] = color2vb('#ab4642') self._th.visible = is_th self._line.set_data(pos, width=lw, color=col) self._line.update() elif form == 'marker': self._mark.set_data(pos, face_color=color, symbol=symbol, size=size, edge_width=0.) self._mark.update() elif form == 'butterfly': # Get soe shape related variables : n, m = len(self._time), int(np.prod(data.shape)) n_rep = int(m / n) data = vispy_array(data) # Build position : pos = np.c_[np.tile(self._time.ravel(), n_rep), data.ravel()] # Disconnect some points : connect = np.c_[np.arange(m - 1), np.arange(1, m)] to_delete = np.linspace(n - 1, m - 1, n_rep) connect = np.delete(connect, to_delete, axis=0) # Build color : col = color2vb(color, length=m) # singcol = np.random.uniform(size=(n_rep, 3), low=.2, # high=.8).astype(np.float32) # col = np.repeat(singcol, n, 0) # Send data : self._line.set_data(pos, width=lw, color=col, connect=connect) self._line.update() # Get camera rectangle : t_min, t_max = pos[:, 0].min(), pos[:, 0].max() d_min, d_max = pos[:, 1].min(), pos[:, 1].max() off = .05 * (d_max - d_min) self.rect = (t_min, d_min - off, t_max - t_min, d_max - d_min + 2 * off) elif form == 'histogram': # histogram # Compute the mesh : mesh = scene.visuals.Histogram(_data, nbins) # Get the vertices and faces of the mesh : vert = mesh.mesh_data.get_vertices() faces = mesh.mesh_data.get_faces() # Pass vertices and faces to the histogram : self._hist.set_data(vert, faces, color=color) # Compute the histogram : raw, xvec = np.histogram(_data, nbins) # Get camera rectangle : t_min, t_max = xvec.min(), xvec.max() d_min, d_max = 0.9 * raw[np.nonzero(raw)].min(), 1.01 * raw.max() self.rect = (t_min, d_min, t_max - t_min, d_max - d_min) # Update object : self._hist.update() elif form == 'tf': # time-frequency map self._tf.set_data(_data, self._sf, cmap=cmap, contrast=.5, norm=norm, baseline=baseline, n_window=window, overlap=overlap, window='hanning', clim=clim) self._tf.interpolation = interpolation self.rect = self._tf.rect # Hide non form elements : self._visibility() # Update annotations : self.update_annotations(str(self))
def __init__(self, name, xyz, data=None, color='red', alpha=1., symbol='disc', radius_min=5., radius_max=10., edge_width=0., edge_color='black', system='mni', mask=None, mask_color='gray', mask_radius=5., text=None, text_size=2., text_color='white', text_bold=False, text_translate=(0., 2., 0.), visible=True, transform=None, parent=None, verbose=None, _z=-10., **kw): """Init.""" VisbrainObject.__init__(self, name, parent, transform, verbose, **kw) # _______________________ CHECKING _______________________ # XYZ : sh = xyz.shape assert sh[1] in [2, 3] self._n_sources = sh[0] pos = xyz if sh[1] == 3 else np.c_[xyz, np.full((len(self), ), _z)] logger.info(' %i sources detected' % self._n_sources) # Radius min and max : assert all( [isinstance(k, (int, float)) for k in (radius_min, radius_max)]) radius_max = max(radius_min, radius_max) self._radius_min, self._radius_max = radius_min, radius_max self._mask_radius = mask_radius # Data : if data is None: data = np.ones((len(self), )) else: assert np.shape(data)[0] == len(self) self._data = vispy_array(data) # System : pos = pos if system == 'mni' else tal2mni(pos) self._xyz = vispy_array(pos) # Color : self._color = color # Edges : self._edge_color, self._edge_width = edge_color, edge_width # Mask : if mask is None: mask = [False] * len(self) self._mask = np.asarray(mask).ravel().astype(bool) assert len(self._mask) == len(self) self._mask_color = color2vb(mask_color) # Text : self._text_size = text_size self._text_color = text_color self._text_translate = text_translate # _______________________ MARKERS _______________________ self._sources = visuals.Markers(pos=self._xyz, name='Markers', edge_color=edge_color, edge_width=edge_width, symbol=symbol, parent=self._node) self._sources.set_gl_state('translucent', depth_test=True, cull_face=False) # _______________________ TEXT _______________________ tvisible = text is None self._text = [''] * len(self) if tvisible else text self._text = np.array(self._text) assert len(self._text) == len(self) self._sources_text = visuals.Text(self._text, pos=self._xyz, bold=text_bold, name='Text', color=color2vb(text_color), font_size=text_size, parent=self._node) self._sources_text.visible = not tvisible tr = vist.STTransform(translate=text_translate) self._sources_text.transform = tr # _______________________ UPDATE _______________________ # Radius / color : self.visible = visible self._update_radius() self.alpha = alpha self._update_color()
def set_data(self, data=None, axis=None, color=None, title=None, force_shape=None, plt_as='grid'): """Set data to the grid of signals. Parameters ---------- data : None Array of data. Could be 1-D, 2-D or 3-D. axis : int | None Time axis location. random : array_like/string/tuple | 'random' Use 'random' for random colors or a color name for uniform color. """ # ====================== CHECKING ====================== # Axis : axis = axis if isinstance(axis, int) else self._axis axis = len(self._sh) - 1 if axis == -1 else axis # Data : if isinstance(data, np.ndarray): # -------------- (n_rows, n_cols, n_time) -------------- if data.ndim == 1: # 1-D array data = data.reshape(1, 1, -1) g_size = (1, 1) elif data.ndim == 2: # 2-D array if axis == 0: # data need to be transposed data = np.swapaxes(data, 0, 1) axis = 1 g_size = (data.shape[0], 1) # (n_row, 1) data = data[np.newaxis, ...] elif data.ndim == 3: # 3-D array if axis != data.ndim - 1: # data need to be transposed data = np.swapaxes(data, axis, -1) axis = data.ndim - 1 g_size = (data.shape[0], data.shape[1]) # -------------- Signals index -------------- m = np.prod(list(data.shape)[0:-1]) sig_index = np.arange(m).reshape(*g_size) # -------------- Plot type -------------- if plt_as == 'row': force_shape = (1, g_size[0] * g_size[1]) elif plt_as == 'col': force_shape = (g_size[0] * g_size[1], 1) # -------------- Optimal 2-D -------------- self._data = data self._ori_shape = list(data.shape)[0:-1] if force_shape is None: n_rows, n_cols = ndsubplot(m) elif len(g_size) == 2: n_rows, n_cols = force_shape data = data.reshape(n_rows, n_cols, len(self)) sig_index = sig_index.reshape(n_rows, n_cols) g_size = (n_rows, n_cols) self._opt_shape = list(data.shape)[0:-1] self._sig_index = sig_index # -------------- (n_rows * n_cols, n_time) -------------- data = np.reshape(data, (m, len(self)), order='F') # -------------- Prepare -------------- # Force demean / detrend of _prep : self._prep.demean, self._prep.detrend = False, False data = self._prep._prepare_data(self._sf, data, 0) # Demean and normalize : kw = {'axis': -1, 'keepdims': True} dmax = np.abs(data).max(**kw) dmax[dmax == 0.] = 1. data -= data.mean(**kw) data /= dmax # data /= data.max() self._dbuffer.set_data(vispy_array(data)) self.g_size = g_size # ====================== INDEX ====================== n, m = len(self), np.prod(g_size) self._sig_index = self._sig_index.reshape(n_rows, n_cols) idg = np.c_[np.repeat(np.repeat(np.arange(n_cols), n_rows), n), np.repeat(np.tile(np.arange(n_rows), n_cols), n)[::-1], np.tile(np.arange(n), m)].astype(np.float32) self._ibuffer.set_data(vispy_array(idg)) # ====================== COLOR ====================== if color is not None: color_1d = color2vb(color) self.shared_program.frag['u_color'] = color_1d.ravel() # ====================== TITLES ====================== # Titles checking : if title is None or (len(title) != m): st, it = '({}, {})', product(range(n_rows), range(n_cols)) title = [st.format(i, k) for i, k in it] # Set text and font size : if not self._txt.text: self._txt.text = title # Get titles position : x_factor, y_factor = 1. / n_cols, 1. / n_rows r_x = np.linspace(-1. + x_factor, 1. - x_factor, n_cols) r_x = np.tile(r_x, n_rows) r_y = np.linspace(-1. + y_factor, 1. - y_factor, n_rows)[::-1] r_y += y_factor r_y = np.repeat(r_y, n_cols) pos = np.c_[r_x, r_y, np.full_like(r_x, -10.)] self._txt.pos = pos.astype(np.float32)