def __init__(self, **kwargs): """Init.""" # Create the main window : super(UiInit, self).__init__(None) self.setupUi(self) # Cameras : grid_rect = (0, 0, 1, 1) cb_rect = (-.05, -2, .8, 4.) cam_signal = viscam.PanZoomCamera() cam_grid = viscam.PanZoomCamera(rect=grid_rect) cam_cbar = viscam.PanZoomCamera(rect=cb_rect) # Canvas creation : cargs = {'size': (800, 600)} self._grid_canvas = VisbrainCanvas(axis=False, name='Grid', cargs=cargs, camera=cam_grid, **kwargs) self._signal_canvas = VisbrainCanvas(axis=True, name='Signal', cargs=cargs, add_cbar=True, camera=cam_signal, **kwargs) self._signal_canvas.wc_cbar.camera = cam_cbar # Add canvas to layout : self._GridLayout.addWidget(self._grid_canvas.canvas.native) self._SignalLayout.addWidget(self._signal_canvas.canvas.native) # Initialize shortcuts : GridShortcuts.__init__(self, self._grid_canvas.canvas) SignalShortcuts.__init__(self, self._signal_canvas.canvas)
def __init__(self, bgcolor='black', verbose=None, **kwargs): """Init.""" # ====================== PyQt creation ====================== _PyQtModule.__init__(self, verbose=verbose, to_describe='view.wc', icon='brain_icon.svg') self._userobj = {} self._gl_scale = 100. # fix appearance for small meshes self._camera = viscam.TurntableCamera(name='MainBrainCamera') # ====================== Canvas creation ====================== UiInit.__init__(self, bgcolor) # GUI creation + canvas PROFILER("Canvas creation") # ====================== App creation ====================== PROFILER("Visual elements", as_type='title') Visuals.__init__(self, self.view.wc, **kwargs) # ====================== Ui interactions ====================== UiElements.__init__(self) # GUI interactions PROFILER("Ui interactions") self._shpopup.set_shortcuts(self.sh) # shortcuts dict # ====================== Cameras ====================== # Main camera : self.view.wc.camera = self._camera self._vbNode.parent = self.view.wc.scene self.atlas.camera = self._camera self.roi.camera = self._camera self.atlas._csize = self.view.canvas.size self.atlas.rotate('top') self.atlas.camera.set_default_state() PROFILER("Cameras creation") # ====================== Colorbar ====================== camera = viscam.PanZoomCamera(rect=(-.2, -2.5, 1, 5)) BrainCbar.__init__(self, camera) PROFILER("Colorbar and panzoom creation") self.background_color(bgcolor) # ====================== Shortcuts ====================== BrainShortcuts.__init__(self, self.cbqt.cbviz._canvas) PROFILER("Set brain shortcuts") self._fcn_on_load() PROFILER("Functions on load")
def _cam_creation(self): """Create a set of cameras.""" # ------------------- Channels ------------------- self._chanCam = [] for k in range(len(self)): self._chanCam.append(FixedCam()) # viscam.PanZoomCamera() # ------------------- Spectrogram ------------------- self._speccam = FixedCam() # viscam.PanZoomCamera() self._specCanvas.set_camera(self._speccam) # ------------------- Hypnogram ------------------- self._hypcam = FixedCam() # viscam.PanZoomCamera() self._hypCanvas.set_camera(self._hypcam) # ------------------- Topoplot ------------------- self._topocam = viscam.PanZoomCamera() self._topoCanvas.set_camera(self._topocam) # ------------------- Time axis ------------------- self._timecam = FixedCam() self._TimeAxis.set_camera(self._timecam) # Keep all cams : self._allCams = (self._chanCam, self._speccam, self._hypcam, self._topocam, self._timecam)
def __init__(self, data, sf=1, **kwargs): """Init.""" # Be sure to have float arguments : if data.dtype != np.float32: data = data.astype(np.float32, copy=False) warn("Data should be an array of float number. Use " "data.astype(np.float32) before opening the interface.") # ====================== ui Arguments ====================== # Background color (for all of the canvas) : bgcolor = kwargs.get('ui_bgcolor', (.09, .09, .09)) nd_title = kwargs.get('nd_title', 'Nd-plot') nd_xlabel = kwargs.get('nd_xlabel', 'X axis') nd_ylabel = kwargs.get('nd_ylabel', 'Y axis') nd_grid = kwargs.get('nd_grid', False) nd_visible = kwargs.get('nd_visible', True) od_grid = kwargs.get('od_grid', True) od_visible = kwargs.get('od_visible', False) od_title = kwargs.get('od_title', '1d-plot') od_xlabel = kwargs.get('od_xlabel', 'X axis') od_ylabel = kwargs.get('od_ylabel', 'Y axis') # Default linewidth : self._ndlw = kwargs.get('nd_lw', 2.) self._1dlw = kwargs.get('od_lw', 2.) self._oridata = np.ascontiguousarray(data) self._sf = np.float32(sf) # print('ID 0: ', id(self._oridata)) # Savename, extension and croping region (usefull for the screenshot) : self._savename = kwargs.get('ui_savename', None) self._extension = kwargs.get('ui_extension', '.png') self._crop = kwargs.get('ui_region', None) if self._extension not in ['png', 'tiff']: self._extension = 'png' # ====================== App creation ====================== # Create the app and initialize all graphical elements : self._app = QtWidgets.QApplication(sys.argv) uiInit.__init__(self, bgcolor, nd_title, nd_xlabel, nd_ylabel, od_title, od_xlabel, od_ylabel) # ====================== Objects creation ====================== visuals.__init__(self, data, self._sf, **kwargs) # ====================== user & GUI interaction ====================== # User <-> GUI : uiElements.__init__(self) # ====================== Cameras ====================== # Nd-plot camera : ndcam = viscam.PanZoomCamera(rect=(-1, -1, 2, 2)) self._ndplt.mesh.set_camera(ndcam) self._ndCanvas.set_camera(ndcam) # 1d-plot camera : odcam = viscam.PanZoomCamera(rect=self._1dplt.mesh.rect) self._1dCanvas.set_camera(odcam) # Fixed colorbar camera : turntable = viscam.TurntableCamera(interactive=True, azimuth=0, elevation=90) self._cbCanvas.set_camera(turntable) self._cbCanvas.wc.camera.set_range(x=(-24, 24), y=(-0.5, 0.5), margin=0) # self._cbCanvas.wc.scene.children[0].parent = None # ====================== Visibility ====================== # Nd-panel : self._CanVisNd.setChecked(nd_visible) self._NdVizPanel.setVisible(nd_visible) self._ndGridTog.setChecked(nd_grid) self._ndCanvas.visible_axis(nd_grid) # 1d-panel : self._CanVis1d.setChecked(od_visible) self._1dVizPanel.setVisible(od_visible) self._1dGridTog.setChecked(od_grid) self._1dCanvas.visible_axis(od_grid) # Finally, update each canvas and tab selection : self._ndCanvas.canvas.update() self._1dCanvas.canvas.update() self._fcn_QuickTabSelec()
def __init__(self, *args, **kwargs): """Init.""" # ====================== ui Arguments ====================== # Background color (for the main and the colorbar canvas) : bgcolor = kwargs.get('ui_bgcolor', (0., 0., 0.)) # Savename, extension and croping region (usefull for the screenshot) : self._savename = kwargs.get('ui_savename', None) self._crop = kwargs.get('ui_region', None) self._autocrop = kwargs.get('ui_autocrop', True) self._uirez = kwargs.get('ui_resolution', 3000.) self._xyzRange = { 'turntable': { 'x': None, 'y': (-1200, 1200), 'z': None }, 'fly': { 'x': (-120, 120), 'y': (-100, 200), 'z': (-90, 90) }, } self._cbarexport = True self._userobj = {} # ====================== App creation ====================== # Create the app and initialize all graphical elements : self._app = QtWidgets.QApplication(sys.argv) uiInit.__init__(self, bgcolor) # Set icon : # pathfile = sys.modules[__name__].__file__ # path = os.path.join(*['brain', 'interface', 'gui', 'vbicon.png']) # self.setWindowIcon(QtGui.QIcon(os.path.join(pathfile.split( # '/vbrain')[0], path))) # ====================== Objects creation ====================== camera = viscam.TurntableCamera(azimuth=0, distance=1000, name='turntable') base.__init__(self, self.view.wc, self._csGrid, self.progressBar, **kwargs) # ====================== UI to visbrain ====================== # Link UI and visbrain function : uiElements.__init__(self) self._shpopup.set_shortcuts(self.sh) # ====================== Cameras ====================== # Main camera : self.view.wc.camera = camera self.atlas.mesh.set_camera(self.view.wc.camera) self.pic.set_camera(self.view.wc.camera) self._vbNode.parent = self.view.wc.scene self._rotate(fixed='axial') self.view.wc.camera.set_default_state() # ====================== Colorbar ====================== # Fixed colorbar camera : camera = viscam.PanZoomCamera(rect=(-.2, -2.5, 1, 5)) # Cbar creation : BrainCbar.__init__(self, camera) # Add shortcuts on it : BrainShortcuts.__init__(self, self.cbqt.cbviz._canvas) self._fcn_on_load()
def __init__(self, bgcolor='black', verbose=None, **kwargs): """Init.""" # ====================== PyQt creation ====================== _PyQtModule.__init__(self, verbose=verbose, to_describe='view.wc', icon='brain_icon.svg') self._userobj = {} self._gl_scale = 100. # fix appearance for small meshes self._camera = viscam.TurntableCamera(name='MainEngramCamera') # ====================== Canvas creation ====================== UiInit.__init__(self, bgcolor) # GUI creation + canvas PROFILER("Canvas creation") # ====================== App creation ====================== PROFILER("Visual elements", as_type='title') Visuals.__init__(self, self.view.wc, **kwargs) # ====================== Metadata Storage ====================== if 'metadata' in kwargs.keys(): self.metadata = kwargs['metadata'] else: self.metadata = {} # ====================== Rotation Kinetics ====================== if 'rotation' in kwargs.keys(): self.rotation = kwargs['rotation'] else: self.rotation = 0 # ====================== Carousel Options ====================== self.ease_xyz = False # Between carousel options self.ignore_streams = True if 'carousel_metadata' in kwargs.keys(): self.carousel_metadata = kwargs['carousel_metadata'] else: self.carousel_metadata = {} # Carousel Display Method if 'carousel_display_method' in kwargs.keys(): self._carousel_display_method = kwargs['carousel_display_method'] else: self._carousel_display_method = 'text' # Carousel Options if 'hierarchy_lookup' in self.carousel_metadata: options = np.asarray(self.carousel_metadata['hierarchy_lookup']) self._carousel_options_inds = [np.asarray([0])] for dims in (range(len(options))): _combs = itertools.combinations(range(len(options)), dims + 1) _combs = list(_combs) for ll, comb in enumerate(_combs): comb = list(comb) if len(comb) > 1: if ll == 0: combs = [np.array(list(comb)) + 1] else: combs.append(np.array(list(comb)) + 1) else: if ll == 0: combs = [np.array([comb[0] + 1])] else: combs.append(np.array([list(comb)[0] + 1])) self._carousel_options_inds.append(combs) self._carousel_options_inds[0] = [self._carousel_options_inds[0]] options = list(options) new_options = [np.asarray(['None'])] for ii in np.arange(len(options)) + 1: new_options.append(options[ii - 1]) self._carousel_options = np.asarray(new_options) else: self._carousel_options_inds = [np.asarray([])] self._carousel_options = np.asarray(['None']) # Carousel Choice if 'carousel_choice' in kwargs.keys(): self._carousel_choice = kwargs['carousel_choice'] self._prev_carousel_choice = kwargs['carousel_choice'] else: self._carousel_choice = [0, 0] self._prev_carousel_choice = [0, 0] # Display Method self.update_carousel() # Toggle Options self._userdistance = [0] self._uservelocity = 0 # ====================== Control Device ====================== if 'control_method' in kwargs.keys(): self.control_method = kwargs['control_method'] else: self.control_method = 'keyboard' if self.control_method is 'IR_Distance': self.ser = serial.Serial('/dev/cu.usbmodem144101') self.use_distance = True else: self.ser = None self.prev_rotation = 0 def arduino_control(method='none'): if self.ser is not None: # Check Arduino inputs try: b = self.ser.readline() # read a byte string string_n = b.decode() # decode byte string into Unicode message = string_n.rstrip() # remove \n and \r messages = message.split('|') distance = messages[0] command = messages[1] except: distance = 500 command = 'NONE' if method == 'IR_Distance': if self.use_distance: THRESHOLD = 20 # cm HEIGHT = 0 flt = float(distance) self._userdistance = np.append( self._userdistance, flt) # convert string to float # Distance Selections if flt < HEIGHT + THRESHOLD: self._carousel_choice[0] = 0 if flt >= HEIGHT + (THRESHOLD) and flt < HEIGHT + ( 2 * THRESHOLD): self._carousel_choice[0] = 1 if flt >= HEIGHT + (2 * THRESHOLD): self._carousel_choice[0] = 3 # Remote Option if command != 'NONE': print(command) if command == 'POWER': sys.exit() if command == 'ST/REPT' and not self.use_distance: if self._carousel_choice[0] < ( len(self._carousel_options_inds) - 1): if self._carousel_choice[0] == 1: self._carousel_choice[0] = 3 else: self._carousel_choice[0] += 1 else: self._carousel_choice[0] = 0 self._carousel_choice[1] = 0 if command == 'EQ': if self.use_distance: self.use_distance = False else: self.use_distance = True if command == 'FUNC/STOP': if self._carousel_choice[1] < ( len(self._carousel_options_inds[ self._carousel_choice[0]]) - 1): self._carousel_choice[1] += 1 else: self._carousel_choice[1] = 0 if command == 'VOL+' or command == 'VOL-': if command == 'VOL+': self.view.wc.camera.distance -= 5000 else: self.view.wc.camera.distance += 5000 if command == 'UP': self.rotation += .25 elif command == 'DOWN': self.rotation -= .25 elif command == 'FAST BACK': if np.sign(self.timescaling) == 1: self.timescaling = -0.1 else: self.timescaling -= 0.10 elif command == 'FAST FORWARD': if np.sign(self.timescaling) == -1: self.timescaling = 0.1 else: self.timescaling += 0.10 elif command == 'PAUSE': if self.timescaling == 0: print('PLAY') self.timescaling = self.default_timescaling self.rotation = self.prev_rotation self.displayed_time = self.time_cache self.time_cache = None else: print('PAUSE') self.prev_rotation = self.rotation self.time_cache = self.displayed_time self.rotation = 0 self.timescaling = 0 self.paused = True if self.paused == True: if command == 'FAST FORWARD': self.time_cache += .02 elif command == 'FAST BACK': self.time_cache -= .02 # Remote Numbers if command == '0': self.view.wc.camera.azimuth = 0 self.view.wc.camera.elevation = 90 elif command == '1': self.view.wc.camera.azimuth = 0 self.view.wc.camera.elevation = -90 elif command == '2': self.view.wc.camera.azimuth = 90 self.view.wc.camera.elevation = 0 elif command == '3': self.view.wc.camera.azimuth = -90 self.view.wc.camera.elevation = 0 elif command == '4': self.view.wc.camera.azimuth = 0 self.view.wc.camera.elevation = 0 elif command == '5': self.view.wc.camera.azimuth = 180 self.view.wc.camera.elevation = 0 elif command == '6': self.view.wc.camera.azimuth = 45 self.view.wc.camera.elevation = 30 elif command == '7': self.view.wc.camera.azimuth = 45 self.view.wc.camera.elevation = -30 elif command == '8': self.view.wc.camera.azimuth = -45 self.view.wc.camera.elevation = 30 elif command == '9': self.view.wc.camera.azimuth = -45 self.view.wc.camera.elevation = -30 # ====================== Timer Creation ====================== self.loop_shift = 0 self.start_offset = 0 self.default_timescaling = 1 / 4 self.timescaling = self.default_timescaling self.time_cache = None self.displayed_time = 0 self.paused = False def on_timer(*args, **kwargs): # Change Source Radii and Connectivity Values if self.time_cache is None: time_inc = (args[0].dt * self.timescaling) self.displayed_time = self.loop_shift + ( self.displayed_time + time_inc) % ( (np.shape(self.sources[0].data)[1] / self.metadata['fs']) - self.loop_shift) else: self.displayed_time = self.loop_shift + (self.time_cache) % ( (np.shape(self.sources[0].data)[1] / self.metadata['fs']) - self.loop_shift) timepoint = int(self.displayed_time * self.metadata['fs']) for source in self.sources: source._update_radius(timepoint=timepoint) for connect in self.connect: connect._update_time(timepoint=timepoint) arduino_control(self.control_method) self.update_target_positions() self.update_carousel() self.update_visibility() self._prev_carousel_choice = self._carousel_choice if len(self._userdistance) > 2: self._userdistance = [-1] # Update Time Display t_str = str(round(self.displayed_time, 3)) + ' s' if not hasattr(self, '_time'): self._time = Text(t_str, parent=self.view.canvas.scene, color='white') else: self._time.text = t_str self._time.anchors = ('right', 'bottom') self._time.font_size = self.view.canvas.size[1] // 200 self._time.pos = (49) * self.view.canvas.size[0] // 50, ( 19) * self.view.canvas.size[1] // 20 self._time.update() # Ease to New Positions if Triggered if self.ease_xyz: self.ease_xyz = False for source in self.sources: out = source._ease_to_target_position() if out: self.ease_xyz = True for connect in self.connect: out = connect._ease_to_target_position() if out: self.ease_xyz = True # if hasattr(self.view.wc, 'camera'): # diff_az = self.target_azimuth - self.view.wc.camera.azimuth # diff_el = self.target_elevation - self.view.wc.camera.elevation # # Ease scene rotation # if (diff_az != 0.) | (diff_el != 0.): # # Flip target and current (since I cannot find a way to update the shortcuts directly) # if self.first_ease: # temp_ = self.target_elevation # self.target_elevation = self.view.wc.camera.elevation # self.view.wc.camera.elevation = temp_ # temp_ = self.target_azimuth # self.target_azimuth = self.view.wc.camera.azimuth # self.view.wc.camera.azimuth = temp_ # self.first_ease = False # if (abs(diff_az) > 0.001) | (abs(diff_el) > 0.001): # self.view.wc.camera.azimuth += .1*(diff_az) # self.view.wc.camera.elevation += .1*(diff_el) # print('updating rotation') # if self.first_ease: # self.first_ease = False # else: # self.view.wc.camera.azimuth = self.target_azimuth # self.view.wc.camera.elevation = self.target_elevation # self.first_ease = True #Iterate scene rotation # else: self.view.wc.camera.azimuth += self.rotation self.view.wc.canvas.update() kw = dict(connect=on_timer, app=CONFIG['VISPY_APP'], interval='auto', iterations=-1) self._app_timer = app.Timer(**kw) self._app_timer.start() # ====================== Ui interactions ====================== UiElements.__init__(self) # GUI interactions PROFILER("Ui interactions") self._shpopup.set_shortcuts(self.sh) # shortcuts dict # ====================== Cameras ====================== # Main camera : self.view.wc.camera = self._camera self._vbNode.parent = self.view.wc.scene self.atlas.camera = self._camera self.roi.camera = self._camera self.atlas._csize = self.view.canvas.size self.atlas.rotate('top') self.atlas.camera.set_default_state() PROFILER("Cameras creation") # Set easing self.target_azimuth = self.view.wc.camera.azimuth self.target_elevation = self.view.wc.camera.elevation self.first_ease = True # ====================== Colorbar ====================== camera = viscam.PanZoomCamera(rect=(-.2, -2.5, 1, 5)) EngramCbar.__init__(self, camera) PROFILER("Colorbar and panzoom creation") self.background_color(bgcolor) # ====================== Shortcuts ====================== EngramShortcuts.__init__(self, self.cbqt.cbviz._canvas) PROFILER("Set engram shortcuts") self._fcn_on_load() PROFILER("Functions on load")
def add_topoplot(self, name, data, xyz=None, channels=None, system='cartesian', unit='degree', title=None, title_color='black', title_size=5., line_color='black', line_width=2., chan_size=2., chan_offset=(0., 0., 0.), chan_mark_color='white', chan_mark_symbol='disc', chan_txt_color='black', bgcolor='white', cbar=True, cblabel=None, cb_txt_size=4., levels=None, level_colors='white', cmap='viridis', clim=None, vmin=None, under='gray', vmax=None, over='red', row=0, col=0, row_span=1, col_span=1, margin=.05): """Add a subplot embedded in a subplot. For now, there's two for using coordinates to define the subplot : * Using the xyz input (must either be in cartesian or spherical coordinate system) * Using the channel input. The Topo class contains a list of existing channel names and will try to identify those in the channels variable. Parameters ---------- name : string Name of the topographic plot. data : array_like Array of data of shape (n_channels,). xyz : array_like | None Array of source's coordinates. channels : list | None List of channel names. system : {'cartesian', 'spherical'} Coordinate system. unit : {'degree', 'rad'} If system is 'spherical', specify if angles are in degrees or radians. title : string | None Title of the topoplot. title_color : array_like/string | 'black' Color for the title. title_size : float | 20. Size of the title. line_color : array_like/string | 'black' Color of lines for the head, nose and eras. line_width : float | 4. Line width for the head, nose and eras. chan_size : float | 12. Size of channel names text. chan_mark_color : array_like/string | 'white' Color of channel markers. chan_mark_symbol : string | 'disc' Symbol to use for markers. Use disc, arrow, ring, clobber, square, diamond, vbar, hbar, cross, tailed_arrow, x, triangle_up, triangle_down, and star. chan_txt_color : array_like/string | 'black' Color of channel names. bgcolor : array_like/string | 'white' Background color. cbar : bool | True Attach a colorbar to the topoplot. cblabel : string | None Colorbar label. cb_txt_size : float | 16. Text size for the colorbar limits and label. levels : array_like/int | None The levels at which the isocurve is constructed. level_colors : string/array_like | 'white' The color to use when drawing the line. If a list is given, it must be of shape (Nlev), if an array is given, it must be of shape (Nlev, ...). and provide one color per level (rgba, colorname). By default, all levels are whites. cmap : string | None Matplotlib colormap (like 'viridis', 'inferno'...). clim : tuple/list | None Colorbar limit. Every values under / over clim will clip. vmin : float | None Every values under vmin will have the color defined using the under parameter. vmax : float | None Every values over vmin will have the color defined using the over parameter. under : tuple/string | None Matplotlib color under vmin. over : tuple/string | None Matplotlib color over vmax. row : int | 0 The row in which to add the widget (0 is the topmost row) col : int | 0 The column in which to add the widget (0 is the leftmost column) row_span : int | 1 The number of rows to be occupied by the topoplot. col_span : int | 1 The number of columns to be occupied by the topoplot. margin : float | .05 Margin percentage between the topoplot and the edge of the subplot. """ # Check if name is avaible : self._check_name_for(name, 'topoplot') # Create the topoplot and set the data : topo = TopoMesh(xyz, channels, system, unit, title, title_color, title_size, line_color, line_width, chan_size, chan_offset, chan_mark_color, chan_mark_symbol, chan_txt_color, bgcolor, cbar, cb_txt_size, margin) topo.set_data(data, levels, level_colors, cmap, clim, vmin, under, vmax, over, cblabel) self[name] = topo # Create a PanZoom camera : cam = viscam.PanZoomCamera(aspect=1., rect=topo.rect) cam.set_default_state() # Create a subplot and add the camera : self._topoGrid[name] = self._grid.add_view(row, col, row_span, col_span, bgcolor=bgcolor, camera=cam) # Add the topoplot to the subplot : self._topoGrid[name].add(self[name].node)
def add_shared_colorbar(self, name, cmap='viridis', clim=(0, 1), vmin=None, vmax=None, under='gray', over='red', cblabel='', cbtxtsz=5., cbtxtsh=2.3, txtcolor='black', txtsz=3., txtsh=1.2, width=.17, border=True, bw=2., limtxt=True, bgcolor='white', ndigits=2, row=0, col=0, row_span=1, col_span=1, rect=(-1.2, -1.2, 2.4, 2.4)): """Add a shared colorbar across subplots. Parameters ---------- cmap : string | None Matplotlib colormap (like 'viridis', 'inferno'...). clim : tuple/list | None Colorbar limit. Every values under / over clim will clip. vmin : float | None Every values under vmin will have the color defined using the under parameter. vmax : float | None Every values over vmin will have the color defined using the over parameter. under : tuple/string | None Matplotlib color under vmin. over : tuple/string | None Matplotlib color over vmax. cblabel : string | '' Colorbar label. cbtxtsz : float | 5.. Text size of the colorbar label. cbtxtsh : float | 2.3 Shift for the colorbar label. txtcolor : string | 'white' Text color. txtsz : float | 3. Text size for clim/vmin/vmax text. txtsh : float | 1.2 Shift for clim/vmin/vmax text. border : bool | True Display colorbar borders. bw : float | 2. Border width. limtxt : bool | True Display vmin/vmax text. bgcolor : tuple/string | (0., 0., 0.) Background color of the colorbar canvas. ndigits : int | 2 Number of digits for the text. row : int | 0 The row in which to add the widget (0 is the topmost row) col : int | 0 The column in which to add the widget (0 is the leftmost column) row_span : int | 1 The number of rows to be occupied by the topoplot. col_span : int | 1 The number of columns to be occupied by the topoplot. rect : tuple | (-1.2, -1.2, 2.4, 2.4) The 2-D area on the screen to display. The rect input describe (x_start, y_start, x_width, y_height). This variable can be used to translate or scale. """ # Check if name is avaible : self._check_name_for(name, 'colorbar') # Create a PanZoom camera : cam = viscam.PanZoomCamera(rect=rect) cam.set_default_state() # Create a subplot and add the camera : self._topoGrid[name] = self._grid.add_view(row, col, row_span, col_span, bgcolor=bgcolor, camera=cam) # Get if vmin and vmax exist : isvmin, isvmax = vmin is not None, vmax is not None # Create a colorbar object : parent = Node(name=name) cbar = CbarVisual(cmap=cmap, clim=clim, vmin=vmin, isvmin=isvmin, vmax=vmax, isvmax=isvmax, under=under, over=over, cblabel=cblabel, cbtxtsz=cbtxtsz, cbtxtsh=cbtxtsh, txtcolor=txtcolor, txtsz=txtsz, txtsh=txtsh, width=width, border=border, bw=bw, limtxt=limtxt, bgcolor=bgcolor, ndigits=ndigits, parent=parent) self[name] = cbar # Add the colorbar to the subplot : self._topoGrid[name].add(parent)
def __init__(self, data, axis=-1, time=None, sf=1., enable_grid=True, form='line', color='black', line_lw=1., line_smooth=False, marker_symbol='disc', marker_size=10., hist_nbins=10, tf_norm=0, tf_baseline=None, tf_interp='gaussian', tf_cmap='viridis', tf_av_window=None, tf_av_overlap=0., tf_clim=None, psd_nperseg=256, psd_noverlap=128, display_grid=True, display_signal=True, annotations=None, annot_txtsz=18., annot_marksz=16., annot_color='#2ecc71', grid_lw=1., grid_smooth=False, grid_titles=None, grid_font_size=10., grid_color='random', grid_shape=None, grid_titles_color='black', verbose=None, **kwargs): """Init.""" dscb = ['_grid_canvas.canvas.scene', '_signal_canvas.canvas.scene'] PyQtModule.__init__(self, verbose=verbose, to_describe=dscb) self._enable_grid = enable_grid self._previous_form = form display_grid = bool(display_grid * self._enable_grid) # ==================== APP CREATION ==================== UiInit.__init__(self, **kwargs) # ==================== DATA CHECKING ==================== if isinstance(data, (list, tuple)): data = np.asarray(data) if not isinstance(data, np.ndarray) or (data.ndim > 3): raise TypeError("data must be an NumPy array with less than three " "dimensions.") if data.ndim == 1 or not self._enable_grid: # disable grid display_grid = self._enable_grid = False self.actionGrid.setEnabled(False) toggle_enable_tab(self.QuickSettings, 'Grid', False) self._data = data.astype(np.float32, copy=False) self._axis = axis # ==================== VISUALS ==================== grid_parent = self._grid_canvas.wc.scene signal_parent = self._signal_canvas.wc.scene Visuals.__init__(self, data, time, sf, axis, grid_titles, grid_color, grid_shape, grid_parent, signal_parent) # ==================== CAMERA ==================== grid_rect = (0, 0, 1, 1) sig_rect = self._signal.rect cb_rect = (-.05, -2, .8, 4.) self._grid_canvas.camera = viscam.PanZoomCamera(rect=grid_rect) self._signal_canvas.camera = viscam.PanZoomCamera(rect=sig_rect) self._signal_canvas.wc_cbar.camera = viscam.PanZoomCamera(rect=cb_rect) # ==================== UI INIT ==================== self._fix_elements_limits() # ------------- Signal ------------- # Signal and axis color : self._sig_color.setText(str(color2tuple(color, astype=float))) ax_color = kwargs.get('axis_color', color2vb('black')) self._axis_color.setText(str(ax_color)) # Title, labels and ticks : self._sig_title.setText(kwargs.get('title', '')) self._sig_title_fz.setValue(kwargs.get('title_font_size', 15.)) self._sig_xlab.setText(kwargs.get('xlabel', '')) self._sig_ylab.setText(kwargs.get('ylabel', '')) self._sig_lab_fz.setValue(kwargs.get('axis_font_size', 12.)) self._sig_ticks_fz.setValue(kwargs.get('tick_font_size', 8.)) # Signal properties : safely_set_cbox(self._sig_form, form) self._sig_lw.setValue(line_lw) # line self._sig_smooth.setChecked(line_smooth) # line self._sig_nbins.setValue(hist_nbins) # histogram self._sig_size.setValue(marker_size) # marker safely_set_cbox(self._sig_symbol, marker_symbol) # marker self._sig_norm.setCurrentIndex(tf_norm) safely_set_cbox(self._sig_tf_interp, tf_interp) self._sig_tf_rev.setChecked(bool(tf_cmap.find('_r') + 1)) self._sig_tf_cmap.addItems(mpl_cmap()) safely_set_cbox(self._sig_tf_cmap, tf_cmap.replace('_r', '')) if (tf_baseline is not None) and (len(tf_baseline) == 2): self._sig_baseline.setChecked(True) self._sig_base_start.setValue(tf_baseline[0]) self._sig_base_end.setValue(tf_baseline[1]) if isinstance(tf_av_window, int): self._sig_averaging.setChecked(True) self._sig_av_win.setValue(tf_av_window) self._sig_av_overlap.setValue(tf_av_overlap) if (tf_clim is not None) and (len(tf_clim) == 2): self._sig_tf_clim.setChecked(True) self._sig_climin.setValue(tf_clim[0]) self._sig_climax.setValue(tf_clim[1]) self._sig_nperseg.setValue(psd_nperseg) self._sig_noverlap.setValue(psd_noverlap) # ------------- Grid ------------- if hasattr(self, '_grid'): n_rows, n_cols = self._grid.g_size self._grid_nrows.setValue(n_rows) self._grid_nrows.setMaximum(np.prod(self._grid.g_size)) self._grid_ncols.setValue(n_cols) self._grid_ncols.setMaximum(np.prod(self._grid.g_size)) gt_st = str(color2tuple(grid_titles_color, astype=float)) self._grid_titles_fz.setValue(grid_font_size) self._grid_titles_color.setText(gt_st) self._grid_lw.setValue(grid_lw) # ------------- Cbar ------------- self._signal_canvas.cbar.txtcolor = ax_color self._signal_canvas.cbar.border = False self._signal_canvas.cbar.cbtxtsz = 15. self._signal_canvas.cbar.txtsz = 12. # ------------- Settings ------------- bgcolor = kwargs.get('bgcolor', 'white') self._set_bgcolor.setText(str(color2tuple(bgcolor, astype=float))) self._grid_smooth.setChecked(grid_smooth) # ------------- Annotations ------------- self._annot_txtsz.setValue(annot_txtsz) self._annot_marksz.setValue(annot_marksz) self._annot_color.setText(str(color2tuple(annot_color, astype=float))) # ------------- Menu ------------- self.actionGrid.setChecked(display_grid) self.actionSignal.setChecked(display_signal) self._fcn_on_creation() # ==================== USER <-> GUI ==================== UiElements.__init__(self, **kwargs) # ==================== SHORTCUTS ==================== self._shpopup.set_shortcuts(self._sh_grid + self._sh_sig) # ------------- Annotations ------------- if annotations is not None: assert os.path.isfile(annotations) self._fcn_load_annotations(filename=annotations)
def __init__(self, bgcolor='black', verbose=None, **kwargs): """Init.""" # ====================== PyQt creation ====================== _PyQtModule.__init__(self, verbose=verbose, to_describe='view.wc', icon='brain_icon.svg') self._userobj = {} self._gl_scale = 100. # fix appearance for small meshes self._camera = viscam.TurntableCamera(name='MainEngramCamera') # ====================== Canvas creation ====================== UiInit.__init__(self, bgcolor) # GUI creation + canvas PROFILER("Canvas creation") # ====================== App creation ====================== PROFILER("Visual elements", as_type='title') Visuals.__init__(self, self.view.wc, **kwargs) # ====================== Metadata Storage ====================== if 'metadata' in kwargs.keys(): self.metadata = kwargs['metadata'] else: self.metadata = {} # ====================== Rotation Kinetics ====================== if 'rotation' in kwargs.keys(): self.rotation = kwargs['rotation'] else: self.rotation = 0 # ====================== Carousel Options ====================== if 'carousel_metadata' in kwargs.keys(): self.carousel_metadata = kwargs['carousel_metadata'] else: self.carousel_metadata = {} # Carousel Display Method if 'carousel_display_method' in kwargs.keys(): self._carousel_display_method = kwargs['carousel_display_method'] else: self._carousel_display_method = 'text' # Carousel Options if 'hierarchy_lookup' in self.carousel_metadata: options = np.asarray(self.carousel_metadata['hierarchy_lookup']) self._carousel_options_inds = [np.asarray([0])] for dims in (range(len(options))): _combs = itertools.combinations(range(len(options)), dims + 1) _combs = list(_combs) for ll, comb in enumerate(_combs): comb = list(comb) if len(comb) > 1: if ll == 0: combs = [np.array(list(comb)) + 1] else: combs.append(np.array(list(comb)) + 1) else: if ll == 0: combs = [np.array([comb[0] + 1])] else: combs.append(np.array([list(comb)[0] + 1])) self._carousel_options_inds.append(combs) self._carousel_options_inds[0] = [self._carousel_options_inds[0]] options = list(options) new_options = [np.asarray(['None'])] for ii in np.arange(len(options)) + 1: new_options.append(options[ii - 1]) self._carousel_options = np.asarray(new_options) else: self._carousel_options_inds = [np.asarray([])] self._carousel_options = np.asarray(['None']) # Carousel Choice if 'carousel_choice' in kwargs.keys(): self._carousel_choice = kwargs['carousel_choice'] self._prev_carousel_choice = kwargs['carousel_choice'] else: self._carousel_choice = [0, 0] self._prev_carousel_choice = [0, 0] # Display Method self.update_carousel() # ====================== Timer Creation ====================== def on_timer(*args, **kwargs): if hasattr(self.view.wc, 'camera'): self.view.wc.camera.azimuth += self.rotation self.view.wc.canvas.update() TIMESCALING = 1 / 1 SHIFT = 0 t = SHIFT + (SHIFT + (args[0].elapsed * TIMESCALING)) % ( (np.shape(self.sources[0].data)[1] / self.metadata['fs']) - SHIFT) timepoint = int(t * self.metadata['fs']) for source in self.sources: source._update_radius(timepoint=timepoint) for connect in self.connect: connect._update_time(timepoint=timepoint) t_str = str(round(t, 3)) + ' s' if not hasattr(self, '_time'): self._time = Text(t_str, parent=self.view.canvas.scene, color='white') else: self._time.text = t_str self._time.anchors = ('right', 'bottom') self._time.font_size = self.view.canvas.size[1] // 200 self._time.pos = (49) * self.view.canvas.size[0] // 50, ( 19) * self.view.canvas.size[1] // 20 self._time.update() kw = dict(connect=on_timer, app=CONFIG['VISPY_APP'], interval='auto', iterations=-1) self._app_timer = app.Timer(**kw) self._app_timer.start() # ====================== Ui interactions ====================== UiElements.__init__(self) # GUI interactions PROFILER("Ui interactions") self._shpopup.set_shortcuts(self.sh) # shortcuts dict # ====================== Cameras ====================== # Main camera : self.view.wc.camera = self._camera self._vbNode.parent = self.view.wc.scene self.atlas.camera = self._camera self.roi.camera = self._camera self.atlas._csize = self.view.canvas.size self.atlas.rotate('top') self.atlas.camera.set_default_state() PROFILER("Cameras creation") # ====================== Colorbar ====================== camera = viscam.PanZoomCamera(rect=(-.2, -2.5, 1, 5)) EngramCbar.__init__(self, camera) PROFILER("Colorbar and panzoom creation") self.background_color(bgcolor) # ====================== Shortcuts ====================== EngramShortcuts.__init__(self, self.cbqt.cbviz._canvas) PROFILER("Set engram shortcuts") self._fcn_on_load() PROFILER("Functions on load")