def __init__(self, **kargs): SVC.__init__(self, **kargs) self.trainX = [] self.trainY = [] self.names = [] self.model = None self.player = SoundPlayer() self.load_mem()
class LetterClassifier(SVC): ''' C=1.0, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape=None, degree=3, gamma='auto', kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False) ''' mem_file = os.path.join(os.environ['APPDATA'], 'training_data.npz') def __init__(self, **kargs): SVC.__init__(self, **kargs) self.trainX = [] self.trainY = [] self.names = [] self.model = None self.player = SoundPlayer() self.load_mem() def plotWavFile(self, fname): if fname == '': return self.filename = fname self.build_recent_actions() s, data = wavfile.read(fname) print("Wav file has rate %s and shape %s" % (s, np.shape(data))) if np.ndim(data) > 1: print("Data has %d dimensions, 1st is being used" % np.ndim(data)) data = data[:, 0] self.ui.plotWidget.setData(data) def teach_gui(self): if not hasattr(self, 'ui'): self.ui = uic.loadUi('LetterClassifier.ui') self.ui.consoleWidget.localNamespace.update({'classifier': self, 'plot': self.ui.plotWidget, 'player': self.player, 'ui': self.ui, "recorderWidget": self.ui.recorderWidget}) self.ui.actionOpen.triggered.connect(lambda : self.plotWavFile(file_manager.getOpenFileName())) self.ui.actionSave_Memory.triggered.connect(lambda : self.save(file_manager.getSaveFileName())) self.ui.menuRecent_Files.aboutToShow.connect(self.build_recent_actions) self.ui.browseButton.pressed.connect(lambda : self.plotWavFile(file_manager.getOpenFileName())) self.ui.learnButton.pressed.connect(self.ui_learn_pressed) self.ui.unlearnButton.pressed.connect(self.ui_unlearn_pressed) self.ui.loadButton.pressed.connect(lambda : self.load_mem(file_manager.getOpenFileName())) self.ui.clearMemButton.pressed.connect(lambda : self.clear_memory(erase=False)) self.ui.predictButton.pressed.connect(self.ui_predict_pressed) self.ui.outputTree.itemClicked.connect(self.ui_tree_clicked) self.ui.setAcceptDrops(True) self.ui.playButton.pressed.connect(self.play_selection) self.ui.eventFilter = self.eventFilter self.ui.installEventFilter(self.ui) self.build_recent_actions() self.ui.closeEvent = lambda ev: self.save() self.ui.show() self.updateTreeView() def ui_tree_clicked(self, item): if item.parent() != None: data = self.trainX[self.names.index(item.text(0))] self.ui.plotWidget.soundLine.setData(data) item = item.parent() self.ui.outputLineEdit.setText(item.text(0)) def play_selection(self): selection = self.ui.plotWidget.getSelection() self.player.write(selection) def build_recent_actions(self): self.ui.menuRecent_Files.clear() def plotFunc(fname): return lambda : self.plotWavFile(fname) if len(file_manager.recent_files()) == 0: no_recent = self.ui.menuRecent_Files.addAction("No Recent Files") no_recent.setEnabled(False) self.ui.menuRecent_Files.addAction(no_recent) for fname in file_manager.recent_files(): self.ui.menuRecent_Files.addAction(QAction(fname, self.ui.menuRecent_Files, triggered=plotFunc(fname))) def eventFilter(self,obj,event): if (event.type()==QEvent.DragEnter): if event.mimeData().hasUrls(): event.accept() # must accept the dragEnterEvent or else the dropEvent can't occur !!! else: event.ignore() if (event.type() == QEvent.Drop): if event.mimeData().hasUrls(): # if file or link is dropped file_manager.update_history(*[url.toString()[8:] for url in event.mimeData().urls()]) url = event.mimeData().urls()[0] # get first url filename=url.toString() filename=str(filename) filename=filename.split('file:///')[1] print('filename={}'.format(filename)) self.plotWavFile(filename) #This fails on windows symbolic links. http://stackoverflow.com/questions/15258506/os-path-islink-on-windows-with-python event.accept() else: event.ignore() return False # lets the event continue to the edit def ui_learn_pressed(self): values = self.ui.plotWidget.getSelection() output = str(self.ui.outputLineEdit.text()) self.ui.outputLineEdit.clear() name = os.path.basename(self.filename) num = 2 while name in self.names: name = "%s_%d" % (os.path.basename(self.filename), num) num += 1 self.add_training_case(name, values, output) self.updateTreeView() def ui_unlearn_pressed(self): items = self.ui.outputTree.selectedItems() for item in items: try: i = self.names.index(item.text(0)) self.trainX.pop(i) self.trainY.pop(i) self.names.pop(i) except Exception as e: print(e) self.updateTreeView() def ui_predict_pressed(self): self.fit() points = self.ui.plotWidget.getSelection() xs = [points[i] for i in np.linspace(0, len(points)-1, self.ui.intervalSpin.value())] val = self.predict(xs) self.ui.predictionLabel.setText("%s" % val) def updateTreeView(self): if not hasattr(self, 'ui') or not self.ui.isVisible(): print("no ui") return self.ui.outputTree.clear() items = {} for i, output in enumerate(self.trainY): if output in items: items[output].append(QTreeWidgetItem([self.names[i]])) else: items[output] = [QTreeWidgetItem([self.names[i]])] for output, children in items.items(): item = QTreeWidgetItem([output]) item.addChildren(children) self.ui.outputTree.addTopLevelItem(item) def clear_memory(self, erase=False): self.trainX = [] self.trainY = [] self.names = [] self.updateTreeView() if erase: os.remove(LetterClassifier.mem_file) def add_training_case(self, name, x, y): self.trainX.append([i for i in x]) self.trainY.append(y) self.names.append(name) def fit(self): x = [] y = [] for i in range(len(self.names)): js = np.linspace(0, len(self.trainX[i]) - 1, self.ui.intervalSpin.value(), dtype=np.int) x.append([self.trainX[i][j] for j in js]) y.append(self.trainY[i]) self.model = SVC.fit(self, x, y) def predict(self, X): return SVC.predict(self, X) def save(self, fname=None): if fname == None: fname = LetterClassifier.mem_file pickle.dump({'trainX': self.trainX, 'trainY': self.trainY, 'names': self.names}, open(fname, 'wb')) #np.savez(LetterClassifier.mem_file, trainX=self.trainX, trainY=self.trainY, names=self.names) def load_mem(self, fname=None): if fname == None: fname = LetterClassifier.mem_file try: if os.path.exists(fname): #f = np.load(fname) f = pickle.load(open(fname, 'rb')) self.trainX = f['trainX'] self.trainY = f['trainY'] self.names = f['names'] if len(self.trainX) != len(self.trainY) or len(self.trainX) != len(self.names) or len(self.trainY) != len(self.names): raise Exception("Invalid sizes") except Exception as e: print(e) if input("Clear memory (y/n): ") == 'y': self.clear_memory()