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
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