class GameLinePanel(wx.Panel): def __init__(self, parent, *args, **kwargs): super().__init__(parent, *args, **kwargs) self.figure = Figure() self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self, -1, self.figure) self.toolbar = NavigationToolbar2Wx(self.canvas) self.toolbar.Realize() sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) self.SetSizer(sizer) self.Fit() def setPanel(self, game): allLines = {"99": [], "101": []} for odds in game["odds"]: if len(odds.keys()): try: allLines["99"].append(odds["99"]) except KeyError: pass try: allLines["101"].append(odds["101"]) except KeyError: pass postLines = [] lastSpread = 0 for g in allLines["99"]: try: temp = float(g["home_spread"]) postLines.append(temp) lastSpread = temp except (KeyError, TypeError, ValueError): postLines.append(lastSpread) self.axes.clear() self.axes.plot(range(len(postLines)), postLines) self.canvas.draw() self.canvas.Refresh()
class SensitivityPlot(wx.Panel): """ Displays plots illustrating the optimized protocol """ def __init__(self, parent, title): self.title = title self._params = None self._phys_params = None wx.Panel.__init__(self, parent, size=wx.Size(300, 600)) sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(sizer) self._spanel = spanel.ScrolledPanel(self, -1) spanel_sizer = wx.BoxSizer(wx.VERTICAL) self._spanel.SetSizer(spanel_sizer) self._figure = Figure(figsize=(3.5, 3.5), dpi=100, facecolor='white') self._canvas = FigureCanvas(self._spanel, -1, self._figure) spanel_sizer.Add(self._canvas, 2, border=5, flag=wx.EXPAND | wx.ALL) sizer.Add(self._spanel, 2, border=5, flag=wx.EXPAND | wx.ALL) self.Layout() self._spanel.SetupScrolling() def set(self, phys_params, scan, params, cost_model): self._phys_params = phys_params self._scan = scan self._params = params self._paramdict = scan.name_params(params) self._refresh_plot() def _refresh_plot(self): self._figure.clf() if self._params is not None: self._update_plot() self._canvas.draw() self._canvas.Refresh() def add_to_report(self, report): report.heading(self.title) img = ReportMatplotlibFigure(self._figure) report.image(type(self).__name__.replace(" ", "_").lower(), img)
class CanvasPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) self.figure = Figure() self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self, -1, self.figure) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) self.SetSizer(self.sizer) self.Fit() def show(self): '''Must be called to display update.''' # https://stackoverflow.com/questions/27878217/pyplot-extend-margin-at-the-bottom-of-a-figure self.figure.tight_layout() #https://stackoverflow.com/questions/10755937/how-to-redraw-a-mathplotlib-figure-in-a-wxpython-panel self.canvas.draw() self.canvas.Refresh() def draw(self): t = arange(0.0, 3.0, 0.01) s = sin(2 * pi * t) # https://matplotlib.org/api/axes_api.html#axes-class self.axes.plot(t, s) self.show() def bar(self, xlabels, yheights): ind = np.arange(len(xlabels)) self.axes.clear() self.axes.bar(ind, yheights, width=0.35) self.axes.set_xticks(ind, minor=False) self.axes.set_xticklabels(xlabels, fontdict=None, \ minor=False, rotation=90) self.show()
class DrawImage(wx.Panel): """ Used to draw a plot onto the Matplotlib figure that is embedded in a wxPython frame. """ def __init__(self, parent): """ Initializes embedded matplotlib figure. """ wx.Panel.__init__(self, parent) self.parent = parent # Create figure, plot space, and canvas for drawing fit image self.figure, self.axes = plt.subplots(1) self.figure.frameon = False self.axes.get_yaxis().set_visible(False) self.axes.get_xaxis().set_visible(False) self.axes.invert_xaxis() self.canvas = FigureCanvas(self, -1, self.figure) # If one wants to add the toolbar uncomment # self.toolbar = Toolbar(self.canvas) # self.toolbar.Realize() self.min = 0 self.max = 0 self.mean = 0 self.median = 0 self.mad = 0 # set sizers self.vertSizer = wx.BoxSizer(wx.VERTICAL) # self.horzSizer = wx.BoxSizer(wx.HORIZONTAL) # add to sizers self.vertSizer.Add(self.canvas, proportion=1, flag=wx.LEFT | wx.TOP | wx.GROW) # self.vertSizer.Add(self.toolbar, proportion=0, flag= wx.EXPAND) self.SetSizer(self.vertSizer) self.Fit() def plotImage(self, data, scale, cmap): """ Should call updatePassedStats first before calling this. Creates new plot to be drawn. """ self.mad = np.median(np.abs(data.ravel() - self.median)) # median absolute deviation deviation = scale * self.mad self.upper = self.median + deviation self.lower = self.median - deviation self.plot = self.axes.imshow(data, vmin=self.lower, vmax=self.upper, origin='lower') # self.axes.invert_xaxis() self.plot.set_clim(vmin=self.lower, vmax=self.upper) self.plot.set_cmap(cmap) self.figure.tight_layout() def refresh(self): """ Draws image onto figure. Call after using plotImage. """ self.canvas.draw() self.canvas.Refresh() def clear(self): """ Clear the current figure to be redrawn. """ self.axes.clear() # Replaced with similar method in AddLinearSpacer def getData(self, image): """ Get fits data. """ return fits.getdata(image) def updateScreenStats(self, imageName): """ Updates the stats on the status bar. """ self.parent.stats.SetStatusText("Min: %.0f" % (self.min), 0) self.parent.stats.SetStatusText("Max: %.0f" % (self.max), 1) self.parent.stats.SetStatusText("Mean: %.1f" % (self.mean), 2) # self.parent.stats.SetStatusText("Mode: %.0f"%(self.mode), 3) self.parent.stats.SetStatusText("Median: %.0f" % (self.median), 3) # Display static text if imageName is not None: self.parent.imageName.SetLabel("%s" % imageName) self.parent.Layout() else: self.parent.imageName.SetLabel("") self.parent.Layout() def updatePassedStats( self, stats_list): # list needs to be [min, max, mean, median] """ Updates the global stats from passed in stat list. """ self.min = stats_list[0] self.max = stats_list[1] self.mean = stats_list[2] self.median = stats_list[3] def updateStats(self, data): """ # Deprecated for a similar method in AddLinearSpacer.py """ self.min = np.min(data.flat) self.max = np.max(data.flat) self.mean = np.mean(data.flat) self.median = np.median(data.flat) def updateLims(self, min, max): """ Update the figure contrast """ self.plot.set_clim(vmin=min, vmax=max) def updateCmap(self, cmap): """ Update the color map of the figure to the passed in one. """ self.plot.set_cmap(cmap) def closeFig(self): """ Close figure when called. Usually used when closing entire GUI. """ plt.close('all')
class SectionFrame(wx.Frame): def __init__(self): """Constructor""" wx.Frame.__init__(self, None, wx.ID_ANY, title='Section') self.panel = wx.Panel(self, wx.ID_ANY) self.figure = Figure() self.axes = self.figure.add_axes([0, 0, 1, 1]) self.canvas = FigureCanvas(self.panel, -1, self.figure) self.canvas.mpl_connect('button_press_event', self.onFigureClick) self.canvas.mpl_connect('button_release_event', self.onFigureRelease) # self.canvas.mpl_connect('motion_notify_event', self.onFigureMotion) self.AnimationBtn = wx.Button(self.panel, wx.ID_ANY, "Animation") self.AnimationBtn.Bind(wx.EVT_BUTTON, self.onAnimationBtn) self.startTimeTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "1", style=wx.TE_CENTRE | wx.TE_PROCESS_ENTER) self.startTimeTxt.Bind(wx.EVT_TEXT_ENTER, self.onstartTimeTxt) self.endTimeTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "1", style=wx.TE_CENTRE | wx.TE_PROCESS_ENTER) self.endTimeTxt.Bind(wx.EVT_TEXT_ENTER, self.onendTimeTxt) self.ZoomInBtn = wx.Button(self.panel, wx.ID_ANY, "Zoom In") self.ZoomInBtn.Bind(wx.EVT_BUTTON, self.onZoomInBtn) self.ZoomOutBtn = wx.Button(self.panel, wx.ID_ANY, "Zoom Out") self.ZoomOutBtn.Bind(wx.EVT_BUTTON, self.onZoomOutBtn) self.PrintBtn = wx.Button(self.panel, wx.ID_ANY, "Print") self.PrintBtn.Bind(wx.EVT_BUTTON, self.onPrintBtn) self.ResetColorBtn = wx.Button(self.panel, wx.ID_ANY, "Reset Color") self.ResetColorBtn.Bind(wx.EVT_BUTTON, self.onResetColorBtn) self.MinColorTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "Min Color", style=wx.TE_CENTRE | wx.TE_PROCESS_ENTER) self.MinColorTxt.Bind(wx.EVT_TEXT_ENTER, self.onMinColorTxt) self.MaxColorTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "Max Color", style=wx.TE_CENTRE | wx.TE_PROCESS_ENTER) self.MaxColorTxt.Bind(wx.EVT_TEXT_ENTER, self.onMaxColorTxt) self.__do_layout() self.filename = "/Users/slgentil/models/croco/croco_visu/moz_his.nc" self.variableName = "u" self.croco = Croco(self.filename) self.startTimeTxt.SetValue(str(self.croco.times[0])) self.startTime = self.croco.times[0] self.startTimeIndex = 0 self.endTimeTxt.SetValue(str(self.croco.times[-1])) self.endTime = self.croco.times[-1] self.endTimeIndex = self.croco.crocoGrid.ntimes - 1 self.timeIndex = 0 self.levelIndex = self.croco.crocoGrid.N - 1 self.xlim = [ np.min(self.croco.crocoGrid._lon), np.max(self.croco.crocoGrid._lon) ] self.ylim = [ np.min(self.croco.crocoGrid._lat), np.max(self.croco.crocoGrid._lat) ] self.updateVariableXY() def __do_layout(self): topSizer = wx.BoxSizer(wx.VERTICAL) canvasSizer = wx.BoxSizer(wx.VERTICAL) buttonsSizer = wx.BoxSizer(wx.HORIZONTAL) colorSizer = wx.BoxSizer(wx.HORIZONTAL) canvasSizer.Add(self.canvas, 0, wx.ALL, 5) buttonsSizer.Add(self.AnimationBtn, 0, wx.ALL, 5) buttonsSizer.Add(self.startTimeTxt, 1, wx.ALL, 5) buttonsSizer.Add(self.endTimeTxt, 1, wx.ALL, 5) buttonsSizer.Add(self.ZoomInBtn, 0, wx.ALL, 5) buttonsSizer.Add(self.ZoomOutBtn, 0, wx.ALL, 5) buttonsSizer.Add(self.PrintBtn, 0, wx.ALL, 5) colorSizer.Add(self.ResetColorBtn, 0, wx.ALL, 5) colorSizer.Add(self.MinColorTxt, 0, wx.ALL, 5) colorSizer.Add(self.MaxColorTxt, 0, wx.ALL, 5) topSizer.Add(canvasSizer, 0, wx.CENTER) topSizer.Add(buttonsSizer, 0, wx.ALL | wx.EXPAND, 5) topSizer.Add(colorSizer, 0, wx.ALL | wx.EXPAND, 5) self.panel.SetSizer(topSizer) topSizer.Fit(self) self.Layout() def onFigureClick(self, event): self.xPress, self.yPress = event.xdata, event.ydata def onFigureRelease(self, event): self.xRelease, self.yRelease = event.xdata, event.ydata def rect_select_callback(self, eclick, erelease): self.xPress, self.yPress = eclick.xdata, eclick.ydata self.xRelease, self.yRelease = erelease.xdata, erelease.ydata print('rect_select_callback:', self.xPress, self.yPress, self.xRelease, self.yRelease) # print(" The button you used were: %s %s" % (eclick.button, erelease.button)) def onAnimationBtn(self, event): os.system("rm -rf ./Figures") try: os.makedirs('./Figures') except: pass anim = animation.FuncAnimation(self.figure, self.animate, \ frames = range(self.startTimeIndex,self.endTimeIndex+1), repeat=False, blit = False) self.canvas.draw() anim.save('./Figures/' + self.variableName + '.mp4') def animate(self, i): self.timeIndex = i self.updateVariableXY(setlim=False) def onstartTimeTxt(self, event): self.startTime = float(self.startTimeTxt.GetValue()) self.startTimeIndex = min( range(len(self.croco.times[:])), key=lambda j: abs(self.startTime - self.croco.times[j])) self.startTimeTxt.SetValue(str(self.croco.times[self.startTimeIndex])) def onendTimeTxt(self, event): self.endTime = float(self.endTimeTxt.GetValue()) self.endTimeIndex = min( range(len(self.croco.times[:])), key=lambda j: abs(self.endTime - self.croco.times[j])) self.endTimeTxt.SetValue(str(self.croco.times[self.endTimeIndex])) def onZoomInBtn(self, event): self.xlim = [ min(self.xPress, self.xRelease), max(self.xPress, self.xRelease) ] self.ylim = [ min(self.yPress, self.yRelease), max(self.yPress, self.yRelease) ] self.drawxy() def onZoomOutBtn(self, event): self.xlim = [ np.min(self.croco.crocoGrid._lon), np.max(self.croco.crocoGrid._lon) ] self.ylim = [ np.min(self.croco.crocoGrid._lat), np.max(self.croco.crocoGrid._lat) ] self.drawxy() def onPrintBtn(self, event): filename = self.variableName + ".png" self.figure.savefig(filename, dpi=self.figure.dpi) def onResetColorBtn(self, event): self.clim = [np.min(self.variableXY), np.max(self.variableXY)] self.MinColorTxt.SetValue('%.2E' % self.clim[0]) self.MaxColorTxt.SetValue('%.2E' % self.clim[1]) self.drawxy() def onMinColorTxt(self, event): self.clim[0] = float(self.MinColorTxt.GetValue()) self.drawxy() def onMaxColorTxt(self, event): self.clim[1] = float(self.MaxColorTxt.GetValue()) self.drawxy() def updateVariableXY(self, setlim=True): time = str(self.timeIndex) level = str(self.levelIndex) try: self.variableXY = self.croco.read_nc(self.variableName, indices="[" + time + "," + level + ",:,:]") except Exception: try: self.variableXY = self.croco.read_nc(self.variableName, indices="[" + time + ",:,:]") except Exception: raise Exception self.drawxy(setlim=setlim) def drawxy(self, setlim=True): # self.canvas.Destroy() # self.figure = Figure(figsize=(figsize[0],figsize[1])) # self.canvas = FigureCanvas(self.PanelCanvas, -1, self.figure) # self.canvas.mpl_connect('button_press_event', self.onFigureClick) # self.canvas.mpl_connect('button_release_event', self.onFigureRelease) self.figure.clear() self.figure.clf() # depth = float(self.LevelTxt.GetValue()) depth = 0 if setlim == True: self.clim = [np.min(self.variableXY), np.max(self.variableXY)] if depth > 0: title = "{:s}, Level={:4d}, Time={:4.1f}".format( self.variableName, self.levelIndex, self.croco.times[self.timeIndex]) else: title = "{:s}, Depth={:4.1f}, Time={:4.1f}".format( self.variableName, depth, self.croco.times[self.timeIndex]) mypcolor(self,self.croco.crocoGrid._lon,self.croco.crocoGrid._lat,self.variableXY,\ title=title,\ xlabel='Longitude',\ ylabel='Latitude',\ xlim=self.xlim,\ ylim=self.ylim,\ clim=self.clim) self.canvas.draw() self.canvas.Refresh() self.Show()
class mainFrame(wx.Frame): """ The main frame of the feedback interface """ title = 'Main Console' def __init__(self, images): # 10x10 inches, 100 dots-per-inch, so set size to (1000,1000) wx.Frame.__init__(self, None, -1, self.title, size=(750, 500), pos=(50, 50)) self.images = images self.npop = len(self.images) self.rewards = np.zeros((self.npop, )) self.comparisons = list(itertools.combinations(range(self.npop), 2)) shuffle(self.comparisons) self.dpi = 100 self.fig = plt.figure(figsize=(7.0, 4.5), dpi=self.dpi) self.fig.subplots_adjust(left=0.1, bottom=0.01, right=0.9, \ top=0.99, wspace=0.05, hspace=0.05) self.ax1 = self.fig.add_subplot(121) self.ax2 = self.fig.add_subplot(122) self.create_main_panel() def create_main_panel(self): self.panel = wx.Panel(self) self.draw() self.canvas = FigCanvas(self.panel, -1, self.fig) self.left_button = wx.Button(self.panel, -1, label="Left is better") self.left_button.Bind(wx.EVT_BUTTON, self.on_left) self.right_button = wx.Button(self.panel, -1, label="Right is better") self.right_button.Bind(wx.EVT_BUTTON, self.on_right) self.equal_button = wx.Button(self.panel, -1, label="Can't tell") self.equal_button.Bind(wx.EVT_BUTTON, self.on_equal) self.hbox = wx.BoxSizer(wx.HORIZONTAL) self.hbox.Add(self.left_button, 0, flag=wx.CENTER | wx.BOTTOM) self.hbox.Add(self.equal_button, 0, flag=wx.CENTER | wx.BOTTOM) self.hbox.Add(self.right_button, 0, flag=wx.CENTER | wx.BOTTOM) self.vbox = wx.BoxSizer(wx.VERTICAL) self.vbox.Add(self.canvas, 0, flag=wx.CENTER | wx.CENTER | wx.GROW) self.vbox.Add(self.hbox, border=20, flag=wx.CENTER | wx.ALIGN_CENTER_VERTICAL) self.panel.SetSizer(self.vbox) self.vbox.Fit(self) def draw(self): print(self.comparisons) self.ax1.clear() self.ax1.imshow(self.images[self.comparisons[0][0]]) self.ax1.axis('off') self.ax2.clear() self.ax2.imshow(self.images[self.comparisons[0][1]]) self.ax2.axis('off') def on_left(self, event): self.rewards[self.comparisons[0][0]] += 1 #self.rewards[self.comparisons[0][1]] -= 1 self.next_or_done() def on_right(self, event): #self.rewards[self.comparisons[0][0]] -= 1 self.rewards[self.comparisons[0][1]] += 1 self.next_or_done() def on_equal(self, event): self.next_or_done() def next_or_done(self): self.comparisons.pop(0) if not self.comparisons: self.Destroy() wx.GetApp().ExitMainLoop() else: self.draw() self.canvas.draw() self.canvas.Refresh()
class HorizonFrame(wx.Frame): """ The main frame of the horizon indicator.""" def __init__(self, state, title): self.state = state # Create Frame and Panel(s) wx.Frame.__init__(self, None, title=title) state.frame = self # Initialisation self.initData() self.initUI() self.startTime = time.time() self.nextTime = 0.0 self.fps = 10.0 def initData(self): # Initialise Attitude self.pitch = 0.0 # Degrees self.roll = 0.0 # Degrees self.yaw = 0.0 # Degrees # History Values self.oldRoll = 0.0 # Degrees # Initialise Rate Information self.airspeed = 0.0 # m/s self.relAlt = 0.0 # m relative to home position self.relAltTime = 0.0 # s The time that the relative altitude was recorded self.climbRate = 0.0 # m/s self.altHist = [] # Altitude History self.timeHist = [] # Time History self.altMax = 0.0 # Maximum altitude since startup # Initialise HUD Info self.heading = 0.0 # 0-360 # Initialise Battery Info self.voltage = 0.0 self.current = 0.0 self.batRemain = 0.0 # Initialise Mode and State self.mode = 'UNKNOWN' self.armed = '' self.safetySwitch = '' # Intialise Waypoint Information self.currentWP = 0 self.finalWP = 0 self.wpDist = 0 self.nextWPTime = 0 self.wpBearing = 0 def initUI(self): # Create Event Timer and Bindings self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.on_timer, self.timer) self.timer.Start(100) self.Bind(wx.EVT_IDLE, self.on_idle) self.Bind(wx.EVT_CHAR_HOOK,self.on_KeyPress) # Create Panel self.panel = wx.Panel(self) self.vertSize = 0.09 self.resized = False # Create Matplotlib Panel self.createPlotPanel() # Fix Axes - vertical is of length 2, horizontal keeps the same lengthscale self.rescaleX() self.calcFontScaling() # Create Horizon Polygons self.createHorizonPolygons() # Center Pointer Marker self.thick = 0.015 self.createCenterPointMarker() # Pitch Markers self.dist10deg = 0.2 # Graph distance per 10 deg self.createPitchMarkers() # Add Roll, Pitch, Yaw Text self.createRPYText() # Add Airspeed, Altitude, Climb Rate Text self.createAARText() # Create Heading Pointer self.createHeadingPointer() # Create North Pointer self.createNorthPointer() # Create Battery Bar self.batWidth = 0.1 self.batHeight = 0.2 self.rOffset = 0.35 self.createBatteryBar() # Create Mode & State Text self.createStateText() # Create Waypoint Text self.createWPText() # Create Waypoint Pointer self.createWPPointer() # Create Altitude History Plot self.createAltHistoryPlot() # Show Frame self.Show(True) self.pending = [] def createPlotPanel(self): '''Creates the figure and axes for the plotting panel.''' self.figure = Figure() self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self,-1,self.figure) self.canvas.SetSize(wx.Size(300,300)) self.axes.axis('off') self.figure.subplots_adjust(left=0,right=1,top=1,bottom=0) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas,1,wx.EXPAND,wx.ALL) self.SetSizerAndFit(self.sizer) self.Fit() def rescaleX(self): '''Rescales the horizontal axes to make the lengthscales equal.''' self.ratio = self.figure.get_size_inches()[0]/float(self.figure.get_size_inches()[1]) self.axes.set_xlim(-self.ratio,self.ratio) self.axes.set_ylim(-1,1) def calcFontScaling(self): '''Calculates the current font size and left position for the current window.''' self.ypx = self.figure.get_size_inches()[1]*self.figure.dpi self.xpx = self.figure.get_size_inches()[0]*self.figure.dpi self.fontSize = self.vertSize*(self.ypx/2.0) self.leftPos = self.axes.get_xlim()[0] self.rightPos = self.axes.get_xlim()[1] def checkReszie(self): '''Checks if the window was resized.''' if not self.resized: oldypx = self.ypx oldxpx = self.xpx self.ypx = self.figure.get_size_inches()[1]*self.figure.dpi self.xpx = self.figure.get_size_inches()[0]*self.figure.dpi if (oldypx != self.ypx) or (oldxpx != self.xpx): self.resized = True else: self.resized = False def createHeadingPointer(self): '''Creates the pointer for the current heading.''' self.headingTri = patches.RegularPolygon((0.0,0.80),3,0.05,color='k',zorder=4) self.axes.add_patch(self.headingTri) self.headingText = self.axes.text(0.0,0.675,'0',color='k',size=self.fontSize,horizontalalignment='center',verticalalignment='center',zorder=4) def adjustHeadingPointer(self): '''Adjust the value of the heading pointer.''' self.headingText.set_text(str(self.heading)) self.headingText.set_size(self.fontSize) def createNorthPointer(self): '''Creates the north pointer relative to current heading.''' self.headingNorthTri = patches.RegularPolygon((0.0,0.80),3,0.05,color='k',zorder=4) self.axes.add_patch(self.headingNorthTri) self.headingNorthText = self.axes.text(0.0,0.675,'N',color='k',size=self.fontSize,horizontalalignment='center',verticalalignment='center',zorder=4) def adjustNorthPointer(self): '''Adjust the position and orientation of the north pointer.''' self.headingNorthText.set_size(self.fontSize) headingRotate = mpl.transforms.Affine2D().rotate_deg_around(0.0,0.0,self.heading)+self.axes.transData self.headingNorthText.set_transform(headingRotate) if (self.heading > 90) and (self.heading < 270): headRot = self.heading-180 else: headRot = self.heading self.headingNorthText.set_rotation(headRot) self.headingNorthTri.set_transform(headingRotate) # Adjust if overlapping with heading pointer if (self.heading <= 10.0) or (self.heading >= 350.0): self.headingNorthText.set_text('') else: self.headingNorthText.set_text('N') def toggleWidgets(self,widgets): '''Hides/shows the given widgets.''' for wig in widgets: if wig.get_visible(): wig.set_visible(False) else: wig.set_visible(True) def createRPYText(self): '''Creates the text for roll, pitch and yaw.''' self.rollText = self.axes.text(self.leftPos+(self.vertSize/10.0),-0.97+(2*self.vertSize)-(self.vertSize/10.0),'Roll: %.2f' % self.roll,color='w',size=self.fontSize) self.pitchText = self.axes.text(self.leftPos+(self.vertSize/10.0),-0.97+self.vertSize-(0.5*self.vertSize/10.0),'Pitch: %.2f' % self.pitch,color='w',size=self.fontSize) self.yawText = self.axes.text(self.leftPos+(self.vertSize/10.0),-0.97,'Yaw: %.2f' % self.yaw,color='w',size=self.fontSize) self.rollText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) self.pitchText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) self.yawText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) def updateRPYLocations(self): '''Update the locations of roll, pitch, yaw text.''' # Locations self.rollText.set_position((self.leftPos+(self.vertSize/10.0),-0.97+(2*self.vertSize)-(self.vertSize/10.0))) self.pitchText.set_position((self.leftPos+(self.vertSize/10.0),-0.97+self.vertSize-(0.5*self.vertSize/10.0))) self.yawText.set_position((self.leftPos+(self.vertSize/10.0),-0.97)) # Font Size self.rollText.set_size(self.fontSize) self.pitchText.set_size(self.fontSize) self.yawText.set_size(self.fontSize) def updateRPYText(self): 'Updates the displayed Roll, Pitch, Yaw Text' self.rollText.set_text('Roll: %.2f' % self.roll) self.pitchText.set_text('Pitch: %.2f' % self.pitch) self.yawText.set_text('Yaw: %.2f' % self.yaw) def createCenterPointMarker(self): '''Creates the center pointer in the middle of the screen.''' self.axes.add_patch(patches.Rectangle((-0.75,-self.thick),0.5,2.0*self.thick,facecolor='orange',zorder=3)) self.axes.add_patch(patches.Rectangle((0.25,-self.thick),0.5,2.0*self.thick,facecolor='orange',zorder=3)) self.axes.add_patch(patches.Circle((0,0),radius=self.thick,facecolor='orange',edgecolor='none',zorder=3)) def createHorizonPolygons(self): '''Creates the two polygons to show the sky and ground.''' # Sky Polygon vertsTop = [[-1,0],[-1,1],[1,1],[1,0],[-1,0]] self.topPolygon = Polygon(vertsTop,facecolor='dodgerblue',edgecolor='none') self.axes.add_patch(self.topPolygon) # Ground Polygon vertsBot = [[-1,0],[-1,-1],[1,-1],[1,0],[-1,0]] self.botPolygon = Polygon(vertsBot,facecolor='brown',edgecolor='none') self.axes.add_patch(self.botPolygon) def calcHorizonPoints(self): '''Updates the verticies of the patches for the ground and sky.''' ydiff = math.tan(math.radians(-self.roll))*float(self.ratio) pitchdiff = self.dist10deg*(self.pitch/10.0) # Sky Polygon vertsTop = [(-self.ratio,ydiff-pitchdiff),(-self.ratio,1),(self.ratio,1),(self.ratio,-ydiff-pitchdiff),(-self.ratio,ydiff-pitchdiff)] self.topPolygon.set_xy(vertsTop) # Ground Polygon vertsBot = [(-self.ratio,ydiff-pitchdiff),(-self.ratio,-1),(self.ratio,-1),(self.ratio,-ydiff-pitchdiff),(-self.ratio,ydiff-pitchdiff)] self.botPolygon.set_xy(vertsBot) def createPitchMarkers(self): '''Creates the rectangle patches for the pitch indicators.''' self.pitchPatches = [] # Major Lines (multiple of 10 deg) for i in [-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9]: width = self.calcPitchMarkerWidth(i) currPatch = patches.Rectangle((-width/2.0,self.dist10deg*i-(self.thick/2.0)),width,self.thick,facecolor='w',edgecolor='none') self.axes.add_patch(currPatch) self.pitchPatches.append(currPatch) # Add Label for +-30 deg self.vertSize = 0.09 self.pitchLabelsLeft = [] self.pitchLabelsRight = [] i=0 for j in [-90,-60,-30,30,60,90]: self.pitchLabelsLeft.append(self.axes.text(-0.55,(j/10.0)*self.dist10deg,str(j),color='w',size=self.fontSize,horizontalalignment='center',verticalalignment='center')) self.pitchLabelsLeft[i].set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) self.pitchLabelsRight.append(self.axes.text(0.55,(j/10.0)*self.dist10deg,str(j),color='w',size=self.fontSize,horizontalalignment='center',verticalalignment='center')) self.pitchLabelsRight[i].set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) i += 1 def calcPitchMarkerWidth(self,i): '''Calculates the width of a pitch marker.''' if (i % 3) == 0: if i == 0: width = 1.5 else: width = 0.9 else: width = 0.6 return width def adjustPitchmarkers(self): '''Adjusts the location and orientation of pitch markers.''' pitchdiff = self.dist10deg*(self.pitch/10.0) rollRotate = mpl.transforms.Affine2D().rotate_deg_around(0.0,-pitchdiff,self.roll)+self.axes.transData j=0 for i in [-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9]: width = self.calcPitchMarkerWidth(i) self.pitchPatches[j].set_xy((-width/2.0,self.dist10deg*i-(self.thick/2.0)-pitchdiff)) self.pitchPatches[j].set_transform(rollRotate) j+=1 # Adjust Text Size and rotation i=0 for j in [-9,-6,-3,3,6,9]: self.pitchLabelsLeft[i].set_y(j*self.dist10deg-pitchdiff) self.pitchLabelsRight[i].set_y(j*self.dist10deg-pitchdiff) self.pitchLabelsLeft[i].set_size(self.fontSize) self.pitchLabelsRight[i].set_size(self.fontSize) self.pitchLabelsLeft[i].set_rotation(self.roll) self.pitchLabelsRight[i].set_rotation(self.roll) self.pitchLabelsLeft[i].set_transform(rollRotate) self.pitchLabelsRight[i].set_transform(rollRotate) i += 1 def createAARText(self): '''Creates the text for airspeed, altitude and climb rate.''' self.airspeedText = self.axes.text(self.rightPos-(self.vertSize/10.0),-0.97+(2*self.vertSize)-(self.vertSize/10.0),'AS: %.1f m/s' % self.airspeed,color='w',size=self.fontSize,ha='right') self.altitudeText = self.axes.text(self.rightPos-(self.vertSize/10.0),-0.97+self.vertSize-(0.5*self.vertSize/10.0),'ALT: %.1f m ' % self.relAlt,color='w',size=self.fontSize,ha='right') self.climbRateText = self.axes.text(self.rightPos-(self.vertSize/10.0),-0.97,'CR: %.1f m/s' % self.climbRate,color='w',size=self.fontSize,ha='right') self.airspeedText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) self.altitudeText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) self.climbRateText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) def updateAARLocations(self): '''Update the locations of airspeed, altitude and Climb rate.''' # Locations self.airspeedText.set_position((self.rightPos-(self.vertSize/10.0),-0.97+(2*self.vertSize)-(self.vertSize/10.0))) self.altitudeText.set_position((self.rightPos-(self.vertSize/10.0),-0.97+self.vertSize-(0.5*self.vertSize/10.0))) self.climbRateText.set_position((self.rightPos-(self.vertSize/10.0),-0.97)) # Font Size self.airspeedText.set_size(self.fontSize) self.altitudeText.set_size(self.fontSize) self.climbRateText.set_size(self.fontSize) def updateAARText(self): 'Updates the displayed airspeed, altitude, climb rate Text' self.airspeedText.set_text('AR: %.1f m/s' % self.airspeed) self.altitudeText.set_text('ALT: %.1f m ' % self.relAlt) self.climbRateText.set_text('CR: %.1f m/s' % self.climbRate) def createBatteryBar(self): '''Creates the bar to display current battery percentage.''' self.batOutRec = patches.Rectangle((self.rightPos-(1.3+self.rOffset)*self.batWidth,1.0-(0.1+1.0+(2*0.075))*self.batHeight),self.batWidth*1.3,self.batHeight*1.15,facecolor='darkgrey',edgecolor='none') self.batInRec = patches.Rectangle((self.rightPos-(self.rOffset+1+0.15)*self.batWidth,1.0-(0.1+1+0.075)*self.batHeight),self.batWidth,self.batHeight,facecolor='lawngreen',edgecolor='none') self.batPerText = self.axes.text(self.rightPos - (self.rOffset+0.65)*self.batWidth,1-(0.1+1+(0.075+0.15))*self.batHeight,'%.f' % self.batRemain,color='w',size=self.fontSize,ha='center',va='top') self.batPerText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) self.voltsText = self.axes.text(self.rightPos-(self.rOffset+1.3+0.2)*self.batWidth,1-(0.1+0.05+0.075)*self.batHeight,'%.1f V' % self.voltage,color='w',size=self.fontSize,ha='right',va='top') self.ampsText = self.axes.text(self.rightPos-(self.rOffset+1.3+0.2)*self.batWidth,1-self.vertSize-(0.1+0.05+0.1+0.075)*self.batHeight,'%.1f A' % self.current,color='w',size=self.fontSize,ha='right',va='top') self.voltsText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) self.ampsText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) self.axes.add_patch(self.batOutRec) self.axes.add_patch(self.batInRec) def updateBatteryBar(self): '''Updates the position and values of the battery bar.''' # Bar self.batOutRec.set_xy((self.rightPos-(1.3+self.rOffset)*self.batWidth,1.0-(0.1+1.0+(2*0.075))*self.batHeight)) self.batInRec.set_xy((self.rightPos-(self.rOffset+1+0.15)*self.batWidth,1.0-(0.1+1+0.075)*self.batHeight)) self.batPerText.set_position((self.rightPos - (self.rOffset+0.65)*self.batWidth,1-(0.1+1+(0.075+0.15))*self.batHeight)) self.batPerText.set_fontsize(self.fontSize) self.voltsText.set_text('%.1f V' % self.voltage) self.ampsText.set_text('%.1f A' % self.current) self.voltsText.set_position((self.rightPos-(self.rOffset+1.3+0.2)*self.batWidth,1-(0.1+0.05)*self.batHeight)) self.ampsText.set_position((self.rightPos-(self.rOffset+1.3+0.2)*self.batWidth,1-self.vertSize-(0.1+0.05+0.1)*self.batHeight)) self.voltsText.set_fontsize(self.fontSize) self.ampsText.set_fontsize(self.fontSize) if self.batRemain >= 0: self.batPerText.set_text(int(self.batRemain)) self.batInRec.set_height(self.batRemain*self.batHeight/100.0) if self.batRemain/100.0 > 0.5: self.batInRec.set_facecolor('lawngreen') elif self.batRemain/100.0 <= 0.5 and self.batRemain/100.0 > 0.2: self.batInRec.set_facecolor('yellow') elif self.batRemain/100.0 <= 0.2 and self.batRemain >= 0.0: self.batInRec.set_facecolor('r') elif self.batRemain == -1: self.batInRec.set_height(self.batHeight) self.batInRec.set_facecolor('k') def createStateText(self): '''Creates the mode and arm state text.''' self.modeText = self.axes.text(self.leftPos+(self.vertSize/10.0),0.97,'UNKNOWN',color='grey',size=1.5*self.fontSize,ha='left',va='top') self.modeText.set_path_effects([PathEffects.withStroke(linewidth=self.fontSize/10.0,foreground='black')]) def updateStateText(self): '''Updates the mode and colours red or green depending on arm state.''' self.modeText.set_position((self.leftPos+(self.vertSize/10.0),0.97)) self.modeText.set_text(self.mode) self.modeText.set_size(1.5*self.fontSize) if self.armed: self.modeText.set_color('red') self.modeText.set_path_effects([PathEffects.withStroke(linewidth=self.fontSize/10.0,foreground='yellow')]) elif (self.armed == False): self.modeText.set_color('lightgreen') self.modeText.set_bbox(None) self.modeText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='black')]) else: # Fall back if unknown self.modeText.set_color('grey') self.modeText.set_bbox(None) self.modeText.set_path_effects([PathEffects.withStroke(linewidth=self.fontSize/10.0,foreground='black')]) def createWPText(self): '''Creates the text for the current and final waypoint, and the distance to the new waypoint.''' self.wpText = self.axes.text(self.leftPos+(1.5*self.vertSize/10.0),0.97-(1.5*self.vertSize)+(0.5*self.vertSize/10.0),'0/0\n(0 m, 0 s)',color='w',size=self.fontSize,ha='left',va='top') self.wpText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='black')]) def updateWPText(self): '''Updates the current waypoint and distance to it.''' self.wpText.set_position((self.leftPos+(1.5*self.vertSize/10.0),0.97-(1.5*self.vertSize)+(0.5*self.vertSize/10.0))) self.wpText.set_size(self.fontSize) if type(self.nextWPTime) is str: self.wpText.set_text('%.f/%.f\n(%.f m, ~ s)' % (self.currentWP,self.finalWP,self.wpDist)) else: self.wpText.set_text('%.f/%.f\n(%.f m, %.f s)' % (self.currentWP,self.finalWP,self.wpDist,self.nextWPTime)) def createWPPointer(self): '''Creates the waypoint pointer relative to current heading.''' self.headingWPTri = patches.RegularPolygon((0.0,0.55),3,0.05,facecolor='lime',zorder=4,ec='k') self.axes.add_patch(self.headingWPTri) self.headingWPText = self.axes.text(0.0,0.45,'1',color='lime',size=self.fontSize,horizontalalignment='center',verticalalignment='center',zorder=4) self.headingWPText.set_path_effects([PathEffects.withStroke(linewidth=1,foreground='k')]) def adjustWPPointer(self): '''Adjust the position and orientation of the waypoint pointer.''' self.headingWPText.set_size(self.fontSize) headingRotate = mpl.transforms.Affine2D().rotate_deg_around(0.0,0.0,-self.wpBearing+self.heading)+self.axes.transData self.headingWPText.set_transform(headingRotate) angle = self.wpBearing - self.heading if angle < 0: angle += 360 if (angle > 90) and (angle < 270): headRot = angle-180 else: headRot = angle self.headingWPText.set_rotation(-headRot) self.headingWPTri.set_transform(headingRotate) self.headingWPText.set_text('%.f' % (angle)) def createAltHistoryPlot(self): '''Creates the altitude history plot.''' self.altHistRect = patches.Rectangle((self.leftPos+(self.vertSize/10.0),-0.25),0.5,0.5,facecolor='grey',edgecolor='none',alpha=0.4,zorder=4) self.axes.add_patch(self.altHistRect) self.altPlot, = self.axes.plot([self.leftPos+(self.vertSize/10.0),self.leftPos+(self.vertSize/10.0)+0.5],[0.0,0.0],color='k',marker=None,zorder=4) self.altMarker, = self.axes.plot(self.leftPos+(self.vertSize/10.0)+0.5,0.0,marker='o',color='k',zorder=4) self.altText2 = self.axes.text(self.leftPos+(4*self.vertSize/10.0)+0.5,0.0,'%.f m' % self.relAlt,color='k',size=self.fontSize,ha='left',va='center',zorder=4) def updateAltHistory(self): '''Updates the altitude history plot.''' self.altHist.append(self.relAlt) self.timeHist.append(self.relAltTime) # Delete entries older than x seconds histLim = 10 currentTime = time.time() point = 0 for i in range(0,len(self.timeHist)): if (self.timeHist[i] > (currentTime - 10.0)): break # Remove old entries self.altHist = self.altHist[i:] self.timeHist = self.timeHist[i:] # Transform Data x = [] y = [] tmin = min(self.timeHist) tmax = max(self.timeHist) x1 = self.leftPos+(self.vertSize/10.0) y1 = -0.25 altMin = 0 altMax = max(self.altHist) # Keep alt max for whole mission if altMax > self.altMax: self.altMax = altMax else: altMax = self.altMax if tmax != tmin: mx = 0.5/(tmax-tmin) else: mx = 0.0 if altMax != altMin: my = 0.5/(altMax-altMin) else: my = 0.0 for t in self.timeHist: x.append(mx*(t-tmin)+x1) for alt in self.altHist: val = my*(alt-altMin)+y1 # Crop extreme noise if val < -0.25: val = -0.25 elif val > 0.25: val = 0.25 y.append(val) # Display Plot self.altHistRect.set_x(self.leftPos+(self.vertSize/10.0)) self.altPlot.set_data(x,y) self.altMarker.set_data(self.leftPos+(self.vertSize/10.0)+0.5,val) self.altText2.set_position((self.leftPos+(4*self.vertSize/10.0)+0.5,val)) self.altText2.set_size(self.fontSize) self.altText2.set_text('%.f m' % self.relAlt) # =============== Event Bindings =============== # def on_idle(self, event): '''To adjust text and positions on rescaling the window when resized.''' # Check for resize self.checkReszie() if self.resized: # Fix Window Scales self.rescaleX() self.calcFontScaling() # Recalculate Horizon Polygons self.calcHorizonPoints() # Update Roll, Pitch, Yaw Text Locations self.updateRPYLocations() # Update Airpseed, Altitude, Climb Rate Locations self.updateAARLocations() # Update Pitch Markers self.adjustPitchmarkers() # Update Heading and North Pointer self.adjustHeadingPointer() self.adjustNorthPointer() # Update Battery Bar self.updateBatteryBar() # Update Mode and State self.updateStateText() # Update Waypoint Text self.updateWPText() # Adjust Waypoint Pointer self.adjustWPPointer() # Update History Plot self.updateAltHistory() # Update Matplotlib Plot self.canvas.draw() self.canvas.Refresh() self.resized = False time.sleep(0.05) def on_timer(self, event): '''Main Loop.''' state = self.state self.loopStartTime = time.time() if state.close_event.wait(0.001): self.timer.Stop() self.Destroy() return # Check for resizing self.checkReszie() if self.resized: self.on_idle(0) # Get attitude information while state.child_pipe_recv.poll(): objList = state.child_pipe_recv.recv() for obj in objList: self.calcFontScaling() if isinstance(obj,Attitude): self.oldRoll = self.roll self.pitch = obj.pitch*180/math.pi self.roll = obj.roll*180/math.pi self.yaw = obj.yaw*180/math.pi # Update Roll, Pitch, Yaw Text Text self.updateRPYText() # Recalculate Horizon Polygons self.calcHorizonPoints() # Update Pitch Markers self.adjustPitchmarkers() elif isinstance(obj,VFR_HUD): self.heading = obj.heading self.airspeed = obj.airspeed self.climbRate = obj.climbRate # Update Airpseed, Altitude, Climb Rate Locations self.updateAARText() # Update Heading North Pointer self.adjustHeadingPointer() self.adjustNorthPointer() elif isinstance(obj,Global_Position_INT): self.relAlt = obj.relAlt self.relAltTime = obj.curTime # Update Airpseed, Altitude, Climb Rate Locations self.updateAARText() # Update Altitude History self.updateAltHistory() elif isinstance(obj,BatteryInfo): self.voltage = obj.voltage self.current = obj.current self.batRemain = obj.batRemain # Update Battery Bar self.updateBatteryBar() elif isinstance(obj,FlightState): self.mode = obj.mode self.armed = obj.armState # Update Mode and Arm State Text self.updateStateText() elif isinstance(obj,WaypointInfo): self.currentWP = obj.current self.finalWP = obj.final self.wpDist = obj.currentDist self.nextWPTime = obj.nextWPTime if obj.wpBearing < 0.0: self.wpBearing = obj.wpBearing + 360 else: self.wpBearing = obj.wpBearing # Update waypoint text self.updateWPText() # Adjust Waypoint Pointer self.adjustWPPointer() elif isinstance(obj, FPS): # Update fps target self.fps = obj.fps # Quit Drawing if too early if (time.time() > self.nextTime): # Update Matplotlib Plot self.canvas.draw() self.canvas.Refresh() self.Refresh() self.Update() # Calculate next frame time if (self.fps > 0): fpsTime = 1/self.fps self.nextTime = fpsTime + self.loopStartTime else: self.nextTime = time.time() def on_KeyPress(self,event): '''To adjust the distance between pitch markers.''' if event.GetKeyCode() == wx.WXK_UP: self.dist10deg += 0.1 print 'Dist per 10 deg: %.1f' % self.dist10deg elif event.GetKeyCode() == wx.WXK_DOWN: self.dist10deg -= 0.1 if self.dist10deg <= 0: self.dist10deg = 0.1 print 'Dist per 10 deg: %.1f' % self.dist10deg # Toggle Widgets elif event.GetKeyCode() == 49: # 1 widgets = [self.modeText,self.wpText] self.toggleWidgets(widgets) elif event.GetKeyCode() == 50: # 2 widgets = [self.batOutRec,self.batInRec,self.voltsText,self.ampsText,self.batPerText] self.toggleWidgets(widgets) elif event.GetKeyCode() == 51: # 3 widgets = [self.rollText,self.pitchText,self.yawText] self.toggleWidgets(widgets) elif event.GetKeyCode() == 52: # 4 widgets = [self.airspeedText,self.altitudeText,self.climbRateText] self.toggleWidgets(widgets) elif event.GetKeyCode() == 53: # 5 widgets = [self.altHistRect,self.altPlot,self.altMarker,self.altText2] self.toggleWidgets(widgets) elif event.GetKeyCode() == 54: # 6 widgets = [self.headingTri,self.headingText,self.headingNorthTri,self.headingNorthText,self.headingWPTri,self.headingWPText] self.toggleWidgets(widgets) # Update Matplotlib Plot self.canvas.draw() self.canvas.Refresh() self.Refresh() self.Update()
class ProfileFrame(wx.Frame): def __init__(self, croco): """ Class for Time Series and Vertical Porfile""" wx.Frame.__init__(self, None, wx.ID_ANY, title='Profile') self.croco = croco self.panel = wx.Panel(self, wx.ID_ANY) self.figure = Figure() # self.axes = self.figure.add_axes([0.1,0.1,0.9,0.9]) self.canvas = FigureCanvas(self.panel, -1, self.figure) self.ZoomInBtn = wx.Button(self.panel, wx.ID_ANY, "Zoom In") self.ZoomInBtn.Bind(wx.EVT_BUTTON, self.onZoomInBtn) self.ZoomOutBtn = wx.Button(self.panel, wx.ID_ANY, "Zoom Out") self.ZoomOutBtn.Bind(wx.EVT_BUTTON, self.onZoomOutBtn) self.PrintBtn = wx.Button(self.panel, wx.ID_ANY, "Print") self.PrintBtn.Bind(wx.EVT_BUTTON, self.onPrintBtn) self.__do_layout() def __do_layout(self): topSizer = wx.BoxSizer(wx.VERTICAL) canvasSizer = wx.BoxSizer(wx.VERTICAL) buttonsSizer = wx.BoxSizer(wx.HORIZONTAL) canvasSizer.Add(self.canvas, 0, wx.ALL, 5) buttonsSizer.Add(self.ZoomInBtn,0, wx.ALL, 5) buttonsSizer.Add(self.ZoomOutBtn,0, wx.ALL, 5) buttonsSizer.Add(self.PrintBtn,0, wx.ALL, 5) topSizer.Add(canvasSizer, 0, wx.CENTER) topSizer.Add(buttonsSizer, 0, wx.ALL|wx.EXPAND, 5) self.panel.SetSizer(topSizer) topSizer.Fit(self) # self.Layout() def onFigureClick(self,event): self.xPress, self.yPress = event.xdata, event.ydata def onFigureRelease(self,event): self.xRelease, self.yRelease = event.xdata, event.ydata def rect_select_callback(self, eclick, erelease): ''' Function for selecting rectangle when zoom in ''' self.xPress, self.yPress = eclick.xdata, eclick.ydata self.xRelease, self.yRelease = erelease.xdata, erelease.ydata self.xlim = [min(self.xPress,self.xRelease),max(self.xPress,self.xRelease)] self.ylim = [ min(self.yPress,self.yRelease),max(self.yPress,self.yRelease)] self.drawCurv(setlim=False) def onZoomInBtn(self,event): self.figure.RS.set_active(True) def onZoomOutBtn(self,event): self.drawCurv() def onPrintBtn(self,event): ''' Save plot in croco_visu/Figures_.../title.png ''' printDir = self.croco.path_script+"/Figures_" + self.croco.get_run_name()+"/" if not os.path.isdir(printDir): os.mkdir(printDir) filename = printDir+self.title + ".png" self.figure.savefig(filename, dpi=self.figure.dpi) def drawCurv(self,profile=None,z=None,title=None,ylabel=None,setlim=True): ''' draw the time series or vertical profile curve ''' if profile is not None: self.profile = profile self.z = z self.title = title self.ylabel = ylabel # Prepare the canvas to receive mouse click event self.canvas.mpl_connect('button_press_event', self.onFigureClick) self.canvas.mpl_connect('button_release_event', self.onFigureRelease) # Set default parameters of the plot if needed if setlim: self.xlim=None self.ylim=None # Draw the curve if self.z is not None: plotCurv(self,x=self.profile,y=self.z,title=self.title,ylabel=self.ylabel, xlim=self.xlim, ylim=self.ylim) else: plotCurv(self,x=self.profile,title=self.title, xlim=self.xlim, ylim=self.ylim) self.canvas.draw() self.canvas.Refresh() self.Show()
class CrocoGui(wx.Frame): ''' Class for the main window (ie horizontal slice) ''' def __init__(self): wx.Frame.__init__(self, None, wx.ID_ANY, title='My Form') self.Panel = wx.Panel(self, wx.ID_ANY) self.OpenFileBtn = wx.Button(self.Panel, wx.ID_ANY, "Open History File ...") self.OpenFileBtn.Bind(wx.EVT_BUTTON, self.onOpenFile) self.OpenFileTxt = wx.StaticText(self.Panel, wx.ID_ANY, " ", style=wx.ALIGN_LEFT) self.CrocoVariableChoice = wx.Choice(self.Panel, wx.ID_ANY, choices=["Croco Variables ..."]) self.CrocoVariableChoice.SetSelection(0) self.CrocoVariableChoice.Bind(wx.EVT_CHOICE, self.onCrocoVariableChoice) self.DerivedVariableChoice = wx.Choice(self.Panel, wx.ID_ANY, choices=["Derived Variables ..."]) self.DerivedVariableChoice.SetSelection(0) self.DerivedVariableChoice.Bind(wx.EVT_CHOICE, self.onDerivedVariableChoice) self.ResetColorBtn = wx.Button(self.Panel, wx.ID_ANY, "Reset Color") self.ResetColorBtn.Bind(wx.EVT_BUTTON, self.onResetColorBtn) self.MinColorTxt = wx.TextCtrl(self.Panel, wx.ID_ANY, "Min Color", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.MinColorTxt.Bind(wx.EVT_TEXT_ENTER, self.onMinColorTxt) self.MaxColorTxt = wx.TextCtrl(self.Panel, wx.ID_ANY, "Max Color", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.MaxColorTxt.Bind(wx.EVT_TEXT_ENTER, self.onMaxColorTxt) self.LabelTime = wx.StaticText(self.Panel,-1,label="Choose Time",style = wx.ALIGN_CENTER) self.LabelMinMaxTime = wx.StaticText(self.Panel, wx.ID_ANY, " ", style=wx.ALIGN_LEFT) self.TimeMinusBtn = wx.Button(self.Panel, wx.ID_ANY, "<") self.TimeMinusBtn.Bind(wx.EVT_BUTTON, self.onTimeMinusBtn) self.TimeTxt = wx.TextCtrl(self.Panel, wx.ID_ANY, "Time", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.TimeTxt.Bind(wx.EVT_TEXT_ENTER, self.onTimeTxt) self.TimePlusBtn = wx.Button(self.Panel, wx.ID_ANY, ">") self.TimePlusBtn.Bind(wx.EVT_BUTTON, self.onTimePlusBtn) self.LabelLevel = wx.StaticText(self.Panel,-1,label="Choose level (level>0, depth<=0)",style = wx.ALIGN_CENTER) self.LabelMinMaxLevel = wx.StaticText(self.Panel, wx.ID_ANY, " ", style=wx.ALIGN_LEFT) self.LabelMinMaxDepth = wx.StaticText(self.Panel, wx.ID_ANY, " ", style=wx.ALIGN_LEFT) self.LevelMinusBtn = wx.Button(self.Panel, wx.ID_ANY, "<") self.LevelMinusBtn.Bind(wx.EVT_BUTTON, self.onLevelMinusBtn) self.LevelTxt = wx.TextCtrl(self.Panel, wx.ID_ANY, "Level", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.LevelTxt.Bind(wx.EVT_TEXT_ENTER, self.onLevelTxt) self.LevelPlusBtn = wx.Button(self.Panel, wx.ID_ANY, ">") self.LevelPlusBtn.Bind(wx.EVT_BUTTON, self.onLevelPlusBtn) self.LonSectionBtn = wx.Button(self.Panel, wx.ID_ANY, "Longitude Section") self.LonSectionBtn.Bind(wx.EVT_BUTTON, self.onLonSectionBtn) self.LonSectionTxt = wx.TextCtrl(self.Panel, wx.ID_ANY, "Longitude", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.LonSectionTxt.Bind(wx.EVT_TEXT_ENTER, self.onLonSectionTxt) self.LatSectionBtn = wx.Button(self.Panel, wx.ID_ANY, "Latitude Section") self.LatSectionBtn.Bind(wx.EVT_BUTTON, self.onLatSectionBtn) self.LatSectionTxt = wx.TextCtrl(self.Panel, wx.ID_ANY, "Latitude", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.LatSectionTxt.Bind(wx.EVT_TEXT_ENTER, self.onLatSectionTxt) # self.HovmullerBtn = wx.Button(self.Panel, wx.ID_ANY, "Hovmuller") # self.HovmullerBtn.Bind(wx.EVT_BUTTON, self.onHovmullerBtn) self.TimeSeriesBtn = wx.Button(self.Panel, wx.ID_ANY, "Time Series") self.TimeSeriesBtn.Bind(wx.EVT_BUTTON, self.onTimeSeriesBtn) self.VerticalProfileBtn = wx.Button(self.Panel, wx.ID_ANY, "Vertical Profile") self.VerticalProfileBtn.Bind(wx.EVT_BUTTON, self.onVerticalProfileBtn) self.PanelCanvas = wx.Panel(self.Panel, -1) self.figure = Figure(figsize=(figsize[0],figsize[1])) self.canvas = FigureCanvas(self.PanelCanvas, -1, self.figure) self.AnimationBtn = wx.Button(self.Panel, wx.ID_ANY, "Animation") self.AnimationBtn.Bind(wx.EVT_BUTTON, self.onAnimationBtn) self.startTimeTxt = wx.TextCtrl(self.Panel, wx.ID_ANY, "1", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.startTimeTxt.Bind(wx.EVT_TEXT_ENTER, self.onstartTimeTxt) self.endTimeTxt = wx.TextCtrl(self.Panel, wx.ID_ANY, "1", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.endTimeTxt.Bind(wx.EVT_TEXT_ENTER, self.onendTimeTxt) self.ZoomInBtn = wx.Button(self.Panel, wx.ID_ANY, "Zoom In") self.ZoomInBtn.Bind(wx.EVT_BUTTON, self.onZoomInBtn) self.ZoomOutBtn = wx.Button(self.Panel, wx.ID_ANY, "Zoom Out") self.ZoomOutBtn.Bind(wx.EVT_BUTTON, self.onZoomOutBtn) self.PrintBtn = wx.Button(self.Panel, wx.ID_ANY, "Print") self.PrintBtn.Bind(wx.EVT_BUTTON, self.onPrintBtn) # self.__set_properties() self.__do_layout() self.sectionXY = SectionFrame() self.currentDirectory = os.getcwd() def __do_layout(self): topSizer = wx.BoxSizer(wx.HORIZONTAL) leftSizer = wx.BoxSizer(wx.VERTICAL) rightSizer = wx.BoxSizer(wx.VERTICAL) openFileSizer = wx.BoxSizer(wx.VERTICAL) chooseVariablesSizer = wx.BoxSizer(wx.HORIZONTAL) colorSizer = wx.BoxSizer(wx.HORIZONTAL) labelTimeSizer = wx.BoxSizer(wx.HORIZONTAL) labelMinMaxTimeSizer = wx.BoxSizer(wx.HORIZONTAL) timeSizer = wx.BoxSizer(wx.HORIZONTAL) labelLevelSizer = wx.BoxSizer(wx.HORIZONTAL) labelMinMaxLevelSizer = wx.BoxSizer(wx.HORIZONTAL) labelMinMaxDepthSizer = wx.BoxSizer(wx.HORIZONTAL) levelSizer = wx.BoxSizer(wx.HORIZONTAL) longitudeSizer = wx.BoxSizer(wx.HORIZONTAL) latitudeSizer = wx.BoxSizer(wx.HORIZONTAL) # hovmullerSizer = wx.BoxSizer(wx.HORIZONTAL) timeSeriesSizer = wx.BoxSizer(wx.HORIZONTAL) profileSizer = wx.BoxSizer(wx.HORIZONTAL) canvasSizer = wx.BoxSizer(wx.VERTICAL) buttonsSizer = wx.BoxSizer(wx.HORIZONTAL) openFileSizer.Add(self.OpenFileBtn, 0, wx.ALL, 5) openFileSizer.Add(self.OpenFileTxt, 1, wx.ALL|wx.EXPAND, 5) chooseVariablesSizer.Add(self.CrocoVariableChoice, 0, wx.ALL, 5) chooseVariablesSizer.Add(self.DerivedVariableChoice, 0, wx.ALL, 5) colorSizer.Add(self.ResetColorBtn, 0, wx.ALL, 5) colorSizer.Add(self.MinColorTxt, 0, wx.ALL, 5) colorSizer.Add(self.MaxColorTxt, 0, wx.ALL, 5) labelTimeSizer.Add(self.LabelTime, 0, wx.ALL|wx.EXPAND, 5) labelMinMaxTimeSizer.Add(self.LabelMinMaxTime, 0, wx.ALL|wx.EXPAND, 5) timeSizer.Add(self.TimeMinusBtn, 0, wx.ALL, 5) timeSizer.Add(self.TimeTxt, 0, wx.ALL, 5) timeSizer.Add(self.TimePlusBtn, 0, wx.ALL, 5) labelLevelSizer.Add(self.LabelLevel, 0, wx.ALL|wx.EXPAND, 5) labelMinMaxLevelSizer.Add(self.LabelMinMaxLevel, 0, wx.ALL|wx.EXPAND, 5) labelMinMaxDepthSizer.Add(self.LabelMinMaxDepth, 0, wx.ALL|wx.EXPAND, 5) levelSizer.Add(self.LevelMinusBtn, 0, wx.ALL, 5) levelSizer.Add(self.LevelTxt, 0, wx.ALL, 5) levelSizer.Add(self.LevelPlusBtn, 0, wx.ALL, 5) longitudeSizer.Add(self.LonSectionBtn, 0, wx.ALL, 5) longitudeSizer.Add(self.LonSectionTxt, 0, wx.ALL, 5) latitudeSizer.Add(self.LatSectionBtn, 0, wx.ALL, 5) latitudeSizer.Add(self.LatSectionTxt, 0, wx.ALL, 5) # hovmullerSizer.Add(self.HovmullerBtn, 0, wx.ALL, 5) timeSeriesSizer.Add(self.TimeSeriesBtn, 0, wx.ALL, 5) profileSizer.Add(self.VerticalProfileBtn, 0, wx.ALL, 5) canvasSizer.Add(self.PanelCanvas, 1, wx.EXPAND , 5) buttonsSizer.Add(self.AnimationBtn,0, wx.ALL, 5) buttonsSizer.Add(self.startTimeTxt,1, wx.ALL, 5) buttonsSizer.Add(self.endTimeTxt,1, wx.ALL, 5) buttonsSizer.Add(self.ZoomInBtn,0, wx.ALL, 5) buttonsSizer.Add(self.ZoomOutBtn,0, wx.ALL, 5) buttonsSizer.Add(self.PrintBtn,0, wx.ALL, 5) leftSizer.Add(openFileSizer, 0,wx.ALL|wx.EXPAND, 5 ) leftSizer.Add(chooseVariablesSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(labelTimeSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(labelMinMaxTimeSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(timeSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(labelLevelSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(labelMinMaxLevelSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(labelMinMaxDepthSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(levelSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(longitudeSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(latitudeSizer, 0, wx.ALL|wx.EXPAND, 5) # leftSizer.Add(hovmullerSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(timeSeriesSizer, 0, wx.ALL|wx.EXPAND, 5) leftSizer.Add(profileSizer, 0, wx.ALL|wx.EXPAND, 5) rightSizer.Add(canvasSizer, 0, wx.EXPAND) rightSizer.Add(buttonsSizer, 0, wx.ALL|wx.EXPAND, 5) rightSizer.Add(colorSizer, 0, wx.ALL|wx.EXPAND, 5) topSizer.Add(leftSizer, 0,wx.ALL|wx.EXPAND, 5 ) topSizer.Add(rightSizer, 0,wx.EXPAND, 5 ) self.Panel.SetSizer(topSizer) self.Panel.SetAutoLayout(True) topSizer.Fit(self) self.Layout() def onOpenFile(self, event): """ Create and show the Open FileDialog to choose the croco file """ # get path of current script croco_gui.py path_script = os.path.dirname(os.path.realpath(__file__)) # show the dialog box and retrieve the path of the file dlg = wx.FileDialog( self, message="Choose a file", defaultDir=self.currentDirectory, defaultFile="", wildcard=wildcard, style=wx.FD_OPEN | wx.FD_MULTIPLE | wx.FD_CHANGE_DIR ) if dlg.ShowModal() == wx.ID_OK: paths = dlg.GetPaths() dlg.Destroy() # Create a instance of the Croco class self.croco = Croco(paths[0]) # get path of current script croco_gui.py self.croco.path_script = path_script # Fill the different parts of the main window from the croco instance self.OpenFileTxt.SetLabel(paths[0]) self.LabelMinMaxTime.SetLabel("Min/Max Time = "+str(self.croco.times[0])+" ... "+ \ str(self.croco.times[self.croco.crocoGrid.ntimes-1])) self.TimeTxt.SetValue(str(self.croco.times[0])) self.timeIndex = 0 self.time = self.croco.times[0] minLevel = 1 maxLevel = int(self.croco.crocoGrid.N) minDepth = - int(self.croco.crocoGrid.h().max()) maxDepth = 0 self.LabelMinMaxLevel.SetLabel("Min/Max Level = 1 ... "+ str(maxLevel)) self.LabelMinMaxDepth.SetLabel("Min/Max Depth = "+ str(minDepth)+" ... "+str(maxDepth)) self.LevelTxt.SetValue(str(self.croco.crocoGrid.N)) self.levelIndex=self.croco.crocoGrid.N - 1 self.startTimeTxt.SetValue(str(self.croco.times[0])) self.startTime = self.croco.times[0] self.startTimeIndex = 0 self.endTimeTxt.SetValue(str(self.croco.times[-1])) self.endTime = self.croco.times[-1] self.endTimeIndex = self.croco.crocoGrid.ntimes -1 self.CrocoVariableChoice.AppendItems(self.croco.ListOfVariables) self.DerivedVariableChoice.AppendItems(self.croco.ListOfDerived) self.lonPress = self.croco.crocoGrid.lon()[int(0.5*self.croco.crocoGrid.M),int(0.5*self.croco.crocoGrid.L)] self.latPress = self.croco.crocoGrid.lat()[int(0.5*self.croco.crocoGrid.M),int(0.5*self.croco.crocoGrid.L)] self.latPressIndex,self.lonPressIndex = self.findLatLonIndex(self.lonPress, self.latPress) self.LonSectionTxt.SetValue('%.2F' % self.lonPress) self.LatSectionTxt.SetValue('%.2F' % self.latPress) def onFigureClick(self,event): self.lonPress, self.latPress = event.xdata, event.ydata self.latPressIndex,self.lonPressIndex = self.findLatLonIndex(self.lonPress, self.latPress) self.LonSectionTxt.SetValue('%.2F' % self.lonPress) self.LatSectionTxt.SetValue('%.2F' % self.latPress) def onFigureRelease(self,event): self.lonRelease, self.latRelease = event.xdata, event.ydata self.lonReleaseIndex,self.latReleaseIndex = self.findLatLonIndex(self.lonRelease, self.latRelease) def rect_select_callback(self, eclick, erelease): ''' Function to select a rectangle when zoom in ''' self.xPress, self.yPress = eclick.xdata, eclick.ydata self.xRelease, self.yRelease = erelease.xdata, erelease.ydata self.xlim = [min(self.xPress,self.xRelease),max(self.xPress,self.xRelease)] self.ylim = [ min(self.yPress,self.yRelease),max(self.yPress,self.yRelease)] self.drawxy(setlim=False) def findLatLonIndex(self, lonValue, latValue): ''' Find nearest value is an array ''' a = abs(self.croco.crocoGrid._lon - lonValue) + \ abs(self.croco.crocoGrid._lat - latValue) return np.unravel_index(a.argmin(),a.shape) # idx,idy = np.where(np.abs(array-value)==np.abs(array-value).min()) def onCrocoVariableChoice(self, event): self.variableName = self.CrocoVariableChoice.GetString(self.CrocoVariableChoice.GetSelection()) self.updateVariableXY() def onDerivedVariableChoice(self, event): self.variableName = self.DerivedVariableChoice.GetString(self.DerivedVariableChoice.GetSelection()) self.updateVariableXY() def onResetColorBtn(self,event): self.clim = [np.min(self.variableXY),np.max(self.variableXY)] self.MinColorTxt.SetValue('%.2E' % self.clim[0]) self.MaxColorTxt.SetValue('%.2E' % self.clim[1]) self.drawxy() def onMinColorTxt(self,event): self.clim[0] = float(self.MinColorTxt.GetValue()) self.drawxy(setlim=False) def onMaxColorTxt(self,event): self.clim[1] = float(self.MaxColorTxt.GetValue()) self.drawxy(setlim=False) def onTimeMinusBtn(self,event): self.timeIndex = max(self.timeIndex - 1,0) self.time = self.croco.times[self.timeIndex] self.TimeTxt.SetValue(str(self.time)) self.updateVariableXY(setlim=False) def onTimePlusBtn(self,event): self.timeIndex = min(self.timeIndex + 1,self.croco.crocoGrid.ntimes - 1) self.time = self.croco.times[self.timeIndex] self.TimeTxt.SetValue(str(self.time)) self.updateVariableXY(setlim=False) def onTimeTxt(self,event): time = float(self.TimeTxt.GetValue()) # find index corresponding to instant time to plot self.timeIndex = min( range( len(self.croco.times[:]) ), key=lambda j:abs(time-self.croco.times[j])) self.TimeTxt.SetValue(str(self.croco.times[self.timeIndex])) self.updateVariableXY(setlim=False) def onLevelMinusBtn(self,event): self.levelIndex = max(self.levelIndex - 1,0) self.LevelTxt.SetValue(str(self.levelIndex + 1)) self.updateVariableXY(setlim=False) def onLevelPlusBtn(self,event): self.levelIndex = min(self.levelIndex + 1,self.croco.crocoGrid.N - 1) self.LevelTxt.SetValue(str(self.levelIndex + 1)) self.updateVariableXY(setlim=False) def onLevelTxt(self,event): depth = float(self.LevelTxt.GetValue()) if depth > 0: self.levelIndex = int(depth)-1 else: zeta = self.croco.read_nc('ssh', indices= "["+str(self.timeIndex)+",:,:]") z = self.croco.crocoGrid.scoord2z_r(zeta, alpha=0., beta=0.) self.levelIndex = np.argmax(z[:,self.latPressIndex,self.lonPressIndex]>=depth) self.updateVariableXY(setlim=False) def onLonSectionBtn(self,event): try: nbdims = len(self.croco.read_var_dim(self.variableName)) except: nbdims = 4 if nbdims < 4 : print("Not 3D variable") return self.drawz(typSection="YZ") def onLonSectionTxt(self,event): try: nbdims = len(self.croco.read_var_dim(self.variableName)) except: nbdims = 4 if nbdims < 4 : print("Not 3D variable") return self.lonPress = float(self.LonSectionTxt.GetValue()) self.latPressIndex,self.lonPressIndex = self.findLatLonIndex(self.lonPress, self.latPress) self.drawz(typSection="YZ") def onLatSectionBtn(self,event): try: nbdims = len(self.croco.read_var_dim(self.variableName)) except: nbdims = 4 if nbdims < 4 : print("Not 3D variable") return self.drawz(typSection="XZ") def onLatSectionTxt(self,event): try: nbdims = len(self.croco.read_var_dim(self.variableName)) except: nbdims = 4 if nbdims < 4 : print("Not 3D variable") return self.latPress = float(self.LatSectionTxt.GetValue()) self.latPressIndex,self.lonPressIndex = self.findLatLonIndex(self.lonPress, self.latPress) self.drawz(typSection="XZ") # def onHovmullerBtn(self,event): # print("Hovmuller") def onTimeSeriesBtn(self,event): self.getTimeSeries() def onVerticalProfileBtn(self,event): try: nbdims = len(self.croco.read_var_dim(self.variableName)) except: nbdims = 4 if nbdims < 4 : print("Not 3D variable") return self.getVertProfile() def onAnimationBtn(self,event): printDir = self.croco.path_script+"/Figures_" + self.croco.get_run_name()+"/" if not os.path.isdir(printDir): os.mkdir(printDir) filename = printDir+self.title + ".mp4" os.system('rm -rf '+filename) save_count = self.endTimeIndex - self.startTimeIndex + 1 anim = animation.FuncAnimation(self.figure, self.animate, \ frames = range(self.startTimeIndex,self.endTimeIndex+1), repeat=False, \ blit = False, save_count=save_count) self.canvas.draw() anim.save(filename) def animate( self, i): ''' function applied at each time step of the animation ''' self.timeIndex = i self.updateVariableXY(setlim=False) def onstartTimeTxt(self,event): self.startTime = float(self.startTimeTxt.GetValue()) self.startTimeIndex = min( range( len(self.croco.times[:]) ), key=lambda j:abs(self.startTime-self.croco.times[j])) self.startTimeTxt.SetValue(str(self.croco.times[self.startTimeIndex])) def onendTimeTxt(self,event): self.endTime = float(self.endTimeTxt.GetValue()) self.endTimeIndex = min( range( len(self.croco.times[:]) ), key=lambda j:abs(self.endTime-self.croco.times[j])) self.endTimeTxt.SetValue(str(self.croco.times[self.endTimeIndex])) def rect_select_callback(self, eclick, erelease): self.xPress, self.yPress = eclick.xdata, eclick.ydata self.xRelease, self.yRelease = erelease.xdata, erelease.ydata self.xlim = [min(self.xPress,self.xRelease),max(self.xPress,self.xRelease)] self.ylim = [ min(self.yPress,self.yRelease),max(self.yPress,self.yRelease)] self.drawxy(setlim=False) def onZoomInBtn(self,event): self.figure.RS.set_active(True) def onZoomOutBtn(self,event): self.xlim = [np.min(self.croco.crocoGrid._lon),np.max(self.croco.crocoGrid._lon)] self.ylim = [np.min(self.croco.crocoGrid._lat),np.max(self.croco.crocoGrid._lat)] self.drawxy(setlim=False) def onPrintBtn(self,event): printDir = self.croco.path_script+"/Figures_" + self.croco.get_run_name()+"/" if not os.path.isdir(printDir): os.mkdir(printDir) filename = printDir+self.title + ".png" self.figure.savefig(filename, dpi=self.figure.dpi) def updateVariableXY(self,setlim=True): ''' Fill the variable self.variableXY with the rigth data''' time = str(self.timeIndex) depth = float(self.LevelTxt.GetValue()) try: dims = self.croco.read_var_dim(self.variableName) except: dims = [] if "x_u" in dims: mask = self.croco.crocoGrid.umask() elif "y_v" in dims: mask = self.croco.crocoGrid.vmask() else: mask = self.croco.crocoGrid.maskr() mask = np.where(mask==0.,np.nan,mask) # Level plot if depth > 0: level = str(int(depth)-1) if self.variableName in self.croco.ListOfVariables: try: self.variableXY = self.croco.read_nc(self.variableName, indices= "["+time+","+level+",:,:]") except Exception: try: self.variableXY = self.croco.read_nc(self.variableName, indices= "["+time+",:,:]") except Exception: raise Exception elif self.variableName in self.croco.ListOfDerived: # depth = float(self.LevelTxt.GetValue()) # if self.variableName == 'pv': if 'pv' in self.variableName: self.variableXY = self.croco.get_pv(self.timeIndex, depth=depth,typ=self.variableName) else: print("unknown variable ",self.variableName) return self.variableXY = mask*self.variableXY # depth plot elif depth <= 0: zeta = self.croco.read_nc('ssh', indices= "["+time+",:,:]") z = self.croco.crocoGrid.scoord2z_r(zeta, alpha=0., beta=0.) if "x_u" in dims: z = self.croco.crocoGrid.rho2u_3d(z) elif "y_v" in dims: z = self.croco.crocoGrid.rho2v_3d(z) minlev,maxlev = self.croco.crocoGrid.zslice(None,self.croco.crocoGrid.maskr(),z,depth,findlev=True) # Variable from croco file if self.variableName in self.croco.ListOfVariables: indices= "["+time+","+str(minlev)+":"+str(maxlev+1)+",:,:]" var = self.croco.read_nc(self.variableName, indices=indices) try: self.variableXY = self.croco.crocoGrid.zslice(var[:,:,:],mask,z[minlev:maxlev+1,:,:],depth)[0] # self.drawxy(setlim=False) except: print("Not enough points") pass # Derived variableXY elif self.variableName in self.croco.ListOfDerived: # if self.variableName == 'pv': if 'pv' in self.variableName: pv = self.croco.get_pv(self.timeIndex, depth=depth, minlev=minlev, maxlev=maxlev,typ=self.variableName) try: self.variableXY = self.croco.crocoGrid.zslice(pv,mask,z[minlev:maxlev,:,:],depth)[0] except: print("Not enough points") pass # Draw the new self.variableXY self.drawxy(setlim=setlim) def drawxy(self,setlim=True): ''' Draw the current variable self.variableXY in the canvas of the main window ''' self.figure.clf() # Prepare the canvas to receive click events self.canvas.mpl_connect('button_press_event', self.onFigureClick) self.canvas.mpl_connect('button_release_event', self.onFigureRelease) variableXY = ma.masked_invalid(self.variableXY) # Set default parameters of the plot if needed if setlim: self.clim = [np.min(variableXY),np.max(variableXY)] self.mincolor = np.min(variableXY) self.MinColorTxt.SetValue('%.2E' % self.mincolor) self.maxcolor = np.max(variableXY) self.MaxColorTxt.SetValue('%.2E' % self.maxcolor) self.xlim = [np.min(self.croco.crocoGrid._lon),np.max(self.croco.crocoGrid._lon)] self.ylim = [np.min(self.croco.crocoGrid._lat),np.max(self.croco.crocoGrid._lat)] depth = float(self.LevelTxt.GetValue()) # Level pyplot if depth > 0: self.title = "{:s}, Level={:4d}, Time={:4.1f}".format(self.variableName,self.levelIndex+1,self.croco.times[self.timeIndex]) # Depth plot else: self.title = "{:s}, Depth={:4.1f}, Time={:4.1f}".format(self.variableName,depth,self.croco.times[self.timeIndex]) mypcolor(self,self.croco.crocoGrid._lon,self.croco.crocoGrid._lat,variableXY,\ title=self.title,\ xlabel='Longitude',\ ylabel='Latitude',\ xlim=self.xlim,\ ylim=self.ylim,\ clim=self.clim) self.canvas.draw() self.canvas.Refresh() self.Refresh() def drawz(self,typSection=None): ''' Create a section window if needed and prepare the of the plot the section ''' time = str(self.timeIndex) lon = str(self.lonPressIndex) lat = str(self.latPressIndex) zeta = self.croco.read_nc('ssh', indices= "["+time+",:,:]") if typSection == "XZ": # Create the window if needed try: self.sectionXZ.IsShown() except: self.sectionXZ = SectionFrame(typSection="XZ", croco=self.croco) section = self.sectionXZ section.section = "Latitude" section.xlabel = "Longitude" section.latlon = self.latPress section.latlonIndex = self.latPressIndex section.x = repmat(self.croco.crocoGrid._lon[self.latPressIndex,:].squeeze(),self.croco.crocoGrid.N,1) section.y = self.croco.crocoGrid.scoord2z_r(zeta, alpha=0., beta=0)[:,self.latPressIndex,:] # Variable from croco file if self.variableName in self.croco.ListOfVariables: section.variableZ = self.croco.read_nc(self.variableName, indices= "["+time+",:,"+lat+",:]") # Derived Variable elif self.variableName in self.croco.ListOfDerived: if 'pv' in self.variableName: pv = self.croco.get_pv(self.timeIndex, minlev=0, maxlev=self.croco.crocoGrid.N-1,typ=self.variableName) section.variableZ = pv[:,self.latPressIndex,:] elif typSection == "YZ": # Create the window if needed try: self.sectionYZ.IsShown() except: self.sectionYZ = SectionFrame(typSection="YZ", croco=self.croco) section = self.sectionYZ section.section = "Longitude" section.xlabel = "Latitude" section.latlon = self.lonPress section.latlonIndex = self.lonPressIndex section.x = repmat(self.croco.crocoGrid._lat[:,self.lonPressIndex].squeeze(),self.croco.crocoGrid.N,1) section.y = self.croco.crocoGrid.scoord2z_r(zeta, alpha=0., beta=0)[:,:,self.lonPressIndex] # Variable from croco file if self.variableName in self.croco.ListOfVariables: section.variableZ = self.croco.read_nc(self.variableName, indices= "["+time+",:,:,"+lon+"]") # Derived Variable elif self.variableName in self.croco.ListOfDerived: # if self.variableName == 'pv': if 'pv' in self.variableName: pv = self.croco.get_pv(self.timeIndex, minlev=0, maxlev=self.croco.crocoGrid.N-1,typ=self.variableName) section.variableZ = pv[:,:,self.lonPressIndex] else: print("drawz: unknown type section: ",typSection) return section.variableName = self.variableName section.time = self.croco.times[self.timeIndex] section.timeIndex = self.timeIndex section.startTimeTxt.SetValue(str(self.croco.times[0])) section.startTime = self.croco.times[0] section.startTimeIndex = 0 section.endTimeTxt.SetValue(str(self.croco.times[-1])) section.endTime = self.croco.times[-1] section.endTimeIndex = self.croco.crocoGrid.ntimes -1 section.drawz() def getTimeSeries(self,profTyp=None): ''' Fill the profile variable of the time series''' lat = str(self.latPressIndex) lon = str(self.lonPressIndex) # timestr = str(self.timeIndex) depth = float(self.LevelTxt.GetValue()) # Create window for time series is needed try: self.profileFrame.IsShown() except Exception: self.profileFrame = ProfileFrame(self.croco) try: dims = self.croco.read_var_dim(self.variableName) except: dims=[] if "x_u" in dims: mask = self.croco.crocoGrid.umask() elif "y_v" in dims: mask = self.croco.crocoGrid.vmask() else: mask = self.croco.crocoGrid.maskr() # Time series on one level if depth > 0: if self.variableName in self.croco.ListOfVariables: level = str(int(depth)-1) print("getTimeSeries: indices=", "[:,"+level+","+lat+","+lon+"]") profile = self.croco.read_nc(self.variableName, indices= "[:,"+level+","+lat+","+lon+"]") elif self.variableName in self.croco.ListOfDerived: level = int(depth) profile = np.zeros_like(self.croco.times) for it in range(len(self.croco.times)): # if self.variableName == 'pv': if 'pv' in self.variableName: profile[it] = self.croco.get_pv(it, depth=level,typ=self.variableName)[self.latPressIndex,self.lonPressIndex] else: print("unknown variable ",self.variableName) return title="{:s}, Lon={:4.1f}, Lat={:4.1f}, level={:4.1f}".\ format(self.variableName,self.lonPress,self.latPress,self.levelIndex+1) # Time series on one depth elif depth <= 0: profile = np.zeros_like(self.croco.times) # for each time step for it in range(len(self.croco.times)): # Calculate z zeta = self.croco.read_nc('ssh', indices= "["+str(it)+",:,:]") z = self.croco.crocoGrid.scoord2z_r(zeta, alpha=0., beta=0.) if "x_u" in dims: z = self.croco.crocoGrid.rho2u_3d(z) elif "y_v" in dims: z = self.croco.crocoGrid.rho2v_3d(z) if self.variableName in self.croco.ListOfVariables: # Find level araound depth maxlev = np.argmax(z[:,self.latPressIndex,self.lonPressIndex]>=depth) minlev = maxlev-1 z1 = z[minlev,self.latPressIndex,self.lonPressIndex] z2 = z[maxlev,self.latPressIndex,self.lonPressIndex] # read variable and do interpolation indices= "["+str(it)+","+str(minlev)+":"+str(maxlev+1)+","+lat+","+lon+"]" var = self.croco.read_nc(self.variableName, indices=indices) profile[it]=((var[0]-var[1])*depth+var[1]*z1-var[0]*z2)/(z1-z2) * \ mask[self.latPressIndex,self.lonPressIndex] elif self.variableName in self.croco.ListOfDerived: minlev,maxlev = self.croco.crocoGrid.zslice(None,mask,z,depth,findlev=True) # if self.variableName == 'pv': if 'pv' in self.variableName: pv = self.croco.get_pv(it, depth=depth, minlev=minlev, maxlev=maxlev,typ=self.variableName) try: pvz = self.croco.crocoGrid.zslice(pv,mask,z[minlev:maxlev,:,:],depth)[0] except: print("Not enough points") pass profile[it]=pvz[self.latPressIndex,self.lonPressIndex] title="{:s}, Lon={:4.1f}, Lat={:4.1f}, depth={:4.1f}".\ format(self.variableName,self.lonPress,self.latPress,depth) # draw curve self.profileFrame.drawCurv(profile,title=title) def getVertProfile(self): ''' Fill the profile variable for the vertical profile''' time = str(self.timeIndex) lat = str(self.latPressIndex) lon = str(self.lonPressIndex) title="{:s}, Lon={:4.1f}, Lat={:4.1f}, Time={:4.1f}".\ format(self.variableName,self.lonPress,self.latPress,\ self.croco.times[self.timeIndex]) zeta = self.croco.read_nc('ssh', indices= "["+time+",:,:]") z = self.croco.crocoGrid._scoord2z('r', zeta, alpha=0., beta=0)[0][:,self.latPressIndex,self.lonPressIndex] if self.variableName in self.croco.ListOfVariables: profile = self.croco.read_nc(self.variableName, indices= "["+time+",:,"+lat+","+lon+"]") elif self.variableName in self.croco.ListOfDerived: # if self.variableName == 'pv': if 'pv' in self.variableName: profile = np.full_like(z, np.nan) pv = self.croco.get_pv(self.timeIndex, minlev=0, maxlev=self.croco.crocoGrid.N-1,typ=self.variableName) profile[1:] = pv[:,self.latPressIndex,self.lonPressIndex] else: print("unknown variable ",self.variableName) return try: self.profileFrame.IsShown() except: self.profileFrame = ProfileFrame(self.croco) self.profileFrame.drawCurv(profile=profile,z=z,title=title,ylabel="depth")
class Plotter(IOTABasePanel): ''' Generic Plotter (will plot anything given specific data) ''' def __init__(self, parent, params=None, info=None, *args, **kwargs): IOTABasePanel.__init__(self, parent=parent, *args, **kwargs) self.info = info self.params = params self.font = {'fontfamily': 'sans-serif', 'fontsize': 12} # For resizing. The idea is to allow the figures to resize only when the # screen is idle; if anything, it'll make window resizing smoother self._resize_flag = False self.Bind(wx.EVT_IDLE, self.onIdle) self.Bind(wx.EVT_SIZE, self.onSize) def onSize(self, e): self._resize_flag = True def onIdle(self, e): if self._resize_flag: self._resize_flag = False self.set_size() def set_size(self): self.set_size_to_panel() def set_size_to_panel(self): size_in_pixels = tuple(self.GetSize()) self.SetSize(size_in_pixels) self.canvas.SetSize(size_in_pixels) size_in_inches = [ float(x) / self.figure.get_dpi() for x in size_in_pixels ] self.figure.set_size_inches(size_in_inches) def set_size_to_canvas(self): size_in_pixels = tuple(self.canvas.GetSize()) self.SetSize(size_in_pixels) self.canvas.SetSize(size_in_pixels) size_in_inches = [ float(x) / self.figure.get_dpi() for x in size_in_pixels ] self.figure.set_size_inches(size_in_inches) def initialize_figure(self, figsize=(9, 9), transparent=True): self.figure = Figure(figsize=figsize) self.canvas = FigureCanvas(self, -1, self.figure) self.main_sizer.Add(self.canvas, 1, flag=wx.EXPAND) if transparent: if wx.Platform == '__WXMAC__': self.figure.patch.set_visible(False) else: bg_color = [i / 255 for i in self.GetBackgroundColour()] self.figure.set_facecolor(color=bg_color) def draw(self, size_to_canvas=False, tight_layout=True): if size_to_canvas: self.set_size_to_canvas() else: self.set_size_to_panel() if tight_layout: self.figure.tight_layout() self.canvas.draw() self.canvas.Refresh() def plot_table_text(self, data): data = [[to_unicode(i) for i in j] for j in data] stripes = zip(*data) col_ws = [max([len(i) for i in strp]) for strp in stripes] set_ws = [5 if i <= 3 else i + 2 for i in col_ws] lines = [] for item in data: for i in item: idx = item.index(i) width = set_ws[idx] item[idx] = i.ljust(width, u' ') line = u''.join(item) lines.append(line) table_txt = u'\n'.join(lines) return table_txt def plot_table(self, data): # allow straight text to be passed on if type(data) in (list, tuple): table_text = self.plot_table_text(data=data) elif type(data) in (str, unicode): table_text = data else: table_text = None if not table_text: raise Sorry( 'IOTA PLOTTER ERROR: Cannot make table! NoneType object ' 'passed instead of string, unicode, list, or tuple') self.table = self.figure.text(0, 0.99, table_text, family='monospace', va='top') self.draw() def plot_res_histogram(self): # Get resolution values hres = list(zip(*self.info.stats['res']['lst']))[2] lres = list(zip(*self.info.stats['lres']['lst']))[2] # Plot figure gsp = gridspec.GridSpec(2, 1) hr = self.figure.add_subplot(gsp[0, :]) hr_n, hr_bins, hr_patches = hr.hist(hres, 20, facecolor='b', alpha=0.75, histtype='stepfilled') hr_height = (np.max(hr_n) + 9) // 10 * 10 hr.axis([np.min(hres), np.max(hres), 0, hr_height]) reslim = 'High Resolution Limit ({})'.format(r'$\AA$') hr.set_xlabel(reslim, fontsize=15) hr.set_ylabel('No. of frames', fontsize=15) lr = self.figure.add_subplot(gsp[1, :]) lr_n, lr_bins, lr_patches = lr.hist(lres, 20, facecolor='b', alpha=0.75, histtype='stepfilled') lr_height = (np.max(lr_n) + 9) // 10 * 10 lr.axis([np.min(lres), np.max(lres), 0, lr_height]) reslim = 'Low Resolution Limit ({})'.format(r'$\AA$') lr.set_xlabel(reslim, fontsize=15) lr.set_ylabel('No. of frames', fontsize=15) self.draw(tight_layout=False) def plot_spotfinding_heatmap(self): hlist = self.info.stats['h']['lst'] alist = self.info.stats['a']['lst'] ch = max(hlist) - min(hlist) + 1 ca = max(alist) - min(alist) + 1 ints = list(zip(hlist, alist)) ic = Counter(ints) hm_data = np.zeros((ch, ca)) for i in ic.items(): hm_data[i[0][0] - min(hlist), i[0][1] - min(alist)] = i[1] rows = range(min(hlist), max(hlist) + 1) cols = range(min(alist), max(alist) + 1) row_labels = [str(i) for i in rows] col_labels = [str(j) for j in cols] ax = self.figure.add_subplot(111) ax.pcolor(hm_data, cmap='Reds') ax.set_yticks(np.arange(len(rows)) + .5, minor=False) ax.set_xticks(np.arange(len(cols)) + .5, minor=False) ax.set_yticklabels(row_labels, minor=False) ax.set_xticklabels(col_labels, minor=False) ax.set_xlabel('Spot area') ax.set_ylabel('Spot height') ax.set_xlim(0, len(cols)) ax.set_ylim(0, len(rows)) # Annotate for y in range(hm_data.shape[0]): for x in range(hm_data.shape[1]): ax.text( x + 0.5, y + 0.5, '%3d' % hm_data[y, x], horizontalalignment='center', verticalalignment='center', ) self.draw(tight_layout=False) def plot_beam_xy(self, write_files=False, return_values=False, threeD=False): """ Plot beam center coordinates and a histogram of distances from the median of beam center coordinates to each set of coordinates. Superpose a predicted mis-indexing shift by L +/- 1 (calculated for each axis). """ # Calculate beam center coordinates and distances beamX = list(zip(*self.info.stats['beamX']['lst']))[2] beamY = list(zip(*self.info.stats['beamY']['lst']))[2] beamZ = list(zip(*self.info.stats['distance']['lst']))[2] beamXY = list(zip(beamX, beamY)) beam_dist = [ math.hypot(i[0] - np.median(beamX), i[1] - np.median(beamY)) for i in beamXY ] beam_dist_std = np.std(beam_dist) beamXYdist = list(zip(beamX, beamY, beam_dist)) # Separate out outliers outliers = [i for i in beamXYdist if i[2] > 2 * beam_dist_std] clean = [i for i in beamXYdist if i[2] <= 2 * beam_dist_std] cbeamX = [i[0] for i in clean] cbeamY = [j[1] for j in clean] obeamX = [i[0] for i in outliers] obeamY = [j[1] for j in outliers] wavelength = self.info.stats['wavelength']['median'] det_distance = self.info.stats['distance']['median'] a = np.median([i[0] for i in self.info.cluster_iterable]) b = np.median([i[1] for i in self.info.cluster_iterable]) c = np.median([i[2] for i in self.info.cluster_iterable]) # Calculate predicted L +/- 1 misindexing distance for each cell edge aD = det_distance * math.tan(2 * math.asin(wavelength / (2 * a))) bD = det_distance * math.tan(2 * math.asin(wavelength / (2 * b))) cD = det_distance * math.tan(2 * math.asin(wavelength / (2 * c))) # Plot figure if threeD: self.figure.set_size_inches(w=8, h=8) ax1 = self.figure.add_subplot(111, projection='3d') Axes3D.mouse_init(ax1) else: self.figure.set_size_inches(w=9, h=13) gsp = gridspec.GridSpec(2, 1, height_ratios=[3, 1]) ax1 = self.figure.add_subplot(gsp[0, :], aspect='equal') # Calculate axis limits of beam center scatter plot ax1_delta = np.ceil(np.max(beam_dist)) xmax = round(np.median(beamX) + ax1_delta) xmin = round(np.median(beamX) - ax1_delta) ymax = round(np.median(beamY) + ax1_delta) ymin = round(np.median(beamY) - ax1_delta) zmax = round(np.ceil(self.info.stats['distance']['max'])) zmin = round(np.floor(self.info.stats['distance']['min'])) ax1.set_xlim(xmin, xmax) ax1.set_ylim(ymin, ymax) if threeD: ax1.set_zlim(zmin, zmax) # Plot beam center scatter plot if threeD: ax1.scatter(beamX, beamY, beamZ, alpha=1, s=20, c='grey', lw=1) ax1.plot([self.info.stats['beamX']['median']], [self.info.stats['beamY']['median']], [self.info.stats['distance']['median']], markersize=8, marker='o', c='yellow', lw=2) else: ax1.scatter(cbeamX, cbeamY, alpha=1, s=20, c='grey', lw=1) ax1.scatter(obeamX, obeamY, alpha=1, s=20, c='red', lw=1) ax1.plot(np.median(beamX), np.median(beamY), markersize=8, marker='o', c='yellow', lw=2) # Plot projected mis-indexing limits for all three axes from matplotlib.patches import Circle circle_a = Circle((np.median(beamX), np.median(beamY)), radius=aD, color='r', fill=False, clip_on=True) circle_b = Circle((np.median(beamX), np.median(beamY)), radius=bD, color='g', fill=False, clip_on=True) circle_c = Circle((np.median(beamX), np.median(beamY)), radius=cD, color='b', fill=False, clip_on=True) ax1.add_patch(circle_a) ax1.add_patch(circle_b) ax1.add_patch(circle_c) # Set labels ax1.set_xlabel('BeamX (mm)', fontsize=15) ax1.set_ylabel('BeamY (mm)', fontsize=15) if threeD: ax1.set_zlabel('Distance (mm)', fontsize=15) ax1.set_title('Beam XYZ Coordinates') else: ax1.set_title('Beam XY Coordinates') if not threeD: # Plot histogram of distances to each beam center from median ax2 = self.figure.add_subplot(gsp[1, :]) ax2_n, ax2_bins, ax2_patches = ax2.hist(beam_dist, 20, facecolor='b', alpha=0.75, histtype='stepfilled') ax2_height = (np.max(ax2_n) + 9) // 10 * 10 ax2.axis([0, np.max(beam_dist), 0, ax2_height]) ax2.set_xlabel('Distance from median (mm)', fontsize=15) ax2.set_ylabel('No. of images', fontsize=15) self.draw(tight_layout=False)
class AnimationLeftPanel(wx.Panel): def __init__(self, parent, user_data): """ Initialize everything here """ super(AnimationLeftPanel, self).__init__(parent, style=wx.BORDER_DOUBLE) self.SetBackgroundColour(wx.Colour("White")) self.user_date = user_data self.InitSignalUI() self.Fit() def InitSignalUI(self): vert_box = wx.BoxSizer(wx.VERTICAL) '''Start of middle_tool_box to initialize plotanimation''' middle_tool_box = wx.BoxSizer(wx.HORIZONTAL) # gauge1 = PG.PyGauge(self, -1, size=(70, 5), pos=(20, 50), style=wx.GA_HORIZONTAL) # gauge1.SetValue(70) # # gauge1.SetDrawValue(draw=True, drawPercent=True, font=None, colour=wx.BLACK, formatString=None) # gauge1.SetBackgroundColour(wx.WHITE) # gauge1.SetBorderColor(wx.BLACK) # middle_tool_box.Add(gauge1, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.TOP, 20) self.figure_animation = Figure() self.axes_animation = self.figure_animation.subplots() # self.figure_animation.set_tight_layout(True) self.women_img2 = mpimg.imread('Lx_Icons/Women.png') self.show_img = self.axes_animation.imshow(self.women_img2) self.canvas_animation = FigureCanvasWxAgg(self, -1, self.figure_animation) # self.axes_animation.xticks(np.arange(0,10,1)) # self.axes_animation.get_xaxis().set_visible(False) # self.axes_animation.get_yaxis().set_visible(False) # self.axes_animation.set_axis_off() # self.figure_animation.subplots_adjust(bottom=0, top=1, left=0, right=1) # tight image # self.axes_animation.set_axis_off() self.figure_animation.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0) self.axes_animation.margins(0, 0) self.figure_animation.gca().xaxis.set_major_locator(plt.NullLocator()) self.figure_animation.gca().yaxis.set_major_locator(plt.NullLocator()) middle_tool_box.Add(self.canvas_animation) vert_box.Add(middle_tool_box) # bottom space added '''End of middle_tool_box''' self.bottomToolbar = wx.ToolBar(self, style=wx.TB_HORIZONTAL | wx.EXPAND | wx.TB_FLAT | wx.TB_NODIVIDER) self.bottomToolbar.SetToolBitmapSize(wx.Size(55, 35)) self.bottomToolbar.SetBackgroundColour('#4086aa') for i in range(25): self.bottomToolbar.AddStretchableSpace() img = wx.Image('Lx_Icons/Keyboard_Normal.png').Scale( 55, 35, wx.IMAGE_QUALITY_HIGH) b_keyboard_tool = self.bottomToolbar.AddTool(1, 'Animation', wx.Bitmap(img), 'Animate current signal') self.Bind(wx.EVT_TOOL, self.on_message_window, b_keyboard_tool) img = wx.Image('Lx_Icons/Pitch.png').Scale(55, 35, wx.IMAGE_QUALITY_HIGH) self.b_pitch_tool = self.bottomToolbar.AddTool(2, 'Pitch', wx.Bitmap(img), 'Pitch') self.on_pitch_click(None, init_pitch=True) self.Bind(wx.EVT_TOOL, self.on_pitch_click, self.b_pitch_tool) # for i in range(1): # self.bottomToolbar.AddStretchableSpace() img = wx.Image('Lx_Icons/Level.png').Scale(55, 35, wx.IMAGE_QUALITY_HIGH) b_level_tool = self.bottomToolbar.AddTool(3, 'Animation', wx.Bitmap(img), 'Animate current signal') self.on_level_click(None, init_level=True) self.Bind(wx.EVT_TOOL, self.on_level_click, b_level_tool) # for i in range(1): # self.bottomToolbar.AddStretchableSpace() img = wx.Image('Lx_Icons/LP.png').Scale(55, 35, wx.IMAGE_QUALITY_HIGH) b_lp_tool = self.bottomToolbar.AddTool(4, 'Animation', wx.Bitmap(img), 'Animate current signal') self.Bind(wx.EVT_TOOL, self.on_animate_signal, b_lp_tool) # for i in range(1): # self.bottomToolbar.AddStretchableSpace() img = wx.Image('Lx_Icons/Eye.png').Scale(55, 35, wx.IMAGE_QUALITY_HIGH) b_eye_tool = self.bottomToolbar.AddTool(5, 'Animation', wx.Bitmap(img), 'Animate current signal') self.Bind(wx.EVT_TOOL, self.on_animate_signal, b_eye_tool) # for i in range(1): # self.bottomToolbar.AddStretchableSpace() self.btnFaceImages = [ 'Lx_Icons/Boy_Face.png', 'Lx_Icons/Girl_Face.png', 'Lx_Icons/Men_Face.png', 'Lx_Icons/Women_Face.png' ] self.btnFaceInverted = [ 'Lx_Icons/Boy_Face_Inverted.png', 'Lx_Icons/Girl_Face_Inverted.png', 'Lx_Icons/Men_Face_Inverted.png', 'Lx_Icons/Women_Face_Inverted.png' ] self.graphFaceImages = [ 'Lx_Icons/Boy.png', 'Lx_Icons/Girl.png', 'Lx_Icons/Man.png', 'Lx_Icons/Women.png' ] self.img_index = 0 img = wx.Image('Lx_Icons/Women_Face.png').Scale( 55, 35, wx.IMAGE_QUALITY_HIGH) b_face_tool = self.bottomToolbar.AddTool(6, 'Animation', wx.Bitmap(img), 'Animate current signal') self.Bind(wx.EVT_TOOL, self.on_face, b_face_tool) # for i in range(1): # self.bottomToolbar.AddStretchableSpace() img = wx.Image('Lx_Icons/Flip.png').Scale(55, 35, wx.IMAGE_QUALITY_HIGH) self.b_flip_tool = self.bottomToolbar.AddTool(7, 'Flip', wx.Bitmap(img), 'Flip') self.on_flip_click(None, init_flip=True) self.Bind(wx.EVT_TOOL, self.on_flip_click, self.b_flip_tool) # for i in range(1): # self.bottomToolbar.AddStretchableSpace() img = wx.Image('Lx_Icons/Ani_Play_Normal.png').Scale( 55, 35, wx.IMAGE_QUALITY_HIGH) b_play_tool = self.bottomToolbar.AddTool(8, 'Animation', wx.Bitmap(img), 'Animate current signal') self.Bind(wx.EVT_TOOL, self.OnClicked, b_play_tool) # for i in range(1): # self.bottomToolbar.AddStretchableSpace() img = wx.Image('Lx_Icons/Ani_Redo_Normal.png').Scale( 55, 35, wx.IMAGE_QUALITY_HIGH) b_redo_tool = self.bottomToolbar.AddTool(9, 'Animation', wx.Bitmap(img), 'Animate current signal') self.Bind(wx.EVT_TOOL, self.on_animate_signal, b_redo_tool) for i in range(45): self.bottomToolbar.AddStretchableSpace() img = wx.Image('Lx_Icons/Ani_Play_Normal.png').Scale( 55, 35, wx.IMAGE_QUALITY_HIGH) b_play_tool = self.bottomToolbar.AddTool(8, 'Animation', wx.Bitmap(img), 'Animate current signal') self.Bind(wx.EVT_TOOL, self.OnClicked, b_play_tool) self.bottomToolbar.Realize() m_radioBoxChoices = [u"1", u"2", u"5", u"10", u"20"] self.m_radioBox = wx.RadioBox(self, wx.ID_ANY, u"Speed", wx.DefaultPosition, wx.DefaultSize, m_radioBoxChoices, 1, wx.RA_SPECIFY_COLS) self.m_radioBox.SetBackgroundColour((64, 134, 170, 1)) self.m_radioBox.SetSelection(2) middle_tool_box.Add(self.m_radioBox, 0, wx.ALIGN_BOTTOM, 5) vert_box.Add(self.bottomToolbar, 0, wx.EXPAND) '''End of bottom_tool_box''' self.SetSizer(vert_box) self.Refresh() self.x = [] self.y = [] self.jaw_outline, = self.axes_animation.plot(self.x, self.y, color='#70361b') def set_animation_data_plot(self, mat_px, mat_py, K2_POA_pos, h2_POA_pos, time): self.mat_px = mat_px # x axis self.mat_py = mat_py # y axis self.K2_POA_pos = K2_POA_pos self.h2_POA_pos = h2_POA_pos # articulation/ movement of red point self.time = time def set_animation_data_plot_s_op2(self, mat_px, mat_py, K2_POA_pos, h2_POA_pos): self.mat_px_s_op2 = mat_px # x axis self.mat_py_s_op2 = mat_py # y axis self.K2_POA_pos_s_op2 = K2_POA_pos self.h2_POA_pos_s_op2 = h2_POA_pos # articulation/ movement of red point def OnClicked2(self, e): print("ok") self.ani = animation.FuncAnimation(self.figure_animation, self.animate_s_op2, init_func=self.init, interval=0.1, frames=len(self.mat_px_s_op2), repeat=False, blit=True) def OnClicked(self, e): print("PLAY") pub.sendMessage("SLIDER_CHANGE", value=None) # interval_val = self.time/len(self.mat_px) self.ani = animation.FuncAnimation(self.figure_animation, self.animate, init_func=self.init, interval=0.1, frames=len(self.mat_px), repeat=False, blit=True) pub.sendMessage("PLAY", value=None) def init(self): # only required for blitting to give a clean slate. self.x = self.mat_px[0] self.y = self.mat_py[0] if not self.Test_flip_click: self.jaw_outline.set_data(self.x, self.y) jaw_area_fill = self.axes_animation.fill_between( self.x, self.y, 0, facecolor=[(254 / 255, 157 / 255, 111 / 255)]) poa = self.axes_animation.scatter(self.h2_POA_pos[0], self.K2_POA_pos[0], color='red', s=150) self.canvas_animation.draw() self.canvas_animation.Refresh() else: self.jaw_outline.set_data(-self.x + 425, self.y) jaw_area_fill = self.axes_animation.fill_between( -self.x + 425, self.y, 0, facecolor=[(254 / 255, 157 / 255, 111 / 255)]) poa = self.axes_animation.scatter(-self.h2_POA_pos[0] + 425, self.K2_POA_pos[0], color='red', s=150) self.canvas_animation.draw() self.canvas_animation.Refresh() return self.show_img, self.jaw_outline def animate_s_op2(self, i): # update the data x = self.mat_px_s_op2[i] y = self.mat_py_s_op2[i] self.jaw_outline.set_data(x, y) poa = self.axes_animation.scatter(self.h2_POA_pos_s_op2[i], self.K2_POA_pos_s_op2[i], color='red', s=150) jaw_area_fill = self.axes_animation.fill_between( x, y, 0, facecolor=[(254 / 255, 157 / 255, 111 / 255)]) return self.show_img, self.jaw_outline, jaw_area_fill, poa def on_animate_signal(self, e): print('Animate signal') def on_pitch_click(self, event, init_pitch=False): if init_pitch: self.Test_pitch_click = False else: self.Test_pitch_click = not self.Test_pitch_click if self.Test_pitch_click: pub.sendMessage("PITCH_CHANGE", value=250) else: pub.sendMessage("PITCH_CHANGE", value=500) def on_level_click(self, event, init_level=False): if init_level: self.Test_level_click = False else: self.Test_level_click = not self.Test_level_click if self.Test_level_click: pub.sendMessage("LEVEL_CHANGE", value=60) else: pub.sendMessage("LEVEL_CHANGE", value=80) def right_side(self): self.jaw_outline, = self.axes_animation.plot(self.x, self.y, color='#70361b') self.jaw_outline.set_data(-self.x + 425, self.y) jaw_area_fill = self.axes_animation.fill_between( -self.x + 425, self.y, 0, facecolor=[(254 / 255, 157 / 255, 111 / 255)]) poa = self.axes_animation.scatter(-self.h2_POA_pos[0] + 425, self.K2_POA_pos[0], color='red', s=150) def left_side(self): self.jaw_outline, = self.axes_animation.plot(self.x, self.y, color='#70361b') self.jaw_outline.set_data(self.x, self.y) jaw_area_fill = self.axes_animation.fill_between( self.x, self.y, 0, facecolor=[(254 / 255, 157 / 255, 111 / 255)]) poa = self.axes_animation.scatter(self.h2_POA_pos[0], self.K2_POA_pos[0], color='red', s=150) def on_face(self, event): if (self.img_index == len(self.btnFaceImages)): self.img_index = 0 if not self.Test_flip_click: img = self.btnFaceImages[self.img_index] png = wx.Image(img, wx.BITMAP_TYPE_ANY).ConvertToBitmap() self.bottomToolbar.SetToolNormalBitmap(id=6, bitmap=png) self.axes_animation.clear() self.axes_animation.set_axis_off() graph_face = self.graphFaceImages[self.img_index] self.women_img2 = mpimg.imread(graph_face) self.show_img = self.axes_animation.imshow(self.women_img2) self.left_side() # self.jaw_outline, = self.axes_animation.plot(self.x, self.y, color='#70361b') # self.jaw_outline.set_data(self.x, self.y) # jaw_area_fill = self.axes_animation.fill_between(self.x, self.y, 0, facecolor=[(254 / 255, 157 / 255, 111 / 255)]) # poa = self.axes_animation.scatter(self.h2_POA_pos[0], self.K2_POA_pos[0], color='red', s=150) self.canvas_animation.draw() self.canvas_animation.Refresh() self.img_index = self.img_index + 1 else: img = self.btnFaceInverted[self.img_index] png = wx.Image(img, wx.BITMAP_TYPE_ANY).ConvertToBitmap() self.bottomToolbar.SetToolNormalBitmap(id=6, bitmap=png) self.axes_animation.clear() self.axes_animation.set_axis_off() graph_face = self.graphFaceImages[self.img_index] self.women_img2 = mpimg.imread(graph_face) self.show_img = np.fliplr(self.women_img2) self.axes_animation.imshow(np.fliplr(self.women_img2)) self.right_side() # self.jaw_outline, = self.axes_animation.plot(self.x, self.y, color='#70361b') # self.jaw_outline.set_data(-self.x + 425, self.y) # jaw_area_fill = self.axes_animation.fill_between(-self.x + 425, self.y, 0, # facecolor=[(254 / 255, 157 / 255, 111 / 255)]) # poa = self.axes_animation.scatter(-self.h2_POA_pos[0] + 425, self.K2_POA_pos[0], color='red', s=150) self.canvas_animation.draw() self.canvas_animation.Refresh() self.img_index = self.img_index + 1 def on_flip_click(self, event, init_flip=False): if init_flip: self.Test_flip_click = False else: self.Test_flip_click = not self.Test_flip_click if self.Test_flip_click: self.axes_animation.clear() self.axes_animation.set_axis_off() self.show_img = np.fliplr(self.women_img2) self.axes_animation.imshow(np.fliplr(self.women_img2)) self.right_side() # self.jaw_outline, = self.axes_animation.plot(self.x, self.y, color='#70361b') # self.jaw_outline.set_data(-self.x + 425, self.y) # jaw_area_fill = self.axes_animation.fill_between(-self.x + 425, self.y, 0, # facecolor=[(254 / 255, 157 / 255, 111 / 255)]) # poa = self.axes_animation.scatter(-self.h2_POA_pos[0] + 425, self.K2_POA_pos[0], color='red', s=150) self.canvas_animation.draw() self.canvas_animation.Refresh() img = "Lx_Icons/Flip_Reverse.png" png = wx.Image(img, wx.BITMAP_TYPE_ANY).ConvertToBitmap() self.bottomToolbar.SetToolNormalBitmap(id=7, bitmap=png) else: self.axes_animation.clear() self.axes_animation.set_axis_off() self.show_img = self.axes_animation.imshow(self.women_img2) # self.left_side() # self.jaw_outline.set_data(self.x, self.y) # jaw_area_fill = self.axes_animation.fill_between(self.x, self.y, 0, # facecolor=[(254 / 255, 157 / 255, 111 / 255)]) # poa = self.axes_animation.scatter(self.h2_POA_pos[0], self.K2_POA_pos[0], color='red', s=150) self.canvas_animation.draw() self.canvas_animation.Refresh() img = "Lx_Icons/Flip.png" png = wx.Image(img, wx.BITMAP_TYPE_ANY).ConvertToBitmap() self.bottomToolbar.SetToolNormalBitmap(id=7, bitmap=png) def on_message_window(self, e): message_dialog = MessageWindow(self) message_dialog.Centre() message_dialog.ShowModal() message_dialog.Destroy() def animate(self, i): # pass values, if condition # update the data x = self.mat_px[i] y = self.mat_py[i] #if reverse play this animation if self.Test_flip_click == False: self.jaw_outline.set_data(x, y) poa = self.axes_animation.scatter(self.h2_POA_pos[i], self.K2_POA_pos[i], color='red', s=150) jaw_area_fill = self.axes_animation.fill_between( x, y, 0, facecolor=[(254 / 255, 157 / 255, 111 / 255)]) else: self.jaw_outline.set_data(-x + 425, y) poa = self.axes_animation.scatter(-self.h2_POA_pos[i] + 425, self.K2_POA_pos[i], color='red', s=150) jaw_area_fill = self.axes_animation.fill_between( -x + 425, y, 0, facecolor=[(254 / 255, 157 / 255, 111 / 255)]) return self.show_img, self.jaw_outline, jaw_area_fill, poa
class PlotPanel(wx.Panel): """ This class defines a 2D XY plot widget based on a Wx Panel widget. """ def __init__(self, parent, title=None): """ Initialize various plotting widgets and data """ super(PlotPanel, self).__init__(parent, style=wx.BORDER_DOUBLE) self.title = title self.figure = Figure(figsize=(1, 1)) # self.axes = self.figure.add_subplot(3, 1, 1) # self.figure.subplots_adjust(hspace=0.5) # 16-11-2019 by AR spacing # self.axes_pitch = self.figure.add_subplot(3, 1, 2) # 16-11-2019 by AR # self.figure.subplots_adjust(hspace=0.5) # 19-11-2019 by AR spacing # self.axes_loudness = self.figure.add_subplot(3, 1, 3) # 19-11-2019 by AR self.canvas = FigureCanvas(self, -1, self.figure) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.EXPAND | wx.ALL, 2) self.SetSizer(self.sizer) self.x_vals = np.arange(0, 5, 0.01) self.y_vals = np.zeros(len(self.x_vals)) # self.draw_pitch() # self.draw() # self.draw_loudness() def draw_pitch(self): """ Draw the object data into an XY plot and refresh the plot """ self.axes_pitch.clear() self.axes_pitch.grid(True, color='lightgray') self.axes_pitch.set_ylabel('Pitch (Hz)') self.axes_pitch.set_ylim(100, 500) self.axes_pitch.plot(self.x_vals, self.y_vals, "b", linewidth=0.5) self.canvas.draw() self.canvas.Refresh() def draw_loudness(self): """ Draw the object data into an XY plot and refresh the plot """ self.axes_loudness.clear() self.axes_loudness.grid(True, color='lightgray') self.axes_loudness.set_ylabel('Level (dB)') self.axes_loudness.set_xlabel('Time (s)') self.axes_loudness.set_ylim(0, 100) self.axes_loudness.plot(self.x_vals, self.y_vals, "b", linewidth=0.5) self.canvas.draw() self.canvas.Refresh() def draw(self): """ Draw the object data into an XY plot and refresh the plot """ self.axes.clear() # self.axes.set_title(self.title) self.axes.grid(True, color='lightgray') self.axes.set_ylabel('Amplitude') self.axes.set_ylim(-1, 1) self.axes.plot(self.x_vals, self.y_vals, "b", linewidth=0.5) self.canvas.draw() self.canvas.Refresh() def set_data(self, xvals, yvals): # update """ Set new data for the object and redraw the XY plot """ self.x_vals = xvals self.y_vals = yvals self.draw() def set_pitch_data(self, xvals, yvals): # update """ Set new data for the object and redraw the XY plot """ self.x_vals = xvals self.y_vals = yvals self.draw_pitch() def set_level_data(self, xvals, yvals): # update """ Set new data for the object and redraw the XY plot """ self.x_vals = xvals self.y_vals = yvals self.draw_loudness()
class Analysis_Panel(wx.Panel): def __init__(self, parent, user_data): """ Initialize everything here """ super(Analysis_Panel, self).__init__(parent, style=wx.BORDER_DOUBLE) self.SetBackgroundColour(wx.Colour("White")) self.x_vals, self.y_vals = None, None # self.speech_x_vals, self.speech_y_vals = None, None self.user_data = user_data self.figure = Figure(figsize=(1, 1)) # DPI = self.figure.get_dpi() # print("DPI:", DPI) # DefaultSize = self.figure.get_size_inches() # print("Default size in Inches", DefaultSize) # print("Which should result in a %i x %i Image" % (DPI * DefaultSize[0], DPI * DefaultSize[1])) self.axes, self.axes_intensity, self.axes_pitch = self.figure.subplots( 3, sharex='col') self.canvas = FigureCanvas(self, -1, self.figure) self.sizer = wx.BoxSizer(wx.VERTICAL) self.figure.subplots_adjust(top=0.98, bottom=0.15) #adjusted correctly self.sld = wx.Slider(self, value=0, minValue=0, maxValue=100, size=(545, -1), style=wx.SL_AUTOTICKS | wx.SL_HORIZONTAL | wx.SL_SELRANGE) self.sizer.Add(self.sld, 0, wx.LEFT, 77) self.sizer.Add(self.canvas, 1, wx.EXPAND) self.SetSizer(self.sizer) self.sizer.Fit(self) # self.InitUI() pub.subscribe(self.changePitch, "PITCH_CHANGE") pub.subscribe(self.changeLevel, "LEVEL_CHANGE") pub.subscribe(self.changeSlider, "SLIDER_CHANGE") pub.subscribe(self.playAnimation, "PLAY") # pub.subscribe(self.changeLevelRight, "LEVEL_RIGHT_CHANGE") def changeSlider(self, value): self.sld.SetValue(min(self.sld.GetValue() + 1, 0)) for i in range(100): self.sld.SetValue(min(self.sld.GetValue() + 1, 100)) time.sleep(0.01) def changePitch(self, value): self.axes_pitch.set_ylim(0, value) self.canvas.draw() self.canvas.Refresh() def changeLevel(self, value): self.axes_intensity.set_ylim(20, value) self.canvas.draw() self.canvas.Refresh() def draw_speech_data(self): self.axes.clear() self.axes.set_ylim(-1, 1) self.axes.set_xlim(self.start_time, self.end_time) self.axes.set_ylabel('Sig.(norm)', fontname="Arial", fontsize=10, labelpad=13) self.axes.tick_params(axis='both', which='major', labelsize=8) self.axes.plot(self.speech_x_vals, self.speech_y_vals, "b", linewidth=0.5) self.l, self.v = self.axes.plot(self.speech_x_vals[0], self.speech_y_vals[0], self.speech_x_vals[-1], self.speech_y_vals[-1], linewidth=0.5, color='red') self.axes.grid(True, color='lightgray') self.canvas.draw() self.canvas.Refresh() def set_data(self, xvals, yvals, start, end): self.speech_x_vals = xvals self.speech_y_vals = yvals self.start_time = start self.end_time = end self.draw_speech_data() def get_data(self): return self.speech_x_vals, self.speech_y_vals def draw_pitch_data(self): self.axes_pitch.clear() self.axes_pitch.set_ylim(0, 500) self.axes_pitch.set_xlim(self.start_time, self.end_time) self.axes_pitch.grid(True, color='lightgray') self.axes_pitch.set_ylabel('Pitch (norm)', fontname="Arial", fontsize=10, labelpad=9) self.axes_pitch.tick_params(axis='both', which='major', labelsize=8) self.axes_pitch.set_xlabel('Time (s)', fontname="Arial", fontsize=10) # self.axes_pitch.get_xaxis().set_visible(False) self.axes_pitch.plot(self.x_vals, self.y_vals, "g", linewidth=0.5) self.canvas.draw() self.canvas.Refresh() def set_pitch_data(self, xvals, yvals, start, end): self.x_vals = xvals self.y_vals = yvals self.start_time = start self.end_time = end self.draw_pitch_data() def draw_intensity_data(self): self.axes_intensity.clear() self.axes_intensity.set_ylim(20, 80) self.axes_intensity.set_xlim(self.start_time, self.end_time) self.axes_intensity.grid(True, color='lightgray') self.axes_intensity.set_ylabel('Level (norm)', fontname="Arial", fontsize=10, labelpad=15) self.axes_intensity.tick_params(axis='both', which='major', labelsize=8) self.axes_intensity.plot(self.x_vals, self.y_vals, "b", linewidth=0.5) self.axes_intensity.xaxis.set_major_locator(ticker.LinearLocator(6)) self.canvas.draw() self.canvas.Refresh() def set_intensity_data(self, xvals, yvals, start, end): self.x_vals = xvals self.y_vals = yvals self.start_time = start self.end_time = end self.draw_intensity_data() def update_line(self, num, line): i = self.speech_x_vals[num] print("val of i") line.set_data([i, i], [self.speech_y_vals[0], self.speech_y_vals[-1]]) return line def playAnimation(self, value): self.line_anim = animation.FuncAnimation(fig=self.figure, func=self.update_line, frames=len( self.speech_x_vals), init_func=None, fargs=(self.l, ), repeat=None) print("Animationplayed")
class RuntimeTab(wx.Panel): def __init__(self, parent, params=None): wx.Panel.__init__(self, parent) self.pparams = params # For some reason MatPlotLib 2.2.3 on GTK 6 does not create transparent # patches (tried set_visible(False), set_facecolor("none"), set_alpha(0), # to no avail). Thus, for GTK only, setting facecolor to background # color; otherwide to 'none'. This may change if other tests reveal the # same problem in other systems. if wx.Platform == '__WXGTK__': bg_color = [i / 255 for i in self.GetBackgroundColour()] else: bg_color = 'none' plt.rc('font', family='sans-serif', size=10) plt.rc('mathtext', default='regular') # Create figure self.prime_sizer = wx.BoxSizer(wx.VERTICAL) self.prime_figure = Figure() # self.prime_figure.patch.set_alpha(0) self.prime_figure.patch.set_facecolor(color=bg_color) # Create nested GridSpec gsp = gridspec.GridSpec(2, 2, height_ratios=[2, 3]) self.cc_axes = self.prime_figure.add_subplot(gsp[0]) self.comp_axes = self.prime_figure.add_subplot(gsp[1]) self.mult_axes = self.comp_axes.twinx() self.rej_table = self.prime_figure.add_subplot(gsp[2]) gsub = gridspec.GridSpecFromSubplotSpec(3, 1, subplot_spec=gsp[3], hspace=0) self.bcc_axes = self.prime_figure.add_subplot(gsub[0]) self.bcomp_axes = self.prime_figure.add_subplot(gsub[1], sharex=self.bcc_axes) self.bmult_axes = self.prime_figure.add_subplot(gsub[2], sharex=self.bcc_axes) self.draw_axes() # Set layout, create canvas, add to sizer self.prime_figure.set_tight_layout(True) self.canvas = FigureCanvas(self, -1, self.prime_figure) self.prime_sizer.Add(self.canvas, proportion=1, flag=wx.EXPAND) # Initialize main sizer self.SetSizer(self.prime_sizer) def draw_axes(self): self.rej_table.axis('off') self.cc_axes.set_title(r'$CC_{1/2}$', fontsize=12) self.cc_axes.set_xlabel('Cycle') self.cc_axes.set_ylabel(r'$CC_{1/2}$ (%)') self.cc_axes.ticklabel_format(axis='y', style='plain') self.comp_axes.set_title('Completeness / Multiplicity', fontsize=12) self.comp_axes.set_xlabel('Cycle') self.comp_axes.set_ylabel('Completeness (%)') self.mult_axes.set_ylabel('# of Observations') self.comp_axes.ticklabel_format(axis='y', style='plain') self.mult_axes.ticklabel_format(axis='y', style='plain') self.bcc_axes.yaxis.get_major_ticks()[0].label1.set_visible(False) self.bcc_axes.yaxis.get_major_ticks()[-1].label1.set_visible(False) if self.pparams.target_anomalous_flag: self.bcc_axes.set_ylabel(r'$CC_{1/2}$ anom (%)') else: self.bcc_axes.set_ylabel(r'$CC_{1/2}$ (%)') plt.setp(self.bcc_axes.get_xticklabels(), visible=False) self.bcomp_axes.yaxis.get_major_ticks()[0].label1.set_visible(False) self.bcomp_axes.yaxis.get_major_ticks()[-1].label1.set_visible(False) self.bcomp_axes.set_ylabel("Comp (%)") plt.setp(self.bcomp_axes.get_xticklabels(), visible=False) self.bmult_axes.yaxis.get_major_ticks()[0].label1.set_visible(False) self.bmult_axes.yaxis.get_major_ticks()[-1].label1.set_visible(False) self.bmult_axes.set_xlabel("Resolution ($\AA$)") self.bmult_axes.set_ylabel("# of Obs") def draw_plots(self, info, total_cycles): # Plot mean CC1/2 meanCC = info['total_cc12'] cycles = range(len(meanCC)) self.cc_axes.clear() self.cc_axes.set_xlim(0, total_cycles) self.cc_axes.set_ylim(0, 100) self.cc_axes.plot(cycles, meanCC, 'o', c='#2b8cbe', ls='-', lw=3) # Plot mean completeness and multiplicity mean_comp = info['total_completeness'] mean_mult = info['total_n_obs'] cycles = range(len(mean_comp)) self.comp_axes.clear() self.mult_axes.clear() self.comp_axes.set_xlim(0, total_cycles) self.comp_axes.set_ylim(0, 100) self.mult_axes.set_xlim(0, total_cycles) self.comp_axes.plot(cycles, mean_comp, c='#f03b20', ls='-', lw=2) comp = self.comp_axes.scatter(cycles, mean_comp, marker='o', s=25, edgecolors='black', color='#f03b20') self.mult_axes.plot(cycles, mean_mult, c='#feb24c', ls='-', lw=2) mult = self.mult_axes.scatter(cycles, mean_mult, marker='o', s=25, edgecolors='black', color='#feb24c') labels = ['Completeness', 'Multiplicity'] self.comp_axes.legend([comp, mult], labels, loc='upper right', fontsize=9, fancybox=True) # Binned bar plots x = info['binned_resolution'][-1] bins = np.arange(len(x)) xlabels = ["{:.2f}".format(i) for i in x] sel_bins = bins[0::len(bins) // 6] sel_xlabels = [xlabels[t] for t in sel_bins] # plot binned stats self.bcc_axes.clear() if self.pparams.target_anomalous_flag: binned_cc = [c * 100 for c in info['binned_cc12_anom'][-1]] else: binned_cc = [c * 100 for c in info['binned_cc12'][-1]] self.bcc_axes.bar(bins, binned_cc, color='#2b8cbe', alpha=0.5, width=1, lw=0) self.bcc_axes.step(bins, binned_cc, color='blue', where='mid') self.bcomp_axes.clear() self.bcomp_axes.bar(bins, info['binned_completeness'][-1], alpha=0.5, color='#f03b20', width=1, lw=0) self.bcomp_axes.step(bins, info['binned_completeness'][-1], color='red', where='mid') self.bmult_axes.clear() self.bmult_axes.bar(bins, info['binned_n_obs'][-1], alpha=0.5, color='#feb24c', width=1, lw=0) self.bmult_axes.step(bins, info['binned_n_obs'][-1], color='orange', where='mid') # Set x-axis tick labels self.bmult_axes.set_xticks(sel_bins) self.bmult_axes.set_xticklabels(sel_xlabels) self.draw_axes() # Rejection table txt = 'No. good frames: {}\n' \ 'No. bad CC frames: {}\n' \ 'No. bad G frames: {}\n' \ 'No. bad unit cell frames: {}\n' \ 'No. bad gamma_e frames: {}\n' \ 'No. bad SE frames: {}\n' \ 'No. observations: {}\n' \ ''.format(info['n_frames_good'][-1], info['n_frames_bad_cc'][-1], info['n_frames_bad_G'][-1], info['n_frames_bad_uc'][-1], info['n_frames_bad_gamma_e'][-1], info['n_frames_bad_SE'][-1], info['n_observations'][-1]) self.rej_table.clear() self.rej_table.axis('off') font = { 'family': 'monospace', 'color': 'darkblue', 'weight': 'normal', 'size': 11, 'linespacing': 2.5 } self.rej_table.text(0, 0.85, txt, fontdict=font, transform=self.rej_table.transAxes, va='top') # Redraw canvas self.canvas.draw_idle() self.canvas.Refresh()
class ChartPanelBase(wx.Panel): def __init__(self, parent, fig, ax, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, name="ChartPanelBase"): """ :param parent: The parent window. :type parent: wx.Window :param fig: The figure to plot on :type fig: :class:`matplotlib.figure.Figure` :param ax: The axes to plot on :type ax: :class:`matplotlib.axes.Axes` :param id: An identifier for the panel. wx.ID_ANY is taken to mean a default. :type id: wx.WindowID, optional :param pos: The panel position. The value wx.DefaultPosition indicates a default position, chosen by either the windowing system or wxWidgets, depending on platform. :type pos: wx.Point, optional :param size: The panel size. The value wx.DefaultSize indicates a default size, chosen by either the windowing system or wxWidgets, depending on platform. :type size: wx.Size, optional :param style: The window style. See wx.Panel. :type style: int, optional :param name: Window name. :type name: str, optional """ wx.Panel.__init__(self, parent, id, pos, size, style | wx.TAB_TRAVERSAL, name) self.fig = fig self.ax = ax self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig) self._do_layout() self.toolbar = NavigationToolbar(self.canvas) self.toolbar.Hide() self.Bind(wx.EVT_SIZE, self.on_size_change, self) self.Bind(wx.EVT_MAXIMIZE, self.on_size_change) def setup_ylim_refresher(self, y_data, x_data): # def on_xlims_change(ax): def update_ylim(*args): # print(*args) # print(str(*args).startswith("MPL MouseEvent")) # Pan if (str(*args).startswith("XPanAxesSubplot") and self.current_canvas_mode != "PAN") or ( str(*args).startswith("MPL MouseEvent") and self.current_canvas_mode != "ZOOM"): self.do_rescale_y(x_data, y_data) self.ax.callbacks.connect('xlim_changed', update_ylim) self.fig.canvas.callbacks.connect("button_release_event", update_ylim) @property def current_canvas_mode(self): """ Returns the current mode of the canvas. Either "PAN", "ZOOM" or None. "PAN" means the canvas is in pan mode. "ZOOM" means the canvas is in zoom mode. None means the canvas is not in either mode. This state can be used for custom selection events (e.g. click somewhere and something happens) :return: The current canvas mode :rtype: str or None """ return self.canvas.toolbar._active def _do_layout(self): # begin wxGlade: ChromatogramPanel.__do_layout sizer = wx.FlexGridSizer(1, 2, 0, 0) sizer.Add(self.canvas, 1, wx.EXPAND, 0) self.SetSizer(sizer) sizer.Fit(self) self.Layout() def reset_view(self, *_): self.canvas.toolbar.home() self.canvas.draw_idle() def previous_view(self, *_): self.canvas.toolbar.back() def rescale_y(self, *_): pass def rescale_x(self, *_): pass def do_rescale_x(self, x_data): ylim = self.ax.get_ylim() self.ax.set_xlim(x_data[0], x_data[-1]) self.fig.canvas.draw() self.ax.set_ylim(*ylim) self.size_change() def get_current_x_index_range(self, x_data): min_x_index = (numpy.abs(x_data - self.ax.get_xlim()[0])).argmin() max_x_index = (numpy.abs(x_data - self.ax.get_xlim()[1])).argmin() return min_x_index, max_x_index def do_rescale_y(self, x_data, y_data): min_x_index, max_x_index = self.get_current_x_index_range(x_data) y_vals_for_range = numpy.take( y_data, [idx for idx in range(min_x_index, max_x_index)]) self.ax.set_ylim(bottom=0, top=max(y_vals_for_range) * 1.1) self.fig.canvas.draw() self.size_change() def zoom(self, enable=True): if self.check_mode("ZOOM", enable): self.canvas.toolbar.zoom() self.canvas.Refresh() def pan(self, enable=True): if self.check_mode("PAN", enable): self.canvas.toolbar.pan() self.canvas.Refresh() def check_mode(self, mode, enable=True): return (enable and self.current_canvas_mode != mode) \ or (not enable and self.current_canvas_mode == mode) def configure_borders(self, _): self.border_config = border_config.border_config(self, self.fig) self.border_config.Show() def constrain_zoom(self, key="x"): # Constrain zoom to x axis only # From https://stackoverflow.com/questions/16705452/matplotlib-forcing-pan-zoom-to-constrain-to-x-axes def press_zoom(self, event): event.key = key NavigationToolbar.press_zoom(self, event) self.fig.canvas.toolbar.press_zoom = types.MethodType( press_zoom, self.fig.canvas.toolbar) # Other Toolbar Options # Save chromatogram as image: save_figure(self, *args) # set_cursor(self, cursor) # Set the current cursor to one of the :class:`Cursors` enums values. # If required by the backend, this method should trigger an update in # the backend event loop after the cursor is set, as this method may be # called e.g. before a long-running task during which the GUI is not # updated. # set_history_buttons(self) # Enable or disable the back/forward button. # forward(self, *args) # move forward in the view lim stack. # print(axes.get_ylim()) # end of class ChromatogramPanel def size_change(self): # code to run whenever window resized # self.canvas.SetMinSize(self.GetSize()) self.canvas.SetSize(self.GetSize()) self.fig.tight_layout() self.Refresh() self.canvas.draw() self.canvas.Refresh() # if event.ClassName == "wxSizeEvent": # event.Skip() def on_size_change(self, _): self.size_change() # event.Skip() def setup_scrollwheel_zooming(self, scale=1.5): # https://stackoverflow.com/a/11562898/3092681 def zoom_factory(ax, base_scale=2.): def zoom_fun(event): # get the current x and y limits cur_xlim = ax.get_xlim() cur_ylim = ax.get_ylim() cur_xrange = (cur_xlim[1] - cur_xlim[0]) * .5 cur_yrange = (cur_ylim[1] - cur_ylim[0]) * .5 xdata = event.xdata # get event x location ydata = event.ydata # get event y location if event.button == 'up': # deal with zoom in scale_factor = 1 / base_scale elif event.button == 'down': # deal with zoom out scale_factor = base_scale else: # deal with something that should never happen scale_factor = 1 print(event.button) # set new limits ax.set_xlim([ xdata - cur_xrange * scale_factor, xdata + cur_xrange * scale_factor ]) ax.set_ylim([ ydata - cur_yrange * scale_factor, ydata + cur_yrange * scale_factor ]) self.canvas.draw() # force re-draw fig = ax.get_figure() # get the figure of interest # attach the call back fig.canvas.mpl_connect('scroll_event', zoom_fun) # return the function return zoom_fun self.__zoom_factory = zoom_factory(self.ax, base_scale=scale) def show_message(self, message): self.ax.text(0.5, 0.5, message, horizontalalignment="center", fontsize='11', transform=self.ax.transAxes) self.canvas.draw() def clear(self): self.ax.clear() self.fig.subplots_adjust(left=0.1, bottom=0.125, top=0.9, right=0.97) self.canvas.draw()
class ShowTifInPath(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) self.fig = plt.figure() self.canvas = FigCanvas(self, -1, self.fig) self.lastFileName = '' self.filesPath = '' self.bindKeyShortcuts() self.createMenuAndToolbar() def bindKeyShortcuts(self): self.canvas.Bind(wx.EVT_KEY_DOWN, self.OnDwnKeyPress) self.canvas.Bind(wx.EVT_KEY_UP, self.OnUpKeyPress) self.canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor) # Create an accelerator table myKeyId_1 = wx.NewId() myKeyId_2 = wx.NewId() self.Bind(wx.EVT_MENU, self.onCtrlShiftF1, id=myKeyId_1) self.Bind(wx.EVT_MENU, self.onShiftAltY, id=myKeyId_2) accel_tbl = wx.AcceleratorTable([ (wx.ACCEL_SHIFT | wx.ACCEL_CTRL, wx.WXK_F1, myKeyId_1), (wx.ACCEL_SHIFT | wx.ACCEL_ALT, ord('Y'), myKeyId_2) ]) self.SetAcceleratorTable(accel_tbl) def onCtrlShiftF1(self, event): """ https://www.blog.pythonlibrary.org/2010/12/02/wxpython-keyboard-shortcuts-accelerators/ """ print "You pressed CTRL+SHIFT+F1" def onShiftAltY(self, event): """ https://www.blog.pythonlibrary.org/2010/12/02/wxpython-keyboard-shortcuts-accelerators/ """ print "You pressed ALT+SHIFT+Y" def createMenuAndToolbar(self): ''' ref: https://www.blog.pythonlibrary.org/2008/07/02/wxpython-working-with-menus-toolbars-and-accelerators/ ''' """ Create the menu bar. """ menuBar = wx.MenuBar() fileMenu = wx.Menu() fileMenu.AppendSeparator() exitMenuItem = fileMenu.Append(wx.NewId(), "&Exit\tAlt+F4", "Exit the application") self.Bind(wx.EVT_MENU, self.OnExit, exitMenuItem) menuBar.Append(fileMenu, "&File") # exitMenuItem.Enable(False) # menuBar.EnableTop(0, False) self.GetParent().SetMenuBar(menuBar) # add it to Frame object """ Create a toolbar. """ self.toolbar = self.GetParent().CreateToolBar() self.toolbar.SetToolBitmapSize((16, 16)) # sets icon size # Use wx.ArtProvider for default icons open_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, (16, 16)) if 'phoenix' in wx.PlatformInfo: openTool = self.toolbar.AddTool(wx.ID_ANY, "Open", open_ico, "Select file to load") else: openTool = self.toolbar.AddSimpleTool(wx.ID_ANY, open_ico, "Open", "Select file to load") # self.Bind(wx.EVT_MENU, self.onSave, saveTool) # Use wx.ArtProvider for default icons save_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, (16, 16)) saveTool = self.toolbar.AddTool(wx.ID_ANY, "Save", save_ico, "Saves the Current Worksheet") # self.Bind(wx.EVT_MENU, self.onSave, saveTool) self.toolbar.AddSeparator() print_ico = wx.ArtProvider.GetBitmap(wx.ART_PRINT, wx.ART_TOOLBAR, (16, 16)) printTool = self.toolbar.AddTool(wx.ID_ANY, "Print", print_ico, "Sends Timesheet to Default Printer") # self.Bind(wx.EVT_MENU, self.onPrint, printTool) # delete_ico = wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_TOOLBAR, (16, 16)) # deleteTool = self.toolbar.AddSimpleTool(wx.ID_ANY, delete_ico, "Delete", "Delete contents of cell") # # self.Bind(wx.EVT_MENU, self.onDelete, deleteTool) # # undo_ico = wx.ArtProvider.GetBitmap(wx.ART_UNDO, wx.ART_TOOLBAR, (16, 16)) # self.undoTool = self.toolbar.AddSimpleTool(wx.ID_UNDO, undo_ico, "Undo", "") # self.toolbar.EnableTool(wx.ID_UNDO, False) # # self.Bind(wx.EVT_TOOL, self.onUndo, self.undoTool) # # redo_ico = wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_TOOLBAR, (16, 16)) # self.redoTool = self.toolbar.AddSimpleTool(wx.ID_REDO, redo_ico, "Redo", "") # self.toolbar.EnableTool(wx.ID_REDO, False) # # self.Bind(wx.EVT_TOOL, self.onRedo, self.redoTool) # This basically shows the toolbar self.toolbar.Realize() def OnExit(self): # SystemExit() self.Close() def ChangeCursor(self, event): self.canvas.SetCursor(wx.Cursor(wx.CURSOR_BULLSEYE)) def updateTif(self, tifFullName): img = mpimg.imread(tifFullName) self.imgplot.set_data(img) self.canvas.draw() # self.vbox.Fit(self) #bad for getting correct resize self.canvas.Refresh() return self.imgplot def showTif(self, tifFullName): img = mpimg.imread(tifFullName) self.imgplot = plt.imshow(img) self.cBar = plt.colorbar() self.toolbar = NavigationToolbar(self.canvas) # plt.axis('off') self.vbox = wx.BoxSizer(wx.VERTICAL) self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) self.vbox.Add(self.toolbar, 0, wx.EXPAND) self.SetSizer(self.vbox) self.vbox.Fit(self) return self.imgplot, self.cBar def OnDwnKeyPress(self, event): pass # print "dwnKey" def OnUpKeyPress(self, event): print "onUpKey" pressedKey = event.GetKeyCode() if (pressedKey == wx.WXK_LEFT) | (pressedKey == wx.WXK_DOWN): print "left / down key" #currentIndex % len(relevant items) filesList = list(panel.filesInfo) if (filesList[3] > 0): filesList[3] = (filesList[3]) - 1 else: filesList[3] = len(filesList[2]) - 1 panel.filesInfo = tuple(filesList) newFileName = panel.filesInfo[2][filesList[3]] panel.updateTif(newFileName) elif (pressedKey == wx.WXK_RIGHT) | (pressedKey == wx.WXK_UP): print "right / up key" #currentIndex % len(relevant items) filesList = list(panel.filesInfo) if (filesList[3] < (len(filesList[2]) - 1)): filesList[3] = (filesList[3]) + 1 else: filesList[3] = 0 panel.filesInfo = tuple(filesList) newFileName = panel.filesInfo[2][filesList[3]] panel.updateTif(newFileName) elif (pressedKey == wx.WXK_NUMPAD_ADD): print "+ key" elif (pressedKey == wx.WXK_NUMPAD_SUBTRACT): print "- key" else: print pressedKey return pressedKey
class mainFrame(wx.Frame): """ The main frame of the application """ title = 'Main Console' def __init__(self, dataFile): # 10x10 inches, 100 dots-per-inch, so set size to (1000,1000) wx.Frame.__init__(self, None, -1, self.title, size=(1000, 1000), pos=(50, 50)) self.dataFile = dataFile data = sio.loadmat(self.dataFile) self.X = np.concatenate((data["X"], data["testX"])) self.y = np.concatenate( (np.squeeze(data["y"]), np.squeeze(data["testy"]))) try: files = data["files"] except KeyError: files = data["train_files"] self.files = np.concatenate( (np.squeeze(files), np.squeeze(data["test_files"]))) self.real_X = self.X[np.where(self.y == 1)] self.real_y = self.y[np.where(self.y == 1)] self.real_files = self.files[np.where(self.y == 1)] self.bogus_X = self.X[np.where(self.y == 0)] self.bogus_y = self.y[np.where(self.y == 0)] self.bogus_files = self.files[np.where(self.y == 0)] m, n = np.shape(self.X) self.m = m self.n = n self.plotDim = np.sqrt(self.n) self.start = 0 self.end = 100 self.to_plot = self.X[self.start:self.end, :] self.files_to_plot = self.files[self.start:self.end] self.max_index = int(np.ceil(np.shape(self.X)[0] / 100.0) * 100) self.new_real_files = [] self.new_bogus_files = [] # Create the mpl Figure and FigCanvas objects. # 10x10 inches, 100 dots-per-inch self.dpi = 100 self.fig = Figure((8.0, 8.0), dpi=self.dpi) self.fig.subplots_adjust(left=0.1, bottom=0.01, right=0.9, top=0.99, wspace=0.05, hspace=0.05) self.AXES = [] for i in range(100): ax = self.fig.add_subplot(10, 10, i + 1) self.AXES.append(ax) self.create_main_panel() self.navigation_control.previous_button.Disable() self.reset_button.Disable() def create_main_panel(self): self.panel = wx.Panel(self) self.set_text = wx.StaticText(self.panel, -1, label="Showing : All (%d examples)" % self.m) self.set_text.SetBackgroundColour(wx.WHITE) font = wx.Font(20, wx.MODERN, wx.NORMAL, wx.BOLD) self.set_text.SetFont(font) self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) self.hbox1.Add(self.set_text, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL) self.draw_fig(True) self.canvas = FigCanvas(self.panel, -1, self.fig) # Bind the 'click' event for clicking on one of the axes self.canvas.mpl_connect('button_press_event', self.on_click) self.navigation_control = NavigationControlBox(self.panel, self, -1, "navigation control") #self.label_key_box = LabelKeyBox(self.panel,-1) self.data_set_control = DataSetControlBox(self.panel, self, -1) self.build_button = wx.Button(self.panel, -1, label="Build") self.build_button.Bind(wx.EVT_BUTTON, self.on_build) self.reset_button = wx.Button(self.panel, -1, label="Reset") self.reset_button.Bind(wx.EVT_BUTTON, self.on_reset) self.exit_button = wx.Button(self.panel, -1, label="Exit") self.exit_button.Bind(wx.EVT_BUTTON, self.on_exit) self.vbox1 = wx.BoxSizer(wx.VERTICAL) self.vbox1.Add(self.build_button, 0, flag=wx.CENTER | wx.BOTTOM) self.vbox1.Add(self.reset_button, 0, flag=wx.CENTER | wx.BOTTOM) self.vbox1.Add(self.exit_button, 0, flag=wx.CENTER | wx.BOTTOM) self.hbox2 = wx.BoxSizer(wx.HORIZONTAL) #self.hbox2.Add(self.label_key_box, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL) self.hbox2.Add(self.data_set_control, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL) self.hbox2.Add(self.navigation_control, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL) self.hbox2.Add(self.vbox1, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL) self.vbox2 = wx.BoxSizer(wx.VERTICAL) self.vbox2.Add(self.hbox1, 0, flag=wx.CENTER | wx.TOP) self.vbox2.Add(self.canvas, 1, flag=wx.CENTER | wx.CENTER | wx.GROW) self.vbox2.Add(self.hbox2, 0, flag=wx.LEFT | wx.TOP) self.panel.SetSizer(self.vbox2) self.vbox2.Fit(self) def draw_fig(self, init=False): for i, ax in enumerate(self.AXES): cmap = "hot" if init: try: image = np.reshape(self.to_plot[i, :], (self.plotDim, self.plotDim), order="F") image = np.flipud(image) ax.imshow(image, interpolation="nearest", cmap=cmap) ax.axis("off") except IndexError: ax.clear() image = np.reshape(np.zeros((self.n, )), (self.plotDim, self.plotDim), order="F") image = np.flipud(image) ax.imshow(image, interpolation="nearest", cmap=cmap) ax.axis("off") try: if self.files_to_plot[i].rstrip().split("/")[-1] in set( self.new_real_files): ax.clear() cmap = "cool" image = np.reshape(self.to_plot[i, :], (self.plotDim, self.plotDim), order="F") image = np.flipud(image) ax.imshow(image, interpolation="nearest", cmap=cmap) ax.axis("off") elif self.files_to_plot[i].rstrip().split("/")[-1] in set( self.new_bogus_files): ax.clear() cmap = "PRGn" image = np.reshape(self.to_plot[i, :], (self.plotDim, self.plotDim), order="F") image = np.flipud(image) ax.imshow(image, interpolation="nearest", cmap=cmap) ax.axis("off") except IndexError: ax.clear() image = np.reshape(np.zeros((self.n, )), (self.plotDim, self.plotDim), order="F") image = np.flipud(image) ax.imshow(image, interpolation="nearest", cmap=cmap) ax.axis("off") def on_click(self, event): """ Enlarge or restore the selected axis. """ # The event received here is of the type # matplotlib.backend_bases.PickEvent # # It carries lots of information, of which we're using # only a small amount here. # if hasattr(self, "inspectorFrame"): return self.axes = event.inaxes if self.axes is None: return self.canvas.draw() self.canvas.Refresh() file = self.files_to_plot[self.AXES.index(self.axes)] if event.button is 1: label = self.y[self.start + self.AXES.index(self.axes)] if label == 0: self.new_real_files.append(file.split("/")[-1]) print "1" self.draw_fig() self.canvas.draw() self.canvas.Refresh() elif label == 1: self.new_bogus_files.append(file.split("/")[-1]) print "2" self.draw_fig() self.canvas.draw() self.canvas.Refresh() elif event.button is 3 and file.split("/")[-1] in set( self.new_real_files): self.new_real_files.remove(file.split("/")[-1]) print "3" self.draw_fig(init=True) self.canvas.draw() self.canvas.Refresh() elif event.button is 3 and file.split("/")[-1] in set( self.new_bogus_files): self.new_bogus_files.remove(file.split("/")[-1]) print "4" self.draw_fig(init=True) self.canvas.draw() self.canvas.Refresh() else: pass #self.draw_fig(init=True) def on_build(self, event): data = sio.loadmat(self.dataFile) X = np.concatenate((data["X"], data["testX"])) y = np.concatenate((np.squeeze(data["y"]), np.squeeze(data["testy"]))) try: files = data["files"] except KeyError: files = data["train_files"] files = np.concatenate( (np.squeeze(files), np.squeeze(data["test_files"]))) for i, file in enumerate(files): print file.rstrip().split("/")[-1], y[i], if file.rstrip().split("/")[-1] in set(self.new_bogus_files): if y[i] == 1: y[i] = 0 if file.rstrip().split("/")[-1] in set(self.new_real_files): if y[i] == 0: y[i] = 1 print y[i] #outputFile = raw_input("Specify output file : ") current_time = datetime.datetime.now().strftime('%Y-%m-%d_%H:%M:%S') if "relabelled" in self.dataFile: saveFile = self.dataFile.split("/")[-1][31:] print saveFile sio.savemat("relabelled_%s_" % current_time + saveFile, \ {"X":X[:.75*self.m], "y":y[:.75*self.m], "train_files": files[:.75*self.m], \ "testX":X[.75*self.m:], "testy":y[.75*self.m:], "test_files":files[.75*self.m:]}) else: sio.savemat("relabelled_%s_" % current_time + self.dataFile.split("/")[-1], \ {"X":X[:.75*self.m], "y":y[:.75*self.m], "train_files": files[:.75*self.m], \ "testX":X[.75*self.m:], "testy":y[.75*self.m:], "test_files":files[.75*self.m:]}) print "[+] Processing complete." def on_reset(self, event): self.new_real_files = [] self.new_bogus_files = [] self.new_ghost_files = [] def on_exit(self, event): self.Destroy() exit(0)
class ChartPanelBase(wx.Panel): """ Panel that contains a matplotlib plotting window, used for displaying an image. The image can be right clicked to bring up a context menu allowing copying, pasting and saving of the image. The image can be panned by holding the left mouse button and moving the mouse, and zoomed in and out using the scrollwheel on the mouse. """ def __init__( self, parent: wx.Window, fig, ax, id: wx.WindowID = wx.ID_ANY, pos: wx.Point = wx.DefaultPosition, size: wx.Sixe = wx.DefaultSize, style=0, name: str = wx.PanelNameStr ): """ :param parent: The parent window. :type parent: wx.Window :param fig: :type fig: :param ax: :type ax: :param id: An identifier for the panel. wx.ID_ANY is taken to mean a default. :type id: wx.WindowID, optional :param pos: The panel position. The value ::wxDefaultPosition indicates a default position, :type pos: wx.Point, optional chosen by either the windowing system or wxWidgets, depending on platform. :param size: The panel size. The value ::wxDefaultSize indicates a default size, chosen by :type size: wx.Size, optional either the windowing system or wxWidgets, depending on platform. :param style: The window style. See wxPanel. :type style: int, optional :param name: Window name. :type name: str, optional """ wx.Panel.__init__(self, parent, id, pos, size, style | wx.TAB_TRAVERSAL, name) self.fig = fig self.ax = ax self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig) self._do_layout() self.toolbar = NavigationToolbar(self.canvas) self.toolbar.Hide() self.Bind(wx.EVT_SIZE, self.on_size_change, self) self.Bind(wx.EVT_MAXIMIZE, self.on_size_change) def setup_ylim_refresher(self, y_data, x_data): """ Setup the function for updating the ylim whenever the xlim changes.s :param y_data: :type y_data: :param x_data: :type x_data: """ def update_ylim(*args): # print(str(*args).startswith("MPL MouseEvent")) # Pan # Zoom, Pan if ((str(*args).startswith("XPanAxesSubplot") and self.canvas.toolbar._active != "PAN") or (str(*args).startswith("MPL MouseEvent") and self.canvas.toolbar._active != "ZOOM")): # print("updated xlims: ", axes.get_xlim()) min_x_index = (numpy.abs(x_data - self.ax.get_xlim()[0])).argmin() max_x_index = (numpy.abs(x_data - self.ax.get_xlim()[1])).argmin() # print(min_x_index, max_x_index) y_vals_for_range = numpy.take(y_data, [idx for idx in range(min_x_index, max_x_index)]) # print(max(y_vals_for_range)) self.ax.set_ylim(bottom=0, top=max(y_vals_for_range) * 1.1) self.fig.canvas.draw() # print("x-val: {}, y-val:{} self.size_change() self.ax.callbacks.connect('xlim_changed', update_ylim) self.fig.canvas.callbacks.connect("button_release_event", update_ylim) def _do_layout(self): # begin wxGlade: ChromatogramPanel.__do_layout sizer = wx.FlexGridSizer(1, 2, 0, 0) sizer.Add(self.canvas, 1, wx.EXPAND, 0) self.SetSizer(sizer) sizer.Fit(self) self.Layout() def reset_view(self, *_): """ Reset the view of the chart """ self.canvas.toolbar.home() self.canvas.draw_idle() def previous_view(self, *_): """ Go to the previous view of the chart """ self.canvas.toolbar.back() def zoom(self, enable: bool = True): """ Enable the Zoom tool """ if enable or (not enable and self.canvas.toolbar._active == "ZOOM"): self.canvas.toolbar.zoom() self.canvas.Refresh() def pan(self, enable: bool = True): """ Enable the Pan tool """ if enable or (not enable and self.canvas.toolbar._active == "PAN"): self.canvas.toolbar.pan() self.canvas.Refresh() def configure_borders(self, event=None): """ Open the 'Configure Borders' dialog """ self.border_config = border_config(self, self.fig) self.border_config.Show() if event: event.Skip() def constrain_zoom(self, key="x"): """ Constrain zoom to the x axis only :param key: :type key: :return: :rtype: """ def press_zoom(self, event): event.key = key NavigationToolbar.press_zoom(self, event) self.fig.canvas.toolbar.press_zoom = types.MethodType(press_zoom, self.fig.canvas.toolbar) # Other Toolbar Options # Save chromatogram as image: save_figure(self, *args) # set_cursor(self, cursor) # Set the current cursor to one of the :class:`Cursors` enums values. # If required by the backend, this method should trigger an update in # the backend event loop after the cursor is set, as this method may be # called e.g. before a long-running task during which the GUI is not # updated. # set_history_buttons(self) # Enable or disable the back/forward button. # forward(self, *args) # move forward in the view lim stack. # print(axes.get_ylim()) # end of class ChromatogramPanel def size_change(self): """ Internal function that runs whenever the window is resized """ # self.canvas.SetMinSize(self.GetSize()) self.canvas.SetSize(self.GetSize()) self.Refresh() self.canvas.draw() self.canvas.Refresh() # if event.ClassName == "wxSizeEvent": # event.Skip() def on_size_change(self, event): """ Event handler for size change events """ self.size_change() # event.Skip() def setup_scrollwheel_zooming(self, scale: float = 1.1): """ Allow zooming of the chart with the scrollwheel :param scale: :type scale: """ def zoom_factory(ax, base_scale: float = 1.1): def zoom_fun(event): # get the current x and y limits cur_xlim = ax.get_xlim() cur_ylim = ax.get_ylim() cur_xrange = (cur_xlim[1] - cur_xlim[0]) * .5 cur_yrange = (cur_ylim[1] - cur_ylim[0]) * .5 xdata = event.xdata # get event x location ydata = event.ydata # get event y location if event.button == 'up': # deal with zoom in scale_factor = 1 / base_scale elif event.button == 'down': # deal with zoom out scale_factor = base_scale else: # deal with something that should never happen scale_factor = 1 print(event.button) # set new limits ax.set_xlim([xdata - cur_xrange * scale_factor, xdata + cur_xrange * scale_factor]) ax.set_ylim([ydata - cur_yrange * scale_factor, ydata + cur_yrange * scale_factor]) self.canvas.draw() # force re-draw fig = ax.get_figure() # get the figure of interest # attach the call back fig.canvas.mpl_connect('scroll_event', zoom_fun) # return the function return zoom_fun self.__zoom_factory = zoom_factory(self.ax, base_scale=scale)
class PlotPanel(wx.Panel): """ The PlotPanel """ def __init__(self, parent, color=None, dpi=None, **kwargs): # initialize Panel if 'id' not in kwargs.keys(): kwargs['id'] = wx.ID_ANY if 'style' not in kwargs.keys(): kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE wx.Panel.__init__(self, parent, **kwargs) self.SetMinSize((100, 40)) # initialize matplotlib stuff self.figure = Figure(None, dpi=dpi, facecolor='white') self.canvas = FigureCanvas(self, -1, self.figure) self.canvas.SetMinSize((30, 10)) self.SetBackgroundColour('white') # Add the canvas to the sizer. self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.EXPAND) self.SetSizer(self.sizer) #self.canvas.mpl_connect('button_press_event', self.onClick) self.canvas.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) self.Bind(wx.EVT_SET_FOCUS, self.onSetFocus2) self.canvas.Bind(wx.EVT_KEY_DOWN, self.onKeyDown) self.Bind(wx.EVT_KEY_DOWN, self.onKeyDown) self.canvas.Bind(wx.EVT_KEY_UP, self.onKeyUp) self.Bind(wx.EVT_KEY_UP, self.onKeyUp) self.Bind(wx.EVT_LEFT_DOWN, self.onLeftDown) self.canvas.Bind(wx.EVT_LEFT_DOWN, self.onLeftDown) def onClick(self, event): print "Clicked in View. event: %s" % event.guiEvent event.guiEvent.ResumePropagation(1) event.guiEvent.Skip() def onWxClick(self, event): print "Got the WX event." def onSetFocus(self, event): print "Canvas got Focus" event.Skip() def onSetFocus2(self, event): print "PlotPanel got Focus" def onKeyDown(self, event): print "Propagating keyDown in plotPanel" event.ResumePropagation(1) event.Skip() def onKeyUp(self, event): print "Propagating keyUp in plotPanel" event.ResumePropagation(1) event.Skip() def onLeftDown(self, event): print "PlotPanel LEFT DOWN" event.ResumePropagation(30) event.Skip() def SetColor(self, rgbtuple=None): """Set figure and canvas colours to be the same.""" if rgbtuple is None: rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() clr = [c / 255. for c in rgbtuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) self.canvas.Refresh()
class PlotGraph(wx.Panel): def __init__(self, parent, *args, **kwargs): super(PlotGraph, self).__init__(parent, *args, **kwargs) self.x_vals = np.arange(0, 10, 0.01) self.y_vals = np.zeros(len(self.x_vals)) self.InitUI() self.span_select = None self.x_data = None self.y_fs = None self.coords_x = [] self.coords_y = [] self.line1, = self.axes.plot(self.x_vals, self.y_vals, "b", linewidth=0.5) self.line2, = self.axes_pitch.plot(self.x_vals, self.y_vals, "g", linewidth=0.5) def InitUI(self): main_box = wx.BoxSizer(wx.VERTICAL) speech_box = wx.BoxSizer(wx.VERTICAL) self.figure = Figure(figsize=(2, 2)) # self.figure.subplots_adjust(right=0.95, wspace=None, hspace=None) self.axes = self.figure.add_subplot(111) self.canvas_speech = FigureCanvas(self, -1, self.figure) self.axes.set_xlim(0, 10) self.axes.set_ylim(-1, 1) self.axes.grid(True, color='lightgray') self.axes.set_ylabel('Sig.(norm)', fontname="Arial", fontsize=10) self.axes.set_xlabel('Time(s)', fontname="Arial", fontsize=10) speech_box.Add(self.canvas_speech, 0, wx.EXPAND) main_box.Add(speech_box, 0, wx.EXPAND, 1) # time_status_box = wx.BoxSizer(wx.HORIZONTAL) # # left_text_box = wx.BoxSizer(wx.HORIZONTAL) # # self.txtstart = wx.StaticText(self, wx.ID_ANY, u" Start Time:", pos=(0,0), size=(200,20), style=wx.ALIGN_CENTER ) # self.font = wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.NORMAL) # self.txtstart.SetFont(self.font) # self.txtstart.Wrap(-1) # left_text_box.Add(self.txtstart, 0, wx.ALL, 10) # # self.hiddenStartTime = wx.StaticText(self, -1, label = "") # left_text_box.Add(self.hiddenStartTime) # # time_status_box.Add(left_text_box, 1, wx.EXPAND, 1) # # middle_text_box = wx.BoxSizer(wx.HORIZONTAL) # # self.txtEnd = wx.StaticText(self, wx.ID_ANY, u" End Time:", pos=(0,0), size=(200,20), style=wx.ALIGN_CENTER) # # self.txtEnd.SetFont(self.font) # self.txtEnd.Wrap(-1) # middle_text_box.Add(self.txtEnd, 0, wx.ALL, 10) # # time_status_box.Add(middle_text_box, 1, wx.EXPAND, 1) # # right_text_box = wx.BoxSizer(wx.HORIZONTAL) # # self.txtDuration = wx.StaticText(self, wx.ID_ANY, u" Selected Duration:", pos=(0,0), size=(200,20), style=wx.ALIGN_LEFT ) # self.txtDuration.SetFont(self.font) # self.txtDuration.Wrap(-1) # right_text_box.Add(self.txtDuration, 0, wx.ALL, 10) # time_status_box.Add(right_text_box, 1, wx.EXPAND,1) # main_box.Add(time_status_box, 1, wx.EXPAND| wx.TOP,15) pitch_box = wx.BoxSizer(wx.VERTICAL) self.figure = Figure(figsize=(2, 2)) self.axes_pitch = self.figure.add_subplot(111) # self.figure.subplots_adjust(right=0.90, wspace=None, hspace=None) self.canvas_pitch = FigureCanvas(self, -1, self.figure) self.axes_pitch.set_xlim(0, 10) self.axes_pitch.set_ylim(-1.0, 1.0) self.axes_pitch.grid(True, color='lightgray') self.axes_pitch.set_ylabel('Selected Sig.(norm)', fontname="Arial", fontsize=10) self.axes_pitch.set_xlabel('Time(s)', fontname="Arial", fontsize=10) pitch_box.Add(self.canvas_pitch, 0, wx.EXPAND) main_box.Add(pitch_box, 0, wx.EXPAND, 1) self.SetSizer(main_box) def draw_speech_data(self): self.axes.clear() self.axes.grid(True, color='lightgray') self.axes.set_ylabel('Sig.(norm)', fontname="Arial", fontsize=10) self.axes.set_xlabel('Time(s)', fontname="Arial", fontsize=10) self.axes.set_ylim(-1, 1) self.axes.set_xlim(0, 10) self.axes.plot(self.x_vals, self.y_vals, "b", linewidth=0.5) self.canvas_speech.draw() self.canvas_speech.Refresh() def set_data(self, xvals, yvals): self.x_vals = xvals self.y_vals = yvals self.draw_speech_data() def draw_pitch_data(self): self.axes_pitch.clear() self.axes_pitch.plot(self.x_vals, self.y_vals, "g", linewidth=0.5) self.canvas_pitch.draw() self.canvas_pitch.Refresh() def set_pitch_data(self, xvals, yvals): self.x_vals = xvals self.y_vals = yvals self.draw_pitch_data() def on_select_span(self, min_val, max_val): self.indmin, self.indmax = np.searchsorted(self.x_vals, (min_val, max_val)) self.indmax = min(len(self.x_vals) - 1, self.indmax) self.thisx = self.x_vals[self.indmin:self.indmax] self.thisy = self.y_vals[self.indmin:self.indmax] self.coords_x = self.thisx self.coords_y = self.thisy self.line2.set_data(self.thisx, self.thisy) self.fs_bottom = 10000 uniq_filename = 'analysis_process.wav' sf.write(uniq_filename, self.thisy, self.fs_bottom) self.axes_pitch.set_xlim( self.thisx[0], self.thisx[-1]) # thisx[0]= Start Time and thisx[-1] = End Time self.axes_pitch.set_ylim(self.thisy.min(), self.thisy.max()) self.figure.canvas.draw_idle() return min_val, max_val def get_audio_data(self): return self.coords_y def start_end_time(self): return self.thisx[-1] - self.thisx[0] def get_audio_data_xy(self): return self.coords_x, self.coords_y def clear_pitch_graph_data(self): print("clear") # self.axes_pitch.clear() # self.canvas_pitch.draw() # self.axes.grid(True, color='lightgray') # self.axes.set_ylabel('Sig.(norm)', fontname="Arial", fontsize=10) # self.axes.set_xlabel('Time(s)', fontname="Arial", fontsize=10) # self.axes.set_ylim(-1, 1) # self.axes.set_xlim(0, 10) # self.axes_pitch.plot(self.x_vals, self.y_vals, "g", linewidth=0.5) # self.canvas_pitch.Refresh() def span_selection_init(self): self.span = mwidgets.SpanSelector(self.axes, self.on_select_span, 'horizontal', useblit=True, rectprops=dict(alpha=0.5, facecolor='red'))
class HistPanel(wx.Panel): def __init__(self, parent, dpi=None, **kwargs): wx.Panel.__init__(self, parent, **kwargs) self.figure = Figure(figsize=(1, 4), dpi=dpi) # self.axes = self.figure.add_subplot(111) self.axes = self.figure.gca() self.canvas = FigureCanvas(self, -1, self.figure) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.EXPAND) self.SetSizer(self.sizer) self._init_plot() # self.add_toolbar() # self.plot_histogram() self.Bind(wx.EVT_PAINT, self.OnPaint) # self.Bind(wx.EVT_SIZE, self.OnSize) # Set up pubsub pub.subscribe(self.OnUpdateHistogram, "2dview.updated.image") def _init_plot(self): # set title self.figure.suptitle("Histogram", fontsize=10) # set label self.axes.set_xlabel("xlabel", fontsize=6) self.axes.set_ylabel("ylabel", fontsize=6) # set ticks self.axes.xaxis.set_tick_params(labelsize=7) self.axes.yaxis.set_tick_params(labelsize=5) def plot_histogram_img(self, img: str): print("plot_histogram_img") self.axes.cla() # t = np.arange(0.0, 3.0, 0.01) # s = np.sin(2 * np.pi * t) # self.axes.plot(t, s) img_data = mpimg.imread(img) self.axes.hist(img_data.ravel(), bins=50) self.canvas.draw() self.canvas.Refresh() def plot_histogram(self, data_array: np.ndarray): print("plot_histogram") self.axes.cla() self.axes.hist(data_array, bins=100) self.canvas.draw() self.canvas.Refresh() def add_toolbar(self): self.toolbar = NavigationToolbar(self.canvas) self.toolbar.Realize() # By adding toolbar in sizer, we are able to put it at the bottom # of the frame - so appearance is closer to G TK version. self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) # update the axes menu on the toolbar self.toolbar.update() def OnUpdateHistogram(self, msg): """Update Histogram When 2D View Image Updated.""" # logger.info(msg) image: Image.Image = msg["image_pil"] data_array = np.array(image) # logger.info(data_array) # flatten to 1-d array self.plot_histogram(data_array.ravel()) def OnPaint(self, e): print(f"OnPaint: {e}") def OnSize(self, e): print(f"OnSize: {e}")
class Panel_Plotting_Helper(wx.Panel): def __init__(self, parent): w, h = parent.GetSize() wx.Panel.__init__(self, parent=parent, size=(w, 0.7 * h), style=wx.SUNKEN_BORDER) self.parent = parent self.legends = [] self.legendpos = [0.5, 1] self.fig = Figure( figsize=(12, 6), dpi=90) # create a figure size 8x6 inches, 80 dots per inches self.splts = [] self.canvas = FigureCanvasWxAgg(self, -1, self.fig) self.toolbar = Toolbar(self.canvas) # matplotlib toolbar # additional toolbar status_txt = wx.StaticText(self.toolbar, label=' Status on hover: ', pos=(230, 7), \ size=(100, 17)) self.status = wx.TextCtrl(self.toolbar, pos=(330,4), size=(300, 22), \ style=wx.TE_READONLY) self.toolbar.Realize() self.figw, self.figh = self.fig.get_window_extent( ).width, self.fig.get_window_extent().height sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.toolbar, 0, wx.GROW) sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) self.SetSizer(sizer) self.box_width_fraction = 1.0 self.box_height_fraction = 0.9 self.lines = [] self.lined = dict() self.draggableList = ['Text', 'Legend'] # print(self.toolbar.GetBackgroundColour()) self.fig.canvas.mpl_connect('resize_event', self.squeeze_legend) self.fig.canvas.mpl_connect('pick_event', self.on_pick) self.fig.canvas.mpl_connect('motion_notify_event', self.on_motion) self.fig.canvas.mpl_connect('figure_leave_event', self.on_leave) def plot_J(self, J, theta, format, r, count): index = count % 3 + 3 self.splts[index].plot(np.arange(len(J)), J, color=format['color'], linewidth=format['linewidth'], linestyle=format['linestyle'], label=format['label'], picker=True) self.splts[index].set_xlabel("Number of Iteration", fontsize=FONT_SIZE) self.splts[index].set_ylabel("Cost value", fontsize=FONT_SIZE) self.set_ticks(self.splts[index], np.arange(len(J)), J) comment = r + ': [\n' for t in theta: comment += ' ' + str(t) + '\n' comment += ']' props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) annotate = self.splts[index].annotate(comment, xy=(len(J)-1, J[len(J)-1]), xytext=(len(J)/2, (J[0]+J[len(J)-1])/2), \ arrowprops=dict(facecolor='black', shrink=0.05), bbox=props, fontsize=FONT_SIZE, picker=True) annotate.draggable(True) def plot_data_gradient_descent(self, X, y, format): print("Plotting data ...") for i in range(int(round(len(self.splts) / 2))): self.plot_data(self.splts[i], X, y, format) self.update_canvas() def plot_data_normal_equation(self, X, y, format): print("Plotting data ...") for i in range(int(round((len(self.splts) + 1) / 2))): self.plot_data(self.splts[i], X, y, format) self.update_canvas() def plot_data(self, splt, X, y, format): line, = splt.plot(X, y, 'ro', color=format['color'], label=format['label'], picker=True) self.set_ticks(splt, X, y) self.lines.append(line) splt.set_xlabel("X1", fontsize=FONT_SIZE) splt.set_ylabel("Y", fontsize=FONT_SIZE) def set_ticks(self, splt, X, y): xticks = self.make_ticks(X) yticks = self.make_ticks(y) splt.set_xticks(xticks) splt.set_yticks(yticks) for tick in splt.get_xticklabels(): tick.set_rotation(45) tick.set_fontsize(FONT_SIZE) for tick in splt.get_yticklabels(): tick.set_rotation(45) tick.set_fontsize(FONT_SIZE) def plot_all_gradient_descent(self, object): print( "Plotting Linear-Regression (Gradient Descent) and J-Convergence ..." ) count = 0 for r in object: c = self.random_color() self.splts[count].plot(object[r]['data']['x'], object[r]['data']['y'], color=c, linestyle="-", label="Linear Regression (alpha=" + r + ")", picker=True) self.set_ticks(self.splts[count], object[r]['data']['x'], object[r]['data']['y']) self.plot_J( object[r]['J_history'], object[r]['theta'], { "color": c, "linewidth": 5, "linestyle": "-", "label": "Convergence of J" }, r, count) count += 1 self.show_legend() self.update_canvas() def plot_all_normal_equation(self, object): print("Plotting Linear-Regression (Normal Equation) ...") count = 0 for r in object: c = self.random_color() line, = self.splts[count].plot( object[r]['data']['x'], object[r]['data']['y'], color=c, linestyle="-", label="Linear Regression (Normal Equation)", picker=True) self.lines.append(line) self.set_ticks(self.splts[count], object[r]['data']['x'], object[r]['data']['y']) comment = 'Theta: [\n' for t in object[r]['theta']: comment += ' ' + str(t[0]) + '\n' comment += ']' # place a text box in upper left in axes coords props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) annotate = self.splts[count].annotate(comment, xy=(min(object[r]['data']['x']), max(object[r]['data']['y'])), \ xytext=(min(object[r]['data']['x']), max(object[r]['data']['y'])), bbox=props, fontsize=FONT_SIZE, picker=True) annotate.draggable(True) count += 1 self.show_legend() self.update_canvas() def show_legend(self): self.legends = [] for i in range(len(self.splts)): splt = self.splts[i] # Shrink current axis by 20% box = splt.get_position() splt.set_position([box.x0, box.y0, box.width * self.box_width_fraction, \ box.height * self.box_height_fraction]) # Now add the legend with some customizations. legend = splt.legend(loc='upper center', ncol=1, fancybox=True, shadow=True) legend.set_bbox_to_anchor((self.legendpos[0], \ self.legendpos[1] + legend.get_window_extent().height/self.figh + 0.25)) legend.figure.canvas.mpl_connect('pick_event', self.on_pick) legend.draggable(True) # lined = dict() # for legline, origline in zip(legend.get_lines(), self.lines): # legline.set_picker(5) # 5 pts tolerance # self.lined[legline] = origline self.legends.append(legend) if legend: # The frame is matplotlib.patches.Rectangle instance surrounding the legend. frame = legend.get_frame() frame.set_facecolor('0.90') # Set the fontsize for label in legend.get_texts(): label.set_fontsize(FONT_SIZE) for label in legend.get_lines(): label.set_linewidth(0.75) # the legend line width else: pass def make_ticks(self, data): minn = np.min(data) maxx = np.max(data) return np.arange(minn, maxx, int((maxx - minn) / 3)) def squeeze_legend(self, evt): new_height = self.fig.get_window_extent().height self.box_height_fraction = new_height / self.figh self.figh = new_height new_width = self.fig.get_window_extent().width self.box_width_fraction = new_width / self.figw self.figw = new_width self.show_legend() self.update_canvas() def on_pick(self, evt): if isinstance(evt.artist, Text): # box_points = evt.artist.get_position() global TEXT_DRAGGABLE TEXT_DRAGGABLE = not TEXT_DRAGGABLE evt.artist.draggable(TEXT_DRAGGABLE) elif isinstance(evt.artist, Line2D): # box_points = evt.artist.get_clip_box() pass elif isinstance(evt.artist, Legend): # box_points = evt.artist.get_clip_box() global LEGEND_DRAGGABLE LEGEND_DRAGGABLE = not LEGEND_DRAGGABLE evt.artist.draggable(LEGEND_DRAGGABLE) else: print(evt.artist) pass # print("You've clicked on a bar with coords:\n %r, %r" % (box_points , evt.artist)) self.update_canvas() def on_motion(self, mouseevt): w, h = self.canvas.GetSize() if mouseevt.x in range(0, int(w + 1)) and mouseevt.y in range( 0, int(h + 1)): self.status.SetValue('Click on %r for dragging On/Off' % self.draggableList) else: pass def on_leave(self, mouseevt): self.status.SetValue('') def make_figure(self, type): self.fig.clf() if type == 'gd': gs = GridSpec(2, 3) gs.update(hspace=0.7, wspace=0.8) self.splts = [ self.fig.add_subplot(gs[int(i / 3), int(i % 3)]) for i in range(2 * 3) ] # grid nxn elif type == 'ne': gs = GridSpec(1, 1) gs.update(hspace=0.7, wspace=0.8) self.splts = [ self.fig.add_subplot(gs[int(i / 3), int(i % 3)]) for i in range(1 * 1) ] # grid nxn else: pass def random_color(self): rgbl = [0, random.random(), random.random()] return tuple(rgbl) def update_canvas(self): self.fig.canvas.draw() self.canvas.Refresh() self.toolbar.update()
class SectionFrame(wx.Frame): def __init__(self,typSection="XY",croco=None): """Class to plot longitude/latitude section""" wx.Frame.__init__(self, None, wx.ID_ANY, title='Section') self.typSection=typSection self.croco = croco self.panel = wx.Panel(self, wx.ID_ANY) self.figure = Figure() self.axes = self.figure.add_axes([0,0,1,1]) self.canvas = FigureCanvas(self.panel, -1, self.figure) self.canvas.mpl_connect('button_press_event', self.onFigureClick) self.canvas.mpl_connect('button_release_event', self.onFigureRelease) self.AnimationBtn = wx.Button(self.panel, wx.ID_ANY, "Animation") self.AnimationBtn.Bind(wx.EVT_BUTTON, self.onAnimationBtn) self.startTimeTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "1", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.startTimeTxt.Bind(wx.EVT_TEXT_ENTER, self.onstartTimeTxt) self.endTimeTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "1", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.endTimeTxt.Bind(wx.EVT_TEXT_ENTER, self.onendTimeTxt) self.ZoomInBtn = wx.Button(self.panel, wx.ID_ANY, "Zoom In") self.ZoomInBtn.Bind(wx.EVT_BUTTON, self.onZoomInBtn) self.ZoomOutBtn = wx.Button(self.panel, wx.ID_ANY, "Zoom Out") self.ZoomOutBtn.Bind(wx.EVT_BUTTON, self.onZoomOutBtn) self.PrintBtn = wx.Button(self.panel, wx.ID_ANY, "Print") self.PrintBtn.Bind(wx.EVT_BUTTON, self.onPrintBtn) self.ResetColorBtn = wx.Button(self.panel, wx.ID_ANY, "Reset Color") self.ResetColorBtn.Bind(wx.EVT_BUTTON, self.onResetColorBtn) self.MinColorTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "Min Color", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.MinColorTxt.Bind(wx.EVT_TEXT_ENTER, self.onMinColorTxt) self.MaxColorTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "Max Color", style=wx.TE_CENTRE|wx.TE_PROCESS_ENTER) self.MaxColorTxt.Bind(wx.EVT_TEXT_ENTER, self.onMaxColorTxt) self.__do_layout() def __do_layout(self): topSizer = wx.BoxSizer(wx.VERTICAL) canvasSizer = wx.BoxSizer(wx.VERTICAL) buttonsSizer = wx.BoxSizer(wx.HORIZONTAL) colorSizer = wx.BoxSizer(wx.HORIZONTAL) canvasSizer.Add(self.canvas, 0, wx.ALL, 5) buttonsSizer.Add(self.AnimationBtn,0, wx.ALL, 5) buttonsSizer.Add(self.startTimeTxt,1, wx.ALL, 5) buttonsSizer.Add(self.endTimeTxt,1, wx.ALL, 5) buttonsSizer.Add(self.ZoomInBtn,0, wx.ALL, 5) buttonsSizer.Add(self.ZoomOutBtn,0, wx.ALL, 5) buttonsSizer.Add(self.PrintBtn,0, wx.ALL, 5) colorSizer.Add(self.ResetColorBtn, 0, wx.ALL, 5) colorSizer.Add(self.MinColorTxt, 0, wx.ALL, 5) colorSizer.Add(self.MaxColorTxt, 0, wx.ALL, 5) topSizer.Add(canvasSizer, 0, wx.CENTER) topSizer.Add(buttonsSizer, 0, wx.ALL|wx.EXPAND, 5) topSizer.Add(colorSizer, 0, wx.ALL|wx.EXPAND, 5) self.panel.SetSizer(topSizer) topSizer.Fit(self) self.Layout() def onFigureClick(self,event): self.xPress, self.yPress = event.xdata, event.ydata def onFigureRelease(self,event): self.xRelease, self.yRelease = event.xdata, event.ydata def rect_select_callback(self, eclick, erelease): ''' Function for ZoomIn button''' self.xPress, self.yPress = eclick.xdata, eclick.ydata self.xRelease, self.yRelease = erelease.xdata, erelease.ydata self.xlim = [min(self.xPress,self.xRelease),max(self.xPress,self.xRelease)] self.ylim = [ min(self.yPress,self.yRelease),max(self.yPress,self.yRelease)] self.drawz(setlim=False) def onAnimationBtn(self,event): ''' Function when Animation button is pressed''' printDir = self.croco.path_script+"/Figures_" + self.croco.get_run_name()+"/" if not os.path.isdir(printDir): os.mkdir(printDir) filename = printDir+self.title + ".mp4" os.system('rm -rf '+filename) self.clim = [np.min(self.variableZ),np.max(self.variableZ)] save_count = self.endTimeIndex - self.startTimeIndex + 1 anim = animation.FuncAnimation(self.figure, self.animate, \ frames = range(self.startTimeIndex,self.endTimeIndex+1), repeat=False, \ blit = False, save_count=save_count) self.canvas.draw() anim.save(filename) def animate( self, i): ''' Function done at each step of the animation''' self.timeIndex = i self.updateVariableZ(timeIndex=i, setlim=False) def onstartTimeTxt(self,event): self.startTime = float(self.startTimeTxt.GetValue()) self.startTimeIndex = min( range( len(self.croco.times[:]) ), key=lambda j:abs(self.startTime-self.croco.times[j])) self.startTimeTxt.SetValue(str(self.croco.times[self.startTimeIndex])) def onendTimeTxt(self,event): self.endTime = float(self.endTimeTxt.GetValue()) self.endTimeIndex = min( range( len(self.croco.times[:]) ), key=lambda j:abs(self.endTime-self.croco.times[j])) self.endTimeTxt.SetValue(str(self.croco.times[self.endTimeIndex])) def onZoomInBtn(self,event): self.figure.RS.set_active(True) def onZoomOutBtn(self,event): self.xlim = [np.min(self.x),np.max(self.x)] self.ylim = [np.min(self.y),np.max(self.y)] self.drawz(setlim=False) def onPrintBtn(self,event): ''' Save the plot in a file croco_visu/Figures_.../title.png ''' printDir = self.croco.path_script+"/Figures_" + self.croco.get_run_name()+"/" if not os.path.isdir(printDir): os.mkdir(printDir) filename = printDir+self.title + ".png" self.figure.savefig(filename, dpi=self.figure.dpi) def onResetColorBtn(self,event): self.clim = [np.min(self.variableZ),np.max(self.variableZ)] self.MinColorTxt.SetValue('%.2E' % self.clim[0]) self.MaxColorTxt.SetValue('%.2E' % self.clim[1]) self.drawz(setlim=False) def onMinColorTxt(self,event): self.clim[0] = float(self.MinColorTxt.GetValue()) self.drawz(setlim=False) def onMaxColorTxt(self,event): self.clim[1] = float(self.MaxColorTxt.GetValue()) self.drawz(setlim=False) def updateVariableZ(self, timeIndex=None, setlim=True): ''' Fill self.variableZ with the new data according modified parameters for the section ''' # Variable in croco file if self.variableName in self.croco.ListOfVariables: if timeIndex is None: timeIndex = self.timeIndex if self.typSection=="YZ": indices="["+str(timeIndex)+",:,:,"+str(self.latlonIndex)+"]" else: indices="["+str(timeIndex)+",:,"+str(self.latlonIndex)+",:]" self.variableZ = self.croco.read_nc(self.variableName, indices= indices) # Derived variable elif self.variableName in self.croco.ListOfDerived: # if self.variableName == 'pv': if 'pv' in self.variableName: pv = self.croco.get_pv(timeIndex, minlev=0, maxlev=self.croco.crocoGrid.N-1,typ=self.variableName) if self.typSection=="YZ": self.variableZ = pv[:,:,self.latlonIndex] else: self.variableZ = pv[:,self.latlonIndex,:] # Plot the section variable self.time = self.croco.times[timeIndex] self.drawz(setlim=setlim) def drawz(self, setlim=True): ''' draw the current self.variableZ variable ''' self.figure.clf() # Prepare canvas to receive the mouse click self.canvas.mpl_connect('button_press_event', self.onFigureClick) self.canvas.mpl_connect('button_release_event', self.onFigureRelease) # Mask Nan values variableZ = ma.masked_invalid(self.variableZ) # Calculate default parameters of the plot if necessary if setlim: self.clim = [np.min(variableZ),np.max(variableZ)] self.mincolor = np.min(variableZ) self.MinColorTxt.SetValue('%.2E' % self.mincolor) self.maxcolor = np.max(variableZ) self.MaxColorTxt.SetValue('%.2E' % self.maxcolor) self.xlim = [np.min(self.x),np.max(self.x)] self.ylim = [np.min(self.y),np.max(self.y)] # Plot variableZ self.title = "{:s}, {:s}={:4.1f}, Time={:4.1f}".format(self.variableName,self.section,self.latlon,self.time) mypcolor(self,self.x,self.y,variableZ,\ title=self.title,\ xlabel=self.xlabel,\ ylabel='Depth',\ xlim=self.xlim,\ ylim=self.ylim,\ clim=self.clim) self.canvas.draw() self.canvas.Refresh() self.Show()
class PreviewPanel(wx.Panel): """ Panel providing a simple image preview for the output of ASL_FILE. Used so user can check their choice of data grouping/ordering looks right """ def __init__(self, parent): wx.Panel.__init__(self, parent, size=wx.Size(300, 600)) self.data = None self.run = None self.slice = -1 self.nslices = 1 self.view = 0 self.figure = Figure(figsize=(3.5, 3.5), dpi=100, facecolor='black') self.axes = self.figure.add_subplot(111, facecolor='black') self.axes.get_xaxis().set_ticklabels([]) self.axes.get_yaxis().set_ticklabels([]) self.canvas = FigureCanvas(self, -1, self.figure) self.canvas.mpl_connect('scroll_event', self.scroll) self.canvas.mpl_connect('button_press_event', self.view_change) self.sizer = wx.BoxSizer(wx.VERTICAL) font = self.GetFont() font.SetWeight(wx.BOLD) text = wx.StaticText(self, label="Data preview - perfusion weighted image") text.SetFont(font) self.sizer.AddSpacer(10) self.sizer.Add(text, 0) self.sizer.Add(self.canvas, 2, border=5, flag=wx.EXPAND | wx.ALL) hbox = wx.BoxSizer(wx.HORIZONTAL) hbox.Add(wx.StaticText( self, label= "Use scroll wheel to change slice, double click to change view"), 0, flag=wx.ALIGN_CENTRE_VERTICAL) self.update_btn = wx.Button(self, label="Update") self.update_btn.Bind(wx.EVT_BUTTON, self._changed) hbox.Add(self.update_btn) self.sizer.Add(hbox) self.sizer.AddSpacer(10) text = wx.StaticText(self, label="Data order preview") text.SetFont(font) self.sizer.Add(text, 0) self.order_preview = AslDataPreview(self, 1, 1, True, "trp", True) self.sizer.Add(self.order_preview, 2, wx.EXPAND) self.SetSizer(self.sizer) self.Layout() def _changed(self, _): self.update() def update(self): """ Update the preview. This is called explicitly when the user clicks the update button as it may be slow """ self.data = None if self.run is not None: self.data = self.run.get_preview_data() if self.data is not None: self.view = 0 self._init_view() self.redraw() def _init_view(self): self.nslices = self.data.shape[2 - self.view] self.slice = int(self.nslices / 2) self.redraw() def redraw(self): """ Redraw the preview image """ self.axes.clear() if self.data is None: return if self.view == 0: sl = self.data[:, :, self.slice] elif self.view == 1: sl = self.data[:, self.slice, :] else: sl = self.data[self.slice, :, :] i = self.axes.imshow(sl.T, interpolation="nearest", vmin=sl.min(), vmax=sl.max()) self.axes.set_ylim(self.axes.get_ylim()[::-1]) i.set_cmap("gray") self.Layout() self.canvas.draw() self.canvas.Refresh() def view_change(self, event): """ Called on mouse click event. Double click changes the view direction and redraws """ if self.data is None: return if event.dblclick: self.view = (self.view + 1) % 3 self._init_view() self.redraw() def scroll(self, event): """ Called on mouse scroll wheel to move through the slices in the current view """ if event.button == "up": if self.slice != self.nslices - 1: self.slice += 1 else: if self.slice != 0: self.slice -= 1 self.redraw()
class GraphFrame(wx.Frame): """ The main frame of the application """ def __init__(self, state): wx.Frame.__init__(self, None, -1, state.title) try: self.SetIcon(icon.SimpleIcon().get_ico()) except Exception: pass self.state = state self.data = [] for i in range(len(state.fields)): self.data.append([]) self.paused = False self.create_main_panel() self.Bind(wx.EVT_IDLE, self.on_idle) self.redraw_timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer) self.redraw_timer.Start(int(1000*self.state.tickresolution)) self.last_yrange = (None, None) def create_main_panel(self): import platform if platform.system() == 'Darwin': from MAVProxy.modules.lib.MacOS import backend_wxagg FigCanvas = backend_wxagg.FigureCanvasWxAgg else: from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas self.panel = wx.Panel(self) self.init_plot() self.canvas = FigCanvas(self.panel, -1, self.fig) self.close_button = wx.Button(self.panel, -1, "Close") self.Bind(wx.EVT_BUTTON, self.on_close_button, self.close_button) self.pause_button = wx.Button(self.panel, -1, "Pause") self.Bind(wx.EVT_BUTTON, self.on_pause_button, self.pause_button) self.Bind(wx.EVT_UPDATE_UI, self.on_update_pause_button, self.pause_button) self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) self.hbox1.Add(self.close_button, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL) self.hbox1.AddSpacer(1) self.hbox1.Add(self.pause_button, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL) self.vbox = wx.BoxSizer(wx.VERTICAL) self.vbox.Add(self.canvas, 1, flag=wx.LEFT | wx.TOP | wx.GROW) self.vbox.Add(self.hbox1, 0, flag=wx.ALIGN_LEFT | wx.TOP) self.panel.SetSizer(self.vbox) self.vbox.Fit(self) def init_plot(self): self.dpi = 100 from matplotlib.figure import Figure self.fig = Figure((6.0, 3.0), dpi=self.dpi) self.axes = self.fig.add_subplot(111) try: self.axes.set_facecolor('white') except AttributeError as e: # this was removed in matplotlib 2.2.0: self.axes.set_axis_bgcolor('white') pylab.setp(self.axes.get_xticklabels(), fontsize=8) pylab.setp(self.axes.get_yticklabels(), fontsize=8) # plot the data as a line series, and save the reference # to the plotted line series # self.plot_data = [] if len(self.data[0]) == 0: max_y = min_y = 0 else: max_y = min_y = self.data[0][0] for i in range(len(self.data)): p = self.axes.plot( self.data[i], linewidth=1, color=self.state.colors[i], label=self.state.fields[i], )[0] self.plot_data.append(p) if len(self.data[i]) != 0: min_y = min(min_y, min(self.data[i])) max_y = max(max_y, max(self.data[i])) # create X data self.xdata = numpy.arange(-self.state.timespan, 0, self.state.tickresolution) self.axes.set_xbound(lower=self.xdata[0], upper=0) if min_y == max_y: self.axes.set_ybound(min_y, max_y+0.1) self.axes.legend(self.state.fields, loc='upper left', bbox_to_anchor=(0, 1.1)) def draw_plot(self): """ Redraws the plot """ state = self.state if len(self.data[0]) == 0: print("no data to plot") return vhigh = max(self.data[0]) vlow = min(self.data[0]) for i in range(1,len(self.plot_data)): vhigh = max(vhigh, max(self.data[i])) vlow = min(vlow, min(self.data[i])) ymin = vlow - 0.05*(vhigh-vlow) ymax = vhigh + 0.05*(vhigh-vlow) if ymin == ymax: ymax = ymin + 0.1 * ymin ymin = ymin - 0.1 * ymin if (ymin, ymax) != self.last_yrange: self.last_yrange = (ymin, ymax) self.axes.set_ybound(lower=ymin, upper=ymax) #self.axes.ticklabel_format(useOffset=False, style='plain') self.axes.grid(True, color='gray') pylab.setp(self.axes.get_xticklabels(), visible=True) pylab.setp(self.axes.get_legend().get_texts(), fontsize='small') for i in range(len(self.plot_data)): ydata = numpy.array(self.data[i]) xdata = self.xdata if len(ydata) < len(self.xdata): xdata = xdata[-len(ydata):] self.plot_data[i].set_xdata(xdata) self.plot_data[i].set_ydata(ydata) self.canvas.draw() self.canvas.Refresh() def on_pause_button(self, event): self.paused = not self.paused def on_update_pause_button(self, event): label = "Resume" if self.paused else "Pause" self.pause_button.SetLabel(label) def on_close_button(self, event): self.redraw_timer.Stop() self.Destroy() def on_idle(self, event): time.sleep(self.state.tickresolution*0.5) def on_redraw_timer(self, event): # if paused do not add data, but still redraw the plot # (to respond to scale modifications, grid change, etc.) # state = self.state if state.close_graph.wait(0.001): self.redraw_timer.Stop() self.Destroy() return while state.child_pipe.poll(): state.values = state.child_pipe.recv() if self.paused: return for i in range(len(self.plot_data)): if (type(state.values[i]) == list): print("ERROR: Cannot plot array of length %d. Use 'graph %s[index]' instead"%(len(state.values[i]), state.fields[i])) self.redraw_timer.Stop() self.Destroy() return if state.values[i] is not None: self.data[i].append(state.values[i]) while len(self.data[i]) > len(self.xdata): self.data[i].pop(0) for i in range(len(self.plot_data)): if state.values[i] is None or len(self.data[i]) < 2: return self.draw_plot()
class pwxChartParms(wx.Frame): def __init__(self, *args, **kwds): self.linestyles = { "solid": "-", "dashed": "--", "dash-dot": "-.", "dotted": ':' } # , "points": '.', "pixels" :',' } self.markerstyles = { "None": ' ', "Circles": 'o', "Up-Triangle": '^', "Dn-Triangle": 'v', "Lt-Triangle": '<', "Rt-Triangle": '>', "Square": 's', "Plus": '+', "Cross": 'x', "Diamond": 'D', "Thin-Diamond": 'd', "Up-Tripod": "2", "Dn-Tripod": "1", "Lt-Tripod": "3", "Rt-Tripod": "4", "Hexagon-1": "H", "Hexagon-2": "h", "Pentagon": 'p', "Vertical": '|', "Horizontal": '_' } self.markerstyleskeys = self.markerstyles.keys() self.markerstyleskeys.sort() # begin wxGlade: pwxChartParms.__init__ kwds["style"] = wx.DEFAULT_FRAME_STYLE #kwds["style"] = wx.RESIZE_BORDER wx.Frame.__init__(self, *args, **kwds) self.sizer_4_staticbox = wx.StaticBox(self, -1, "Line Parameters") self.sizer_5_staticbox = wx.StaticBox(self, -1, "") self.sizer_6_staticbox = wx.StaticBox(self, -1, "") self.sizer_3_staticbox = wx.StaticBox(self, -1, "Trace name") self.label_1 = wx.StaticText(self, -1, "Line label: ", style=wx.ALIGN_RIGHT | wx.ALIGN_CENTRE) self.label_ctrl_trace = wx.StaticText(self, -1, "", style=wx.ALIGN_RIGHT | wx.EXPAND) self.button_trace_color = wx.Button(self, -1, "Color of trace") #self.spin_ctrl_1 = wx.SpinCtrl(self, -1, "1", min=0, max=10) self.slider_ctrl_linewd = wx.Slider(self,-1,value=1,minValue=0,maxValue=10, \ style=wx.SL_HORIZONTAL| wx.SL_AUTOTICKS | wx.SL_LABELS) self.combo_box_line_type = wx.ComboBox(self, -1, "solid", choices=self.linestyles.keys(), style=wx.CB_DROPDOWN) self.button_marker_color = wx.Button(self, -1, "Color of marker") #self.spin_ctrl_marker = wx.SpinCtrl(self, -1, "1", min=0, max=10) self.slider_ctrl_marker = wx.Slider(self,-1,value=1,minValue=0,maxValue=10, \ style=wx.SL_HORIZONTAL| wx.SL_AUTOTICKS | wx.SL_LABELS) self.combo_box_marker_type = wx.ComboBox(self, -1, "None", choices=self.markerstyleskeys, style=wx.CB_DROPDOWN) self.m_myFigure = Figure(figsize=(1, 1), dpi=100) # Set the appropriately self.m_canvas = FigureCanvas(self, -1, self.m_myFigure) self.button_3 = wx.Button(self, -1, "Redraw") self.button_4 = wx.Button(self, -1, "Reset") self.button_5 = wx.Button(self, -1, "Apply") self.__set_properties() self.__do_layout() # end wxGlade # # I have to set the bindings here. # self.Bind(wx.EVT_BUTTON, self.drawSampleTrace, self.button_3) self.Bind(wx.EVT_BUTTON, self.resetLine, self.button_4) self.Bind(wx.EVT_BUTTON, self.applyParms, self.button_5) self.Bind(wx.EVT_CLOSE, self.handleDeadPlot) self.Bind(wx.EVT_BUTTON, self.setTraceColor, self.button_trace_color) self.Bind(wx.EVT_BUTTON, self.setMarkerColor, self.button_marker_color) self.Bind(wx.EVT_COMBOBOX, self.setTraceStyle, self.combo_box_line_type) self.Bind(wx.EVT_COMBOBOX, self.setMarkerStyle, self.combo_box_marker_type) #self.Bind(wx.EVT_SPINCTRL, self.setLineWidth, self.spin_ctrl_1) self.Bind(wx.EVT_SCROLL, self.setLineWidth, self.slider_ctrl_linewd) self.Bind(wx.EVT_SCROLL, self.setMarkerWidth, self.slider_ctrl_marker) #self.Bind(wx.EVT_SPINCTRL, self.setMarkerWidth, self.spin_ctrl_marker) def __set_properties(self): # begin wxGlade: pwxChartParms.__set_properties self.SetTitle("Set Line Parameters") self.combo_box_line_type.SetSelection(-1) self.combo_box_marker_type.SetSelection(-1) # end wxGlade def __do_layout(self): # begin wxGlade: pwxChartParms.__do_layout sizer_1 = wx.BoxSizer(wx.VERTICAL) sizer_2 = wx.BoxSizer(wx.VERTICAL) sizer_6 = wx.StaticBoxSizer(self.sizer_6_staticbox, wx.HORIZONTAL) sizer_5 = wx.StaticBoxSizer(self.sizer_5_staticbox, wx.HORIZONTAL) sizer_4 = wx.StaticBoxSizer(self.sizer_4_staticbox, wx.HORIZONTAL) sizer_3 = wx.StaticBoxSizer(self.sizer_3_staticbox, wx.HORIZONTAL) sizer_3.Add(self.label_1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 1) sizer_3.Add(self.label_ctrl_trace, 1, wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 0) sizer_2.Add(sizer_3, 0, wx.EXPAND, 0) sizer_4.Add(self.button_trace_color, 1, wx.EXPAND | wx.ADJUST_MINSIZE, 0) #sizer_4.Add(self.spin_ctrl_1, 1, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) sizer_4.Add( self.slider_ctrl_linewd, 1, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 0) sizer_4.Add(self.combo_box_line_type, 0, wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 0) sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) sizer_5.Add(self.button_marker_color, 1, wx.EXPAND | wx.ADJUST_MINSIZE, 0) #sizer_5.Add(self.spin_ctrl_marker, 1, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) sizer_5.Add( self.slider_ctrl_marker, 1, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 0) sizer_5.Add(self.combo_box_marker_type, 0, wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 0) sizer_2.Add(sizer_5, 0, wx.EXPAND, 0) #sizer_2.Add(self.text_ctrl_1, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) #self.sizer = wx.BoxSizer(wx.VERTICAL) sizer_2.Add(self.m_canvas, 1, wx.LEFT | wx.TOP | wx.GROW) sizer_6.Add(self.button_3, 1, wx.EXPAND | wx.ADJUST_MINSIZE, 0) sizer_6.Add(self.button_4, 1, wx.EXPAND | wx.ADJUST_MINSIZE, 0) sizer_6.Add(self.button_5, 1, wx.EXPAND | wx.ADJUST_MINSIZE, 0) sizer_2.Add(sizer_6, 0, wx.EXPAND, 0) sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) self.SetAutoLayout(True) self.SetSizer(sizer_1) sizer_1.Fit(self) sizer_1.SetSizeHints(self) self.Layout() # end wxGlade self.m_firstAxes = None self.x = arange(10) * 1.0 self.y = arange(10) * 1.0 self.label = '' self.lineColor = 'b' self.lineStyle = '-' self.lineWidth = 1 self.markerType = '' self.markerColor = 'r' self.markerSize = 0 self.master = None self.linenumber = 0 def handleDeadPlot(self, event): if self.master == None: return self.master.handleDeadLineParms(self.master) def applyParms(self, event): if self.master == None: return self.master.setLineParameters(self.master, self.linenumber, [ self.label, self.lineStyle, self.lineColor, self.lineWidth, self.markerType, self.markerColor, self.markerSize ]) def setMaster(self, who, ln): self.master = who self.linenumber = ln def getParameters(self): return ([ self.label, self.lineColor, self.lineStyle, self.lineWidth, self.markerType, self.markerColor, self.markerSize ]) def setParameters(self, parms): """ lbl, style.color.width of line type.color.size of marker. """ self.label, self.lineStyle , self.lineColor , self.lineWidth , self.markerType , \ self.markerColor , self.markerSize = parms self.drawSampleTrace() def resetLine(self, event=None): self.lineStyle = '-' self.lineColor = 'b' self.lineWidth = 1 self.markerType = '' self.markerColor = 'r' self.markerSize = 0 self.drawSampleTrace() def setLineWidth(self, event): self.lineWidth = int(event.GetEventObject().GetValue()) self.drawSampleTrace() def setMarkerWidth(self, event): self.markerSize = int(event.GetEventObject().GetValue()) self.drawSampleTrace() def setTraceStyle(self, event): x = event.GetEventObject().GetValue() self.lineStyle = self.linestyles.get(x, '-') self.drawSampleTrace() def setMarkerStyle(self, event): x = event.GetEventObject().GetValue() self.markerType = self.markerstyles.get(x, '') self.drawSampleTrace() def setTraceColor(self, event): dlg = wx.ColourDialog(None) if dlg.ShowModal() == wx.ID_OK: data = dlg.GetColourData() self.button_trace_color.SetBackgroundColour(data.GetColour()) xlist = data.GetColour() self.lineColor = "#%02X%02X%02X" % (xlist.Red(), xlist.Green(), xlist.Blue()) dlg.Destroy() self.drawSampleTrace() def setMarkerColor(self, event): dlg = wx.ColourDialog(None) if dlg.ShowModal() == wx.ID_OK: data = dlg.GetColourData() self.button_marker_color.SetBackgroundColour(data.GetColour()) xlist = data.GetColour() self.markerColor = "#%02X%02X%02X" % (xlist.Red(), xlist.Green(), xlist.Blue()) dlg.Destroy() self.drawSampleTrace() def drawSampleTrace(self, event=None): #print self.lineColor #print "Line style = " , self.lineStyle #print self.lineWidth #print "Marker Type = ", self.markerType #print self.markerColor #print self.markerSize self.label_ctrl_trace.SetLabel(self.label) self.m_myFigure.clf() r1 = [0.1, 0.1, 0.8, 0.8] self.m_firstAxes = self.m_myFigure.add_axes(r1, label='firstAxes') self.m_firstAxes.plot(self.x, self.y, color=self.lineColor, linestyle=self.lineStyle, linewidth=self.lineWidth, marker=self.markerType, markerfacecolor=self.markerColor, markersize=self.markerSize) self.m_canvas.Refresh()
class PlotOutputPanel(wx.Panel): """ Displays plots illustrating the optimized protocol """ def __init__(self, parent): self._opt_output = None self._params = None wx.Panel.__init__(self, parent, size=wx.Size(300, 600)) sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(sizer) plds_panel = wx.Panel(self) plds_sizer = wx.BoxSizer(wx.HORIZONTAL) plds_panel.SetSizer(plds_sizer) font = wx.Font(8, wx.FONTFAMILY_TELETYPE, wx.NORMAL, wx.NORMAL, False) label = wx.StaticText(plds_panel, label="Optimized PLDs (s)") plds_sizer.Add(label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) self._plds_text = wx.TextCtrl(plds_panel, style=wx.TE_READONLY) self._plds_text.SetFont(font) plds_sizer.Add(self._plds_text, 5, wx.ALL, 5) label = wx.StaticText(plds_panel, label="Scan time (s)") plds_sizer.Add(label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) self._scantime_text = wx.TextCtrl(plds_panel, style=wx.TE_READONLY) self._scantime_text.SetFont(font) plds_sizer.Add(self._scantime_text, 1, wx.ALL, 5) plds_panel.Layout() sizer.Add(plds_panel, 0, wx.EXPAND) hpanel = wx.Panel(self) hsizer = wx.BoxSizer(wx.HORIZONTAL) hpanel.SetSizer(hsizer) plot_choice_label = wx.StaticText(hpanel, label="Plot selection") hsizer.Add(plot_choice_label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) self._plot_choice = wx.Choice( hpanel, choices=["CBF error", "ATT error", "Kinetic curve"]) self._plot_choice.SetSelection(0) self._plot_choice.Bind(wx.EVT_CHOICE, self._update_plot) hsizer.Add(self._plot_choice, 1, wx.ALL | wx.ALIGN_RIGHT | wx.EXPAND, 5) #hpanel.Layout() sizer.Add(hpanel, 0) figure = Figure(figsize=(3.5, 3.5), dpi=100, facecolor='white') self._plot_axes = figure.add_subplot(111) figure.subplots_adjust(bottom=0.2) self._canvas = FigureCanvas(self, -1, figure) sizer.Add(self._canvas, 2, border=5, flag=wx.EXPAND | wx.ALL) self.Layout() def set_optimized_scan(self, params, scan, opt_output): self._opt_output = opt_output self._params = params self._scan = scan self._plds_text.Clear() self._plds_text.AppendText(" ".join( [str(pld) for pld in opt_output.plds])) self._scantime_text.Clear() self._scantime_text.AppendText(str(opt_output.scan_time)) self._update_plot() def _update_plot(self, _evt=None): if self._opt_output is None: return cbf_var = np.squeeze( np.mean(np.sqrt(np.abs(self._opt_output.cov_optimized[..., 0, 0])), axis=0)) att_var = np.squeeze( np.mean(np.sqrt(np.abs(self._opt_output.cov_optimized[..., 1, 1])), axis=0)) self._plot_axes.clear() if self._plot_choice.GetSelection() == 0: self._plot_axes.set_title("Estimated CBF error") self._plot_axes.set_ylabel('SD (ml/100g/min)') self._plot_axes.set_xlabel("ATT (s)") self._plot_axes.set_ylim(0, 10) self._plot_axes.plot(self._opt_output.att, cbf_var, label="Optimized protocol") self._plot_axes.legend() elif self._plot_choice.GetSelection() == 1: self._plot_axes.set_title("Estimated ATT error") self._plot_axes.set_ylabel("SD (s)") self._plot_axes.set_xlabel("ATT (s)") self._plot_axes.set_ylim(0, 0.25) self._plot_axes.plot(self._opt_output.att, att_var, label="Optimized protocol") self._plot_axes.legend() else: self._plot_axes.set_title("ASL kinetic curve") self._plot_axes.set_ylabel("Relative signal") self._plot_axes.set_xlabel("Time (s)") atts = np.linspace(1.0, 1.6, 3) for att in atts: xdata, ydata = self._kinetic_model(att, self._scan.tau, pldmax=max( self._opt_output.plds)) self._plot_axes.plot(xdata, ydata, label="ATT=%.2fs" % att) for pld in self._opt_output.plds: self._plot_axes.axvline(pld + self._scan.tau, linestyle='--', color='green') self._plot_axes.legend() self._canvas.draw() self._canvas.Refresh() def _kinetic_model(self, att, tau, f=50.0, lam=0.9, m0=1.0, alpha=0.85, t1b=1.65, t1t=1.445, pldmax=5.0): t_all = np.linspace(0, tau + pldmax + 1, 50) M = np.zeros(len(t_all)) f = f / 6000 # Fix units t1prime = 1 / (1.0 / t1t + f / lam) # During bolus relevant_ts = np.logical_and(t_all > att, t_all <= tau + att) t = t_all[relevant_ts] M[relevant_ts] = np.exp( -att / t1b) * (1 - np.exp(-(t - att) / t1prime)) # After bolus relevant_ts = t_all > att + tau t = t_all[relevant_ts] M[relevant_ts] = np.exp(-att / t1b) * np.exp( -(t - tau - att) / t1prime) * (1 - np.exp(-tau / t1prime)) M *= 2 * m0 * f * t1prime * alpha return t_all, M
class ClientGUI(wx.Frame): def __init__(self): self.create_GUI() def create_GUI(self): #This function creates buttons with defined position and connects(binds) them with events that #This function creates buttons with defined position and connects(binds) them with events that #####Global start variable#### self.local_time = time() self.AirT_cjc = -2. self.OasisT_cjc = -2. self.smooth_factor = 1 self.calib = [1, 0, 1, 0, 0] self.time_list = [ 10 * 50, 30 * 50, 60 * 50, 60 * 2 * 50, 60 * 5 * 50, 60 * 10 * 50, 60 * 30 * 50, 3600 * 1 * 50, 3600 * 2 * 50, 3600 * 6 * 50, 3600 * 12 * 50, len(buffer.buffer[0, :]) ] self.time_range = 10 * 50 self.txt_font_size = 10 self.arg2 = 10 self.environment = 0 #APS is 0, NIH is 1; localhost is 2 self.DicObjects = { } #this is a dictionary with all different objects in GUI ##Create Frame ans assign panel frame = wx.Frame.__init__(self, None, wx.ID_ANY, "Monitor (DI-245)", pos=(0, 0)) self.panel = wx.Panel(self, wx.ID_ANY, style=wx.BORDER_THEME, size=(400, 70), pos=(0, 0)) ########################################################################### ##MENU STARTS: for the GUI ########################################################################### file_item = {} about_item = {} self.calib_item = {} self.opt_item = {} menubar = wx.MenuBar() fileMenu = wx.Menu() file_item[2] = fileMenu.Append(wx.ID_EXIT, 'Quit', 'Quit application') self.Bind(wx.EVT_MENU, self.OnQuit, file_item[2]) calibMenu = wx.Menu() self.calib_item[0] = calibMenu.Append(wx.NewId(), "Calibrate", "") self.Bind(wx.EVT_MENU, self._on_server_comm, self.calib_item[0]) optMenu = wx.Menu() self.opt_item[0] = optMenu.Append(wx.NewId(), '(0) Echo Server') self.opt_item[1] = optMenu.Append(wx.NewId(), '(1) Close Server') self.opt_item[2] = optMenu.Append(wx.NewId(), '(2) CA Broadcast') self.opt_item[6] = optMenu.Append(wx.NewId(), '(6) Perform calibration') self.opt_item[7] = optMenu.Append(wx.NewId(), '(7) Get calibration') self.Bind(wx.EVT_MENU, self._on_server_comm, self.opt_item[0]) self.Bind(wx.EVT_MENU, self._on_server_comm, self.opt_item[1]) aboutMenu = wx.Menu() about_item[0] = aboutMenu.Append(wx.ID_ANY, 'Client About') about_item[1] = aboutMenu.Append(wx.ID_ANY, 'Server About') self.Bind(wx.EVT_MENU, self._on_client_about, about_item[0]) self.Bind(wx.EVT_MENU, self._on_server_about, about_item[1]) menubar.Append(fileMenu, '&File') menubar.Append(calibMenu, '&Calibration') menubar.Append(optMenu, '&Options') menubar.Append(aboutMenu, '&About') self.SetMenuBar(menubar) self.Centre() self.Show(True) ########################################################################### ###MENU ENDS### ########################################################################### sizer = wx.GridBagSizer(5, 2) text4 = wx.StaticText(self.panel, label="Server IP") sizer.Add(text4, pos=(0, 0), flag=wx.TOP | wx.LEFT, border=5) self.ip_dropdown_list = [[ '164.54.161.34', '128.231.5.78', '127.0.0.1' ], ['APS', 'NIH', 'localhost']] self.IP_choice = wx.Choice(self.panel, choices=self.ip_dropdown_list[1][:]) self.IP_choice.SetSelection(self.environment) self.IP_choice.Bind(wx.EVT_CHOICE, self._on_change_ip_press) sizer.Add(self.IP_choice, pos=(0, 1), span=(1, 1), flag=wx.TOP | wx.EXPAND, border=5) self.flashingText = wx.StaticText(self.panel) self.flashingText.SetLabel('Ready') sizer.Add(self.flashingText, pos=(0, 3), flag=wx.TOP | wx.LEFT, border=5) self.DicObjects[4] = wx.Button(self.panel, label="Start") sizer.Add(self.DicObjects[4], pos=(0, 4), flag=wx.TOP | wx.RIGHT, border=5) self.DicObjects[4].Bind(wx.EVT_BUTTON, self.mthd_buttons) self.live_checkbox = wx.CheckBox(self.panel, id=wx.ID_ANY, label="Live", style=0, validator=wx.DefaultValidator, name='LiveCheckBoxNameStr') sizer.Add(self.live_checkbox, pos=(1, 0), flag=wx.TOP | wx.LEFT, border=5) self.live_checkbox.SetValue(False) self.live_checkbox.Disable() self.DicObjects['server time'] = wx.StaticText(self.panel) self.DicObjects['server time'].SetLabel('') sizer.Add(self.DicObjects['server time'], pos=(1, 1), flag=wx.TOP | wx.LEFT, border=5) self.DicObjects['server time'].SetLabel('Press Start Button') text5 = wx.StaticText(self.panel, label="time") sizer.Add(text5, pos=(1, 3), flag=wx.TOP | wx.LEFT, border=5) self.time_dropdown_list = [ '10 s', '30 s', '1 min', '2 min', '5 min', '10 min', '30 min', '1 h', '2 h', '6 h', '12 h', 'max' ] #, 'max'] self.time_choice = wx.Choice(self.panel, choices=self.time_dropdown_list) sizer.Add(self.time_choice, pos=(1, 4), span=(4, 5), flag=wx.LEFT | wx.TOP, border=5) self.time_choice.Bind(wx.EVT_CHOICE, self._on_change_time_press) self.time_choice.SetSelection(1) self.live_checkbox.SetValue(False) sizer.AddGrowableCol(2) self.panel.SetSizer(sizer) self.dpi = 100 self.figure = Figure((4, 6), dpi=self.dpi) self.axes0 = self.figure.add_subplot(411) self.axes1 = self.figure.add_subplot(412) self.axes2 = self.figure.add_subplot(413) self.axes3 = self.figure.add_subplot(414) self.canvas = FCW(self, -1, self.figure) gsizer = wx.BoxSizer(wx.VERTICAL) gsizer.Add(self.panel, 0) gsizer.Add(self.canvas, 1, wx.EXPAND) self.SetSizer(gsizer) self.Fit() self.redraw_timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer) self.redraw_timer.Start(1000) self.draw(None) def _on_client_about(self, event): "Called from the Help/About" from os.path import basename from inspect import getfile filename = getfile(lambda x: None) info = basename(filename) + " version: " + __version__ + "\n" + __doc__ dlg = wx.MessageDialog(self, info, "About", wx.OK | wx.ICON_INFORMATION) dlg.CenterOnParent() dlg.ShowModal() dlg.Destroy() def _on_server_about(self, event): wx.MessageBox('This is information about the server', 'Server Info', wx.OK | wx.ICON_INFORMATION) def OnQuit(self, event): self.Close() def _on_change_ip_press(self, event): info("Dropdown IP menu: selected %s , New IP address : %r" % (self.ip_dropdown_list[1][self.IP_choice.GetSelection()], self.ip_dropdown_list[0][self.IP_choice.GetSelection()])) client.ip_address_server = self.ip_dropdown_list[0][ self.IP_choice.GetSelection()] self.live_checkbox.SetValue(False) self.live_checkbox.Disable() def _on_change_time_press(self, event): self.time_list = [ 10 * 50, 30 * 50, 60 * 50, 60 * 2 * 50, 60 * 5 * 50, 60 * 10 * 50, 60 * 30 * 50, 3600 * 1 * 50, 3600 * 2 * 50, 3600 * 6 * 50, 3600 * 12 * 50, len(buffer.buffer[0, :]) ] self.time_range = self.time_list[self.time_choice.GetSelection()] if self.time_range >= len(buffer.buffer[0, :]): self.time_range = self.time_list[len(self.time_list) - 1] self.time_choice.SetSelection(len(self.time_list) - 1) info('self time_range selected %r' % (self.time_range)) if self.time_range == 10 * 50: self.smooth_factor = 1 self.redraw_timer.Start(1000) elif self.time_range == 30 * 50: self.smooth_factor = 1 self.redraw_timer.Start(1000) elif self.time_range == 1 * 60 * 50: self.smooth_factor = 20 self.redraw_timer.Start(1000) elif self.time_range == 2 * 60 * 50: self.smooth_factor = 30 self.redraw_timer.Start(1000) elif self.time_range == 5 * 60 * 50: self.smooth_factor = 50 self.redraw_timer.Start(1000) elif self.time_range == 10 * 60 * 50: self.smooth_factor = 60 self.redraw_timer.Start(1000) elif self.time_range == 0.5 * 3600 * 50: self.smooth_factor = 50 self.redraw_timer.Start(1000) elif self.time_range == 3600 * 50: self.smooth_factor = 250 self.redraw_timer.Start(3000) elif self.time_range == 2 * 3600 * 50: self.smooth_factor = 500 self.redraw_timer.Start(4000) elif self.time_range == 6 * 3600 * 50: self.smooth_factor = 2000 self.redraw_timer.Start(5000) elif self.time_range == 12 * 3600 * 50: self.smooth_factor = 6000 self.redraw_timer.Start(5000) elif self.time_range > 12 * 3600 * 50: self.smooth_factor = 12000 self.redraw_timer.Start(10000) else: self.smooth_factor = 1 self.draw(None) def _on_command_list_select(self, event): info('commands from the list selected') # self._create_button(0,'Echo (0)',(step_h*0+step_h_zero,step_v*0+step_v_zero),'mthd_buttons') # self._create_button(1,'Close Server (1)',(step_h*0+step_h_zero,step_v*1+step_v_zero),'mthd_buttons') # self._create_button(2,'Broadcast burst (2)',(step_h*0+step_h_zero,step_v*2+step_v_zero),'mthd_buttons') # self._create_button(3,'Get mean(N) (3)',(step_h*0+step_h_zero,step_v*3+step_v_zero),'mthd_buttons') # self._create_button(4,'All buffer (4)',(step_h*0+step_h_zero,step_v*4+step_v_zero),'mthd_buttons') # self._create_button(5,'Update buffer (5)',(step_h*0+step_h_zero,step_v*5+step_v_zero),'mthd_buttons') # self._create_button(6,'Plot (6)',(step_h*0+step_h_zero,step_v*6+step_v_zero),'_on_button_plot') # self._create_button(7,'Save to file (7)',(step_h*0+step_h_zero,step_v*7+step_v_zero),'_on_save_file_press') def _set_response(self, response_arg): self.local_time = response_arg[1] self.DicObjects['server time'].SetLabel( strftime("%Y-%m-%d %H:%M:%S", localtime(self.local_time))) def method_result(self, method='window'): if method == 'window': self.DicObjects['result'].SetLabel(str(self.result)) def help_button(self, event): info('Help button was pressed') def _on_button_plot(self, event): info('plot button pressed') self.draw(event) def _on_server_comm(self, event): # self.calib_item[0]= calibMenu.Append(wx.NewId(), "Calibrate" ,"") # self.opt_item[0]= optMenu.Append(wx.NewId(), 'Echo Server') # self.opt_item[1]= optMenu.Append(wx.NewId(), 'Close Server') try: if event.GetId() == self.calib_item[0].GetId(): command = 6 elif event.GetId() == self.opt_item[0].GetId(): command = 0 elif event.GetId() == self.opt_item[1].GetId(): command = 1 flag = True except: flag = False if event == 7: command = 7 flag = True info('sending command = %r' % (command)) if flag: client._connect() client._send(str(command)) sleep(0.005) client._receive() client.server.close() info('Command processed: %r' % client.response_arg[0]) info('server time: %r' % client.response_arg[1]) info('arg1: %r' % client.response_arg[2]) info('arg2: %r' % client.response_arg[3]) if command == 6: self.calib = client.response_arg[2] if command == 7: self.calib = client.response_arg[2] self._set_response(client.response_arg) def _on_save_file_press(self, event): #msgpack_packb([time(),], default=m.encode) np.savetxt('DI_245_circular_buffer' + str(time()) + '.csv', np.transpose(buffer.buffer), delimiter=',', fmt='%1.4e') def mthd_buttons(self, event): """ This method is an event handler. It cross refences the event Id and an Id stored in a dictionary to determine what to do. """ if event == 'change_ip': pass else: self.flashingText.SetLabel('Pulling') info('Event ID %r' % event.GetId()) raw_commands = '0' for i in self.DicObjects.keys(): if event.GetId() == self.DicObjects[i].GetId(): raw_commands = str(i) if i == 3: raw_commands = raw_commands + ',' + str(self.arg2) print('raw_commands %r' % raw_commands) client._connect() client._send(raw_commands) sleep(0.005) client._receive() client.server.close() if client.response_arg[0] == 0: print('Command processed:', client.response_arg[0]) print('server time:', client.response_arg[1]) print('arg1:', client.response_arg[2]) print('arg2:', client.response_arg[3]) self._set_response(client.response_arg) elif client.response_arg[0] == 1: print("Server has been shut down") self._set_response(client.response_arg) elif client.response_arg[0] == 2: print('Command processed:', client.response_arg[0]) print('server time:', client.response_arg[1]) print('arg1:', client.response_arg[2]) print('arg2:', client.response_arg[3]) self._set_response(client.response_arg) elif client.response_arg[0] == 3: print('Command processed:', client.response_arg[0]) print('server time:', client.response_arg[1]) print('arg1:', client.response_arg[2]) print('arg2:', client.response_arg[3]) self._set_response(client.response_arg) self._update_readings(client.response_arg) elif client.response_arg[0] == 4: print('test') print('Command processed:', client.response_arg[0]) print('server time:', client.response_arg[1]) print('arg1:', client.response_arg[2]) print('arg2:', client.response_arg[3]) buffer.get_all(int(client.response_arg[2]), client.response_arg[3]) self._set_response(client.response_arg) self._on_server_comm(7) self.live_checkbox.SetValue(True) self.live_checkbox.Enable() elif client.response_arg[0] == 5: print('Command processed:', client.response_arg[0]) print('server time:', client.response_arg[1]) print('arg1:', client.response_arg[2]) print('arg2:', client.response_arg[3]) print('client.response_arg[2]', client.response_arg[2]) buffer.get_update(int(client.response_arg[2]), client.response_arg[3]) self._set_response(client.response_arg) elif client.response_arg[0] == 6: print('Command processed:', client.response_arg[0]) print('server time:', client.response_arg[1]) print('arg1:', client.response_arg[2]) print('arg2:', client.response_arg[3]) self.calib = client.response_arg[2] self._set_response(client.response_arg) elif client.response_arg[0] == 7: print('Command processed:', client.response_arg[0]) print('server time:', client.response_arg[1]) print('arg1:', client.response_arg[2]) print('arg2:', client.response_arg[3]) self.calib = client.response_arg[2] self._set_response(client.response_arg) else: print('Command processed:', client.response_arg[0]) print('server time:', client.response_arg[1]) print('arg1:', client.response_arg[2]) print('arg2:', client.response_arg[3]) self._set_response(client.response_arg) self.flashingText.SetLabel('Ready') ################################################################################# ########### Plotting ################################################################################# def on_redraw_timer(self, event): if self.live_checkbox.IsChecked( ): #plot only if the live checkbox is checked self.flashingText.SetLabel('Pulling') client._connect() client._send('5') sleep(0.005) client._receive() client._server_close() buffer.get_update(client.response_arg[2], client.response_arg[3]) self._set_response(client.response_arg) self.draw(event) self.flashingText.SetLabel('Ready') def smooth(self, y, step=1 ): #this is a smoothing function that helps speed up plotting if step == 1: y_out = y else: y_out = np.zeros(len(y) / step) for i in range(len(y_out)): if i == 0: y_out[i] = np.mean(y[0:int((1) * step)]) elif i == len(y_out) - 1: y_out[i] = np.mean(y[int((i) * step):]) else: y_out[i] = np.mean(y[int((i) * step):int((i + 1) * step)]) return y_out def draw(self, event): x = self.smooth(np.arange(-self.time_range * 0.02, 0, 0.02), self.smooth_factor) self.axes0.cla() self.axes1.cla() self.axes2.cla() self.axes3.cla() plot_from = buffer.pointerC - self.time_range plot_to = buffer.pointerC if buffer.pointerC > self.time_range: y1 = self.smooth(( (buffer.buffer[0, plot_from:plot_to] - 8192.) * 0.25 / 8192.) / self.calib[0], self.smooth_factor) y2 = self.smooth(( (buffer.buffer[2, plot_from:plot_to] - 8192.) * 0.25 / 8192.) / self.calib[2], self.smooth_factor) y3 = self.smooth( (buffer.buffer[1, plot_from:plot_to] - 8192.) * 0.036621 + 100. - self.calib[1], self.smooth_factor) y4 = self.smooth( (buffer.buffer[3, plot_from:plot_to] - 8192.) * 0.036621 + 100. - self.calib[3], self.smooth_factor) else: y = np.concatenate( (buffer.buffer[0, plot_from:], buffer.buffer[0, 0:plot_to])) y1 = self.smooth(((y - 8192.) * 0.25 / 8192.) / self.calib[0], self.smooth_factor) y = np.concatenate( (buffer.buffer[2, plot_from:], buffer.buffer[2, 0:plot_to])) y2 = self.smooth(((y - 8192.) * 0.25 / 8192.) / self.calib[2], self.smooth_factor) y = np.concatenate( (buffer.buffer[1, plot_from:], buffer.buffer[1, 0:plot_to])) y3 = self.smooth((y - 8192.) * 0.036621 + 100. - self.calib[1], self.smooth_factor) y = np.concatenate( (buffer.buffer[3, plot_from:], buffer.buffer[3, 0:plot_to])) y4 = self.smooth((y - 8192.) * 0.036621 + 100. - self.calib[3], self.smooth_factor) self.axes0.plot(x, y1, '-b', label='Upstream') self.axes1.plot(x, y2, '-g', label='Downstream') self.axes2.plot(x, y3, '-r') self.axes3.plot(x, y4, '-r') self.axes0.set_title('Pressure upstream') self.axes1.set_title('Pressure downstream') self.axes2.set_title('Air Temperature') self.axes3.set_title('Oasis Temperature') self.axes3.set_xlabel("time, seconds") self.axes0.set_xticklabels([]) self.axes1.set_xticklabels([]) self.axes2.set_xticklabels([]) self.axes0.set_xlim([np.min(x), np.max(x)]) self.axes1.set_xlim([np.min(x), np.max(x)]) self.axes2.set_xlim([np.min(x), np.max(x)]) self.axes3.set_xlim([np.min(x), np.max(x)]) self.axes0.set_ylim([ np.min(y1) - np.abs(np.min(y1)) * 0.02, np.max(y1) + np.abs(np.max(y1)) * 0.02 ]) self.axes1.set_ylim([ np.min(y2) - np.abs(np.min(y2)) * 0.02, np.max(y2) + np.abs(np.max(y2)) * 0.02 ]) self.axes2.set_ylim([ np.min(y3) - np.abs(np.min(y3)) * 0.02, np.max(y3) + np.abs(np.max(y3)) * 0.02 ]) self.axes3.set_ylim([ np.min(y4) - np.abs(np.min(y4)) * 0.02, np.max(y4) + np.abs(np.max(y4)) * 0.02 ]) self.axes0.grid() self.axes1.grid() self.axes2.grid() self.axes3.grid() divider = 5 #this is a tick divider, meaning how many ticks we have in plots. 5 tick = 6 div is a good choice step = (np.max(x) - np.min(x)) / divider range_lst = [] for i in range(divider + 1): range_lst.append(np.min(x) + step * i) label_lst = [] if self.time_choice.GetSelection( ) == 0 or self.time_choice.GetSelection( ) == 1 or self.time_choice.GetSelection( ) == 2 or self.time_choice.GetSelection() == 3: time_format = '%M:%S' elif self.time_choice.GetSelection( ) == 4 or self.time_choice.GetSelection( ) == 5 or self.time_choice.GetSelection() == 6: time_format = '%H:%M' else: time_format = '%H:%M:%S' for i in range(len(range_lst) - 1): label_lst.append( strftime(time_format, localtime(self.local_time + range_lst[i]))) i = i + 1 label_lst.append( strftime('%H:%M:%S', localtime(self.local_time + range_lst[i]))) self.axes3.set_xticklabels(label_lst) self.axes0.set_xticks(range_lst) self.axes1.set_xticks(range_lst) self.axes2.set_xticks(range_lst) self.axes3.set_xticks(range_lst) self.axes3.set_xlabel("local time") self.canvas.Refresh() self.canvas.Update() self.canvas.draw()