def mouseSetEdges(self, event): """method used to capture mouse events from plot""" # capture click data and draw dot for user feedback if event.xdata == None: return dlog(str(event.xdata)) if (self.add == None): dlog('Error: BGSub has no subplot to draw to') return if self.leftedge == None: self.leftedge = event.xdata elif self.rightedge == None: if self.leftedge < event.xdata: self.rightedge = event.xdata else: self.rightedge = self.leftedge self.leftedge = event.xdata self.hullButton.config(state=NORMAL) self.peakButton.config(state=NORMAL) else: middle = (self.leftedge + self.rightedge) / 2 if event.xdata < middle: self.leftedge = event.xdata elif event.xdata > middle: self.rightedge = event.xdata self.add.cla() self.add.plot(self.chiplot.xdata, self.chiplot.ydata) self.add.plot([self.leftedge, self.leftedge], [self.chiplot.ymin, self.chiplot.ymax], color='r') if self.rightedge != None: self.add.plot([self.rightedge, self.rightedge], [self.chiplot.ymin, self.chiplot.ymax], color='r') self.canvas.draw()
def zoomup(self, event): """NOT USED method used to capture mouse events from plot""" # capture click data and draw dot for user feedback if event.xdata != None: self.zoomend = event.xdata if abs(self.zoomend - self.zoomstart) < self.zoommin: return if(self.add == None): dlog('Error: Centroid has no subplot to draw to') return # zoom in on the graph if(self.connect != None): self.canvas.mpl_disconnect(self.connect) self.connect = None self.canvas.mpl_disconnect(self.zoomdrag) self.zoomdrag = None self.canvas.mpl_disconnect(self.zoomstop) self.zoomstop = None # create a new chiplot to find the convex hull of if(self.zoomstart < self.zoomend): left = int(self.zoomstart) right = int(self.zoomend) else: left = int(self.zoomend) right = int(self.zoomstart) self.workingChiplot = Chiplot(self.chiplot.xdata[left:right], self.chiplot.ydata[left:right]) self.prompt.set(self.originalprompt) self.add.cla() self.zoomButton.config(state = NORMAL) self.analyzeButton.config(state = NORMAL) self.displayPlot()
def clear(self): dlog('in centroid.clear') self.add.cla() if self.dialogWindow != None: self.dialogWindow.destroy() self.dialogWindow = None if(self.connect != None): self.canvas.mpl_disconnect(self.connect) self.connect = None if(self.zoomdrag != None): self.canvas.mpl_disconnect(self.zoomdrag) self.zoomdrag = None if(self.zoomstop != None): self.canvas.mpl_disconnect(self.zoomstop) self.zoomstop = None if(self.keybaseline != None): self.canvas.mpl_disconnect(self.keybaseline) self.keybaseline = None # reset class specific variables self.zoomstart = None self.zoomend = None self.workingChiplot = self.chiplot self.leftedge = None self.rightedge = None self.baseline = None self.area = None self.cent = None self.analyzeButton.config(text = "Analyze Peak", command = self.analyze, state = NORMAL) self.zoomButton.config(state = NORMAL) self.displayPlot()
def mouseSetEdges(self, event): """method used to capture mouse events from plot""" # capture click data and draw dot for user feedback if event.xdata == None: return dlog(str(event.xdata)) if(self.add == None): dlog('Error: Centroid has no subplot to draw to') return if self.setFunc.get() == 'edges': if self.leftedge == None: self.leftedge = event.xdata elif self.rightedge == None: if self.leftedge < event.xdata: self.rightedge = event.xdata else: self.rightedge = self.leftedge self.leftedge = event.xdata self.analyzeButton.config(state = NORMAL) else: middle = (self.leftedge+self.rightedge)/2 if event.xdata < middle: self.leftedge = event.xdata elif event.xdata > middle: self.rightedge = event.xdata if self.setFunc.get() == 'baseline': self.baseline = event.ydata self.baselinevar.set(str(self.baseline)) self.add.cla() self.displayPlot()
def clear(self): dlog('in BackgroundSub.clear') self.add.cla() if self.dialogWindow != None: self.dialogWindow.destroy() self.dialogWindow = None if (self.connect != None): self.canvas.mpl_disconnect(self.connect) self.connect = None self.workingChiplot = None self.leftedge = None self.rightedge = None self.xhull = None self.yhull = None self.xsmooth = None self.ysmooth = None self.peaks = list() self.zoomed = 0 self.smoothButton.config(state=DISABLED) self.subtractButton.config(state=DISABLED) self.hullButton.config(text='ConvexHull', command=self.hull, state=DISABLED) self.peakButton.config(state=DISABLED) self.displayPlot()
def finishZoom(self, event): if(self.zoomend < self.zoomstart and self.zoomend != None): left = self.zoomend right = self.zoomstart else: left = self.zoomstart right = self.zoomend for i in range(0, len(self.chiplot.xdata)): if((self.chiplot.xdata[i] < left) and (self.chiplot.xdata[i+1] > left)): left = self.chiplot.xdata[i] if((self.chiplot.xdata[i] < right) and (self.chiplot.xdata[i+1] > right)): right = self.chiplot.xdata[i] dlog('left: '+str(left)+' self.zoomstart: '+str(self.zoomstart)) left = self.chiplot.xdata.index(left) right = self.chiplot.xdata.index(right) self.workingChiplot = Chiplot(self.chiplot.xdata[left:right], self.chiplot.ydata[left:right]) self.prompt.set(self.originalprompt) self.add.cla() self.zoomButton.config(state = NORMAL) self.analyzeButton.config(state = NORMAL) self.zoomClean(event) self.displayPlot()
def zoom(self): dlog('In zoom') if(self.connect != None): self.canvas.mpl_disconnect(self.connect) self.connect = self.canvas.mpl_connect('button_press_event', self.zoomdown) self.zoomButton.config(state = DISABLED) self.analyzeButton.config(state = DISABLED) self.prompt.set('Click the left and right boundaries of the area you would like to zoom in to')
def calcArea(self, x, y): dlog('in area') """Using Trapezoid rule for now to get a rough approximation of the size of the peak""" self.area = 0 for i in range(1, len(y)): h = float(x[i] - x[i-1]) self.area += (y[i]-self.baseline + y[i-1]-self.baseline)*h/2 dlog("Area of peak centered at "+str(self.cent)+" is "+str(self.area)+" units squared", 'l')
def zoomOut(self): dlog('zooming out') self.add.cla() self.add.plot(self.workingChiplot.xdata, self.workingChiplot.ydata) if (self.xsmooth != None): self.add.plot(self.xsmooth, self.ysmooth, color='g') if (self.xhull != None): self.add.plot(self.xhull, self.yhull, color='r') self.canvas.draw()
def sign(d): if d > 0: return 1 if d == 0: return 0 if d < 0: return -1 dlog('Error in determining sign') return None
def clean(self): dlog('reclaiming centroid object') for control in self.controls: control.destroy() del control if(self.connect != None): self.canvas.mpl_disconnect(self.connect) if self.dialogWindow != None: self.dialogWindow.destroy() del self.dialogWindow self.fig.clf()
def moveBaseline(self, event): dlog('moving baseline') key = event.key self.basemove = max(self.workingChiplot.ydata)/100 if (key == 'up'): self.baseline += self.basemove if (key=='down'): self.baseline -= self.basemove self.baselinevar.set(str(self.baseline)) self.add.cla() dlog('focus change') self.displayPlot()
def displayPlot(self): """creates a sub plot to display the chiplot and then links up the events""" dlog('in display plot of Background Subtract') if(self.add == None): self.add=self.fig.add_subplot(111) self.add.plot(self.workingChiplot.xdata, self.workingChiplot.ydata) if self.leftedge != None: self.add.plot([self.leftedge,self.leftedge], [self.workingChiplot.ymin, self.workingChiplot.ymax], color = 'r') if self.rightedge != None: self.add.plot([self.rightedge,self.rightedge], [self.workingChiplot.ymin, self.workingChiplot.ymax], color = 'r') if self.baseline != None: self.add.plot([self.workingChiplot.xmin,self.workingChiplot.xmax], [self.baseline, self.baseline], color = 'g') self.canvas.draw()
def pchipChiplot(x, y, chiplot): """Interpolates the set of given points with a spline function and returns the evaluation of this function at xpoints""" dlog('in pchip') # copy lists x = x[:] y = y[:] # Generate the Pchip from the convex hull pchipy = pchip(x, y, chiplot.xdata) dlog(str(len(chiplot.xdata))+','+str(len(pchipy)), 'd') return chiplot.xdata, pchipy
def displayPlot(self): """creates a sub plot to display the chiplot and then links up the events""" dlog('in display plot of Splitter') if (self.add == None): self.add = self.fig.add_subplot(111) self.add.plot(self.chiplot.xdata, self.chiplot.ydata) self.canvas.draw() if (self.connect == None): self.connect = self.canvas.mpl_connect('button_press_event', self.mouseDown) self.prompt.set( 'Set the number of peaks, then define peaks by clicking to the right and left of them\nThe chiplot will automagically split when enough peaks have been selected, or you can select split from the commands below' )
def calcPeaks(self): # sort the clicks, and then find the average of the reflections self.clicks.sort() dlog(('calculating peaks, reflections and center: ' + self.reflections.get() + ' ' + str(self.validcenter.get()))) numPeaks = int(self.reflections.get()) * 2 + int( self.validcenter.get()) if (len(self.clicks) < numPeaks * 2): numPeaks = int(len(self.clicks) / 2) dlog('num of peaks calculated: ' + str(numPeaks)) for i in range(0, numPeaks): lower = self.clicks[i * 2] upper = self.clicks[i * 2 + 1] self.peaks.append(self.findPeak(lower, upper))
def displayPlot(self): """creates a sub plot to display the chiplot and then links up the events""" dlog('in display plot of Background Subtract') if (self.add == None): self.add = self.fig.add_subplot(111) #will need change. self.add.plot(self.chiplot.xdata, self.chiplot.ydata) self.canvas.draw() if (self.connect == None): self.connect = self.canvas.mpl_connect('button_press_event', self.mouseSetEdges) self.prompt.set( 'Select the left and right edges of the chiplot to use in the convex hull program\nThen eliminate negative peaks using the command below or run the convex hull algorithm' )
def splitChiplot(self, error): # actually split the chiplot and write the halves to a file splitCenter = int(self.center) + 1 #rewrite lx data as to start from beginning going to center self.lxdata = list() dlog('self.center: ' + str(self.center)) i = 0 while (self.chiplot.xdata[i] < self.center): #Problem here - might work now holder = (self.center - self.chiplot.xdata[i]) self.lxdata.append(holder) i = i + 1 lydata = self.chiplot.ydata[:i] self.lxdata.reverse() lydata.reverse() #changing rx data yIndex = i while (i < len(self.chiplot.xdata)): self.rxdata.append(self.chiplot.xdata[i] - self.center) i = i + 1 dlog('leng of rxdata, rydata: ' + str(i) + ' ' + str(yIndex)) self.leftChi = Chiplot(self.lxdata, lydata, self.chiplot.filename + "l", self.chiplot.projection) self.rightChi = Chiplot(self.rxdata, self.chiplot.ydata[yIndex:], self.chiplot.filename + "r", self.chiplot.projection) directory, filename = os.path.split(self.chiplot.filename) window = Toplevel() window.title("Output split chiplots") Label( window, text= 'Chiplot split, verify the split by the green line, if it needs to be redone, select Redo below\nOtherwise output files to custom or standard filenames:\nLeft standard: ' + filename + 'l.xy' + '\nRight standard: ' + filename + 'r.xy').grid(row=0, columnspan=3) Label(window, text=error, fg='#f00').grid(row=1, columnspan=3) Button(window, text="Redo", command=self.clear).grid(row=2, column=0, sticky=W) Button(window, text="Standard", command=self.standardFiles).grid(row=2, column=1, sticky=E) Button(window, text="Custom", command=self.customFiles).grid(row=2, column=2, sticky=W) # Label(window, text = '\n').grid(row = 3, column = 3) window.lift() self.enableButtons() self.dialogWindow = window
def zoommove(self, event): """NOT USED method used to capture mouse events from plot""" # capture click data and draw dot for user feedback if event.xdata == None: return if(self.add == None): dlog('Error: Centroid has no subplot to draw to') return # set the start coords for the zooming regions self.zoomend = event.xdata self.add.cla() self.displayPlot() self.add.plot([self.zoomstart, self.zoomstart], [self.workingChiplot.ymin, self.workingChiplot.ymax], color = 'r') self.add.plot([self.zoomend, self.zoomend], [self.workingChiplot.ymin, self.workingChiplot.ymax], color = 'r') self.canvas.draw()
def standardFiles(self): self.dialogWindow.destroy() self.dialogWindow = None if self.workingChiplot.writeFile(False, '.bak') < 0: dlog( 'Unable to output background subtraction of chiplot: ' + self.chiplot.filename, 'l') self.dialogWindow = errorMessage( self.clear, self.ignoreError, 'Error outputing background subtracted chiplots', "Chiplot's background successfully taken out but unable to output file correctly", 'Unable to output subtracted chiplot: ' + self.chiplot.filename) else: dlog('Outputing background subtraction to ' + self.chiplot.filename + '.bak')
def pchip(x, y, u): # calculate the first derivative at each section # there will be len(x)-1 h = list() h0 = x[0] for h1 in x[1:]: h.append(h1-h0) h0 = h1 delta = list() for i in range(len(h)): delta.append((y[i+1]-y[i])/h[i]) d = list() d.append(pchipend(h[0], h[1], delta[0], delta[1])) for i in range(1,len(x)-1): d.append(pchipslopes(h[i-1], h[i], delta[i-1], delta[i])) d.append(pchipend(h[-1], h[-2], delta[-1], delta[-2])) # evaluate function pchipy = list() dlog('evaluating pchip') segmentlx = x[0] segmently = y[0] dlog(str(len(d))+','+str(len(delta))+','+str(len(h))) for i in range(len(delta)): dlog(str(i)) segmentrx = x[i+1] segmentry = y[i+1] leftindex = u.index(segmentlx) rightindex = u.index(segmentrx) dlog(str(d[i])+','+str(delta[i])+','+str(d[i+1])) c = (3*delta[i] - 2*d[i] - d[i+1])/h[i] b = (d[i] - 2*delta[i] + d[i+1])/(h[i]**2) dfloat = d[i] for j in u[leftindex:rightindex]: j = j - u[leftindex] dlog('j: '+str(j)) pchipy.append(segmently + j*(dfloat + j*(c + j*b))) segmentlx = segmentrx segmently = segmentry # append the last point pchipy.append(y[-1]) return pchipy
def mouseDown(self, event): """method used to capture mouse events from plot""" # capture click data and draw dot for user feedback if event.xdata == None: return self.clicks.append(event.xdata) log = 'click ' + str(event.xdata) + ":" + str(event.ydata) dlog(log, 'l') if (self.add == None): dlog('Error: Splitter has no subplot to draw to') return self.add.scatter([event.xdata], [event.ydata]) self.canvas.draw() neededClicks = int(self.reflections.get()) * 2 * 2 + int( self.validcenter.get()) * 2 if (len(self.clicks) == neededClicks): self.split()
def analyze(self): dlog('in analyze') if(self.connect != None): dlog('UNABLE TO SET ANALYZE!\n') return self.baseLineRadio.config(state = NORMAL) self.edgesRadio.config(state = NORMAL) self.linePrompt.config(state = NORMAL) self.connect = self.canvas.mpl_connect('button_press_event', self.mouseSetEdges) self.keybaseline = self.canvas.mpl_connect('key_press_event', self.moveBaseline) self.analyzeButton.config(text = 'Run Analyze', command = self.runAnalyze, state = DISABLED) self.zoomButton.config(state = DISABLED) self.baseline = self.workingChiplot.average() self.baselinevar.set(str(self.baseline)) self.prompt.set('select the right and left bounds of the peak and then use the up and down arrow keys to adjust the baseline of the peak\n when done, run the analyzation from the command below') self.add.cla() self.displayPlot()
def clear(self): dlog('in Splitter.clear') if (self.clicks != None): del self.clicks self.clicks = list() self.add.cla() if (self.peaks != None): del self.peaks self.peaks = list() self.center = None self.leftChi = None self.rightChi = None self.splitbutton.config(state=NORMAL) if self.dialogWindow != None: self.dialogWindow.destroy() self.dialogWindow = None self.displayPlot()
def convexHull(chiplot): """method that computes the convex hull of the given chiplot within the bounds and returns two list objects the first, xdata and the second ydata for the convex hull points""" dlog('in convexHull') xhull = list() yhull = list() # the first point is always the start of the convex hull xhull.append(chiplot.xdata[0]) yhull.append(chiplot.ydata[0]) lasthullindex = 0 points = len(chiplot.ydata) # Here is the actual algorithm! while (lasthullindex < points - 1): slope = ( chiplot.ydata[lasthullindex + 1] - chiplot.ydata[lasthullindex] ) / (chiplot.xdata[lasthullindex + 1] - chiplot.xdata[lasthullindex]) dlog('slope: ' + str(slope)) currenthullindex = lasthullindex + 1 currenthully = chiplot.ydata[lasthullindex] dlog('last hull point: ' + str(chiplot.xdata[lasthullindex]) + ',' + str(chiplot.ydata[lasthullindex])) for i in range(currenthullindex + 1, points): extrapolation = currenthully + slope * ( chiplot.xdata[i] - chiplot.xdata[lasthullindex]) if chiplot.ydata[i] < extrapolation: dlog('computing slope with new point: ' + str(chiplot.xdata[i]) + ',' + str(chiplot.ydata[i])) slope = ((chiplot.ydata[i] - chiplot.ydata[lasthullindex]) / (chiplot.xdata[i] - chiplot.xdata[lasthullindex])) dlog('slope: ' + str(slope)) currenthullindex = i # Store the hull points to be used for a spline fit xhull.append(chiplot.xdata[currenthullindex]) yhull.append(chiplot.ydata[currenthullindex]) lasthullindex = currenthullindex return xhull, yhull
def zoomdown(self, event): """method used to capture mouse events from plot""" # capture click data and draw dot for user feedback if event.xdata == None: return if(self.add == None): dlog('Error: Centroid has no subplot to draw to') return # set the start coords for the zooming regions if(self.zoomstart == None): self.zoomstart = event.xdata self.add.plot([self.zoomstart, self.zoomstart], [self.workingChiplot.ymin, self.workingChiplot.ymax], color = 'r') else: self.zoomend = event.xdata self.add.plot([self.zoomend, self.zoomend], [self.workingChiplot.ymin, self.workingChiplot.ymax], color = 'r') self.finishZoom(event) self.canvas.draw()
def customFiles(self): filename = tkinter.filedialog.asksaveasfilename( initialdir=os.path.dirname(self.chiplot.filename), initialfile=os.path.basename(self.chiplot.filename) + '.bak', title='Background Subtracted Chiplot') if filename == '': return self.dialogWindow.destroy() self.dialogWindow = None if self.workingChiplot.writeFile(False, '', filename) < 0: dlog( 'Unable to output background subtraction of chiplot: ' + self.chiplot.filename, 'l') self.dialogWindow = errorMessage( self.clear, self.ignoreError, 'Error outputing background subtracted chiplots', "Chiplot's background successfully taken out but unable to output file correctly", 'Unable to output subtracted chiplot: ' + self.chiplot.filename) else: dlog('Outputing background subtraction to ' + filename)
def standardFiles(self): self.dialogWindow.destroy() self.dialogWindow = None if self.leftChi.writeFile(True, 'l.xy') < 0: dlog( 'Unable to output left side of chiplot: ' + self.chiplot.filename, 'l') self.dialogWindow = errorMessage( self.clear, self.ignoreError, 'Error outputing split chiplots', 'Chiplot split but unable to output files correctly', 'Unable to output left side of chiplot: ' + self.chiplot.filename) return if self.rightChi.writeFile(True, 'r.xy') < 0: dlog( 'Unable to output right side of chiplot: ' + self.chiplot.filename, 'l') self.dialogWindow = errorMessage( self.clear, self.ignoreError, 'Error outputing split chiplots', 'Chiplot split but unable to output files correctly', 'Unable to output right side of chiplot: ' + self.chiplot.filename) dlog( 'Split chiplot into: ' + self.chiplot.filename + 'l.xy and ' + self.chiplot.filename + 'r.xy', 'l')
def zoomIn(self, event): if event.xdata == None: return dlog(str(event.xdata)) dlog("zooming in") if (self.add == None): dlog('Error: BGSub has no subplot to draw to') return lower = event.xdata for i in range(0, len(self.workingChiplot.xdata)): if ((self.workingChiplot.xdata[i] < lower) and (self.workingChiplot.xdata[i + 1] > lower)): lower = self.workingChiplot.xdata[i] clickIndex = self.workingChiplot.xdata.index(lower) leftIndex = clickIndex - 50 rightIndex = clickIndex + 50 if leftIndex < 0 or rightIndex >= len(self.workingChiplot.xdata): self.zoomed = 0 return self.add.cla() self.add.plot(self.workingChiplot.xdata[leftIndex:rightIndex], self.workingChiplot.ydata[leftIndex:rightIndex]) if (self.xsmooth != None): self.add.plot(self.xsmooth[leftIndex:rightIndex], self.ysmooth[leftIndex:rightIndex], color='g') self.canvas.draw()
def peakElim(self, event=None): """eliminates the peaks from the chiplot""" dlog('in peak eliminator of Background Subtract') if event == None: if (self.connect != None): self.canvas.mpl_disconnect(self.connect) self.connect = self.canvas.mpl_connect('button_press_event', self.peakElim) self.prompt.set( 'click to the left then right (order is important) of large negative peaks that would damage the convex hull\nWhen the large negative peaks have been removed run the convex hull algorithm' ) return if event.xdata == None: return dlog(str(event.xdata)) self.peaks.append(event.xdata) if len(self.peaks) % 2 == 1: self.hullButton.config(state=DISABLED) else: self.hullButton.config(state=NORMAL) self.add.plot([event.xdata, event.xdata], [self.chiplot.ymin, self.chiplot.ymax], color='k') self.canvas.draw()