def __init__(self, viewer, parent=None, order=0): self._viewer = viewer self._interaction_box = viewer.overlays.interaction_box self.node = Compound([Line(), Markers(), Markers()], parent=parent) self.node.order = order self._on_interaction_box_change() self._interaction_box.events.points.connect( self._on_interaction_box_change) self._interaction_box.events.show.connect( self._on_interaction_box_change) self._interaction_box.events.show_handle.connect( self._on_interaction_box_change) self._interaction_box.events.show_vertices.connect( self._on_interaction_box_change) self._interaction_box.events.selected_vertex.connect( self._on_interaction_box_change) self._interaction_box.events.transform.connect( self._on_interaction_box_change) self._highlight_width = 1.5 self._vertex_size = 10 self._rotation_handle_length = 20 self._highlight_color = (0, 0.6, 1) self.square_marker_node.symbol = 'square' self.square_marker_node.scaling = False self.round_marker_node.symbol = 'disc' self.round_marker_node.scaling = False
def add_chan(self, chan, color=None, values=None, limits_c=None, colormap=CHAN_COLORMAP, alpha=None): """Add channels to visualization Parameters ---------- chan : instance of Channels channels to plot color : tuple 3-, 4-element tuple, representing RGB and alpha, between 0 and 1 values : ndarray array with values for each channel limits_c : tuple of 2 floats, optional min and max values to normalize the color colormap : str one of the colormaps in vispy alpha : float transparency (0 = transparent, 1 = opaque) """ # reuse previous limits if limits_c is None and self._chan_limits is not None: limits_c = self._chan_limits chan_colors, limits = _prepare_colors(color=color, values=values, limits_c=limits_c, colormap=colormap, alpha=alpha, chan=chan) self._chan_limits = limits xyz = chan.return_xyz() marker = Markers() marker.set_data(pos=xyz, size=CHAN_SIZE, face_color=chan_colors) self._add_mesh(marker)
def create_cities(self): # initialize city markers self.markers = Markers(parent=self.view.scene) # move z-direction a bit negative (means nearer to the viewer) self.markers.transform = STTransform(translate=(0, 0, -10)) cities = utils.get_cities_coords() cnameList = [] ccoordList = [] for k, v in cities.items(): cnameList.append(k) ccoordList.append(v) ccoord = np.vstack(ccoordList) ccoord = utils.wgs84_to_radolan(ccoord) pos_scene = np.zeros((ccoord.shape[0], 2), dtype=np.float32) pos_scene[:] = ccoord - self.r0 # initialize Markers self.markers.set_data(pos=pos_scene, symbol="disc", edge_color="blue", face_color='red', size=10) # initialize Markertext self.text = Text(text=cnameList, pos=pos_scene, font_size=15, anchor_x='right', anchor_y='top', parent=self.view.scene)
def add_mesh_data_to_view(mdata, view, want_faces=True, want_points=True, want_lines=True, transform=transforms.MatrixTransform()): color = mdata.get('color', 'g') if isinstance(color, str) and color == 'random': color = np.random.random(3).tolist() else: color = Color(color).rgb.tolist() res = Attributize() res.lines = [] res.objs = [] if want_lines and 'lines' in mdata: for polyline in mdata.lines: if isinstance(polyline, Attributize): width = polyline.get('width', 1) method = 'gl' if width > 1: method = 'gl' l = Line( pos=np.array(np.array(polyline.polyline)), antialias=True, method=method, color=np.array(polyline.colors), width=width,) else: l = Line(pos=np.array(np.array(polyline)), antialias=False, method='gl', color=color) l.transform = transform view.add(l) res.lines.append(l) res.objs.append(l) if want_points and mdata.get('points', None) is not None: scatter = Markers() #mdata.points = np.array(( # (10.928140, -51.417831, -213.253723), # (0.000000, -46.719570, -205.607208), # (0.000000, -53.499737, -215.031876), # (0.000000, -69.314308, -223.780746), # (0.000000, -89.549263, -170.910568),)) #mdata.points = np.array(((-12.138942,-55.812309,-217.007050),(10.928140,-51.417831,-213.253723),(-7.289741,-43.585541,-200.506531))) points_color = mdata.get('points_color', color) points_size = mdata.get('points_size', 10) points = np.array(mdata.points) #print('PLOTTING ', points, points_size) if len(points) == 0: return scatter.set_data(points, edge_color=None, face_color=points_color, size=points_size) scatter.transform = transform view.add(scatter) res.objs.append(scatter) res.points = scatter if want_faces and 'mesh' in mdata: mesh = Mesh(meshdata=mdata.mesh, color=color + [0.7]) mesh.transform = transform view.add(mesh) res.mesh = mesh res.objs.append(mesh) return res
def __init__(self): app.Canvas.__init__(self, keys='interactive', size=(512, 512 + 2*32), title="Marker demo [press space to change marker]") self.index = 0 self.scale = 1. self.markers = Markers() self.markers.set_data(pos) self.markers.set_style(marker_types[self.index])
def test_markers(): """Test basic marker / point-sprite support""" # this is probably too basic, but it at least ensures that point sprites # work for people with TestingCanvas() as c: marker = Markers() marker.set_data(np.array([[50, 50]], np.float32)) c.draw_visual(marker) marker = _screenshot(alpha=False) assert 10 < (marker == 255).sum() < 100
def attach(self, viewer, view, canvas, parent=None, order=0): super().attach(viewer, view, canvas, parent, order) self.node = Markers(pos=self._markers_data, parent=parent) self.node.transform = STTransform() self.node.order = order self._nodes = [self.node] self._viewer.dims.events.ndisplay.connect(self._on_data_change) self._on_data_change(None)
def _on_display_change(self): parent = self.node.parent self.node.transforms = ChainTransform() self.node.parent = None if self.layer.dims.ndisplay == 2: self.node = Compound([Line(), Markers(), Markers()]) else: self.node = Markers() self.node.parent = parent self.layer._update_dims() self.layer._set_view_slice() self.reset()
def __init__(self, symbol='disc', positions=None, size=4.0, edge_size=0.5, face_colour=None, edge_colour=None, scaling=False, parent=None): """ Convenient symbol visual based on :class:`vispy.scene.visuals.Markers` class instance. Parameters ---------- symbol : unicode, optional Symbol type to draw. positions : array_like, optional Positions of symbols. size : numeric, optional Symbol size. edge_size : numeric, optional Symbol edge size. face_colour : array_like, optional Uniform symbol colour. edge_colour : array_like, optional Uniform symbol edge colour. scaling : bool, optional Marker will scale when zooming. parent : Node, optional Parent of the symbol visual in the `SceneGraph`. """ Markers.__init__(self) self.set_data( positions, size=size, edge_width=edge_size, face_color=face_colour, edge_color=edge_colour, scaling=scaling) self.symbol = symbol if parent is not None: parent.add(self)
def __init__(self, symbol='disc', positions=None, size=4.0, edge_size=0.5, face_colour=None, edge_colour=None, scaling=False, parent=None): """ Convenient symbol visual based on :class:`vispy.scene.visuals.Markers` class instance. Parameters ---------- symbol : unicode, optional Symbol type to draw. positions : array_like, optional Positions of symbols. size : numeric, optional Symbol size. edge_size : numeric, optional Symbol edge size. face_colour : array_like, optional Uniform symbol colour. edge_colour : array_like, optional Uniform symbol edge colour. scaling : bool, optional Marker will scale when zooming. parent : Node, optional Parent of the symbol visual in the `SceneGraph`. """ Markers.__init__(self) self.set_data(positions, size=size, edge_width=edge_size, face_color=face_colour, edge_color=edge_colour, scaling=scaling) self.symbol = symbol if parent is not None: parent.add(self)
def __init__(self, layer): # Create a compound visual with the following four subvisuals: # Lines: The lines of the interaction box used for highlights. # Markers: The the outlines for each point used for highlights. # Markers: The actual markers of each point. node = Compound([Line(), Markers(), Markers()]) super().__init__(layer, node) self.layer.events.symbol.connect(lambda e: self._on_data_change()) self.layer.events.edge_width.connect(lambda e: self._on_data_change()) self.layer.events.edge_color.connect(lambda e: self._on_data_change()) self.layer.events.face_color.connect(lambda e: self._on_data_change()) self.layer.events.highlight.connect( lambda e: self._on_highlight_change()) self.layer.dims.events.ndisplay.connect( lambda e: self._on_display_change()) self._on_display_change()
class VispyScatterVisual(VispyBaseVisual): def __init__(self, color='red', symbol='x'): super().__init__() self._color = Color(color) self._symbol = symbol self._markers_data = -1e8 * np.ones((1, 2)) def attach(self, viewer, view, canvas, parent=None, order=0): super().attach(viewer, view, canvas, parent, order) self.node = Markers(pos=self._markers_data, parent=parent) self.node.transform = STTransform() self.node.order = order self._nodes = [self.node] self._viewer.dims.events.ndisplay.connect(self._on_data_change) self._on_data_change(None) def setVisible(self, value): super().setVisible(value) self._on_data_change(None) def setData(self, x, y): self._markers_data = np.column_stack((x, y)) self._on_data_change(None) def _on_data_change(self, event): if not self._attached or not self._visible: return # Actual number of displayed dims ndisplay = len(self._viewer.dims.displayed) if ndisplay != 2: raise ValueError('ndisplay not supported') self.node.set_data(self._markers_data, edge_color=self._color, face_color=self._color, symbol=self._symbol)
def test_markers(): """Test basic marker / point-sprite support""" # this is probably too basic, but it at least ensures that point sprites # work for people np.random.seed(57983) data = np.random.normal(size=(30, 2), loc=50, scale=10) with TestingCanvas() as c: marker = Markers(parent=c.scene) marker.set_data(data) assert_image_approved(c.render(), "visuals/markers.png") # Test good correlation at high-dpi with TestingCanvas(px_scale=2) as c: marker = Markers(parent=c.scene) marker.set_data(data) assert_image_approved(c.render(), "visuals/markers.png")
class Canvas(app.Canvas): def __init__(self): app.Canvas.__init__(self, keys='interactive', size=(512, 512 + 2*32), title="Marker demo [press space to change marker]") self.index = 0 self.scale = 1. self.markers = Markers() self.markers.set_data(pos) self.markers.set_style(marker_types[self.index]) def on_initialize(self, event): # We need to give a transform to our visual self.transform = STTransform() self.markers._program.vert['transform'] = self.transform.shader_map() self.apply_zoom() def on_draw(self, event): gloo.clear(color='white') self.markers.draw() def on_mouse_wheel(self, event): """Use the mouse wheel to zoom.""" self.scale *= 1.25 if event.delta[1] > 0 else 0.8 self.scale = max(min(self.scale, 1e2), 1e-2) self.apply_zoom() def on_resize(self, event): self.apply_zoom() def apply_zoom(self): gloo.set_viewport(0, 0, *self.size) self.transform.scale = (2 * self.scale / self.size[0], 2 * self.scale / self.size[1], 1.) self.transform.translate = [-1, -1] self.update() def on_key_press(self, event): if event.text == ' ': self.index = (self.index + 1) % (len(marker_types)) self.markers.set_style(marker_types[self.index]) self.update()
def __init__(self, layer): # Create a compound visual with the following four subvisuals: # Markers: corresponding to the vertices of the interaction box or the # shapes that are used for highlights. # Lines: The lines of the interaction box used for highlights. # Mesh: The mesh of the outlines for each shape used for highlights. # Mesh: The actual meshes of the shape faces and edges node = Compound([Mesh(), Mesh(), Line(), Markers()]) super().__init__(layer, node) self.layer.events.edge_width.connect(self._on_data_change) self.layer.events.edge_color.connect(self._on_data_change) self.layer.events.face_color.connect(self._on_data_change) self.layer.events.highlight.connect(self._on_highlight_change) self._reset_base() self._on_data_change() self._on_highlight_change()
def __init__(self): self.clamp_filter = ClampSizeFilter() super().__init__([Markers(), Markers(), Line(), Text()]) self.attach(self.clamp_filter) self.scaling = True
def create_marker(self, id, pos, name): marker = Markers(parent=self.view.scene) marker.transform = STTransform(translate=(0, 0, -10)) marker.interactive = True # add id marker.unfreeze() marker.id = id marker.freeze() marker.set_data(pos=pos[np.newaxis], symbol="disc", edge_color="blue", face_color='red', size=10) # initialize Markertext text = Text(text=name, pos=pos, font_size=15, anchor_x='right', anchor_y='top', parent=self.view.scene) return marker, text
def __init__( self, coords, *, symbol='o', size=10, edge_width=1, edge_color='black', face_color='white', n_dimensional=False, name=None, ): # Create a compound visual with the following four subvisuals: # Lines: The lines of the interaction box used for highlights. # Markers: The the outlines for each point used for highlights. # Markers: The actual markers of each point. visual = Compound([Line(), Markers(), Markers()]) super().__init__(visual, name) self.events.add( mode=Event, size=Event, face_color=Event, edge_color=Event, symbol=Event, n_dimensional=Event, ) self._colors = get_color_names() # Freeze refreshes with self.freeze_refresh(): # Save the point coordinates self._data = coords # Save the point style params self.symbol = symbol self.n_dimensional = n_dimensional self.edge_width = edge_width self.sizes = size self.edge_colors = list( itertools.islice(ensure_iterable(edge_color, color=True), 0, len(self.data))) self.face_colors = list( itertools.islice(ensure_iterable(face_color, color=True), 0, len(self.data))) # The following point properties are for the new points that will # be added. For any given property, if a list is passed to the # constructor so each point gets its own value then the default # value is used when adding new points if np.isscalar(size): self._size = size else: self._size = 10 if type(edge_color) is str: self._edge_color = edge_color else: self._edge_color = 'black' if type(face_color) is str: self._face_color = face_color else: self._face_color = 'white' # Indices of selected points self._selected_data = [] self._selected_data_stored = [] self._selected_data_history = [] # Indices of selected points within the currently viewed slice self._selected_view = [] # Index of hovered point self._hover_point = None self._hover_point_stored = None self._selected_box = None self._mode = Mode.PAN_ZOOM self._mode_history = self._mode self._status = self.mode self._drag_start = None # Nx2 array of points in the currently viewed slice self._data_view = np.empty((0, 2)) # Sizes of points in the currently viewed slice self._sizes_view = 0 # Full data indices of points located in the currently viewed slice self._indices_view = [] self._drag_box = None self._drag_box_stored = None self._is_selecting = False self._clipboard = {} # update flags self._need_display_update = False self._need_visual_update = False # Re intitialize indices depending on image dims self._indices = (0, ) * (self.ndim - 2) + ( slice(None, None, None), slice(None, None, None), ) # Trigger generation of view slice and thumbnail self._set_view_slice()
class RadolanCanvas(SceneCanvas): def __init__(self, **kwargs): super(RadolanCanvas, self).__init__(keys='interactive', **kwargs) # set size ov Canvas self.size = 450, 450 # unfreeze needed to add more elements self.unfreeze() # add grid central widget self.grid = self.central_widget.add_grid() # add view to grid self.view = self.grid.add_view(row=0, col=0) self.view.border_color = (0.5, 0.5, 0.5, 1) # add signal emitters self.mouse_moved = EventEmitter(source=self, type="mouse_moved") # block double clicks self.events.mouse_double_click.block() # initialize empty RADOLAN image img_data = np.zeros((900, 900)) # initialize colormap, we take cubehelix for now # this is the most nice colormap for radar in vispy cmap = 'cubehelix' # initialize Image Visual with img_data # add to view self.image = Image( img_data, method='subdivide', #interpolation='bicubic', cmap=cmap, parent=self.view.scene) # add transform to Image # (mostly positioning within canvas) self.image.transform = STTransform(translate=(0, 0, 0)) # get radolan ll point coodinate into self.r0 self.r0 = utils.get_radolan_origin() # create cities (Markers and Text Visuals self.create_cities() # create PanZoomCamera self.cam = PanZoomCamera(name="PanZoom", rect=Rect(0, 0, 900, 900), aspect=1, parent=self.view.scene) self.view.camera = self.cam self._mouse_position = None self.freeze() # print FPS to console, vispy SceneCanvas internal function self.measure_fps() def create_cities(self): # initialize city markers self.markers = Markers(parent=self.view.scene) # move z-direction a bit negative (means nearer to the viewer) self.markers.transform = STTransform(translate=(0, 0, -10)) cities = utils.get_cities_coords() cnameList = [] ccoordList = [] for k, v in cities.items(): cnameList.append(k) ccoordList.append(v) ccoord = np.vstack(ccoordList) ccoord = utils.wgs84_to_radolan(ccoord) pos_scene = np.zeros((ccoord.shape[0], 2), dtype=np.float32) pos_scene[:] = ccoord - self.r0 # initialize Markers self.markers.set_data(pos=pos_scene, symbol="disc", edge_color="blue", face_color='red', size=10) # initialize Markertext self.text = Text(text=cnameList, pos=pos_scene, font_size=15, anchor_x='right', anchor_y='top', parent=self.view.scene) def on_mouse_move(self, event): point = self.scene.node_transform(self.image).map(event.pos)[:2] self._mouse_position = point # emit signal self.mouse_moved()
def __init__(self): super().__init__([Mesh(), Mesh(), Line(), Markers(), Text()])
def debug(self, measurements, file_path, add_geodesic): # Model object model = mesh_lib.Model(file_path) model_point_coordinates = model.get_coords() canvas = scene.SceneCanvas(keys='interactive') view = canvas.central_widget.add_view() # all model - GREEN points = Markers(parent=view.scene) points.set_data( pos=model_point_coordinates, edge_color=None, face_color=(0, 1, 0, .3), size=5 ) data_list = [] for m in measurements: # measurements in config file # parsing key vertexes and description text point_1 = int(m[1]) + 1 point_2 = int(m[2]) + 1 point_3 = int(m[3]) + 1 text = " ".join(m[4:]) # coordinates of key vertexes key_coords = model.get_coords((point_1, point_2, point_3)) # plane that goes through all three key vertexes plane = mesh_lib.get_plane(key_coords) # key vertexes WHITE points = Markers() points.set_data( pos=key_coords, edge_color=None, face_color=(1, 1, 1, 1), size=5 ) # "C" - circumference if m[0] == "C": # 3 segments of path (indexes) p_1 = model.get_path(point_1, point_2) p_2 = model.get_path(point_2, point_3) p_3 = model.get_path(point_3, point_1) # full path path = p_1 + p_2[1:] + p_3[1:] # "L" - Length if m[0] == "L": # 2 segments of path (indexes) p_1 = model.get_path(point_1, point_2) p_2 = model.get_path(point_2, point_3) # full path path = p_1 + p_2[1:] # geodesic geodesic_coordinates = model.get_coords(path) geodesic_length = mesh_lib.get_length(geodesic_coordinates) print("{0}:".format(text)) print( " Geodesic distance: {0} cm".format( round(100 * geodesic_length, 3) ) ) if add_geodesic: # if debug_full # geodesic line - RED line = Line(parent=view.scene) line.set_data( pos=geodesic_coordinates, color=(1, 0, 0, 1) ) # approximated flattened_coordinates = mesh_lib.get_projections(plane, geodesic_coordinates) flattened_length = mesh_lib.get_length(flattened_coordinates) print( " Approximated distance: {0} cm".format( round(100 * flattened_length, 3) ) ) data_list.append(geodesic_length) data_list.append(flattened_length) # flattened line - BLUE line = Line(parent=view.scene) line.set_data( pos=flattened_coordinates, color=(0, 0, 1, 1) ) view.camera = 'turntable' view.camera.fov = 45 view.camera.distance = 3 axis = XYZAxis(parent=view.scene) final_result = {"canvas":canvas,"data":data_list} return final_result
import mercantile import numpy as np from vismap import Canvas, MercatorTransform from vispy import app from vispy.scene.visuals import Text, Markers c = Canvas(show=True) c.title = 'Issue 5' c.view.camera.rect = (-1.08475e+07, 4.18788e+06), (2886.92, 2886.92) c.view.add_tiles_for_current_zoom() # add reference marker, using calculated x, y long, lat = -97.441296, 35.18048 x, y = mercantile.xy(long, lat) m_expected = Markers(parent=c.view.scene) m_expected.set_data(np.array([(x, y, 0)]), face_color=(0, 1, 1)) t_ok = Text( 'Expected position', pos=(x + 100, y), anchor_x='left', parent=c.view.scene, color=(0, 1, 1), ) t_ok.order = 10 m_bad = c.view.marker_at((long - 0.0005, lat), face_color=(1, 0, 0)) t_bad = Text( 'Actual position', pos=(long, lat),
def __init__(self): super().__init__([Markers(), Markers(), Line(), Text()]) self.scaling = True
well_x = 200 * np.ones(n_log_samples) delta_x = 0.3 * np.random.randn(n_log_samples) well_x += np.cumsum(delta_x) # Get Y and Z coordinates. well_y = 100 * np.ones(n_log_samples) well_z = np.linspace(0, 80, n_log_samples) # Concate X, Y, and Z coordinates. well_log_coords = np.stack((well_x, well_y, well_z), axis=1) # Get well log colors. cmap = get_colormap('hsl') values = np.random.uniform(-1.5, 2.5, n_log_samples) values = np.convolve(values, np.ones((20, )) / 20, mode='same') well_log_colors = np.array([cmap.map(x) for x in values]).squeeze() well_log = Markers(pos=well_log_coords, symbol='hbar', size=15, face_color=well_log_colors, edge_width=0) canvas4 = SeismicCanvas(title='Voting Scores', visual_nodes=visual_nodes + [well_log], xyz_axis=xyz_axis, colorbar=colorbar, **canvas_params) # Image 5: seismic with fault skin surfaces (meshes). fault_cmap = 'hsl' fault_range = (0, 180) # Read from skin files using FaultSkin class. skin_dir = './F3_fault_skins'
n_log_samples = 500 # Get X coordinates by Random walking. well_x = 200 * np.ones(n_log_samples) delta_x = 0.3 * np.random.randn(n_log_samples) well_x += np.cumsum(delta_x) # Get Y and Z coordinates. well_y = 100 * np.ones(n_log_samples) well_z = np.linspace(0, 80, n_log_samples) # Concate X, Y, and Z coordinates. well_log_coords = np.stack((well_x, well_y, well_z), axis=1) # Get well log colors. cmap = get_colormap('hsl') values = np.random.uniform(-1.5, 2.5, n_log_samples) values = np.convolve(values, np.ones((20,))/20, mode='same') well_log_colors = np.array([cmap.map(x) for x in values]).squeeze() well_log = Markers(pos=well_log_coords, symbol='hbar', size=15, face_color=well_log_colors, edge_width=0) well_log.set_gl_state(depth_test=False) visual_nodes.append(well_log) canvas4 = SeismicCanvas(title='Voting Scores', visual_nodes=visual_nodes, xyz_axis=xyz_axis, colorbar=colorbar, **canvas_params) # Image 5: seismic with fault skin surfaces (meshes). fault_surfaces = [] fault_cmap = 'hsl' fault_range = (0, 180)
class VispyPointsLayer(VispyBaseLayer): _highlight_color = (0, 0.6, 1) _highlight_width = 1.5 def __init__(self, layer): # Create a compound visual with the following four subvisuals: # Lines: The lines of the interaction box used for highlights. # Markers: The the outlines for each point used for highlights. # Markers: The actual markers of each point. node = Compound([Line(), Markers(), Markers()]) super().__init__(layer, node) self.layer.events.symbol.connect(lambda e: self._on_data_change()) self.layer.events.edge_width.connect(lambda e: self._on_data_change()) self.layer.events.edge_color.connect(lambda e: self._on_data_change()) self.layer.events.face_color.connect(lambda e: self._on_data_change()) self.layer.events.highlight.connect( lambda e: self._on_highlight_change()) self.layer.dims.events.ndisplay.connect( lambda e: self._on_display_change()) self._on_display_change() def _on_display_change(self): parent = self.node.parent self.node.transforms = ChainTransform() self.node.parent = None if self.layer.dims.ndisplay == 2: self.node = Compound([Line(), Markers(), Markers()]) else: self.node = Markers() self.node.parent = parent self.layer._update_dims() self.layer._set_view_slice() self.reset() def _on_data_change(self): if len(self.layer._data_view) > 0: edge_color = [ self.layer.edge_colors[i] for i in self.layer._indices_view[::-1] ] face_color = [ self.layer.face_colors[i] for i in self.layer._indices_view[::-1] ] else: edge_color = 'white' face_color = 'white' # Set vispy data, noting that the order of the points needs to be # reversed to make the most recently added point appear on top # and the rows / columns need to be switch for vispys x / y ordering if len(self.layer._data_view) == 0: data = np.zeros((1, self.layer.dims.ndisplay)) size = [0] else: data = self.layer._data_view size = self.layer._sizes_view if self.layer.dims.ndisplay == 2: set_data = self.node._subvisuals[2].set_data else: set_data = self.node.set_data set_data( data[::-1, ::-1] + 0.5, size=size[::-1], edge_width=self.layer.edge_width, symbol=self.layer.symbol, edge_color=edge_color, face_color=face_color, scaling=True, ) self.node.update() def _on_highlight_change(self): if self.layer.dims.ndisplay == 3: return if len(self.layer._highlight_index) > 0: # Color the hovered or selected points data = self.layer._data_view[self.layer._highlight_index] if data.ndim == 1: data = np.expand_dims(data, axis=0) size = self.layer._sizes_view[self.layer._highlight_index] face_color = [ self.layer.face_colors[i] for i in self.layer._indices_view[self.layer._highlight_index] ] else: data = np.zeros((1, self.layer.dims.ndisplay)) size = 0 face_color = 'white' self.node._subvisuals[1].set_data( data[:, ::-1] + 0.5, size=size, edge_width=self._highlight_width, symbol=self.layer.symbol, edge_color=self._highlight_color, face_color=face_color, scaling=True, ) if 0 in self.layer._highlight_box.shape: pos = np.zeros((1, 2)) width = 0 else: pos = self.layer._highlight_box width = self._highlight_width self.node._subvisuals[0].set_data(pos=pos[:, ::-1] + 0.5, color=self._highlight_color, width=width) def reset(self): self._reset_base() self._on_data_change() self._on_highlight_change()