コード例 #1
0
ファイル: plot.py プロジェクト: BackupTheBerlios/pulsar-svn
class PlotFigure(wx.Window):
#============================================================================
    def __init__(self,parent,size=wx.DefaultSize, filename=None, options=None):

        wx.Window.__init__( self, parent, id=-1, style=wx.NO_BORDER)
        self.fig = Figure((21,21),60)
        self.canvas = FigureCanvas(self, -1, self.fig)
        self.toolbar = Toolbar(self.canvas)
        self.choice=PlotChoice(self)
        self.choice.mode="Standard"
        self.toolbar.Realize()
        self.parent=parent
        # On Windows, default frame size behaviour is incorrect
        # you don't need this under Linux
        tw, th = self.toolbar.GetSizeTuple()
        fw, fh = self.canvas.GetSizeTuple()
        self.toolbar.SetSize(wx.Size(fw, th))
        
        # Create a figure manager to manage things
        self.figmgr = FigureManager(self.canvas, 1, self)
        self.Fit()

        self.filename=filename
        if DEBUG :
            DEBUG_MSG("plot :"+filename)
        self.n=0
        self.ni=0
        self.vl=0
        self.vl1=0
        self.sw=0
        self.sw1=0
        self.flag_sum=False
        
        try:          
            [dirname,shortfilename]=os.path.split(filename)
            [basename,extension]=os.path.splitext(shortfilename)

            self.title=basename
            self.filename=dirname+"\\"+basename+".spe"            

            if not options:
                self.options={'units': 'ppm',
                              'titles': 'no',
                              'yoffset': '0.001',
                              'yaxis': 'yes'}
            self.grid=False
        except:
            pass

    def GetToolBar(self):
        # You will need to override GetToolBar if you are using an 
        # unmanaged toolbar in your frame
         
        return self.toolbar
    
    def read_spectra(self):
        #frequency=(i+1)*sw/n-sw/2.
        #ppm=frequency*1.e6/abs(vl)
        DEBUG_MSG("read_spectra : "+self.filename)
        
        try: #Handling filename error (Correction of a bug for NEw in file menu)
            f=open(self.filename,"rb")
        except:
            return False
        
        try: # Handling opening erros
            #first the header
            line=f.readline()    # PULSAR string
            DEBUG_MSG(rtn(line))
            line=f.readline()    # NP string
            DEBUG_MSG(rtn(line))
            items=line.split('=')
            n=int(items[1])     
            line=f.readline()    # SW string
            DEBUG_MSG(rtn(line))
            items=line.split('=')
            sw=float(items[1])
            line=f.readline()    # VL
            DEBUG_MSG(rtn(line))
            items=line.split('=')
            vl=float(items[1])
            line=f.readline()    # NI or LB string?
            DEBUG_MSG(rtn(line))
            items=line.split('=')
            ni=1 #by default
            if string.strip(items[0])=="NI":     
                ni=int(items[1])
                line=f.readline()    #SW1
                DEBUG_MSG(rtn(line))
                items=line.split('=')
                sw1=float(items[1])
                line=f.readline()    #VL1
                DEBUG_MSG(rtn(line))
                items=line.split('=')
                vl1=float(items[1])
                line=f.readline()    #SUM
                DEBUG_MSG(rtn(line))
                items=line.split('=')
                flag_sum=eval(string.upper(items[1]))
                line=f.readline()    # LB string
                DEBUG_MSG(rtn(line))
                items=line.split('=')     
            #now we have to read LB
            self.lb=[]
            self.lb.append(float(items[1]))
            #and GB
            line=f.readline()
            DEBUG_MSG(rtn(line))
            items=line.split('=')
            self.gb=[]
            self.gb.append(float(items[1]))
            #and CONCENTRATION
            line=f.readline() 
            DEBUG_MSG(rtn(line))
            items=line.split('=')
            self.concentration=[]
            self.concentration.append(float(items[1]))
            if ni>1:
                for j in range(ni-1):
                    line=f.readline() #LB
                    DEBUG_MSG(rtn(line))
                    items=line.split('=')
                    self.lb.append(float(items[1]))
                    line=f.readline() #GB
                    DEBUG_MSG(rtn(line))
                    items=line.split('=')
                    self.gb.append(float(items[1]))
                    line=f.readline() #concentration
                    DEBUG_MSG(rtn(line))
                    items=line.split('=')
                    self.concentration.append(float(items[1])) 

            self.ydata = []
            self.spec = []
            
            line=f.readline() # read TYPE
            DEBUG_MSG(rtn(line))

            line=f.readline()  # read YDATA or XDATA
            DEBUG_MSG(rtn(line))

        except: # There was an error
            WRITE_STRING("***ERROR***: Badly formatted header")
            f.close()
            return false

        if string.find(line,"YDATA")>-1: # check if there is a YDATA directive
            try:     
                self.label=string.join(string.split(line)[1:],' ')
                print self.label
                print ni
                for j in range(ni):
                    line=f.readline()
                    if not isinstance(line,str):
                        self.ydata.append(float(line))
                    else:
                        self.ydata.append(line)
            except:
                WRITE_ERROR("bad YDATA labels")
                f.close()
                return false

            line=f.readline()
            DEBUG_MSG(rtn(line)) # read XDATA

        try:
            for j in range(ni):
                DEBUG_MSG("\treading spectrum"+str(j+1))
                xy = []
                DEBUG_MSG("n %13i"%n)
                for i in range(n):
                    line=f.readline()
                    items=line.split(' ')
                    x=float(items[0])
                    y=float(items[1])
                    xy.append(complex(x,y)*self.concentration[j])
                DEBUG_MSG("end reading "+str(j+1))
                self.spec.append(array(xy))

            line=f.readline()       
            DEBUG_MSG(rtn(line))
            if string.find(line,"END")>-1:
                DEBUG_MSG("reading file success!")
        except:
            WRITE_STRING("***ERROR***: problem when reading X,Y data in the *.spe file!")
            f.close()
            return false
            
        self.frequency, self.ppm = [], []
        for i in range(n):
            self.frequency.append((i+1)*sw/n-sw/2.)
            self.ppm.append(((i+1)*sw/n-sw/2.)*1.e6/abs(vl))

        #save some data as class properties
        self.n=n
        self.ni=ni
        self.vl=vl
        self.sw=sw
        if ni > 1:
            self.vl1=vl1
            self.sw1=sw1
            self.flag_sum=flag_sum
            
        #perform the fft and broadening
        addlb(ni, self.spec, self.sw, self.lb, self.gb, self.concentration)

        #sum of the spectra
        if self.flag_sum:
            p=[]
            for i in range (n):
                sum=complex(0.,0.)
                for j in range(ni):
                    sum=sum+self.spec[j][i]
                p.append(sum)      
            self.spec.append(array(p))
            self.ni=ni+1    
        return True
    
    #------------------------------------------------    
    def plot_data(self,mode=None, offset=None):
    #------------------------------------------------
        """ PLOT_SPECTRA:
        Plot one or more 1D spectra on the same figure
        """

        if not mode or mode=='reset':
            try:
                if not self.read_spectra(): return False
            except:
                return False
            
            self.maxi=0
            for j in range(self.ni):
                mxi=max(map(abs,self.spec[j]))
                self.maxi=max(mxi,self.maxi)
                self.offset=0
                
            if self.ni<6:
                mode='standard'
            else:
                mode='popt'

        else:
            mode= string.lower(mode)

##        if mode == 'reset' :
##            try:
##                if not self.read_spectra(): return False
##            except:
##                return False
##                
##            self.maxi=0
##            for j in range(self.ni):
##                mxi=max(map(abs,self.spec[j]))
##                self.maxi=max(mxi,self.maxi)
##            self.offset=0

        mx=self.ni+1
        self.dlg = wx.ProgressDialog("Spectrum plotting",
                       "...wait...",
                       maximum = mx+1,
                       parent=self,
                        # style = wx.PD_CAN_ABORT
                        #| wx.PD_APP_MODAL
                        #| wx.PD_ELAPSED_TIME
                        #| wx.PD_ESTIMATED_TIME
                        #| wx.PD_REMAINING_TIME
                           )

        keepGoing = True
        count = 0
        self.fig.clear()
        self.plotdata = self.fig.add_subplot(111)
        if offset :
            self.offset=offset
        else:
            self.offset=0

        #------------------
        if mode == "popt":

            if self.ni == 1:
                mode=="standard"
            else:
                self.fig.clear()
                self.plotdat=None
                self.plotdata = self.fig.add_subplot(111)
                xticks=[]
                xtickslabel=[]
                spacing=10*(round(log10(self.ni))-1)
                DEBUG_MSG("%5i %5i"%(self.ni, spacing))
                if spacing<2: spacing=2
                for i in range(self.ni):
                    X=[float(self.n-j-1+i*self.n)/self.n for j in range(self.n)]
                    if self.ydata:
                        if i%spacing==0:
                            xticks.append(float(self.n/2+i*self.n)/self.n)
                            if not isinstance(self.ydata[i],str):
                                xtickslabel.append(string.strip(str('%10.3f'%float(self.ydata[i]))))
                            else:
                                xtickslabel.append(string.strip(str('%s'%self.ydata[i])))
                            
                    Y=[k.real for k in self.spec[i]]
                    self.plotdata.plot(X, array(Y))
                    count += 1
                    keepGoing = self.dlg.Update(count)

                self.plotdata.set_xlabel('Index')   
                if self.ydata:
                    self.plotdata.set_xticks(xticks)   
                    self.plotdata.set_xticklabels(xtickslabel)
                    self.plotdata.set_xlabel(self.label)
                    
                self.plotdata.set_ylabel('Intensity (a.u.)\n\n')                   
                self.plotdata.set_title("POPT display, "+self.title)
                self.plotdata.grid(self.grid)
            
        #------------------
        if mode == "popt 2d":
            if self.ni == 1:
                mode=="standard"
            else:                
                self.fig.clear()
                self.plotdata = self.fig.add_subplot(111)

                count += 1
                keepGoing = self.dlg.Update(count)

                X=[]
                Y=[]
                Z=[]
                X=self.ppm
                Y=range(self.ni)
                yticks=[]
                ytickslabel=[]
                spacing=10*(round(log10(self.ni))-1)
                if spacing<2: spacing=2
                maxi=0.
                mini=0.
                for i in range(self.ni):
                    Zt=[k.real for k in self.spec[i]]
                    mxi=max(map(abs,Zt))
                    mni=min(map(abs,Zt))
                    maxi=max(maxi,mxi)
                    mini=min(mini,mni)
                    Z.append(array(Zt))
                    if self.ydata:
                        if i%spacing==0:
                            yticks.append(i)
                            ytickslabel.append(string.strip(str('%10.3f'%self.ydata[i])))
                amp=(maxi-mini)
                levels=arange(mini-amp*.05,maxi+amp*.05,amp/self.ni)
                print mini,maxi
                cmap=pylab.cm.get_cmap('jet', len(levels)-1)
                
                cset = self.plotdata.contourf(X, Y, Z, levels, cmap=cmap,)

                #cset2 = self.plotdata.contour(X, Y, Z, cset.levels,
                #        colors = 'k',
                #        hold='on')
                self.plotdata.set_xlim(self.ppm[len(self.ppm)-1],self.ppm[0])
                self.plotdata.set_xlabel('Chemical shift (ppm)')
                self.plotdata.set_ylabel('Index\n')
                if self.ydata:
                    self.plotdata.set_yticks(yticks)   
                    self.plotdata.set_yticklabels(ytickslabel)
                    self.plotdata.set_ylabel(self.label+'\n')

                self.plotdata.set_title("POPT 2D display, "+self.title)
    ##                clabels=[mini,0.,maxi]
    ##                self.fig.colorbar(cset,clabels=clabels)
    ##                #self.plotdata.grid(self.grid)


        if mode == 'reset' or mode=="standard" :
            #print string.lower(self.options['units'])
            if string.lower(self.options['units'])=="hz":
                for i in range(self.ni):
                    spec=[]
                    shift=(i+1)*self.offset*self.maxi           
                    spec=[shift + x.real for x in self.spec[i]]
                    self.plotdata.plot(self.frequency, array(spec))
                    count += 1
                    keepGoing = self.dlg.Update(count)
                self.plotdata.set_xlim(self.frequency[len(self.frequency)-1],self.frequency[0])
                self.plotdata.set_xlabel('Frequency (Hz)')
            else:
                for i in range(self.ni):
                    shift=(i+1)*self.offset*self.maxi           
                    spec=[shift + x.real for x in self.spec[i]]
                    self.plotdata.plot(self.ppm, array(spec))
                    count += 1
                    keepGoing = self.dlg.Update(count)
                self.plotdata.set_xlim(self.ppm[len(self.ppm)-1],self.ppm[0])
                self.plotdata.set_xlabel('Chemical shift (ppm)')
            if string.lower(self.options['yaxis'])!="no": 
                self.plotdata.set_ylabel('Intensity (a.u.)\n')
            else:    
                self.plotdata.set_yticks([])   
                self.plotdata.set_yticklabels([])         
            self.plotdata.set_title(self.title)
            self.plotdata.grid(self.grid)

       #update everything and exit
        self.canvas.draw()
        self.toolbar.update()

        self.dlg.Destroy()
        return True
コード例 #2
0
class Plot(wx.Frame):
    def __init__(self, parent, id=-1, dpi=None, **kwargs):
        # begin wxGlade: MyFrame.__init__
        kwargs["style"] = wx.DEFAULT_FRAME_STYLE
        kwargs["size"] = (600, 600)
        wx.Frame.__init__(self, parent, id=id, **kwargs)
        # create figure

        self.figure = mpl.figure.Figure(dpi=dpi, figsize=(2, 2))
        self.canvas = Canvas(self, -1, self.figure)

        #self.toolbar = Toolbar(self.canvas)
        #self.toolbar.Realize()
        self.add_toolbar()
        #self.axes = self.figure.gca()
        self.PNL_AXES = wx.Panel(parent=self)
        # additional controls
        xAxisDataLabel = wx.StaticText(parent=self.PNL_AXES, label='X data:')
        yAxisDataLabel = wx.StaticText(parent=self.PNL_AXES, label='Y data:')
        self.xAxisData = wx.Choice(self.PNL_AXES)
        self.yAxisData = wx.Choice(self.PNL_AXES)
        self.xAxisScale = wx.Choice(self.PNL_AXES)
        self.xAxisScale.AppendItems(["linear scale", "log10 scale"])
        self.xAxisScale.Select(0)
        self.yAxisScale = wx.Choice(self.PNL_AXES)
        self.yAxisScale.AppendItems(["linear scale", "log10 scale"])
        self.yAxisScale.Select(0)

        axesPanelSizer = wx.FlexGridSizer(rows=0, cols=3, vgap=0, hgap=0)
        axesPanelSizer.Add(xAxisDataLabel, 0, wx.LEFT)
        axesPanelSizer.Add(self.xAxisData, 0, wx.LEFT)
        axesPanelSizer.Add(self.xAxisScale, 0, wx.LEFT)
        axesPanelSizer.Add(yAxisDataLabel, 0, wx.LEFT)
        axesPanelSizer.Add(self.yAxisData, 0, wx.LEFT)
        axesPanelSizer.Add(self.yAxisScale, 0, wx.LEFT)

        self.PNL_AXES.SetSizer(axesPanelSizer)
        self.PNL_AXES.SetAutoLayout(True)
        axesPanelSizer.Fit(self.PNL_AXES)
        axesPanelSizer.SetSizeHints(self.PNL_AXES)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.EXPAND)
        sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
        sizer.Add(self.PNL_AXES, 0, wx.LEFT | wx.EXPAND)
        self.SetSizer(sizer)

        self.Layout()

        #self.__set_properties()
        # couple the EVENTS
        # self.Bind(wx.EVT_CHECKBOX, self.stop, self.check_run)
        self.Bind(event=wx.EVT_CLOSE, handler=self.OnClose)
        self.Bind(event=wx.EVT_CHOICE,
                  handler=self.OnSetXlabel,
                  source=self.xAxisData)
        self.Bind(event=wx.EVT_CHOICE,
                  handler=self.OnSetYlabel,
                  source=self.yAxisData)
        self.Bind(event=wx.EVT_CHOICE,
                  handler=self.OnSetXScale,
                  source=self.xAxisScale)
        self.Bind(event=wx.EVT_CHOICE,
                  handler=self.OnSetYScale,
                  source=self.yAxisScale)

        self.acquizitionRunning = True
        # create queue instance for the plot handling:
        self.plottingThread = Queue.Queue(1)
        # create redrawing deamon who will eat the queue
        self.backgndDraw = threading.Thread(target=self._redrawPlot)
        self.backgndDraw.setDaemon(True)
        self.backgndDraw.start()

        self.getPoints = threading.Thread(target=self._checkData)
        self.getPoints.setDaemon(True)
        return

    def add_toolbar(self):
        self.toolbar = Toolbar(self.canvas)
        self.toolbar.Realize()
        if wx.Platform == '__WXMAC__':
            # Mac platform (OSX 10.3, MacPython) does not seem to cope with
            # having a toolbar in a sizer. This work-around gets the buttons
            # back, but at the expense of having the toolbar at the top
            self.SetToolBar(self.toolbar)
        else:
            # On Windows platform, default window size is incorrect, so set
            # toolbar width to figure width.
            tw, th = self.toolbar.GetSizeTuple()
            fw, fh = self.canvas.GetSizeTuple()
            # By adding toolbar in sizer, we are able to put it at the bottom
            # of the frame - so appearance is closer to GTK version.
            # As noted above, doesn't work for Mac.
            self.toolbar.SetSize(wx.Size(fw, th))
            #self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
            # update the axes menu on the toolbar
            self.toolbar.update()

    def set_my_title(self, title):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle(title)
        axes = self.figure.gca()
        axes.set_title(title, visible=True)
        # end wxGlade
    def bind_data(self, datastore):
        self.datagram = datastore.get_datagram()
        self.graphTitle = datastore.dataFileName[-50:]
        self.set_my_title(self.graphTitle)
        self.lastDataRow = 0
        self.xAxisData.Clear()
        self.xAxisData.AppendItems(self.datagram.extract_header())
        self.xAxisData.Select(0)
        self.xIndex = self.xAxisData.GetStringSelection()
        self.yAxisData.Clear()
        self.yAxisData.AppendItems(self.datagram.extract_header())
        self.yAxisData.Select(0)
        self.yIndex = self.yAxisData.GetStringSelection()
        #self.timer.start()
        # update the axis label
        axes = self.figure.gca()
        axes.set_ylabel(self.yIndex, visible=True)
        axes.set_xlabel(self.xIndex, visible=True)

    def start_acquizition(self):
        self.acquizitionRunning = True
        self.getPoints.start()

    def _checkData(self):
        """
        periodically check for new data acquired
        """
        while self.acquizitionRunning:
            currentRow = self.datagram.get_current_data_row()
            if currentRow > self.lastDataRow:
                xFrom = 0
                xTo = currentRow
                try:
                    self.plottingThread.put(item=(xFrom, xTo),
                                            block=False,
                                            timeout=0)
                except:
                    pass
            time.sleep(0.1)

    def reloadData(self, xFrom=0, xTo=None):
        # which axes to plot in?
        axes = self.figure.gca()
        axes.clear()
        # get data:
        index = self.datagram.extract_data(key=self.xIndex,
                                           from_to=(xFrom, xTo))
        # check the scales:
        xScale = self.xAxisScale.GetStringSelection()
        if xScale == "log10 scale":
            index = log10(abs(index))
            axes.set_xlabel(('(log10(abs( %s ))' % self.xIndex), visible=True)
        if xScale == "linear scale":
            axes.set_xlabel(self.xIndex, visible=True)

        values = self.datagram.extract_data(key=self.yIndex,
                                            from_to=(xFrom, xTo))
        # check the scales:

        yScale = self.yAxisScale.GetStringSelection()
        if yScale == "log10 scale":
            values = log10(abs(values))
            axes.set_ylabel(('(log10(abs( %s ))' % self.yIndex), visible=True)
        if yScale == "linear scale":
            axes.set_ylabel(self.yIndex, visible=True)
        # plot and show the graph
        axes.set_title(self.graphTitle, visible=True)
        axes.scatter(
            index,
            values,
            s=10,
            c='r',
            marker='+',
        )
        axes.autoscale_view()
        self.canvas.draw()

    def _redrawPlot(self):
        while self.acquizitionRunning:
            (xFrom,
             xTo) = self.plottingThread.get(block=True)  # obtain data to plot
            self.reloadData(xFrom, xTo)

            #self.timer.start()
            time.sleep(0.1)

    def OnClose(self, event):
        self.Show(False)
        return

    def OnPaint(self, event):
        self.canvas.draw()
        return

    def OnSetXlabel(self, event):
        self.xIndex = event.GetString()
        # update the axis label
        #axes = self.figure.gca()
        #axes.set_xlabel(self.xIndex,visible=True)

        if not self.acquizitionRunning:
            self.reloadData()

        return

    def OnSetYlabel(self, event):
        self.yIndex = event.GetString()
        # update the axis label
        #axes = self.figure.gca()
        #axes.set_ylabel(self.yIndex,visible=True)
        if not self.acquizitionRunning:
            self.reloadData()

        return

    def OnSetXScale(self, event):
        scale = event.GetString()
        # update the axis label
        #axes = self.figure.gca()
        #axes.set_xlabel(self.xIndex,visible=True)

        if not self.acquizitionRunning:
            self.reloadData()

        return

    def OnSetYScale(self, event):
        scale = event.GetString()
        # update the axis label
        #axes = self.figure.gca()
        #axes.set_ylabel(self.yIndex,visible=True)
        if not self.acquizitionRunning:
            self.reloadData()

        return