class Annotator: def __init__(self, parent): self.parent = parent parent.title("Sound Annotation/Analyzation Tool") self.initUI() def initUI(self): self.labeldict = {} self.show = [] self.timeValues = [] self.stamp = -1 self.stampHistory = [] self.funclist = { "rms", "hfc", "complex", "complex_phase", "flux", "superflux", "noveltycurve", "CNNOnsetDetector", "RNNOnsetDetector", "modifiedKL", "weightedPhaseDev", "PhaseDev", "rectifiedComplexDomain", "ninos" } self.featurelist = [ "Audio", "rms", "spectralCentroid", "spectralRolloff", "zcr", "spectralEntropy", "spectralFlux", "StrongDecay", "stft" ] self.hopsizes = [] self.calculated_features_dict = {} self.calculated_features = [] self.calculated_featuresParams = [] self.defaultParams = { 'rms': (512, 1024, 'hann'), 'Audio': (), 'spectralCentroid': (512, 1024, 'hann'), 'spectralRolloff': (512, 1024, 'hann'), 'spectralFlux': (512, 1024, 'hann'), 'zcr': (512, 1024), 'spectralEntropy': (512, 1024, 'hann'), 'StrongDecay': (512, 1024), 'stft': (512, 1024) } self.chunk_size = 2048 self.mag = [] self.phase = [] self.sem = asyncio.Semaphore() # Info text self.info = StringVar() self.info.set("welcome") self.info_widget = Message(self.parent, textvariable=self.info, width=300) self.info_widget.grid(row=0, column=3, sticky=W + N + E + S, rowspan=2) # define options for opening file self.file_opt = options = {} options['defaultextension'] = '.wav' options['filetypes'] = [('All files', '.*'), ('Wav files', '.wav')] options['initialdir'] = os.getcwd() + "/sounds" if (options['initialdir'][-1] != '/'): options['initialdir'] += '/' # BUTTON TO SET DIRECTORY self.directory_button = Button(self.parent, text="Directory", command=self.set_directory) self.directory_button.grid(row=1, column=0, sticky=W) #TEXTBOX TO PRINT PATH OF THE SOUND FILE self.filelocation = Entry(self.parent) self.filelocation["width"] = 25 self.filelocation.grid(row=0, column=0, sticky=W, padx=10) self.filelocation.delete(0, END) self.filename = '' # initial file self.filelocation.insert(0, self.file_opt['initialdir'] + self.filename) #BUTTON TO BROWSE SOUND FILE self.open_file = Button(self.parent, text="Browse...", command=self.browse_file) self.open_file.grid(row=0, column=0, sticky=W, padx=(220, 6)) #BUTTON TO PLOT SOUND FILE self.preview = Button(self.parent, text="Plot", command=self.plot, bg="gray30", fg="white") self.preview.grid(row=0, column=0, sticky=W, padx=(300, 6)) #BUTTON TO draw stamps self.draw = Button(self.parent, text="Draw", command=self.drawAllStamps, bg="gray30", fg="white") self.draw.grid(row=1, column=0, sticky=W, padx=(420, 6)) # Dropdown Function Select self.funcname = StringVar() self.funcname.set("Select a function") self.fselect = OptionMenu(self.parent, self.funcname, *self.funclist) self.fselect.grid(row=1, column=2, sticky=W) # Button to Apply function self.afuncbtn = Button(self.parent, text="Apply", command=self.applyfunction, bg="gray30", fg="white") self.afuncbtn.grid(row=1, column=2, sticky=W, padx=(300, 6)) # Dropdown SHOW FEATURE self.featurename = StringVar() self.featurename.set("Audio") self.featurename.trace("w", self.changeparams) self.ftselect = OptionMenu(self.parent, self.featurename, *self.featurelist) self.ftselect.grid(row=0, column=2, sticky=W) # Entry for feature params self.featureParamsEntry = Entry(self.parent) self.featureParamsEntry.grid(row=0, column=2, sticky=W, padx=(150, 6)) self.featureParamsEntry.bind("<Enter>", self.updateinfo) # Button to show feature self.afuncbtn = Button(self.parent, text="Show", command=self.showfeature, bg="gray30", fg="white") self.afuncbtn.grid(row=0, column=2, sticky=W, padx=(300, 6)) # Button to send top feature to below plot self.sendbelowbtn = Button(self.parent, text="v", command=self.sendbelow) self.sendbelowbtn.grid(row=0, column=2, sticky=W, padx=(360, 6)) #BUTTON TO PLAY/STOP , shortcut: spacebar self.play_mode = tk.BooleanVar(self.parent, False) self.new_sound = tk.BooleanVar(self.parent, False) self.playbutton = Button(self.parent, text="Play", command=self.playsound) self.playbutton.grid(row=0, column=0, sticky=W, padx=(350, 6)) self.parent.bind("<space>", self.playsound) #BUTTON TO SAVE AND LOAD NEXT SOUND FILE self.saveload = Button(self.parent, text="Save& Load Next", command=self.saveAndNext) self.saveload.grid(row=0, column=1, sticky=W) #BUTTON TO ADD LABELS self.addlabel_button = Button(self.parent, text="Add/Manage Labels", command=self.addlabel_gui) self.addlabel_button.grid(row=0, column=0, sticky=W, padx=(420, 6)) # BUTTON TO DISCARD CURRENT ANNOTATIONS self.discardbutton = Button(self.parent, text="Discard", command=self.discard) self.discardbutton.grid(row=0, column=4, sticky=W) #BUTTON TO get next self.load_next = Button(self.parent, text="Next Sound", command=self.getNext) self.load_next.grid(row=1, column=0, sticky=W, padx=(220, 6)) # BUTTON TO QUIT self.quitbutton = Button(self.parent, text="Quit", command=self.quit) self.quitbutton.grid(row=3, column=4, sticky=W) # tickbox to autoload existing annotations self.ALoad = IntVar() self.autoload_annotations = Checkbutton(master=self.parent, text="Autoload Annotations?", variable=self.ALoad, onvalue=1, offvalue=0) self.autoload_annotations.grid(row=1, column=1, sticky=W) # tickbox to convert time to samples self.isTime = IntVar() self.timeorsamples = Checkbutton(master=self.parent, text="time?", variable=self.isTime, onvalue=1, offvalue=0) self.timeorsamples.grid(row=1, column=0, sticky=W, padx=(500, 6)) # tickbox to enable discarding labels self.DLabels = IntVar() self.discardlabels_check = Checkbutton(master=self.parent, text="Discard Labels?", variable=self.DLabels, onvalue=1, offvalue=0) self.discardlabels_check.grid(row=1, column=4, sticky=W) # init figure for plotting self.currentplot = 0 fig = plt.figure(figsize=(18, 7), dpi=100) self.mainplot = fig.add_subplot(211) self.secplot = fig.add_subplot(212) self.canvas = FigureCanvasTkAgg(fig, self.parent) self.canvaswidget = self.canvas.get_tk_widget() self.canvaswidget.grid(row=2, column=0, columnspan=5, sticky=W) toolbarFrame = Frame(master=self.parent) toolbarFrame.grid(row=3, column=0, columnspan=7) self.toolbar = NavigationToolbar2Tk(self.canvas, toolbarFrame) self.toolbar.update() self.canvas._tkcanvas.grid(row=2, column=0, columnspan=7, sticky=W) self.background = self.canvas.copy_from_bbox(self.mainplot.bbox) self.cursor = self.mainplot.axvline(color="k", animated=True) self.cursor.set_xdata(0) self.colors = [ 'r', 'g', 'c', 'm', 'y', '#FFBD33', '#924A03', '#D00000', '#D000D0', '#6800D0', '#095549', 'b', 'r', 'r' ] # modification to original handler of 'release_zoom', "release_pan" and "_update_view" from NavigationToolbar2 # latest one is for forward, backward and home buttons self.release_zoom_orig = self.toolbar.release_zoom self.toolbar.release_zoom = self.new_release_zoom self.release_pan_orig = self.toolbar.release_pan self.toolbar.release_pan = self.new_release_pan self._update_view_orig = self.toolbar._update_view self.toolbar._update_view = self.new_update_view self.canvas.mpl_connect('toolbar_event', self.handle_toolbar) cid1 = self.canvas.mpl_connect("button_press_event", self.onclick) self.parent.bind("<Escape>", self.release_stamp) self.parent.bind("x", self.discard_last) self.p = pyaudio.PyAudio() self.parent.bind("<<playbackmove>>", self.playbackMove) def callbackstream(in_data, frame_count, time_info, status): self.sem.acquire() data = self.wf.readframes(frame_count) self.parent.event_generate("<<playbackmove>>", when="now") self.sem.release() return (data, pyaudio.paContinue) self._callbackstream = callbackstream def updateinfo(self, event, *args): caller = event.widget if str(caller) == '.!entry2': self.info.set(getattr(features, self.featurename.get()).__doc__) def applyfunction(self): values = getattr(libod, self.funcname.get())(self.filelocation.get()) if len(values) == 0: self.info.set("No detections") else: self.labeldict[len(self.labeldict)] = self.funcname.get() var = IntVar() var.set(1) self.show.append(var) self.timeValues.append([i * 44100 for i in values]) self.drawAllStamps() def set_directory(self): directory = tkFileDialog.askdirectory() + '/' self.file_opt['initialdir'] = directory def release_stamp(self, event=None): self.stamp = -1 self.info.set("Cursor") def discard_last(self, event=None ): # discard last annotation for current sound. button: X self.mainplot.lines.pop() self.canvas.draw() self.background = self.canvas.copy_from_bbox(self.mainplot.bbox) self.timeValues[self.stampHistory[-1]].pop() self.stampHistory.pop() def discard(self): # discard all annotations self.timeValues = [] if (self.DLabels.get() == True or self.ALoad.get() == True): self.labeldict = {} self.show = [] else: for i in range(len(self.labeldict)): self.timeValues.append([]) self.stamp = -1 self.stampHistory = [] self.mag = [] self.phase = [] self.hopsizes = [] self.calculated_features_dict = {} self.calculated_features = [] self.calculated_featuresParams = {} self.currentplot = 0 def label(self, event): self.info.set(self.labeldict[int(event.char) - 1] + " is selected") self.stamp = int(event.char) - 1 def addlabel(self): self.labeldict[len(self.labeldict)] = self.newlabel_entry.get() var = IntVar() var.set(1) self.show.append(var) self.parent.bind("%d" % len(self.labeldict), self.label) self.timeValues.append([]) def deselect(self): for cb in self.checkbuttons: cb.deselect() def addlabel_gui(self): frame_addlabel = Toplevel(master=self.parent) frame_addlabel.geometry( "%dx%d%+d%+d" % (400, 100 + 33 * len(self.labeldict), 200, 200)) frame_addlabel.title("Add Labels") self.newlabel_entry = Entry(frame_addlabel) self.newlabel_entry.grid(row=0, column=0) labels_text = "Current Labels:" w = Message(frame_addlabel, text=labels_text, width=150) w.grid(row=1, column=0) labels_text = "Display?" w = Message(frame_addlabel, text=labels_text, width=150) w.grid(row=1, column=1) self.checkbuttons = [] for i in range(len(self.labeldict)): labels_text = '%d' % (i + 1) + '. ' + self.labeldict[i] w = Message(frame_addlabel, text=labels_text, width=150) w.grid(row=i + 2, column=0) check = Checkbutton(master=frame_addlabel, text="", variable=self.show[i], onvalue=1, offvalue=0) check.grid(row=i + 2, column=1, sticky=W) self.checkbuttons.append(check) addbutton = Button(frame_addlabel, text="Add", command=self.addlabel) addbutton.grid(row=0, column=1, sticky=W) togglebutton = Button(frame_addlabel, text="Deselect", command=self.deselect) togglebutton.grid(row=1, column=2, sticky=W) def quit(self): try: self.stream.close() self.wf.close() self.p.terminate() except: print("no audio init") finally: self.parent.destroy() def initStream(self): self.stream = self.p.open(format=8, channels=1, rate=44100, output=True, stream_callback=self._callbackstream, start=True, frames_per_buffer=self.chunk_size) def playsound(self, event=None): if self.sem.locked(): return if self.play_mode.get() == True: try: self.playbutton.config(text="Play") self.stream.close() self.stream.close() self.play_mode.set(False) except: print("stop failed") else: try: self.initStream() self.play_mode.set(True) self.playbutton.config(text="Stop") except: print("stop failed") def playbackMove(self, event=None): # move cursor by audio chunk size incr = (self.chunk_size) // self.hopsizes[self.currentplot] self.cursor.set_xdata(self.cursor.get_xdata() + incr) self.updateCursor() def new_release_zoom(self, *args, **kwargs): self.release_zoom_orig(*args, **kwargs) s = 'toolbar_event' event = Event(s, self) self.canvas.callbacks.process(s, Event('toolbar_event', self)) def new_release_pan(self, *args, **kwargs): self.release_pan_orig(*args, **kwargs) s = 'toolbar_event' event = Event(s, self) self.canvas.callbacks.process(s, Event('toolbar_event', self)) def new_update_view(self, *args, **kwargs): self._update_view_orig(*args, **kwargs) s = 'toolbar_event' event = Event(s, self) self.canvas.callbacks.process(s, Event('toolbar_event', self)) def handle_toolbar(self, event): self.canvas.draw() self.background = self.canvas.copy_from_bbox(self.mainplot.bbox) def onclick(self, event): if (self.toolbar._active == 'ZOOM' or self.toolbar._active == 'PAN'): pass elif (self.stamp > -1): self.stampHistory.append(self.stamp) self.timeValues[self.stamp].append(event.xdata * self.hopsizes[self.currentplot]) self.mainplot.draw_artist( self.mainplot.axvline(x=event.xdata, color=self.colors[self.stamp])) self.canvas.draw() self.background = self.canvas.copy_from_bbox(self.mainplot.bbox) self.info.set("Cursor") self.stamp = -1 else: self.cursor.set_xdata(event.xdata) self.wf.setpos(int(event.xdata * self.hopsizes[self.currentplot])) self.updateCursor() def updateCursor(self): self.canvas.restore_region(self.background) self.mainplot.draw_artist(self.cursor) self.canvas.blit(self.mainplot.bbox) def browse_file(self): self.filename = os.path.basename( tkFileDialog.askopenfilename(**self.file_opt)) self.filelocation.delete(0, END) self.filelocation.insert(0, self.file_opt['initialdir'] + self.filename) def changeparams(self, *args): self.featureParamsEntry.delete(0, END) try: self.featureParamsEntry.insert( 0, str(self.defaultParams[self.featurename.get()])) except: self.featureParamsEntry.insert(0, "()") print("No default params for selected feature") def showfeature(self): self.mainplot.clear() featureName = self.featurename.get() featureParams = eval(self.featureParamsEntry.get()) if featureName in self.calculated_features_dict and self.calculated_featuresParams[ featureName] != featureParams: # if a feature is calculated before and params are the same; plot the saved result self.currentplot = self.calculated_features_dict[featureName] if len(self.calculated_features[self.currentplot].shape) == 2: ylim = 5000 binToFreq = np.arange(0, ylim, 43.066) # Fs/N self.mainplot.pcolormesh( np.arange( self.calculated_features[self.currentplot].shape[0]), binToFreq, self.calculated_features[ self.currentplot].T[:binToFreq.size, :]) else: self.mainplot.plot(self.calculated_features[self.currentplot]) self.canvas.draw() self.background = self.canvas.copy_from_bbox(self.mainplot.bbox) hopSize = self.hopsizes[self.calculated_features_dict[featureName]] else: self.currentplot = len(self.calculated_features) self.calculated_features_dict[featureName] = self.currentplot result, hopSize = getattr(features, featureName)(self.audio, featureParams) if len(result.shape) == 2: ylim = 5000 binToFreq = np.arange(0, ylim, 43.066) # Fs/N self.mainplot.pcolormesh(np.arange(result.shape[0]), binToFreq, result.T[:binToFreq.size, :]) else: self.mainplot.plot(result) self.canvas.draw() self.background = self.canvas.copy_from_bbox(self.mainplot.bbox) self.calculated_features.append(result) self.hopsizes.append(hopSize) self.calculated_featuresParams[featureName] = featureParams self.drawAllStamps() def sendbelow(self): self.secplot.clear() if len(self.calculated_features[self.currentplot].shape) == 2: ylim = 5000 binToFreq = np.arange(0, ylim, 43.066) # Fs/N self.secplot.pcolormesh( np.arange(self.calculated_features[self.currentplot].shape[0]), binToFreq, self.calculated_features[ self.currentplot].T[:binToFreq.size, :]) else: self.secplot.plot(self.calculated_features[self.currentplot]) self.canvas.draw() def plot(self): self.discard() inputFile = self.filelocation.get() self.wf = wave.open(inputFile, 'rb') self.featurename.set("Audio") self.audio = MonoLoader(filename=inputFile, sampleRate=44100)() self.showfeature() self.cursor.set_xdata(0) self.canvaswidget.focus_set() if (self.ALoad.get() == 1): self.loadAnnotations() def saveAnnotations(self): directory = self.file_opt[ 'initialdir'] + "Annotations/" + self.filename.split('.')[ 0] # deleting .wav if not os.path.exists(directory): os.makedirs(directory) for i in self.labeldict: with open(directory + '/%s.txt' % self.labeldict[i], 'w') as filehandle: json.dump(self.timeValues[i], filehandle) def loadAnnotations(self): directory = self.file_opt[ 'initialdir'] + "Annotations/" + self.filename.split('.')[0] + "/" if not os.path.exists(directory): print("No annotations") else: for x in sorted(os.listdir(directory)): with open(directory + x, 'r') as filehandle: values = json.load(filehandle) if self.isTime.get() == 1: values = [v * 44100 for v in values] self.labeldict[len(self.labeldict)] = x.split('.')[0] var = IntVar() var.set(1) self.show.append(var) self.timeValues.append(values) def getNext(self): self.discard() fileList = sorted(os.listdir(self.file_opt['initialdir'])) nextIndex = fileList.index(self.filename) + 1 if nextIndex == 0 or nextIndex == len(fileList): print("No more files") else: self.filename = fileList[nextIndex] self.filelocation.delete(0, END) self.filelocation.insert( 0, self.file_opt['initialdir'] + fileList[nextIndex]) self.plot() def drawAllStamps(self): hs = self.hopsizes[self.currentplot] try: del self.mainplot.lines[1:] except: pass for i in self.labeldict: if self.show[i].get() == 1: for j in self.timeValues[i]: self.mainplot.draw_artist( self.mainplot.axvline(x=j // hs, color=self.colors[i])) self.canvas.draw() self.background = self.canvas.copy_from_bbox(self.mainplot.bbox) def saveAndNext(self): self.saveAnnotations() self.getNext() self.plot()
line, = ax.plot(evo.time, evo.data) ax.set_ylim([0, 100]) ax.get_xaxis().set_animated(True) #ax.get_yaxis().set_animated(True) line.set_animated(True) canvas.draw() background = canvas.copy_from_bbox(fig.bbox) # now redraw and blit ax.draw_artist(ax.get_xaxis()) ax.draw_artist(line) canvas.blit(ax.clipbox) while True: evo.update() line.set_xdata(evo.time) line.set_ydata(evo.getData()) ax.set_xlim([evo.time[0], evo.time[-1]]) #ax.set_ylim([max(evo.data),min(evo.data)]) # restore the background, draw animation,blit canvas.restore_region(background) ax.draw_artist(ax.get_xaxis()) #ax.draw_artist(ax.get_yaxis()) ax.draw_artist(line) canvas.blit(ax.clipbox) canvas.flush_events()
class FittingWindow: def __init__(self, master,ramanspectrum =None): global guessplot,dataplot self.master = master self.textframe= Frame(master = self.master) self.scroll = Tkinter.Scrollbar(self.textframe) self.scroll.grid(row=0,column=1) self.t = Tkinter.Text(self.textframe,yscrollcommand=self.scroll.set,width=30) self.scroll.config(command=self.t.yview) self.t.grid(row=0,column=0) self.plotframe = Frame(master = self.master) self.frame = Frame(master = self.master) self.textframe.grid(row=0,column=0,columnspan=3) self.plotframe.grid(row = 0, column = 3, columnspan = 11,sticky = 'ew') self.frame.grid(column = 1, row = 1,columnspan = 11, rowspan = 3,sticky = 'snew') self.buttonframe = Frame(master = self.master) self.buttonframe.grid(column=0, row =1) ############################## self.menubar = Menu(self.master) self.filemenu = Menu(self.menubar, tearoff=0) self.filemenu.add_command(label="New window", command = lambda: FittingWindow(Toplevel())) self.filemenu.add_command(label="Open", command = self.open_data) self.filemenu.add_command(label="Save",command = None) self.filemenu.add_command(label="SaveFig",command = None) self.filemenu.add_command(label="ViewNotebook",command = None) self.filemenu.add_command(label="Exit", command = self.quitproc) self.menubar.add_cascade(label="File", menu=self.filemenu) self.master.config(menu= self.menubar) ############################## self.fit_button = Tkinter.Button(master = self.buttonframe, command = self.fit_and_draw, width = 5, text = 'FitNow') self.fit_button.grid(row = 3, column = 0) self.open_button = Tkinter.Button(master = self.buttonframe, command = self.open_data, width = 5, text = 'open') self.open_button.grid(row = 4, column = 0) # self.open_ref_button = Tkinter.Button(master = self.buttonframe, command = self.open_ref, width = 5, text = 'Choose reference') # self.open_ref_button.grid(row = 5, column = 0) # self.open_bkg_button = Tkinter.Button(master = self.buttonframe, command = self.open_bkg, width = 5, text = 'Choose background') # self.open_bkg_button.grid(row = 6, column = 0) # # self.ref_label = Tkinter.Label(master = self.buttonframe, text = '') # self.ref_label.grid(row = 7, column = 0) # # self.bkg_label = Tkinter.Label(master = self.buttonframe, text = '') # self.bkg_label.grid(row = 8, column = 0) self.smoothbutton = Tkinter.Button(master = self.buttonframe, command = self.smoothdata, width = 5, text = 'Smooth') self.smoothbutton.grid(row = 5, column = 0) self.function_list=[ 'OneGaussian', 'TwoGaussian', 'ThreeGaussian', 'FourGaussian', 'FiveGaussian'] self.var_func = StringVar() self.var_func.set(self.function_list[0]) self.MotorMenu = OptionMenu(self.buttonframe,self.var_func, *self.function_list, command = self.init_function) self.MotorMenu.grid(row = 3,column =1,sticky = W) self.normalization_constant = 1 self.scale_list = [] self.var_list = [] self.fig = Figure(figsize=(5,3)) self.ax1 = self.fig.add_subplot(111) dataplot = self.ax1.plot(arange(2800,3605,5),zeros((161,)),animated = True)[0]#(ax = self.ax1).lines[-1] guessplot = self.ax1.plot(arange(2800,3605,5),zeros((161,)),animated = True)[0] self.canvas = FigureCanvasTkAgg(self.fig,master = self.plotframe) self.canvas.show() self.canvas._tkcanvas.pack(side=TOP, fill = BOTH,expand =True) self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.plotframe) self.toolbar.update() self.toolbar.pack(side= BOTTOM, fill = BOTH,expand =True)#,expand = True)#fill=BOTH)#, expand=1) self.canvas.draw() self.canvas.show() self.background = self.canvas.copy_from_bbox(self.ax1.bbox) self.reference = numpy.ndarray((161,)) self.reference[:] = 1 self.reference_name = '' self.guess = list() self.name = [''] if ramanspectrum is None: self.a = pandas.Series(zeros(161),arange(2800,3605,5)) else: self.a = copy(ramanspectrum) print self.a self.t.insert(END,'data multiplied by'+str(1/max(self.a))) self.a[:]/=max(self.a.values) self.startfreq_text = Entry(self.buttonframe,width = 5) self.startfreq = min(array(self.a.index)) self.startfreq_text.insert(END,str(self.startfreq)) self.startfreq_text.bind("<Return>", self.update_limits) self.startfreq_text.grid(row = 0 , column =1,sticky = W) self.endfreq_text = Entry(self.buttonframe,width = 5) self.endfreq = max(array(self.a.index)) self.endfreq_text.insert(END,str(self.endfreq)) self.endfreq_text.bind("<Return>", self.update_limits) self.endfreq_text.grid(row = 1 , column =1,sticky = W) if self.init_function('OneLorentzian') == -1: self.t.insert(END, 'error initializing fit function') self.ax1.cla() self.canvas.show() self.background = self.canvas.copy_from_bbox(self.ax1.bbox) dataplot = self.ax1.plot(array(self.a.index),self.a.values,animated=True)[0] x= array(self.a.index) guessplot = self.ax1.plot(x,zeros(self.a.size),animated=True)[0] self.ax1.set_xlim(min(self.a.index),max(self.a.index)) self.ax1.set_ylim(min(self.a.values),1) self.canvas.show() self.raw = self.a.copy self.startidx = 0 self.endidx = -1 self.update_limits(0) return None def nothing(self): return 0 def quitproc(self): self.master.destroy() return 0 def init_function(self,functiontype): global function import inspect if functiontype == None: functiontype = self.var_func.get() self.functiontype = functiontype if functiontype == 'OneLorentzian': def function(x,A1,w1,G1,m,b): return m*x/1000+b + A1**2/((x-w1)**2+G1**2) elif functiontype == 'TwoLorentzian': def function(x,A1,A2,w1,w2,G1,G2,m,b): return m*x/1000+b + A1**2/((x-w1)**2+G1**2) +A2**2/((x-w2)**2+G2**2) elif functiontype == 'ThreeLorentzian': def function(x,A1,A2,A3,w1,w2,w3,G1,G2,G3,m,b): return m*x/1000+b + A1**2/((x-w1)**2+G1**2) +A2**2/((x-w2)**2+G2**2) +A3**2/((x-w3)**2+G3**2) elif functiontype == 'FourLorentzian': def function(x,A1,A2,A3,A4,w1,w2,w3,w4,G1,G2,G3,G4,m,b): return m*x/1000+b + A1**2/((x-w1)**2+G1**2) +A2**2/((x-w2)**2+G2**2) +A3**2/((x-w3)**2+G3**2) +A4**2/((x-w4)**2+G4**2) elif functiontype == 'FiveLorentzian': def function(x,A1,A2,A3,A4,A5,w1,w2,w3,w4,w5,G1,G2,G3,G4,G5,m,b): return m*x/1000+b + A1**2/((x-w1)**2+G1**2) +A2**2/((x-w2)**2+G2**2) +A3**2/((x-w3)**2+G3**2) +A4**2/((x-w4)**2+G4**2)+A5**2/((x-w5)**2+G5**2) elif functiontype == 'OneGaussian': def function(x,A1,w1,G1,m,b): return m*x/1000+b + A1*exp(-(x-w1)**2/G1) elif functiontype == 'TwoGaussian': def function(x,A1,A2,w1,w2,G1,G2,m,b): return A1*exp(-(x-w1)**2/G1) +A2*exp(-(x-w2)**2/G2) +m*x/1000+b elif functiontype == 'ThreeGaussian': def function(x,A1,A2,A3,w1,w2,w3,G1,G2,G3,m,b): return m*x/1000+b + A1*exp(-(x-w1)**2/G1) +A2*exp(-(x-w2)**2/G2) +A3*exp(-(x-w3)**2/G3) elif functiontype == 'FourGaussian': def function(x,A1,A2,A3,A4,w1,w2,w3,w4,G1,G2,G3,G4,m,b): return m*x/1000+b +A1*exp(-(x-w1)**2/G1) +A2*exp(-(x-w2)**2/G2) +A3*exp(-(x-w3)**2/G3) +A4*exp(-(x-w4)**2/G4) elif functiontype == 'FiveGaussian': def function(x,A1,A2,A3,A4,A5,w1,w2,w3,w4,w5,G1,G2,G3,G4,G5,m,b): return m*x/1000+b + (A1/G1*numpy.sqrt(2*pi))*exp(-(x-w1)**2/(2*G1**2)) +(A2/G2*numpy.sqrt(2*pi))*exp(-(x-w2)**2/(2*G2**2)) +(A3/G3*numpy.sqrt(2*pi))*exp(-(x-w3)**2/(2*G3**2)) +(A4/G4*numpy.sqrt(2*pi))*exp(-(x-w4)**2/(2*G4**2)) +(A5/G5*numpy.sqrt(2*pi))*exp(-(x-w5)**2/(2*G5**2)) else: tkMessageBox.showerror('Not regconized function') def function(x,m,b): return m*x/1000+b #============================================================================== self.w_name = list() self.w_name = inspect.getargspec(function).args[1:] self.guess= [] for w in self.w_name: if 'A' in w: self.guess.append(0.1) elif 'w' in w: self.guess.append(1000) elif 'G' in w: self.guess.append(10) else: self.guess.append(0) #================================================================================ for i in range(len(self.scale_list),len(self.w_name)): self.scale_list.append(Scale(master = self.frame,command = self.guessdraw)) for i in range(len(self.w_name),len(self.scale_list)): self.scale_list[i].grid_forget() for i in range(len(self.w_name)): self.scale_list[i].config(label = self.w_name[i]) self.scale_list[i].grid(row = int(i/8), column = i%8) if self.w_name[i][0] == 'A': self.scale_list[i].config(from_ =0, to = 5,resolution = 0.1) self.scale_list[i].set(1) elif self.w_name[i][0] == 'w': self.scale_list[i].config(from_ = self.startfreq-20, to = self.endfreq+20,resolution = 1) self.scale_list[i].set(2800) elif self.w_name[i][0] == 'G': self.scale_list[i].config(from_ = 1, to = 50) self.scale_list[i].set(7) elif self.w_name[i][0] == 'm': self.scale_list[i].config(from_ = -5, to = 5, resolution = 0.05) self.scale_list[i].set(0) elif self.w_name[i][0] == 'b': self.scale_list[i].config(from_ = -5, to = 5, resolution = 0.05) self.scale_list[i].set(0) else: self.t.insert(END, "Variable not recognized:", self.w_name[i] ) self.scale_list[i].bind('<B1-Motion>',self.guessdraw) return 0 def smoothdata(self): self.a.smoooth() self.guessdraw(0) def update_limits(self,extra): functiontype = self.var_func.get() self.startfreq = max(float(self.startfreq_text.get()),min(array(self.a.index))) self.endfreq = min(float(self.endfreq_text.get()),max(array(self.a.index))) self.startidx = self.a.nearest(self.startfreq) self.endidx = self.a.nearest(self.endfreq) for i in range(len(self.guess)): self.guess[i] = self.scale_list[i].get() self.ax1.cla() self.canvas.show() self.background = self.canvas.copy_from_bbox(self.ax1.bbox) dataplot = self.ax1.plot(array(self.a.index[self.startidx:self.endidx]),self.a.values[self.startidx:self.endidx],animated=True)[0]#(ax = self.ax1).lines[-1] x= array(self.a.index[self.startidx:self.endidx]) guessplot = self.ax1.plot(x,zeros(x.size),animated=True)[0] #self.ax1.set_xlim(min(self.a.index),max(self.a.index)) #self.ax1.set_ylim(min(self.a.values),1) self.canvas.show() self.guessdraw(0) return 0 def open_data(self): global dataplot,guessplot self.name = self.DisplaySpectrum() if self.name == -1: return 0 try: self.a = RamanSpectrum(self.name) self.normalization_constant= 1/max(self.a) self.startfreq = min(array(self.a.index)) self.startfreq_text.insert(END,str(self.startfreq)) self.endfreq = max(array(self.a.index)) self.endfreq_text.insert(END,str(self.endfreq)) except: self.t.insert(END, 'error opening spectrum') return -1 self.raw = self.a.copy self.ax1.cla() self.canvas.show() self.background = self.canvas.copy_from_bbox(self.ax1.bbox) dataplot = self.ax1.plot(array(self.a.index),self.a.values,animated=True)[0]#(ax = self.ax1).lines[-1] x= array(self.a.index) guessplot = self.ax1.plot(x,zeros(self.a.size),animated=True)[0] self.ax1.set_xlim(min(self.a.index),max(self.a.index)) self.ax1.set_ylim(min(self.a.values),1) self.canvas.show() self.update_limits(0) return 0 def open_ref(self): pass return 0 def open_bkg(self): pass return 0 def recalc_data(self): if self.raw.shape == self.reference.shape: self.a= SG_Smooth(self.raw,width = 11,order = 3)/self.reference/self.normalization_constant self.ax1.cla() plot(self.a[0],self.raw/self.reference) plot(self.a[0],self.a[1]) else: self.t.insert(END, "reference invalid") self.reference_name = "No IR Reference" self.ax1.cla() self.ax1.plot(self.a[0],self.a[1]) self.canvas.draw() return 0 def guessdraw(self,ex): global function,guessplot,dataplot x = array(self.a.index[self.startidx:self.endidx+1]) for i in range(len(self.guess)): self.guess[i] = self.scale_list[i].get() self.canvas.restore_region(self.background) self.ax1.lines[-1].set_xdata(x) self.ax1.lines[-1].set_ydata(function(x,*self.guess)) for l in self.ax1.lines: self.ax1.draw_artist(l) self.canvas.blit(self.ax1.bbox) return 0 def fit_and_draw(self): global function print type(self.a) if type(self.a) == pandas.core.series.Series: self.a = RamanSpectrum(self.a) #result = fitspectrum(self.a, (float(self.a.index[self.startidx]),float(self.a.index[self.endidx+1])),'Custom',self.guess,function = function) print self.guess result = fitspectrum(self.a, (self.startfreq,self.endfreq),'Custom',self.guess,function = function) fittingparameters = result[0] xfit = result[1] yfit = result[2] if result == -1: tkMessageBox.showerror('Fit Failed') return 0 z = list(fittingparameters[0]) self.canvas.restore_region(self.background) self.ax1.lines[-1].set_xdata(xfit) self.ax1.lines[-1].set_ydata(yfit) for l in self.ax1.lines: self.ax1.draw_artist(l) for i in range(len(self.w_name)): #self.scale_list[i].set(result[0][i]) if "w" in self.w_name[i]: self.ax1.axvline(x = z[i], ymin = 0, ymax = 1 ,color = 'r') self.canvas.blit(self.ax1.bbox) self.t.insert(END, " \nResult Found for " + str(self.name)) self.t.insert(END, " \nReferenced to IR spectrum " +self.reference_name) self.t.insert(END, " \nNormalized by constant "+str(self.normalization_constant)) for i in range(len(self.w_name)): self.t.insert(END, ' \n'+self.w_name[i]+': '+str(z[i])) return 0 def DisplaySpectrum(self): import re global name_list, str_name_list file_opt = options = {} options['defaultextension'] = '.spe' options['filetypes'] = [('all files', '.*'),('SPE files', '.SPE'), ('csv files','.csv'),('text files','.txt')] options['title'] = 'Open Spectrum...' options['initialdir'] = '/home/chris/Documents/DataWeiss' str_name_list = tkFileDialog.askopenfilename(**options) if str_name_list == '': return -1 return str_name_list
class App(Tk): def __init__(self): Tk.__init__(self) self.title("Baja GUI") self.grid() cw = 1 # cell width ch = 2 cr = self.winfo_screenwidth() / 32 print(self.winfo_screenheight()) print(self.winfo_screenwidth()) # Root level frames self.controlFrame = Frame(self, bg='grey', borderwidth=0, width=self.winfo_screenwidth(), height=(self.winfo_screenheight()/4)) self.displayFrame = Frame(self, bg='grey', borderwidth=0) # Serial Control Frame self.serialFrame = Frame(self.controlFrame, borderwidth=0) self.COMPort = StringVar() self.COMPortTextBox = Entry(self.serialFrame, textvariable = self.COMPort) self.COMPort.set('/dev/ttyUSB0') self.COMBaud = StringVar() self.COMBaudTextBox = Entry(self.serialFrame, textvariable = self.COMBaud) self.COMBaud.set('9600') self.COMButton = Button(self.serialFrame, text = "Start Serial", command = self.StartSerial) self.SerialSendButton = Button(self.serialFrame, text = "Send to Board", command = self.SendToSerial) self.SerialSendToDriverButton = Button(self.serialFrame, text = "Send to Driver", command = self.SendToDriver) self.SerialSendTextBox = Entry(self.serialFrame) # Extra Buttons self.SerialStopButton = Button(self.serialFrame, text = "Stop Serial", command = self.StopSerial) self.comeBackToPitNowButton = Button(self.controlFrame, text = "Pit Now", command = self.PitNow) self.comeBackToPitNextLapButton = Button(self.controlFrame, text = "Pit Next Lap", command = self.PitNextLap) # Informative Things self.dataBarFrame = Frame(self.controlFrame) self.numActiveThreads = StringVar() self.numThreadsLabel = Label(self.dataBarFrame, textvariable = self.numActiveThreads) self.numActiveThreads.set('Threads\n' + str(threading.enumerate().__len__())) self.numThreadsLabel.grid(column = 0, row = 0) self.counter = StringVar() self.counterLabel = Label(self.dataBarFrame, textvariable = self.counter) self.counter.set('Counter\n' + 'N/A') self.counterLabel.grid(column = 1, row = 0) self.gpsDate = StringVar() self.gpsDateLabel = Label(self.dataBarFrame, textvariable = self.gpsDate) self.gpsDate.set('Date\n' + '010100') self.gpsDateLabel.grid(column = 2, row = 0) self.gpsTime = StringVar() self.gpsTimeLabel = Label(self.dataBarFrame, textvariable = self.gpsTime) self.gpsTime.set('Time\n' + '00000000') self.gpsTimeLabel.grid(column = 3, row = 0) self.numSats = StringVar() self.numSatsLabel = Label(self.dataBarFrame, textvariable = self.numSats) self.numSats.set('Sats\n' + 'NSA') self.numSatsLabel.grid(column = 4, row = 0) self.currentLatitude = StringVar() self.latitudeLabel = Label(self.dataBarFrame, textvariable = self.currentLatitude) self.currentLatitude.set("Latitude\n" + 'Unknown') self.latitudeLabel.grid(column = 5, row = 0) self.currentLongitude = StringVar() self.longitudeLabel = Label(self.dataBarFrame, textvariable = self.currentLongitude) self.currentLongitude.set("Longitude\n" + 'Unknown') self.longitudeLabel.grid(column = 6, row = 0) self.currentSpeed = StringVar() self.speedLabel = Label(self.dataBarFrame, textvariable=self.currentSpeed) self.currentSpeed.set("Speed\n" + "86") self.speedLabel.grid(column = 7, row = 0) self.currentDashTemp = StringVar() self.dashTempLabel = Label(self.dataBarFrame, textvariable=self.currentDashTemp) self.currentDashTemp.set("Dash Temp\n" + "N/A") self.dashTempLabel.grid(column = 8, row = 0) self.batteryVoltage = StringVar() self.batteryVoltageLabel = Label(self.dataBarFrame, textvariable = self.batteryVoltage) self.batteryVoltage.set("BATT\n" + "N/A") self.batteryVoltageLabel.grid(column = 9, row = 0) self.xbeeSignalStrength = StringVar() self.xbeeSignalStrengthLabel = Label(self.dataBarFrame, textvariable = self.xbeeSignalStrength) self.xbeeSignalStrength.set("XBee\n" + "N/A") self.xbeeSignalStrengthLabel.grid(column = 10, row = 0) self.currentFrontBrakeAvg = StringVar() self.frontBrakeAvgLabel = Label(self.dataBarFrame, textvariable = self.currentFrontBrakeAvg) self.currentFrontBrakeAvg.set("Front Brake Avg\n" + "N/A") self.frontBrakeAvgLabel.grid(column = 11, row = 0) self.currentFrontBrakeMax = StringVar() self.frontBrakeMaxLabel = Label(self.dataBarFrame, textvariable = self.currentFrontBrakeMax) self.currentFrontBrakeMax.set("Front Brake Max\n" + "N/A") self.frontBrakeMaxLabel.grid(column = 12, row = 0) self.currentRearBrakeAvg = StringVar() self.rearBrakeAvgLabel = Label(self.dataBarFrame, textvariable = self.currentRearBrakeAvg) self.currentRearBrakeAvg.set("Rear Brake Avg\n" + "N/A") self.rearBrakeAvgLabel.grid(column = 13, row = 0) self.currentRearBrakeMax = StringVar() self.rearBrakeMaxLabel = Label(self.dataBarFrame, textvariable = self.currentRearBrakeMax) self.currentRearBrakeMax.set("Rear Brake Max\n" + "N/A") self.rearBrakeMaxLabel.grid(column = 14, row = 0) self.currentSteeringAvg = StringVar() self.steeringAvgLabel = Label(self.dataBarFrame, textvariable = self.currentSteeringAvg) self.currentSteeringAvg.set("Steering\n" + "Yes") self.steeringAvgLabel.grid(column = 15, row = 0) self.buttonPressed = StringVar() self.buttonPressedLabel = Label(self.dataBarFrame, textvariable = self.buttonPressed, borderwidth = 1) self.buttonPressed.set("Button\n" + "No") self.buttonPressedLabel.grid(column = 16, row = 0) self.currentPrimaryRPM = StringVar() self.currentSecondaryRPM = StringVar() # Accelerometer self.accX = [0] self.maxX = [0] self.accY = [0] self.maxY = [0] self.accZ = [0] self.maxZ = [0] # self.rearTemp = [0] self.listbox = Listbox(self.controlFrame) # Set to full screen self.attributes('-fullscreen', True) # Bind <Return> Keypress to text boxes self.SerialSendTextBox.bind("<Return>", self.SendOnReturn) self.COMBaudTextBox.bind("<Return>", self.StartSerialOnReturn) # Pack Serial Controls into Serial Frame self.SerialSendTextBox.grid(column = 0, row=0, sticky=EW) self.SerialSendButton.grid(column = 2, row=0) self.SerialSendToDriverButton.grid(column = 3, row = 0) self.COMPortTextBox.grid(column = 4, row=0, sticky = E) self.COMBaudTextBox.grid(column=6, row=0, sticky = E) self.COMButton.grid(column = 8, row=0, sticky = NE) self.SerialStopButton.grid(row = 0, column = 9, sticky=NE) # Pack Control Widgets into Control Frame self.serialFrame.grid(row = 0, column=0, columnspan=12, sticky=EW) self.comeBackToPitNowButton.grid(row=0, column=10, sticky=NSEW) self.comeBackToPitNextLapButton.grid(row=1, column=10, sticky=NSEW) self.dataBarFrame.grid(row = 1, column = 0, columnspan = 10, sticky = EW) self.listbox.grid(row = 2, column = 0, columnspan=10, sticky = EW) # Pack Control Frame into root self.controlFrame.grid(row = 0, sticky=EW) # Top Level Display Frames self.leftDisplayFrame = Frame(self.displayFrame, bg='grey', borderwidth=0, width=(self.winfo_screenwidth()/2)) self.rightDisplayFrame = Frame(self.displayFrame, bg='grey', borderwidth=0, width=(self.winfo_screenwidth()/2)) # Inside Left Display Frames self.topLeftDisplayFrame = Frame(self.leftDisplayFrame, bg='grey', borderwidth=0, height=(self.winfo_screenheight()/4)) self.middleLeftDisplayFrame = Frame(self.leftDisplayFrame, bg='grey', borderwidth=0, height=(self.winfo_screenheight()/4)) self.bottomLeftDisplayFrame = Frame(self.leftDisplayFrame, bg='grey', borderwidth=0, height=(self.winfo_screenheight()/4)) # Inside Top Left Display Frames # Inside Middle Left Display Frames self.brakeFrame = Frame(self.middleLeftDisplayFrame, borderwidth=0) # Inside Bottom Left Display Frames self.driveTrainTempFrame = Frame(self.bottomLeftDisplayFrame, borderwidth=0) self.driveTrainRPMFrame = Frame(self.bottomLeftDisplayFrame, borderwidth=0) # Inside Rigt Display Frames self.shieldTempFrame = Frame(self.rightDisplayFrame, borderwidth=0, bg='grey', height=(self.winfo_screenheight()/8)) self.shieldHealthFrame = Frame(self.rightDisplayFrame, borderwidth=0, bg='grey') # Construct Items for Display Frame self.gpsFigure, self.gpsAxes = plt.subplots(figsize=(2*ch,2*ch), dpi=cr*2) self.speedFigure, self.speedAxes = plt.subplots(figsize=(2*ch,2*ch), dpi=cr) self.rpmFigure, self.rpmAxes = plt.subplots(figsize=(ch,ch), dpi=cr) self.dashTempFigure, self.dashTempAxes = plt.subplots(figsize=(2*ch,ch), dpi=cr) self.rearTempFigure, self.rearTempAxes = plt.subplots(figsize=(2*ch,ch), dpi=cr) self.gearTempFigure, self.gearTempAxes = plt.subplots(figsize=(2*ch,ch), dpi=cr) self.cvtTempFigure, self.cvtTempAxes = plt.subplots(figsize=(2*ch,ch), dpi=cr) self.battFigure, self.battAxes = plt.subplots(figsize=(ch,ch), dpi=cr) self.frontBrakeFigure, self.frontBrakeAxes = plt.subplots(figsize=(2*ch,ch), dpi=cr) self.rearBrakeFigure, self.rearBrakeAxes = plt.subplots(figsize=(2*ch,ch), dpi=cr) self.steeringFigure, self.steeringAxes = plt.subplots(figsize=(ch,2*ch), dpi=cr) self.buttonFigure, self.buttonGraph = plt.subplots(figsize=(ch,ch), dpi=cr) self.accFigure, self.accAxes = plt.subplots(figsize=(2*ch,2*ch), dpi=cr) self.zFigure, self.zAxes = plt.subplots(figsize=(ch, 2*ch), dpi=cr) # GPS Axes Setup self.gpsFigure.patch.set_visible(False) self.gpsAxes.set_title('GPS') #self.gpsAxes.set_xlim(-110.953,-110.952) self.gpsAxes.set_xlim(-118823207 - 3000,-118823207 + 3000) self.gpsAxes.set_ylim(34749085 - 3000,34749085 + 3000) self.gpsAxes.hold(True) self.gpsCanvas = FigureCanvasTkAgg(self.gpsFigure, master=self.rightDisplayFrame) self.gpsCanvas.show() # speed Axes Setup self.speedFigure.patch.set_visible(False) self.speedAxes.set_title('Speed') self.speedAxes.set_xlim(0,100) self.speedAxes.set_ylim(0,50) self.speedAxes.hold(True) self.speedCanvas = FigureCanvasTkAgg(self.speedFigure, master=self.topLeftDisplayFrame) self.speedCanvas.show() # Speed Textbox Setup # Dash Temperature Axes Setup self.dashTempFigure.patch.set_visible(False) self.dashTempAxes.set_title('Dash Temperature') # self.ten_wide = [0,1,2,3,4,5,6,7,8,9] self.dashTempAxes.set_xlim(0,100) # self.dashTempAxes.autoscale(enable=True, axis='x') self.dashTempAxes.set_ylim(0,100) self.dashTempAxes.hold(True) self.dashTempCanvas = FigureCanvasTkAgg(self.dashTempFigure, master=self.shieldTempFrame) self.dashTempCanvas.show() # self.dashTempCanvas.draw() # Rear Temperature Axes Setup self.rearTempFigure.patch.set_visible(False) self.rearTempAxes.set_title('Rear Temperature') self.rearTempAxes.set_xlim(0,500) self.rearTempAxes.set_ylim(0,100) self.rearTempAxes.hold(True) self.rearTempCanvas = FigureCanvasTkAgg(self.rearTempFigure, master=self.shieldTempFrame) self.rearTempCanvas.show() # # Gearbox Temperature Axes Setup self.gearTempFigure.patch.set_visible(False) self.gearTempAxes.set_title('Gearbox Temperature') self.gearTempAxes.set_xlim(0,500) self.gearTempAxes.set_ylim(0,100) self.gearTempAxes.hold(True) self.gearTempCanvas = FigureCanvasTkAgg(self.gearTempFigure, master=self.driveTrainTempFrame) self.gearTempCanvas.show() # # CVT Temperature Axes Setup self.cvtTempAxes.set_title('CVT Temperature') self.cvtTempAxes.set_xlim(0,500) self.cvtTempAxes.set_ylim(0,100) self.cvtTempAxes.hold(True) self.cvtTempCanvas = FigureCanvasTkAgg(self.cvtTempFigure, master=self.driveTrainTempFrame) self.cvtTempCanvas.show() # # Acceleration Axes Setup self.accFigure.patch.set_visible(False) self.accAxes.set_title('Acceleration 2-D') self.accAxes.set_xlim(-2, 2) self.accAxes.set_ylim(-2, 2) self.accAxes.hold(True) self.accCanvas = FigureCanvasTkAgg(self.accFigure, master=self.middleLeftDisplayFrame) self.accCanvas.show() self.zFigure.patch.set_visible(False) self.zAxes.set_title('Z-Acc') self.zAxes.set_xlim(-2, 2) self.zAxes.set_ylim(-2, 2) self.zAxes.hold(True) self.zCanvas = FigureCanvasTkAgg(self.zFigure, master=self.topLeftDisplayFrame) self.zCanvas.show() self.steeringFigure.patch.set_visible(False) self.steeringAxes.set_title('Steering') self.steeringAxes.set_xlim(-2, 2) self.steeringAxes.set_ylim(-2, 2) self.steeringAxes.hold(True) self.steeringCanvas = FigureCanvasTkAgg(self.steeringFigure, master=self.topLeftDisplayFrame) self.steeringCanvas.show() # Front Brake Axes Setup self.frontBrakeFigure.patch.set_visible(False) self.frontBrakeAxes.set_title('Front Brake Pressure') self.frontBrakeAxes.set_xlim(0,500) self.frontBrakeAxes.set_ylim(0,100) self.frontBrakeAxes.hold(True) self.frontBrakeCanvas = FigureCanvasTkAgg(self.frontBrakeFigure, master=self.brakeFrame) self.frontBrakeCanvas.show() # Rear Brake Axes Setup self.rearBrakeFigure.patch.set_visible(False) self.rearBrakeAxes.set_title('Rear Brake Pressure') self.rearBrakeAxes.set_xlim(0,500) self.rearBrakeAxes.set_ylim(0,100) self.rearBrakeAxes.hold(True) self.rearBrakeCanvas = FigureCanvasTkAgg(self.rearBrakeFigure, master=self.brakeFrame) self.rearBrakeCanvas.show() # Layout # Pack Brake Pressure self.frontBrakeCanvas.get_tk_widget().grid(column = 0, row=0, sticky=N) # self.frontBrakeCanvas._tkcanvas.grid(column=0, row=0, sticky=N) self.rearBrakeCanvas.get_tk_widget().grid(column=0, row=1, sticky=S) # self.rearBrakeCanvas._tkcanvas.grid(column=0, row=1, sticky=S) # Pack Drive Train RPM # Pack Drive Train Temp self.gearTempCanvas.get_tk_widget().grid(column = 0, row=0, sticky=W) # self.gearTempCanvas._tkcanvas.grid(column=0, row=0, sticky=W) self.cvtTempCanvas.get_tk_widget().grid(column=1, row=0, sticky=E) # self.cvtTempCanvas._tkcanvas.grid(column=1, row=0, sticky=E) # Pack stuff into top left # self.speedTextBox.grid(column=1, row=0, sticky=NSEW) self.zCanvas.get_tk_widget().grid(column=0, row=0, sticky=NSEW) self.steeringCanvas.get_tk_widget().grid(column=1, row=0, sticky=NSEW) self.speedCanvas.get_tk_widget().grid(column=2, row=0 , sticky=NSEW) # self.speedCanvas._tkcanvas.grid(column=2 , row=0 , sticky=NSEW) # Pack stuff into middle left self.accCanvas.get_tk_widget().grid(column=0 , row=1 , sticky=W ) # self.accCanvas._tkcanvas.grid(column=0 , row=1 , sticky=W ) self.brakeFrame.grid(column=1 , row=1 , sticky=E) # Pack stuff into bottom left self.driveTrainTempFrame.grid(column=0 , row=5 , sticky=N ) self.driveTrainRPMFrame.grid(column=0 , row=6 , sticky=S ) # Pack Left Display self.topLeftDisplayFrame.grid(column=0 , row=2 , sticky=NSEW ) self.middleLeftDisplayFrame.grid(column=0 , row=4 , sticky=NSEW ) self.bottomLeftDisplayFrame.grid(column=0 , row=6 , sticky=NSEW ) # Pack Shield Temp self.dashTempCanvas.get_tk_widget().grid(column=0 , row=5 ) # self.dashTempCanvas._tkcanvas.grid(column=0 , row=5 , sticky=W ) self.rearTempCanvas.get_tk_widget().grid(column=1 , row=5 ) # self.rearTempCanvas._tkcanvas.grid(column=1 , row=5 , sticky=E ) # Pack Shield Health # Pack stuff inside right display self.gpsCanvas.get_tk_widget().grid(column=4 , row=2 , sticky=NSEW ) # self.gpsCanvas._tkcanvas.grid(column=4 , row=2 , sticky=NSEW ) self.shieldTempFrame.grid(column=4 , row=5 , sticky=N ) self.shieldHealthFrame.grid(column=4 , row=6 , sticky=N ) # TODO: Button Press notification goes here... # Pack Display Frame self.leftDisplayFrame.grid(column=0 , row=3 , sticky=NS ) self.rightDisplayFrame.grid(column=5 , row=3 , sticky=NS ) # Pack Display Into Root self.displayFrame.grid(column=0 , row=2 , sticky=NSEW ) # Initialize Data Variables # Dash Data # self.counter.set(0) # Commented to preserve initial text value, left here to preserve variable order/index # self.gpsDate = 0 # self.gpsTime = 0 # self.numSats = 0 self.latitude = [32236562] self.longitude = [-110952322] self.speed = [0]*102 self.dashTemp = [0]*102 # self.batteryVoltage = 0 # self.xbeeSignalStrength = 0 self.frontBrakeAvg = [0] self.frontBrakeMax = [0] self.rearBrakeAvg = [0] self.rearBrakeMax = [0] self.steeringAvg = [0] # self.buttonPressed = 0 # Rear Board Data self.primaryRPM = 0 self.secondaryRPM = 0 # Accelerometer self.accX = [0] self.maxX = [0] self.accY = [0] self.maxY = [0] self.accZ = [0] self.maxZ = [0] # self.rearTemp = [0] self.hundred_array = list(range(0,102)) self.gpsBackground = self.gpsCanvas.copy_from_bbox(self.gpsAxes.bbox) self.speedBackground = self.speedCanvas.copy_from_bbox(self.speedAxes.bbox) self.dashTempBackground = self.dashTempCanvas.copy_from_bbox(self.dashTempAxes.bbox) self.gpsPlot = self.gpsAxes.plot(self.longitude, self.latitude, '-')[0] self.speedPlot = self.speedAxes.plot(self.hundred_array,self.speed)[0] self.dashTempPlot = self.dashTempAxes.plot(self.hundred_array, self.dashTemp)[0] # Create Queues for talking to serial line asyncronously self.rx = queue.Queue() self.tx = queue.Queue() def StartSerial(self): self.listbox.insert(0, "Baud Rate: " + self.COMBaud.get()) self.listbox.insert(0, "COM Port: " + self.COMPort.get()) self.numActiveThreads.set('Threads\n' + str(threading.enumerate().__len__())) if (threading.enumerate().__len__()!=1): self.serialThread.join() #print(threading.enumerate().__len__()) self.numActiveThreads.set('Threads\n' + str(threading.enumerate().__len__())) self.serialThread = SerialThread(self.COMPort, self.COMBaud, self.rx, self.tx) self.serialThread.start() self.numActiveThreads.set('Threads\n' + str(threading.enumerate().__len__())) self.process_serial() def StopSerial(self): self.listbox.insert(0, "Serial Stopped") if (threading.enumerate().__len__()!=1): self.serialThread.join() self.numActiveThreads.set('Threads\n' + str(threading.enumerate().__len__())) def PitNow(self): self.listbox.insert(0, "Pit Now") self.tx.put("<PIT NOW>\n") def PitNextLap(self): self.listbox.insert(0, "Pit Next Lap") self.tx.put("<PIT NEXT LAP>\n") def SendOnReturn(self, event): self.SendToSerial() def StartSerialOnReturn(self, event): self.StartSerial() def SendToSerial(self): text_contents = self.SerialSendTextBox.get() self.listbox.insert(0, text_contents) self.tx.put(text_contents) self.SerialSendTextBox.delete(0,END) def SendToDriver(self): text_contents = self.SerialSendTextBox.get() self.listbox.insert(0, text_contents) self.tx.put('<') self.tx.put(text_contents) self.tx.put('>') self.SerialSendTextBox.delete(0,END) def process_serial(self): text = StringVar() if self.rx.qsize(): # self.listbox.delete(0,END) try: dataString = self.rx.get() except Queue.Empty: pass self.listbox.insert(0, dataString) data = dataString.split(bytes(', ','UTF-8')) print(data.__len__()) if(data.__len__()==18 or data.__len__()==28): try: i = 0 # Dash Data self.counter.set('Counter\n' + str(int(data[0]))) i = 1 self.gpsDate.set('Date\n' + str(int(data[1]))) i = 2 self.gpsTime.set('Time\n' + str(int(data[2]))) i = 3 self.numSats.set('Sats\n' + str(int(data[3]))) if (float(data[4])/1000000 < 100 and float(data[5])/1000000 < 200): i = 4 self.latitude.append(int(data[4])) self.currentLatitude.set('Latitude\n' + str(int(data[4]))) i = 5 self.longitude.append(int(data[5])) self.currentLongitude.set('Longitude\n' + str(int(data[5]))) i = 6 self.speed.append(float(data[6])) self.currentSpeed.set('Speed\n' + str(float(data[6]))) self.currentSpeed.set('Speed\n' + str(float(data[6]))) i = 7 self.dashTemp.append(float(data[7])) self.currentDashTemp.set('Dash Temp\n' + str(float(data[7])) + 'C') i = 8 self.batteryVoltage.set('Batt\n' + str(int(data[8]))) i = 9 self.xbeeSignalStrength.set('XBee\n' + str(int(data[9]))) i = 10 self.frontBrakeAvg.append(float(data[10])) i = 11 self.frontBrakeMax.append(int(data[11])) i = 12 self.rearBrakeAvg.append(float(data[12])) i = 13 self.rearBrakeMax.append(int(data[13])) i = 14 self.steeringAvg.append(float(data[14])) i = 15 # self.buttonPressed = int(data[15]) i = 16 # # # Rear Board Data # self.primaryRPM = 0 # self.secondaryRPM = 0 # # # # Accelerometer # self.accX = [0] # self.maxX = [0] # self.accY = [0] # self.maxY = [0] # self.accZ = [0] # self.maxZ = [0] # # # # self.rearTemp = [0] except: print('Exception Raised!' + str(i)) pass self.gpsCanvas.restore_region(self.gpsBackground) self.gpsPlot.set_data(self.longitude[1:], self.latitude[1:]) self.gpsAxes.draw_artist(self.gpsPlot) self.gpsCanvas.blit(self.gpsAxes.bbox) self.speedCanvas.restore_region(self.speedBackground) self.speedPlot.set_data(self.hundred_array[-101:], self.speed[-101:]) self.speedAxes.draw_artist(self.speedPlot) self.speedCanvas.blit(self.speedAxes.bbox) self.dashTempCanvas.restore_region(self.dashTempBackground) self.dashTempPlot.set_data(self.hundred_array[-101:], self.dashTemp[-101:]) self.dashTempAxes.draw_artist(self.dashTempPlot) self.dashTempCanvas.blit(self.dashTempAxes.bbox) self.after(100, self.process_serial) # Graceful Exit def destroy(e): sys.exit()
class Viewer(tk.Frame): def __init__(self, parent, collection=None, with_toolbar=True): tk.Frame.__init__(self, parent) # toolbar if with_toolbar: self.create_toolbar() # canvas #canvas_frame = tk.Frame(self) #canvas_frame.pack(side=tk.LEFT,fill=tk.BOTH,expand=1) #title_frame = tk.Frame(canvas_frame) #title_frame.pack(side=tk.TOP,anchor=tk.NW) #tk.Label(title_frame,text=" Plot Title: ").pack(side=tk.LEFT) #self._title = tk.Entry(title_frame,width=30) #self._title.pack(side=tk.LEFT) #tk.Button(title_frame, text='Set', command=lambda: self.updateTitle() # ).pack(side=tk.LEFT) self.fig = plt.Figure(figsize=(8, 6)) self.ax = self.fig.add_subplot(111) self.canvas = FigureCanvasTkAgg(self.fig, master=self) self.setupMouseNavigation() self.navbar = ToolBar(self.canvas, self, self.ax) # for matplotlib features self.setupNavBarExtras(self.navbar) self.canvas.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=1) # spectra list self.create_listbox() # toggle options self.mean = False self.median = False self.max = False self.min = False self.std = False self.spectrum_mode = False self.show_flagged = True # data self.collection = collection self.head = 0 self.flag_filepath = os.path.abspath('./flagged_spectra.txt') if collection: self.update_artists(new_lim=True) self.update_list() # pack self.pack(fill=tk.BOTH, expand=1) self.color = '#000000' def returnToSelectMode(self): if self.ax.get_navigate_mode() == 'PAN': #Turn panning off self.navbar.pan() elif self.ax.get_navigate_mode() == 'ZOOM': #Turn zooming off self.navbar.zoom() def setupNavBarExtras(self, navbar): working_dir = os.path.dirname(os.path.abspath(__file__)) img = Image.open(os.path.join(working_dir, "select.png")) #self.select_icon = tk.PhotoImage(file=os.path.join(working_dir,"select.png")) self.select_icon = tk.PhotoImage(img) self.select_button = tk.Button(navbar, width="24", height="24", image=img, command=self.returnToSelectMode).pack( side=tk.LEFT, anchor=tk.W) self.dirLbl = tk.Label(navbar, text="Viewing: None") self.dirLbl.pack(side=tk.LEFT, anchor=tk.W) def plotConfig(self): config = PlotConfigDialog(self, title=self.ax.get_title(), xlabel=self.ax.get_xlabel(), ylabel=self.ax.get_ylabel(), xlim=self.ax.get_xlim(), ylim=self.ax.get_ylim()) if (config.applied): print(config.title) print(config.xlim) self.ax.set_title(config.title) self.ax.set_xlabel(config.xlabel) self.ax.set_ylabel(config.ylabel) self.ax.set_xlim(*config.xlim) self.ax.set_ylim(*config.ylim) self.canvas.draw() def rectangleStartEvent(self, event): self._rect = None self._rect_start = event def rectangleMoveEvent(self, event): try: dx = event.xdata - self._rect_start.xdata dy = event.ydata - self._rect_start.ydata except TypeError: #we're out of canvas bounds return if self._rect is not None: self._rect.remove() self._rect = Rectangle( (self._rect_start.xdata, self._rect_start.ydata), dx, dy, color='k', ls='--', lw=1, fill=False) self.ax.add_patch(self._rect) self.ax.draw_artist(self._rect) def rectangleEndEvent(self, event): if self._rect is not None: self._rect.remove() else: #make a small, fake rectangle class FakeEvent(object): def __init__(self, x, y): self.xdata, self.ydata = x, y dy = (self.ax.get_ylim()[1] - self.ax.get_ylim()[0]) / 100. self._rect_start = FakeEvent(event.xdata - 10, event.ydata + dy) event = FakeEvent(event.xdata + 10, event.ydata - dy) if not self.collection is None: x0 = min(self._rect_start.xdata, event.xdata) x1 = max(self._rect_start.xdata, event.xdata) y0 = min(self._rect_start.ydata, event.ydata) y1 = max(self._rect_start.ydata, event.ydata) try: #if our data is sorted, we can easily isolate it x_data = self.collection.data.loc[x0:x1] except: #Pandas builtin throws an error, use another pandas builtin data = self.collection.data in_xrange = (data.index >= x0) & (data.index <= x1) x_data = data.iloc[in_xrange] ylim = sorted([self._rect_start.ydata, event.ydata]) is_in_box = ((x_data > y0) & (x_data < y1)).any() highlighted = is_in_box.index[is_in_box].tolist() key_list = list(self.collection._spectra.keys()) self.update_selected(highlighted) flags = self.collection.flags for highlight in highlighted: #O(n^2) woof if (not (highlight in flags)) or self.show_flagged: pos = key_list.index(highlight) self.listbox.selection_set(pos) def setupMouseNavigation(self): self.clicked = False self.select_mode = 'rectangle' self._bg_cache = None START_EVENTS = {'rectangle': self.rectangleStartEvent} MOVE_EVENTS = {'rectangle': self.rectangleMoveEvent} END_EVENTS = {'rectangle': self.rectangleEndEvent} def onMouseDown(event): if self.ax.get_navigate_mode() is None: self._bg_cache = self.canvas.copy_from_bbox(self.ax.bbox) self.clicked = True START_EVENTS[self.select_mode](event) def onMouseUp(event): if self.ax.get_navigate_mode() is None: self.canvas.restore_region(self._bg_cache) self.canvas.blit(self.ax.bbox) self.clicked = False END_EVENTS[self.select_mode](event) def onMouseMove(event): if self.ax.get_navigate_mode() is None: if (self.clicked): self.canvas.restore_region(self._bg_cache) MOVE_EVENTS[self.select_mode](event) self.canvas.blit(self.ax.bbox) self.canvas.mpl_connect('button_press_event', onMouseDown) self.canvas.mpl_connect('button_release_event', onMouseUp) self.canvas.mpl_connect('motion_notify_event', onMouseMove) @property def head(self): return self._head @head.setter def head(self, value): if not hasattr(self, '_head'): self._head = 0 else: self._head = value % len(self.collection) def set_head(self, value): if isinstance(value, Iterable): if len(value) > 0: value = value[0] else: value = 0 self.head = value if self.spectrum_mode: self.update() self.update_selected() @property def collection(self): return self._collection @collection.setter def collection(self, value): if isinstance(value, Spectrum): # create new collection self._collection = Collection(name=Spectrum.name, spectra=[value]) if isinstance(value, Collection): self._collection = value else: self._collection = None def move_selected_to_top(self): selected = self.listbox.curselection() keys = [self.collection.spectra[s].name for s in selected] for s in selected[::-1]: self.listbox.delete(s) self.listbox.insert(0, *keys) self.listbox.selection_set(0, len(keys)) def unselect_all(self): self.listbox.selection_clear(0, tk.END) self.update_selected() def select_all(self): self.listbox.selection_set(0, tk.END) self.update_selected() def invert_selection(self): for i in range(self.listbox.size()): if self.listbox.selection_includes(i): self.listbox.selection_clear(i) else: self.listbox.selection_set(i) self.update_selected() def change_color(self): cpicker = ColorPickerDialog(self) #rgb,color = askcolor(self.color) if cpicker.applied: self.color = cpicker.color self.color_pick.config(bg=self.color) #update our list of chosen colors selected = self.listbox.curselection() selected_keys = [self.collection.spectra[s].name for s in selected] for key in selected_keys: self.colors[key] = self.color self.update() def select_by_name(self): pattern = self.name_filter.get() for i in range(self.listbox.size()): if pattern in self.listbox.get(i): self.listbox.selection_set(i) else: self.listbox.selection_clear(i) self.update_selected() def create_listbox(self): self._sbframe = tk.Frame(self) list_label = tk.Frame(self._sbframe) list_label.pack(side=tk.TOP, anchor=tk.N, fill=tk.X) tk.Label(list_label, text="Name:").pack(side=tk.LEFT, anchor=tk.W) self.name_filter = tk.Entry(list_label, width=14) self.name_filter.pack(side=tk.LEFT, anchor=tk.W) tk.Button(list_label, text="Select", command=lambda: self.select_by_name()).pack(side=tk.LEFT, anchor=tk.W) self.sblabel = tk.Label(list_label, text="Showing: 0") self.sblabel.pack(side=tk.RIGHT) self.scrollbar = tk.Scrollbar(self._sbframe) self.listbox = tk.Listbox(self._sbframe, yscrollcommand=self.scrollbar.set, selectmode=tk.EXTENDED, width=30) self.scrollbar.config(command=self.listbox.yview) self.list_tools = tk.Frame(self._sbframe) tk.Button(self.list_tools, text="To Top", command=lambda: self.move_selected_to_top()).pack( side=tk.TOP, anchor=tk.NW, fill=tk.X) tk.Button(self.list_tools, text="Select All", command=lambda: self.select_all()).pack(side=tk.TOP, anchor=tk.NW, fill=tk.X) tk.Button(self.list_tools, text="Clear", command=lambda: self.unselect_all()).pack(side=tk.TOP, anchor=tk.NW, fill=tk.X) tk.Button(self.list_tools, text="Invert", command=lambda: self.invert_selection()).pack(side=tk.TOP, anchor=tk.NW, fill=tk.X) self.color_field = tk.Frame(self.list_tools) tk.Label(self.color_field, text="Color:").pack(side=tk.LEFT) self.color_pick = tk.Button(self.color_field, text="", command=lambda: self.change_color(), bg='#000000') self.color_pick.pack(side=tk.RIGHT, anchor=tk.NW, fill=tk.X, expand=True) self.color_field.pack(side=tk.TOP, anchor=tk.NW, fill=tk.X) self.list_tools.pack(side=tk.RIGHT, anchor=tk.NW) self.scrollbar.pack(side=tk.RIGHT, anchor=tk.E, fill=tk.Y) self.listbox.pack(side=tk.RIGHT, anchor=tk.E, fill=tk.Y) self.listbox.bind('<<ListboxSelect>>', lambda x: self.set_head(self.listbox.curselection())) self._sbframe.pack(side=tk.RIGHT, anchor=tk.E, fill=tk.Y) def create_toolbar(self): self.toolbar = tk.Frame(self) tk.Button(self.toolbar, text='Read', command=lambda: self.read_dir()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='Mode', command=lambda: self.toggle_mode()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text="Plot Config", command=lambda: self.plotConfig()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='Show/Hide Flagged', command=lambda: self.toggle_show_flagged()).pack( side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='Flag/Unflag', command=lambda: self.toggle_flag()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='Unflag all', command=lambda: self.unflag_all()).pack(side=tk.LEFT, fill=tk.X, expand=1) #tk.Button(self.toolbar, text='Save Flag', command=lambda: # self.save_flag()).pack(side=tk.LEFT,fill=tk.X,expand=1) tk.Button(self.toolbar, text='Save Flags', command=lambda: self.save_flag_as()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='Stitch', command=lambda: self.stitch()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='Jump_Correct', command=lambda: self.jump_correct()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='mean', command=lambda: self.toggle_mean()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='median', command=lambda: self.toggle_median()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='max', command=lambda: self.toggle_max()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='min', command=lambda: self.toggle_min()).pack(side=tk.LEFT, fill=tk.X, expand=1) tk.Button(self.toolbar, text='std', command=lambda: self.toggle_std()).pack(side=tk.LEFT, fill=tk.X, expand=1) self.toolbar.pack(side=tk.TOP, fill=tk.X) def updateTitle(self): print("Hello world!") self.ax.set_title(self._title.get()) self.canvas.draw() def set_collection(self, collection): new_lim = True if self.collection is None else False self.collection = collection self.update_artists(new_lim=new_lim) self.update() self.update_list() def read_dir(self): try: directory = os.path.split( filedialog.askopenfilename(filetypes=( ("Supported types", "*.asd *.sed *.sig *.pico"), ("All files", "*"), )))[0] except: return if not directory: return c = Collection(name="collection", directory=directory) self.set_collection(c) self.dirLbl.config(text="Viewing: " + directory) def reset_stats(self): if self.mean_line: self.mean_line.remove() self.mean_line = None self.mean = False if self.median_line: self.median_line.remove() self.median_line = None self.median = False if self.max_line: self.max_line.remove() self.max_line = None self.max = False if self.min_line: self.min_line.remove() self.min_line = None self.min = False if self.std_line: self.std_line.remove() self.std_line = None self.std = False def toggle_mode(self): if self.spectrum_mode: self.spectrum_mode = False else: self.spectrum_mode = True self.update() def toggle_show_flagged(self): if self.show_flagged: self.show_flagged = False else: self.show_flagged = True self.update() def unflag_all(self): #new flags -> new statistics self.reset_stats() for spectrum in list(self.collection.flags): self.collection.unflag(spectrum) self.update() self.update_list() def toggle_flag(self): #new flags -> new statistics self.reset_stats() selected = self.listbox.curselection() keys = [self.listbox.get(s) for s in selected] for i, key in enumerate(keys): print(i, key) spectrum = key if spectrum in self.collection.flags: self.collection.unflag(spectrum) self.listbox.itemconfigure(selected[i], foreground='black') else: self.collection.flag(spectrum) self.listbox.itemconfigure(selected[i], foreground='red') # update figure self.update() def save_flag(self): ''' save flag to self.flag_filepath''' with open(self.flag_filepath, 'w') as f: for spectrum in self.collection.flags: print(spectrum, file=f) def save_flag_as(self): ''' modify self.flag_filepath and call save_flag()''' flag_filepath = filedialog.asksaveasfilename() if os.path.splitext(flag_filepath)[1] == '': flag_filepath = flag_filepath + '.txt' self.flag_filepath = flag_filepath self.save_flag() def update_list(self): self.listbox.delete(0, tk.END) for i, spectrum in enumerate(self.collection.spectra): self.listbox.insert(tk.END, spectrum.name) if spectrum.name in self.collection.flags: self.listbox.itemconfigure(i, foreground='red') self.update_selected() def ask_for_draw(self): #debounce canvas updates now = datetime.now() print(now - self.last_draw) if ((now - self.last_draw).total_seconds() > 0.5): self.canvas.draw() self.last_draw = now def update_artists(self, new_lim=False): if self.collection is None: return #update values being plotted -> redo statistics self.mean_line = None self.median_line = None self.max_line = None self.min_line = None self.std_line = None # save limits if new_lim == False: xlim = self.ax.get_xlim() ylim = self.ax.get_ylim() # plot self.ax.clear() # show statistics if self.spectrum_mode: idx = self.listbox.curselection() if len(idx) == 0: idx = [self.head] spectra = [self.collection.spectra[i] for i in idx] flags = [s.name in self.collection.flags for s in spectra] print("flags = ", flags) flag_style = ' ' if self.show_flagged: flag_style = 'r' artists = Collection(name='selection', spectra=spectra).plot( ax=self.ax, style=list(np.where(flags, flag_style, self.color)), picker=1) self.ax.set_title('selection') # c = str(np.where(spectrum.name in self.collection.flags, 'r', 'k')) # spectrum.plot(ax=self.ax, label=spectrum.name, c=c) else: # red curves for flagged spectra flag_style = ' ' if self.show_flagged: flag_style = 'r' flags = [ s.name in self.collection.flags for s in self.collection.spectra ] print("flags = ", flags) self.collection.plot(ax=self.ax, style=list(np.where(flags, flag_style, 'k')), picker=1) #self.ax.set_title(self.collection.name) keys = [s.name for s in self.collection.spectra] artists = self.ax.lines self.artist_dict = {key: artist for key, artist in zip(keys, artists)} self.colors = {key: 'black' for key in keys} self.ax.legend().remove() self.navbar.setHome(self.ax.get_xlim(), self.ax.get_ylim()) self.canvas.draw() self.sblabel.config(text="Showing: {}".format(len(artists))) def update_selected(self, to_add=None): """ Update, only on flaged""" if self.collection is None: return if to_add: for key in to_add: self.artist_dict[key].set_linestyle('--') else: keys = [s.name for s in self.collection.spectra] selected = self.listbox.curselection() selected_keys = [self.collection.spectra[s].name for s in selected] for key in keys: if key in selected_keys: self.artist_dict[key].set_linestyle('--') else: self.artist_dict[key].set_linestyle('-') self.canvas.draw() def update(self): """ Update the plot """ if self.collection is None: return # show statistics if self.spectrum_mode: self.ax.clear() idx = self.listbox.curselection() if len(idx) == 0: idx = [self.head] spectra = [self.collection.spectra[i] for i in idx] flags = [s.name in self.collection.flags for s in spectra] print("flags = ", flags) flag_style = ' ' if self.show_flagged: flag_style = 'r' Collection(name='selection', spectra=spectra).plot( ax=self.ax, style=list(np.where(flags, flag_style, 'k')), picker=1) self.ax.set_title('selection') # c = str(np.where(spectrum.name in self.collection.flags, 'r', 'k')) # spectrum.plot(ax=self.ax, label=spectrum.name, c=c) else: # red curves for flagged spectra keys = [s.name for s in self.collection.spectra] for key in keys: if key in self.collection.flags: if self.show_flagged: self.artist_dict[key].set_visible(True) self.artist_dict[key].set_color('red') else: self.artist_dict[key].set_visible(False) else: self.artist_dict[key].set_color(self.colors[key]) self.artist_dict[key].set_visible(True) if self.show_flagged: self.sblabel.config( text="Showing: {}".format(len(self.artist_dict))) else: self.sblabel.config(text="Showing: {}".format( len(self.artist_dict) - len(self.collection.flags))) ''' self.collection.plot(ax=self.ax, style=list(np.where(flags, flag_style, 'k')), picker=1) self.ax.set_title(self.collection.name) ''' if self.spectrum_mode: #self.ax.legend() pass else: #self.ax.legend().remove() pass self.ax.set_ylabel(self.collection.measure_type) #toggle appearance of statistics if self.mean_line != None: self.mean_line.set_visible(self.mean) if self.median_line != None: self.median_line.set_visible(self.median) if self.max_line != None: self.max_line.set_visible(self.max) if self.min_line != None: self.min_line.set_visible(self.min) if self.std_line != None: self.std_line.set_visible(self.std) self.canvas.draw() def next_spectrum(self): if not self.spectrum_mode: return self.head = (self.head + 1) % len(self.collection) self.update() def stitch(self): ''' Known Bugs ---------- Can't stitch one spectrum and plot the collection ''' self.collection.stitch() self.update_artists() def jump_correct(self): ''' Known Bugs ---------- Only performs jump correction on 1000 and 1800 wvls and 1 reference ''' self.collection.jump_correct([1000, 1800], 1) self.update_artists() def toggle_mean(self): if self.mean: self.mean = False else: self.mean = True if not self.mean_line: self.collection.mean().plot(ax=self.ax, c='b', label=self.collection.name + '_mean', lw=3) self.mean_line = self.ax.lines[-1] self.update() def toggle_median(self): if self.median: self.median = False else: self.median = True if not self.median_line: self.collection.median().plot(ax=self.ax, c='g', label=self.collection.name + '_median', lw=3) self.median_line = self.ax.lines[-1] self.update() def toggle_max(self): if self.max: self.max = False else: self.max = True if not self.max_line: self.collection.max().plot(ax=self.ax, c='y', label=self.collection.name + '_max', lw=3) self.max_line = self.ax.lines[-1] self.update() def toggle_min(self): if self.min: self.min = False else: self.min = True if not self.min_line: self.collection.min().plot(ax=self.ax, c='m', label=self.collection.name + '_min', lw=3) self.min_line = self.ax.lines[-1] self.update() def toggle_std(self): if self.std: self.std = False else: self.std = True if not self.std_line: self.collection.std().plot(ax=self.ax, c='c', label=self.collection.name + '_std', lw=3) self.std_line = self.ax.lines[-1] self.update()
class Root(Widget, Generic[_T]): tk_widget: Optional[tk.Frame] canvas: Optional[FigureCanvasTkAgg] background_img: Optional[FigureImage] def __init__(self, params, w: int = 1429, h: int = 799, dpi: int = 141, color: str = '#000000', **kwargs) -> None: Widget.__init__(self) self.params = params self.w = w self.h = h self.dpi = dpi self.face_color = color matplotlib_config() self.fig: plt.Figure = plt.figure( figsize=(self.w / self.dpi, self.h / self.dpi), dpi=self.dpi, facecolor=self.face_color, ) self.gs = self.fig.add_gridspec(nrows=90, ncols=160, left=0, right=1, top=1, bottom=0, hspace=0, wspace=0) self.properties = kwargs self.artists = {} self.tk_widget = None self.canvas = None self.background_img = None self._bg = None self._initialized = None self.__post_init__() def for_tk(self, parent: Union[tk.Tk, tk.Frame, tk.Canvas]) -> tk.Canvas: self.tk_widget = parent self.canvas = FigureCanvasTkAgg(self.fig, master=parent) widget = self.canvas.get_tk_widget() widget.pack(fill=tk.BOTH, expand=1) return widget @staticmethod def load_img(fp: PATH_LIKE) -> np.array: return plt.imread(cbook.get_sample_data(fp)) @timer def save_img(self, fp: PATH_LIKE) -> None: self.fig.savefig(fp, transparent=True) @timer def set_background_from_img(self, img_array: np.array) -> None: self.background_img = plt.figimage(img_array) self.background_img.set_zorder(-999) def update(self, iteration_data: ITERATION_DATA) -> None: raise NotImplementedError def init(self) -> None: self._initialized = self._initialized or self.init_results() or True self.reset_results() self._bg = self._bg or self.canvas.copy_from_bbox( self.canvas.figure.bbox) self.draw_artists() def draw_artists(self) -> None: self.canvas.restore_region(self._bg) list(map(self.canvas.figure.draw_artist, self.animated)) self.canvas.blit(self.canvas.figure.bbox) def __call__(self, iteration_data: List[ITERATION_DATA]): if hasattr(iteration_data, '__iter__'): list(map(self.update, iteration_data)) else: self.update(iteration_data) self.draw_artists() def _set_background(self) -> None: pass def populate_from_iteration(self, iteration) -> None: raise NotImplementedError def _init_results(self) -> None: pass def set_result(self, *args) -> None: pass def _reset_results(self) -> None: pass
class TensileTestView(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent) # Initialize this class as a frame self.animationBgCol = "black" # Animation canvas background colour # Create and configure main frame mainArea = tk.Frame(self, bg=st.MAIN_AREA_BG) mainArea.grid(row=0, column=0, sticky="nsew") mainArea.grid_propagate(0) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) # Create and configure main grids grid = tuple([i for i in range(20)]) mainArea.grid_columnconfigure(grid, weight=1, minsize=50) mainArea.grid_rowconfigure(grid, weight=1, minsize=35) # Create title label = tk.Label(mainArea, text="Mechanical Workshop", font=st.LARGE_FONT, bg=st.MAIN_AREA_BG, fg=st.TITLE_COLOUR) label.grid(row=0, column=14, columnspan=6, sticky='nse') # Create description label = tk.Label( mainArea, text="We are now going to perform a tensile test on the " + "sheet of aluminum that we cold rolled! We can see our sample of aluminum on the left side of " + "the screen as well as a stress-strain graph on the right side of the screen. " + "Press the start button to begin the tensile test!", bg=st.INPUT_BG, wraplength=650, fg='black', justify='left', relief='ridge') label.grid(row=1, column=6, rowspan=2, columnspan=14, sticky='nesw') # Canvas for graphic simulation self.height = 595 self.width = 250 self.animationWindow = tk.Canvas(mainArea, bg=self.animationBgCol, height=self.height, width=self.width, bd=0, highlightthickness=0, relief='ridge') self.animationWindow.grid(row=2, column=1, columnspan=5, rowspan=17, sticky='ne') # Create Plot self.f = Figure(figsize=(6, 6), dpi=100) self.a = self.f.add_subplot(111) self.a.grid(color='grey', linestyle='-', linewidth=0.3) self.a.set_ylabel('Stress (MPa)') self.a.set_xlabel('Strain (-)') self.line = self.a.plot([], [], "-") self.a.format_coord = lambda x, y: "Strain (-)={:6.4f}, Stress (MPa)={:6.3f}".format( x, y) # Create canvas for plot self.graphWindow = FigureCanvasTkAgg(self.f, mainArea) self.graphWindow.get_tk_widget().grid(row=5, column=6, rowspan=12, columnspan=12) self.BG = self.graphWindow.copy_from_bbox(self.a.bbox) self.OG = self.BG # Load arrow images self.arrow = ImageTk.PhotoImage(file=st.IMG_PATH + "left_arrow.png") self.arrowClicked = ImageTk.PhotoImage(file=st.IMG_PATH + "left_arrow_clicked.png") self.arrowDisabled = ImageTk.PhotoImage(file=st.IMG_PATH + "left_arrow_disabled.png") # Arrow for previous page self.nextPage = tk.Button(mainArea, image=self.arrow, borderwidth=0) self.nextPage.image = self.arrow self.nextPage.grid(row=9, rowspan=2, column=0, sticky='nesw') # Button to start simulation self.animationButton = ttk.Button(mainArea, text="Start") self.animationButton.grid(row=3, rowspan=2, column=6, columnspan=3, sticky='nesw') # Text for displaying cold work self.CW_text = tk.Label(mainArea, text='', borderwidth=2, bg=st.INPUT_BG, font=st.MEDIUM_FONT) self.CW_text.grid(row=0, rowspan=2, column=2, columnspan=3, sticky='nsew') # Draw the rod self.rod = Rod(self.animationWindow, self.width, self.height, self.animationBgCol) self.rod.drawRod() # Create toolbar for plot self.toolbar = NavigationToolbar2Tk(self.graphWindow, mainArea) self.toolbar.update() self.toolbar.grid(row=17, column=6, rowspan=2, columnspan=10, sticky='nsew') # Draw mac logo logoImg = ImageTk.PhotoImage(Image.open(st.IMG_PATH + "macLogo.png")) canvas = tk.Canvas(mainArea, bg=st.MAIN_AREA_BG, width=130, height=71, bd=0, highlightthickness=0, relief='ridge') canvas.create_image(130 / 2, 71 / 2, image=logoImg, anchor="center") canvas.image = logoImg canvas.grid(row=17, column=17, rowspan=3, columnspan=3) def setGraphSize(self, x, y): """ Set the graph size. Assume it is called before any other function """ self.a.set_xlim([-0.01, x + 0.3]) self.a.set_ylim([0, y + 50]) self.graphWindow.draw() self.BG = self.graphWindow.copy_from_bbox(self.a.bbox) def pressArrow(self): """ Change arrow picture to "pressed arrow" """ self.nextPage.config(image=self.arrowClicked) self.nextPage.image = self.arrowClicked def normalArrow(self): """ Change arrow picture to "normal arrow" """ self.nextPage.config(image=self.arrow) self.nextPage.image = self.arrow def disableArrow(self): """ Change arrow picture to "disabled arrow" """ self.nextPage.config(image=self.arrowDisabled) self.nextPage.image = self.arrowDisabled def resetCanvas(self): """ Reset the rod on canvas """ self.rod.resetRod() def setCW(self, val): """ Set the coldwork text """ self.CW_text.config(text="%CW = " + str(val)) def updateGraph(self, xvals, yvals): """ Update the graph with xvals and yvals. This function is called at a given framerate """ self.line[0].set_data(xvals, yvals) self.graphWindow.restore_region(self.BG) self.a.draw_artist(self.line[0]) self.graphWindow.blit(self.a.bbox) self.graphWindow.flush_events() def updateAnimation(self, elongation, widthFact, neckWidthFact, neckHeightFact): """ Update the canvas based on given values. This function is called at a given framerate """ self.rod.updateRod(elongation, widthFact, neckWidthFact, neckHeightFact) def generateFracture(self, EL): """ Generate a fracture in the Rod. Function is called at the end of the animation """ self.rod.drawFracture(EL)
class MultichannelPlot(matplotlib.figure.Figure): def __init__(self, master, row=0, column=0, rowspan=5, columnspan=5, width=5, height=3, update_prot="blit"): matplotlib.figure.Figure.__init__(self, figsize=(width, height)) self.update_prot = update_prot self.frame = Frame(master=master) self.frame.config(bd=5) self.frame.grid(row=row, column=column, padx=5, pady=5) self.channel_list = [] self.array_list = [] self.color_list = ["r", "b", "g", "c", "m", "y", "k"] self.a = self.add_subplot(MultichannelAxis(self, 111)) self.canvas = FigureCanvasTkAgg(self, master=self.frame) self.canvas.show() self.canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=True) self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.frame) self.toolbar.update() self.toolbar.pack(side=BOTTOM, fill=BOTH, expand=True) # ,expand = True)#fill=BOTH)#, expand=1) self.canvas.draw() self.background = self.canvas.copy_from_bbox(self.a.bbox) return None def AddChannel(self, spec_array, channel_type, color=None): if color == None or color == "": self.a.add_line(Channel([], [], self, spec_array, channel_type, color=self.color_list[0])) self.color_list.append(self.color_list[0]) del (self.color_list[0]) else: self.a.add_line(Channel([], [], self, spec_array, channel_type, color=color)) # self.Update() self.Redraw() return self.a.lines[-1] def RemoveChannel(self, channel): self.a.lines.remove(channel) self.Redraw() return 0 def SetChannelColor(self, channel, clr): if clr != "": channel.color = clr else: channel.color = self.color_list[0] self.color_list.append(self.color_list[0]) del (self.color_list[0]) return 0 def ShowChannel(self, channel): channel.set_visible(True) self.Update() return 0 def HideChannel(self, channel): channel.set_visible(False) self.Update() return 0 def Redraw(self): self.a.relim() self.a.autoscale_view(tight=False) self.canvas.draw() self.canvas.restore_region(self.background) for line in self.a.lines: self.a.draw_artist(line) self.canvas.blit(self.a.bbox) return 0 def SaveFigure(self, filename): self.f_copy = self.a self.f_copy.savefig("a.png") return 0 def Update(self): if self.update_prot == "draw": self.canvas.draw() return 0 (lower_y_lim, upper_y_lim) = self.a.get_ylim() (lower_x_lim, upper_x_lim) = self.a.get_xlim() scaley_bool = False scalex_bool = False scaley_down_bool = True for channel in self.a.lines: if channel.get_visible() == True: channel.ChannelUpdate() scaley_bool = ( scaley_bool or max(channel.get_ydata()) > upper_y_lim or min(channel.get_ydata()) < lower_y_lim ) scaley_down_bool = scaley_down_bool and max(channel.get_ydata()) < upper_y_lim * 0.6 scalex_bool = ( scalex_bool or max(channel.get_xdata()) != upper_x_lim or min(channel.get_xdata()) != lower_x_lim ) if scaley_bool or scalex_bool or scaley_down_bool: self.Redraw() else: self.canvas.restore_region(self.background) for line in self.a.lines: self.a.draw_artist(line) self.canvas.blit(self.a.bbox) return 0
class PlotFrame(tk.Frame): def __init__(self, master): tk.Frame.__init__(self, master) self.fwidth = 512 self.fheight = 720 self.configure(bd=2, width=self.fwidth, height=self.fheight, relief='sunken') self.grid_propagate(0) self.dpi = 100 self.f = Figure(figsize=(self.fwidth / self.dpi, self.fheight / self.dpi), dpi=self.dpi, facecolor=(1, 1, 1, 0)) self.canvas = FigureCanvasTkAgg(self.f, self) self.top = self.f.add_subplot(311) self.middle = self.f.add_subplot(312) self.bottom = self.f.add_subplot(313) self.xData = np.linspace(0, 100 * np.pi, 1000, endpoint=False) self.yDataB = np.sin(self.xData) self.yDataM = np.sin(self.xData) * np.sin(self.xData * 0.5 + .4) self.yDataT = np.sin(self.xData)**2 + np.cos(self.xData * 1.1 + 0.15) self.startTime = time.time() self.canvas.draw() self.backgroundB = self.canvas.copy_from_bbox(self.bottom.bbox) self.backgroundT = self.canvas.copy_from_bbox(self.top.bbox) self.backgroundM = self.canvas.copy_from_bbox(self.middle.bbox) self.pointsB = self.bottom.plot(self.xData, self.yDataB)[0] self.pointsM = self.middle.plot(self.xData, self.yDataM)[0] self.pointsT = self.top.plot(self.xData, self.yDataT)[0] def animate2(self, reScaled): scale = True if reScaled: self.f.clf() self.showCanvas.grid_forget() self.f = Figure(figsize=(self.fwidth / self.dpi, self.fheight / self.dpi), dpi=self.dpi, facecolor=(1, 1, 1, 0)) self.canvas = FigureCanvasTkAgg(self.f, self) self.top = self.f.add_subplot(311) self.middle = self.f.add_subplot(312) self.bottom = self.f.add_subplot(313) self.canvas.draw() self.backgroundB = self.canvas.copy_from_bbox(self.bottom.bbox) self.backgroundT = self.canvas.copy_from_bbox(self.top.bbox) self.backgroundM = self.canvas.copy_from_bbox(self.middle.bbox) self.pointsB = self.bottom.plot(self.xData, self.yDataB)[0] self.pointsM = self.middle.plot(self.xData, self.yDataM)[0] self.pointsT = self.top.plot(self.xData, self.yDataT)[0] scale = False if scale: t = time.time() - self.startTime N = len(self.xData) currentIdx = int(N * ((t / 4) % 1)) scalingNumber = N * 0.1 waveShape = np.exp(-np.arange(N) / scalingNumber)[::-1] colorArray = np.array([(1, 0, 0, a) for a in np.roll(waveShape, currentIdx)]) self.yDataB = np.roll(self.yDataB, 1) self.yDataT = np.roll(self.yDataT, 1) self.yDataM = np.roll(self.yDataM, 1) self.pointsB.set_data(self.xData, self.yDataB) self.pointsT.set_data(self.xData, self.yDataT) self.pointsM.set_data(self.xData, self.yDataM) self.canvas.restore_region(self.backgroundB) self.canvas.restore_region(self.backgroundT) self.canvas.restore_region(self.backgroundM) self.bottom.draw_artist(self.pointsB) self.middle.draw_artist(self.pointsM) self.top.draw_artist(self.pointsT) self.canvas.blit(self.bottom.bbox) self.canvas.blit(self.top.bbox) self.canvas.blit(self.middle.bbox) self.showCanvas = self.canvas.get_tk_widget() self.showCanvas.grid()