class FormantPlot: def __init__(self, parent, path, root, plotID, formApp): self.plotHeight = PLOTHEIGHT self.plotWidth = PLOTWIDTH self.root = root self.formApp = formApp self.vowelType = formApp.vowelType self.parent = parent self.path = path self.id = plotID self.buttonCounter = 0 if plotID == 0 or plotID == 1: self.gender = "male" else: self.gender = "female" self.hasFormants = False #plot Setup: self.updateRate = 30 self.setupPlot() self.drawGoldStandardMonophthongs(True) self.createKey() self.createAxis() self.prevX = 0 self.prevY = 0 # sound Setup: self.initialiseSounds() self.formantRadius = 2 self.formantColour = 'black' self.isRecording = False self.lineHiddens = False self.loadedPlots = False self.hasloadedPlots = False self.backgroundNoiseDistance = 50 self.count = 0 self.notStopped = False def setupPlot(self): #Plot self.formantPlotFrame = self.parent # self.formantPlotCanvas = Canvas(self.formantPlotFrame, height=PLOTHEIGHT-60, width=PLOTWIDTH, bg='white') self.formantPlotCanvas = Canvas(self.formantPlotFrame, height=PLOTHEIGHT, width=PLOTWIDTH, bg='white') #self.formantPlotCanvas.grid(row=0 ,column=0, sticky=N+S+E+W) self.formantPlotCanvas.pack(fill=BOTH, expand=YES) self.formantPlotCanvas.bind("<Button-1>", self.requestRecord) #Creates the loudnessMeter on the formant plot canvas. self.loudnessMeter = LoudnessMeter(self.formantPlotCanvas, YSHIFT) self.createBoxs() def createButtons(self): self.buttonCounter += 1 self.formantPlotCanvas.delete('buttons') height = (int)((float)(2) * (self.plotHeight / PLOTHEIGHT)) font = ('Arial', '12') self.formantPlotCanvas.create_rectangle(0, self.plotHeight - height * 30 - 8, self.plotWidth + 10, self.plotHeight + 10, tags='buttons', fill='#d3d3d3') text = " Back to Menu " helpButton = Button(self.parent, text=text, command=self.goBackToMenu, font=font) helpButton.configure(height=height, activebackground='green', anchor=W, relief=GROOVE) helpButtonWindow = self.formantPlotCanvas.create_window( 2, self.plotHeight - 4 * (self.plotHeight / PLOTHEIGHT), anchor=SW, tags=('backButton', 'buttons'), window=helpButton) text = text = 14 * " " + "Record" + 14 * " " self.recordButton = Button(self.parent, text=text, font=font, command=self.requestRecord) self.recordButton.configure(height=height, activebackground='green', anchor=W, relief=GROOVE, bd=3) self.formantPlotCanvas.create_window( (self.plotWidth / 2), self.plotHeight - 4 * (self.plotHeight / PLOTHEIGHT) - 25, anchor=CENTER, tags=('recordButton', 'buttons'), window=self.recordButton) if self.buttonCounter > 2 and self.formantPlotCanvas.winfo_height( ) <= 580: self.formantPlotCanvas.delete("recordButton") self.formantPlotCanvas.create_window( (self.plotWidth / 2), self.plotHeight - 4 * (self.plotHeight / PLOTHEIGHT) - 15, anchor=CENTER, tags=('recordButton', 'buttons'), window=self.recordButton) if self.vowelType == 'short': text = " Short Vowels " else: text = ' Long Vowels ' self.vowelButton = Button(self.parent, text=text, font=font, command=self.toggleVowelType) self.vowelButton.configure(height=height, activebackground='green', anchor=W, relief=GROOVE, bd='3') self.formantPlotCanvas.create_window(self.plotWidth, self.plotHeight - 4 * (self.plotHeight / PLOTHEIGHT), anchor=SE, tags=('vowelButton', 'buttons'), window=self.vowelButton) self.formantPlotCanvas.itemconfig('buttons', state='normal') def goBackToMenu(self): self.formApp.backToMenu() def toggleVowelType(self, *event): if self.isRecording == False: self.formApp.toggleVowelType() def loadHelp(self): pass def createBoxs(self): self.formantPlotCanvas.delete('boxes') boxWidth = 150 font = ('Arial', '15') x1 = (PLOTWIDTH / 2) * (self.plotWidth / PLOTWIDTH) - (boxWidth) y1 = 2 x2 = (PLOTWIDTH / 2) * (self.plotWidth / PLOTWIDTH) y2 = 32 self.recordingBox = self.formantPlotCanvas.create_rectangle( x1, y1, x2, y2, tag=('boxes', 'Recording'), fill='orange', outline='black') self.recordingBoxText = self.formantPlotCanvas.create_text( (x1 + x2) / 2, (y1 + y2) / 2, tag=('boxes', 'recordingText'), text='Loading...', font=font, fill='black') self.formantPlotCanvas.itemconfig('Recording', state='hidden') self.formantPlotCanvas.itemconfig('recordingText', state='hidden') x1 = (PLOTWIDTH / 2) * (self.plotWidth / PLOTWIDTH) y1 = 2 x2 = (PLOTWIDTH / 2) * (self.plotWidth / PLOTWIDTH) + boxWidth y2 = 32 self.recordingBox = self.formantPlotCanvas.create_rectangle( x1, y1, x2, y2, tag=('boxes', 'Loudness'), outline='black') self.recordingBoxText = self.formantPlotCanvas.create_text( (x1 + x2) / 2, (y1 + y2) / 2, tag=('boxes', 'toLoud'), text='Too Loud.', font=font, fill='black') self.recordingBoxText = self.formantPlotCanvas.create_text( (x1 + x2) / 2, (y1 + y2) / 2, tag=('boxes', 'toQuiet'), text='Too Quiet.', font=font, fill='black') self.formantPlotCanvas.itemconfig('toLoud', state='hidden') self.formantPlotCanvas.itemconfig('toQuiet', state='hidden') self.formantPlotCanvas.itemconfig('Loudness', state='hidden') def resize(self, width, height): print self.formantPlotCanvas.winfo_height() print self.formantPlotCanvas.winfo_width() self.plotWidth = (float)(width) self.plotHeight = (float)(height) self.drawGoldStandardMonophthongs(True) self.redrawPlotInfo() self.createBoxs() self.createButtons() def createKey(self, ): self.formantPlotCanvas.delete("legend") font = ('Arial', '13') radius = 4 x = self.plotWidth - 160 y = 15 self.formantPlotCanvas.create_text(x + 80, y, text="Key:", tag='legend', font=font) self.formantPlotCanvas.create_oval(x - radius, y + 20 - radius, x + radius, y + 20 + radius, tag='legend', fill='black') self.formantPlotCanvas.create_text(x + 80, y + 20, text='Recorded Vowels', tag='legend', font=font) self.formantPlotCanvas.create_oval(x - radius, y + 40 - radius, x + radius, y + 40 + radius, tag='legend', fill='yellow') self.formantPlotCanvas.create_text(x + 80, y + 40, text='Loaded Vowels', tag='legend', font=font) self.formantPlotCanvas.create_line(x - 15, 0, x - 15, y + 50, tag='legend') self.formantPlotCanvas.create_line(x - 15, y + 50, self.plotWidth + 50, y + 50, tag='legend') def createAxis(self): self.formantPlotCanvas.delete("formantAxes") xFrameScale = (self.plotWidth / PLOTWIDTH) yFrameScale = (self.plotHeight / PLOTHEIGHT) self.formantPlotCanvas.create_line( XSHIFT * xFrameScale, (self.plotHeight - YSHIFT * yFrameScale), self.plotWidth, (self.plotHeight - YSHIFT * yFrameScale), tags="formantAxes") yAxisCount = 15 yIncrement = ((self.plotHeight - YSHIFT) / yAxisCount) for yIndex in range(yAxisCount): y = yIndex * yIncrement self.formantPlotCanvas.create_line(XSHIFT * xFrameScale - 8, y, XSHIFT * xFrameScale, y, tags="formantAxes") self.formantPlotCanvas.create_line(XSHIFT * xFrameScale, 0, XSHIFT * xFrameScale, self.plotHeight - YSHIFT * yFrameScale, tags="formantAxes") xAxisCount = 20 xIncrement = (self.plotWidth - XSHIFT * xFrameScale) / xAxisCount for xIndex in range(xAxisCount): x = xIndex * xIncrement self.formantPlotCanvas.create_line( XSHIFT * xFrameScale + x, self.plotHeight - YSHIFT * yFrameScale + 8, XSHIFT * xFrameScale + x, self.plotHeight - YSHIFT * yFrameScale, tags="formantAxes") self.formantPlotCanvas.create_text( (XSHIFT * xFrameScale + self.plotWidth) / 2, self.plotHeight - YSHIFT * yFrameScale + 20, text="Tongue Position", font=('Arial', '13'), tags="formantAxes") self.formantPlotCanvas.create_text(XSHIFT * xFrameScale + 22, self.plotHeight - YSHIFT * yFrameScale + 15, text="Front", font=('Arial', '13'), tags="formantAxes") self.formantPlotCanvas.create_text(self.plotWidth - 30, self.plotHeight - YSHIFT * yFrameScale + 15, text="Back", font=('Arial', '13'), tags="formantAxes") self.formantPlotCanvas.create_text( XSHIFT * xFrameScale / 2, (self.plotHeight - YSHIFT * yFrameScale) / 2, text="Mouth", font=('Arial', '13'), tags="formantAxes") self.formantPlotCanvas.create_text( XSHIFT * xFrameScale / 2, ((self.plotHeight - YSHIFT * yFrameScale) / 2) + 15, text="Openness", font=('Arial', '13'), tags="formantAxes") self.formantPlotCanvas.create_text(XSHIFT * xFrameScale / 2, self.plotHeight - YSHIFT * yFrameScale - 15, text="Open", font=('Arial', '13'), tags="formantAxes") self.formantPlotCanvas.create_text(XSHIFT * xFrameScale / 2, 20, text="Closed", font=('Arial', '13'), tags="formantAxes") def drawGoldStandardMonophthongs(self, toFill): self.formantPlotCanvas.delete("ellipses") vowelType = self.vowelType (xScale, xShift, yScale, yShift) = self.getPlotScaleInfo(vowelType) data = self.goldStandardMonophthongs(self.id, vowelType) xFrameScale = (self.plotWidth / PLOTWIDTH) yFrameScale = (self.plotHeight / PLOTHEIGHT) std = 1 for f1mean, f1sd, f2mean, f2sd, vowel in data: font = ('Arial', '20', 'bold') x1 = ((f2mean - std * f2sd) * xScale - xShift) * xFrameScale y1 = ((f1mean - std * f1sd) * yScale - yShift) * yFrameScale x2 = ((f2mean + std * f2sd) * xScale - xShift) * xFrameScale y2 = ((f1mean + std * f1sd) * yScale - yShift) * yFrameScale if toFill: currentOval = self.formantPlotCanvas.create_oval( x1, y1, x2, y2, outline='black', tag='ellipses', fill='#ffffff', activefill='#e3c5d6') else: currentOval = self.formantPlotCanvas.create_oval( x1, y1, x2, y2, outline='black', tag='ellipses', activefill='#e3c5d6') ovalText = self.formantPlotCanvas.create_text( (f2mean * xScale - xShift) * xFrameScale, (f1mean * yScale - yShift) * yFrameScale, fill='red', font=font, tag='ellipses', text=vowel) #creating the overlap for f1mean, f1sd, f2mean, f2sd, vowel in data: x1 = ((f2mean - std * f2sd) * xScale - xShift) * xFrameScale y1 = ((f1mean - std * f1sd) * yScale - yShift) * yFrameScale x2 = ((f2mean + std * f2sd) * xScale - xShift) * xFrameScale y2 = ((f1mean + std * f1sd) * yScale - yShift) * yFrameScale currentOval = self.formantPlotCanvas.create_oval(x1, y1, x2, y2, outline='black', tag='ellipses') def redrawPlotInfo(self): self.drawGoldStandardMonophthongs(False) self.createAxis() self.createKey() self.replotFormants() self.replotloadedPlots() def getPlotScaleInfo(self, vowelType): plotID = self.id if plotID == 0: if vowelType == 'short': xScale = 1.5 xShift = 400 yScale = 2 yShift = 100 else: xScale = 1.5 xShift = 400 yScale = 2 yShift = 100 elif plotID == 1: if vowelType == 'short': xScale = 1.5 xShift = 400 yScale = 3 yShift = 200 else: xScale = 1.5 xShift = 400 yScale = 3 yShift = 200 elif plotID == 2: if vowelType == 'short': xScale = 1.2 xShift = 130 yScale = 1.8 yShift = 130 else: xScale = 1.2 xShift = 130 yScale = 1.8 yShift = 130 elif plotID == 3: if vowelType == 'short': xScale = 1.2 xShift = 150 yScale = 2.3 yShift = 175 else: xScale = 1.2 xShift = 150 yScale = 2.3 yShift = 175 else: print "ERROR ID INVALID" xScale = 0 xShift = 0 yScale = 0 yShift = 0 return (xScale, xShift, yScale, yShift) def goldStandardMonophthongs(self, plotID, vowelType): path = self.path if plotID == 0: if vowelType == 'short': data = self.appendData(path, 'data\maori\monDataNativeMale.txt') else: data = self.appendData(path, 'data\maori\longVowelNativeMale.txt') elif plotID == 1: if vowelType == 'short': data = self.appendData(path, 'data\maori\monDataModernMale.txt') else: data = self.appendData(path, 'data\maori\longVowelModernMale.txt') elif plotID == 2: if vowelType == 'short': data = self.appendData(path, 'data\maori\monDataNativeFemale.txt') else: data = self.appendData(path, 'data\maori\longVowelNativeFemale.txt') elif plotID == 3: if vowelType == 'short': data = self.appendData(path, 'data\maori\monDataModernFemale.txt') else: data = self.appendData(path, 'data\maori\longVowelModernFemale.txt') return data def appendData(self, pat, str): MonophthongDataPath = os.path.join(pat, str) MonophthongFile = open(MonophthongDataPath, 'r') MonophthongData = [] #Code from ywan478 2010 SoftEng206 Project #Load in the monophthong data for males for monophthongDataLine in MonophthongFile: monophthongDataLine = monophthongDataLine.split() #F1 mean and standard deviation monophthongDataLine[0] = (int(float(monophthongDataLine[0])) / SCALEDOWN) monophthongDataLine[1] = (int(float(monophthongDataLine[1])) / SCALEDOWN) #F2 mean and standard deviation monophthongDataLine[2] = PLOTWIDTH - (int( float(monophthongDataLine[2])) / SCALEDOWN) + XSHIFT + XOFFSET monophthongDataLine[3] = (int(float(monophthongDataLine[3])) / SCALEDOWN) MonophthongData.append(monophthongDataLine) #End code from ywan478 return MonophthongData #*********************************************************************************************************** # Sound ''' Creates the Snack Sound objects used in the formant plot. ''' def initialiseSounds(self): tkSnack.initializeSnack(self.root) self.recordedAudio = Sound() self.soundCopy = Sound() self.loadedAudio = Sound() def replotFormants(self): if (self.hasFormants == True): self.formantPlotCanvas.delete("userformants") radius = self.formantRadius color = self.formantColour for index in range(len(self.xPlotList)): x = self.xPlotList[index] y = self.yPlotList[index] self.formantPlotCanvas.create_oval( x * (self.plotWidth / PLOTWIDTH) - radius, y * (self.plotHeight / PLOTHEIGHT) - radius, x * (self.plotWidth / PLOTWIDTH) + radius, y * (self.plotHeight / PLOTHEIGHT) + radius, fill=color, tags="userformants") def replotloadedPlots(self): if (self.hasloadedPlots == True): self.formantPlotCanvas.delete("loadedPlots") self.formantPlotCanvas.delete("loadedLines") radius = self.formantRadius color = 'yellow' prevX = self.xLoadedPlotList[0] prevY = self.yLoadedPlotList[0] for index in range(len(self.xLoadedPlotList)): x = self.xLoadedPlotList[index] y = self.yLoadedPlotList[index] xScaled = x * (self.plotWidth / PLOTWIDTH) yScaled = y * (self.plotHeight / PLOTHEIGHT) prevXScaled = prevX * (self.plotWidth / PLOTWIDTH) prevYScaled = prevY * (self.plotHeight / PLOTHEIGHT) self.formantPlotCanvas.create_oval( x * (self.plotWidth / PLOTWIDTH) - radius, y * (self.plotHeight / PLOTHEIGHT) - radius, x * (self.plotWidth / PLOTWIDTH) + radius, y * (self.plotHeight / PLOTHEIGHT) + radius, fill=color, tags="loadedPlots") if ((((x - prevX)**2 + (y - prevY)**2)**(0.5)) < self.backgroundNoiseDistance): self.formantPlotCanvas.create_line(prevXScaled, prevYScaled, xScaled, yScaled, tags='loadedLines') prevX = x prevY = y """ Plot Fomrants takes a sound file and plots the last formant in the file. """ def plotFormants(self, sound): #Gets the probablity of sound being a voice for the last formant in the sound file. (false means last formant, true means all formants) probabilityOfVoicing = SoundProcessing.getProbabilityOfVoicing( sound, False) if probabilityOfVoicing == 1.0: formant = SoundProcessing.getFormants(sound, self.id, False) #Only plot the latest formants of the sound if there's a good chance that it is the user speaking instead of background noise. if formant != None: (xScale, xShift, yScale, yShift) = self.getPlotScaleInfo(self.vowelType) #GetUser default or user defined colour and radius for the individual formants radius = self.formantRadius color = self.formantColour yPreScale = formant[0] / SCALEDOWN xPreScale = PLOTWIDTH - (formant[1] / SCALEDOWN) + XSHIFT + XOFFSET x = (xPreScale * xScale - xShift) y = (yPreScale * yScale - yShift) self.count += 1 #Only plot of the Points are on the Grid. They can go over the axis though. if (x > 0) and (y < PLOTHEIGHT): distance = (((x - self.prevX)**2 + (y - self.prevY)**2)**(0.5)) if (distance < self.backgroundNoiseDistance) and distance > 0: self.hasFormants = True self.formantPlotCanvas.create_oval( x * (self.plotWidth / PLOTWIDTH) - radius, y * (self.plotHeight / PLOTHEIGHT) - radius, x * (self.plotWidth / PLOTWIDTH) + radius, y * (self.plotHeight / PLOTHEIGHT) + radius, fill=color, tags="userformants") self.xPlotList.append(x) self.yPlotList.append(y) self.prevX = x self.prevY = y if not self.isRecording: if formant != None: pass """ Determines if to record or stop. """ def requestRecord(self, *event): if self.isRecording: if self.isLoading: pass else: self.stop() else: self.record() """ record is called when the record button is pressed it starts recording the users sounds and makes the formant plot react accordingly. """ def record(self): self.isLoading = True text = 15 * " " + "Stop" + 15 * " " self.recordButton.config(text=text, bg='orange', state='disabled') self.vowelButton.config(state='disabled') self.hasFormants = True self.xPlotList = [] self.yPlotList = [] self.root.resizable( False, False ) #DISALLOWS the window to be resized both verically and horizonally. self.notStopped = True self.recordedAudio.record() self.isRecording = True #self.stopButton.config(state='normal') #self.clearScreenButton.config(state='disabled') self.formantPlotCanvas.itemconfig('Recording', state='normal', fill='orange') self.formantPlotCanvas.itemconfig('recordingText', state='normal', text='Loading...') thread.start_new_thread(self.multiThreadUpdateCanvas, ("Thread-1", self.notStopped)) self.count2 = 0 def multiThreadUpdateCanvas(self, threadName, notStopped): self.clear() sleep(1.2) self.isLoading = False text = 15 * " " + "Stop" + 15 * " " self.recordButton.config(text=text, bg='#CE2029', state='normal') self.formantPlotCanvas.itemconfig('Recording', fill='red') self.formantPlotCanvas.itemconfig('recordingText', text='Recording') try: while self.notStopped: self.count2 += 1 self.soundCopy.copy(self.recordedAudio) SoundProcessing.crop(self.soundCopy) self.plotFormants(self.soundCopy) if self.count2 % 10 == 0: self.updateLoudnessMeter(self.soundCopy) except Exception: import traceback print traceback.format_exc() def stop(self): self.isRecording = False self.recordButton.config(text=" Record ", bg='white') self.notStopped = False self.formantPlotCanvas.itemconfig('boxes', state='hidden') self.loudnessMeter.clearMeter self.recordedAudio.stop() self.root.after(200, self.removeLoudness) self.count = 0 self.root.resizable( True, True ) #Allows the window to be resized both verically and horizonally. self.vowelButton.config(state='normal') def removeLoudness(self): self.loudnessMeter.clearMeter() self.formantPlotCanvas.itemconfig('toLoud', state='hidden') self.formantPlotCanvas.itemconfig('toQuiet', state='hidden') self.formantPlotCanvas.itemconfig('Loudness', state='hidden') """ Clears the screen of all plots, lines and loaded plots. """ def clear(self): self.hasFormants = False self.hasloadedPlots = False self.formantPlotCanvas.delete('userformants') self.formantPlotCanvas.delete('loadedPlots') self.formantPlotCanvas.delete('loadedLines') def changeColor(self): self.formantColour = 'pink' ''' Update the formant plot and loudness meter if the user is still recording. ''' def updateAllCanvases(self): self.soundCopy.copy(self.recordedAudio) SoundProcessing.crop(self.soundCopy) self.plotFormants(self.soundCopy) self.updateLoudnessMeter(self.soundCopy) if self.isRecording: self.updateAllCanvases() def updateLoudnessMeter(self, sound): try: self.loudnessMeter.updateMeter(sound) except IndexError: pass def playAudioFile(self): self.loadedAudio.play() def loadAudioFile(self): self.formantPlotCanvas.delete("loadedLines") os.chdir("../..") self.xLoadedPlotList = [] self.yLoadedPlotList = [] self.loadedPlots = True print os.getcwd() filename = tkFileDialog.askopenfilename(initialdir="Recording") radius = self.formantRadius self.formantPlotCanvas.delete('loadedPlots') self.loadedAudio.config(load=filename) os.chdir("Formant/dist") import wave import contextlib fname = filename with contextlib.closing(wave.open(fname, 'r')) as f: frames = f.getnframes() rate = f.getframerate() duration = float(frames) / float(rate) loadedPlots = SoundProcessing.getFormants(self.loadedAudio, self.gender, True) probabilityOfVoicingList = SoundProcessing.getProbabilityOfVoicing( self.loadedAudio, True) self.formantPlotCanvas.delete('loadedPlots') sleeptime = float(duration) / len(probabilityOfVoicingList) thread.start_new_thread( self.multiThreadLoader, ("Thread-2", sleeptime, probabilityOfVoicingList, loadedPlots)) def multiThreadPlayer(self, threadName, sound): sound.play() ''' multiThreadLoader plots the formant plots onto the formant plot using an additional thread to allow the application not to freeze especially if the audio file is very large. ''' def multiThreadLoader(self, threadName, delay, probabilityOfVoicingList, loadedPlots): self.hasloadedPlots = True self.count = 0 try: radius = self.formantRadius for i in range(0, len(loadedPlots)): probabilityOfVoicing = probabilityOfVoicingList[i] if probabilityOfVoicing == 1.0: formant = loadedPlots[i] latestF1 = formant[0] / SCALEDOWN latestF2 = PLOTWIDTH - (formant[1] / SCALEDOWN) + XSHIFT + XOFFSET (xScale, xShift, yScale, yShift) = self.getPlotScaleInfo(self.vowelType) if latestF2 > XSHIFT and latestF1 < PLOTHEIGHT - YSHIFT: self.prevplotted = True self.prevX = latestF2 * xScale - xShift self.prevY = latestF1 * yScale - yShift break for i in range(0, len(loadedPlots)): probabilityOfVoicing = probabilityOfVoicingList[i] if probabilityOfVoicing == 1.0: formant = loadedPlots[i] latestF1 = formant[0] / SCALEDOWN latestF2 = PLOTWIDTH - (formant[1] / SCALEDOWN) + XSHIFT + XOFFSET (xScale, xShift, yScale, yShift) = self.getPlotScaleInfo(self.vowelType) if latestF2 > XSHIFT and latestF1 < PLOTHEIGHT - YSHIFT: x = latestF2 * xScale - xShift y = latestF1 * yScale - yShift if ((((x - self.prevX)**2 + (y - self.prevY)**2) **(0.5)) < self.backgroundNoiseDistance): self.xLoadedPlotList.append(x) self.yLoadedPlotList.append(y) x1 = x * (self.plotWidth / PLOTWIDTH) - radius y1 = y * (self.plotHeight / PLOTHEIGHT) - radius x2 = x * (self.plotWidth / PLOTWIDTH) + radius y2 = y * (self.plotHeight / PLOTHEIGHT) + radius if (self.prevplotted == True): self.formantPlotCanvas.create_line( self.prevX * (self.plotWidth / PLOTWIDTH), self.prevY * (self.plotHeight / PLOTHEIGHT), x * (self.plotWidth / PLOTWIDTH), y * (self.plotHeight / PLOTHEIGHT), fill='black', tags='loadedLines') pass xCoord = x1 self.formantPlotCanvas.create_oval( x1, y1, x2, y2, fill='yellow', tags="loadedPlots") self.prevplotted = True self.count += 1 else: self.prevplotter = False self.prevX = x self.prevY = y except Exception: import traceback print traceback.format_exc() self.formantPlotCanvas.itemconfig("loadedLines", state='hidden') self.lineHiddens = True self.redrawPlotInfo() self.count = 0 def toggleLoadedPlots(self): if self.loadedPlots: self.formantPlotCanvas.itemconfig("loadedPlots", state="hidden") self.loadedPlots = False else: self.formantPlotCanvas.itemconfig("loadedPlots", state="normal") self.loadedPlots = True def toggleLines(self): if self.lineHiddens: self.formantPlotCanvas.itemconfig("loadedLines", state="normal") self.lineHiddens = False else: self.formantPlotCanvas.itemconfig("loadedLines", state="hidden") self.lineHiddens = True def toggleBackgroundNoise(self, level): if level == 0: self.backgroundNoiseDistance = 10000 elif level == 1: self.backgroundNoiseDistance = 100 elif level == 2: self.backgroundNoiseDistance = 50 elif level == 3: self.backgroundNoiseDistance = 30 else: self.backgroundNoiseDistance = 10 def callback(self, event): print "canvas clicked"