def __init__(self, parent=None, parent_sp=None, visible=True, cmap='gray'): """Init.""" CrossSectionsSplit.__init__(self, parent_sp) self._visible_cs = visible self._cmap_cs = cmap ####################################################################### # TRANFORMATIONS ####################################################################### # Translations : self._tr_coron = vist.STTransform() self._tr_sagit = vist.STTransform() self._tr_axial = vist.STTransform() # Rotations : rot_m90x = vist.MatrixTransform(rotate(-90, [1, 0, 0])) rot_180x = vist.MatrixTransform(rotate(180, [1, 0, 0])) rot_90y = vist.MatrixTransform(rotate(90, [0, 1, 0])) rot_m90y = vist.MatrixTransform(rotate(-90, [0, 1, 0])) rot_m180y = vist.MatrixTransform(rotate(-180, [0, 1, 0])) rot_90z = vist.MatrixTransform(rotate(90, [0, 0, 1])) # Tranformations : tf_sagit = [self._tr_sagit, rot_90z, rot_m90y, rot_m90x] tf_coron = [self._tr_coron, rot_90z, rot_180x, rot_90y] tf_axial = [self._tr_axial, rot_m180y, rot_90z] ####################################################################### # ELEMENTS ####################################################################### # Create a root node : self._node_cs = scene.Node(name='Cross-Sections') self._node_cs.parent = parent self._node_cs.visible = visible # Axial : self.axial = ImageSection(parent=self._node_cs, name='Axial') self.axial.transform = vist.ChainTransform(tf_axial) # Coronal : self.coron = ImageSection(parent=self._node_cs, name='Coronal') self.coron.transform = vist.ChainTransform(tf_coron) # Sagittal : self.sagit = ImageSection(parent=self._node_cs, name='Sagittal') self.sagit.transform = vist.ChainTransform(tf_sagit) # Set GL state : kwargs = { 'depth_test': True, 'cull_face': False, 'blend': False, 'blend_func': ('src_alpha', 'one_minus_src_alpha') } self.sagit.set_gl_state('translucent', **kwargs) self.coron.set_gl_state('translucent', **kwargs) self.axial.set_gl_state('translucent', **kwargs)
def __init__(self, name='indicator', alpha=.3, visible=True, parent=None): # Create a vispy image object : image = color2vb('gray', alpha=alpha)[np.newaxis, ...] self.mesh = scene.visuals.Image(data=image, name=name, parent=parent) self.mesh.transform = vist.STTransform() self.mesh.visible = visible
def __init__( self, hidden=False): # hidden=true useful for speed when creating video self.canvas = scene.SceneCanvas(keys='interactive', size=(1900, 1145), show=not hidden, config=dict(samples=4), resizable=True, always_on_top=True, bgcolor='white', vsync=True) # Set up a viewbox to display the cube with interactive arcball self.view = self.canvas.central_widget.add_view() self.view.bgcolor = '#efefef' self.view.camera = TurntableCamera(fov=60.0, elevation=30.0, azimuth=280.0) # add a colored 3D axis for orientation axis = scene.visuals.XYZAxis(parent=self.view.scene) self.cfs = [] self.spheres = [] self.crumbs = [] self.markers = scene.visuals.Markers(parent=self.view.scene) self.markers.transform = transforms.STTransform() self.obstacles = []
def set_data(self, tox=None, width=None, time=None, unit='seconds', markers=None): """Move the main square.""" # Get factor according to unit : if unit == 'seconds': fact = 1. elif unit == 'minutes': fact = 60. elif unit == 'hours': fact = 3660. # Move the square if (tox, width, time) != (None, None, None): self.mesh.transform = vist.STTransform(translate=tox / fact, scale=width / fact) # Update camera : self.wc.camera.rect = (0, 0, (time.max() - time.min()) / fact, 1) # Set markers : if markers is not None: if markers.size: pos = np.zeros((len(markers), 3), dtype=np.float32) pos[:, 0] = markers / fact pos[:, 1] = .5 pos[:, 2] = -10 else: pos = np.full((1, 3), -10, dtype=np.float32) self.markers.set_data(pos=pos, symbol='triangle_down', size=20., face_color='#42ab46', edge_width=0.)
def _rescale(self): height, width = self._data.shape[:2] vscale = -2. / height hscale = 2. / width zdepth = -0.01 * self._order transform = transforms.STTransform(scale=(hscale, vscale), translate=(-1, 1, zdepth)) self.visual.transform = transform
def test_st_mapping(): p1 = [[5., 7.], [23., 8.]] p2 = [[-1.3, -1.4], [1.1, 1.2]] t = tr.STTransform() t.set_mapping(p1, p2) assert np.allclose(t.map(p1)[:, :len(p2)], p2)
def __init__(self, scale, coo): self.obj = scene.visuals.Box(width=1, height=1, edge_color='black') self.obj.transform = transforms.STTransform(translate=(0., 0., 0.), scale=(scale, scale, scale)) self.coo = coo
def __init__(self): app.Canvas.__init__(self, keys='interactive') self.size = (800, 800) global pos self.visuals = [] polygon = visuals.PolygonVisual(pos=pos, color=(0.8, .2, 0, 1), border_color=(1, 1, 1, 1)) polygon.transform = transforms.STTransform(scale=(200, 200), translate=(600, 600)) self.visuals.append(polygon) ellipse = visuals.EllipseVisual(pos=(0, 0, 0), radius=(100, 100), color=(0.2, 0.2, 0.8, 1), border_color=(1, 1, 1, 1), start_angle=180., span_angle=150.) ellipse.transform = transforms.STTransform(scale=(0.9, 1.5), translate=(200, 200)) self.visuals.append(ellipse) rect = visuals.RectangleVisual(pos=(600, 200, 0), height=200., width=300., radius=[30., 30., 0., 0.], color=(0.5, 0.5, 0.2, 1), border_color='white') rect.transform = transforms.NullTransform() self.visuals.append(rect) rpolygon = visuals.RegularPolygonVisual(pos=(200., 600., 0), radius=160, color=(0.2, 0.8, 0.2, 1), border_color=(1, 1, 1, 1), sides=6) rpolygon.transform = transforms.NullTransform() self.visuals.append(rpolygon) for v in self.visuals: v.tr_sys = transforms.TransformSystem(self) v.tr_sys.visual_to_document = v.transform self.show() self._timer = app.Timer('auto', connect=self.on_timer, start=True)
def __init__(self): app.Canvas.__init__(self, keys='interactive', size=(800, 800)) global pos self.visuals = [] polygon = visuals.PolygonVisual(pos=pos, color=(0.8, .2, 0, 1), border_color=(1, 1, 1, 1), border_width=3) polygon.transform = transforms.STTransform(scale=(200, 200), translate=(600, 600)) self.visuals.append(polygon) ellipse = visuals.EllipseVisual(center=(0, 0, 0), radius=(100, 150), color=(0.2, 0.2, 0.8, 1), border_color=(1, 1, 1, 1), border_width=3, start_angle=180., span_angle=150.) ellipse.transform = transforms.STTransform(scale=(0.9, 1.5), translate=(200, 300)) self.visuals.append(ellipse) rect = visuals.RectangleVisual(center=(600, 200, 0), height=200., width=300., radius=[30., 30., 0., 0.], color=(0.5, 0.5, 0.2, 1), border_width=3, border_color='white') rect.transform = transforms.NullTransform() self.visuals.append(rect) rpolygon = visuals.RegularPolygonVisual(center=(200., 600., 0), radius=160, color=(0.2, 0.8, 0.2, 1), border_color=(1, 1, 1, 1), border_width=3, sides=6) rpolygon.transform = transforms.NullTransform() self.visuals.append(rpolygon) self.show()
def __init__(self, name, data, xyz, select=None, line_width=1.5, color='white', ts_amp=6., ts_width=20., alpha=1., antialias=False, translate=(0., 0., 1.), transform=None, parent=None, verbose=None, _z=-10., **kw): """Init.""" # Init Visbrain object base class : VisbrainObject.__init__(self, name, parent, transform, verbose, **kw) # _______________________ CHECKING _______________________ # Data : assert isinstance(data, np.ndarray) and data.ndim == 2 self._n_nodes, self._n_pts = data.shape self._data = data # XYZ : sh = xyz.shape assert sh[1] in [2, 3] xyz = xyz if sh[1] == 3 else np.c_[xyz, np.full((len(self), ), _z)] self._xyz = xyz.astype(np.float32) # Select : select = np.arange(len(self)) if select is None else select assert isinstance(select, (list, np.ndarray)) self._select = select # Amplitude / width : assert isinstance(ts_amp, float) and isinstance(ts_width, float) self._ts_amp, self._ts_width = ts_amp, ts_width # Translate : assert len(translate) == 3 tr = vist.STTransform(translate=translate) self._translate = translate # Line width : self._line_width = line_width # Color : self._color = color2vb(color, alpha=alpha) self._alpha = alpha # _______________________ LINE _______________________ self._ts = visuals.Line(name='TimeSeriesObjLine', parent=self._node, width=line_width, color=self._color, antialias=antialias) self._ts.transform = tr self._build_line()
def _define_transformation(self): sh = self._sh r90 = vist.MatrixTransform() r90.rotate(90, (0, 0, 1)) rx180 = vist.MatrixTransform() rx180.rotate(180, (1, 0, 0)) # Sagittal transformation : norm_sagit = vist.STTransform(scale=(1. / sh[1], 1. / sh[2], 1.), translate=(-1., 0., 0.)) tf_sagit = vist.ChainTransform([norm_sagit, r90, rx180]) self._im_sagit.transform = tf_sagit # Coronal transformation : norm_coron = vist.STTransform(scale=(1. / sh[0], 1. / sh[2], 1.), translate=(0., 0., 0.)) tf_coron = vist.ChainTransform([norm_coron, r90, rx180]) self._im_coron.transform = tf_coron # Axial transformation : norm_axis = vist.STTransform(scale=(2. / sh[1], 2. / sh[0], 1.), translate=(-1., 0., 0.)) tf_axial = vist.ChainTransform([norm_axis, rx180]) self._im_axial.transform = tf_axial
def __init__(self, name, data, xyz, select=None, pic_width=7., pic_height=7., alpha=1., cmap='viridis', clim=None, vmin=None, vmax=None, under='gray', over='red', translate=(0., 0., 1.), transform=None, parent=None, verbose=None, _z=-10., **kw): """Init.""" VisbrainObject.__init__(self, name, parent, transform, verbose, **kw) self._update_cbar_args(cmap, clim, vmin, vmax, under, over) # _______________________ CHECKING _______________________ # Data : assert isinstance(data, np.ndarray) and data.ndim == 3. self._n_nodes = data.shape[0] self._minmax = (data.min(), data.max()) # XYZ : sh = xyz.shape assert (sh[1] in [2, 3]) and (sh[0] == len(self)) xyz = xyz if sh[1] == 3 else np.c_[xyz, np.full((len(self), ), _z)] self._xyz = xyz.astype(np.float32) # Select : assert (select is None) or isinstance(select, (list, np.ndarray)) # Width, height : assert all( [isinstance(k, (int, float)) for k in (pic_height, pic_width)]) self._pic_width, self._pic_height = pic_width, pic_height # Translate : assert len(translate) == 3 tr = vist.STTransform(translate=translate) self._translate = translate # Alpha : assert isinstance(alpha, (int, float)) and (0. <= alpha <= 1.) self._alpha = alpha # _______________________ IMAGE _______________________ self._pic = PicMesh(data, xyz, pic_width, pic_height, translate, select, **self.to_kwargs()) self._pic.transform = tr self._pic.parent = self._node
def on_resize(self, event): gloo.set_viewport(0, 0, *event.physical_size) vp = (0, 0, self.physical_size[0], self.physical_size[1]) self.context.set_viewport(*vp) for visual in self.visuals: # TODO on Retina display, this needs to be 0.5, due to Hi-DPI, otherwise # lines are not shown where expected scale = 0.5 visual.transform = transforms.STTransform(scale=(vp[2] * scale, vp[3] * scale, 1.)) visual.transforms.configure(canvas=self, viewport=vp)
def test_st_transform(): # Check that STTransform maps exactly like MatrixTransform pts = np.random.normal(size=(10, 4)) scale = (1, 7.5, -4e-8) translate = (1e6, 0.2, 0) st = tr.STTransform(scale=scale, translate=translate) at = tr.MatrixTransform() at.scale(scale) at.translate(translate) assert np.allclose(st.map(pts), at.map(pts)) assert np.allclose(st.inverse.map(pts), at.inverse.map(pts))
def test_isocurve(ctx): ctx = VispyCtx(display_status=True) scale = 0.1 cx = np.arange(-100, 100, scale) data = np.meshgrid(cx, cx) ff = f(data) levels = [0, 10] image = Image(ff, parent=ctx.view.scene) # move image behind curves image.transform = transforms.STTransform(scale=(scale, scale), translate=(0, 0, 0.5)) color_lev = ['r', 'black'] curve = Isocurve(ff, levels=levels, color_lev=color_lev, parent=ctx.view.scene) curve.transform = transforms.STTransform(scale=(scale, scale)) # Set 2D camera ctx.view.camera = PanZoomCamera(aspect=1) # the camera will scale to the contents in the scene ctx.view.camera.set_range() ctx.run(cam=False) return ctx
def set_data(self, xlim, ylim): """Move the visual indicator. Args: xlim: tuple A tuple of two float indicating where xlim start and xlim end. ylim: tuple A tuple of two floats indicating where ylim start and ylim end. """ tox = (xlim[0], ylim[0], -1.) sc = (xlim[1] - xlim[0], ylim[1] - ylim[0], 1.) # Move the square self.mesh.transform = vist.STTransform(translate=tox, scale=sc)
def __init__(self, name='scorwinindicator', alpha=.75, visible=True, parent=None, color='red', barwidth=.20): # width of the vertical bars self.barwidth = barwidth # Create two vispy image object for the start and end of window # "Start mesh" : first vertical bar image_start = color2vb(color, alpha=alpha)[np.newaxis, ...] self.mesh_start = scene.visuals.Image(data=image_start, name=name, parent=parent) self.mesh_start.transform = vist.STTransform() self.mesh_start.visible = visible # "End mesh" : second vertical bar image_end = color2vb(color, alpha=alpha)[np.newaxis, ...] self.mesh_end = scene.visuals.Image(data=image_end, name=name, parent=parent) self.mesh_end.transform = vist.STTransform() self.mesh_end.visible = visible
def __init__(self, camera, parent=None, fcn=None): # Initialize PrepareData : PrepareData.__init__(self, axis=0) # Keep camera : self._camera = camera self._rect = (0., 0., 0., 0.) self._fcn = fcn # Time-frequency map self.tf = TFmapsMesh(parent=parent) # Spectrogram self.mesh = scene.visuals.Image(np.zeros((2, 2)), parent=parent, name='Fourier transform') self.mesh.transform = vist.STTransform()
def __init__(self, parent=None): """Init.""" # Create two dictionaries (for coordinates and text) : self._annotations = {} self._annotations_txt = {} # Create markers for annotations : pos = np.random.rand(2, 3) self._annot_mark = scene.visuals.Markers(pos=pos, parent=parent) self._annot_mark.visible = False # Create text for annotations : self._annot_text = scene.visuals.Text(parent=parent, anchor_x='left', bold=True, font_size=14.) tr = (self._time.max() - self._time.min()) / 50. self._annot_text.transform = vist.STTransform(translate=(tr, 0., 0.)) self._annot_text.visible = False
def get_st_transform(self, z, x, y): """ Return the STTransform for the current zoom, x, and y tile. """ bbox = mercantile.xy_bounds(x, y, z) scale = (bbox.right - bbox.left) / 256 scale = scale, scale, 1 # place the tiles up high, so that everything will show up correctly # TODO: figure out why setting z super high works! Not sure if it's # expected behavior or just a detail of the current Vispy # implementation. Seems like setting order would be a better way, # but it doesn't work. # If we ever switch to a different type of camera probably nothing # will work. translate = bbox.left, bbox.bottom, 9e5 - z return transforms.STTransform(scale=scale, translate=translate)
def plot(self): with open("./episode_1.pkl", "rb") as f: self.data = pickle.load(f) canvas = vispy.scene.SceneCanvas(keys="interactive", show=True, bgcolor="white") view = canvas.central_widget.add_view() self.idx = 0 colors = cm.get_cmap("tab10")(np.linspace(0.0, 1.0, 10)) self.color_id = colors[self.data["particle_ids"][0, self.idx, :, 1]] self.data["flex_states"][:, :, :, [0, 1, 2]] = self.data[ "flex_states"][:, :, :, [0, 2, 1]] pos = self.data["flex_states"][0, self.idx, :, :3] self.scatter = visuals.Markers() self.scatter.set_data(pos, edge_color=None, face_color=self.color_id, size=5) floor = visuals.Plane(width=5, height=5) wall = visuals.Plane(width=5, height=1, direction="+x", width_segments=4, height_segments=10) wall._mesh.color = "green" view.add(wall) wall.transform = transforms.STTransform(translate=(-2.5, 0.0, 0.5)) view.add(self.scatter) view.add(floor) view.camera = "turntable" # or try 'arcball' # add a colored 3D axis for orientation axis = visuals.XYZAxis(parent=view.scene) self.reverse = False timer = app.Timer(interval="1.1") timer.connect(self.update) timer.start(0.04) vispy.app.run()
def text_plot(self): """Plot some text for each source. The text is then translate to not cover the source. If no text is detected, a empty text object is created. """ if self.stext is not None: # Create text object : self.stextmesh = visu.Text(text=self.stext, color=self.stextcolor, font_size=self.stextsize, pos=self.xyz, bold=True, name='SourcesText') # Set text texture : self.stextmesh.set_gl_state('translucent', depth_test=True) # Apply a transformation to text elements to not cover sources : self.stextmesh.transform = vist.STTransform( translate=self.stextshift) else: self.stextmesh = visu.Text(name='NoneText')
def _fcn_textupdate(self): """Update text of each sources. This method can be used to set text visible / hide, to translate the text in order to not cover the source sphere and to change the color / fontsize of each text. Finally, this method update the text according to selected properties. """ # Text visible : self.sources.stextmesh.visible = self.grpText.isChecked() # Translate text (do not cover the source): t = vist.STTransform(translate=list( [self.x_text.value(), self.y_text.value(), self.z_text.value()])) self.sources.stextmesh.transform = t # Color and fontsize : _, self.sources.stextcolor = textline2color( str(self.q_stextcolor.text())) self.sources.stextsize = self.q_stextsize.value() # Update text : self.sources.text_update()
def __init__(self, axis=True, x_label='', name='', bgcolor=(1., 1., 1.), indic_color='darkred', fcn=[]): """Init.""" # Create the main canvas : self.canvas = scene.SceneCanvas(keys=None, bgcolor=bgcolor, show=False) _ = [self.canvas.connect(k) for k in fcn] # noqa # Create a grid : grid = self.canvas.central_widget.add_grid(margin=0) grid.spacing = 0 # Add x-axis : self.xaxis = scene.AxisWidget(orientation='bottom', text_color='black') if axis: pad = grid.add_widget(row=0, col=0) pad.width_max = 50 _col = int(axis) grid.add_widget(self.xaxis, row=1, col=_col) # Main plot : self.wc = grid.add_view(row=0, col=_col, border_color='black') # Add a square indicator : image = color2vb(indic_color)[np.newaxis, ...] self.mesh = scene.visuals.Image(image, name='Time indicator') self.mesh.transform = vist.STTransform() self.mesh.parent = self.wc.scene # Add markers : pos = np.full((1, 3), -10, dtype=np.float32) self.markers = Markers(pos=pos, parent=self.wc.scene) self.markers.set_gl_state('translucent')
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', text=None, text_size=3., text_color='black', 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)] # 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 # Data : if data is None: data = np.ones((len(self),)) else: data = np.asarray(data).ravel() assert len(data) == 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) # _______________________ 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._update_color() self.alpha = alpha
def __init__(self, parent=None, **kwargs): """Init.""" # _____________________ INIT _____________________ self._n = 1000 self._ratio = 4 / 5 CbarBase.__init__(self, **kwargs) # _____________________ CANVAS _____________________ if parent is None: # Define a canvas : self._canvas = scene.SceneCanvas(keys='interactive', show=False, resizable=True, dpi=600, bgcolor=self._bgcolor, size=(300, 900)) self._wc = self._canvas.central_widget.add_view() parent = self._wc.scene # Define the camera : self._camera = FixedCam(rect=(-1.2, -1.2, 2.4, 2.4)) self._wc.camera = self._camera self.parent = parent # _____________________ OBJECTS _____________________ # --------------------- Node --------------------- # Define node parent and limit node : self._cbNode = Node(name='Colorbar', parent=parent) self._limNode = Node(name='Limits', parent=self._cbNode) # Rescale between (-1., 1.) : self._rsc = vist.STTransform(scale=(self._width, 2 / self._n, 1), translate=(0, -1., 0)) # Set transformation to the node : self._cbNode.transform = self._rsc # --------------------- Image --------------------- self._mImage = visuals.Image(parent=self._cbNode, name='image') # --------------------- Border --------------------- pos = np.array([[0., 0., -3.], [1., 0., -3.], [1., 0., -3.], [1., self._n, -3.], [1., self._n, -3.], [0., self._n, -3.], [0., self._n, -3.], [0., 0., -3.]]) self._mBorder = visuals.Line(parent=self._cbNode, name='Border') self._mBorder.set_data(pos=pos, width=2., connect='segments', color=self._txtcolor) self._mBorder.visible = self._border # --------------------- Labels --------------------- # Clim labels : self._mClimM = visuals.Text(parent=self._limNode, color=self._txtcolor, font_size=self._txtsz, name='Clim_M', anchor_x='left') self._mClimm = visuals.Text(parent=self._limNode, color=self._txtcolor, font_size=self._txtsz, name='Clim_m', anchor_x='left') # Cblabel : self._mcblabel = visuals.Text(parent=self._limNode, name='Cblabel', color=self._txtcolor, anchor_x='center', font_size=self._cbtxtsz) self._mcblabel.rotation = -90 # Vmin/Vmax : self._vmMNode = Node(name='VminVmax', parent=self._limNode) self._mVm = visuals.Text(parent=self._vmMNode, color=self._txtcolor, font_size=self._ratio * self._txtsz, name='Vmin', anchor_x='left') self._mVM = visuals.Text(parent=self._vmMNode, color=self._txtcolor, font_size=self._ratio * self._txtsz, name='Vmax', anchor_x='left') # Build colorbar : self._build(True, 'all')
def test_transform_chain(): # Make dummy classes for easier distinguishing the transforms class DummyTrans(tr.BaseTransform): glsl_map = "vec4 trans(vec4 pos) {return pos;}" glsl_imap = "vec4 trans(vec4 pos) {return pos;}" class TransA(DummyTrans): pass class TransB(DummyTrans): pass class TransC(DummyTrans): pass # Create test transforms a, b, c = TransA(), TransB(), TransC() # Test Chain creation assert tr.ChainTransform().transforms == [] assert tr.ChainTransform(a).transforms == [a] assert tr.ChainTransform(a, b).transforms == [a, b] assert tr.ChainTransform(a, b, c, a).transforms == [a, b, c, a] # Test composition by multiplication assert_chain_objects(a * b, tr.ChainTransform(a, b)) assert_chain_objects(a * b * c, tr.ChainTransform(a, b, c)) assert_chain_objects(a * b * c * a, tr.ChainTransform(a, b, c, a)) # Test adding/prepending to transform chain = tr.ChainTransform() chain.append(a) assert chain.transforms == [a] chain.append(b) assert chain.transforms == [a, b] chain.append(c) assert chain.transforms == [a, b, c] chain.prepend(b) assert chain.transforms == [b, a, b, c] chain.prepend(c) assert chain.transforms == [c, b, a, b, c] # Test simplifying t1 = tr.STTransform(scale=(2, 3)) t2 = tr.STTransform(translate=(3, 4)) t3 = tr.STTransform(translate=(3, 4)) # Create multiplied versions t123 = t1 * t2 * t3 t321 = t3 * t2 * t1 c123 = tr.ChainTransform(t1, t2, t3) c321 = tr.ChainTransform(t3, t2, t1) c123s = c123.simplified c321s = c321.simplified # assert isinstance(t123, tr.STTransform) # or the test is useless assert isinstance(t321, tr.STTransform) # or the test is useless assert isinstance(c123s, tr.ChainTransform) # or the test is useless assert isinstance(c321s, tr.ChainTransform) # or the test is useless # Test Mapping t1 = tr.STTransform(scale=(2, 3)) t2 = tr.STTransform(translate=(3, 4)) chain1 = tr.ChainTransform(t1, t2) chain2 = tr.ChainTransform(t2, t1) # assert chain1.transforms == [t1, t2] # or the test is useless assert chain2.transforms == [t2, t1] # or the test is useless # m12 = (t1 * t2).map((1, 1)).tolist() m21 = (t2 * t1).map((1, 1)).tolist() m12_ = chain1.map((1, 1)).tolist() m21_ = chain2.map((1, 1)).tolist() # #print(m12, m21, m12_, m21_) assert m12 != m21 assert m12 == m12_ assert m21 == m21_ # Test shader map t1 = tr.STTransform(scale=(2, 3)) t2 = tr.STTransform(translate=(3, 4)) chain = tr.ChainTransform(t1, t2) # funcs = chain.shader_map().dependencies() funcsi = chain.shader_imap().dependencies() # assert t1.shader_map() in funcs assert t2.shader_map() in funcs assert t1.shader_imap() in funcsi assert t2.shader_imap() in funcsi
def set_data(self, data, levels=None, level_colors='white', cmap='viridis', clim=None, vmin=None, under='gray', vmax=None, over='red', cblabel=None): """Set data to the topoplot. Parameters ---------- data : array_like Array of data of shape (n_channels) 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. cblabel : string | None Colorbar label. """ # ================== XYZ / CHANNELS / DATA ================== xyz = self._xyz[self._keeponly] channels = list(np.array(self._channels)[self._keeponly]) data = np.asarray(data, dtype=float).ravel() if len(data) == len(self): data = data[self._keeponly] # =================== CHANNELS =================== # Markers : radius = normalize(data, 10., 30.) self.chanMarkers.set_data(pos=xyz, size=radius, edge_color='black', face_color=self._chan_mark_color, symbol=self._chan_mark_symbol) # Names : if channels is not None: self.chanText.text = channels self.chanText.pos = xyz # =================== GRID =================== pos_x, pos_y = xyz[:, 0], xyz[:, 1] xmin, xmax = pos_x.min(), pos_x.max() ymin, ymax = pos_y.min(), pos_y.max() xi = np.linspace(xmin, xmax, self._pix) yi = np.linspace(ymin, ymax, self._pix) xh, yi = np.meshgrid(xi, yi) grid = self._griddata(pos_x, pos_y, data, xh, yi) # =================== INTERPOLATION =================== if self._interp is not None: grid = self._grid_interpolation(grid) csize = max(self._pix, grid.shape[0]) # Variables : l = csize / 2 # noqa y, x = np.ogrid[-l:l, -l:l] mask = x**2 + y**2 < l**2 nmask = np.invert(mask) # =================== DISC =================== # Force min < off-disc values < max : grid[nmask] = data.mean() grid = normalize(grid, data.min(), data.max()) clim = (data.min(), data.max()) if clim is None else clim image = array2colormap(grid, cmap=cmap, clim=clim, vmin=vmin, vmax=vmax, under=under, over=over) image[nmask] = self._bgcolor self.disc.set_data(image) # =================== COLORBAR =================== if hasattr(self, 'cbar'): self.cbar.clim = clim self.cbar.cmap = cmap self.cbar.isvmin = vmin is not None self.cbar.vmin = vmin self.cbar.under = under self.cbar.isvmax = vmax is not None self.cbar.vmax = vmax self.cbar.over = over self.cbar.cblabel = cblabel # =================== LEVELS =================== if levels is not None: if isinstance(levels, int): levels = np.linspace(grid.min(), grid.max(), levels) if isinstance(level_colors, str): # Get colormaps : cmaps = mpl_cmap(bool(level_colors.find('_r') + 1)) if level_colors in cmaps: level_colors = array2colormap(levels, cmap=level_colors) grid[nmask] = np.inf self.iso = visuals.Isocurve(data=grid, parent=self.node_head, levels=levels, color_lev=level_colors, width=2.) self.iso.transform = vist.STTransform(translate=(0., 0., -5.))
def __init__(self, canvas, **kwargs): """Init.""" # Create a root node : self._vbNode = scene.Node(name='Engram') self._vbNode.transform = vist.STTransform(scale=[self._gl_scale] * 3) logger.debug("Engram rescaled " + str([self._gl_scale] * 3)) PROFILER("Root node", level=1) # ========================= SOURCES ========================= self.sources = CombineSources(kwargs.get('source_obj', None)) if self.sources.name is None: self._obj_type_lst.model().item(4).setEnabled(False) # Disable menu : self.menuDispSources.setChecked(False) self.menuTransform.setEnabled(False) self.sources.parent = self._vbNode PROFILER("Sources object", level=1) # ========================= CONNECTIVITY ========================= self.connect = CombineConnect(kwargs.get('connect_obj', None)) if self.connect.name is None: self._obj_type_lst.model().item(5).setEnabled(False) self.menuDispConnect.setEnabled(False) self.connect.parent = self._vbNode PROFILER("Connect object", level=1) # ========================= TIME-SERIES ========================= self.tseries = CombineTimeSeries(kwargs.get('time_series_obj', None)) if self.tseries.name is None: self._obj_type_lst.model().item(6).setEnabled(False) self.tseries.parent = self._vbNode PROFILER("Time-series object", level=1) # ========================= PICTURES ========================= self.pic = CombinePictures(kwargs.get('picture_obj', None)) if self.pic.name is None: self._obj_type_lst.model().item(7).setEnabled(False) self.pic.parent = self._vbNode PROFILER("Pictures object", level=1) # ========================= VECTORS ========================= self.vectors = CombineVectors(kwargs.get('vector_obj', None)) if self.vectors.name is None: self._obj_type_lst.model().item(8).setEnabled(False) self.vectors.parent = self._vbNode PROFILER("Vectors object", level=1) # ========================= VOLUME ========================= # ----------------- Volume ----------------- if kwargs.get('vol_obj', None) is None: self.volume = VolumeObj('brodmann') self.volume.visible_obj = False else: self.volume = kwargs.get('vol_obj') if self.volume.name not in self.volume.list(): self.volume.save(tmpfile=True) self.volume.parent = self._vbNode PROFILER("Volume object", level=1) # ----------------- ROI ----------------- if kwargs.get('roi_obj', None) is None: self.roi = RoiObj('brodmann') self.roi.visible_obj = False else: self.roi = kwargs.get('roi_obj') if self.roi.name not in self.roi.list(): self.roi.save(tmpfile=True) self.roi.parent = self._vbNode PROFILER("ROI object", level=1) # ----------------- Cross-sections ----------------- if kwargs.get('cross_sec_obj', None) is None: self.cross_sec = CrossSecObj('brodmann') else: self.cross_sec = kwargs.get('cross_sec_obj') if self.cross_sec.name not in self.cross_sec.list(): self.cross_sec.save(tmpfile=True) self.cross_sec.visible_obj = False self.cross_sec.text_size = 2. self.cross_sec.parent = self._csView.wc.scene self._csView.camera = self.cross_sec._get_camera() self.cross_sec.set_shortcuts_to_canvas(self._csView) PROFILER("Cross-sections object", level=1) # ========================= ENGRAM ========================= if kwargs.get('engram_obj', None) is None: self.atlas = BrainObj('B1') else: self.atlas = kwargs['engram_obj'] if self.atlas.name not in self.atlas.list(): self.atlas.save(tmpfile=True) self.atlas.scale = self._gl_scale self.atlas.parent = self._vbNode PROFILER("Engram object", level=1)
def __init__(self, xyz=None, channels=None, system='cartesian', unit='degree', title=None, title_color='black', title_size=20., line_color='black', line_width=4., chan_size=12., chan_offset=(0., 0., 0.), chan_mark_color='white', chan_mark_symbol='disc', chan_txt_color='black', bgcolor='white', cbar=True, cb_txt_size=10., margin=.05, parent=None): """Init.""" # ======================== VARIABLES ======================== self._bgcolor = color2vb(bgcolor) scale = 800. # fix GL bugs for small plots pos = np.zeros((1, 3), dtype=np.float32) # Colors : title_color = color2vb(title_color) line_color = color2vb(line_color) chan_txt_color = color2vb(chan_txt_color) self._chan_mark_color = color2vb(chan_mark_color) self._chan_mark_symbol = chan_mark_symbol # Disc interpolation : self._interp = .1 self._pix = 64 csize = int(self._pix / self._interp) if self._interp else self._pix l = csize / 2 # noqa # ======================== NODES ======================== # Main topoplot node : self.node = scene.Node(name='Topoplot', parent=parent) self.node.transform = vist.STTransform(scale=[scale] * 3) # Headset + channels : self.node_headfull = scene.Node(name='HeadChan', parent=self.node) # Headset node : self.node_head = scene.Node(name='Headset', parent=self.node_headfull) # Channel node : self.node_chan = scene.Node(name='Channels', parent=self.node_headfull) self.node_chan.transform = vist.STTransform(translate=(0., 0., -10.)) # Cbar node : self.node_cbar = scene.Node(name='Channels', parent=self.node) # Dictionaries : kw_line = { 'width': line_width, 'color': line_color, 'parent': self.node_head } # ======================== PARENT VISUALS ======================== # Main disc : self.disc = visuals.Image(pos=pos, name='Disc', parent=self.node_head, interpolation='bilinear') # Title : self.title = visuals.Text(text=title, pos=(0., .6, 0.), name='Title', parent=self.node, font_size=title_size, color=title_color, bold=True) self.title.font_size *= 1.1 # ======================== HEAD / NOSE / EAR ======================== # ------------------ HEAD ------------------ # Head visual : self.head = visuals.Line(pos=pos, name='Head', **kw_line) # Head circle : theta = np.arange(0, 2 * np.pi, 0.001) head = np.full((len(theta), 3), -1., dtype=np.float32) head[:, 0] = l * (1. + np.cos(theta)) head[:, 1] = l * (1. + np.sin(theta)) self.head.set_data(pos=head) # ------------------ NOSE ------------------ # Nose visual : self.nose = visuals.Line(pos=pos, name='Nose', **kw_line) # Nose data : wn, hn = csize * 50. / 512., csize * 30. / 512. nose = np.array([[l - wn, 2 * l - wn, 2.], [l, 2 * l + hn, 2.], [l, 2 * l + hn, 2.], [l + wn, 2 * l - wn, 2.]]) self.nose.set_data(pos=nose, connect='segments') # ------------------ EAR ------------------ we, he = csize * 10. / 512., csize * 30. / 512. ye = l + he * np.sin(theta) # Ear left data : self.earL = visuals.Line(pos=pos, name='EarLeft', **kw_line) # Ear left visual : ear_l = np.full((len(theta), 3), 3., dtype=np.float32) ear_l[:, 0] = 2 * l + we * np.cos(theta) ear_l[:, 1] = ye self.earL.set_data(pos=ear_l) # Ear right visual : self.earR = visuals.Line(pos=pos, name='EarRight', **kw_line) # Ear right data : ear_r = np.full((len(theta), 3), 3., dtype=np.float32) ear_r[:, 0] = 0. + we * np.cos(theta) ear_r[:, 1] = ye self.earR.set_data(pos=ear_r) # ================== CHANNELS ================== # Channel's markers : self.chanMarkers = visuals.Markers(pos=pos, name='ChanMarkers', parent=self.node_chan) # Channel's text : self.chanText = visuals.Text(pos=pos, name='ChanText', parent=self.node_chan, anchor_x='center', color=chan_txt_color, font_size=chan_size) # ================== CAMERA ================== self.rect = ((-scale / 2) * (1 + margin), (-scale / 2) * (1 + margin), scale * (1. + cbar * .3 + margin), scale * (1.11 + margin)) # ================== CBAR ================== if cbar: self.cbar = CbarVisual(cbtxtsz=1.2 * cb_txt_size, txtsz=cb_txt_size, txtcolor=title_color, cbtxtsh=2., parent=self.node_cbar) self.node_cbar.transform = vist.STTransform(scale=(.6, .4, 1.), translate=(.6, 0., 0.)) # ================== COORDINATES ================== auto = self._get_channel_coordinates(xyz, channels, system, unit) if auto: eucl = np.sqrt(self._xyz[:, 0]**2 + self._xyz[:, 1]**2).max() self.node_head.transform = vpnormalize(head, dist=2 * eucl) # Rescale between (-1:1, -1:1) = circle : circle = vist.STTransform(scale=(.5 / eucl, .5 / eucl, 1.)) self.node_headfull.transform = circle # Text translation : tr = np.array([0., .8, 0.]) + np.array(chan_offset) else: # Get coordinates of references along the x and y-axis : ref_x, ref_y = self._get_ref_coordinates() # Recenter the topoplot : t = vist.ChainTransform() t.prepend(vprecenter(head)) # Rescale (-ref_x:ref_x, -ref_y:ref_y) (ref_x != ref_y => ellipse) coef_x = 2 * ref_x / head[:, 0].max() coef_y = 2 * ref_y / head[:, 1].max() t.prepend(vist.STTransform(scale=(coef_x, coef_y, 1.))) self.node_head.transform = t # Rescale between (-1:1, -1:1) = circle : circle = vist.STTransform(scale=(.5 / ref_x, .5 / ref_y, 1.)) self.node_headfull.transform = circle # Text translation : tr = np.array([0., .04, 0.]) + np.array(chan_offset) self.chanText.transform = vist.STTransform(translate=tr) # ================== GRID INTERPOLATION ================== # Interpolation vectors : x = y = np.arange(0, self._pix, 1) xnew = ynew = np.arange(0, self._pix, self._interp) # Grid interpolation function : def _grid_interpolation(grid): f = interp2d(x, y, grid, kind='linear') return f(xnew, ynew) self._grid_interpolation = _grid_interpolation