Пример #1
0
class Plot(wx.Panel):
    def __init__(self, parent, id=-1, dpi=None):
        ps = parent.GetSize()
        wx.Panel.__init__(self, parent, id=id, size=ps)
        self.SetBackgroundColour('WHITE')
        self.figure = mpl.figure.Figure(dpi=dpi,
                                        facecolor='w',
                                        figsize=(ps[0] * .09, ps[1] * .09))
        #self.figure.SetBackgroundColour('WHITE')
        self.canvas = Canvas(self, -1, self.figure)
        self.canvas.SetBackgroundColour('WHITE')
        self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.doSave)

    def doSave(self, event):
        dlg = wx.FileDialog(self,
                            message="Save file as ...",
                            defaultDir=os.curdir,
                            defaultFile="",
                            wildcard="*.png",
                            style=wx.FD_SAVE)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
        dlg.Destroy()
        self.figure.savefig(path,
                            dpi=None,
                            facecolor='w',
                            edgecolor='w',
                            orientation='portrait',
                            papertype=None,
                            format='png',
                            transparent=False,
                            bbox_inches=None,
                            pad_inches=0.1,
                            frameon=None)
Пример #2
0
class RandomPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self._figure = Figure()
        self._axes = self._figure.add_subplot(1, 1, 1)
        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()
        self._scale = 2.0
        self._canvas.Bind(wx.EVT_LEFT_DOWN, self.up)
        self._canvas.Bind(wx.EVT_RIGHT_DOWN, self.down)
        return

    def draw(self, size=200):
        im = numpy.empty([size, size])

        import random

        for i in range(size):
            for j in range(size):
                im[i, j] = random.random() * self._scale

        plot = self._axes.imshow(im)
        plot.set_clim(0.0, 1.0)
        self._canvas.draw()

        return

    def up(self, event):
        self._scale += 0.1
        self.draw()
        return

    def down(self, event):
        self._scale -= 0.1
        self.draw()
        return
Пример #3
0
 def __init__(self,parent,id,title):
     wx.Frame.__init__(self,parent,id,title,style= wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER, size = (480,640))
     self.fig = Figure((6,6),dpi=80)
     panel = wx.Panel(self,-1)
     sizer = wx.BoxSizer(wx.VERTICAL)
     agg = FigureCanvasWxAgg(panel,-1,self.fig)
     self.point_x = []
     self.point_y = []
     sizer.Add(agg,0,wx.TOP)
     self.labelText = wx.StaticText(panel,-1,"You have not clicked! ")
     sizer.Add(self.labelText,0,wx.Top)
     panel.SetSizer(sizer)
     agg.Bind(wx.EVT_LEFT_DOWN,self.onLeftClick)
     self.clickcount = 0
     self.draw_figure()
Пример #4
0
class CanvasFrameMap(wx.Frame):
    def __init__(self, ):
        wx.Frame.__init__(self, None, -1, 'Activity Map', size=(750, 750))

        self.SetBackgroundColour(wx.NamedColor("BLACK"))

        self.figure = Figure(figsize=(5, 5))
        self.axes = self.figure.add_subplot(111)

        duder = array(rangevecReorg)
        duder.shape = 80, 80

        self.axes.imshow(duder,
                         origin='upper',
                         cmap=cm.hot,
                         extent=(0, 80, 0, 80))
        self.axes.set_xlabel(str(FileString[0]))
        self.axes.set_ylabel('y')
        self.figure_canvas = FigureCanvas(self, -1, self.figure)

        # Note that event is a MplEvent
        self.figure_canvas.mpl_connect('motion_notify_event',
                                       self.UpdateStatusBar)
        self.figure_canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.figure_canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(self.sizer)
        self.Fit()

        self.statusBar = wx.StatusBar(self, -1)
        self.statusBar.SetFieldsCount(1)
        self.SetStatusBar(self.statusBar)

        self.toolbar = NavigationToolbar2Wx(self.figure_canvas)
        self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
        self.toolbar.Show()

    def ChangeCursor(self, event):
        self.figure_canvas.SetCursor(wx.StockCursor(wx.CURSOR_BULLSEYE))

    def UpdateStatusBar(self, event):
        if event.inaxes:
            x, y = event.xdata, event.ydata
            self.statusBar.SetStatusText(
                ("x= " + str(int(x)) + "  y=" + str(int(y))), 0)
Пример #5
0
class CanvasFrame(wx.Frame):
    def __init__(self, ):
        wx.Frame.__init__(self,None,-1,
                         'CanvasFrame',size=(550,350))

        self.SetBackgroundColour(wx.NamedColour("WHITE"))

        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        t = arange(0.0,3.0,0.01)
        s = sin(2*pi*t)

        self.axes.plot(t,s)
        self.axes.set_xlabel('t')
        self.axes.set_ylabel('sin(t)')
        self.figure_canvas = FigureCanvas(self, -1, self.figure)

        # Note that event is a MplEvent
        self.figure_canvas.mpl_connect('motion_notify_event', self.UpdateStatusBar)
        self.figure_canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.figure_canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(self.sizer)
        self.Fit()

        self.statusBar = wx.StatusBar(self, -1)
        self.statusBar.SetFieldsCount(1)
        self.SetStatusBar(self.statusBar)

        self.toolbar = NavigationToolbar2Wx(self.figure_canvas)
        self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
        self.toolbar.Show()

    def ChangeCursor(self, event):
        self.figure_canvas.SetCursor(wx.StockCursor(wx.CURSOR_BULLSEYE))

    def UpdateStatusBar(self, event):
        if event.inaxes:
            x, y = event.xdata, event.ydata
            self.statusBar.SetStatusText(( "x= " + str(x) +
                                           "  y=" +str(y) ),
                                           0)
Пример #6
0
    class Frame(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, parent=None, title="Colourmap Selection")

            self.figure = Figure(dpi=80, figsize=(2, 2))
            self.canvas = Canvas(self, -1, self.figure)
            self.axes = self.figure.gca()
            x = y = numpy.linspace(-3, 3, 80)
            X, Y = numpy.meshgrid(x, y)
            V = numpy.sin(Y**2 + X**2)
            self.mapper = FigureImage(self.figure)
            im = self.axes.pcolor(x, y, V, shading='flat')
            try:
                cb = self.mapper.callbacksSM.connect('changed', ChangeCM(im))
            except AttributeError:  # Using 0.91 style
                self.mapper.add_observer(im)
            #self.figure.colorbar(self.mapper)

            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.canvas, 1, wx.EXPAND)
            self.SetSizer(sizer)

            self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnContext)

        def OnContext(self, evt):
            popup = wx.Menu()
            item = popup.Append(wx.ID_ANY, '&Grid on/off', 'Toggle grid lines')
            wx.EVT_MENU(self, item.GetId(), self.OnGridToggle)
            cmapmenu = CMapMenu(self,
                                callback=self.OnColormap,
                                mapper=self.mapper,
                                canvas=self.canvas)
            item = popup.AppendMenu(wx.ID_ANY, "Colourmaps", cmapmenu)
            self.PopupMenu(popup, evt.GetPositionTuple())

        def OnColormap(self, name):
            print "Selected colormap", name

        def OnGridToggle(self, event):
            self.axes.grid()
            self.canvas.draw_idle()
class CanvasFrame(wx.Frame):
    def __init__(self, ):
        super().__init__(None, -1, 'CanvasFrame', size=(550, 350))

        self.figure = Figure()
        self.axes = self.figure.add_subplot()
        t = np.arange(0.0, 3.0, 0.01)
        s = np.sin(2 * np.pi * t)

        self.axes.plot(t, s)
        self.axes.set_xlabel('t')
        self.axes.set_ylabel('sin(t)')
        self.figure_canvas = FigureCanvas(self, -1, self.figure)

        # Note that event is a MplEvent
        self.figure_canvas.mpl_connect('motion_notify_event',
                                       self.UpdateStatusBar)
        self.figure_canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.figure_canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(self.sizer)
        self.Fit()

        self.statusBar = wx.StatusBar(self, -1)
        self.SetStatusBar(self.statusBar)

        self.toolbar = NavigationToolbar2Wx(self.figure_canvas)
        self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
        self.toolbar.Show()

    def ChangeCursor(self, event):
        self.figure_canvas.SetCursor(wx.Cursor(wx.CURSOR_BULLSEYE))

    def UpdateStatusBar(self, event):
        if event.inaxes:
            self.statusBar.SetStatusText("x={}  y={}".format(
                event.xdata, event.ydata))
Пример #8
0
class RegistrationPanel(wx.Panel):
    def __init__(self,
                 parent,
                 ID=-1,
                 label="",
                 pos=wx.DefaultPosition,
                 size=(100, 25)):
        #(0) Initialize panel:
        wx.Panel.__init__(self,
                          parent,
                          ID,
                          pos,
                          size,
                          style=wx.STATIC_BORDER | wx.WANTS_CHARS,
                          name=label)
        self.SetMinSize(size)
        self.parent = parent
        self.q = [0, 0, 0, 1]
        self.th = 5
        #(1) Create Matplotlib figure:
        self.figure = Figure(facecolor='0.8')
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        self._resize()
        self._create_axes()
        self.canvas.Bind(wx.EVT_KEY_DOWN, self.callback_key)
        self.canvas.Bind(wx.EVT_CHAR_HOOK, self.callback_key)

    def callback_key(self, event):
        keycode = event.GetKeyCode()

        #(0) Escape to exit:
        if keycode == wx.WXK_ESCAPE:
            ans = wx.MessageBox('Are you sure you want to quit?', '',
                                wx.YES_NO | wx.CENTRE | wx.NO_DEFAULT, self)
            if ans == wx.YES:
                self.parent.quit()
        #(1) Enter to finish:
        if keycode == wx.WXK_RETURN:
            self.parent.forward()
        #(2) Update transformation parameters:
        amp = 0.1 + (event.ControlDown() * (1 - 0.1)) + (event.ShiftDown() *
                                                         (5 - 0.1))
        if keycode == wx.WXK_UP: self.q[1] += amp
        if keycode == wx.WXK_DOWN: self.q[1] -= amp
        if keycode == wx.WXK_LEFT: self.q[0] -= amp
        if keycode == wx.WXK_RIGHT: self.q[0] += amp

        if keycode == 328: self.q[0] -= amp
        if keycode == 330: self.q[0] += amp
        if keycode == 326: self.q[1] -= amp
        if keycode == 332: self.q[1] += amp

        if keycode in [91, 123]: self.q[2] += 0.2 * amp  # '['
        if keycode in [93, 125]: self.q[2] -= 0.2 * amp  # ']'
        self.transform()

    def _create_axes(self):
        self.ax = self.figure.add_axes((0, 0, 1, 1), axisbg=[0.5] * 3)
        pyplot.setp(self.ax, xticks=[], yticks=[])

    def _resize(self):
        szPixels = tuple(self.GetClientSize())
        self.canvas.SetSize(szPixels)
        szInches = float(szPixels[0]) / self.figure.get_dpi(), float(
            szPixels[1]) / self.figure.get_dpi()
        self.figure.set_size_inches(szInches[0], szInches[1])

    def cla(self):
        self.ax.cla()
        self.ax.set_position([0, 0, 1, 1])
        self.ax.set_axis_bgcolor([0.5] * 3)
        pyplot.setp(self.ax, xticks=[], yticks=[], xlim=(0, 1), ylim=(0, 1))
        self.ax.axis('tight')
        self.canvas.draw()

    def plot(self):  #initial plot (after navigating to a new image)
        I = PM.transform2D(self.I, self.q)
        self.IT = I.copy()
        self.plot_source()
        # I[I==0] = np.nan
        # self.ax.imshow(I, interpolation='nearest', origin='lower', vmin=0, vmax=self.cmax)
        pyplot.setp(self.ax, xticks=[], yticks=[])
        self.ax.set_axis_bgcolor([0.05] * 3)
        self.ax.axis('image')
        self.canvas.draw()

    def plot_source(
            self):  #plot source (thresholded according to slider value)
        if self.ax.images:
            self.ax.images.pop(0)
        I = self.IT.copy()
        I[I <= self.th] = np.nan
        self.ax.imshow(I,
                       interpolation='nearest',
                       origin='lower',
                       vmin=0,
                       vmax=self.cmax)

    def plot_template(
            self,
            I0,
            th=0):  #plot template (thresholded according to slider value)
        self.th = th
        if self.ax.collections:
            self.ax.collections.pop(0)
        self.ax.contour(I0 > th, 1, colors="0.5", linewidths=3)
        self.plot_source()
        self.canvas.draw()

    def set_Iq(self, I, q):
        self.I = I.copy()
        self.q = q
        self.cmax = 0.95 * I.max()

    def transform(self):  #transform the source
        I = PM.transform2D(self.I, self.q)
        self.IT = I.copy()
        self.plot_source()
        self.canvas.draw()
Пример #9
0
class ModelView(wx.Panel):
    title = 'Profile'
    default_size = (600, 400)

    def __init__(self, *args, **kw):
        wx.Panel.__init__(self, *args, **kw)

        # Fig
        self.fig = Figure(
            figsize=(1, 1),
            dpi=75,
            facecolor='white',
            edgecolor='white',
        )
        # Canvas
        self.canvas = FigureCanvas(self, -1, self.fig)
        self.fig.set_canvas(self.canvas)

        # Axes
        self.axes = self.fig.add_axes(Subplot(self.fig, 111))
        self.axes.set_autoscale_on(False)
        self.theta_axes = self.axes.twinx()
        self.theta_axes.set_autoscale_on(False)

        # Show toolbar or not?
        self.toolbar = NavigationToolbar2WxAgg(self.canvas)
        self.toolbar.Show(True)

        # Create a figure manager to manage things
        self.figmgr = FigureManager(self.canvas, 1, self)

        # Panel layout
        self.profile_selector_label = wx.StaticText(self, label="Sample")
        self.profile_selector = wx.Choice(self)
        self.profile_selector.Hide()
        self.profile_selector_label.Hide()
        self.Bind(wx.EVT_CHOICE, self.OnProfileSelect)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas,
                       1,
                       border=2,
                       flag=wx.LEFT | wx.TOP | wx.GROW)
        self.tbsizer = wx.BoxSizer(wx.HORIZONTAL)
        self.tbsizer.Add(self.toolbar, 0, wx.ALIGN_CENTER_VERTICAL)
        self.tbsizer.AddSpacer(20)
        self.tbsizer.Add(self.profile_selector_label, 0,
                         wx.ALIGN_CENTER_VERTICAL)
        self.tbsizer.AddSpacer(5)
        self.tbsizer.Add(self.profile_selector, 0, wx.ALIGN_CENTER_VERTICAL)
        self.sizer.Add(self.tbsizer)

        self.SetSizer(self.sizer)
        self.sizer.Fit(self)

        # Status bar
        frame = self.GetTopLevelParent()
        self.statusbar = frame.GetStatusBar()
        if self.statusbar is None:
            self.statusbar = frame.CreateStatusBar()
        status_update = lambda msg: self.statusbar.SetStatusText(msg)

        # Set the profile interactor
        self.profile = ProfileInteractor(self.axes,
                                         self.theta_axes,
                                         status_update=status_update)

        # Add context menu and keyboard support to canvas
        self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnContextMenu)
        #self.canvas.Bind(wx.EVT_LEFT_DOWN, lambda evt: self.canvas.SetFocus())

        self.model = None
        self._need_interactors = self._need_redraw = False
        self.Bind(wx.EVT_SHOW, self.OnShow)

    def OnContextMenu(self, event):
        """
        Forward the context menu invocation to profile, if profile exists.
        """
        sx, sy = event.GetX(), event.GetY()
        #transform = self.axes.transData
        #data_x,data_y = pixel_to_data(transform, sx, self.fig.bbox.height-sy)

        popup = wx.Menu()
        item = popup.Append(wx.ID_ANY, '&Grid on/off', 'Toggle grid lines')
        wx.EVT_MENU(self, item.GetId(), lambda _:
                    (self.axes.grid(), self.fig.canvas.draw_idle()))
        item = popup.Append(wx.ID_ANY, '&Rescale', 'Show entire profile')
        wx.EVT_MENU(
            self, item.GetId(), lambda _:
            (self.profile.reset_limits(), self.profile.draw_idle()))
        self.PopupMenu(popup, (sx, sy))
        return False

    def OnProfileSelect(self, event):
        self._set_profile(*self.profiles[event.GetInt()])

    # ==== Model view interface ===
    def OnShow(self, event):
        if not event.Show:
            return
        #print "showing profile"
        if self._need_redraw:
            self.redraw(reset_interactors=False, reset_limits=True)
        #event.Skip()

    def get_state(self):
        return self.model

    def set_state(self, state):
        self.set_model(state)

    def set_model(self, model):
        # print ">>>>>>> refl1d profile set model"
        self.model = model
        self.redraw(reset_interactors=True, reset_limits=True)

    def update_model(self, model):
        # print ">>>>>>> refl1d profile update model"
        if self.model == model:
            self.redraw(reset_interactors=False, reset_limits=True)

    def update_parameters(self, model):
        # print ">>>>>>> refl1d profile update parameters"
        if self.model == model:
            self.redraw(reset_interactors=False, reset_limits=False)

    def redraw(self, reset_interactors=False, reset_limits=False):
        if reset_interactors:
            self._need_interactors = True

        if not self.IsShown():
            self._need_redraw = True
            return

        if self._need_interactors:
            self._create_interactors()
            self._set_profile(*self.profiles[0])
            self._need_interactors = False

        self.profile.redraw(reset_limits=reset_limits)

    # =============================================
    def _create_interactors(self):
        self.profiles = []

        def add_profiles(name, exp, idx):
            if isinstance(exp, MixedExperiment):
                for i, p in enumerate(exp.parts):
                    self.profiles.append((name + chr(ord("a") + i), p, idx))
            else:
                self.profiles.append((name, exp, idx))

        if isinstance(self.model, MultiFitProblem):
            for i, p in enumerate(self.model.models):
                if hasattr(p.fitness, "reflectivity"):
                    name = p.fitness.name
                    if not name: name = "M%d" % (i + 1)
                    add_profiles(name, p.fitness, i)
        else:
            add_profiles("", self.model.fitness, -1)

        self.profile_selector.Clear()
        if len(self.profiles) > 1:
            self.profile_selector.AppendItems([k for k, _, _ in self.profiles])
            self.profile_selector_label.Show()
            self.profile_selector.Show()
            self.profile_selector.SetSelection(0)
        else:
            self.profile_selector_label.Hide()
            self.profile_selector.Hide()

    def _set_profile(self, name, experiment, idx):
        # Turn the model into a user interface
        # It is the responsibility of the party that is indicating
        # that a redraw is necessary to clear the precalculated
        # parts of the view; otherwise the theory function calculator
        # is going to be triggered twice.  This happens inside profile
        # before the profile is calculated.  Note that the profile
        # panel will receive its own signal, which will cause the
        # profile interactor to draw itself again.  We hope this isn't
        # too much of a problem.
        def signal_update():
            """Notify other views that the model has changed"""
            signal.update_parameters(model=self.model)

        def force_recalc():
            self.model.model_update()

        if isinstance(self.model, MultiFitProblem):
            self.model.set_active_model(idx)
        self.profile.set_experiment(experiment,
                                    force_recalc=force_recalc,
                                    signal_update=signal_update)

    def onPrinterSetup(self, event=None):
        self.canvas.Printer_Setup(event=event)

    def onPrinterPreview(self, event=None):
        self.canvas.Printer_Preview(event=event)

    def onPrint(self, event=None):
        self.canvas.Printer_Print(event=event)

    def OnSaveFigureMenu(self, evt):
        """
        Save the current figure as an image file
        """
        dlg = wx.FileDialog(
            self,
            message="Save Figure As ...",
            defaultDir=os.getcwd(),
            defaultFile="",
            wildcard=
            "PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|All files (*.*)|*.*",
            style=wx.SAVE)
        _val = dlg.ShowModal()
        if _val == wx.ID_CANCEL: return  #Do nothing
        if _val == wx.ID_OK:
            outfile = dlg.GetPath()

        dlg.Destroy()

        # Save
        self.fig.savefig(outfile)

    def GetToolBar(self):
        """
        backend_wx call this function. KEEP it
        """
        return None

    def OnPanelFrameClose(self, evt):
        """
        On Close this Frame
        """
        self.Destroy()
        evt.Skip()

    def OnCopyFigureMenu(self, evt):
        """
        Copy the current figure
        """
        CopyImage(self.canvas)

    def CanShowContextMenu(self):
        return True

    def quit_on_error(self):
        numpy.seterr(all='raise')
        ProfileInteractor._debug = True
        BaseInteractor._debug = True
Пример #10
0
class PanelSpec(wx.Panel):
    def __init__(self, parent, parentMainFrame):
        wx.Panel.__init__(self, parent)
        self.CreatePanel()
        self.setSpLabel()
        self.parent = parentMainFrame

        self.FFT_Max_X = 5995
        self.FFT_Min_X = 70
        self.FFT_Max_Y = 60
        self.FFT_Min_Y = -120

        ######## upload ###########
        self.start_upload = 0

        ###### download #########
        self.download = 0
        self.dir = ""

        ############################
        self.thread = 0

    def getstartUploadOnce(self):
        return self.start_upload

    def getisDownLoad(self):
        return self.download

    def getDownloadDir(self):
        return self.dir

    def restore2unstart(self):
        self.start_upload = 0

    def restoreisDownLoad(self):
        self.download = 0

    ######################################################

    def CreatePanel(self):
        self.Figure = matplotlib.figure.Figure()
        self.axes = self.Figure.add_axes([0.05, 0.05, 0.93, 0.93])
        self.FigureCanvas = FigureCanvas(self, -1, self.Figure)
        self.ButtonAutoY = wx.Button(self, -1, label=u"纵轴恢复")
        self.ButtonAutoX = wx.Button(self, -1, label=u"横轴恢复")
        self.Max_Y = wx.TextCtrl(self,
                                 -1,
                                 '60',
                                 size=(60, 20),
                                 style=wx.TE_PROCESS_ENTER)
        self.Min_Y = wx.TextCtrl(self,
                                 -1,
                                 '-120',
                                 size=(60, 20),
                                 style=wx.TE_PROCESS_ENTER)
        self.Min_X = wx.TextCtrl(self,
                                 -1,
                                 '70',
                                 size=(60, 20),
                                 style=wx.TE_PROCESS_ENTER)
        self.Max_X = wx.TextCtrl(self,
                                 -1,
                                 '5995',
                                 size=(60, 20),
                                 style=wx.TE_PROCESS_ENTER)

        self.Upload = wx.Button(self, -1, label=u"数据上传")
        self.Download = wx.Button(self, -1, label=u"本地存储")

        ###################################test sizer##############################

        self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)

        bSizer4 = wx.BoxSizer(wx.VERTICAL)

        gSizer6 = wx.GridSizer(1, 7, 0, 0)

        gSizer6.Add(self.ButtonAutoX, 0,
                    wx.ALL | wx.ALIGN_BOTTOM | wx.ALIGN_RIGHT, 5)

        gSizer6.Add(self.ButtonAutoY, 0, wx.ALL, 5)
        gSizer6.AddSpacer((0, 0), 1, wx.EXPAND, 5)
        gSizer6.AddSpacer((0, 0), 1, wx.EXPAND, 5)
        gSizer6.AddSpacer((0, 0), 1, wx.EXPAND, 5)

        gSizer6.Add(self.Upload, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
        gSizer6.Add(self.Download, 0, wx.ALL | wx.ALIGN_LEFT, 5)

        bSizer4.Add(gSizer6, 0, wx.EXPAND, 5)

        bSizer5 = wx.BoxSizer(wx.HORIZONTAL)

        gSizer8 = wx.GridSizer(2, 1, 0, 0)

        gSizer8.Add(self.Max_Y, 0, wx.ALL, 5)

        gSizer8.Add(self.Min_Y, 0, wx.ALIGN_BOTTOM | wx.ALL, 5)

        bSizer5.Add(gSizer8, 0, wx.EXPAND, 5)

        gSizer10 = wx.GridSizer(1, 1, 0, 0)

        gSizer10.Add(self.FigureCanvas, 1, wx.ALL | wx.EXPAND, 5)

        bSizer5.Add(gSizer10, 5, wx.EXPAND, 5)

        bSizer4.Add(bSizer5, 4, wx.EXPAND, 5)

        gSizer9 = wx.GridSizer(1, 2, 0, 0)

        #         gSizer9.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 )
        #         self.m_textCtrl16 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( 80,-1 ), 0 )
        gSizer9.Add(self.Min_X, 0, wx.ALL, 5)

        #         self.m_textCtrl17 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( 80,-1 ), 0 )
        gSizer9.Add(self.Max_X, 0, wx.ALIGN_RIGHT | wx.ALL, 5)

        bSizer4.Add(gSizer9, 0, wx.EXPAND, 5)

        self.SetSizer(bSizer4)
        self.Layout()

        self.Centre(wx.BOTH)

        #####################################################################################
        self.Bind(wx.EVT_TEXT_ENTER, self.OnEnterMin_X, self.Min_X)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnEnterMax_X, self.Max_X)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnEnterMax_Y, self.Max_Y)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnEnterMin_Y, self.Min_Y)
        self.Bind(wx.EVT_BUTTON, self.OnAutoX, self.ButtonAutoX)
        self.Bind(wx.EVT_BUTTON, self.OnAutoY, self.ButtonAutoY)
        self.Bind(wx.EVT_BUTTON, self.OnUpload, self.Upload)
        self.Bind(wx.EVT_BUTTON, self.OnDownload, self.Download)

        self.popupmenu = wx.Menu()
        StringList = ["Add Marker", "Remove Marker", "All Marker Off"]
        for text in StringList:
            item = self.popupmenu.Append(-1, text)
            self.FigureCanvas.Bind(wx.EVT_CONTEXT_MENU, self.OnShowPopup)
            self.FigureCanvas.Bind(wx.EVT_MENU, self.OnPopupItemSelected, item)
        '''
        Array=linspace(70, 5995,238)
        self.xDataList=[]
        self.LineSpec=[]
        self.LineSpecBack=[]
        for i in xrange(237):
            xData=linspace(Array[i],Array[i+1],1024)
            self.xDataList.append(xData)
        
        ydata=[0]*1024
        for xData in self.xDataList:
            lineSpec,=self.axes.plot(xData,ydata,'y')
            lineSpecBack,=self.axes.plot(xData,ydata,'r')
            self.LineSpec.append(lineSpec)
            self.LineSpecBack.append(lineSpecBack)
        '''
        self.xData = linspace(70, 6470, 1024)
        self.yData = [0] * 1024
        self.lineSpec, = self.axes.plot(self.xData, self.yData, 'y')
        self.lineSpecBack, = self.axes.plot(self.xData, self.yData, 'r')
        ####Marker############
        self.drs = []

    def OnUpload(self, event):
        self.start_upload = 1

    def OnDownload(self, event):
        if (self.Download.GetLabel() == "LocalSave"):
            '''
            dlg=dialog_download(self)
            dlg.ShowModal()
            if(dlg.isValid):
                self.dir=dlg.m_dirPick.GetPath()
                print self.dir 
                '''
            self.download = 1
            self.Download.SetLabel(u"停止存储")
            '''start the thread localsave'''
            if (self.thread == 0):
                self.thread = thread_localsave.LocalSaveThread(
                    self.parent, self.parent.queueFFTLocalSave,
                    self.parent.queueAbLocalSave)
                self.thread.start()

            else:
                self.thread.event.set()

        else:
            '''stop the thread localsave'''
            self.thread.stop()

            self.Download.SetLabel(u"本地存储")
            self.download = 0

    def OnAutoX(self, event):
        self.setSpLabel(begin_X=self.parent.FreqMin,end_X=self.parent.FreqMax , \
            begin_Y=self.FFT_Min_Y,end_Y=self.FFT_Max_Y)
        self.FigureCanvas.draw()
        self.FFT_Min_X = self.parent.FreqMin
        self.FFT_Max_X = self.parent.FreqMax
        self.Min_X.SetValue(str(self.FFT_Min_X))
        self.Max_X.SetValue(str(self.FFT_Max_X))

    def OnAutoY(self, event):
        self.setSpLabel(begin_X=self.FFT_Min_X, end_X=self.FFT_Max_X)
        self.FigureCanvas.draw()
        self.FFT_Min_Y = -120
        self.FFT_Max_Y = 60
        self.Min_Y.SetValue("-120")
        self.Max_Y.SetValue("60")

    def OnEnterMin_X(self, event):
        self.FFT_Min_X = int(self.Min_X.GetValue())
        self.setSpLabel(self.FFT_Min_X, self.FFT_Max_X, self.FFT_Min_Y,
                        self.FFT_Max_Y)
        self.FigureCanvas.draw()

    def OnEnterMax_X(self, event):
        self.FFT_Max_X = int(self.Max_X.GetValue())
        self.setSpLabel(self.FFT_Min_X, self.FFT_Max_X, self.FFT_Min_Y,
                        self.FFT_Max_Y)
        self.FigureCanvas.draw()

    def OnEnterMin_Y(self, event):
        self.FFT_Min_Y = int(self.Min_Y.GetValue())
        self.setSpLabel(self.FFT_Min_X, self.FFT_Max_X, self.FFT_Min_Y,
                        self.FFT_Max_Y)
        self.FigureCanvas.draw()

    def OnEnterMax_Y(self, event):
        self.FFT_Max_Y = int(self.Max_Y.GetValue())
        self.setSpLabel(self.FFT_Min_X, self.FFT_Max_X, self.FFT_Min_Y,
                        self.FFT_Max_Y)
        self.FigureCanvas.draw()

    def OnShowPopup(self, event):
        pos = event.GetPosition()
        pos = self.FigureCanvas.ScreenToClient(pos)
        self.FigureCanvas.PopupMenu(self.popupmenu, pos)

    def OnPopupItemSelected(self, event):
        item = self.popupmenu.FindItemById(event.GetId())
        text = item.GetText()
        if (text == "Add Marker"):
            self.OnAddMarker()
        elif (text == "Remove Marker"):
            self.OnRemove()
        elif (text == "All Marker Off"):
            self.OnAllRemove()

    def DrawMarker(self, Max_X, Max_Y):
        distance = ((self.FFT_Max_X - self.FFT_Min_X) / 10)**2
        index = len(self.drs) + 1
        rect, = self.axes.plot(Max_X, Max_Y, 'rd', markersize=10)
        text = self.axes.text(Max_X + 5,
                              Max_Y + 2,
                              'M' + str(index),
                              color='r')
        textM=self.axes.text(self.FFT_Min_X+5,self.FFT_Max_Y-5*(index),'M'+str(index)+':'  \
            +'%.2f'%(Max_X)+'MHz  '+'%.2f'%(Max_Y)+'dBm')
#         DragRect=DraggableRectangle(rect,text,textM,self.LineSpec,self.FigureCanvas)
#         DragRect.setM_id('M'+str(index)+':')
#
#         DragRect.setRadius(distance)
#         DragRect.connect()
#         self.drs.append(DragRect)
#self.FigureCanvas.draw()

    def OnAddMarker(self):
        if (len(self.drs) < 4):
            startSection = (self.FFT_Min_X - 70) / 25
            endSection = (self.FFT_Max_X - 70) / 25
            lenStart = len(self.LineSpec[startSection].get_ydata())
            lenEnd = len(self.LineSpec[endSection].get_ydata())
            indexStart = int(
                (self.FFT_Min_X - (startSection * 25 + 70)) * lenStart / 25.0)
            indexEnd = int(
                (self.FFT_Max_X - (endSection * 25 + 70)) * lenEnd / 25.0)
            MaxList = []
            MaxList.append(
                max(
                    list(self.LineSpec[startSection].get_ydata())
                    [indexStart:lenStart]))
            for i in range(startSection + 1, endSection, 1):
                MaxList.append(max(list(self.LineSpec[i].get_ydata())))
            if (indexEnd != 0):
                MaxList.append(
                    max(
                        list(self.LineSpec[endSection].get_ydata())
                        [0:indexEnd]))

            Max_Y = max(MaxList)
            Max_Y_Index = MaxList.index(Max_Y) + startSection
            y = self.LineSpec[Max_Y_Index].get_ydata()
            Max_X_Index = list(y).index(Max_Y)
            Max_X = 70 + Max_Y_Index * 25 + Max_X_Index * 25.0 / len(y)
            self.DrawMarker(Max_X, Max_Y)

    def OnRemove(self):

        if (len(self.axes.texts)):
            self.axes.lines.pop()
            self.axes.texts.pop()
            self.axes.texts.pop()
            self.drs.pop()
            #self.FigureCanvas.draw()

    def OnAllRemove(self):

        while (len(self.axes.texts)):
            self.axes.lines.pop()
            self.axes.texts.pop()
            self.axes.texts.pop()
            self.drs.pop()
        #self.FigureCanvas.draw()

    def setSpLabel(self, begin_X=70, end_X=5995, begin_Y=-120, end_Y=60):
        self.ylabel('dBm')
        self.xlabel('MHz')
        self.ylim(begin_Y, end_Y)
        self.xlim(begin_X, end_X)
        yticks = linspace(begin_Y, end_Y, 11)  ##11个数总共###
        yticklabels = [str(int(i)) for i in yticks]
        xticks = linspace(begin_X, end_X, 11)

        xticklabels = [str('%0.1f' % (i)) for i in xticks]
        self.axes.set_xticks(xticks)
        self.axes.set_xticklabels(xticklabels, rotation=0)
        self.axes.set_yticks(yticks)
        self.axes.set_yticklabels(yticklabels, rotation=0)
        self.axes.grid(True)
        #self.FigureCanvas.draw()

    def PowerSpectrum(self, funcPara, y):

        if (funcPara == 0x51 or funcPara == 0x56):

            self.lineSpec.set_ydata(array(y))
            '''
            for i in range(len(self.drs)):
                self.drs[i].yData=self.LineSpec 
                self.DrawAfterRelease()
                '''
        elif (funcPara == 0x52 or funcPara == 0x57):

            self.lineSpecBack.set_ydata(array(y))
        self.FigureCanvas.draw()

    def DrawAfterRelease(self):

        for i in range(len(self.drs)):
            xData = self.drs[i].rect.get_xdata()

            index = (int(xData) - 70) / 25
            Section = index * 25 + 70
            y = self.LineSpec[index].get_ydata()

            index_Y = (xData - Section) * len(y) / 25.0
            Marker_Y = list(y)[int(index_Y)]
            self.drs[i].rect.set_ydata(Marker_Y)
            self.drs[i].textMarker.set_position((xData, Marker_Y + 2))
            self.drs[i].textM.set_text(self.drs[i].M_index+'%.2f'%(xData)+ \
                'MHz  '+'%.2f'%(Marker_Y)+'dBm')

    def xlim(self, x_min, x_max):
        self.axes.set_xlim(x_min, x_max)

    def ylim(self, y_min, y_max):
        self.axes.set_ylim(y_min, y_max)

    def xlabel(self, XabelString="X"):
        self.axes.set_xlabel(XabelString)

    def ylabel(self, YabelString="Y"):
        self.axes.set_ylabel(YabelString)
Пример #11
0
class CanvasPanel(wx.Panel):
    """ plot frame based on the Generic Frame class"""
    def __init__(self, parent, figure, *args, **kargs):
        wx.Panel.__init__(self, parent)
        # initialize the external data source

        figure.set_dpi(150)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)

        self.figurecavas = FigureCanvas(self, -1, figure)
        sizer.Add(self.figurecavas, 0,
                  wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)

        self.figurecavas.mpl_connect('pick_event', self.OnPick)
        self.figurecavas.mpl_connect('button_press_event', self.OnButtonPress)
        self.figurecavas.mpl_connect('motion_notify_event',
                                     self.UpdateStatusBar)
        self.figurecavas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)
        self.figurecavas.mpl_connect('key_press_event', self.OnKeyPressed)

        # add interactive curve pick function

        # setup the tool bar
        self.toolbar = MyNavigationToolbar(self.figurecavas, True)
        self.toolbar.Realize()

        sizer.Add(self.toolbar, 0,
                  wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)

        self.text_x = wx.TextCtrl(self, wx.NewId(), "Value X:", size=(100, -1))
        self.text_y = wx.TextCtrl(self, wx.NewId(), "Value Y:", size=(100, -1))

        sizer.Add(
            self.text_x, 0,
            wx.TOP | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)
        sizer.Add(
            self.text_y, 0,
            wx.TOP | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)

        self.sizerinuse = sizer
        # bind resize event
        wx.EVT_SIZE(self, self.OnSize)

        # show the frame

        self.Show()

    def OnPick(self, event):
        print 'picked'

    def OnButtonPress(self, event):
        ''' button press event'''
        pass

    def OnKeyPressed(self, event):
        #print 'keypressed'
        pass

    def ResizeCanvas(self):

        pass
        '''
        size = self.Parent.GetClientSize()
        
        self.figurecavas.resize(size[0],size[1])
        
        self.figurecavas.draw()
        
        print self.figurecavas.Size
        print self.Size
        print self.Parent.Size
        '''

    def OnSize(self, event):

        event.Skip()
        #wx.CallAfter(self.ResizeCanvas)

    def FigureUpdate(self, newfigure=None):

        if newfigure != None:
            newfigure.set_dpi(150)
            #self.figurecavas.figure.clear()
            self.figurecavas.figure = newfigure  #FigureCanvas(self, -1, newfigure)

        self.figurecavas.draw()

        self.figurecavas.Update()

        self.Update()
        self.Refresh()

    def ChangeCursor(self, event):
        """ change the cursor within the canvas"""
        self.figurecavas.SetCursor(wx.StockCursor(wx.CURSOR_BULLSEYE))

    def UpdateStatusBar(self, event):
        """ update the statue bar for point position"""
        if event.inaxes:
            x, y = event.xdata, event.ydata
            self.text_x.SetValue(str(x))
            self.text_y.SetValue(str(y))
            #self.statusBar.SetStatusText(( "x= " + str(x) +
            #                               "  y=" +str(y) ),
            #                               0)
    def set_limits(self, limits):
        """
        Set limits for the x and y axes,
        Operation based on current ax
        """
        ax1 = self.figurecavas.figure.axes[0]
        if limits != None:
            if limits[0] != None and limits[0] != 'None':
                ax1.set_xlim(xmin=float(limits[0]))
            if limits[1] != None and limits[1] != 'None':
                ax1.set_xlim(xmax=float(limits[1]))
            if limits[2] != None and limits[2] != 'None':
                ax1.set_ylim(ymin=float(limits[2]))
            if limits[3] != None and limits[3] != 'None':
                ax1.set_ylim(ymax=float(limits[3]))
        return ax1

    def set_labels(self, label):
        """
        Set labels for the x and y axes
        """
        ax = self.figurecavas.figure.axes[0]
        ax.set_xlabel(label[0])
        ax.set_ylabel(label[1])
Пример #12
0
class PVWindow(wx.Frame):

    #########################Init Funcions#############################

    def __init__(self,parent=None,dpi=100,geoid=Geodesic.WGS84,fontsize=8):
        """Constructor"""
        #call init of super class
        default_style = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.NO_FULL_REPAINT_ON_RESIZE | wx.WS_EX_CONTEXTHELP | wx.FRAME_EX_CONTEXTHELP
        wx.Frame.__init__(self, parent, title="Phase Viewer %s"%parent.__version__,style=default_style, size=(400*2,300*2))
        self.Bind(wx.EVT_CLOSE, self.on_close_main)

        self.parent=parent
        self.dpi = dpi
        self.geoid = geoid
        self.fontsize = fontsize
        self.mouse_left_down = False

        self.panel = wx.Panel(self,-1,size=(400*2,300*2))

        #Populate UI and Menu
        self.init_UI()
        self.create_menu()
        self.configure()

        self.update()

    def init_UI(self):
        spacing = 10

        #-----------------------------------------Make SideBar-----------------------------------------------------#

        side_bar_sizer = wx.BoxSizer(wx.VERTICAL)

        #####-------------------------------------Make FilterBox---------------------------------------------------#

        filter_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "Filter Options"), wx.VERTICAL)
        highlow_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "Highcut/Lowcut"), wx.HORIZONTAL)
        order_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "Order"), wx.HORIZONTAL)
        text_input_sizer = wx.BoxSizer(wx.HORIZONTAL)

        null_filter = lambda x,y,z,fs,order: x
        self.filters = {"None":null_filter,"Butterworth Bandpass":sk.butter_bandpass_filter,"Butterworth Lowpass":sk.butter_lowpass_filter}
        list_filters = ["None","Butterworth Bandpass","Butterworth Lowpass"]
        self.filter_type_box = wx.ComboBox(self.panel, id=wx.ID_ANY,size=(200, 25), value=list_filters[0], choices=list_filters, style=wx.CB_DROPDOWN|wx.TE_READONLY)
        self.Bind(wx.EVT_COMBOBOX, self.on_select_filter,self.filter_type_box)

        self.lowcut_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(50,25))
        self.highcut_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(50,25))
        self.order_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(50,25))

        order_sizer.Add(self.order_box, 1, wx.ALIGN_RIGHT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing)
        highlow_sizer.AddMany([(self.lowcut_box, 1, wx.ALIGN_LEFT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing),
                               (self.highcut_box, 1, wx.ALIGN_RIGHT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing)])
        text_input_sizer.AddMany([(highlow_sizer, 2, wx.ALIGN_LEFT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing),
                                  (order_sizer, 1, wx.ALIGN_RIGHT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing)])
        filter_sizer.AddMany([(self.filter_type_box, 1, wx.ALIGN_CENTER|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing),
                              (text_input_sizer, 1, wx.ALIGN_CENTER|wx.ALIGN_BOTTOM|wx.EXPAND|wx.ALL, spacing)])

        #####-------------------------------------Make BoundsBox---------------------------------------------------#

        bounds_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "Bounds"), wx.HORIZONTAL)
        bounds_diff_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.low_bound_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(50,25))
        self.high_bound_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(50,25))
        self.aero_diff_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(50,25))

        bounds_sizer.AddMany([(self.low_bound_box, 1, wx.ALIGN_LEFT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing),
                              (self.high_bound_box, 1, wx.ALIGN_RIGHT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing)])
        bounds_diff_sizer.AddMany([(bounds_sizer, 2, wx.ALIGN_LEFT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing),
                                   (self.aero_diff_box, 1, wx.ALIGN_RIGHT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing)])

        #####-------------------------------------Make UpdateBtn---------------------------------------------------#

        self.update_button = wx.Button(self.panel, id=wx.ID_ANY, label='Update',size=(200,50))
        self.Bind(wx.EVT_BUTTON, self.on_update_button, self.update_button)

        #-------------------------------------Make Figures---------------------------------------------------------#

        self.power_fig = Figure((3, 3), dpi=self.dpi)
        self.power_canvas = FigCanvas(self.panel, -1, self.power_fig)
        self.power_toolbar = NavigationToolbar(self.power_canvas)
#        psk.remove_axis_lines_and_ticks(self.ax)
        self.power_toolbar.Hide()
        self.power_plot_setting = "Zoom"
        self.power_toolbar.zoom()
        self.power_canvas.Bind(wx.EVT_MIDDLE_DOWN,self.on_middle_click_power_plot)

        self.fig = Figure((4, 3), dpi=self.dpi)
        self.canvas = FigCanvas(self.panel, -1, self.fig)
        self.toolbar = NavigationToolbar(self.canvas)
#        psk.remove_axis_lines_and_ticks(self.ax)
        self.toolbar.Hide()
        self.plot_setting = "Zoom"
        self.toolbar.zoom()
        self.canvas.Bind(wx.EVT_MIDDLE_DOWN,self.on_middle_click_plot)
        self.canvas.Bind(wx.EVT_MOTION,self.on_move_mouse_plot)
        self.canvas.Bind(wx.EVT_LEFT_DOWN, self.on_left_click_down)
        self.canvas.Bind(wx.EVT_LEFT_UP, self.on_left_click_up)
#        self.canvas.Bind(wx.EVT_RIGHT_DCLICK, self.on_select_dright_click)

        #----------------------------------Build UI and Fit--------------------------------------------------------#

        side_bar_sizer.AddMany([(filter_sizer, 1, wx.ALIGN_LEFT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing),
                                (bounds_diff_sizer, 1, wx.ALIGN_LEFT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing),
                                (self.update_button, 1, wx.ALIGN_LEFT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing),
                                (self.power_canvas, 1, wx.ALIGN_LEFT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing)])

        outer_sizer = wx.BoxSizer(wx.HORIZONTAL)
        outer_sizer.AddMany([#(grd_sizer,1,wx.ALIGN_CENTER|wx.ALIGN_TOP|wx.EXPAND|wx.LEFT|wx.RIGHT,spacing),
                             (side_bar_sizer,1,wx.ALIGN_CENTER|wx.ALIGN_TOP|wx.EXPAND),
                             (self.canvas,10,wx.ALIGN_CENTER|wx.ALIGN_TOP|wx.EXPAND)])

        self.panel.SetSizerAndFit(outer_sizer)

    def create_menu(self):
        """
        Generates Menu
        """

        self.menubar = wx.MenuBar()

        #-----------------
        # File Menu
        #-----------------

        menu_file = wx.Menu()

        menu_file.AppendSeparator()
        m_exit = menu_file.Append(-1, "&Exit\tCtrl-Q", "Exit")
        self.Bind(wx.EVT_MENU, self.on_close_main, m_exit)

        #-----------------

        self.menubar.Append(menu_file, "&File")
        self.SetMenuBar(self.menubar)

    def configure(self):
        self.lowcut_box.SetValue("%.2f"%0.01)
        self.highcut_box.SetValue("%.2f"%0.1)
        self.order_box.SetValue("%d"%3)
        self.low_bound_box.SetValue("%.2f"%(-50.0))
        self.high_bound_box.SetValue("%.2f"%50.0)
        self.aero_diff_box.SetValue("%.1f"%0.0)


    #########################Update UI Funcions#############################

    def update(self):

        self.fig.clear() #clear
        self.power_fig.clear()

        self.draw_figures() #draw

        self.canvas.draw() #rerender
        self.power_canvas.draw()

    def on_close_main(self,event):
        self.parent.pv_open=False
        self.Destroy()

    ###################Button and Dropdown Functions#########################

#    def on_change_grd_btn(self,event):
#        dlg = wx.FileDialog(
#            self, message="Choose Grid File",
#            defaultDir=self.parent.WD,
#            defaultFile="",
#            wildcard="Grid Files (*.grd,*.nc,*.ncf)|*.grd;*.nc;*.ncf|All Files (*.*)|*.*",
#            style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST
#            )
#        if dlg.ShowModal() == wx.ID_OK:
#            self.grd_file = dlg.GetPath()
#            self.grd_path.SetValue(self.grd_file)
#            self.update()
#            dlg.Destroy()
#        else: dlg.Destroy()

    def on_select_filter(self,event):
        self.update()

    def on_update_button(self,event):
        self.update()

    ###########################Figure Funcions###############################

    def on_middle_click_plot(self,event):
        if event.LeftIsDown() or event.ButtonDClick(): event.Skip(); return
        elif self.plot_setting == "Zoom":
            self.plot_setting = "Pan"
            self.toolbar.pan('off')
        elif self.plot_setting == "Pan":
            self.plot_setting = "Pick"
            self.toolbar.pan('off')
            myCursor= wx.StockCursor(wx.CURSOR_IBEAM)
            self.canvas.SetCursor(myCursor)
        elif self.plot_setting == "Pick":
            self.plot_setting = "Zoom"
            self.toolbar.zoom()
        event.Skip()

    def on_middle_click_power_plot(self,event):
        if event.LeftIsDown() or event.ButtonDClick(): event.Skip(); return
        elif self.power_plot_setting == "Zoom":
            self.power_plot_setting = "Pan"
            self.power_toolbar.pan('off')
        elif self.power_plot_setting == "Pan":
            self.power_plot_setting = "Zoom"
            self.power_toolbar.zoom()
        event.Skip()

    def on_move_mouse_plot(self,event):
        pos=event.GetPosition()
        width, height = self.canvas.get_width_height()
        pos = [pos[0],height-pos[1]]
        pos = self.ax0.transData.inverted().transform(pos)

#        self.annotate_point(pos,xy=(1-0.02,1-0.02),xycoords="axes fraction",bbox=dict(boxstyle="round", fc="w",alpha=.5),fontsize=self.fontsize,va='top',ha='right')

        self.plot_tracer_point(pos[0],linestyle='--',color='red',alpha=.5)

        self.canvas.draw()

        event.Skip()

    def on_left_click_down(self,event):
        if self.plot_setting!="Pick": event.Skip(); return
        pos=event.GetPosition()
        width, height = self.canvas.get_width_height()
        pos = [pos[0],height-pos[1]]
        pos = self.ax0.transData.inverted().transform(pos)
        self.tmp_new_bounds = [pos[0],None]
        self.mouse_left_down = True
        event.Skip()

    def on_left_click_up(self,event):
        if self.plot_setting!="Pick": event.Skip(); return
        pos=event.GetPosition()
        width, height = self.canvas.get_width_height()
        pos = [pos[0],height-pos[1]]
        pos = self.ax0.transData.inverted().transform(pos)
        self.tmp_new_bounds[1] = pos[0]
        self.mouse_left_down = False

        if abs(self.tmp_new_bounds[1]-self.tmp_new_bounds[0])>0:
            self.low_bound_box.SetValue("%.1f"%float(min(self.tmp_new_bounds)))
            self.high_bound_box.SetValue("%.1f"%float(max(self.tmp_new_bounds)))

        self.update()

        event.Skip()

    ##########################Additional Plotting and Backend Functions################

    def on_parent_select_track(self):
        self.update()

    def plot_tracer_point(self,x,**kwargs):
        try:
            for tracer in self.tracers:
                tracer.remove()
        except (AttributeError,ValueError) as e: pass
        self.tracers = []
        self.tracers.append(self.ax0.axvline(x,**kwargs))
        self.tracers.append(self.ax1.axvline(x,**kwargs))
        self.tracers.append(self.ax2.axvline(x,**kwargs))
        if self.mouse_left_down:
            myCursor= wx.StockCursor(wx.CURSOR_IBEAM)
            self.canvas.SetCursor(myCursor)
            self.tracers.append(self.ax0.axvspan(min([self.tmp_new_bounds[0],x]),max([self.tmp_new_bounds[0],x]),color="yellow",alpha=.4))
            self.tracers.append(self.ax1.axvspan(min([self.tmp_new_bounds[0],x]),max([self.tmp_new_bounds[0],x]),color="yellow",alpha=.4))
            self.tracers.append(self.ax2.axvspan(min([self.tmp_new_bounds[0],x]),max([self.tmp_new_bounds[0],x]),color="yellow",alpha=.4))

    def draw_figures(self):

        ####################################################Get Values
        dsk_row = self.parent.dsk_row
        track = self.parent.track
        ddis = float(self.parent.samp_dis_box.GetValue())
        if ddis==0: self.parent.user_warning("Synthetic is required for comparision of phase, start by initalilzing a synthetic"); return
        synth_dis = self.parent.dis_synth
        synth_mag = self.parent.synth

        filter_type = self.filter_type_box.GetValue()
        lowcut = float(self.lowcut_box.GetValue())
        highcut = float(self.highcut_box.GetValue())
        order = int(self.order_box.GetValue())

        left_bound = float(self.low_bound_box.GetValue())
        right_bound = float(self.high_bound_box.GetValue())
        aero_diff = float(self.aero_diff_box.GetValue())

        left_idx = np.argmin(np.abs(synth_dis-left_bound))
        right_idx = np.argmin(np.abs(synth_dis-right_bound))
        left_idx,right_idx = min([left_idx,right_idx]),max([left_idx,right_idx])

        bin_range,bin_num = (-180,180),120

        ###################################################Filter Data

        data_path = os.path.join(dsk_row["data_dir"],dsk_row["comp_name"])
        data_df = utl.open_mag_file(data_path)
        projected_distances = utl.calc_projected_distance(dsk_row['inter_lon'],dsk_row['inter_lat'],data_df['lon'].tolist(),data_df['lat'].tolist(),(180+dsk_row['strike'])%360)
        shifted_mag = sk.phase_shift_data(data_df["mag"],dsk_row["phase_shift"])
        if np.any(np.diff(projected_distances["dist"])<0): itshifted_mag = np.interp(-synth_dis,-projected_distances["dist"],shifted_mag)
        else: itshifted_mag = np.interp(synth_dis,projected_distances["dist"],shifted_mag)
        fitshifted_mag = self.filters[filter_type](itshifted_mag,lowcut,highcut,fs=1/ddis,order=order)

        ###################################################Actual Plotting

        outer = gridspec.GridSpec(4, 1)

        ###################################################Axis 0: Magnetic profiles
        self.ax0 = self.fig.add_subplot(outer[0])

        if self.parent.show_other_comp: #Handle Other Aeromag Component

            if dsk_row["track_type"]=="aero":
                if "Ed.lp" in track:
                    other_track = track.replace("Ed.lp","Vd.lp")
                    total_track = track.replace("Ed.lp","Td.lp")
                    other_phase = dsk_row["phase_shift"]-90
                elif "Hd.lp" in track:
                    other_track = track.replace("Hd.lp","Vd.lp")
                    total_track = track.replace("Hd.lp","Td.lp")
                    other_phase = dsk_row["phase_shift"]-90
                elif "Vd.lp" in track:
                    other_track = track.replace("Vd.lp","Ed.lp")
                    total_track = track.replace("Vd.lp","Td.lp")
                    if other_track not in self.parent.deskew_df["comp_name"].tolist(): other_track = track.replace("Vd.lp","Hd.lp")
                    other_phase = dsk_row["phase_shift"]+90
                else: self.parent.user_warning("Improperly named component files should have either Ed.lp, Hd.lp, or Vd.lp got: %s"%track); return
                oth_row = self.parent.deskew_df[self.parent.deskew_df["comp_name"]==other_track].iloc[0]

                oth_data_path = os.path.join(oth_row["data_dir"],oth_row["comp_name"])
                tot_data_path = os.path.join(oth_row["data_dir"],total_track) #Should be in same place

                oth_data_df = utl.open_mag_file(oth_data_path)
                oth_shifted_mag = sk.phase_shift_data(oth_data_df["mag"],other_phase)
                if np.any(np.diff(projected_distances["dist"])<0): oth_itshifted_mag = np.interp(-synth_dis,-projected_distances["dist"],oth_shifted_mag)
                else: oth_itshifted_mag = np.interp(synth_dis,projected_distances["dist"],oth_data_df)
                oth_fitshifted_mag = self.filters[filter_type](oth_itshifted_mag,lowcut,highcut,fs=1/ddis,order=order)
                if filter_type=="None": psk.plot_skewness_data(oth_row,other_phase,self.ax0,xlims=[None,None],color='darkgreen',zorder=2,picker=True,alpha=.7,return_objects=True,flip=True)
                else: self.ax0.plot(synth_dis,oth_fitshifted_mag,color="#299C29",zorder=3,alpha=.6)

                tot_data_df = utl.open_mag_file(tot_data_path)
                if np.any(np.diff(projected_distances["dist"])<0): tot_imag = np.interp(-synth_dis,-projected_distances["dist"],tot_data_df["mag"])
                else: tot_imag = np.interp(synth_dis,projected_distances["dist"],tot_data_df["mag"])
                tot_fimag = self.filters[filter_type](tot_imag,lowcut,highcut,fs=1/ddis,order=order)

        if filter_type=="None": psk.plot_skewness_data(dsk_row,dsk_row["phase_shift"],self.ax0,xlims=[None,None],zorder=3,picker=True,return_objects=True,flip=True)
        else: self.ax0.plot(synth_dis,fitshifted_mag,color="#7F7D7D",zorder=3,alpha=.6)
        self.ax0.plot(self.parent.dis_synth,self.parent.synth,'r-',alpha=.4,zorder=1)
        self.ax0.set_ylabel("Magnetic Profiles")
#        self.ax0.get_xaxis().set_ticklabels([])

        ###################################################Axis 1/2: Phase Angles and Differences

        self.ax1 = self.fig.add_subplot(outer[1], sharex=self.ax0)
        self.ax2 = self.fig.add_subplot(outer[2], sharex=self.ax0)

        ###################################################Calculate: Phase Differences
        trimmed_dis = synth_dis[left_idx:right_idx]
        trimmed_synth = synth_mag[left_idx:right_idx]
        trimmed_fitshifted_mag = fitshifted_mag[left_idx:right_idx]

        al_data = np.angle(hilbert(fitshifted_mag),deg=False)[left_idx:right_idx]
        al_synth = np.angle(hilbert(np.real(synth_mag)),deg=False)[left_idx:right_idx]

        data_synth_diff = phase_diff_func(al_synth,al_data)

        if self.parent.show_other_comp and dsk_row["track_type"]=="aero":
            trimmed_oth_fitshifted_mag = oth_fitshifted_mag[left_idx:right_idx]
            al_oth = np.angle(hilbert(oth_fitshifted_mag),deg=False)[left_idx:right_idx]

            oth_synth_diff = phase_diff_func(al_synth,al_oth)
            oth_data_diff = phase_diff_func(al_oth,al_data)

            if abs(aero_diff) > 0:
                idx = ma.array(np.abs(oth_data_diff)<aero_diff)

                self.ax1.plot((trimmed_dis[~idx]),(np.rad2deg(al_oth[~idx])),color="darkgreen",linestyle=":")

                self.ax2.plot((trimmed_dis[~idx]),(oth_synth_diff[~idx]),color="tab:pink",alpha=.8,linestyle=":")
                self.ax2.plot((trimmed_dis[~idx]),(oth_data_diff[~idx]),color="tab:grey",alpha=.8,linestyle=":")

                self.ax1.plot((trimmed_dis[~idx]),(np.rad2deg(al_data[~idx])),color="k",linestyle=":")
                self.ax1.plot((trimmed_dis[~idx]),(np.rad2deg(al_synth[~idx])),color="r",linestyle=":")

                self.ax2.plot((trimmed_dis[~idx]),(data_synth_diff[~idx]),color="tab:red",alpha=.8,linestyle=":")

#                import pdb; pdb.set_trace()
#                not_trimmed_dis = (trimmed_dis[~idx])
#                not_trimmed_dis[np.diff(~idx,prepend=[0])] = ma.masked
#                not_al_data = (al_data[~idx])
#                not_al_data[np.diff(~idx)] = ma.masked
#                not_al_synth = (al_synth[~idx])
#                not_al_synth[np.diff(~idx)] = ma.masked
#                not_al_oth = (al_oth[~idx])
#                not_al_oth[np.diff(~idx)] = ma.masked
#                not_data_synth_diff = (data_synth_diff[~idx])
#                not_data_synth_diff[np.diff(~idx)] = ma.masked
#                not_oth_synth_diff = (oth_synth_diff[~idx])
#                not_oth_synth_diff[np.diff(~idx)] = ma.masked
#                not_oth_data_diff = (oth_data_diff[~idx])
#                not_oth_data_diff[np.diff(~idx)] = ma.masked
                trimmed_dis = (trimmed_dis[idx])
                al_data = (al_data[idx])
                al_synth = (al_synth[idx])
                al_oth = (al_oth[idx])
                data_synth_diff = (data_synth_diff[idx])
                oth_synth_diff = (oth_synth_diff[idx])
                oth_data_diff = (oth_data_diff[idx])

            self.ax1.plot(trimmed_dis,np.rad2deg(al_oth),color="darkgreen")

            self.ax2.plot(trimmed_dis,oth_synth_diff,color="tab:pink",alpha=.8)
            self.ax2.plot(trimmed_dis,oth_data_diff,color="tab:grey",alpha=.8)

        self.ax1.plot(trimmed_dis,np.rad2deg(al_data),color="k")
        self.ax1.plot(trimmed_dis,np.rad2deg(al_synth),color="r")

        self.ax2.plot(trimmed_dis,data_synth_diff,color="tab:red",alpha=.8)
#        self.ax2.get_xaxis.set_ticklabels
        self.ax0.set_xlim(*self.parent.ax.get_xlim())
        self.ax0.set_ylim(*self.parent.ax.get_ylim())

        self.ax1.set_ylabel("Phase Angles")
        self.ax2.set_ylabel("Phase Differences")


        ###################################################Axis 2.1: Power Spectrum
#        inner = gridspec.GridSpecFromSubplotSpec(1, 2, subplot_spec=outer[2])#, hspace=0.)
#        self.ax2 = self.fig.add_subplot(inner[0])


        ###################################################Axis 2.2: Phase Statistics
        self.ax3 = self.fig.add_subplot(outer[3])

        if self.parent.show_other_comp and dsk_row["track_type"]=="aero":
            self.ax3.hist(oth_synth_diff,range=bin_range,bins=bin_num,color="tab:pink",alpha=.5,zorder=2)
            self.ax3.hist(oth_data_diff,range=bin_range,bins=bin_num,color="tab:grey",alpha=.5,zorder=1)

        self.ax3.hist(data_synth_diff,range=bin_range,bins=bin_num,color="tab:red",alpha=.5,zorder=3)
        self.ax3.axvline(np.median(data_synth_diff),color="k",alpha=.5,zorder=5,linestyle=":")
        self.ax3.axvline(np.mean(data_synth_diff),color="k",alpha=.5,zorder=5)
        self.ax3.axvspan(np.mean(data_synth_diff)-np.std(data_synth_diff),np.mean(data_synth_diff)+np.std(data_synth_diff),color="tab:grey",alpha=.3,zorder=0)

        self.ax3.annotate(r"$\theta_{mean}$ = $%.1f^\circ \pm %.1f^\circ$"%(np.mean(data_synth_diff),np.std(data_synth_diff)) + "\n" + r"$\theta_{median}$ = %.1f$^\circ$"%np.median(data_synth_diff),xy=(0.02,1-0.02),xycoords="axes fraction",bbox=dict(boxstyle="round", fc="w",alpha=.5),fontsize=self.fontsize,va='top',ha='left')

        self.ax3.set_ylabel(r"$\Delta \theta$ Count")

        self.fig.suptitle("%s\n%s\n"%(dsk_row["sz_name"],track))

        ###################################################Power Figure

        N = (right_idx-left_idx) #Length of signal in distance domain
        NW = 3 #following Parker and O'brien '97 and HJ-Gordon '03 we use a time-bandwith product of 6 (Nw is half)
        Ns = 5 #Number of points to use in running average smoothing

        #Handle Distance Domain
#        import pdb; pdb.set_trace()
        Sk_complex, weights, eigenvalues=pmtm(itshifted_mag[left_idx:right_idx], NW=NW, NFFT=N, show=False)
        Sk = np.abs(Sk_complex)**2
        smoothed_tshifted_freq = (np.mean(Sk * np.transpose(weights), axis=0) * ddis)[N//2:][::-1]
#        smoothed_tshifted_freq = np.convolve(smoothed_tshifted_freq, np.ones((Ns,))/Ns, mode='same') #10 point running average smoothing
        tdata_freqs = np.linspace(0.0, 1.0/(2.0*ddis), N-N//2) #0 to Nyquest

        self.power_ax = self.power_fig.add_subplot(111)

        if self.parent.show_other_comp and dsk_row["track_type"]=="aero":
            Sk_complex, weights, eigenvalues=pmtm(oth_itshifted_mag[left_idx:right_idx], NW=NW, NFFT=N, show=False)
            Sk = np.abs(Sk_complex)**2
            oth_smoothed_tshifted_freq = (np.mean(Sk * np.transpose(weights), axis=0) * ddis)[N//2:][::-1]
#            oth_smoothed_tshifted_freq = np.convolve(oth_smoothed_tshifted_freq, np.ones((Ns,))/Ns, mode='same') #10 point running average smoothing
            self.power_ax.semilogy(tdata_freqs, oth_smoothed_tshifted_freq, color="darkgreen")
#            self.power_ax.semilogy(tdata_freqs, oth_smoothed_tshifted_freq+smoothed_tshifted_freq, color="grey")


            Sk_complex, weights, eigenvalues=pmtm(tot_imag[left_idx:right_idx], NW=NW, NFFT=N, show=False)
            Sk = np.abs(Sk_complex)**2
            tot_smoothed_tshifted_freq = (np.mean(Sk * np.transpose(weights), axis=0) * ddis)[N//2:][::-1]
#            tot_smoothed_tshifted_freq = np.convolve(tot_smoothed_tshifted_freq, np.ones((Ns,))/Ns, mode='same') #10 point running average smoothing
            self.power_ax.semilogy(tdata_freqs, tot_smoothed_tshifted_freq, color="tab:orange")

        #Old Numpy Method
#        synth_freqs = np.fft.fftfreq(len(synth_dis[left_idx:right_idx]),ddis)
#        tdata_freqs = np.fft.fftfreq(len(shifted_mag[left_idx:right_idx]),ddis)
#        tshifted_freq = np.fft.fft(shifted_mag[left_idx:right_idx])
#        fitshifted_freq = np.fft.fft(fitshifted_mag[left_idx:right_idx])
#        tsynth_freq = np.fft.fft(synth_mag[left_idx:right_idx])

        self.power_ax.semilogy(tdata_freqs, smoothed_tshifted_freq, color="k",zorder=100)

#        self.power_ax.semilogy(tdata_freqs, np.abs(tshifted_freq), color="k")
#        self.power_ax.plot(synth_freqs, np.abs(fitshifted_freq), color="#7F7D7D")
#        self.power_ax.plot(synth_freqs, np.abs(tsynth_freq), color="r")

        self.power_ax.set_xlim(0.0,0.4)
        self.power_ax.set_ylim(1e-1,1e6)
Пример #13
0
class RightGraph(wx.Panel):
    def __init__(self, parent, statusbar):
        wx.Panel.__init__(self, parent, wx.ID_ANY)
        self.statusbar = statusbar

        self.fig = Figure((7.0, 6.0))
        self.canvas = FigCanvas(self, -1, self.fig)
        self.fig.patch.set_facecolor(colorBackgroundGraph)

        self.ax = self.fig.add_subplot(111)
        self.ax.set_ylabel("Intensity (a.u.)", fontdict=font)
        self.ax.set_xlabel(r'2$\theta$ (deg.)', fontdict=font)
        self.toolbar = NavigationToolbar(self.canvas)
        self.toolbar.Hide()
        self.canvas.toolbar.zoom()
        self.toolbar.Disable()

        self.ly = self.ax.axvline(color='r', lw=0.0)  # the vert line
        self.lx = self.ax.axhline(color='r', lw=0.0)  # the horiz line

        if not hasattr(self, "UnzoomID"):
            self.UnzoomID = wx.NewId()
            self.CheckedGridId = wx.NewId()
            self.CursorId = wx.NewId()
            self.Bind(wx.EVT_MENU, self.OnUnzoom, id=self.UnzoomID)
            self.Bind(wx.EVT_MENU, self.CheckedGrid, id=self.CheckedGridId)
            self.Bind(wx.EVT_MENU, self.CursorMove, id=self.CursorId)
        """build the menu"""
        self.menu = wx.Menu()
        self.item_unzoom = self.menu.Append(self.UnzoomID, "Unzoom")
        self.item_grid = self.menu.Append(self.CheckedGridId,
                                          "Show/Hide grid",
                                          kind=wx.ITEM_CHECK)
        self.item_cursor = self.menu.Append(self.CursorId,
                                            "Show/Hide cursor",
                                            kind=wx.ITEM_CHECK)
        self.item_unzoom.Enable(False)
        self.item_grid.Enable(False)
        self.item_cursor.Enable(False)

        self.connect = self.canvas.mpl_connect
        self.disconnect = self.canvas.mpl_disconnect

        self.update_zoom = self.connect('motion_notify_event',
                                        self.MouseOnGraph)
        self.update_coord = self.connect('motion_notify_event',
                                         self.on_update_coordinate)
        self.disconnect(self.update_zoom)
        self.disconnect(self.update_coord)

        self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)

        self.c_data = ""
        self.c_fit = ""
        self.c_live = ""
        self.l_data = ""
        self.l_fit = ""
        self.l_live = ""

        mastersizer = wx.BoxSizer(wx.VERTICAL)
        mastersizer.Add(self.canvas, 1, wx.EXPAND)
        mastersizer.Add(self.toolbar, 0, wx.EXPAND)

        pub.subscribe(self.OnDrawGraph, pubsub_Draw_XRD)
        pub.subscribe(self.OnDrawGraphLive, pubsub_Draw_Fit_Live_XRD)
        pub.subscribe(self.onFit, pubsub_OnFit_Graph)
        pub.subscribe(self.on_color, pubsub_Graph_change_color_style)

        self.on_color()

        self.SetSizer(mastersizer)
        self.Layout()
        self.Fit()

    def on_color(self):
        a = P4Rm()
        self.c_data = a.DefaultDict['c_data']
        self.c_fit = a.DefaultDict['c_fit']
        self.c_live = a.DefaultDict['c_fit_live']
        self.l_data = a.DefaultDict['l_data']
        self.l_fit = a.DefaultDict['l_fit']
        self.l_live = a.DefaultDict['l_fit_live']
        self.c_bkg = a.DefaultDict['c_graph_background']

    def OnDrawGraph(self, b=None):
        a = P4Rm()
        self.ax.clear()
        if b == 1:
            self.ax.semilogy(2 * a.ParamDict['th'] * 180 / np.pi,
                             a.ParamDict['Iobs'], 'o-k')
        elif b == 2:
            self.ax.set_xlim([0, 1])
            self.ax.set_ylim([0, 1])
            self.ax.clear()
        else:
            a = P4Rm()
            xx = 2 * a.ParamDict['th'] * 180 / np.pi
            Iobs_len = len(a.ParamDict['Iobs'])
            I_i_len = len(a.ParamDict['I_i'])
            if Iobs_len == I_i_len:
                I_val = a.ParamDict['I_i']
            else:
                I_val = a.ParamDictbackup['I_i']
            self.ax.semilogy(xx,
                             a.ParamDict['Iobs'],
                             color=self.c_data,
                             ls=self.l_data,
                             marker='o')
            self.ax.semilogy(xx, I_val, color=self.c_fit, ls=self.l_fit)
            middle = int(len(a.ParamDict['th']) / 2)
            self.ly = self.ax.axvline(x=xx[middle], color='r', lw=0.0)
            self.lx = self.ax.axhline(color='r', lw=0.0)  # the horiz line
        self.ax.set_ylabel("Intensity (a.u.)", fontdict=font)
        self.ax.set_xlabel(r'2$\theta$ (deg.)', fontdict=font)
        if LooseVersion(matplotlib_vers) < LooseVersion("2.0.0"):
            self.ax.set_axis_bgcolor(self.c_bkg)
        else:
            self.ax.set_facecolor(self.c_bkg)
        self.CheckedGrid()
        self.CursorMove()

    def OnDrawGraphLive(self, val=None):
        a = P4Rm()
        if val != []:
            P4Rm.ParamDict['I_fit'] = val
        self.ax.clear()
        self.ax.semilogy(a.ParamDict['th4live'],
                         a.ParamDict['Iobs'],
                         color=self.c_data,
                         ls=self.l_data,
                         marker='o')
        self.ax.semilogy(a.ParamDict['th4live'],
                         a.ParamDict['I_fit'],
                         color=self.c_live,
                         ls=self.l_live)
        self.ax.set_ylabel("Intensity (a.u.)", fontdict=font)
        self.ax.set_xlabel(r'2$\theta$ (deg.)', fontdict=font)
        self.canvas.draw()

    def onFit(self, b=None):
        if b == 1:
            self.update_zoom = self.connect('motion_notify_event',
                                            self.MouseOnGraph)
            self.update_coord = self.connect('motion_notify_event',
                                             self.on_update_coordinate)
            self.item_unzoom.Enable(True)
            self.item_grid.Enable(True)
            self.item_cursor.Enable(True)
        else:
            self.disconnect(self.update_zoom)
            self.disconnect(self.update_coord)

            self.menu.Check(self.CursorId, check=False)
            self.item_unzoom.Enable(False)
            self.item_grid.Enable(False)
            self.item_cursor.Enable(False)
            self.ly.set_linewidth(0)
            self.lx.set_linewidth(0)

    def MouseOnGraph(self, event):
        a = P4Rm()
        if a.fitlive == 1:
            return
        if event.inaxes != None:
            if a.ParamDict['Iobs'] != "":
                xlim = self.ax.get_xlim()
                xlim_min = xlim[0] * np.pi / (2 * 180)
                xlim_max = xlim[1] * np.pi / (2 * 180)
                itemindex = where((a.ParamDictbackup['th'] > xlim_min)
                                  & (a.ParamDictbackup['th'] < xlim_max))
                t1 = itemindex[0][0]
                t2 = itemindex[0][-1]
                P4Rm.ParamDict['th'] = a.ParamDictbackup['th'][t1:t2]
                P4Rm.ParamDict['Iobs'] = a.ParamDictbackup['Iobs'][t1:t2]
                P4Rm.ParamDict['th4live'] = 2 * a.ParamDict['th'] * 180 / np.pi

    def OnRightDown(self, event):
        a = P4Rm()
        if a.fitlive == 1:
            return
        else:
            self.PopupMenu(self.menu)

    def OnUnzoom(self, event=None):
        self.canvas.toolbar.home()
        P4Rm.zoomOn = 0
        a = P4Rm()
        P4Rm.ParamDict['th'] = a.ParamDictbackup['th']
        P4Rm.ParamDict['Iobs'] = a.ParamDictbackup['Iobs']
        P4Rm.ParamDict['th4live'] = 2 * a.ParamDict['th'] * 180 / np.pi
        pub.sendMessage(pubsub_Re_Read_field_paramters_panel)
        self.CheckedGrid()
        self.CursorMove()

    def CheckedGrid(self, event=None):
        if self.menu.IsChecked(self.CheckedGridId) is True:
            self.ax.grid(True, color='gray')
        elif self.menu.IsChecked(self.CheckedGridId) is False:
            self.ax.grid(False)
        self.canvas.draw()

    def CursorMove(self, event=None):
        if self.menu.IsChecked(self.CursorId) is True:
            self.ly.set_linewidth(1)
            self.lx.set_linewidth(1)
        elif self.menu.IsChecked(self.CursorId) is False:
            self.ly.set_linewidth(0)
            self.lx.set_linewidth(0)

    def on_update_coordinate(self, event):
        if event.inaxes is None:
            self.statusbar.SetStatusText(u"", 1)
            self.statusbar.SetStatusText(u"", 2)
            return
        else:
            x, y = event.xdata, event.ydata
            self.ly.set_xdata(x)
            self.lx.set_ydata(y)
            xfloat = round(float(x), 4)
            yfloat = round(float(y), 8)
            self.statusbar.SetStatusText(u"x = " + str(xfloat), 1)
            self.statusbar.SetStatusText(u"y = " + str(yfloat), 2)
            self.canvas.draw()
Пример #14
0
class RTPWindow(wx.Frame):

    #########################Init Funcions#############################

    def __init__(self,parent=None,dpi=100,geoid=Geodesic.WGS84,resolution="50m",center_lon=0.,fontsize=8, verbose=False):
        """Constructor"""
        #call init of super class
        default_style = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.NO_FULL_REPAINT_ON_RESIZE | wx.WS_EX_CONTEXTHELP | wx.FRAME_EX_CONTEXTHELP
        wx.Frame.__init__(self, parent, title="Pole Plot %s"%parent.__version__,style=default_style, size=(600*2,600*2))
        self.Bind(wx.EVT_CLOSE, self.on_close_main)

        self.parent=parent
        if not pymax_found: self.parent.user_warning("PyRot module PyMax not found, pole plot viewer will not be usable"); self.on_close_window(-1)
        else: self.parent.rtp_open=True
        self.center_lon = center_lon
        self.dpi = dpi
        self.geoid = geoid
        self.resolution = resolution
        self.fontsize = fontsize
        self.verbose = verbose
        self.poles_to_plot = []

        self.panel = wx.Panel(self,-1,size=(400*2,300*2))

        #Populate UI and Menu
        self.init_UI()
        self.create_menu()
        self.configure()

        self.update()

    def init_UI(self):
        spacing = 10

        #------------------------------------Make DropDown Box-----------------------------------------------------#

        latlon_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "Window Boundaries"), wx.VERTICAL)
        proj_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "Choose Projection"), wx.VERTICAL)
        refresh_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "Refresh Figure"), wx.HORIZONTAL)

        projs = ["North Polar Stereographic","South Polar Stereographic","Orthographic"]
        self.proj_box = wx.ComboBox(self.panel, id=wx.ID_ANY,size=(100, 25), value=projs[0], choices=projs, style=wx.CB_DROPDOWN|wx.TE_READONLY)
        self.Bind(wx.EVT_COMBOBOX, self.on_select_proj,self.proj_box)

        self.max_lat_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(25,25))
        self.min_lat_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(25,25))
        self.max_lon_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(25,25))
        self.min_lon_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(25,25))
#        self.down_sample_box = wx.TextCtrl(self.panel, id=wx.ID_ANY|wx.TE_CENTRE, size=(50,25))\

        self.re_render_button = wx.Button(self.panel, id=wx.ID_ANY, label='Refresh Figure',size=(50,25))
        self.Bind(wx.EVT_BUTTON, self.on_re_render_button, self.re_render_button)
        self.add_pole_button = wx.Button(self.panel, id=wx.ID_ANY, label='Add Pole',size=(50,25))
        self.Bind(wx.EVT_BUTTON, self.on_add_pole_button, self.add_pole_button)

        #Projection sizer
        proj_sizer.Add(self.proj_box, 1, wx.ALIGN_LEFT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing)

        #Lat-Lon Sizer
        lat_sizer = wx.BoxSizer(wx.HORIZONTAL)
        lat_sizer.AddMany([(self.min_lat_box, 1, wx.ALIGN_LEFT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing),
                           (self.max_lat_box, 1, wx.ALIGN_RIGHT|wx.ALIGN_TOP|wx.EXPAND|wx.ALL, spacing)])
        lon_sizer = wx.BoxSizer(wx.HORIZONTAL)
        lon_sizer.AddMany([(self.min_lon_box, 1, wx.ALIGN_LEFT|wx.ALIGN_BOTTOM|wx.EXPAND|wx.ALL, spacing),
                           (self.max_lon_box, 1, wx.ALIGN_RIGHT|wx.ALIGN_BOTTOM|wx.EXPAND|wx.ALL, spacing)])
        latlon_sizer.AddMany([(lat_sizer, 1, wx.ALIGN_TOP|wx.EXPAND, spacing),
                              (lon_sizer, 1, wx.ALIGN_BOTTOM|wx.EXPAND, spacing)])

        #Downsample sizer with downsample box and refresh button
        refresh_sizer.AddMany([(self.re_render_button, 1, wx.ALIGN_LEFT|wx.ALIGN_BOTTOM|wx.EXPAND|wx.ALL, spacing),
                               (self.add_pole_button, 1, wx.ALIGN_RIGHT|wx.ALIGN_BOTTOM|wx.EXPAND|wx.ALL, spacing)])

        #Combine projection and downsample sizers
        proj_ds_sizer = wx.BoxSizer(wx.VERTICAL)
        proj_ds_sizer.AddMany([(proj_sizer, 1, wx.ALIGN_TOP|wx.EXPAND, spacing),
                               (refresh_sizer, 1, wx.ALIGN_BOTTOM|wx.EXPAND, spacing)])

        #Combine all in final sizer
        all_txt_btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
        all_txt_btn_sizer.AddMany([(proj_ds_sizer, 1, wx.ALIGN_LEFT|wx.EXPAND, spacing),
                                   (latlon_sizer, 1, wx.ALIGN_RIGHT|wx.EXPAND, spacing)])

        #-------------------------------------Make Figure----------------------------------------------------------#

        self.fig = Figure((2, 2), dpi=self.dpi)
        self.canvas = FigCanvas(self.panel, -1, self.fig)
        self.toolbar = NavigationToolbar(self.canvas)
        self.ax = self.fig.add_subplot(111)
        psk.remove_axis_lines_and_ticks(self.ax)
        self.toolbar.Hide()
        self.plot_setting = "Zoom"
        self.toolbar.zoom()
        self.canvas.Bind(wx.EVT_MIDDLE_DOWN,self.on_middle_click_plot)
#        self.canvas.Bind(wx.EVT_MOTION,self.on_move_mouse_plot)
        self.canvas.Bind(wx.EVT_LEFT_DCLICK, self.on_select_dleft_click)
        self.canvas.Bind(wx.EVT_RIGHT_DCLICK, self.on_select_dright_click)

        #----------------------------------Build UI and Fit--------------------------------------------------------#

        outer_sizer = wx.BoxSizer(wx.VERTICAL)
        outer_sizer.AddMany([#(grd_sizer,1,wx.ALIGN_CENTER|wx.ALIGN_TOP|wx.EXPAND|wx.LEFT|wx.RIGHT,spacing),
                             (all_txt_btn_sizer,1,wx.ALIGN_CENTER|wx.ALIGN_TOP|wx.EXPAND),
                             (self.canvas,10,wx.ALIGN_CENTER|wx.ALIGN_TOP|wx.EXPAND)])

        self.panel.SetSizerAndFit(outer_sizer)

    def create_menu(self):
        """
        Generates Menu
        """

        self.menubar = wx.MenuBar()

        #-----------------
        # File Menu
        #-----------------

        menu_file = wx.Menu()

        m_import_poles = menu_file.Append(-1, "&Import Poles From CSV", "ImportPoles")
        self.Bind(wx.EVT_MENU, self.on_import_poles, m_import_poles)

        menu_file.AppendSeparator()
        submenu_save_plots = wx.Menu()

        m_save_plot = submenu_save_plots.Append(-1, "&Save Plot", "")
        self.Bind(wx.EVT_MENU, self.on_save_plot, m_save_plot,"save-plot")

        m_new_sub_plots = menu_file.Append(-1, "&Save Result", submenu_save_plots)

        menu_file.AppendSeparator()
        m_exit = menu_file.Append(-1, "&Exit\tCtrl-Q", "Exit")
        self.Bind(wx.EVT_MENU, self.on_close_main, m_exit)

        #-----------------
        # Edit Menu
        #-----------------

        menu_edit = wx.Menu()

        self.m_remove_pole = menu_edit.Append(-1, "&Remove Last Pole\tCtrl-Z", "RemovePole")
        self.Bind(wx.EVT_MENU, self.on_remove_pole, self.m_remove_pole)

        self.m_remove_all_poles = menu_edit.Append(-1, "&Remove All Poles\tCtrl-Z", "RemovePolesAll")
        self.Bind(wx.EVT_MENU, self.on_remove_all_poles, self.m_remove_all_poles)

        self.m_add_strike_unc = menu_edit.AppendCheckItem(-1, "&Add Strike Uncertainty\tCtrl-R", "CalcStrikes")
        self.Bind(wx.EVT_MENU, self.on_add_strike_unc, self.m_add_strike_unc)

        self.m_solve_askw = menu_edit.AppendCheckItem(-1, "&Solve for Anomalous Skewness\tCtrl-A-R", "SolveAskw")
        self.Bind(wx.EVT_MENU, self.on_solve_askw, self.m_solve_askw)

        #-----------------
        # View Menu
        #-----------------

        menu_view = wx.Menu()

        self.m_show_lunes = menu_view.AppendCheckItem(-1, "&Show Lunes", "ShowLunes")
        self.m_show_lunes.Check()
        self.Bind(wx.EVT_MENU, self.on_show_lunes, self.m_show_lunes)

        self.m_show_pole = menu_view.AppendCheckItem(-1, "&Show Pole", "ShowPole")
#        self.m_show_pole.Check()
        self.Bind(wx.EVT_MENU, self.on_show_pole, self.m_show_pole)

        self.m_show_a95 = menu_view.AppendCheckItem(-1, "&Show A95", "ShowA95")
        self.m_show_a95.Check()
        self.Bind(wx.EVT_MENU, self.on_show_a95, self.m_show_a95)

        self.m_show_selected = menu_view.AppendCheckItem(-1, "&Show Selected", "ShowSelected")
        self.m_show_selected.Check()
        self.Bind(wx.EVT_MENU, self.on_show_selected, self.m_show_selected)

        #-----------------

        self.menubar.Append(menu_file, "&File")
        self.menubar.Append(menu_edit, "&Edit")
        self.menubar.Append(menu_view, "&View")
        self.SetMenuBar(self.menubar)

    def configure(self):
        self.min_lat_box.SetValue("%.1f"%60.)
        self.max_lat_box.SetValue("%.1f"%90.)
        self.min_lon_box.SetValue("%.1f"%-180.)
        self.max_lon_box.SetValue("%.1f"%180.)
        self.window = [None,None,None,None]

    #########################Update UI Funcions#############################

    def update(self): #Populates Logger and makes plot
        self.make_map() #Make Background Map

        if self.m_show_pole.IsChecked():

            if len(self.parent.deskew_df[self.parent.deskew_df["track_type"]=="ship"]) > 0:
                self.parent.save_max_file(".tmp.max",ship_only=True) #Save tmp max file to disk for debugging purposes and to more easily punch data into format using previous functions
                comment,header,ship_data = pymax.read_max_file(".tmp.max") #Read max file
                if len(ship_data["phs"])>2: #If more than 2 profiles (even-determined) invert ship
                    (plat,plon,pmag,maj_se,min_se,phi),chisq,dof = pymax.max_likelihood_pole(ship_data, trial_pole=header[:3], out_path="synth_mag_gui.maxout", save_full_data_kernel=self.verbose, step=header[-1], max_steps=100, comment=comment)
                    s1_ship = np.sqrt(chisq/dof)*ship_data["phs"][0][1][1] #ship 1sigma
                else: s1_ship = 0
            else: ship_data,s1_ship = {"phs":[["none",[0.,0.]]]},0

            if len(self.parent.deskew_df[self.parent.deskew_df["track_type"]=="aero"]) > 0:
                self.parent.save_max_file(".tmp.max",aero_only=True) #Do same for aero only data
                comment,header,aero_data = pymax.read_max_file(".tmp.max")
                if len(aero_data["phs"])>2:
                    (plat,plon,pmag,maj_se,min_se,phi),chisq,dof = pymax.max_likelihood_pole(aero_data, trial_pole=header[:3], out_path="synth_mag_gui.maxout", save_full_data_kernel=self.verbose, step=header[-1], max_steps=100, comment=comment)
                    s1_aero = np.sqrt(chisq/dof)*aero_data["phs"][0][1][1]
                else: s1_aero = 0
            else: aero_data,s1_aero = {"phs":[["none",[0.,0.]]]},0

            self.parent.save_max_file(".tmp.max") #now read all data and change s1 to match above
            comment,header,data = pymax.read_max_file(".tmp.max")
            if len(data["phs"])==0: return
            for i in range(len(data["phs"])):
                if len(ship_data["phs"]) > 0 and data["phs"][i][1][1]==ship_data["phs"][0][1][1]:
                    data["phs"][i][1][1] = s1_ship
                elif len(aero_data["phs"]) > 0 and data["phs"][i][1][1]==aero_data["phs"][0][1][1]:
                    data["phs"][i][1][1] = s1_aero

            if self.m_solve_askw.IsChecked(): (plat,plon,pmag,askw,maj_se,min_se,phi),chisq,dof = pymax.max_likelihood_pole(data, trial_pole=header[:3], out_path="synth_mag_gui.maxout", save_full_data_kernel=self.verbose, step=header[-1], max_steps=100, comment=comment, solve_anom_skew=self.m_solve_askw.IsChecked())
            else: (plat,plon,pmag,maj_se,min_se,phi),chisq,dof = pymax.max_likelihood_pole(data, trial_pole=header[:3], out_path="synth_mag_gui.maxout", save_full_data_kernel=self.verbose, step=header[-1], max_steps=100, comment=comment, solve_anom_skew=self.m_solve_askw.IsChecked())
            if self.m_add_strike_unc.IsChecked(): #If strike unc is to be included calculate it!!!
                (maj_se,min_se,phi) = cs.calc_strikes_and_add_err(self.parent.deskew_path,mlat=plat,mlon=plon,ma=maj_se,mb=min_se,mphi=phi,geoid=self.geoid,outfile=".tmp_dsk_cs",filter_by_quality=False,visualize=False,convergence_level=1e-5)
                os.remove(".tmp_dsk_cs")

            #write pole coordinates and 1sigmas to plot for user
            if phi<0: phi = phi+180
            elif phi>180: phi = phi%180
            if self.m_show_a95.IsChecked():
                f_factor = f.ppf(.95,2,dof)
                print(f_factor)
                maj_se,min_se = maj_se*np.sqrt(f_factor),min_se*np.sqrt(f_factor)
            if self.m_solve_askw.IsChecked(): self.ax.annotate(r"%.1f$^\circ$N, %.1f$^\circ$E"%(plat,plon)+"\n"+r"%.1f$^\circ$, %.1f$^\circ$, N%.1fE"%(maj_se,min_se,phi)+"\n"+"Anom. Skw. = %.1f"%askw+"\n"+r"$\chi^2_\nu$ = %.2f"%(chisq/dof)+"\n"+r"$1\sigma_{aero}$=%.1f"%(s1_aero)+"\n"+r"$1\sigma_{ship}$=%.1f"%(s1_ship),xy=(1-0.02,1-0.02),xycoords="axes fraction",bbox=dict(boxstyle="round", fc="w",alpha=.5),fontsize=self.fontsize,ha='right',va='top')
            else: self.ax.annotate(r"%.1f$^\circ$N, %.1f$^\circ$E"%(plat,plon)+"\n"+r"%.1f$^\circ$, %.1f$^\circ$, N%.1fE"%(maj_se,min_se,phi)+"\n"+r"$\chi^2_\nu$ = %.2f"%(chisq/dof)+"\n"+r"$1\sigma_{aero}$=%.1f"%(s1_aero)+"\n"+r"$1\sigma_{ship}$=%.1f"%(s1_ship),xy=(1-0.02,1-0.02),xycoords="axes fraction",bbox=dict(boxstyle="round", fc="w",alpha=.5),fontsize=self.fontsize,ha='right',va='top')
            #plot inverted pole
            self.ax = psk.plot_pole(plon,plat,phi,np.sqrt(chisq/dof)*maj_se,np.sqrt(chisq/dof)*min_se,m=self.ax, alpha=.5, zorder=10000)
        if self.m_show_lunes.IsChecked():
            #filter deskew_df to only data labeled "good" and plot lunes
            if self.m_solve_askw.IsChecked():
                srf,asf = self.parent.get_srf_asf()
                new_asf = lambda sr: asf(sr)+askw
                self.parent.deskew_df = sk.calc_aei(self.parent.deskew_df,srf,new_asf)
            else:
                self.parent.deskew_df = sk.calc_aei(self.parent.deskew_df,*self.parent.get_srf_asf())
            dsk_to_plot = self.parent.deskew_df[self.parent.deskew_df["quality"]=="g"]
            if self.m_show_selected.IsChecked():
                try: self.ax = psk.plot_lunes(dsk_to_plot,self.ax,idx_selected=self.parent.dsk_idx)
                except AttributeError: self.ax = psk.plot_lunes(dsk_to_plot,self.ax) #catch no selected data case
            else: self.ax = psk.plot_lunes(dsk_to_plot,self.ax)
#            os.remove(".tmp.max") #remove the deskew file on disk

        #plot any additional poles
        for pole_rec in self.poles_to_plot:
            print(pole_rec)
            self.ax = psk.plot_pole(*pole_rec[0],color=pole_rec[1],m=self.ax,zorder=1000)

        #set the map extent to match user input
        print([float(self.min_lon_box.GetValue()),float(self.max_lon_box.GetValue()),float(self.min_lat_box.GetValue()),float(self.max_lat_box.GetValue())])
        self.ax.set_extent([float(self.min_lon_box.GetValue()),float(self.max_lon_box.GetValue()),float(self.min_lat_box.GetValue()),float(self.max_lat_box.GetValue())], ccrs.PlateCarree())

        self.canvas.draw() #rerender

    def on_close_main(self,event):
        self.parent.rtp_open=False
        self.Destroy()

    ############################Menu Funcions################################

    def on_import_poles(self,event):
        dlg = wx.FileDialog(
            self, message="Choose CSV File",
            defaultDir=self.parent.WD,
            wildcard="Files (*.csv)|*.csv|All Files (*.*)|*.*",
            style=wx.FD_OPEN
            )
        if dlg.ShowModal() == wx.ID_OK:
            import_csv=dlg.GetPath()
            df_poles = pd.read_csv(import_csv,sep=None)
        dlg.Destroy()

        uniform_cols = list(map(lambda x: str(x).lower(), df_poles.columns))
        df_poles.columns = uniform_cols
        try:
            lat_col = next(filter(lambda x: x.startswith("lat"), uniform_cols))
            lon_col = next(filter(lambda x: x.startswith("lon"), uniform_cols))
            maj_col = next(filter(lambda x: x.startswith("maj"), uniform_cols))
            min_col = next(filter(lambda x: x.startswith("min"), uniform_cols))
            azi_col = next(filter(lambda x: x.startswith("azi"), uniform_cols))
        except:
            self.parent.user_warning("""Couldn't find a required column. There must be at least 5 columns.
                                        These 5 columns must have labels that start with lat, lon, maj, min, azi
                                        in any order and case insensitive. If more than one column fits these
                                        conditions then the first column is taken.""")
            return
        try: color_col = next(filter(lambda x: "color" in x, uniform_cols))
        except: color_col=None
        for i,row in df_poles.iterrows():
            if isinstance(color_col,type(None)):
                self.parent.user_warning("No Color for Pole (%.1f,%.1f), please specify"%(row[lat_col],row[lon_col]))
                cdlg = wx.ColourDialog(self)
                if cdlg.ShowModal() == wx.ID_OK:
                    color = tuple(np.array(cdlg.GetColourData().GetColour().Get())/255)
                else: color = "tab:blue"
            else: color = row[color_col]
            self.poles_to_plot.append([row[[lon_col,lat_col,azi_col,maj_col,min_col]].values,color])
        self.update()

    def on_save_plot(self,event):
        self.toolbar.save_figure()

    def on_remove_pole(self,event):
        self.poles_to_plot = self.poles_to_plot[:-1]
        self.update()

    def on_remove_all_poles(self,event):
        self.poles_to_plot = []
        self.update()

    def on_add_strike_unc(self,event):
        self.update()

    def on_solve_askw(self,event):
        self.update()

    def on_show_lunes(self,event):
        self.update()

    def on_show_pole(self,event):
        self.update()

    def on_show_a95(self,event):
        self.update()

    def on_show_selected(self,event):
        self.update()

    ###################Button and Dropdown Functions#########################

#    def on_change_grd_btn(self,event):
#        dlg = wx.FileDialog(
#            self, message="Choose Grid File",
#            defaultDir=self.parent.WD,
#            defaultFile="",
#            wildcard="Grid Files (*.grd,*.nc,*.ncf)|*.grd;*.nc;*.ncf|All Files (*.*)|*.*",
#            style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST
#            )
#        if dlg.ShowModal() == wx.ID_OK:
#            self.grd_file = dlg.GetPath()
#            self.grd_path.SetValue(self.grd_file)
#            self.update()
#            dlg.Destroy()
#        else: dlg.Destroy()

    def on_select_proj(self,event):
        self.update()

    def on_re_render_button(self,event):
        self.update()

    def on_add_pole_button(self,event):
        pdlg = PoleDialog(self) #run text entry dialog
        if pdlg.ShowModal() == wx.ID_OK:
            new_pole = [pdlg.lon,pdlg.lat,pdlg.phi,pdlg.a,pdlg.b]
        else: return
        pdlg.Destroy()
        cdata = wx.ColourData()
        cdata.SetChooseFull(True)
#        cdata.SetChooseAlpha(True)
        cdata.SetColour(wx.Colour(255, 0, 0, 128))
        cdlg = wx.ColourDialog(self,cdata)
        if cdlg.ShowModal() == wx.ID_OK:
            new_color = tuple(np.array(cdlg.GetColourData().GetColour().Get())/255)
        else: color = "#00FFFF88"
        if len(new_color)==3 or new_color[3]==1.: new_color =  (new_color[0],new_color[1],new_color[2],.5)
        elif len(new_color)<3:
            raise RuntimeError("If you're looking at this error in the terminal while running SynthMag GUI, you shouldn't be able to get here and something is significantly wrong with the color picker. Contact the dev on github.")
        cdlg.Destroy()
        self.poles_to_plot.append([new_pole,new_color]) #add new pole to list
        self.update() #update figure

    ###########################Figure Funcions###############################

    def on_middle_click_plot(self,event):
        if event.LeftIsDown() or event.ButtonDClick(): event.Skip(); return
        elif self.plot_setting == "Zoom":
            self.plot_setting = "Pan"
            self.toolbar.pan('off')
        elif self.plot_setting == "Pan":
            self.plot_setting = "Zoom"
            self.toolbar.zoom()
        event.Skip()

#    def on_move_mouse_plot(self,event):
#        try: dsk_row = self.parent.dsk_row
#        except AttributeError: event.Skip(); return
#        pos=event.GetPosition()
#        width, height = self.canvas.get_width_height()
#        pos = [pos[0],height-pos[1]]
#        pos = self.ax.transData.inverted().transform(pos)
#        lonlat = ccrs.PlateCarree().transform_point(*pos,self.proj)
#        self.plot_tracer_on_self_and_parent(dsk_row,lonlat)
#        self.parent.canvas.draw()
#        self.canvas.draw()
#        event.Skip()

    def on_select_dleft_click(self,event): #TODO make rtp
        try: self.parent.dsk_row
        except AttributeError: event.Skip(); return

        pos=event.GetPosition()
        width, height = self.canvas.get_width_height()
        pos = [pos[0],height-pos[1]]
        pos = self.ax.transData.inverted().transform(pos)

        plonlat = ccrs.PlateCarree().transform_point(*pos,self.proj)
        srf,asf = self.parent.get_srf_asf()
        reduced_skewness,rel_reduced_amplitude = sk.reduce_dsk_row_to_pole(self.parent.dsk_row,*plonlat,asf,srf)
        self.parent.phase_shift_box.SetValue("%.1f"%reduced_skewness)
        self.parent.deskew_df.at[self.parent.dsk_idx,'phase_shift'] = reduced_skewness
        self.parent.deskew_df.at[self.parent.dsk_idx,'rel_amp'] = rel_reduced_amplitude
        self.parent.dsk_row = self.parent.deskew_df.loc[self.parent.dsk_idx].iloc[0]

        self.parent.update(event)
        self.update()

    def on_select_dright_click(self,event): #TODO make rtp
        try: self.parent.deskew_df
        except AttributeError: event.Skip(); return

        pos=event.GetPosition()
        width, height = self.canvas.get_width_height()
        pos = [pos[0],height-pos[1]]
        pos = self.ax.transData.inverted().transform(pos)

        plonlat = ccrs.PlateCarree().transform_point(*pos,self.proj)
        srf,asf = self.parent.get_srf_asf()
        for i,row in self.parent.deskew_df.iterrows():
            reduced_skewness,rel_reduced_amplitude = sk.reduce_dsk_row_to_pole(row,*plonlat,asf,srf)
            self.parent.deskew_df.at[i,'phase_shift'] = reduced_skewness
            self.parent.deskew_df.at[i,'rel_amp'] = rel_reduced_amplitude
        self.parent.deskew_df = sk.calc_aei(self.parent.deskew_df,srf,asf)
        try: self.parent.dsk_row = self.parent.deskew_df.loc[self.parent.dsk_idx].iloc[0]
        except (AttributeError,KeyError) as e: pass

        self.parent.update(event)
        self.update()

    ##########################Additional Plotting and Backend Functions################

    def on_parent_select_track(self):
        self.update()

    def make_map(self):
        #set basemap
        try: self.fig.delaxes(self.ax)
        except AttributeError: self.parent.user_warning("Unable to remove previous axis and refresh map, raise issue with Dev.")
        #TODO: ADD TRANSVERSE MERCATOR AT STRIKE AS OPTION
        if self.proj_box.GetValue() == 'North Polar Stereographic':
            self.proj = ccrs.NorthPolarStereo(central_longitude=self.center_lon,true_scale_latitude=None,globe=None)
            self.ax = self.fig.add_subplot(111,projection=self.proj)
#            pgeo.make_circular_ax(self.ax)
        elif self.proj_box.GetValue() == 'South Polar Stereographic':
            self.proj = ccrs.SouthPolarStereo(central_longitude=self.center_lon,true_scale_latitude=None,globe=None)
            self.ax = self.fig.add_subplot(111,projection=self.proj)
#            pgeo.make_circular_ax(self.ax)
        elif self.proj_box.GetValue() == 'Orthographic':
            self.proj = ccrs.Orthographic(central_longitude=self.center_lon)
            self.ax = self.fig.add_subplot(111,projection=self.proj)
        else: self.parent.user_warning("Projection %s not supported"%str(self.proj_box.GetValue())); return

#        self.ax.set_xticks(np.arange(0, 370, 10.), crs=ccrs.PlateCarree())
#        self.ax.set_yticks(np.arange(-80, 90, 10.), crs=ccrs.PlateCarree())
#        self.ax.tick_params(grid_linewidth=.5,grid_linestyle=":",color="k",labelsize=8)
#        lon_formatter = LongitudeFormatter(zero_direction_label=True)
#        lat_formatter = LatitudeFormatter()
#        self.ax.xaxis.set_major_formatter(lon_formatter)
#        self.ax.yaxis.set_major_formatter(lat_formatter)
        self.ax.gridlines(color='grey', alpha=0.5, linestyle='--',linewidth=.5)
        land = cfeature.NaturalEarthFeature('physical', 'land', self.resolution, edgecolor="black", facecolor="grey", linewidth=2)
        self.ax.add_feature(land)
Пример #15
0
class SRMWindow(wx.Frame):

    #########################Init Funcions#############################

    def __init__(self,
                 spreading_rate_path,
                 parent=None,
                 starting_sz="",
                 fontsize=8,
                 dpi=200):
        """Constructor"""
        #call init of super class
        default_style = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.NO_FULL_REPAINT_ON_RESIZE | wx.WS_EX_CONTEXTHELP | wx.FRAME_EX_CONTEXTHELP
        wx.Frame.__init__(self,
                          parent,
                          title="Spreading Rate Model %s" % parent.__version__,
                          style=default_style,
                          size=(400 * 2, 300 * 2))
        self.Bind(wx.EVT_CLOSE, self.on_close_main)

        self.parent = parent
        self.dpi = dpi
        self.spreading_rate_path = spreading_rate_path

        self.panel = wx.Panel(self, -1, size=(400 * 2, 300 * 2))

        #Populate UI and Menu
        self.init_UI()
        self.create_menu()

        self.sz = starting_sz
        try:
            self.open_srm()
        except:
            self.srm = None

        self.update()

    def init_UI(self):
        spacing = 10

        #---------------------------------Make ListCtrl for SR---------------------------------------------------#

        self.logger = EditableListCtrl(self.panel,
                                       ID=wx.ID_ANY,
                                       size=(300, 300),
                                       style=wx.LC_REPORT)
        self.logger.InsertColumn(0, 'End Age', width=150)
        self.logger.InsertColumn(1, 'Half Rate', width=150)
        #        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_click_listctrl, self.logger)
        #        self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK,self.on_right_click_listctrl,self.logger)
        #        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_select_measurement, self.logger)

        #-----------------------------Make DropDown Box and Update-----------------------------------------------#

        sz_sizer = wx.StaticBoxSizer(
            wx.StaticBox(self.panel, wx.ID_ANY, "Choose Spreading Zone"),
            wx.VERTICAL)

        self.sz_box = wx.ComboBox(self.panel,
                                  id=wx.ID_ANY,
                                  size=(150, 25),
                                  choices=[],
                                  style=wx.CB_DROPDOWN | wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_COMBOBOX, self.on_select_sz, self.sz_box)
        self.Bind(wx.EVT_TEXT_ENTER, self.on_enter_sz, self.sz_box)

        add_rate_sizer = wx.StaticBoxSizer(
            wx.StaticBox(self.panel, wx.ID_ANY, "Add Rate to Model"),
            wx.HORIZONTAL)
        self.add_end_age_box = wx.TextCtrl(self.panel,
                                           id=wx.ID_ANY,
                                           size=(50, 25))
        self.add_half_rate_box = wx.TextCtrl(self.panel,
                                             id=wx.ID_ANY,
                                             size=(50, 25))
        self.add_rate_btn = wx.Button(self.panel,
                                      id=wx.ID_ANY,
                                      label='Add Rate',
                                      size=(50, 25))
        self.Bind(wx.EVT_BUTTON, self.on_add_rate_btn, self.add_rate_btn)
        add_rate_sizer.AddMany([
            (self.add_end_age_box, 1, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL
             | wx.LEFT | wx.BOTTOM | wx.EXPAND, spacing),
            (self.add_half_rate_box, 1, wx.ALIGN_LEFT
             | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.BOTTOM | wx.EXPAND,
             spacing),
            (self.add_rate_btn, 1, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL
             | wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, spacing),
        ])

        update_delete_sizer = wx.BoxSizer(wx.HORIZONTAL)
        delete_btn = wx.Button(self.panel,
                               id=wx.ID_ANY,
                               label='Delete Selected',
                               size=(75, 25))
        self.Bind(wx.EVT_BUTTON, self.on_delete_btn, delete_btn)

        update_button = wx.Button(self.panel,
                                  id=wx.ID_ANY,
                                  label='Save and Update',
                                  size=(75, 25))
        self.Bind(wx.EVT_BUTTON, self.on_update_button, update_button)
        update_delete_sizer.AddMany([
            (update_button, 1,
             wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.EXPAND,
             spacing),
            (delete_btn, 1, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT
             | wx.RIGHT | wx.EXPAND, spacing)
        ])

        sz_sizer.AddMany([
            (self.sz_box, 2, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL
             | wx.LEFT | wx.RIGHT | wx.TOP | wx.EXPAND, spacing),
            (add_rate_sizer, 3, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL
             | wx.LEFT | wx.RIGHT | wx.TOP | wx.EXPAND, spacing),
            (update_delete_sizer, 2, wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL
             | wx.LEFT | wx.RIGHT | wx.TOP | wx.BOTTOM | wx.EXPAND, spacing)
        ])

        #-------------------------------------Make Figure----------------------------------------------------------#

        self.fig = Figure((2, 2), dpi=self.dpi)
        self.canvas = FigCanvas(self.panel, -1, self.fig)
        self.toolbar = NavigationToolbar(self.canvas)
        self.ax = self.fig.add_subplot(111)
        psk.remove_axis_lines_and_ticks(self.ax)
        self.toolbar.Hide()
        self.plot_setting = "Zoom"
        self.toolbar.zoom()
        self.canvas.Bind(wx.EVT_MIDDLE_DOWN, self.on_middle_click_plot)

        #----------------------------------Build UI and Fit--------------------------------------------------------#

        side_bar_sizer = wx.BoxSizer(wx.VERTICAL)
        side_bar_sizer.AddMany([
            (sz_sizer, 1, wx.ALIGN_LEFT | wx.ALIGN_TOP | wx.LEFT | wx.RIGHT
             | wx.BOTTOM | wx.TOP | wx.EXPAND, spacing),
            (self.canvas, 8, wx.ALIGN_LEFT | wx.ALIGN_TOP | wx.LEFT | wx.RIGHT
             | wx.BOTTOM | wx.EXPAND, spacing)
        ])

        outer_sizer = wx.BoxSizer(wx.HORIZONTAL)
        outer_sizer.AddMany([
            (self.logger, 1, wx.ALIGN_LEFT | wx.ALIGN_TOP | wx.EXPAND),
            (side_bar_sizer, 3, wx.ALIGN_LEFT | wx.ALIGN_TOP | wx.EXPAND)
        ])

        self.panel.SetSizerAndFit(outer_sizer)

    def create_menu(self):
        """
        Generates Menu
        """

        self.menubar = wx.MenuBar()

        #-----------------
        # File Menu
        #-----------------

        menu_file = wx.Menu()

        menu_file.AppendSeparator()
        m_exit = menu_file.Append(-1, "&Exit\tCtrl-Q", "Exit")
        self.Bind(wx.EVT_MENU, self.on_close_main, m_exit)

        #-----------------

        self.menubar.Append(menu_file, "&File")
        self.SetMenuBar(self.menubar)

    #########################Update UI Funcions#############################

    def update_self_and_parent(self):
        utl.write_sr_model_file(self.srm, self.spreading_rate_path)
        try:
            srf, _ = sk.generate_spreading_rate_model(self.spreading_rate_path)
            self.parent.sr_box.SetValue(
                "%.1f" % (srf(self.parent.dsk_row["sz_name"],
                              (self.parent.dsk_row["age_min"] +
                               self.parent.dsk_row["age_max"]) / 2)))
        except (AttributeError, KeyError) as e:
            pass

        self.update()
        self.parent.update_synth = True
        self.parent.update(-1)

    def update(self):  #Populates Logger and makes plot

        if self.parent.spreading_rate_path != self.spreading_rate_path:
            self.spreading_rate_path = self.parent.spreading_rate_path
            self.open_srm()

        if self.spreading_rate_path == None: return

        self.logger.DeleteAllItems()
        points = [[], []]
        if self.sz in self.srm.keys():
            prev_age = 0
            for i, (end_age, half_rate) in enumerate(self.srm[self.sz]):
                self.logger.InsertItem(i, "%.3f" % end_age)
                self.logger.SetItem(i, 1, "%.3f" % half_rate)

                if end_age > 1e3: end_age = prev_age + 10
                if i == 0 and end_age > 10: prev_age = end_age - 10
                if prev_age == 0 and end_age <= 0: prev_age = end_age - 10
                points[0].append(prev_age)
                points[0].append(end_age)
                points[1].append(half_rate)
                points[1].append(half_rate)
                prev_age = end_age

        self.ax.clear()

        self.ax.plot(points[0], points[1], 'k-')

        self.canvas.draw()

    def on_close_main(self, event):
        self.parent.srmw_open = False
        self.Destroy()

    ###################Button and Dropdown Functions#########################

    def on_select_sz(self, event):
        self.sz = self.sz_box.GetValue()
        self.update()

    def on_enter_sz(self, event):
        sz_tmp = self.sz_box.GetValue()
        if sz_tmp in sz_box.GetItems():
            self.sz = sz_tmp
        else:
            if self.srm != None and self.parent.user_warning(
                    "Spreading Zone provided not in spreading rate model would you like to add to model?"
            ):
                self.sz = sz_tmp
                self.srm[self.sz] = [1e10, 40]
            else:
                self.sz_box.SetValue("")
                self.sz = None
        self.update()

    def on_update_button(
            self, event):  #Saves the edits and calls update on self and parent

        new_sz_srm = []
        for i in range(self.logger.GetItemCount()):
            try:
                new_sz_srm.append([
                    float(self.logger.GetItemText(i, 0)),
                    float(self.logger.GetItemText(i, 1))
                ])
            except ValueError:
                self.parent.user_warning(
                    "Half Rate and Age to add must be numbers got %s,%s instead"
                    % (self.logger.GetItemText(
                        i, 0), self.logger.GetItemText(i, 1)))
                return
        self.srm[self.sz] = new_sz_srm

        self.update_self_and_parent()

    def on_add_rate_btn(self, event):

        try:
            new_end_age, new_half_rate = float(
                self.add_end_age_box.GetValue()), float(
                    self.add_half_rate_box.GetValue())
        except ValueError:
            self.parent.user_warning(
                "Half Rate and Age to add must be numbers got %s,%s instead" %
                (str(new_end_age), str(new_half_rate)))
            return

        try:
            if new_end_age in np.array(self.srm[self.sz])[:, 0]:
                self.srm[self.sz] = [
                    [new_end_age, new_half_rate] if self.srm[self.sz][i][0]
                    == new_end_age else self.srm[self.sz][i]
                    for i in range(len(self.srm[self.sz]))
                ]
            else:
                self.srm[self.sz] += [[new_end_age, new_half_rate]]
            self.srm[self.sz].sort(key=cmp_to_key(lambda x, y: x[0] - y[0]))
        except (KeyError, IndexError) as e:
            self.srm[self.sz] = [[new_end_age, new_half_rate]]

        self.update_self_and_parent()

    def on_delete_btn(self, event):

        next_i, del_idxs = self.logger.GetNextSelected(-1), []
        if next_i == -1: return
        while next_i != -1:
            del_idxs.append(next_i)
            next_i = self.logger.GetNextSelected(next_i)

        new_sz_srm = []
        for i in range(self.logger.GetItemCount()):
            if i in del_idxs: continue  #Skip deleted data
            try:
                new_sz_srm.append([
                    float(self.logger.GetItemText(i, 0)),
                    float(self.logger.GetItemText(i, 1))
                ])
            except ValueError:
                self.parent.user_warning(
                    "Half Rate and Age to add must be numbers got %s,%s instead"
                    % (self.logger.GetItemText(
                        i, 0), self.logger.GetItemText(i, 1)))
                return

        self.srm[self.sz] = new_sz_srm

        self.update_self_and_parent()

    ###########################Figure Funcions###############################

    def on_middle_click_plot(self, event):
        if event.LeftIsDown() or event.ButtonDClick():
            event.Skip()
            return
        elif self.plot_setting == "Zoom":
            self.plot_setting = "Pan"
            self.toolbar.pan('off')
        elif self.plot_setting == "Pan":
            self.plot_setting = "Zoom"
            self.toolbar.zoom()
        event.Skip()

    ###########################Utility Funcions###############################

    def open_srm(self):
        self.srm = utl.open_sr_model_file(self.spreading_rate_path)
        self.sz_box.SetItems([""] + sorted(list(self.srm.keys())))
        self.sz_box.SetValue(self.sz)
Пример #16
0
class InterpretationEditorFrame(wx.Frame):

    #########################Init Funcions#############################

    def __init__(self,parent):
        """Constructor"""
        #set parent and resolution
        self.parent = parent
        self.GUI_RESOLUTION=self.parent.GUI_RESOLUTION
        #call init of super class
        default_style = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.NO_FULL_REPAINT_ON_RESIZE | wx.WS_EX_CONTEXTHELP | wx.FRAME_EX_CONTEXTHELP
        wx.Frame.__init__(self, self.parent, title="Interpretation Editor version:%s"%CURRENT_VERSION,style=default_style, size=(675*self.GUI_RESOLUTION,425*self.GUI_RESOLUTION))
        self.Bind(wx.EVT_CLOSE, self.on_close_edit_window)
        #setup wx help provider class to give help messages
        provider = wx.SimpleHelpProvider()
        wx.HelpProvider.Set(provider)
        self.helper = wx.ContextHelp(doNow=False)
        #make the Panel
        self.panel = wx.Panel(self,-1,size=(700*self.GUI_RESOLUTION,450*self.GUI_RESOLUTION))
        #set icon
        self.SetIcon(self.parent.icon)
#        icon = wx.Icon()
#        icon_path = os.path.join(IMG_DIRECTORY, 'PmagPy.ico')
#        if os.path.exists(icon_path):
#            icon.CopyFromBitmap(wx.Bitmap(icon_path), wx.BITMAP_TYPE_ANY)
#            self.SetIcon(icon)
        self.specimens_list=self.parent.specimens
        self.current_fit_index = None
        self.search_query = ""
        self.font_type = self.parent.font_type
        #build UI and menu
        self.init_UI()
        self.create_menu()
        #update with stuff
        self.on_select_level_name(None)

    def init_UI(self):
        """
        Builds User Interface for the interpretation Editor
        """

        #set fonts
        FONT_WEIGHT=1
        if sys.platform.startswith('win'): FONT_WEIGHT=-1
        font1 = wx.Font(9+FONT_WEIGHT, wx.SWISS, wx.NORMAL, wx.NORMAL, False, self.font_type)
        font2 = wx.Font(12+FONT_WEIGHT, wx.SWISS, wx.NORMAL, wx.NORMAL, False, self.font_type)

        #if you're on mac do some funny stuff to make it look okay
        is_mac = False
        if sys.platform.startswith("darwin"):
            is_mac = True

        self.search_bar = wx.SearchCtrl(self.panel, size=(350*self.GUI_RESOLUTION,25) ,style=wx.TE_PROCESS_ENTER | wx.TE_PROCESS_TAB | wx.TE_NOHIDESEL)
        self.Bind(wx.EVT_TEXT_ENTER, self.on_enter_search_bar,self.search_bar)
        self.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.on_enter_search_bar,self.search_bar)
        self.search_bar.SetHelpText(dieh.search_help)
#        self.Bind(wx.EVT_TEXT, self.on_complete_search_bar,self.search_bar)

        #build logger
        self.logger = wx.ListCtrl(self.panel, -1, size=(100*self.GUI_RESOLUTION,475*self.GUI_RESOLUTION),style=wx.LC_REPORT)
        self.logger.SetFont(font1)
        self.logger.InsertColumn(0, 'specimen',width=75*self.GUI_RESOLUTION)
        self.logger.InsertColumn(1, 'fit name',width=65*self.GUI_RESOLUTION)
        self.logger.InsertColumn(2, 'max',width=55*self.GUI_RESOLUTION)
        self.logger.InsertColumn(3, 'min',width=55*self.GUI_RESOLUTION)
        self.logger.InsertColumn(4, 'n',width=25*self.GUI_RESOLUTION)
        self.logger.InsertColumn(5, 'fit type',width=60*self.GUI_RESOLUTION)
        self.logger.InsertColumn(6, 'dec',width=45*self.GUI_RESOLUTION)
        self.logger.InsertColumn(7, 'inc',width=45*self.GUI_RESOLUTION)
        self.logger.InsertColumn(8, 'mad',width=45*self.GUI_RESOLUTION)
        self.logger.InsertColumn(9, 'dang',width=45*self.GUI_RESOLUTION)
        self.logger.InsertColumn(10, 'a95',width=45*self.GUI_RESOLUTION)
        self.logger.InsertColumn(11, 'K',width=45*self.GUI_RESOLUTION)
        self.logger.InsertColumn(12, 'R',width=45*self.GUI_RESOLUTION)
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnClick_listctrl, self.logger)
        self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK,self.OnRightClickListctrl,self.logger)
        self.logger.SetHelpText(dieh.logger_help)

        #set fit attributes boxsizers
        self.display_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "display options"), wx.HORIZONTAL)
        self.name_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "fit name/color"), wx.VERTICAL)
        self.bounds_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "fit bounds"), wx.VERTICAL)
        self.buttons_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY), wx.VERTICAL)

        #logger display selection box
        UPPER_LEVEL = self.parent.level_box.GetValue()
        if UPPER_LEVEL=='sample':
            name_choices = self.parent.samples
        if UPPER_LEVEL=='site':
            name_choices = self.parent.sites
        if UPPER_LEVEL=='location':
            name_choices = self.parent.locations
        if UPPER_LEVEL=='study':
            name_choices = ['this study']

        self.level_box = wx.ComboBox(self.panel, -1, size=(110*self.GUI_RESOLUTION, 25), value=UPPER_LEVEL, choices=['sample','site','location','study'], style=wx.CB_DROPDOWN|wx.TE_READONLY)
        self.Bind(wx.EVT_COMBOBOX, self.on_select_high_level,self.level_box)
        self.level_box.SetHelpText(dieh.level_box_help)

        self.level_names = wx.ComboBox(self.panel, -1, size=(110*self.GUI_RESOLUTION, 25), value=self.parent.level_names.GetValue(), choices=name_choices, style=wx.CB_DROPDOWN|wx.TE_READONLY)
        self.Bind(wx.EVT_COMBOBOX, self.on_select_level_name,self.level_names)
        self.level_names.SetHelpText(dieh.level_names_help)

        #mean type and plot display boxes
        self.mean_type_box = wx.ComboBox(self.panel, -1, size=(110*self.GUI_RESOLUTION, 25), value=self.parent.mean_type_box.GetValue(), choices=['Fisher','Fisher by polarity','None'], style=wx.CB_DROPDOWN|wx.TE_READONLY, name="high_type")
        self.Bind(wx.EVT_COMBOBOX, self.on_select_mean_type_box,self.mean_type_box)
        self.mean_type_box.SetHelpText(dieh.mean_type_help)

        self.mean_fit_box = wx.ComboBox(self.panel, -1, size=(110*self.GUI_RESOLUTION, 25), value=self.parent.mean_fit, choices=(['None','All'] + self.parent.fit_list), style=wx.CB_DROPDOWN|wx.TE_READONLY, name="high_type")
        self.Bind(wx.EVT_COMBOBOX, self.on_select_mean_fit_box,self.mean_fit_box)
        self.mean_fit_box.SetHelpText(dieh.mean_fit_help)

        #show box
        if UPPER_LEVEL == "study" or UPPER_LEVEL == "location":
            show_box_choices = ['specimens','samples','sites']
        if UPPER_LEVEL == "site":
            show_box_choices = ['specimens','samples']
        if UPPER_LEVEL == "sample":
            show_box_choices = ['specimens']

        self.show_box = wx.ComboBox(self.panel, -1, size=(110*self.GUI_RESOLUTION, 25), value='specimens', choices=show_box_choices, style=wx.CB_DROPDOWN|wx.TE_READONLY,name="high_elements")
        self.Bind(wx.EVT_COMBOBOX, self.on_select_show_box,self.show_box)
        self.show_box.SetHelpText(dieh.show_help)

        #coordinates box
        self.coordinates_box = wx.ComboBox(self.panel, -1, size=(110*self.GUI_RESOLUTION, 25), choices=self.parent.coordinate_list, value=self.parent.coordinates_box.GetValue(), style=wx.CB_DROPDOWN|wx.TE_READONLY, name="coordinates")
        self.Bind(wx.EVT_COMBOBOX, self.on_select_coordinates,self.coordinates_box)
        self.coordinates_box.SetHelpText(dieh.coordinates_box_help)

        #bounds select boxes
        self.tmin_box = wx.ComboBox(self.panel, -1, size=(80*self.GUI_RESOLUTION, 25), choices=[''] + self.parent.T_list, style=wx.CB_DROPDOWN|wx.TE_READONLY, name="lower bound")
        self.tmin_box.SetHelpText(dieh.tmin_box_help)

        self.tmax_box = wx.ComboBox(self.panel, -1, size=(80*self.GUI_RESOLUTION, 25), choices=[''] + self.parent.T_list, style=wx.CB_DROPDOWN|wx.TE_READONLY, name="upper bound")
        self.tmax_box.SetHelpText(dieh.tmax_box_help)

        #color box
        self.color_dict = self.parent.color_dict
        self.color_box = wx.ComboBox(self.panel, -1, size=(80*self.GUI_RESOLUTION, 25), choices=[''] + sorted(self.color_dict.keys()), style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER, name="color")
        self.Bind(wx.EVT_TEXT_ENTER, self.add_new_color, self.color_box)
        self.color_box.SetHelpText(dieh.color_box_help)

        #name box
        self.name_box = wx.TextCtrl(self.panel, -1, size=(80*self.GUI_RESOLUTION, 25), name="name")
        self.name_box.SetHelpText(dieh.name_box_help)

        #more mac stuff
        h_size_buttons,button_spacing = 25,5.5
        if is_mac: h_size_buttons,button_spacing = 18,0.

        #buttons
        self.add_all_button = wx.Button(self.panel, id=-1, label='add new fit to all specimens',size=(160*self.GUI_RESOLUTION,h_size_buttons))
        self.add_all_button.SetFont(font1)
        self.Bind(wx.EVT_BUTTON, self.add_fit_to_all, self.add_all_button)
        self.add_all_button.SetHelpText(dieh.add_all_help)

        self.add_fit_button = wx.Button(self.panel, id=-1, label='add fit to highlighted specimens',size=(160*self.GUI_RESOLUTION,h_size_buttons))
        self.add_fit_button.SetFont(font1)
        self.Bind(wx.EVT_BUTTON, self.add_highlighted_fits, self.add_fit_button)
        self.add_fit_button.SetHelpText(dieh.add_fit_btn_help)

        self.delete_fit_button = wx.Button(self.panel, id=-1, label='delete highlighted fits',size=(160*self.GUI_RESOLUTION,h_size_buttons))
        self.delete_fit_button.SetFont(font1)
        self.Bind(wx.EVT_BUTTON, self.delete_highlighted_fits, self.delete_fit_button)
        self.delete_fit_button.SetHelpText(dieh.delete_fit_btn_help)

        self.apply_changes_button = wx.Button(self.panel, id=-1, label='apply changes to highlighted fits',size=(160*self.GUI_RESOLUTION,h_size_buttons))
        self.apply_changes_button.SetFont(font1)
        self.Bind(wx.EVT_BUTTON, self.apply_changes, self.apply_changes_button)
        self.apply_changes_button.SetHelpText(dieh.apply_changes_help)

        #windows
        display_window_0 = wx.GridSizer(2, 1, 10*self.GUI_RESOLUTION, 19*self.GUI_RESOLUTION)
        display_window_1 = wx.GridSizer(2, 1, 10*self.GUI_RESOLUTION, 19*self.GUI_RESOLUTION)
        display_window_2 = wx.GridSizer(2, 1, 10*self.GUI_RESOLUTION, 19*self.GUI_RESOLUTION)
        name_window = wx.GridSizer(2, 1, 10*self.GUI_RESOLUTION, 19*self.GUI_RESOLUTION)
        bounds_window = wx.GridSizer(2, 1, 10*self.GUI_RESOLUTION, 19*self.GUI_RESOLUTION)
        buttons1_window = wx.GridSizer(4, 1, 5*self.GUI_RESOLUTION, 19*self.GUI_RESOLUTION)
        display_window_0.AddMany( [(self.coordinates_box, wx.ALIGN_LEFT),
                                   (self.show_box, wx.ALIGN_LEFT)] )
        display_window_1.AddMany( [(self.level_box, wx.ALIGN_LEFT),
                                   (self.level_names, wx.ALIGN_LEFT)] )
        display_window_2.AddMany( [(self.mean_type_box, wx.ALIGN_LEFT),
                                   (self.mean_fit_box, wx.ALIGN_LEFT)] )
        name_window.AddMany( [(self.name_box, wx.ALIGN_LEFT),
                                (self.color_box, wx.ALIGN_LEFT)] )
        bounds_window.AddMany( [(self.tmin_box, wx.ALIGN_LEFT),
                                (self.tmax_box, wx.ALIGN_LEFT)] )
        buttons1_window.AddMany( [(self.add_fit_button, wx.ALL|wx.ALIGN_CENTER|wx.SHAPED, 0),
                                  (self.add_all_button, wx.ALL|wx.ALIGN_CENTER|wx.SHAPED, 0),
                                  (self.delete_fit_button, wx.ALL|wx.ALIGN_CENTER|wx.SHAPED, 0),
                                  (self.apply_changes_button, wx.ALL|wx.ALIGN_CENTER|wx.SHAPED, 0)])
        self.display_sizer.Add(display_window_0, 1, wx.TOP|wx.EXPAND, 8)
        self.display_sizer.Add(display_window_1, 1, wx.TOP | wx.LEFT|wx.EXPAND, 8)
        self.display_sizer.Add(display_window_2, 1, wx.TOP | wx.LEFT|wx.EXPAND, 8)
        self.name_sizer.Add(name_window, 1, wx.TOP, 5.5)
        self.bounds_sizer.Add(bounds_window, 1, wx.TOP, 5.5)
        self.buttons_sizer.Add(buttons1_window, 1, wx.TOP, 0)

        #duplicate high levels plot
        self.fig = Figure((2.5*self.GUI_RESOLUTION, 2.5*self.GUI_RESOLUTION), dpi=100)
        self.canvas = FigCanvas(self.panel, -1, self.fig, )
        self.toolbar = NavigationToolbar(self.canvas)
        self.toolbar.Hide()
        self.toolbar.zoom()
        self.high_EA_setting = "Zoom"
        self.canvas.Bind(wx.EVT_LEFT_DCLICK,self.on_equalarea_high_select)
        self.canvas.Bind(wx.EVT_MOTION,self.on_change_high_mouse_cursor)
        self.canvas.Bind(wx.EVT_MIDDLE_DOWN,self.home_high_equalarea)
        self.canvas.Bind(wx.EVT_RIGHT_DOWN,self.pan_zoom_high_equalarea)
        self.canvas.SetHelpText(dieh.eqarea_help)

        self.eqarea = self.fig.add_subplot(111)
        draw_net(self.eqarea)

        #Higher Level Statistics Box
        self.stats_sizer = wx.StaticBoxSizer( wx.StaticBox( self.panel, wx.ID_ANY,"mean statistics"  ), wx.VERTICAL)

        for parameter in ['mean_type','dec','inc','alpha95','K','R','n_lines','n_planes']:
            COMMAND="self.%s_window=wx.TextCtrl(self.panel,style=wx.TE_CENTER|wx.TE_READONLY,size=(100*self.GUI_RESOLUTION,25))"%parameter
            exec(COMMAND)
            COMMAND="self.%s_window.SetBackgroundColour(wx.WHITE)"%parameter
            exec(COMMAND)
            COMMAND="self.%s_window.SetFont(font2)"%parameter
            exec(COMMAND)
            COMMAND="self.%s_outer_window = wx.GridSizer(1,2,5*self.GUI_RESOLUTION,15*self.GUI_RESOLUTION)"%parameter
            exec(COMMAND)
            COMMAND="""self.%s_outer_window.AddMany([
                    (wx.StaticText(self.panel,label='%s',style=wx.TE_CENTER),wx.EXPAND),
                    (self.%s_window, wx.EXPAND)])"""%(parameter,parameter,parameter)
            exec(COMMAND)
            COMMAND="self.stats_sizer.Add(self.%s_outer_window, 1, wx.ALIGN_LEFT|wx.EXPAND, 0)"%parameter
            exec(COMMAND)

        self.switch_stats_button = wx.SpinButton(self.panel, id=wx.ID_ANY, style=wx.SP_HORIZONTAL|wx.SP_ARROW_KEYS|wx.SP_WRAP, name="change stats")
        self.Bind(wx.EVT_SPIN, self.on_select_stats_button,self.switch_stats_button)
        self.switch_stats_button.SetHelpText(dieh.switch_stats_btn_help)

        #construct panel
        hbox0 = wx.BoxSizer(wx.HORIZONTAL)
        hbox0.Add(self.name_sizer,flag=wx.ALIGN_TOP|wx.EXPAND,border=8)
        hbox0.Add(self.bounds_sizer,flag=wx.ALIGN_TOP|wx.EXPAND,border=8)

        vbox0 = wx.BoxSizer(wx.VERTICAL)
        vbox0.Add(hbox0,flag=wx.ALIGN_TOP,border=8)
        vbox0.Add(self.buttons_sizer,flag=wx.ALIGN_TOP,border=8)

        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox1.Add(vbox0,flag=wx.ALIGN_TOP,border=8)
        hbox1.Add(self.stats_sizer,flag=wx.ALIGN_TOP,border=8)
        hbox1.Add(self.switch_stats_button,flag=wx.ALIGN_TOP|wx.EXPAND,border=8)

        vbox1 = wx.BoxSizer(wx.VERTICAL)
        vbox1.Add(self.display_sizer,flag=wx.ALIGN_TOP,border=8)
        vbox1.Add(hbox1,flag=wx.ALIGN_TOP,border=8)
        vbox1.Add(self.canvas,proportion=1,flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,border=8)

        vbox2 = wx.BoxSizer(wx.VERTICAL)
        vbox2.Add(self.search_bar,proportion=.5,flag=wx.ALIGN_LEFT | wx.ALIGN_BOTTOM | wx.EXPAND, border=8)
        vbox2.Add(self.logger,proportion=1,flag=wx.ALIGN_LEFT|wx.EXPAND,border=8)

        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2.Add(vbox2,proportion=1,flag=wx.ALIGN_LEFT|wx.EXPAND)
        hbox2.Add(vbox1,flag=wx.ALIGN_TOP|wx.EXPAND)

        self.panel.SetSizerAndFit(hbox2)
        hbox2.Fit(self)

    def create_menu(self):

        menubar = wx.MenuBar()

        #--------------------------------------------------------------------

        menu_file = wx.Menu()

        m_change_WD = menu_file.Append(-1, "Change Working Directory\tCtrl-W","")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_change_working_directory, m_change_WD)

        m_make_MagIC_results_tables = menu_file.Append(-1, "&Save MagIC pmag tables\tCtrl-Shift-S", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_make_MagIC_results_tables, m_make_MagIC_results_tables)

        submenu_save_plots = wx.Menu()

        m_save_high_level = submenu_save_plots.Append(-1, "&Save high level plot", "")
        self.Bind(wx.EVT_MENU, self.parent.on_save_high_level, m_save_high_level,"Eq")

        m_new_sub_plots = menu_file.AppendSubMenu(submenu_save_plots, "&Save plot")

        menu_file.AppendSeparator()
        m_exit = menu_file.Append(-1, "E&xit\tCtrl-Q", "Exit")
        self.Bind(wx.EVT_MENU, self.on_close_edit_window, m_exit)

        #--------------------------------------------------------------------

        menu_Analysis = wx.Menu()

        submenu_criteria = wx.Menu()

        m_change_criteria_file = submenu_criteria.Append(-1, "&Change acceptance criteria", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_change_criteria, m_change_criteria_file)

        m_import_criteria_file =  submenu_criteria.Append(-1, "&Import criteria file", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_criteria_file, m_import_criteria_file)

        m_new_sub = menu_Analysis.AppendSubMenu(submenu_criteria, "Acceptance criteria")

        m_import_LSQ = menu_Analysis.Append(-1, "&Import Interpretations from LSQ file\tCtrl-L", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_read_from_LSQ, m_import_LSQ)

        m_previous_interpretation = menu_Analysis.Append(-1, "&Import previous interpretations from a redo file\tCtrl-R", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_previous_interpretation, m_previous_interpretation)

        m_save_interpretation = menu_Analysis.Append(-1, "&Save current interpretations to a redo file\tCtrl-S", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_save_interpretation, m_save_interpretation)

        #--------------------------------------------------------------------

        menu_Tools = wx.Menu()

        m_view_VGP = menu_Tools.Append(-1, "&View VGPs\tCtrl-Shift-V", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_view_vgps, m_view_VGP)

        #--------------------------------------------------------------------

        menu_Help = wx.Menu()

        m_help = menu_Help.Append(-1, "&Usage and Tips\tCtrl-H", "")
        self.Bind(wx.EVT_MENU, self.on_menu_help, m_help)

        m_cookbook = menu_Help.Append(-1, "&PmagPy Cookbook\tCtrl-Shift-W", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_cookbook, m_cookbook)

        m_docs = menu_Help.Append(-1, "&Open Docs\tCtrl-Shift-H", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_docs, m_docs)

        m_git = menu_Help.Append(-1, "&Github Page\tCtrl-Shift-G", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_git, m_git)

        m_debug = menu_Help.Append(-1, "&Open Debugger\tCtrl-Shift-D", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_debug, m_debug)

        #--------------------------------------------------------------------

        menu_edit = wx.Menu()

        m_new = menu_edit.Append(-1, "&New interpretation\tCtrl-N", "")
        self.Bind(wx.EVT_MENU, self.parent.on_btn_add_fit, m_new)

        m_delete = menu_edit.Append(-1, "&Delete interpretation\tCtrl-D", "")
        self.Bind(wx.EVT_MENU, self.parent.on_btn_delete_fit, m_delete)

        m_next_interp = menu_edit.Append(-1, "&Next interpretation\tCtrl-Up", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_next_interp, m_next_interp)

        m_previous_interp = menu_edit.Append(-1, "&Previous interpretation\tCtrl-Down", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_prev_interp, m_previous_interp)

        m_next_specimen = menu_edit.Append(-1, "&Next Specimen\tCtrl-Right", "")
        self.Bind(wx.EVT_MENU, self.parent.on_next_button, m_next_specimen)

        m_previous_specimen = menu_edit.Append(-1, "&Previous Specimen\tCtrl-Left", "")
        self.Bind(wx.EVT_MENU, self.parent.on_prev_button, m_previous_specimen)

        menu_coordinates = wx.Menu()

        m_speci = menu_coordinates.Append(-1, "&Specimen Coordinates\tCtrl-P", "")
        self.Bind(wx.EVT_MENU, self.parent.on_menu_change_speci_coord, m_speci)
        if "geographic" in self.parent.coordinate_list:
            m_geo = menu_coordinates.Append(-1, "&Geographic Coordinates\tCtrl-G", "")
            self.Bind(wx.EVT_MENU, self.parent.on_menu_change_geo_coord, m_geo)
        if "tilt-corrected" in self.parent.coordinate_list:
            m_tilt = menu_coordinates.Append(-1, "&Tilt-Corrected Coordinates\tCtrl-T", "")
            self.Bind(wx.EVT_MENU, self.parent.on_menu_change_tilt_coord, m_tilt)

        m_coords = menu_edit.AppendSubMenu(menu_coordinates, "&Coordinate Systems")

        #--------------------------------------------------------------------

        #self.menubar.Append(menu_preferences, "& Preferences")
        menubar.Append(menu_file, "&File")
        menubar.Append(menu_edit, "&Edit")
        menubar.Append(menu_Analysis, "&Analysis")
        menubar.Append(menu_Tools, "&Tools")
        menubar.Append(menu_Help, "&Help")
        self.SetMenuBar(menubar)

    ################################Logger Functions##################################

    def update_editor(self):
        """
        updates the logger and plot on the interpretation editor window
        """

        self.fit_list = []
        self.search_choices = []
        for specimen in self.specimens_list:
            if specimen not in self.parent.pmag_results_data['specimens']: continue
            self.fit_list += [(fit,specimen) for fit in self.parent.pmag_results_data['specimens'][specimen]]

        self.logger.DeleteAllItems()
        offset = 0
        for i in range(len(self.fit_list)):
            i -= offset
            v = self.update_logger_entry(i)
            if v == "s": offset += 1

    def update_logger_entry(self,i):
        """
        helper function that given a index in this objects fit_list parameter inserts a entry at that index
        @param: i -> index in fit_list to find the (specimen_name,fit object) tup that determines all the data for this logger entry.
        """
        if i < len(self.fit_list):
            tup = self.fit_list[i]
        elif i < self.logger.GetItemCount():
            self.logger.DeleteItem(i)
            return
        else: return

        coordinate_system = self.parent.COORDINATE_SYSTEM
        fit = tup[0]
        pars = fit.get(coordinate_system)
        fmin,fmax,n,ftype,dec,inc,mad,dang,a95,sk,sr2 = "","","","","","","","","","",""

        specimen = tup[1]
        if coordinate_system=='geographic':
            block_key = 'zijdblock_geo'
        elif coordinate_system=='tilt-corrected':
            block_key = 'zijdblock_tilt'
        else:
            block_key = 'zijdblock'

        name = fit.name
        if pars == {} and self.parent.Data[specimen][block_key] != []:
            fit.put(specimen, coordinate_system, self.parent.get_PCA_parameters(specimen,fit,fit.tmin,fit.tmax,coordinate_system,fit.PCA_type))
            pars = fit.get(coordinate_system)
        if self.parent.Data[specimen][block_key]==[]:
            spars = fit.get('specimen')
            fmin = fit.tmin
            fmax = fit.tmax
            if 'specimen_n' in list(spars.keys()): n = str(spars['specimen_n'])
            else: n = 'No Data'
            if 'calculation_type' in list(spars.keys()): ftype = spars['calculation_type']
            else: ftype = 'No Data'
            dec = 'No Data'
            inc = 'No Data'
            mad = 'No Data'
            dang = 'No Data'
            a95 = 'No Data'
            sk = 'No Data'
            sr2 = 'No Data'
        else:
            if 'measurement_step_min' in list(pars.keys()): fmin = str(fit.tmin)
            else: fmin = "N/A"
            if 'measurement_step_max' in list(pars.keys()): fmax = str(fit.tmax)
            else: fmax = "N/A"
            if 'specimen_n' in list(pars.keys()): n = str(pars['specimen_n'])
            else: n = "N/A"
            if 'calculation_type' in list(pars.keys()): ftype = pars['calculation_type']
            else: ftype = "N/A"
            if 'specimen_dec' in list(pars.keys()): dec = "%.1f"%pars['specimen_dec']
            else: dec = "N/A"
            if 'specimen_inc' in list(pars.keys()): inc = "%.1f"%pars['specimen_inc']
            else: inc = "N/A"
            if 'specimen_mad' in list(pars.keys()): mad = "%.1f"%pars['specimen_mad']
            else: mad = "N/A"
            if 'specimen_dang' in list(pars.keys()): dang = "%.1f"%pars['specimen_dang']
            else: dang = "N/A"
            if 'specimen_alpha95' in list(pars.keys()): a95 = "%.1f"%pars['specimen_alpha95']
            else: a95 = "N/A"
            if 'specimen_k' in list(pars.keys()): sk = "%.1f"%pars['specimen_k']
            else: sk = "N/A"
            if 'specimen_r' in list(pars.keys()): sr2 = "%.1f"%pars['specimen_r']
            else: sr2 = "N/A"

        if self.search_query != "":
            entry = (specimen+name+fmin+fmax+n+ftype+dec+inc+mad+dang+a95+sk+sr2).replace(" ","").lower()
            if self.search_query not in entry:
                self.fit_list.pop(i)
                if i < self.logger.GetItemCount():
                    self.logger.DeleteItem(i)
                return "s"
        for e in (specimen,name,fmin,fmax,n,ftype,dec,inc,mad,dang,a95,sk,sr2):
            if e not in self.search_choices:
                self.search_choices.append(e)

        if i < self.logger.GetItemCount():
            self.logger.DeleteItem(i)
        self.logger.InsertItem(i, str(specimen))
        self.logger.SetItem(i, 1, name)
        self.logger.SetItem(i, 2, fmin)
        self.logger.SetItem(i, 3, fmax)
        self.logger.SetItem(i, 4, n)
        self.logger.SetItem(i, 5, ftype)
        self.logger.SetItem(i, 6, dec)
        self.logger.SetItem(i, 7, inc)
        self.logger.SetItem(i, 8, mad)
        self.logger.SetItem(i, 9, dang)
        self.logger.SetItem(i, 10, a95)
        self.logger.SetItem(i, 11, sk)
        self.logger.SetItem(i, 12, sr2)
        self.logger.SetItemBackgroundColour(i,"WHITE")
        a,b = False,False
        if fit in self.parent.bad_fits:
            self.logger.SetItemBackgroundColour(i,"red")
            b = True
        if self.parent.current_fit == fit:
            self.logger.SetItemBackgroundColour(i,"LIGHT BLUE")
            self.logger_focus(i)
            self.current_fit_index = i
            a = True
        if a and b:
            self.logger.SetItemBackgroundColour(i,"red")

    def update_current_fit_data(self):
        """
        updates the current_fit of the parent Zeq_GUI entry in the case of it's data being changed
        """
        if self.current_fit_index:
            self.update_logger_entry(self.current_fit_index)

    def change_selected(self,new_fit):
        """
        updates passed in fit or index as current fit for the editor (does not affect parent),
        if no parameters are passed in it sets first fit as current
        @param: new_fit -> fit object to highlight as selected
        """
        if len(self.fit_list)==0: return
        if self.search_query and self.parent.current_fit not in [x[0] for x in self.fit_list]: return
        if self.current_fit_index == None:
            if not self.parent.current_fit: return
            for i,(fit,specimen) in enumerate(self.fit_list):
                if fit == self.parent.current_fit:
                    self.current_fit_index = i
                    break
        i = 0
        if isinstance(new_fit, Fit):
            for i, (fit,speci) in enumerate(self.fit_list):
                if fit == new_fit:
                    break
        elif type(new_fit) is int:
            i = new_fit
        elif new_fit != None:
            print(('cannot select fit of type: ' + str(type(new_fit))))
        if self.current_fit_index != None and \
        len(self.fit_list) > 0 and \
        self.fit_list[self.current_fit_index][0] in self.parent.bad_fits:
            self.logger.SetItemBackgroundColour(self.current_fit_index,"")
        else:
            self.logger.SetItemBackgroundColour(self.current_fit_index,"WHITE")
        self.current_fit_index = i
        if self.fit_list[self.current_fit_index][0] in self.parent.bad_fits:
            self.logger.SetItemBackgroundColour(self.current_fit_index,"red")
        else:
            self.logger.SetItemBackgroundColour(self.current_fit_index,"LIGHT BLUE")

    def logger_focus(self,i,focus_shift=16):
        """
        focuses the logger on an index 12 entries below i
        @param: i -> index to focus on
        """
        if self.logger.GetItemCount()-1 > i+focus_shift:
            i += focus_shift
        else:
            i = self.logger.GetItemCount()-1
        self.logger.Focus(i)

    def OnClick_listctrl(self, event):
        """
        Edits the logger and the Zeq_GUI parent object to select the fit that was newly selected by a double click
        @param: event -> wx.ListCtrlEvent that triggered this function
        """
        i = event.GetIndex()
        if self.parent.current_fit == self.fit_list[i][0]: return
        self.parent.initialize_CART_rot(self.fit_list[i][1])
        si = self.parent.specimens.index(self.fit_list[i][1])
        self.parent.specimens_box.SetSelection(si)
        self.parent.select_specimen(self.fit_list[i][1])
        self.change_selected(i)
        fi = 0
        while (self.parent.s == self.fit_list[i][1] and i >= 0): i,fi = (i-1,fi+1)
        self.parent.update_fit_box()
        self.parent.fit_box.SetSelection(fi-1)
        self.parent.update_selection()

    def OnRightClickListctrl(self, event):
        """
        Edits the logger and the Zeq_GUI parent object so that the selected interpretation is now marked as bad
        @param: event -> wx.ListCtrlEvent that triggered this function
        """
        i = event.GetIndex()
        fit,spec = self.fit_list[i][0],self.fit_list[i][1]
        if fit in self.parent.bad_fits:
            if not self.parent.mark_fit_good(fit,spec=spec): return
            if i == self.current_fit_index:
                self.logger.SetItemBackgroundColour(i,"LIGHT BLUE")
            else:
                self.logger.SetItemBackgroundColour(i,"WHITE")
        else:
            if not self.parent.mark_fit_bad(fit): return
            if i == self.current_fit_index:
                self.logger.SetItemBackgroundColour(i,"red")
            else:
                self.logger.SetItemBackgroundColour(i,"red")
        self.parent.calculate_high_levels_data()
        self.parent.plot_high_levels_data()
        self.logger_focus(i)

    ##################################Search Bar Functions###############################

    def on_enter_search_bar(self,event):
        self.search_query = self.search_bar.GetValue().replace(" ","").lower()
        self.update_editor()

#    def on_complete_search_bar(self,event):
#        self.search_bar.AutoComplete(self.search_choices)

    ###################################ComboBox Functions################################

    def update_bounds_boxes(self,B_list):
        self.tmin_box.SetItems(B_list)
        self.tmax_box.SetItems(B_list)

    def add_new_color(self,event):
        new_color = self.color_box.GetValue()
        if ':' in new_color:
            color_list = new_color.split(':')
            color_name = color_list[0]
            if len(color_list[1])==7 and color_list[1].startswith('#'):
                for c in color_list[1][1:]:
                    if ord(c) < 48 or ord(c) > 70:
                        self.parent.user_warning('invalid hex color must be of form #0F0F0F');return
                color_val = color_list[1]
            elif '(' in color_list[1] and ')' in color_list[1]:
                color_val = list(map(eval, tuple(color_list[1].strip('( )').split(','))))
                for val in color_val:
                    if val > 1 or val < 0: self.parent.user_warning("invalid RGB sequence"); return
            else: self.parent.user_warning("colors must be given as a valid hex color or rgb tuple"); return
        else:
            self.parent.user_warning("New colors must be passed in as $colorname:$colorval where $colorval is a valid hex color or rgb tuple"); return
        self.color_dict[color_name] = color_val
        #clear old box
        self.color_box.Clear()
        #update fit box
        self.color_box.SetItems([''] + sorted(self.color_dict.keys()))

    def on_select_coordinates(self,event):
        self.parent.coordinates_box.SetStringSelection(self.coordinates_box.GetStringSelection())
        self.parent.onSelect_coordinates(event)

    def on_select_show_box(self,event):
        """
        Changes the type of mean shown on the high levels mean plot so that single dots represent one of whatever the value of this box is.
        @param: event -> the wx.COMBOBOXEVENT that triggered this function
        """
        self.parent.UPPER_LEVEL_SHOW=self.show_box.GetValue()
        self.parent.calculate_high_levels_data()
        self.parent.plot_high_levels_data()


    def on_select_high_level(self,event,called_by_parent=False):
        """
        alters the possible entries in level_names combobox to give the user selections for which specimen interpretations to display in the logger
        @param: event -> the wx.COMBOBOXEVENT that triggered this function
        """
        UPPER_LEVEL=self.level_box.GetValue()

        if UPPER_LEVEL=='sample':
            self.level_names.SetItems(self.parent.samples)
            self.level_names.SetStringSelection(self.parent.Data_hierarchy['sample_of_specimen'][self.parent.s])

        if UPPER_LEVEL=='site':
            self.level_names.SetItems(self.parent.sites)
            self.level_names.SetStringSelection(self.parent.Data_hierarchy['site_of_specimen'][self.parent.s])

        if UPPER_LEVEL=='location':
            self.level_names.SetItems(self.parent.locations)
            self.level_names.SetStringSelection(self.parent.Data_hierarchy['location_of_specimen'][self.parent.s])

        if UPPER_LEVEL=='study':
            self.level_names.SetItems(['this study'])
            self.level_names.SetStringSelection('this study')

        if not called_by_parent:
            self.parent.level_box.SetStringSelection(UPPER_LEVEL)
            self.parent.onSelect_high_level(event,True)

        self.on_select_level_name(event)

    def on_select_level_name(self,event,called_by_parent=False):
        """
        change this objects specimens_list to control which specimen interpretatoins are displayed in this objects logger
        @param: event -> the wx.ComboBoxEvent that triggered this function
        """
        high_level_name=str(self.level_names.GetValue())

        if self.level_box.GetValue()=='sample':
            self.specimens_list=self.parent.Data_hierarchy['samples'][high_level_name]['specimens']
        elif self.level_box.GetValue()=='site':
            self.specimens_list=self.parent.Data_hierarchy['sites'][high_level_name]['specimens']
        elif self.level_box.GetValue()=='location':
            self.specimens_list=self.parent.Data_hierarchy['locations'][high_level_name]['specimens']
        elif self.level_box.GetValue()=='study':
            self.specimens_list=self.parent.Data_hierarchy['study']['this study']['specimens']

        if not called_by_parent:
            self.parent.level_names.SetStringSelection(high_level_name)
            self.parent.onSelect_level_name(event,True)

        self.specimens_list.sort(key=spec_key_func)
        self.update_editor()

    def on_select_mean_type_box(self, event):
        """
        set parent Zeq_GUI to reflect change in this box and change the
        @param: event -> the wx.ComboBoxEvent that triggered this function
        """
        new_mean_type = self.mean_type_box.GetValue()
        if new_mean_type == "None":
            self.parent.clear_high_level_pars()
        self.parent.mean_type_box.SetStringSelection(new_mean_type)
        self.parent.onSelect_mean_type_box(event)

    def on_select_mean_fit_box(self, event):
        """
        set parent Zeq_GUI to reflect the change in this box then replot the high level means plot
        @param: event -> the wx.COMBOBOXEVENT that triggered this function
        """
        new_mean_fit = self.mean_fit_box.GetValue()
        self.parent.mean_fit_box.SetStringSelection(new_mean_fit)
        self.parent.onSelect_mean_fit_box(event)

    ###################################Button Functions##################################

    def on_select_stats_button(self,event):
        """

        """
        i = self.switch_stats_button.GetValue()
        self.parent.switch_stats_button.SetValue(i)
        self.parent.update_high_level_stats()

    def add_highlighted_fits(self, evnet):
        """
        adds a new interpretation to each specimen highlighted in logger if multiple interpretations are highlighted of the same specimen only one new interpretation is added
        @param: event -> the wx.ButtonEvent that triggered this function
        """

        specimens = []
        next_i = self.logger.GetNextSelected(-1)
        if next_i == -1: return
        while next_i != -1:
            fit,specimen = self.fit_list[next_i]
            if specimen in specimens:
                next_i = self.logger.GetNextSelected(next_i)
                continue
            else: specimens.append(specimen)
            next_i = self.logger.GetNextSelected(next_i)

        for specimen in specimens:
            self.add_fit_to_specimen(specimen)

        self.update_editor()
        self.parent.update_selection()

    def add_fit_to_all(self,event):
        for specimen in self.parent.specimens:
            self.add_fit_to_specimen(specimen)

        self.update_editor()
        self.parent.update_selection()

    def add_fit_to_specimen(self,specimen):
        if specimen not in self.parent.pmag_results_data['specimens']:
            self.parent.pmag_results_data['specimens'][specimen] = []

        new_name = self.name_box.GetLineText(0)
        new_color = self.color_box.GetValue()
        new_tmin = self.tmin_box.GetValue()
        new_tmax = self.tmax_box.GetValue()

        if not new_name:
            next_fit = str(len(self.parent.pmag_results_data['specimens'][specimen]) + 1)
            while ("Fit " + next_fit) in [x.name for x in self.parent.pmag_results_data['specimens'][specimen]]:
                next_fit = str(int(next_fit) + 1)
            new_name = ("Fit " + next_fit)
        if not new_color:
            next_fit = str(len(self.parent.pmag_results_data['specimens'][specimen]) + 1)
            new_color = self.parent.colors[(int(next_fit)-1) % len(self.parent.colors)]
        else: new_color = self.color_dict[new_color]
        if not new_tmin: new_tmin = None
        if not new_tmax: new_tmax = None

        if new_name in [x.name for x in self.parent.pmag_results_data['specimens'][specimen]]:
            print(('-E- interpretation called ' + new_name + ' already exsists for specimen ' + specimen))
            return

        self.parent.add_fit(specimen, new_name, new_tmin, new_tmax, color=new_color,suppress_warnings=True)

    def delete_highlighted_fits(self, event):
        """
        iterates through all highlighted fits in the logger of this object and removes them from the logger and the Zeq_GUI parent object
        @param: event -> the wx.ButtonEvent that triggered this function
        """

        next_i = -1
        deleted_items = []
        while True:
            next_i = self.logger.GetNextSelected(next_i)
            if next_i == -1:
                break
            deleted_items.append(next_i)
        deleted_items.sort(reverse=True)
        for item in deleted_items:
            self.delete_entry(index=item)
        self.parent.update_selection()

    def delete_entry(self, fit = None, index = None):
        """
        deletes the single item from the logger of this object that corrisponds to either the passed in fit or index. Note this function mutaits the logger of this object if deleting more than one entry be sure to pass items to delete in from highest index to lowest or else odd things can happen.
        @param: fit -> Fit object to delete from this objects logger
        @param: index -> integer index of the entry to delete from this objects logger
        """
        if type(index) == int and not fit:
            fit,specimen = self.fit_list[index]
        if fit and type(index) == int:
            for i, (f,s) in enumerate(self.fit_list):
                if fit == f:
                    index,specimen = i,s
                    break

        if index == self.current_fit_index: self.current_fit_index = None
        if fit not in self.parent.pmag_results_data['specimens'][specimen]:
            print(("cannot remove item (entry #: " + str(index) + ") as it doesn't exist, this is a dumb bug contact devs"))
            self.logger.DeleteItem(index)
            return
        self.parent.pmag_results_data['specimens'][specimen].remove(fit)
        del self.fit_list[index]
        self.logger.DeleteItem(index)

    def apply_changes(self, event):
        """
        applies the changes in the various attribute boxes of this object to all highlighted fit objects in the logger, these changes are reflected both in this object and in the Zeq_GUI parent object.
        @param: event -> the wx.ButtonEvent that triggered this function
        """

        new_name = self.name_box.GetLineText(0)
        new_color = self.color_box.GetValue()
        new_tmin = self.tmin_box.GetValue()
        new_tmax = self.tmax_box.GetValue()

        next_i = -1
        changed_i = []
        while True:
            next_i = self.logger.GetNextSelected(next_i)
            if next_i == -1:
                break
            specimen = self.fit_list[next_i][1]
            fit = self.fit_list[next_i][0]
            if new_name:
                if new_name not in [x.name for x in self.parent.pmag_results_data['specimens'][specimen]]: fit.name = new_name
            if new_color:
                fit.color = self.color_dict[new_color]
            #testing
            not_both = True
            if new_tmin and new_tmax:
                if fit == self.parent.current_fit:
                    self.parent.tmin_box.SetStringSelection(new_tmin)
                    self.parent.tmax_box.SetStringSelection(new_tmax)
                fit.put(specimen,self.parent.COORDINATE_SYSTEM, self.parent.get_PCA_parameters(specimen,fit,new_tmin,new_tmax,self.parent.COORDINATE_SYSTEM,fit.PCA_type))
                not_both = False
            if new_tmin and not_both:
                if fit == self.parent.current_fit:
                    self.parent.tmin_box.SetStringSelection(new_tmin)
                fit.put(specimen,self.parent.COORDINATE_SYSTEM, self.parent.get_PCA_parameters(specimen,fit,new_tmin,fit.tmax,self.parent.COORDINATE_SYSTEM,fit.PCA_type))
            if new_tmax and not_both:
                if fit == self.parent.current_fit:
                    self.parent.tmax_box.SetStringSelection(new_tmax)
                fit.put(specimen,self.parent.COORDINATE_SYSTEM, self.parent.get_PCA_parameters(specimen,fit,fit.tmin,new_tmax,self.parent.COORDINATE_SYSTEM,fit.PCA_type))
            changed_i.append(next_i)

        offset = 0
        for i in changed_i:
            i -= offset
            v = self.update_logger_entry(i)
            if v == "s":
                offset += 1

        self.parent.update_selection()

    ###################################Canvas Functions##################################

    def scatter(self,*args,**kwargs):
#        args_corrected = self.eqarea.transAxes.transform(vstack(args).T)
#        x,y = args_corrected.T
        return self.eqarea.scatter(*args,**kwargs)

    def plot(self,*args,**kwargs):
#        args_corrected = self.eqarea.transAxes.transform(vstack(args).T)
#        x,y = args_corrected.T
        return self.eqarea.plot(*args,**kwargs)

    def write(self,text):
        return self.eqarea.text(-1.2,1.15,text,{'family':self.font_type, 'fontsize':10*self.GUI_RESOLUTION, 'style':'normal','va':'center', 'ha':'left' })

    def draw_net(self):
        draw_net(self.eqarea)

    def draw(self):
        self.toolbar.home()
        self.eqarea.set_xlim(-1., 1.)
        self.eqarea.set_ylim(-1., 1.)
        self.eqarea.axes.set_aspect('equal')
        self.eqarea.axis('off')
        self.canvas.draw()

    def pan_zoom_high_equalarea(self,event):
        """
        Uses the toolbar for the canvas to change the function from zoom to pan or pan to zoom
        @param: event -> the wx.MouseEvent that triggered this funciton
        """
        if event.LeftIsDown() or event.ButtonDClick():
            return
        elif self.high_EA_setting == "Zoom":
            self.high_EA_setting = "Pan"
            try: self.toolbar.pan('off')
            except TypeError: pass
        elif self.high_EA_setting == "Pan":
            self.high_EA_setting = "Zoom"
            try: self.toolbar.zoom()
            except TypeError: pass
        else:
            self.high_EA_setting = "Zoom"
            try: self.toolbar.zoom()
            except TypeError: pass

    def home_high_equalarea(self,event):
        """
        returns high equal area to it's original position
        @param: event -> the wx.MouseEvent that triggered the call of this function
        @alters: toolbar setting
        """
        self.toolbar.home()

    def on_change_high_mouse_cursor(self,event):
        """
        If mouse is over data point making it selectable change the shape of the cursor
        @param: event -> the wx Mouseevent for that click
        """
        if self.show_box.GetValue() != "specimens": return
        if not self.parent.high_EA_xdata or not self.parent.high_EA_ydata: return
        pos=event.GetPosition()
        width, height = self.canvas.get_width_height()
        pos[1] = height - pos[1]
        xpick_data,ypick_data = pos
        xdata_org = self.parent.high_EA_xdata
        ydata_org = self.parent.high_EA_ydata
        data_corrected = self.eqarea.transData.transform(vstack([xdata_org,ydata_org]).T)
        xdata,ydata = data_corrected.T
        xdata = list(map(float,xdata))
        ydata = list(map(float,ydata))
        e = 4e0

        if self.high_EA_setting == "Zoom":
            self.canvas.SetCursor(wx.Cursor(wx.CURSOR_CROSS))
        else:
            self.canvas.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
        for i,(x,y) in enumerate(zip(xdata,ydata)):
            if 0 < sqrt((x-xpick_data)**2. + (y-ypick_data)**2.) < e:
                self.canvas.SetCursor(wx.Cursor(wx.CURSOR_HAND))
                break
        event.Skip()

    def on_equalarea_high_select(self,event):
        self.parent.on_equalarea_high_select(event,fig = self.eqarea, canvas = self.canvas)

    ###############################Menu Functions######################################

    def on_menu_help(self,event):
        """
        Toggles the GUI's help mode which allows user to click on any part of the dialog and get help
        @param: event -> wx.MenuEvent that triggers this function
        """
        self.helper.BeginContextHelp(None)

    ###############################Window Functions######################################

    def on_close_edit_window(self, event):
        """
        the function that is triggered on the close of the interpretation editor window
        @param: event -> wx.WindowEvent that triggered this function
        """

        self.parent.ie_open = False
        self.Destroy()
Пример #17
0
class PanelSpec(wx.Panel):
    def __init__(self, parent, parentMainFrame):
        wx.Panel.__init__(self, parent)
        self.CreatePanel()
        self.setSpLabel()
        self.parent = parentMainFrame
        self.FFT_Max_X = 5995
        self.FFT_Min_X = 70
        self.FFT_Max_Y = 60
        self.FFT_Min_Y = -120

    def CreatePanel(self):
        self.Figure = matplotlib.figure.Figure()
        self.axes = self.Figure.add_axes([0.05, 0.05, 0.93, 0.93])
        self.FigureCanvas = FigureCanvas(self, -1, self.Figure)
        self.ButtonAutoY = wx.Button(self, -1, label="AutoScaleY")
        self.ButtonAutoX = wx.Button(self, -1, label="AutoScaleX")
        self.Max_Y = wx.TextCtrl(self,
                                 -1,
                                 '60',
                                 size=(60, 20),
                                 style=wx.TE_PROCESS_ENTER)
        self.Min_Y = wx.TextCtrl(self,
                                 -1,
                                 '-120',
                                 size=(60, 20),
                                 style=wx.TE_PROCESS_ENTER)
        self.Min_X = wx.TextCtrl(self,
                                 -1,
                                 '70',
                                 size=(60, 20),
                                 style=wx.TE_PROCESS_ENTER)
        self.Max_X = wx.TextCtrl(self,
                                 -1,
                                 '5995',
                                 size=(60, 20),
                                 style=wx.TE_PROCESS_ENTER)
        sizer = wx.GridBagSizer(5, 5)

        sizer.Add(self.ButtonAutoX, pos=(0, 1), flag=wx.TOP, border=5)
        sizer.Add(self.ButtonAutoY, pos=(0, 2), flag=wx.TOP, border=5)
        sizer.Add(self.Max_Y, pos=(1, 0), flag=wx.ALL, border=5)
        sizer.Add(self.Min_Y, pos=(17, 0), flag=wx.ALL, border=5)
        sizer.Add(self.FigureCanvas, pos=(1, 1), span=(18, 14), flag=wx.EXPAND)
        sizer.Add(self.Min_X, pos=(19, 1), flag=wx.RIGHT | wx.BOTTOM, border=5)
        sizer.Add(self.Max_X, pos=(19, 14), flag=wx.BOTTOM, border=5)

        sizer.AddGrowableCol(10)
        sizer.AddGrowableRow(10)
        self.SetSizer(sizer)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnEnterMin_X, self.Min_X)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnEnterMax_X, self.Max_X)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnEnterMax_Y, self.Max_Y)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnEnterMin_Y, self.Min_Y)
        self.Bind(wx.EVT_BUTTON, self.OnAutoX, self.ButtonAutoX)
        self.Bind(wx.EVT_BUTTON, self.OnAutoY, self.ButtonAutoY)

        self.popupmenu = wx.Menu()
        StringList = ["Add Marker", "Remove Marker", "All Marker Off"]
        for text in StringList:
            item = self.popupmenu.Append(-1, text)
            self.FigureCanvas.Bind(wx.EVT_CONTEXT_MENU, self.OnShowPopup)
            self.FigureCanvas.Bind(wx.EVT_MENU, self.OnPopupItemSelected, item)
        '''
        Array=linspace(70, 5995,238)
        self.xDataList=[]
        self.LineSpec=[]
        self.LineSpecBack=[]
        for i in xrange(237):
            xData=linspace(Array[i],Array[i+1],1024)
            self.xDataList.append(xData)
        
        ydata=[0]*1024
        for xData in self.xDataList:
            lineSpec,=self.axes.plot(xData,ydata,'y')
            lineSpecBack,=self.axes.plot(xData,ydata,'r')
            self.LineSpec.append(lineSpec)
            self.LineSpecBack.append(lineSpecBack)
        '''
        self.xData = linspace(70, 6470, 1024)
        self.yData = [0] * 1024
        self.lineSpec, = self.axes.plot(self.xData, self.yData, 'y')
        self.lineSpecBack, = self.axes.plot(self.xData, self.yData, 'r')
        ####Marker############
        self.drs = []

    def OnAutoX(self, event):
        self.setSpLabel(begin_X=self.parent.FreqMin,end_X=self.parent.FreqMax , \
            begin_Y=self.FFT_Min_Y,end_Y=self.FFT_Max_Y)
        self.FigureCanvas.draw()
        self.FFT_Min_X = self.parent.FreqMin
        self.FFT_Max_X = self.parent.FreqMax
        self.Min_X.SetValue(str(self.FFT_Min_X))
        self.Max_X.SetValue(str(self.FFT_Max_X))

    def OnAutoY(self, event):
        self.setSpLabel(begin_X=self.FFT_Min_X, end_X=self.FFT_Max_X)
        self.FigureCanvas.draw()
        self.FFT_Min_Y = -120
        self.FFT_Max_Y = 60
        self.Min_Y.SetValue("-120")
        self.Max_Y.SetValue("60")

    def OnEnterMin_X(self, event):
        self.FFT_Min_X = int(self.Min_X.GetValue())
        self.setSpLabel(self.FFT_Min_X, self.FFT_Max_X, self.FFT_Min_Y,
                        self.FFT_Max_Y)
        self.FigureCanvas.draw()

    def OnEnterMax_X(self, event):
        self.FFT_Max_X = int(self.Max_X.GetValue())
        self.setSpLabel(self.FFT_Min_X, self.FFT_Max_X, self.FFT_Min_Y,
                        self.FFT_Max_Y)
        self.FigureCanvas.draw()

    def OnEnterMin_Y(self, event):
        self.FFT_Min_Y = int(self.Min_Y.GetValue())
        self.setSpLabel(self.FFT_Min_X, self.FFT_Max_X, self.FFT_Min_Y,
                        self.FFT_Max_Y)
        self.FigureCanvas.draw()

    def OnEnterMax_Y(self, event):
        self.FFT_Max_Y = int(self.Max_Y.GetValue())
        self.setSpLabel(self.FFT_Min_X, self.FFT_Max_X, self.FFT_Min_Y,
                        self.FFT_Max_Y)
        self.FigureCanvas.draw()

    def OnShowPopup(self, event):
        pos = event.GetPosition()
        pos = self.FigureCanvas.ScreenToClient(pos)
        self.FigureCanvas.PopupMenu(self.popupmenu, pos)

    def OnPopupItemSelected(self, event):
        item = self.popupmenu.FindItemById(event.GetId())
        text = item.GetText()
        if (text == "Add Marker"):
            self.OnAddMarker()
        elif (text == "Remove Marker"):
            self.OnRemove()
        elif (text == "All Marker Off"):
            self.OnAllRemove()

    def DrawMarker(self, Max_X, Max_Y):
        distance = ((self.FFT_Max_X - self.FFT_Min_X) / 10)**2
        index = len(self.drs) + 1
        rect, = self.axes.plot(Max_X, Max_Y, 'rd', markersize=10)
        text = self.axes.text(Max_X + 5,
                              Max_Y + 2,
                              'M' + str(index),
                              color='r')
        textM=self.axes.text(self.FFT_Min_X+5,self.FFT_Max_Y-5*(index),'M'+str(index)+':'  \
            +'%.2f'%(Max_X)+'MHz  '+'%.2f'%(Max_Y)+'dBm')
#         DragRect=DraggableRectangle(rect,text,textM,self.LineSpec,self.FigureCanvas)
#         DragRect.setM_id('M'+str(index)+':')
#
#         DragRect.setRadius(distance)
#         DragRect.connect()
#         self.drs.append(DragRect)
#self.FigureCanvas.draw()

    def OnAddMarker(self):
        if (len(self.drs) < 4):
            startSection = (self.FFT_Min_X - 70) / 25
            endSection = (self.FFT_Max_X - 70) / 25
            lenStart = len(self.LineSpec[startSection].get_ydata())
            lenEnd = len(self.LineSpec[endSection].get_ydata())
            indexStart = int(
                (self.FFT_Min_X - (startSection * 25 + 70)) * lenStart / 25.0)
            indexEnd = int(
                (self.FFT_Max_X - (endSection * 25 + 70)) * lenEnd / 25.0)
            MaxList = []
            MaxList.append(
                max(
                    list(self.LineSpec[startSection].get_ydata())
                    [indexStart:lenStart]))
            for i in range(startSection + 1, endSection, 1):
                MaxList.append(max(list(self.LineSpec[i].get_ydata())))
            if (indexEnd != 0):
                MaxList.append(
                    max(
                        list(self.LineSpec[endSection].get_ydata())
                        [0:indexEnd]))

            Max_Y = max(MaxList)
            Max_Y_Index = MaxList.index(Max_Y) + startSection
            y = self.LineSpec[Max_Y_Index].get_ydata()
            Max_X_Index = list(y).index(Max_Y)
            Max_X = 70 + Max_Y_Index * 25 + Max_X_Index * 25.0 / len(y)
            self.DrawMarker(Max_X, Max_Y)

    def OnRemove(self):

        if (len(self.axes.texts)):
            self.axes.lines.pop()
            self.axes.texts.pop()
            self.axes.texts.pop()
            self.drs.pop()
            #self.FigureCanvas.draw()

    def OnAllRemove(self):

        while (len(self.axes.texts)):
            self.axes.lines.pop()
            self.axes.texts.pop()
            self.axes.texts.pop()
            self.drs.pop()
        #self.FigureCanvas.draw()

    def setSpLabel(self, begin_X=70, end_X=5995, begin_Y=-120, end_Y=60):
        self.ylabel('dBm')
        self.xlabel('MHz')
        self.ylim(begin_Y, end_Y)
        self.xlim(begin_X, end_X)
        yticks = linspace(begin_Y, end_Y, 11)  ##11个数总共###
        yticklabels = [str(int(i)) for i in yticks]
        xticks = linspace(begin_X, end_X, 11)

        xticklabels = [str(int(i)) for i in xticks]
        self.axes.set_xticks(xticks)
        self.axes.set_xticklabels(xticklabels, rotation=0)
        self.axes.set_yticks(yticks)
        self.axes.set_yticklabels(yticklabels, rotation=0)
        self.axes.grid(True)
        #self.FigureCanvas.draw()

    def PowerSpectrum(self, funcPara, y):

        if (funcPara == 0x51 or funcPara == 0x56):

            self.lineSpec.set_ydata(array(y))
            '''
            for i in range(len(self.drs)):
                self.drs[i].yData=self.LineSpec 
                self.DrawAfterRelease()
                '''
        elif (funcPara == 0x52 or funcPara == 0x57):

            self.lineSpecBack.set_ydata(array(y))
        self.FigureCanvas.draw()

    def DrawAfterRelease(self):

        for i in range(len(self.drs)):
            xData = self.drs[i].rect.get_xdata()

            index = (int(xData) - 70) / 25
            Section = index * 25 + 70
            y = self.LineSpec[index].get_ydata()

            index_Y = (xData - Section) * len(y) / 25.0
            Marker_Y = list(y)[int(index_Y)]
            self.drs[i].rect.set_ydata(Marker_Y)
            self.drs[i].textMarker.set_position((xData, Marker_Y + 2))
            self.drs[i].textM.set_text(self.drs[i].M_index+'%.2f'%(xData)+ \
                'MHz  '+'%.2f'%(Marker_Y)+'dBm')

    def xlim(self, x_min, x_max):
        self.axes.set_xlim(x_min, x_max)

    def ylim(self, y_min, y_max):
        self.axes.set_ylim(y_min, y_max)

    def xlabel(self, XabelString="X"):
        self.axes.set_xlabel(XabelString)

    def ylabel(self, YabelString="Y"):
        self.axes.set_ylabel(YabelString)
Пример #18
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 MyFrame(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self,parent, id, 'scrollable plot',
                style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER,
                size=(800, 400))
        self.panel = wx.Panel(self, -1)

        self.fig = Figure((5, 4), 75)
        self.canvas = FigureCanvasWxAgg(self.panel, -1, self.fig)
        self.scroll_range = 400
        self.canvas.SetScrollbar(wx.HORIZONTAL, 0, 5, 
                                 self.scroll_range)
        
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, -1, wx.EXPAND)

        self.panel.SetSizer(sizer)
        self.panel.Fit()

        self.init_data()
        self.init_plot()

        self.canvas.Bind(wx.EVT_SCROLLWIN, self.OnScrollEvt)

    def init_data(self):
        
        # Generate some data to plot:
        self.dt = 0.01
        self.t = arange(0,5,self.dt)
        self.x = sin(2*pi*self.t)

        # Extents of data sequence: 
        self.i_min = 0
        self.i_max = len(self.t)

        # Size of plot window:       
        self.i_window = 100

        # Indices of data interval to be plotted:
        self.i_start = 0
        self.i_end = self.i_start + self.i_window

    def init_plot(self):
        self.axes = self.fig.add_subplot(111)
        self.plot_data = \
                  self.axes.plot(self.t[self.i_start:self.i_end],
                                 self.x[self.i_start:self.i_end])[0]

    def draw_plot(self):

        # Update data in plot:
        self.plot_data.set_xdata(self.t[self.i_start:self.i_end])
        self.plot_data.set_ydata(self.x[self.i_start:self.i_end])

        # Adjust plot limits:
        self.axes.set_xlim((min(self.t[self.i_start:self.i_end]),
                           max(self.t[self.i_start:self.i_end])))
        self.axes.set_ylim((min(self.x[self.i_start:self.i_end]),
                            max(self.x[self.i_start:self.i_end])))

        # Redraw:                  
        self.canvas.draw()

    def OnScrollEvt(self, event):

	# Update the indices of the plot:
        self.i_start = self.i_min + event.GetPosition()
        self.i_end = self.i_min + self.i_window + event.GetPosition()
        self.draw_plot()
Пример #20
0
class main_gui(wx.Frame):
    '''Setting up the placement and '''
    def __init__(self, parent, file_path):
        if args.debug: print('main_gui.__init__')
        self.args = args
        self.initialize_controls(parent)
        self.box_sizer.Add(self.panel1, 0, wx.EXPAND)

        ## Initialize GUI plot
        self.figure = Figure()
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.box_sizer.Add(self.canvas, 1, wx.EXPAND)

        ## Default rectangle variable
        self.pressed = False

        ## Initialize bottom text bar
        self.box_sizer.Add(self.status_bar, 0, border=0, flag=0)
        self.status_bar.SetStatusText('Ready', 0)
        rect = self.status_bar.GetFieldRect(0)

        ## Set up names
        self.video_file = file_path

        ## Create a dialog box at the beginning if the video path is not a real file
        if self.args.video_file == None:
            openFileDialog = wx.FileDialog(self, "Open Video file", "", "",
                                           "Video files (*.*)|*.*",
                                           wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)

            ## Closing program if Browse box is closed
            if openFileDialog.ShowModal() == wx.ID_CANCEL:
                print(
                    '\nExiting Program. Must select a video from box or enter path into command line\n'
                )
                raise SystemExit

            ## Setting video name from dialog box selection
            self.video_file = openFileDialog.GetPath()

        ## Passing individual inputs from GUI to a list
        self.update_names()
        self.input_names = [
            'x', 'y', 'w', 'h', 'check_frame', 'blank_0', 'blank_n', 'crop_0',
            'crop_n', 'threshold', 'diameter', 'minmass', 'maxsize', 'ecc_low',
            'ecc_high', 'vials', 'window', 'pixel_to_cm', 'frame_rate',
            'vial_id_vars', 'outlier_TB', 'outlier_LR', 'naming_convention',
            'path_project', 'file_suffix', 'convert_to_cm_sec', 'trim_outliers'
        ]
        self.parameter_names = [
            'self.input_' + item for item in self.input_names
        ]
        self.input_values = [  ## int
            self.input_x,
            self.input_y,
            self.input_w,
            self.input_h,
            self.input_check_frame,
            self.input_blank_0,
            self.input_blank_n,
            self.input_crop_0,
            self.input_crop_n,
            self.input_threshold,
            self.input_diameter,
            self.input_minmass,
            self.input_maxsize,
            self.input_ecc_low,
            self.input_ecc_high,
            self.input_vials,
            self.input_window,
            self.input_pixel_to_cm,
            self.input_frame_rate,
            self.input_vial_id_vars,
            self.input_outlier_TB,
            self.input_outlier_LR,
            ## str
            self.input_naming_convention,
            self.input_path_project,
            self.input_file_suffix,
            ## bool
            self.input_convert_to_cm_sec,
            self.input_checkBox_trim_outliers
        ]

        ## Enable all buttons
        button_list = [
            'browse_video', 'reload_video', 'test_parameters',
            'store_parameters'
        ]
        for button in button_list:
            exec('self.button_' + button + '.Enable(True)')

        ## Load video
        self.load_video()
        self.status_bar.SetStatusText("Ready...", 0)
        if args.debug: print('End of init')
        return

    def update_variables(self):
        '''Updates the detection variables'''
        if args.debug: print('main_gui.update_variables')
        variables = []

        ## Including integers
        for item, jtem in zip(self.input_names[:22], self.input_values[:22]):
            #             print('int',item,jtem)
            phrase = str(item + '=' + jtem.GetValue())
            if args.debug: print('    ' + phrase)
            variables.append(phrase)

        ## Including strings - type I
        for item, jtem in zip(self.input_names[22:24],
                              self.input_values[22:24]):
            #             print('str-I',item,jtem)
            phrase = str(item + '="' + jtem.GetValue() + '"')
            if args.debug: print('    ' + phrase)
            variables.append(phrase)

        ## Including strings - type II
        for item, jtem in zip(self.input_names[24:25],
                              self.input_values[24:25]):
            #             print('str-II',item,jtem)
            phrase = str(item + '="' + str(jtem) + '"')
            if args.debug: print(phrase)
            variables.append(phrase)

        ## Including booleans
        for item, jtem in zip(self.input_names[25:], self.input_values[25:]):
            #             print('bool',item,jtem)
            phrase = str(item + '=%s' % str(jtem.GetValue()))
            if args.debug: print('    ' + phrase)
            variables.append(phrase)

        return variables

    def load_video(self):
        '''Function for loading the video when the respective button is pressed'''
        if args.debug: print('main_gui.load_video')

        ## Set up
        self.status_bar.SetStatusText("Loading video", 0)
        self.figure.clear()
        self.axes = [
            self.figure.add_subplot(111),
        ]

        ## Confirm file is a path, or folder has specified suffix
        status = self.check_specified_video()
        if status:
            print("Loading:", self.video_file)
            self.update_names()
            for item in self.input_values[:4]:
                item.SetEditable(True)
                item.Enable(True)
            self.checkBox_fixed_ROI.Enable(True)
            self.input_convert_to_cm_sec.Enable(True)

            ## Busy cursor while the detector object is called and initialized
            wx.BeginBusyCursor()
            try:
                vars = self.update_variables()
                self.detector = detector(self.video_file,
                                         gui=True,
                                         variables=vars)

                self.axes[0].imshow(self.detector.image_stack[0])
                self.figure.canvas.draw()
            finally:
                wx.EndBusyCursor()

            ## Setting mechanism for drawing the ROI rectangle
            self.canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)
            self.canvas.mpl_connect('button_press_event', self.draw_rectangle)
            self.canvas.mpl_connect('button_release_event', self.on_release)
            self.canvas.mpl_connect('motion_notify_event', self.on_motion)
            self.rect = Rectangle((0, 0), 1, 1, fill=False, ec='r')
            self.axes[0].add_patch(self.rect)

            ## Auto-set GUI parameters from the video
            self.input_blank_0.SetValue('0')
            self.input_blank_n.SetValue(str(self.detector.n_frames))
            self.input_crop_0.SetValue('0')
            self.input_crop_n.SetValue(str(self.detector.n_frames))
            self.input_check_frame.SetValue('0')
            self.input_ecc_low.SetValue('0')
            self.input_ecc_high.SetValue('1')
            self.input_ecc_high.SetValue('1')
            self.input_path_project.SetValue(self.folder)
            self.input_naming_convention.SetValue(self.name)
            self.input_vial_id_vars.SetValue(
                str(len(self.input_naming_convention.GetValue().split('_'))))

            ## Display the 0th and frame corresponding with (most likely) t = 2 seconds
            try:
                self.input_frame_rate = int(self.input_frame_rate.GetValue())
            except:
                pass
            if self.detector.n_frames < self.input_frame_rate * 2:
                self.input_check_frame.SetValue(str(self.detector.n_frames))

            ## Try to make the local linear regression window size 2 seconds, but if not then 35% of the frames in the video
            if self.detector.n_frames < self.input_frame_rate * 2:
                self.input_window.SetValue(
                    str(int(len(self.detector.image_stack) * .35)))
            else:
                self.input_window.SetValue(str(int(self.input_frame_rate) * 2))

            ## Enable Test parameter button if disabled from prior testing
            self.button_test_parameters.Enable(True)
            self.x0, self.y0 = 0, 0
            self.x1, self.y1 = self.detector.width, self.detector.height

            ## Display the first frame of the video in the GUI
            self.update_ROIdisp()
            self.canvas.draw()
        else:
            return

    def update_names(self):
        '''Updates the names of variables within the program. Generally variables set for naming files.'''
        if args.debug: print('main_gui.update_names')
        self.status_bar.SetStatusText("Updating file names...", 0)
        self.text_video_path.SetLabelText(self.video_file)
        self.folder, self.name = os.path.split(self.video_file)
        self.name, self.input_file_suffix = self.name.split('.')

        ## Naming files to be generated
        self.name_noext = os.path.join(self.folder, self.name)
        self.path_data = self.name_noext + '.raw.csv'
        self.path_filter = self.name_noext + '.filter.csv'
        self.path_plot = self.name_noext + '.diag.png'
        self.path_slope = self.name_noext + '.slopes.csv'
        if args.debug: print('name:', self.name_noext, "+ file suffixes")

        ## Set path_project default to the folder of the selected video file
        if self.input_path_project == '': self.input_path_project = self.folder
        return

    def check_specified_video(self):
        if args.debug: print('main_gui.check_specified_video')
        self.status_bar.SetStatusText("Checking specified video...", 0)

        ## Check file path and update names
        if os.path.isfile(self.video_file):
            self.button_reload_video.Enable(True)
            self.button_test_parameters.Enable(True)
            self.update_names()
            self.input_file_suffix = '.' + self.video_file.split(
                '/')[-1].split('.')[-1]
            return True

        else:
            self.video_file = "No or invalid file entered. Please change the file path"
            self.button_browse_video.Enable(True)
            return False

    ## Commands for drawing the ROI rectangle
    def ChangeCursor(self, event):
        '''Change cursor into crosshair type when enter the plot area'''
        self.canvas.SetCursor(wx.Cursor(wx.CURSOR_CROSS))
        return

    def draw_rectangle(self, event):
        '''Draw ROI rectangle'''
        self.status_bar.SetStatusText(
            "Draw rectangle from upper-left to lower-right", 0)
        self.pressed = True
        if self.checkBox_fixed_ROI.Enabled:
            try:
                self.x0 = int(event.xdata)
                self.y0 = int(event.ydata)

                ## If the fixed_ROI box is checked, handle values differently
                if self.checkBox_fixed_ROI.GetValue():
                    self.x1 = self.x0 + int(eval(self.input_w.GetValue()))
                    self.y1 = self.y0 + int(eval(self.input_h.GetValue()))
                    self.rect.set_width(self.x1 - self.x0)
                    self.rect.set_height(self.y1 - self.y0)
                    self.rect.set_xy((self.x0, self.y0))
                    self.canvas.draw()

                ## Set the values in the GUI and program to drawn rectangle
                self.input_x.SetValue(str(self.x0))
                self.input_y.SetValue(str(self.y0))
                self.input_h.SetValue(str(self.rect.get_height()))
                self.input_w.SetValue(str(self.rect.get_width()))
            except:
                pass
        return

    def on_release(self, event):
        '''When mouse is on plot and button is released, redraw ROI rectangle, update ROI values'''
        self.status_bar.SetStatusText("Specify the detector parameters...", 0)
        self.pressed = False
        if self.checkBox_fixed_ROI.Enabled:
            if self.checkBox_fixed_ROI.GetValue():
                pass
            else:
                self.redraw_rect(event)
            self.update_ROIdisp()
        return

    def on_motion(self, event):
        '''If the mouse is on plot and if the mouse button is pressed, redraw ROI rectangle'''
        if self.pressed & self.checkBox_fixed_ROI.Enabled & (
                not self.checkBox_fixed_ROI.GetValue()):
            # Redraw the rectangle
            self.redraw_rect(event)
            self.update_ROIdisp()
        return

    def redraw_rect(self, event):
        '''Draw the ROI rectangle overlay'''
        try:
            x1 = int(event.xdata)
            y1 = int(event.ydata)
            if any([self.x1 != x1, self.y1 != y1]):
                self.x1 = x1
                self.y1 = y1
                self.rect.set_xy((self.x0, self.y0))
                self.rect.set_width(self.x1 - self.x0)
                self.rect.set_height(self.y1 - self.y0)

                self.canvas.draw()
            else:
                pass
        except:
            pass
        return

    def update_ROIdisp(self):
        '''Updates the ROI coordinates as the rectangle is drawn.'''
        self.input_x.SetValue(str(self.x0))
        self.input_y.SetValue(str(self.y0))
        self.input_h.SetValue(str(int(self.y1) - int(self.y0)))
        self.input_w.SetValue(str(int(self.x1) - int(self.x0)))
        return

    def OnButton_testParButton(self, event):
        '''Tests the entered parameters when the `Test parameters` button is pressed'''
        if args.debug: print('main_gui.OnButton_testParButton')
        self.status_bar.SetStatusText("Testing parameters...", 0)

        #Prep the parameters
        variables = self.update_variables()
        self.checkBox_fixed_ROI.Enable(False)

        ## Set up figure for plots
        self.figure.clear()
        self.axes = [
            self.figure.add_subplot(231),
            self.figure.add_subplot(232),
            self.figure.add_subplot(233),
            self.figure.add_subplot(234),
            self.figure.add_subplot(235),
            self.figure.add_subplot(236)
        ]

        ## Busy cursor while the main function runs
        wx.BeginBusyCursor()
        try:
            variables = variables + ['debug=' + str(args.debug)]
            self.detector.parameter_testing(variables, self.axes)
        finally:
            wx.EndBusyCursor()

        ## Renders plots in the GUI
        self.figure.tight_layout()
        self.figure.canvas.draw()

        # Enable buttons and print statements once parameter testing is complete
        self.button_reload_video.Enable(True)
        self.button_store_parameters.Enable(True)
        if args.debug: print('Parameter testing complete')
        self.status_bar.SetStatusText(
            "Refine detector parameters by reloading the video, or finish optimization by pressing 'Save configuration'",
            0)
        return

    def OnButton_strParButton(self, event):
        '''Runs the 'save_parameter' function for creating the configuration file'''
        if args.debug: print('main_gui.OnButton_strParButton')
        self.save_parameter()
        self.button_store_parameters.SetBackgroundColour(
            wx.Colour(241, 241, 241))

    def set_config_file(self):
        '''Set path for the project folder'''
        if args.debug: print('main_gui.OnButton_strParButton')
        ## Figure out where to save configuration file
        if os.path.isdir(self.input_path_project):
            if not self.input_path_project.endswith('/'):
                self.input_path_project = self.input_path_project + '/'
            self.path_parameters = self.input_path_project + self.name + '.cfg'
        else:
            self.path_parameters = self.path_noext + '.cfg'
        return self.path_parameters

    def save_parameter(self):
        if args.debug: print('main_gui.save_parameter')
        '''
        Save parameters as python list.
        New parameter sets appended to the config file.
        Each parameter sets come with a comment line, contain the datetime of analysis
        '''

        variables = self.update_variables()
        try:
            self.input_path_project = self.input_path_project.GetValue()
        except:
            pass

        self.path_parameters = self.set_config_file()

        ## Printing output to configuration file
        print('Saving parameters to:', self.path_parameters)
        with open(self.path_parameters, 'w') as f:
            print('## FreeClimber ##', file=f)
        f.close()

        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        with open(self.path_parameters, 'a') as f:
            print('## Generated from file: ' + self.video_file, file=f)
            print('##     @ ' + now, file=f)
            print('##', file=f)
            print('## Analysis parameters:', file=f)
            for item in variables:
                print(item, file=f)
        f.close()
        print("Configuration settings saved")
        return

    def OnButton_Browse(self, event):
        if args.debug: print('main_gui.OnButton_Browse')
        openFileDialog = wx.FileDialog(self, "Open Video file", "", "",
                                       "Video files (*.*)|*.*",
                                       wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
        if openFileDialog.ShowModal() == wx.ID_CANCEL:
            pass
        else:
            self.video_file = openFileDialog.GetPath()
            self.update_names()
            self.load_video()
        self.figure.clear()
        return

    def OnButton_LoadVideo(self, event):
        '''Calls function to load the video when the `reload` button is pressed'''
        if args.debug: print('main_gui.OnButton_LoadVideo')
        self.load_video()
        return

    def initialize_sizers(self):
        '''Initializes the GUI window orientation'''
        if args.debug: print('main_gui.initialize_sizers')
        # Generated method, do not edit
        self.box_sizer = wx.BoxSizer(orient=wx.VERTICAL)
        self.SetSizer(self.box_sizer)
        return

    def initialize_controls(self, prnt):
        '''Initializes the GUI controls, for which there are many'''
        if args.debug: print('main_gui.initialize_controls')
        # Generated method, do not edit
        wx.Frame.__init__(self,
                          id=wxID_text_title,
                          name='',
                          parent=prnt,
                          pos=wx.Point(100, 30),
                          size=wx.Size(950, 759),
                          style=wx.DEFAULT_FRAME_STYLE,
                          title='FreeClimber')
        self.SetClientSize(wx.Size(950, 737))

        ######
        ## Inputs for ROI Rectangle
        self.panel1 = wx.Panel(id=wxID_panel_1,
                               name='panel1',
                               parent=self,
                               pos=wx.Point(0, 0),
                               size=wx.Size(950, 231),
                               style=wx.TAB_TRAVERSAL)

        ## Step 1 boxes
        self.text_step_1a = wx.StaticText(id=wxID_text_step_1a,
                                          label=u'Step 1a: Specify a video',
                                          name='text_step_1a',
                                          parent=self.panel1,
                                          pos=wx.Point(col1, 10),
                                          size=wx.Size(box_dimensions),
                                          style=wx.ALIGN_CENTER)

        ## Browse
        self.button_browse_video = wx.Button(id=wxID_browse_video,
                                             label=u'Browse...',
                                             name=u'button_browse_video',
                                             parent=self.panel1,
                                             pos=wx.Point(col1, 30),
                                             size=wx.Size(box_dimensions),
                                             style=0)
        self.button_browse_video.Bind(wx.EVT_BUTTON,
                                      self.OnButton_Browse,
                                      id=wxID_browse_video)

        self.text_step_1b = wx.StaticText(id=wxID_text_step_1b,
                                          label=u'Step 1b: Define options',
                                          name='text_step_1b',
                                          parent=self.panel1,
                                          pos=wx.Point(col1, 65),
                                          size=wx.Size(box_dimensions),
                                          style=wx.ALIGN_CENTER)

        ## Pixel to cm
        self.text_pixel_to_cm = wx.StaticText(
            id=wxID_text_pixel_to_cm,
            label=u"Pixels / cm:",
            name='text_pixel_to_cm',
            parent=self.panel1,
            pos=wx.Point(col1, 85),
            size=wx.Size(medium_box_dimensions),
            style=0)
        self.input_pixel_to_cm = wx.TextCtrl(
            id=wxID_input_pixel_to_cm,
            name=u'input_pixel_to_cm',
            parent=self.panel1,
            pos=wx.Point(col1 + 95, 85),
            size=wx.Size(medium_box_dimensions),
            style=0,
            value=u"1")

        ## Frame Rate
        self.text_frame_rate = wx.StaticText(id=wxID_frame_rate,
                                             label=u'Frames / sec:',
                                             name='text_frame_rate',
                                             parent=self.panel1,
                                             pos=wx.Point(col1, 115),
                                             size=wx.Size(box_dimensions),
                                             style=0)
        self.input_frame_rate = wx.TextCtrl(
            id=wxID_frame_rate,
            name=u'input_frame_rate',
            parent=self.panel1,
            pos=wx.Point(col1 + 95, 115),
            size=wx.Size(medium_box_dimensions),
            style=0,
            value='25')

        ## Check box to convert final slope to cm
        self.input_convert_to_cm_sec = wx.CheckBox(
            id=wxID_input_convert_to_cm_sec,
            label=u'Convert to cm / sec',
            name=u'input_convert_to_cm_sec',
            parent=self.panel1,
            pos=wx.Point(col1, 145),
            size=wx.Size(250, 22),
            style=0)

        ## Step 2 boxes
        self.text_step_2 = wx.StaticText(id=wxID_text_step_2,
                                         label=u'Step 2: Select ROI',
                                         name='text_step_2',
                                         parent=self.panel1,
                                         pos=wx.Point(col2, 10),
                                         size=wx.Size(box_dimensions),
                                         style=wx.ALIGN_LEFT)
        ## X
        self.text_x = wx.StaticText(id=wxID_text_x,
                                    label=u'x-pos.',
                                    name='text_x',
                                    parent=self.panel1,
                                    pos=wx.Point(col2, 30),
                                    size=wx.Size(medium_box_dimensions),
                                    style=wx.ALIGN_LEFT)
        self.input_x = wx.TextCtrl(id=wxID_input_x,
                                   name=u'input_x',
                                   parent=self.panel1,
                                   style=0,
                                   value=u'0',
                                   pos=wx.Point(col2 + 55, 30),
                                   size=wx.Size(medium_box_dimensions))

        ## Y
        self.text_y = wx.StaticText(id=wxID_text_y,
                                    label=u'y-pos.',
                                    name='text_y',
                                    parent=self.panel1,
                                    pos=wx.Point(col2, 55),
                                    size=wx.Size(medium_box_dimensions),
                                    style=wx.ALIGN_LEFT)
        self.input_y = wx.TextCtrl(id=wxID_input_y,
                                   name=u'input_y',
                                   parent=self.panel1,
                                   pos=wx.Point(col2 + 55, 55),
                                   size=wx.Size(medium_box_dimensions),
                                   style=0,
                                   value=u'0')

        ## Width
        self.text_w = wx.StaticText(id=wxID_text_w,
                                    label=u'Width:',
                                    name='text_w',
                                    parent=self.panel1,
                                    pos=wx.Point(col2, 80),
                                    size=wx.Size(medium_box_dimensions),
                                    style=wx.ALIGN_LEFT)
        self.input_w = wx.TextCtrl(id=wxID_input_w,
                                   name=u'input_w',
                                   parent=self.panel1,
                                   pos=wx.Point(col2 + 55, 80),
                                   size=wx.Size(medium_box_dimensions),
                                   style=0,
                                   value=u'0')

        ## Height
        self.text_h = wx.StaticText(id=wxID_text_h,
                                    label=u'Height:',
                                    name='text_h',
                                    parent=self.panel1,
                                    pos=wx.Point(col2, 105),
                                    size=wx.Size(medium_box_dimensions),
                                    style=wx.ALIGN_LEFT)
        self.input_h = wx.TextCtrl(id=wxID_input_h,
                                   name=u'input_h',
                                   parent=self.panel1,
                                   pos=wx.Point(col2 + 55, 105),
                                   size=wx.Size(medium_box_dimensions),
                                   style=0,
                                   value=u'0')

        ## ROI rectangle stays same dimensions but can be redrawn. Not critical to keep
        self.checkBox_fixed_ROI = wx.CheckBox(id=wxID_check_box_ROI,
                                              label=u'Fixed ROI Size?',
                                              name=u'checkBox_fixed_ROI',
                                              parent=self.panel1,
                                              pos=wx.Point(col2, 145),
                                              size=wx.Size(250, 22),
                                              style=0)
        self.checkBox_fixed_ROI.SetValue(False)
        ######

        ## Detection parameters
        self.text_step_3 = wx.StaticText(
            id=wxID_text_step_3,
            label=u'Step 3: Specify spot parameters',
            name='text_step_3',
            parent=self.panel1,
            pos=wx.Point(col3, 10),
            size=wx.Size(100, 22),
            style=wx.ALIGN_LEFT)

        ## Expected spot diameter
        self.text_diameter = wx.StaticText(id=wxID_text_diameter,
                                           label=u'Diameter:',
                                           name='text_diameter',
                                           parent=self.panel1,
                                           pos=wx.Point(col3, 30),
                                           size=wx.Size(medium_box_dimensions),
                                           style=0)
        self.input_diameter = wx.TextCtrl(id=wxID_input_diameter,
                                          name=u'input_diameter',
                                          parent=self.panel1,
                                          pos=wx.Point(col3 + 100, 30),
                                          size=wx.Size(medium_box_dimensions),
                                          style=0,
                                          value=u'7')

        ## Maximum spot diameter
        self.text_maxsize = wx.StaticText(id=wxID_text_maxsize,
                                          label=u'MaxDiameter:',
                                          name='text_maxsize',
                                          parent=self.panel1,
                                          pos=wx.Point(col3, 55),
                                          size=wx.Size(medium_box_dimensions),
                                          style=0)
        self.input_maxsize = wx.TextCtrl(id=wxID_input_maxsize,
                                         name=u'input_maxsize',
                                         parent=self.panel1,
                                         pos=wx.Point(col3 + 100, 55),
                                         size=wx.Size(medium_box_dimensions),
                                         style=0,
                                         value=u'11')

        ## Minimum spot 'mass'
        self.text_minmass = wx.StaticText(id=wxID_text_minmass,
                                          label=u'MinMass:',
                                          name='text_minmass',
                                          parent=self.panel1,
                                          pos=wx.Point(col3, 80),
                                          size=wx.Size(medium_box_dimensions),
                                          style=0)
        self.input_minmass = wx.TextCtrl(id=wxID_input_minmass,
                                         name=u'input_minmass',
                                         parent=self.panel1,
                                         pos=wx.Point(col3 + 100, 80),
                                         size=wx.Size(medium_box_dimensions),
                                         style=0,
                                         value=u'100')

        ## Spot threshold
        self.text_threshold = wx.StaticText(
            id=wxID_text_threshold,
            label=u'Threshold:',
            name='text_threshold',
            parent=self.panel1,
            pos=wx.Point(col3, 105),
            size=wx.Size(medium_box_dimensions),
            style=0)
        self.input_threshold = wx.TextCtrl(id=wxID_input_threshold,
                                           name=u'input_threshold',
                                           parent=self.panel1,
                                           pos=wx.Point(col3 + 100, 105),
                                           size=wx.Size(medium_box_dimensions),
                                           style=0,
                                           value=u'"auto"')

        ## Eccentricity range
        self.text_ecc = wx.StaticText(id=wxID_text_ecc,
                                      label=u'Ecc/circularity:',
                                      name='text_ecc',
                                      parent=self.panel1,
                                      pos=wx.Point(col3, 130),
                                      size=wx.Size(medium_box_dimensions),
                                      style=0)
        self.input_ecc_low = wx.TextCtrl(id=wxID_input_ecc_low,
                                         name=u'input_ecc_low',
                                         parent=self.panel1,
                                         pos=wx.Point(col3 + 100, 130),
                                         size=wx.Size(small_box_dimensions),
                                         style=0,
                                         value=u'0')
        self.input_ecc_high = wx.TextCtrl(id=wxID_input_ecc_high,
                                          name=u'input_ecc_high',
                                          parent=self.panel1,
                                          pos=wx.Point(col3 + 140, 130),
                                          size=wx.Size(small_box_dimensions),
                                          style=0,
                                          value=u'0')

        #### Step 4 arguments
        ## Check frames
        self.text_step_4 = wx.StaticText(
            id=wxID_text_step_4,
            label=u'Step 4: Additional parameters',
            name='text_step_4',
            parent=self.panel1,
            pos=wx.Point(col4, 10),
            size=wx.Size(100, 22),
            style=wx.ALIGN_LEFT)

        ## Background frames
        self.text_background_frames = wx.StaticText(
            id=wxID_text_background_frames,
            label=u'Background frames:',
            name='text_background_frames',
            parent=self.panel1,
            pos=wx.Point(col4, 30),
            size=wx.Size(medium_box_dimensions),
            style=0)
        self.input_blank_0 = wx.TextCtrl(id=wxID_input_blank_0,
                                         name=u'input_blank_0',
                                         parent=self.panel1,
                                         pos=wx.Point(col4 + 130, 30),
                                         size=wx.Size(small_box_dimensions),
                                         style=0,
                                         value=u'0')
        self.input_blank_n = wx.TextCtrl(id=wxID_input_blank_n,
                                         name=u'input_blank_n',
                                         parent=self.panel1,
                                         pos=wx.Point(col4 + 170, 30),
                                         size=wx.Size(small_box_dimensions),
                                         style=0,
                                         value=u'0')

        ## crop frames
        self.text_crop_frames = wx.StaticText(
            id=wxID_text_crop_frames,
            label=u'Crop frames:',
            name='text_crop_frames',
            parent=self.panel1,
            pos=wx.Point(col4, 55),
            size=wx.Size(medium_box_dimensions),
            style=0)
        self.input_crop_0 = wx.TextCtrl(id=wxID_input_crop_0,
                                        name=u'input_crop_0',
                                        parent=self.panel1,
                                        pos=wx.Point(col4 + 130, 55),
                                        size=wx.Size(small_box_dimensions),
                                        style=0,
                                        value=u'0')
        self.input_crop_n = wx.TextCtrl(id=wxID_input_crop_n,
                                        name=u'input_crop_n',
                                        parent=self.panel1,
                                        pos=wx.Point(col4 + 170, 55),
                                        size=wx.Size(small_box_dimensions),
                                        style=0,
                                        value=u'0')

        ## Check frames
        self.text_check_frames = wx.StaticText(id=wxID_text_check_frames,
                                               label=u'Check frame:',
                                               name='text_check_frames',
                                               parent=self.panel1,
                                               pos=wx.Point(col4, 80),
                                               size=wx.Size(115, 17),
                                               style=0)

        self.input_check_frame = wx.TextCtrl(
            id=wxID_input_check_frame,
            name=u'input_check_frame',
            parent=self.panel1,
            pos=wx.Point(col4 + 130, 80),
            size=wx.Size(small_box_dimensions),
            style=0,
            value=u'0')

        ## Vials
        self.text_vials = wx.StaticText(id=wxID_text_vials,
                                        label=u'Number of vials:',
                                        name='text_vials',
                                        parent=self.panel1,
                                        pos=wx.Point(col4, 105),
                                        size=wx.Size(133, 22),
                                        style=0)
        self.input_vials = wx.TextCtrl(id=wxID_input_vials,
                                       name=u'input_vials',
                                       parent=self.panel1,
                                       pos=wx.Point(col4 + 130, 105),
                                       size=wx.Size(small_box_dimensions),
                                       style=0,
                                       value=u'1')

        ## Window size
        self.text_window = wx.StaticText(id=wxID_text_window,
                                         label=u'Window size:',
                                         name='text_window',
                                         parent=self.panel1,
                                         pos=wx.Point(col4, 130),
                                         size=wx.Size(133, 22),
                                         style=0)
        self.input_window = wx.TextCtrl(id=wxID_input_window,
                                        name=u'input_window',
                                        parent=self.panel1,
                                        pos=wx.Point(col4 + 130, 130),
                                        size=wx.Size(small_box_dimensions),
                                        style=0,
                                        value='1')

        ## Edge trim
        self.input_checkBox_trim_outliers = wx.CheckBox(
            id=wxID_check_box_outlier,
            label=u'Trim outliers? (TB                      LR)',
            name=u'checkBox_outlier',
            parent=self.panel1,
            pos=wx.Point(col4, 155),
            size=wx.Size(250, 22),
            style=0)
        self.input_checkBox_trim_outliers.SetValue(False)
        self.input_outlier_TB = wx.TextCtrl(id=wxID_outlier_TB,
                                            name=u'input_outlier_TB',
                                            parent=self.panel1,
                                            pos=wx.Point(col4 + 130, 155),
                                            size=wx.Size(small_box_dimensions),
                                            style=0,
                                            value=u'1')
        self.input_outlier_LR = wx.TextCtrl(id=wxID_outlier_LR,
                                            name=u'input_outlier_LR',
                                            parent=self.panel1,
                                            pos=wx.Point(col4 + 170, 155),
                                            size=wx.Size(small_box_dimensions),
                                            style=0,
                                            value=u'3')

        self.text_step_5 = wx.StaticText(id=wxID_text_step_5,
                                         label=u'Step 5: Naming parameters',
                                         name='text_step_5',
                                         parent=self.panel1,
                                         pos=wx.Point(col5, 10),
                                         size=wx.Size(100, 22),
                                         style=wx.ALIGN_LEFT)

        ## Naming convention
        self.text_naming_convention = wx.StaticText(
            id=wxID_text_naming_convention,
            label=u"Naming pattern:",
            name='text_naming_convention',
            parent=self.panel1,
            pos=wx.Point(col5, 30),
            size=wx.Size(medium_box_dimensions),
            style=0)
        self.input_naming_convention = wx.TextCtrl(
            id=wxID_input_naming_convention,
            name=u'input_naming_convention',
            parent=self.panel1,
            pos=wx.Point(col5, 50),
            size=wx.Size(large_box_dimensions),
            style=0,
            value='')

        ## Variables
        self.text_vial_id_vars = wx.StaticText(id=wxID_text_vial_id_vars,
                                               label=u'Vial_ID variables:',
                                               name='text_vial_id_vars',
                                               parent=self.panel1,
                                               pos=wx.Point(col5, 80),
                                               size=wx.Size(133, 22),
                                               style=0)
        self.input_vial_id_vars = wx.TextCtrl(
            id=wxID_input_vial_id_vars,
            name=u'input_vial_id_vars',
            parent=self.panel1,
            pos=wx.Point(col5 + 130, 80),
            size=wx.Size(small_box_dimensions),
            style=0,
            value=u'2')

        self.text_path_project = wx.StaticText(
            id=wxID_text_path_project,
            label=u"Project path:",
            name='text_path_project',
            parent=self.panel1,
            pos=wx.Point(col4 - 45, 180),
            size=wx.Size(medium_box_dimensions),
            style=0)
        self.input_path_project = wx.TextCtrl(id=wxID_input_path_project,
                                              name=u'input_path_project',
                                              parent=self.panel1,
                                              pos=wx.Point(col4 + 40, 180),
                                              size=wx.Size(350, 22),
                                              style=0,
                                              value='')

        ## Bottom panels
        self.text_video_path = wx.StaticText(id=wxID_video_path,
                                             label='Video Path',
                                             name='text_video_path',
                                             parent=self.panel1,
                                             pos=wx.Point(10, 205),
                                             size=wx.Size(930, 22),
                                             style=0)
        self.text_video_path.SetBackgroundColour(wx.Colour(241, 241, 241))

        self.button_test_parameters = wx.Button(id=wxID_test_parameters,
                                                label=u'Test parameters',
                                                name=u'button_test_parameters',
                                                parent=self.panel1,
                                                pos=wx.Point(col1, 180),
                                                size=wx.Size(140, 22),
                                                style=wx.ALIGN_CENTER)
        self.button_test_parameters.Bind(wx.EVT_BUTTON,
                                         self.OnButton_testParButton,
                                         id=wxID_test_parameters)

        self.button_reload_video = wx.Button(id=wxID_reload_video,
                                             label=u'Reload video',
                                             name=u'button_reload_video',
                                             parent=self.panel1,
                                             pos=wx.Point(col1 + 160 * 1, 180),
                                             size=wx.Size(140, 22),
                                             style=wx.ALIGN_CENTER)
        self.button_reload_video.Bind(wx.EVT_BUTTON,
                                      self.OnButton_LoadVideo,
                                      id=wxID_reload_video)

        self.button_store_parameters = wx.Button(
            id=wxID_store_parameters,
            label=u'Save configuration',
            name=u'button_store_parameters',
            parent=self.panel1,
            pos=wx.Point(col1 + 160 * 2, 180),
            size=wx.Size(140, 22),
            style=wx.ALIGN_CENTER)
        self.button_store_parameters.Bind(wx.EVT_BUTTON,
                                          self.OnButton_strParButton,
                                          id=wxID_store_parameters)

        ## Text box at the bottom
        self.status_bar = wx.StatusBar(id=wxID_status_bar,
                                       name='status_bar',
                                       parent=self,
                                       style=0)
        self.initialize_sizers()
        return
Пример #21
0
class Spectrogram(StandardMonitorPage):
    """Main class for a page that generates real-time spectrogram plots of EEG.
    """
    def __init__(self, *args, **kwargs):
        """Construct a new Spectrogram page.

        Args:
            *args, **kwargs:  Arguments to pass to the Page base class.
        """
        self.initConfig()

        # initialize Page base class
        StandardMonitorPage.__init__(self,
                                     name='Spectrogram',
                                     configPanelClass=ConfigPanel,
                                     *args,
                                     **kwargs)

        self.initCanvas()
        self.initLayout()

    def initConfig(self):
        self.filter = True  # use raw or filtered signal
        self.chanIndex = 0  # index of channel to show
        self.width = 5.0  # width of window to use for computing PSD

        self.decimationFactor = 1  # decimation factor, e.g., 2 will decimate to half sampRate

        self.interpolation = 'none'

        self.normScale = 'log'
        self.scale = -2

        self.method = 'Wavelet'

        self.setRefreshDelay(200)

        self.waveletConfig = util.Holder(nFreq=100, span=10)

        self.fourierConfig = util.Holder()

    def initCanvas(self):
        """Initialize a new matplotlib canvas, figure and axis.
        """
        self.plotPanel = wx.Panel(self)
        self.plotPanel.SetBackgroundColour('white')
        plotSizer = wx.BoxSizer(orient=wx.VERTICAL)
        self.plotPanel.SetSizer(plotSizer)

        self.fig = plt.Figure(facecolor='white')
        #self.canvas = FigureCanvas(parent=self, id=wx.ID_ANY, figure=self.fig)
        self.canvas = FigureCanvas(parent=self.plotPanel,
                                   id=wx.ID_ANY,
                                   figure=self.fig)

        self.ax = self.fig.add_subplot(1, 1, 1)
        self.ax.set_xlabel('Time (s)')
        self.ax.set_ylabel('Frequency (Hz)')

        self.cbAx = self.fig.add_axes([0.91, 0.05, 0.03, 0.93])

        #self.fig.subplots_adjust(hspace=0.0, wspace=0.0,
        #    left=0.035, right=0.92, top=0.98, bottom=0.05)

        self.adjustMargins()

        self.firstPlot()

        self.lastSize = (0, 0)
        self.needsResizePlot = True
        self.canvas.Bind(wx.EVT_SIZE, self.resizePlot)
        self.canvas.Bind(wx.EVT_IDLE, self.idleResizePlot)

        ##self.plotToolbar = widgets.PyPlotNavbar(self.canvas)
        ##plotSizer.Add(self.plotToolbar, proportion=0, flag=wx.EXPAND)
        plotSizer.Add(self.canvas, proportion=1, flag=wx.EXPAND)

        #self.plotToolbar.Hide()

    def initLayout(self):
        self.initStandardLayout()

        plotPaneAuiInfo = aui.AuiPaneInfo().Name('canvas').Caption(
            'Spectrogram').CenterPane()
        #self.auiManager.AddPane(self.canvas, plotPaneAuiInfo)
        self.auiManager.AddPane(self.plotPanel, plotPaneAuiInfo)

        self.auiManager.Update()

        self.canvas.Hide()

    def afterUpdateSource(self):
        self.configPanel.updateChannels()

    def afterStart(self):
        # make sure canvas is visible
        self.canvas.Show()
        self.plotPanel.Layout()

        # trigger initial plot update
        self.needsFirstPlot = True

    def getCap(self):
        cap = self.src.getEEGSecs(self.width, filter=self.filter, copy=False)
        if self.decimationFactor > 1:
            cap.decimate(self.decimationFactor)

        return cap

    def getSpectrum(self, cap):
        # configurable XXX - idfah
        data = cap.data[:, self.chanIndex] * sig.windows.tukey(
            cap.data.shape[0])  # tukey or hann? XXX - idfah

        freqs, powers, phases = self.cwt.apply(data)

        # configurable XXX - idfah
        powers = np.clip(powers, 1.0e-10, np.inf)

        return freqs, powers

    def firstPlot(self, event=None):
        cap = self.getCap()

        self.cwt = sig.CWT(sampRate=cap.getSampRate(),
                           freqs=self.waveletConfig.nFreq,
                           span=self.waveletConfig.span)

        if self.isRunning():
            freqs, powers = self.getSpectrum(cap)
        else:
            freqs = np.arange(1, self.src.getSampRate() // 2 + 1)
            powers = np.zeros((128, 10, 1))
            powers[0, 0, 0] = 1.0

        self.ax.cla()
        self.cbAx.cla()

        self.ax.set_xlabel('Time (s)')
        self.ax.set_ylabel('Frequency (Hz)')

        self.wimg = self.ax.imshow(powers[:, :, 0].T,
                                   interpolation=self.interpolation,
                                   origin='lower',
                                   aspect='auto',
                                   norm=self.getNorm(),
                                   extent=self.getExtent(cap, freqs),
                                   cmap=plt.cm.get_cmap('jet'),
                                   animated=True)

        self.cbar = self.fig.colorbar(self.wimg, cax=self.cbAx)
        self.cbar.set_label(r'Power Density ($V^2 / Hz$)')

        #self.updateNorm(powers)

        self.canvas.draw()

        #self.background = self.canvas.copy_from_bbox(self.fig.bbox)
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)

        self.needsFirstPlot = False

    def adjustMargins(self):
        self.fig.subplots_adjust(hspace=0.0,
                                 wspace=0.0,
                                 left=0.045,
                                 right=0.90,
                                 top=0.98,
                                 bottom=0.07)

    def resizePlot(self, event):
        # prevents handling extra resize events, hack XXX - idfah
        size = self.canvas.GetSize()
        if self.lastSize == size:
            return
        else:
            self.lastSize = size

        # this is all a hack to do resizing on idle when page is not running
        # should this be a custom FigureCanvas derived widget? XXX - idfah
        if self.isRunning():
            # when running, just do event.Skip() this will
            # call canvas._onSize since it is second handler
            self.needsResizePlot = False
            event.Skip()
        else:
            # flag to resize on next idle event
            self.needsResizePlot = True

    def idleResizePlot(self, event):
        # if not running and flagged for resize
        if not self.isRunning() and self.needsResizePlot:
            ##self.adjustMargins()
            self.needsResizePlot = False
            # call canvas resize method manually
            # hack alert, we just pass None as event
            # since it's not used anyway
            self.canvas._onSize(None)

    def getExtent(self, cap, freqs):
        return (0.0, cap.getNObs() / float(cap.getSampRate()), np.min(freqs),
                np.max(freqs))

    def getNorm(self):
        mx = 10**self.scale

        if self.normScale == 'linear':
            mn = 0.0
            norm = pltLinNorm(mn, mx)

        elif self.normScale == 'log':
            mn = 1e-10
            norm = pltLogNorm(mn, mx)

        else:
            raise RuntimeError('Invalid norm %s.' % norm)

        return norm

    def updatePlot(self, event=None):
        """Draw the spectrogram plot.
        """
        if self.needsFirstPlot:
            self.firstPlot()

        else:
            cap = self.getCap()
            freqs, powers = self.getSpectrum(cap)

            #self.updateNorm(powers)

            self.canvas.restore_region(self.background)
            self.wimg.set_array(powers[:, :, 0].T)
            self.wimg.set_extent(self.getExtent(cap, freqs))
            self.ax.draw_artist(self.wimg)

            ##self.cbAx.draw_artist(self.cbar.patch)
            ##self.cbAx.draw_artist(self.cbar.solids)

            #self.cbar.draw_all()
            #self.canvas.blit(self.cbAx.bbox)

            #self.canvas.blit(self.fig.bbox)
            self.canvas.blit(self.ax.bbox)

            # for debugging, redraws everything
            ##self.canvas.draw()

    def captureImage(self, event=None):
        ## Parts borrowed from backends_wx.py from matplotlib
        # Fetch the required filename and file type.
        filetypes, exts, filter_index = self.canvas._get_imagesave_wildcards()
        default_file = self.canvas.get_default_filename()
        dlg = wx.FileDialog(self, "Save to file", "", default_file, filetypes,
                            wx.SAVE | wx.OVERWRITE_PROMPT)
        dlg.SetFilterIndex(filter_index)
        if dlg.ShowModal() == wx.ID_OK:
            dirname = dlg.GetDirectory()
            filename = dlg.GetFilename()
            format = exts[dlg.GetFilterIndex()]
            basename, ext = os.path.splitext(filename)
            if ext.startswith('.'):
                ext = ext[1:]
            if ext in ('svg', 'pdf', 'ps', 'eps', 'png') and format != ext:
                #looks like they forgot to set the image type drop
                #down, going with the extension.
                format = ext
            self.canvas.print_figure(os.path.join(dirname, filename),
                                     format=format)
Пример #22
0
class FIRBandpassConfigPanel(FilterConfigPanel):
    def __init__(self, *args, **kwargs):
        FilterConfigPanel.__init__(self, *args, **kwargs)

        # options go in top-level sizer
        self.initOptions()

        # other stuff split horizontally by bottomSizer
        self.bottomSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.initSliders()
        self.initResponse()
        self.sizer.Add(self.bottomSizer, proportion=1, flag=wx.EXPAND)

        self.initLayout()

    def initOptions(self):
        optionsSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.filtTypeComboBox = wx.ComboBox(self, choices=list(self.flt.filtMap.keys()),
            value=self.flt.filtType, style=wx.CB_DROPDOWN)
        self.Bind(wx.EVT_COMBOBOX, self.setFiltType, self.filtTypeComboBox)
        optionsSizer.Add(self.filtTypeComboBox, proportion=1,
                flag=wx.LEFT | wx.TOP | wx.RIGHT | wx.ALIGN_CENTER, border=20)

        self.sizer.Add(optionsSizer, proportion=0)#, flag=wx.EXPAND)

    def setFiltType(self, event):
        filtType = self.filtTypeComboBox.GetValue()

        if filtType not in self.flt.filtMap.keys():
            raise RuntimeError('Invalid filter type: %s.' % str(filtType))

        self.flt.filtType = filtType
        self.updateResponse()

    def initSliders(self):
        sliderSizer = wx.BoxSizer(wx.HORIZONTAL)

        lowFreqControlBox = widgets.ControlBox(self, label='lowFreq', orient=wx.VERTICAL)
        self.lowFreqText = wx.StaticText(self, label='%6.2f(Hz)' % self.flt.lowFreq)
        lowFreqTextSizer = wx.BoxSizer(orient=wx.VERTICAL)
        lowFreqTextSizer.Add(self.lowFreqText, proportion=0, flag=wx.ALIGN_CENTER_HORIZONTAL)
        self.lowFreqSlider = wx.Slider(self, style=wx.SL_VERTICAL | wx.SL_INVERSE,
                minValue=0, maxValue=int(self.flt.nyquist*4), value=int(self.flt.lowFreq*4))
        self.Bind(wx.EVT_SLIDER, self.setLowFreq, self.lowFreqSlider)
        lowFreqControlBox.Add(lowFreqTextSizer, proportion=0,
                flag=wx.TOP | wx.BOTTOM | wx.EXPAND, border=8)
        lowFreqControlBox.Add(self.lowFreqSlider, proportion=1,
                flag=wx.LEFT | wx.RIGHT | wx.EXPAND, border=25)

        sliderSizer.Add(lowFreqControlBox, proportion=1,
                flag=wx.ALL | wx.EXPAND, border=10)

        highFreqControlBox = widgets.ControlBox(self, label='highFreq', orient=wx.VERTICAL)
        self.highFreqText = wx.StaticText(self, label='%6.2f(Hz)' % self.flt.highFreq)
        highFreqTextSizer = wx.BoxSizer(orient=wx.VERTICAL)
        highFreqTextSizer.Add(self.highFreqText, proportion=0, flag=wx.ALIGN_CENTER_HORIZONTAL)
        self.highFreqSlider = wx.Slider(self, style=wx.SL_VERTICAL | wx.SL_INVERSE,
                minValue=0, maxValue=int(self.flt.nyquist*4), value=int(self.flt.highFreq*4))
        self.Bind(wx.EVT_SLIDER, self.setHighFreq, self.highFreqSlider)
        highFreqControlBox.Add(highFreqTextSizer, proportion=0,
                flag=wx.TOP | wx.BOTTOM | wx.EXPAND, border=8)
        highFreqControlBox.Add(self.highFreqSlider, proportion=1,
                flag=wx.LEFT | wx.RIGHT | wx.EXPAND, border=25)

        sliderSizer.Add(highFreqControlBox, proportion=1,
                flag=wx.ALL | wx.EXPAND, border=10)

        orderControlBox = widgets.ControlBox(self, label='Order', orient=wx.VERTICAL)
        self.orderText = wx.StaticText(self, label='%2d' % self.flt.order)
        orderTextSizer = wx.BoxSizer(orient=wx.VERTICAL)
        orderTextSizer.Add(self.orderText, proportion=0, flag=wx.ALIGN_CENTER_HORIZONTAL)
        self.orderSlider = wx.Slider(self, style=wx.SL_VERTICAL | wx.SL_INVERSE,
                minValue=2, maxValue=50, value=self.flt.order // 2)
        self.Bind(wx.EVT_SLIDER, self.setOrder, self.orderSlider)
        orderControlBox.Add(orderTextSizer, proportion=0,
                flag=wx.TOP | wx.BOTTOM | wx.EXPAND, border=8)
        orderControlBox.Add(self.orderSlider, proportion=1,
                flag=wx.LEFT | wx.RIGHT | wx.EXPAND, border=25)

        sliderSizer.Add(orderControlBox, proportion=1,
                flag=wx.ALL | wx.EXPAND, border=10)

        self.bottomSizer.Add(sliderSizer, proportion=1, flag=wx.EXPAND)

    def setLowFreq(self, event):
        self.flt.lowFreq = self.lowFreqSlider.GetValue() / 4.0
        self.lowFreqText.SetLabel('%6.2f(Hz)' % self.flt.lowFreq)
        self.updateResponse()

    def setHighFreq(self, event):
        self.flt.highFreq = self.highFreqSlider.GetValue() / 4.0
        self.highFreqText.SetLabel('%6.2f(Hz)' % self.flt.highFreq)
        self.updateResponse()

    def setOrder(self, event):
        self.flt.order = self.orderSlider.GetValue() * 2
        self.orderText.SetLabel('%2d' % self.flt.order)
        self.updateResponse()

    def initResponse(self):
        self.freqResponseFig = plt.Figure()
        self.freqResponseCanvas = FigureCanvas(parent=self,
                id=wx.ID_ANY, figure=self.freqResponseFig)
        self.freqResponseAx = self.freqResponseFig.add_subplot(1,1,1)
        #self.freqResponseFig.tight_layout()

        self.phaseResponseFig = plt.Figure()
        self.phaseResponseCanvas = FigureCanvas(parent=self,
                id=wx.ID_ANY, figure=self.phaseResponseFig)
        self.phaseResponseAx = self.phaseResponseFig.add_subplot(1,1,1)
        #self.freqResponseFig.tight_layout()

        responseSizer = wx.BoxSizer(wx.VERTICAL)

        freqResponseControlBox = widgets.ControlBox(self,
                label='Frequency Response', orient=wx.VERTICAL)
        freqResponseControlBox.Add(self.freqResponseCanvas, proportion=1,
                flag=wx.ALL | wx.EXPAND, border=8)
        responseSizer.Add(freqResponseControlBox, proportion=1,
                flag=wx.TOP | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=10)

        phaseResponseControlBox = widgets.ControlBox(self,
                label='Phase Response', orient=wx.VERTICAL)
        phaseResponseControlBox.Add(self.phaseResponseCanvas, proportion=1,
                flag=wx.ALL | wx.EXPAND, border=8)
        responseSizer.Add(phaseResponseControlBox, proportion=1,
                flag=wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=10)

        self.bottomSizer.Add(responseSizer, proportion=1, flag=wx.EXPAND)

        self.freqResponseCanvas.SetMinSize((0,0))
        self.phaseResponseCanvas.SetMinSize((0,0))

        # could we prevent resize when panel is not visible? XXX - idfah
        self.freqResponseLastSize = (0,0)
        self.freqResponseCanvas.Bind(wx.EVT_SIZE, self.freqResponseResize)
        self.phaseResponseLastSize = (0,0)
        self.phaseResponseCanvas.Bind(wx.EVT_SIZE, self.phaseResponseResize)

        self.updateResponse()

    def freqResponseResize(self, event):
        # prevents handling extra resize events, hack XXX - idfah
        size = self.freqResponseCanvas.GetSize()
        if self.freqResponseLastSize == size:
            return

        self.freqResponseLastSize = size
        event.Skip()

    def phaseResponseResize(self, event):
        # prevents handling extra resize events, hack XXX - idfah
        size = self.phaseResponseCanvas.GetSize()
        if self.phaseResponseLastSize == size:
            return

        self.phaseResponseLastSize = size
        event.Skip()

    def updateResponse(self):
        self.flt.updateFilter()

        self.freqResponseAx.cla()
        self.flt.bp.plotFreqResponse(ax=self.freqResponseAx, linewidth=2)
        self.freqResponseAx.autoscale(tight=True)
        self.freqResponseAx.legend(prop={'size': 12})
        self.freqResponseCanvas.draw()

        self.phaseResponseAx.cla()
        self.flt.bp.plotPhaseResponse(ax=self.phaseResponseAx, linewidth=2)
        self.phaseResponseAx.legend(prop={'size': 12})
        self.phaseResponseAx.autoscale(tight=True)

        self.phaseResponseCanvas.draw()
Пример #23
0
class PlotPanel(wx.Panel):
    zoom_levels = [100.0, 110.0, 125.0, 150.0, 200.0, 250.0, 300.0, 400.0]
    dose_contour_levels = [
        10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 95.0, 98 - 0,
        100.0, 102.0
    ]

    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.is_closeable = False
        self.parent = parent
        self.active_plan = None
        self.plot_mouse_action = None

        pub.subscribe(self.on_patient_loaded, "patient.loaded.ini")
        pub.subscribe(self.set_active_image, "plot.image.active_id")
        pub.subscribe(self.voi_changed, "voi.selection_changed")
        pub.subscribe(self.plan_changed, "plan.active.changed")
        pub.subscribe(self.plan_field_changed, "plan.field.selection_changed")
        pub.subscribe(self.plan_dose_changed, "plan.dose.active_changed")
        pub.subscribe(self.plan_dose_removed, "plan.dose.removed")
        pub.subscribe(self.plan_let_added, "plan.let.added")
        pub.subscribe(self.plan_let_removed, "plan.let.removed")
        pub.subscribe(self.target_dose_changed,
                      "plan.dose.target_dose_changed")
        self.plotmode = "Transversal"

    def __del__(self):
        pub.unsubscribe(self.on_patient_loaded, "patient.loaded.ini")
        pub.unsubscribe(self.set_active_image, "plot.image.active_id")
        pub.unsubscribe(self.voi_changed, "voi.selection_changed")
        pub.unsubscribe(self.plan_changed, "plan.active.changed")
        pub.unsubscribe(self.plan_field_changed,
                        "plan.field.selection_changed")
        pub.unsubscribe(self.plan_dose_changed, "plan.dose.active_changed")
        pub.unsubscribe(self.plan_dose_removed, "plan.dose.removed")
        pub.unsubscribe(self.plan_let_added, "plan.let.added")
        pub.unsubscribe(self.plan_let_removed, "plan.let.removed")
        pub.unsubscribe(self.target_dose_changed,
                        "plan.dose.target_dose_changed")

    def target_dose_changed(self, msg):
        self.Draw()

    def Init(self):
        self.plotutil = PlotUtil()
        self.figure = Figure(None, 100)
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        # ~ self.canvas.SetDoubleBuffered(True)
        self.clear()
        self.plotutil.set_draw_in_gui(True)
        self.figure.set_frameon(True)
        rect = self.figure.patch
        rect.set_facecolor('black')

    def plan_dose_changed(self, msg):
        if msg.data["plan"] is self.active_plan:
            self.plotutil.set_dose(msg.data["dose"].get_dosecube())
            self.Draw()

    def plan_field_changed(self, msg):
        self.Draw()

    def plan_dose_removed(self, msg):
        if msg.data["plan"] is self.active_plan:
            self.plotutil.set_dose(None)
            self.Draw()

    def plan_let_added(self, msg):
        if msg.data["plan"] is self.active_plan:
            self.plotutil.set_let(msg.data["let"])
            self.Draw()

    def plan_let_removed(self, msg):
        if msg.data["plan"] is self.active_plan:
            self.plotutil.set_let(None)
            self.Draw()

    def plan_changed(self, msg):
        self.active_plan = msg.data
        if self.active_plan is None:
            self.plotutil.set_plan(None)
            self.plotutil.set_dose(None)
            self.plotutil.set_let(None)
        else:
            self.plotutil.set_plan(self.active_plan)
            doseobj = self.active_plan.get_dose()

            if doseobj is not None:
                self.plotutil.set_dose(doseobj.get_dosecube())
            else:
                self.plotutil.set_dose(None)
            self.plotutil.set_let(self.active_plan.get_let())
        self.Draw()

    def set_toolbar(self, toolbar):
        id = wx.NewId()
        selector = wx.Choice(toolbar, id)
        selector.Append("Transversal")
        selector.Append("Sagital")
        selector.Append("Coronal")
        idx = selector.FindString(self.plotmode)
        selector.Select(idx)

        toolbar.AddControl(selector)
        wx.EVT_CHOICE(selector, id, self.plot_mode_changed)

        id = wx.NewId()
        self.zoom_in_btn = toolbar.AddLabelTool(
            id, '', wx.Bitmap(get_resource_path('zoom_in.png')))
        wx.EVT_MENU(toolbar, id, self.zoom_in)

        id = wx.NewId()
        self.zoom_out_btn = toolbar.AddLabelTool(
            id, '', wx.Bitmap(get_resource_path('zoom_out.png')))
        wx.EVT_MENU(toolbar, id, self.zoom_out)

    def zoom_buttons_visible(self):
        zoom_idx = self.zoom_levels.index(self.plotutil.get_zoom())
        self.zoom_in_btn.Enable(True)
        self.zoom_out_btn.Enable(True)

        if len(self.zoom_levels) == zoom_idx + 1:
            self.zoom_in_btn.Enable(False)
        if zoom_idx == 0:
            self.zoom_out_btn.Enable(False)

    def zoom_in(self, evt):
        zoom_idx = self.zoom_levels.index(self.plotutil.get_zoom())
        zoom_idx += 1
        if len(self.zoom_levels) > zoom_idx:
            zoom = self.zoom_levels[zoom_idx]
            self.plotutil.set_zoom(zoom)
            self.zoom_buttons_visible()
            self.Draw()

    def zoom_out(self, evt):
        zoom_idx = self.zoom_levels.index(self.plotutil.get_zoom())
        zoom_idx -= 1
        if zoom_idx >= 0:
            zoom = self.zoom_levels[zoom_idx]
            self.plotutil.set_zoom(zoom)
            self.zoom_buttons_visible()
            self.Draw()

    def plot_mode_changed(self, evt):
        self.plotmode = evt.GetString()
        self.plotutil.set_plot_plan(self.plotmode)
        self.image_idx = int(self.plotutil.get_images_count() / 2)
        self.clear()
        self.Draw()

    def clear(self):
        self.figure.clear()
        self.subplot = self.figure.add_subplot(111)
        self.plotutil.set_figure(self.subplot)

    def voi_changed(self, msg):
        voi = msg.data
        if voi.is_selected():
            self.plotutil.add_voi(voi.voxelplan_voi)
        else:
            self.plotutil.remove_voi(voi.voxelplan_voi)
        self.Draw()

    def set_active_image(self, msg):
        if self.plotmode == "Transversal":
            self.image_idx = msg.data
            self.Draw()

    def on_patient_loaded(self, msg):
        self.data = msg.data
        ctx = self.data.get_images().get_voxelplan()

        self.plotutil.set_ct(ctx)

        self.image_idx = int(ctx.dimz / 2)
        self.setSize()
        self.bind_keys()

    def get_figure(self):
        return self.figure

    def bind_keys(self):
        self.Bind(wx.EVT_MOUSEWHEEL, self.on_mouse_wheel)
        self.Bind(wx.EVT_ENTER_WINDOW, self.on_mouse_enter)
        self.Bind(wx.EVT_LEAVE_WINDOW, self.on_mouse_leave)

        self.Bind(wx.EVT_SIZE, self.on_size)
        self.canvas.Bind(wx.EVT_KEY_DOWN, self.on_key_down)
        self.canvas.mpl_connect('motion_notify_event', self.on_mouse_move_plot)
        self.canvas.mpl_connect('button_press_event', self.on_mouse_press_plot)
        self.canvas.mpl_connect('button_release_event',
                                self.on_mouse_action_ended)
        self.canvas.mpl_connect('figure_leave_event',
                                self.on_mouse_action_ended)

    def on_mouse_press_plot(self, evt):
        if evt.button is 3:
            pos = evt.guiEvent.GetPosition()
            standard = True
            if hasattr(self.plotutil, "contrast_bar"):
                bar = self.plotutil.contrast_bar
                if evt.inaxes is bar.ax:
                    menu = self.right_click_contrast()
                    standard = False
            if hasattr(self.plotutil, "dose_bar"):
                bar = self.plotutil.dose_bar
                if evt.inaxes is bar.ax:
                    menu = self.right_click_dose()
                    standard = False

            if standard:
                menu = self.normal_right_click_menu()

            wx.CallAfter(self.show_menu, menu)
            if self.canvas.HasCapture():
                self.canvas.ReleaseMouse()

        elif evt.button is 1:
            if hasattr(self.plotutil, "contrast_bar"):
                bar = self.plotutil.contrast_bar
                if evt.inaxes is bar.ax:
                    if evt.ydata >= 0.50:
                        self.plot_mouse_action = "contrast_top"
                    else:
                        self.plot_mouse_action = "contrast_bottom"
            if hasattr(self.plotutil, "dose_bar"):
                bar = self.plotutil.dose_bar
                if evt.inaxes is bar.ax:
                    if evt.ydata >= 0.50:
                        self.plot_mouse_action = "dose_top"
                    else:
                        self.plot_mouse_action = "dose_bottom"
            if hasattr(self.plotutil, "let_bar"):
                bar = self.plotutil.let_bar
                if evt.inaxes is bar.ax:
                    if evt.ydata >= 0.50:
                        self.plot_mouse_action = "let_top"
                    else:
                        self.plot_mouse_action = "let_bottom"

        self.mouse_pos_ini = [evt.x, evt.y]
        evt.guiEvent.Skip()

    def show_menu(self, menu):
        self.PopupMenu(menu)

    def on_mouse_action_ended(self, evt):
        self.plot_mouse_action = None

    def on_mouse_move_plot(self, evt):
        pos = [evt.x, evt.y]
        if self.plot_mouse_action is not None:
            step = [
                pos[0] - self.mouse_pos_ini[0], pos[1] - self.mouse_pos_ini[1]
            ]
            if self.plot_mouse_action == "contrast_top":
                contrast = self.plotutil.get_contrast()
                stepsize = np.log(contrast[1] - contrast[0])
                contrast[1] -= stepsize * step[1]
                self.plotutil.set_contrast(contrast)
            elif self.plot_mouse_action == "contrast_bottom":
                contrast = self.plotutil.get_contrast()
                stepsize = np.log(contrast[1] - contrast[0])
                contrast[0] -= stepsize * step[1]
                self.plotutil.set_contrast(contrast)
            elif self.plot_mouse_action == "dose_top":
                dose = self.plotutil.get_min_max_dose()
                dose[1] -= 0.30 * step[1]
                self.plotutil.set_dose_min_max(dose)
            elif self.plot_mouse_action == "dose_bottom":
                dose = self.plotutil.get_min_max_dose()
                dose[0] -= 0.30 * step[1]
                self.plotutil.set_dose_min_max(dose)
            elif self.plot_mouse_action == "let_top":
                let = self.plotutil.get_min_max_let()
                let[1] -= 0.30 * step[1]
                self.plotutil.set_let_min_max(let)
            elif self.plot_mouse_action == "let_bottom":
                let = self.plotutil.get_min_max_let()
                let[0] -= 0.30 * step[1]
                self.plotutil.set_let_min_max(let)
            self.Draw()
        elif evt.button == 1 and evt.inaxes is self.plotutil.fig_ct.axes:
            if not None in self.mouse_pos_ini:
                step = [
                    pos[0] - self.mouse_pos_ini[0],
                    pos[1] - self.mouse_pos_ini[1]
                ]
                if self.plotutil.move_center(step):
                    self.Draw()

        self.mouse_pos_ini = [evt.x, evt.y]
        if hasattr(self.plotutil,
                   "fig_ct") and evt.inaxes is self.plotutil.fig_ct.axes:
            point = self.plotutil.pixel_to_pos(
                [round(evt.xdata), round(evt.ydata)])

            text = "X: %.2f mm Y: %.2f mm / X: %d px Y: %d px" % (
                point[1][0], point[1][1], point[0][0], point[0][1])
            pub.sendMessage("statusbar.update", {"number": 1, "text": text})
            dim = self.data.get_image_dimensions()
            if self.plotmode == "Transversal":
                pos = [round(evt.xdata), round(evt.ydata), self.image_idx]
            elif self.plotmode == "Sagital":
                pos = [
                    dim[0] - round(evt.xdata), self.image_idx,
                    dim[2] - round(evt.ydata)
                ]
            elif self.plotmode == "Coronal":
                pos = [
                    self.image_idx, dim[1] - round(evt.xdata),
                    dim[2] - round(evt.ydata)
                ]
            try:
                ct_value = self.data.get_image_cube()[pos[2], pos[1], pos[0]]
                text = "Value: %.1f" % (ct_value)
                plan = self.active_plan
                if plan is not None:
                    dose = plan.get_dose_cube()
                    if dose is not None:
                        dose_value = dose[pos[2], pos[1], pos[0]]
                        target_dose = plan.get_dose().get_dose()
                        if not target_dose == 0.0:
                            dose_value *= target_dose / 1000
                            text += " / Dose: %.1f Gy" % (float(dose_value))
                        else:
                            dose_value /= 10
                            text += " / Dose: %.1f %%" % (float(dose_value))

                    let = plan.get_let_cube()
                    if let is not None:
                        let_value = let[pos[2], pos[1], pos[0]]
                        text += " / LET: %.1f kev/um" % (let_value)
            except IndexError as e:
                pass
            pub.sendMessage("statusbar.update", {"number": 2, "text": text})

    def normal_right_click_menu(self):
        menu = wx.Menu()
        voi_menu = wx.Menu()

        for voi in self.data.get_vois():
            id = wx.NewId()
            item = voi_menu.AppendCheckItem(id, voi.get_name())
            if voi.is_selected():
                item.Check()
            wx.EVT_MENU(self, id, self.menu_voi_selected)
        if voi_menu.GetMenuItemCount() > 0:
            menu.AppendSubMenu(voi_menu, "Vois")
        view_menu = wx.Menu()

        active_plan = self.active_plan
        if active_plan is not None:
            dose = active_plan.get_dose()
            dose_type_menu = wx.Menu()
            if dose is not None:
                id = wx.NewId()
                item = view_menu.AppendCheckItem(id, "View Dose")
                if self.plotutil.get_dose() is not None:
                    item.Check()
                wx.EVT_MENU(self, id, self.toogle_dose)

                id = wx.NewId()
                item = dose_type_menu.Append(id, "Color wash")
                wx.EVT_MENU(self, id, self.change_dose_to_colorwash)

                id = wx.NewId()
                item = dose_type_menu.Append(id, "Contour")
                wx.EVT_MENU(self, id, self.change_dose_to_contour)

                menu.AppendSubMenu(dose_type_menu, "Dose Visalization")
                if self.plotutil.get_dose_plot() == "contour":
                    dose_contour_menu = wx.Menu()
                    for level in self.dose_contour_levels:
                        id = wx.NewId()
                        item = dose_contour_menu.AppendCheckItem(
                            id, "%d %%" % level)
                        for contour in self.plotutil.get_dose_contours():
                            if contour["doselevel"] == level:
                                item.Check()
                        wx.EVT_MENU(self, id, self.toogle_dose_contour)
                    menu.AppendSubMenu(dose_contour_menu,
                                       "Dose Contour levels")

            let = active_plan.get_let()

            if let is not None:
                id = wx.NewId()
                item = view_menu.AppendCheckItem(id, "View LET")
                if self.plotutil.get_let() is not None:
                    item.Check()
                wx.EVT_MENU(self, id, self.toogle_let)

            if view_menu.GetMenuItemCount() > 0:
                menu.AppendSubMenu(view_menu, "View")

            field_menu = wx.Menu()
            for field in active_plan.get_fields():
                id = wx.NewId()
                item = field_menu.AppendCheckItem(id, field.get_name())
                if field.is_selected():
                    item.Check()
                wx.EVT_MENU(self, id, self.menu_field_selected)
            if field_menu.GetMenuItemCount() > 0:
                menu.AppendSubMenu(field_menu, "Fields")

        jump_menu = wx.Menu()
        id = wx.NewId()
        item = jump_menu.Append(id, "First")
        wx.EVT_MENU(self, id, self.jump_to_first)

        id = wx.NewId()
        item = jump_menu.Append(id, "Middle")
        wx.EVT_MENU(self, id, self.jump_to_middle)

        id = wx.NewId()
        item = jump_menu.Append(id, "Last")
        wx.EVT_MENU(self, id, self.jump_to_last)

        menu.AppendSubMenu(jump_menu, "Jump To")
        return menu

    def right_click_dose(self):
        menu = wx.Menu()
        id = wx.NewId()
        item = menu.Append(id, "Reset")
        wx.EVT_MENU(menu, id, self.reset_dose_range)

        colormap_menu = wx.Menu()

        id = wx.NewId()
        colormap_menu.Append(id, "Continuous")
        wx.EVT_MENU(colormap_menu, id, self.set_colormap_dose)

        id = wx.NewId()
        colormap_menu.Append(id, "Discrete")
        wx.EVT_MENU(colormap_menu, id, self.set_colormap_dose)

        item = menu.AppendSubMenu(colormap_menu, "Colorscale")

        scale_menu = wx.Menu()

        id = wx.NewId()
        scale_menu.Append(id, "Auto")
        wx.EVT_MENU(scale_menu, id, self.set_dose_scale)

        if self.active_plan.get_dose().get_dose() > 0.0:
            id = wx.NewId()
            scale_menu.Append(id, "Absolute")
            wx.EVT_MENU(scale_menu, id, self.set_dose_scale)

        id = wx.NewId()
        scale_menu.Append(id, "Relative")
        wx.EVT_MENU(scale_menu, id, self.set_dose_scale)

        item = menu.AppendSubMenu(scale_menu, "Scale")

        return menu

    def right_click_contrast(self):
        menu = wx.Menu()
        id = wx.NewId()
        item = menu.Append(id, "Reset")
        wx.EVT_MENU(menu, id, self.reset_contrast)
        return menu

    def set_colormap_dose(self, evt):
        colormap = plt.get_cmap(None)
        name = evt.GetEventObject().GetLabel(evt.GetId())
        if name == "Discrete":
            colormap = cmap_discretize(colormap, 10)
        self.plotutil.set_colormap_dose(colormap)
        self.Draw()

    def set_dose_scale(self, evt):
        scale = {"auto": "auto", "absolute": "abs", "relative": "rel"}
        name = evt.GetEventObject().GetLabel(evt.GetId())
        self.plotutil.set_dose_axis(scale[name.lower()])
        self.Draw()

    def reset_dose_range(self, evt):
        self.plotutil.set_dose_min_max(0, 100)
        self.Draw()

    def reset_contrast(self, evt):
        contrast = [-100, 400]
        self.plotutil.set_contrast(contrast)
        self.Draw()

    def jump_to_first(self, evt):
        self.image_idx = 0
        self.Draw()

    def jump_to_middle(self, evt):
        self.image_idx = self.plotutil.get_images_count() / 2
        self.Draw()

    def jump_to_last(self, evt):
        self.image_idx = self.plotutil.get_images_count() - 1
        self.Draw()

    def toogle_dose_contour(self, evt):
        value = float(evt.GetEventObject().GetLabel(evt.GetId()).split()[0])
        if evt.IsChecked():
            self.plotutil.add_dose_contour({"doselevel": value, "color": "b"})
        else:
            for contour in self.plotutil.get_dose_contours():
                if contour["doselevel"] == value:
                    self.plotutil.remove_dose_contour(contour)
        self.Draw()

    def toogle_dose(self, evt):
        if self.plotutil.get_dose() is None:
            self.plotutil.set_dose(self.active_plan.get_dose().get_dosecube())
        else:
            self.plotutil.set_dose(None)
        self.Draw()

    def toogle_let(self, evt):
        if self.plotutil.get_let() is None:
            self.plotutil.set_let(self.active_plan.get_let())
        else:
            self.plotutil.set_let(None)
        self.Draw()

    def menu_voi_selected(self, evt):
        name = evt.GetEventObject().GetLabel(evt.GetId())
        name = name.replace("__", "_")
        voi = self.data.get_vois().get_voi_by_name(name)
        if not voi is None:
            voi.toogle_selected()

    def menu_field_selected(self, evt):
        name = evt.GetEventObject().GetLabel(evt.GetId())
        field = self.active_plan.get_fields().get_field_by_name(name)
        field.toogle_selected(self.active_plan)

    def change_dose_to_colorwash(self, evt):
        self.plotutil.set_dose_plot("colorwash")
        self.Draw()

    def change_dose_to_contour(self, evt):
        self.plotutil.set_dose_plot("contour")
        self.Draw()

    def on_size(self, evt):
        """Refresh the view when the size of the panel changes."""

        self.setSize()

    def on_mouse_wheel(self, evt):
        delta = evt.GetWheelDelta()
        rot = evt.GetWheelRotation()
        rot = rot / delta

        if evt.ControlDown():
            if (rot >= 1):
                self.zoom_in(None)
            elif (rot < 1):
                self.zoom_out(None)
            return
        n_images = self.data.get_images().get_voxelplan().dimz
        if n_images:
            if (rot >= 1):
                if (self.image_idx > 0):
                    self.image_idx -= 1
                    self.Draw()
            if (rot <= -1):
                if (self.image_idx < self.plotutil.get_images_count() - 1):
                    self.image_idx += 1
                    self.Draw()

    def on_key_down(self, evt):
        prevkey = [wx.WXK_UP, wx.WXK_PAGEUP]
        nextkey = [wx.WXK_DOWN, wx.WXK_PAGEDOWN]
        code = evt.GetKeyCode()
        if code in prevkey:
            if (self.image_idx > 0):
                self.image_idx -= 1
                self.Draw()
        elif code in nextkey:
            if (self.image_idx < self.plotutil.get_images_count() - 1):
                self.image_idx += 1
                self.Draw()

    def on_mouse_enter(self, evt):
        """Set a flag when the cursor enters the window."""
        self.mouse_in_window = True

    def on_mouse_leave(self, evt):
        """Set a flag when the cursor leaves the window."""

        self.mouse_in_window = False

    def setSize(self):
        size = self.parent.GetClientSize()
        size[1] = size[1] - 40
        size[0] = size[0] - 5
        pixels = tuple(size)
        self.canvas.SetSize(pixels)
        self.figure.set_size_inches(
            float(pixels[0]) / self.figure.get_dpi(),
            float(pixels[1]) / self.figure.get_dpi())
        self.Draw()

    def Draw(self):
        self.plotutil.plot(self.image_idx)

        self.figure.subplots_adjust(left=0,
                                    bottom=0,
                                    right=1,
                                    top=1,
                                    wspace=None,
                                    hspace=None)
        # self.figure.tight_layout(pad=0.0)

        if hasattr(self.plotutil, "dose_bar"):
            bar = self.plotutil.dose_bar
            bar.ax.yaxis.label.set_color('white')
            bar.ax.tick_params(axis='y', colors='white', labelsize=8)
        if hasattr(self.plotutil, "let_bar"):
            bar = self.plotutil.let_bar
            bar.ax.yaxis.label.set_color('white')
            bar.ax.yaxis.label.set_color('white')
            bar.ax.tick_params(axis='y', colors='white', labelsize=8)
        if hasattr(self.plotutil, "contrast_bar"):
            bar = self.plotutil.contrast_bar
            bar.ax.yaxis.label.set_color('white')
            bar.ax.yaxis.set_label_position('left')
            [t.set_color("white") for t in bar.ax.yaxis.get_ticklabels()]
            [t.set_size(8) for t in bar.ax.yaxis.get_ticklabels()]

            # bar.ax.tick_params(axis='y', colors='white',labelsize=8,labelleft=True,labelright=False)

        self.canvas.draw()
Пример #24
0
class Calculatrice(Panel_simple):
    __titre__ = u"Calculatrice" # Donner un titre a chaque module

    def __init__(self, *args, **kw):
        Panel_simple.__init__(self, *args, **kw)

        self.interprete = Interprete(calcul_exact = self.param("calcul_exact"),
                                ecriture_scientifique = self.param("ecriture_scientifique"),
                                changer_separateurs = self.param("changer_separateurs"),
                                separateurs_personnels = self.param("separateurs_personnels"),
                                copie_automatique = self.param("copie_automatique"),
                                formatage_OOo = self.param("formatage_OOo"),
                                formatage_LaTeX = self.param("formatage_LaTeX"),
                                ecriture_scientifique_decimales = self.param("ecriture_scientifique_decimales"),
                                precision_calcul = self.param("precision_calcul"),
                                precision_affichage = self.param("precision_affichage"),
                                simpify = True,
                                )

##        self.entrees = wx.BoxSizer(wx.HORIZONTAL)
##        self.entree = wx.TextCtrl(self, size = (550, -1), style = wx.TE_PROCESS_ENTER)
##        self.entrees.Add(self.entree, 1, wx.ALL|wx.GROW, 5)
##        self.valider = wx.Button(self, wx.ID_OK)
##        self.entrees.Add(self.valider, 0, wx.ALL, 5)
        self.entree = LigneCommande(self, longueur = 550, action = self.affichage_resultat)
        self.entree.SetToolTip(wx.ToolTip(u"[Maj]+[Entrée] pour une valeur approchée."))

        self.corps = wx.BoxSizer(wx.HORIZONTAL)
        self.gauche = wx.BoxSizer(wx.VERTICAL)
        self.resultats = wx.TextCtrl(self, size = (450,310), style = wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH)
        self.gauche.Add(self.resultats, 0, wx.ALL, 5)

        self.figure = Figure(figsize=(5,1.3),frameon=True, facecolor="w")
        self.visualisation = FigureCanvas(self, -1, self.figure)
        self.axes = self.figure.add_axes([0, 0, 1, 1], frameon=False)
        self.axes.axison = False
        self.pp_texte = self.axes.text(0.5, 0.5, "", horizontalalignment='center', verticalalignment='center', transform = self.axes.transAxes, size=18)
        self.gauche.Add(self.visualisation, 0, wx.ALL|wx.ALIGN_CENTER, 5)
        self.corps.Add(self.gauche, 0, wx.ALL, 5)


        ### Pave numerique de la calculatrice ###
        # On construit le pavé de la calculatrice.
        # Chaque bouton du pavé doit provoquer l'insertion de la commande correspondante.

        self.pave  = wx.BoxSizer(wx.VERTICAL)
        self.corps.Add(self.pave, 0, wx.ALL, 5)
        boutons = ["2nde", "ans", "ouv", "ferm", "egal", "7", "8", "9", "div", "x", "4", "5", "6", "mul", "y", "1", "2", "3", "minus", "z", "0", "pt", "pow", "plus", "t", "rac", "sin", "cos", "tan", "exp", "i", "pi", "e", "abs", "mod"]
        inserer = ["", "ans()", "(", ")", "=", "7", "8", "9",  "/", "x", "4", "5", "6", "*", "y", "1", "2", "3", "-", "z", "0", ".", "^", "+", "t", "sqrt(", ("sin(", "asin(", "sinus / arcsinus"), ("cos(", "acos(", "cosinus / arccosinus"), ("tan(", "atan(", "tangente / arctangente"), ("exp(", "ln(", "exponentielle / logarithme neperien"), ("i", "cbrt(", "i / racine cubique"), ("pi", "sinh(", "pi / sinus hyperbolique"), ("e", "cosh", "e / cosinus hyperbolique"), ("abs(", "tanh", "valeur absolue / tangente hyperbolique"), (" mod ", "log10(", "modulo / logarithme decimal")]

        self.seconde = False # indique si la touche 2nde est activee.

        def action(event = None):
            self.seconde = not self.seconde
            if self.seconde: self.message(u"Touche [2nde] activée.")
            else: self.message("")

        self.actions = [action]

        for i in range(len(boutons)):
            # On aligne les boutons de la calculatrice par rangees de 5.
            if i%5 == 0:
                self.rangee = wx.BoxSizer(wx.HORIZONTAL)
                self.pave.Add(self.rangee, 0, wx.ALL,0)

            # Ensuite, on construit une liste de fonctions, parallelement à la liste des boutons.
            if i > 0:
                def action(event = None, entree = self.entree, j = i):
                    if type(inserer[j]) == tuple:
                        entree.WriteText(inserer[j][self.seconde])
                    else:
                        entree.WriteText(inserer[j])
                    n = entree.GetInsertionPoint()
                    entree.SetFocus()
                    entree.SetInsertionPoint(n)
                    self.seconde = False
                    self.message("")
                self.actions.append(action)

            bmp = png('btn_' + boutons[i])
            bouton = wx.BitmapButton(self, -1, bmp, style=wx.NO_BORDER)
            bouton.SetBackgroundColour(self.GetBackgroundColour())
            espace = 3
            if param.plateforme == "Linux":
                espace = 0
            self.rangee.Add(bouton, 0, wx.ALL, espace)
            # A chaque bouton, on associe une fonction de la liste.
            bouton.Bind(wx.EVT_BUTTON, self.actions[i])
            if type(inserer[i]) == tuple: bouton.SetToolTipString(inserer[i][2])

        self.pave.Add(wx.BoxSizer(wx.HORIZONTAL))


        ### Liste des options ###
        # En dessous du pavé apparait la liste des différents modes de fonctionnement de la calculatrice.

        # Calcul exact
        ligne = wx.BoxSizer(wx.HORIZONTAL)
        self.cb_calcul_exact = wx.CheckBox(self)
        self.cb_calcul_exact.SetValue(not self.param("calcul_exact"))
        ligne.Add(self.cb_calcul_exact, flag = wx.ALIGN_CENTER_VERTICAL)
        ligne.Add(wx.StaticText(self, -1, u" Valeur approchée."), flag = wx.ALIGN_CENTER_VERTICAL)
        self.pave.Add(ligne)

        self.cb_calcul_exact.Bind(wx.EVT_CHECKBOX, self.EvtCalculExact)

        # Notation scientifique
        ligne = wx.BoxSizer(wx.HORIZONTAL)
        self.cb_notation_sci = wx.CheckBox(self)
        self.cb_notation_sci.SetValue(self.param("ecriture_scientifique"))
        ligne.Add(self.cb_notation_sci, flag = wx.ALIGN_CENTER_VERTICAL)
        self.st_notation_sci = wx.StaticText(self, -1, u" Écriture scientifique (arrondie à ")
        ligne.Add(self.st_notation_sci, flag = wx.ALIGN_CENTER_VERTICAL)
        self.sc_decimales = wx.SpinCtrl(self, -1, size = (45, -1), min = 0, max = 11)
        self.sc_decimales.SetValue(self.param("ecriture_scientifique_decimales"))
        ligne.Add(self.sc_decimales, flag = wx.ALIGN_CENTER_VERTICAL)
        self.st_decimales = wx.StaticText(self, -1, u" décimales).")
        ligne.Add(self.st_decimales, flag = wx.ALIGN_CENTER_VERTICAL)
        self.pave.Add(ligne)

        self.EvtCalculExact()

        self.cb_notation_sci.Bind(wx.EVT_CHECKBOX, self.EvtNotationScientifique)
        self.sc_decimales.Bind(wx.EVT_SPINCTRL, self.EvtNotationScientifique)

        # Copie du résultat dans le presse-papier
        ligne = wx.BoxSizer(wx.HORIZONTAL)
        self.cb_copie_automatique = wx.CheckBox(self)
        self.cb_copie_automatique.SetValue(self.param("copie_automatique"))
        ligne.Add(self.cb_copie_automatique, flag = wx.ALIGN_CENTER_VERTICAL)
        ligne.Add(wx.StaticText(self, -1, u" Copie du résultat dans le presse-papier."), flag = wx.ALIGN_CENTER_VERTICAL)
        self.pave.Add(ligne)

        self.cb_copie_automatique.Bind(wx.EVT_CHECKBOX, self.EvtCopieAutomatique)

        # En mode LaTeX
        ligne = wx.BoxSizer(wx.HORIZONTAL)
        self.cb_copie_automatique_LaTeX = wx.CheckBox(self)
        self.cb_copie_automatique_LaTeX.SetValue(self.param("copie_automatique_LaTeX"))
        ligne.Add(self.cb_copie_automatique_LaTeX, flag = wx.ALIGN_CENTER_VERTICAL)
        self.st_copie_automatique_LaTeX = wx.StaticText(self, -1, u" Copie au format LaTeX (si possible).")
        ligne.Add(self.st_copie_automatique_LaTeX, flag = wx.ALIGN_CENTER_VERTICAL)
        self.pave.Add(ligne)

        self.EvtCopieAutomatique()
        self.cb_copie_automatique_LaTeX.Bind(wx.EVT_CHECKBOX, self.EvtCopieAutomatiqueLatex)

        # Autres options
        self.options = [(u"Virgule comme séparateur décimal.", u"changer_separateurs"),
##                    (u"Copie du résultat dans le presse-papier.", u"copie_automatique"),
                    (u"Accepter la syntaxe OpenOffice.org", u"formatage_OOo"),
                    (u"Accepter la syntaxe LaTeX", u"formatage_LaTeX"),
                        ]
        self.options_box = []
        for i in range(len(self.options)):
            ligne = wx.BoxSizer(wx.HORIZONTAL)
            self.options_box.append(wx.CheckBox(self))
            ligne.Add(self.options_box[i], flag = wx.ALIGN_CENTER_VERTICAL)
            self.options_box[i].SetValue(self.param(self.options[i][1]))
            def action(event, chaine = self.options[i][1], entree = self.entree, self = self):
                self.param(chaine, not self.param(chaine))
                entree.SetFocus()
            self.options_box[i].Bind(wx.EVT_CHECKBOX, action)
            ligne.Add(wx.StaticText(self, -1, " " + self.options[i][0]), flag = wx.ALIGN_CENTER_VERTICAL)
            self.pave.Add(ligne)


        self.option1 = wx.BoxSizer(wx.HORIZONTAL)
        self.pave.Add(self.option1)
        #wx.CheckBox(self)

        self.option2 = wx.BoxSizer(wx.HORIZONTAL)
        self.pave.Add(self.option2)


        self.sizer = wx.BoxSizer(wx.VERTICAL)
##        self.sizer.Add(self.entrees, 0, wx.ALL, 5)
        self.sizer.Add(self.entree, 0, wx.ALL, 5)
        self.sizer.Add(self.corps, 0, wx.ALL, 5)
        self.SetSizer(self.sizer)
        self.Fit()

        # historique des calculs
##        self.entree.Bind(wx.EVT_KEY_UP, self.EvtChar)
        self.entree.texte.Bind(wx.EVT_RIGHT_DOWN, self.EvtMenu)
##        #self.Bind(wx.EVT_CHAR, self.EvtChar, self.entree)
##        self.valider.Bind(wx.EVT_BUTTON, self.affichage_resultat)
        self.visualisation.Bind(wx.EVT_RIGHT_DOWN, self.EvtMenuVisualisation)


        self.initialiser()

    def activer(self):
        # Actions à effectuer lorsque l'onglet devient actif
        self.entree.SetFocus()


    def _sauvegarder(self, fgeo):
        fgeo.contenu["Calculatrice"] = [{}]
        fgeo.contenu["Calculatrice"][0]["Historique"] = [repr(self.entree.historique)]
#        fgeo.contenu["Calculatrice"][0]["Resultats"] = [repr(self.interprete.derniers_resultats)]
        fgeo.contenu["Calculatrice"][0]["Affichage"] = [self.resultats.GetValue()]
        fgeo.contenu["Calculatrice"][0]["Etat_interne"] = [self.interprete.save_state()]
        fgeo.contenu["Calculatrice"][0]["Options"] = [{}]
        for i in range(len(self.options)):
            fgeo.contenu["Calculatrice"][0]["Options"][0][self.options[i][1]] = [str(self.options_box[i].GetValue())]



    def _ouvrir(self, fgeo):
        if fgeo.contenu.has_key("Calculatrice"):
            calc = fgeo.contenu["Calculatrice"][0]
            self.initialiser()

            self.entree.historique = eval_safe(calc["Historique"][0])
#            self.interprete.derniers_resultats = securite.eval_safe(calc["Resultats"][0])
            self.resultats.SetValue(calc["Affichage"][0] + "\n")
            self.interprete.load_state(calc["Etat_interne"][0])

            liste = calc["Options"][0].items()
            options = [option for aide, option in self.options]
            for key, value in liste:
                value = eval_safe(value[0])
                self.param(key, value)
                if key in options:
                    self.options_box[options.index(key)].SetValue(value)
            # il faudrait encore sauvegarder les variables, mais la encore, 2 problemes :
            # - pb de securite pour evaluer les variables
            # - pb pour obtenir le code source d'une fonction.
            # Pour remedier a cela, il faut envisager de :
            # - creer un module d'interpretation securisee.
            # - rajouter a chaque fonction un attribut __code__, ou creer une nouvelle classe.


    def modifier_pp_texte(self, chaine):
        u"""Modifier le résultat affiché en LaTeX (pretty print)."""
        if self.param("latex"):
            chaine = "$" + chaine + "$"
        else:
            chaine = chaine.replace("\\mapsto", "\\rightarrow")
            if chaine.startswith(r"$\begin{bmatrix}"):
                chaine = chaine.replace(r"\begin{bmatrix}", r'\left({')
                chaine = chaine.replace(r"\end{bmatrix}", r'}\right)')
                chaine = chaine.replace(r"&", r'\,')
        self.pp_texte.set_text(chaine)
        self.visualisation.draw()

    def vers_presse_papier(self, event = None, texte = None):
        if texte is None:
            texte = self.dernier_resultat
        Panel_simple.vers_presse_papier(texte)

    def copier_latex(self, event = None):
        self.vers_presse_papier(texte = self.interprete.latex_dernier_resultat.strip("$"))

    def initialiser(self, event = None):
        self.dernier_resultat = "" # dernier resultat, sous forme de chaine formatee pour l'affichage
        self.entree.initialiser()
        self.interprete.initialiser()
        self.resultats.Clear()

    def affichage_resultat(self, commande, **kw):
        # Commandes spéciales:
        if commande in ('clear', 'clear()', 'efface', 'efface()'):
            self.initialiser()
            self.modifier_pp_texte(u"Calculatrice réinitialisée.")
            return

        self.modifie = True
        try:
            try:
                if kw["shift"]:
                    self.interprete.calcul_exact = False
                resultat, latex = self.interprete.evaluer(commande)
                if latex == "$?$": # provoque une erreur (matplotlib 0.99.1.1)
                    latex = u"Désolé, je ne sais pas faire..."
            finally:
                self.interprete.calcul_exact = self.param('calcul_exact')
            aide = resultat.startswith("\n== Aide sur ")
            #LaTeX
            debug("Expression LaTeX: " + latex)
            try:
                self.modifier_pp_texte((latex or resultat) if not aide else '')
            except Exception:
                print_error()
                self.modifier_pp_texte("<Affichage impossible>")
            #Presse-papier
            self.dernier_resultat = resultat
            if self.param("copie_automatique"):
                if self.param("copie_automatique_LaTeX"):
                    self.copier_latex()
                else:
                    self.vers_presse_papier()
            # TextCtrl
            numero = str(len(self.interprete.derniers_resultats))
            # Évite le décalage entre la première ligne et les suivantes (matrices)
            if "\n" in resultat and not aide:
                resultat = "\n" + "\n".join(20*" " + ligne for ligne in resultat.split("\n"))
            self.resultats.AppendText(u" Calcul n\xb0" + numero + " :   "
                                                        + uu(commande) + u"\n Résultat :"
                                                        + " "*(4+len(numero))
                                                        + resultat + "\n__________________\n\n")
            self.message(u"Calcul effectué." + self.interprete.warning)
            self.entree.Clear()
            self.resultats.SetInsertionPoint(len(self.resultats.GetValue()))
            self.resultats.SetFocus()
            self.resultats.ScrollLines(1)
            self.entree.SetFocus()
        except Exception:
            self.message(u"Calcul impossible.")
            self.entree.SetFocus()
            if param.debug:
                raise


    def EvtMenu(self, event):
        if not event.ControlDown():
            event.Skip()
            return
        def generer_fonction(nom, parenthese = True, self = self):
            def f(event = None, panel = self, nom = nom, parenthese = parenthese):
                deb, fin = panel.entree.GetSelection()
                if parenthese:
                    panel.entree.SetInsertionPoint(fin)
                    panel.entree.WriteText(")")
                    panel.entree.SetInsertionPoint(deb)
                    panel.entree.WriteText(nom + "(")
                    panel.entree.SetFocus()
                    if deb == fin:
                        final = fin + len(nom) + 1
                    else:
                        final = fin + len(nom) + 2
                else:
                    panel.entree.WriteText(nom)
                    final = fin + len(nom)
                panel.entree.SetFocus()
                panel.entree.SetInsertionPoint(final)
                panel.entree.SetSelection(final, final)
            return f
        menu = wx.Menu()
        menu.SetTitle(u"Fonctions mathématiques")
        debut = True
        for rubrique in __classement__:
            if not debut:
                menu.AppendSeparator()
            debut = False
            for titre, nom, doc in __classement__[rubrique]:
                i = wx.NewId()
                menu.Append(i, titre, doc)
                if rubrique != "Symboles":
                    menu.Bind(wx.EVT_MENU, generer_fonction(nom), id =i)
                else:
                    menu.Bind(wx.EVT_MENU, generer_fonction(nom, False), id =i) # pas de parenthese apres un symbole
        self.PopupMenu(menu)
        menu.Destroy()
#        self.entree.SetFocus()


    def EvtMenuVisualisation(self, event):
        menu = wx.Menu()
        i = wx.NewId()
        menu.Append(i, "Copier LaTeX",  "Copier le code LaTeX dans le presse-papier.")
        menu.Bind(wx.EVT_MENU, self.copier_latex, id=i)
        self.PopupMenu(menu)
        menu.Destroy()



    def param(self, parametre, valeur = no_argument, defaut = False):
        if valeur is not no_argument:
            setattr(self.interprete, parametre, valeur)
        return Panel_simple.param(self, parametre = parametre, valeur = valeur, defaut = defaut)

    def EvtCalculExact(self, event = None):
        valeur = self.cb_calcul_exact.GetValue()
        self.param("calcul_exact", not valeur)
        if valeur:
            self.cb_notation_sci.Enable()
            self.st_notation_sci.Enable()
            self.sc_decimales.Enable()
            self.st_decimales.Enable()
        else:
            self.cb_notation_sci.Disable()
            self.st_notation_sci.Disable()
            self.sc_decimales.Disable()
            self.st_decimales.Disable()


    def EvtNotationScientifique(self, event = None):
        self.param("ecriture_scientifique", self.cb_notation_sci.GetValue())
        self.param("ecriture_scientifique_decimales", self.sc_decimales.GetValue())

    def EvtCopieAutomatique(self, event = None):
        valeur = self.cb_copie_automatique.GetValue()
        self.param("copie_automatique", valeur)
        if valeur:
            self.cb_copie_automatique_LaTeX.Enable()
            self.st_copie_automatique_LaTeX.Enable()
        else:
            self.cb_copie_automatique_LaTeX.Disable()
            self.st_copie_automatique_LaTeX.Disable()

    def EvtCopieAutomatiqueLatex(self, event = None):
        self.param("copie_automatique_LaTeX", self.cb_copie_automatique_LaTeX.GetValue())

    def EtatInterne(self, event):
        contenu = self.interprete.save_state()
        h = FenCode(self, u"État interne de l'inteprète", contenu, self.interprete.load_state)
        h.Show(True)
Пример #25
0
class matplotsink(wx.Panel):
    def __init__(self, parent, title, queue, gsz, zoom):
        wx.Panel.__init__(self, parent, wx.SIMPLE_BORDER)

        self.gsz = gsz
        self.parent = parent
        self.title = title
        self.q = queue
        self.zoom = zoom
        self.paused = False

        #        self.create_menu()
        #        self.create_status_bar()
        self.create_main_panel()

    def create_menu(self):
        self.menubar = wx.MenuBar()

        menu_file = wx.Menu()
        m_expt = menu_file.Append(-1, "&Save plot\tCtrl-S",
                                  "Save plot to file")
        self.Bind(wx.EVT_MENU, self.on_save_plot, m_expt)
        menu_file.AppendSeparator()
        m_exit = menu_file.Append(-1, "E&xit\tCtrl-X", "Exit")
        self.Bind(wx.EVT_MENU, self.on_exit, m_exit)
        self.menubar.Append(menu_file, "&File")
        self.SetMenuBar(self.menubar)

    def create_main_panel(self):
        self.panel = self

        self.init_plot()
        self.canvas = FigCanvas(self.panel, -1, self.fig)
        self.scroll_range = 400
        self.canvas.SetScrollbar(wx.HORIZONTAL, 0, 5, self.scroll_range)
        self.canvas.Bind(wx.EVT_SCROLLWIN, self.OnScrollEvt)

        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.cb_grid = wx.CheckBox(self.panel,
                                   -1,
                                   "Show Grid",
                                   style=wx.ALIGN_RIGHT)
        self.Bind(wx.EVT_CHECKBOX, self.on_cb_grid, self.cb_grid)
        self.cb_grid.SetValue(True)

        self.cb_xlab = wx.CheckBox(self.panel,
                                   -1,
                                   "Show X labels",
                                   style=wx.ALIGN_RIGHT)
        self.Bind(wx.EVT_CHECKBOX, self.on_cb_xlab, self.cb_xlab)
        self.cb_xlab.SetValue(True)

        self.hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        self.hbox1.Add(self.pause_button,
                       border=5,
                       flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)
        self.hbox1.AddSpacer(20)
        self.hbox1.Add(self.cb_grid,
                       border=5,
                       flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)
        self.hbox1.AddSpacer(10)
        self.hbox1.Add(self.cb_xlab,
                       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)
        self.ani = animation.FuncAnimation(self.fig,
                                           self.draw_plot,
                                           interval=100)

    def OnScrollEvt(self, event):
        self.i_start = event.GetPosition()
        self.i_end = self.i_window + event.GetPosition()
        self.draw_plot(0)

    def create_status_bar(self):
        self.statusbar = self.CreateStatusBar()

    def draw_test(self, event):
        self.xar = np.arange(len(self.q.queue))
        self.yar = np.array(self.q.queue)
        self.axes.plot(self.xar, self.yar)

    def init_plot(self):
        self.dpi = 100
        self.fig = Figure((3.0, 3.0), dpi=self.dpi)
        self.fig.set_size_inches(7.0, 4.0)
        self.fig.set_dpi(self.dpi)

        self.axes = self.fig.add_subplot(111)
        self.axes.set_axis_bgcolor('black')
        self.axes.set_title(self.title, size=12)

        pylab.setp(self.axes.get_xticklabels(), fontsize=8)
        pylab.setp(self.axes.get_yticklabels(), fontsize=8)
        self.i_window = self.gsz
        self.i_start = 0
        self.i_end = self.i_start + self.i_window
        # plot the data as a line series, and save the reference
        # to the plotted line series
        #
        self.plot_data = self.axes.plot(
            [],
            linewidth=1,
            color=(1, 1, 0),
        )[0]

    def draw_plot(self, event):
        """ Redraws the plot
         """
        if len(list(self.q.queue)) > 1 and not self.paused:

            if self.zoom:
                xmax = len(list(
                    self.q.queue)) if len(list(self.q.queue)) > 50 else 50

                xmin = xmax - 50
                # for ymin and ymax, find the minimal and maximal values
                # in the data set and add a mininal margin.
                #
                # note that it's easy to change this scheme to the
                # minimal/maximal value in the current display, and not
                # the whole data set.
                #
                ymin = round(min(list(self.q.queue)), 0) - 1

                ymax = round(max(list(self.q.queue)), 0) + 1

                self.axes.set_xbound(lower=xmin, upper=xmax)
                self.axes.set_ybound(lower=ymin, upper=ymax)

                # anecdote: axes.grid assumes b=True if any other flag is
                # given even if b is set to False.
                # so just passing the flag into the first statement won't
                # work.
                #
                if self.cb_grid.IsChecked():
                    self.axes.grid(True, color='gray')
                else:
                    self.axes.grid(False)

                # Using setp here is convenient, because get_xticklabels
                # returns a list over which one needs to explicitly
                # iterate, and setp already handles this.
                #
                pylab.setp(self.axes.get_xticklabels(),
                           visible=self.cb_xlab.IsChecked())

                self.plot_data.set_xdata(np.arange(len(list(self.q.queue))))
                self.plot_data.set_ydata(np.array(list(self.q.queue)))
                self.canvas.draw()

            else:
                if self.cb_grid.IsChecked():
                    self.axes.grid(True, color='gray')
                else:
                    self.axes.grid(False)

        # Using setp here is convenient, because get_xticklabels
        # returns a list over which one needs to explicitly
        # iterate, and setp already handles this.

                pylab.setp(self.axes.get_xticklabels(),
                           visible=self.cb_xlab.IsChecked())

                self.plot_data.set_xdata(
                    np.arange(len(list(
                        self.q.queue)))[self.i_start:self.i_end])
                self.plot_data.set_ydata(
                    np.array(list(self.q.queue))[self.i_start:self.i_end])
                self.axes.set_xlim(
                    min(
                        np.arange(len(list(
                            self.q.queue)))[self.i_start:self.i_end]),
                    max(
                        np.arange(len(list(
                            self.q.queue)))[self.i_start:self.i_end]))
                #		 if self.zoom:
                self.axes.set_ylim(min(np.array(list(self.q.queue))),
                                   max(np.array(list(self.q.queue))))

                self.canvas.draw()

    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_cb_grid(self, event):
        self.draw_plot(0)

    def on_cb_xlab(self, event):
        self.draw_plot(0)

    def on_save_plot(self, event):
        file_choices = "PNG (*.png)|*.png"

        dlg = wx.FileDialog(self,
                            message="Save plot as...",
                            defaultDir=os.getcwd(),
                            defaultFile="plot.png",
                            wildcard=file_choices,
                            style=wx.SAVE)

        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            self.canvas.print_figure(path, dpi=self.dpi)
            self.flash_status_message("Saved to %s" % path)

    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.)
        #
        if not self.paused:
            self.data += self.datagen.next()
        self.draw_plot(0)

    def on_exit(self, event):
        self.Destroy()

    def flash_status_message(self, msg, flash_len_ms=1500):
        self.statusbar.SetStatusText(msg)
        self.timeroff = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_flash_status_off, self.timeroff)
        self.timeroff.Start(flash_len_ms, oneShot=True)

    def on_flash_status_off(self, event):
        self.statusbar.SetStatusText('')
Пример #26
0
class PlotPanel(wx.Panel):
    def __init__(self, parent, app):
        self._app = app
        self._plot_context = app._plot_context
        self.animation = None
        self.canvas_force_resize = False
        self.canvas_last_resize_s = None

        wx.Panel.__init__(self, parent, -1)

        self.canvas = FigureCanvasWxAgg(self, -1, self._plot_context.fig)
        self.toolbar = NavigationToolbar2WxAgg(
            self.canvas)  # matplotlib toolbar
        self.toolbar.Realize()

        self.canvas.Bind(wx.EVT_SIZE, self.OnSizeCanvas)

        # Now put all into a sizer which will resize the figure when the window size changes
        sizer = wx.BoxSizer(wx.VERTICAL)
        # This way of adding to sizer allows resizing
        sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        # Best to allow the toolbar to resize!
        sizer.Add(self.toolbar, 0, wx.GROW)
        self.SetSizer(sizer)
        self.Fit()

    def OnSizeCanvas(self, event):
        logger.debug(f"_on_size_canvas {event.GetSize()}")
        self.canvas_last_resize_s = time.time()
        if self.canvas_force_resize:
            event.Skip()

    def init_plot_data(self):
        self.toolbar.update()  # Not sure why this is needed - ADS

        def endless_iter():
            yield from itertools.count(start=42)

        self._plot_context.plotData.startup_duration.log(
            "FuncAnimation() - before")
        self.animation = matplotlib.animation.FuncAnimation(
            fig=self._plot_context.fig,
            func=self.animate,
            frames=endless_iter(),
            # Delay between frames in milliseconds
            interval=1000,
            # A function used to draw a clear frame. If not given, the results of drawing from the first item in the frames sequence will be used.
            init_func=None,
            repeat=False,
        )
        self._plot_context.plotData.startup_duration.log(
            "FuncAnimation() - after")

        # Important: If this statement is BEFORE 'FuncAnimation', the animation sometimes does not start!
        with Duration("update_presentation():") as elapsed:
            self._plot_context.update_presentation()

    def GetToolBar(self):
        # You will need to override GetToolBar if you are using an
        # unmanaged toolbar in your frame
        return self.toolbar

    @log_duration
    def animate(self, i):
        self._plot_context.plotData.startup_duration.log(
            "animate() - beginning")

        if self.canvas_last_resize_s:
            # The frame has been resized
            if self.canvas_last_resize_s + 0.5 < time.time():
                # And the last event was more than 500ms ago
                logger.info("matplotlib-canvas: delayed resize")
                # self.canvas.SetSize(self.canvas_requested_size)
                self.canvas_force_resize = True
                self.Layout()
                self.canvas_force_resize = False
                self.canvas_last_resize_s = None

        self._plot_context.animate()
Пример #27
0
class PlotFrame(wx.Frame):
    help_msg = """  Menus for  
     Save           export figure (png,eps,bmp) to file 
     Copy           copy bitmap of figure to the system clipboard
     Print Setup    setup size of figure for printing
     Print Preview  preview printer page
     Print          send figure to a system printer
     Exit           end application
    
     where 'figure' means an image of the matplotlib canvas
 
  In addition, "Ctrl-C" is bound to copy-figure-to-clipboard
"""

    start_msg = """        Use Menus to test printing
        or Ctrl-C to copy plot image to clipboard  """

    about_msg = """        printing_in_wx version 0.1  12-Nov-2004
        Matt Newville <*****@*****.**>"""

    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Test Printing with WX Backend")
        self.fig = Figure((5.0, 3.0), 100)
        self.canvas = FigCanvas(self, -1, self.fig)
        self.axes = self.fig.add_axes([0.15, 0.15, 0.75, 0.75])

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        sizer.Add(wx.StaticText(self, -1, self.start_msg), 0,
                  wx.ALIGN_LEFT | wx.TOP)

        self.canvas.Bind(wx.EVT_KEY_DOWN, self.onKeyEvent)

        self.SetSizer(sizer)
        self.Fit()
        self.Build_Menus()
        self.Plot_Data()

    def Build_Menus(self):
        """ build menus """
        MENU_EXIT = wx.NewId()
        MENU_SAVE = wx.NewId()
        MENU_PRINT = wx.NewId()
        MENU_PSETUP = wx.NewId()
        MENU_PREVIEW = wx.NewId()
        MENU_CLIPB = wx.NewId()
        MENU_HELP = wx.NewId()

        menuBar = wx.MenuBar()

        f0 = wx.Menu()
        f0.Append(MENU_SAVE, "&Export", "Save Image of Plot")
        f0.AppendSeparator()
        f0.Append(MENU_PSETUP, "Page Setup...", "Printer Setup")
        f0.Append(MENU_PREVIEW, "Print Preview...", "Print Preview")
        f0.Append(MENU_PRINT, "&Print", "Print Plot")
        f0.AppendSeparator()
        f0.Append(MENU_EXIT, "E&xit", "Exit")
        menuBar.Append(f0, "&File")

        f1 = wx.Menu()
        f1.Append(MENU_HELP, "Quick Reference", "Quick Reference")

        menuBar.Append(f1, "&Help")

        self.SetMenuBar(menuBar)

        self.Bind(wx.EVT_MENU, self.onPrint, id=MENU_PRINT)
        self.Bind(wx.EVT_MENU, self.onPrinterSetup, id=MENU_PSETUP)
        self.Bind(wx.EVT_MENU, self.onPrinterPreview, id=MENU_PREVIEW)
        self.Bind(wx.EVT_MENU, self.onClipboard, id=MENU_CLIPB)
        self.Bind(wx.EVT_MENU, self.onExport, id=MENU_SAVE)
        self.Bind(wx.EVT_MENU, self.onExit, id=MENU_EXIT)
        self.Bind(wx.EVT_MENU, self.onHelp, id=MENU_HELP)

    # the printer / clipboard methods are implemented
    # in backend_wx, and so are very simple to use.
    def onPrinterSetup(self, event=None):
        self.canvas.Printer_Setup(event=event)

    def onPrinterPreview(self, event=None):
        self.canvas.Printer_Preview(event=event)

    def onPrint(self, event=None):
        self.canvas.Printer_Print(event=event)

    def onClipboard(self, event=None):
        self.canvas.Copy_to_Clipboard(event=event)

    def onKeyEvent(self, event=None):
        """ capture , act upon keystroke events"""
        if event == None: return
        key = event.KeyCode()
        if (key < wx.WXK_SPACE or key > 255): return

        if (event.ControlDown() and chr(key) == 'C'):  # Ctrl-C
            self.onClipboard(event=event)

    def onHelp(self, event=None):
        dlg = wx.MessageDialog(self, self.help_msg, "Quick Reference",
                               wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def onExport(self, event=None):
        """ save figure image to file"""
        file_choices = "PNG (*.png)|*.png|" \
                       "PS (*.ps)|*.ps|" \
                       "EPS (*.eps)|*.eps|" \
                       "BMP (*.bmp)|*.bmp"

        thisdir = os.getcwd()

        dlg = wx.FileDialog(self,
                            message='Save Plot Figure as...',
                            defaultDir=thisdir,
                            defaultFile='plot.png',
                            wildcard=file_choices,
                            style=wx.SAVE)

        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            self.canvas.print_figure(path, dpi=300)
            if (path.find(thisdir) == 0):
                path = path[len(thisdir) + 1:]
            print 'Saved plot to %s' % path

    def onExit(self, event=None):
        self.Destroy()

    def Plot_Data(self):
        t = numpy.arange(0.0, 5.0, 0.01)
        s = numpy.sin(2.0 * numpy.pi * t)
        c = numpy.cos(0.4 * numpy.pi * t)
        self.axes.plot(t, s)
        self.axes.plot(t, c)
Пример #28
0
class PlotFrame(wx.Frame):
    help_msg="""  Menus for
     Import...import project settings file
     Export...export figure (png, jpg) to file
     Print Setup...setup size of figure for printing
     Print Preview...preview printer page
     Print...send figure to a system printer
     Exit...end application

     Basic-2D...View basic 2D representation of data
     Advanced-2D...View 2D representation (with span selection control)
     Advanced-3D...View 3D representation of data

     View-Grid...Toggle grid
     View-Legend...Toggle legend
     View-Fill...Toggle fill representation of data (only for 2D)

     where 'figure' means an image of the matplotlib canvas

     In addition, "Ctrl-C" is bound to copy-figure-to-clipboard    
    """

    about_msg="""
        Option_price_visualisation v0.1  29-Aug-2013

        Nathan Floor, [email protected]
    """

    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Visualise Option Prices and Greeks", size=(300, 500))
        self.Bind(wx.EVT_KEY_DOWN, self.onKeyEvent)

        # intialise variables when start program
        self.viewLegend = False
        self.viewGrid = True
        self.viewFill = False
        
        self.reInitialiseData()
        
        # build interface
        self.Build_Menus()
        self.Build_Panel()
        self.statusbar = self.CreateStatusBar()
        self.Plot_Data()
        self.SetSize(size=(900, 550))

    def reInitialiseData(self):
        self.fileReader = csvReader.Reader()
        self.current_view = 0
        self.time = numpy.arange(0, 31, 1)
        self.indmin = 0
        self.indmax = 31
        self.strike_price = 0

        # initialise data arrays
        self.option_price = []
        self.stock_price = []
        self.delta = []
        self.gamma = []
        self.vega = []
        self.theta = []
        self.rho = []
        self.risidual = []
        
        # initialise secondary data sets
        self.option_price_fill = []
        self.time_span_fill = []
        self.delta_fill = []
        self.gamma_fill = []
        self.vega_fill = []
        self.theta_fill = []
        self.rho_fill = []
        
        # initialise bump values
        self.stock_bump = 0
        self.time_bump = 0
        self.rate_bump = 0
        self.volitile_bump = 0

    # on span-selection of graph
    def onselect(self, xmin, xmax):
        # initialise data sets
        option_price = []
        delta = []
        gamma = []
        theta = []
        rho = []
        vega = []
        maxYLimlist = []
        minYLimlist = []

        # identify the indices of new data set based on selection
        self.indmin = int(xmin)
        #self.indmax = numpy.searchsorted(t, (xmin, xmax))
        self.indmax = min(len(self.time)-1, int(xmax)+1)

        self.time_span_fill = self.time[self.indmin:self.indmax]
        if len(self.option_price) > 0:
            option_price = numpy.array(map(float, self.option_price[self.stock_bump]))
            self.option_price_fill = option_price[self.indmin:self.indmax]
            #  append to lists for axes limits
            maxYLimlist.append(max(self.option_price_fill))
            minYLimlist.append(min(self.option_price_fill))
            if not self.viewFill:
                self.line1.set_data(self.time_span_fill, self.option_price_fill)
        if len(self.delta) > 0:
            delta = numpy.array(map(float, self.delta[self.stock_bump]))
            self.delta_fill = delta[self.indmin:self.indmax]
            #  append to lists for axes limits
            maxYLimlist.append(max(self.delta_fill))
            minYLimlist.append(min(self.delta_fill))
            if not self.viewFill:
                self.line2.set_data(self.time_span_fill, self.delta_fill)
        if len(self.gamma) > 0:
            gamma = numpy.array(map(float, self.gamma[self.stock_bump]))
            self.gamma_fill = gamma[self.indmin:self.indmax]
            #  append to lists for axes limits
            maxYLimlist.append(max(self.gamma_fill))
            minYLimlist.append(min(self.gamma_fill))
            if not self.viewFill:
                self.line3.set_data(self.time_span_fill, self.gamma_fill)
        if len(self.theta) > 0:
            theta = numpy.array(map(float, self.theta[self.time_bump]))
            self.theta_fill = theta[self.indmin:self.indmax]
            #  append to lists for axes limits
            maxYLimlist.append(max(self.theta_fill))
            minYLimlist.append(min(self.theta_fill))
            if not self.viewFill:
                self.line4.set_data(self.time_span_fill, self.theta_fill)
        if len(self.rho) > 0:
            rho = numpy.array(map(float, self.rho[self.rate_bump]))
            self.rho_fill = rho[self.indmin:self.indmax]
            #  append to lists for axes limits
            maxYLimlist.append(max(self.rho_fill))
            minYLimlist.append(min(self.rho_fill))
            if not self.viewFill:
                self.line5.set_data(self.time_span_fill, self.rho_fill)
        if len(self.vega) > 0:
            vega = numpy.array(map(float, self.vega[self.volitile_bump]))
            self.vega_fill = vega[self.indmin:self.indmax]
            #  append to lists for axes limits
            maxYLimlist.append(max(self.vega_fill))
            minYLimlist.append(min(self.vega_fill))
            if not self.viewFill:
                self.line6.set_data(self.time_span_fill, self.vega_fill)
        if len(self.risidual) > 0:
            risidual = numpy.array(map(float, self.risidual[self.stock_bump]))
            self.risidual_fill = risidual[self.indmin:self.indmax]
            #  append to lists for axes limits
            maxYLimlist.append(max(self.risidual_fill))
            minYLimlist.append(min(self.risidual_fill))
            if not self.viewFill:
                self.line7.set_data(self.time_span_fill, self.risidual_fill)

        if len(maxYLimlist) > 0:
            maxYLim = max(maxYLimlist)
        else:
            maxYLim = 1
        if len(minYLimlist) > 0:
            minYLim = min(minYLimlist)
        else:
            minYLim = 0

        self.axes2.set_xlim(self.time_span_fill[0]-1, self.time_span_fill[-1]+1)
        self.axes2.set_ylim(minYLim, maxYLim)
        if not self.viewFill:
            self.canvas.draw()
        else:
            self.Plot_Data()

    def Build_Panel(self):
        self.panel = wx.Panel(self)

        # Create Figure and canvas objects
        self.fig = Figure((6.0, 4.0))
        self.canvas = FigCanvas(self.panel, -1, self.fig)
        self.axes = self.fig.add_subplot(111)

        # setup slider-widgets for controlling GUI
        self.sliderPanel = wx.Panel(self.panel)
        self.stockSlider_label = wx.StaticText(self.sliderPanel, -1, "Stock Price: ")
        self.stockSlider = wx.Slider(self.sliderPanel, value=5, minValue=1, maxValue=9, 
            pos=(20, 20), size=(100,-1), style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS)
        # self.stockSlider.SetTickFreq(9, 1)
        self.rateSlider_label = wx.StaticText(self.sliderPanel, -1, "Interest Rate: ")
        self.rateSlider = wx.Slider(self.sliderPanel, value=5, minValue=1, maxValue=9, 
            pos=(20, 20), size=(100,-1), style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS)
        self.rateSlider.SetTickFreq(1, 1)
        self.timeStepSlider_label = wx.StaticText(self.sliderPanel, -1, "Time Step: ")
        self.timeStepSlider = wx.Slider(self.sliderPanel, value=5, minValue=1, maxValue=9, 
            pos=(20, 20), size=(100,-1), style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS)
        self.timeStepSlider.SetTickFreq(1, 1)

        self.Bind(wx.EVT_SLIDER, self.onStockSlider, self.stockSlider)
        self.Bind(wx.EVT_SLIDER, self.onRateSlider, self.rateSlider)
        self.Bind(wx.EVT_SLIDER, self.ontimeStepSlider, self.timeStepSlider)        

        # setup options-widgets for controlling graphs
        self.callRadio = wx.RadioButton(self.panel, label="Call options", pos=(10, 10))
        self.putRadio = wx.RadioButton(self.panel, label="Put options", pos=(10, 30))
        self.callRadio.SetValue(True)        
        self.spaceKeeper = wx.StaticText(self.panel, -1, '')
        self.optionPriceCheck = wx.CheckBox(self.panel, label="view Option Price", pos=(20, 20))
        self.deltaCheck = wx.CheckBox(self.panel, label="show Delta", pos=(20, 20))
        self.gammaCheck = wx.CheckBox(self.panel, label="show Gamma", pos=(20, 20))
        self.rhoCheck = wx.CheckBox(self.panel, label="show Rho", pos=(20, 20))
        self.thetaCheck = wx.CheckBox(self.panel, label="show Theta", pos=(20, 20))
        self.fillCheck = wx.CheckBox(self.panel, label="show fill feature", pos=(20, 20))
        self.risidualCheck = wx.CheckBox(self.panel, label="Show Residual", pos=(20, 20))
        self.differenceCheck = wx.CheckBox(self.panel, label="Show Difference", pos=(20, 20))
        self.effectCheck = wx.CheckBox(self.panel, label="Show Greek's effect on option price", pos=(20, 20))
        self.effectCheck.SetValue(True)

        self.Bind(wx.EVT_RADIOBUTTON, self.onCallRadio, self.callRadio)
        self.Bind(wx.EVT_RADIOBUTTON, self.onPutRadio, self.putRadio)
        self.Bind(wx.EVT_CHECKBOX, self.onOptionPrice, self.optionPriceCheck)
        self.Bind(wx.EVT_CHECKBOX, self.onDelta, self.deltaCheck)
        self.Bind(wx.EVT_CHECKBOX, self.onGamma, self.gammaCheck)
        self.Bind(wx.EVT_CHECKBOX, self.onRho, self.rhoCheck)
        self.Bind(wx.EVT_CHECKBOX, self.onTheta, self.thetaCheck)
        self.Bind(wx.EVT_CHECKBOX, self.onRisidual, self.risidualCheck)
        self.Bind(wx.EVT_CHECKBOX, self.onDifferenceCheck, self.differenceCheck)
        self.Bind(wx.EVT_CHECKBOX, self.onShowEffects, self.effectCheck)
        self.Bind(wx.EVT_CHECKBOX, self.onShowFillEffect, self.fillCheck)

        # Create the navigation toolbar, tied to the canvas
        self.toolbar = NavigationToolbar(self.canvas)

        ####################
        # Layout with sizers
        ####################
        flags = wx.ALIGN_LEFT | wx.ALL | wx.ALIGN_CENTER_VERTICAL
        self.sizer = wx.BoxSizer(wx.VERTICAL)

        self.hboxMainBlock = wx.BoxSizer(wx.HORIZONTAL)
        self.vboxOptions = wx.BoxSizer(wx.VERTICAL)
        self.hboxSliders = wx.BoxSizer(wx.HORIZONTAL)
        self.flexiGridSizer = wx.FlexGridSizer(4, 2, 3, 10)

        # adds border around sliders to group related widgets
        self.vboxOptions.AddSpacer(10)
        self.sliderStaticBox = wx.StaticBox(self.sliderPanel, -1, 'Bump Sliders')
        self.sliderBorder = wx.StaticBoxSizer(self.sliderStaticBox, orient=wx.VERTICAL)
        self.flexiGridSizer.AddMany([(self.stockSlider_label), (self.stockSlider, 1, wx.ALL), 
            (self.rateSlider_label), (self.rateSlider, 1, wx.EXPAND), (self.timeStepSlider_label), (self.timeStepSlider, 1, wx.EXPAND)])
        self.sliderBorder.Add(self.flexiGridSizer, 1, wx.ALL, 5)
        self.sliderPanel.SetSizer(self.sliderBorder)
        self.vboxOptions.Add(self.sliderPanel, 0, flag=wx.ALIGN_LEFT|wx.ALL)

        # add border for type of option price
        self.optionsBorder = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, 'Option Price Type'), orient=wx.VERTICAL)
        self.flexiOptions = wx.FlexGridSizer(3, 1, 3, 10)
        self.flexiOptions.AddMany([(self.callRadio, 1, wx.EXPAND), 
            (self.putRadio, 1, wx.EXPAND), (self.optionPriceCheck, 1, wx.EXPAND)])            
        self.optionsBorder.Add(self.flexiOptions, 1, wx.ALL, 5)
        self.vboxOptions.Add(self.optionsBorder, 0, flag=wx.ALIGN_LEFT|wx.ALL|wx.GROW)
        
        # add border for greeks
        self.greekOptionsBorder = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, 'Greek effect Options'), orient=wx.VERTICAL)
        self.flexiOptions2 = wx.FlexGridSizer(6, 1, 3, 10)
        self.flexiOptions2.AddMany([(self.deltaCheck, 1, wx.EXPAND), (self.gammaCheck, 1, wx.EXPAND), 
            (self.rhoCheck, 1, wx.EXPAND), (self.thetaCheck, 1, wx.EXPAND), (self.risidualCheck, 1, wx.EXPAND)])
        self.greekOptionsBorder.Add(self.flexiOptions2, 1, wx.ALL, 5)
        self.vboxOptions.Add(self.greekOptionsBorder, 1, flag=wx.ALIGN_LEFT|wx.ALL|wx.GROW)
        #self.vboxOptions.AddSpacer(5)
        
        # add border for other checkable options
        self.otherOptionsBorder = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, 'Extra Options'), orient=wx.VERTICAL)
        self.flexiOptions3 = wx.FlexGridSizer(3, 1, 3, 10)
        self.flexiOptions3.AddMany([(self.fillCheck, 1, wx.EXPAND), (self.differenceCheck, 1, wx.EXPAND), 
            (self.effectCheck, 1, wx.EXPAND)])
        self.otherOptionsBorder.Add(self.flexiOptions3, 1, wx.ALL, 5)
        self.vboxOptions.Add(self.otherOptionsBorder, 0, flag=wx.ALIGN_LEFT|wx.ALL|wx.GROW)
        self.vboxOptions.AddSpacer(5)

        self.hboxMainBlock.Add(self.vboxOptions, 0, flag=flags)
        self.hboxMainBlock.Add(self.canvas, 1, flag=wx.ALIGN_RIGHT|wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
        self.sizer.Add(self.hboxMainBlock, 1, wx.ALL|wx.EXPAND)

        self.sizer.Add(self.toolbar, 0, wx.ALL|wx.ALIGN_RIGHT)
        self.sizer.AddSpacer(1)

        self.canvas.Bind(wx.EVT_KEY_DOWN, self.onKeyEvent)
        self.Bind(wx.EVT_CLOSE, self.onExit)

        self.panel.SetSizer(self.sizer)
        self.sizer.Fit(self)
        self.Center()

    def Build_Menus(self):
        """ build menus """
        MENU_EXIT = wx.NewId()
        MENU_OPEN = wx.NewId()
        MENU_SAVE = wx.NewId()
        MENU_PRINT = wx.NewId()
        MENU_PSETUP = wx.NewId()
        MENU_PREVIEW =wx.NewId()
        MENU_CLIPB =wx.NewId()
        MENU_VIEW_GRID = wx.NewId()
        MENU_HELP =wx.NewId()
        MENU_BASIC = wx.NewId()
        MENU_ADVANCE = wx.NewId()
        MENU_LEGEND = wx.NewId()
        MENU_3D = wx.NewId()
        MENU_ABOUT = wx.NewId()

        menuBar = wx.MenuBar()

        f0 = wx.Menu()
        importItem = wx.MenuItem(f0, MENU_OPEN, "&Import\tCtrl+I")
        f0.AppendItem(importItem)  
        f0.Append(MENU_SAVE,   "&Export",   "Save Image of Plot")
        f0.AppendSeparator()
        printMenu = wx.Menu()
        printMenu.Append(MENU_PSETUP, "Page Setup...",    "Printer Setup")
        printMenu.Append(MENU_PREVIEW,"Print Preview...", "Print Preview")
        printItem = wx.MenuItem(printMenu, MENU_PRINT,  "Print\tCtrl+P")
        printMenu.AppendItem(printItem)
        f0.AppendMenu(-1, '&Print', printMenu)
        f0.AppendSeparator()
        exitItem = wx.MenuItem(f0, MENU_EXIT, 'E&xit\tCtrl+Q')
        f0.AppendItem(exitItem)
        menuBar.Append(f0,     "&File")

        f1 = wx.Menu()
        f1.Append(MENU_BASIC, '&Basic', "Basic View(2D)")
        f1.Append(MENU_ADVANCE, '&Advanced-2D', "Advanced View(2D)")
        f1.Append(MENU_3D, 'A&dvanced-3D', "Advanced View(3D)")

        optionsMenu = wx.Menu()
        viewGridItem = wx.MenuItem(optionsMenu, MENU_VIEW_GRID, 'View &Grid\tCtrl+G')
        optionsMenu.AppendItem(viewGridItem)
        viewLegendItem = wx.MenuItem(optionsMenu, MENU_LEGEND, 'View &Legend\tCtrl+L')
        optionsMenu.AppendItem(viewLegendItem)
        f1.AppendMenu(-1, "&Options", optionsMenu)

        menuBar.Append(f1, "&View")

        f2 = wx.Menu()
        f2.Append(MENU_HELP, "Quick &Reference",  "Quick Reference")
        f2.Append(MENU_ABOUT, "&About",  "About this interface")
        menuBar.Append(f2, "&Help")

        self.SetMenuBar(menuBar)

        self.Bind(wx.EVT_MENU, self.onImport,       id=MENU_OPEN)
        self.Bind(wx.EVT_MENU, self.onPrint,        id=MENU_PRINT)
        self.Bind(wx.EVT_MENU, self.onPrinterSetup, id=MENU_PSETUP)
        self.Bind(wx.EVT_MENU, self.onPrinterPreview, id=MENU_PREVIEW)
        self.Bind(wx.EVT_MENU, self.onClipboard,    id=MENU_CLIPB)
        self.Bind(wx.EVT_MENU, self.onExport,       id=MENU_SAVE)
        self.Bind(wx.EVT_MENU, self.onExit ,        id=MENU_EXIT)
        self.Bind(wx.EVT_MENU, self.onViewGrid,     id=MENU_VIEW_GRID)
        self.Bind(wx.EVT_MENU, self.onViewLegend,     id=MENU_LEGEND)
        self.Bind(wx.EVT_MENU, self.onHelp,         id=MENU_HELP)
        self.Bind(wx.EVT_MENU, self.onAbout,         id=MENU_ABOUT)
        self.Bind(wx.EVT_MENU, self.onBasicView,    id=MENU_BASIC)
        self.Bind(wx.EVT_MENU, self.onAdvancedView, id=MENU_ADVANCE)
        self.Bind(wx.EVT_MENU, self.onAdvanced3DView, id=MENU_3D)

    """ Menu event methods """
    def onViewLegend(self, event=None):
        if self.viewLegend:
            self.viewLegend = False
            self.Plot_Data()
        else:
            self.viewLegend = True
            # use proxy artist
            plot_op = Line2D([], [], linewidth=3, color="black") 
            plot_delta = Line2D([], [], linewidth=3, color="royalblue") 
            plot_gamma = Line2D([], [], linewidth=3, color="cyan") 
            plot_theta = Line2D([], [], linewidth=3, color="green") 
            plot_rho = Line2D([], [], linewidth=3, color="darkorange") 
            plot_risidual = Line2D([], [], linewidth=3, color="purple")

            # Shink current axis by 15%
            box = self.axes.get_position()
            self.axes.set_position([box.x0, box.y0, box.width * 0.88, box.height])
            # Put a legend to the right of the current axis
            self.axes.legend([plot_op, plot_delta, plot_gamma, plot_theta, plot_rho, plot_risidual], ['Option Price', 'Delta', 'Gamma', 'Theta', 'Rho', 'Residual'],
                loc='center left', bbox_to_anchor=(1, 0.5), prop={'size':8})

            if self.current_view == 1:
                box = self.axes2.get_position()
                self.axes2.set_position([box.x0, box.y0, box.width * 0.88, box.height])
                # Put a legend to the right of the current axis
                self.axes2.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop={'size':8})
            self.canvas.draw()

    def onBasicView(self, event=None):
        self.current_view = 0
        # show sliders panel
        self.sliderPanel.Enable()
        self.toolbar.Enable()
        self.fillCheck.Enable()
        self.panel.Layout()
        self.Plot_Data()

    def onAdvancedView(self, event=None):
        self.current_view = 1
        # show sliders panel
        self.sliderPanel.Enable()
        self.toolbar.Enable()
        self.fillCheck.Enable()
        self.panel.Layout()
        self.Plot_Data()

    def onAdvanced3DView(self, event=None):
        self.current_view = 2
        # hide slider panel since will not be used
        self.sliderPanel.Disable()
        self.toolbar.Disable()
        self.fillCheck.Disable()
        self.panel.Layout()   
        self.Plot_Data()

    def onPrinterSetup(self,event=None):
        self.canvas.Printer_Setup(event=event)

    def onPrinterPreview(self,event=None):
        self.canvas.Printer_Preview(event=event)

    def onPrint(self,event=None):
        self.canvas.Printer_Print(event=event)

    def onClipboard(self,event=None):
        self.canvas.Copy_to_Clipboard(event=event)

    def onKeyEvent(self,event=None):
        """ capture and act upon keystroke events """
        if event == None: return
        key = event.GetKeyCode()
        if (key < wx.WXK_SPACE or  key > 255):  return

        if (event.ControlDown() and chr(key)=='C'): # Ctrl-C
            self.onClipboard(event=event)
        if (event.ControlDown() and chr(key)=='P'): # Ctrl-P
            self.onPrinterPreview(event=event)

    def onHelp(self, event=None):
        dlg = wx.MessageDialog(self, self.help_msg, "Quick Reference", wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def onAbout(self, event=None):
        dlg = wx.MessageDialog(self, self.about_msg, "About", wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def onViewGrid(self, event=None):
        if self.viewGrid:
            self.viewGrid = False
        else:
            self.viewGrid = True
        for a in self.fig.axes:
            a.grid(self.viewGrid)
        self.canvas.draw()

    def onExport(self,event=None):
        """ save figure image to file"""
        file_choices = "PNG (*.png)|*.png|" \
                       "JPEG (*.jpg)|*.jpg|" \
                       "BMP (*.bmp)|*.bmp"

        thisdir  = os.getcwd()

        dlg = wx.FileDialog(self, message='Save Plot Figure as...',
                            defaultDir = thisdir, defaultFile='plot.png',
                            wildcard=file_choices, style=wx.SAVE)

        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            self.canvas.print_figure(path,dpi=300)
            if (path.find(thisdir) ==  0):
                path = path[len(thisdir)+1:]
            print('Saved plot to %s' % path)

    def onImport(self, event=None):
        """ Import csv file of option prices and greeks """
        file_choices = "SETTINGS (*.settings)|*.settings"
        thisdir  = ''.join(os.getcwd()+'/data')

        # import output file
        dlg = wx.FileDialog(self, message='Import option prices and greeks (Outputs)',
                            defaultDir = thisdir, defaultFile='data.settings',
                            wildcard=file_choices, style=wx.OPEN)

        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            projectDir = path.rsplit('/', 1)[0]
            #projectDir = path.rsplit('\\', 1)[0]
            self.reInitialiseData()
            
            # this also involves reading in all the data
            self.number_bumps = self.fileReader.loadSettingsFile(path, projectDir, self.statusbar)
            print('Opened settings file at %s' % path)
        else:
            dlg = wx.MessageDialog(self, "Failed to import the correct settings file.", "Complication", wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            return

        # populate data
        self.strike_price = self.fileReader.getStrikePrice()
        self.stock_price = self.fileReader.getStockPrice()
        self.option_price = self.fileReader.getOptionPrice(self.callRadio.GetValue(), self.optionPriceCheck.IsChecked())
        self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), self.deltaCheck.IsChecked())
        self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), self.gammaCheck.IsChecked())
        # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), self.vegaCheck.IsChecked())
        self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), self.thetaCheck.IsChecked())
        self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), self.rhoCheck.IsChecked())

        self.onBasicView()

    def onExit(self,event=None):
        dlg = wx.MessageDialog(None, 'Are you sure to exit?', 'Confirm', wx.YES_NO|wx.NO_DEFAULT|wx.ICON_QUESTION)
        ret = dlg.ShowModal()
        if ret == wx.ID_YES:
            self.Destroy()

    """ GUI event methods """
    def onShowFillEffect(self, event=None):
        if self.fillCheck.IsChecked():
            if self.differenceCheck.IsChecked():
                self.differenceCheck.SetValue(False)
                # reload and replot data
                self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), 
                    self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
                self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), 
                    self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
                # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), 
                #    self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
                self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), 
                    self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
                self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), 
                    self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
                self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(),
                    self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
            
            self.viewFill = True
        else:
            self.viewFill = False
        self.Plot_Data()

    def onCallRadio(self, event=None):
        self.option_price = self.fileReader.getOptionPrice(self.callRadio.GetValue(), 
            self.optionPriceCheck.IsChecked())
        self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), 
            self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), 
            self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), 
        #     self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), 
            self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), 
            self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(),
            self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.Plot_Data()

    def onPutRadio(self, event=None):
        self.option_price = self.fileReader.getOptionPrice(self.callRadio.GetValue(), 
            self.optionPriceCheck.IsChecked())
        self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), 
            self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), 
            self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), 
        #     self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), 
            self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), 
            self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(),
            self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.Plot_Data() 

    def onOptionPrice(self, event=None):
        self.option_price = self.fileReader.getOptionPrice(self.callRadio.GetValue(), 
                self.optionPriceCheck.IsChecked())
        self.Plot_Data()

    def onDelta(self, event=None):
        self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), 
            self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.Plot_Data()

    def onGamma(self, event=None):
        self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), 
            self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())

        self.Plot_Data()

    def onRho(self, event=None):
        self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), 
            self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.Plot_Data()

    def onTheta(self, event=None):
        self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), 
            self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.Plot_Data()

    def onVega(self, event=None):
        self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), 
            self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.Plot_Data()

    def onRisidual(self, event=None):
        self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(),
            self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())

        # print(self.risidual)
        self.Plot_Data()

    def onShowEffects(self, event=None):
        if not self.effectCheck.IsChecked():
            warning_msg = """
                This setting will plot the value of the greeks, but not terms of the option price. This means that the greek graphs will no-longer be comparable. You will still be able to plot the greeks against each other though.

                Do you want to continue?
            """
            dlg = wx.MessageDialog(self, warning_msg, "Take Note", wx.YES_NO | wx.ICON_INFORMATION)
            ret = dlg.ShowModal()
            if ret == wx.ID_NO:
                dlg.Destroy()
                self.effectCheck.SetValue(True)
                return
            dlg.Destroy()
            self.differenceCheck.Disable()
            self.fillCheck.Disable()
            self.optionPriceCheck.SetValue(False)
            self.onOptionPrice()
            self.optionPriceCheck.Disable()
        else:
            self.differenceCheck.Enable()
            self.optionPriceCheck.Enable()
            if self.current_view != 2:
                self.fillCheck.Enable()

        # reload and replot data
        self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), 
            self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), 
            self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), 
        #     self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), 
            self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), 
            self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(),
            self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())

        self.Plot_Data()

    def onDifferenceCheck(self, event=None):
        if self.fillCheck.IsChecked():    
            self.fillCheck.SetValue(False)
            self.viewFill = False

        # reload and replot data
        self.delta = self.fileReader.getDeltaValues(self.callRadio.GetValue(), 
            self.deltaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.gamma = self.fileReader.getGammaValues(self.callRadio.GetValue(), 
            self.gammaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        # self.vega = self.fileReader.getVegaValues(self.callRadio.GetValue(), 
        #     self.vegaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.theta = self.fileReader.getThetaValues(self.callRadio.GetValue(), 
            self.thetaCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.rho = self.fileReader.getRhoValues(self.callRadio.GetValue(), 
            self.rhoCheck.IsChecked(), self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.risidual = self.fileReader.getRisidualValues(self.callRadio.GetValue(), self.risidualCheck.IsChecked(),
            self.differenceCheck.IsChecked(), self.effectCheck.IsChecked())
        self.Plot_Data()

    def onStockSlider(self, event=None):
        self.statusbar.SetStatusText("Stock price bump: "+str(self.stockSlider.GetValue()))
        self.stock_bump = self.stockSlider.GetValue()-1
        self.Plot_Data()

    def onRateSlider(self, event=None):
        self.statusbar.SetStatusText("Interest Rate bump: "+str(self.rateSlider.GetValue()))
        self.rate_bump = self.rateSlider.GetValue()-1
        self.Plot_Data()

    def onVolatilSlider(self, event=None):
        self.statusbar.SetStatusText("Volatility bump: "+str(self.volatilSlider.GetValue()))
        self.volitile_bump = self.volatilSlider.GetValue()-1
        self.Plot_Data()

    def ontimeStepSlider(self, event=None):
        self.statusbar.SetStatusText("Time step bump: "+str(self.timeStepSlider.GetValue()))
        self.time_bump = self.timeStepSlider.GetValue()-1
        self.Plot_Data()
        self.Plot_Data()

    """ Graph plotting methods """
    def clearPlots(self):
        """ Clear all graphs and plots for next draw """
        for a in self.fig.axes:
            self.fig.delaxes(a)

    def Plotter_2D_general(self, axes):
        # plot option price graph
        temp_option_price = []
        if len(self.option_price) > 0:
            temp_option_price = numpy.array(map(float, self.option_price[self.stock_bump]))
        if len(self.option_price) > 0:
            axes.plot(self.time, self.option_price[self.stock_bump], color='black')
        
        # stagger plot effects of greeks 
        temp_delta = []
        temp_gamma = []
        temp_theta = []
        temp_rho = []
        temp_risidual = []
        if len(self.delta) > 0:
            temp_delta = numpy.array(self.delta[self.stock_bump])
        if len(self.gamma) > 0:
            temp_gamma = numpy.array(self.gamma[self.stock_bump])
        if len(self.rho) > 0:
            temp_rho = numpy.array(self.rho[self.rate_bump])
        if len(self.theta) > 0:
            temp_theta = numpy.array(self.theta[self.time_bump])
        if len(self.risidual) > 0:
            temp_risidual = numpy.array(self.risidual[self.stock_bump])

        if not self.differenceCheck.IsChecked() and len(temp_option_price) > 0:
            for t in self.time:
                greeks_below = []
                greeks_above = []  # above/below option price
                if t < 30:
                    # sort arrays
                    if len(temp_delta) > 0:
                        if temp_delta[t+1] > temp_option_price[t+1]:
                            greeks_above.append([temp_delta[t:t+2], 'delta'])
                        else:
                            greeks_below.append([temp_delta[t:t+2], 'delta'])
                    if len(temp_gamma) > 0:
                        if temp_gamma[t+1] > temp_option_price[t+1]:
                            greeks_above.append([temp_gamma[t:t+2], 'gamma'])
                        else:
                            greeks_below.append([temp_gamma[t:t+2], 'gamma'])
                    if len(temp_theta) > 0:
                        if temp_theta[t+1] > temp_option_price[t+1]:
                            greeks_above.append([temp_theta[t:t+2], 'theta'])
                        else:
                            greeks_below.append([temp_theta[t:t+2], 'theta'])
                    if len(temp_rho) > 0:
                        if temp_rho[t+1] > temp_option_price[t+1]:
                            greeks_above.append([temp_rho[t:t+2], 'rho'])
                        else:
                            greeks_below.append([temp_rho[t:t+2], 'rho'])
                    if len(temp_risidual) > 0:
                        if temp_risidual[t+1] > temp_option_price[t+1]:
                            greeks_above.append([temp_risidual[t:t+2], 'risidual'])
                        else:
                            greeks_below.append([temp_risidual[t:t+2], 'risidual'])

                    temp_time = numpy.arange(t, t+2, 1)    
                    greeks_above = sorted(greeks_above, key=lambda tup: tup[0][1])
                    greeks_below = sorted(greeks_below, key=lambda tup: tup[0][1], reverse=True)

                    # PLOT stagger greek effects
                    temp_time = numpy.arange(t, t+2, 1)
                    temp1 = numpy.array(temp_option_price[t:t+2])

                    # print(t, greeks_below, greeks_above)
                    for g in greeks_above:
                        # print(t)
                        temp2 = numpy.array([temp_option_price[t], g[0][1]])
                        if self.viewFill and len(self.option_price) > 0:
                            if g[1] == 'delta':
                                axes.fill_between(temp_time, temp2, temp1, color='blue')
                            if g[1] == 'gamma':
                                axes.fill_between(temp_time, temp2, temp1, color='cyan')
                            if g[1] == 'theta':
                                axes.fill_between(temp_time, temp2, temp1, color='green')
                            if g[1] == 'rho':
                                axes.fill_between(temp_time, temp2, temp1, color='darkorange')
                            if g[1] == 'risidual':
                                axes.fill_between(temp_time, temp2, temp1, color='purple')
                        if g[1] == 'delta':
                            axes.plot(temp_time, temp2, label="Delta", color='blue')
                        if g[1] == 'gamma':
                            axes.plot(temp_time, temp2, label="Gamma", color='cyan')
                        if g[1] == 'theta':
                            axes.plot(temp_time, temp2, label="Theta", color='green')
                        if g[1] == 'rho':
                            axes.plot(temp_time, temp2, label="Rho", color='darkorange')
                        if g[1] == 'risidual':
                            axes.plot(temp_time, temp2, label="risidual", color='purple')
                        temp1 = temp2

                    temp1 = numpy.array(temp_option_price[t:t+2])
                    for g in greeks_below:
                        temp2 = numpy.array([temp_option_price[t], g[0][1]])
                        if self.viewFill and len(self.option_price) > 0:
                            if g[1] == 'delta':
                                axes.fill_between(temp_time, temp2, temp1, color='blue')
                            if g[1] == 'gamma':
                                axes.fill_between(temp_time, temp2, temp1, color='cyan')
                            if g[1] == 'theta':
                                axes.fill_between(temp_time, temp2, temp1, color='green')
                            if g[1] == 'rho':
                                axes.fill_between(temp_time, temp2, temp1, color='darkorange')
                            if g[1] == 'risidual':
                                axes.fill_between(temp_time, temp2, temp1, color='purple')
                        if g[1] == 'delta':
                            axes.plot(temp_time, temp2, label="Delta", color='blue')
                        if g[1] == 'gamma':
                            axes.plot(temp_time, temp2, label="Gamma", color='cyan')
                        if g[1] == 'theta':
                            axes.plot(temp_time, temp2, label="Theta", color='green')
                        if g[1] == 'rho':
                            axes.plot(temp_time, temp2, label="Rho", color='darkorange')
                        if g[1] == 'risidual':
                            axes.plot(temp_time, temp2, label="risidual", color='purple')
                        temp1 = temp2
        else:
            # plot difference between greeks and option price
            if len(self.delta) > 0:
                axes.plot(self.delta[self.stock_bump], color='blue')
            if len(self.gamma) > 0:
                axes.plot(self.gamma[self.stock_bump], color='cyan')
            # if len(self.vega) > 0:
            #    axes.plot(self.vega[self.volitile_bump], label="Vega", color='yellow')
            if len(self.theta) > 0:
                axes.plot(self.time, self.theta[self.time_bump], color='green')
            if len(self.rho) > 0:
                axes.plot(self.time, self.rho[self.rate_bump], color='darkorange')
            if len(self.risidual) > 0:
                axes.plot(self.time, self.risidual[self.stock_bump], color='purple')

        if self.viewLegend:
            # use proxy artist
            plot_op = Line2D([], [], linewidth=3, color="black") 
            plot_delta = Line2D([], [], linewidth=3, color="royalblue") 
            plot_gamma = Line2D([], [], linewidth=3, color="cyan") 
            plot_theta = Line2D([], [], linewidth=3, color="green") 
            plot_rho = Line2D([], [], linewidth=3, color="darkorange") 
            plot_risidual = Line2D([], [], linewidth=3, color="purple")

            # Shink current axis by 15%
            box = axes.get_position()
            axes.set_position([box.x0, box.y0, box.width * 0.88, box.height])
            # Put a legend to the right of the current axis
            axes.legend([plot_op, plot_delta, plot_gamma, plot_theta, plot_rho, plot_risidual], ['Option Price', 'Delta', 'Gamma', 'Theta', 'Rho', 'Residual'],
                loc='center left', bbox_to_anchor=(1, 0.5), prop={'size':8})

    def Plot_Data(self):
        if self.current_view == 1:
            self.Plot_Data_advanced()
        elif self.current_view == 2:
            self.Plot_Data_3D()
        elif self.current_view == 0:            
            """ Basic 2D graph plotter """
            self.clearPlots()
            
            self.axes = self.fig.add_subplot(111) # can use add_axes, but then nav-toolbar would not work
            self.axes.set_xlim(0, 30)
            self.axes.grid(self.viewGrid)

            self.Plotter_2D_general(self.axes)

            # set caption and axes labels
            self.axes.set_xlabel('Time (Daily)')
            if self.effectCheck.IsChecked():
                self.axes.set_ylabel('Price (Rands)')
                if hasattr(self, 'title'):
                    self.title.set_text('Option Prices and breakdown of the effects of Greeks')
                else:
                    self.title = self.fig.suptitle('Option Prices and breakdown of the effects of Greeks')
            else:
                self.axes.set_ylabel('Greek Value')
                if hasattr(self, 'title'):
                    self.title.set_text('Raw Greek values not in terms of option price')
                else:
                    self.title = self.fig.suptitle('Greek values not in terms of option price')

            self.canvas.draw()

    def Plot_Data_advanced(self):
        """ Advanced 2D plotter """
        self.clearPlots()
        self.axes2 = self.fig.add_subplot(212)
        self.axes = self.fig.add_subplot(211, sharex=self.axes2)
        self.axes.set_xlim(0, 30)
        self.axes.grid(self.viewGrid)        
        self.axes2.grid(self.viewGrid)

        self.Plotter_2D_general(self.axes)

        # plot strike price and stock price curve
        if self.strike_price > 0:
            self.axes2.plot([0, 30], [self.strike_price, self.strike_price], label="Strike Price", color='red')

        # plot stock price curve
        temp_stock_price = numpy.array(self.stock_price)
        if len(temp_stock_price) > 0:
            self.axes2.plot(self.time, temp_stock_price, label="Stock Price", color='blue')

        # set limits for x and y axes
        # self.axes2.set_xlim(self.time_span_fill[0], self.time_span_fill[-1])
        # self.axes2.set_ylim(min(p, key=float), max(p, key=float))

        # set caption and axes labels
        self.axes2.set_xlabel('Time (Daily)')
        self.axes2.set_ylabel('Price (Rands)')
        if self.effectCheck.IsChecked():
            self.axes.set_ylabel('Price (Rands)')
            if hasattr(self, 'title'):
                self.title.set_text('Option Prices and breakdown of the effects of Greeks')
            else:
                self.title = self.fig.suptitle('Option Prices and breakdown of the effects of Greeks')
        else:
            self.axes.set_ylabel('Greek Value')
            if hasattr(self, 'title'):
                self.title.set_text('Raw Greek values not in terms of option price')
            else:
                self.title = self.fig.suptitle('Greek values not in terms of option price')

        # set useblit True on gtkagg for enhanced performance
        # self.span = SpanSelector(self.axes, self.onselect, 'horizontal', useblit=True, rectprops=dict(alpha=0.5, facecolor='red'))

        if self.viewLegend:
            # Shink current axis by 15%
            box = self.axes2.get_position()
            self.axes2.set_position([box.x0, box.y0, box.width * 0.88, box.height])
            # Put a legend to the right of the current axis
            self.axes2.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop={'size':8})

        self.canvas.draw()

    def Plot_Data_3D(self):
        """ Advanced 3D plotter """
        # plot graphs
        self.clearPlots()
            
        self.axes = self.fig.add_subplot(111, projection='3d') # can use add_axes, but then nav-toolbar would not work
        self.axes.grid(self.viewGrid)

        b = numpy.arange(0, 9, 1)
        X2D, Y2D = numpy.meshgrid(self.time, b)
        Z2D = None
        
        # plot option price surface
        if len(self.option_price) > 0:
            Z2D = [[float(string) for string in inner] for inner in self.option_price]            
            surf = self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1,
                antialiased=False, alpha=0.75, cmap=cm.afmhot, zorder=0.5)  #cm.coolwarm, cm.winter, cm.autumn
            cbar = self.fig.colorbar(surf, shrink=0.5, aspect=5)
            cbar.set_label('Option Price', rotation=90)

            ### TODO - mayavi ###
            # X2D, Y2D = numpy.mgrid[self.time, b]
            # print(X2D)
            # s = mlab.surf(Z2D)
            # mlab.show()

        # plot greek surfaces
        if len(self.delta) > 0:
            Z2D = [[float(string) for string in inner] for inner in self.delta]
            self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1,
                antialiased=False, alpha=0.75, color='blue')

        if len(self.gamma) > 0:
            Z2D = [[float(string) for string in inner] for inner in self.gamma]
            self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1,
                antialiased=False, alpha=0.75, color='cyan')
                
        if len(self.theta) > 0:
            Z2D = [[float(string) for string in inner] for inner in self.theta]
            self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1,
                antialiased=False, alpha=0.75, color='green')
                
        if len(self.rho) > 0:
            Z2D = [[float(string) for string in inner] for inner in self.rho]
            self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1,
                antialiased=False, alpha=0.75, color='orange')
                
        # if len(self.vega) > 0:
        #     Z2D = [[float(string) for string in inner] for inner in self.vega]
        #     self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1,
        #         antialiased=False, alpha=0.75, color='aqua')

        if len(self.risidual) > 0:
            Z2D = [[float(string) for string in inner] for inner in self.risidual]
            self.axes.plot_surface(X2D, Y2D, Z2D, rstride=1, cstride=1,
                antialiased=False, alpha=0.75, color='rosybrown')
        
        if Z2D != None:
            # cset1 = self.axes.contourf(X2D, Y2D, Z2D, zdir='z', offset=300, cmap=cm.afmhot)
            self.axes.contourf(X2D, Y2D, Z2D, zdir='x', offset=0, cmap=cm.coolwarm)
            self.axes.contour(X2D, Y2D, Z2D, zdir='y', offset=-0.3, cmap=cm.winter)
            # cset = self.axes.contour(X2D, Y2D, Z2D, zdir='y', offset=10, cmap=cm.afmhot)
            # cbar = self.fig.colorbar(cset1, shrink=0.7, aspect=3)
            # cbar = self.fig.colorbar(cset2, shrink=0.7, aspect=3)
            # cbar = self.fig.colorbar(cset3, shrink=0.5, aspect=5)
            # cbar.set_label('Option Proce', rotation=90)

        # set captions and axis labels
        self.axes.set_xlabel('Time (Days)')
        self.axes.set_xlim(0, 35)
        self.axes.set_ylabel('Bump Size')
        #~ self.axes.set_ylim(-3, 8)
        # self.axes.set_zlabel('Price (Rands)')
        # ~ self.axes.set_zlim(-100, 100)

        if self.effectCheck.IsChecked():
            if self.differenceCheck.IsChecked():
                self.axes.set_zlabel('Greek Value')
            else:
                self.axes.set_zlabel('Price (Rands)')
            if hasattr(self, 'title'):
                self.title.set_text('Option Prices and breakdown of the effects of Greeks')
            else:
                self.title = self.fig.suptitle('Option Prices and breakdown of the effects of Greeks')
        else:
            self.axes.set_zlabel('Greek Value')
            if hasattr(self, 'title'):
                self.title.set_text('Raw Greek values not in terms of option price')
            else:
                self.title = self.fig.suptitle('Greek values not in terms of option price')

        self.canvas.draw()
Пример #29
0
class STAPanel(wx.Panel):
    """ Receptive field plot.
    """
    def __init__(self, parent, label, name='sta_panel'):
        super(STAPanel, self).__init__(parent, -1, name=name)

        self.interpolation_changed = True
        self.show_colorbar_changed = True
        self.show_contour_changed = True
        self.showing_colorbar = True
        self.showing_contour = False
        self.image_fitting = None
        self.image_fitter = None

        # default data type
        self.collecting_data = True
        self.connected_to_server = True
        self.data = None
        self.sta_data = None
        self.psth_data = None
        self.data_type = None
        self.start_data()
        self.update_sta_data_thread = None
        self.update_psth_data_thread = None

        self.axes = None
        self.im = None
        self.img_dim = None
        self.cbar = None

        self.gauss_fitter = None
        self.gabor_fitter = None

        self.peak_time = None
        self.cmap = 'jet'
        # reverse time in ms
        time_slider = 85
        self.time = time_slider / 1000

        self.dpi = 100
        self.fig = Figure((6.0, 6.0), dpi=self.dpi, facecolor='w')
        self.canvas = FigCanvas(self, -1, self.fig)
        self.fig.subplots_adjust(bottom=0.06, left=0.06, right=0.95, top=0.95)

        # popup menu of cavas
        interpolations = ['none', 'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36', 'hanning', 'hamming', 'hermite', \
                               'kaiser', 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos']
        self.interpolation = 'nearest'
        self.interpolation_menu = wx.Menu()
        for interpolation in interpolations:
            item = self.interpolation_menu.AppendRadioItem(-1, interpolation)
            # check default interpolation
            if interpolation == self.interpolation:
                self.interpolation_menu.Check(item.GetId(), True)
            self.Bind(wx.EVT_MENU, self.on_interpolation_selected, item)
            wx.FindWindowByName('main_frame').Bind(
                wx.EVT_MENU, self.on_interpolation_selected, item)
        self.popup_menu = wx.Menu()
        self.popup_menu.AppendMenu(-1, '&Interpolation',
                                   self.interpolation_menu)
        self.canvas.Bind(wx.EVT_CONTEXT_MENU, self.on_show_popup)
        wx.FindWindowByName('main_frame').menu_view.AppendSubMenu(
            self.interpolation_menu, '&Interpolation')

        self.make_chart()

        #layout things
        box = wx.StaticBox(self, -1, label)
        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)

        # options
        self.options = OptionPanel(self, 'Options', time=time_slider)
        self.Bind(EVT_TIME_UPDATED, self.on_update_time_slider)
        # results
        self.data_form = STADataPanel(self, 'Results', text_size=(250, 150))

        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(self.options, 1, wx.TOP | wx.CENTER, 0)
        vbox.Add(self.data_form, 1, wx.TOP | wx.CENTER, 0)

        # canvas
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        hbox.Add(self.canvas,
                 0,
                 flag=wx.ALL | wx.ALIGN_LEFT | wx.ALIGN_TOP,
                 border=5)
        hbox.Add(vbox,
                 0,
                 flag=wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_TOP,
                 border=5)

        sizer.Add(hbox, 0, wx.ALIGN_CENTRE)
        self.SetSizer(sizer)
        sizer.Fit(self)

        self.update_sta_data_timer = wx.Timer(self, wx.NewId())
        self.Bind(wx.EVT_TIMER, self.on_update_sta_data_timer,
                  self.update_sta_data_timer)
        self.update_sta_data_timer.Start(2000)

        self.update_psth_data_timer = wx.Timer(self, wx.NewId())
        self.Bind(wx.EVT_TIMER, self.on_update_psth_data_timer,
                  self.update_psth_data_timer)
        self.update_psth_data_timer.Start(3000)

    def make_chart(self, img=None):
        self.fig.clear()
        self.axes = self.fig.add_subplot(111)
        if img is None:
            img = np.zeros((32, 32)) + 0.5
            img = self.sta_data.float_to_rgb(img, cmap=self.cmap)
        self.img_dim = img.shape
        self.im = self.axes.imshow(img, interpolation=self.interpolation)
        if self.showing_colorbar:
            self.cbar = self.fig.colorbar(self.im,
                                          shrink=1.0,
                                          fraction=0.045,
                                          pad=0.05,
                                          ticks=[])
        adjust_spines(self.axes,
                      spines=['left', 'bottom'],
                      spine_outward=[],
                      xticks='bottom',
                      yticks='left',
                      tick_label=['x', 'y'])
        #self.axes.autoscale_view(scalex=True, scaley=True)
        self.fig.canvas.draw()

    def set_data(self, data):
        self.data = data

    def update_slider(self, data):
        selected_unit = wx.FindWindowByName('unit_choice').get_selected_unit()
        if selected_unit:
            channel, unit = selected_unit
            peak_time = data[channel][unit][
                'peak_time'] if channel in data and unit in data[
                    channel] else None
            parent = wx.FindWindowByName('main_frame')
            options_panel = parent.chart_panel.options
            auto_time = options_panel.autotime_cb.GetValue()
            if auto_time and peak_time is not None:
                self.peak_time = peak_time
                options_panel.time_slider.SetValue(peak_time)
                evt = wx.CommandEvent(wx.wxEVT_COMMAND_SLIDER_UPDATED)
                evt.SetId(options_panel.time_slider.GetId())
                options_panel.on_slider_update(evt)
                wx.PostEvent(parent, evt)

    def update_chart(self, data=None):
        if data is None and self.data is None:
            return
        elif data is None and self.data is not None:
            data = self.data

        if isinstance(self.sta_data, RevCorr.STAData):
            self.data_type = 'white_noise'
        if isinstance(self.sta_data, RevCorr.ParamMapData):
            self.data_type = 'param_mapping'

        selected_unit = wx.FindWindowByName('unit_choice').get_selected_unit()
        if selected_unit:
            channel, unit = selected_unit
            img = self.sta_data.get_img(data,
                                        channel,
                                        unit,
                                        tau=self.time,
                                        img_format='rgb')
            if self.img_dim != img.shape or self.interpolation_changed or self.show_colorbar_changed \
            or self.showing_contour or self.show_contour_changed:
                self.interpolation_changed = False
                self.show_colorbar_changed = False
                self.show_contour_changed = False
                self.make_chart(img)
                self.img_dim = img.shape

                if self.showing_colorbar:
                    self.cbar.set_ticks([0.0, 0.5, 1.0])
                    if isinstance(self.sta_data, RevCorr.STAData):
                        self.cbar.set_ticklabels(["-1", "0", "1"])
                    if isinstance(self.sta_data, RevCorr.ParamMapData):
                        self.cbar.set_ticklabels(["0.0", "0.5", "1.0"])

            self.data_form.gen_results(self.peak_time)

            if self.image_fitting is not None:
                float_img = self.sta_data.get_img(data,
                                                  channel,
                                                  unit,
                                                  tau=self.time,
                                                  img_format='float')
                if self.image_fitting == 'gauss':
                    params, img = self.image_fitter.gaussfit2d(
                        float_img, returnfitimage=True)
                    level = twodgaussian(params)(params[3] + params[5],
                                                 params[2] + params[4])
                elif self.image_fitting == 'gabor':
                    params, img = self.image_fitter.gaborfit2d(
                        float_img, returnfitimage=True)
                    level = twodgabor(params)(params[3] + params[5],
                                              params[2] + params[4])
                if self.showing_contour:
                    self.axes.contour(img, [level])
                self.data_form.gen_results(self.peak_time, params, img,
                                           self.data_type, self.image_fitting)
                img = self.sta_data.float_to_rgb(img, cmap=self.cmap)

            self.im.set_data(img)
            self.im.autoscale()
            self.canvas.draw()

    def on_update_sta_data_timer(self, _event):
        if self.collecting_data and self.connected_to_server:
            self.update_sta_data_thread = UpdateDataThread(self, self.sta_data)
            self.update_sta_data_thread.start()

    def on_update_psth_data_timer(self, _event):
        if self.collecting_data and self.connected_to_server:
            self.update_psth_data_thread = UpdateDataThread(
                self, self.psth_data)
            self.update_psth_data_thread.start()

    def on_update_time_slider(self, event):
        self.time = event.get_time()
        self.update_chart()

    def start_data(self):
        data_type = wx.FindWindowByName('main_frame').get_data_type()
        if data_type == 'sparse_noise':
            self.sta_data = RevCorr.STAData()
        elif data_type == 'param_map':
            self.sta_data = RevCorr.ParamMapData()
        if self.psth_data is None:
            self.psth_data = TimeHistogram.PSTHAverage()
        self.collecting_data = True
        self.connected_to_server = True

    def stop_data(self):
        self.collecting_data = False
        self.clear_data()
        self.sta_data = None
        self.psth_data = None

    def restart_data(self):
        self.stop_data()
        self.start_data()

    def sparse_noise_data(self):
        self.sta_data = RevCorr.STAData()
        self.restart_data()

    def param_mapping_data(self):
        self.sta_data = RevCorr.ParamMapData()
        self.restart_data()

    def choose_fitting(self, fitting):
        if fitting == 'none':
            self.image_fitting = None
            self.image_fitter = None
        if fitting == 'gauss':
            self.image_fitting = 'gauss'
            self.image_fitter = GaussFit()
        if fitting == 'gabor':
            self.image_fitting = 'gabor'
            self.image_fitter = GaborFit()

    def show_colorbar(self, checked):
        self.show_colorbar_changed = True
        self.showing_colorbar = checked

    def show_contour(self, checked):
        self.show_contour_changed = True
        self.showing_contour = checked

    def on_show_popup(self, event):
        pos = event.GetPosition()
        pos = event.GetEventObject().ScreenToClient(pos)
        self.PopupMenu(self.popup_menu, pos)

    def on_interpolation_selected(self, event):
        item = self.interpolation_menu.FindItemById(event.GetId())
        interpolation = item.GetText()
        if interpolation != self.interpolation:
            self.interpolation_changed = True
        self.interpolation = interpolation
        if hasattr(self, 'data'):
            self.update_chart(self.data)

    def open_file(self, path, callback):
        data_type = wx.FindWindowByName('main_frame').get_data_type()
        if data_type == 'sparse_noise':
            self.sta_data = RevCorr.STAData(path)
        elif data_type == 'param_map':
            self.sta_data = RevCorr.ParamMapData(path)
        self.psth_data = TimeHistogram.PSTHAverage(path)
        UpdateFileDataThread(self, self.sta_data, callback).start()
        UpdateFileDataThread(self, self.psth_data, callback).start()
        self.connected_to_server = False

    def save_data(self):
        data_dict = {}
        data_dict['data_type'] = self.data_type
        data_dict['data'] = self.data
        return data_dict

    def save_chart(self, path):
        self.canvas.print_figure(path, dpi=self.dpi)

    def clear_data(self):
        self.data = None
        self.make_chart()
        wx.FindWindowByName('main_frame').unit_choice.clear_unit()
        self.data_form.clear_data()
Пример #30
0
class plot_2d_data(wx.Frame):
    """Generic 2d plotting routine - inputs are:
    - data (2d array of values),
    - x and y extent of the data,
    - title of graph, and
    - pixel mask to be used during summation  - must have same dimensions as data
    (only data entries corresponding to nonzero values in pixel_mask will be summed)
    - plot_title, x_label and y_label are added to the 2d-plot as you might expect"""

    def __init__(self, data, extent, caller = None, scale = 'log', window_title = 'log plot', pixel_mask = None, plot_title = "data plot", x_label = "x", y_label = "y", parent=None):
        wx.Frame.__init__(self, parent=None, title=window_title, pos = wx.DefaultPosition, size=wx.Size(800,600))
        print parent
        self.extent = extent
        self.data = data
        self.caller = caller
        self.window_title = window_title
        x_range = extent[0:2]
        #x_range.sort()
        self.x_min, self.x_max = x_range
        y_range = extent[2:4]
        #y_range.sort()
        self.y_min, self.y_max = y_range
        self.plot_title = plot_title
        self.x_label = x_label
        self.y_label = y_label
        self.slice_xy_range = (x_range, y_range)
        self.ID_QUIT = wx.NewId()
        self.ID_LOGLIN = wx.NewId()
        self.ID_UPCOLLIM = wx.NewId()
        self.ID_LOWCOLLIM = wx.NewId()

        menubar = wx.MenuBar()
        filemenu = wx.Menu()
        quit = wx.MenuItem(filemenu, 1, '&Quit\tCtrl+Q')
        #quit.SetBitmap(wx.Bitmap('icons/exit.png'))
        filemenu.AppendItem(quit)

        plotmenu = wx.Menu()
        self.menu_log_lin_toggle = plotmenu.Append(self.ID_LOGLIN, 'Plot 2d data with log color scale', 'plot 2d on log scale', kind=wx.ITEM_CHECK)
        self.Bind(wx.EVT_MENU, self.toggle_2d_plot_scale, id=self.ID_LOGLIN)
        menu_upper_colormap_limit = plotmenu.Append(self.ID_UPCOLLIM, 'Set upper limit of color map', 'Set upper limit of color map')
        self.Bind(wx.EVT_MENU, self.set_new_upper_color_limit, id=self.ID_UPCOLLIM)
        menu_lower_colormap_limit = plotmenu.Append(self.ID_LOWCOLLIM, 'Set lower limit of color map', 'Set lower limit of color map')
        self.Bind(wx.EVT_MENU, self.set_new_lower_color_limit, id=self.ID_LOWCOLLIM)
        #live_on_off = wx.MenuItem(live_update, 1, '&Live Update\tCtrl+L')
        #quit.SetBitmap(wx.Bitmap('icons/exit.png'))
        #live_update.AppendItem(self.live_toggle)
        #self.menu_log_lin_toggle.Check(True)

        menubar.Append(filemenu, '&File')
        menubar.Append(plotmenu, '&Plot')
        self.SetMenuBar(menubar)
        self.Centre()

        if pixel_mask == None:
            pixel_mask = ones(data.shape)

        if pixel_mask.shape != data.shape:
            print "Warning: pixel mask shape incompatible with data"
            pixel_mask = ones(data.shape)

        self.pixel_mask = pixel_mask

        self.show_data = transpose(data.copy())
        #self.minimum_intensity = self.data[pixel_mask.nonzero()].min()
        # correct for floating-point weirdness:
        self.minimum_intensity = self.data[self.data > 1e-17].min()

        #if scale == 'log':
            #self.show_data = log ( self.data.copy().T + self.minimum_intensity/2.0 )
            #self._scale = 'log'
            #self.menu_log_lin_toggle.Check(True)

        #elif (scale =='lin' or scale == 'linear'):
            #self._scale = 'lin'
            #self.menu_log_lin_toggle.Check(True)


        #self.bin_data = caller.bin_data
        #self.params = caller.params
        #fig = figure()
        self.fig = Figure(dpi=80, figsize=(5,5))
        #self.fig = figure()
        fig = self.fig
        self.canvas = Canvas(self, -1, self.fig)
        self.show_sliceplots = False # by default, sliceplots on
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND)

        #self.toolbar = Toolbar(self.canvas)
        self.toolbar = MyNavigationToolbar(self.canvas, True, self)
        self.toolbar.Realize()
        if wx.Platform == '__WXMAC__':
            # Mac platform (OSX 10.3, MacPython) does not seem to cope with
            # having a toolbar in a sizer. This work-around gets the buttons
            # back, but at the expense of having the toolbar at the top
            self.SetToolBar(self.toolbar)
        else:
            # On Windows platform, default window size is incorrect, so set
            # toolbar width to figure width.
            tw, th = self.toolbar.GetSizeTuple()
            fw, fh = self.canvas.GetSizeTuple()
            # By adding toolbar in sizer, we are able to put it at the bottom
            # of the frame - so appearance is closer to GTK version.
            # As noted above, doesn't work for Mac.
            self.toolbar.SetSize(wx.Size(fw, th))
            self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)

        self.statusbar = self.CreateStatusBar()
        self.statusbar.SetFieldsCount(2)
        self.statusbar.SetStatusWidths([-1, -2])
        self.statusbar.SetStatusText("Current Position:", 0)

        self.canvas.mpl_connect('motion_notify_event', self.onmousemove)
        #self.canvas.mpl_connect('button_press_event', self.right_click_handler)
        #self.axes = fig.add_subplot(111)
        #self.axes = self.fig.gca()
        #ax = self.axes
        self.mapper = FigureImage(self.fig)
        #im = self.axes.pcolor(x,y,V,shading='flat')
        #self.mapper.add_observer(im)



        #self.show_data = transpose(log(self.show_data + self.minimum_intensity / 2.0))

        #self.canvas.mpl_connect('pick_event', self.log_lin_select)

        ax = fig.add_subplot(221, label='2d_plot')
        fig.sx = fig.add_subplot(222, label='sx', picker=True)
        fig.sx.xaxis.set_picker(True)
        fig.sx.yaxis.set_picker(True)
        fig.sx.yaxis.set_ticks_position('right')
        fig.sx.set_zorder(1)
        fig.sz = fig.add_subplot(223, label='sz', picker=True)
        fig.sz.xaxis.set_picker(True)
        fig.sz.yaxis.set_picker(True)
        fig.sz.set_zorder(1)
        self.RS = RectangleSelector(ax, self.onselect, drawtype='box', useblit=True)
        fig.slice_overlay = None

        ax.set_position([0.125,0.1,0.7,0.8])
        fig.cb = fig.add_axes([0.85,0.1,0.05,0.8])
        fig.cb.set_zorder(2)

        fig.ax = ax
        fig.ax.set_zorder(2)
        self.axes = ax
        ax.set_title(plot_title)
        #connect('key_press_event', self.toggle_selector)
        if scale == 'log':
            self.show_data = log ( self.data.copy().T + self.minimum_intensity/2.0 )
            self.__scale = 'log'
            self.fig.cb.set_xlabel('$\log_{10}I$')
            self.menu_log_lin_toggle.Check(True)

        elif (scale =='lin' or scale == 'linear'):
            self.__scale = 'lin'
            self.fig.cb.set_xlabel('$I$')
            self.menu_log_lin_toggle.Check(False)

        im = self.axes.imshow(self.show_data, interpolation='nearest', aspect='auto', origin='lower',cmap=cm.jet, extent=extent)
        #im = ax.imshow(data, interpolation='nearest', aspect='auto', origin='lower',cmap=cm.jet, extent=extent)
        fig.im = im
        ax.set_xlabel(x_label, size='large')
        ax.set_ylabel(y_label, size='large')
        self.toolbar.update()
        #zoom_colorbar(im)

        #fig.colorbar(im, cax=fig.cb)
        zoom_colorbar(im=im, cax=fig.cb)
        #figure(fig.number)
        #fig.canvas.draw()
        #return


        self.SetSizer(self.sizer)
        self.Fit()

        self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnContext)
        self.Bind(wx.EVT_CLOSE, self.onExit)
        self.sliceplots_off()
        self.SetSize(wx.Size(800,600))
        self.canvas.draw()
        return

    def onExit(self, event):
        self.Destroy()

    def exit(self, event):
        wx.GetApp().Exit()


    def set_new_upper_color_limit(self, evt = None):
        current_uplim = self.fig.im.get_clim()[1]
        current_lowlim = self.fig.im.get_clim()[0]
        dlg = wx.TextEntryDialog(None, "Change upper limit of color map (currently %f)" % current_uplim, defaultValue = "%f" % current_uplim)
        if dlg.ShowModal() == wx.ID_OK:
            new_val = dlg.GetValue()
            xlab = self.fig.cb.get_xlabel()
            ylab = self.fig.cb.get_ylabel()
            self.fig.im.set_clim((current_lowlim, float(new_val)))
            self.fig.cb.set_xlabel(xlab)
            self.fig.cb.set_ylabel(ylab)
            self.fig.canvas.draw()
        dlg.Destroy()

    def set_new_lower_color_limit(self, evt = None):
        current_uplim = self.fig.im.get_clim()[1]
        current_lowlim = self.fig.im.get_clim()[0]
        dlg = wx.TextEntryDialog(None, "Change lower limit of color map (currently %f)" % current_lowlim, defaultValue = "%f" % current_lowlim)
        if dlg.ShowModal() == wx.ID_OK:
            new_val = dlg.GetValue()
            xlab = self.fig.cb.get_xlabel()
            ylab = self.fig.cb.get_ylabel()
            self.fig.im.set_clim((float(new_val), current_uplim))
            self.fig.cb.set_xlabel(xlab)
            self.fig.cb.set_ylabel(ylab)
            self.fig.canvas.draw()
        dlg.Destroy()

    def OnContext(self, evt):
        print self.show_sliceplots
        mpl_x = evt.X
        mpl_y = self.fig.canvas.GetSize()[1] - evt.Y
        mpl_mouseevent = matplotlib.backend_bases.MouseEvent('button_press_event', self.canvas, mpl_x, mpl_y, button = 3)

        if (mpl_mouseevent.inaxes == self.fig.ax):
            self.area_context(mpl_mouseevent, evt)
        elif ((mpl_mouseevent.inaxes == self.fig.sx or mpl_mouseevent.inaxes == self.fig.sz) and (self.show_sliceplots == True)):
            self.lineplot_context(mpl_mouseevent, evt)

    def area_context(self, mpl_mouseevent, evt):
        area_popup = wx.Menu()
        item1 = area_popup.Append(wx.ID_ANY,'&Grid on/off', 'Toggle grid lines')
        wx.EVT_MENU(self, item1.GetId(), self.OnGridToggle)
        cmapmenu = CMapMenu(self, callback = self.OnColormap, mapper=self.mapper, canvas=self.canvas)
        item2 = area_popup.Append(wx.ID_ANY,'&Toggle log/lin', 'Toggle log/linear scale')
        wx.EVT_MENU(self, item2.GetId(), lambda evt: self.toggle_log_lin(mpl_mouseevent))
        item3 = area_popup.AppendMenu(wx.ID_ANY, "Colourmaps", cmapmenu)
        self.PopupMenu(area_popup, evt.GetPositionTuple())

    def figure_list_dialog(self):
        figure_list = get_fignums()
        figure_list_names = []
        for fig in figure_list:
            figure_list_names.append('Figure ' + str(fig))
        figure_list_names.insert(0, 'New Figure')
        figure_list.insert(0, None)
        #selection_num = wx.GetSingleChoiceIndex('Choose other plot', '', other_plot_names)
        dlg = wx.SingleChoiceDialog(None, 'Choose figure number', '', figure_list_names)
        dlg.SetSize(wx.Size(640,480))
        if dlg.ShowModal() == wx.ID_OK:
            selection_num=dlg.GetSelection()
        dlg.Destroy()
        print selection_num
        return figure_list[selection_num]

    def lineplot_context(self, mpl_mouseevent, evt):
        popup = wx.Menu()
        item1 = popup.Append(wx.ID_ANY,'&Toggle log/lin', 'Toggle log/linear scale of slices')
        wx.EVT_MENU(self, item1.GetId(), lambda evt: self.toggle_log_lin(mpl_mouseevent))
        if mpl_mouseevent.inaxes == self.fig.sx:
            item2 = popup.Append(wx.ID_ANY, "Save x slice", "save this slice")
            wx.EVT_MENU(self, item2.GetId(), self.save_x_slice)
            item3 = popup.Append(wx.ID_ANY, '&Popout plot', 'Open this data in a figure window')
            wx.EVT_MENU(self, item3.GetId(), lambda evt: self.popout_x_slice())
        elif mpl_mouseevent.inaxes == self.fig.sz:
            item2 = popup.Append(wx.ID_ANY, "Save y slice", "save this slice")
            wx.EVT_MENU(self, item2.GetId(), self.save_y_slice)
            item3 = popup.Append(wx.ID_ANY, '&Popout plot', 'Open this data in a new plot window')
            wx.EVT_MENU(self, item3.GetId(), lambda evt: self.popout_y_slice())
        self.PopupMenu(popup, evt.GetPositionTuple())


    def popout_y_slice(self, event=None, figure_num = None, label = None):
        if figure_num == None:
            figure_num = self.figure_list_dialog()
        fig = figure(figure_num) # if this is None, matplotlib automatically increments figure number to highest + 1
        ax = self.fig.sz
        slice_desc = '\nsliceplot([%f,%f],[%f,%f])' % (self.slice_xy_range[0][0],self.slice_xy_range[0][1],self.slice_xy_range[1][0],self.slice_xy_range[1][1])
        if figure_num == None:
            default_title = self.plot_title + slice_desc
            dlg = wx.TextEntryDialog(None, 'Enter title for plot', defaultValue = default_title)
            if dlg.ShowModal() == wx.ID_OK:
                title = dlg.GetValue()
            else:
                title = default_title
            dlg.Destroy()
            new_ax = fig.add_subplot(111)
            new_ax.set_title(title, size='large')
            new_ax.set_xlabel(self.x_label, size='x-large')
            new_ax.set_ylabel('$I_{summed}$', size='x-large')
        else:
            new_ax = fig.axes[0]
        if label == None:
            default_label = self.window_title + ': ' + self.plot_title + slice_desc
            dlg = wx.TextEntryDialog(None, 'Enter data label (for plot legend)', defaultValue = default_label)
            if dlg.ShowModal() == wx.ID_OK:
                label = dlg.GetValue()
            else:
                label = default_label
            dlg.Destroy()
        xy = ax.lines[0].get_data()
        x = xy[0]
        y = xy[1]
        new_ax.plot(x,y, label = label)
        font = FontProperties(size='small')
        lg = legend(prop=font)
        drag_lg = DraggableLegend(lg)
        drag_lg.connect()
        fig.canvas.draw()
        fig.show()

    def popout_x_slice(self, event=None, figure_num = None, label = None):
        if figure_num == None:
            figure_num = self.figure_list_dialog()
        fig = figure(figure_num)
        ax = self.fig.sx
        slice_desc = '\nsliceplot([%f,%f],[%f,%f])' % (self.slice_xy_range[0][0],self.slice_xy_range[0][1],self.slice_xy_range[1][0],self.slice_xy_range[1][1])
        if figure_num == None:
            default_title = self.plot_title + slice_desc
            dlg = wx.TextEntryDialog(None, 'Enter title for plot', defaultValue = default_title)
            if dlg.ShowModal() == wx.ID_OK:
                title = dlg.GetValue()
            else:
                title = default_title
            dlg.Destroy()
            new_ax = fig.add_subplot(111)
            new_ax.set_title(title, size='large')
            new_ax.set_xlabel(self.y_label, size='x-large')
            new_ax.set_ylabel('$I_{summed}$', size='x-large')
        else:
            new_ax = fig.axes[0]
        if label == None:
            default_label = self.window_title + ': ' + self.plot_title + slice_desc
            dlg = wx.TextEntryDialog(None, 'Enter data label (for plot legend)', defaultValue = default_label)
            if dlg.ShowModal() == wx.ID_OK:
                label = dlg.GetValue()
            else:
                label = default_label
            dlg.Destroy()
        xy = ax.lines[0].get_data()
        x = xy[1]
        y = xy[0]
        new_ax.plot(x,y, label = label)
        font = FontProperties(size='small')
        lg = legend(prop=font)
        drag_lg = DraggableLegend(lg)
        drag_lg.connect()
        fig.canvas.draw()
        fig.show()

    def save_x_slice(self, event=None, outFileName=None):
        if outFileName == None:
            dlg = wx.FileDialog(None, "Save 2d data as:", '', "", "", wx.FD_SAVE)
            if dlg.ShowModal() == wx.ID_OK:
                fn = dlg.GetFilename()
                fd = dlg.GetDirectory()
            dlg.Destroy()
            outFileName = fd + '/' + fn
        outFile = open(outFileName, 'w')
        outFile.write('#'+self.title+'\n')
        outFile.write('#xmin: ' + str(self.slice_xy_range[0][0]) + '\n')
        outFile.write('#xmax: ' + str(self.slice_xy_range[0][1]) + '\n')
        outFile.write('#ymin: ' + str(self.slice_xy_range[1][0]) + '\n')
        outFile.write('#ymax: ' + str(self.slice_xy_range[1][1]) + '\n')
        outFile.write("#y\tslice_x_data\n")
        if not (self.slice_x_data == None):
            for i in range(self.slice_x_data.shape[0]):
                x = self.y[i]
                y = self.slice_x_data[i]
                outFile.write(str(x) + "\t" + str(y) + "\n")
        outFile.close()
        print('saved x slice in %s' % (outFileName))
        return

    def save_y_slice(self, event=None, outFileName=None):
        if outFileName == None:
            dlg = wx.FileDialog(None, "Save 2d data as:", '', "", "", wx.FD_SAVE)
            if dlg.ShowModal() == wx.ID_OK:
                fn = dlg.GetFilename()
                fd = dlg.GetDirectory()
            dlg.Destroy()
            outFileName = fd + '/' + fn
        outFile = open(outFileName, 'w')
        outFile.write('#'+self.title+'\n')
        outFile.write('#xmin: ' + str(self.slice_xrange[0]) + '\n')
        outFile.write('#xmax: ' + str(self.slice_xrange[1]) + '\n')
        outFile.write('#ymin: ' + str(self.slice_yrange[0]) + '\n')
        outFile.write('#ymax: ' + str(self.slice_yrange[1]) + '\n')
        outFile.write("#x\tslice_y_data\n")
        if not (self.slice_y_data == None):
            for i in range(self.slice_y_data.shape[0]):
                x = self.x[i]
                y = self.slice_y_data[i]
                outFile.write(str(x) + "\t" + str(y) + "\n")
        outFile.close()
        print('saved y slice in %s' % (outFileName))
        return


    def OnGridToggle(self, event):
        self.fig.ax.grid()
        self.fig.canvas.draw_idle()

    def OnColormap(self, name):
        print "Selected colormap",name
        self.fig.im.set_cmap(get_cmap(name))
        self.fig.canvas.draw()

    def toggle_2d_plot_scale(self, event=None):
        if self.__scale == 'log':
            self.show_data = self.data.T
            self.fig.im.set_array(self.show_data)
            self.fig.im.autoscale()
            self.fig.cb.set_xlabel('$I$')
            self.__scale = 'lin'
            self.menu_log_lin_toggle.Check(False)
            self.statusbar.SetStatusText("%s scale" % self.__scale, 0)
            self.fig.canvas.draw_idle()
        elif self.__scale == 'lin':
            self.show_data = log ( self.data.copy().T + self.minimum_intensity/2.0 )
            self.fig.im.set_array(self.show_data)
            self.fig.im.autoscale()
            self.fig.cb.set_xlabel('$\log_{10}I$')
            self.__scale = 'log'
            self.menu_log_lin_toggle.Check(True)
            self.statusbar.SetStatusText("%s scale" % self.__scale, 0)
            self.fig.canvas.draw_idle()


    def toggle_log_lin(self,event):

        ax = event.inaxes
        label = ax.get_label()

        if label == '2d_plot':
            self.toggle_2d_plot_scale()

        if label == 'sz':
            scale = ax.get_yscale()
            if scale == 'log':
                ax.set_yscale('linear')
                ax.figure.canvas.draw_idle()
            elif scale == 'linear':
                ax.set_yscale('log')
                ax.figure.canvas.draw_idle()

        elif label == 'sx':
            scale = ax.get_xscale()
            if scale == 'log':
                ax.set_xscale('linear')
                ax.figure.canvas.draw_idle()
            elif scale == 'linear':
                ax.set_xscale('log')
                ax.figure.canvas.draw_idle()


    def onmousemove(self,event):
        # the cursor position is given in the wx status bar
        #self.fig.gca()
        if event.inaxes:
            x, y = event.xdata, event.ydata
            self.statusbar.SetStatusText("%s scale x = %.3g, y = %.3g" % (self.__scale,x,y), 1)
            #self.statusbar.SetStatusText("y = %.3g" %y, 2)


    def onselect(self, eclick, erelease):
        x_range = [eclick.xdata, erelease.xdata]
        y_range = [eclick.ydata, erelease.ydata]
        ax = eclick.inaxes
        self.sliceplot((x_range, y_range), ax)
        print 'sliceplot(([%f,%f],[%f,%f]))' % (x_range[0],x_range[1],y_range[0],y_range[1])

    def sliceplots_off(self):
        self.fig.ax.set_position([0.125,0.1,0.7,0.8])
        self.fig.cb.set_position([0.85,0.1,0.05,0.8])
        #self.fig.cb.set_visible(True)
        self.fig.sx.set_visible(False)
        self.fig.sz.set_visible(False)
        if self.fig.slice_overlay:
            self.fig.slice_overlay[0].set_visible(False)
        self.RS.set_active(False)
        self.show_sliceplots = False
        self.fig.canvas.draw()

    def sliceplots_on(self):
        self.fig.ax.set_position([0.125,0.53636364, 0.35227273,0.36363636])
        self.fig.cb.set_position([0.49,0.53636364, 0.02, 0.36363636])
        self.fig.sx.set_position([0.58,0.53636364, 0.35227273,0.36363636])
        self.fig.sx.set_visible(True)
        self.fig.sz.set_visible(True)
        #self.fig.cb.set_visible(False)
        if self.fig.slice_overlay:
            self.fig.slice_overlay[0].set_visible(True)
        self.RS.set_active(True)
        self.show_sliceplots = True
        self.fig.canvas.draw()

    def toggle_sliceplots(self):
        """switch between views with and without slice plots"""
        if self.show_sliceplots == True:
            self.sliceplots_off()
        else: # self.show_sliceplots == False
            self.sliceplots_on()

    def show_slice_overlay(self, x_range, y_range, x, slice_y_data, y, slice_x_data):
        """sum along x and z within the box defined by qX- and qZrange.
        sum along qx is plotted to the right of the data,
        sum along qz is plotted below the data.
        Transparent white rectangle is overlaid on data to show summing region"""
        from matplotlib.ticker import FormatStrFormatter, ScalarFormatter

        if self.fig == None:
            print('No figure for this dataset is available')
            return

        fig = self.fig
        ax = fig.ax
        extent = fig.im.get_extent()

        if fig.slice_overlay == None:
            fig.slice_overlay = ax.fill([x_range[0],x_range[1],x_range[1],x_range[0]],[y_range[0],y_range[0],y_range[1],y_range[1]],fc='white', alpha=0.3)
            fig.ax.set_ylim(extent[2],extent[3])
        else:
            fig.slice_overlay[0].xy = [(x_range[0],y_range[0]), (x_range[1],y_range[0]), (x_range[1],y_range[1]), (x_range[0],y_range[1])]
        fig.sz.clear()
        default_fmt = ScalarFormatter(useMathText=True)
        default_fmt.set_powerlimits((-2,4))
        fig.sz.xaxis.set_major_formatter(default_fmt)
        fig.sz.yaxis.set_major_formatter(default_fmt)
        fig.sz.xaxis.set_major_formatter(FormatStrFormatter('%.2g'))
        fig.sz.set_xlim(x[0], x[-1])
        fig.sz.plot(x, slice_y_data)
        fig.sx.clear()
        fig.sx.yaxis.set_major_formatter(default_fmt)
        fig.sx.xaxis.set_major_formatter(default_fmt)
        fig.sx.yaxis.set_ticks_position('right')
        fig.sx.yaxis.set_major_formatter(FormatStrFormatter('%.2g'))
        fig.sx.set_ylim(y[0], y[-1])
        fig.sx.plot(slice_x_data, y)

        fig.im.set_extent(extent)
        fig.canvas.draw()

    def copy_intensity_range_from(self, other_plot):
        if isinstance(other_plot, type(self)):
            xlab = self.fig.cb.get_xlabel()
            ylab = self.fig.cb.get_ylabel()

            self.fig.im.set_clim(other_plot.fig.im.get_clim())
            self.fig.cb.set_xlabel(xlab)
            self.fig.cb.set_ylabel(ylab)
            self.fig.canvas.draw()

    def sliceplot(self, xy_range, ax = None):
        """sum along x and z within the box defined by qX- and qZrange.
        sum along qx is plotted to the right of the data,
        sum along qz is plotted below the data.
        Transparent white rectangle is overlaid on data to show summing region"""
        self.sliceplots_on()
        x_range, y_range = xy_range
        x, slice_y_data, y, slice_x_data = self.do_xy_slice(x_range, y_range)
        self.x = x
        self.slice_y_data = slice_y_data
        self.y = y
        self.slice_x_data = slice_x_data
        self.slice_xy_range = xy_range

        self.show_slice_overlay(x_range, y_range, x, slice_y_data, y, slice_x_data)

    def do_xy_slice(self, x_range, y_range):
        """ slice up the data, once along x and once along z.
        returns 4 arrays:  a y-axis for the x data,
        an x-axis for the y data."""
        #params = self.params
        print 'doing xy slice'
        data = self.data
        pixels = self.pixel_mask
        # zero out any pixels in the sum that have zero in the pixel count:
        data[pixels == 0] = 0

        normalization_matrix = ones(data.shape)
        normalization_matrix[pixels == 0] = 0
        x_min = min(x_range)
        x_max = max(x_range)
        y_min = min(y_range)
        y_max = max(y_range)

        x_size,y_size = data.shape
        global_x_range = (self.x_max - self.x_min)
        global_y_range = (self.y_max - self.y_min)

        x_pixel_min = round( (x_min - self.x_min) / global_x_range * x_size )
        x_pixel_max = round( (x_max - self.x_min) / global_x_range * x_size )
        y_pixel_min = round( (y_min - self.y_min) / global_y_range * y_size )
        y_pixel_max = round( (y_max - self.y_min) / global_y_range * y_size )

        #correct any sign switches:
        if (x_pixel_min > x_pixel_max):
            new_min = x_pixel_max
            x_pixel_max = x_pixel_min
            x_pixel_min = new_min

        if (y_pixel_min > y_pixel_max):
            new_min = y_pixel_max
            y_pixel_max = y_pixel_min
            y_pixel_min = new_min

        new_x_min = x_pixel_min / x_size * global_x_range + self.x_min
        new_x_max = x_pixel_max / x_size * global_x_range + self.x_min
        new_y_min = y_pixel_min / y_size * global_y_range + self.y_min
        new_y_max = y_pixel_max / y_size * global_y_range + self.y_min

        x_pixel_min = int(x_pixel_min)
        x_pixel_max = int(x_pixel_max)
        y_pixel_min = int(y_pixel_min)
        y_pixel_max = int(y_pixel_max)

        y_norm_factor = sum(normalization_matrix[x_pixel_min:x_pixel_max,y_pixel_min:y_pixel_max], axis=1)
        x_norm_factor = sum(normalization_matrix[x_pixel_min:x_pixel_max,y_pixel_min:y_pixel_max], axis=0)
        # make sure the normalization has a minimum value of 1 everywhere,
        # to avoid divide by zero errors:
        y_norm_factor[y_norm_factor == 0] = 1
        x_norm_factor[x_norm_factor == 0] = 1

        slice_y_data = sum(data[x_pixel_min:x_pixel_max,y_pixel_min:y_pixel_max], axis=1) / y_norm_factor
        slice_x_data = sum(data[x_pixel_min:x_pixel_max,y_pixel_min:y_pixel_max], axis=0) / x_norm_factor

        #slice_y_data = slice_y_data
        #slice_x_data = slice_x_data

        x_vals = arange(slice_y_data.shape[0], dtype = 'float') / slice_y_data.shape[0] * (new_x_max - new_x_min) + new_x_min
        y_vals = arange(slice_x_data.shape[0], dtype = 'float') / slice_x_data.shape[0] * (new_y_max - new_y_min) + new_y_min

        return x_vals, slice_y_data, y_vals, slice_x_data