def show_surface_and_vol(vol, pp_isosurface, showVol='MIP', clim=(-200, 1000), isoTh=300, climEditor=True): """ Show the generated isosurface in original volume """ f = vv.figure() ax = vv.gca() ax.daspect = 1, 1, -1 ax.axis.axisColor = 1, 1, 1 ax.bgcolor = 0, 0, 0 # show vol and iso vertices show_ctvolume(vol, showVol=showVol, isoTh=isoTh, clim=clim, climEditor=climEditor) label = pick3d(vv.gca(), vol) vv.plot(pp_isosurface, ms='.', ls='', mc='r', alpha=0.2, mw=4) a = vv.gca() f.eventKeyDown.Bind(lambda event: _utils_GUI.ViewPresets(event, [a])) print('------------------------') print('Use keys 1, 2, 3, 4 and 5 for preset anatomic views') print('Use v for a default zoomed view') print('Use x to show and hide axis') print('------------------------') vv.xlabel('x (mm)') vv.ylabel('y (mm)') vv.zlabel('z (mm)') return label
def DoAction(self): """ This method is affiliated to the method <self.SartAction> """ #################################################### # # Zak add you code here # e.g., in what follows we just acquire spectra # #################################################### # If you want to apply some radom phase maske then uncomment the following: #amplitude_mask = self.PulseShaper.GetZeroMask() + 1 #phase_mask = np.random.rand(max_amplitude_mask.size) #self.PulseShaper.SetMasks(amplitude_mask, phase_mask) # Getting spectrum spectrum = self.Spectrometer.AcquiredData() # Plot the spectra visvis.gca().Clear() visvis.plot(self.wavelengths, spectrum) visvis.xlabel("wavelength (nm)") visvis.ylabel("counts") visvis.title("Spectrum from radom pulse shape") self.fig.DrawNow() # Going to the next iteration if self._continue_action: wx.CallAfter(self.DoAction)
def Draw(self, nodesNr=0, drawTex=True, fignr=101, **kwargs): # Init visualization if fignr is not None: f = vv.figure(fignr) vv.clf() a = vv.gca() else: a = vv.gca() a.cameraType = '3d' a.daspect = 1, 1, -1 a.daspectAuto = False # f.position = -769.00, 342.00, 571.00, 798.00 #f.position = 269.00, 342.00, 571.00, 798.00 # Draw texture? if drawTex: self._tex1 = vv.volshow(self._vol) # Draw nodes? nodes = { 0: None, 1: self._nodes1, 2: self._nodes2, 3: self._nodes3 }[nodesNr] if nodes is not None: nodes.draw(**kwargs) a.SetLimits()
def visualize(im, vol, sz=0.25, thr=0.99): im, vol = im.numpy(), vol.numpy() print("Image shape:", im.shape) print("Volume shape:", vol.shape) # overlap with 3d representation + BGR->RGB im = im.transpose(1, 2, 0) # H,W,C im = im[:, :, ::-1] im = cv2.resize(im, (128, 128)) t = vv.imshow(im) t.interpolate = True # interpolate pixels # volshow will use volshow3 and rendering the isosurface if OpenGL version is >= 2.0 # Otherwise, it will show slices with bars that you can move (much less useful). im = (im * 128 + 128).astype(np.uint8) # im = np.ones_like(im) volRGB = np.stack(((vol >= thr) * im[:, :, 0], (vol >= thr) * im[:, :, 1], (vol >= thr) * im[:, :, 2]), axis=3) v = vv.volshow(volRGB, renderStyle='iso') v.transformations[1].sz = sz # Z rescaling l0 = vv.gca() l0.light0.ambient = 0.9 # 0.2 is default for light 0 l0.light0.diffuse = 1.0 # 1.0 is default a = vv.gca() a.axis.visible = 0 a.camera.fov = 0 # orthographic vv.use().Run()
def _createWindow(self, name, im, axis): vv.figure() vv.gca() vv.clf() fig = vv.imshow(im) dims = im.shape ''' Change color bounds ''' if im.dtype == np.uint8: fig.clim.Set(0, 255) else: fig.clim.Set(0., 1.) fig.GetFigure().title = name ''' Show ticks on axes? ''' if not axis: fig.GetAxes().axis.visible = False bgcolor = (0.,0.,0.) else: fig.GetAxes().axis.showBox = False bgcolor = (1.,1.,1.) ''' Set background color ''' fig.GetFigure().bgcolor = bgcolor fig.GetAxes().bgcolor = bgcolor ''' Setup keyboard event handler ''' fig.eventKeyDown.Bind(self._keyHandler) win = {'name':name, 'canvas':fig, 'shape':dims, 'keyEvent':None, 'text':[]} self.open_windows.append(win) return win
def on_key(event): """KEY commands for user interaction UP/DOWN = show/hide nodes ENTER = show edge and attribute values [select 2 nodes] DELETE = remove edge [select 2 nodes] CTRL = replace intially created ringparts ESCAPE = FINISH: refine, smooth """ if event.key == vv.KEY_DOWN: # hide nodes t1.visible = False t2.visible = False t3.visible = False for node_point in node_points: node_point.visible = False if event.key == vv.KEY_UP: # show nodes for node_point in node_points: node_point.visible = True if event.key == vv.KEY_ENTER: select1 = selected_nodes[0].node select2 = selected_nodes[1].node c, ct, p, l = _utils_GUI.get_edge_attributes(model, select1, select2) # visualize edge and deselect nodes selected_nodes[1].faceColor = 'b' selected_nodes[0].faceColor = 'b' selected_nodes.clear() _utils_GUI.set_edge_labels(t1,t2,t3,ct,c,l) a = vv.gca() view = a.GetView() pp = Pointset(p) # visvis meshes do not work with PointSet line = vv.solidLine(pp, radius = 0.2) line.faceColor = 'y' a.SetView(view) if event.key == vv.KEY_DELETE: # remove edge assert len(selected_nodes) == 2 select1 = selected_nodes[0].node select2 = selected_nodes[1].node c, ct, p, l = _utils_GUI.get_edge_attributes(model, select1, select2) model.remove_edge(select1, select2) # visualize removed edge, show keys and deselect nodes selected_nodes[1].faceColor = 'b' selected_nodes[0].faceColor = 'b' selected_nodes.clear() _utils_GUI.set_edge_labels(t1,t2,t3,ct,c,l) a = vv.gca() view = a.GetView() pp = Pointset(p) line = vv.solidLine(pp, radius = 0.2) line.faceColor = 'r' a.SetView(view) if event.key == vv.KEY_CONTROL: # replace intially created ringparts ringparts(ringpart=ringpart) figparts()
def ScanVoltage(self): """ Using the iterator <self.scan_pixel_voltage_pair> record the spectral response by applying the voltages """ # Pause calibration, if user requested try: if self.pause_calibration: return except AttributeError: return try: param = self.scan_pixel_voltage_pair.next() self.PulseShaper.SetUniformMasks(*param) # Getting spectrum spectrum = self.Spectrometer.AcquiredData() # Save the spectrum try: self.SpectraGroup["voltages_%d_%d" % param] = spectrum except RuntimeError: print "There was RuntimeError while saving scan voltages_%d_%d" % param # Plot the spectra visvis.gca().Clear() visvis.plot(self.wavelengths, spectrum) visvis.xlabel("wavelength (nm)") visvis.ylabel("counts") # Scanning progress info self.scanned += 1. percentage_completed = 100. * self.scanned / self.scan_length seconds_left = (time.clock() - self.initial_time) * ( 100. / percentage_completed - 1.) # convert to hours:min:sec m, s = divmod(seconds_left, 60) h, m = divmod(m, 60) title_info = param + (percentage_completed, h, m, s) visvis.title( "Scanning spectrum by applying voltages %d/%d. Progress: %.1f%% completed. Time left: %d:%02d:%02d." % title_info) self.fig.DrawNow() # Measure the next pair wx.CallAfter(self.ScanVoltage) except StopIteration: # Perform processing of the measured data wx.CallAfter(self.ExtractPhaseFunc, filename=self.calibration_file.filename) # All voltages are scanned self.StopAllJobs() # Sop using the shaper self.PulseShaper.StopDevice()
def refresh(self): if len(self._value)>1: a = vv.gca() view = a.GetView() a.Clear() vv.volshow3(self._value, renderStyle='mip', cm=self._colorMap ) if not self._first: a = vv.gca() a.SetView(view) self._first=False
def value(self, value): a = vv.gca() view = a.GetView() a.Clear() vv.volshow3(value, renderStyle='mip') if not self._first: a = vv.gca() a.SetView(view) self._first=False
def DrawSpectrum(self, event): """ Draw spectrum interactively """ spectrum = self.Spectrometer.AcquiredData() if spectrum == RETURN_FAIL: return # Display the spectrum if len(spectrum.shape) > 1: try: self.__interact_2d_spectrum__.SetData(spectrum) except AttributeError: visvis.cla() visvis.clf() # Spectrum is a 2D image visvis.subplot(211) self.__interact_2d_spectrum__ = visvis.imshow(spectrum, cm=visvis.CM_JET) visvis.subplot(212) # Plot a vertical binning spectrum = spectrum.sum(axis=0) # Linear spectrum try: self.__interact_1d_spectrum__.SetYdata(spectrum) except AttributeError: if self.wavelengths is None: self.__interact_1d_spectrum__ = visvis.plot(spectrum, lw=3) visvis.xlabel("pixels") else: self.__interact_1d_spectrum__ = visvis.plot(self.wavelengths, spectrum, lw=3) visvis.xlabel("wavelength (nm)") visvis.ylabel("counts") if self.is_autoscaled_spectrum: # Smart auto-scale linear plot try: self.spectrum_plot_limits = GetSmartAutoScaleRange( spectrum, self.spectrum_plot_limits) except AttributeError: self.spectrum_plot_limits = GetSmartAutoScaleRange(spectrum) visvis.gca().SetLimits(rangeY=self.spectrum_plot_limits) # Display the current temperature try: visvis.title("Temperature %d (C)" % self.Spectrometer.GetTemperature()) except AttributeError: pass
def refresh(self): if len(self._value) > 1: vv.figure(self._fig.nr) a = vv.gca() view = a.GetView() a.Clear() vv.volshow3(self._value, renderStyle='mip', cm=self._colorMap) if not self._first: a = vv.gca() a.SetView(view) self._first = False
def refresh(self): if len(self._value)>1: vv.figure(self._fig.nr) a = vv.gca() view = a.GetView() a.Clear() vv.volshow3(self._value, renderStyle='mip', cm=self._colorMap, clim=self._colors_limits ) if not self._first: a = vv.gca() a.SetView(view) self._first=False
def DrawModelAxes(vol, graph=None, ax=None, axVis=False, meshColor=None, getLabel=False, mc='b', lc='g', mw=7, lw=0.6, **kwargs): """ Draw model with volume with axes set ax = axes to draw (a1 or a2 or a3); graph = sd._nodes1 or 2 or 3 meshColor = None or faceColor e.g. 'g' """ #todo: prevent TypeError: draw() got an unexpected keyword argument mc/lc when not given as required variable #todo: *args voor vol in drawModelAxes of **kwargs[key] in functies hieronder if ax is None: ax = vv.gca() ax.MakeCurrent() ax.daspect = 1, 1, -1 ax.axis.axisColor = 1, 1, 1 ax.bgcolor = 0, 0, 0 ax.axis.visible = axVis vv.xlabel('x (mm)') vv.ylabel('y (mm)') vv.zlabel('z (mm)') if graph is None: show_ctvolume(vol, graph, axis=ax, removeStent=False, **kwargs) label = pick3d(vv.gca(), vol) return label if hasattr(graph, 'number_of_edges'): if graph.number_of_edges( ) == 0: # get label from picked seeds sd._nodes1 show_ctvolume(vol, graph, axis=ax, **kwargs) label = pick3d(vv.gca(), vol) graph.Draw(mc=mc, lc=lc) return label if not meshColor is None: bm = create_mesh(graph, 0.5) # (argument is strut tickness) m = vv.mesh(bm) m.faceColor = meshColor # 'g' show_ctvolume(vol, graph, axis=ax, **kwargs) graph.Draw(mc=mc, lc=lc) if getLabel == True: label = pick3d(vv.gca(), vol) return label else: pick3d(vv.gca(), vol) return
def ScanVoltage (self) : """ Using the iterator <self.scan_pixel_voltage_pair> record the spectral response by applying the voltages """ # Pause calibration, if user requested try : if self.pause_calibration : return except AttributeError : return try : param = self.scan_pixel_voltage_pair.next() self.PulseShaper.SetUniformMasks(*param) # Getting spectrum spectrum = self.Spectrometer.AcquiredData() # Save the spectrum try : self.SpectraGroup["voltages_%d_%d" % param] = spectrum except RuntimeError : print "There was RuntimeError while saving scan voltages_%d_%d" % param # Plot the spectra visvis.gca().Clear() visvis.plot (self.wavelengths, spectrum) visvis.xlabel("wavelength (nm)") visvis.ylabel("counts") # Scanning progress info self.scanned += 1. percentage_completed = 100.*self.scanned/self.scan_length seconds_left = ( time.clock() - self.initial_time )*(100./percentage_completed - 1.) # convert to hours:min:sec m, s = divmod(seconds_left, 60) h, m = divmod(m, 60) title_info = param + (percentage_completed, h, m, s) visvis.title ("Scanning spectrum by applying voltages %d/%d. Progress: %.1f%% completed. Time left: %d:%02d:%02d." % title_info) self.fig.DrawNow() # Measure the next pair wx.CallAfter(self.ScanVoltage) except StopIteration : # Perform processing of the measured data wx.CallAfter(self.ExtractPhaseFunc, filename=self.calibration_file.filename) # All voltages are scanned self.StopAllJobs() # Sop using the shaper self.PulseShaper.StopDevice()
def __init__(self): # Create figure and axes vv.figure() self._a = a = vv.gca() vv.title("Hold mouse to draw lines. Use 'rgbcmyk' and '1-9' keys.") # Set axes a.SetLimits((0, 1), (0, 1)) a.cameraType = "2d" a.daspectAuto = False a.axis.showGrid = True # Init variables needed during drawing self._active = None self._pp = Pointset(2) # Create null and empty line objects self._line1 = None self._line2 = vv.plot(vv.Pointset(2), ls="+", lc="c", lw="2", axes=a) # Bind to events a.eventMouseDown.Bind(self.OnDown) a.eventMouseUp.Bind(self.OnUp) a.eventMotion.Bind(self.OnMotion) a.eventKeyDown.Bind(self.OnKey)
def show(items, normals=None): """Function that shows a mesh object. """ for item in items: vv.clf() # convert to visvis.Mesh class new_normals = [] new_vertices = [] for k, v in item.vertices.iteritems(): new_normals.append(item.normal(k)) new_vertices.append(v) mesh = item.to_visvis_mesh() mesh.SetVertices(new_vertices) mesh.SetNormals(new_normals) mesh.faceColor = 'y' mesh.edgeShading = 'plain' mesh.edgeColor = (0, 0, 1) axes = vv.gca() if axes.daspectAuto is None: axes.daspectAuto = False axes.SetLimits() if normals is not None: for normal in normals: sl = solidLine(normal, 0.15) sl.faceColor = 'r' # Show title and enter main loop vv.title('Show') app = vv.use() app.Run()
def __init__(self): # Init visualization fig = vv.figure(102); vv.clf() a = vv.gca() # Init points pp = Pointset(2) pp.append(14,12) pp.append(12,16) pp.append(16,16) self._pp = vv.plot(pp, ls='', ms='.', mw=10, mc='g') # Init line representing the circle self._cc = vv.plot(pp, lc='r', lw=2, ms='.', mw=5, mew=0, mc='r') # Set limits a.SetLimits((0,32), (0,32)) a.daspectAuto = False # Init object being moved self._movedPoint = None # Enable callbacks self._pp.hitTest = True self._pp.eventMouseDown.Bind(self.OnDown) self._pp.eventMouseUp.Bind(self.OnUp) a.eventMotion.Bind(self.OnMotion) a.eventDoubleClick.Bind(self.OnDD) # Start self.Apply()
def showModel3d(basedir,ptcode, ctcode, cropname='ring', showVol='MIP', showmodel=True, graphname='model', **kwargs): """ show model and vol in 3d by mip iso or 2D graphname 'all' draws all graph models stored in s, if multiple """ s = loadmodel(basedir, ptcode, ctcode, cropname, modelname='modelavgreg') vol = loadvol(basedir, ptcode, ctcode, cropname, what='avgreg').vol # figure f = vv.figure(); vv.clf() f.position = 0.00, 22.00, 1920.00, 1018.00 a = vv.gca() a.axis.axisColor = 1,1,1 a.axis.visible = False a.bgcolor = 0,0,0 a.daspect = 1, 1, -1 t = show_ctvolume(vol, axis=a, showVol=showVol, removeStent=False, climEditor=True, **kwargs) label = pick3d(a, vol) vv.xlabel('x (mm)');vv.ylabel('y (mm)');vv.zlabel('z (mm)') if showmodel: if graphname == 'all': for key in dir(s): if key.startswith('model'): s[key].Draw(mc='b', mw = 5, lc='g', alpha = 0.5) else: s[graphname].Draw(mc='b', mw = 5, lc='g', alpha = 0.5) vv.title('Model for LSPEAS %s - %s' % (ptcode[8:], ctcode)) # f.eventKeyDown.Bind(lambda event: _utils_GUI.RotateView(event, [a], axishandling=False )) f.eventKeyDown.Bind(lambda event: _utils_GUI.ViewPresets(event, [a]) ) return f, a, label, s
def ShowImg (self) : """ Draw image """ if self._abort_img : # Exit return # Get image img = self.dev.StopImgAqusition() # Display image try : if img <> RETURN_FAIL : self._img_plot.SetData(img) except AttributeError : visvis.cla() visvis.clf() self._img_plot = visvis.imshow(img) visvis.title ('Camera view') ax = visvis.gca() ax.axis.xTicks = [] ax.axis.yTicks = [] # Start acquisition of histogram self.dev.StartImgAqusition() wx.CallAfter(self.ShowImg)
def compareGraphsVisually(graph1, graph2, fig=None): """ compareGraphsVisually(graph1, graph2, fig=None) Show the two graphs together in a figure. Matched nodes are indicated by lines between them. """ # Get figure if isinstance(fig,int): fig = vv.figure(fig) elif fig is None: fig = vv.figure() # Prepare figure and axes fig.Clear() a = vv.gca() a.cameraType = '3d'; a.daspectAuto = False # Draw both graphs graph1.Draw(lc='b', mc='b') graph2.Draw(lc='r', mc='r') # Set the limits a.SetLimits() # Make a line from the edges pp = Pointset(3) for node in graph1: if hasattr(node, 'match') and node.match is not None: pp.append(node); pp.append(node.match) # Plot edges vv.plot(pp, lc='g', ls='+')
def add_text(text, pos, angle=0, fontName=None, fontSize=9, color='k', bgcolor=None, axes=None): ''' Adds a text in the world space. Returns the Text object. Parameters: text - String. The text of the label pos - Tuple with two or three numbers. The (x,y,z) position of the text in world space. angle - Float or int. The rotation of the label in degrees. fontname- String. Either 'mono', 'sans' or 'serif'. fontSize- Int. Size of the text. Default 9. color - A 3-tuple or a character in 'rgbycmkw', etc that defines text color. Default 'k' (black). bgcolor - Background color. See color. Default None. axes - Axes wherein the label is placed. If None then the current axes is chosen. ''' if axes is None: axes = vv.gca() text = vv.Text(axes, text, *pos, fontName=fontName, fontSize=fontSize, color=color) text.bgcolor = bgcolor text.textAngle = angle return text
def title(text, axes=None): """ title(text, axes=None) Show title above axes. Remove title by suplying an empty string. Parameters ---------- text : string The text to display. axes : Axes instance Display the image in this axes, or the current axes if not given. """ if axes is None: axes = vv.gca() # seek Title object for child in axes.children: if isinstance(child, vv.Title): ob = child ob.text = text break else: ob = vv.Title(axes, text) # destroy if no text, return object otherwise if not text: ob.Destroy() return None else: return ob
def __init__(self): # Create figure and axes vv.figure() self._a = a = vv.gca() vv.title("Hold mouse to draw lines. Use 'rgbcmyk' and '1-9' keys.") # Set axes a.SetLimits((0,1), (0,1)) a.cameraType = '2d' a.daspectAuto = False a.axis.showGrid = True # Init variables needed during drawing self._active = None self._pp = Pointset(2) # Create null and empty line objects self._line1 = None self._line2 = vv.plot(vv.Pointset(2), ls='+', lc='c', lw='2', axes=a) # Bind to events a.eventMouseDown.Bind(self.OnDown) a.eventMouseUp.Bind(self.OnUp) a.eventMotion.Bind(self.OnMotion) a.eventKeyDown.Bind(self.OnKey)
def plot_points(pp, mc='g', ms='o', mw=8, alpha=0.5, ls='', ax=None, **kwargs): """ Plot a point or set of points in current axis and restore current view alpha 0.9 = solid; 0.1 transparant """ if ax is None: ax = vv.gca() # check if pp is 1 point and not a PointSet if not isinstance(pp, PointSet): pp = np.asarray(pp) if pp.ndim == 1: p = PointSet(3) p.append(pp) pp = p # get view and plot view = ax.GetView() point = vv.plot(PointSet(pp), mc=mc, ms=ms, mw=mw, ls=ls, alpha=alpha, axes=ax, **kwargs) ax.SetView(view) return point
def ShowImg(self): """ Draw image """ if self._abort_img: # Exit return # Get image img = self.dev.StopImgAqusition() # Display image try: if img <> RETURN_FAIL: self._img_plot.SetData(img) except AttributeError: visvis.cla() visvis.clf() self._img_plot = visvis.imshow(img) visvis.title('Camera view') ax = visvis.gca() ax.axis.xTicks = [] ax.axis.yTicks = [] # Start acquisition of histogram self.dev.StartImgAqusition() wx.CallAfter(self.ShowImg)
def ViewPresets(event, axis=None, keyboard=['1', '2', '3', '4', '5']): """ View presets for anatomic views: anterior, posterior, left, right, top, bottom. 1, 2.. keys or provide keyboard keys Can be used with f.eventKeyDown.Bind(lambda event: _utils_GUI.ViewPresets(event, [a1, a2]) ) """ if axis is None: ax = vv.gca() axis = [ax] for ax in axis: view = ax.GetView() view['roll'] = 0 # sagital LR if event.text == keyboard[0]: view['azimuth'] = 90 view['elevation'] = 0 # posterior elif event.text == keyboard[1]: view['azimuth'] = 0 view['elevation'] = 0 # sagital RL elif event.text == keyboard[2]: view['azimuth'] = -90 view['elevation'] = 0 elif event.text == keyboard[3]: view['azimuth'] = -180 view['elevation'] = 90 elif event.text == keyboard[4]: view['azimuth'] = 0 view['elevation'] = -90 elif event.text == 'z': view['zoom'] = 0.0198 ax.SetView(view) if event.text == 'x': # axes visible or hide AxesVis(axis)
def vis3Dfit(fitted, vol, model, ptcode, ctcode, showAxis, **kwargs): """Visualize ellipse fit in 3D with CT volume in current axis input: fitted = _fit3D output = (pp3, plane, pp3_2, e3) """ from stentseg.utils import fitting import numpy as np pp3,plane,pp3_2,e3 = fitted[0],fitted[1],fitted[2],fitted[3] a = vv.gca() # show_ctvolume(vol, model, showVol=showVol, clim=clim0, isoTh=isoTh) show_ctvolume(vol, model, **kwargs) vv.xlabel('x (mm)');vv.ylabel('y (mm)');vv.zlabel('z (mm)') vv.title('Ellipse fit for model %s - %s' % (ptcode[7:], ctcode)) a.axis.axisColor= 1,1,1 a.bgcolor= 0,0,0 a.daspect= 1, 1, -1 # z-axis flipped a.axis.visible = showAxis # For visualization, calculate 4 points on rectangle that lies on the plane x1, x2 = pp3.min(0)[0]-0.3, pp3.max(0)[0]+0.3 y1, y2 = pp3.min(0)[1]-0.3, pp3.max(0)[1]+0.3 p1 = x1, y1, -(x1*plane[0] + y1*plane[1] + plane[3]) / plane[2] p2 = x2, y1, -(x2*plane[0] + y1*plane[1] + plane[3]) / plane[2] p3 = x2, y2, -(x2*plane[0] + y2*plane[1] + plane[3]) / plane[2] p4 = x1, y2, -(x1*plane[0] + y2*plane[1] + plane[3]) / plane[2] vv.plot(pp3, ls='', ms='.', mc='y', mw = 10) vv.plot(fitting.project_from_plane(pp3_2, plane), lc='r', ls='', ms='.', mc='r', mw=9) # vv.plot(fitting.project_from_plane(fitting.sample_circle(c3), plane), lc='r', lw=2) vv.plot(fitting.project_from_plane(fitting.sample_ellipse(e3), plane), lc='b', lw=2) vv.plot(np.array([p1, p2, p3, p4, p1]), lc='g', lw=2) # vv.legend('3D points', 'Projected points', 'Circle fit', 'Ellipse fit', 'Plane fit') vv.legend('3D points', 'Projected points', 'Ellipse fit', 'Plane fit')
def view(viewparams=None, axes=None, **kw): """ view(viewparams=None, axes=None, **kw) Get or set the view parameters for the given axes. Parameters ---------- viewparams : dict View parameters to set. axes : Axes instance The axes the view parameters are for. Uses the current axes by default. keyword pairs View parameters to set. These take precidence. If neither viewparams or any keyword pairs are given, returns the current view parameters (as a dict). Otherwise, sets the view parameters given. """ if axes is None: axes = vv.gca() if viewparams or kw: axes.SetView(viewparams, **kw) else: return axes.GetView()
def vis2Dfit(fitted, ptcode, ctcode, showAxis): """Visualize ellipse fit in 2D in current axis input: fitted = _fit3D output = (pp3, plane, pp3_2, e3) """ from stentseg.utils import fitting import numpy as np plane,pp3_2,e3 = fitted[1],fitted[2],fitted[3] # endpoints axis x0,y0,res1,res2,phi = e3[0], e3[1], e3[2], e3[3], e3[4] dxax1 = np.cos(phi)*res1 dyax1 = np.sin(phi)*res1 dxax2 = np.cos(phi+0.5*np.pi)*res2 dyax2 = np.sin(phi+0.5*np.pi)*res2 p1ax1, p2ax1 = (x0+dxax1, y0+dyax1), (x0-dxax1, y0-dyax1) p1ax2, p2ax2 = (x0+dxax2, y0+dyax2), (x0-dxax2, y0-dyax2) a = vv.gca() vv.xlabel('x (mm)');vv.ylabel('y (mm)') vv.title('Ellipse fit for model %s - %s' % (ptcode[7:], ctcode)) a.axis.axisColor= 0,0,0 a.bgcolor= 0,0,0 a.axis.visible = showAxis a.daspectAuto = False a.axis.showGrid = True vv.plot(pp3_2, ls='', ms='.', mc='r', mw=9) vv.plot(fitting.sample_ellipse(e3), lc='b', lw=2) vv.plot(np.array([p1ax1, p2ax1]), lc='w', lw=2) # major axis vv.plot(np.array([p1ax2, p2ax2]), lc='w', lw=2) # minor axis vv.legend('3D points projected to plane', 'Ellipse fit on projected points')
def __init__(self, audiofile=None, fs=22050, bandwidth=300,freqRange= 5000, dynamicRange=48, noiseFloor =-72, parent = None): super(Spec, self).__init__() backend = 'pyqt4' app = vv.use(backend) Figure = app.GetFigureClass() self.fig= Figure(self) self.fig.enableUserInteraction = True self.fig._widget.setMinimumSize(700,350) self.axes = vv.gca() self.audiofilename = audiofile self.freqRange = freqRange self.fs = fs self.NFFT = int(1.2982804/bandwidth*self.fs) self.overlap = int(self.NFFT/2) self.noiseFloor = noiseFloor self.dynamicRange = dynamicRange self.timeLength = 60 self.resize(700,250) layout = QtGui.QVBoxLayout() layout.addWidget(self.fig._widget) self.setLayout(layout) self.win = gaussian(self.NFFT,self.NFFT/6) self.show()
def solidTeapot(translation=None, scaling=None, direction=None, rotation=None, axesAdjust=True, axes=None): """ solidTeapot( translation=None, scaling=None, direction=None, rotation=None, axesAdjust=True, axes=None) Create a model of a teapot (a teapotahedron) with its bottom at the origin. Returns an OrientableMesh instance. Parameters ---------- Note that translation, scaling, and direction can also be given using a Point instance. translation : (dx, dy, dz), optional The translation in world units of the created world object. scaling: (sx, sy, sz), optional The scaling in world units of the created world object. direction: (nx, ny, nz), optional Normal vector that indicates the direction of the created world object. rotation: scalar, optional The anle (in degrees) to rotate the created world object around its direction vector. axesAdjust : bool If True, this function will call axes.SetLimits(), and set the camera type to 3D. If daspectAuto has not been set yet, it is set to False. axes : Axes instance Display the bars in the given axes, or the current axes if not given. """ # Load mesh data bm = vv.meshRead('teapot.ssdf') # Use current axes? if axes is None: axes = vv.gca() # Create Mesh object m = vv.OrientableMesh(axes, bm) # if translation is not None: m.translation = translation if scaling is not None: m.scaling = scaling if direction is not None: m.direction = direction if rotation is not None: m.rotation = rotation # Adjust axes if axesAdjust: if axes.daspectAuto is None: axes.daspectAuto = False axes.cameraType = '3d' axes.SetLimits() # Done axes.Draw() return m
def add_label(text, pos, angle=0, fontName=None, fontSize=9, color='k', bgcolor=None, axes=None): ''' Adds a label inside the axes. Returns the Label object. Parameters: text - String. The text of the label pos - Tuple with two numbers. The (x,y) position of the label with origin at the upper left corner. angle - Float or int. The rotation of the label in degrees. fontname- String. Either 'mono', 'sans' or 'serif'. fontSize- Int. Size of the text. Default 9. color - A 3-tuple or a character in 'rgbycmkw', etc that defines text color. Default 'k' (black). bgcolor - Background color. See color. Default None. axes - Axes wherein the label is placed. If None then the current axes is chosen. ''' if axes is None: axes = vv.gca() label = vv.Label(axes, text, fontName, fontSize, color) label.position = pos label.bgcolor = bgcolor label.textAngle = angle return label
def _visualise_world_visvis(X, Y, Z, format="surf"): """ Legacy function to produce a surface render using visvis :param X: :param Y: :param Z: :param format: """ import visvis as vv # m2 = vv.surf(worldx[::detail], worldy[::detail], worldz[::detail]) app = vv.use() # prepare axes a = vv.gca() a.cameraType = '3d' a.daspectAuto = False # print("view", a.camera.GetViewParams()) # a.SetView(loc=(-1000,0,0)) # a.camera.SetView(None, loc=(-1000,0,0)) if format == "surf": l = vv.surf(X, Y, Z) a.SetLimits(rangeX=(-0.2, 0.2), rangeY=(-0.5, 0.5), rangeZ=(-0.5, 0), margin=0.02) else: # draw points pp = vv.Pointset( np.concatenate([X.flatten(), Y.flatten(), Z.flatten()], axis=0).reshape((-1, 3))) l = vv.plot(pp, ms='.', mc='r', mw='5', ls='', mew=0) l.alpha = 0.2 app.Run()
def __init__(self, mvertices, mverticesDeltas, mangleChanges): """ Allows measureing on the motions of a stent by placing a ring around it. The z-position of the ring can be changed using a slider. The ring is oriented purely in the xy plane; it is not orthogonal to the stent's centerline! """ # For interacting self._interact_over = False self._interact_down = False self._screenVec = None self._refPos = (0,0) self._screenVec = None self._refZ = 0 # Get axes axes = vv.gca() # Get vertices etc. vertices, indices, normals, texcords = self._CalculateDonut() # Initialize vv.OrientableMesh.__init__(self, axes, vertices, indices, normals, values=texcords, verticesPerFace=4) self.faceColor = 'c' # Make hittable self.hitTest = True # Bind events self.eventEnter.Bind(self._OnMouseEnter) self.eventLeave.Bind(self._OnMouseLeave) self.eventMouseDown.Bind(self._OnMouseDown) self.eventMouseUp.Bind(self._OnMouseUp) self.eventMotion.Bind(self._OnMouseMotion) # Variables for "child" objects self._slider = None self._line = None # Store data per vertex self._mvertices = mvertices self._mverticesDeltas = mverticesDeltas self._mangleChanges = mangleChanges # Get limits and halfway position limits = self._getVertexLimits(mvertices)[2] halfway = limits.min+limits.range*0.5 # Create slider if True: self._slider = vv.Slider(self.GetFigure(), limits, halfway) self._slider.eventSliderChanged.Bind(self.onSliderChanged) self._slider.eventSliding.Bind(self.onSliderSliding) # Init self.performMeasurements(halfway)
def drawmodelphasescycles(vol1, model1, modelori1, showVol, isoTh=300, removeStent=False, showmodelavgreg=False, showvol=True, phases=range(10), colors='cgmrcgywmb', meshWithColors=False, stripSizeZ=None, ax=None): """ draw model and volume (show optional) at different phases cycle """ if ax is None: ax = vv.gca() ax.daspect = 1, 1, -1 ax.axis.axisColor = 0, 0, 0 ax.bgcolor = 1, 1, 1 vv.xlabel('x (mm)') vv.ylabel('y (mm)') vv.zlabel('z (mm)') # draw t = show_ctvolume(vol1, modelori1, showVol=showVol, removeStent=removeStent, climEditor=True, isoTh=isoTh, clim=clim0, stripSizeZ=stripSizeZ) if showmodelavgreg: # show model and CT mid cycle mw = 5 for model in model1: model.Draw(mc='b', mw=mw, lc='b', alpha=0.5) label = pick3d(ax, vol1) if not showvol: t.visible = False # get models in different phases for model in model1: for phasenr in phases: model_phase = get_graph_in_phase(model, phasenr=phasenr) if meshWithColors: modelmesh1 = create_mesh_with_abs_displacement(model_phase, radius=radius, dim=dimensions) m = vv.mesh(modelmesh1, colormap=vv.CM_JET, clim=clim2) #todo: use colormap Viridis or Magma as JET is not linear (https://bids.github.io/colormap/) else: model_phase.Draw(mc=colors[phasenr], mw=10, lc=colors[phasenr]) # modelmesh1 = create_mesh(model_phase, radius = radius) # m = vv.mesh(modelmesh1); m.faceColor = colors[phasenr] if meshWithColors: vv.colorbar() return ax
def cla(): """ cla() Clear the current axes. """ a = vv.gca() a.Clear() return a
def DrawSpectrum (self, event) : """ Draw spectrum interactively """ spectrum = self.Spectrometer.AcquiredData() if spectrum == RETURN_FAIL : return # Display the spectrum if len(spectrum.shape) > 1: try : self.__interact_2d_spectrum__.SetData(spectrum) except AttributeError : visvis.cla(); visvis.clf(); # Spectrum is a 2D image visvis.subplot(211) self.__interact_2d_spectrum__ = visvis.imshow(spectrum, cm=visvis.CM_JET) visvis.subplot(212) # Plot a vertical binning spectrum = spectrum.sum(axis=0) # Linear spectrum try : self.__interact_1d_spectrum__.SetYdata(spectrum) except AttributeError : if self.wavelengths is None : self.__interact_1d_spectrum__ = visvis.plot (spectrum, lw=3) visvis.xlabel ("pixels") else : self.__interact_1d_spectrum__ = visvis.plot (self.wavelengths, spectrum, lw=3) visvis.xlabel("wavelength (nm)") visvis.ylabel("counts") if self.is_autoscaled_spectrum : # Smart auto-scale linear plot try : self.spectrum_plot_limits = GetSmartAutoScaleRange(spectrum, self.spectrum_plot_limits) except AttributeError : self.spectrum_plot_limits = GetSmartAutoScaleRange(spectrum) visvis.gca().SetLimits ( rangeY=self.spectrum_plot_limits ) # Display the current temperature try : visvis.title ("Temperature %d (C)" % self.Spectrometer.GetTemperature() ) except AttributeError : pass
def paint(self, visvis): vv.clf() colors = ['r','g','b','c','m','y','k'] for index, dataset in enumerate(self._value): l = visvis.plot(dataset, ms='o', mc=colors[ index % len(colors) ], mw='3', ls='', mew=0 ) l.alpha = 0.3 self._a = vv.gca() self._a.daspectAuto = True
def ShowSpectra_by_VaryingPixelBundle(self): """ This method is affiliated to the method <self.VaryPixelBundle> """ # Exit if the iterator is not defined try: self.pixel_bundel_value_iter except AttributeError: return try: voltage = self.pixel_bundel_value_iter.next() # Set the mask for pixel bundle width = self.SettingsNotebook.CalibrateShaper.pixel_bundle_width.GetValue( ) / 2 start_pixel_bundle = self.pixel_to_vary.GetValue() mask = np.copy(self.fixed_mask) if width: mask[max(start_pixel_bundle - width, 0):min(mask.size, start_pixel_bundle + width)] = voltage else: # Enforce single pixel width mask[min(max(start_pixel_bundle, 0), mask.size)] = voltage self.PulseShaper.SetMasks(mask, self.fixed_mask) # Getting spectrum spectrum = self.Spectrometer.AcquiredData() # Plot the spectra visvis.gca().Clear() visvis.plot(self.wavelengths, spectrum) visvis.xlabel("wavelength (nm)") visvis.ylabel("counts") visvis.title("Voltage %d / %d " % (voltage, self.fixed_mask[0])) self.fig.DrawNow() # Going to the next iteration wx.CallAfter(self.ShowSpectra_by_VaryingPixelBundle) except StopIteration: # Finish the job self.StopAllJobs()
def paint(self, visvis): vv.clf() colors = ["r", "g", "b", "c", "m", "y", "k"] for index, dataset in enumerate(self._value): l = visvis.plot(dataset, ms="o", mc=colors[index % len(colors)], mw="3", ls="", mew=0) l.alpha = 0.3 self._a = vv.gca() self._a.daspectAuto = True
def solidLine(pp, radius=1.0, N=16, axesAdjust=True, axes=None): """ solidLine(pp, radius=1.0, N=16, axesAdjust=True, axes=None) Creates a solid line in 3D space. Parameters ---------- Note that translation, scaling, and direction can also be given using a Point instance. pp : Pointset The sequence of points of which the line consists. radius : scalar or sequence The radius of the line to create. If a sequence if given, it specifies the radius for each point in pp. N : int The number of subdivisions around its centerline. If smaller than 8, flat shading is used instead of smooth shading. axesAdjust : bool If True, this function will call axes.SetLimits(), and set the camera type to 3D. If daspectAuto has not been set yet, it is set to False. axes : Axes instance Display the bars in the given axes, or the current axes if not given. """ # Check first argument if is_Pointset(pp): pass else: raise ValueError('solidLine() needs a Pointset or list of pointsets.') # Obtain mesh and make a visualization mesh baseMesh = lineToMesh(pp, radius, N) ## Visualize # Get axes if axes is None: axes = vv.gca() # Create mesh object m = vv.Mesh(axes, baseMesh) # Adjust axes if axesAdjust: if axes.daspectAuto is None: axes.daspectAuto = False axes.cameraType = '3d' axes.SetLimits() # Return axes.Draw() return m
def remove_nodes_by_selected_point(graph, vol, axes, label, clim, location='posterior', **kwargs): """ removes nodes and edges in graph. Graph is separated by coord of selected point use location to define what to remove, e.g. posterior to remove nodes in spine Input : graph, axes, label of selected point, dimension how to separate graph Output: graph is modified locally and visualized in current view """ from stentseg.utils.picker import pick3d, label2worldcoordinates from stentseg.utils.visualization import DrawModelAxes if graph is None: print('No nodes removed, graph is NoneType') return coord1 = np.asarray(label2worldcoordinates(label), dtype=np.float32) # x,y,z if location == 'posterior': seeds = np.asarray(sorted( graph.nodes(), key=lambda x: x[1])) # sort dim small to large falseindices = np.where( seeds[:, 1] > coord1[1] ) # tuple wih array of indices with values higher than coord y = 1 if location == 'anterior': seeds = np.asarray(sorted(graph.nodes(), key=lambda x: x[1])) falseindices = np.where(seeds[:, 1] < coord1[1]) elif location == 'proximal': seeds = np.asarray(sorted(graph.nodes(), key=lambda x: x[2])) falseindices = np.where( seeds[:, 2] < coord1[2]) # dim z = 2; origin proximal elif location == 'distal': seeds = np.asarray(sorted(graph.nodes(), key=lambda x: x[2])) falseindices = np.where(seeds[:, 2] > coord1[2]) # dim z = 2 elif location == 'left': seeds = np.asarray(sorted(graph.nodes(), key=lambda x: x[0])) falseindices = np.where(seeds[:, 0] > coord1[0]) elif location == 'right': seeds = np.asarray(sorted(graph.nodes(), key=lambda x: x[0])) falseindices = np.where(seeds[:, 0] < coord1[0]) # get seeds for removal by indices falseseeds = seeds[falseindices[0]] # remove from graph graph.remove_nodes_from(tuple(map( tuple, falseseeds))) # use map to convert to tuples view = axes.GetView() axes.Clear() DrawModelAxes(vol, graph, ax=axes, clim=clim, **kwargs) axes.SetView(view) if graph.number_of_edges() == 0: # get label from picked seeds sd._nodes1 label = pick3d(vv.gca(), vol) return label
def __plot(self, spectrum): vv.clf() axes = vv.gca() axes.axis.showGrid = True axes.axis.xLabel = 'Frequency (MHz)' axes.axis.yLabel = 'Level (dB)' total = len(spectrum) count = 0. for _time, sweep in spectrum.items(): alpha = (total - count) / total vv.plot(sweep.keys(), sweep.values(), lw=1, alpha=alpha) count += 1
def __init__(self, parent): super(VisPolar, self).__init__(parent) self.lines = dict() self.polar = None vv.polarplot([0], [0], lc='w', axesAdjust=True) self.axes = vv.gca() self.params = self.axes.camera.GetViewParams() self.axes.axisType = 'polar' self.axes.axis.angularRefPos = 0 # 0 deg points up self.axes.axis.isCW = True # changes angular sense (azimuth instead of phi) self.axes.axis.showGrid = True fig = self.axes.GetFigure()
def colorbar(axes=None): """ colorbar(axes=None) Attach a colorbar to the given axes (or the current axes if not given). The reference to the colorbar instance is returned. Also see the vv.ColormapEditor wibject. """ if axes is None: axes = vv.gca() return vv.Colorbar(axes)
def ShowSpectra_by_VaryingPixelBundle (self) : """ This method is affiliated to the method <self.VaryPixelBundle> """ # Exit if the iterator is not defined try : self.pixel_bundel_value_iter except AttributeError : return try : voltage = self.pixel_bundel_value_iter.next() # Set the mask for pixel bundle width = self.SettingsNotebook.CalibrateShaper.pixel_bundle_width.GetValue() / 2 start_pixel_bundle = self.pixel_to_vary.GetValue() mask = np.copy(self.fixed_mask) if width: mask[max(start_pixel_bundle-width, 0):min(mask.size, start_pixel_bundle+width)] = voltage else: # Enforce single pixel width mask[min(max(start_pixel_bundle,0),mask.size)] = voltage self.PulseShaper.SetMasks( mask, self.fixed_mask) # Getting spectrum spectrum = self.Spectrometer.AcquiredData() # Plot the spectra visvis.gca().Clear() visvis.plot (self.wavelengths, spectrum) visvis.xlabel("wavelength (nm)") visvis.ylabel("counts") visvis.title ("Voltage %d / %d " % (voltage, self.fixed_mask[0]) ) self.fig.DrawNow() # Going to the next iteration wx.CallAfter (self.ShowSpectra_by_VaryingPixelBundle) except StopIteration : # Finish the job self.StopAllJobs()
def _makeColorBar(text, axes=None): ''' Convenience function that finds the current colorbar in the axes or creates a new one if one does not exist. The reason is that colorbars can not be deleted without clearing the whole figure, and several colorbars can exist simultaneously. This should be avoided. ''' if axes is None: axes = vv.gca() colBar = getColorbar(axes) if colBar is None: vv.colorbar(axes).SetLabel(text) #Creates a colorbar and sets the label. else: colBar.SetLabel(text)# A colorbar already exists, Change label.
def getColorbar(axes=None): ''' Returns the Colorbar. If axes is None the colorbar in the current axes will be found. If several colorbars exists in the axes the first found will be returned If no colorbar is found None is returned. ''' #An ugly solution, but visvis seems to have no other way of getting the colorbar, #or most other entities that exist in the axes. if axes is None: axes = vv.gca() for obj in axes.children: if type(obj) == Colorbar: return obj return None
def createWindow(self, name, im, axis): vv.figure() vv.gca() vv.clf() fig = vv.imshow(im) dims = im.shape ''' Change color bounds ''' if im.dtype == np.uint8: fig.clim.Set(0, 255) else: fig.clim.Set(im.min(), im.max()) fig.GetFigure().title = name ''' Show ticks on axes? ''' if not axis: fig.GetAxes().axis.visible = False bgcolor = (0.,0.,0.) else: fig.GetAxes().axis.showBox = False bgcolor = (1.,1.,1.) fig.GetFigure().bgcolor = bgcolor fig.GetAxes().bgcolor = bgcolor fig.eventKeyUp.Bind(self.keyHandler) win = {'name':name, 'figure':fig, 'shape':dims, 'keyEvent':None} self.open_windows.append(win) return win
def axis(command, axes=None): """ axis(command, axes=None) Convenience function to set axis properties. Note that all functionality can also be applied via the properties of the Axis object. Parameters ---------- command : string The setting command to apply. See below. axes : Axes instance The axes to apply the setting to. Uses the current axes by default. Possible string commands ------------------------ * off: hide the axis (Axes.axis.visible = False) * on: show the axis (Axes.axis.visible = True) * equal: make a circle be displayed circular (Axes.daspectAuto = False) * auto: change the range for each dimension indepdently (Axes.daspectAuto = True) * tight: show all data (Axes.SetLimits()) * ij: flip the y-axis (make second element of Axes.daspect negative) * xy: (make all elements of Axes.daspect positive) If you want to set an Axes' limits, use Axes.SetLimits(xlim, ylim, zlim). """ # Get axes if axes is None: axes = vv.gca() if command == 'off': axes.axis.visible = 0 elif command == 'on': axes.axis.visible = 1 elif command == 'equal': axes.daspectAuto = 0 elif command == 'auto': axes.daspectAuto = 1 elif command == 'tight': axes.SetLimits() elif command == 'ij': da = [abs(tmp) for tmp in axes.daspect] axes.daspect = da[0], -abs(da[1]), da[2] elif command == 'xy': da = [abs(tmp) for tmp in axes.daspect] axes.daspect = da[0], abs(da[1]), da[2] else: raise ValueError('Unknown command in vv.axis().')
def ginput(N=0, axes=None, ms='+', **kwargs): """ ginput(N=0, axes=None, ms='+', **kwargs) Graphical input: select N number of points with the mouse. Returns a 2D pointset. Parameters ---------- N : int The maximum number of points to capture. If N=0, will keep capturing until the user stops it. The capturing always stops when enter is pressed or the mouse is double clicked. In the latter case a final point is added. axes : Axes instance The axes to capture the points in, or the current axes if not given. ms : markerStyle The marker style to use for the points. See plot. Any other keyword arguments are passed to plot to show the selected points and the lines between them. """ # Get axes if not axes: axes = vv.gca() # Get figure fig = axes.GetFigure() if not fig: return # Init pointset, helper, and line object line = vv.plot(Pointset(2), axes=axes, ms=ms, **kwargs) pp = line._points ginputHelper.Start(axes, pp, N) # Enter a loop while ginputHelper.axes: fig._ProcessGuiEvents() time.sleep(0.1) # Remove line object and return points pp = Pointset(pp[:,:2]) line.Destroy() return pp
def setupAxes(self): """ Sets up the axes initially. Shows a 2d view with a range based on the sensor positions. Might want to give the user the option to set the range in future releases. The if statement is for when the sensors got switched.. which only happens on 2 subjects, but totally messes up the axes view then. """ vv.clf() self.axes = vv.gca() self.axisLabeler = self.axes.axis self.axes.cameraType = 3 self.axes.daspectAuto= False #.SetLimits(#rangeX = (xmin,xmax),rangeY = (ymin,ymax), rangeZ = (zmin,zmax)) self.axisLabeler.showGrid = True
def ylabel(text, axes=None): """ ylabel(text, axes=None) Set the ylabel of an axes. Note that you can also use "axes.axis.yLabel = text". Parameters ---------- text : string The text to display. axes : Axes instance Display the image in this axes, or the current axes if not given. """ if axes is None: axes = vv.gca() axes.axis.yLabel = text
def __init__(self, sampleinterval=0.1, timewindow=10.0, size=(600, 350)): # Data stuff self._interval = int(sampleinterval * 1000) self._bufsize = int(timewindow / sampleinterval) self.databuffer = collections.deque([0.0] * self._bufsize, self._bufsize) self.x = np.linspace(-timewindow, 0.0, self._bufsize) self.y = np.zeros(self._bufsize, dtype=np.float) # Visvis stuff self.app = vv.use("qt4") vv.title("Dynamic Plotting with VisVis") self.line = vv.plot(self.x, self.y, lc="b", lw=3, ms="+") vv.xlabel("time") vv.ylabel("amplitude") self.ax = vv.gca() self.timer = vv.Timer(self.app, 50, oneshot=False) self.timer.Bind(self.updateplot) self.timer.Start()