Exemplo n.º 1
0
class BoxPlotPanel(FigureCanvasWxAgg):
    def __init__(self, parent, points, **kwargs):
        '''
        points -- a dictionary mapping x axis values to lists of values to plot
        '''
        self.figure = Figure()
        FigureCanvasWxAgg.__init__(self, parent, -1, self.figure, **kwargs)
        self.canvas = self.figure.canvas
        self.SetMinSize((100,100))
        self.figure.set_facecolor((1,1,1))
        self.figure.set_edgecolor((1,1,1))
        self.canvas.SetBackgroundColour('white')
        
        self.navtoolbar = None
        self.setpoints(points)
        
    def setpoints(self, points):
        '''
        Updates the data to be plotted and redraws the plot.
        points - list of array samples, where each sample will be plotted as a 
                 separate box plot against the same y axis
        '''
        self.xlabels = []
        self.points = []
        ignored = 0
        for label, values in sorted(points.items()):
            if type(label) in [tuple, list]:
                self.xlabels += [','.join([str(l) for l in label])]
            else:
                self.xlabels += [label]
            self.points += [np.array(values).astype('f')[~ np.isnan(values)]]
            ignored += len(np.array(values)[np.isnan(values)])
        
        if not hasattr(self, 'subplot'):
            self.subplot = self.figure.add_subplot(111)
        self.subplot.clear()
        # nothing to plot?
        if len(self.points)==0:
            logging.warn('No data to plot.')
            return
        self.subplot.boxplot(self.points, sym='k.')
        if len(self.points) > 1:
            self.figure.autofmt_xdate()
        self.subplot.set_xticklabels(self.xlabels)
        self.reset_toolbar()
        if ignored == 0:
            logging.info('Boxplot: Plotted %s points.'%(sum(map(len, self.points))))
        else:
            logging.warn('Boxplot: Plotted %s points. Ignored %s NaNs.'
                          %(sum(map(len, self.points)), ignored))
        
    def set_x_axis_label(self, label):
        self.subplot.set_xlabel(label)
    
    def set_y_axis_label(self, label):
        self.subplot.set_ylabel(label)
    
    def get_point_lists(self):
        return self.points
    
    def get_xlabels(self):
        return self.xlabels
    
    def get_toolbar(self):
        if not self.navtoolbar:
            self.navtoolbar = NavigationToolbar(self.canvas)
            self.navtoolbar.DeleteToolByPos(6)
        return self.navtoolbar

    def reset_toolbar(self):
        # Cheat since there is no way reset
        if self.navtoolbar:
            self.navtoolbar._nav_stack.clear()
            self.navtoolbar.push_current()
Exemplo n.º 2
0
class SuperPosition(wx.Frame):
    """main user interface for super position"""
  
    def __init__(self, parent=None, files=[],*args, **kwargs):
        wx.Frame.__init__(self, parent, -1, size = (800, 600))
        
        self.files = files
        self.Options = GraphOptions(self,extended=False)
        self.createMenu()
        self.setWindow()
        self.createPanel()
        self.createList()
        self.draw_figure()
        
    def createMenu(self):
        """create menu bar"""
        
        self.menubar = wx.MenuBar()  
        self.fileMenu = wx.Menu()
        self.plotMenu = wx.Menu(
                                )
        qms = self.fileMenu.Append(wx.ID_ANY, '&Save Plot')
        qec = self.fileMenu.Append(wx.ID_ANY, '&Save Data')
        self.Bind(wx.EVT_MENU, self.OnSaveData, qec)
        
        self.fileMenu.AppendSeparator()
        
        subtract = self.plotMenu.Append(100, "Subtract Plots")
        self.Bind(wx.EVT_MENU, self.OnSubtract, subtract)
        mean = self.plotMenu.Append(wx.ID_ANY, "Average Plots")
        self.Bind(wx.EVT_MENU, self.OnMean, mean)
        self.plotMenu.AppendSeparator()
        
        self.showLegend = self.plotMenu.Append(wx.ID_ANY,"Show &Legend",kind=wx.ITEM_CHECK)
        self.Bind(wx.EVT_MENU, self.OnUpdatePlot, self.showLegend)
        self.showLegend.Check(True)
        
        pltoptions = self.plotMenu.Append(wx.ID_ANY, "&Plot Options")
        self.Bind(wx.EVT_MENU,self.OnPlotOptions, pltoptions)
        
        qme = self.fileMenu.Append(wx.ID_EXIT, '&Quit')
        self.Bind(wx.EVT_MENU, self.OnQuit, qme)
        self.Bind(wx.EVT_MENU,self.OnSavePlot,qms)
        
        self.menubar.Append(self.fileMenu, '&File')
        self.menubar.Append(self.plotMenu, '&Plot')
        self.SetMenuBar(self.menubar) 
        
    def setWindow(self):
        """create main panel"""
    
        self.SetTitle("SMP Superposition Viewer")
        self.SetMinSize((600,400))
        self.Centre()
        self.Maximize()
        self.Show()
        
    def createPanel(self):
        
        self.panelPlot = wx.Panel(self)
        self.panelPlot.SetFocus()
        
        self.list = ulc.UltimateListCtrl(self.panelPlot, agwStyle=wx.LC_REPORT|wx.LC_VRULES|wx.LC_HRULES|wx.LC_SINGLE_SEL|ulc.ULC_HAS_VARIABLE_ROW_HEIGHT)
        
        self.dpi = 100
        self.fig = Figure((5.0, 4.0), dpi=self.dpi)
        self.canvas = FigCanvas(self.panelPlot, -1, self.fig)
        self.axes = self.fig.add_subplot(111)     
               
        self.plot_toolbar = NavigationToolbar(self.canvas)
        self.plot_toolbar.DeleteToolByPos(8) #delete save, subplot and spacer from tool bar
        self.plot_toolbar.DeleteToolByPos(7)
        self.plot_toolbar.DeleteToolByPos(6)
        
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(self.canvas, 10, wx.LEFT | wx.TOP | wx.GROW)
        vbox.Add(self.plot_toolbar, 0, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
        vbox.Add(self.list,3, wx.LEFT | wx.TOP | wx.GROW)
        
        self.panelPlot.SetSizer(vbox)
        vbox.Fit(self)
 
    def createList(self):
        """List Elements"""
               
        #colums
        self.list.InsertColumn(0,"File Name")
        self.list.InsertColumn(1,"active")
        self.list.InsertColumn(2,"Offset x [mm]")
        self.list.InsertColumn(3,"Offset y [N]")
        self.list.InsertColumn(4, "x Stretch Factor")
        self.list.InsertColumn(5,"Smooth")
        self.list.InsertColumn(6,"Color")
        self.list.InsertColumn(7,"Style")
        self.list.InsertColumn(8,"Width")
        
        self.list.SetColumnWidth(0,500)
        self.list.SetColumnWidth(1,-2)
        self.list.SetColumnWidth(2,150)
        self.list.SetColumnWidth(3,150)
        self.list.SetColumnWidth(5,150)
        
        #entries
        for item in self.files:
            self.addItem(item)
    
    def addItem(self,item):
        colors=["blue","black","green","red","yellow","orange","pink","purple","brown",
                "gray","darkblue","silver","darkgreen","darkred","gold"]
        styles=["-","-.",":","steps","--","_"]
        #create elements
        i = self.list.GetItemCount()
        index = self.list.InsertStringItem(i, item.filename)
        box = wx.CheckBox(self.list)
        box.SetValue(True)
        dx  = FloatSpin(self.list,-1,value=- item.surface,min_val=-500.000,max_val=500.000,increment=1,digits=2)
        dy  = FloatSpin(self.list,-1,value=0.000,min_val=-50.00,max_val=50.00,increment=0.01,digits=2)
        stretch = FloatSpin(self.list,-1,value=1,min_val=0.5,max_val=1.5,increment=0.001,digits=3)
        smooth = wx.SpinCtrl(self.list,-1,min=0,max=2000,initial=200)
        color = wx.ComboBox(self.list, -1, choices=colors, style=wx.CB_READONLY,value=colors[i%len(colors)])
        style = wx.ComboBox(self.list, -1, choices=styles, style=wx.CB_READONLY,value="-")
        width = wx.SpinCtrl(self.list, -1,name="Width",initial=1,min=1,max=10)
        
        #append elements to files properties
        item.index = index
        item.box = box
        item.dx = dx
        item.dy = dy
        item.stretch = stretch
        item.smooth = smooth
        item.color = color
        item.style = style
        item.width = width
        
        #append elements to list
        self.list.SetItemWindow(index,1,item.box,expand=True)
        self.list.SetItemWindow(index,2,item.dx,expand=True)
        self.list.SetItemWindow(index,3,item.dy,expand=True)
        self.list.SetItemWindow(index,4,item.stretch,expand=True)
        self.list.SetItemWindow(index,5,item.smooth,expand=True)
        self.list.SetItemWindow(index,6,item.color,expand=True)
        self.list.SetItemWindow(index,7,item.style,expand=True)
        self.list.SetItemWindow(index,8,item.width,expand=True)
        
        #set events to update plot
        self.Bind(wx.EVT_CHECKBOX, self.OnUpdatePlot, item.box)
        self.Bind(wx.EVT_SPINCTRL, self.OnUpdatePlot, item.dx)
        self.Bind(wx.EVT_SPINCTRL, self.OnUpdatePlot, item.dy)
        self.Bind(wx.EVT_SPINCTRL, self.OnUpdatePlot, item.stretch)
        self.Bind(wx.EVT_SPINCTRL, self.OnUpdatePlot, item.smooth)
        self.Bind(wx.EVT_COMBOBOX, self.OnUpdatePlot, item.color)
        self.Bind(wx.EVT_COMBOBOX, self.OnUpdatePlot, item.style)
        self.Bind(wx.EVT_SPINCTRL, self.OnUpdatePlot, item.width)
                
    def draw_figure(self,autozoom=False):
        """draw active files"""
        
        self.setPlotOptions(autozoom) 
        active = 0
        for i in range(len(self.files)):
            current = self.files[i]
            if current.box.GetValue():
                    active += 1
                    x,y = self.adaptData(current)
                    self.axes.plot(x, y,
                                   color = current.color.GetValue(),
                                   linestyle = current.style.GetValue(),
                                   linewidth = current.width.GetValue(),
                                   label = basename(current.filename)
                                   )                       
           
        
        self.canvas.draw()
        
        self.plotMenu.Enable(100,active >= 2)
        
    def setPlotOptions(self, autozoom=False):  
    
        if autozoom:
            xlim = self.axes.get_xlim()
            ylim = self.axes.get_ylim()
            self.axes.clear()
            self.axes.set_xlim(xlim)
            self.axes.set_ylim(ylim)
        else:
            self.axes.clear()
            if not self.Options.auto_x:
                self.axes.set_xlim(self.Options.xlim[0],self.Options.xlim[1]) 
        
            if not self.Options.auto_y:
                self.axes.set_ylim(self.Options.ylim[0],self.Options.ylim[1]) 
        
        if not self.Options.auto_yticks:
            self.axes.yaxis.set_major_locator(MaxNLocator(self.Options.yticks))
        if not self.Options.auto_xticks:
            self.axes.xaxis.set_major_locator(MaxNLocator(self.Options.xticks))

        self.axes.grid(True)
        
        self.axes.tick_params(labeltop=self.Options.mirrorx,labelright=self.Options.mirrory)
        
        self.axes.set_xlabel(self.Options.xlabel)  
        self.axes.set_ylabel(self.Options.ylabel)

        self.axes.set_title("SMP Super Position Viewer") 
        
        if self.showLegend.IsChecked():
            print "show legend"
            self.axes.legend(loc = "upper left")
        
    def OnUpdatePlot(self,e):      
        self.draw_figure(True)
        
    def OnAddItem(self,e):
        files = openFile()
        if files != None:
            for entry in files:
                item = smp.Pnt(entry)
                self.addItem(item)
        self.drawPlot()
        
    def OnSavePlot(self,e):
        """Save Plot Event"""
        
        file_choices = "PNG (*.png)|*.PNG"
        filename = "_SuperPos.png"
        
        dlg = wx.FileDialog(
            self, 
            message = "Save Plot as...",
            defaultDir = os.getcwd(),
            defaultFile = filename,
            wildcard = file_choices,
            style = wx.SAVE|wx.OVERWRITE_PROMPT)
        
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            self.canvas.print_figure(path, dpi=self.dpi)
            
        dlg.Destroy()      
    
    def OnSaveData(self,e):
        wx.MessageBox('Not implemented yet', 'Info', 
                            wx.OK | wx.ICON_INFORMATION)
        lines = self.axes.lines
        """
        data = []
        for line in lines:
            data.append(line.get_data())
        
        np.savetxt(fname = "/home/grimm/Desktop/test.txt", 
                   X = np.array(data),
                   fmt = '%.18e',
                   delimiter = '\t',
                   newline = '\n',
                   header = '# Automatic written file from SMP SUper Position Viewer',
                   comments='# ')
    
        """
    
    def OnPlotOptions(self,e):
        self.Options.Show()
            
    def OnSubtract(self,e):
        choices = []
        files = []
        for entry in self.files:
            if entry.box.GetValue():
                choices.append(os.path.basename(entry.filename))
                files.append(entry)
                
        dlg = wx.SingleChoiceDialog(parent = self,
                                    message = "select reference",
                                    caption = "Subtract Plots",
                                    choices = choices,
                                    )
        
        if dlg.ShowModal() == wx.ID_OK:
            ref = files[dlg.GetSelection()]
            files.pop(dlg.GetSelection())
            xref, yref = self.adaptData(ref)
            fref = interp1d(xref,yref)
            xref_min = np.min(xref)
            xref_max = np.max(xref)
            
            for entry in files:
                xsub, ysub = self.adaptData(entry)
                fsub = interp1d(xsub,ysub)
                xsub_min = np.min(xsub)
                xsub_max = np.max(xsub)
                
                if xsub_min >= xref_min: xmin = xsub_min
                else:                    xmin = xref_min
                if xsub_max >= xref_max: xmax = xref_max
                else:                    xmax = xsub_max                              
                
                x_new = np.arange(xmin,xmax,0.1)
                f_ref = fref(x_new)
                f_sub = fsub(x_new)
                y_new =  f_ref - f_sub
                
                rsme = calc.rsme(f_ref, f_sub)
                                              
                self.axes.plot(x_new, y_new,
                               linestyle = "--",
                               color = entry.color.GetValue(),
                               label = basename(entry.filename) + " - " + basename(ref.filename) + ", rsme = %0.3g" %rsme)
                              
        self.axes.legend(loc = "upper left")
        self.axes.autoscale(False)
        self.canvas.draw()
        dlg.Destroy()
        
    def OnMean(self,e):
            #get prepared data
            data = []
            for entry in self.files:
                if entry.box.GetValue():
                    data.append(self.adaptData(entry))
                    
            
            #find common range
            xmins = []
            xmaxs = []               
            for entry in data:
                xmins.append(entry[0][0])
                xmaxs.append(entry[0][-1])
                
            xmin = np.amax(xmins)
            xmax = np.amin(xmaxs)
            x_new = np.arange(xmin,xmax,0.004)
            y_new = []
            #interpolate data to get same number of data points
            for entry in data:
                fint = interp1d(entry[0],entry[1])
                y_new.append(fint(x_new)) 
            y_new = np.transpose(np.array(y_new))
            y_mean = np.mean(y_new,1)        
            
            #plot average
            self.setPlotOptions()
            
            self.axes.plot(x_new, y_mean,
                               linestyle = "-",
                               color = "r",
                               label = "mean")
                              
            self.canvas.draw()
  
    def adaptData(self, pnt):
        x_corrected = (calc.downsample(pnt.data[:,0],pnt.smooth.GetValue()) + pnt.dx.GetValue()) * pnt.stretch.GetValue()
        y_corrected = calc.downsample(pnt.data[:,1],pnt.smooth.GetValue()) + pnt.dy.GetValue()
        return x_corrected,y_corrected
    
    def OnQuit(self,e):
        self.Destroy()