Exemplo n.º 1
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)
Exemplo n.º 2
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)
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))
Exemplo n.º 4
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)
Exemplo n.º 5
0
class LeftGraphBottom(wx.Panel):
    def __init__(self, parent, statusbar):
        wx.Panel.__init__(self, parent)
        self.statusbar = statusbar
        """
        An polygon editor.
        Key-bindings
          't' toggle vertex markers on and off.  When vertex markers are on,
              you can move them, delete them
          'd' delete the vertex under point
          'i' insert a vertex at point.  You must be within epsilon of the
              line connecting two existing vertices
        """
        self.fig = Figure((4.0, 3.0))
        self.canvas = FigCanvas(self, -1, self.fig)
        self.ax = self.fig.add_subplot(111)
        """ subplots_adjust(bottom=0.14): permet d'ajuster la taille du canevas
        en prenant en compte la legende
        sinon la legende est rognee"""
        self.fig.subplots_adjust(bottom=0.20)
        self.ax.set_ylabel("DW", fontdict=font)
        self.ax.set_xlabel("Depth ($\AA$)", fontdict=font)
        self.toolbar = NavigationToolbar(self.canvas)
        self.toolbar.Hide()
        self.fig.patch.set_facecolor(colorBackgroundGraph)

        self._ind = None  # the active vert
        self.poly = []
        self.line = []
        self.showverts = True
        self.epsilon = 5  # max pixel distance to count as a vertex hit
        self.new_coord = {'indice': 0, 'x': 0, 'y': 0}
        self.modelpv = False

        xs = [-1]
        ys = [-1]
        poly = Polygon(list(zip(xs, ys)),
                       ls='solid',
                       fill=False,
                       closed=False,
                       animated=True)
        self.ax.set_xlim([0, 1])
        self.ax.set_ylim([0, 1])
        self.c_dw = ""
        self.l_dw = ""

        self.canvas.mpl_connect('draw_event', self.draw_callback)
        self.canvas.mpl_connect('button_press_event',
                                self.button_press_callback)
        self.canvas.mpl_connect('button_release_event',
                                self.button_release_callback)
        self.canvas.mpl_connect('motion_notify_event',
                                self.motion_notify_callback)
        self.canvas.mpl_connect('scroll_event', self.scroll_callback)
        self.canvas.mpl_connect('motion_notify_event',
                                self.on_update_coordinate)

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

        pub.subscribe(self.draw_c, pubsub_draw_graph)
        pub.subscribe(self.OnDrawGraph, pubsub_Draw_DW)
        pub.subscribe(self.scale_manual, pubsub_Update_Scale_DW)
        pub.subscribe(self.on_color, pubsub_Graph_change_color_style)

        self.on_color()
        self.draw_c(poly, xs, ys)

        self.SetSizer(mastersizer)
        self.Fit()

    def on_color(self):
        a = P4Rm()
        self.c_dw = a.DefaultDict['c_dw']
        self.l_dw = a.DefaultDict['l_dw']
        self.c_bkg = a.DefaultDict['c_graph_background']

    def OnDrawGraph(self, b=None):
        a = P4Rm()
        self.modelpv = a.modelPv
        self.ax.clear()
        if a.AllDataDict['damaged_depth'] == 0:
            self.ax.text(0.5,
                         0.5,
                         "No Damage",
                         size=30,
                         rotation=0.,
                         ha="center",
                         va="center",
                         bbox=dict(
                             boxstyle="round",
                             ec='red',
                             fc=self.c_dw,
                         ))
            x_dwp = [-1]
            y_dwp = [-1]
            xs = [-1]
            ys = [-1]
            self.ax.set_xticklabels([])
            self.ax.set_yticklabels([])
            self.ax.set_xlim([0, 1])
            self.ax.set_ylim([0, 1])
        else:
            if b != 2:
                x_dwp = a.ParamDict['x_dwp']
                y_dwp = a.ParamDict['DW_shifted']
                xs = deepcopy(a.ParamDict['depth'])
                ys = deepcopy(a.ParamDict['DW_i'])
                P4Rm.DragDrop_DW_x = x_dwp
                P4Rm.DragDrop_DW_y = y_dwp
                ymin = min(ys) - min(ys) * 10 / 100
                ymax = max(ys) + max(ys) * 10 / 100
                self.ax.set_ylim([ymin, ymax])
                if a.ParamDict['x_dwp'] != "":
                    self.ax.set_xlim(
                        [a.ParamDict['depth'][-1], a.ParamDict['depth'][0]])
            elif b == 2:
                x_dwp = [-1]
                y_dwp = [-1]
                xs = [-1]
                ys = [-1]
                self.ax.set_xlim([0, 1])
                self.ax.set_ylim([0, 1])
        poly = Polygon(list(zip(x_dwp, y_dwp)),
                       lw=0,
                       ls='solid',
                       color=self.c_dw,
                       fill=False,
                       closed=False,
                       animated=True)
        if self.modelpv is True:
            P4Rm.ParamDict['dwp_pv_backup'] = a.ParamDict['dwp']
        self.draw_c(poly, xs, ys)

    def draw_c(self, data, x, y):
        self.ax.plot(x, y, color=self.c_dw, lw=2., ls='solid')
        self.ax.set_ylabel("DW", fontdict=font)
        self.ax.set_xlabel("Depth ($\AA$)", 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.poly = data
        xs, ys = zip(*self.poly.xy)
        self.line = Line2D(xs,
                           ys,
                           lw=0,
                           ls='solid',
                           color=self.c_dw,
                           marker='.',
                           ms=32,
                           markerfacecolor=self.c_dw,
                           markeredgecolor='k',
                           mew=1.0)
        self.ax.add_line(self.line)
        self.ax.add_patch(self.poly)
        self.canvas.SetCursor(Cursor(wx.CURSOR_HAND))
        self.canvas.draw()

    def draw_callback(self, event):
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        self.ax.draw_artist(self.poly)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)

    def get_ind_under_point(self, event):
        'get the index of the vertex under point if within epsilon tolerance'

        # display coords
        xy = np.asarray(self.poly.xy)
        xyt = self.poly.get_transform().transform(xy)
        xt, yt = xyt[:, 0], xyt[:, 1]
        d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
        indseq = np.nonzero(np.equal(d, np.amin(d)))[0]
        ind = indseq[0]

        if d[ind] >= self.epsilon:
            ind = None
        return ind

    def button_press_callback(self, event):
        'whenever a mouse button is pressed'
        a = P4Rm()
        val = a.xrd_graph_loaded
        if self.canvas.HasCapture():
            self.canvas.ReleaseMouse()
            if not self.showverts:
                return
            if event.inaxes is None:
                return
            if event.button != 1:
                return
            if val == 1:
                self._ind = self.get_ind_under_point(event)
                self.new_coord['indice'] = self._ind

    def button_release_callback(self, event):
        'whenever a mouse button is released'
        a = P4Rm()
        val = a.xrd_graph_loaded
        if self.canvas.HasCapture():
            self.canvas.ReleaseMouse()
        else:
            if not self.showverts:
                return
            if event.button != 1:
                return
            if self.new_coord['indice'] is not None and val == 1:
                a = P4Rm()
                temp_1 = self.new_coord['y']
                temp_2 = self.new_coord['x']
                P4Rm.DragDrop_DW_y[self.new_coord['indice']] = temp_1
                P4Rm.DragDrop_DW_x[self.new_coord['indice']] = temp_2
                if a.AllDataDict['model'] == 0:
                    temp = self.new_coord['y']
                    P4Rm.DragDrop_DW_y[self.new_coord['indice']] = temp
                    temp = [
                        dw * scale for dw, scale in zip(
                            a.DragDrop_DW_y, a.ParamDict['scale_dw'])
                    ]
                    temp = [float(format(value, '.8f')) for value in temp]
                    temp2 = np.concatenate([temp, [a.ParamDict['dw_out']]])
                    P4Rm.ParamDict['dwp'] = deepcopy(temp2)
                    P4Rm.ParamDictbackup['dwp'] = deepcopy(temp2)
                elif a.AllDataDict['model'] == 1:
                    temp = self.new_coord['y']
                    P4Rm.DragDrop_DW_y[self.new_coord['indice']] = temp
                    temp = [
                        dw * scale for dw, scale in zip(
                            a.DragDrop_DW_y, a.ParamDict['scale_dw'])
                    ]
                    temp = [float(format(value, '.8f')) for value in temp]
                    temp2 = np.concatenate([[a.ParamDict['dw_out'][0]], temp,
                                            [a.ParamDict['dw_out'][1]]])
                    P4Rm.ParamDict['dwp'] = deepcopy(temp2)
                    P4Rm.ParamDictbackup['dwp'] = deepcopy(temp2)
                elif a.AllDataDict['model'] == 2:
                    t_temp = a.ParamDict['depth'] + a.ParamDict['z']
                    t = t_temp[0]
                    dwp_temp = range(7)
                    dwp_temp[0] = a.DragDrop_DW_y[0]
                    dwp_temp[1] = 1 - a.DragDrop_DW_x[0] / t
                    dwp_temp[2] = 2 * (-1 + a.ParamDict['dwp'][1] +
                                       a.DragDrop_DW_x[1] / t)
                    dwp_temp[3] = 2 * (1 - a.ParamDict['dwp'][1] -
                                       1 * a.DragDrop_DW_x[2] / t)
                    dwp_temp[4] = a.ParamDict['dwp'][4]
                    dwp_temp[5] = a.ParamDict['dwp'][5]
                    dwp_temp[6] = a.DragDrop_DW_y[3]
                    P4Rm.ParamDict['dwp'] = deepcopy(dwp_temp)
                    P4Rm.ParamDictbackup['dwp'] = deepcopy(dwp_temp)
                    P4Rm.ParamDict['dwp_pv'] = deepcopy(dwp_temp)
                pub.sendMessage(pubsub_Update_Fit_Live)
            self._ind = None

    def scroll_callback(self, event):
        if not event.inaxes:
            return
        a = P4Rm()
        if event.key == 'u' and event.button == 'up':
            temp = a.ParamDict['DW_multiplication'] + 0.01
            P4Rm.ParamDict['DW_multiplication'] = temp
        elif event.key == 'u' and event.button == 'down':
            temp = a.ParamDict['DW_multiplication'] - 0.01
            P4Rm.ParamDict['DW_multiplication'] = temp
        P4Rm.ParamDict['dwp'] = multiply(a.ParamDictbackup['dwp'],
                                         a.ParamDict['DW_multiplication'])
        pub.sendMessage(pubsub_Re_Read_field_paramters_panel, event=event)

    def scale_manual(self, event, val=None):
        a = P4Rm()
        if val is not None:
            P4Rm.ParamDict['DW_multiplication'] = val
        P4Rm.ParamDict['dwp'] = multiply(a.ParamDict['dwp'],
                                         a.ParamDict['DW_multiplication'])
        pub.sendMessage(pubsub_Re_Read_field_paramters_panel, event=event)

    def motion_notify_callback(self, event):
        'on mouse movement'
        a = P4Rm()
        if a.AllDataDict['damaged_depth'] == 0:
            return
        if not self.showverts:
            return
        if self._ind is None:
            return
        if event.inaxes is None:
            return
        if event.button != 1:
            return

        if self.modelpv is True:
            if self._ind == 0:
                y = event.ydata
                x = event.xdata
            elif self._ind == 1 or self._ind == 2:
                y = a.DragDrop_DW_y[self.new_coord['indice']]
                x = event.xdata
            else:
                x = a.DragDrop_DW_x[self.new_coord['indice']]
                y = event.ydata
        else:
            y = event.ydata
            x = a.DragDrop_DW_x[self.new_coord['indice']]

        self.new_coord['x'] = x
        self.new_coord['y'] = y
        self.poly.xy[self._ind] = x, y
        self.line.set_data(zip(*self.poly.xy))

        self.canvas.restore_region(self.background)
        self.ax.draw_artist(self.poly)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)

    def on_update_coordinate(self, event):
        if event.inaxes is None:
            self.statusbar.SetStatusText(u"", 1)
            self.statusbar.SetStatusText(u"", 2)
        else:
            a = P4Rm()
            if not a.AllDataDict['damaged_depth'] == 0:
                x, y = event.xdata, event.ydata
                xfloat = round(float(x), 2)
                yfloat = round(float(y), 2)
                self.statusbar.SetStatusText(u"x = " + str(xfloat), 1)
                self.statusbar.SetStatusText(u"y = " + str(yfloat), 2)
                xy = np.asarray(self.poly.xy)
                xyt = self.poly.get_transform().transform(xy)
                xt, yt = xyt[:, 0], xyt[:, 1]
                d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
                indseq = np.nonzero(np.equal(d, np.amin(d)))[0]
                ind = indseq[0]

                if d[ind] >= self.epsilon:
                    self.canvas.SetCursor(Cursor(wx.CURSOR_ARROW))
                elif d[ind] <= self.epsilon:
                    self.canvas.SetCursor(Cursor(wx.CURSOR_HAND))
Exemplo n.º 6
0
class PlotPanel(BasePanel):
    """
    MatPlotlib 2D plot as a wx.Panel, suitable for embedding
    in any wx.Frame.   This does provide a right-click popup
    menu for configuration, zooming, saving an image of the
    figure, and Ctrl-C for copy-image-to-clipboard.

    For more features, see PlotFrame, which embeds a PlotPanel
    and also provides, a Menu, StatusBar, and Printing support.
    """
    def __init__(self,
                 parent,
                 size=(700, 450),
                 dpi=150,
                 axisbg=None,
                 facecolor=None,
                 fontsize=9,
                 trace_color_callback=None,
                 output_title='plot',
                 with_data_process=True,
                 theme=None,
                 **kws):

        self.trace_color_callback = trace_color_callback
        BasePanel.__init__(self, parent, output_title=output_title, **kws)

        self.conf = PlotConfig(panel=self,
                               theme=theme,
                               with_data_process=with_data_process)
        self.data_range = {}
        self.win_config = None
        self.cursor_callback = None
        self.lasso_callback = None
        self.cursor_mode = 'zoom'
        self.parent = parent
        self.figsize = (size[0] * 1.0 / dpi, size[1] * 1.0 / dpi)
        self.dpi = dpi
        self.conf.facecolor = ifnotNone(axisbg, self.conf.facecolor)
        self.conf.facecolor = ifnotNone(facecolor, self.conf.facecolor)

        # axesmargins : margins in px left/top/right/bottom
        self.axesmargins = (30, 30, 30, 30)

        self.BuildPanel()
        self.conf.user_limits = {}  # [None, None, None, None]
        self.data_range = {}
        self.conf.zoom_lims = []
        self.conf.axes_traces = {}

    def plot(self,
             xdata,
             ydata,
             side='left',
             title=None,
             xlabel=None,
             ylabel=None,
             y2label=None,
             use_dates=False,
             **kws):
        """
        create a new plot of x/y data, clearing any existing plot on the panel



        """
        allaxes = self.fig.get_axes()
        if len(allaxes) > 1:
            for ax in allaxes[1:]:
                if ax in self.data_range:
                    self.data_range.pop(ax)
                self.fig.delaxes(ax)

        self.data_range = {}
        self.conf.zoom_lims = []
        self.conf.axes_traces = {}
        self.clear()
        axes = self.axes
        if side == 'right':
            axes = self.get_right_axes()
        self.conf.reset_lines()
        self.conf.yscale = 'linear'
        self.conf.user_limits[axes] = [None, None, None, None]

        if xlabel is not None:
            self.set_xlabel(xlabel, delay_draw=True)
        if ylabel is not None:
            self.set_ylabel(ylabel, delay_draw=True)
        if y2label is not None:
            self.set_y2label(y2label, delay_draw=True)
        if title is not None:
            self.set_title(title, delay_draw=True)
        self.use_datas = ifnotNone(use_dates, self.use_dates)
        return self.oplot(xdata, ydata, side=side, **kws)

    def oplot(self,
              xdata,
              ydata,
              side='left',
              label=None,
              xlabel=None,
              ylabel=None,
              y2label=None,
              title=None,
              dy=None,
              ylog_scale=None,
              xlog_scale=None,
              grid=None,
              xmin=None,
              xmax=None,
              ymin=None,
              ymax=None,
              color=None,
              style=None,
              drawstyle=None,
              linewidth=2,
              marker=None,
              markersize=None,
              refresh=True,
              show_legend=None,
              legend_loc='best',
              legend_on=True,
              delay_draw=False,
              bgcolor=None,
              framecolor=None,
              gridcolor=None,
              labelfontsize=None,
              titlefontsize=None,
              legendfontsize=None,
              fullbox=None,
              axes_style=None,
              zorder=None,
              viewpad=None,
              theme=None,
              **kws):
        """
        basic plot method, adding to an existing display

        """
        self.cursor_mode = 'zoom'
        conf = self.conf
        conf.plot_type = 'lineplot'
        axes = self.axes
        if theme is not None:
            conf.set_theme(theme=theme)
        if side == 'right':
            axes = self.get_right_axes()
        # set y scale to log/linear
        if ylog_scale is not None:
            conf.yscale = {False: 'linear', True: 'log'}[ylog_scale]

        if xlog_scale is not None:
            conf.xscale = {False: 'linear', True: 'log'}[xlog_scale]

        axes.xaxis.set_major_formatter(FuncFormatter(self.xformatter))
        if self.use_dates:
            xdata = [datetime.fromtimestamp(i) for i in xdata]
            xdata = dates.date2num(xdata)
            # axes.xaxis.set_major_locator(dates.AutoDateLocator())

        linewidth = ifNone(linewidth, 2)
        conf.viewpad = ifnotNone(viewpad, conf.viewpad)

        if xlabel is not None:
            self.set_xlabel(xlabel, delay_draw=delay_draw)
        if ylabel is not None:
            self.set_ylabel(ylabel, delay_draw=delay_draw)
        if y2label is not None:
            self.set_y2label(y2label, delay_draw=delay_draw)
        if title is not None:
            self.set_title(title, delay_draw=delay_draw)
        if show_legend is not None:
            conf.set_legend_location(legend_loc, legend_on)
            conf.show_legend = show_legend

        conf.show_grid = ifnotNone(grid, conf.show_grid)

        # set data range for this trace
        # datarange = [min(xdata), max(xdata), min(ydata), max(ydata)]

        if axes not in conf.user_limits:
            conf.user_limits[axes] = [None, None, None, None]

        conf.user_limits[axes][0] = ifnotNone(xmin, conf.user_limits[axes][0])
        conf.user_limits[axes][1] = ifnotNone(xmax, conf.user_limits[axes][1])
        conf.user_limits[axes][2] = ifnotNone(ymin, conf.user_limits[axes][2])
        conf.user_limits[axes][3] = ifnotNone(ymax, conf.user_limits[axes][3])

        if axes == self.axes:
            axes.yaxis.set_major_formatter(FuncFormatter(self.yformatter))
        else:
            axes.yaxis.set_major_formatter(FuncFormatter(self.y2formatter))

        zorder = ifNone(zorder, 5 * (conf.ntrace + 1))

        if axes not in conf.axes_traces:
            conf.axes_traces[axes] = []
        conf.axes_traces[axes].append(conf.ntrace)

        conf.gridcolor = ifnotNone(gridcolor, conf.gridcolor)
        conf.facecolor = ifnotNone(bgcolor, conf.facecolor)

        if framecolor is not None:
            self.canvas.figure.set_facecolor(framecolor)

        conf.set_trace_zorder(zorder, delay_draw=True)
        if color:
            conf.set_trace_color(color, delay_draw=True)
        if style:
            conf.set_trace_style(style, delay_draw=True)
        if marker:
            conf.set_trace_marker(marker, delay_draw=True)
        if linewidth is not None:
            conf.set_trace_linewidth(linewidth, delay_draw=True)
        if markersize is not None:
            conf.set_trace_markersize(markersize, delay_draw=True)
        if drawstyle is not None:
            conf.set_trace_drawstyle(drawstyle, delay_draw=True)
        if dy is None:
            _lines = axes.plot(xdata,
                               ydata,
                               drawstyle=drawstyle,
                               zorder=zorder)
        else:
            _lines = axes.errorbar(xdata, ydata, yerr=dy, zorder=zorder)

        if axes not in conf.data_save:
            conf.data_save[axes] = []
        conf.data_save[axes].append((xdata, ydata))

        if conf.show_grid and axes == self.axes:
            # I'm sure there's a better way...
            for i in axes.get_xgridlines() + axes.get_ygridlines():
                i.set_color(conf.gridcolor)
                i.set_zorder(-100)
            axes.grid(True)
        else:
            axes.grid(False)

        if (self.conf.xscale == 'log' or self.conf.yscale == 'log'):
            self.set_logscale(xscale=self.conf.xscale,
                              yscale=self.conf.yscale,
                              delay_draw=delay_draw)

        if label is None:
            label = 'trace %i' % (conf.ntrace + 1)
        conf.set_trace_label(label, delay_draw=True)
        needs_relabel = False
        if labelfontsize is not None:
            conf.labelfont.set_size(labelfontsize)
            needs_relabel = True
        if titlefontsize is not None:
            conf.titlefont.set_size(titlefontsize)
            needs_relabel = True

        if legendfontsize is not None:
            conf.legendfont.set_size(legendfontsize)
            needs_relabel = True

        if conf.ntrace < len(conf.lines):
            conf.lines[conf.ntrace] = _lines
        else:
            conf.init_trace(conf.ntrace, 'black', 'solid')
            conf.lines.append(_lines)

        # now set plot limits:
        if not delay_draw:
            self.set_viewlimits()

        if refresh:
            conf.refresh_trace(conf.ntrace)
            needs_relabel = True

        if conf.show_legend and not delay_draw:
            conf.draw_legend()

        if needs_relabel and not delay_draw:
            conf.relabel()

        # axes style ('box' or 'open')
        conf.axes_style = 'box'
        if fullbox is not None and not fullbox:
            conf.axes_style = 'open'
        if axes_style in ('open', 'box', 'bottom'):
            conf.axes_style = axes_style
        conf.set_axes_style(delay_draw=delay_draw)
        if not delay_draw:
            self.draw()
            self.canvas.Refresh()
        conf.ntrace = conf.ntrace + 1
        # print("# oplot done")
        return _lines

    def plot_many(self,
                  datalist,
                  side='left',
                  title=None,
                  xlabel=None,
                  ylabel=None,
                  **kws):
        """
        plot many traces at once, taking a list of (x, y) pairs
        """
        def unpack_tracedata(tdat, **kws):
            if (isinstance(tdat, dict) and 'xdata' in tdat
                    and 'ydata' in tdat):
                xdata = tdat.pop('xdata')
                ydata = tdat.pop('ydata')
                out = kws
                out.update(tdat)
            elif isinstance(tdat, (list, tuple)):
                out = kws
                xdata = tdat[0]
                ydata = tdat[1]
            return (xdata, ydata, out)

        opts = dict(side=side,
                    title=title,
                    xlabel=xlabel,
                    ylabel=ylabel,
                    delay_draw=True)
        opts.update(kws)
        x0, y0, opts = unpack_tracedata(datalist[0], **opts)

        self.plot(x0, y0, **opts)

        for dat in datalist[1:]:
            x, y, opts = unpack_tracedata(dat, delay_draw=True)
            self.oplot(x, y, **opts)

        conf = self.conf
        if conf.show_legend:
            conf.draw_legend()
        conf.relabel()
        self.draw()
        self.canvas.Refresh()

    def add_text(self,
                 text,
                 x,
                 y,
                 side='left',
                 size=None,
                 rotation=None,
                 ha='left',
                 va='center',
                 family=None,
                 **kws):
        """add text at supplied x, y position
        """
        axes = self.axes
        if side == 'right':
            axes = self.get_right_axes()
        dynamic_size = False
        if size is None:
            size = self.conf.legendfont.get_size()
            dynamic_size = True
        t = axes.text(x,
                      y,
                      text,
                      ha=ha,
                      va=va,
                      size=size,
                      rotation=rotation,
                      family=family,
                      **kws)
        self.conf.added_texts.append((dynamic_size, t))
        self.draw()

    def add_arrow(self,
                  x1,
                  y1,
                  x2,
                  y2,
                  side='left',
                  shape='full',
                  color='black',
                  width=0.01,
                  head_width=0.03,
                  overhang=0,
                  **kws):
        """add arrow supplied x, y position"""
        dx, dy = x2 - x1, y2 - y1

        axes = self.axes
        if side == 'right':
            axes = self.get_right_axes()
        axes.arrow(x1,
                   y1,
                   dx,
                   dy,
                   shape=shape,
                   length_includes_head=True,
                   fc=color,
                   edgecolor=color,
                   width=width,
                   head_width=head_width,
                   overhang=overhang,
                   **kws)
        self.draw()

    def scatterplot(self,
                    xdata,
                    ydata,
                    label=None,
                    size=10,
                    color=None,
                    edgecolor=None,
                    selectcolor=None,
                    selectedge=None,
                    xlabel=None,
                    ylabel=None,
                    y2label=None,
                    xmin=None,
                    xmax=None,
                    ymin=None,
                    ymax=None,
                    viewpad=None,
                    title=None,
                    grid=None,
                    callback=None,
                    **kw):

        if xlabel is not None:
            self.set_xlabel(xlabel)
        if ylabel is not None:
            self.set_ylabel(ylabel)
        if y2label is not None:
            self.set_y2label(y2label)
        if title is not None:
            self.set_title(title)
        if grid is not None:
            self.conf.show_grid = grid
        if callback is not None:
            self.lasso_callback = callback

        self.conf.plot_type = 'scatter'
        self.cursor_mode = 'lasso'
        if color is not None:
            self.conf.scatter_normalcolor = color
        if edgecolor is not None:
            self.conf.scatter_normaledge = edgecolor
        if selectcolor is not None:
            self.conf.scatter_selectcolor = selectcolor
        if selectedge is not None:
            self.conf.scatter_selectedge = selectedge
        if viewpad is not None:
            conf.viewpad = viewpad

        axes = self.axes
        self.conf.user_limits[axes] = [xmin, xmax, ymin, ymax]

        self.conf.axes_traces = {axes: [0]}
        self.conf.set_trace_label('scatterplot')
        # self.conf.set_trace_datarange((min(xdata), max(xdata),
        #                                min(ydata), max(ydata)))

        self.conf.scatter_xdata = xdata
        self.conf.scatter_ydata = ydata
        self.axes.scatter(xdata,
                          ydata,
                          c=self.conf.scatter_normalcolor,
                          edgecolors=self.conf.scatter_normaledge)

        if self.conf.show_grid:
            for i in axes.get_xgridlines() + axes.get_ygridlines():
                i.set_color(self.conf.gridcolor)
                i.set_zorder(-30)
            axes.grid(True)
        else:
            axes.grid(False)
        xrange = max(xdata) - min(xdata)
        yrange = max(ydata) - min(ydata)

        xmin = min(xdata) - xrange / 25.0
        xmax = max(xdata) + xrange / 25.0
        ymin = min(ydata) - yrange / 25.0
        ymax = max(ydata) + yrange / 25.0

        axes.set_xlim((xmin, xmax), emit=True)
        axes.set_ylim((ymin, ymax), emit=True)
        self.set_viewlimits()
        self.draw()

    def lassoHandler(self, vertices):
        conf = self.conf
        if self.conf.plot_type == 'scatter':
            xd, yd = conf.scatter_xdata, conf.scatter_ydata
            sdat = list(zip(xd, yd))
            oldmask = conf.scatter_mask
            try:
                self.axes.scatter(xd[where(oldmask)],
                                  yd[where(oldmask)],
                                  s=conf.scatter_size,
                                  c=conf.scatter_normalcolor,
                                  edgecolors=conf.scatter_normaledge)
            except IndexError:
                self.axes.scatter(xd,
                                  yd,
                                  s=conf.scatter_size,
                                  c=conf.scatter_normalcolor,
                                  edgecolors=conf.scatter_normaledge)

            mask = conf.scatter_mask = inside_poly(vertices, sdat)
            pts = nonzero(mask)[0]
            self.axes.scatter(xd[where(mask)],
                              yd[where(mask)],
                              s=conf.scatter_size,
                              c=conf.scatter_selectcolor,
                              edgecolors=conf.scatter_selectedge)

        else:
            xdata = self.axes.lines[0].get_xdata()
            ydata = self.axes.lines[0].get_ydata()
            sdat = [(x, y) for x, y in zip(xdata, ydata)]
            mask = inside_poly(vertices, sdat)
            pts = nonzero(mask)[0]

        self.lasso = None
        self.draw()
        # self.canvas.draw_idle()
        if (self.lasso_callback is not None
                and hasattr(self.lasso_callback, '__call__')):
            self.lasso_callback(data=sdat, selected=pts, mask=mask)

    def set_xylims(self, limits, axes=None, side='left'):
        "set user-defined limits and apply them"
        if axes is None:
            axes = self.axes
            if side == 'right':
                axes = self.get_right_axes()
        self.conf.user_limits[axes] = list(limits)
        self.unzoom_all()

    def set_viewlimits(self):
        """updates xy limits of a plot based on current data,
        user defined limits, and any zoom level

        """
        self.conf.set_viewlimits()

    def get_viewlimits(self, axes=None):
        if axes is None: axes = self.axes
        xmin, xmax = axes.get_xlim()
        ymin, ymax = axes.get_ylim()
        return (xmin, xmax, ymin, ymax)

    def clear(self):
        """ clear plot """
        for ax in self.fig.get_axes():
            ax.cla()
        self.conf.ntrace = 0
        self.conf.xlabel = ''
        self.conf.ylabel = ''
        self.conf.y2label = ''
        self.conf.title = ''
        self.conf.data_save = {}

    def reset_config(self):
        """reset configuration to defaults."""
        self.conf.set_defaults()

    def unzoom(self, event=None, **kws):
        """ zoom out 1 level, or to full data range """
        self.conf.unzoom(full=False)

    def unzoom_all(self, event=None):
        """ zoom out full data range """
        self.conf.unzoom(full=True)

    def process_data(self, event=None, expr=None):
        if expr in self.conf.data_expressions:
            self.conf.data_expr = expr
            self.conf.process_data()
            self.draw()
        if expr is None:
            expr = ''
        if self.conf.data_deriv:
            if expr is None:
                expr = 'y'
            expr = "deriv(%s)" % expr
        self.write_message("plotting %s" % expr, panel=0)

    def toggle_deriv(self, evt=None, value=None):
        "toggle derivative of data"
        if value is None:
            self.conf.data_deriv = not self.conf.data_deriv

            expr = self.conf.data_expr or ''
            if self.conf.data_deriv:
                expr = "deriv(%s)" % expr
            self.write_message("plotting %s" % expr, panel=0)

            self.conf.process_data()

    def set_logscale(self,
                     event=None,
                     xscale='linear',
                     yscale='linear',
                     delay_draw=False):
        "set log or linear scale for x, y axis"
        self.conf.set_logscale(xscale=xscale,
                               yscale=yscale,
                               delay_draw=delay_draw)

    def toggle_legend(self, evt=None, show=None):
        "toggle legend display"
        if show is None:
            show = not self.conf.show_legend
            self.conf.show_legend = show
        self.conf.draw_legend()

    def toggle_grid(self, evt=None, show=None):
        "toggle grid display"
        if show is None:
            show = not self.conf.show_grid
        self.conf.enable_grid(show)

    def configure(self, event=None):
        """show configuration frame"""
        if self.win_config is not None:
            try:
                self.win_config.Raise()
            except:
                self.win_config = None

        if self.win_config is None:
            self.win_config = PlotConfigFrame(
                parent=self,
                config=self.conf,
                trace_color_callback=self.trace_color_callback)
            self.win_config.Raise()

    ####
    ## create GUI
    ####
    def BuildPanel(self):
        """ builds basic GUI panel and popup menu"""
        self.fig = Figure(self.figsize, dpi=self.dpi)
        # 1 axes for now
        self.gridspec = GridSpec(1, 1)
        self.axes = self.fig.add_subplot(self.gridspec[0],
                                         facecolor=self.conf.facecolor)
        self.canvas = FigureCanvas(self, -1, self.fig)

        self.printer.canvas = self.canvas
        self.set_bg(self.conf.framecolor)
        self.conf.canvas = self.canvas
        self.canvas.SetCursor(wxCursor(wx.CURSOR_CROSS))
        self.canvas.mpl_connect("pick_event", self.__onPickEvent)

        # overwrite ScalarFormatter from ticker.py here:
        self.axes.xaxis.set_major_formatter(FuncFormatter(self.xformatter))
        self.axes.yaxis.set_major_formatter(FuncFormatter(self.yformatter))

        # This way of adding to sizer allows resizing
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 2, wx.LEFT | wx.TOP | wx.BOTTOM | wx.EXPAND, 0)
        self.SetAutoLayout(True)
        self.autoset_margins()
        self.SetSizer(sizer)
        self.Fit()

        canvas_draw = self.canvas.draw

        def draw(*args, **kws):
            self.autoset_margins()
            canvas_draw(*args, **kws)

        self.canvas.draw = draw
        self.addCanvasEvents()

    def _updateCanvasDraw(self):
        """ Overload of the draw function that update
        axes position before each draw"""
        fn = self.canvas.draw

        def draw2(*a, **k):
            self._updateGridSpec()
            return fn(*a, **k)

        self.canvas.draw = draw2

    def get_default_margins(self):
        """get default margins"""
        trans = self.fig.transFigure.inverted().transform

        # Static margins
        l, t, r, b = self.axesmargins
        (l, b), (r, t) = trans(((l, b), (r, t)))

        # Extent
        dl, dt, dr, db = 0, 0, 0, 0
        for i, ax in enumerate(self.fig.get_axes()):
            (x0, y0), (x1, y1) = ax.get_position().get_points()
            try:
                (ox0, oy0), (ox1, oy1) = ax.get_tightbbox(
                    self.canvas.get_renderer()).get_points()
                (ox0, oy0), (ox1, oy1) = trans(((ox0, oy0), (ox1, oy1)))
                dl = min(0.2, max(dl, (x0 - ox0)))
                dt = min(0.2, max(dt, (oy1 - y1)))
                dr = min(0.2, max(dr, (ox1 - x1)))
                db = min(0.2, max(db, (y0 - oy0)))
            except:
                pass

        return (l + dl, t + dt, r + dr, b + db)

    def autoset_margins(self):
        """auto-set margins  left, bottom, right, top
        according to the specified margins (in pixels)
        and axes extent (taking into account labels,
        title, axis)
        """
        if not self.conf.auto_margins:
            return
        # coordinates in px -> [0,1] in figure coordinates
        trans = self.fig.transFigure.inverted().transform

        # Static margins
        if not self.use_dates:
            self.conf.margins = l, t, r, b = self.get_default_margins()
            self.gridspec.update(left=l, top=1 - t, right=1 - r, bottom=b)
        # Axes positions update
        for ax in self.fig.get_axes():
            try:
                ax.update_params()
            except ValueError:
                pass
            ax.set_position(ax.figbox)

    def draw(self):
        self.canvas.draw()

    def update_line(self,
                    trace,
                    xdata,
                    ydata,
                    side='left',
                    draw=False,
                    update_limits=True):
        """ update a single trace, for faster redraw """

        x = self.conf.get_mpl_line(trace)
        x.set_data(xdata, ydata)
        # datarange = [xdata.min(), xdata.max(), ydata.min(), ydata.max()]
        # self.conf.set_trace_datarange(datarange, trace=trace)
        axes = self.axes
        if side == 'right':
            axes = self.get_right_axes()

        if update_limits:
            self.set_viewlimits()
        if draw:
            self.draw()

    def get_figure(self):
        return self.fig

    def __onPickEvent(self, event=None):
        """pick events"""
        legline = event.artist
        trace = self.conf.legend_map.get(legline, None)
        visible = True
        if trace is not None and self.conf.hidewith_legend:
            line, legline, legtext = trace
            visible = not line.get_visible()
            line.set_visible(visible)
            if visible:
                legline.set_zorder(10.00)
                legline.set_alpha(1.00)
                legtext.set_zorder(10.00)
                legtext.set_alpha(1.00)
            else:
                legline.set_alpha(0.50)
                legtext.set_alpha(0.50)

    ####
    ## GUI events
    ####
    def report_leftdown(self, event=None):
        if event is None:
            return
        ex, ey = event.x, event.y
        msg = ''
        try:
            x, y = self.axes.transData.inverted().transform((ex, ey))
        except:
            x, y = event.xdata, event.ydata

        if x is not None and y is not None:
            msg = ("X,Y= %s, %s" % (self._xfmt, self._yfmt)) % (x, y)
        if len(self.fig.get_axes()) > 1:
            ax2 = self.fig.get_axes()[1]
            try:
                x2, y2 = ax2.transData.inverted().transform((ex, ey))
                msg = "X,Y,Y2= %s, %s, %s" % (self._xfmt, self._yfmt,
                                              self._y2fmt) % (x, y, y2)
            except:
                pass

        nsbar = getattr(self, 'nstatusbar', 1)
        self.write_message(msg, panel=max(0, nsbar - 2))
        if (self.cursor_callback is not None
                and hasattr(self.cursor_callback, '__call__')):
            self.cursor_callback(x=event.xdata, y=event.ydata)
Exemplo n.º 7
0
class MegaPlotWindow(PlotWindow):
    """Specialized four-panel PlotWindow for displaying
    A, B, and C scans of a three-dimensional dataset"""
    def __init__(self, parent, data_file):
        self.parent = parent
        self.data_file = data_file
        self.controller = MegaPlotWindowController(self, data_file)
        module_logger.info("Successfully initialized MegaPlotWindow.")
        self.load_data()

    @property
    def axes(self):
        """Returns a tuple of all the view's axes"""
        return (self.ascan_axes, self.hbscan_axes, self.vbscan_axes,
                self.cscan_axes)

    def init_ui(self):
        """Creates the PlotWindow UI"""
        parent_x, parent_y = self.parent.GetPositionTuple()
        parent_w, parent_h = self.parent.GetSize()
        self.SetPosition((parent_x + parent_w + ui_defaults.widget_margin,
                          ui_defaults.widget_margin))
        self.main_panel = wx.Panel(self)
        self.main_panel_sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer = wx.BoxSizer(wx.VERTICAL)

        # Controls for specifying (x,y,z) position in 3D dataset
        self.ctrl_panel = wx.Panel(self.main_panel)
        self.ctrl_sizer = wx.BoxSizer(wx.HORIZONTAL)
        info_lbl = wx.StaticText(self.ctrl_panel, wx.ID_ANY,
                                 u"Coordinates In Data:", wx.DefaultPosition,
                                 wx.DefaultSize)
        self.ctrl_sizer.Add(info_lbl, ui_defaults.lbl_pct,
                            ui_defaults.lblsizer_flags,
                            ui_defaults.widget_margin)
        xpos_lbl = wx.StaticText(self.ctrl_panel, wx.ID_ANY, u"X Position",
                                 wx.DefaultPosition, wx.DefaultSize)
        self.ctrl_sizer.Add(xpos_lbl, ui_defaults.lbl_pct,
                            ui_defaults.lblsizer_flags,
                            ui_defaults.widget_margin)
        self.xpos_sc = wx.SpinCtrl(self.ctrl_panel,
                                   wx.ID_ANY,
                                   value="",
                                   min=0,
                                   max=self.controller.data.shape[1] - 1)
        self.Bind(wx.EVT_SPINCTRL, self.controller.on_xy_change, self.xpos_sc)
        self.ctrl_sizer.Add(self.xpos_sc, ui_defaults.ctrl_pct,
                            ui_defaults.sizer_flags, ui_defaults.widget_margin)
        ypos_lbl = wx.StaticText(self.ctrl_panel, wx.ID_ANY, u"Y Position",
                                 wx.DefaultPosition, wx.DefaultSize)
        self.ctrl_sizer.Add(ypos_lbl, ui_defaults.lbl_pct,
                            ui_defaults.lblsizer_flags,
                            ui_defaults.widget_margin)
        self.ypos_sc = wx.SpinCtrl(self.ctrl_panel,
                                   wx.ID_ANY,
                                   value="",
                                   min=0,
                                   max=self.controller.data.shape[0] - 1)
        self.Bind(wx.EVT_SPINCTRL, self.controller.on_xy_change, self.ypos_sc)
        self.ctrl_sizer.Add(self.ypos_sc, ui_defaults.ctrl_pct,
                            ui_defaults.sizer_flags, ui_defaults.widget_margin)
        self.slice_cb = wx.CheckBox(self.ctrl_panel,
                                    wx.ID_ANY,
                                    "Plot Z Index As C Scan",
                                    style=wx.ALIGN_RIGHT)
        self.slice_cb.SetToolTipString(
            u"Use the specified index in Z as the C Scan plot data")
        self.slice_cb.SetValue(True)
        self.ctrl_sizer.Add(self.slice_cb, ui_defaults.lbl_pct,
                            ui_defaults.sizer_flags, ui_defaults.widget_margin)
        self.slice_sc = wx.SpinCtrl(self.ctrl_panel,
                                    wx.ID_ANY,
                                    value="",
                                    min=0,
                                    max=self.controller.data.shape[2] - 1)
        self.Bind(wx.EVT_SPINCTRL, self.controller.on_sliceidx_change,
                  self.slice_sc)
        slice_lbl = wx.StaticText(self.ctrl_panel, wx.ID_ANY, u"Slice Index",
                                  wx.DefaultPosition, wx.DefaultSize)
        self.ctrl_sizer.Add(slice_lbl, ui_defaults.lbl_pct,
                            ui_defaults.lblsizer_flags,
                            ui_defaults.widget_margin)
        self.ctrl_sizer.Add(self.slice_sc, ui_defaults.ctrl_pct,
                            ui_defaults.sizer_flags, ui_defaults.widget_margin)
        self.ctrl_panel.SetSizerAndFit(self.ctrl_sizer)
        self.main_panel_sizer.Add(self.ctrl_panel, ui_defaults.lbl_pct,
                                  ui_defaults.sizer_flags,
                                  ui_defaults.widget_margin)
        self.figure = Figure()
        self.canvas = FigureCanvas(self.main_panel, wx.ID_ANY, self.figure)
        self.ascan_axes = self.figure.add_subplot(221)
        self.vbscan_axes = self.figure.add_subplot(222)
        self.hbscan_axes = self.figure.add_subplot(223)
        self.cscan_axes = self.figure.add_subplot(224)
        self.cscan_cursor = Cursor(self.cscan_axes,
                                   useblit=True,
                                   color="#4F6581",
                                   alpha=0.5)
        self.figure.canvas.mpl_connect("button_press_event",
                                       self.controller.on_click)
        self.main_panel_sizer.Add(self.canvas, 1, ui_defaults.sizer_flags, 0)
        self.navtools_cb = wx.CheckBox(self.main_panel, wx.ID_ANY,
                                       "Use Plot Navigation Tools")
        self.navtools_cb.SetValue(self.controller.get_navtools_config())
        self.navtools_cb.SetToolTipString("Check to use pan/zoom tools")
        self.Bind(wx.EVT_CHECKBOX, self.controller.on_check_navtools,
                  self.navtools_cb)
        self.main_panel_sizer.Add(self.navtools_cb, ui_defaults.lbl_pct,
                                  ui_defaults.sizer_flags,
                                  ui_defaults.widget_margin)
        self.add_toolbar()
        self.SetIcon(self.parent.GetIcon())
        self.main_panel.SetSizerAndFit(self.main_panel_sizer)
        self.sizer.Add(self.main_panel, 1, ui_defaults.sizer_flags, 0)
        self.SetSizerAndFit(self.sizer)

    def add_toolbar(self):
        """Creates the matplotlib toolbar (zoom, pan/scroll, etc.)
        for the plot"""
        self.toolbar = NavigationToolbar2Wx(self.canvas)
        self.toolbar.Realize()
        if wx.Platform == '__WXMAC__':
            self.SetToolBar(self.toolbar)
        else:
            tw, th = self.toolbar.GetSizeTuple()
            fw, fh = self.canvas.GetSizeTuple()
            self.toolbar.SetSize(wx.Size(fw, th))
            self.main_panel_sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND, 0)
        self.toolbar.update()
        self.toggle_toolbar()

    def toggle_toolbar(self):
        """Enables / disables the navigation toolbar and sets
        cursors accordingly."""
        if self.navtools_enabled():
            self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
        else:
            self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
        self.toolbar.Enable(self.navtools_enabled())
        self.controller.set_navtools_config(self.navtools_enabled())

    def init_plot_menu(self):
        """Creates the Plot menu"""
        self.plot_mnu = wx.Menu()

        self.labels_mnu = wx.Menu()  # Titles and Labels
        plottitle_mnui = wx.MenuItem(self.labels_mnu,
                                     wx.ID_ANY,
                                     text="Set Plot Title",
                                     help="Set Plot Title")
        self.Bind(wx.EVT_MENU,
                  self.controller.on_set_plottitle,
                  id=plottitle_mnui.GetId())
        self.labels_mnu.AppendItem(plottitle_mnui)
        xlbl_mnui = wx.MenuItem(self.labels_mnu,
                                wx.ID_ANY,
                                text="Set X Axis Label",
                                help="Set X Axis Label")
        self.Bind(wx.EVT_MENU,
                  self.controller.on_set_xlabel,
                  id=xlbl_mnui.GetId())
        self.labels_mnu.AppendItem(xlbl_mnui)
        ylbl_mnui = wx.MenuItem(self.labels_mnu,
                                wx.ID_ANY,
                                text="Set Y Axis Label",
                                help="Set Y Axis Label")
        self.Bind(wx.EVT_MENU,
                  self.controller.on_set_ylabel,
                  id=ylbl_mnui.GetId())
        self.labels_mnu.AppendItem(ylbl_mnui)
        cbarlbl_mnui = wx.MenuItem(self.labels_mnu,
                                   wx.ID_ANY,
                                   text='Set Colorbar Label',
                                   help='Set Colorbar Label')
        self.Bind(wx.EVT_MENU,
                  self.controller.on_set_cbarlbl,
                  id=cbarlbl_mnui.GetId())
        self.labels_mnu.AppendItem(cbarlbl_mnui)
        self.plot_mnu.AppendMenu(wx.ID_ANY, "Title And Labels",
                                 self.labels_mnu)

        self.colormaps_mnu = wx.Menu()  # Colormaps
        self.preview_cmaps_mnui = wx.MenuItem(
            self.colormaps_mnu,
            wx.ID_ANY,
            text='Preview Colormaps',
            help='Preview available colormaps')
        self.Bind(wx.EVT_MENU,
                  self.controller.on_preview_cmaps,
                  id=self.preview_cmaps_mnui.GetId())
        self.colormaps_mnu.AppendItem(self.preview_cmaps_mnui)
        self.select_cmap_mnui = wx.MenuItem(self.colormaps_mnu,
                                            wx.ID_ANY,
                                            text='Select Colormap...',
                                            help='Selects colormap')
        self.Bind(wx.EVT_MENU,
                  self.controller.on_select_cmap,
                  id=self.select_cmap_mnui.GetId())
        self.colormaps_mnu.AppendItem(self.select_cmap_mnui)
        self.create_cmap_mnui = wx.MenuItem(self.colormaps_mnu,
                                            wx.ID_ANY,
                                            text='Create Colormap...',
                                            help='Create or edit a colormap')
        self.colormaps_mnu.AppendItem(self.create_cmap_mnui)
        self.Bind(wx.EVT_MENU,
                  self.controller.on_create_cmap,
                  id=self.create_cmap_mnui.GetId())
        self.plot_mnu.AppendMenu(wx.ID_ANY, "Colormaps", self.colormaps_mnu)
        self.show_colorbar_mnui = wx.MenuItem(
            self.plot_mnu,
            wx.ID_ANY,
            text="Show Colorbar",
            help="Show color scale in image plot",
            kind=wx.ITEM_CHECK)
        self.Bind(wx.EVT_MENU,
                  self.controller.on_toggle_colorbar,
                  id=self.show_colorbar_mnui.GetId())
        self.plot_mnu.AppendItem(self.show_colorbar_mnui)
        self.show_colorbar_mnui.Check(self.controller.get_colorbar_config())
        self.plot_conventional_bscans_mnui = wx.MenuItem(
            self.plot_mnu,
            wx.ID_ANY,
            text="Plot Conventional B-scans",
            help="Plot conventional 2D B-scans",
            kind=wx.ITEM_CHECK)
        self.Bind(wx.EVT_MENU,
                  self.controller.on_change_bscans,
                  id=self.plot_conventional_bscans_mnui.GetId())
        self.plot_mnu.AppendItem(self.plot_conventional_bscans_mnui)
        self.plot_conventional_bscans_mnui.Check(
            self.controller.conventional_bscans)
        gridtoggle_mnui = wx.MenuItem(self.plot_mnu,
                                      wx.ID_ANY,
                                      text="Toggle Grid",
                                      help="Turns grid on or off")
        self.plot_mnu.AppendItem(gridtoggle_mnui)
        self.Bind(wx.EVT_MENU,
                  self.controller.on_toggle_grid,
                  id=gridtoggle_mnui.GetId())
        self.menubar.Append(self.plot_mnu, "&Plot")

    def init_specific_ops_menu(self):
        """Creates any plot-specific Operations menu items"""
        self.setcscan_mnui = wx.MenuItem(
            self.ops_mnu,
            wx.ID_ANY,
            text="Define C Scan",
            help="Specify function to generate C Scan")
        self.Bind(wx.EVT_MENU,
                  self.controller.on_define_cscan,
                  id=self.setcscan_mnui.GetId())
        self.ops_mnu.AppendItem(self.setcscan_mnui)
        self.rect_mnu = wx.Menu()  # Rectification operations
        self.fullrect_mnui = wx.MenuItem(self.rect_mnu,
                                         wx.ID_ANY,
                                         text="Full",
                                         help="Full Rectification")
        self.Bind(wx.EVT_MENU,
                  self.controller.on_rectify,
                  id=self.fullrect_mnui.GetId())
        self.rect_mnu.AppendItem(self.fullrect_mnui)
        self.ops_mnu.AppendMenu(wx.ID_ANY, 'Rectify', self.rect_mnu)
        self.gate_mnu = wx.Menu()  # Gates operations
        for gate in self.controller.gates:
            gate_name = self.controller.gates[gate][0]
            gate_desc = "Applies a {0} gate function to the data".format(
                gate_name)
            gate_mnui = wx.MenuItem(self.gate_mnu,
                                    id=gate,
                                    text=gate_name,
                                    help=gate_desc)
            self.gate_mnu.AppendItem(gate_mnui)
            self.Bind(wx.EVT_MENU,
                      self.controller.on_apply_gate,
                      id=gate_mnui.GetId())
        self.ops_mnu.AppendMenu(wx.ID_ANY, 'Gates', self.gate_mnu)

    def navtools_enabled(self):
        """Returns True if plot navigation bar is enabled"""
        return self.navtools_cb.IsChecked()

    @property
    def plot_conventional_bscans(self):
        """True if the Bscan plots should be conventional 2D imgplots vs. the original Megaplot 1D"""
        return self.plot_conventional_bscans_mnui.IsChecked()

    @plot_conventional_bscans.setter
    def plot_conventional_bscans(self, on=True):
        """Sets the use of conventional Bscans or the original 1D Megaplot Bscans"""
        self.plot_conventional_bscans_mnui.Check(on)

    @property
    def plot_linear_bscans(self):
        """True if the Bscan plots should be the original 1D Megaplot plots"""
        return not self.plot_conventional_bscans
Exemplo n.º 8
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()
Exemplo n.º 9
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
Exemplo n.º 10
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])
Exemplo n.º 11
0
class Plotter(wx.Frame):
    def __init__(self, parent, ID, title):
        wx.Frame.__init__(self, parent, ID, title, wx.DefaultPosition,
                          wx.Size(600, 600))
        self.initGui()
        self.initMenu()
        self.Centre()
        self.Show()
        self.graphs = []
        self.currentGraph = {}

    def initGui(self):
        # Create main panel
        panel = wx.Panel(self)
        panel.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
        # Set sizers
        sizer0 = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(sizer0)
        # Set gui elements
        sizer1 = wx.BoxSizer(wx.HORIZONTAL)
        loadData = wx.Button(panel, label='Load Graphs')
        loadData.Bind(wx.EVT_BUTTON, self.OnLoad)
        sizer1.Add(loadData, flag=wx.ALIGN_CENTER_VERTICAL)
        sizer1.Add((20, -1))
        sizer1.Add(wx.StaticText(panel, label='Current Graph'),
                   flag=wx.ALIGN_CENTER_VERTICAL)
        sizer1.Add((4, -1))
        self.graphsList = wx.ComboBox(panel,
                                      choices=[],
                                      size=[300, 24],
                                      style=wx.CB_READONLY)
        self.graphsList.Bind(wx.EVT_COMBOBOX, self.OnSelectGraph)
        sizer1.Add(self.graphsList, proportion=1)
        sizer0.Add(sizer1,
                   flag=wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL | wx.TOP
                   | wx.LEFT | wx.RIGHT | wx.BOTTOM,
                   border=20)
        # Matplotlib item
        panelcolour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        facecolor = [channel / float(255) for channel in panelcolour]
        self.figure = Figure(figsize=(-1, -1),
                             dpi=80,
                             facecolor=facecolor,
                             linewidth=1.0)
        self.figure.subplots_adjust(left=0.08,
                                    bottom=0.08,
                                    right=0.98,
                                    top=0.98)
        self.canvas = FigCanvas(panel, -1, self.figure)
        self.axes = self.figure.add_subplot(111)
        self.axes.set_xlabel('X-Axis')
        self.axes.set_ylabel('Y-Axis')
        self.axes.set_xlim(0.0, 1.0)
        self.axes.set_ylim(0.0, 1.0)
        matplotlib.rcParams.update({'font.size': 12})
        self.axes.grid(False)
        sizer0.Add(self.canvas,
                   1,
                   flag=wx.GROW | wx.LEFT | wx.RIGHT,
                   border=20)
        self.toolbar = NavigationToolbar(self.canvas)
        sizer0.Add(self.toolbar,
                   0,
                   flag=wx.ALIGN_CENTER_HORIZONTAL | wx.LEFT | wx.RIGHT,
                   border=20)
        sizer0.Add((-1, 20))
        self.statusBar = wx.StatusBar(self, -1)
        self.statusBar.SetFieldsCount(1)
        self.SetStatusBar(self.statusBar)
        self.canvas.mpl_connect('motion_notify_event', self.UpdateStatusBar)
        self.canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)
        # Redefine close event
        self.Bind(wx.EVT_CLOSE, self.OnClose)

    def initMenu(self):
        menubar = wx.MenuBar()
        # File menu
        fileMenu = wx.Menu()
        openItem = wx.MenuItem(fileMenu, 11, '&Open\tCtrl+O')
        self.Bind(wx.EVT_MENU, self.OnOpen, id=11)
        saveItem = wx.MenuItem(fileMenu, 12, '&Save\tCtrl+S')
        self.Bind(wx.EVT_MENU, self.OnSave, id=12)
        exitItem = wx.MenuItem(fileMenu, 13, '&Exit\tAlt+F4')
        self.Bind(wx.EVT_MENU, self.OnClose, id=13)
        fileMenu.AppendItem(openItem)
        fileMenu.AppendItem(saveItem)
        fileMenu.AppendSeparator()
        fileMenu.AppendItem(exitItem)
        # Edit menu
        editMenu = wx.Menu()
        loadItem = wx.MenuItem(editMenu, 21, '&Load data')
        self.Bind(wx.EVT_MENU, self.OnLoad, id=21)
        clearItem = wx.MenuItem(editMenu, 22, '&Clear memory')
        self.Bind(wx.EVT_MENU, self.OnClear, id=22)
        editMenu.AppendItem(loadItem)
        editMenu.AppendItem(clearItem)
        # Help menu
        helpMenu = wx.Menu()
        aboutItem = wx.MenuItem(helpMenu, 31, '&About\tCtrl+A')
        #self.Bind(wx.EVT_MENU, self.OnAbout, id=31)
        helpItem = wx.MenuItem(helpMenu, 32, '&Help\tF1')
        #self.Bind(wx.EVT_MENU, self.OnHelp, id=32)
        helpMenu.AppendItem(aboutItem)
        helpMenu.AppendSeparator()
        helpMenu.AppendItem(helpItem)
        menubar.Append(fileMenu, '&File')
        menubar.Append(editMenu, '&Edit')
        menubar.Append(helpMenu, '&Help')
        self.SetMenuBar(menubar)

    def ChangeCursor(self, event):
        self.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(numpy.rint(x)) + "; y = " + str(numpy.rint(y))),
                0)

    def OnLoad(self, event):
        # Load a dictionary with plots
        self.graphs = []
        self.graphs.extend(stored.plots)
        # Update a list of graphs
        #self.graphsList.Enable()
        self.graphsList.Clear()
        for graph in self.graphs:
            self.graphsList.Append(graph['Title'])
        event.Skip()

    def OnClear(self, event):
        # Clear a dictionary with plots
        self.graphs = []
        self.graphsList.Clear()
        event.Skip()

    def OnOpen(self, event):
        dlg = wx.FileDialog(self,
                            message="Choose a file",
                            defaultDir=os.getcwd(),
                            defaultFile="",
                            wildcard="*.dat",
                            style=wx.OPEN | wx.CHANGE_DIR)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            dataFile = open(path, 'r')
            # Read data file
            # ...
        dlg.Destroy()

    def OnSave(self, event):
        if (bool(self.graphs) == True) and (bool(self.currentGraph) == True):
            dialog = wx.FileDialog(None,
                                   message="Save data as ...",
                                   defaultDir=os.getcwd(),
                                   defaultFile="",
                                   wildcard="*.dat",
                                   style=wx.SAVE | wx.OVERWRITE_PROMPT)
            if dialog.ShowModal() == wx.ID_OK:
                path = dialog.GetPath()
                # Create a file
                dataFile = open(path, 'w')
                # Fill in the content of a data file
                title = 'Title: ' + self.currentGraph['Title'] + '\n'
                type = 'Type: ' + self.currentGraph['Type'] + '\n'
                xTitle = 'xTitle: ' + self.currentGraph['xTitle'] + '\n'
                yTitle = 'yTitle: ' + self.currentGraph['yTitle'] + '\n'
                axesTitles = '{0:>10s}'.format('x') + '{0:>10s}'.format(
                    'y') + '{0:>10s}'.format('z') + '\n'
                dataFile.write(title)
                dataFile.write(type)
                dataFile.write(xTitle)
                dataFile.write(yTitle)
                dataFile.write(axesTitles)
                # Write x,y,z to a data file
                graphType = self.currentGraph['Type']
                print(self.currentGraph['xData'])
                #print self.currentGraph['xData'].shape[0], self.currentGraph['yData'].shape[0], self.currentGraph['zData'].shape
                dim = self.currentGraph['xData'].shape[0]
                if (graphType == 'DistanceMap'):
                    for i in range(dim):
                        x = self.currentGraph['xData'][i]
                        dataFile.write('{0:10.2f}'.format(x))
                        y = self.currentGraph['yData'][i]
                        dataFile.write('{0:10.2f}'.format(y))
                        for j in range(dim):
                            z = self.currentGraph['zData'][i][j]
                            dataFile.write('{0:10.2f}'.format(z))
                        dataFile.write('\n')
                if (graphType == 'DifferenceMap'):
                    pass
                if (graphType == 'DistancePlot'):
                    pass
                if (graphType == 'AccessibilityPlot'):
                    pass
                dataFile.close()
            dialog.Destroy()

    def OnClose(self, event):
        stored.mtsslplot = 0
        self.Destroy()

    def OnSelectGraph(self, event):
        # Read on the selected graph
        title = self.graphsList.GetStringSelection()
        for graph in self.graphs:
            if (graph['Title'] == title):
                self.currentGraph = graph
        # Plot the selected graph
        self.plotGraph()
        event.Skip()

    def plotGraph(self):
        #print "Selecting graph"
        self.refreshFigure()
        # Read on the type of a graph
        graphType = self.currentGraph['Type']
        if (graphType == 'DistanceMap'):
            self.plotDistanceMap()
        if (graphType == 'DifferenceMap'):
            self.plotDifferenceMap()
        if (graphType == 'DistancePlot'):
            self.plotDistancePlot()
        if (graphType == 'AccessibilityPlot'):
            self.plotAccessibilityPlot()
        if (graphType == 'DistanceDistribution'):
            #print "plotting distribution"
            self.plotDistanceDistribution()

    def refreshFigure(self):
        self.figure.clear()
        self.axes = self.figure.add_subplot(111)
        self.axes.set_xlabel('X-Axis')
        self.axes.set_ylabel('Y-Axis')
        self.axes.set_xlim(0.0, 1.0)
        self.axes.set_ylim(0.0, 1.0)
        matplotlib.rcParams.update({'font.size': 12})

    def plotDistanceMap(self):
        # Read on x,y,z
        x = self.currentGraph['xData'] - 0.5 * numpy.ones(
            len(self.currentGraph['xData']))
        y = self.currentGraph['yData'] - 0.5 * numpy.ones(
            len(self.currentGraph['yData']))
        X, Y = numpy.meshgrid(x, y)
        Z = self.currentGraph['zData']
        # Define colormap
        cmap = colors.ListedColormap(['blue', 'green', 'orange', 'red'])
        cmap.set_under('white')
        cmap.set_over('white')
        bounds = [1, 15, 50, 80, 100]
        norm = colors.BoundaryNorm(bounds, cmap.N)
        # Draw surface plot
        img = self.axes.pcolor(X, Y, Z, cmap=cmap, norm=norm)
        self.axes.set_xlim(x.min(), x.max())
        self.axes.set_ylim(y.min(), y.max())
        self.axes.set_xlabel(self.currentGraph['xTitle'])
        self.axes.set_ylabel(self.currentGraph['yTitle'])
        # Cosmetics
        #matplotlib.rcParams.update({'font.size': 12})
        xminorLocator = MultipleLocator(10)
        yminorLocator = MultipleLocator(10)
        self.axes.xaxis.set_minor_locator(xminorLocator)
        self.axes.yaxis.set_minor_locator(yminorLocator)
        self.axes.tick_params(direction='out', length=6, width=1)
        self.axes.tick_params(which='minor',
                              direction='out',
                              length=3,
                              width=1)
        self.axes.xaxis.labelpad = 15
        self.axes.yaxis.labelpad = 15
        # Draw colorbar
        colorbar = self.figure.colorbar(img,
                                        boundaries=[0, 1, 15, 50, 80, 100],
                                        spacing='proportional',
                                        ticks=[15, 50, 80, 100],
                                        extend='both')
        colorbar.ax.set_xlabel('Angstrom')
        colorbar.ax.xaxis.set_label_position('top')
        colorbar.ax.xaxis.labelpad = 20
        self.figure.tight_layout()
        self.canvas.draw()

    def plotDifferenceMap(self):
        # Read on x,y,z
        x = self.currentGraph['xData'] - 0.5 * numpy.ones(
            len(self.currentGraph['xData']))
        y = self.currentGraph['yData'] - 0.5 * numpy.ones(
            len(self.currentGraph['yData']))
        X, Y = numpy.meshgrid(x, y)
        Z = self.currentGraph['zData']
        # Draw surface plot
        img = self.axes.pcolor(X,
                               Y,
                               Z,
                               cmap='jet',
                               vmin=0.0,
                               vmax=numpy.amax(Z))
        self.axes.set_xlim(x.min(), x.max())
        self.axes.set_ylim(y.min(), y.max())
        self.axes.set_xlabel(self.currentGraph['xTitle'])
        self.axes.set_ylabel(self.currentGraph['yTitle'])
        # Cosmetics
        #matplotlib.rcParams.update({'font.size': 18})
        xminorLocator = MultipleLocator(10)
        yminorLocator = MultipleLocator(10)
        self.axes.xaxis.set_minor_locator(xminorLocator)
        self.axes.yaxis.set_minor_locator(yminorLocator)
        self.axes.tick_params(direction='out', length=6, width=1)
        self.axes.tick_params(which='minor',
                              direction='out',
                              length=3,
                              width=1)
        self.axes.xaxis.labelpad = 15
        self.axes.yaxis.labelpad = 15
        # Draw colorbar
        colorbar = self.figure.colorbar(img)
        colorbar.ax.set_xlabel('Angstrom')
        colorbar.ax.xaxis.set_label_position('top')
        colorbar.ax.xaxis.labelpad = 20
        self.figure.tight_layout()
        self.canvas.draw()

    def plotDistancePlot(self):
        # Read on x,y
        x = self.currentGraph['xData']
        y = self.currentGraph['yData']
        # Remove data points with distances <= 0
        index = numpy.zeros(1)
        for i in range(0, y.shape[0]):
            if (y[i] <= 0):
                index = numpy.append(index, i)
                index = numpy.delete(index, 0)
        Y = numpy.delete(y, index)
        X = numpy.delete(x, index)
        # Plot graph
        self.axes.plot(X,
                       Y,
                       linestyle='solid',
                       linewidth=0.5,
                       color='black',
                       marker='o',
                       markerfacecolor='white',
                       markeredgecolor='black',
                       markersize=6,
                       markeredgewidth=1)
        Xmin = 0
        Xmax = X.max() + 1
        Ymin = 0
        Ymax = Y.max() * 1.05
        self.axes.set_xlim(Xmin, Xmax)
        self.axes.set_ylim(Ymin, Ymax)
        self.axes.set_xlabel(self.currentGraph['xTitle'])
        self.axes.set_ylabel(self.currentGraph['yTitle'])
        # Color the distance ranges
        self.axes.fill_between([Xmin, Xmax], 15, Ymin, color='blue', alpha=0.4)
        self.axes.fill_between([Xmin, Xmax], 50, 15, color='green', alpha=0.4)
        self.axes.fill_between([Xmin, Xmax], 80, 50, color='orange', alpha=0.4)
        self.axes.fill_between([Xmin, Xmax], Ymax, 80, color='red', alpha=0.4)
        # Cosmetics
        #matplotlib.rcParams.update({'font.size': 18})
        xminorLocator = MultipleLocator(10)
        yminorLocator = MultipleLocator(10)
        self.axes.xaxis.set_minor_locator(xminorLocator)
        self.axes.yaxis.set_minor_locator(yminorLocator)
        self.axes.tick_params(direction='out', length=6, width=1)
        self.axes.tick_params(which='minor',
                              direction='out',
                              length=3,
                              width=1)
        self.axes.xaxis.labelpad = 15
        self.axes.yaxis.labelpad = 15
        self.figure.tight_layout()
        self.canvas.draw()

    def plotDistanceDistribution(self):
        # Read on x,y
        x = self.currentGraph['xData']
        y = self.currentGraph['yData']
        # Remove data points with distances <= 0
        index = numpy.zeros(1)
        for i in range(0, y.shape[0]):
            if (y[i] <= 0):
                index = numpy.append(index, i)
                index = numpy.delete(index, 0)
        Y = numpy.delete(y, index)
        X = numpy.delete(x, index)
        # Plot graph
        self.axes.plot(
            X,
            Y,
            linestyle='solid',
            linewidth=0.5,
            color='red',
            #marker='.',
            markerfacecolor='white',
            markeredgecolor='black',
            markersize=6,
            markeredgewidth=1)
        Xmin = 0
        Xmax = X.max() + 1
        Ymin = 0
        Ymax = Y.max() * 1.05
        self.axes.set_xlim(Xmin, Xmax)
        self.axes.set_ylim(Ymin, Ymax)
        self.axes.set_xlabel(self.currentGraph['xTitle'])
        self.axes.set_ylabel(self.currentGraph['yTitle'])
        # Color the distance ranges
        #self.axes.fill_between([Xmin, Xmax], 15, Ymin, color='blue', alpha=0.4)
        #self.axes.fill_between([Xmin, Xmax], 50, 15, color='green', alpha=0.4)
        #self.axes.fill_between([Xmin, Xmax], 80, 50, color='orange', alpha=0.4)
        #self.axes.fill_between([Xmin, Xmax], Ymax, 80, color='red', alpha=0.4)
        # Cosmetics
        #matplotlib.rcParams.update({'font.size': 18})
        xminorLocator = MultipleLocator(10)
        yminorLocator = MultipleLocator(10)
        self.axes.xaxis.set_minor_locator(xminorLocator)
        self.axes.yaxis.set_minor_locator(yminorLocator)
        self.axes.tick_params(direction='out', length=6, width=1)
        self.axes.tick_params(which='minor',
                              direction='out',
                              length=3,
                              width=1)
        self.axes.xaxis.labelpad = 15
        self.axes.yaxis.labelpad = 15
        self.figure.tight_layout()
        self.canvas.draw()

    def plotAccessibilityPlot(self):
        # Read on x,y
        x = self.currentGraph['xData']
        y = self.currentGraph['yData']
        X = x
        Y = y
        # Plot graph
        self.axes.plot(X,
                       Y,
                       linestyle='solid',
                       linewidth=0.5,
                       color='red',
                       marker='.',
                       markerfacecolor='white',
                       markeredgecolor='black',
                       markersize=6,
                       markeredgewidth=1)
        Xmin = 0
        Xmax = X.max() + 1
        Ymin = 0
        Ymax = Y.max() * 1.05
        self.axes.set_xlim(Xmin, Xmax)
        self.axes.set_ylim(Ymin, Ymax)
        self.axes.set_xlabel(self.currentGraph['xTitle'])
        self.axes.set_ylabel(self.currentGraph['yTitle'])
        # Cosmetics
        #self.figure.set_size_inches(30,3)
        #matplotlib.rcParams.update({'font.size': 18})
        xminorLocator = MultipleLocator(10)
        yminorLocator = MultipleLocator(10)
        self.axes.xaxis.set_minor_locator(xminorLocator)
        self.axes.yaxis.set_minor_locator(yminorLocator)
        self.axes.tick_params(direction='out', length=6, width=1)
        self.axes.tick_params(which='minor',
                              direction='out',
                              length=3,
                              width=1)
        self.axes.xaxis.labelpad = 15
        self.axes.yaxis.labelpad = 15
        self.figure.tight_layout()
        self.canvas.draw()
Exemplo n.º 12
0
class PlotPanel(BasePanel):
    """
    MatPlotlib 2D plot as a wx.Panel, suitable for embedding
    in any wx.Frame.   This does provide a right-click popup
    menu for configuration, zooming, saving an image of the
    figure, and Ctrl-C for copy-image-to-clipboard.

    For more features, see PlotFrame, which embeds a PlotPanel
    and also provides, a Menu, StatusBar, and Printing support.
    """
    def __init__(self,
                 parent,
                 size=(700, 450),
                 dpi=150,
                 axisbg=None,
                 facecolor=None,
                 fontsize=9,
                 trace_color_callback=None,
                 output_title='plot',
                 with_data_process=True,
                 **kws):

        self.trace_color_callback = trace_color_callback
        matplotlib.rc('axes', axisbelow=True)
        matplotlib.rc('lines', linewidth=2)
        matplotlib.rc('xtick', labelsize=fontsize, color='k')
        matplotlib.rc('ytick', labelsize=fontsize, color='k')
        matplotlib.rc('legend', fontsize=fontsize)
        matplotlib.rc('grid', linewidth=0.5, linestyle='-')

        BasePanel.__init__(self, parent, output_title=output_title, **kws)

        self.conf = PlotConfig(panel=self, with_data_process=with_data_process)
        self.data_range = {}
        self.win_config = None
        self.cursor_callback = None
        self.lasso_callback = None
        self.cursor_mode = 'zoom'
        self.parent = parent
        self.figsize = (size[0] * 1.0 / dpi, size[1] * 1.0 / dpi)
        self.dpi = dpi
        if facecolor is not None:
            self.conf.bgcolor = facecolor
        if axisbg is not None:
            self.conf.bgcolor = axisbg

        # axesmargins : margins in px left/top/right/bottom
        self.axesmargins = (30, 30, 30, 30)

        self.BuildPanel()
        self.conf.user_limits = {}  # [None, None, None, None]
        self.data_range = {}
        self.conf.zoom_lims = []
        self.conf.axes_traces = {}

    def plot(self,
             xdata,
             ydata,
             side='left',
             title=None,
             xlabel=None,
             ylabel=None,
             y2label=None,
             use_dates=False,
             **kws):
        """
        plot (that is, create a new plot: clear, then oplot)
        """
        allaxes = self.fig.get_axes()
        if len(allaxes) > 1:
            for ax in allaxes[1:]:
                if ax in self.data_range:
                    self.data_range.pop(ax)
                self.fig.delaxes(ax)

        self.data_range = {}
        self.conf.zoom_lims = []
        self.conf.axes_traces = {}
        self.clear()
        axes = self.axes
        if side == 'right':
            axes = self.get_right_axes()
        self.conf.ntrace = 0
        self.conf.yscale = 'linear'
        self.conf.user_limits[axes] = [None, None, None, None]

        if xlabel is not None:
            self.set_xlabel(xlabel)
        if ylabel is not None:
            self.set_ylabel(ylabel)
        if y2label is not None:
            self.set_y2label(y2label)
        if title is not None:
            self.set_title(title)
        if use_dates is not None:
            self.use_dates = use_dates
        return self.oplot(xdata, ydata, side=side, **kws)

    def oplot(self,
              xdata,
              ydata,
              side='left',
              label=None,
              xlabel=None,
              ylabel=None,
              y2label=None,
              title=None,
              dy=None,
              ylog_scale=None,
              xlog_scale=None,
              grid=None,
              xmin=None,
              xmax=None,
              ymin=None,
              ymax=None,
              color=None,
              style=None,
              drawstyle=None,
              linewidth=2,
              marker=None,
              markersize=None,
              refresh=True,
              show_legend=None,
              legend_loc='best',
              legend_on=True,
              delay_draw=False,
              bgcolor=None,
              framecolor=None,
              gridcolor=None,
              labelfontsize=None,
              legendfontsize=None,
              fullbox=None,
              axes_style=None,
              zorder=None,
              **kws):
        """ basic plot method, overplotting any existing plot """
        self.cursor_mode = 'zoom'
        conf = self.conf
        conf.plot_type = 'lineplot'

        axes = self.axes
        if side == 'right':
            axes = self.get_right_axes()
        # set y scale to log/linear
        if ylog_scale is not None:
            conf.yscale = {False: 'linear', True: 'log'}[ylog_scale]

        if xlog_scale is not None:
            conf.xscale = {False: 'linear', True: 'log'}[xlog_scale]

        axes.xaxis.set_major_formatter(FuncFormatter(self.xformatter))
        if self.use_dates:
            xdata = [datetime.fromtimestamp(i) for i in xdata]
            xdata = dates.date2num(xdata)
            # axes.xaxis.set_major_locator(dates.AutoDateLocator())

        if linewidth is None:
            linewidth = 2

        if xlabel is not None:
            self.set_xlabel(xlabel)
        if ylabel is not None:
            self.set_ylabel(ylabel)
        if y2label is not None:
            self.set_y2label(y2label)
        if title is not None:
            self.set_title(title)
        if show_legend is not None:
            conf.set_legend_location(legend_loc, legend_on)
            conf.show_legend = show_legend

        if grid is not None:
            conf.show_grid = grid

        # set data range for this trace
        datarange = [min(xdata), max(xdata), min(ydata), max(ydata)]

        if axes not in conf.user_limits:
            conf.user_limits[axes] = [None, None, None, None]

        if xmin is not None:
            conf.user_limits[axes][0] = xmin
        if xmax is not None:
            conf.user_limits[axes][1] = xmax
        if ymin is not None:
            conf.user_limits[axes][2] = ymin
        if ymax is not None:
            conf.user_limits[axes][3] = ymax

        if axes == self.axes:
            axes.yaxis.set_major_formatter(FuncFormatter(self.yformatter))
        else:
            axes.yaxis.set_major_formatter(FuncFormatter(self.y2formatter))

        n = conf.ntrace
        if zorder is None:
            zorder = 5 * (n + 1)
        if axes not in conf.axes_traces:
            conf.axes_traces[axes] = []
        conf.axes_traces[axes].append(n)

        if bgcolor is not None:
            conf.bgcolor = bgcolor
            axes.set_axis_bgcolor(bgcolor)
        if framecolor is not None:
            self.canvas.figure.set_facecolor(framecolor)

        conf.set_trace_zorder(zorder, delay_draw=True)
        if color:
            conf.set_trace_color(color, delay_draw=True)
        if style:
            conf.set_trace_style(style, delay_draw=True)
        if marker:
            conf.set_trace_marker(marker, delay_draw=True)
        if linewidth is not None:
            conf.set_trace_linewidth(linewidth, delay_draw=True)
        if markersize is not None:
            conf.set_trace_markersize(markersize, delay_draw=True)
        if drawstyle is not None:
            conf.set_trace_drawstyle(drawstyle, delay_draw=True)

        if gridcolor is not None:
            conf.gridcolor = gridcolor
        if dy is None:
            _lines = axes.plot(xdata,
                               ydata,
                               drawstyle=drawstyle,
                               zorder=zorder)
        else:
            _lines = axes.errorbar(xdata, ydata, yerr=dy, zorder=zorder)

        if axes not in conf.data_save:
            conf.data_save[axes] = []
        conf.data_save[axes].append((xdata, ydata))

        if conf.show_grid and axes == self.axes:
            # I'm sure there's a better way...
            for i in axes.get_xgridlines() + axes.get_ygridlines():
                i.set_color(conf.gridcolor)
                i.set_zorder(-100)
            axes.grid(True)
        else:
            axes.grid(False)

        if (self.conf.xscale == 'log' or self.conf.yscale == 'log'):
            self.set_logscale(xscale=self.conf.xscale, yscale=self.conf.yscale)

        if label is None:
            label = 'trace %i' % (conf.ntrace + 1)
        conf.set_trace_label(label, delay_draw=True)
        conf.set_trace_datarange(datarange)
        needs_relabel = False
        if labelfontsize is not None:
            conf.labelfont.set_size(labelfontsize)
            needs_relabel = True

        if legendfontsize is not None:
            conf.legendfont.set_size(legendfontsize)
            needs_relabel = True

        if n < len(conf.lines):
            conf.lines[n] = _lines
        else:
            conf._init_trace(n, 'black', 'solid')
            conf.lines.append(_lines)

        # now set plot limits:
        self.set_viewlimits()
        if refresh:
            conf.refresh_trace(conf.ntrace)
            needs_relabel = True

        if conf.show_legend and not delay_draw:
            conf.draw_legend()

        if needs_relabel and not delay_draw:
            conf.relabel()

        # axes style ('box' or 'open')
        conf.axes_style = 'box'
        if fullbox is not None and not fullbox:
            conf.axes_style = 'open'
        if axes_style in ('open', 'box', 'bottom'):
            conf.axes_style = axes_style
        conf.set_axes_style(delay_draw=delay_draw)
        if not delay_draw:
            self.draw()
            self.canvas.Refresh()
        conf.ntrace = conf.ntrace + 1
        return _lines

    def plot_many(self,
                  datalist,
                  side='left',
                  title=None,
                  xlabel=None,
                  ylabel=None,
                  **kws):
        """
        plot many traces at once, taking a list of (x, y) pairs
        """
        def unpack_tracedata(tdat, **kws):
            if (isinstance(tdat, dict) and 'xdata' in tdat
                    and 'ydata' in tdat):
                xdata = tdat.pop('xdata')
                ydata = tdat.pop('ydata')
                out = kws
                out.update(tdat)
            elif isinstance(tdat, (list, tuple)):
                out = kws
                xdata = tdat[0]
                ydata = tdat[1]
            return (xdata, ydata, out)

        opts = dict(side=side,
                    title=title,
                    xlabel=xlabel,
                    ylabel=ylabel,
                    delay_draw=True)
        opts.update(kws)
        x0, y0, opts = unpack_tracedata(datalist[0], **opts)

        self.plot(x0, y0, **opts)

        for dat in datalist[1:]:
            x, y, opts = unpack_tracedata(dat, delay_draw=True)
            self.oplot(x, y, **opts)

        conf = self.conf
        if conf.show_legend:
            conf.draw_legend()
        conf.relabel()
        self.draw()
        self.canvas.Refresh()

    def add_text(self,
                 text,
                 x,
                 y,
                 side='left',
                 size=None,
                 rotation=None,
                 ha='left',
                 va='center',
                 family=None,
                 **kws):
        """add text at supplied x, y position"""
        axes = self.axes
        if side == 'right':
            axes = self.get_right_axes()
        dynamic_size = False
        if size is None:
            size = self.conf.legendfont.get_size()
            dynamic_size = True
        t = axes.text(x,
                      y,
                      text,
                      ha=ha,
                      va=va,
                      size=size,
                      rotation=rotation,
                      family=family,
                      **kws)
        self.conf.added_texts.append((dynamic_size, t))
        self.draw()

    def add_arrow(self,
                  x1,
                  y1,
                  x2,
                  y2,
                  side='left',
                  shape='full',
                  color='black',
                  width=0.01,
                  head_width=0.03,
                  overhang=0,
                  **kws):
        """add arrow supplied x, y position"""
        dx, dy = x2 - x1, y2 - y1

        axes = self.axes
        if side == 'right':
            axes = self.get_right_axes()
        axes.arrow(x1,
                   y1,
                   dx,
                   dy,
                   shape=shape,
                   length_includes_head=True,
                   fc=color,
                   edgecolor=color,
                   width=width,
                   head_width=head_width,
                   overhang=overhang,
                   **kws)
        self.draw()

    def scatterplot(self,
                    xdata,
                    ydata,
                    label=None,
                    size=10,
                    color=None,
                    edgecolor=None,
                    selectcolor=None,
                    selectedge=None,
                    xlabel=None,
                    ylabel=None,
                    y2label=None,
                    xmin=None,
                    xmax=None,
                    ymin=None,
                    ymax=None,
                    title=None,
                    grid=None,
                    callback=None,
                    **kw):

        if xlabel is not None:
            self.set_xlabel(xlabel)
        if ylabel is not None:
            self.set_ylabel(ylabel)
        if y2label is not None:
            self.set_y2label(y2label)
        if title is not None:
            self.set_title(title)
        if grid is not None:
            self.conf.show_grid = grid
        if callback is not None:
            self.lasso_callback = callback

        self.conf.plot_type = 'scatter'
        self.cursor_mode = 'lasso'
        if color is not None:
            self.conf.scatter_normalcolor = color
        if edgecolor is not None:
            self.conf.scatter_normaledge = edgecolor
        if selectcolor is not None:
            self.conf.scatter_selectcolor = selectcolor
        if selectedge is not None:
            self.conf.scatter_selectedge = selectedge

        axes = self.axes
        self.conf.user_limits[axes] = (xmin, xmax, ymin, ymax)

        self.conf.axes_traces = {axes: [0]}
        self.conf.set_trace_label('scatterplot')
        self.conf.set_trace_datarange(
            (min(xdata), max(xdata), min(ydata), max(ydata)))

        fcols = [to_rgba(self.conf.scatter_normalcolor) for x in xdata]
        ecols = [self.conf.scatter_normaledge] * len(xdata)

        self.conf.scatter_data = [(x, y) for x, y in zip(xdata, ydata)]
        self.conf.scatter_size = size
        self.conf.scatter_coll = CircleCollection(
            sizes=(size, ),
            facecolors=fcols,
            edgecolors=ecols,
            offsets=self.conf.scatter_data,
            transOffset=self.axes.transData)
        self.axes.add_collection(self.conf.scatter_coll)

        if self.conf.show_grid:
            for i in axes.get_xgridlines() + axes.get_ygridlines():
                i.set_color(self.conf.gridcolor)
                i.set_zorder(-30)
            axes.grid(True)
        else:
            axes.grid(False)
        self.set_viewlimits()
        self.draw()

    def lassoHandler(self, vertices):
        conf = self.conf

        if self.conf.plot_type == 'scatter':
            fcols = conf.scatter_coll.get_facecolors()
            ecols = conf.scatter_coll.get_edgecolors()
            sdat = conf.scatter_data
            mask = inside_poly(vertices, sdat)
            pts = nonzero(mask)[0]
            self.conf.scatter_mask = mask
            for i in range(len(sdat)):
                if i in pts:
                    ecols[i] = to_rgba(conf.scatter_selectedge)
                    fcols[i] = to_rgba(conf.scatter_selectcolor)
                    fcols[i][3] = 0.3
                    ecols[i][3] = 0.8
                else:
                    fcols[i] = to_rgba(conf.scatter_normalcolor)
                    ecols[i] = to_rgba(conf.scatter_normaledge)
        else:
            xdata = self.axes.lines[0].get_xdata()
            ydata = self.axes.lines[0].get_ydata()
            sdat = [(x, y) for x, y in zip(xdata, ydata)]
            mask = inside_poly(vertices, sdat)
            # print mask
            pts = nonzero(mask)[0]

        self.lasso = None
        self.draw()
        # self.canvas.draw_idle()
        if (self.lasso_callback is not None
                and hasattr(self.lasso_callback, '__call__')):
            self.lasso_callback(data=sdat, selected=pts, mask=mask)

    def set_xylims(self, limits, axes=None, side='left'):
        "set user-defined limits and apply them"
        if axes is None:
            axes = self.axes
            if side == 'right':
                axes = self.get_right_axes()
        self.conf.user_limits[axes] = limits
        self.unzoom_all()

    def set_viewlimits(self):
        """updates xy limits of a plot based on current data,
        user defined limits, and any zoom level

        """
        self.conf.set_viewlimits()

    def get_viewlimits(self, axes=None):
        if axes is None: axes = self.axes
        xmin, xmax = axes.get_xlim()
        ymin, ymax = axes.get_ylim()
        return (xmin, xmax, ymin, ymax)

    def clear(self):
        """ clear plot """
        for ax in self.fig.get_axes():
            ax.cla()
        self.conf.ntrace = 0
        self.conf.xlabel = ''
        self.conf.ylabel = ''
        self.conf.y2label = ''
        self.conf.title = ''
        self.conf.data_save = {}

    def reset_config(self):
        """reset configuration to defaults."""
        self.conf.set_defaults()

    def unzoom(self, event=None, **kws):
        """ zoom out 1 level, or to full data range """
        self.conf.unzoom(full=False)

    def unzoom_all(self, event=None):
        """ zoom out full data range """
        self.conf.unzoom(full=True)

    def process_data(self, event=None, expr=None):
        if expr in self.conf.data_expressions:
            self.conf.data_expr = expr
            self.conf.process_data()
            self.draw()
        if expr is None:
            expr = ''
        if self.conf.data_deriv:
            if expr is None:
                expr = 'y'
            expr = "deriv(%s)" % expr
        self.write_message("plotting %s" % expr, panel=0)

    def toggle_deriv(self, evt=None, value=None):
        "toggle derivative of data"
        if value is None:
            self.conf.data_deriv = not self.conf.data_deriv

            expr = self.conf.data_expr or ''
            if self.conf.data_deriv:
                expr = "deriv(%s)" % expr
            self.write_message("plotting %s" % expr, panel=0)

            self.conf.process_data()

    def set_logscale(self, event=None, xscale='linear', yscale='linear'):
        "set log or linear scale for x, y axis"
        self.conf.set_logscale(xscale=xscale, yscale=yscale)

    def toggle_legend(self, evt=None, show=None):
        "toggle legend display"
        if show is None:
            show = not self.conf.show_legend
            self.conf.show_legend = show
        self.conf.draw_legend()

    def toggle_grid(self, evt=None, show=None):
        "toggle grid display"
        if show is None:
            show = not self.conf.show_grid
        self.conf.enable_grid(show)

    def configure(self, event=None):
        """show configuration frame"""
        if self.win_config is not None:
            try:
                self.win_config.Raise()
            except:
                self.win_config = None

        if self.win_config is None:
            self.win_config = PlotConfigFrame(
                parent=self,
                config=self.conf,
                trace_color_callback=self.trace_color_callback)
            self.win_config.Raise()

    ####
    ## create GUI
    ####
    def BuildPanel(self):
        """ builds basic GUI panel and popup menu"""
        self.fig = Figure(self.figsize, dpi=self.dpi)
        # 1 axes for now
        self.gridspec = GridSpec(1, 1)
        kwargs = {'facecolor': self.conf.bgcolor}
        if matplotlib.__version__ < "2.0":
            kwargs = {'axisbg': self.conf.bgcolor}

        self.axes = self.fig.add_subplot(self.gridspec[0], **kwargs)

        self.canvas = FigureCanvas(self, -1, self.fig)

        self.printer.canvas = self.canvas
        self.set_bg(self.conf.framecolor)
        self.conf.canvas = self.canvas
        self.canvas.SetCursor(wxCursor(wx.CURSOR_CROSS))
        self.canvas.mpl_connect("pick_event", self.__onPickEvent)

        # overwrite ScalarFormatter from ticker.py here:
        self.axes.xaxis.set_major_formatter(FuncFormatter(self.xformatter))
        self.axes.yaxis.set_major_formatter(FuncFormatter(self.yformatter))

        # This way of adding to sizer allows resizing
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 2, wx.LEFT | wx.TOP | wx.BOTTOM | wx.EXPAND, 0)
        self.SetAutoLayout(True)
        self.autoset_margins()
        self.SetSizer(sizer)
        self.Fit()

        canvas_draw = self.canvas.draw

        def draw(*args, **kws):
            self.autoset_margins()
            canvas_draw(*args, **kws)

        self.canvas.draw = draw
        self.addCanvasEvents()

    def _updateCanvasDraw(self):
        """ Overload of the draw function that update
        axes position before each draw"""
        fn = self.canvas.draw

        def draw2(*a, **k):
            self._updateGridSpec()
            return fn(*a, **k)

        self.canvas.draw = draw2

    def get_default_margins(self):
        """get default margins"""
        trans = self.fig.transFigure.inverted().transform

        # Static margins
        l, t, r, b = self.axesmargins
        (l, b), (r, t) = trans(((l, b), (r, t)))

        # Extent
        dl, dt, dr, db = 0, 0, 0, 0
        for i, ax in enumerate(self.fig.get_axes()):
            (x0, y0), (x1, y1) = ax.get_position().get_points()
            try:
                (ox0, oy0), (ox1, oy1) = ax.get_tightbbox(
                    self.canvas.get_renderer()).get_points()
                (ox0, oy0), (ox1, oy1) = trans(((ox0, oy0), (ox1, oy1)))
                dl = max(dl, (x0 - ox0))
                dt = max(dt, (oy1 - y1))
                dr = max(dr, (ox1 - x1))
                db = max(db, (y0 - oy0))
            except:
                pass

        # print(" > %.3f %.3f %.3f %.3f " % (dl, dt, dr, db))
        return (l + dl, t + dt, r + dr, b + db)

    def autoset_margins(self):
        """auto-set margins  left, bottom, right, top
        according to the specified margins (in pixels)
        and axes extent (taking into account labels,
        title, axis)
        """
        if not self.conf.auto_margins:
            return
        # coordinates in px -> [0,1] in figure coordinates
        trans = self.fig.transFigure.inverted().transform

        # Static margins
        if not self.use_dates:
            self.conf.margins = l, t, r, b = self.get_default_margins()
            self.gridspec.update(left=l, top=1 - t, right=1 - r, bottom=b)

        # Axes positions update
        for ax in self.fig.get_axes():
            try:
                ax.update_params()
            except ValueError:
                pass
            ax.set_position(ax.figbox)

    def draw(self):
        self.canvas.draw()

    def update_line(self,
                    trace,
                    xdata,
                    ydata,
                    side='left',
                    draw=False,
                    update_limits=True):
        """ update a single trace, for faster redraw """

        x = self.conf.get_mpl_line(trace)
        x.set_data(xdata, ydata)
        datarange = [xdata.min(), xdata.max(), ydata.min(), ydata.max()]
        self.conf.set_trace_datarange(datarange, trace=trace)
        axes = self.axes
        if side == 'right':
            axes = self.get_right_axes()

        if update_limits:
            self.set_viewlimits()
        if draw:
            self.draw()

    def get_figure(self):
        return self.fig

    def __onPickEvent(self, event=None):
        """pick events"""
        legline = event.artist
        trace = self.conf.legend_map.get(legline, None)
        visible = True
        if trace is not None and self.conf.hidewith_legend:
            line, legline, legtext = trace
            visible = not line.get_visible()
            line.set_visible(visible)
            if visible:
                legline.set_zorder(10.00)
                legline.set_alpha(1.00)
                legtext.set_zorder(10.00)
                legtext.set_alpha(1.00)
            else:
                legline.set_alpha(0.50)
                legtext.set_alpha(0.50)

    def onExport(self, event=None, **kws):
        ofile = ''
        title = 'unknown plot'

        if self.conf.title is not None:
            title = ofile = self.conf.title.strip()
        if len(ofile) > 64:
            ofile = ofile[:63].strip()
        if len(ofile) < 1:
            ofile = 'plot'

        for c in ' .:";|/\\(){}[]\'&^%*$+=-?!@#':
            ofile = ofile.replace(c, '_')

        while '__' in ofile:
            ofile = ofile.replace('__', '_')

        ofile = ofile + '.dat'

        dlg = wx.FileDialog(self,
                            message='Export Map Data to ASCII...',
                            defaultDir=os.getcwd(),
                            defaultFile=ofile,
                            style=wx.FD_SAVE | wx.FD_CHANGE_DIR)

        if dlg.ShowModal() == wx.ID_OK:
            self.writeASCIIFile(dlg.GetPath(), title=title)

    def writeASCIIFile(self, fname, title='unknown plot'):
        buff = ["# X,Y Data for %s" % title, "#------------", "#     X     Y"]
        lines = self.axes.get_lines()
        x0 = lines[0].get_xaxis()
        y0 = lines[0].get_yaxis()
        lab0 = lines[0].get_label().strip()
        if len(lab0) < 1: lab0 = 'Y'
        buff.append("#   X    %s" % lab0)
        outa = [x0, y0]
        npts = len(x0)
        if len(lines) > 1:
            for ix, line in enumerate(lines[1:]):
                lab = ['#   ', '       ', line.get_label().strip()]
                x = line.get_xdata()
                y = line.get_ydata()
                npts = max(npts, len(y))
                if not all(x == x0):
                    lab0[1] = ' X%i ' % (ix + 2)
                    out.append(x)
                out.append(line.get_ydata())

        fout = open(fname, 'w')
        fout.write("%s\n" % "\n".join(buff))
        fout.close()

        orig_dir = os.path.abspath(os.curdir)
        thisdir = os.getcwd()
        file_choices = "DAT (*.dat)|*.dat|ALL FILES (*.*)|*.*"
        dlg = wx.FileDialog(self,
                            message='Export Plot Data to ASCII...',
                            defaultDir=thisdir,
                            defaultFile=ofile,
                            wildcard=file_choices,
                            style=wx.FD_SAVE | wx.FD_CHANGE_DIR)

        if dlg.ShowModal() == wx.ID_OK:
            self.writeASCIIFile(dlg.GetPath(), title=title)
        os.chdir(orig_dir)

    def writeASCIIFile(self, fname, title='unknown plot'):
        "save plot data to external file"

        buff = ["# Plot Data for %s" % title, "#------"]

        out = []
        labs = []
        itrace = 0
        for ax in self.fig.get_axes():
            for line in ax.lines:
                itrace += 1
                x = line.get_xdata()
                y = line.get_ydata()
                ylab = line.get_label()

                if len(ylab) < 1: ylab = ' Y%i' % itrace
                if len(ylab) < 4: ylab = ' %s%s' % (' ' * 4, lab)
                for c in ' .:";|/\\(){}[]\'&^%*$+=-?!@#':
                    ylab = ylab.replace(c, '_')

                pad = max(1, 13 - len(ylab))
                lab = '     X%i   %s%s  ' % (itrace, ' ' * pad, ylab)
                out.extend([x, y])
                labs.append(lab)
        buff.append('# %s ' % (' '.join(labs)))

        npts = [len(a) for a in out]
        for i in range(max(npts)):
            oline = []
            for a in out:
                d = nan
                if i < len(a): d = a[i]
                oline.append(gformat(d))
            buff.append(' '.join(oline))

        if itrace > 0:
            fout = open(fname, 'w')
            fout.write("%s\n" % "\n".join(buff))
            fout.close()
            self.write_message("Exported data to '%s'" % fname, panel=0)

    ####
    ## GUI events
    ####
    def report_leftdown(self, event=None):
        if event is None:
            return
        ex, ey = event.x, event.y
        msg = ''
        try:
            x, y = self.axes.transData.inverted().transform((ex, ey))
        except:
            x, y = event.xdata, event.ydata

        if x is not None and y is not None:
            msg = ("X,Y= %s, %s" % (self._xfmt, self._yfmt)) % (x, y)
        if len(self.fig.get_axes()) > 1:
            ax2 = self.fig.get_axes()[1]
            try:
                x2, y2 = ax2.transData.inverted().transform((ex, ey))
                msg = "X,Y,Y2= %s, %s, %s" % (self._xfmt, self._yfmt,
                                              self._y2fmt) % (x, y, y2)
            except:
                pass

        nsbar = getattr(self, 'nstatusbar', 1)
        self.write_message(msg, panel=max(0, nsbar - 2))
        if (self.cursor_callback is not None
                and hasattr(self.cursor_callback, '__call__')):
            self.cursor_callback(x=event.xdata, y=event.ydata)
Exemplo n.º 13
0
class ShowTifInPath(wx.Panel):
    def __init__(self, parent):

        wx.Panel.__init__(self, parent)

        self.fig = plt.figure()
        self.canvas = FigCanvas(self, -1, self.fig)

        self.lastFileName = ''
        self.filesPath = ''

        self.bindKeyShortcuts()

        self.createMenuAndToolbar()

    def bindKeyShortcuts(self):

        self.canvas.Bind(wx.EVT_KEY_DOWN, self.OnDwnKeyPress)
        self.canvas.Bind(wx.EVT_KEY_UP, self.OnUpKeyPress)
        self.canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)

        # Create an accelerator table
        myKeyId_1 = wx.NewId()
        myKeyId_2 = wx.NewId()
        self.Bind(wx.EVT_MENU, self.onCtrlShiftF1, id=myKeyId_1)
        self.Bind(wx.EVT_MENU, self.onShiftAltY, id=myKeyId_2)

        accel_tbl = wx.AcceleratorTable([
            (wx.ACCEL_SHIFT | wx.ACCEL_CTRL, wx.WXK_F1, myKeyId_1),
            (wx.ACCEL_SHIFT | wx.ACCEL_ALT, ord('Y'), myKeyId_2)
        ])

        self.SetAcceleratorTable(accel_tbl)

    def onCtrlShiftF1(self, event):
        """ https://www.blog.pythonlibrary.org/2010/12/02/wxpython-keyboard-shortcuts-accelerators/ """
        print "You pressed CTRL+SHIFT+F1"

    def onShiftAltY(self, event):
        """ https://www.blog.pythonlibrary.org/2010/12/02/wxpython-keyboard-shortcuts-accelerators/ """
        print "You pressed ALT+SHIFT+Y"

    def createMenuAndToolbar(self):
        '''
        ref: https://www.blog.pythonlibrary.org/2008/07/02/wxpython-working-with-menus-toolbars-and-accelerators/
        '''
        """ Create the menu bar. """
        menuBar = wx.MenuBar()
        fileMenu = wx.Menu()
        fileMenu.AppendSeparator()
        exitMenuItem = fileMenu.Append(wx.NewId(), "&Exit\tAlt+F4",
                                       "Exit the application")
        self.Bind(wx.EVT_MENU, self.OnExit, exitMenuItem)
        menuBar.Append(fileMenu, "&File")
        # exitMenuItem.Enable(False)
        # menuBar.EnableTop(0, False)
        self.GetParent().SetMenuBar(menuBar)  # add it to Frame object
        """        Create a toolbar.        """
        self.toolbar = self.GetParent().CreateToolBar()
        self.toolbar.SetToolBitmapSize((16, 16))  # sets icon size

        # Use wx.ArtProvider for default icons
        open_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR,
                                            (16, 16))
        if 'phoenix' in wx.PlatformInfo:
            openTool = self.toolbar.AddTool(wx.ID_ANY, "Open", open_ico,
                                            "Select file to load")
        else:
            openTool = self.toolbar.AddSimpleTool(wx.ID_ANY, open_ico, "Open",
                                                  "Select file to load")
        # self.Bind(wx.EVT_MENU, self.onSave, saveTool)

        # Use wx.ArtProvider for default icons
        save_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR,
                                            (16, 16))
        saveTool = self.toolbar.AddTool(wx.ID_ANY, "Save", save_ico,
                                        "Saves the Current Worksheet")
        # self.Bind(wx.EVT_MENU, self.onSave, saveTool)

        self.toolbar.AddSeparator()

        print_ico = wx.ArtProvider.GetBitmap(wx.ART_PRINT, wx.ART_TOOLBAR,
                                             (16, 16))
        printTool = self.toolbar.AddTool(wx.ID_ANY, "Print", print_ico,
                                         "Sends Timesheet to Default Printer")
        # self.Bind(wx.EVT_MENU, self.onPrint, printTool)

        # delete_ico = wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_TOOLBAR, (16, 16))
        # deleteTool = self.toolbar.AddSimpleTool(wx.ID_ANY, delete_ico, "Delete", "Delete contents of cell")
        # # self.Bind(wx.EVT_MENU, self.onDelete, deleteTool)
        #
        # undo_ico = wx.ArtProvider.GetBitmap(wx.ART_UNDO, wx.ART_TOOLBAR, (16, 16))
        # self.undoTool = self.toolbar.AddSimpleTool(wx.ID_UNDO, undo_ico, "Undo", "")
        # self.toolbar.EnableTool(wx.ID_UNDO, False)
        # # self.Bind(wx.EVT_TOOL, self.onUndo, self.undoTool)
        #
        # redo_ico = wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_TOOLBAR, (16, 16))
        # self.redoTool = self.toolbar.AddSimpleTool(wx.ID_REDO, redo_ico, "Redo", "")
        # self.toolbar.EnableTool(wx.ID_REDO, False)
        # # self.Bind(wx.EVT_TOOL, self.onRedo, self.redoTool)

        # This basically shows the toolbar
        self.toolbar.Realize()

    def OnExit(self):
        # SystemExit()
        self.Close()

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

    def updateTif(self, tifFullName):
        img = mpimg.imread(tifFullName)
        self.imgplot.set_data(img)
        self.canvas.draw()
        # self.vbox.Fit(self)  #bad for getting correct resize
        self.canvas.Refresh()

        return self.imgplot

    def showTif(self, tifFullName):
        img = mpimg.imread(tifFullName)
        self.imgplot = plt.imshow(img)

        self.cBar = plt.colorbar()
        self.toolbar = NavigationToolbar(self.canvas)
        # plt.axis('off')

        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.vbox.Add(self.toolbar, 0, wx.EXPAND)

        self.SetSizer(self.vbox)

        self.vbox.Fit(self)

        return self.imgplot, self.cBar

    def OnDwnKeyPress(self, event):
        pass
        # print "dwnKey"

    def OnUpKeyPress(self, event):
        print "onUpKey"
        pressedKey = event.GetKeyCode()
        if (pressedKey == wx.WXK_LEFT) | (pressedKey == wx.WXK_DOWN):
            print "left / down key"
            #currentIndex % len(relevant items)
            filesList = list(panel.filesInfo)
            if (filesList[3] > 0):
                filesList[3] = (filesList[3]) - 1
            else:
                filesList[3] = len(filesList[2]) - 1
            panel.filesInfo = tuple(filesList)
            newFileName = panel.filesInfo[2][filesList[3]]
            panel.updateTif(newFileName)

        elif (pressedKey == wx.WXK_RIGHT) | (pressedKey == wx.WXK_UP):
            print "right / up key"
            #currentIndex % len(relevant items)
            filesList = list(panel.filesInfo)
            if (filesList[3] < (len(filesList[2]) - 1)):
                filesList[3] = (filesList[3]) + 1
            else:
                filesList[3] = 0
            panel.filesInfo = tuple(filesList)
            newFileName = panel.filesInfo[2][filesList[3]]
            panel.updateTif(newFileName)

        elif (pressedKey == wx.WXK_NUMPAD_ADD):
            print "+ key"
        elif (pressedKey == wx.WXK_NUMPAD_SUBTRACT):
            print "- key"
        else:
            print pressedKey

        return pressedKey
Exemplo n.º 14
0
class Plotter(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent=parent)
        self.initGui()
        self.Centre()
        self.Show()
        self.graphsToPlot = []
        self.currentGraph = {}
        #listen to messages from checklistbox
        pub.subscribe(self.__onItemChecked, 'item.checked')

    #the list of plots changed
    def __onItemChecked(self, data):
        self.graphsToPlot = []
        for key, value in data.iteritems():
            self.graphsToPlot.append(value)
        self.plotGraphs()

    def initGui(self):
        # Create main panel
        panel = self
        panel.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
        # Set sizers
        sizer0 = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(sizer0)
        # Matplotlib item
        panelcolour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        facecolor = [channel / float(255) for channel in panelcolour]
        self.figure = plt.figure(
            figsize=(-1, -1), dpi=80, facecolor=facecolor, linewidth=1.0
        )  #Figure(figsize=(-1, -1), dpi=80, facecolor=facecolor, linewidth=1.0)
        self.figure.subplots_adjust(left=0.08,
                                    bottom=0.08,
                                    right=0.98,
                                    top=0.98)
        self.canvas = FigCanvas(panel, -1, self.figure)
        self.mainAxes = plt.subplot2grid((1, 1), (0, 0))
        self.mainAxes.set_xlabel('X-Axis')
        self.mainAxes.set_ylabel('Y-Axis')
        self.mainAxes.set_xlim(0.0, 1.0)
        self.mainAxes.set_ylim(0.0, 1.0)
        matplotlib.rcParams.update({'font.size': 12})
        self.mainAxes.grid(False)
        sizer0.Add(self.canvas,
                   1,
                   flag=wx.GROW | wx.LEFT | wx.RIGHT,
                   border=20)
        self.toolbar = NavigationToolbar(self.canvas)
        sizer0.Add(self.toolbar,
                   0,
                   flag=wx.ALIGN_CENTER_HORIZONTAL | wx.LEFT | wx.RIGHT,
                   border=20)
        sizer0.Add((-1, 10))
        self.mouseMove = self.canvas.mpl_connect('motion_notify_event',
                                                 self.updateStatusBar)
        self.onKey = self.canvas.mpl_connect('key_press_event', self.onKey)
        self.canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)
        self.plotLogo()
        # Redefine close event
        #self.Bind(wx.EVT_CLOSE, self.OnClose)

    def ChangeCursor(self, event):
        self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))

    def onKey(self, event):
        if event.inaxes and event.key == "s":
            x, y = event.xdata, event.ydata
            try:
                cmd.delete("mtsslPlot")
                cmd.select("mtsslPlot", "resi %i or resi %i" % (x, y))
            except:
                print "Could not select: resi %i or resi %i" % (x, y)

    def updateStatusBar(self, event):
        #could be made faster using animation blits:
        #http://scipy-cookbook.readthedocs.org/items/Matplotlib_Animations.html
        if event.inaxes:
            x, y = event.xdata, event.ydata
            if event.inaxes == self.mainAxes:
                if self.currentGraph[
                        "Type"] == "DistanceMap" or self.currentGraph[
                            "Type"] == "DifferenceMap":
                    z = self.currentGraph["zData"][x, y]
                    statusString = "x = %i; y = %i; z = %i" % (x, y, z)
                    pub.sendMessage('update.statusBar', data=statusString)

                #plot crosshair
                try:
                    self.mainCrosshairX.remove()
                    self.mainCrosshairY.remove()
                    self.upperCrosshairY.remove()
                    self.rightCrosshairX.remove()
                except:
                    pass
                try:
                    self.mainCrosshairX = self.mainAxes.axhline(y, color="red")
                    self.mainCrosshairY = self.mainAxes.axvline(x, color="red")
                    self.upperCrosshairY = self.axes1.axvline(x, color="red")
                    self.rightCrosshairX = self.axes3.axhline(y, color="red")
                    self.figure.tight_layout()
                    self.canvas.draw()
                except:
                    pass
            else:
                statusString = "x = %i; y = %i" % (x, y)
                pub.sendMessage('update.statusBar', data=statusString)

    def plotGraphs(self):
        # Which type of graph is it
        if len(self.graphsToPlot) > 0:
            graphType = self.graphsToPlot[0]["Type"]
            if (graphType == 'DistanceMap'):
                self.plotDistanceMap(self.graphsToPlot)
            if (graphType == 'DifferenceMap'):
                self.plotDifferenceMap(self.graphsToPlot)
            if (graphType == 'DistancePlot'):
                self.plotDistancePlot(self.graphsToPlot)
            if (graphType == 'AccessibilityPlot'):
                self.plotAccessibilityPlot(self.graphsToPlot)
            if (graphType == 'DistanceDistribution'):
                self.plotDistanceDistribution(self.graphsToPlot)
            self.currentGraph = self.graphsToPlot[0]
            pub.sendMessage('update.statusBar', data="Data plotted.")
        else:
            self.figure.clf()
            self.plotLogo()
            self.canvas.draw()
            pub.sendMessage('update.statusBar',
                            data="Nothing to plot. Please select a plot.")

    def refreshFigure(self):
        self.figure.clear()
        self.mainAxes.set_xlabel('X-Axis')
        self.mainAxes.set_ylabel('Y-Axis')
        self.mainAxes.set_xlim(0.0, 1.0)
        self.mainAxes.set_ylim(0.0, 1.0)
        matplotlib.rcParams.update({'font.size': 12})

    def plotDistanceMap(self, graphs):
        #there should only be one graph in graphs
        graph = graphs[0]
        # Read on x,y,z
        x = graph['xData'] - 0.5 * numpy.ones(len(graph['xData']))
        y = graph['yData'] - 0.5 * numpy.ones(len(graph['yData']))
        id = graph["id"]
        accessibilityPlots = []
        for plot in stored.plots:
            try:
                if id == plot["id"] and plot["Type"] == "AccessibilityPlot":
                    accessibilityPlots.append(plot)
            except:
                pass
        #print accessibilityPlots
        acc1x = accessibilityPlots[0]["xData"]
        acc1y = accessibilityPlots[0]["yData"]
        acc2x = accessibilityPlots[1]["xData"]
        acc2y = accessibilityPlots[1]["yData"]

        xlim = graph['xlim']
        ylim = graph['ylim']
        X, Y = numpy.meshgrid(x, y)
        Z = graph['zData']

        # Define colormap
        cmap = colors.ListedColormap(
            ['blue', 'green', 'yellow', 'orange', 'red'])
        cmap.set_under('white')
        cmap.set_over('red')
        cmap.set_bad(color="grey")
        bounds = [1, 15, 40, 60, 80, 100]
        norm = colors.BoundaryNorm(bounds, cmap.N)

        # Draw plot
        self.mainAxes = plt.subplot2grid((5, 5), (1, 0), colspan=4, rowspan=4)
        self.axes1 = plt.subplot2grid((5, 5), (0, 0),
                                      colspan=4,
                                      sharex=self.mainAxes)
        self.axes3 = plt.subplot2grid((5, 5), (1, 4),
                                      rowspan=4,
                                      sharey=self.mainAxes)
        self.axes4 = plt.subplot2grid((5, 5), (0, 4))
        self.axes1.plot(acc1x,
                        acc1y,
                        linestyle='solid',
                        linewidth=0.5,
                        color='dimgrey',
                        markersize=6,
                        markeredgewidth=1)
        img = self.mainAxes.pcolormesh(x, y, Z, cmap=cmap, norm=norm)
        self.mainAxes.set_xlim(xlim)
        self.mainAxes.set_ylim(ylim)
        self.mainAxes.set_xlabel(graph['xTitle'])
        self.mainAxes.set_ylabel(graph['yTitle'])
        self.axes3.plot(acc2y,
                        acc2x,
                        linestyle='solid',
                        linewidth=0.5,
                        color='dimgrey',
                        markersize=6,
                        markeredgewidth=1)

        # Cosmetics
        xminorLocator = MultipleLocator(10)
        yminorLocator = MultipleLocator(10)
        self.axes1.xaxis.set_ticks_position('top')
        self.axes1.set_yticks(self.axes1.get_ylim())
        self.axes1.set_ylabel("Access.")
        self.axes3.yaxis.set_ticks_position('right')
        self.axes3.set_xticks(self.axes1.get_ylim())
        self.axes3.set_xlabel("Access.")
        # Draw colorbar
        colorbar = plt.colorbar(img, cax=self.axes4)
        colorbar.ax.set_xlabel('Angstrom')
        colorbar.ax.xaxis.set_label_position('top')
        #colorbar.ax.xaxis.labelpad = 20
        self.figure.tight_layout()
        self.canvas.draw()

    def plotDifferenceMap(self, graphs):
        #there should only be one graph in graphs
        graph = graphs[0]
        # Read on x,y,z
        x = graph['xData'] - 0.5 * numpy.ones(len(graph['xData']))
        y = graph['yData'] - 0.5 * numpy.ones(len(graph['yData']))
        id = graph["id"]
        accessibilityPlots = []
        for plot in stored.plots:
            if id == plot["id"] and plot["Type"] == "AccessibilityPlot":
                accessibilityPlots.append(plot)
        #print accessibilityPlots
        acc1x = accessibilityPlots[0]["xData"]
        acc1y = accessibilityPlots[0]["yData"]
        acc2x = accessibilityPlots[1]["xData"]
        acc2y = accessibilityPlots[1]["yData"]

        X, Y = numpy.meshgrid(x, y)
        Z = graph['zData']
        xlim = graph['xlim']
        ylim = graph['ylim']
        # Draw surface plot
        self.mainAxes = plt.subplot2grid((5, 5), (1, 0), colspan=4, rowspan=4)
        self.axes1 = plt.subplot2grid((5, 5), (0, 0),
                                      colspan=4,
                                      sharex=self.mainAxes)
        self.axes3 = plt.subplot2grid((5, 5), (1, 4),
                                      rowspan=4,
                                      sharey=self.mainAxes)
        self.axes4 = plt.subplot2grid((5, 5), (0, 4))
        self.axes1.plot(acc1x,
                        acc1y,
                        linestyle='solid',
                        linewidth=0.5,
                        color='dimgrey',
                        markersize=6,
                        markeredgewidth=1)
        try:
            plt.register_cmap(name='plasma', cmap=cmaps.plasma)
            plt.set_cmap(cmaps.plasma)
            cmap = plt.get_cmap(cmaps.plasma)
        except:
            cmap = matplotlib.cm.jet
        cmap.set_bad(color="grey")
        img = self.mainAxes.pcolormesh(X,
                                       Y,
                                       Z,
                                       cmap=cmap,
                                       vmin=0.0,
                                       vmax=numpy.amax(Z))
        self.mainAxes.set_xlim(xlim)
        self.mainAxes.set_ylim(ylim)
        self.mainAxes.set_xlabel(graph['xTitle'])
        self.mainAxes.set_ylabel(graph['yTitle'])
        self.axes3.plot(acc2y,
                        acc2x,
                        linestyle='solid',
                        linewidth=0.5,
                        color='dimgrey',
                        markersize=6,
                        markeredgewidth=1)
        # Cosmetics
        xminorLocator = MultipleLocator(10)
        yminorLocator = MultipleLocator(10)
        self.mainAxes.xaxis.set_minor_locator(xminorLocator)
        self.mainAxes.yaxis.set_minor_locator(yminorLocator)
        self.mainAxes.tick_params(direction='out', length=6, width=1)
        self.mainAxes.tick_params(which='minor',
                                  direction='out',
                                  length=3,
                                  width=1)
        self.mainAxes.xaxis.labelpad = 15
        self.mainAxes.yaxis.labelpad = 15
        self.axes1.xaxis.set_ticks_position('top')
        self.axes1.set_yticks(self.axes1.get_ylim())
        self.axes1.set_ylabel("Access.")
        self.axes3.yaxis.set_ticks_position('right')
        self.axes3.set_xticks(self.axes1.get_ylim())
        self.axes3.set_xlabel("Access.")
        # Draw colorbar
        colorbar = plt.colorbar(img, cax=self.axes4)
        colorbar.ax.set_xlabel('Angstrom')
        colorbar.ax.xaxis.set_label_position('top')
        #colorbar.ax.xaxis.labelpad = 20
        self.figure.tight_layout()
        self.canvas.draw()

    def plotDistancePlot(self, graphs):
        # Plot graph
        axes = plt.subplot2grid((1, 1), (0, 0))
        for graph in graphs:
            axes.plot(
                graph['xData'],
                graph['yData'],
                linestyle='solid',
                linewidth=3,
                color=graph['Color'],
                #marker='o',
                #markerfacecolor='white',
                #markeredgecolor='black',
                #markersize=3.5,
                #markeredgewidth=1
            )
        Xmin = 0
        Xmax = graph['xData'].max() + 1
        Ymin = 0
        Ymax = 100
        axes.set_xlim(graph['xlim'])
        axes.set_ylim(Ymin, Ymax)
        axes.set_xlabel(graph['xTitle'])
        axes.set_ylabel(graph['yTitle'])
        # Color the distance ranges
        axes.fill_between([Xmin, Xmax], 15, Ymin, color='blue', alpha=0.15)
        axes.fill_between([Xmin, Xmax], 40, 15, color='green', alpha=0.15)
        axes.fill_between([Xmin, Xmax], 60, 40, color='yellow', alpha=0.15)
        axes.fill_between([Xmin, Xmax], 80, 60, color='orange', alpha=0.15)
        axes.fill_between([Xmin, Xmax], Ymax, 80, color='red', alpha=0.15)
        # Cosmetics
        xminorLocator = MultipleLocator(10)
        yminorLocator = MultipleLocator(10)
        axes.xaxis.set_minor_locator(xminorLocator)
        axes.yaxis.set_minor_locator(yminorLocator)
        axes.tick_params(direction='out', length=6, width=1)
        axes.tick_params(which='minor', direction='out', length=3, width=1)
        axes.xaxis.labelpad = 15
        axes.yaxis.labelpad = 15
        self.figure.tight_layout()
        self.canvas.draw()

    def plotDistanceDistribution(self, graphs):
        axes = plt.subplot2grid((1, 1), (0, 0))
        for graph in graphs:
            index = numpy.zeros(1)
            for i in range(0, graph['yData'].shape[0]):
                if (graph['yData'][i] <= 0):
                    index = numpy.append(index, i)
                    index = numpy.delete(index, 0)
            Y = numpy.delete(graph['yData'], index)
            X = numpy.delete(graph['xData'], index)
            axes.plot(
                X,
                Y,
                linestyle='solid',
                linewidth=3,
                color=graph['Color'],
                #markerfacecolor='white',
                #markeredgecolor='black',
                markersize=3.5,
                #markeredgewidth=1
            )
        Xmin = 0
        Xmax = graph['xData'].max() + 1
        Ymin = 0
        Ymax = graph['yData'].max() * 1.05
        axes.set_xlim(graph['xlim'])
        axes.set_ylim(Ymin, Ymax)
        axes.set_xlabel(graph['xTitle'])
        axes.set_ylabel(graph['yTitle'])
        xminorLocator = MultipleLocator(10)
        yminorLocator = MultipleLocator(10)
        axes.xaxis.set_minor_locator(xminorLocator)
        axes.yaxis.set_minor_locator(yminorLocator)
        axes.tick_params(direction='out', length=6, width=1)
        axes.tick_params(which='minor', direction='out', length=3, width=1)
        axes.xaxis.labelpad = 15
        axes.yaxis.labelpad = 15
        self.figure.tight_layout()
        self.canvas.draw()

    def plotAccessibilityPlot(self, graphs):
        axes = plt.subplot2grid((1, 1), (0, 0))
        for graph in graphs:
            axes.plot(
                graph['xData'],
                graph['yData'],
                linestyle='solid',
                linewidth=3,
                color=graph['Color'],
                marker='.',
                #markerfacecolor='white',
                #markeredgecolor='black',
                markersize=3.5,
                #markeredgewidth=1
            )
        Xmin = 0
        Xmax = graph['xData'].max() + 1
        Ymin = 0
        Ymax = graph['yData'].max() * 1.05
        axes.set_xlim(graph['xlim'])
        axes.set_ylim(Ymin, Ymax)
        axes.set_xlabel(graph['xTitle'])
        axes.set_ylabel(graph['yTitle'])
        # Cosmetics
        xminorLocator = MultipleLocator(10)
        yminorLocator = MultipleLocator(10)
        axes.xaxis.set_minor_locator(xminorLocator)
        axes.yaxis.set_minor_locator(yminorLocator)
        axes.tick_params(direction='out', length=6, width=1)
        axes.tick_params(which='minor', direction='out', length=3, width=1)
        axes.xaxis.labelpad = 15
        axes.yaxis.labelpad = 15
        self.figure.tight_layout()
        self.canvas.draw()

    def plotLogo(self):
        axes = plt.subplot2grid((1, 1), (0, 0))
        img = mpimg.imread(os.path.dirname(__file__) + "/logo.png")
        axes.imshow(img)
Exemplo n.º 15
0
class MainPanel(wx.Dialog):
    def __init__(self,
                 parent,
                 pathToPlugins=None):  #, main_playlist, nb_playlist):
        if (not pathToPlugins == None):
            RESFILE = os.path.join(pathToPlugins,
                                   'x2') + os.sep + "layout_x2.xml"

        wx.Dialog.__init__(self,
                           parent,
                           -1,
                           style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
        self.parent = parent
        self.nb_playlist = 0
        self.main_playlist = self.parent.lc_playlist

        #self.super_parent = super_parent

        # XML Resources can be loaded from a file like this:
        res = xrc.XmlResource(RESFILE)
        # Now create a panel from the resource data
        panel = res.LoadPanel(self, "m_pa_x2main")

        #self.panel = panel
        #background = 'tulips.jpg'
        #img = wx.Image(background, wx.BITMAP_TYPE_ANY)
        #self.buffer = wx.BitmapFromImage(img)
        #dc = wx.BufferedDC(wx.ClientDC(panel), self.buffer)
        #self.panel.Bind(wx.EVT_PAINT, self.OnPaint)

        # control references --------------------
        self.pa_x2main = xrc.XRCCTRL(self, 'm_pa_x2main')
        self.pa_x2_graph = xrc.XRCCTRL(self, 'm_pa_x2_graph')
        self.lc_x2_plist = xrc.XRCCTRL(self, 'm_lc_x2_plist')
        self.cl_x2_features = xrc.XRCCTRL(self, 'm_cl_x2_features')
        self.sl_x2_pointsize = xrc.XRCCTRL(self, 'm_sl_x2_pointsize')
        self.lc_x2_plist.InsertColumn(0, "Artist")
        self.lc_x2_plist.InsertColumn(1, "Song")
        self.lc_x2_plist.SetColumnWidth(0, 100)
        self.lc_x2_plist.SetColumnWidth(1, 100)

        self.Bind(wx.EVT_BUTTON,
                  self.OnAutoGenerateX2Playist,
                  id=xrc.XRCID('m_bu_x2_plize'))
        self.Bind(wx.EVT_BUTTON,
                  self.OnCenterClick,
                  id=xrc.XRCID('m_bu_x2_center'))
        self.Bind(wx.EVT_SLIDER,
                  self.OnPointSizeClick,
                  id=xrc.XRCID('m_sl_x2_pointsize'))
        self.Bind(wx.EVT_SPIN, self.OnZoomClick, id=xrc.XRCID('m_sb_x2_zoom'))
        self.Bind(wx.EVT_SPIN, self.OnPanXClick, id=xrc.XRCID('m_sb_x2_panx'))
        self.Bind(wx.EVT_SPIN, self.OnPanYClick, id=xrc.XRCID('m_sb_x2_pany'))
        self.Bind(wx.EVT_CHECKBOX,
                  self.OnXAxisClick,
                  id=xrc.XRCID('m_cb_x2_xlog'))
        self.Bind(wx.EVT_CHECKBOX,
                  self.OnYAxisClick,
                  id=xrc.XRCID('m_cb_x2_ylog'))
        self.Bind(wx.EVT_CHECKLISTBOX, self.OnCheckListBox,
                  self.cl_x2_features)

        self.current_zoom = 0
        self.current_panx = 0
        self.current_pany = 0

        #features array

        #tag_array = GetTags()
        self.cl_x2_features.Set(FEATURES_ARRAY)
        #self.cl_x2_features.AppendItems(tag_array)

        self.figure = Figure(None, None, (1, 1, 1), None, 1.0, True,
                             None)  #facecolor=0.75, edgecolor='white')
        #(figsize=None, dpi=None, facecolor=None, edgecolor=None, linewidth=1.0, frameon=True, subplotpars=None)
        self.MakeScatt([0, 1, 2, 3])
        self.build_graph()
        self.build_collection()
        self.canvas = FigureCanvas(self.pa_x2_graph, -1, self.figure)

        self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)

        self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown)
        #self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
        self.Bind(wx.EVT_RIGHT_UP, self.OnMouseRightUp)
        self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown)
        #self.canvas.Bind(wx.EVT_MOTION, self.OnMouseMotion)
        self.canvas.Bind(wx.EVT_RIGHT_UP, self.OnMouseRightUp)

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

        #lasso
        self.mpl = self.canvas.mpl_connect('button_press_event', self.onpress)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.pa_x2main, 1, wx.EXPAND | wx.ALL, 5)
        self.SetSizer(sizer)
        self.SetAutoLayout(True)
        self.Fit()

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

    def OnPaint(self, evt):
        dc = wx.BufferedPaintDC(self.panel, self.buffer)

    def ChangeCursor(self, curtype):
        self.canvas.SetCursor(wx.StockCursor(curtype))

    def OnMouseRightDown(self, evt):
        self.canvas.mpl_disconnect(self.mpl)
        self.canvas.Bind(wx.EVT_MOTION, self.OnMouseMotion)
        self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
        self.ChangeCursor(wx.CURSOR_HAND)
        self.Refresh()
        self.oldx = evt.GetPosition()[0]
        self.oldy = evt.GetPosition()[1]
        #self.wPos = self.ClientToScreen((0,0))
        self.CaptureMouse()
        #print 'right-down'

    def OnMouseMotion(self, evt):
        if evt.Dragging() and evt.RightIsDown():
            dPos = evt.GetPosition(
            )  #evt.GetEventObject().ClientToScreen(evt.GetPosition())
            #nPos = (self.wPos.x + (dPos.x - self.ldPos.x), -2)
            #nPos = (self.wPos.x + (dPos.x - self.ldPos.x), self.wPos.y + (dPos.y - self.ldPos.y))
            #print(nPos)
            #print self.ldPos

            curx = dPos[0]
            cury = dPos[1]
            x = self.axes.get_xaxis()
            y = self.axes.get_yaxis()
            if (curx - self.oldx) < -10:
                x.pan(.5)
                self.oldx = curx
            if (curx - self.oldx) > 10:
                x.pan(-.5)
                self.oldx = curx
            if (cury - self.oldy) > 10:
                y.pan(.5)
                self.oldy = cury
            if (cury - self.oldy) < -10:
                y.pan(-.5)
                self.oldy = cury

            self.canvas.draw()

    def OnMouseRightUp(self, evt):
        try:
            self.ReleaseMouse()
        except wx._core.PyAssertionError:
            pass
        self.ChangeCursor(wx.CURSOR_DEFAULT)
        self.canvas.Unbind(wx.EVT_MOTION)
        self.Unbind(wx.EVT_MOTION)
        self.mpl = self.canvas.mpl_connect('button_press_event', self.onpress)

    def UpdateStatusBar(self, event):
        if event.inaxes:
            x, y = event.xdata, event.ydata
            self.statusBar.SetStatusText(("x= " + str(x) + "  y=" + str(y)), 0)

    def OnPointSizeClick(self, event):
        self.point_size = self.sl_x2_pointsize.GetValue(
        ) + 50  # range 50 to 300
        self.figure.clear()
        self.build_graph()
        self.build_collection()
        self.canvas.draw()

    def OnCenterClick(self, event):
        self.figure.clear()
        self.build_graph()
        self.build_collection()
        self.canvas.draw()

    def OnZoomClick(self, event=None):
        x = self.axes.get_xaxis()
        y = self.axes.get_yaxis()
        if event.GetPosition() > self.current_zoom:
            x.zoom(1)
            y.zoom(1)
        else:
            x.zoom(-1)
            y.zoom(-1)
        self.current_zoom = event.GetPosition()
        self.canvas.draw()

    def OnMouseWheel(self, evt):
        rotation = evt.GetWheelRotation()
        x = self.axes.get_xaxis()
        y = self.axes.get_yaxis()
        if rotation > 0:
            x.zoom(1)
            y.zoom(1)
        else:
            x.zoom(-1)
            y.zoom(-1)
        self.canvas.draw()
        # Done handling event
        #evt.Skip()

    def OnPanXClick(self, event):
        x = self.axes.get_xaxis()
        y = self.axes.get_yaxis()
        if event.GetPosition() > self.current_panx:
            x.pan(1)
        else:
            x.pan(-1)
        self.current_panx = event.GetPosition()
        self.canvas.draw()

    def OnPanYClick(self, event):
        x = self.axes.get_xaxis()
        y = self.axes.get_yaxis()
        if event.GetPosition() > self.current_pany:
            y.pan(1)
        else:
            y.pan(-1)
        self.current_pany = event.GetPosition()
        self.canvas.draw()

    def OnXAxisClick(self, event):
        if self.axes.get_xscale() == 'log':
            self.axes.set_xscale('linear')
        else:
            self.axes.set_xscale('log')
        #self.axes.autoscale_view()
        #self.canvas.draw_idle()
        #self.axes.autoscale_view()
        self.canvas.draw()
        #self.canvas.Refresh(eraseBackground=False)

    def OnYAxisClick(self, event):
        if self.axes.get_yscale() == 'log':
            self.axes.set_yscale('linear')
        else:
            self.axes.set_yscale('log')
        #self.axes.autoscale_view()
        self.canvas.draw()

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

    def OnCheckListBox(self, event):
        index = event.GetSelection()
        label = self.cl_x2_features.GetString(index)
        #print label
        #print index
        self.cl_x2_features.SetSelection(
            index)  # so that (un)checking also selects (moves the highlight)
        #print self.cl_x2_features.GetCount()
        selected_array = []
        for x in range(0, self.cl_x2_features.GetCount()):
            if self.cl_x2_features.IsChecked(x) == True:
                selected_array.append(x)
        print selected_array
        if len(selected_array) >= 1:
            #print 'fofofofof'
            self.figure.clear()
            self.MakeScatt(selected_array)
            self.build_graph()
            self.build_collection()
            self.canvas.draw()

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

    def MakeScatt(self, selected_array):

        pre_data_array, self.song_array, self.color_array, use_std = GetResultsArray(
            selected_array)
        #print pre_data_array
        pca1, pca2, pca3 = pca_module.PCA_svd(pre_data_array, use_std)
        #print self.data_array
        #print pca1
        #self.data = pca1
        #print pca2
        #grab the first 2 components
        self.data_array = np.array_split(pca1, [
            2,
        ], axis=1)[0]
        #print self.data_array

        #self.axes.set_xlabel(r'$\Delta_i$', fontsize=20)
        #self.axes.set_ylabel(r'$\Delta_{i+1}$', fontsize=20)
        #self.axes.set_title('Volume and percent change')
        #self.axes.grid(True)
        ### use zoom instead
        #self.xmin = self.data1.min()# - (self.data1.max() * 0.1)
        #self.xmax = self.data1.max()# * 1.1
        #self.ymin = self.data2.min()# - (self.data2.max() * 0.1)
        #self.ymax = self.data2.max()# * 1.1

    def build_graph(self):

        self.axes = self.figure.add_subplot(111, axisbg=(1, 1, 1))
        self.figure.subplots_adjust(left=0, right=1, top=1, bottom=0)
        #self.axes.frame_on(False)
        #subplot(111, axisbg='darkslategray')
        #ax = fig.add_subplot(111)
        #self.axes.scatter(self.data2, self.data1, c=[0.5,0.5,1.0], s=200, alpha=0.5)

    def build_collection(self):
        self.point_size = self.sl_x2_pointsize.GetValue(
        ) + 50  # range 50 to 300
        self.collection = RegularPolyCollection(
            #self.axes.figure.dpi,
            numsides=80,
            sizes=(self.point_size, ),
            facecolors=self.color_array,
            offsets=self.data_array,
            transOffset=self.axes.transData)
        self.collection.set_alpha(0.7)
        self.axes.add_collection(self.collection)

        #self.axes.axis([self.xmin, self.xmax, self.ymin, self.ymax])
        self.axes.autoscale_view()
        x = self.axes.get_xaxis()
        y = self.axes.get_yaxis()
        x.zoom(-1)
        y.zoom(-1)
        #self.axes.axis('tight')
        ##self.axes.axis('off')

    def callback(self, verts):
        facecolors = self.collection.get_facecolors()
        ind = nonzero(points_inside_poly(self.data_array, verts))[0]
        for i in range(len(self.data_array)):
            if i in ind:
                facecolors[i] = (1, 1, 0, .5)
                #print facecolors[i]
                #pass
            else:
                facecolors[i] = self.color_array[i]
                #pass

        #print facecolors[i]
        self.canvas.draw_idle()
        self.canvas.widgetlock.release(self.lasso)
        del self.lasso
        #self.ind = ind
        self.pass_data(ind)

    def onpress(self, event):
        #print event.button
        if self.canvas.widgetlock.locked():
            #print 'foo'
            self.canvas.widgetlock.release(self.lasso)
            #return
        if event.inaxes is None:
            return
        self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata),
                           self.callback)
        # acquire a lock on the widget drawing
        self.canvas.widgetlock(self.lasso)

    def pass_data(self, ind):
        #populate parents list control
        self.lc_x2_plist.DeleteAllItems()
        for x in ind:
            self.lc_x2_plist.InsertStringItem(0, self.song_array[x][0])
            self.lc_x2_plist.SetStringItem(0, 1, self.song_array[x][1])
        #pass

    def update_data(self):
        pass
        #self.figure.clf()
        #build_graph(self)
        #self.MakeScatt()
        #self.build_collection()

    def OnAutoGenerateX2Playist(self, event):
        # copy the sifted list to the playlist
        self.parent.CheckClear()
        insert_at = self.parent.lc_playlist.GetItemCount()
        for x in range(self.lc_x2_plist.GetItemCount(), 0, -1):
            artist = self.lc_x2_plist.GetItem(x - 1, 0).GetText()
            song = self.lc_x2_plist.GetItem(x - 1, 1).GetText()
            self.parent.SetPlaylistItem(insert_at, artist, song, '', '')
        #save the playlist
        self.parent.SavePlaylist()
        # switch tabs
        self.parent.nb_main.SetSelection(self.nb_playlist)
Exemplo n.º 16
0
class PlotPanel(wx.Panel):
    ''' Base class for the plotting in GenX - all the basic functionallity
        should be implemented in this class. The plots should be derived from
        this class. These classes should implement an update method to update
        the plots.
    '''
    def __init__(self, parent, id = -1, color = None, dpi = None
            , style = wx.NO_FULL_REPAINT_ON_RESIZE|wx.EXPAND|wx.ALL
            , config = None, config_name = '', **kwargs):

        wx.Panel.__init__(self,parent, id = id, style = style, **kwargs)

        self.parent = parent
        self.callback_window = self
        self.config = config
        self.config_name = config_name
        self.figure = Figure(None,dpi)
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        self.canvas.SetExtraStyle(wx.EXPAND)
        self.SetColor(color)
        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)
        self._resizeflag = True
        self.print_size = (15./2.54, 12./2.54)
        #self._SetSize()

        # Flags and bindings for zooming
        self.zoom = False
        self.zooming = False
        self.scale = 'linear'
        self.autoscale = True


        self.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnLeftMouseButtonDown)
        self.canvas.Bind(wx.EVT_LEFT_UP, self.OnLeftMouseButtonUp)
        self.canvas.Bind(wx.EVT_MOTION, self.OnMouseMove)
        self.canvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick)
        self.canvas.Bind(wx.EVT_RIGHT_UP, self.OnContextMenu)

        cursor = wx.StockCursor(wx.CURSOR_CROSS)
        self.canvas.SetCursor(cursor)
        self.old_scale_state = True
        self.ax = None

        # Init printout stuff
        self.fig_printer = FigurePrinter(self)

        # Create the drawing bitmap
        self.bitmap =wx.EmptyBitmap(1, 1)
#        DEBUG_MSG("__init__() - bitmap w:%d h:%d" % (w,h), 2, self)
        self._isDrawn = False

    def SetColor(self, rgbtuple=None):
        ''' Set the figure and canvas color to be the same '''
        if not rgbtuple:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        col = [c/255. for c in rgbtuple]
        self.figure.set_facecolor(col)
        self.figure.set_edgecolor(col)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    def _onSize(self, evt):
        self._resizeflag = True
        self._SetSize()
        #self.canvas.draw(repaint = False)

    def _onIdle(self, evt):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()
            #self.canvas.gui_repaint(drawDC = wx.PaintDC(self))


    def _SetSize(self, pixels = None):
        ''' This method can be called to force the Plot to be a desired
            size which defaults to the ClientSize of the Panel.
        '''
        if not pixels:
            pixels = self.GetClientSize()

        self.canvas.SetSize(pixels)
        #self.figure.set_size_inches(pixels[0]/self.figure.get_dpi()
        #, pixels[1]/self.figure.get_dpi())

    def ReadConfig(self):
        '''ReadConfig(self) --> None

        Reads in the config file
        '''
        bool_items = ['zoom', 'autoscale']
        bool_func = [self.SetZoom, self.SetAutoScale]

        if not self.config:
            return


        vals = []
        for index in range(len(bool_items)):
            try:
                val = self.config.get_boolean(self.config_name,\
                        bool_items[index])
            except io.OptionError as e:
                print('Could not locate option %s.%s'\
                %(self.config_name, bool_items[index]))
                vals.append(None)
            else:
                vals.append(val)

        try:
            scale = self.config.get(self.config_name, 'y scale')
            string_sucess = True
        except io.OptionError as e:
            string_sucess = False
            print('Could not locate option %s.%s'\
            %(self.config_name, 'scale'))
        else:
            self.SetYScale(scale)

        # This is done due to that the zoom and autoscale has to read
        # before any commands are issued in order not to overwrite
        # the config
        [bool_func[i](vals[i]) for i in range(len(vals)) if vals[i]]


    def WriteConfig(self):
        '''WriteConfig(self) --> None

        Writes the current settings to the config file
        '''
        if self.config:
            self.config.set(self.config_name, 'zoom', self.GetZoom())
            self.config.set(self.config_name, 'autoscale', self.GetAutoScale())
            self.config.set(self.config_name, 'y scale', self.GetYScale())

    def SetZoom(self, active = False):
        '''
        set the zoomstate
        '''
        #if not self.zoom_sel:
            #self.zoom_sel = RectangleSelector(self.ax,\
            # self.box_select_callback, drawtype='box',useblit=False)
        #print help(self.zoom_sel.ignore)

        if active:
            #self.zoom_sel.ignore = lambda x: False
            self.zoom = True
            cursor = wx.StockCursor(wx.CURSOR_MAGNIFIER)
            self.canvas.SetCursor(cursor)
            if self.callback_window:
                evt = state_changed(zoomstate = True,\
                        yscale = self.GetYScale(), autoscale = self.autoscale)
                wx.PostEvent(self.callback_window, evt)
            if self.ax:
                #self.ax.set_autoscale_on(False)
                self.old_scale_state = self.GetAutoScale()
                self.SetAutoScale(False)

        else:
            #self.zoom_sel.ignore = lambda x: True
            self.zoom = False
            cursor = wx.StockCursor(wx.CURSOR_CROSS)
            self.canvas.SetCursor(cursor)
            if self.callback_window:
                evt = state_changed(zoomstate = False,\
                    yscale = self.GetYScale(), autoscale = self.autoscale)
                wx.PostEvent(self.callback_window, evt)
            if self.ax:
                #self.ax.set_autoscale_on(self.autoscale)
                self.SetAutoScale(self.old_scale_state)
        self.WriteConfig()

    def GetZoom(self):
        '''GetZoom(self) --> state [bool]
        Returns the zoom state of the plot panel.
        True = zoom active
        False = zoom inactive
        '''
        return self.zoom

    def SetAutoScale(self, state):
        '''SetAutoScale(self, state) --> None

        Sets autoscale of the main axes wheter or not it should autoscale
        when plotting
        '''
        #self.ax.set_autoscale_on(state)
        self.autoscale = state
        self.WriteConfig()
        evt = state_changed(zoomstate = self.GetZoom(),\
                        yscale = self.GetYScale(), autoscale = self.autoscale)
        wx.PostEvent(self.callback_window, evt)


    def GetAutoScale(self):
        '''GetAutoScale(self) --> state [bool]

        Returns the autoscale state, true if the plots is automatically
        scaled for each plot command.
        '''
        return self.autoscale

    def AutoScale(self, force = False):
        '''AutoScale(self) --> None

        A log safe way to autoscale the plots - the ordinary axis tight
        does not work for negative log data. This works!
        '''
        if not (self.autoscale or force):
            return
        # If nothing is plotted no autoscale use defaults...
        if sum([len(line.get_ydata()) > 0 for line in self.ax.lines]) == 0:
            self.ax.set_xlim(0, 1)
            self.ax.set_ylim(1e-3, 1.0)
            return
        if self.scale == 'log':
            #print 'log scaling'
            # Find the lowest possible value of all the y-values that are
            #greater than zero. check so that y data contain data before min
            # is applied
            tmp = [line.get_ydata().compress(line.get_ydata() > 0.0).min()\
                   for line in self.ax.lines if array(line.get_ydata() > 0.0).sum() > 0]
            if len(tmp) > 0:
                ymin = min(tmp)
            else:
                ymin = 1e-3
            tmp = [line.get_ydata().compress(line.get_ydata() > 0.0).max()\
                   for line in self.ax.lines if array(line.get_ydata() > 0.0).sum() > 0]
            if len(tmp) > 0:
                ymax = max(tmp)
            else:
                ymax = 1
        else:
            ymin = min([array(line.get_ydata()).min()\
                     for line in self.ax.lines if len(line.get_ydata()) > 0])
            ymax = max([array(line.get_ydata()).max()\
                   for line in self.ax.lines if len(line.get_ydata()) > 0])
        tmp = [array(line.get_xdata()).min()\
                    for line in self.ax.lines if len(line.get_ydata()) > 0]
        if len(tmp) > 0:
            xmin = min(tmp)
        else:
            xmin = 0
        tmp = [array(line.get_xdata()).max()\
                    for line in self.ax.lines if len(line.get_ydata()) > 0]
        if len(tmp) > 0:
            xmax = max(tmp)
        else:
            xmax = 1
        # Set the limits
        #print 'Autoscaling to: ', ymin, ymax
        self.ax.set_xlim(xmin, xmax)
        self.ax.set_ylim(ymin*(1-sign(ymin)*0.05), ymax*(1+sign(ymax)*0.05))
        #self.ax.set_yscale(self.scale)
        self.flush_plot()

    def SetYScale(self, scalestring):
        ''' SetYScale(self, scalestring) --> None

        Sets the y-scale of the main plotting axes. Currently accepts
        'log' or 'lin'.
        '''
        if self.ax:
            if scalestring == 'log':
                self.scale = 'log'
                self.AutoScale(force = True)
                try:
                    self.ax.set_yscale('log')
                except OverflowError:
                    self.AutoScale(force = True)
            elif scalestring == 'linear' or scalestring == 'lin':
                self.scale = 'linear'
                self.ax.set_yscale('linear')
                self.AutoScale(force = True)
            else:
                raise ValueError('Not allowed scaling')
            self.flush_plot()
            evt = state_changed(zoomstate = self.GetZoom(),\
                        yscale = self.GetYScale(), autoscale = self.autoscale)
            wx.PostEvent(self.callback_window, evt)
            self.WriteConfig()

    def GetYScale(self):
        '''GetYScale(self) --> String

        Returns the current y-scale in use. Currently the string
        'log' or 'linear'. If the axes does not exist it returns None.
        '''
        if self.ax:
            return self.ax.get_yscale()
        else:
            return None


    def CopyToClipboard(self, event = None):
        '''CopyToClipboard(self, event) --> None

        Copy the plot to the clipboard.
        '''
        self.canvas.Copy_to_Clipboard(event = event)

    def PrintSetup(self, event = None):
        '''PrintSetup(self) --> None

        Sets up the printer. Creates a dialog box
        '''
        self.fig_printer.pageSetup()

    def PrintPreview(self, event = None):
        '''PrintPreview(self) --> None

        Prints a preview on screen.
        '''
        self.fig_printer.previewFigure(self.figure)

    def Print(self, event= None):
        '''Print(self) --> None

        Print the figure.
        '''
        self.fig_printer.printFigure(self.figure)


    def SetCallbackWindow(self, window):
        '''SetCallbackWindow(self, window) --> None

        Sets the callback window that should recieve the events from
        picking.
        '''

        self.callback_window = window

    def OnLeftDblClick(self, event):
        if self.ax and self.zoom:
            tmp = self.GetAutoScale()
            self.SetAutoScale(True)
            self.AutoScale()
            self.SetAutoScale(tmp)
            #self.AutoScale()
            #self.flush_plot()
            #self.ax.set_autoscale_on(False)

    def OnLeftMouseButtonDown(self, event):
        self.start_pos = event.GetPosition()
        #print 'Left Mouse button pressed ', self.ax.transData.inverse_xy_tup(self.start_pos)
        class Point:
            pass
        p = Point()
        p.x, p.y = self.start_pos
        size = self.canvas.GetClientSize()
        p.y = (size.height - p.y)
        if self.zoom and self.ax:
            if mat_ver > zoom_ver:
                in_axes = self.ax.in_axes(p)
            else:
                in_axes = self.ax.in_axes(*self.start_pos)
            if in_axes:
                self.zooming = True
                self.cur_rect = None
                self.canvas.CaptureMouse()
            else:
                self.zooming = False
        elif self.ax:
            size = self.canvas.GetClientSize()
            if mat_ver > zoom_ver:
                xy = self.ax.transData.inverted().transform(\
                    array([self.start_pos[0], size.height-self.start_pos[1]])\
                    [newaxis,:])
                x, y = xy[0,0], xy[0,1]
            else:
                x, y = self.ax.transData.inverse_xy_tup(\
                    (self.start_pos[0], size.height - self.start_pos[1]))
            if self.callback_window:
                evt = plot_position(text = '(%.3e, %.3e)'%(x, y))
                wx.PostEvent(self.callback_window, evt)
            #print x,y


    def OnMouseMove(self, event):
        if self.zooming and event.Dragging() and event.LeftIsDown():
            self.cur_pos = event.GetPosition()
            #print 'Mouse Move ', self.ax.transData.inverse_xy_tup(self.cur_pos)
            class Point:
                pass
            p = Point()
            p.x, p.y = self.cur_pos
            size = self.canvas.GetClientSize()
            p.y = (size.height - p.y)
            if mat_ver > zoom_ver:
                in_axes = self.ax.in_axes(p)
            else:
                in_axes = self.ax.in_axes(*self.start_pos)
            if in_axes:
                new_rect = (min(self.start_pos[0], self.cur_pos[0]),
                            min(self.start_pos[1], self.cur_pos[1]),
                        abs(self.cur_pos[0] - self.start_pos[0]),
                        abs(self.cur_pos[1] - self.start_pos[1]))
                self._DrawAndErase(new_rect, self.cur_rect)
                self.cur_rect = new_rect
        #event.Skip()

    def OnLeftMouseButtonUp(self, event):
        if self.canvas.HasCapture():
            #print 'Left Mouse button up'
            self.canvas.ReleaseMouse()
            if self.zooming and self.cur_rect:
                # Note: The coordinte system for matplotlib have a different
                # direction of the y-axis and a different origin!
                size = self.canvas.GetClientSize()
                if mat_ver > zoom_ver:
                    start = self.ax.transData.inverted().transform(\
                    array([self.start_pos[0], size.height-self.start_pos[1]])[newaxis,:])
                    end = self.ax.transData.inverted().transform(\
                    array([self.cur_pos[0], size.height-self.cur_pos[1]])[newaxis, :])
                    xend, yend = end[0,0], end[0,1]
                    xstart, ystart = start[0,0], start[0,1]
                else:
                    xstart, ystart = self.ax.transData.inverse_xy_tup(\
                        (self.start_pos[0], size.height-self.start_pos[1]))
                    xend, yend = self.ax.transData.inverse_xy_tup(\
                        (self.cur_pos[0], size.height-self.cur_pos[1]))

                #print xstart, xend
                #print ystart, yend
                self.ax.set_xlim(min(xstart,xend), max(xstart,xend))
                self.ax.set_ylim(min(ystart,yend), max(ystart,yend))
                self.flush_plot()
            self.zooming = False

    def _DrawAndErase(self, box_to_draw, box_to_erase = None):
        '''_DrawAndErase(self, box_to_draw, box_to_erase = None) --> None
        '''
        dc = wx.ClientDC(self.canvas)
        # dc.BeginDrawing()
        dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.SetLogicalFunction(wx.XOR)
        if box_to_erase:
            dc.DrawRectangle(*box_to_erase)
        dc.DrawRectangle(*box_to_draw)
        # dc.EndDrawing()

    def OnContextMenu(self, event):
        '''OnContextMenu(self, event) --> None

        Callback to show the popmenu for the plot which allows various
        settings to be made.
        '''
        menu = wx.Menu()

        zoomID = wx.NewId()
        menu.AppendCheckItem(zoomID, "Zoom")
        menu.Check(zoomID, self.GetZoom())
        def OnZoom(event):
            self.SetZoom(not self.GetZoom())
        self.Bind(wx.EVT_MENU, OnZoom, id = zoomID)

        zoomallID = wx.NewId()
        menu.Append(zoomallID, 'Zoom All')
        def zoomall(event):
            tmp = self.GetAutoScale()
            self.SetAutoScale(True)
            self.AutoScale()
            self.SetAutoScale(tmp)
            #self.flush_plot()
        self.Bind(wx.EVT_MENU, zoomall, id = zoomallID)

        copyID = wx.NewId()
        menu.Append(copyID, "Copy")
        def copy(event):
            self.CopyToClipboard()
        self.Bind(wx.EVT_MENU, copy, id = copyID)

        yscalemenu = wx.Menu()
        logID = wx.NewId()
        linID = wx.NewId()
        yscalemenu.AppendRadioItem(logID, "log")
        yscalemenu.AppendRadioItem(linID, "linear")
        menu.AppendMenu(-1, "y-scale", yscalemenu)
        if self.GetYScale() == 'log':
            yscalemenu.Check(logID, True)
        else:
            yscalemenu.Check(linID, True)

        def yscale_log(event):
            if self.ax:
                self.SetYScale('log')
                self.AutoScale()
                self.flush_plot()
        def yscale_lin(event):
            if self.ax:
                self.SetYScale('lin')
                self.AutoScale()
                self.flush_plot()
        self.Bind(wx.EVT_MENU, yscale_log, id = logID)
        self.Bind(wx.EVT_MENU, yscale_lin, id = linID)

        autoscaleID = wx.NewId()
        menu.AppendCheckItem(autoscaleID, "Autoscale")
        menu.Check(autoscaleID, self.GetAutoScale())
        def OnAutoScale(event):
            self.SetAutoScale(not self.GetAutoScale())
        self.Bind(wx.EVT_MENU, OnAutoScale, id = autoscaleID)

        # Time to show the menu
        self.PopupMenu(menu)

        menu.Destroy()

    def flush_plot(self):
        #self._SetSize()
        #self.canvas.gui_repaint(drawDC = wx.PaintDC(self))
        #self.ax.set_yscale(self.scale)
        self.canvas.draw()

    def update(self, data):
        pass