Пример #1
0
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()
Пример #2
0
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)
Пример #3
0
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()
Пример #4
0
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')
Пример #5
0
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()
Пример #8
0
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()
Пример #9
0
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")
Пример #10
0
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()
Пример #13
0
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")
Пример #14
0
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()
Пример #15
0
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()
Пример #16
0
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)
Пример #18
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)
Пример #19
0
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'))
Пример #21
0
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}")
Пример #22
0
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()
Пример #23
0
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()
Пример #24
0
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()
Пример #25
0
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()
Пример #26
0
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()
Пример #27
0
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
Пример #28
0
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()