class BeldenSNPApp(QtWidgets.QMainWindow, MainWindow.Ui_MainWindow, QtWidgets.QAction, QtWidgets.QFileDialog, QtWidgets.QListView, QtWidgets.QDialog, QtCore.Qt): ''' This class handles all of the user sent commands from the GUI. ''' def __init__(self): super(self.__class__, self).__init__() self.setupUi(self) fileMenu = self.actionImport_SnP newProject = self.actionNew_Project #Initialize sample sample Table self.sampleTable.setColumnCount(4) self.sampleTable.setHorizontalHeaderLabels( [None, "Name", "Date", "Limit"]) self.sampleTable.setSortingEnabled(True) self.sampleTable.setContextMenuPolicy(self.CustomContextMenu) self.sampleTable.customContextMenuRequested.connect( self.tableContextMenu) self.selected = [] #Initialize Tab widget for sample info #self.sampleTable.customContextMenuRequested.connect(self.tableContextMenu) #New Project self.Project = Project() #Initialize plot parameters self.activeParameter = "Main" #We want the the first sample tab to display to be the Main tab. nav = NavigationToolbar( self.graphicsView, self ) #Sets up the menu at the bottom of the GUI which lets us interact with the matplotlib plots self.verticalLayout_3.addWidget(nav) #Here, we process any arguments that might be sent the program from outside of the interface. #In other words, when ever a user right click on an SNP files, rather than opening them in Notepad, it would be opened in this interface. arguments = sys.argv[1:] if len(arguments): self.Project.importSNP(arguments) self.displaySamplesInTable() self.comm = Communication() self.settings = Settings() self.threadpool = QtCore.QThreadPool() self.poolMutex = QtCore.QMutex() self.paramWidgetList = [] # Comment out this line to get messanges to appear in terminal instead of in app. self.setupConsole() #@QtCore.pyqtSlot() def addPlug(self): testName, result = QtWidgets.QInputDialog.getText( self, "Add a Plug Sample", "Please enter a plug name") if result and len(testName) > 0 and not testName.isspace(): print("%s!" % testName) self.Project.addPlug(testName) self.displaySamplesInTable() else: return def addEmbed(self): testName, result = QtWidgets.QInputDialog.getText( self, "Add an Embedded Sample", "Please enter a sample name") if result and len(testName) > 0 and not testName.isspace(): print("%s!" % testName) self.Project.addEmbed(testName) self.displaySamplesInTable() else: return def addAlien(self): testName, result = QtWidgets.QInputDialog.getText( self, "Add an Alien Test", "Please enter a Test name") if result and len(testName) > 0 and not testName.isspace(): print("%s!" % testName) self.Project.addAlien(testName) self.displaySamplesInTable() else: return def newProject(self): self.Project = Project() self.sampleTable.setRowCount(0) def deleteSample(self): self.Project.delete(self.selected) self.displaySamplesInTable() self.setActiveSample() def setLimit(self): type = None if self.selected[0].__repr__() == "Embed" or self.selected[0].__repr__( ) == "Plug": type = "Embedding" limitDialog = LimitDialog(type=type) result = limitDialog.showDialog() if result: item = limitDialog.getSelection().internalPointer().standard for limit in item.limits.values(): if not (limit == ""): for function in limit.functions: for symbol in function.free_symbols: if not (str(symbol) == 'f'): ret = QtWidgets.QInputDialog.getDouble( self, "Enter the parameter value", "Please enter the value for the parameter " + str(symbol) + " : ") limit.setParamValue(symbol, ret[0]) for sample in self.selected: worker = GenericWorker(sample.setStandard, standard=item) worker.signals.finished.connect(self.displaySamplesInTable) self.threadpool.start(worker) def setActiveSample(self): self.plot(None, None) self.selected = [] for i in self.sampleTable.selectionModel().selectedRows(): self.selected.append( self.sampleTable.item(i.row(), 0).data(Qt.UserRole)) #print self.selected if len(self.selected) >= 1: self.Project.activeSample = self.selected if len(self.selected ) == 1: #Since only one sample can be displayed at a time if self.selected[0].__repr__() == "Alien": self.setupAlien() elif self.selected[0].__repr__() == "Embed": self.setupEmbed() elif self.selected[0].__repr__() == "Plug": self.setupPlug() elif self.selected[0].__repr__() == "SNP": self.displaySampleParams(self.selected) elif len(self.selected) > 1 or len(self.selected) < 1: self.displaySampleParams(None) def displaySamplesInTable(self): #self.blockSignals( False ) print("Finished TREAD !") self.blockSignals(False) measurementCount = len(self.Project.measurements) self.sampleTable.setRowCount(measurementCount) for i, measurement in enumerate(self.Project.measurements): #Column 0 (type) type = measurement.__repr__()[0] self.sampleTable.setItem(i, 0, QtWidgets.QTableWidgetItem(type)) self.sampleTable.item(i, 0).setData(Qt.UserRole, measurement) #Column 1 (name) self.sampleTable.setItem( i, 1, QtWidgets.QTableWidgetItem(measurement.name)) self.sampleTable.item(i, 1).setData(Qt.UserRole, measurement) #Column 2 (date) self.sampleTable.setItem( i, 2, QtWidgets.QTableWidgetItem(measurement.date)) self.sampleTable.item(i, 2).setData(Qt.UserRole, measurement) #Column 3 (standard) if measurement.standard is not None: self.sampleTable.setItem( i, 3, QtWidgets.QTableWidgetItem(measurement.standard.name)) self.sampleTable.item(i, 3).setData(Qt.UserRole, measurement) self.sampleTable.resizeColumnsToContents() self.setActiveSample() def setupEmbed(self): self.param_tabs.clear() self.embeddingWidget = EmbeddingWidget(self.param_tabs, sample=self.selected[0], graph=self.graphicsView, comm=self.comm, project=self.Project) self.embeddingWidget.proc_addPlug.connect(self.addPlug) self.embeddingWidget.proc_importPlug.connect(self.importPlug) #self.param_tabs.addTab(self.embeddingWidget.widget, "Embedding Main") def setupPlug(self): self.param_tabs.clear() self.plugWidget = PlugWidget(self.param_tabs, sample=self.selected[0], graph=self.graphicsView, comm=self.comm) #self.param_tabs.addTab(self.embeddingWidget.widget, "Embedding Main") def setupAlien(self): self.param_tabs.clear() self.alienWidget = AlienWidget(self.param_tabs, sample=self.selected[0], graph=self.graphicsView, comm=self.comm) #self.param_tabs.addTab(self.embeddingWidget.widget, "Embedding Main") def importSnp(self): #Whenever the user clicks on the import SNP button, it opens a file dialog options = self.Options() options |= self.DontUseNativeDialog files, _ = self.getOpenFileNames(self, "Select SNP(s)", "", "sNp Files (*.s*p)", options=options) #print files print(files) #This needs to be in thread Look into this : https://realpython.com/python-pyqt-qthread/ #for file in files: #self.blockSignals( True ) self.blockSignals(True) worker = GenericWorker(function=self.Project.importSNP, files=files) worker.signals.finished.connect(self.displaySamplesInTable) self.threadpool.start(worker) #self.my_worker.start.connect(self.my_worker.run) '''self.threadPool.append(my_thread) self.my_worker = my_worker self.importSNPTask = self.Project.importSNP(samples = files) self.importSNPTask.notifyFinished.connect(self.displaySamplesInTable) self.importSNPTask.started.connect(self.startImport) self.importSNPTask.start.emit()''' #self.Project.importSNP(files) #print(self.rs.RL.items()) #self.plot(self.rs.NEXT) USE THIS !!!!!!! #self.displaySamplesInTable() def startImport(self): print("START IMPORT THREAD : ", int(QtCore.QThread.currentThreadId())) def plot(self, x=None, param_dict=None, limit=None, unit="Mhz", avgLimit=None): self.graphicsView.figure.clear() #ax.set_xlim(300*(10**3), 10**9) #self.ax.semilogx(x, self.pitch, '.-', label=label, c=color) if x is not None or param_dict is not None: ax = self.graphicsView.figure.add_subplot(111) #print param_dict.keys() color = iter(cm.rainbow(np.linspace(0, 1, len(param_dict.keys())))) for key in sorted(param_dict.keys()): c = next(color) #print key #a = scipy.signal.decimate(x, 10) if len(x) == len(param_dict[key]): ax.semilogx(x, param_dict[key], label=key, c=c) #print key ax.xaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter()) #self.figure.tight_layout() ax.grid(which="both") ax.set_xlabel('Freq ({})'.format(unit)) ax.set_ylabel('dB') ax.set_title(self.activeParameter) if self.activeParameter.replace(" ", "") == "PropagationDelay": ax.set_ylabel('nSec') if limit is not None: ax.semilogx(*zip(*limit), linestyle='--', label="limit", c=c) if avgLimit is not None: ax.semilogx(*zip(*avgLimit), linestyle='--', label="average limit", c=c) ax.legend(loc='upper left', ncol=1 if len(param_dict.keys()) <= 8 else 2) #self.ax.legend() self.graphicsView.draw() def pairRename(self): pair_names = self.settings.pairNames num_pairs = self.settings.numPairs try: names = pairNameDialog.PairNameDialog(pair_names, num_pairs).getPairNames() self.settings.pairNames = names except Exception as e: print(e) def pairRenameAlien(self): pair_names = self.settings.pairNamesAlien num_pairs = self.settings.numPairs try: names = pairNameDialog.PairNameDialog(pair_names, num_pairs).getPairNames() self.settings.pairNamesAlien = names except Exception as e: print(e) def setPairNumberAlien(self): sample = self.selected[0] pair_names = sample.port_name num_pairs = sample.numPairs try: names = pairNameDialog.PairNameDialog(pair_names, num_pairs).getPairNames() #self.settings.pairNamesAlien = names sample.port_rename(names) if len(self.selected ) == 1: #Since only one sample can be displayed at a time self.setupAlien() except Exception as e: print(e) def setPairNumber(self): sample = self.selected[0] if sample.__repr__() == "Alien": self.setPairNumberAlien() return snp = sample.snpFile sided = sample.one_sided standard = sample.standard pair_names = sample.port_name try: names = pairNameDialog.PairNameDialog( pair_names, sample.num_ports_dd).getPairNames() #self.settings.pairNames = names sample.__init__(snp, sided, standard, pair_names=names) sample.getParameters() sample.setStandard(standard) self.Project.activeSample = self.selected #print self.selected if len(self.selected ) == 1: #Since only one sample can be displayed at a time self.displaySampleParams(self.selected) except Exception as e: print(e) def tableContextMenu(self, pos): #print self.selected try: if len(self.selected) > 0 and all("SNP" in sample.__repr__() for sample in self.selected): #Start by getting info on the sample. (If they're all the same type or not) menu = QtWidgets.QMenu() setLimit = menu.addAction("Set Limit") if len(self.selected) == 1: setPairNumber = menu.addAction("Renumber Pairs") test_type = menu.addMenu( "Set Test Type" ) #Set the sub menu to select the different types of matrixes one_sided = test_type.addAction("One Sided") end_end = test_type.addAction("End to End") one_sided.setCheckable(True) end_end.setCheckable(True) exportExcel = menu.addAction("Export To Excel") exportPDF = menu.addAction("Export To PDF") delete = menu.addAction("Delete") #get test type for samples. If theyre all one sided, all #end-end or all different. #To start get the test type of the first sample _one_sided = self.selected[0].one_sided print(_one_sided) for sample in self.selected: if _one_sided != sample.one_sided: _one_sided = None break if _one_sided == True: one_sided.setChecked(True) end_end.setChecked(False) elif _one_sided == False: one_sided.setChecked(False) end_end.setChecked(True) else: one_sided.setChecked(False) end_end.setChecked(False) action = menu.exec_(QtGui.QCursor.pos()) if action == one_sided: for sample in self.selected: sample.reCalc(one_sided=True) self.Project.activeSample = self.selected #print self.selected if len( self.selected ) == 1: #Since only one sample can be displayed at a time self.displaySampleParams(self.selected) elif len(self.selected) > 1: self.displaySampleParams(None) elif action == end_end: for sample in self.selected: sample.reCalc(one_sided=False) if len( self.selected ) == 1: #Since only one sample can be displayed at a time self.displaySampleParams(self.selected) elif len(self.selected) > 1: self.displaySampleParams(None) elif action == exportExcel: print(self.selected) self.generateExcel() elif action == exportPDF: print(self.selected) self.generatePDF() elif action == delete: self.deleteSample() elif action == setLimit: self.setLimit() #self.Project.activeMeasurements = selected elif action == setPairNumber and len(self.selected) == 1: self.setPairNumber() return 1 elif len(self.selected) > 0 and not all( "SNP" in sample.__repr__() for sample in self.selected): menu = QtWidgets.QMenu() setLimit = menu.addAction("Set Limit") if len(self.selected) == 1: setPairNumber = menu.addAction("Renumber Pairs") if self.selected[0].__repr__() == "Embed": saveDeembed = menu.addAction( "Save Embedding Measurement") exportExcel = menu.addAction("Export To Excel") exportPDF = menu.addAction("Export To PDF") delete = menu.addAction("Delete") #get test type for samples. If theyre all one sided, all #end-end or all different. #To start get the test type of the first sample action = menu.exec_(QtGui.QCursor.pos()) if action == exportExcel: print(self.selected) self.generateExcel() elif action == exportPDF: print(self.selected) self.generatePDF() elif action == delete: self.deleteSample() elif action == setLimit: self.setLimit() elif action == saveDeembed: self.saveDeembedding() elif action == setPairNumber and len(self.selected) == 1: self.setPairNumber() #self.Project.activeMeasurements = selected return 1 menu = QtWidgets.QMenu() addSNP = menu.addAction("Add Sample") addAlien = menu.addAction("Add Alien Sample") addEmbed = menu.addAction("Add Emdedding Sample") addPlug = menu.addAction("Add Plug Sample") selectAll = menu.addAction("Select All") action = menu.exec_(QtGui.QCursor.pos()) if action == selectAll: self.sampleTable.selectAll() elif action == addSNP: self.importSnp() elif action == addAlien: self.addAlien() elif action == addEmbed: self.addEmbed() elif action == addPlug: self.addPlug() except Exception as e: print(e) def generateExcel(self): #file, _ = self.getSaveFileName(self,"Export Excel Repport", "","Excel File (*.xlsx)") if len(self.selected) == 0: samples = self.Project.measurements else: samples = self.selected print(samples) self.Project.generateExcelReport(samples) def generatePDF(self): #file, _ = self.getSaveFileName(self,"Export Excel Repport", "","Excel File (*.xlsx)") if len(self.selected) == 0: samples = self.Project.measurements else: samples = self.selected self.Project.generatePDFReport(samples) def displaySampleParams(self, sample): currentTab = self.activeParameter if sample == None: self.param_tabs.clear() return self.param_tabs.clear() #print sample self.sample = sample[0] #print self.sample #Create a tab widget containing a main tab and all the parameters #Start off by creating the home tab self.mainTab = QtWidgets.QWidget() self.mainTabWidget = MainWidget.Ui_MainWidget() self.mainTabWidget.setupUi(self.mainTab) self.setupMainTab() self.param_tabs.addTab(self.mainTab, "Main") self.tab_list = [] self.tab_list.append(self.mainTab) self.paramWidgetList = [] self.paramWidgetList.append(None) #values = self.calculateErrors(pool=os.cpu_count()) allPass = True failedParams = [] self.blockSignals(True) for param in self.sample.parameters: self.new_tab = ParameterWidget( param.replace(" ", ''), self.sample, graph=self.graphicsView) #, values[param.replace(" ","")]) self.paramWidgetList.append(self.new_tab) self.tab_list.append(self.new_tab.widget) self.param_tabs.addTab(self.new_tab.widget, param) allPass = allPass and self.new_tab.hasPassed if not self.new_tab.hasPassed: failedParams.append(param) if allPass: self.mainTabWidget.passLabel.setText("Pass") else: self.mainTabWidget.passLabel.setText("Fail") self.mainTabWidget.failsLabel.setText(str(failedParams)) for i in range(0, self.param_tabs.count()): if self.param_tabs.tabText(i) == currentTab: index = i break else: index = 0 self.blockSignals(False) self.param_tabs.setCurrentIndex(index) self.tabChange(index) def tabChange(self, index): #This function is called whenever a parameter self.tab_index = index #self.param_tabs.currentIndex() self.activeParameter = self.param_tabs.tabText(self.tab_index) print("Active Parameter = ", self.activeParameter) if self.selected: sample = self.selected[0] else: return #print index if self.tab_index >= 1: if sample.__repr__() == "Embed": tab_index = self.param_tabs.currentIndex() activeParameter = self.param_tabs.tabText(self.tab_index) self.embeddingWidget.embedPlotUpdate(activeParameter) if sample.__repr__() == "Plug": tab_index = self.param_tabs.currentIndex() activeParameter = self.param_tabs.tabText(self.tab_index) self.plugWidget.plugPlotUpdate(activeParameter) elif sample.__repr__() == "Alien": try: self.alienWidget except AttributeError: self.alienWidget = None if self.alienWidget is None: self.setupAlien() self.alienWidget.alienPlotUpdate() elif sample.__repr__() == "SNP": currentParamWidget = self.paramWidgetList[self.tab_index] currentParamWidget.plotUpdate(sample, self.activeParameter) #print(self.sample.frequency.unit) #worstValue = sample.getWorstValue(self.activeParameter) #print(worstValue) else: self.plot(None, None) def setupMainTab(self): self.mainTabWidget.testNameLabel.setText(self.sample.name + " : ") self.mainTabWidget.dateLabel.setText(self.sample.date.__str__()) self.mainTabWidget.limitLabel.setText(self.sample.standard.__str__()) def importPlug(self): options = self.Options() options |= self.DontUseNativeDialog file, _ = self.getOpenFileName(self, "Select Plug", "", "Plug (*.plug)", options=options) #print files print(file) p = self.Project.addPlug(" ") p.deserialize(file) self.displaySamplesInTable() def importDeembedding(self): options = self.Options() options |= self.DontUseNativeDialog file, _ = self.getOpenFileName(self, "Select Deembeding", "", "Deembedding (*.mbed)", options=options) #print files print(file) f = open(file, 'rb') temp = pickle.load(f) f.close() plug = temp.plug self.Project.measurements.append(plug) d = self.Project.addEmbed(" ") d.deserialize(file) self.displaySamplesInTable() def saveDeembedding(self): if len(self.selected) == 1: sample = self.selected[0] outputFile, _ = self.getSaveFileName(self, "Save Deembedding", "", "Deembedding file (*.mbed)") sample.serialize(file=outputFile) def saveProject(self): pass def openProject(self): pass def connect(self): connectDialog = ConnectDialog(self.comm) res = connectDialog.showDialog() if res and self.comm._connected: if connectDialog.calib is False: self.comm.setCal(connectDialog.newDial.typeBox.currentIndex()) self.actionWho_am_I.setEnabled(True) self.actionCalibrate.setEnabled(True) self.actionCalibrate_2.setEnabled(True) self.actionDisconnect.setEnabled(True) self.actionConnect.setEnabled(False) self.actionMeasure.setEnabled(True) self.actionRun.setEnabled(True) def disconnect(self): self.comm.disconnect() self.actionMeasure.setEnabled(False) self.actionWho_am_I.setEnabled(False) self.actionCalibrate.setEnabled(False) self.actionCalibrate_2.setEnabled(False) self.actionDisconnect.setEnabled(False) self.actionRun.setEnabled(False) self.actionConnect.setEnabled(True) def whoAmI(self): self.comm.whoAmI() def aquire(self): try: vnaDialog = VNATestDialog() res = vnaDialog.exec_() if res: name = vnaDialog.getSampleName() ports = vnaDialog.getPorts() sample_file = self.comm.acquire( name, ports, vnaDialog.getVNACOnfiguration()) print(sample_file) self.Project.importSNP([sample_file]) self.displaySamplesInTable() except Exception as e: print(e) '''try: if file:=self.comm.aquireInterface(): self.Project.importSNP([file]) self.displaySamplesInTable() except Exception as e: print(e)''' def simpleAquire(self): pass def reject(self): pass def calibrate(self): print("CALIBRATE") self.comm.calibrate() def setupConsole(self): self.consoleWidget = ConsoleWidget(parent=self.console_widget) sys.stdout = EmittingStream( textWritten=self.consoleWidget.writeToConsole) # test def __del__(self): # test # Restore sys.stdout sys.stdout = sys.__stdout__