def modelDefaults(self): model = QStandardItemModel() model.setHorizontalHeaderLabels([ self.tr('enabled'), self.tr('map to'), self.tr('label'), self.tr('ODK type'), self.tr('hint'), self.tr('required'), self.tr('default'), self.tr('QVar_type'), self.tr('widget'), self.tr('choices'), self.tr('appearance'), self.tr('read_only'), self.tr('calculation') ]) self.setModel(model) self.hideColumn(7) self.hideColumn(8) self.hideColumn(11) self.hideColumn(12) for column in range(0,12): if column > 3: width = 60 elif column == 3: width = 90 else: width = 140 self.setColumnWidth(column,width) return model model.itemChanged.connect(self.cleanTreeItem)
def actualizePeakModelComparative(): model = QStandardItemModel() #root=MSDialogController.getColouredRootItem(sample) sampleList = QApplication.instance().model groups = sampleList.peaksGrouping() model.setVerticalHeaderLabels([ "/".join(map(str, round([mass, rt], 4).tolist())) for mass, rt in sorted(groups.keys(), key=lambda x: x[0]) ]) model.setHorizontalHeaderLabels( [spl.shortName() for spl in sampleList.isamples()]) for i, key in enumerate(sorted(groups.keys(), key=lambda x: x[0])): zeros = [0.] * len(sampleList) for peak in groups[key]: try: idx = [spl.shortName() for spl in sampleList ].index(peak.sample.shortName()) except ValueError: print "Error in %s" % MSDialogController.actualizePeakModelComparative.__name__ zeros[idx] = peak for j in xrange(len(zeros)): item = QStandardItem() if not zeros[j]: item.setBackground(QBrush(Qt.red)) item.setText("Not found") else: MSDialogController.setRightIcon( zeros[j], item) #set the colour actually item.setText(str(round(zeros[j].area, 2))) model.setItem(i, j, item) return model
class dockUrlMonitor(QTreeView): ''' dock widget for get all credentials logger netcreds''' def __init__(self, parent=None,info={}): super(dockUrlMonitor, self).__init__(parent) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.model = QStandardItemModel() self.model.setHorizontalHeaderLabels(['URL','HTTP-Headers']) self.setModel(self.model) self.setUniformRowHeights(True) self.setColumnWidth(0,130) def writeModeData(self,data): ''' get data output and add on QtableWidgets ''' ParentMaster = QStandardItem('[ {0[src]} > {0[dst]} ] {1[Method]} {1[Host]}{1[Path]}'.format( data['urlsCap']['IP'], data['urlsCap']['Headers'])) ParentMaster.setIcon(QIcon('icons/accept.png')) ParentMaster.setSizeHint(QSize(30,30)) for item in data['urlsCap']['Headers']: ParentMaster.appendRow([QStandardItem('{}'.format(item)), QStandardItem(data['urlsCap']['Headers'][item])]) self.model.appendRow(ParentMaster) self.setFirstColumnSpanned(ParentMaster.row(), self.rootIndex(), True) self.scrollToBottom() def clear(self): self.model.clear() def stopProcess(self): self.clearSelection()
class dockUrlMonitor(QTreeView): ''' dock widget for get all credentials logger netcreds''' def __init__(self, parent=None, info={}): super(dockUrlMonitor, self).__init__(parent) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.model = QStandardItemModel() self.model.setHorizontalHeaderLabels(['URL', 'HTTP-Headers']) self.setModel(self.model) self.setUniformRowHeights(True) self.setColumnWidth(0, 130) def writeModeData(self, data): ''' get data output and add on QtableWidgets ''' ParentMaster = QStandardItem( '[ {0[src]} > {0[dst]} ] {1[Method]} {1[Host]}{1[Path]}'.format( data['urlsCap']['IP'], data['urlsCap']['Headers'])) ParentMaster.setIcon(QIcon('icons/accept.png')) ParentMaster.setSizeHint(QSize(30, 30)) for item in data['urlsCap']['Headers']: ParentMaster.appendRow([ QStandardItem('{}'.format(item)), QStandardItem(data['urlsCap']['Headers'][item]) ]) self.model.appendRow(ParentMaster) self.setFirstColumnSpanned(ParentMaster.row(), self.rootIndex(), True) self.scrollToBottom() def clear(self): self.model.clear() def stopProcess(self): self.clearSelection()
def __display_table_rslt(self, table_rows): ''' controls table_comp_rslt widget fill the widget with table_rows list @param table_rows: [] ''' rows_count = len(table_rows) model = QStandardItemModel(rows_count, 3) model.setHorizontalHeaderLabels(TAB_LABELS) # fill model with data for row in range(rows_count): for col in range(3): item = QStandardItem() item.setData(str(table_rows[row][col]), Qt.DisplayRole) model.setItem(row, col, item) # self.table_comp_rslt.clearContents() if self.table_comp_rslt.isSortingEnabled(): self.table_comp_rslt.setSortingEnabled(False) proxy = numsort.NumberSortModel() proxy.setSourceModel(model) self.table_comp_rslt.setModel(proxy) self.table_comp_rslt.resizeColumnsToContents() self.table_comp_rslt.setSortingEnabled(True)
def initialize_buckets_table(self): self.storj_engine = StorjEngine() # init StorjEngine logger.info("resolving buckets") model = QStandardItemModel(1, 1) # initialize model for inserting to table model.setHorizontalHeaderLabels(['Name', 'Storage', 'Transfer', 'ID']) i = 0 try: for bucket in self.storj_engine.storj_client.bucket_list(): item = QStandardItem(bucket.name) model.setItem(i, 0, item) # row, column, item (QStandardItem) item = QStandardItem(str(bucket.storage)) model.setItem(i, 1, item) # row, column, item (QStandardItem) item = QStandardItem(str(bucket.transfer)) model.setItem(i, 2, item) # row, column, item (QStandardItem) item = QStandardItem(bucket.id) model.setItem(i, 3, item) # row, column, item (QStandardItem) i = i + 1 except sjexc.StorjBridgeApiError as e: QtGui.QMessageBox.about( self, 'Unhandled bucket resolving exception', 'Exception: %s' % e) self.bucket_manager_ui.total_buckets_label.setText(str(i)) # set label of user buckets number self.bucket_manager_ui.bucket_list_tableview.setModel(model) self.bucket_manager_ui.bucket_list_tableview.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)
def actualizePeakModelComparative(): model = QStandardItemModel() #root=MSDialogController.getColouredRootItem(sample) sampleList = QApplication.instance().model groups = sampleList.peaksGrouping() model.setVerticalHeaderLabels(["/".join(map(str, round([mass, rt], 4).tolist())) for mass, rt in sorted(groups.keys(), key=lambda x:x[0])]) model.setHorizontalHeaderLabels([spl.shortName() for spl in sampleList.isamples()]) for i, key in enumerate(sorted(groups.keys(), key=lambda x:x[0])): zeros = [0.] * len(sampleList) for peak in groups[key]: try: idx = [spl.shortName() for spl in sampleList].index(peak.sample.shortName()) except ValueError: print "Error in %s"%MSDialogController.actualizePeakModelComparative.__name__ zeros[idx] = peak for j in xrange(len(zeros)): item = QStandardItem() if not zeros[j]: item.setBackground(QBrush(Qt.red)) item.setText("Not found") else: MSDialogController.setRightIcon(zeros[j], item)#set the colour actually item.setText(str(round(zeros[j].area, 2))) model.setItem(i, j, item) return model
class BreakpointsViewer(QTreeView): """ showing bps """ def __init__(self, parent): super(QTreeView, self).__init__(parent) self.setAutoScroll(True) self.source_files = {} self.focus_signal = None self.header().setResizeMode(QHeaderView.ResizeToContents) self._show_args = None self.bp_data = QStandardItemModel() self.setModel(self.bp_data) self.setAlternatingRowColors(True) def set_focus_signal(self, signal): """ set callback to focus source file line""" self.focus_signal = signal def clear(self): """ clear the widget""" self.bp_data.clear() self.bp_data.setHorizontalHeaderLabels(['ID', 'Hits', 'Ignore Count', 'Condition']) def update_bp_info(self, target): """ update breakpoint info """ self.clear() root = self.bp_data.invisibleRootItem() for breakpoint in target.breakpoint_iter(): if not breakpoint.IsValid() or breakpoint.IsInternal(): continue bp_item = QStandardItem(str(breakpoint.id)) bp_row =[bp_item, QStandardItem(str(breakpoint.GetHitCount())), QStandardItem(str(breakpoint.GetIgnoreCount())), QStandardItem(str(breakpoint.GetCondition()))] for loc in breakpoint: loc_row = [QStandardItem(str(loc.GetID())), QStandardItem(str(loc.GetAddress().GetLineEntry()))] bp_item.appendRow(loc_row) root.appendRow(bp_row) self.expandToDepth(1) def mousePressEvent(self, event): """ overrided """ idx = self.indexAt(event.pos()) if idx.isValid() and self.focus_signal: model = idx.model() idx = idx.sibling(idx.row(), 0) if idx.isValid(): item = model.itemFromIndex(idx) if item and item.isSelectable(): if item in self.source_files: file_info = self.source_files[item] if self.focus_signal: self.focus_signal.emit(file_info.GetFileSpec().fullpath, file_info.GetLine()) self.frame_changed.emit(self.frames[item]) else: logging.error('frame cannot find associated source file') QTreeView.mousePressEvent(self, event)
def buildModel(self, choosenOne): identificationModel = QStandardItemModel() if choosenOne.formulas: identificationModel.setHorizontalHeaderLabels(["score", "formula", "diff mass", "names"]) for i, f in enumerate(choosenOne.formulas.iterkeys()): identificationModel.setItem(i, 0, MSStandardItem(str(choosenOne.formulas[f]["score"]))) identificationModel.setItem(i, 1, QStandardItem(str(f))) identificationModel.setItem(i, 2, MSStandardItem(str(choosenOne.formulas[f]["diffmass"]))) identificationModel.setItem(i, 3, QStandardItem(choosenOne.formulas[f]["names"])) return identificationModel
def _configure_model(self): model = QStandardItemModel(0, 3, self) # Set headers headers = [ self.tr('Name'), self.tr('Data Type'), self.tr('Description') ] model.setHorizontalHeaderLabels(headers) self.setModel(model)
def populateTable(self, table): cols = len(self.param.cols) rows = len(table) model = QStandardItemModel(rows, cols) # Set headers model.setHorizontalHeaderLabels(self.param.cols) # Populate table for i in xrange(rows): for j in xrange(cols): item = QStandardItem(table[i][j]) model.setItem(i, j, item) self.tblView.setModel(model)
def set_headers(self, qtable): feature_type = utils_giswater.get_item_data( self.dlg_lot, self.dlg_lot.cmb_visit_class, 2).lower() columns_name = self.controller.get_columns_list('om_visit_lot_x_' + str(feature_type)) columns_name.append(['validate']) standard_model = QStandardItemModel() qtable.setModel(standard_model) qtable.horizontalHeader().setStretchLastSection(True) # # Get headers headers = [] for x in columns_name: headers.append(x[0]) # Set headers standard_model.setHorizontalHeaderLabels(headers)
def getSampleModel(spl, flags='peak', **kw): from gui.MetBaseGui import MSStandardItem if flags not in ('peak', 'cluster', 'id'): return model = QStandardItemModel() if flags == 'peak': from utils.misc import Hot areas = [peak.area for peak in spl.rawPeaks.ipeaks()] mxInt = max(areas) model.setHorizontalHeaderLabels(MSSample.peakModelLabel) for i, peak in enumerate(spl.rawPeaks.ipeaks()): model.setItem(i, 0, MSStandardItem(str(peak.mass()))) model.item(i, 0).setBackground( QBrush(Hot._get_color(areas[i] / mxInt, True, alpha=0.5))) model.setItem(i, 1, MSStandardItem(str(peak.rt))) model.item(i, 1).setBackground( QBrush(Hot._get_color(areas[i] / mxInt, True, alpha=0.5))) model.setItem(i, 2, MSStandardItem(str(peak.area))) model.item(i, 2).setBackground( QBrush(Hot._get_color(areas[i] / mxInt, True, alpha=0.5))) model.setItem(i, 3, MSStandardItem(str(peak.sn))) model.item(i, 3).setBackground( QBrush(Hot._get_color(areas[i] / mxInt, True, alpha=0.5))) model.setItem(i, 4, MSStandardItem(str(peak.r_coef))) model.item(i, 4).setBackground( QBrush(Hot._get_color(areas[i] / mxInt, True, alpha=0.5))) elif flags == 'cluster': model.setHorizontalHeaderLabels(MSSample.clusterModelLabel) for i, peak in enumerate(spl.mappedPeaks.ipeaks()): model.setItem(i, 0, MSStandardItem(str(peak.mass()))) model.setItem(i, 1, MSStandardItem(str(peak.rt))) model.setItem(i, 2, MSStandardItem(str(peak.area))) info_iso = "" info_frag = "" for iso in peak.isoCluster: info_iso += '%s/%s\t' % (str(iso.mass()), str(iso.rt)) for add in peak.fragCluster: info_frag += '%s/%s\t' % (str(add.mass()), str(add.rt)) model.setItem(i, 3, MSStandardItem(info_iso)) model.setItem(i, 4, MSStandardItem(info_frag)) return model
def getSampleModel(spl, flags='peak', **kw): from gui.MetBaseGui import MSStandardItem if flags not in ('peak', 'cluster', 'id'): return model = QStandardItemModel() if flags=='peak': from utils.misc import Hot areas=[peak.area for peak in spl.rawPeaks.ipeaks()] mxInt=max(areas) model.setHorizontalHeaderLabels(MSSample.peakModelLabel) for i, peak in enumerate(spl.rawPeaks.ipeaks()): model.setItem(i, 0, MSStandardItem(str(peak.mass()))) model.item(i, 0).setBackground(QBrush(Hot._get_color(areas[i]/mxInt, True, alpha=0.5))) model.setItem(i, 1, MSStandardItem(str(peak.rt))) model.item(i, 1).setBackground(QBrush(Hot._get_color(areas[i]/mxInt, True, alpha=0.5))) model.setItem(i, 2, MSStandardItem(str(peak.area))) model.item(i, 2).setBackground(QBrush(Hot._get_color(areas[i]/mxInt, True, alpha=0.5))) model.setItem(i, 3, MSStandardItem(str(peak.sn))) model.item(i, 3).setBackground(QBrush(Hot._get_color(areas[i]/mxInt, True, alpha=0.5))) model.setItem(i, 4, MSStandardItem(str(peak.r_coef))) model.item(i, 4).setBackground(QBrush(Hot._get_color(areas[i]/mxInt, True, alpha=0.5))) elif flags=='cluster': model.setHorizontalHeaderLabels(MSSample.clusterModelLabel) for i, peak in enumerate(spl.mappedPeaks.ipeaks()): model.setItem(i, 0, MSStandardItem(str(peak.mass()))) model.setItem(i, 1, MSStandardItem(str(peak.rt))) model.setItem(i, 2, MSStandardItem(str(peak.area))) info_iso ="";info_frag="" for iso in peak.isoCluster: info_iso += '%s/%s\t'%(str(iso.mass()),str(iso.rt)) for add in peak.fragCluster: info_frag += '%s/%s\t'%(str(add.mass()),str(add.rt)) model.setItem(i, 3, MSStandardItem(info_iso)) model.setItem(i, 4, MSStandardItem(info_frag)) return model
def __init__(self, data, parent=None): """Constructor.""" super(GDALLocationInfoForm, self).__init__(parent) self.setupUi(self) self.treeView.setSelectionBehavior(QAbstractItemView.SelectRows) model = QStandardItemModel() model.setHorizontalHeaderLabels([self.tr('object/attribute'), self.tr('value')]) self.treeView.setModel(model) self.treeView.setUniformRowHeights(True) for object_name, object_attrs in data.items(): parent = QStandardItem(object_name) for attr_name, attr_value in object_attrs.items(): attr_name_item = QStandardItem(attr_name) attr_value_item = QStandardItem(attr_value) parent.appendRow([attr_name_item, attr_value_item]) model.appendRow(parent)
class EntryList: def __init__(self, filename=None): self.scopes = {} self.topLevelEntries = [] self.model = QStandardItemModel() self.model.setHorizontalHeaderLabels(["Name", "File", "Line", "Type"]) if filename: self.readFromFile(filename) def readFromFile(self, filename): self.scopes = {} self.topLevelEntries = [] self.model.clear() self.model.setHorizontalHeaderLabels(["Name", "File", "Line", "Type"]) e = ctags.TagEntry() tf = ctags.CTags(filename) while tf.next(e): self.addFromTagEntry(e) def getScope(self, scope): hier = scope.split("::") for s in range(len(hier)): scopename = "::".join(hier[0:s+1]) if scopename not in self.scopes: self.scopes[scopename] = Struct(self) return self.scopes[scope] def addFromTagEntry(self, e): kind = e['kind'] name = e['name'] file_ = e['file'] lineNumber = int(e['lineNumber']) if e['struct']: scope = e['struct'] elif e['class']: scope = e['class'] else: scope = None # Only add a class/struct if it wasn't present in the file before; this # can happen if there are template specializations such as myclass and # myclass<T>, which are both represented as myclass in the file. If the # entry is present, it will have a line number, so use that as a # heuristic ;). add = True if kind == "class": n = self.getScope(scope+"::"+name if scope else name) if n.lineNumber == None: n.setValues(name, file_, lineNumber, scope, Struct.CLASS) else: add = False elif kind == "struct": n = self.getScope(scope+"::"+name if scope else name) if n.lineNumber == None: n.setValues(name, file_, lineNumber, scope, Struct.STRUCT) else: add = False elif kind == "function": n = Function(self) n.setValues(name, file_, lineNumber, scope, e['signature']) elif kind == "member" and scope: # namespace members are declared as member, but don't have a scope n = Member(self) n.setValues(name, file_, lineNumber, scope, {"private": Member.PRIVATE, "protected": Member.PROTECTED, "public": Member.PUBLIC, None: None}[e['access']]) else: n = Entry(self) n.setValues(name, file_, lineNumber, scope) if add: n.addToParent()
class OWTestLearners(widget.OWWidget): name = "Test & Score" description = "Cross-validation accuracy estimation." icon = "icons/TestLearners1.svg" priority = 100 inputs = [("Learner", Learner, "set_learner", widget.Multiple), ("Data", Table, "set_train_data", widget.Default), ("Test Data", Table, "set_test_data"), ("Preprocessor", Preprocess, "set_preprocessor")] outputs = [("Predictions", Orange.data.Table), ("Evaluation Results", Orange.evaluation.Results)] settingsHandler = settings.ClassValuesContextHandler() #: Resampling/testing types KFold, LeaveOneOut, ShuffleSplit, TestOnTrain, TestOnTest = 0, 1, 2, 3, 4 #: Selected resampling type resampling = settings.Setting(0) #: Number of folds for K-fold cross validation k_folds = settings.Setting(10) #: Number of repeats for ShuffleSplit sampling n_repeat = settings.Setting(10) #: ShuffleSplit sampling p sample_p = settings.Setting(75) TARGET_AVERAGE = "(Average over classes)" class_selection = settings.ContextSetting(TARGET_AVERAGE) def __init__(self): super().__init__() self.data = None self.test_data = None self.preprocessor = None self.train_data_missing_vals = False self.test_data_missing_vals = False #: An Ordered dictionary with current inputs and their testing #: results. self.learners = OrderedDict() sbox = gui.widgetBox(self.controlArea, "Sampling") rbox = gui.radioButtons( sbox, self, "resampling", callback=self._param_changed ) gui.appendRadioButton(rbox, "Cross validation") ibox = gui.indentedBox(rbox) gui.spin(ibox, self, "k_folds", 2, 50, label="Number of folds:", callback=self.kfold_changed) gui.appendRadioButton(rbox, "Leave one out") gui.appendRadioButton(rbox, "Random sampling") ibox = gui.indentedBox(rbox) gui.spin(ibox, self, "n_repeat", 2, 50, label="Repeat train/test", callback=self.shuffle_split_changed) gui.widgetLabel(ibox, "Relative training set size:") gui.hSlider(ibox, self, "sample_p", minValue=1, maxValue=99, ticks=20, vertical=False, labelFormat="%d %%", callback=self.shuffle_split_changed) gui.appendRadioButton(rbox, "Test on train data") gui.appendRadioButton(rbox, "Test on test data") rbox.layout().addSpacing(5) self.apply_button = gui.button( rbox, self, "Apply", callback=self.apply, default=True) self.cbox = gui.widgetBox(self.controlArea, "Target class") self.class_selection_combo = gui.comboBox( self.cbox, self, "class_selection", items=[], sendSelectedValue=True, valueType=str, callback=self._on_target_class_changed, contentsLength=8) gui.rubber(self.controlArea) self.view = QTreeView( rootIsDecorated=False, uniformRowHeights=True, wordWrap=True, editTriggers=QTreeView.NoEditTriggers ) header = self.view.header() header.setResizeMode(QHeaderView.ResizeToContents) header.setDefaultAlignment(Qt.AlignCenter) header.setStretchLastSection(False) self.result_model = QStandardItemModel(self) self.result_model.setHorizontalHeaderLabels(["Method"]) self.view.setModel(self.result_model) self.view.setItemDelegate(ItemDelegate()) box = gui.widgetBox(self.mainArea, "Evaluation Results") box.layout().addWidget(self.view) def sizeHint(self): return QSize(780, 1) def set_learner(self, learner, key): """ Set the input `learner` for `key`. """ if key in self.learners and learner is None: # Removed del self.learners[key] else: self.learners[key] = Input(learner, None, None) self._invalidate([key]) def set_train_data(self, data): """ Set the input training dataset. """ self.error(0) self.information(0) if data and not data.domain.class_var: self.error(0, "Train data input requires a class variable") data = None if isinstance(data, SqlTable): if data.approx_len() < AUTO_DL_LIMIT: data = Table(data) else: self.information(0, "Train data has been sampled") data_sample = data.sample_time(1, no_cache=True) data_sample.download_data(AUTO_DL_LIMIT, partial=True) data = Table(data_sample) self.warning(4) self.train_data_missing_vals = data is not None and \ np.isnan(data.Y).any() if self.train_data_missing_vals or self.test_data_missing_vals: self.warning(4, self._get_missing_data_warning( self.train_data_missing_vals, self.test_data_missing_vals )) if data: data = RemoveNaNClasses(data) self.data = data self.closeContext() if data is not None: self._update_class_selection() self.openContext(data.domain.class_var) self._invalidate() def set_test_data(self, data): """ Set the input separate testing dataset. """ self.error(1) self.information(1) if data and not data.domain.class_var: self.error(1, "Test data input requires a class variable") data = None if isinstance(data, SqlTable): if data.approx_len() < AUTO_DL_LIMIT: data = Table(data) else: self.information(1, "Test data has been sampled") data_sample = data.sample_time(1, no_cache=True) data_sample.download_data(AUTO_DL_LIMIT, partial=True) data = Table(data_sample) self.warning(4) self.test_data_missing_vals = data is not None and \ np.isnan(data.Y).any() if self.train_data_missing_vals or self.test_data_missing_vals: self.warning(4, self._get_missing_data_warning( self.train_data_missing_vals, self.test_data_missing_vals )) if data: data = RemoveNaNClasses(data) self.test_data = data if self.resampling == OWTestLearners.TestOnTest: self._invalidate() def _get_missing_data_warning(self, train_missing, test_missing): return "Instances with unknown target values were removed from{}data"\ .format(train_missing * test_missing * " " or train_missing * " train " or test_missing * " test ") def set_preprocessor(self, preproc): """ Set the input preprocessor to apply on the training data. """ self.preprocessor = preproc self._invalidate() def handleNewSignals(self): """Reimplemented from OWWidget.handleNewSignals.""" self._update_class_selection() self.apply() def kfold_changed(self): self.resampling = OWTestLearners.KFold self._param_changed() def shuffle_split_changed(self): self.resampling = OWTestLearners.ShuffleSplit self._param_changed() def _param_changed(self): self._invalidate() def _update_results(self): """ Run/evaluate the learners. """ self.warning([1, 2]) self.error(2) if self.data is None: return class_var = self.data.domain.class_var if self.resampling == OWTestLearners.TestOnTest: if self.test_data is None: self.warning(2, "Missing separate test data input") return elif self.test_data.domain.class_var != class_var: self.error(2, ("Inconsistent class variable between test " + "and train data sets")) return # items in need of an update items = [(key, slot) for key, slot in self.learners.items() if slot.results is None] learners = [slot.learner for _, slot in items] if len(items) == 0: return if self.test_data is not None and \ self.resampling != OWTestLearners.TestOnTest: self.warning(1, "Test data is present but unused. " "Select 'Test on test data' to use it.") rstate = 42 def update_progress(finished): self.progressBarSet(100 * finished) common_args = dict( store_data=True, preprocessor=self.preprocessor, callback=update_progress) self.setStatusMessage("Running") self.progressBarInit() try: if self.resampling == OWTestLearners.KFold: warnings = [] results = Orange.evaluation.CrossValidation( self.data, learners, k=self.k_folds, random_state=rstate, warnings=warnings, **common_args) if warnings: self.warning(2, warnings[0]) elif self.resampling == OWTestLearners.LeaveOneOut: results = Orange.evaluation.LeaveOneOut( self.data, learners, **common_args) elif self.resampling == OWTestLearners.ShuffleSplit: train_size = self.sample_p / 100 results = Orange.evaluation.ShuffleSplit( self.data, learners, n_resamples=self.n_repeat, train_size=train_size, test_size=None, random_state=rstate, **common_args) elif self.resampling == OWTestLearners.TestOnTrain: results = Orange.evaluation.TestOnTrainingData( self.data, learners, **common_args) elif self.resampling == OWTestLearners.TestOnTest: results = Orange.evaluation.TestOnTestData( self.data, self.test_data, learners, **common_args) else: assert False except RuntimeError as e: self.error(2, str(e)) self.setStatusMessage("") self.progressBarFinished() return learner_key = {slot.learner: key for key, slot in self.learners.items()} for learner, result in zip(learners, split_by_model(results)): stats = None if class_var.is_discrete: scorers = classification_stats.scores elif class_var.is_continuous: scorers = regression_stats.scores else: scorers = None if scorers: ex = result.failed[0] if ex: stats = [Try.Fail(ex)] * len(scorers) result = Try.Fail(ex) else: stats = [Try(lambda: score(result)) for score in scorers] result = Try.Success(result) key = learner_key[learner] self.learners[key] = \ self.learners[key]._replace(results=result, stats=stats) self.setStatusMessage("") self.progressBarFinished() def _update_header(self): # Set the correct horizontal header labels on the results_model. headers = ["Method"] if self.data is not None: if self.data.domain.has_discrete_class: headers.extend(classification_stats.headers) else: headers.extend(regression_stats.headers) # remove possible extra columns from the model. for i in reversed(range(len(headers), self.result_model.columnCount())): self.result_model.takeColumn(i) self.result_model.setHorizontalHeaderLabels(headers) def _update_stats_model(self): # Update the results_model with up to date scores. # Note: The target class specific scores (if requested) are # computed as needed in this method. model = self.view.model() # clear the table model, but preserving the header labels for r in reversed(range(model.rowCount())): model.takeRow(r) target_index = None if self.data is not None: class_var = self.data.domain.class_var if class_var.is_discrete and \ self.class_selection != self.TARGET_AVERAGE: target_index = class_var.values.index(self.class_selection) else: class_var = None errors = [] has_missing_scores = False for key, slot in self.learners.items(): name = learner_name(slot.learner) head = QStandardItem(name) head.setData(key, Qt.UserRole) if isinstance(slot.results, Try.Fail): head.setToolTip(str(slot.results.exception)) head.setText("{} (error)".format(name)) head.setForeground(QtGui.QBrush(Qt.red)) errors.append("{name} failed with error:\n" "{exc.__class__.__name__}: {exc!s}" .format(name=name, exc=slot.results.exception)) row = [head] if class_var is not None and class_var.is_discrete and \ target_index is not None: if slot.results is not None and slot.results.success: ovr_results = results_one_vs_rest( slot.results.value, target_index) stats = [Try(lambda: score(ovr_results)) for score in classification_stats.scores] else: stats = None else: stats = slot.stats if stats is not None: for stat in stats: item = QStandardItem() if stat.success: item.setText("{:.3f}".format(stat.value[0])) else: item.setToolTip(str(stat.exception)) has_missing_scores = True row.append(item) model.appendRow(row) if errors: self.error(3, "\n".join(errors)) else: self.error(3) if has_missing_scores: self.warning(3, "Some scores could not be computed") else: self.warning(3) def _update_class_selection(self): self.class_selection_combo.setCurrentIndex(-1) self.class_selection_combo.clear() if not self.data: return if self.data.domain.has_discrete_class: self.cbox.setVisible(True) class_var = self.data.domain.class_var items = [self.TARGET_AVERAGE] + class_var.values self.class_selection_combo.addItems(items) class_index = 0 if self.class_selection in class_var.values: class_index = class_var.values.index(self.class_selection) + 1 self.class_selection_combo.setCurrentIndex(class_index) self.class_selection = items[class_index] else: self.cbox.setVisible(False) def _on_target_class_changed(self): self._update_stats_model() def _invalidate(self, which=None): # Invalidate learner results for `which` input keys # (if None then all learner results are invalidated) if which is None: which = self.learners.keys() model = self.view.model() statmodelkeys = [model.item(row, 0).data(Qt.UserRole) for row in range(model.rowCount())] for key in which: self.learners[key] = \ self.learners[key]._replace(results=None, stats=None) if key in statmodelkeys: row = statmodelkeys.index(key) for c in range(1, model.columnCount()): item = model.item(row, c) if item is not None: item.setData(None, Qt.DisplayRole) item.setData(None, Qt.ToolTipRole) self.apply_button.setEnabled(True) def apply(self): self.apply_button.setEnabled(False) self._update_header() # Update the view to display the model names self._update_stats_model() self._update_results() self._update_stats_model() self.commit() def commit(self): valid = [slot for slot in self.learners.values() if slot.results is not None and slot.results.success] if valid: # Evaluation results combined = results_merge([slot.results.value for slot in valid]) combined.learner_names = [learner_name(slot.learner) for slot in valid] # Predictions & Probabilities predictions = combined.get_augmented_data(combined.learner_names) else: combined = None predictions = None self.send("Evaluation Results", combined) self.send("Predictions", predictions)
class ConnectionsDialog(QtGui.QDialog, Ui_DlgConnections): on_connect = pyqtSignal(str, str) on_add = pyqtSignal(str, list) on_connection_change = pyqtSignal() on_zoom_change = pyqtSignal() _connections_array = "connections" _table_headers = OrderedDict([("ID", "id"), ("Min. Zoom", "minzoom"), ("Max. Zoom", "maxzoom"), ("Description", "description")]) _OMT = "OpenMapTiles.com" _predefined_connections = { _OMT: "https://free.tilehosting.com/data/v3.json?key={token}" } _tokens = {_OMT: "6irhAXGgsi8TrIDL0211"} def __init__(self, default_browse_directory): QtGui.QDialog.__init__(self) self.setupUi(self) self.options = OptionsGroup(self.grpOptions, self._on_zoom_change) self.settings = QSettings("VtrSettings") self.connections = {} self.selected_connection = None self.selected_layer_id = None self.cbxConnections.currentIndexChanged['QString'].connect( self._handle_connection_change) self.btnCreateConnection.clicked.connect(self._create_connection) self.btnConnect.clicked.connect(self._handle_connect) self.btnEdit.clicked.connect(self._edit_connection) self.btnDelete.clicked.connect(self._delete_connection) self.btnAdd.clicked.connect(self._load_tiles_for_connection) self.btnSave.clicked.connect(self._export_connections) self.btnLoad.clicked.connect(self._import_connections) self.btnHelp.clicked.connect(lambda: webbrowser.open(_HELP_URL)) self.btnBrowse.clicked.connect(self._select_file_path) self.btnBrowseTrexCache.clicked.connect(self._select_trex_cache_folder) self.open_path = None self.browse_path = default_browse_directory self.model = QStandardItemModel() self.model.setHorizontalHeaderLabels(self._table_headers.keys()) self.tblLayers.setModel(self.model) self._load_connections() self._add_loaded_connections() self.edit_connection_dialog = EditConnectionDialog() _update_size(self) def _select_file_path(self): open_file_name = QFileDialog.getOpenFileName( None, "Select Mapbox Tiles", self.browse_path, "Mapbox Tiles (*.mbtiles)") if open_file_name and os.path.isfile(open_file_name): self.txtPath.setText(open_file_name) self._handle_path_or_folder_selection(open_file_name) def _select_trex_cache_folder(self): open_file_name = QFileDialog.getExistingDirectory( None, "Select t-rex Cache directory", self.browse_path) if open_file_name and os.path.isdir(open_file_name): self.txtTrexCachePath.setText(open_file_name) self._handle_path_or_folder_selection(open_file_name) def _handle_path_or_folder_selection(self, path): self.browse_path = path self.open_path = path name = os.path.basename(path) self.on_connect.emit(name, path) def _on_zoom_change(self): self.on_zoom_change.emit() def set_nr_of_tiles(self, nr_tiles): self.options.set_nr_of_tiles(nr_tiles) def _load_tiles_for_connection(self): indexes = self.tblLayers.selectionModel().selectedRows() selected_layers = map(lambda i: self.model.item(i.row()).text(), indexes) name, url = self._get_current_connection() self.on_add.emit(url, selected_layers) def _export_connections(self): file_name = QFileDialog.getSaveFileName( None, "Export Vector Tile Reader Connections", "", "csv (*.csv)") if file_name: with open(file_name, 'w') as csvfile: fieldnames = ['name', 'url'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() for name in self.connections: writer.writerow({ 'name': name, 'url': self.connections[name] }) def _import_connections(self): file_name = QFileDialog.getOpenFileName( None, "Export Vector Tile Reader Connections", "", "csv (*.csv)") if file_name: with open(file_name, 'r') as csvfile: reader = csv.DictReader(csvfile) for row in reader: self._set_connection_url(row['name'], row['url']) self._add_loaded_connections() def _load_connections(self): settings = self.settings connections = settings.beginReadArray(self._connections_array) for i in range(connections): settings.setArrayIndex(i) name = settings.value("name") url = settings.value("url") self._set_connection_url(name, url) settings.endArray() def _add_loaded_connections(self): for index, name in enumerate(self._predefined_connections.keys()): url = self._predefined_connections[name] self._set_connection_url(name, url) for name in sorted(self.connections): is_already_added = self.cbxConnections.findText(name) != -1 if not is_already_added: self.cbxConnections.addItem(name) if len(self.connections) > 0: self.cbxConnections.setCurrentIndex(0) def _delete_connection(self): index = self.cbxConnections.currentIndex() connection = self.cbxConnections.currentText() msg = "Are you sure you want to remove the connection '{}' and all associated settings?".format( connection) reply = QMessageBox.question(self.activateWindow(), 'Confirm Delete', msg, QMessageBox.Yes, QMessageBox.No) if reply == QtGui.QMessageBox.Yes: self.cbxConnections.removeItem(index) self.connections.pop(connection) self._save_connections() def _save_connections(self): settings = self.settings settings.beginWriteArray(self._connections_array) for index, key in enumerate(self.connections): settings.setArrayIndex(index) settings.setValue("name", key) settings.setValue("url", self.connections[key]) settings.endArray() def _set_connection_url(self, name, url): self.connections[name] = url def _handle_connect(self): conn = self._get_current_connection() name = conn[0] url = conn[1] self.on_connect.emit(name, url) self.txtPath.setText("") def _get_current_connection(self): if self.tabServer.isEnabled(): name = self.cbxConnections.currentText() url = self.connections[name] elif self.tabFile.isEnabled(): url = self.txtPath.text() name = os.path.basename(url) else: url = self.txtTrexCachePath.text() name = os.path.basename(url) if name in self._predefined_connections: url = url.replace("{token}", self._tokens[name]) return name, url def show(self): self.exec_() def keep_dialog_open(self): return self.chkKeepOpen.isChecked() def set_layers(self, layers): self.model.removeRows(0, self.model.rowCount()) for row_index, layer in enumerate(layers): for header_index, header in enumerate(self._table_headers.keys()): header_value = self._table_headers[header] if header_value in layer: value = str(layer[header_value]) else: value = "-" self.model.setItem(row_index, header_index, QStandardItem(value)) add_enabled = layers is not None and len(layers) > 0 self.btnAdd.setEnabled(add_enabled) def _edit_connection(self): conn = self._get_current_connection() self._create_or_update_connection(name=conn[0], url=conn[1]) def _create_connection(self): self._create_or_update_connection("", "") def _create_or_update_connection(self, name=None, url=None): self.edit_connection_dialog.set_name_and_path(name, url) result = self.edit_connection_dialog.exec_() if result == QtGui.QDialog.Accepted: newname, newurl = self.edit_connection_dialog.get_connection() self._set_connection_url(newname, newurl) if newname != name: self.cbxConnections.addItem(newname) self.cbxConnections.setCurrentIndex(len(self.connections) - 1) self._save_connections() def _handle_connection_change(self, name): self.set_layers([]) enable_connect = False enable_edit = False if name in self.connections: enable_connect = True enable_edit = name not in self._predefined_connections self.btnConnect.setEnabled(enable_connect) self.btnEdit.setEnabled(enable_edit) self.btnDelete.setEnabled(enable_edit) self.on_connection_change.emit()
def table(window): tw = TableWidget(window, "Enter", foo, useTextEdit=False) model = QStandardItemModel(tw) model.setHorizontalHeaderLabels([u"foo", u"bar"]) tw.setModel(model) return tw
class ProgramInfoFiles(QWidget, Ui_ProgramInfoFiles): def __init__(self, context, update_main_ui_state, set_widget_enabled, is_alive, show_upload_files_wizard, show_download_wizard): QWidget.__init__(self) self.setupUi(self) self.session = context.session self.script_manager = context.script_manager self.program = context.program self.update_main_ui_state = update_main_ui_state self.set_widget_enabled = set_widget_enabled self.is_alive = is_alive self.show_download_wizard = show_download_wizard self.bin_directory = posixpath.join(self.program.root_directory, 'bin') self.refresh_in_progress = False self.any_refresh_in_progress = False # set from ProgramInfoMain.update_ui_state self.available_files = [] self.available_directories = [] self.folder_icon = QIcon(load_pixmap('folder-icon.png')) self.file_icon = QIcon(load_pixmap('file-icon.png')) self.tree_files_model = QStandardItemModel(self) self.tree_files_model_header = ['Name', 'Size', 'Last Modified'] self.tree_files_proxy_model = FilesProxyModel(self) self.last_download_directory = get_home_path() self.tree_files_model.setHorizontalHeaderLabels( self.tree_files_model_header) self.tree_files_proxy_model.setSourceModel(self.tree_files_model) self.tree_files.setModel(self.tree_files_model) self.tree_files.setModel(self.tree_files_proxy_model) self.tree_files.setColumnWidth(0, 210) self.tree_files.setColumnWidth(1, 85) self.tree_files.selectionModel().selectionChanged.connect( self.update_ui_state) self.tree_files.activated.connect(self.rename_activated_file) self.button_upload_files.clicked.connect(show_upload_files_wizard) self.button_download_files.clicked.connect( self.download_selected_files) self.button_rename_file.clicked.connect(self.rename_selected_file) self.button_delete_files.clicked.connect(self.delete_selected_files) self.label_error.setVisible(False) def update_ui_state(self): selection_count = len(self.tree_files.selectionModel().selectedRows()) self.set_widget_enabled(self.button_upload_files, not self.any_refresh_in_progress) self.set_widget_enabled( self.button_download_files, not self.any_refresh_in_progress and selection_count > 0) self.set_widget_enabled( self.button_rename_file, not self.any_refresh_in_progress and selection_count == 1) self.set_widget_enabled( self.button_delete_files, not self.any_refresh_in_progress and selection_count > 0) def close_all_dialogs(self): pass def refresh_files_done(self): self.refresh_in_progress = False self.update_main_ui_state() def refresh_files(self): def cb_walk(result): okay, message = check_script_result(result, decode_stderr=True) if not okay: self.label_error.setText('<b>Error:</b> ' + Qt.escape(message)) self.label_error.setVisible(True) self.refresh_files_done() return self.label_error.setVisible(False) def expand_async(data): try: walk = json.loads( zlib.decompress(buffer(data)).decode('utf-8')) except: walk = None if walk == None or not isinstance(walk, dict): available_files = [] available_directories = [] walk = None else: available_files, available_directories = expand_walk_to_lists( walk) return walk, available_files, available_directories def cb_expand_success(result): walk, available_files, available_directories = result self.available_files = available_files self.available_directories = available_directories if walk != None: expand_walk_to_model(walk, self.tree_files_model, self.folder_icon, self.file_icon) else: self.label_error.setText( '<b>Error:</b> Received invalid data') self.label_error.setVisible(True) self.tree_files.header().setSortIndicator(0, Qt.AscendingOrder) self.refresh_files_done() def cb_expand_error(): self.label_error.setText('<b>Error:</b> Internal async error') self.label_error.setVisible(True) self.refresh_files_done() async_call(expand_async, result.stdout, cb_expand_success, cb_expand_error) self.refresh_in_progress = True self.update_main_ui_state() width1 = self.tree_files.columnWidth(0) width2 = self.tree_files.columnWidth(1) self.tree_files_model.clear() self.tree_files_model.setHorizontalHeaderLabels( self.tree_files_model_header) self.tree_files.setColumnWidth(0, width1) self.tree_files.setColumnWidth(1, width2) self.script_manager.execute_script('walk', cb_walk, [self.bin_directory], max_length=1024 * 1024, decode_output_as_utf8=False) def get_directly_selected_name_items(self): selected_indexes = self.tree_files.selectedIndexes() selected_name_items = [] for selected_index in selected_indexes: if selected_index.column() == 0: mapped_index = self.tree_files_proxy_model.mapToSource( selected_index) selected_name_items.append( self.tree_files_model.itemFromIndex(mapped_index)) return selected_name_items def download_selected_files(self): selected_name_items = self.get_directly_selected_name_items() if len(selected_name_items) == 0: return downloads = [] def expand(name_item): item_type = name_item.data(USER_ROLE_ITEM_TYPE) if item_type == ITEM_TYPE_DIRECTORY: for i in range(name_item.rowCount()): expand(name_item.child(i, 0)) elif item_type == ITEM_TYPE_FILE: filename = get_full_item_path(name_item) downloads.append( Download(filename, QDir.toNativeSeparators(filename))) for selected_name_item in selected_name_items: expand(selected_name_item) if len(downloads) == 0: return download_directory = get_existing_directory( get_main_window(), 'Download Files', self.last_download_directory) if len(download_directory) == 0: return self.last_download_directory = download_directory self.show_download_wizard('files', download_directory, downloads) def rename_activated_file(self, index): if index.column() == 0 and not self.any_refresh_in_progress: mapped_index = self.tree_files_proxy_model.mapToSource(index) name_item = self.tree_files_model.itemFromIndex(mapped_index) item_type = name_item.data(USER_ROLE_ITEM_TYPE) # only rename files via activation, because directories are expanded if item_type == ITEM_TYPE_FILE: self.rename_item(name_item) def rename_selected_file(self): selection_count = len(self.tree_files.selectionModel().selectedRows()) if selection_count != 1: return selected_name_items = self.get_directly_selected_name_items() if len(selected_name_items) != 1: return self.rename_item(selected_name_items[0]) def rename_item(self, name_item): item_type = name_item.data(USER_ROLE_ITEM_TYPE) if item_type == ITEM_TYPE_FILE: title = 'Rename File' type_name = 'file' else: title = 'Rename Directory' type_name = 'directory' old_name = name_item.text() # get new name dialog = ExpandingInputDialog(get_main_window()) dialog.setModal(True) dialog.setWindowTitle(title) dialog.setLabelText('Enter new {0} name:'.format(type_name)) dialog.setInputMode(QInputDialog.TextInput) dialog.setTextValue(old_name) dialog.setOkButtonText('Rename') if dialog.exec_() != QDialog.Accepted: return new_name = dialog.textValue() if new_name == old_name: return # check that new name is valid if len( new_name ) == 0 or new_name == '.' or new_name == '..' or '/' in new_name: QMessageBox.critical( get_main_window(), title + ' Error', 'A {0} name cannot be empty, cannot be one dot [.], cannot be two dots [..] and cannot contain a forward slash [/].' .format(type_name)) return # check that new name is not already in use name_item_parent = name_item.parent() if name_item_parent == None: name_item_parent = self.tree_files_model.invisibleRootItem() for i in range(name_item_parent.rowCount()): if new_name == name_item_parent.child(i).text(): QMessageBox.critical( get_main_window(), title + ' Error', 'The new {0} name is already in use.'.format(type_name)) return absolute_old_name = posixpath.join(self.bin_directory, get_full_item_path(name_item)) absolute_new_name = posixpath.join( posixpath.split(absolute_old_name)[0], new_name) def cb_rename(result): if not report_script_result( result, title + ' Error', u'Could not rename {0}'.format(type_name)): return name_item.setText(new_name) if self.tree_files.header().sortIndicatorSection() == 0: self.tree_files.header().setSortIndicator( 0, self.tree_files.header().sortIndicatorOrder()) self.script_manager.execute_script( 'rename', cb_rename, [absolute_old_name, absolute_new_name]) def delete_selected_files(self): button = QMessageBox.question( get_main_window(), 'Delete Files', 'Irreversibly deleting selected files and directories.', QMessageBox.Ok, QMessageBox.Cancel) if not self.is_alive() or button != QMessageBox.Ok: return selected_name_items = set(self.get_directly_selected_name_items()) if len(selected_name_items) == 0: return script_instance_ref = [None] def progress_canceled(): script_instance = script_instance_ref[0] if script_instance == None: return self.script_manager.abort_script(script_instance) progress = ExpandingProgressDialog(self) progress.set_progress_text_visible(False) progress.setModal(True) progress.setWindowTitle('Delete Files') progress.setLabelText('Collecting files and directories to delete') progress.setRange(0, 0) progress.canceled.connect(progress_canceled) progress.show() files_to_delete = [] dirs_to_delete = [] all_done = False while not all_done: all_done = True for selected_name_item in list(selected_name_items): item_done = False parent = selected_name_item.parent() while not item_done and parent != None: if parent in selected_name_items: selected_name_items.remove(selected_name_item) item_done = True else: parent = parent.parent() if item_done: all_done = False break for selected_name_item in selected_name_items: path = get_full_item_path(selected_name_item) item_type = selected_name_item.data(USER_ROLE_ITEM_TYPE) if item_type == ITEM_TYPE_DIRECTORY: dirs_to_delete.append(posixpath.join(self.bin_directory, path)) else: files_to_delete.append(posixpath.join(self.bin_directory, path)) message = 'Deleting ' if len(files_to_delete) == 1: message += '1 file ' elif len(files_to_delete) > 1: message += '{0} files '.format(len(files_to_delete)) if len(dirs_to_delete) == 1: if len(files_to_delete) > 0: message += 'and ' message += '1 directory' elif len(dirs_to_delete) > 1: if len(files_to_delete) > 0: message += 'and ' message += '{0} directories'.format(len(dirs_to_delete)) progress.setLabelText(message) def cb_delete(result): script_instance = script_instance_ref[0] if script_instance != None: aborted = script_instance.abort else: aborted = False script_instance_ref[0] = None progress.cancel() self.refresh_files() if aborted: QMessageBox.information(get_main_window(), 'Delete Files', u'Delete operation was aborted.') return report_script_result( result, 'Delete Files Error', 'Could not delete selected files/directories:') script_instance_ref[0] = self.script_manager.execute_script( 'delete', cb_delete, [json.dumps(files_to_delete), json.dumps(dirs_to_delete)], execute_as_user=True)
def __init__(self, parent=None): super(LayerSelectionPage, self).__init__(parent) self.parent = parent #convenience link self.confconn_link = self.parent.parent.confconn #flag top prevent read read action on keyword delete. New logic makes this redundant #self.keywordbypass = False QToolTip.setFont(QFont('SansSerif', 10)) #label filterlabel = QLabel('Filter') availablelabel = QLabel('Available Layers') selectionlabel = QLabel('Layer Selections') keywordlabel = QLabel('Keyword') explainlabel = QLabel( "Edit Group assignments using this dialog or to simply initialise the Layer-Config just click 'Finish'" ) #selection buttons chooseallbutton = QPushButton('>>') chooseallbutton.setFixedWidth(self.XFER_BW) chooseallbutton.clicked.connect(self.doChooseAllClickAction) choosebutton = QPushButton('>') choosebutton.setFixedWidth(self.XFER_BW) choosebutton.clicked.connect(self.doChooseClickAction) rejectbutton = QPushButton('<') rejectbutton.setFixedWidth(self.XFER_BW) rejectbutton.clicked.connect(self.doRejectClickAction) rejectallbutton = QPushButton('<<') rejectallbutton.setFixedWidth(self.XFER_BW) rejectallbutton.clicked.connect(self.doRejectAllClickAction) #operation buttons finishbutton = QPushButton('Finish') finishbutton.setToolTip('Finish and Close layer selection dialog') finishbutton.clicked.connect(self.parent.close) resetbutton = QPushButton('Reset') resetbutton.font() resetbutton.setToolTip( 'Read Layer from LDS GetCapabilities request. Overwrites current Layer Config' ) resetbutton.clicked.connect(self.doResetClickAction) self.available_sfpm = LDSSFPAvailableModel(self) self.selection_sfpm = LDSSFPSelectionModel(self) self.available_sfpm.setSourceModel(self.parent.available_model) self.selection_sfpm.setSourceModel(self.parent.selection_model) #textedits filteredit = QLineEdit('') filteredit.setToolTip( 'Filter Available-Layers pane (filter operates across Name and Title fields and accepts Regex expressions)' ) filteredit.textChanged.connect(self.available_sfpm.setActiveFilter) self.keywordcombo = QComboBox() self.keywordcombo.setToolTip( 'Select or Add a unique identifier to be saved in layer config (keyword)' ) self.keywordcombo.addItems(list(self.confconn_link.assigned)) self.keywordcombo.setEditable(True) self.keywordcombo.activated.connect(self.doKeyComboChangeAction) lgindex = self.confconn_link.getLayerGroupIndex( self.confconn_link.lgval, col=1) lgentry = self.confconn_link.lglist[lgindex] if LU.assessNone( lgindex) else None #keywordedit = self.keywordcombo.lineEdit().text().toUtf8().data().decode('utf8')# for writing #if no entry or layer indicated then blank self.keywordcombo.lineEdit().setText( '' if lgentry is None or lgentry[0] == LORG.LAYER else lgentry[1]) #self.confconn_link.lgval)#TODO. group only #header headmodel = QStandardItemModel() headmodel.setHorizontalHeaderLabels([ i[2] for i in self.colparams ][:self.parent.available_model.columnCount()]) headview1 = QHeaderView(Qt.Horizontal) headview1.setModel(headmodel) headview1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) headview2 = QHeaderView(Qt.Horizontal) headview2.setModel(headmodel) headview2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) #table self.available = QTableView() self.available.setSelectionBehavior(QAbstractItemView.SelectRows) self.available.setSelectionMode(QAbstractItemView.MultiSelection) self.selection = QTableView() self.selection.setSelectionBehavior(QAbstractItemView.SelectRows) self.selection.setSelectionMode(QAbstractItemView.MultiSelection) #interesting, must set model after selection attributes but before headers else row selections/headers don't work properly self.available.setModel(self.available_sfpm) self.selection.setModel(self.selection_sfpm) self.available.setSortingEnabled(True) self.available.setHorizontalHeader(headview1) self.selection.setSortingEnabled(True) self.selection.setHorizontalHeader(headview2) for cp in self.colparams: self.available.setColumnWidth(cp[0], cp[1]) self.selection.setColumnWidth(cp[0], cp[1]) self.available.verticalHeader().setVisible(False) self.available.horizontalHeader().setVisible(True) self.selection.verticalHeader().setVisible(False) self.selection.horizontalHeader().setVisible(True) #layout vbox00 = QVBoxLayout() vbox00.addWidget(availablelabel) vbox00.addWidget(self.available) vbox01 = QVBoxLayout() vbox01.addWidget(chooseallbutton) vbox01.addWidget(choosebutton) vbox01.addWidget(rejectbutton) vbox01.addWidget(rejectallbutton) vbox02 = QVBoxLayout() vbox02.addWidget(selectionlabel) vbox02.addWidget(self.selection) vbox10 = QVBoxLayout() vbox10.addWidget(filterlabel) vbox10.addWidget(filteredit) hbox12 = QHBoxLayout() hbox12.addWidget(keywordlabel) hbox12.addStretch(1) #hbox12.addWidget(inspbutton) #hbox12.addWidget(addbutton) #hbox12.addWidget(delbutton) vbox12 = QVBoxLayout() vbox12.addLayout(hbox12) vbox12.addWidget(self.keywordcombo) #00|01|02 #10|11|12 grid0 = QGridLayout() grid0.addLayout(vbox00, 1, 0) grid0.addLayout(vbox01, 1, 1) grid0.addLayout(vbox02, 1, 2) grid0.addLayout(vbox10, 0, 0) grid0.addLayout(vbox12, 0, 2) hbox2 = QHBoxLayout() hbox2.addWidget(resetbutton) hbox2.addStretch(1) hbox2.addWidget(explainlabel) hbox2.addWidget(finishbutton) #gbox1.setLayout(hbox2) vbox3 = QVBoxLayout() vbox3.addLayout(grid0) #vbox3.addLayout(hbox3) #vbox3.addWidget(line0) vbox3.addLayout(hbox2) self.setLayout(vbox3)
class MainWindow(QMainWindow, Ui_MainWindow): qtcb_enumerate = pyqtSignal(str, str, 'char', type((0,)), type((0,)), int, int) qtcb_connected = pyqtSignal(int) qtcb_disconnected = pyqtSignal(int) def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setupUi(self) signal.signal(signal.SIGINT, self.exit_brickv) signal.signal(signal.SIGTERM, self.exit_brickv) self.async_thread = async_start_thread(self) self.setWindowTitle("Brick Viewer " + config.BRICKV_VERSION) self.tree_view_model_labels = ['Name', 'UID', 'Position', 'FW Version'] self.tree_view_model = QStandardItemModel(self) self.tree_view.setModel(self.tree_view_model) self.tree_view.doubleClicked.connect(self.item_double_clicked) self.set_tree_view_defaults() # Remove dummy tab self.tab_widget.removeTab(1) self.name = '<unknown>' self.uid = '<unknown>' self.version = (0, 0, 0) self.disconnect_times = [] self.qtcb_enumerate.connect(self.cb_enumerate) self.qtcb_connected.connect(self.cb_connected) self.qtcb_disconnected.connect(self.cb_disconnected) self.ipcon = IPConnection() self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.qtcb_enumerate.emit) self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.qtcb_connected.emit) self.ipcon.register_callback(IPConnection.CALLBACK_DISCONNECTED, self.qtcb_disconnected.emit) self.current_device_info = None self.flashing_window = None self.advanced_window = None self.delayed_refresh_updates_timer = QTimer() self.delayed_refresh_updates_timer.timeout.connect(self.delayed_refresh_updates) self.delayed_refresh_updates_timer.setInterval(500) self.reset_view() self.button_advanced.setDisabled(True) self.tab_widget.currentChanged.connect(self.tab_changed) self.tab_widget.setMovable(True) self.tab_widget.tabBar().installEventFilter(self) self.button_connect.clicked.connect(self.connect_clicked) self.button_flashing.clicked.connect(self.flashing_clicked) self.button_advanced.clicked.connect(self.advanced_clicked) self.plugin_manager = PluginManager() # host info self.host_infos = config.get_host_infos(config.HOST_INFO_COUNT) self.host_index_changing = True for host_info in self.host_infos: self.combo_host.addItem(host_info.host) self.last_host = None self.combo_host.currentIndexChanged.connect(self.host_index_changed) self.spinbox_port.setValue(self.host_infos[0].port) self.spinbox_port.valueChanged.connect(self.port_changed) self.checkbox_authentication.stateChanged.connect(self.authentication_state_changed) self.label_secret.hide() self.edit_secret.hide() self.edit_secret.setEchoMode(QLineEdit.Password) self.edit_secret.textEdited.connect(self.secret_changed) self.checkbox_secret_show.hide() self.checkbox_secret_show.stateChanged.connect(self.secret_show_state_changed) self.checkbox_remember_secret.hide() self.checkbox_remember_secret.stateChanged.connect(self.remember_secret_state_changed) self.checkbox_authentication.setChecked(self.host_infos[0].use_authentication) self.edit_secret.setText(self.host_infos[0].secret) self.checkbox_remember_secret.setChecked(self.host_infos[0].remember_secret) self.host_index_changing = False # auto-reconnect self.label_auto_reconnects.hide() self.auto_reconnects = 0 # RED Session losts self.label_red_session_losts.hide() self.red_session_losts = 0 # override QMainWindow.closeEvent def closeEvent(self, event): self.exit_brickv() def exit_brickv(self, signal=None, frame=None): if self.current_device_info is not None: self.current_device_info.plugin.stop_plugin() self.current_device_info.plugin.destroy_plugin() self.update_current_host_info() config.set_host_infos(self.host_infos) self.do_disconnect() if signal != None and frame != None: print("Received SIGINT or SIGTERM, shutting down.") sys.exit() def host_index_changed(self, i): if i < 0: return self.host_index_changing = True self.spinbox_port.setValue(self.host_infos[i].port) self.checkbox_authentication.setChecked(self.host_infos[i].use_authentication) self.edit_secret.setText(self.host_infos[i].secret) self.checkbox_remember_secret.setChecked(self.host_infos[i].remember_secret) self.host_index_changing = False def port_changed(self, value): self.update_current_host_info() def authentication_state_changed(self, state): visible = state == Qt.Checked self.label_secret.setVisible(visible) self.edit_secret.setVisible(visible) self.checkbox_secret_show.setVisible(visible) self.checkbox_remember_secret.setVisible(visible) self.update_current_host_info() def secret_changed(self): self.update_current_host_info() def secret_show_state_changed(self, state): if state == Qt.Checked: self.edit_secret.setEchoMode(QLineEdit.Normal) else: self.edit_secret.setEchoMode(QLineEdit.Password) self.update_current_host_info() def remember_secret_state_changed(self, state): self.update_current_host_info() def tab_changed(self, i): if not hasattr(self.tab_widget.widget(i), '_info'): new_current_device_info = None else: new_current_device_info = self.tab_widget.widget(i)._info new_current_device_info.plugin.start_plugin() # stop the now deselected plugin, if there is one that's running if self.current_device_info is not None: self.current_device_info.plugin.stop_plugin() self.current_device_info = new_current_device_info def update_current_host_info(self): if self.host_index_changing: return i = self.combo_host.currentIndex() if i < 0: return #self.host_infos[i].host = self.combo_host.currentText() self.host_infos[i].port = self.spinbox_port.value() self.host_infos[i].use_authentication = self.checkbox_authentication.isChecked() self.host_infos[i].secret = self.edit_secret.text() self.host_infos[i].remember_secret = self.checkbox_remember_secret.isChecked() def remove_all_device_infos(self): for device_info in infos.get_device_infos(): self.remove_device_info(device_info.uid) def remove_device_info(self, uid): tab_id = self.tab_for_uid(uid) device_info = infos.get_info(uid) device_info.plugin.stop_plugin() device_info.plugin.destroy_plugin() if tab_id >= 0: self.tab_widget.removeTab(tab_id) # ensure that the widget gets correctly destroyed. otherwise QWidgets # tend to leak as Python is not able to collect their PyQt object tab_window = device_info.tab_window device_info.tab_window = None # If we reboot the RED Brick, the tab_window sometimes is # already None here if tab_window != None: tab_window.hide() tab_window.setParent(None) plugin = device_info.plugin device_info.plugin = None if plugin != None: plugin.hide() plugin.setParent(None) infos.remove_info(uid) def reset_view(self): self.tab_widget.setCurrentIndex(0) self.remove_all_device_infos() self.update_tree_view() def do_disconnect(self): self.auto_reconnects = 0 self.label_auto_reconnects.hide() self.red_session_losts = 0 self.label_red_session_losts.hide() self.reset_view() async_next_session() # force garbage collection, to ensure that all plugin related objects # got destroyed before disconnect is called. this is especially # important for the RED Brick plugin because its relies on releasing # the the RED Brick API objects in the __del__ method as a last resort # to avoid leaking object references. but this only works if garbage # collection is done before disconnect is called gc.collect() try: self.ipcon.disconnect() except: pass def do_authenticate(self, is_auto_reconnect): if not self.checkbox_authentication.isChecked(): return True try: secret = self.edit_secret.text().encode('ascii') except: self.do_disconnect() QMessageBox.critical(self, 'Connection', 'Authentication secret cannot contain non-ASCII characters.', QMessageBox.Ok) return False self.ipcon.set_auto_reconnect(False) # don't auto-reconnect on authentication error try: self.ipcon.authenticate(secret) except: self.do_disconnect() if is_auto_reconnect: extra = ' after auto-reconnect' else: extra = '' QMessageBox.critical(self, 'Connection', 'Could not authenticate' + extra + '. Check secret and ensure ' + 'authentication for Brick Daemon is enabled.', QMessageBox.Ok) return False self.ipcon.set_auto_reconnect(True) return True def flashing_clicked(self): if self.flashing_window is None: self.flashing_window = FlashingWindow(self) self.flashing_window.show() self.flashing_window.refresh_updates_clicked() def advanced_clicked(self): if self.advanced_window is None: self.advanced_window = AdvancedWindow(self) self.advanced_window.show() def connect_clicked(self): if self.ipcon.get_connection_state() == IPConnection.CONNECTION_STATE_DISCONNECTED: try: self.last_host = self.combo_host.currentText() self.button_connect.setDisabled(True) self.button_connect.setText("Connecting ...") self.button_connect.repaint() QApplication.processEvents() self.ipcon.connect(self.last_host, self.spinbox_port.value()) except: self.button_connect.setDisabled(False) self.button_connect.setText("Connect") QMessageBox.critical(self, 'Connection', 'Could not connect. Please check host, check ' + 'port and ensure that Brick Daemon is running.') else: self.do_disconnect() def item_double_clicked(self, index): uid_index = index.sibling(index.row(), 1) if uid_index.isValid(): uid_text = uid_index.data() self.show_plugin(uid_text) def create_tab_window(self, device_info, connected_uid, position): tab_window = TabWindow(self.tab_widget, device_info.name, self.untab) tab_window._info = device_info tab_window.set_callback_on_tab(lambda index: self.ipcon.get_connection_state() == IPConnection.CONNECTION_STATE_PENDING and \ self.tab_widget.setTabEnabled(index, False)) layout = QVBoxLayout(tab_window) info_bar = QHBoxLayout() # uid info_bar.addWidget(QLabel('UID:')) label = QLabel('{0}'.format(device_info.uid)) label.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard) info_bar.addWidget(label) info_bar.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # connected uid if connected_uid != '0': info_bar.addWidget(QLabel('Connected to:')) button = QToolButton() button.setText(connected_uid) button.clicked.connect(lambda: self.show_plugin(connected_uid)) info_bar.addWidget(button) info_bar.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # position info_bar.addWidget(QLabel('Position:')) info_bar.addWidget(QLabel('{0}'.format(position.upper()))) info_bar.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # firmware version label_version_name = QLabel('Version:') label_version = QLabel('...') if not device_info.plugin.has_custom_version(label_version_name, label_version): label_version_name.setText('FW Version:') label_version.setText(infos.get_version_string(device_info.plugin.firmware_version)) info_bar.addWidget(label_version_name) info_bar.addWidget(label_version) info_bar.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # timeouts info_bar.addWidget(QLabel('Timeouts:')) label_timeouts = QLabel('0') info_bar.addWidget(label_timeouts) layout.addLayout(info_bar) # actions actions = device_info.plugin.get_actions() if actions != None: if type(actions) == QAction: button = QPushButton(actions.text()) button.clicked.connect(actions.trigger) else: button = QToolButton() button.setText(actions[0]) button.setPopupMode(QToolButton.InstantPopup) button.setToolButtonStyle(Qt.ToolButtonTextOnly) button.setArrowType(Qt.DownArrow) button.setAutoRaise(True) menu = QMenu(actions[0]) button.setMenu(menu) for action in actions[1]: menu.addAction(action) info_bar.addSpacerItem(QSpacerItem(40, 20, QSizePolicy.Expanding)) info_bar.addWidget(button) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) device_info.plugin.label_timeouts = label_timeouts device_info.plugin.layout().setContentsMargins(0, 0, 0, 0) layout.addWidget(line) layout.addWidget(device_info.plugin) return tab_window def tab_move(self, event): # visualize rearranging of tabs (if allowed by tab_widget) if self.tab_widget.isMovable(): if event.type() == QEvent.MouseButtonPress and event.button() & Qt.LeftButton: QApplication.setOverrideCursor(QCursor(Qt.SizeHorCursor)) elif event.type() == QEvent.MouseButtonRelease and event.button() & Qt.LeftButton: QApplication.restoreOverrideCursor() return False def untab(self, tab_index): tab = self.tab_widget.widget(tab_index) tab.untab() tab._info.plugin.start_plugin() self.tab_widget.setCurrentIndex(0) def eventFilter(self, source, event): if source is self.tab_widget.tabBar(): return self.tab_move(event) return False def tab_for_uid(self, uid): for i in range(1, self.tab_widget.count()): try: if self.tab_widget.widget(i)._info.uid == uid: return i except: pass return -1 def show_plugin(self, uid): i = self.tab_for_uid(uid) tab_window = infos.get_info(uid).tab_window if i > 0 and self.tab_widget.isTabEnabled(i): self.tab_widget.setCurrentIndex(i) QApplication.setActiveWindow(tab_window) tab_window.show() tab_window.activateWindow() tab_window.raise_() def cb_enumerate(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type): if self.ipcon.get_connection_state() != IPConnection.CONNECTION_STATE_CONNECTED: # ignore enumerate callbacks that arrived after the connection got closed return if enumeration_type in [IPConnection.ENUMERATION_TYPE_AVAILABLE, IPConnection.ENUMERATION_TYPE_CONNECTED]: device_info = infos.get_info(uid) something_changed_ref = [False] if device_info == None: if device_identifier == BrickMaster.DEVICE_IDENTIFIER: device_info = infos.BrickMasterInfo() elif device_identifier == BrickRED.DEVICE_IDENTIFIER: device_info = infos.BrickREDInfo() elif position in ('a', 'b', 'c', 'd', 'A', 'B', 'C', 'D'): position = position.lower() device_info = infos.BrickletInfo() else: device_info = infos.BrickInfo() something_changed_ref[0] = True def set_device_info_value(name, value): if getattr(device_info, name) != value: setattr(device_info, name, value) something_changed_ref[0] = True set_device_info_value('uid', uid) set_device_info_value('connected_uid', connected_uid) set_device_info_value('position', position) set_device_info_value('hardware_version', hardware_version) set_device_info_value('firmware_version_installed', firmware_version) set_device_info_value('device_identifier', device_identifier) set_device_info_value('protocol_version', 2) set_device_info_value('enumeration_type', enumeration_type) if device_info.type == 'bricklet': for brick_info in infos.get_brick_infos(): if brick_info.uid == device_info.connected_uid: if brick_info.bricklets[position] != device_info: brick_info.bricklets[position] = device_info something_changed_ref[0] = True elif device_info.type == 'brick': for bricklet_info in infos.get_bricklet_infos(): if bricklet_info.connected_uid == device_info.uid: if device_info.bricklets[bricklet_info.position] != bricklet_info: device_info.bricklets[bricklet_info.position] = bricklet_info something_changed_ref[0] = True if device_info.plugin == None: plugin = self.plugin_manager.get_plugin(device_identifier, self.ipcon, uid, hardware_version, firmware_version) device_info.plugin = plugin device_info.name = plugin.name device_info.url_part = plugin.get_url_part() infos.add_info(device_info) device_info.tab_window = self.create_tab_window(device_info, connected_uid, position) device_info.tab_window.setWindowFlags(Qt.Widget) device_info.tab_window.tab() something_changed_ref[0] = True if something_changed_ref[0]: self.update_tree_view() elif enumeration_type == IPConnection.ENUMERATION_TYPE_DISCONNECTED: for device_info in infos.get_device_infos(): if device_info.uid == uid: self.tab_widget.setCurrentIndex(0) self.remove_device_info(device_info.uid) if device_info.type == 'brick': for port in device_info.bricklets: if device_info.bricklets[port] and device_info.bricklets[port].uid == uid: device_info.bricklets[port] = None self.update_tree_view() def hack_to_remove_red_brick_tab(self, red_brick_uid): for device_info in infos.get_device_infos(): if device_info.uid == red_brick_uid: self.tab_widget.setCurrentIndex(0) self.remove_device_info(device_info.uid) self.red_session_losts += 1 self.label_red_session_losts.setText('RED Brick Session Loss Count: {0}'.format(self.red_session_losts)) self.label_red_session_losts.show() break self.update_tree_view() def cb_connected(self, connect_reason): self.disconnect_times = [] self.update_ui_state() if connect_reason == IPConnection.CONNECT_REASON_REQUEST: self.auto_reconnects = 0 self.label_auto_reconnects.hide() self.red_session_losts = 0 self.label_red_session_losts.hide() self.ipcon.set_auto_reconnect(True) index = self.combo_host.findText(self.last_host) if index >= 0: self.combo_host.removeItem(index) host_info = self.host_infos[index] del self.host_infos[index] self.host_infos.insert(0, host_info) else: index = self.combo_host.currentIndex() host_info = self.host_infos[index].duplicate() host_info.host = self.last_host self.host_infos.insert(0, host_info) self.combo_host.insertItem(-1, self.last_host) self.combo_host.setCurrentIndex(0) while self.combo_host.count() > config.HOST_INFO_COUNT: self.combo_host.removeItem(self.combo_host.count() - 1) if not self.do_authenticate(False): return try: self.ipcon.enumerate() except: self.update_ui_state() elif connect_reason == IPConnection.CONNECT_REASON_AUTO_RECONNECT: self.auto_reconnects += 1 self.label_auto_reconnects.setText('Auto-Reconnect Count: {0}'.format(self.auto_reconnects)) self.label_auto_reconnects.show() if not self.do_authenticate(True): return try: self.ipcon.enumerate() except: self.update_ui_state() else: try: self.ipcon.enumerate() except: self.update_ui_state() def cb_disconnected(self, disconnect_reason): if disconnect_reason == IPConnection.DISCONNECT_REASON_REQUEST: self.auto_reconnects = 0 self.label_auto_reconnects.hide() self.red_session_losts = 0 self.label_red_session_losts.hide() if disconnect_reason == IPConnection.DISCONNECT_REASON_REQUEST or not self.ipcon.get_auto_reconnect(): self.update_ui_state() elif len(self.disconnect_times) >= 3 and self.disconnect_times[-3] < time.time() + 1: self.disconnect_times = [] self.ipcon.set_auto_reconnect(False) self.update_ui_state() self.reset_view() QMessageBox.critical(self, 'Connection', 'Stopped automatic reconnecting due to multiple connection errors in a row.') else: self.disconnect_times.append(time.time()) self.update_ui_state(IPConnection.CONNECTION_STATE_PENDING) def set_tree_view_defaults(self): self.tree_view_model.setHorizontalHeaderLabels(self.tree_view_model_labels) self.tree_view.expandAll() self.tree_view.setColumnWidth(0, 250) self.tree_view.setColumnWidth(1, 85) self.tree_view.setColumnWidth(2, 85) self.tree_view.setColumnWidth(3, 90) self.tree_view.setExpandsOnDoubleClick(False) self.tree_view.setSortingEnabled(True) self.tree_view.header().setSortIndicator(0, Qt.AscendingOrder) def update_ui_state(self, connection_state=None): # FIXME: need to call processEvents() otherwise get_connection_state() # might return the wrong value QApplication.processEvents() if connection_state is None: connection_state = self.ipcon.get_connection_state() self.button_connect.setDisabled(False) self.button_flashing.setDisabled(False) if connection_state == IPConnection.CONNECTION_STATE_DISCONNECTED: self.button_connect.setText('Connect') self.combo_host.setDisabled(False) self.spinbox_port.setDisabled(False) self.checkbox_authentication.setDisabled(False) self.edit_secret.setDisabled(False) self.button_advanced.setDisabled(True) elif connection_state == IPConnection.CONNECTION_STATE_CONNECTED: self.button_connect.setText("Disconnect") self.combo_host.setDisabled(True) self.spinbox_port.setDisabled(True) self.checkbox_authentication.setDisabled(True) self.edit_secret.setDisabled(True) self.update_advanced_window() # restart all pause plugins for info in infos.get_device_infos(): info.plugin.resume_plugin() elif connection_state == IPConnection.CONNECTION_STATE_PENDING: self.button_connect.setText('Abort Pending Automatic Reconnect') self.combo_host.setDisabled(True) self.spinbox_port.setDisabled(True) self.checkbox_authentication.setDisabled(True) self.edit_secret.setDisabled(True) self.button_advanced.setDisabled(True) self.button_flashing.setDisabled(True) # pause all running plugins for info in infos.get_device_infos(): info.plugin.pause_plugin() enable = connection_state == IPConnection.CONNECTION_STATE_CONNECTED for i in range(1, self.tab_widget.count()): self.tab_widget.setTabEnabled(i, enable) for device_info in infos.get_device_infos(): device_info.tab_window.setEnabled(enable) QApplication.processEvents() def update_tree_view(self): self.tree_view_model.clear() for info in infos.get_brick_infos(): parent = [QStandardItem(info.name), QStandardItem(info.uid), QStandardItem(info.position.upper()), QStandardItem('.'.join(map(str, info.firmware_version_installed)))] for item in parent: item.setFlags(item.flags() & ~Qt.ItemIsEditable) self.tree_view_model.appendRow(parent) for port in sorted(info.bricklets): if info.bricklets[port] and info.bricklets[port].protocol_version == 2: child = [QStandardItem(port.upper() + ': ' + info.bricklets[port].name), QStandardItem(info.bricklets[port].uid), QStandardItem(info.bricklets[port].position.upper()), QStandardItem('.'.join(map(str, info.bricklets[port].firmware_version_installed)))] for item in child: item.setFlags(item.flags() & ~Qt.ItemIsEditable) parent[0].appendRow(child) self.set_tree_view_defaults() self.update_advanced_window() self.delayed_refresh_updates_timer.start() def update_advanced_window(self): self.button_advanced.setEnabled(len(infos.get_brick_infos()) > 0) def delayed_refresh_updates(self): self.delayed_refresh_updates_timer.stop() if self.flashing_window is not None and self.flashing_window.isVisible(): self.flashing_window.refresh_updates_clicked()
class OWMPR(OWWidget): name = 'ModelMap Projection Rank' description = 'Ranking projections by estimating projection quality' icon = "icons/ModelMap.svg" inputs = [('Data', Table, 'set_data', Default)] outputs = [('Features', AttributeList)] want_main_area = False settingsHandler = DomainContextHandler() variable_changed = Signal() def __init__(self): super().__init__() self.data = None self.progress = None self.infoa = gui.widgetLabel(self.controlArea, "No data loaded.") self.projectionTable = QTableView() self.controlArea.layout().addWidget(self.projectionTable) self.projectionTable.setSelectionBehavior(QTableView.SelectRows) self.projectionTable.setSelectionMode(QTableView.SingleSelection) self.projectionTable.setSortingEnabled(True) self.projectionTableModel = QStandardItemModel(self) self.projectionTableModel.setHorizontalHeaderLabels( ["P-Index", "", ""]) self.projectionTable.setModel(self.projectionTableModel) self.projectionTable.setColumnWidth(0, 90) self.projectionTable.sortByColumn(0, Qt.DescendingOrder) self.projectionTable.selectionModel().selectionChanged.connect( self.on_selection_changed) gui.button(self.controlArea, self, "Rank Projections", callback=self.rank, default=True) self.resize(370, 600) def set_data(self, data): self.data = data self.infoa.setText("Data set: {}".format(data.name) if self. data else "No data loaded.") def rank(self): if self.progress: return disc = Orange.feature.discretization.EqualWidth(n=10) ndomain = Orange.data.Domain([ disc(self.data, attr) if type(attr) == Orange.data.variable.ContinuousVariable else attr for attr in self.data.domain.attributes ], self.data.domain.class_vars) t = self.data.from_table(ndomain, self.data) attrs = t.domain.attributes tables = {} l = 0 self.progress = gui.ProgressBar(self, len(attrs) * (len(attrs) - 1) / 2) for i in range(len(attrs)): for j in range(i): ct = np.array( contingency.get_contingency(t, attrs[j], attrs[i])) pindex, _, _ = p_index(ct) tables[i, j] = ct item = QStandardItem() item.setData(float(pindex), Qt.DisplayRole) self.projectionTableModel.setItem(l, 0, item) item = QStandardItem() item.setData(attrs[i].name, Qt.DisplayRole) self.projectionTableModel.setItem(l, 1, item) item = QStandardItem() item.setData(attrs[j].name, Qt.DisplayRole) self.projectionTableModel.setItem(l, 2, item) self.progress.advance() l += 1 self.progress.finish() self.progress = None def on_selection_changed(self, selected, deselected): """Called when the ranks view selection changes.""" a1 = selected.indexes()[1].data().replace('D_', '') a2 = selected.indexes()[2].data().replace('D_', '') d = self.data.domain self.send("Features", AttributeList([d[a1], d[a2]]))
class FormItem(QStandardItem): def __init__(self, name, fields, setup): super(FormItem, self).__init__(name) fields = [("Name", str, name)] + fields self.name = lambda: str(self.text()) self.names, _, _ = zip(*fields) self.dtypes = {} self.widgets = {} self.method_names = [] self.val_items = {} self.expr_items = {} self.group_items = {} self.setup = setup self.params_model = QStandardItemModel() self.params_model.itemChanged.connect(self.update_name) self.params_model.setHorizontalHeaderLabels(["Name", "Formula", "Evaluated"]) self.params_widget = QTableView() self.params_widget.setModel(self.params_model) self.params_widget.setItemDelegate(FormDelegate(self.params_model, self.widgets)) self.params_widget.verticalHeader().hide() for name, item_type, default in fields: self.add_field(name, item_type, default) self.params_widget.resizeRowsToContents() self.context_menu = ActionsMenu([]) self.params_model.itemChanged.connect(self.notify_group_item_children) def notify_group_item_children(self, item): method_name = method_style(self.params_model.item(item.row(), 0).text()) if method_name in self.group_items: current_item = self.dtypes[method_name](item.text()) previous_item = self.dtypes[method_name](self.group_items[method_name]) self.group_items[method_name] = current_item current_item.register_dependency(self) previous_item.unregister_dependency(self) def add_field(self, word_name, item_type, value): word_name = word_style(word_name) method_name = method_style(word_name) if item_type is int: self.dtypes[method_name] = int self.widgets[word_name] = lambda: IntVarLineEdit(self.setup) elif item_type is float: self.dtypes[method_name] = float self.widgets[word_name] = lambda: VarLineEdit(self.setup) elif isinstance(item_type, bool): self.dtypes[method_name] = bool self.widgets[word_name] = QCheckBox elif isinstance(item_type, (list, tuple)): self.dtypes[method_name] = str self.widgets[word_name] = \ lambda grp=item_type, **kwargs: MyComboBox(grp, **kwargs) elif isinstance(item_type, GroupItem): group = item_type value = group.items_list()[0].text() self.dtypes[method_name] = lambda i_name, grp=group: grp.item_from_name(i_name) self.widgets[word_name] = \ lambda grp=group, **kwargs: ItemsComboBox(grp, **kwargs) self.group_items[method_name] = value group.item_from_name(value).register_dependency(self) self.expr_items[method_name] = QStandardItem(str(value)) self.val_items[method_name] = ConstantItem("") self.params_model.appendRow([ConstantItem(word_name), self.expr_items[method_name], self.val_items[method_name]]) self.method_names.append(method_name) def set_name(self, name): self.setText(name) self.params_model.item(0, 1).setText(name) def update_name(self): self.setText(self.params_model.item(0, 1).text()) def eval_item(self, item): if item in self.method_names: dtype = self.dtypes[item] text = self.val_items[item].text() if text == "": text = self.expr_items[item].text() return dtype(text) else: raise AttributeError(item) def __getattr__(self, item): return self.eval_item(item)
class OWConfusionMatrix(widget.OWWidget): name = "Confusion Matrix" description = "Shows a confusion matrix." icon = "icons/ConfusionMatrix.svg" priority = 1001 inputs = [{ "name": "Evaluation Results", "type": Orange.evaluation.Results, "handler": "set_results" }] outputs = [{"name": "Selected Data", "type": Orange.data.Table}] quantities = [ "Number of instances", "Proportion of predicted", "Proportion of actual" ] selected_learner = settings.Setting([]) selected_quantity = settings.Setting(0) append_predictions = settings.Setting(True) append_probabilities = settings.Setting(False) autocommit = settings.Setting(True) def __init__(self, parent=None): super().__init__(parent) self.data = None self.results = None self.learners = [] box = gui.widgetBox(self.controlArea, "Learners") self.learners_box = gui.listBox(box, self, "selected_learner", "learners", callback=self._learner_changed) box = gui.widgetBox(self.controlArea, "Show") gui.comboBox(box, self, "selected_quantity", items=self.quantities, callback=self._update) box = gui.widgetBox(self.controlArea, "Select") gui.button(box, self, "Correct", callback=self.select_correct, autoDefault=False) gui.button(box, self, "Misclassified", callback=self.select_wrong, autoDefault=False) gui.button(box, self, "None", callback=self.select_none, autoDefault=False) self.outputbox = box = gui.widgetBox(self.controlArea, "Output") gui.checkBox(box, self, "append_predictions", "Predictions", callback=self._invalidate) gui.checkBox(box, self, "append_probabilities", "Probabilities", callback=self._invalidate) gui.auto_commit(self.controlArea, self, "autocommit", "Send Data", "Auto send is on") grid = QGridLayout() grid.setContentsMargins(0, 0, 0, 0) grid.addWidget(QLabel("Predicted"), 0, 1, Qt.AlignCenter) grid.addWidget(VerticalLabel("Actual Class"), 1, 0, Qt.AlignCenter) self.tablemodel = QStandardItemModel() self.tableview = QTableView(editTriggers=QTableView.NoEditTriggers) self.tableview.setModel(self.tablemodel) self.tableview.selectionModel().selectionChanged.connect( self._invalidate) grid.addWidget(self.tableview, 1, 1) self.mainArea.layout().addLayout(grid) def set_results(self, results): """Set the input results.""" self.clear() self.warning([0, 1]) data = None if results is not None: if results.data is not None: data = results.data if data is not None and \ not isinstance(data.domain.class_var, Orange.data.DiscreteVariable): data = None results = None self.warning( 0, "Confusion Matrix cannot be used for regression results.") self.results = results self.data = data if data is not None: class_values = data.domain.class_var.values elif results is not None: raise NotImplementedError if results is not None: nmodels, ntests = results.predicted.shape headers = class_values + [unicodedata.lookup("N-ARY SUMMATION")] # NOTE: The 'learner_names' is set in 'Test Learners' widget. if hasattr(results, "learner_names"): self.learners = results.learner_names else: self.learners = ["L %i" % (i + 1) for i in range(nmodels)] self.tablemodel.setVerticalHeaderLabels(headers) self.tablemodel.setHorizontalHeaderLabels(headers) self.tablemodel.setRowCount(len(class_values) + 1) self.tablemodel.setColumnCount(len(class_values) + 1) self.selected_learner = [0] self._update() def clear(self): self.results = None self.data = None self.tablemodel.clear() # Clear learners last. This action will invoke `_learner_changed` # method self.learners = [] def select_correct(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(n): index = self.tablemodel.index(i, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def select_wrong(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(n): for j in range(i + 1, n): index = self.tablemodel.index(i, j) selection.select(index, index) index = self.tablemodel.index(j, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect) def select_none(self): self.tableview.selectionModel().clear() def commit(self): if self.results is not None and self.data is not None \ and self.selected_learner: indices = self.tableview.selectedIndexes() indices = {(ind.row(), ind.column()) for ind in indices} actual = self.results.actual selected_learner = self.selected_learner[0] learner_name = self.learners[selected_learner] predicted = self.results.predicted[selected_learner] selected = [ i for i, t in enumerate(zip(actual, predicted)) if t in indices ] row_indices = self.results.row_indices[selected] extra = [] class_var = self.data.domain.class_var metas = self.data.domain.metas if self.append_predictions: predicted = numpy.array(predicted[selected], dtype=object) extra.append(predicted.reshape(-1, 1)) var = Orange.data.DiscreteVariable( "{}({})".format(class_var.name, learner_name), class_var.values) metas = metas + (var, ) if self.append_probabilities and \ self.results.probabilities is not None: probs = self.results.probabilities[selected_learner, selected] extra.append(numpy.array(probs, dtype=object)) pvars = [ Orange.data.ContinuousVariable("p({})".format(value)) for value in class_var.values ] metas = metas + tuple(pvars) X = self.data.X[row_indices] Y = self.data.Y[row_indices] M = self.data.metas[row_indices] row_ids = self.data.ids[row_indices] M = numpy.hstack((M, ) + tuple(extra)) domain = Orange.data.Domain(self.data.domain.attributes, self.data.domain.class_vars, metas) data = Orange.data.Table.from_numpy(domain, X, Y, M) data.ids = row_ids data.name = learner_name else: data = None self.send("Selected Data", data) def _invalidate(self): self.commit() def _learner_changed(self): # The selected learner has changed self._update() self._invalidate() def _update(self): # Update the displayed confusion matrix if self.results is not None and self.selected_learner: index = self.selected_learner[0] cmatrix = confusion_matrix(self.results, index) colsum = cmatrix.sum(axis=0) rowsum = cmatrix.sum(axis=1) total = rowsum.sum() if self.selected_quantity == 0: value = lambda i, j: int(cmatrix[i, j]) elif self.selected_quantity == 1: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / colsum[i]) if colsum[i] else "N/A") elif self.selected_quantity == 2: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / rowsum[i]) if colsum[i] else "N/A") else: assert False model = self.tablemodel for i, row in enumerate(cmatrix): for j, _ in enumerate(row): item = model.item(i, j) if item is None: item = QStandardItem() item.setData(value(i, j), Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) model.setItem(i, j, item) font = model.invisibleRootItem().font() bold_font = QFont(font) bold_font.setBold(True) def sum_item(value): item = QStandardItem() item.setData(value, Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) item.setFont(bold_font) return item N = len(colsum) for i in range(N): model.setItem(N, i, sum_item(int(colsum[i]))) model.setItem(i, N, sum_item(int(rowsum[i]))) model.setItem(N, N, sum_item(int(total)))
class InputDialog(GenericDialog): TBL_HEADER_LABEL=["Input Mesh", "Output group name"] def __init__(self, parent=None, name="InputDialog", modal=0): """ This initializes a dialog windows to define the input data of the plugin function. The input data consist in a list of meshes characterizes each by a name, a pointer to the smesh servant object, a type and a group name (see data model in the inputdata.py). """ GenericDialog.__init__(self, parent, name, modal) # Set up the user interface from Designer. self.__ui = Ui_InputFrame() # BE CAREFULL HERE, the ui form is NOT drawn in the global # dialog (already containing some generic widgets) but in the # center panel created in the GenericDialog as a void # container for the form. The InputFrame form is supposed # here to create only the widgets to be placed in the center # panel. Then, the setupUi function of this form draws itself # in the specified panel, i.e. the panel returned by # self.getPanel(). self.__ui.setupUi(self.getPanel()) self.setWindowTitle("Specification of input files") # The icon are supposed to be located in the plugin folder, # i.e. in the same folder than this python module file iconfolder=os.path.dirname(os.path.abspath(__file__)) icon = QIcon() icon.addFile(os.path.join(iconfolder,"select.png")) self.__ui.btnSmeshObject.setIcon(icon) icon = QIcon() icon.addFile(os.path.join(iconfolder,"addinput.png")) self.__ui.btnAddInput.setIcon(icon) icon = QIcon() icon.addFile(os.path.join(iconfolder,"deleteinput.png")) self.__ui.btnDeleteInput.setIcon(icon) # We specify here the items in the combo box (even if already # defined in the designer) so that we can be sure of the item # indexation. self.MESHTYPE_ICONS = {} meshTypeIndex = InputData.MESHTYPES.CONCRETE self.__ui.cmbMeshType.setItemText(meshTypeIndex, "Béton") icon = QIcon() icon.addFile(os.path.join(iconfolder,"concrete.png")) self.__ui.cmbMeshType.setItemIcon(meshTypeIndex, icon) self.MESHTYPE_ICONS[meshTypeIndex] = icon meshTypeIndex = InputData.MESHTYPES.STEELBAR self.__ui.cmbMeshType.setItemText(meshTypeIndex, "Acier") icon = QIcon() icon.addFile(os.path.join(iconfolder,"steelbar.png")) self.__ui.cmbMeshType.setItemIcon(meshTypeIndex, icon) self.MESHTYPE_ICONS[meshTypeIndex] = icon # The click on btnSmeshObject (signal clicked() emitted by the # button btnSmeshObject) is connected to the slot # onSelectSmeshObject, etc ... self.connect(self.__ui.btnSmeshObject, SIGNAL('clicked()'), self.onSelectSmeshObject ) self.connect(self.__ui.btnAddInput, SIGNAL('clicked()'), self.onAddInput ) self.connect(self.__ui.btnDeleteInput, SIGNAL('clicked()'), self.onDeleteInput ) # Set up the model of the Qt table list self.__inputModel = QStandardItemModel(0,2) self.__inputModel.setHorizontalHeaderLabels(InputDialog.TBL_HEADER_LABEL) self.__ui.tblListInput.setModel(self.__inputModel) self.__ui.tblListInput.verticalHeader().hide() self.__ui.tblListInput.horizontalHeader().setStretchLastSection(True) # Note that the type is not display explicitly in the Qt table # because it is specified using an icon on the text of the # name item. # Note that PADDER does not support group name longer than 8 # characters. We apply then this limit in the gui field. self.__ui.txtGroupName.setMaxLength(GROUPNAME_MAXLENGTH) self.clear() self.smeshStudyTool = SMeshStudyTools() def clear(self): """ This function clears the data gui area and associated values. """ self.__ui.txtSmeshObject.setText("") self.__ui.txtGroupName.setText("") self.__inputModel.clear() self.__inputModel.setHorizontalHeaderLabels(InputDialog.TBL_HEADER_LABEL) if not DEBUG_MODE: self.__ui.txtSmeshObject.setEnabled(False) self.__ui.btnAddInput.setEnabled(False) self.__selectedMesh = None self.__dictInputData = {} self.__nbConcreteMesh = 0 self.__nbSteelbarMesh = 0 def accept(self): """ This function is the slot connected to the button OK """ # The dialog is raised in a non modal mode to get # interactivity with the parents windows. Then we have to emit # a signal to warn the parent observer that the dialog has # been validated so that it can process the event GenericDialog.accept(self) if self.wasOk(): self.emit(SIGNAL('inputValidated()')) def onSelectSmeshObject(self): ''' This function is the slot connected on the mesh selection button. It memorizes the selected mesh and put its name in the text field of the dialog box. ''' mySObject, myEntry = guihelper.getSObjectSelected() if CORBA.is_nil(mySObject): self.__ui.txtSmeshObject.setText("You must choose a mesh") self.__ui.txtGroupName.setText("") self.__ui.txtSmeshObject.setEnabled(False) self.__ui.btnAddInput.setEnabled(False) self.__selectedMesh = None return self.smeshStudyTool.updateStudy(studyedit.getActiveStudyId()) self.__selectedMesh = self.smeshStudyTool.getMeshObjectFromSObject(mySObject) if CORBA.is_nil(self.__selectedMesh): self.__ui.txtSmeshObject.setText("The selected object is not a mesh") self.__ui.txtGroupName.setText("") self.__ui.txtSmeshObject.setEnabled(False) self.__ui.btnAddInput.setEnabled(False) self.__selectedMesh = None return myName = mySObject.GetName() self.__ui.txtSmeshObject.setText(myName) self.__ui.txtSmeshObject.setEnabled(True) self.__ui.btnAddInput.setEnabled(True) # We can suggest a default group name from the mesh name self.__ui.txtGroupName.setText(myName) def onAddInput(self): """ This function is the slot connected to the Add button. It creates a new entry in the list of input data, or updates this entry if it already exists. """ meshName = str(self.__ui.txtSmeshObject.text().trimmed()) meshObject = self.__selectedMesh meshType = self.__ui.cmbMeshType.currentIndex() groupName = str(self.__ui.txtGroupName.text().trimmed()) self.__addInputInGui(meshName, meshObject, meshType, groupName) self.__addInputInMap(meshName, meshObject, meshType, groupName) def __addInputInGui(self, meshName, meshObject, meshType, groupName): """ This function adds an entry with the specified data int the GUI table (for data visualization purpose). """ # The mesh name is used as the key index in the model. We have # to check first if this item already exists in the list. tblItems = self.__inputModel.findItems(meshName) row = self.__inputModel.rowCount() if not tblItems: tblItems = [] tblItems.append(QStandardItem()) # input mesh name tblItems.append(QStandardItem()) # output group name else: row = tblItems[0].index().row() tblItems.append(self.__inputModel.item(row,1)) tblItems[0].setText(meshName) tblItems[0].setIcon(self.MESHTYPE_ICONS[meshType]) tblItems[1].setText(groupName) self.__inputModel.setItem(row,0,tblItems[0]) self.__inputModel.setItem(row,1,tblItems[1]) self.__ui.tblListInput.setCurrentIndex(tblItems[0].index()) def __addInputInMap(self, meshName, meshObject, meshType, groupName): """ This function adds an entry with the specified data in the internal map (for data management purpose). """ # if the entry already exists, we remove it to replace by a # new one if self.__dictInputData.has_key(meshName): self.__delInputFromMap(meshName) inputData = InputData() inputData.meshName = meshName inputData.meshObject = meshObject inputData.meshType = meshType inputData.groupName = groupName # The key of the map is the mesh name self.__dictInputData[meshName] = inputData if inputData.meshType == InputData.MESHTYPES.CONCRETE: self.__nbConcreteMesh += 1 else: self.__nbSteelbarMesh += 1 print inputData print "meshType = ",inputData.meshType print "nb concrete mesh ",self.__nbConcreteMesh print "nb steelbar mesh ",self.__nbSteelbarMesh def onDeleteInput(self): """ This function is the slot connected to the Delete button. It remove from the data list the entry selected in the Qt table. """ selectedIdx = self.__ui.tblListInput.selectedIndexes() if selectedIdx: row = selectedIdx[0].row() tblItem = self.__inputModel.item(row,0) meshName = str(tblItem.text()) self.__inputModel.takeRow(row) # Don't forget to remove this entry from the mesh object # internal dictionnary self.__delInputFromMap(meshName) def __delInputFromMap(self, meshName): """ This function removes the specified entry from the internal map (for data management purpose) """ inputData = self.__dictInputData.pop(meshName) if inputData.meshType == InputData.MESHTYPES.CONCRETE: self.__nbConcreteMesh -= 1 else: self.__nbSteelbarMesh -= 1 print inputData print "nb concrete mesh ",self.__nbConcreteMesh print "nb steelbar mesh ",self.__nbSteelbarMesh def setData(self, listInputData=[]): """ This function fills the dialog widgets with values provided by the specified data list. """ self.clear() for inputData in listInputData: meshName = inputData.meshName meshObject = inputData.meshObject meshType = inputData.meshType groupName = inputData.groupName self.__addInputInGui(meshName, meshObject, meshType, groupName) self.__addInputInMap(meshName, meshObject, meshType, groupName) if not DEBUG_MODE: self.onSelectSmeshObject() def getData(self): """ This function returns a list of InputData that corresponds to the data in the dialog widgets of the current dialog. """ # Note that the values() function returns a copy of the list # of values. return self.__dictInputData.values() def checkData(self): """ This function checks if the data are valid, from the dialog window point of view. """ if self.__nbConcreteMesh == 0 and self.__nbSteelbarMesh == 0: self.checkDataMessage = "You must define at least one mesh (CONCRETE or STEELBAR)" return False if self.__nbConcreteMesh > 1: self.checkDataMessage = "You define multiple CONCRETE meshes." self.checkDataMessage += "You should verify first that your version of PADDER support this configuration." # just warn the user, but don't block QMessageBox.information(self, "Info", self.checkDataMessage) return True return True
class LogDialog(QDialogWithDpi): """LogDialog for the Freeseer project. It is the dialog window for the log. There is an instance for every FreeseerApp. It has a LogHandler which calls LogDialog's message() method when a new log message is received. The call to message() causes a call to add_entry() which adds the information to a new row in the table. """ def __init__(self, parent=None): super(LogDialog, self).__init__(parent) self.resize(800, 500) self.app = QApplication.instance() icon = QIcon() icon.addPixmap(QPixmap(_fromUtf8(":/freeseer/logo.png")), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) layout = QVBoxLayout() self.setLayout(layout) self.level = 0 self.handler = LogHandler() self.table_model = QStandardItemModel(0, 5) header_names = ["Date", "Level", "Module", "Message", "LevelNo"] date_column = header_names.index("Date") level_column = header_names.index("Level") module_column = header_names.index("Module") self.level_num_column = header_names.index("LevelNo") self.table_model.setHorizontalHeaderLabels(header_names) self.table_view = QTableView() self.table_view.setModel(self.table_model) self.table_view.horizontalHeader().setStretchLastSection(True) self.table_view.setColumnWidth(date_column, self.set_width_with_dpi(125)) self.table_view.setColumnWidth(level_column, self.set_width_with_dpi(60)) self.table_view.setColumnWidth(module_column, self.set_width_with_dpi(250)) self.table_view.setColumnHidden(self.level_num_column, True) self.table_view.setShowGrid(False) self.table_view.horizontalHeader().setClickable(False) self.table_view.verticalHeader().hide() self.table_view.setStyleSheet("""Qtable_view::item { border-bottom: 1px solid lightgrey; selection-background-color: white; selection-color: black; }""") top_panel = QHBoxLayout() self.log_levels = ["Debug", "Info", "Warning", "Error"] self.level_colors = ["#3E4C85", "#269629", "#B0AB21", "#B32020"] self.levels_label = QLabel("Filter Level: ") self.levels_label.setStyleSheet("QLabel { font-weight: bold }") self.current_level_label = QLabel(self.log_levels[0]) self.current_level_label.setStyleSheet("QLabel {{ color: {} }}".format( self.level_colors[0])) self.clear_button = QPushButton("Clear Log") self.levels_slider = QSlider(Qt.Horizontal) self.levels_slider.setStyleSheet(""" QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #FFFFFF, stop:1 #E3E3E3); border: 1px solid #707070; width: 10px; margin-top: -4px; margin-bottom: -4px; border-radius: 4px; } QSlider::handle:horizontal:hover { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #DEDEDE, stop:1 #C9C9C9); border: 1px solid #4F4F4F; border-radius: 4px; } QSlider::sub-page:horizontal { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #BFBFBF, stop: 1 #9E9E9E); background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, stop: 0 #9E9E9E, stop: 1 #858585); border: 1px solid #777; height: 10px; border-radius: 4px; } QSlider::add-page:horizontal { background: #fff; border: 1px solid #707070; height: 10px; border-radius: 4px; }""") self.levels_slider.setRange(0, len(self.log_levels) - 1) self.levels_slider.setTickPosition(QSlider.TicksBelow) self.levels_slider.setTickInterval(1) top_panel.addSpacerItem(self.qspacer_item_with_dpi(10, 0)) top_panel.addWidget(self.levels_label, 3) top_panel.addWidget(self.current_level_label, 2) top_panel.addWidget(self.levels_slider, 8) top_panel.addSpacerItem(self.qspacer_item_with_dpi(25, 0)) top_panel.addWidget(self.clear_button, 10) layout.addLayout(top_panel) layout.addWidget(self.table_view) self.connect(self.clear_button, SIGNAL('clicked()'), functools.partial(self.table_model.setRowCount, 0)) self.connect(self.levels_slider, SIGNAL('valueChanged(int)'), self.slider_set_level) self.setWindowTitle("Log") self.handler.add_listener(self) def __del__(self): self.handler.remove_listener(self) def retranslate(self): self.setWindowTitle(self.app.translate("LogDialog", "Log")) self.clear_button.setText(self.app.translate("LogDialog", "Clear Log")) self.levels_label.setText("{}: ".format( self.app.translate("LogDialog", "Filter Level"))) def message(self, message): """Passes the log fields to add_entry() It is called by LogHandler when a log message is received""" self.add_entry(message["time"], message["level"], message["full_module_name"], message["message"], str(message["levelno"])) def add_entry(self, date, level, module, message, levelno): """Adds the given fields to a new row in the log table It is called by message() when a log message is received""" items = [ QStandardItem(date), QStandardItem(level), QStandardItem(module), QStandardItem(message), QStandardItem(levelno) ] for item in items: item.setEditable(False) self.table_model.appendRow(items) def slider_set_level(self, level): self.current_level_label.setText(self.log_levels[level]) self.current_level_label.setStyleSheet("QLabel {{ color: {} }}".format( self.level_colors[level])) self.set_level(level + 1) def set_level(self, level): """Sets the current level of the LogDialog. Level is based on the selection made in the levels_combo_box. It hides all messages with a lower level.""" self.level = level * 10 for i in range(self.table_model.rowCount()): if int(str(self.table_model.item( i, self.level_num_column).text())) < self.level: self.table_view.setRowHidden(i, True) else: self.table_view.setRowHidden(i, False)
def get_gds_model(progress=lambda val: None): """ Initialize and return a GDS datasets model. :param progress: A progress callback. :rval tuple: A tuple of (QStandardItemModel, geo.GDSInfo, [geo.GDS]) .. note:: The returned QStandardItemModel's thread affinity is set to the GUI thread. """ progress(1) info = geo.GDSInfo() search_keys = ["dataset_id", "title", "platform_organism", "description"] cache_dir = serverfiles.localpath(geo.DOMAIN) gds_link = "http://www.ncbi.nlm.nih.gov/sites/GDSbrowser?acc={0}" pm_link = "http://www.ncbi.nlm.nih.gov/pubmed/{0}" gds_list = [] def is_cached(gds): return os.path.exists( os.path.join(cache_dir, gds["dataset_id"]) + ".soft.gz") def item(displayvalue, item_values={}): item = QStandardItem() item.setData(displayvalue, Qt.DisplayRole) for role, value in item_values.items(): item.setData(value, role) return item def gds_to_row(gds): #: Text for easier full search. search_text = " | ".join( [gds.get(key, "").lower() for key in search_keys]) row = [ item(" " if is_cached(gds) else "", {TextFilterRole: search_text}), item(gds["dataset_id"], {LinkRole: gds_link.format(gds["dataset_id"])}), item(gds["title"]), item(gds["platform_organism"]), item(len(gds["samples"])), item(gds["feature_count"]), item(gds["gene_count"]), item(len(gds["subsets"])), item( gds.get("pubmed_id", ""), { LinkRole: pm_link.format(gds["pubmed_id"]) if gds.get("pubmed_id") else None }) ] return row model = QStandardItemModel() model.setHorizontalHeaderLabels([ "", "ID", "Title", "Organism", "Samples", "Features", "Genes", "Subsets", "PubMedID" ]) progress(20) for gds in info.values(): model.appendRow(gds_to_row(gds)) gds_list.append(gds) progress(50) if QThread.currentThread() is not QCoreApplication.instance().thread(): model.moveToThread(QCoreApplication.instance().thread()) return model, info, gds_list
class ProgramInfoFiles(QWidget, Ui_ProgramInfoFiles): def __init__(self, context, update_main_ui_state, set_widget_enabled, is_alive, show_upload_files_wizard, show_download_wizard): QWidget.__init__(self) self.setupUi(self) self.session = context.session self.script_manager = context.script_manager self.program = context.program self.update_main_ui_state = update_main_ui_state self.set_widget_enabled = set_widget_enabled self.is_alive = is_alive self.show_download_wizard = show_download_wizard self.bin_directory = posixpath.join(self.program.root_directory, 'bin') self.refresh_in_progress = False self.any_refresh_in_progress = False # set from ProgramInfoMain.update_ui_state self.available_files = [] self.available_directories = [] self.folder_icon = QIcon(load_pixmap('folder-icon.png')) self.file_icon = QIcon(load_pixmap('file-icon.png')) self.tree_files_model = QStandardItemModel(self) self.tree_files_model_header = ['Name', 'Size', 'Last Modified'] self.tree_files_proxy_model = FilesProxyModel(self) self.last_download_directory = get_home_path() self.tree_files_model.setHorizontalHeaderLabels(self.tree_files_model_header) self.tree_files_proxy_model.setSourceModel(self.tree_files_model) self.tree_files.setModel(self.tree_files_model) self.tree_files.setModel(self.tree_files_proxy_model) self.tree_files.setColumnWidth(0, 210) self.tree_files.setColumnWidth(1, 85) self.tree_files.selectionModel().selectionChanged.connect(self.update_ui_state) self.tree_files.activated.connect(self.rename_activated_file) self.button_upload_files.clicked.connect(show_upload_files_wizard) self.button_download_files.clicked.connect(self.download_selected_files) self.button_rename_file.clicked.connect(self.rename_selected_file) self.button_change_file_permissions.clicked.connect(self.change_permissions_of_selected_file) self.button_delete_files.clicked.connect(self.delete_selected_files) self.label_error.setVisible(False) def update_ui_state(self): selection_count = len(self.tree_files.selectionModel().selectedRows()) self.set_widget_enabled(self.button_upload_files, not self.any_refresh_in_progress) self.set_widget_enabled(self.button_download_files, not self.any_refresh_in_progress and selection_count > 0) self.set_widget_enabled(self.button_rename_file, not self.any_refresh_in_progress and selection_count == 1) self.set_widget_enabled(self.button_change_file_permissions, not self.any_refresh_in_progress and selection_count == 1) self.set_widget_enabled(self.button_delete_files, not self.any_refresh_in_progress and selection_count > 0) def close_all_dialogs(self): pass def refresh_files_done(self): self.refresh_in_progress = False self.update_main_ui_state() def refresh_files(self): def cb_walk(result): okay, message = check_script_result(result, decode_stderr=True) if not okay: self.label_error.setText('<b>Error:</b> ' + Qt.escape(message)) self.label_error.setVisible(True) self.refresh_files_done() return self.label_error.setVisible(False) def expand_async(data): try: walk = json.loads(zlib.decompress(buffer(data)).decode('utf-8')) except: walk = None if walk == None or not isinstance(walk, dict): available_files = [] available_directories = [] walk = None else: available_files, available_directories = expand_walk_to_lists(walk) return walk, available_files, available_directories def cb_expand_success(result): walk, available_files, available_directories = result self.available_files = available_files self.available_directories = available_directories if walk != None: expand_walk_to_model(walk, self.tree_files_model, self.folder_icon, self.file_icon) else: self.label_error.setText('<b>Error:</b> Received invalid data') self.label_error.setVisible(True) self.tree_files.header().setSortIndicator(0, Qt.AscendingOrder) self.refresh_files_done() def cb_expand_error(): self.label_error.setText('<b>Error:</b> Internal async error') self.label_error.setVisible(True) self.refresh_files_done() async_call(expand_async, result.stdout, cb_expand_success, cb_expand_error) self.refresh_in_progress = True self.update_main_ui_state() width1 = self.tree_files.columnWidth(0) width2 = self.tree_files.columnWidth(1) self.tree_files_model.clear() self.tree_files_model.setHorizontalHeaderLabels(self.tree_files_model_header) self.tree_files.setColumnWidth(0, width1) self.tree_files.setColumnWidth(1, width2) self.script_manager.execute_script('walk', cb_walk, [self.bin_directory], max_length=1024*1024, decode_output_as_utf8=False) def get_directly_selected_name_items(self): selected_indexes = self.tree_files.selectedIndexes() selected_name_items = [] for selected_index in selected_indexes: if selected_index.column() == 0: mapped_index = self.tree_files_proxy_model.mapToSource(selected_index) selected_name_items.append(self.tree_files_model.itemFromIndex(mapped_index)) return selected_name_items def download_selected_files(self): selected_name_items = self.get_directly_selected_name_items() if len(selected_name_items) == 0: return downloads = [] def expand(name_item): item_type = name_item.data(USER_ROLE_ITEM_TYPE) if item_type == ITEM_TYPE_DIRECTORY: for i in range(name_item.rowCount()): expand(name_item.child(i, 0)) elif item_type == ITEM_TYPE_FILE: filename = get_full_item_path(name_item) downloads.append(Download(filename, QDir.toNativeSeparators(filename))) for selected_name_item in selected_name_items: expand(selected_name_item) if len(downloads) == 0: return download_directory = get_existing_directory(get_main_window(), 'Download Files', self.last_download_directory) if len(download_directory) == 0: return self.last_download_directory = download_directory self.show_download_wizard('files', download_directory, downloads) def rename_activated_file(self, index): if index.column() == 0 and not self.any_refresh_in_progress: mapped_index = self.tree_files_proxy_model.mapToSource(index) name_item = self.tree_files_model.itemFromIndex(mapped_index) item_type = name_item.data(USER_ROLE_ITEM_TYPE) # only rename files via activation, because directories are expanded if item_type == ITEM_TYPE_FILE: self.rename_item(name_item) def rename_selected_file(self): selection_count = len(self.tree_files.selectionModel().selectedRows()) if selection_count != 1: return selected_name_items = self.get_directly_selected_name_items() if len(selected_name_items) != 1: return self.rename_item(selected_name_items[0]) def rename_item(self, name_item): item_type = name_item.data(USER_ROLE_ITEM_TYPE) if item_type == ITEM_TYPE_FILE: title = 'Rename File' type_name = 'file' else: title = 'Rename Directory' type_name = 'directory' old_name = name_item.text() # get new name dialog = ExpandingInputDialog(get_main_window()) dialog.setModal(True) dialog.setWindowTitle(title) dialog.setLabelText('Enter new {0} name:'.format(type_name)) dialog.setInputMode(QInputDialog.TextInput) dialog.setTextValue(old_name) dialog.setOkButtonText('Rename') if dialog.exec_() != QDialog.Accepted: return new_name = dialog.textValue() if new_name == old_name: return # check that new name is valid if len(new_name) == 0 or new_name == '.' or new_name == '..' or '/' in new_name: QMessageBox.critical(get_main_window(), title + ' Error', 'A {0} name cannot be empty, cannot be one dot [.], cannot be two dots [..] and cannot contain a forward slash [/].' .format(type_name)) return # check that new name is not already in use name_item_parent = name_item.parent() if name_item_parent == None: name_item_parent = self.tree_files_model.invisibleRootItem() for i in range(name_item_parent.rowCount()): if new_name == name_item_parent.child(i).text(): QMessageBox.critical(get_main_window(), title + ' Error', 'The new {0} name is already in use.'.format(type_name)) return absolute_old_name = posixpath.join(self.bin_directory, get_full_item_path(name_item)) absolute_new_name = posixpath.join(posixpath.split(absolute_old_name)[0], new_name) def cb_rename(result): if not report_script_result(result, title + ' Error', u'Could not rename {0}'.format(type_name)): return name_item.setText(new_name) if self.tree_files.header().sortIndicatorSection() == 0: self.tree_files.header().setSortIndicator(0, self.tree_files.header().sortIndicatorOrder()) self.script_manager.execute_script('rename', cb_rename, [absolute_old_name, absolute_new_name]) def change_permissions_of_selected_file(self): selection_count = len(self.tree_files.selectionModel().selectedRows()) if selection_count != 1: return selected_name_items = self.get_directly_selected_name_items() if len(selected_name_items) != 1: return name_item = selected_name_items[0] item_type = name_item.data(USER_ROLE_ITEM_TYPE) old_permissions = name_item.data(USER_ROLE_PERMISSIONS) if item_type == ITEM_TYPE_FILE: title = 'Change File Permissions' type_name = 'file' else: title = 'Change Directory Permissions' type_name = 'directory' dialog = ProgramInfoFilesPermissions(get_main_window(), title, old_permissions) if dialog.exec_() != QDialog.Accepted: return new_permissions = dialog.get_permissions() if new_permissions == (old_permissions & 0o777): return absolute_name = posixpath.join(self.bin_directory, get_full_item_path(name_item)) def cb_change_permissions(result): if not report_script_result(result, title + ' Error', u'Could change {0} permissions'.format(type_name)): return name_item.setData(new_permissions, USER_ROLE_PERMISSIONS) self.script_manager.execute_script('change_permissions', cb_change_permissions, [absolute_name, str(new_permissions)]) def delete_selected_files(self): button = QMessageBox.question(get_main_window(), 'Delete Files', 'Irreversibly deleting selected files and directories.', QMessageBox.Ok, QMessageBox.Cancel) if not self.is_alive() or button != QMessageBox.Ok: return selected_name_items = set(self.get_directly_selected_name_items()) if len(selected_name_items) == 0: return script_instance_ref = [None] def progress_canceled(): script_instance = script_instance_ref[0] if script_instance == None: return self.script_manager.abort_script(script_instance) progress = ExpandingProgressDialog(self) progress.set_progress_text_visible(False) progress.setModal(True) progress.setWindowTitle('Delete Files') progress.setLabelText('Collecting files and directories to delete') progress.setRange(0, 0) progress.canceled.connect(progress_canceled) progress.show() files_to_delete = [] dirs_to_delete = [] all_done = False while not all_done: all_done = True for selected_name_item in list(selected_name_items): item_done = False parent = selected_name_item.parent() while not item_done and parent != None: if parent in selected_name_items: selected_name_items.remove(selected_name_item) item_done = True else: parent = parent.parent() if item_done: all_done = False break for selected_name_item in selected_name_items: path = get_full_item_path(selected_name_item) item_type = selected_name_item.data(USER_ROLE_ITEM_TYPE) if item_type == ITEM_TYPE_DIRECTORY: dirs_to_delete.append(posixpath.join(self.bin_directory, path)) else: files_to_delete.append(posixpath.join(self.bin_directory, path)) message = 'Deleting ' if len(files_to_delete) == 1: message += '1 file ' elif len(files_to_delete) > 1: message += '{0} files '.format(len(files_to_delete)) if len(dirs_to_delete) == 1: if len(files_to_delete) > 0: message += 'and ' message += '1 directory' elif len(dirs_to_delete) > 1: if len(files_to_delete) > 0: message += 'and ' message += '{0} directories'.format(len(dirs_to_delete)) progress.setLabelText(message) def cb_delete(result): script_instance = script_instance_ref[0] if script_instance != None: aborted = script_instance.abort else: aborted = False script_instance_ref[0] = None progress.cancel() self.refresh_files() if aborted: QMessageBox.information(get_main_window(), 'Delete Files', u'Delete operation was aborted.') return report_script_result(result, 'Delete Files Error', 'Could not delete selected files/directories:') script_instance_ref[0] = self.script_manager.execute_script('delete', cb_delete, [json.dumps(files_to_delete), json.dumps(dirs_to_delete)], execute_as_user=True)
def randomize_groups(self): #participant_list_form = Participant_list() #participant_list_form.show() #participant_list_form.ui3.label.setText("sdsdfdsf") #ex2.ui.label_6.setText("test") participant_list_form = ex3 # participant_list_form = Participant_list() # participant_list_form.show() tv = participant_list_form.ui3.tableView # set the table model tablemdata = 0 #tabledata.append([2, 2, 2, 2, 2]) # tabledata.remove([0]) # tabledata.append([1, 1, 1, 1, 1]) # table.model().layoutChanged.emit() tablemodel = MyTableModel(tabledata, header, self) rowcount = int(tablemodel.rowCount(None)) tvmodel = tv.model() nums = [x+1 for x in range(rowcount)] random.shuffle(nums) print nums #iterating list #print i+1 % groups_to_create # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # init widgets view = ex8.ui8.treeView view.setSelectionBehavior(QAbstractItemView.SelectRows) model = QStandardItemModel() model.setHorizontalHeaderLabels(header) view.setModel(model) view.setUniformRowHeights(True) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # populate data groups_to_create = int(self.ui.lineEdit.text()) participants_in_group = int(self.ui.lineEdit_2.text()) divider = 0 group = 1 parent1 = QStandardItem('Grupa {}'.format(group)) for i, val in enumerate(nums): if divider == participants_in_group: divider = 0 group = group + 1 parent1 = QStandardItem('Grupa {}'.format(group)) divider = divider + 1 if val != 0: print "Grupa " + str(group) + " Osoby: " + str(val) self.tableindex_id = tablemodel.index (val-1,1) self.tableindex_surname = tablemodel.index (val-1,2) child1 = QStandardItem(str(val)+' '+" ") child2 = QStandardItem(str(tablemodel.data(self.tableindex_id, Qt.DisplayRole))) child3 = QStandardItem(str(tablemodel.data(self.tableindex_surname, Qt.DisplayRole))) parent1.appendRow([child1, child2, child3]) model.appendRow(parent1) # span container columns view.setFirstColumnSpanned(i, view.rootIndex(), True) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # expand third container index = model.indexFromItem(parent1) view.expand(index) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # select last row selmod = view.selectionModel() index2 = model.indexFromItem(child3) selmod.select(index2, QItemSelectionModel.Select | QItemSelectionModel.Rows) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ print i+1 if i+1 > 3: print i / groups_to_create else: print i / groups_to_create #index = tablemodel.index(row, 1) print nums
class VizRank(OWWidget): name = "Rank projections (Scatter Plot)" want_control_area = False def __init__(self, parent_widget): super().__init__() self.parent_widget = parent_widget self.running = False self.progress = None self.k = 10 self.projectionTable = QTableView() self.mainArea.layout().addWidget(self.projectionTable) self.projectionTable.setSelectionBehavior(QTableView.SelectRows) self.projectionTable.setSelectionMode(QTableView.SingleSelection) self.projectionTable.setSortingEnabled(True) self.projectionTableModel = QStandardItemModel(self) self.projectionTable.setModel(self.projectionTableModel) self.projectionTable.selectionModel().selectionChanged.connect( self.on_selection_changed) self.button = gui.button(self.mainArea, self, "Start evaluation", callback=self.toggle, default=True) self.resize(380, 512) self._initialize() def _initialize(self): self.running = False self.projectionTableModel.clear() self.projectionTableModel.setHorizontalHeaderLabels( ["Score", "Feature 1", "Feature 2"]) self.projectionTable.setColumnWidth(0, 60) self.projectionTable.setColumnWidth(1, 120) self.projectionTable.setColumnWidth(2, 120) self.button.setText("Start evaluation") self.button.setEnabled(False) self.pause = False self.data = None self.attrs = [] self.scores = [] self.i, self.j = 0, 0 if self.progress: self.progress.finish() self.progress = None self.information(0) if self.parent_widget.data: if not self.parent_widget.data.domain.class_var: self.information( 0, "Data with a class variable is required.") return if len(self.parent_widget.data.domain.attributes) < 2: self.information(0, 'At least 2 unique features are needed.') return if len(self.parent_widget.data) < 2: self.information(0, 'At least 2 instances are needed.') return self.button.setEnabled(True) def on_selection_changed(self, selected, deselected): """Called when the ranks view selection changes.""" a1 = selected.indexes()[1].data() a2 = selected.indexes()[2].data() self.parent_widget.update_attr(attributes=(a1, a2)) def toggle(self): self.running ^= 1 if self.running: self.button.setText("Pause") self.run() else: self.button.setText("Continue") self.button.setEnabled(False) def run(self): graph = self.parent_widget.graph y_full = self.parent_widget.data.Y if not self.attrs: self.attrs = self.score_heuristic() if not self.progress: self.progress = gui.ProgressBar( self, len(self.attrs) * (len(self.attrs) - 1) / 2) for i in range(self.i, len(self.attrs)): ind1 = graph.attribute_name_index[self.attrs[i]] for j in range(self.j, i): if not self.running: self.i, self.j = i, j if not self.projectionTable.selectedIndexes(): self.projectionTable.selectRow(0) self.button.setEnabled(True) return ind2 = graph.attribute_name_index[self.attrs[j]] X = graph.scaled_data[[ind1, ind2], :] valid = graph.get_valid_list([ind1, ind2]) X = X[:, valid].T if X.shape[0] < self.k: self.progress.advance() continue y = y_full[valid] n_neighbors = min(self.k, len(X) - 1) knn = NearestNeighbors(n_neighbors=n_neighbors).fit(X) ind = knn.kneighbors(return_distance=False) if self.parent_widget.data.domain.has_discrete_class: score = np.sum(y[ind] == y.reshape(-1, 1)) / ( len(y_full) * n_neighbors) else: score = r2_score(y, np.mean( y[ind], axis=1)) * (len(y) / len(y_full)) pos = bisect_left(self.scores, score) self.projectionTableModel.insertRow( len(self.scores) - pos, [ QStandardItem("{:.4f}".format(score)), QStandardItem(self.attrs[j]), QStandardItem(self.attrs[i]) ]) self.scores.insert(pos, score) self.progress.advance() self.j = 0 self.progress.finish() if not self.projectionTable.selectedIndexes(): self.projectionTable.selectRow(0) self.button.setText("Finished") self.button.setEnabled(False) def score_heuristic(self): X = self.parent_widget.graph.scaled_data.T Y = self.parent_widget.data.Y dom = Domain( [ContinuousVariable(str(i)) for i in range(X.shape[1])], self.parent_widget.data.domain.class_vars) data = Table(dom, X, Y) relief = ReliefF if isinstance(dom.class_var, DiscreteVariable) else RReliefF weights = relief(n_iterations=100, k_nearest=self.k)(data) attrs = sorted(zip( weights, (x.name for x in self.parent_widget.data.domain.attributes)), reverse=True) return [a for _, a in attrs]
class SetupDialog(QDialog, Ui_SetupDialog): """ Function and Event handling class for the Ui_SetupDialog. """ def __init__(self, parent): QDialog.__init__(self, parent) self._gui_logger = GUILogger("GUILogger", logging.INFO) self._gui_job = None EventLogger.add_logger(self._gui_logger) # FIXME better way to find interval and uids in tree_widget?! self.__tree_interval_tooltip = "Update interval in seconds" self.__tree_uid_tooltip = "UID cannot be empty" self.data_logger_thread = None self.tab_debug_warning = False self.device_dialog = None self.host_infos = None self.last_host = None self.host_index_changing = None self.setupUi(self) self.model_data = QStandardItemModel(self) self.model_data.setHorizontalHeaderLabels( ['Time', 'Name', 'UID', 'Var', 'Raw', 'Unit']) self.table_data.setModel(self.model_data) self.table_data.setColumnWidth(0, 160) self.table_data.setColumnWidth(1, 170) self.table_data.setColumnWidth(2, 50) self.table_data.setColumnWidth(3, 110) self.table_data.setColumnWidth(4, 70) self.table_data.setColumnWidth(5, 100) self.model_devices = QStandardItemModel(self) self.model_devices.setHorizontalHeaderLabels(['Device', 'Value']) self.tree_devices.setModel(self.model_devices) self.tree_devices.setColumnWidth(0, 300) self.widget_initialization() self.btn_start_logging.setIcon( QIcon(load_pixmap('data_logger/start-icon.png'))) timestamp = int(time.time()) self.edit_csv_file_name.setText( os.path.join(get_home_path(), 'logger_data_{0}.csv'.format(timestamp))) self.edit_log_file_name.setText( os.path.join(get_home_path(), 'logger_debug_{0}.log'.format(timestamp))) self.combo_data_time_format.addItem( utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_data_time_format.addItem( utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_data_time_format.addItem( utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso') self.combo_data_time_format.addItem( utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix') self.combo_debug_time_format.addItem( utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_debug_time_format.addItem( utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_debug_time_format.addItem( utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso') self.combo_debug_time_format.addItem( utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix') self.combo_log_level.addItem('Debug', 'debug') self.combo_log_level.addItem('Info', 'info') self.combo_log_level.addItem('Warning', 'warning') self.combo_log_level.addItem('Error', 'error') self.combo_log_level.addItem('Critical', 'critical') self.combo_log_level.setCurrentIndex(0) # debug self.combo_debug_level.addItem('Debug', logging.DEBUG) self.combo_debug_level.addItem('Info', logging.INFO) self.combo_debug_level.addItem('Warning', logging.WARNING) self.combo_debug_level.addItem('Error', logging.ERROR) self.combo_debug_level.addItem('Critical', logging.CRITICAL) self.combo_debug_level.setCurrentIndex(1) # info self.update_ui_state() def update_ui_state(self): data_to_csv_file = self.check_data_to_csv_file.isChecked() debug_to_log_file = self.check_debug_to_log_file.isChecked() self.label_csv_file_name.setVisible(data_to_csv_file) self.edit_csv_file_name.setVisible(data_to_csv_file) self.btn_browse_csv_file_name.setVisible(data_to_csv_file) self.label_log_file_name.setVisible(debug_to_log_file) self.edit_log_file_name.setVisible(debug_to_log_file) self.btn_browse_log_file_name.setVisible(debug_to_log_file) self.label_log_level.setVisible(debug_to_log_file) self.combo_log_level.setVisible(debug_to_log_file) def widget_initialization(self): """ Sets default values for some widgets """ # Login data self.host_info_initialization() self.signal_initialization() def signal_initialization(self): """ Init of all important Signals and connections. """ # Buttons self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked) self.btn_save_config.clicked.connect(self.btn_save_config_clicked) self.btn_load_config.clicked.connect(self.btn_load_config_clicked) self.check_data_to_csv_file.stateChanged.connect(self.update_ui_state) self.check_debug_to_log_file.stateChanged.connect(self.update_ui_state) self.btn_browse_csv_file_name.clicked.connect( self.btn_browse_csv_file_name_clicked) self.btn_browse_log_file_name.clicked.connect( self.btn_browse_log_file_name_clicked) self.btn_clear_debug.clicked.connect(self.btn_clear_debug_clicked) self.combo_debug_level.currentIndexChanged.connect( self.combo_debug_level_changed) self.btn_add_device.clicked.connect(self.btn_add_device_clicked) self.btn_remove_device.clicked.connect(self.btn_remove_device_clicked) self.btn_remove_all_devices.clicked.connect( self.btn_remove_all_devices_clicked) self.tab_widget.currentChanged.connect(self.tab_reset_warning) self.btn_clear_data.clicked.connect(self.btn_clear_data_clicked) self.connect(self._gui_logger, QtCore.SIGNAL(GUILogger.SIGNAL_NEW_MESSAGE), self.add_debug_message) self.connect(self._gui_logger, QtCore.SIGNAL(GUILogger.SIGNAL_NEW_MESSAGE_TAB_HIGHLIGHT), self.highlight_debug_tab) self.combo_host.currentIndexChanged.connect(self._host_index_changed) self.spin_port.valueChanged.connect(self._port_changed) def host_info_initialization(self): """ initialize host by getting information out of brickv.config """ self.host_infos = config.get_host_infos(config.HOST_INFO_COUNT) self.host_index_changing = True for host_info in self.host_infos: self.combo_host.addItem(host_info.host) self.last_host = None self.combo_host.setCurrentIndex(0) self.spin_port.setValue(self.host_infos[0].port) self.host_index_changing = False def btn_start_logging_clicked(self): """ Start/Stop of the logging process """ if (self.data_logger_thread is not None) and (not self.data_logger_thread.stopped): self.btn_start_logging.clicked.disconnect() self.data_logger_thread.stop() self._reset_stop() elif self.data_logger_thread is None: from brickv.data_logger import main self._gui_job = GuiDataJob(name="GuiData-Writer") self.connect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row) self.data_logger_thread = main.main( None, GuiConfigHandler.create_config(self), self._gui_job) if self.data_logger_thread is not None: self.btn_start_logging.setText("Stop Logging") self.btn_start_logging.setIcon( QIcon(load_pixmap('data_logger/stop-icon.png'))) self.tab_devices.setEnabled(False) self.tab_setup.setEnabled(False) self.tab_widget.setCurrentIndex( self.tab_widget.indexOf(self.tab_data)) self.tab_reset_warning() def _reset_stop(self): self.tab_devices.setEnabled(True) self.tab_setup.setEnabled(True) self.btn_start_logging.setText("Start Logging") self.btn_start_logging.setIcon( QIcon(load_pixmap('data_logger/start-icon.png'))) self.disconnect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row) self.data_logger_thread = None self._gui_job = None self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked) def btn_save_config_clicked(self): filename = get_save_file_name(get_main_window(), 'Save Config', get_home_path(), 'JSON Files (*.json)') if len(filename) == 0: return if not filename.lower().endswith('.json'): filename += '.json' config = GuiConfigHandler.create_config(self) if not save_config(config, filename): QMessageBox.warning( get_main_window(), 'Save Config', 'Could not save config to file! See Debug tab for details.', QMessageBox.Ok) def btn_load_config_clicked(self): filename = get_open_file_name(get_main_window(), 'Load Config', get_home_path(), 'JSON Files (*.json)') if len(filename) == 0: return config = load_and_validate_config(filename) if config == None: QMessageBox.warning( get_main_window(), 'Load Config', 'Could not load config from file! See Debug tab for details.', QMessageBox.Ok) return self.update_setup_tab(config) self.update_devices_tab(config) def btn_browse_csv_file_name_clicked(self): if len(self.edit_csv_file_name.text()) > 0: last_dir = os.path.dirname( os.path.realpath(self.edit_csv_file_name.text())) else: last_dir = get_home_path() filename = get_save_file_name(get_main_window(), 'Choose CSV File', last_dir, "CSV Files (*.csv)") if len(filename) > 0: if not filename.lower().endswith('.csv'): filename += '.csv' self.edit_csv_file_name.setText(filename) def btn_browse_log_file_name_clicked(self): if len(self.edit_log_file_name.text()) > 0: last_dir = os.path.dirname( os.path.realpath(self.edit_log_file_name.text())) else: last_dir = get_home_path() filename = get_save_file_name(get_main_window(), 'Choose Log File', last_dir, "Log Files (*.log)") if len(filename) > 0: if not filename.lower().endswith('.log'): filename += '.log' self.edit_log_file_name.setText(filename) def btn_add_device_clicked(self): """ Opens the DeviceDialog in Add-Mode. """ if self.device_dialog is None: self.device_dialog = DeviceDialog(self) self.device_dialog.btn_refresh_clicked() self.device_dialog.show() def btn_remove_device_clicked(self): selection = self.tree_devices.selectionModel().selectedIndexes() while len(selection) > 0: index = selection[0] while index.parent() != self.model_devices.invisibleRootItem( ).index(): index = index.parent() self.model_devices.removeRows(index.row(), 1) # get new selection, because row removal might invalid indices selection = self.tree_devices.selectionModel().selectedIndexes() def btn_remove_all_devices_clicked(self): self.model_devices.removeRows(0, self.model_devices.rowCount()) def btn_clear_data_clicked(self): self.model_data.removeRows(0, self.model_data.rowCount()) def tab_reset_warning(self): """ Resets the Warning @ the debug tab. """ if not self.tab_debug_warning or self.tab_widget.currentWidget( ).objectName() != self.tab_debug.objectName(): return self.tab_debug_warning = False self.tab_set(self.tab_widget.indexOf(self.tab_debug), self.palette().color(QPalette.WindowText), None) def combo_debug_level_changed(self): """ Changes the log level dynamically. """ self._gui_logger.level = self.combo_debug_level.itemData( self.combo_debug_level.currentIndex()) def tab_set(self, tab_index, color, icon=None): """ Sets the font Color and an icon, if given, at a specific tab. """ from PyQt4.QtGui import QIcon self.tab_widget.tabBar().setTabTextColor(tab_index, color) if icon is not None: self.tab_widget.setTabIcon(tab_index, QIcon(icon)) else: self.tab_widget.setTabIcon(tab_index, QIcon()) def _host_index_changed(self, i): """ Persists host information changes like in brickv.mainwindow Changes port if the host was changed """ if i < 0: return self.host_index_changing = True self.spin_port.setValue(self.host_infos[i].port) self.host_index_changing = False def _port_changed(self, value): """ Persists host information changes like in brickv.mainwindow """ if self.host_index_changing: return i = self.combo_host.currentIndex() if i < 0: return self.host_infos[i].port = self.spin_port.value() def update_setup_tab(self, config): EventLogger.debug('Updating setup tab from config') self.combo_host.setEditText(config['hosts']['default']['name']) self.spin_port.setValue(config['hosts']['default']['port']) self.combo_data_time_format.setCurrentIndex( max( self.combo_data_time_format.findData( config['data']['time_format']), 0)) self.check_data_to_csv_file.setChecked( config['data']['csv']['enabled']) self.edit_csv_file_name.setText( config['data']['csv']['file_name'].decode('utf-8')) self.combo_debug_time_format.setCurrentIndex( max( self.combo_debug_time_format.findData( config['debug']['time_format']), 0)) self.check_debug_to_log_file.setChecked( config['debug']['log']['enabled']) self.edit_log_file_name.setText( config['debug']['log']['file_name'].decode('utf-8')) self.combo_log_level.setCurrentIndex( max( self.combo_debug_time_format.findData( config['debug']['log']['level']), 0)) def update_devices_tab(self, config): EventLogger.debug('Updating devices tab from config') self.model_devices.removeRows(0, self.model_data.rowCount()) for device in config['devices']: self.add_device_to_tree(device) def add_device_to_tree(self, device): # check if device is already added if len(device['uid']) > 0: for row in range(self.model_devices.rowCount()): existing_name = self.model_devices.item(row, 0).text() exisitng_uid = self.tree_devices.indexWidget( self.model_devices.item(row, 1).index()).text() if device['name'] == existing_name and device[ 'uid'] == exisitng_uid: EventLogger.info( 'Ignoring duplicate device "{0}" with UID "{1}"'. format(device['name'], device['uid'])) return # add device name_item = QStandardItem(device['name']) uid_item = QStandardItem('') self.model_devices.appendRow([name_item, uid_item]) edit_uid = QLineEdit() edit_uid.setPlaceholderText('Enter UID') edit_uid.setValidator( QRegExpValidator(QRegExp( '^[{0}]{{1,6}}$'.format(BASE58)))) # FIXME: use stricter logic edit_uid.setText(device['uid']) self.tree_devices.setIndexWidget(uid_item.index(), edit_uid) value_specs = device_specs[device['name']]['values'] parent_item = QStandardItem('Values') name_item.appendRow([parent_item, QStandardItem('')]) self.tree_devices.expand(parent_item.index()) # add values for value_spec in value_specs: value_name_item = QStandardItem(value_spec['name']) value_interval_item = QStandardItem('') parent_item.appendRow([value_name_item, value_interval_item]) spinbox_interval = QSpinBox() spinbox_interval.setRange(0, (1 << 31) - 1) spinbox_interval.setSingleStep(1) spinbox_interval.setValue( device['values'][value_spec['name']]['interval']) spinbox_interval.setSuffix(' seconds') self.tree_devices.setIndexWidget(value_interval_item.index(), spinbox_interval) if value_spec['subvalues'] != None: for subvalue_name in value_spec['subvalues']: subvalue_name_item = QStandardItem(subvalue_name) subvalue_check_item = QStandardItem('') value_name_item.appendRow( [subvalue_name_item, subvalue_check_item]) check_subvalue = QCheckBox() check_subvalue.setChecked(device['values'][ value_spec['name']]['subvalues'][subvalue_name]) self.tree_devices.setIndexWidget( subvalue_check_item.index(), check_subvalue) self.tree_devices.expand(name_item.index()) # add options option_specs = device_specs[device['name']]['options'] if option_specs != None: parent_item = QStandardItem('Options') name_item.appendRow([parent_item, QStandardItem('')]) for option_spec in option_specs: option_name_item = QStandardItem(option_spec['name']) option_widget_item = QStandardItem('') parent_item.appendRow([option_name_item, option_widget_item]) if option_spec['type'] == 'choice': widget_option_value = QComboBox() for option_value_spec in option_spec['values']: widget_option_value.addItem( option_value_spec[0].decode('utf-8'), option_value_spec[1]) widget_option_value.setCurrentIndex( widget_option_value.findText(device['options'][ option_spec['name']]['value'].decode('utf-8'))) elif option_spec['type'] == 'int': widget_option_value = QSpinBox() widget_option_value.setRange(option_spec['minimum'], option_spec['maximum']) widget_option_value.setSuffix(option_spec['suffix']) widget_option_value.setValue( device['options'][option_spec['name']]['value']) elif option_spec['type'] == 'bool': widget_option_value = QCheckBox() widget_option_value.setChecked( device['options'][option_spec['name']]['value']) self.tree_devices.setIndexWidget(option_widget_item.index(), widget_option_value) def add_debug_message(self, message): self.text_debug.append(message) while self.text_debug.document().blockCount() > 1000: cursor = QTextCursor(self.text_debug.document().begin()) cursor.select(QTextCursor.BlockUnderCursor) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) cursor.removeSelectedText() if self.checkbox_debug_auto_scroll.isChecked(): self.text_debug.verticalScrollBar().setValue( self.text_debug.verticalScrollBar().maximum()) def btn_clear_debug_clicked(self): self.text_debug.clear() def highlight_debug_tab(self): """ SIGNAL function: Highlight the debug tab when an error occurs. """ if not self.tab_debug_warning and self.tab_widget.currentWidget( ).objectName() != self.tab_debug.objectName(): self.tab_debug_warning = True self.tab_set( self.tab_widget.indexOf(self.tab_debug), QColor(255, 0, 0), os.path.join(get_resources_path(), "warning-icon.png")) def table_add_row(self, csv_data): """ SIGNAL function: Adds new CSV Data into the Table. """ rows = self.model_data.rowCount() while rows >= 1000: self.model_data.removeRow(0) rows = self.model_data.rowCount() row_number = None if rows > 0: try: row_number = int( self.model_data.headerData(rows - 1, Qt.Vertical)) except ValueError: pass self.model_data.appendRow([ QStandardItem(csv_data.timestamp), QStandardItem(csv_data.name), QStandardItem(csv_data.uid), QStandardItem(csv_data.var_name), QStandardItem(str(csv_data.raw_data)), QStandardItem(csv_data.var_unit.decode('utf-8')) ]) if row_number != None: self.model_data.setHeaderData(rows, Qt.Vertical, str(row_number + 1)) if self.checkbox_data_auto_scroll.isChecked(): self.table_data.scrollToBottom()
class ObstacleTable(QSortFilterProxyModel): MocMultiplier = 1 SelectionMode = SelectionModeType.Automatic def __init__(self, surfacesList, fileWriter=None): QSortFilterProxyModel.__init__(self) ObstacleTable.SelectionMode = SelectionModeType.Automatic self.manualPolygon = None self.surfacesList = surfacesList self.surfaceType = None self.source = QStandardItemModel() self.setSourceModel(self.source) # tableView.hideColumn(self.IndexObjectId) # tableView.hideColumn(self.IndexLayerId) # tableView.hideColumn(self.IndexX) # tableView.hideColumn(self.IndexY) # tableView.hideColumn(self.IndexLat) # tableView.hideColumn(self.IndexLon) # tableView.hideColumn(self.IndexSurface) self.hideColumnLabels = [ ObstacleTableColumnType.ObjectId, ObstacleTableColumnType.LayerId, ObstacleTableColumnType.X, ObstacleTableColumnType.Y, ObstacleTableColumnType.Lat, ObstacleTableColumnType.Lon, ObstacleTableColumnType.Surface ] self.fixedColumnLabels = [ ObstacleTableColumnType.ObjectId, ObstacleTableColumnType.LayerId, ObstacleTableColumnType.Name, ObstacleTableColumnType.X, ObstacleTableColumnType.Y, ObstacleTableColumnType.Lat, ObstacleTableColumnType.Lon, ObstacleTableColumnType.AltM, ObstacleTableColumnType.AltFt, ObstacleTableColumnType.TreesM, ObstacleTableColumnType.TreesFt ] self.IndexObjectId = 0 self.IndexLayerId = 1 self.IndexName = 2 self.IndexX = 3 self.IndexY = 4 self.IndexLat = 5 self.IndexLon = 6 self.IndexAltM = 7 self.IndexAltFt = 8 self.IndexTreesM = 9 self.IndexTreesFt = 10 self.IndexOcaM = -1 self.IndexOcaFt = -1 self.IndexOchM = -1 self.IndexOchFt = -1 self.IndexObstArea = -1 self.IndexDistInSecM = -1 self.IndexMocAppliedM = -1 self.IndexMocAppliedFt = -1 self.IndexMocMultiplier = -1 self.IndexMocReqM = -1 self.IndexMocReqFt = -1 self.IndexDoM = -1 self.IndexDrM = -1 self.IndexDzM = -1 self.IndexDxM = -1 self.IndexDsocM = -1 self.IndexHeightLossM = -1 self.IndexHeightLossFt = -1 self.IndexAcAltM = -1 self.IndexAcAltFt = -1 self.IndexAltReqM = -1 self.IndexAltReqFt = -1 self.IndexCritical = -1 self.IndexMACG = -1 self.IndexPDG = -1 self.IndexSurfAltM = -1 self.IndexSurfAltFt = -1 self.IndexDifferenceM = -1 self.IndexDifferenceFt = -1 self.IndexIlsX = -1 self.IndexIlsY = -1 self.IndexEqAltM = -1 self.IndexEqAltFt = -1 self.IndexSurfaceName = -1 self.IndexDisregardable = -1 self.IndexCloseIn = -1 self.IndexTag = -1 self.IndexSurface = -1 self.IndexArea = -1 self.IndexHLAppliedM = -1 self.setHeaderLabels() self.setFilterKeyColumn(self.IndexSurface) self.setSortRole(Qt.UserRole + 1) self.layoutChanged.connect(self.setVerticalHeader) self.btnLocate = None self.tblObstacles = None def FilterDisregardableObstacles(self, state): if state: self.setFilterKeyColumn(self.IndexDisregardable) self.setFilterFixedString("Yes") self.setFilterKeyColumn(self.IndexSurface) def setSurfaceType(self, surfaceType): self.surfaceType = surfaceType def setFilterFixedString(self, filterString): QSortFilterProxyModel.setFilterFixedString(self, filterString) self.setVerticalHeader() if self.btnLocate != None and self.tblObstacles != None: selectedIndexes = self.tblObstacles.selectedIndexes() if len(selectedIndexes) == 0: self.btnLocate.setEnabled(False) else: self.btnLocate.setEnabled(True) def setLocateBtn(self, btnLocate): self.btnLocate = btnLocate self.btnLocate.setEnabled(False) self.btnLocate.clicked.connect(self.btnLocateClicked) def btnLocateClicked(self): if self.tblObstacles == None: return selectedIndexes = self.tblObstacles.selectedIndexes() self.locate(selectedIndexes) def tblObstaclesClicked(self, idx): if len(self.tblObstacles.selectedIndexes()) > 0: self.btnLocate.setEnabled(True) def setTableView(self, tblObstacles): self.tblObstacles = tblObstacles self.tblObstacles.setSelectionBehavior(QAbstractItemView.SelectRows) self.tblObstacles.setSortingEnabled(True) self.tblObstacles.clicked.connect(self.tblObstaclesClicked) self.tblObstacles.verticalHeader().sectionClicked.connect( self.tblObstaclesClicked) pass def setHeaderLabels(self): # print self.setHeaderData(1, Qt.Vertical, 1, Qt.DisplayRole) pass def setVerticalHeader(self): for i in range(self.rowCount()): self.setHeaderData(i, Qt.Vertical, i + 1, Qt.DisplayRole) def setHiddenColumns(self, tableView): tableView.hideColumn(self.IndexObjectId) tableView.hideColumn(self.IndexLayerId) tableView.hideColumn(self.IndexX) tableView.hideColumn(self.IndexY) tableView.hideColumn(self.IndexLat) tableView.hideColumn(self.IndexLon) tableView.hideColumn(self.IndexSurface) def getExtentForLocate(self, sourceRow): extent = None surfaceType = None if self.IndexSurface < 0: surfaceType = self.surfaceType else: surfaceType = self.source.item(sourceRow, self.IndexSurface).text() surfaceLayers = QgisHelper.getSurfaceLayers(self.surfaceType) for sfLayer in surfaceLayers: lId = sfLayer.name() if lId.contains(surfaceType): extent = sfLayer.extent() break return extent def clear(self): self.source.clear() self.source.setHorizontalHeaderLabels(self.fixedColumnLabels) # self.setHeaderLabels() def locate(self, selectedRowIndexes): if selectedRowIndexes == None or len(selectedRowIndexes) <= 0: return sourceRow = self.mapToSource(selectedRowIndexes[0]).row() objectId = int(self.source.item(sourceRow, self.IndexObjectId).text()) layerId = self.source.item(sourceRow, self.IndexLayerId).text() QgisHelper.selectFeature(layerId, objectId) layer = QgsMapLayerRegistry.instance().mapLayer(layerId) crs = define._canvas.mapSettings().destinationCrs() if crs.mapUnits() == QGis.Meters: x = float(self.source.item(sourceRow, self.IndexX).text()) y = float(self.source.item(sourceRow, self.IndexY).text()) extent = QgsRectangle(x - 350, y - 350, x + 350, y + 350) else: x, result1 = self.source.item(sourceRow, self.IndexLon).data().toDouble() y, result2 = self.source.item(sourceRow, self.IndexLat).data().toDouble() extent = QgsRectangle(x - 0.005, y - 0.005, x + 0.005, y + 0.005) point = QgsPoint(x, y) # extent = self.getExtentForLocate(sourceRow) if extent is None: return QgisHelper.zoomExtent(point, extent, 2) pass def loadObstacles(self, surfaceLayers): if self.source.rowCount() > 0: self.source.clear() self.source.setHorizontalHeaderLabels(self.fixedColumnLabels) demEvaluateAg = None existingDemFlag = False obstacleLayersDEM = QgisHelper.getSurfaceLayers(SurfaceTypes.DEM) obstacleLayers = QgisHelper.getSurfaceLayers(SurfaceTypes.Obstacles) if obstacleLayersDEM != None and len(obstacleLayersDEM) > 0: if QMessageBox.question( None, "Question", "Do you want to use DEM for evaluating Obstacle?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: self.loadObstaclesDEM(obstacleLayersDEM, surfaceLayers) if obstacleLayers != None and len(obstacleLayers) > 0: # if QMessageBox.question(None, "Question", "Do you want to use DEM for evaluating Obstacle?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.No: self.loadObstaclesVector(obstacleLayers, surfaceLayers) return True def loadObstaclesDEM(self, obstacleLayersDEM, surfaceLayers): progressMessageBar = define._messagBar.createMessage( "Loading DEM Obstacles...") self.progress = QProgressBar() self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(self.progress) define._messagBar.pushWidget(progressMessageBar, define._messagBar.INFO) maxium = 0 offset = 0.0 self.progress.setValue(0) wCount = 0 hCount = 0 for ly in obstacleLayersDEM: demDataProvider = ly.dataProvider() boundDem = demDataProvider.extent() xMin = boundDem.xMinimum() xMax = boundDem.xMaximum() yMin = boundDem.yMinimum() yMax = boundDem.yMaximum() bound = QgisHelper.getIntersectExtent( ly, QgsGeometry.fromRect(boundDem), surfaceLayers) # boundGeom = QgsGeometry.fromRect(bound) if bound == None: continue block = ly.dataProvider().block(0, ly.extent(), ly.width(), ly.height()) xMinimum = ly.dataProvider().extent().xMinimum() yMaximum = ly.dataProvider().extent().yMaximum() yMinimum = ly.dataProvider().extent().yMinimum() xMaximum = ly.dataProvider().extent().xMaximum() xOffSet = ly.extent().width() / ly.width() yOffSet = ly.extent().height() / ly.height() offset = xOffSet if bound.xMinimum() < xMinimum: wStartNumber = 0 xStartValue = xMinimum else: wStartNumber = int((bound.xMinimum() - xMinimum) / xOffSet) xStartValue = bound.xMinimum() if yMaximum < bound.yMaximum(): hStartNumber = 0 yStartValue = yMaximum else: hStartNumber = int((yMaximum - bound.yMaximum()) / yOffSet) yStartValue = bound.yMaximum() if bound.xMaximum() > xMaximum: xEndValue = xMaximum else: xEndValue = bound.xMaximum() if yMinimum > bound.yMinimum(): yEndValue = yMinimum else: yEndValue = bound.yMinimum() wCount = int(math.fabs(xEndValue - xStartValue) / xOffSet) hCount = int(math.fabs(yEndValue - yStartValue) / yOffSet) pixelCount = hCount maxium += pixelCount cellSizeWnd = cellsizeWnd(offset, wCount * hCount, maxium * 0.04) cellSizeWnd.setWindowTitle("Input Cell Size") result = cellSizeWnd.exec_() cellRate = 1 if result == 1: offset = cellSizeWnd.cellsize maxium = cellSizeWnd.cellCount + 2 cellRate = cellSizeWnd.cellRate # print cellSizeWnd.textedit1.text() if maxium == 0: return False self.progress.setMaximum(maxium) trees = define._treesDEM tolerance = define._toleranceDEM for obstacleLayer in obstacleLayersDEM: obstacleUnits = obstacleLayer.crs().mapUnits() demDataProvider = obstacleLayer.dataProvider() boundDem = demDataProvider.extent() bound = QgisHelper.getIntersectExtent( obstacleLayer, QgsGeometry.fromRect(boundDem), surfaceLayers) if bound == None: continue boundGeom = QgsGeometry.fromRect(bound) if not boundGeom.intersects(QgsGeometry.fromRect(boundDem)): continue block = obstacleLayer.dataProvider().block(1, obstacleLayer.extent(), obstacleLayer.width(), obstacleLayer.height()) xMinimum = obstacleLayer.extent().xMinimum() yMaximum = obstacleLayer.extent().yMaximum() yMinimum = obstacleLayer.extent().yMinimum() xMaximum = obstacleLayer.extent().xMaximum() xOffSet = obstacleLayer.extent().width() / obstacleLayer.width() yOffSet = obstacleLayer.extent().height() / obstacleLayer.height() if bound.xMinimum() < xMinimum: hStartNumber = 0 xStartValue = xMinimum else: hStartNumber = int((bound.xMinimum() - xMinimum) / xOffSet) xStartValue = bound.xMinimum() if yMaximum < bound.yMaximum(): wStartNumber = 0 yStartValue = yMaximum else: wStartNumber = int((yMaximum - bound.yMaximum()) / yOffSet) yStartValue = bound.yMaximum() if bound.xMaximum() > xMaximum: xEndValue = xMaximum else: xEndValue = bound.xMaximum() if yMinimum > bound.yMinimum(): yEndValue = yMinimum else: yEndValue = bound.yMinimum() wCount = int(math.fabs(xEndValue - xStartValue) / offset) hCount = int(math.fabs(yEndValue - yStartValue) / offset) xPixelWidth = 0.0 yPixelWidth = 0.0 featureID = 0 # i = 0 # k = 0 # altitudeList = [] # self.progress.setValue(0) # while i <= hCount - 1: # j = 0 # while j <= wCount - 1: # if block.isNoData(j * int(cellRate) + wStartNumber, i* int(cellRate) + hStartNumber): # self.progress.setValue(k) # QApplication.processEvents() # j += 1 # k += 1 # altitudeList.append(None) # continue # altitude = block.value(j * int(cellRate) + wStartNumber, i * int(cellRate) + hStartNumber) # altitudeList.append(altitude) # self.progress.setValue(k) # QApplication.processEvents() # j += 1 # k += 1 # i += 1 i = 0 k = 0 name = "DEM" semiXoffset = xOffSet / 2 semiYoffset = yOffSet / 2 while i <= hCount - 1: j = 0 while j <= wCount - 1: if block.isNoData(j * cellRate + wStartNumber, i * cellRate + hStartNumber): self.progress.setValue(k) QApplication.processEvents() j += 1 k += 1 continue altitude = block.value(j * cellRate + wStartNumber, i * cellRate + hStartNumber) # # if block.isNoData(j * int(cellRate) + wStartNumber, i* int(cellRate) + hStartNumber): # # j += 1 # # self.progress.setValue(self.progress.value() + 1) # # QApplication.processEvents() # # continue # # altitude = block.value(j* int(cellRate) + wStartNumber, i* int(cellRate)+ hStartNumber) # altitude = altitudeList[k] # if altitude == None: # self.progress.setValue(k) # QApplication.processEvents() # j += 1 # k += 1 # continue point = QgsPoint( xStartValue + (i * cellRate) * xOffSet + semiXoffset, yStartValue - (j * cellRate - 1) * yOffSet - semiYoffset) position = Point3D() positionDegree = Point3D() if define._canvas.mapUnits() == QGis.Meters: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): position = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: position = Point3D(point.x(), point.y(), altitude) else: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): positionDegree = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: positionDegree = Point3D(point.x(), point.y(), altitude) obstacle = Obstacle(name, position, obstacleLayer.id(), featureID, None, trees, ObstacleTable.MocMultiplier, tolerance) obstacle.positionDegree = positionDegree if self.manualPolygon != None: if not self.manualPolygon.contains(obstacle.Position): continue self.checkObstacle(obstacle) self.progress.setValue(k) QApplication.processEvents() j += 1 featureID += 1 k += 1 i += 1 self.progress.setValue(maxium) define._messagBar.hide() self.manualPolygon = None def loadObstaclesVector(self, obstacleLayers, surfaceLayers): progressMessageBar = define._messagBar.createMessage( "Loading Vector Obstacles...") self.progress = QProgressBar() self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(self.progress) define._messagBar.pushWidget(progressMessageBar, define._messagBar.INFO) maxium = 0 self.progress.setValue(0) for ly in obstacleLayers: maxium += ly.featureCount() if maxium == 0: return False self.progress.setMaximum(maxium) for obstacleLayer in obstacleLayers: obstacleUnits = obstacleLayer.crs().mapUnits() features = QgisHelper.getFeaturesInLayerExtent( define._canvas, obstacleLayer, surfaceLayers, SelectionModeType.Automatic) # print len(features) for feature in features: name = feature.attribute("Name").toString() altitude = feature.attribute("Altitude").toFloat()[0] trees = define._trees tolerance = define._tolerance point = feature.geometry().asPoint() position = Point3D() positionDegree = Point3D() if define._canvas.mapUnits() == QGis.Meters: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): position = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: position = Point3D(point.x(), point.y(), altitude) else: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): positionDegree = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: positionDegree = Point3D(point.x(), point.y(), altitude) featureId = feature.id() layerId = obstacleLayer.id() obstacle = Obstacle(name, position, layerId, featureId, None, trees, ObstacleTable.MocMultiplier, tolerance) obstacle.positionDegree = positionDegree # obstacle.positionDegree = positionDegree self.checkObstacle(obstacle) self.progress.setValue(self.progress.value() + 1) QApplication.processEvents() QApplication.processEvents() self.progress.setValue(maxium) define._messagBar.hide() self.manualPolygon = None def addObstacleToModel(self, obstacle, checkResult=None): standardItemList = [] # obstacle.positionDegree = QgisHelper.Meter2Degree(obstacle.Position.x(), obstacle.Position.y()) standardItem = QStandardItem(str(obstacle.featureId)) standardItem.setData(obstacle.featureId) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.layerId)) standardItem.setData(obstacle.layerId) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.name)) standardItem.setData(obstacle.name) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.Position.x())) standardItem.setData(obstacle.Position.x()) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.Position.y())) standardItem.setData(obstacle.Position.y()) standardItemList.append(standardItem) value = QVariant(QgisHelper.strDegree(obstacle.positionDegree.y())) standardItem = QStandardItem(value.toString()) standardItem.setData(obstacle.positionDegree.y()) standardItemList.append(standardItem) strV = QgisHelper.strDegree(obstacle.positionDegree.y()) value = QVariant(QgisHelper.strDegree(obstacle.positionDegree.x())) standardItem = QStandardItem(value.toString()) standardItem.setData(obstacle.positionDegree.x()) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.Position.z())) standardItem.setData(obstacle.Position.z()) standardItemList.append(standardItem) standardItem = QStandardItem( str(Unit.ConvertMeterToFeet(obstacle.Position.z()))) standardItem.setData(Unit.ConvertMeterToFeet(obstacle.Position.z())) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.trees)) standardItem.setData(obstacle.trees) standardItemList.append(standardItem) standardItem = QStandardItem( str(Unit.ConvertMeterToFeet(obstacle.trees))) standardItem.setData(Unit.ConvertMeterToFeet(obstacle.trees)) standardItemList.append(standardItem) # for i in range(len(standardItemList), self.source.columnCount()): # standardItemList.append(QStandardItem("None")) self.source.appendRow(standardItemList) standardItem = QStandardItem(str(obstacle.mocMultiplier)) standardItem.setData(obstacle.mocMultiplier) self.source.setItem(self.source.rowCount() - 1, self.IndexMocMultiplier, standardItem) def checkObstacle(self, obstacle): pass def CompareObstacleRows(self, newRow, row, ignore): pass def method_0(self, obstacle_0): colCount = self.columnCount() objectId = range(colCount) objectId[0] = (obstacle_0.featureId) objectId[1] = (obstacle_0.name) objectId[2] = (obstacle_0.position.x()) objectId[3] = (obstacle_0.position.y()) objectId[4] = (obstacle_0.Position.z()) position = obstacle_0.position objectId[6] = (Unit.ConvertMeterToFeet(position.z())) objectId[7] = (obstacle_0.trees) objectId[8] = (Unit.ConvertMeterToFeet(obstacle_0.Trees)) if (self.IndexMocMultiplier > -1): objectId[self.IndexMocMultiplier] = obstacle_0.MocMultiplier return objectId def method_1(self, object_0): pass
class OWKMeans(widget.OWWidget): name = "k-Means" description = "k-means clustering algorithm with silhouette-based " \ "quality estimation." icon = "icons/KMeans.svg" priority = 2100 inputs = [("Data", Table, "set_data")] outputs = [("Annotated Data", Table, widget.Default), ("Centroids", Table)] INIT_KMEANS, INIT_RANDOM = range(2) INIT_METHODS = "Initialize with KMeans++", "Random initialization" SILHOUETTE, INTERCLUSTER, DISTANCES = range(3) SCORING_METHODS = [("Silhouette", lambda km: km.silhouette, False), ("Inter-cluster distance", lambda km: km.inter_cluster, True), ("Distance to centroids", lambda km: km.inertia, True)] OUTPUT_CLASS, OUTPUT_ATTRIBUTE, OUTPUT_META = range(3) OUTPUT_METHODS = ("Class", "Feature", "Meta") resizing_enabled = False k = Setting(8) k_from = Setting(2) k_to = Setting(8) optimize_k = Setting(False) max_iterations = Setting(300) n_init = Setting(10) smart_init = Setting(INIT_KMEANS) scoring = Setting(SILHOUETTE) append_cluster_ids = Setting(True) place_cluster_ids = Setting(OUTPUT_CLASS) output_name = Setting("Cluster") auto_run = Setting(False) def __init__(self): super().__init__() self.data = None self.km = None self.optimization_runs = [] box = gui.widgetBox(self.controlArea, "Number of Clusters") layout = QGridLayout() bg = gui.radioButtonsInBox( box, self, "optimize_k", [], orientation=layout, callback=self.update) layout.addWidget( gui.appendRadioButton(bg, "Fixed", addToLayout=False), 1, 1) sb = gui.widgetBox(None, margin=0, orientation="horizontal") self.fixedSpinBox = gui.spin( sb, self, "k", minv=2, maxv=30, controlWidth=60, alignment=Qt.AlignRight, callback=self.update_k) gui.rubber(sb) layout.addWidget(sb, 1, 2) layout.addWidget( gui.appendRadioButton(bg, "Optimized", addToLayout=False), 2, 1) ftobox = gui.widgetBox(None, orientation="horizontal") ftobox.layout().setMargin(0) layout.addWidget(ftobox) gui.spin( ftobox, self, "k_from", minv=2, maxv=29, controlWidth=60, alignment=Qt.AlignRight, callback=self.update_from) gui.widgetLabel(ftobox, " To: ") self.fixedSpinBox = gui.spin( ftobox, self, "k_to", minv=3, maxv=30, controlWidth=60, alignment=Qt.AlignRight, callback=self.update_to) gui.rubber(ftobox) layout.addWidget(gui.widgetLabel(None, "Scoring: "), 5, 1, Qt.AlignRight) layout.addWidget( gui.comboBox( None, self, "scoring", label="Scoring", items=list(zip(*self.SCORING_METHODS))[0], callback=self.update), 5, 2) box = gui.widgetBox(self.controlArea, "Initialization") gui.comboBox( box, self, "smart_init", items=self.INIT_METHODS, callback=self.update) layout = QGridLayout() box2 = gui.widgetBox(box, orientation=layout) box2.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) layout.addWidget(gui.widgetLabel(None, "Re-runs: "), 0, 0, Qt.AlignLeft) sb = gui.widgetBox(None, margin=0, orientation="horizontal") layout.addWidget(sb, 0, 1) gui.lineEdit( sb, self, "n_init", controlWidth=60, valueType=int, validator=QIntValidator(), callback=self.update) layout.addWidget(gui.widgetLabel(None, "Maximal iterations: "), 1, 0, Qt.AlignLeft) sb = gui.widgetBox(None, margin=0, orientation="horizontal") layout.addWidget(sb, 1, 1) gui.lineEdit(sb, self, "max_iterations", controlWidth=60, valueType=int, validator=QIntValidator(), callback=self.update) box = gui.widgetBox(self.controlArea, "Output") gui.comboBox(box, self, "place_cluster_ids", label="Append cluster id as ", orientation="horizontal", callback=self.send_data, items=self.OUTPUT_METHODS) gui.lineEdit(box, self, "output_name", label="Name ", orientation="horizontal", callback=self.send_data) gui.auto_commit(self.controlArea, self, "auto_run", "Run", checkbox_label="Run after any change ", orientation="horizontal") gui.rubber(self.controlArea) self.table_model = QStandardItemModel(self) self.table_model.setHorizontalHeaderLabels(["k", "Score"]) self.table_model.setColumnCount(2) self.table_box = gui.widgetBox( self.mainArea, "Optimization Report", addSpace=0) table = self.table_view = QTableView(self.table_box) table.setHorizontalScrollMode(QTableView.ScrollPerPixel) table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) table.setSelectionMode(QTableView.SingleSelection) table.setSelectionBehavior(QTableView.SelectRows) table.verticalHeader().hide() table.setItemDelegateForColumn(1, gui.TableBarItem(self)) table.setModel(self.table_model) table.selectionModel().selectionChanged.connect( self.table_item_selected) table.setColumnWidth(0, 40) table.setColumnWidth(1, 120) table.horizontalHeader().setStretchLastSection(True) self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.mainArea.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred) self.table_box.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding) self.table_view.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding) self.table_box.layout().addWidget(self.table_view) self.hide_show_opt_results() def adjustSize(self): self.ensurePolished() s = self.sizeHint() self.resize(s) def hide_show_opt_results(self): [self.mainArea.hide, self.mainArea.show][self.optimize_k]() QTimer.singleShot(100, self.adjustSize) def sizeHint(self): s = self.controlArea.sizeHint() if self.optimize_k and not self.mainArea.isHidden(): s.setWidth(s.width() + self.mainArea.sizeHint().width() + 4 * self.childrenRect().x()) return s def update_k(self): self.optimize_k = False self.update() def update_from(self): self.k_to = max(self.k_from + 1, self.k_to) self.optimize_k = True self.update() def update_to(self): self.k_from = min(self.k_from, self.k_to - 1) self.optimize_k = True self.update() def set_optimization(self): self.updateOptimizationGui() self.update() def check_data_size(self, n): if n > len(self.data): self.error("Not enough unique data instances ({}) for given " "number of clusters ({}).".format(len(self.data), n)) return False return True def run_optimization(self): # Disabling is needed since this function is not reentrant # Fast clicking on, say, "To: " causes multiple calls try: self.controlArea.setDisabled(True) self.optimization_runs = [] if self.check_data_size(self.k_to): self.optimization_runs = [] kmeans = KMeans( init=['random', 'k-means++'][self.smart_init], n_init=self.n_init, max_iter=self.max_iterations) with self.progressBar(self.k_to - self.k_from + 1) as progress: for k in range(self.k_from, self.k_to + 1): progress.advance() kmeans.params["n_clusters"] = k self.optimization_runs.append((k, kmeans(self.data))) finally: self.controlArea.setDisabled(False) self.show_results() self.send_data() def cluster(self): if not self.check_data_size(self.k): return self.km = KMeans( n_clusters=self.k, init=['random', 'k-means++'][self.smart_init], n_init=self.n_init, max_iter=self.max_iterations)(self.data) self.send_data() def run(self): self.error() if not self.data: return if self.optimize_k: self.run_optimization() else: self.cluster() commit = run def show_results(self): minimize = self.SCORING_METHODS[self.scoring][2] k_scores = [(k, self.SCORING_METHODS[self.scoring][1](run)) for k, run in self.optimization_runs] scores = list(zip(*k_scores))[1] if minimize: best_score, worst_score = min(scores), max(scores) else: best_score, worst_score = max(scores), min(scores) best_run = scores.index(best_score) score_span = (best_score - worst_score) or 1 max_score = max(scores) nplaces = min(5, int(abs(math.log(max(max_score, 1e-10)))) + 2) fmt = "{{:.{}}}".format(nplaces) model = self.table_model model.setRowCount(len(k_scores)) for i, (k, score) in enumerate(k_scores): item = model.item(i, 0) if item is None: item = QStandardItem() item.setData(k, Qt.DisplayRole) item.setTextAlignment(Qt.AlignCenter) model.setItem(i, 0, item) item = model.item(i, 1) if item is None: item = QStandardItem() item.setData(fmt.format(score), Qt.DisplayRole) bar_ratio = 0.95 * (score - worst_score) / score_span item.setData(bar_ratio, gui.TableBarItem.BarRole) model.setItem(i, 1, item) self.table_view.resizeRowsToContents() self.table_view.selectRow(best_run) self.table_view.show() if minimize: self.table_box.setTitle("Scoring (smaller is better)") else: self.table_box.setTitle("Scoring (bigger is better)") QTimer.singleShot(0, self.adjustSize) def update(self): self.hide_show_opt_results() self.run() def selected_row(self): indices = self.table_view.selectedIndexes() rows = {ind.row() for ind in indices} if len(rows) == 1: return rows.pop() def table_item_selected(self): row = self.selected_row() if row is not None: self.send_data(row) def send_data(self, row=None): if self.optimize_k: if row is None: row = self.selected_row() km = self.optimization_runs[row][1] else: km = self.km if not self.data or not km: self.send("Annotated Data", None) self.send("Centroids", None) return clust_var = DiscreteVariable( self.output_name, values=["C%d" % (x + 1) for x in range(km.k)]) clust_ids = km(self.data) domain = self.data.domain attributes, classes = domain.attributes, domain.class_vars meta_attrs = domain.metas if self.place_cluster_ids == self.OUTPUT_CLASS: if classes: meta_attrs += classes classes = [clust_var] elif self.place_cluster_ids == self.OUTPUT_ATTRIBUTE: attributes += (clust_var, ) else: meta_attrs += (clust_var, ) domain = Domain(attributes, classes, meta_attrs) new_table = Table.from_table(domain, self.data) new_table.get_column_view(clust_var)[0][:] = clust_ids.X.ravel() centroids = Table(Domain(km.pre_domain.attributes), km.centroids) self.send("Annotated Data", new_table) self.send("Centroids", centroids) @check_sql_input def set_data(self, data): self.data = data if data is None: self.table_model.setRowCount(0) else: self.data = data self.run() def send_report(self): self.report_items(( ("Number of clusters", self.optimization_runs[self.selected_row()][1].k if self.optimize_k else self.k), ("Optimization", self.optimize_k != 0 and "{}, {} re-runs limited to {} steps".format( self.INIT_METHODS[self.smart_init].lower(), self.n_init, self.max_iterations)), ("Cluster ID in output", self.append_cluster_ids and "'{}' (as {})".format( self.output_name, self.OUTPUT_METHODS[self.place_cluster_ids].lower())) )) if self.data: self.report_data("Data", self.data) if self.optimize_k: self.report_table( "Scoring by {}".format(self.SCORING_METHODS[self.scoring][0] ), self.table_view)
class ClusterWidget(QSplitter): def __init__(self, peaks, parent=None): QSplitter.__init__(self, Qt.Vertical, parent) self.peaks = peaks self.choosenOne = [pe for pe in self.peaks if pe is not None][0] #self.peakModel = QStandardItemModel() self.identificationModel = QStandardItemModel() self.setupUi() self.setModel() self.connect(self.calcCorr, SIGNAL('pressed()'), self.setRankValue) #self.setRankValue() def setupUi(self): self.widget = MSView( MSQtCanvas(self.peaks, "peaks@%s" % str(self.peaks[0]), labels={ 'bottom': 'RT(s)', 'left': 'INTENSITY' }, flags='peak')) self.tableView = QTableView() self.tableView.horizontalHeader().setStretchLastSection(True) self.tableView.setSortingEnabled(True) self.corr = QLabel("Nan") self.calcCorr = QPushButton("r_coef:") #v = QVBoxLayout(self) self.addWidget(self.widget) self.wid = QWidget() vb = QVBoxLayout() vb.addWidget(self.calcCorr) vb.addWidget(self.corr) hb = QHBoxLayout(self.wid) #if self.choosenOne.formulas: hb.addWidget(self.tableView) #else: # hb.addWidget(QLabel("Identification not performed yet...")) hb.addLayout(vb) self.addWidget(self.wid) def setModel(self): from gui.MetBaseGui import MSStandardItem #we assume that the different peaks have the same identifiers #TODO: may have to merge several stuffs later if self.choosenOne.formulas: self.identificationModel.setHorizontalHeaderLabels( ["score", "formula", "diff mass", "names"]) for i, f in enumerate(self.choosenOne.formulas.iterkeys()): self.identificationModel.setItem( i, 0, MSStandardItem(str(self.choosenOne.formulas[f]["score"]))) self.identificationModel.setItem(i, 1, QStandardItem(str(f))) self.identificationModel.setItem( i, 2, MSStandardItem(str( self.choosenOne.formulas[f]["diffmass"]))) self.identificationModel.setItem( i, 3, QStandardItem(self.choosenOne.formulas[f]["names"])) if self.choosenOne.formulas[f]["names"] != 'Not Found': for j in xrange(4): self.identificationModel.item(i, j).setBackground( QBrush(Qt.green)) else: for j in xrange(4): self.identificationModel.item(i, j).setBackground( QBrush(Qt.red)) self.tableView.setModel(self.identificationModel) def setRankValue(self): #m = qApp.instance().model #m.pearsonIntraCalculation() #peaks =[] #for spl in m: # peaks+=[p.r_coef for p in spl.mappedPeaks if p.r_coef] #if not self.choosenOne.r_coef: self.choosenOne.pCalcBasedOnPeakShape() #from _bisect import bisect_left #x = bisect_left(sorted(peaks), self.choosenOne.r_coef) s = '<br><b>%f</b></br>' % np.round(self.choosenOne.r_coef, 4) #s+='<br><b>Rank: </b>%d</br>'%abs(len(peaks)-x) self.corr.setText(s)
class dbmanagerUI(QMainWindow, ui_dbmanager.Ui_dbmanagerUI): """Main UI for MASAR database manager.""" def __init__(self): """""" super(dbmanagerUI, self).__init__() self.setupUi(self) self.statusbar.showMessage("Ready") exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit Masar Configuration Manager.') exitAction.triggered.connect(QtGui.qApp.quit) self.groupdatabasemenubar() #default database source, could be 0: SQLite, 1: MongoDB, and 2: MySQL self.dbsource = None self.defaultdbinfo = self._loadmasarconfig() self.usedefaultdb = True self.comboxboxSignalMapper = QtCore.QSignalMapper(self) self.comboxboxSignalMapper.mapped[QtGui.QWidget].connect(self.comboboxSignalMapperMapped) self.pushbuttonSignalMapper = QtCore.QSignalMapper(self) self.pushbuttonSignalMapper.mapped[QtGui.QWidget].connect(self.pushbuttonSignalMapperMapped) self.showpvbuttonSignalMapper = QtCore.QSignalMapper(self) self.showpvbuttonSignalMapper.mapped[QtGui.QWidget].connect(self.showpvbuttonSignalMapperMapped) self.choosepvbuttonSignalMapper = QtCore.QSignalMapper(self) self.choosepvbuttonSignalMapper.mapped[QtGui.QWidget].connect(self.choosepvbuttonSignalMapperMapped) self.currentselectedrow4config = -1 self.selectedsystem = "Others" # self.pvgrouptreeview = QTreeView() self.pvGroupTreeView.setSelectionBehavior(QAbstractItemView.SelectRows) self.pvgroupmodel = QStandardItemModel() # self.pvgroupmodel.setHorizontalHeaderLabels(['id', 'date', 'version', "description"]) self.pvgroupmodel.setHorizontalHeaderLabels(["PV Groups"]) self.pvGroupTreeView.setModel(self.pvgroupmodel) self.pvGroupTreeView.setUniformRowHeights(True) @QtCore.pyqtSlot(QtGui.QWidget) def comboboxSignalMapperMapped(self, comboBox): if self.masarConfigTableWidget.cellWidget(comboBox.row, comboBox.column + 1).isEnabled(): self.masarConfigTableWidget.cellWidget(comboBox.row, comboBox.column + 1).setEnabled(False) button = self.masarConfigTableWidget.cellWidget(comboBox.row, comboBox.column + 1) palette = QtGui.QPalette(button.palette()) # make a copy of the palette palette.setColor(QtGui.QPalette.ButtonText, QtGui.QColor('grey')) button.setPalette(palette) else: self.masarConfigTableWidget.cellWidget(comboBox.row, comboBox.column + 1).setEnabled(True) button = self.masarConfigTableWidget.cellWidget(comboBox.row, comboBox.column + 1) palette = QtGui.QPalette(button.palette()) # make a copy of the palette palette.setColor(QtGui.QPalette.ButtonText, QtGui.QColor('red')) button.setPalette(palette) @QtCore.pyqtSlot(QtGui.QWidget) def pushbuttonSignalMapperMapped(self, pushbutton): configstatus = str(self.masarConfigTableWidget.cellWidget(pushbutton.row, pushbutton.column-1).currentText()) cid = str(self.masarConfigTableWidget.item(pushbutton.row, 0).text()) cname = str(self.masarConfigTableWidget.item(pushbutton.row, 1).text()) if self.updatemasarconfigstatus(configstatus, cid, configname=cname): palette = QtGui.QPalette(pushbutton.palette()) # make a copy of the palette palette.setColor(QtGui.QPalette.ButtonText, QtGui.QColor('grey')) pushbutton.setPalette(palette) pushbutton.setEnabled(False) @QtCore.pyqtSlot(QtGui.QWidget) def showpvbuttonSignalMapperMapped(self, showpvbutton): if self.newConfigTableWidget.item(showpvbutton.row, showpvbutton.column + 2) is None: raise RuntimeError("Unknown pv file") pvfilename = self.newConfigTableWidget.item(showpvbutton.row, showpvbutton.column + 2).text() if not os.path.isfile(pvfilename): raise RuntimeError("Invalid pv file name for (row, col): (%s, %s)" % (showpvbutton.row, showpvbutton.column + 2)) text = ", ".join(np.loadtxt(str(pvfilename), dtype=str, comments="#")) if self.newConfigTableWidget.item(showpvbutton.row, 0) is not None: head = self.newConfigTableWidget.item(showpvbutton.row, 0).text() else: head = "" msg = QMessageBox(self, windowTitle='PVs for group %s' % head, text="The following PVs to be added:") msg.setDetailedText(text) msg.exec_() @QtCore.pyqtSlot(QtGui.QWidget) def choosepvbuttonSignalMapperMapped(self, chhosepvbutton): self.newConfigTableWidget.setItem(chhosepvbutton.row, chhosepvbutton.column+1, QTableWidgetItem(QFileDialog.getOpenFileName(self, "Open File"))) def _loadmasarconfig(self): cf = ConfigParser.SafeConfigParser() cf.read([ os.path.expanduser('~/.masarservice.conf'), '/etc/masarservice.conf', 'masarservice.conf', "%s/masarservice.conf" % os.path.abspath(os.path.dirname(__file__)) ]) return cf def groupdatabasemenubar(self): """Group 3 Databases menu together to make selection exclusive.""" group = QtGui.QActionGroup(self) self.actionSQLite.setActionGroup(group) self.actionMongoDB.setActionGroup(group) self.actionMySQL.setActionGroup(group) def actionsqlitemenu(self): """Answer action when SQLite is selected.""" if self.actionSQLite.isChecked(): self.dbsource = 0 self.defaultsqlitedb() self.listPvGroupPushButton.setEnabled(True) def actionmongodbmenu(self): """Answer action when MongoDB is selected.""" if self.actionMongoDB.isChecked(): self.dbsource = 1 self.defaultmongodb() self.listPvGroupPushButton.setEnabled(False) def actionmysqlmenu(self): """Answer action when MySQL is selected.""" if self.actionMySQL.isChecked(): QMessageBox.warning(self, 'Warning', "MySQL support not implemented yet.") self.actionMySQL.setChecked(False) if self.dbsource == 0: self.actionSQLite.setChecked(True) elif self.dbsource == 1: self.actionMongoDB.setChecked(True) def showdefaultdbinfo(self): """""" if self.dbsource == 0: self.defaultsqlitedb() elif self.dbsource == 1: self.defaultmongodb() elif self.dbsource == 2: QMessageBox.warning(self, 'Warning', "MySQL support not implemented yet.") def defaultsqlitedb(self): """""" if self.defaultdbinfo.has_section("sqlite"): self.databaseDefault.setText(self.defaultdbinfo.get("sqlite", "database")) self.hostDefault.clear() self.portDefault.clear() self.userDefault.clear() def defaultmongodb(self): """""" if self.defaultdbinfo.has_section("mongodb"): self.databaseDefault.setText(self.defaultdbinfo.get("mongodb", "database")) self.hostDefault.setText(self.defaultdbinfo.get("mongodb", "host")) self.portDefault.setText(self.defaultdbinfo.get("mongodb", "port")) self.userDefault.setText(self.defaultdbinfo.get("mongodb", "username")) def getdatabasename(self): """""" self.database = self.databaseLineEdit.text() def getdatabaseport(self): """""" self.databaseport = self.databaseportLineEdit.text() def getdatabasehost(self): """""" self.databasehost = self.databaseHostLineEdit.text() def getdatabasepw(self): """""" self.databasepw = self.databasePwLineEdit.text() def showmasarconfigs(self): """""" result = None if self.dbsource == 0: # get data from sqlite if self.usedefaultdb: # masardb = str(self.databaseDefault.text()) masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: raise RuntimeError("Cannot find MASAR SQLite Database") import pymasarsqlite conn = pymasarsqlite.utils.connect() result = pymasarsqlite.service.retrieveServiceConfigs(conn, servicename="masar") pymasarsqlite.utils.close(conn) elif self.dbsource == 1: # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo mongoconn, collection = pymasarmongo.db.utils.conn(host=host, port=port, db=database) resultdict = pymasarmongo.pymasarmongo.pymasar.retrieveconfig(mongoconn, collection) pymasarmongo.db.utils.close(mongoconn) result = [['id', 'name', 'desc', 'date', 'version', 'status']] for res in resultdict: result.append([res['configidx'], res['name'], res['desc'], res['created_on'], res['version'], res['status']]) # res['system'] if result is not None: self._setconfigtable(result) def choosedbsrc(self, bool): """Choose DB source""" if bool: self.usedefaultdb = True else: self.usedefaultdb = False def _setconfigtable(self, content): """""" # head = self.masarConfigTableWidget.horizontalHeader() self.masarConfigTableWidget.clearContents() # self.masarConfigTableWidget.setHorizontalHeaderLabels(head) if len(content) > 1: self.masarConfigTableWidget.setRowCount(len(content)-1) n = 0 data = sorted(content[1:], key=itemgetter(0), reverse=True) for res in data: m = 0 for item in res: if not isinstance(item, basestring): item = str(item) if item: if m == 5: newitem = QtGui.QComboBox() newitem.addItem("active") newitem.addItem("inactive") if item == "active": newitem.setCurrentIndex(0) else: newitem.setCurrentIndex(1) newitem.row = n newitem.column = m self.masarConfigTableWidget.setCellWidget(n, m, newitem) self.comboxboxSignalMapper.setMapping(newitem, newitem) newitem.currentIndexChanged.connect(self.comboxboxSignalMapper.map) updatebutton = QtGui.QPushButton() updatebutton.setText("Update") updatebutton.setEnabled(False) updatebutton.row = n updatebutton.column = m+1 self.pushbuttonSignalMapper.setMapping(updatebutton, updatebutton) self.masarConfigTableWidget.setCellWidget(n, m+1, updatebutton) updatebutton.clicked.connect(self.pushbuttonSignalMapper.map) else: newitem = QTableWidgetItem(item) newitem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) self.masarConfigTableWidget.setItem(n, m, newitem) m += 1 n += 1 self.masarConfigTableWidget.resizeColumnsToContents() def updatemasarconfigstatus(self, configstatus, cid, configname=None): if self.dbsource == 0: # get data from sqlite if self.usedefaultdb: masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: raise RuntimeError("Cannot find MASAR SQLite Database") import pymasarsqlite conn = pymasarsqlite.utils.connect() pymasarsqlite.service.updateServiceConfigStatus(conn, cid, status=configstatus) pymasarsqlite.utils.save(conn) pymasarsqlite.utils.close(conn) elif self.dbsource == 1: # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo mongoconn, collection = pymasarmongo.db.utils.conn(host=host, port=port, db=database) pymasarmongo.pymasarmongo.pymasar.updateconfig(mongoconn, collection, configname, configidx=int(cid), status=configstatus) pymasarmongo.db.utils.close(mongoconn) return True def addnewpvgrouprow(self): """Add a new row to add pv group to MASAR configuration""" print ("""Add a new row to add pv group to MASAR configuration""") currowcount = self.newConfigTableWidget.rowCount() self.newConfigTableWidget.setRowCount(currowcount + 1) showpvbutton = QtGui.QPushButton() showpvbutton.setText("Show PVs") showpvbutton.setEnabled(True) showpvbutton.row = currowcount showpvbutton.column = 2 self.showpvbuttonSignalMapper.setMapping(showpvbutton, showpvbutton) self.newConfigTableWidget.setCellWidget(currowcount, showpvbutton.column, showpvbutton) showpvbutton.clicked.connect(self.showpvbuttonSignalMapper.map) choosepvbutton = QtGui.QPushButton() choosepvbutton.setText("PV File") choosepvbutton.setEnabled(True) choosepvbutton.row = currowcount choosepvbutton.column = 3 self.choosepvbuttonSignalMapper.setMapping(choosepvbutton, choosepvbutton) self.newConfigTableWidget.setCellWidget(currowcount, choosepvbutton.column, choosepvbutton) choosepvbutton.clicked.connect(self.choosepvbuttonSignalMapper.map) def removepvgrouprow(self): """Remove selected pv group from the configuration to be added into MASAR database""" if self.currentselectedrow4config == -1: raise RuntimeError("No pv group selected.") rownametobedelete = self.newConfigTableWidget.item(self.currentselectedrow4config, 0) if rownametobedelete is not None: rownametobedelete = rownametobedelete.text() self.newConfigTableWidget.removeRow(self.currentselectedrow4config) if rownametobedelete is not None: print ("Successfully delete pv group: ", rownametobedelete) else: print ("Successfully delete row: ", self.currentselectedrow4config) self.currentselectedrow4config = -1 def savemasarsqlite(self): """""" # get data from sqlite if self.usedefaultdb: masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: QMessageBox.warning(self, "Warning", "Cannot find MASAR SQLite Database") return import pymasarsqlite conn = pymasarsqlite.utils.connect() existedresult = pymasarsqlite.service.retrieveServiceConfigs(conn, servicename="masar") newcfgdata = self._getnewconfigurationdata(existedresult) if newcfgdata is None: QMessageBox.warning(self, "Warning", "Not enough information for a new configuration.") return newcfgname = newcfgdata[0] desc = newcfgdata[1] msystem = newcfgdata[2] # config data format: [[name], [desc], [pv files]] cfgdata = newcfgdata[3] if newcfgname is None or msystem is None or newcfgdata is None: # Nothing to be added. QMessageBox.warning(self, "Warning", "No name or system is given, or empty configuration data.") return for i in range(len(cfgdata[0])): if cfgdata[0][i] is None: QMessageBox.warning(self, "Warning", "Wrong PV group name") return if cfgdata[2][i] is not None and os.path.isfile(cfgdata[2][i]): pvs = list(np.loadtxt(cfgdata[2][i], dtype=str, comments="#")) if len(pvs) > 0: for j, pv in enumerate(pvs): pvs[j] = pv.strip() pymasarsqlite.pvgroup.savePvGroup(conn, cfgdata[0][i], func=cfgdata[1][i]) pymasarsqlite.pvgroup.saveGroupPvs(conn, cfgdata[0][i], pvs) try: pymasarsqlite.service.saveServiceConfig(conn, "masar", newcfgname, configdesc=desc, system=msystem) pymasarsqlite.service.saveServicePvGroup(conn, newcfgname, cfgdata[0]) except Exception as e: QMessageBox.warning(self, "Error", e.message) return pymasarsqlite.utils.save(conn) QMessageBox.information(self, "Congratulation", "A new configuration has been added successfully.") pymasarsqlite.utils.close(conn) def savemasarmongodb(self): """""" # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo mongoconn, collection = pymasarmongo.db.utils.conn(host=host, port=port, db=database) existedresult = pymasarmongo.pymasarmongo.pymasar.retrieveconfig(mongoconn, collection) existedcfg = [] for res in existedresult: existedcfg.append([res['configidx'], res['name'], res['desc'], res['created_on'], res['version'], res['status']]) newcfgdata = self._getnewconfigurationdata(existedcfg) if newcfgdata is None: # Nothing to be added. raise ValueError("Empty configuration.") newcfgname = newcfgdata[0] desc = newcfgdata[1] msystem = newcfgdata[2] # config data format: [[name], [desc], [pv files]] cfgdata = newcfgdata[3] pvs = [] for pvf in cfgdata[2]: if pvf is not None and os.path.isfile(pvf): pvs += list(np.loadtxt(pvf, dtype=str, comments="#")) if pvs: for i, pv in enumerate(pvs): pvs[i] = pv.strip() pymasarmongo.pymasarmongo.pymasar.saveconfig(mongoconn, collection, newcfgname, desc=desc, system=msystem, pvlist={"names": pvs}) QMessageBox.information(self, "Congratulation", "A new configuration has been added successfully.") else: QMessageBox.warning(self, "Warning", "No PVs available for the new configuration.") pymasarmongo.db.utils.close(mongoconn) def submitmasarconfig(self): """submit a new configuration to MASAR database""" if self.dbsource is None: QMessageBox.warning(self, "Warning", "Unknown database source.\nPlease select which database should be use.") return if self.dbsource == 0: self.savemasarsqlite() elif self.dbsource == 1: self.savemasarmongodb() def _getnewconfigurationdata(self, existedresult): """""" newcfgname = self.newConfigurationLineEdit.text() if newcfgname is None or str(newcfgname) == "": QMessageBox.warning(self, "Warning", "Name of configuration is empty.") return None elif str(newcfgname) in np.array(existedresult)[:, 1]: QMessageBox.warning(self, "Warning", "Configuration (%s) exists already." % str(newcfgname)) return None else: newcfgname = str(newcfgname) desc = self.newConfigurationDescription.text() if str(desc) == "": desc = None else: desc = str(desc) msystem = str(self.systemComboBox.currentText()) if msystem == "Others": msystem = self.systemLineEdit.text() if msystem is None or str(msystem) == "": QMessageBox.warning(self, "Warning", "System for configuration (%s) not specified yet." % str(newcfgname)) return None else: msystem = str(msystem) pvgroups = self.newConfigTableWidget.rowCount() if pvgroups == 0: QMessageBox.warning(self, "Warning", "No PV founded for new configuration (%s)." % str(newcfgname)) return None pvgroupnames = [] pvgroupdescs = [] pvgroupfiles = [] for count in range(pvgroups): # Collect PV group name information if self.newConfigTableWidget.item(count, 0) is not None and str(self.newConfigTableWidget.item(count, 0).text()) != "": pvgname = str(self.newConfigTableWidget.item(count, 0).text()) if pvgname in pvgroupnames: QMessageBox.warning(self, "Warning", "Duplicated pv group name: %s." % str(pvgname)) return None pvgroupnames.append(pvgname) elif self.newConfigTableWidget.item(count, 4) is None or str(self.newConfigTableWidget.item(count, 4)) == "": continue elif self.dbsource == 1: pvgroupnames.append(None) else: QMessageBox.warning(self, "Warning", "Empty pv group name.") return None # reply = QMessageBox.question(self, "Message", # "pv group name not specified for row {}.\nContinue?".format(count), # QMessageBox.Yes | QMessageBox.No, QMessageBox.No) # if reply == QMessageBox.Yes: # pvgroupnames.append(None) # else: # return None # Collection PV group descriptions if self.newConfigTableWidget.item(count, 1) is not None: pvgroupdescs.append(str(self.newConfigTableWidget.item(count, 1).text())) else: pvgroupdescs.append(None) # PV files for the pv group. if self.newConfigTableWidget.item(count, 4) is not None: pvgroupfiles.append(str(self.newConfigTableWidget.item(count, 4).text())) else: pvgroupfiles.append(None) if pvgroupfiles: return newcfgname, desc, msystem, [pvgroupnames, pvgroupdescs, pvgroupfiles] else: return None def currentselectedrow(self, row, col): """Cache current selected row in MASAR configuration Table Widget.""" self.currentselectedrow4config = row def updateselectedsystem(self, system): """Update selected system if value changed""" self.selectedsystem = str(system) def updatesystemcombobox(self): """Update selected system if value changed""" self.systemComboBox.clear() if self.dbsource == 0: # get data from sqlite if self.usedefaultdb: # masardb = str(self.databaseDefault.text()) masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: raise RuntimeError("Cannot find MASAR SQLite Database") import pymasarsqlite conn = pymasarsqlite.utils.connect() result = pymasarsqlite.service.retrieveServiceConfigProps(conn, propname="system", servicename="masar") index = 0 if len(result) > 1: res = sorted(set(list(np.array(result[1:])[:, 3]))) #for res in result[1:]: self.systemComboBox.addItems(res) index = len(res) self.systemComboBox.addItem("Others") self.systemComboBox.setCurrentIndex(index) pymasarsqlite.utils.close(conn) elif self.dbsource == 1: # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo mongoconn, collection = pymasarmongo.db.utils.conn(host=host, port=port, db=database) result = pymasarmongo.pymasarmongo.pymasar.retrieveconfig(mongoconn, collection) pymasarmongo.db.utils.close(mongoconn) results = [] for res in result: if res["system"] not in results: results.append(res["system"]) res = sorted(set(results)) self.systemComboBox.addItems(res) index = len(res) self.systemComboBox.addItem("Others") self.systemComboBox.setCurrentIndex(index) def listpvgroups(self): """""" self.pvgroupmodel.clear() self.pvgroupmodel.setHorizontalHeaderLabels(["PV Groups"]) if self.dbsource == 0: # get data from sqlite if self.usedefaultdb: # masardb = str(self.databaseDefault.text()) masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: raise RuntimeError("Cannot find MASAR SQLite Database") import pymasarsqlite conn = pymasarsqlite.utils.connect() result = pymasarsqlite.pvgroup.retrievePvGroups(conn) if len(result) > 0: result = sorted(result, key=itemgetter(0), reverse=True) for res in result: parent1 = QStandardItem(res[1]) child1 = QStandardItem('id: {}'.format(res[0])) child2 = QStandardItem('description: {}'.format(res[2])) child3 = QStandardItem('date: {}'.format(res[3])) child4 = QStandardItem('version: {}'.format(res[4])) parent1.appendColumn([child1, child2, child3, child4]) self.pvgroupmodel.appendRow(parent1) selmod = self.pvGroupTreeView.selectionModel() index2 = self.pvgroupmodel.indexFromItem(child3) selmod.select(index2, QItemSelectionModel.Select | QItemSelectionModel.Rows) pymasarsqlite.utils.close(conn) self.pvGroupTreeView.setContextMenuPolicy(Qt.CustomContextMenu) self.pvGroupTreeView.clicked.connect(self.showpvsinpvgroup) # self.connect(self.pvGroupTreeView, # QtCore.SIGNAL("clicked(QModelIndex)"), # #QtCore.SIGNAL("customContextMenuRequested(const QPoint &)"), # self.doMenu) elif self.dbsource == 1: # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo def showpvsinpvgroup(self, point): if point.model().itemFromIndex(point).child(0) is None: return reply = QMessageBox.question(self, 'Message', "show all pvs belong to group {} ?".format(point.model(). itemFromIndex(point). text()), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: pvgroupidx = int(str(point.model().itemFromIndex(point).child(0).text().split(":")[1]).strip()) # msg = QMessageBox(self) msg = ShowPvMessageBox() msg.setWindowTitle('PVs for group {}'.format(point.model().itemFromIndex(point).text())) msg.setText("Click show details to see all pvs.") # windowTitle = 'PVs for group {}'.format(point.model().itemFromIndex(point).text()) if self.dbsource == 0: # get data from sqlite if self.usedefaultdb: # masardb = str(self.databaseDefault.text()) masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: raise RuntimeError("Cannot find MASAR SQLite Database") import pymasarsqlite conn = pymasarsqlite.utils.connect() result = pymasarsqlite.pvgroup.retrieveGroupPvs(conn, pvgroupidx) text = "\n".join(list(np.array(result)[:, 0])) msg.setDetailedText(text) msg.exec_() elif self.dbsource == 1: # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo
class OWTestLearners(widget.OWWidget): name = "Test Learners" description = "Cross-validation accuracy estimation." icon = "icons/TestLearners1.svg" priority = 100 inputs = [("Learner", Orange.classification.Learner, "set_learner", widget.Multiple), ("Data", Orange.data.Table, "set_train_data", widget.Default), ("Test Data", Orange.data.Table, "set_test_data")] outputs = [("Evaluation Results", Orange.evaluation.Results)] settingsHandler = settings.ClassValuesContextHandler() #: Resampling/testing types KFold, LeaveOneOut, Bootstrap, TestOnTrain, TestOnTest = 0, 1, 2, 3, 4 #: Selected resampling type resampling = settings.Setting(0) #: Number of folds for K-fold cross validation k_folds = settings.Setting(10) #: Number of repeats for bootstrap sampling n_repeat = settings.Setting(10) #: Bootstrap sampling p sample_p = settings.Setting(75) class_selection = settings.ContextSetting("(None)") def __init__(self, parent=None): super().__init__(parent) self.train_data = None self.test_data = None #: An Ordered dictionary with current inputs and their testing #: results. self.learners = OrderedDict() sbox = gui.widgetBox(self.controlArea, "Sampling") rbox = gui.radioButtons( sbox, self, "resampling", callback=self._param_changed ) gui.appendRadioButton(rbox, "Cross validation") ibox = gui.indentedBox(rbox) gui.spin(ibox, self, "k_folds", 2, 50, label="Number of folds:", callback=self.kfold_changed) gui.appendRadioButton(rbox, "Leave one out") gui.appendRadioButton(rbox, "Random sampling") ibox = gui.indentedBox(rbox) gui.spin(ibox, self, "n_repeat", 2, 50, label="Repeat train/test", callback=self.bootstrap_changed) gui.widgetLabel(ibox, "Relative training set size:") gui.hSlider(ibox, self, "sample_p", minValue=1, maxValue=100, ticks=20, vertical=False, labelFormat="%d %%", callback=self.bootstrap_changed) gui.appendRadioButton(rbox, "Test on train data") gui.appendRadioButton(rbox, "Test on test data") rbox.layout().addSpacing(5) gui.button(rbox, self, "Apply", callback=self.apply) self.cbox = gui.widgetBox(self.controlArea, "Target class") self.class_selection_combo = gui.comboBox(self.cbox, self, "class_selection", items=[], callback=self._select_class, sendSelectedValue=True, valueType=str) gui.rubber(self.controlArea) self.view = QTreeView( rootIsDecorated=False, uniformRowHeights=True, wordWrap=True, editTriggers=QTreeView.NoEditTriggers ) header = self.view.header() header.setResizeMode(QHeaderView.ResizeToContents) header.setDefaultAlignment(Qt.AlignCenter) header.setStretchLastSection(False) self.result_model = QStandardItemModel() self.view.setModel(self.result_model) self.view.setItemDelegate(ItemDelegate()) self._update_header() box = gui.widgetBox(self.mainArea, "Evaluation Results") box.layout().addWidget(self.view) def set_learner(self, learner, key): if key in self.learners and learner is None: del self.learners[key] else: self.learners[key] = Input(learner, None, ()) self._update_stats_model() def set_train_data(self, data): self.error(0) if data and not data.domain.class_var: self.error(0, "Train data input requires a class variable") data = None self.train_data = data self.closeContext() if data is not None: self.openContext(data.domain.class_var) self._update_header() self._update_class_selection() self._invalidate() def set_test_data(self, data): self.error(1) if data and not data.domain.class_var: self.error(1, "Test data input requires a class variable") data = None self.test_data = data if self.resampling == OWTestLearners.TestOnTest: self._invalidate() def handleNewSignals(self): self.update_results() self.commit() def kfold_changed(self): self.resampling = OWTestLearners.KFold self._param_changed() def bootstrap_changed(self): self.resampling = OWTestLearners.Bootstrap self._param_changed() def _param_changed(self): self._invalidate() def update_results(self): self.warning([1, 2]) self.error(2) if self.train_data is None: return if self.resampling == OWTestLearners.TestOnTest: if self.test_data is None: self.warning(2, "Missing separate test data input") return elif self.test_data.domain.class_var != \ self.train_data.domain.class_var: self.error(2, ("Inconsistent class variable between test " + "and train data sets")) return # items in need of an update items = [(key, input) for key, input in self.learners.items() if input.results is None] learners = [input.learner for _, input in items] self.setStatusMessage("Running") if self.test_data is not None and \ self.resampling != OWTestLearners.TestOnTest: self.warning(1, "Test data is present but unused. " "Select 'Test on test data' to use it.") # TODO: Test each learner individually try: if self.resampling == OWTestLearners.KFold: results = Orange.evaluation.CrossValidation( self.train_data, learners, k=self.k_folds, store_data=True ) elif self.resampling == OWTestLearners.LeaveOneOut: results = Orange.evaluation.LeaveOneOut( self.train_data, learners, store_data=True ) elif self.resampling == OWTestLearners.Bootstrap: p = self.sample_p / 100.0 results = Orange.evaluation.Bootstrap( self.train_data, learners, n_resamples=self.n_repeat, p=p, store_data=True ) elif self.resampling == OWTestLearners.TestOnTrain: results = Orange.evaluation.TestOnTrainingData( self.train_data, learners, store_data=True ) elif self.resampling == OWTestLearners.TestOnTest: if self.test_data is None: return results = Orange.evaluation.TestOnTestData( self.train_data, self.test_data, learners, store_data=True ) else: assert False except Exception as e: self.error(2, str(e)) return self.results = results results = list(split_by_model(results)) class_var = self.train_data.domain.class_var if class_var.is_discrete: stats = [classification_stats(self.one_vs_rest(res)) for res in results] else: stats = [regression_stats(res) for res in results] self._update_header() for (key, input), res, stat in zip(items, results, stats): self.learners[key] = input._replace(results=res, stats=stat) self.setStatusMessage("") self._update_stats_model() def _update_header(self): headers = ["Method"] if self.train_data is not None: if self.train_data.domain.class_var.is_discrete: headers.extend(classification_stats.headers) else: headers.extend(regression_stats.headers) for i in reversed(range(len(headers), self.result_model.columnCount())): self.result_model.takeColumn(i) self.result_model.setHorizontalHeaderLabels(headers) def _update_stats_model(self): model = self.view.model() for r in reversed(range(model.rowCount())): model.takeRow(r) for input in self.learners.values(): name = learner_name(input.learner) row = [] head = QStandardItem() head.setData(name, Qt.DisplayRole) row.append(head) for stat in input.stats: item = QStandardItem() item.setData(" {:.3f} ".format(stat[0]), Qt.DisplayRole) row.append(item) model.appendRow(row) def _update_class_selection(self): self.class_selection_combo.clear() if not self.train_data: return if self.train_data.domain.class_var.is_discrete: self.cbox.setVisible(True) values = self.train_data.domain.class_var.values self.class_selection_combo.addItem("(None)") self.class_selection_combo.addItems(values) class_index = 0 if self.class_selection in self.train_data.domain.class_var.values: class_index = self.train_data.domain.class_var.values.index(self.class_selection)+1 else: self.class_selection = '(None)' self.class_selection_combo.setCurrentIndex(class_index) self.previous_class_selection = "(None)" else: self.cbox.setVisible(False) def one_vs_rest(self, res): if self.class_selection != '(None)' and self.class_selection != 0: class_ = self.train_data.domain.class_var.values.index(self.class_selection) actual = res.actual == class_ predicted = res.predicted == class_ return Results( nmethods=1, domain=self.train_data.domain, actual=actual, predicted=predicted) else: return res def _select_class(self): if self.previous_class_selection == self.class_selection: return results = list(split_by_model(self.results)) items = [(key, input) for key, input in self.learners.items()] learners = [input.learner for _, input in items] class_var = self.train_data.domain.class_var if class_var.is_discrete: stats = [classification_stats(self.one_vs_rest(res)) for res in results] else: stats = [regression_stats(res) for res in results] for (key, input), res, stat in zip(items, results, stats): self.learners[key] = input._replace(results=res, stats=stat) self.setStatusMessage("") self._update_stats_model() self.previous_class_selection = self.class_selection def _invalidate(self, which=None): if which is None: which = self.learners.keys() all_keys = list(self.learners.keys()) model = self.view.model() for key in which: self.learners[key] = \ self.learners[key]._replace(results=None, stats=None) if key in self.learners: row = all_keys.index(key) for c in range(1, model.columnCount()): item = model.item(row, c) if item is not None: item.setData(None, Qt.DisplayRole) def apply(self): self.update_results() self.commit() def commit(self): results = [val.results for val in self.learners.values() if val.results is not None] if results: combined = results_merge(results) combined.learner_names = [learner_name(val.learner) for val in self.learners.values()] else: combined = None self.send("Evaluation Results", combined)
def __init__(self, parent=None): super(LayerSelectionPage, self).__init__(parent) self.parent = parent #convenience link self.confconn_link = self.parent.parent.confconn #flag top prevent read read action on keyword delete. New logic makes this redundant #self.keywordbypass = False QToolTip.setFont(QFont('SansSerif', 10)) #label filterlabel = QLabel('Filter') availablelabel = QLabel('Available Layers') selectionlabel = QLabel('Layer Selections') keywordlabel = QLabel('Keyword') explainlabel = QLabel("Edit Group assignments using this dialog or to simply initialise the Layer-Config just click 'Finish'") #selection buttons chooseallbutton = QPushButton('>>') chooseallbutton.setFixedWidth(self.XFER_BW) chooseallbutton.clicked.connect(self.doChooseAllClickAction) choosebutton = QPushButton('>') choosebutton.setFixedWidth(self.XFER_BW) choosebutton.clicked.connect(self.doChooseClickAction) rejectbutton = QPushButton('<') rejectbutton.setFixedWidth(self.XFER_BW) rejectbutton.clicked.connect(self.doRejectClickAction) rejectallbutton = QPushButton('<<') rejectallbutton.setFixedWidth(self.XFER_BW) rejectallbutton.clicked.connect(self.doRejectAllClickAction) #operation buttons finishbutton = QPushButton('Finish') finishbutton.setToolTip('Finish and Close layer selection dialog') finishbutton.clicked.connect(self.parent.close) resetbutton = QPushButton('Reset') resetbutton.font() resetbutton.setToolTip('Read Layer from LDS GetCapabilities request. Overwrites current Layer Config') resetbutton.clicked.connect(self.doResetClickAction) self.available_sfpm = LDSSFPAvailableModel(self) self.selection_sfpm = LDSSFPSelectionModel(self) self.available_sfpm.setSourceModel(self.parent.available_model) self.selection_sfpm.setSourceModel(self.parent.selection_model) #textedits filteredit = QLineEdit('') filteredit.setToolTip('Filter Available-Layers pane (filter operates across Name and Title fields and accepts Regex expressions)') filteredit.textChanged.connect(self.available_sfpm.setActiveFilter) self.keywordcombo = QComboBox() self.keywordcombo.setToolTip('Select or Add a unique identifier to be saved in layer config (keyword)') self.keywordcombo.addItems(list(self.confconn_link.assigned)) self.keywordcombo.setEditable(True) self.keywordcombo.activated.connect(self.doKeyComboChangeAction) lgindex = self.confconn_link.getLayerGroupIndex(self.confconn_link.lgval,col=1) lgentry = self.confconn_link.lglist[lgindex] if LU.assessNone(lgindex) else None #keywordedit = self.keywordcombo.lineEdit().text().toUtf8().data().decode('utf8')# for writing #if no entry or layer indicated then blank self.keywordcombo.lineEdit().setText('' if lgentry is None or lgentry[0]==LORG.LAYER else lgentry[1])#self.confconn_link.lgval)#TODO. group only #header headmodel = QStandardItemModel() headmodel.setHorizontalHeaderLabels([i[2] for i in self.colparams][:self.parent.available_model.columnCount()]) headview1 = QHeaderView(Qt.Horizontal) headview1.setModel(headmodel) headview1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) headview2 = QHeaderView(Qt.Horizontal) headview2.setModel(headmodel) headview2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) #table self.available = QTableView() self.available.setSelectionBehavior(QAbstractItemView.SelectRows) self.available.setSelectionMode(QAbstractItemView.MultiSelection) self.selection = QTableView() self.selection.setSelectionBehavior(QAbstractItemView.SelectRows) self.selection.setSelectionMode(QAbstractItemView.MultiSelection) #interesting, must set model after selection attributes but before headers else row selections/headers don't work properly self.available.setModel(self.available_sfpm) self.selection.setModel(self.selection_sfpm) self.available.setSortingEnabled(True) self.available.setHorizontalHeader(headview1) self.selection.setSortingEnabled(True) self.selection.setHorizontalHeader(headview2) for cp in self.colparams: self.available.setColumnWidth(cp[0],cp[1]) self.selection.setColumnWidth(cp[0],cp[1]) self.available.verticalHeader().setVisible(False) self.available.horizontalHeader().setVisible(True) self.selection.verticalHeader().setVisible(False) self.selection.horizontalHeader().setVisible(True) #layout vbox00 = QVBoxLayout() vbox00.addWidget(availablelabel) vbox00.addWidget(self.available) vbox01 = QVBoxLayout() vbox01.addWidget(chooseallbutton) vbox01.addWidget(choosebutton) vbox01.addWidget(rejectbutton) vbox01.addWidget(rejectallbutton) vbox02 = QVBoxLayout() vbox02.addWidget(selectionlabel) vbox02.addWidget(self.selection) vbox10 = QVBoxLayout() vbox10.addWidget(filterlabel) vbox10.addWidget(filteredit) hbox12 = QHBoxLayout() hbox12.addWidget(keywordlabel) hbox12.addStretch(1) #hbox12.addWidget(inspbutton) #hbox12.addWidget(addbutton) #hbox12.addWidget(delbutton) vbox12 = QVBoxLayout() vbox12.addLayout(hbox12) vbox12.addWidget(self.keywordcombo) #00|01|02 #10|11|12 grid0 = QGridLayout() grid0.addLayout(vbox00,1,0) grid0.addLayout(vbox01,1,1) grid0.addLayout(vbox02,1,2) grid0.addLayout(vbox10,0,0) grid0.addLayout(vbox12,0,2) hbox2 = QHBoxLayout() hbox2.addWidget(resetbutton) hbox2.addStretch(1) hbox2.addWidget(explainlabel) hbox2.addWidget(finishbutton) #gbox1.setLayout(hbox2) vbox3 = QVBoxLayout() vbox3.addLayout(grid0) #vbox3.addLayout(hbox3) #vbox3.addWidget(line0) vbox3.addLayout(hbox2) self.setLayout(vbox3)
class OWMPR(OWWidget): name = 'ModelMap Projection Rank' description = 'Ranking projections by estimating projection quality' icon = "icons/ModelMap.svg" inputs = [('Data', Table, 'set_data', Default)] outputs = [('Features', AttributeList)] want_main_area = False settingsHandler = DomainContextHandler() variable_changed = Signal() def __init__(self): super().__init__() self.data = None self.progress = None self.infoa = gui.widgetLabel(self.controlArea, "No data loaded.") self.projectionTable = QTableView() self.controlArea.layout().addWidget(self.projectionTable) self.projectionTable.setSelectionBehavior(QTableView.SelectRows) self.projectionTable.setSelectionMode(QTableView.SingleSelection) self.projectionTable.setSortingEnabled(True) self.projectionTableModel = QStandardItemModel(self) self.projectionTableModel.setHorizontalHeaderLabels(["P-Index", "", ""]) self.projectionTable.setModel(self.projectionTableModel) self.projectionTable.setColumnWidth(0, 90) self.projectionTable.sortByColumn(0, Qt.DescendingOrder) self.projectionTable.selectionModel().selectionChanged.connect(self.on_selection_changed) gui.button(self.controlArea, self, "Rank Projections", callback=self.rank, default=True) self.resize(370, 600) def set_data(self, data): self.data = data self.infoa.setText("Data set: {}".format(data.name) if self.data else "No data loaded.") def rank(self): if self.progress: return disc = Orange.preprocess.discretize.EqualWidth(n=10) ndomain = Orange.data.Domain( [disc(self.data, attr) if type(attr) == Orange.data.variable.ContinuousVariable else attr for attr in self.data.domain.attributes], self.data.domain.class_vars) t = self.data.from_table(ndomain, self.data) attrs = t.domain.attributes tables = {} l = 0 self.progress = gui.ProgressBar(self, len(attrs) * (len(attrs) - 1) / 2) for i in range(len(attrs)): for j in range(i): ct = np.array(contingency.get_contingency(t, attrs[j], attrs[i])) pindex, _, _ = p_index(ct) tables[i, j] = ct item = QStandardItem() item.setData(float(pindex), Qt.DisplayRole) self.projectionTableModel.setItem(l, 0, item) item = QStandardItem() item.setData(attrs[i].name, Qt.DisplayRole) self.projectionTableModel.setItem(l, 1, item) item = QStandardItem() item.setData(attrs[j].name, Qt.DisplayRole) self.projectionTableModel.setItem(l, 2, item) self.progress.advance() l += 1 self.progress.finish() self.progress = None def on_selection_changed(self, selected, deselected): """Called when the ranks view selection changes.""" a1 = selected.indexes()[1].data().replace('D_', '') a2 = selected.indexes()[2].data().replace('D_', '') d = self.data.domain self.send("Features", AttributeList([d[a1], d[a2]]))
class OWConfusionMatrix(widget.OWWidget): name = "Confusion Matrix" description = "Shows a confusion matrix." icon = "icons/ConfusionMatrix.svg" priority = 1001 inputs = [{"name": "Evaluation Results", "type": Orange.evaluation.testing.Results, "handler": "set_results"}] outputs = [{"name": "Selected Data", "type": Orange.data.Table}] quantities = ["Number of instances", "Observed and expected instances", "Proportion of predicted", "Proportion of true"] selected_learner = settings.Setting([]) selected_quantity = settings.Setting(0) append_predictions = settings.Setting(True) append_probabilities = settings.Setting(False) autocommit = settings.Setting(True) def __init__(self, parent=None): super().__init__(parent) self.results = None self.learners = [] self._invalidated = False box = gui.widgetBox(self.controlArea, "Learners") self.learners_box = gui.listBox( box, self, "selected_learner", "learners", callback=self._learner_changed ) box = gui.widgetBox(self.controlArea, "Show") combo = gui.comboBox(box, self, "selected_quantity", items=self.quantities, callback=self._update) box = gui.widgetBox(self.controlArea, "Selection") gui.button(box, self, "Correct", callback=self.select_correct, autoDefault=False) gui.button(box, self, "Misclassified", callback=self.select_wrong, autoDefault=False) gui.button(box, self, "None", callback=self.select_none, autoDefault=False) self.outputbox = box = gui.widgetBox(self.controlArea, "Output") gui.checkBox(box, self, "append_predictions", "Append class predictions", callback=self._invalidate) gui.checkBox(box, self, "append_probabilities", "Append predicted class probabilities", callback=self._invalidate) b = gui.button(box, self, "Commit", callback=self.commit, default=True) cb = gui.checkBox(box, self, "autocommit", "Commit automatically") gui.setStopper(self, b, cb, "_invalidated", callback=self.commit) grid = QGridLayout() grid.setContentsMargins(0, 0, 0, 0) grid.addWidget(QLabel("Predicted"), 0, 1, Qt.AlignCenter) grid.addWidget(VerticalLabel("Correct Class"), 1, 0, Qt.AlignCenter) self.tablemodel = QStandardItemModel() self.tableview = QTableView( editTriggers=QTableView.NoEditTriggers, ) self.tableview.setModel(self.tablemodel) self.tableview.selectionModel().selectionChanged.connect( self._invalidate ) grid.addWidget(self.tableview, 1, 1) self.mainArea.layout().addLayout(grid) def set_results(self, results): """Set the input results.""" self.clear() self.warning([0, 1]) data = None if results is not None: if results.data is not None: data = results.data if data is not None and \ not isinstance(data.domain.class_var, Orange.data.DiscreteVariable): data = None results = None self.warning( 0, "Confusion Matrix cannot be used for regression results.") self.results = results self.data = data if data is not None: class_values = data.domain.class_var.values elif results is not None: raise NotImplementedError if results is not None: nmodels, ntests = results.predicted.shape headers = class_values + [unicodedata.lookup("N-ARY SUMMATION")] # NOTE: The 'fitter_names' is set in 'Test Learners' widget. if hasattr(results, "fitter_names"): self.learners = results.fitter_names else: self.learners = ["L %i" % (i + 1) for i in range(nmodels)] self.tablemodel.setVerticalHeaderLabels(headers) self.tablemodel.setHorizontalHeaderLabels(headers) self.tablemodel.setRowCount(len(class_values) + 1) self.tablemodel.setColumnCount(len(class_values) + 1) self.selected_learner = [0] self._update() def clear(self): self.learners = [] self.results = None self.data = None self.tablemodel.clear() def select_correct(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(n): index = self.tablemodel.index(i, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect ) def select_wrong(self): selection = QItemSelection() n = self.tablemodel.rowCount() for i in range(n): for j in range(i + 1, n): index = self.tablemodel.index(i, j) selection.select(index, index) index = self.tablemodel.index(j, i) selection.select(index, index) self.tableview.selectionModel().select( selection, QItemSelectionModel.ClearAndSelect ) def select_none(self): self.tableview.selectionModel().clear() def commit(self): if self.results and self.data: indices = self.tableview.selectedIndexes() indices = {(ind.row(), ind.column()) for ind in indices} actual = self.results.actual selected_learner = self.selected_learner[0] learner_name = self.learners[selected_learner] predicted = self.results.predicted[selected_learner] selected = [i for i, t in enumerate(zip(actual, predicted)) if t in indices] row_indices = self.results.row_indices[selected] extra = [] class_var = self.data.domain.class_var metas = self.data.domain.metas if self.append_predictions: predicted = numpy.array(predicted[selected], dtype=object) extra.append(predicted.reshape(-1, 1)) var = Orange.data.DiscreteVariable( "{}({})".format(class_var.name, learner_name), class_var.values ) metas = metas + (var,) if self.append_probabilities and \ self.results.probabilities is not None: probs = self.results.probabilities[selected_learner, selected] extra.append(numpy.array(probs, dtype=object)) pvars = [Orange.data.ContinuousVariable("p({})".format(value)) for value in class_var.values] metas = metas + tuple(pvars) X = self.data.X[row_indices] Y = self.data.Y[row_indices] M = self.data.metas[row_indices] M = numpy.hstack((M,) + tuple(extra)) domain = Orange.data.Domain( self.data.domain.attributes, self.data.domain.class_vars, metas ) data = Orange.data.Table.from_numpy(domain, X, Y, M) else: data = None self.send("Selected Data", data) self._invalidated = False def _invalidate(self): if self.autocommit: self.commit() else: self._invalidated = True def _learner_changed(self): # The selected learner has changed self._update() def _update(self): # Update the displayed confusion matrix if self.results is not None and self.selected_learner: index = self.selected_learner[0] cmatrix = confusion_matrix(self.results, index) colsum = cmatrix.sum(axis=0) rowsum = cmatrix.sum(axis=1) total = rowsum.sum() if self.selected_quantity == 0: value = lambda i, j: int(cmatrix[i, j]) elif self.selected_quantity == 1: priors = numpy.outer(rowsum, colsum) / total value = lambda i, j: \ "{} / {:5.3f}".format(cmatrix[i, j], priors[i, j]) elif self.selected_quantity == 2: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / colsum[i]) if colsum[i] else "N/A") elif self.selected_quantity == 3: value = lambda i, j: \ ("{:2.1f} %".format(100 * cmatrix[i, j] / rowsum[i]) if colsum[i] else "N/A") else: assert False model = self.tablemodel for i, row in enumerate(cmatrix): for j, _ in enumerate(row): item = model.item(i, j) if item is None: item = QStandardItem() item.setData(value(i, j), Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) model.setItem(i, j, item) font = model.invisibleRootItem().font() bold_font = QFont(font) bold_font.setBold(True) def sum_item(value): item = QStandardItem() item.setData(value, Qt.DisplayRole) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) item.setFlags(Qt.ItemIsEnabled) item.setFont(bold_font) return item N = len(colsum) for i in range(N): model.setItem(N, i, sum_item(int(colsum[i]))) model.setItem(i, N, sum_item(int(rowsum[i]))) model.setItem(N, N, sum_item(int(total)))
window.show() tray = QSystemTrayIcon(icon) menu = QMenu() actionShow = QAction("Show Leopard Flower", menu) actionExit = QAction("Exit", menu) menu.addAction(actionShow) menu.addAction(actionExit) tray.setContextMenu(menu) tray.show() actionShow.triggered.connect(window.show) actionExit.triggered.connect(window.realQuit) modelAll = QStandardItemModel() modelAll.setHorizontalHeaderLabels( ("Name", "Process ID", "Permissions", "Full path", "Incoming allowed", "Outgoing allowed", "Incoming denied", "Outgoing denied")) modelActive = QStandardItemModel() modelActive.setHorizontalHeaderLabels( ("Name", "Process ID", "Permissions", "Full path", "Incoming allowed", "Outgoing allowed", "Incoming denied", "Outgoing denied")) window.tableView.setModel(modelAll) dialogOut = myDialogOut() dialogOut.setWindowTitle("Leopard Flower firewall") dialogIn = myDialogIn() dialogIn.setWindowTitle("Leopard Flower firewall") prefs_dialog = mForm() ruleslock = Lock() msgq_init() sys.exit(app.exec_())
class MSMainWindow(QMainWindow): """Gui of the main window""" # MAX_RECENT_FILES = 10 # start putting links spyder numpy scipy et tutti quanti links = ( "http://numpy.scipy.org/", "http://packages.python.org/spyder/", "http://www.riverbankcomputing.co.uk/software/pyqt/intro", ) pluginPath = path.normcase("pluginmanager/plugins/") def __init__(self, availablePlugins): """ Constructor with all the models needed setup menus """ QMainWindow.__init__(self) self.setDockOptions(QMainWindow.VerticalTabs | QMainWindow.AnimatedDocks) self.plugins = availablePlugins self.pluginsInst = [] settings = QSettings( "INRA/INSA", "-".join([QApplication.instance().APPLICATION_NAME_STR, QApplication.instance().VERSION_STR]) ) self.recentFiles = list(settings.value("RecentFiles").toStringList()) self.setStyleSheet(stylesheet) self.pipeline = MSPipelineToolBar("Pipeline toolbar", parent=self) self.addToolBar(0x1, self.pipeline) self._setupModels() self._setupUi() self._setupMenus() def _setupModels(self): """ Warning:Causes segfault when horizontal labels set to True on aura peu etre a la fin un model par sampleList c'est ce qui parait le plus logique """ # drag and drop table sample self.sampleModel = QStandardItemModel(self) self.sampleModel.setHorizontalHeaderLabels(["Sample", "Class"]) # treeView1 self.spectraModel = QStandardItemModel(self) # treeview2 self.peakModel = QStandardItemModel(self) # treeview3 self.clusterModel = QStandardItemModel(self) def _setupMenus(self): # file self.fileMenu = QMenu("&File") self.fileMenu.setTearOffEnabled(True) self.op = QMenu("&Open...", self.fileMenu) self.op.setIcon(QIcon(path.normcase("gui/icons/fileopen.png"))) open_ = QAction("&Open rawfiles", self) open_.setToolTip("Open an mzXML or netCDF file") open_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_O)) open_icon = QIcon(path.normcase("gui/icons/fileopen.png")) open_.setIcon(open_icon) self.op.addAction(open_) load_ = QAction("&Open projects...", self) load_.setToolTip("load binary file containing saved objects") load_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_S)) load_icon = QIcon(QPixmap(path.normcase("gui/icons/project_open.png"))) load_.setIcon(load_icon) self.op.addAction(load_) self.fileMenu.addMenu(self.op) save_ = QAction("&Save...", self) save_.setToolTip("save the actual application model") save_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_S)) save_icon = QIcon(path.normcase("gui/icons/save_all.png")) save_.setIcon(save_icon) self.fileMenu.addAction(save_) pkl = QAction("&load a peaklist", self) # TODO:load peaklist pkl.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_P)) pkl.setToolTip("load a peaklist and process it") pkl.setIcon(QIcon(path.normcase("gui/icons/featuredetect.png"))) self.fileMenu.addAction(pkl) convert_ = QAction("&Convert...", self) convert_.setEnabled(False) convert_.setToolTip("Convert a .wiff file if Analyst(c) is installed") convert_icon = QIcon(path.normcase("gui/icons/goto.png")) convert_.setIcon(convert_icon) self.fileMenu.addAction(convert_) a = self.fileMenu.addAction(QIcon(path.normcase("gui/icons/process.png")), "&Launch a batch") a.setEnabled(False) b = self.fileMenu.addAction(QIcon(path.normcase("gui/icons/process.png")), "&Merge") b.setToolTip("Merge MRM file") # b.setEnabled(False) self.fileMenu.addSeparator() # # for i in xrange(self.MAX_RECENT_FILES): # a = QAction('', self) # a.setVisible(False) # self.fileMenu.addAction(a) # # for i in xrange(min(self.MAX_RECENT_FILES, len(self.recentFiles))): # self.fileMenu.actions()[5+i].setVisible(True) # self.fileMenu.actions()[5+i].setText(self.recentFiles[i].split('/')[-1]) exit_action = QAction("&Exit", self) exit_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q)) exit_action.setIcon(QIcon(QPixmap(path.normcase("gui/icons/exit.png")))) self.fileMenu.addAction(exit_action) self.menuBar().addMenu(self.fileMenu) self.editMenu = QMenu("&Edit") self.editMenu.setTearOffEnabled(True) self.editMenu.addAction(QIcon(path.normcase("gui/icons/edit_undo.png")), "&Undo...") self.editMenu.addAction(QIcon(path.normcase("gui/icons/edit_redo.png")), "&Redo...") self.editMenu.actions()[0].setEnabled(False) self.editMenu.actions()[1].setEnabled(False) self.editMenu.addSeparator() self.editMenu.addAction(QIcon(path.normcase("gui/icons/run.png")), "&Preferences") self.exportMenu = QMenu("&Export...") self.exportMenu.setIcon(QIcon(path.normcase("gui/icons/file_export.png"))) self.exportMenu.addAction("&Peaklist") self.exportMenu.addAction("&Clusters intensity matrix") self.editMenu.addMenu(self.exportMenu) self.menuBar().addMenu(self.editMenu) # view self.viewMenu = QMenu("&View") self.viewMenu.setTearOffEnabled(True) self.viewMenu.addAction( QIcon(path.normcase("gui/icons/window_duplicate")), "&Cascade View", self.mdiArea.cascadeSubWindows, QKeySequence(Qt.CTRL + Qt.Key_K), ) self.viewMenu.addAction( QIcon(path.normcase("gui/icons/view_icon")), "&Title View", self.mdiArea.tileSubWindows, QKeySequence(Qt.CTRL + Qt.Key_N), ) self.viewMenu.addAction( QIcon(path.normcase("gui/icons/stop_process.png")), "&Close all subWindows", self.mdiArea.closeAllSubWindows, QKeySequence(Qt.CTRL + Qt.Key_W), ) self.plotting = QMenu("&Plotting...") self.plotting.setIcon(QIcon(QPixmap(path.normcase("gui/icons/plot.png")))) self.plotting.addAction("&3D Plot") # self.plotting.addAction("&Cytoscape web") self.plotting.addAction("&Spectrogram Plot") # self.multiplePlot = QAction("&Visualize Raw/Treated Data", self) # self.multiplePlot.setCheckable(True) # self.multiplePlot.setEnabled(False) # self.sub_plot_.addAction(self.multiplePlot) self.viewMenu.addMenu(self.plotting) self.viewMenu.addSeparator() self.show_hide = QMenu("&Show/Hide") m = self.createPopupMenu() m.setTitle("&Show/Hide") self.viewMenu.addMenu(m) # self.pref = QMenu("&Preferences") # self.pref.addAction(self.multiplePlot) # self.viewMenu.addMenu(self.pref) self.menuBar().addMenu(self.viewMenu) # algorithm self.algoMenu = QMenu("&Algorithm") self.algoMenu.setTearOffEnabled(True) self.preProcessing = QMenu("&PreProcessing(experimental)") self.preProcessing.addAction("&Smoothing raw data...") self.preProcessing.addAction("&Cut off raw data...") self.preProcessing.addAction("&Calibration (mz dimension)") self.preProcessing.addAction("&Resize sample...") self.algoMenu.addMenu(self.preProcessing) self.peakPickingMenu = QMenu("&Peack Picking & Alignement(XCMS)", self) self.peakPickingMenu.setIcon(QIcon(path.normcase("gui/icons/pickedpeakicon.png"))) matched = QAction("&MatchedFiltered", self) matched.setIcon(QIcon(path.normcase("gui/icons/RLogo"))) matched.setToolTip("Peak Detection and Integration using MatchedFiltered algorithm") self.peakPickingMenu.addAction(matched) centwave = QAction("&CentWave", self) centwave.setIcon(QIcon(path.normcase("gui/icons/RLogo"))) centwave.setToolTip("Peak Detection and Integration using CentWave algorithm") self.peakPickingMenu.addAction(centwave) # peak_.setShortcut(.QKeySequence(CTRL + Key_P)) # peak_icon=.QIcon(.QPixmap(path.normcase("gui/icons/pickedpeakicon.png"))) # peak_.setIcon(peak_icon) self.algoMenu.addMenu(self.peakPickingMenu) self.alignment = QMenu("&Alignment") self.alignment.setIcon(QIcon(path.normcase("gui/icons/format_indent_more.png"))) self.alignment.addAction("&Polynomial fitting(exp)") self.alignment.addAction("&DynamicTimeWarping") self.alignment.addAction("&ObiWarp") self.alignment.actions()[2].setEnabled(False) self.algoMenu.addMenu(self.alignment) self.algoMenu.addAction("Normalization") clust_ = QAction("&Clustering", self) clust_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_L)) clust_icon = QIcon(QPixmap(path.normcase("gui/icons/cluster.png"))) clust_.setIcon(clust_icon) self.algoMenu.addAction(clust_) id_ = QAction("&Identification", self) id_.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_I)) id_.setToolTip("Try to identify peaks with several methods") id_.setIcon(QIcon(QPixmap(path.normcase("gui/icons/findcompound.png")))) self.algoMenu.addAction(id_) self.menuBar().addMenu(self.algoMenu) # tools self.toolsMenu = QMenu("&Tools") self.toolsMenu.setTearOffEnabled(True) web = QAction("&Web Browser", self) web.setIcon(QIcon(QPixmap(path.normcase("gui/icons/applications_internet.png")))) self.toolsMenu.addAction(web) # cyto = QAction("&cytoscape", self) # cyto_icon =QIcon(QPixmap(path.normcase("gui/icons/cytoscape.jpeg"))) # cyto.setIcon(cyto_icon) # self.toolsMenu.addAction(cyto) editor = QAction("&Editor", self) editor.setIcon(QIcon(QPixmap(path.normcase("gui/icons/document_sign.png")))) self.toolsMenu.addAction(editor) pet = QAction("&Short Periodic Table", self) pet.setIcon(QIcon(QPixmap(path.normcase("gui/icons/pet.jpg")))) self.toolsMenu.addAction(pet) self.menuBar().addMenu(self.toolsMenu) # plugins self.pluginMenu = QMenu("&Plugins") self.pluginMenu.setTearOffEnabled(True) instPl = QAction("&Install a plugin", self) instPl.setIcon(QIcon(path.normcase("gui/icons/pluginInstall.png"))) self.pluginMenu.addAction(instPl) self.launchingMenu = QMenu("&Launch PLugins", self) self.launchingMenu.setIcon(QIcon(path.normcase("gui/icons/plugin"))) for plug in self.plugins: # fullname="".join([self.pluginPath, str(plug)]) mod = imp.load_source(self.__module__, plug) if mod.autoActivation: qApp = QApplication.instance() name = getattr(mod, "className") cls = getattr(mod, name) p = cls(qApp.model, self, parent=self) # p=qApp.pluginManager.loadPlugin(qApp.model, self, plug.split('/')[-1]) self.pluginsInst.append(p) else: self.launchingMenu.addAction(plug.split("/")[-1]) self.pluginMenu.addMenu(self.launchingMenu) self.pluginMenu.addAction(QIcon(path.normcase("gui/icons/process_stop.png")), "&Remove loaded Plugin") self.menuBar().addMenu(self.pluginMenu) # about self.aboutMenu = QMenu("&About") self.aboutMenu.setTearOffEnabled(True) metms = QAction(QIcon(path.normcase("gui/icons/deluge.png")), "&about metMS...", self) self.aboutMenu.addAction(metms) pyqt = QAction("&about PyQt4...", self) pyqt_icon = QIcon(QPixmap(path.normcase("gui/icons/logo_QT4.png"))) pyqt.setIcon(pyqt_icon) self.aboutMenu.addAction(pyqt) metms = QAction("&metMS Documentation", self) metms_icon = QIcon(QPixmap(path.normcase("gui/icons/deluge.png"))) metms.setIcon(metms_icon) self.aboutMenu.addAction(metms) self.menuBar().addMenu(self.aboutMenu) def _setupUi(self, background=None): """ Make the GUI """ # mdi self.mdiArea = MSMdiArea(self) self.mdiArea.setBackground(QBrush(QPixmap(path.normcase("gui/icons/blac2.png")))) # QColor(Qt.blue).darker())) self.setCentralWidget(self.mdiArea) # sample dock widget self.sampleDockWidget = QDockWidget("Samples", self) # sampleWidget = QWidget() self.sampleTableView = MSDragFromTableView() self.sampleTableView.setModel(self.sampleModel) self.sampleTableView.setSelectionBehavior(1) self.sampleTableView.verticalHeader().hide() self.sampleTableView.verticalHeader().setDefaultSectionSize(15) self.sampleTableView.horizontalHeader().setDefaultSectionSize(150) self.sampleDockWidget.setWidget(self.sampleTableView) # sampleWidget) self.sampleDockWidget.visible = True # workflow dock self.workflowDockWidget = QDockWidget("Visualizer", self) self.workflowDockWidget.visible = True a = QWidget(self) v = QVBoxLayout(a) q = QToolBar() # self.workingSample = QLabel("Working Sample:None") # q.addWidget(self.workingSample) q.addWidget(QLabel("ppm :")) self.ppmEditer = QDoubleSpinBox() self.usePpm = QCheckBox("use ?") q.addWidget(self.ppmEditer) q.addWidget(self.usePpm) q.addSeparator() self.removeButton = QToolButton(self) self.removeButton.setIcon(QIcon(path.normcase("gui/icons/delete.png"))) q.addWidget(self.removeButton) self.markAsGood = QAction(QIcon(path.normcase("gui/icons/button_ok.png")), "mark peak as good", self) self.markAsBad = QAction(QIcon(path.normcase("gui/icons/stop.png")), "mark peak as bad", self) self.hideItem = QAction(QIcon(path.normcase("gui/icons/list_remove.png")), "Hide Item", self) q.addAction(self.markAsGood) q.addAction(self.markAsBad) q.addAction(self.hideItem) v.addWidget(q) self.tabWidget = QTabWidget() self.tab = QWidget() verticalLayout = QVBoxLayout(self.tab) self.treeView = MSToDropTableView() self.treeView.verticalHeader().setDefaultSectionSize(20) self.treeView.setModel(self.spectraModel) self.spectraLabel = QLabel("Sample: None") verticalLayout.addWidget(self.treeView) verticalLayout.addWidget(self.spectraLabel) self.tabWidget.addTab(self.tab, QIcon(path.normcase("gui/icons/spectrumicon.png")), "Spectra") self.tab_2 = QWidget() verticalLayout_4 = QVBoxLayout(self.tab_2) self.treeView_2 = MSToDropTableView() # MSTreeView(self.tab_2)# QTableView(self)# self.treeView_2.verticalHeader().setDefaultSectionSize(20) self.treeView_2.setModel(self.peakModel) self.peakLabel = QLabel("Sample: None") verticalLayout_4.addWidget(self.treeView_2) verticalLayout_4.addWidget(self.peakLabel) self.tabWidget.addTab(self.tab_2, QIcon(path.normcase("gui/icons/peakicon.png")), "Peaks List") self.tab_3 = QWidget() verticalLayout_5 = QVBoxLayout(self.tab_3) self.treeView_3 = MSToDropTreeView() self.treeView_3.setAnimated(True) self.treeView_3.setModel(self.clusterModel) self.clusterLabel = QLabel("Sample: None") verticalLayout_5.addWidget(self.treeView_3) verticalLayout_5.addWidget(self.clusterLabel) self.tabWidget.addTab(self.tab_3, QIcon(path.normcase("gui/icons/clustering.png")), "Clusters") self.tabWidget.setCurrentIndex(0) for l in (self.spectraLabel, self.peakLabel, self.clusterLabel): l.setAutoFillBackground(True) v.addWidget(self.tabWidget) self.workflowDockWidget.setWidget(a) self.addDockWidget(Qt.DockWidgetArea(0x2), self.workflowDockWidget) from gui.MetBaseGui import MSIsoCalculator self.isoCalc = MSIsoCalculator(self) self.isoCalcDockWidget = QDockWidget("isotopes calculation", self) self.isoCalcDockWidget.setWidget(self.isoCalc) self.addDockWidget(Qt.DockWidgetArea(0x2), self.isoCalcDockWidget) self.isoCalcDockWidget.setVisible(False) self.isoCalcDockWidget.visible = False from gui.MetBaseGui import FormulaGenerator self.generator = FormulaGenerator(self) self.generatorDockWidget = QDockWidget("formula generator", self) self.generatorDockWidget.setWidget(self.generator) self.addDockWidget(Qt.DockWidgetArea(0x2), self.generatorDockWidget) self.generatorDockWidget.setVisible(False) self.generatorDockWidget.visible = False self.compoundTreeView = MSCompoundTreeView(self) self.compoundDockWidget = QDockWidget("Compounds", self) self.compoundDockWidget.setWidget(self.compoundTreeView) self.addDockWidget(Qt.DockWidgetArea(0x2), self.compoundDockWidget) self.compoundDockWidget.setVisible(False) self.compoundDockWidget.visible = False self.comparativeTableView = QTableView(self) self.comparativeTableView.horizontalHeader().setStretchLastSection(True) self.comparativeTableView.verticalHeader().setDefaultSectionSize(20) self.comparativeDock = QDockWidget("Comparative View", self) self.comparativeDock.setWidget(self.comparativeTableView) self.addDockWidget(Qt.DockWidgetArea(0x8), self.comparativeDock) self.comparativeDock.setVisible(False) self.comparativeDock.visible = False self.tabifyDockWidget(self.compoundDockWidget, self.isoCalcDockWidget) self.tabifyDockWidget(self.isoCalcDockWidget, self.workflowDockWidget) self.tabifyDockWidget(self.workflowDockWidget, self.generatorDockWidget) # set the end # WARNING: possible that the internal shell widget cause random segfault # with the error of QObject::killTimers...? not sure ! self.shell = QWidget() # InternalShell(namespace={'metms': QApplication.instance()}, # parent=self, # multithreaded=False) self.shellDock = QDockWidget("Python Shell", self) self.shellDock.setWindowIcon(QIcon(path.normcase("gui/icons/stop.png"))) self.shellDock.setWidget(self.shell) self.shellDock.setMinimumWidth(255) self.shellDock.visible = True self.addDockWidget(0x2, self.shellDock) self.addDockWidget(0x2, self.sampleDockWidget) self.tabifyDockWidget(self.shellDock, self.sampleDockWidget) self.pb = QProgressBar(self) self.pb.setMaximumWidth(245) self.stopProcess = QToolButton(self) self.stopProcess.setIcon(QIcon(path.normcase("gui/icons/process_stop.png"))) m = QMenu() # self.connect(m, SIGNAL('triggered(QAction*'), QApplication.instance().taskManager.abortByName) self.stopProcess.setMenu(m) self.stopProcess.setPopupMode(1) # Menu Button # self.connect(self.stopProcess, SIGNAL("clicked()"), self.stopThread) self.statusBar().addPermanentWidget(self.stopProcess) self.statusBar().addPermanentWidget(self.pb) def updateStopProcessMenu(self): """ update the menu of the stop process button, based directly on the processes stored by the task manager """ self.stopProcess.menu().clear() for c in QApplication.instance().taskManager: self.stopProcess.menu().addAction(c.title) # QApplication.instance().taskManager.abort(QApplication.instance().taskManager[-1]) def addMdiSubWindow(self, plot, title="", showMaximized=False): """ Allow addition of new window in the mdiarea """ win = self.mdiArea.addSubWindow(plot) # print "widget parent", plot.parent() win.setAttribute(Qt.WA_DeleteOnClose) # win.connect(win, SIGNAL('destroyed(QObject *)'), self.testdestroy) # plot.setParent(win) win.setWindowTitle(title) if showMaximized: win.showMaximized() else: win.resize(400, 300) win.show() return win def updateTreeView(self): """ Tree View update switch spectre/chromato """ if self.treeView.model() == self.spectraModel: self.treeView.setModel(self.chromaModel) self.tabWidget.setTabText(0, "Chroma") else: self.treeView.setModel(self.spectraModel) # self.treeView.setSelectionMode(1) self.tabWidget.setTabText(0, "Spectra") def addTreeViewModel(self, model1, model2): """Add a model """ self.chromaModel.appendRow(model1) self.spectraModel.appendRow(model2) def _actionHovered(self, action): """emulate tooltip cause they do not work that much""" tip = action.toolTip() QToolTip.showText(QCursor.pos(), tip) def showErrorMessage(self, title, string): QMessageBox.critical(self, title, string, 0, 0) def showWarningMessage(self, title, string): return QMessageBox.warning(self, title, string, QMessageBox.Ok | QMessageBox.Cancel) def showInformationMessage(self, title, string): QMessageBox.information(self, title, string, 0) def updateProgressBar(self, i): """update the value of the progress bar for all the treatment""" self.pb.setValue(min(i, 100)) def to_indetermined_mode(self): self.pb.setMaximum(0) def to_determined_mode(self): self.pb.setMaximum(100) def showInStatusBar(self, string, time=5000): self.statusBar().showMessage(string, time) def addInterpreterDock(self, shell): self.shellDock = QDockWidget(self) self.shellDock.setWidget(shell) self.shellDock.setWindowTitle("shell") self.addDockWidget(0x2, self.shellDock) def showMetMSInformation(self): QMessageBox.about( self, self.tr("About %1").arg("metMS"), self.tr( """<b>%1 %2</b> <br>metabolite Mass Spectrometry <p>Copyright © 2010 Marco INSA, INRA <br>Licensed under the terms of the CeciLL License <p>Developed and maintained by Marco <br>Bug reports and feature requests: <a href="http://github.com/jerkos/metms">metMS site</a><br> Discussions around the project: <a href="http://groups.google.com/group/spyderlib">Google Group</a> <p>This project is part of the BRIDGE project <p>Python %3, Qt %4, PyQt %5""" ) .arg("metMS") .arg(__version__) .arg(platform.python_version()) .arg(QT_VERSION_STR) .arg(PYQT_VERSION_STR), )
class OWTestLearners(widget.OWWidget): name = "Test & Score" description = "Cross-validation accuracy estimation." icon = "icons/TestLearners1.svg" priority = 100 inputs = [("Learner", Learner, "set_learner", widget.Multiple), ("Data", Table, "set_train_data", widget.Default), ("Test Data", Table, "set_test_data"), ("Preprocessor", Preprocess, "set_preprocessor")] outputs = [("Predictions", Orange.data.Table), ("Evaluation Results", Orange.evaluation.Results)] settingsHandler = settings.ClassValuesContextHandler() #: Resampling/testing types KFold, ShuffleSplit, LeaveOneOut, TestOnTrain, TestOnTest = 0, 1, 2, 3, 4 #: Selected resampling type resampling = settings.Setting(0) #: Number of folds for K-fold cross validation k_folds = settings.Setting(10) #: Stratified sampling for K-fold cv_stratified = settings.Setting(True) #: Number of repeats for ShuffleSplit sampling n_repeat = settings.Setting(10) #: ShuffleSplit sampling p sample_p = settings.Setting(75) #: Stratified sampling for Random Sampling shuffle_stratified = settings.Setting(True) TARGET_AVERAGE = "(Average over classes)" class_selection = settings.ContextSetting(TARGET_AVERAGE) def __init__(self): super().__init__() self.data = None self.test_data = None self.preprocessor = None self.train_data_missing_vals = False self.test_data_missing_vals = False #: An Ordered dictionary with current inputs and their testing #: results. self.learners = OrderedDict() sbox = gui.widgetBox(self.controlArea, "Sampling") rbox = gui.radioButtons(sbox, self, "resampling", callback=self._param_changed) gui.appendRadioButton(rbox, "Cross validation") ibox = gui.indentedBox(rbox) gui.spin(ibox, self, "k_folds", 2, 50, label="Number of folds:", callback=self.kfold_changed) gui.checkBox(ibox, self, "cv_stratified", "Stratified", callback=self.kfold_changed) gui.appendRadioButton(rbox, "Random sampling") ibox = gui.indentedBox(rbox) gui.spin(ibox, self, "n_repeat", 2, 50, label="Repeat train/test", callback=self.shuffle_split_changed) gui.widgetLabel(ibox, "Relative training set size:") gui.hSlider(ibox, self, "sample_p", minValue=1, maxValue=99, ticks=20, vertical=False, labelFormat="%d %%", callback=self.shuffle_split_changed) gui.checkBox(ibox, self, "shuffle_stratified", "Stratified", callback=self.shuffle_split_changed) gui.appendRadioButton(rbox, "Leave one out") gui.appendRadioButton(rbox, "Test on train data") gui.appendRadioButton(rbox, "Test on test data") rbox.layout().addSpacing(5) self.apply_button = gui.button(rbox, self, "Apply", callback=self.apply, default=True) self.cbox = gui.widgetBox(self.controlArea, "Target class") self.class_selection_combo = gui.comboBox( self.cbox, self, "class_selection", items=[], sendSelectedValue=True, valueType=str, callback=self._on_target_class_changed, contentsLength=8) gui.rubber(self.controlArea) self.view = QTreeView(rootIsDecorated=False, uniformRowHeights=True, wordWrap=True, editTriggers=QTreeView.NoEditTriggers) header = self.view.header() header.setResizeMode(QHeaderView.ResizeToContents) header.setDefaultAlignment(Qt.AlignCenter) header.setStretchLastSection(False) self.result_model = QStandardItemModel(self) self.result_model.setHorizontalHeaderLabels(["Method"]) self.view.setModel(self.result_model) self.view.setItemDelegate(ItemDelegate()) box = gui.widgetBox(self.mainArea, "Evaluation Results") box.layout().addWidget(self.view) def sizeHint(self): return QSize(780, 1) def set_learner(self, learner, key): """ Set the input `learner` for `key`. """ if key in self.learners and learner is None: # Removed del self.learners[key] else: self.learners[key] = Input(learner, None, None) self._invalidate([key]) def set_train_data(self, data): """ Set the input training dataset. """ self.error(0) self.information(0) if data and not data.domain.class_var: self.error(0, "Train data input requires a class variable") data = None if isinstance(data, SqlTable): if data.approx_len() < AUTO_DL_LIMIT: data = Table(data) else: self.information(0, "Train data has been sampled") data_sample = data.sample_time(1, no_cache=True) data_sample.download_data(AUTO_DL_LIMIT, partial=True) data = Table(data_sample) self.warning(4) self.train_data_missing_vals = data is not None and \ np.isnan(data.Y).any() if self.train_data_missing_vals or self.test_data_missing_vals: self.warning( 4, self._get_missing_data_warning(self.train_data_missing_vals, self.test_data_missing_vals)) if data: data = RemoveNaNClasses(data) self.data = data self.closeContext() if data is not None: self._update_class_selection() self.openContext(data.domain.class_var) self._invalidate() def set_test_data(self, data): """ Set the input separate testing dataset. """ self.error(1) self.information(1) if data and not data.domain.class_var: self.error(1, "Test data input requires a class variable") data = None if isinstance(data, SqlTable): if data.approx_len() < AUTO_DL_LIMIT: data = Table(data) else: self.information(1, "Test data has been sampled") data_sample = data.sample_time(1, no_cache=True) data_sample.download_data(AUTO_DL_LIMIT, partial=True) data = Table(data_sample) self.warning(4) self.test_data_missing_vals = data is not None and \ np.isnan(data.Y).any() if self.train_data_missing_vals or self.test_data_missing_vals: self.warning( 4, self._get_missing_data_warning(self.train_data_missing_vals, self.test_data_missing_vals)) if data: data = RemoveNaNClasses(data) self.test_data = data if self.resampling == OWTestLearners.TestOnTest: self._invalidate() def _get_missing_data_warning(self, train_missing, test_missing): return "Instances with unknown target values were removed from{}data"\ .format(train_missing * test_missing * " " or train_missing * " train " or test_missing * " test ") def set_preprocessor(self, preproc): """ Set the input preprocessor to apply on the training data. """ self.preprocessor = preproc self._invalidate() def handleNewSignals(self): """Reimplemented from OWWidget.handleNewSignals.""" self._update_class_selection() self.apply() def kfold_changed(self): self.resampling = OWTestLearners.KFold self._param_changed() def shuffle_split_changed(self): self.resampling = OWTestLearners.ShuffleSplit self._param_changed() def _param_changed(self): self._invalidate() def _update_results(self): """ Run/evaluate the learners. """ self.warning([1, 2]) self.error([2, 4]) if self.data is None: return class_var = self.data.domain.class_var if self.resampling == OWTestLearners.TestOnTest: if self.test_data is None: self.warning(2, "Missing separate test data input") return elif self.test_data.domain.class_var != class_var: self.error(2, ("Inconsistent class variable between test " + "and train data sets")) return # items in need of an update items = [(key, slot) for key, slot in self.learners.items() if slot.results is None] learners = [slot.learner for _, slot in items] if len(items) == 0: return if self.test_data is not None and \ self.resampling != OWTestLearners.TestOnTest: self.warning( 1, "Test data is present but unused. " "Select 'Test on test data' to use it.") rstate = 42 def update_progress(finished): self.progressBarSet(100 * finished) common_args = dict(store_data=True, preprocessor=self.preprocessor, callback=update_progress) self.setStatusMessage("Running") with self.progressBar(): try: if self.resampling == OWTestLearners.KFold: if len(self.data) < self.k_folds: self.error(4, "Number of folds exceeds the data size") return warnings = [] results = Orange.evaluation.CrossValidation( self.data, learners, k=self.k_folds, random_state=rstate, warnings=warnings, **common_args) if warnings: self.warning(2, warnings[0]) elif self.resampling == OWTestLearners.LeaveOneOut: results = Orange.evaluation.LeaveOneOut( self.data, learners, **common_args) elif self.resampling == OWTestLearners.ShuffleSplit: train_size = self.sample_p / 100 results = Orange.evaluation.ShuffleSplit( self.data, learners, n_resamples=self.n_repeat, train_size=train_size, test_size=None, stratified=self.shuffle_stratified, random_state=rstate, **common_args) elif self.resampling == OWTestLearners.TestOnTrain: results = Orange.evaluation.TestOnTrainingData( self.data, learners, **common_args) elif self.resampling == OWTestLearners.TestOnTest: results = Orange.evaluation.TestOnTestData( self.data, self.test_data, learners, **common_args) else: assert False except RuntimeError as e: self.error(2, str(e)) self.setStatusMessage("") return learner_key = { slot.learner: key for key, slot in self.learners.items() } for learner, result in zip(learners, split_by_model(results)): stats = None if class_var.is_discrete: scorers = classification_stats.scores elif class_var.is_continuous: scorers = regression_stats.scores else: scorers = None if scorers: ex = result.failed[0] if ex: stats = [Try.Fail(ex)] * len(scorers) result = Try.Fail(ex) else: stats = [Try(lambda: score(result)) for score in scorers] result = Try.Success(result) key = learner_key[learner] self.learners[key] = \ self.learners[key]._replace(results=result, stats=stats) self.setStatusMessage("") def _update_header(self): # Set the correct horizontal header labels on the results_model. headers = ["Method"] if self.data is not None: if self.data.domain.has_discrete_class: headers.extend(classification_stats.headers) else: headers.extend(regression_stats.headers) # remove possible extra columns from the model. for i in reversed(range(len(headers), self.result_model.columnCount())): self.result_model.takeColumn(i) self.result_model.setHorizontalHeaderLabels(headers) def _update_stats_model(self): # Update the results_model with up to date scores. # Note: The target class specific scores (if requested) are # computed as needed in this method. model = self.view.model() # clear the table model, but preserving the header labels for r in reversed(range(model.rowCount())): model.takeRow(r) target_index = None if self.data is not None: class_var = self.data.domain.class_var if self.data.domain.has_discrete_class and \ self.class_selection != self.TARGET_AVERAGE: target_index = class_var.values.index(self.class_selection) else: class_var = None errors = [] has_missing_scores = False for key, slot in self.learners.items(): name = learner_name(slot.learner) head = QStandardItem(name) head.setData(key, Qt.UserRole) if isinstance(slot.results, Try.Fail): head.setToolTip(str(slot.results.exception)) head.setText("{} (error)".format(name)) head.setForeground(QtGui.QBrush(Qt.red)) errors.append("{name} failed with error:\n" "{exc.__class__.__name__}: {exc!s}".format( name=name, exc=slot.results.exception)) row = [head] if class_var is not None and class_var.is_discrete and \ target_index is not None: if slot.results is not None and slot.results.success: ovr_results = results_one_vs_rest(slot.results.value, target_index) stats = [ Try(lambda: score(ovr_results)) for score in classification_stats.scores ] else: stats = None else: stats = slot.stats if stats is not None: for stat in stats: item = QStandardItem() if stat.success: item.setText("{:.3f}".format(stat.value[0])) else: item.setToolTip(str(stat.exception)) has_missing_scores = True row.append(item) model.appendRow(row) if errors: self.error(3, "\n".join(errors)) else: self.error(3) if has_missing_scores: self.warning(3, "Some scores could not be computed") else: self.warning(3) def _update_class_selection(self): self.class_selection_combo.setCurrentIndex(-1) self.class_selection_combo.clear() if not self.data: return if self.data.domain.has_discrete_class: self.cbox.setVisible(True) class_var = self.data.domain.class_var items = [self.TARGET_AVERAGE] + class_var.values self.class_selection_combo.addItems(items) class_index = 0 if self.class_selection in class_var.values: class_index = class_var.values.index(self.class_selection) + 1 self.class_selection_combo.setCurrentIndex(class_index) self.class_selection = items[class_index] else: self.cbox.setVisible(False) def _on_target_class_changed(self): self._update_stats_model() def _invalidate(self, which=None): # Invalidate learner results for `which` input keys # (if None then all learner results are invalidated) if which is None: which = self.learners.keys() model = self.view.model() statmodelkeys = [ model.item(row, 0).data(Qt.UserRole) for row in range(model.rowCount()) ] for key in which: self.learners[key] = \ self.learners[key]._replace(results=None, stats=None) if key in statmodelkeys: row = statmodelkeys.index(key) for c in range(1, model.columnCount()): item = model.item(row, c) if item is not None: item.setData(None, Qt.DisplayRole) item.setData(None, Qt.ToolTipRole) self.apply_button.setEnabled(True) def apply(self): self.apply_button.setEnabled(False) self._update_header() # Update the view to display the model names self._update_stats_model() self._update_results() self._update_stats_model() self.commit() def commit(self): valid = [ slot for slot in self.learners.values() if slot.results is not None and slot.results.success ] if valid: # Evaluation results combined = results_merge([slot.results.value for slot in valid]) combined.learner_names = [ learner_name(slot.learner) for slot in valid ] # Predictions & Probabilities predictions = combined.get_augmented_data(combined.learner_names) else: combined = None predictions = None self.send("Evaluation Results", combined) self.send("Predictions", predictions) def send_report(self): if not self.data or not self.learners: return if self.resampling == self.KFold: stratified = 'Stratified ' if self.cv_stratified else '' items = [ ("Sampling type", "{}{}-fold Cross validation".format(stratified, self.k_folds)) ] elif self.resampling == self.LeaveOneOut: items = [("Sampling type", "Leave one out")] elif self.resampling == self.ShuffleSplit: stratified = 'Stratified ' if self.shuffle_stratified else '' items = [ ("Sampling type", "{}Shuffle split, {} random samples with {}% data ".format( stratified, self.n_repeat, self.sample_p)) ] elif self.resampling == self.TestOnTrain: items = [("Sampling type", "No sampling, test on training data")] elif self.resampling == self.TestOnTest: items = [("Sampling type", "No sampling, test on testing data")] else: items = [] if self.data.domain.has_discrete_class: items += [("Target class", self.class_selection.strip("()"))] if items: self.report_items("Settings", items) self.report_table("Scores", self.view)
class FlashingWindow(QDialog, Ui_Flashing): def __init__(self, parent): QDialog.__init__(self, parent) self.setupUi(self) self.tool_infos = {} self.firmware_infos = {} self.plugin_infos = {} self.brick_infos = [] self.refresh_updates_pending = False self.parent = parent self.tab_widget.currentChanged.connect(self.tab_changed) self.button_serial_port_refresh.clicked.connect(self.refresh_serial_ports) self.combo_firmware.currentIndexChanged.connect(self.firmware_changed) self.button_firmware_save.clicked.connect(self.firmware_save_clicked) self.button_firmware_browse.clicked.connect(self.firmware_browse_clicked) self.button_uid_load.clicked.connect(self.uid_load_clicked) self.button_uid_save.clicked.connect(self.uid_save_clicked) self.combo_brick.currentIndexChanged.connect(self.brick_changed) self.combo_port.currentIndexChanged.connect(self.port_changed) self.combo_plugin.currentIndexChanged.connect(self.plugin_changed) self.button_plugin_save.clicked.connect(self.plugin_save_clicked) self.button_plugin_browse.clicked.connect(self.plugin_browse_clicked) infos.get_infos_changed_signal().connect(self.update_bricks) self.update_tool_label.hide() self.no_connection_label.hide() self.refresh_serial_ports() self.combo_firmware.addItem(CUSTOM) self.combo_firmware.setDisabled(True) self.firmware_changed(0) self.combo_plugin.addItem(CUSTOM) self.combo_plugin.setDisabled(True) self.plugin_changed(0) self.brick_changed(0) self.update_tree_view_model_labels = ['Name', 'UID', 'Installed', 'Latest'] self.update_tree_view_model = QStandardItemModel(self) self.update_tree_view.setModel(self.update_tree_view_model) self.update_tree_view.setSortingEnabled(True) self.update_tree_view.header().setSortIndicator(0, Qt.AscendingOrder) self.update_button_refresh.clicked.connect(self.refresh_updates_clicked) self.update_button_bricklets.clicked.connect(self.auto_update_bricklets_clicked) self.update_ui_state() self.update_bricks() def refresh_latest_version_info(self, progress): self.tool_infos = {} self.firmware_infos = {} self.plugin_infos = {} self.combo_firmware.clear() self.combo_plugin.clear() self.combo_firmware.setDisabled(False) self.combo_plugin.setDisabled(False) progress.setLabelText('Discovering latest versions on tinkerforge.com') progress.setMaximum(0) progress.setValue(0) progress.show() okay = True try: response = urllib2.urlopen(LATEST_VERSIONS_URL, timeout=10) latest_versions_data = response.read() response.close() except urllib2.URLError: okay = False progress.cancel() self.combo_firmware.setDisabled(True) self.combo_plugin.setDisabled(True) self.popup_fail('Updates / Flashing', 'Latest version information on tinkerforge.com is not available (error code 1). Please report this to [email protected].\n\nFirmwares and plugins can be flashed from local files only.') if okay: def report_malformed(error_code): progress.cancel() self.combo_firmware.setDisabled(True) self.combo_plugin.setDisabled(True) self.popup_fail('Updates / Flashing', 'Latest version information on tinkerforge.com is malformed (error code {0}). Please report this to [email protected].\n\nFirmwares and plugins can be flashed from local files only.'.format(error_code)) for line in latest_versions_data.split('\n'): line = line.strip() if len(line) < 1: continue parts = line.split(':') if len(parts) != 3: okay = False report_malformed(2) break latest_version_parts = parts[2].split('.') if len(latest_version_parts) != 3: okay = False report_malformed(3) break try: latest_version = int(latest_version_parts[0]), int(latest_version_parts[1]), int(latest_version_parts[2]) except: okay = False report_malformed(4) break if parts[0] == 'tools': tool_info = infos.ToolInfo() tool_info.firmware_version_latest = latest_version self.tool_infos[parts[1]] = tool_info elif parts[0] == 'bricks': self.refresh_firmware_info(parts[1], latest_version) elif parts[0] == 'bricklets': self.refresh_plugin_info(parts[1], latest_version) if okay: # update combo_firmware if len(self.firmware_infos) > 0: self.combo_firmware.addItem(SELECT) self.combo_firmware.insertSeparator(self.combo_firmware.count()) for firmware_info in sorted(self.firmware_infos.values(), key=lambda x: x.name): name = '{0} ({1}.{2}.{3})'.format(firmware_info.name, *firmware_info.firmware_version_latest) self.combo_firmware.addItem(name, firmware_info.url_part) if self.combo_firmware.count() > 0: self.combo_firmware.insertSeparator(self.combo_firmware.count()) # update combo_plugin if len(self.plugin_infos) > 0: self.combo_plugin.addItem(SELECT) self.combo_plugin.insertSeparator(self.combo_plugin.count()) for plugin_info in sorted(self.plugin_infos.values(), key=lambda x: x.name): name = '{0} ({1}.{2}.{3})'.format(plugin_info.name, *plugin_info.firmware_version_latest) self.combo_plugin.addItem(name, plugin_info.url_part) if self.combo_plugin.count() > 0: self.combo_plugin.insertSeparator(self.combo_plugin.count()) self.combo_firmware.addItem(CUSTOM) self.firmware_changed(0) self.combo_plugin.addItem(CUSTOM) self.plugin_changed(0) self.update_ui_state() def refresh_firmware_info(self, url_part, latest_version): name = url_part if name in ['dc', 'imu']: name = name.upper() else: words = name.split('_') parts = [] for word in words: parts.append(word[0].upper() + word[1:]) name = ' '.join(parts) firmware_info = infos.FirmwareInfo() firmware_info.name = name firmware_info.url_part = url_part firmware_info.firmware_version_latest = latest_version self.firmware_infos[url_part] = firmware_info def refresh_plugin_info(self, url_part, latest_version): name = url_part if name in ['gps', 'ptc']: name = name.upper() elif name.startswith('lcd_'): name = name.replace('lcd_', 'LCD_') if url_part.startswith('lcd_20x4_'): name = name.replace('_v11', '_1.1').replace('_v12', '_1.2') elif name.startswith('io'): name = name.replace('io', 'IO-') elif name.endswith('_ir'): name = name.replace('_ir', '_IR') elif name.endswith('_us'): name = name.replace('_us', '_US') elif name.startswith('led_'): name = name.replace('led_', 'LED_') elif name.endswith('_v2'): name = name.replace('_v2', '_2.0') words = name.split('_') parts = [] for word in words: parts.append(word[0].upper() + word[1:]) name = ' '.join(parts) name = name.replace('Voltage Current', 'Voltage/Current') name = name.replace('Nfc Rfid', 'NFC/RFID') name = name.replace('0 20ma', '0-20mA') plugin_info = infos.PluginInfo() plugin_info.name = name plugin_info.url_part = url_part plugin_info.firmware_version_latest = latest_version self.plugin_infos[url_part] = plugin_info def update_bricks(self): self.brick_infos = [] self.combo_brick.clear() items = {} for info in infos.get_brick_infos(): items[info.get_combo_item()] = info for item in sorted(items.keys()): self.brick_infos.append(items[item]) self.combo_brick.addItem(item) if self.combo_brick.count() == 0: self.combo_brick.addItem(NO_BRICK) self.update_ui_state() def create_progress_bar(self, title): progress = QProgressDialog(self) progress.setAutoClose(False) progress.setWindowTitle(title) progress.setCancelButton(None) progress.setWindowModality(Qt.WindowModal) return progress def popup_ok(self, title, message): QMessageBox.information(self, title, message, QMessageBox.Ok) def popup_fail(self, title, message): QMessageBox.critical(self, title, message, QMessageBox.Ok) def refresh_serial_ports(self): progress = self.create_progress_bar('Discovering') current_text = self.combo_serial_port.currentText() self.combo_serial_port.clear() try: progress.setLabelText('Discovering serial ports') progress.setMaximum(0) progress.setValue(0) progress.show() ports = get_serial_ports() except: progress.cancel() self.combo_serial_port.addItem(NO_BOOTLOADER) self.update_ui_state() self.popup_fail('Brick', 'Could not discover serial ports') else: preferred_index = None for port in ports: if preferred_index is None: if 'ttyACM' in port[0] or \ 'ttyUSB' in port[0] or \ 'usbmodemfd' in port[0] or \ 'AT91 USB to Serial Converter' in port[1] or \ 'GPS Camera Detect' in port[1]: preferred_index = self.combo_serial_port.count() if len(port[1]) > 0 and port[0] != port[1]: self.combo_serial_port.addItem(u'{0} - {1}'.format(port[0], port[1]), port[0]) else: self.combo_serial_port.addItem(port[0], port[0]) if self.combo_serial_port.count() == 0: self.combo_serial_port.addItem(NO_BOOTLOADER) elif preferred_index is not None: self.combo_serial_port.setCurrentIndex(preferred_index) else: index = self.combo_serial_port.findText(current_text) if index >= 0: self.combo_serial_port.setCurrentIndex(index) self.update_ui_state() progress.cancel() def update_ui_state(self): is_firmware_select = self.combo_firmware.currentText() == SELECT is_firmware_custom = self.combo_firmware.currentText() == CUSTOM is_no_bootloader = self.combo_serial_port.currentText() == NO_BOOTLOADER has_bricklet_ports = self.combo_port.count() > 0 self.combo_serial_port.setEnabled(not is_no_bootloader) self.combo_port.setEnabled(has_bricklet_ports) self.combo_plugin.setEnabled(has_bricklet_ports and self.combo_plugin.count() > 1) self.button_firmware_save.setEnabled(not is_firmware_select and not is_no_bootloader) self.edit_custom_firmware.setEnabled(is_firmware_custom) self.button_firmware_browse.setEnabled(is_firmware_custom) self.edit_uid.setEnabled(has_bricklet_ports) self.button_uid_load.setEnabled(has_bricklet_ports) self.button_uid_save.setEnabled(has_bricklet_ports) is_plugin_select = self.combo_plugin.currentText() == SELECT is_plugin_custom = self.combo_plugin.currentText() == CUSTOM is_no_brick = self.combo_brick.currentText() == NO_BRICK self.combo_brick.setEnabled(not is_no_brick) self.button_plugin_save.setEnabled(not is_plugin_select and not is_no_brick) self.edit_custom_plugin.setEnabled(is_plugin_custom) self.button_plugin_browse.setEnabled(is_plugin_custom) self.tab_widget.setTabEnabled(2, len(self.brick_infos) > 0) def firmware_changed(self, index): self.update_ui_state() def firmware_browse_clicked(self): if len(self.edit_custom_firmware.text()) > 0: last_dir = os.path.dirname(os.path.realpath(self.edit_custom_firmware.text())) else: last_dir = get_home_path() filename = get_open_file_name(get_main_window(), 'Open Firmware', last_dir, '*.bin') if len(filename) > 0: self.edit_custom_firmware.setText(filename) def firmware_save_clicked(self): port_name = self.combo_serial_port.itemData(self.combo_serial_port.currentIndex()) try: samba = SAMBA(port_name) except SAMBAException as e: self.refresh_serial_ports() self.popup_fail('Brick', 'Could not connect to Brick: {0}'.format(str(e))) return except SerialException as e: self.refresh_serial_ports() self.popup_fail('Brick', str(e)[0].upper() + str(e)[1:]) return except: self.refresh_serial_ports() self.popup_fail('Brick', 'Could not connect to Brick') return progress = ProgressWrapper(self.create_progress_bar('Flashing')) samba.progress = progress current_text = self.combo_firmware.currentText() # Get firmware name = None version = None if current_text == SELECT: return elif current_text == CUSTOM: firmware_file_name = self.edit_custom_firmware.text() try: with open(firmware_file_name, 'rb') as f: firmware = f.read() except IOError: progress.cancel() self.popup_fail('Brick', 'Could not read firmware file') return else: url_part = self.combo_firmware.itemData(self.combo_firmware.currentIndex()) name = self.firmware_infos[url_part].name version = self.firmware_infos[url_part].firmware_version_latest progress.reset('Downloading {0} Brick firmware {1}.{2}.{3}'.format(name, *version), 0) response = None try: response = urllib2.urlopen(FIRMWARE_URL + 'bricks/{0}/brick_{0}_firmware_{1}_{2}_{3}.bin'.format(url_part, *version), timeout=10) except urllib2.URLError: pass beta = 5 while response is None and beta > 0: try: response = urllib2.urlopen(FIRMWARE_URL + 'bricks/{0}/brick_{0}_firmware_{2}_{3}_{4}_beta{1}.bin'.format(url_part, beta, *version), timeout=10) except urllib2.URLError: beta -= 1 if response is None: progress.cancel() self.popup_fail('Brick', 'Could not download {0} Brick firmware {1}.{2}.{3}'.format(name, *version)) return try: length = int(response.headers['Content-Length']) progress.setMaximum(length) progress.update(0) QApplication.processEvents() firmware = '' chunk = response.read(1024) while len(chunk) > 0: firmware += chunk progress.update(len(firmware)) chunk = response.read(1024) response.close() except urllib2.URLError: progress.cancel() self.popup_fail('Brick', 'Could not download {0} Brick firmware {1}.{2}.{3}'.format(name, *version)) return # Get IMU UID imu_uid = None imu_calibration = None lock_imu_calibration_pages = False if name == 'IMU': # IMU 1.0.9 and earlier have a bug in their flash locking that makes # them unlook the wrong pages. Therefore, the calibration pages # must not be locked for this versions if version[1] > 0 or (version[1] == 0 and version[2] > 9): lock_imu_calibration_pages = True try: imu_uid = base58encode(uid64_to_uid32(samba.read_uid64())) except SerialException as e: progress.cancel() self.popup_fail('Brick', 'Could read UID of IMU Brick: {0}'.format(str(e))) return except: progress.cancel() self.popup_fail('Brick', 'Could read UID of IMU Brick') return result = QMessageBox.question(self, 'IMU Brick', 'Restore factory calibration for IMU Brick [{0}] from tinkerforge.com?'.format(imu_uid), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) # Download IMU calibration if result == QMessageBox.Yes: progress.reset('Downloading factory calibration for IMU Brick', 0) try: imu_calibration_text = '' response = urllib2.urlopen(IMU_CALIBRATION_URL + '{0}.txt'.format(imu_uid), timeout=10) chunk = response.read(1024) while len(chunk) > 0: imu_calibration_text += chunk chunk = response.read(1024) response.close() except urllib2.HTTPError as e: if e.code == 404: imu_calibration_text = None self.popup_ok('IMU Brick', 'No factory calibration for IMU Brick [{0}] available'.format(imu_uid)) else: progress.cancel() self.popup_fail('IMU Brick', 'Could not download factory calibration for IMU Brick [{0}]'.format(imu_uid)) return except urllib2.URLError: progress.cancel() self.popup_fail('IMU Brick', 'Could not download factory calibration for IMU Brick [{0}]'.format(imu_uid)) return if imu_calibration_text is not None: if len(imu_calibration_text) == 0: progress.cancel() self.popup_fail('IMU Brick', 'Could not download factory calibration for IMU Brick [{0}]'.format(imu_uid)) return try: imu_calibration_matrix = parse_imu_calibration(imu_calibration_text) # Ensure proper temperature relation if imu_calibration_matrix[5][1][7] <= imu_calibration_matrix[5][1][3]: imu_calibration_matrix[5][1][7] = imu_calibration_matrix[5][1][3] + 1 imu_calibration_array = imu_calibration_matrix[0][1][:6] + \ imu_calibration_matrix[1][1][:3] + \ imu_calibration_matrix[2][1][:6] + \ imu_calibration_matrix[3][1][:3] + \ imu_calibration_matrix[4][1][:6] + \ imu_calibration_matrix[5][1][:8] imu_calibration = struct.pack('<32h', *imu_calibration_array) except: progress.cancel() self.popup_fail('IMU Brick', 'Could not parse factory calibration for IMU Brick [{0}]'.format(imu_uid)) return # Flash firmware def report_result(reboot_okay): if current_text == CUSTOM: if reboot_okay: message = 'Successfully restarted Brick!' else: message = 'Manual restart of Brick required!' else: if reboot_okay: message = 'Successfully restarted {0} Brick!'.format(name) else: message = 'Manual restart of {0} Brick required!'.format(name) if current_text == CUSTOM: self.popup_ok('Brick', 'Successfully flashed firmware.\n' + message) elif imu_calibration is not None: self.popup_ok('Brick', 'Successfully flashed {0} Brick firmware {1}.{2}.{3}.\n'.format(name, *version) + 'Successfully restored factory calibration.\n' + message) else: self.popup_ok('Brick', 'Successfully flashed {0} Brick firmware {1}.{2}.{3}.\n'.format(name, *version) + message) try: samba.flash(firmware, imu_calibration, lock_imu_calibration_pages) # close serial device before showing dialog, otherwise exchanging # the brick while the dialog is open will force it to show up as ttyACM1 samba = None progress.cancel() report_result(True) except SAMBARebootError as e: samba = None progress.cancel() self.refresh_serial_ports() report_result(False) except SAMBAException as e: samba = None progress.cancel() self.refresh_serial_ports() self.popup_fail('Brick', 'Could not flash Brick: {0}'.format(str(e))) except SerialException as e: samba = None progress.cancel() self.refresh_serial_ports() self.popup_fail('Brick', 'Could not flash Brick: {0}'.format(str(e))) except: samba = None progress.cancel() self.refresh_serial_ports() self.popup_fail('Brick', 'Could not flash Brick') def uid_save_clicked(self): device, port = self.current_device_and_port() uid = self.edit_uid.text() if len(uid) == 0: self.popup_fail('Bricklet', 'UID cannot be empty') return for c in uid: if c not in BASE58: self.popup_fail('Bricklet', "UID cannot contain '{0}'".format(c)) return try: if base58decode(uid) > 0xFFFFFFFF: self.popup_fail('Bricklet', 'UID is too long') return except: self.popup_fail('Bricklet', 'UID is invalid') return try: self.parent.ipcon.write_bricklet_uid(device, port, uid) except Error as e: self.popup_fail('Bricklet', 'Could not write UID: ' + error_to_name(e)) return try: uid_read = self.parent.ipcon.read_bricklet_uid(device, port) except Error as e: self.popup_fail('Bricklet', 'Could not read written UID: ' + error_to_name(e)) return if uid == uid_read: self.popup_ok('Bricklet', 'Successfully wrote UID.\nNew UID will be used after reset of the connected Brick.') else: self.popup_fail('Bricklet', 'Could not write UID: Verification failed') def uid_load_clicked(self): device, port = self.current_device_and_port() try: uid = self.parent.ipcon.read_bricklet_uid(device, port) except Error as e: self.edit_uid.setText('') self.popup_fail('Bricklet', 'Could not read UID: ' + error_to_name(e)) return self.edit_uid.setText(uid) def brick_changed(self, index): self.combo_port.clear() if index < 0 or len(self.brick_infos) == 0: self.combo_port.addItems(['A', 'B', 'C', 'D']) return brick_info = self.brick_infos[index] for key in sorted(brick_info.bricklets.keys()): bricklet_info = brick_info.bricklets[key] if bricklet_info is None: self.combo_port.addItem(key.upper()) else: name = '{0}: {1}'.format(key.upper(), bricklet_info.get_combo_item()) self.combo_port.addItem(name, bricklet_info.url_part) self.update_ui_state() def port_changed(self, index): self.edit_uid.setText('') if index < 0: self.combo_plugin.setCurrentIndex(0) return url_part = self.combo_port.itemData(index) if url_part == None or len(url_part) == 0: self.combo_plugin.setCurrentIndex(0) return i = self.combo_plugin.findData(url_part) if i < 0: self.combo_plugin.setCurrentIndex(0) else: self.combo_plugin.setCurrentIndex(i) b = self.combo_brick.currentIndex() p = self.combo_port.currentIndex() if b < 0 or p < 0: return self.edit_uid.setText(self.brick_infos[b].bricklets[('a', 'b', 'c', 'd')[p]].uid) def plugin_changed(self, index): self.update_ui_state() def download_bricklet_plugin(self, progress, url_part, name, version, popup=False): progress.setLabelText('Downloading {0} Bricklet plugin {1}.{2}.{3}'.format(name, *version)) progress.setMaximum(0) progress.show() response = None try: response = urllib2.urlopen(FIRMWARE_URL + 'bricklets/{0}/bricklet_{0}_firmware_{1}_{2}_{3}.bin'.format(url_part, *version), timeout=10) except urllib2.URLError: pass beta = 5 while response is None and beta > 0: try: response = urllib2.urlopen(FIRMWARE_URL + 'bricklets/{0}/bricklet_{0}_firmware_{2}_{3}_{4}_beta{1}.bin'.format(url_part, beta, *version), timeout=10) except urllib2.URLError: beta -= 1 if response is None: progress.cancel() if popup: self.popup_fail('Bricklet', 'Could not download {0} Bricklet plugin {1}.{2}.{3}'.format(name, *version)) return None try: length = int(response.headers['Content-Length']) progress.setMaximum(length) progress.setValue(0) QApplication.processEvents() plugin = [] chunk = response.read(256) while len(chunk) > 0: plugin += map(ord, chunk) # Convert plugin to list of bytes progress.setValue(len(plugin)) chunk = response.read(256) response.close() except urllib2.URLError: progress.cancel() if popup: self.popup_fail('Bricklet', 'Could not download {0} Bricklet plugin {1}.{2}.{3}'.format(name, *version)) return None return plugin def write_bricklet_plugin(self, plugin, device, port, name, progress, popup=True): # Write progress.setLabelText('Writing plugin: ' + name) progress.setMaximum(0) progress.setValue(0) progress.show() plugin_chunks = [] offset = 0 while offset < len(plugin): chunk = plugin[offset:offset + IPConnection.PLUGIN_CHUNK_SIZE] if len(chunk) < IPConnection.PLUGIN_CHUNK_SIZE: chunk += [0] * (IPConnection.PLUGIN_CHUNK_SIZE - len(chunk)) plugin_chunks.append(chunk) offset += IPConnection.PLUGIN_CHUNK_SIZE progress.setMaximum(len(plugin_chunks)) position = 0 for chunk in plugin_chunks: try: self.parent.ipcon.write_bricklet_plugin(device, port, position, chunk) except Error as e: progress.cancel() if popup: self.popup_fail('Bricklet', 'Could not write Bricklet plugin: ' + error_to_name(e)) return False position += 1 progress.setValue(position) time.sleep(0.015) QApplication.processEvents() time.sleep(0.1) # Verify progress.setLabelText('Verifying written plugin: ' + name) progress.setMaximum(len(plugin_chunks)) progress.setValue(0) progress.show() time.sleep(0.1) position = 0 for chunk in plugin_chunks: try: read_chunk = list(self.parent.ipcon.read_bricklet_plugin(device, port, position)) except Error as e: progress.cancel() if popup: self.popup_fail('Bricklet', 'Could not read Bricklet plugin back for verification: ' + error_to_name(e)) return False if read_chunk != chunk: progress.cancel() if popup: self.popup_fail('Bricklet', 'Could not flash Bricklet plugin: Verification error') return False position += 1 progress.setValue(position) time.sleep(0.015) QApplication.processEvents() return True def plugin_save_clicked(self): progress = self.create_progress_bar('Flashing') current_text = self.combo_plugin.currentText() # Get plugin if current_text == SELECT: return elif current_text == CUSTOM: plugin_file_name = self.edit_custom_plugin.text() try: with open(plugin_file_name, 'rb') as f: plugin = map(ord, f.read()) # Convert plugin to list of bytes except IOError: progress.cancel() self.popup_fail('Bricklet', 'Could not read plugin file') return else: url_part = self.combo_plugin.itemData(self.combo_plugin.currentIndex()) name = self.plugin_infos[url_part].name version = self.plugin_infos[url_part].firmware_version_latest plugin = self.download_bricklet_plugin(progress, url_part, name, version) if not plugin: return # Flash plugin device, port = self.current_device_and_port() if current_text == CUSTOM: if not self.write_bricklet_plugin(plugin, device, port, os.path.split(plugin_file_name)[-1], progress): return else: if not self.write_bricklet_plugin(plugin, device, port, name, progress): return progress.cancel() if current_text == CUSTOM: self.popup_ok('Bricklet', 'Successfully flashed plugin.\nNew plugin will be used after reset of the connected Brick.') else: self.popup_ok('Bricklet', 'Successfully flashed {0} Bricklet plugin {1}.{2}.{3}.\nNew plugin will be used after reset of the connected Brick.'.format(name, *version)) def current_device_and_port(self): port_names = ['a', 'b', 'c', 'd'] return (self.current_device(), port_names[self.combo_port.currentIndex()]) def current_device(self): try: return self.brick_infos[self.combo_brick.currentIndex()].plugin.device except: return None def plugin_browse_clicked(self): last_dir = get_home_path() if len(self.edit_custom_plugin.text()) > 0: last_dir = os.path.dirname(os.path.realpath(self.edit_custom_plugin.text())) filename = get_open_file_name(get_main_window(), 'Open Plugin', last_dir, '*.bin') if len(filename) > 0: self.edit_custom_plugin.setText(filename) def auto_update_bricklets_clicked(self): def brick_for_bricklet(bricklet): for device_info in infos.get_brick_infos(): if bricklet.position in device_info.bricklets and \ device_info.bricklets[bricklet.position] == bricklet: return device_info progress = self.create_progress_bar('Auto-Updating Bricklets') bricks_to_reset = set() for device_info in infos.get_device_infos(): if device_info.type == 'bricklet': if device_info.protocol_version == 2 and device_info.firmware_version_installed < device_info.firmware_version_latest: plugin = self.download_bricklet_plugin(progress, device_info.url_part, device_info.name, device_info.firmware_version_latest) if not plugin: progress.cancel() self.refresh_updates_clicked() return brick = brick_for_bricklet(device_info) if self.write_bricklet_plugin(plugin, brick.plugin.device, device_info.position, device_info.name, progress): bricks_to_reset.add(brick) else: progress.cancel() self.refresh_updates_clicked() return elif device_info.type == 'brick': for port in device_info.bricklets: if not device_info.bricklets[port]: continue if device_info.bricklets[port].protocol_version == 1 and \ device_info.bricklets[port].firmware_version_installed < device_info.bricklets[port].firmware_version_latest: plugin = self.download_bricklet_plugin(progress, device_info.bricklets[port].url_part, device_info.bricklets[port].name, device_info.bricklets[port].firmware_version_latest) if not plugin: progress.cancel() self.refresh_updates_clicked() return brick = brick_for_bricklet(device_info.bricklets[port]) if self.write_bricklet_plugin(plugin, brick.plugin.device, port, device_info.bricklets[port].name, progress): bricks_to_reset.add(brick) else: progress.cancel() self.refresh_updates_clicked() return for brick in bricks_to_reset: try: brick.plugin.device.reset() except: pass progress.setLabelText('Waiting for Bricks to reset') progress.setMaximum(400) progress.setValue(0) for i in range(400): time.sleep(0.03) progress.setValue(i) progress.cancel() def tab_changed(self, i): if i == 0 and self.refresh_updates_pending: self.refresh_updates_clicked() elif i == 2: self.brick_changed(self.combo_brick.currentIndex()) self.port_changed(self.combo_port.currentIndex()) def refresh_updates_clicked(self): if self.tab_widget.currentIndex() != 0: self.refresh_updates_pending = True return self.update_button_refresh.setDisabled(True) self.refresh_updates_pending = False url_part_proto1_map = { # 'name': 'url_part' 'Ambient Light Bricklet': 'ambient_light', 'Analog In Bricklet': 'analog_in', 'Analog Out Bricklet': 'analog_out', 'Barometer Bricklet': 'barometer', 'Current12 Bricklet': 'current12', 'Current25 Bricklet': 'current25', 'Distance IR Bricklet': 'distance_ir', 'Dual Relay Bricklet': 'dual_relay', 'GPS Bricklet': 'gps', 'Humidity Bricklet': 'humidity', 'Industrial Digital In 4 Bricklet': 'industrial_digital_in_4', 'Industrial Digital Out 4 Bricklet': 'industrial_digital_out_4', 'Industrial Quad Relay Bricklet': 'industrial_quad_relay', 'IO-16 Bricklet': 'io16', 'IO-4 Bricklet': 'io4', 'Joystick Bricklet': 'joystick', 'LCD 16x2 Bricklet': 'lcd_16x2', 'LCD 20x4 Bricklet': 'lcd_20x4_v11', 'Linear Poti Bricklet': 'linear_poti', 'Piezo Buzzer Bricklet': 'piezo_buzzer', 'Rotary Poti Bricklet': 'rotary_poti', 'Temperature Bricklet': 'temperature', 'Temperature-IR Bricklet': 'temperature_ir', 'Voltage Bricklet': 'voltage', 'Voltage/Current Bricklet': 'voltage_current', } progress = self.create_progress_bar('Discovering') okay = True try: urllib2.urlopen(FIRMWARE_URL, timeout=10).read() self.no_connection_label.hide() except urllib2.URLError: okay = False progress.cancel() self.no_connection_label.show() return if okay: self.refresh_latest_version_info(progress) def get_color_for_device(device): if device.firmware_version_installed >= device.firmware_version_latest: return None, False if device.firmware_version_installed[0] <= 1: return QBrush(Qt.red), True return QBrush(QColor(255, 160, 55)), True try: infos.get_info(infos.UID_BRICKV).firmware_version_latest = self.tool_infos['brickv'].firmware_version_latest except: infos.get_info(infos.UID_BRICKV).firmware_version_latest = (0, 0, 0) for device_info in infos.get_device_infos(): if device_info.type == 'brick': try: device_info.firmware_version_latest = self.firmware_infos[device_info.url_part].firmware_version_latest except: device_info.firmware_version_latest = (0, 0, 0) elif device_info.type == 'bricklet': try: device_info.firmware_version_latest = self.plugin_infos[device_info.url_part].firmware_version_latest except: device_info.firmware_version_latest = (0, 0, 0) progress.cancel() self.update_tree_view_model.clear() self.update_tree_view_model.setHorizontalHeaderLabels(self.update_tree_view_model_labels) is_update = False protocol1_errors = set() items = [] for device_info in infos.get_infos(): if device_info.type == 'brick': parent = [QStandardItem(device_info.name), QStandardItem(device_info.uid), QStandardItem(get_version_string(device_info.firmware_version_installed)), QStandardItem(get_version_string(device_info.firmware_version_latest))] color, update = get_color_for_device(device_info) if update: is_update = True for item in parent: item.setFlags(item.flags() & ~Qt.ItemIsEditable) item.setData(color, Qt.BackgroundRole) parent[0].setData(device_info.uid, Qt.UserRole) items.append(parent) for port in device_info.bricklets: if not device_info.bricklets[port] or device_info.bricklets[port].protocol_version == 1: try: protv, fw, name = device_info.plugin.device.get_protocol1_bricklet_name(port) except: protocol1_errors.add(device_info.uid) child = [QStandardItem(port.upper() + ': Protocol 1.0 Bricklet with Error'), QStandardItem(''), QStandardItem(''), QStandardItem('')] for item in child: item.setFlags(item.flags() & ~Qt.ItemIsEditable) item.setData(QBrush(Qt.magenta), Qt.BackgroundRole) parent[0].appendRow(child) continue if protv == 1: # Hack for LCD 20x4 Bricklet (name is not set early enough in firmware) if fw == (1, 1, 1) and name == '': name = 'LCD 20x4 Bricklet' bricklet_info = infos.BrickletInfo() bricklet_info.protocol_version = 1 bricklet_info.name = name bricklet_info.position = port bricklet_info.firmware_version_installed = tuple(fw) device_info.bricklets[port] = bricklet_info for key in url_part_proto1_map: if key in device_info.bricklets[port].name: bricklet_info.url_part = url_part_proto1_map[key] break try: bricklet_info.firmware_version_latest = self.plugin_infos[bricklet_info.url_part].firmware_version_latest except KeyError: pass if device_info.bricklets[port]: child = [QStandardItem(port.upper() + ': ' + device_info.bricklets[port].name), QStandardItem(device_info.bricklets[port].uid), QStandardItem(get_version_string(device_info.bricklets[port].firmware_version_installed)), QStandardItem(get_version_string(device_info.bricklets[port].firmware_version_latest))] color, update = get_color_for_device(device_info.bricklets[port]) if update: is_update = True for item in child: item.setFlags(item.flags() & ~Qt.ItemIsEditable) item.setData(color, Qt.BackgroundRole) parent[0].appendRow(child) elif device_info.type == 'tool' and 'Brick Viewer' in device_info.name: parent = [QStandardItem(device_info.name), QStandardItem(''), QStandardItem(get_version_string(device_info.firmware_version_installed)), QStandardItem(get_version_string(device_info.firmware_version_latest))] color, update = get_color_for_device(device_info) if update: self.update_tool_label.show() else: self.update_tool_label.hide() for item in parent: item.setFlags(item.flags() & ~Qt.ItemIsEditable) item.setData(color, Qt.BackgroundRole) items.append(parent) t = 0 if len(protocol1_errors) > 0: # if there were protocol1 errors give the enumerate callback a # chance to update the infos to have correct information to filter # out false-positive protocol1 errors that were detected due to # fast USB unplug t = 200 QTimer.singleShot(t, lambda: self.refresh_updates_clicked_second_step(is_update, items, protocol1_errors)) def refresh_updates_clicked_second_step(self, is_update, items, protocol1_errors): protocol1_error_still_there = False # filter out false-positive protocol1 errors for device_uid in protocol1_errors: if infos.get_info(device_uid) != None: protocol1_error_still_there = True continue for i in range(len(items)): if items[i][0].data(Qt.UserRole) == device_uid: del items[i] break for item in items: self.update_tree_view_model.appendRow(item) self.update_tree_view.expandAll() self.update_tree_view.setColumnWidth(0, 260) self.update_tree_view.setColumnWidth(1, 75) self.update_tree_view.setColumnWidth(2, 75) self.update_tree_view.setColumnWidth(3, 75) self.update_tree_view.setSortingEnabled(True) self.update_tree_view.header().setSortIndicator(0, Qt.AscendingOrder) if is_update: self.update_button_bricklets.setEnabled(True) else: self.update_button_bricklets.setEnabled(False) self.brick_changed(self.combo_brick.currentIndex()) self.update_button_refresh.setDisabled(False) if protocol1_error_still_there: message = """ There was an error during the auto-detection of Bricklets with Protocol 1.0 plugins. Those cannot be updated automatically, but you can update them manually: - Disconnect the affected Bricklets from their Brick and restart the Brick without the Bricklets. - Ensure that the Brick shows up correctly. - Connect the Bricklet to the Brick again, while the Brick is already running. - Select the "Bricklet" tab and update the plugin manually. """ QMessageBox.critical(self, "Bricklet with Error", message, QMessageBox.Ok)
def get_gds_model(progress=lambda val: None): """ Initialize and return a GDS datasets model. :param progress: A progress callback. :rval tuple: A tuple of (QStandardItemModel, geo.GDSInfo, [geo.GDS]) .. note:: The returned QStandardItemModel's thread affinity is set to the GUI thread. """ progress(1) info = geo.GDSInfo() search_keys = ["dataset_id", "title", "platform_organism", "description"] cache_dir = serverfiles.localpath(geo.DOMAIN) gds_link = "http://www.ncbi.nlm.nih.gov/sites/GDSbrowser?acc={0}" pm_link = "http://www.ncbi.nlm.nih.gov/pubmed/{0}" gds_list = [] def is_cached(gds): return os.path.exists(os.path.join(cache_dir, gds["dataset_id"]) + ".soft.gz") def item(displayvalue, item_values={}): item = QStandardItem() item.setData(displayvalue, Qt.DisplayRole) for role, value in item_values.items(): item.setData(value, role) return item def gds_to_row(gds): #: Text for easier full search. search_text = " | ".join([gds.get(key, "").lower() for key in search_keys]) row = [ item(" " if is_cached(gds) else "", {TextFilterRole: search_text}), item(gds["dataset_id"], {LinkRole: gds_link.format(gds["dataset_id"])}), item(gds["title"]), item(gds["platform_organism"]), item(len(gds["samples"])), item(gds["feature_count"]), item(gds["gene_count"]), item(len(gds["subsets"])), item(gds.get("pubmed_id", ""), {LinkRole: pm_link.format(gds["pubmed_id"]) if gds.get("pubmed_id") else None}) ] return row model = QStandardItemModel() model.setHorizontalHeaderLabels( ["", "ID", "Title", "Organism", "Samples", "Features", "Genes", "Subsets", "PubMedID"] ) progress(20) for gds in info.values(): model.appendRow(gds_to_row(gds)) gds_list.append(gds) progress(50) if QThread.currentThread() is not QCoreApplication.instance().thread(): model.moveToThread(QCoreApplication.instance().thread()) return model, info, gds_list
class OWTestLearners(widget.OWWidget): name = "Test Learners" description = "" icon = "icons/TestLearners1.svg" priority = 100 inputs = [("Learner", Orange.classification.Learner, "set_learner", widget.Multiple), ("Data", Orange.data.Table, "set_train_data", widget.Default), ("Test Data", Orange.data.Table, "set_test_data")] outputs = [("Evaluation Results", testing.Results)] #: Resampling/testing types KFold, LeaveOneOut, Bootstrap, TestOnTrain, TestOnTest = 0, 1, 2, 3, 4 #: Selected resampling type resampling = settings.Setting(0) #: Number of folds for K-fold cross validation k_folds = settings.Setting(10) #: Number of repeats for bootstrap sampling n_repeat = settings.Setting(10) #: Bootstrap sampling p sample_p = settings.Setting(75) def __init__(self, parent=None): super().__init__(parent) self.train_data = None self.test_data = None #: An Ordered dictionary with current inputs and their testing #: results. self.learners = OrderedDict() sbox = gui.widgetBox(self.controlArea, "Sampling") rbox = gui.radioButtons( sbox, self, "resampling", callback=self._param_changed ) gui.appendRadioButton(rbox, "Cross validation") ibox = gui.indentedBox(rbox) gui.spin(ibox, self, "k_folds", 2, 50, label="Number of folds:", callback=self.kfold_changed) gui.appendRadioButton(rbox, "Leave one out") gui.appendRadioButton(rbox, "Random sampling") ibox = gui.indentedBox(rbox) gui.spin(ibox, self, "n_repeat", 2, 50, label="Repeat train/test", callback=self.bootstrap_changed) gui.widgetLabel(ibox, "Relative training set size:") gui.hSlider(ibox, self, "sample_p", minValue=1, maxValue=100, ticks=20, vertical=False, labelFormat="%d %%", callback=self.bootstrap_changed) gui.appendRadioButton(rbox, "Test on train data") gui.appendRadioButton(rbox, "Test on test data") rbox.layout().addSpacing(5) gui.button(rbox, self, "Apply", callback=self.apply) gui.rubber(self.controlArea) self.view = QTreeView( rootIsDecorated=False, uniformRowHeights=True, wordWrap=True, editTriggers=QTreeView.NoEditTriggers ) header = self.view.header() header.setResizeMode(QHeaderView.ResizeToContents) header.setDefaultAlignment(Qt.AlignCenter) header.setStretchLastSection(False) self.result_model = QStandardItemModel() self.view.setModel(self.result_model) self.view.setItemDelegate(ItemDelegate()) self._update_header() box = gui.widgetBox(self.mainArea, "Evaluation Results") box.layout().addWidget(self.view) def set_learner(self, learner, key): if key in self.learners and learner is None: del self.learners[key] else: self.learners[key] = Input(learner, None, ()) self._update_stats_model() def set_train_data(self, data): self.error(0) if data is not None: if data.domain.class_var is None: self.error(0, "Train data input requires a class variable") data = None self.train_data = data self._update_header() self._invalidate() def set_test_data(self, data): self.error(1) if data is not None: if data.domain.class_var is None: self.error(1, "Test data input requires a class variable") data = None self.test_data = data if self.resampling == OWTestLearners.TestOnTest: self._invalidate() def handleNewSignals(self): self.update_results() self.commit() def kfold_changed(self): self.resampling = OWTestLearners.KFold self._param_changed() def bootstrap_changed(self): self.resampling = OWTestLearners.Bootstrap self._param_changed() def _param_changed(self): self._invalidate() def update_results(self): self.warning([1, 2]) self.error(2) if self.train_data is None: return if self.resampling == OWTestLearners.TestOnTest: if self.test_data is None: self.warning(2, "Missing separate test data input") return elif self.test_data.domain.class_var != \ self.train_data.domain.class_var: self.error(2, ("Inconsistent class variable between test " + "and train data sets")) return # items in need of an update items = [(key, input) for key, input in self.learners.items() if input.results is None] learners = [input.learner for _, input in items] self.setStatusMessage("Running") if self.test_data is not None and \ self.resampling != OWTestLearners.TestOnTest: self.warning(1, "Test data is present but unused. " "Select 'Test on test data' to use it.") # TODO: Test each learner individually if self.resampling == OWTestLearners.KFold: results = testing.CrossValidation( self.train_data, learners, k=self.k_folds, store_data=True ) elif self.resampling == OWTestLearners.LeaveOneOut: results = testing.LeaveOneOut( self.train_data, learners, store_data=True ) elif self.resampling == OWTestLearners.Bootstrap: p = self.sample_p / 100.0 results = testing.Bootstrap( self.train_data, learners, n_resamples=self.n_repeat, p=p, store_data=True ) elif self.resampling == OWTestLearners.TestOnTrain: results = testing.TestOnTrainingData( self.train_data, learners, store_data=True ) elif self.resampling == OWTestLearners.TestOnTest: if self.test_data is None: return results = testing.TestOnTestData( self.train_data, self.test_data, learners, store_data=True ) else: assert False results = list(split_by_model(results)) class_var = self.train_data.domain.class_var if is_discrete(class_var): test_stats = classification_stats else: test_stats = regression_stats self._update_header() stats = [test_stats(res) for res in results] for (key, input), res, stat in zip(items, results, stats): self.learners[key] = input._replace(results=res, stats=stat) self.setStatusMessage("") self._update_stats_model() def _update_header(self): headers = ["Method"] if self.train_data is not None: if is_discrete(self.train_data.domain.class_var): headers.extend(classification_stats.headers) else: headers.extend(regression_stats.headers) for i in reversed(range(len(headers), self.result_model.columnCount())): self.result_model.takeColumn(i) self.result_model.setHorizontalHeaderLabels(headers) def _update_stats_model(self): model = self.view.model() for r in reversed(range(model.rowCount())): model.takeRow(r) for input in self.learners.values(): name = learner_name(input.learner) row = [] head = QStandardItem() head.setData(name, Qt.DisplayRole) row.append(head) for stat in input.stats: item = QStandardItem() item.setData(" {:.3f} ".format(stat[0]), Qt.DisplayRole) row.append(item) model.appendRow(row) def _invalidate(self, which=None): if which is None: which = self.learners.keys() all_keys = list(self.learners.keys()) model = self.view.model() for key in which: self.learners[key] = \ self.learners[key]._replace(results=None, stats=None) if key in self.learners: row = all_keys.index(key) for c in range(1, model.columnCount()): item = model.item(row, c) if item is not None: item.setData(None, Qt.DisplayRole) def apply(self): self.update_results() self.commit() def commit(self): results = [val.results for val in self.learners.values() if val.results is not None] if results: combined = results_merge(results) combined.learner_names = [learner_name(val.learner) for val in self.learners.values()] else: combined = None self.send("Evaluation Results", combined)
class MainWindow(QMainWindow, Ui_MainWindow): qtcb_enumerate = pyqtSignal(str, str, 'char', type((0,)), type((0,)), int, int) qtcb_connected = pyqtSignal(int) qtcb_disconnected = pyqtSignal(int) def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setupUi(self) self.setWindowIcon(QIcon(os.path.join(get_program_path(), "brickv-icon.png"))) signal.signal(signal.SIGINT, self.exit_brickv) signal.signal(signal.SIGTERM, self.exit_brickv) self.async_thread = async_start_thread(self) self.setWindowTitle("Brick Viewer " + config.BRICKV_VERSION) self.tree_view_model_labels = ['Name', 'UID', 'FW Version'] self.tree_view_model = QStandardItemModel() self.tree_view.setModel(self.tree_view_model) self.tree_view.doubleClicked.connect(self.item_double_clicked) self.set_tree_view_defaults() # Remove dummy tab self.tab_widget.removeTab(1) self.last_tab = 0 self.name = '<unknown>' self.uid = '<unknown>' self.version = (0, 0, 0) self.disconnect_times = [] self.qtcb_enumerate.connect(self.cb_enumerate) self.qtcb_connected.connect(self.cb_connected) self.qtcb_disconnected.connect(self.cb_disconnected) self.ipcon = IPConnection() self.ipcon.set_auto_reauthenticate(False) self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.qtcb_enumerate.emit) self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.qtcb_connected.emit) self.ipcon.register_callback(IPConnection.CALLBACK_DISCONNECTED, self.qtcb_disconnected.emit) self.flashing_window = None self.advanced_window = None self.delayed_refresh_updates_timer = QTimer() self.delayed_refresh_updates_timer.timeout.connect(self.delayed_refresh_updates) self.delayed_refresh_updates_timer.setInterval(500) self.reset_view() self.button_advanced.setDisabled(True) self.tab_widget.currentChanged.connect(self.tab_changed) self.button_connect.pressed.connect(self.connect_pressed) self.button_flashing.pressed.connect(self.flashing_pressed) self.button_advanced.pressed.connect(self.advanced_pressed) self.plugin_manager = PluginManager() self.combo_host.addItem(config.get_host()) self.combo_host.addItems(config.get_host_history(HOST_HISTORY_SIZE - 1)) self.spinbox_port.setValue(config.get_port()) self.last_host = self.combo_host.currentText() self.last_port = self.spinbox_port.value() self.checkbox_authentication.stateChanged.connect(self.authentication_state_changed) self.label_secret.hide() self.edit_secret.hide() self.edit_secret.setEchoMode(QLineEdit.Password) self.checkbox_secret_show.hide() self.checkbox_secret_show.stateChanged.connect(self.secret_show_state_changed) self.checkbox_remember_secret.hide() if config.get_use_authentication(): self.checkbox_authentication.setCheckState(Qt.Checked) if config.get_remember_secret(): self.edit_secret.setText(config.get_secret()) self.checkbox_remember_secret.setCheckState(Qt.Checked) self.label_auto_reconnects.hide() self.auto_reconnects = 0 def closeEvent(self, event): self.exit_brickv() def exit_brickv(self, signl=None, frme=None): try: uid = self.tab_widget.widget(self.last_tab)._uid infos.infos[uid].plugin.stop() except: pass host = str(self.combo_host.currentText()) history = [] for i in range(self.combo_host.count()): h = str(self.combo_host.itemText(i)) if h != host and h not in history: history.append(h) config.set_host(host) config.set_host_history(history[:HOST_HISTORY_SIZE - 1]) config.set_port(self.spinbox_port.value()) config.set_use_authentication(self.checkbox_authentication.isChecked()) remember_secret = self.checkbox_remember_secret.isChecked() config.set_remember_secret(remember_secret) if remember_secret: config.set_secret(str(self.edit_secret.text())) else: config.set_secret(config.DEFAULT_SECRET) self.reset_view() try: self.ipcon.disconnect() except: pass if signl != None and frme != None: print "Received SIGINT or SIGTERM, shutting down." sys.exit() def start(self): pass def stop(self): pass def destroy(self): pass def authentication_state_changed(self, state): visible = state == Qt.Checked self.label_secret.setVisible(visible) self.edit_secret.setVisible(visible) self.checkbox_secret_show.setVisible(visible) self.checkbox_remember_secret.setVisible(visible) def secret_show_state_changed(self, state): if state == Qt.Checked: self.edit_secret.setEchoMode(QLineEdit.Normal) else: self.edit_secret.setEchoMode(QLineEdit.Password) def tab_changed(self, i): try: uid = self.tab_widget.widget(i)._uid infos.infos[uid].plugin.start() except: pass try: uid = self.tab_widget.widget(self.last_tab)._uid infos.infos[uid].plugin.stop() except: pass self.last_tab = i def reset_view(self): self.tab_widget.setCurrentIndex(0) keys_to_remove = [] for key in infos.infos: if infos.infos[key].type in ('brick', 'bricklet'): try: infos.infos[key].plugin.stop() except: pass try: infos.infos[key].plugin.destroy() except: pass keys_to_remove.append(key) for key in keys_to_remove: try: infos.infos.pop(key) except: pass for i in reversed(range(1, self.tab_widget.count())): self.tab_widget.removeTab(i) self.update_tree_view() def do_disconnect(self): self.auto_reconnects = 0 self.label_auto_reconnects.hide() self.reset_view() async_next_session() try: self.ipcon.disconnect() except: pass def do_authenticate(self, is_auto_reconnect): if not self.checkbox_authentication.isChecked(): return True try: secret = str(self.edit_secret.text()).encode('ascii') except: self.do_disconnect() QMessageBox.critical(self, 'Connection', 'Authentication secret cannot contain non-ASCII characters.', QMessageBox.Ok) return False self.ipcon.set_auto_reconnect(False) # don't auto-reconnect on authentication error try: self.ipcon.authenticate(secret) except: self.do_disconnect() if is_auto_reconnect: extra = ' after auto-reconnect' else: extra = '' QMessageBox.critical(self, 'Connection', 'Could not authenticate' + extra + '. Check secret and ensure ' + 'authentication for Brick Daemon is enabled.', QMessageBox.Ok) return False self.ipcon.set_auto_reconnect(True) return True def flashing_pressed(self): first = False if self.flashing_window is None: first = True self.flashing_window = FlashingWindow(self) self.update_flashing_window() self.flashing_window.show() self.flashing_window.refresh_updates_pressed() def advanced_pressed(self): if self.advanced_window is None: self.advanced_window = AdvancedWindow(self) self.update_advanced_window() self.advanced_window.show() def connect_pressed(self): if self.ipcon.get_connection_state() == IPConnection.CONNECTION_STATE_DISCONNECTED: try: self.last_host = self.combo_host.currentText() self.last_port = self.spinbox_port.value() self.button_connect.setDisabled(True) self.button_connect.setText("Connecting ...") self.button_connect.repaint() QApplication.processEvents() self.ipcon.connect(self.last_host, self.last_port) except: self.button_connect.setDisabled(False) self.button_connect.setText("Connect") QMessageBox.critical(self, 'Connection', 'Could not connect. Please check host, check ' + 'port and ensure that Brick Daemon is running.') else: self.do_disconnect() def item_double_clicked(self, index): text = str(index.data().toString()) i = self.tab_for_uid(text) if i > 0: self.tab_widget.setCurrentIndex(i) def connected_uid_pressed(self, connected_uid): i = self.tab_for_uid(connected_uid) if i > 0: self.tab_widget.setCurrentIndex(i) def create_plugin_container(self, plugin, connected_uid, position): container = QWidget() container._uid = plugin.uid layout = QVBoxLayout(container) info = QHBoxLayout() # uid info.addWidget(QLabel('UID:')) label = QLabel('{0}'.format(plugin.uid)) label.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard) info.addWidget(label) info.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # connected uid if connected_uid != '0': info.addWidget(QLabel('Connected to:')) button = QToolButton() button.setText(connected_uid) button.pressed.connect(lambda: self.connected_uid_pressed(connected_uid)) info.addWidget(button) info.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # position info.addWidget(QLabel('Position:')) info.addWidget(QLabel('{0}'.format(position.upper()))) info.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # firmware version info.addWidget(QLabel('FW Version:')) info.addWidget(QLabel('{0}'.format(plugin.version_str))) info.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # timeouts info.addWidget(QLabel('Timeouts:')) label_timeouts = QLabel('0') info.addWidget(label_timeouts) layout.addLayout(info) if plugin.is_brick(): button = QPushButton('Reset') if plugin.has_reset_device(): button.clicked.connect(plugin.reset_device) else: button.setDisabled(True) info.addSpacerItem(QSpacerItem(40, 20, QSizePolicy.Expanding)) info.addWidget(button) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) plugin.label_timeouts = label_timeouts plugin.layout().setContentsMargins(0, 0, 0, 0) layout.addWidget(line) layout.addWidget(plugin) return container def tab_for_uid(self, uid): for i in range(1, self.tab_widget.count()): try: widget = self.tab_widget.widget(i) if widget._uid == uid: return i except: pass return -1 def cb_enumerate(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type): if self.ipcon.get_connection_state() != IPConnection.CONNECTION_STATE_CONNECTED: # ignore enumerate callbacks that arrived after the connection got closed return if enumeration_type in [IPConnection.ENUMERATION_TYPE_AVAILABLE, IPConnection.ENUMERATION_TYPE_CONNECTED]: if device_identifier == BrickMaster.DEVICE_IDENTIFIER: info = infos.BrickMasterInfo() elif position in ('a', 'b', 'c', 'd', 'A', 'B', 'C', 'D'): position = position.lower() info = infos.BrickletInfo() else: info = infos.BrickInfo() if uid in infos.infos: info = infos.infos[uid] else: infos.infos[uid] = info for device in infos.infos.values(): if device.type == 'brick': if info.type == 'bricklet': if device.uid == connected_uid: device.bricklets[position] = info if device.type == 'bricklet': if info.type == 'brick': if uid == device.connected_uid: info.bricklets[device.position] = device info.uid = uid info.connected_uid = connected_uid info.position = position info.hardware_version = hardware_version info.firmware_version_installed = firmware_version info.device_identifier = device_identifier info.protocol_version = 2 info.enumeration_type = enumeration_type for device in infos.infos.values(): if device.type in ('brick', 'bricklet'): if device.uid == uid and device.plugin != None: return plugin = self.plugin_manager.get_plugin(device_identifier, self.ipcon, uid, firmware_version) if plugin is not None: info.plugin = plugin if plugin.is_hardware_version_relevant(hardware_version): info.name = '{0} {1}.{2}'.format(plugin.name, hardware_version[0], hardware_version[1]) else: info.name = plugin.name info.url_part = plugin.get_url_part() c = self.create_plugin_container(plugin, connected_uid, position) info.plugin_container = c self.tab_widget.addTab(c, info.name) elif enumeration_type == IPConnection.ENUMERATION_TYPE_DISCONNECTED: for device_info in infos.infos.values(): if device_info.type in ('brick', 'bricklet'): if device_info.uid == uid: try: self.tab_widget.setCurrentIndex(0) if device_info.plugin: try: device_info.plugin.stop() except: pass try: device_info.plugin.destroy() except: pass i = self.tab_for_uid(device_info.uid) self.tab_widget.removeTab(i) except: pass if device_info.type == 'brick': for port in device_info.bricklets: if device_info.bricklets[port]: if device_info.bricklets[port].uid == uid: device_info.bricklets[port] = None try: infos.infos.pop(uid) except: pass self.update_tree_view() def cb_connected(self, connect_reason): self.disconnect_times = [] self.update_ui_state() if connect_reason == IPConnection.CONNECT_REASON_REQUEST: self.auto_reconnects = 0 self.label_auto_reconnects.hide() self.ipcon.set_auto_reconnect(True) index = self.combo_host.findText(self.last_host) if index >= 0: self.combo_host.removeItem(index) self.combo_host.insertItem(-1, self.last_host) self.combo_host.setCurrentIndex(0) while self.combo_host.count() > HOST_HISTORY_SIZE: self.combo_host.removeItem(self.combo_host.count() - 1) if not self.do_authenticate(False): return try: self.ipcon.enumerate() except: self.update_ui_state() elif connect_reason == IPConnection.CONNECT_REASON_AUTO_RECONNECT: self.auto_reconnects += 1 self.label_auto_reconnects.setText('Auto-Reconnect Count: {0}'.format(self.auto_reconnects)) self.label_auto_reconnects.show() if not self.do_authenticate(True): return try: self.ipcon.enumerate() except: self.update_ui_state() else: try: self.ipcon.enumerate() except: self.update_ui_state() def cb_disconnected(self, disconnect_reason): if disconnect_reason == IPConnection.DISCONNECT_REASON_REQUEST: self.auto_reconnects = 0 self.label_auto_reconnects.hide() if disconnect_reason == IPConnection.DISCONNECT_REASON_REQUEST or not self.ipcon.get_auto_reconnect(): self.update_ui_state() elif len(self.disconnect_times) >= 3 and self.disconnect_times[-3] < time.time() + 1: self.disconnect_times = [] self.ipcon.set_auto_reconnect(False) self.update_ui_state() self.reset_view() QMessageBox.critical(self, 'Connection', 'Stopped automatic reconnecting due to multiple connection errors in a row.', QMessageBox.Ok) else: self.disconnect_times.append(time.time()) self.update_ui_state(IPConnection.CONNECTION_STATE_PENDING) def set_tree_view_defaults(self): self.tree_view_model.setHorizontalHeaderLabels(self.tree_view_model_labels) self.tree_view.expandAll() self.tree_view.setColumnWidth(0, 260) self.tree_view.setColumnWidth(1, 75) self.tree_view.setColumnWidth(2, 85) self.tree_view.setSortingEnabled(True) self.tree_view.header().setSortIndicator(0, Qt.AscendingOrder) def update_ui_state(self, connection_state=None): # FIXME: need to call processEvents() otherwise get_connection_state() # might return the wrong value QApplication.processEvents() if connection_state is None: connection_state = self.ipcon.get_connection_state() self.button_connect.setDisabled(False) self.button_flashing.setDisabled(False) if connection_state == IPConnection.CONNECTION_STATE_DISCONNECTED: self.button_connect.setText('Connect') self.combo_host.setDisabled(False) self.spinbox_port.setDisabled(False) self.checkbox_authentication.setDisabled(False) self.edit_secret.setDisabled(False) self.button_advanced.setDisabled(True) elif connection_state == IPConnection.CONNECTION_STATE_CONNECTED: self.button_connect.setText("Disconnect") self.combo_host.setDisabled(True) self.spinbox_port.setDisabled(True) self.checkbox_authentication.setDisabled(True) self.edit_secret.setDisabled(True) self.update_advanced_window(False) elif connection_state == IPConnection.CONNECTION_STATE_PENDING: self.button_connect.setText('Abort Pending Automatic Reconnect') self.combo_host.setDisabled(True) self.spinbox_port.setDisabled(True) self.checkbox_authentication.setDisabled(True) self.edit_secret.setDisabled(True) self.button_advanced.setDisabled(True) self.button_flashing.setDisabled(True) enable = connection_state == IPConnection.CONNECTION_STATE_CONNECTED for i in range(1, self.tab_widget.count()): self.tab_widget.setTabEnabled(i, enable) QApplication.processEvents() def update_tree_view(self): self.tree_view_model.clear() for device_info in sorted(infos.infos.values(), cmp=lambda x, y: cmp(x.name, y.name)): if device_info.type == 'brick': parent = [QStandardItem(device_info.name), QStandardItem(device_info.uid), QStandardItem('.'.join(map(str, device_info.firmware_version_installed)))] for item in parent: item.setFlags(item.flags() & ~Qt.ItemIsEditable) self.tree_view_model.appendRow(parent) for port in sorted(device_info.bricklets): if device_info.bricklets[port] and device_info.bricklets[port].protocol_version == 2: child = [QStandardItem(port.upper() + ': ' +device_info.bricklets[port].name), QStandardItem(device_info.bricklets[port].uid), QStandardItem('.'.join(map(str, device_info.bricklets[port].firmware_version_installed)))] for item in child: item.setFlags(item.flags() & ~Qt.ItemIsEditable) parent[0].appendRow(child) self.set_tree_view_defaults() self.update_flashing_window() self.update_advanced_window() self.delayed_refresh_updates_timer.start() def update_flashing_window(self): if self.flashing_window is not None: self.flashing_window.update_bricks() def update_advanced_window(self, update_window=True): has_brick = False for info in infos.infos.values(): if info.type == 'brick': has_brick = True self.button_advanced.setEnabled(has_brick) if self.advanced_window is not None and update_window: self.advanced_window.update_bricks() def delayed_refresh_updates(self): self.delayed_refresh_updates_timer.stop() if self.flashing_window is not None and self.flashing_window.isVisible(): self.flashing_window.refresh_updates_pressed()
class VizRank(OWWidget): name = "Rank projections (Scatter Plot)" def __init__(self, parent_widget): super().__init__() self.parent_widget = parent_widget self.want_control_area = False self.running = False self.progress = None self.k = 10 self.projectionTable = QTableView() self.mainArea.layout().addWidget(self.projectionTable) self.projectionTable.setSelectionBehavior(QTableView.SelectRows) self.projectionTable.setSelectionMode(QTableView.SingleSelection) self.projectionTable.setSortingEnabled(True) self.projectionTableModel = QStandardItemModel(self) self.projectionTable.setModel(self.projectionTableModel) self.projectionTable.selectionModel().selectionChanged.connect( self.on_selection_changed) self.button = gui.button(self.mainArea, self, "Start evaluation", callback=self.toggle, default=True) self.resize(380, 512) self._initialize() def _initialize(self): self.running = False self.projectionTableModel.clear() self.projectionTableModel.setHorizontalHeaderLabels( ["Score", "Feature 1", "Feature 2"]) self.projectionTable.setColumnWidth(0, 60) self.projectionTable.setColumnWidth(1, 120) self.projectionTable.setColumnWidth(2, 120) self.button.setText("Start evaluation") self.button.setEnabled(False) self.pause = False self.data = None self.attrs = [] self.scores = [] self.i, self.j = 0, 0 if self.progress: self.progress.finish() self.progress = None self.information(0) if self.parent_widget.data: if not self.parent_widget.data.domain.class_var: self.information( 0, "Data with a class variable is required.") return if len(self.parent_widget.data.domain.attributes) < 2: self.information( 0, 'At least 2 unique features are needed.') return self.button.setEnabled(True) def on_selection_changed(self, selected, deselected): """Called when the ranks view selection changes.""" a1 = selected.indexes()[1].data() a2 = selected.indexes()[2].data() self.parent_widget.update_attr(attributes=(a1, a2)) def toggle(self): self.running ^= 1 if self.running: self.button.setText("Pause") self.run() else: self.button.setText("Continue") self.button.setEnabled(False) def run(self): graph = self.parent_widget.graph y_full = self.parent_widget.data.Y norm = 1 / (len(y_full) * self.k) if not self.attrs: self.attrs = self.score_heuristic() if not self.progress: self.progress = gui.ProgressBar( self, len(self.attrs) * (len(self.attrs) - 1) / 2) for i in range(self.i, len(self.attrs)): ind1 = graph.attribute_name_index[self.attrs[i]] for j in range(self.j, i): if not self.running: self.i, self.j = i, j if not self.projectionTable.selectedIndexes(): self.projectionTable.selectRow(0) self.button.setEnabled(True) return ind2 = graph.attribute_name_index[self.attrs[j]] X = graph.scaled_data[[ind1, ind2], :] valid = graph.get_valid_list([ind1, ind2]) X = X[:, valid].T y = y_full[valid] knn = NearestNeighbors(n_neighbors=self.k).fit(X) ind = knn.kneighbors(return_distance=False) score = norm * np.sum(y[ind] == y.reshape(-1, 1)) pos = bisect_left(self.scores, score) self.projectionTableModel.insertRow( len(self.scores) - pos, [QStandardItem("{:.4f}".format(score)), QStandardItem(self.attrs[j]), QStandardItem(self.attrs[i])]) self.scores.insert(pos, score) self.progress.advance() self.j = 0 self.progress.finish() if not self.projectionTable.selectedIndexes(): self.projectionTable.selectRow(0) self.button.setText("Finished") self.button.setEnabled(False) def score_heuristic(self): X = self.parent_widget.graph.scaled_data.T Y = self.parent_widget.data.Y dom = Orange.data.Domain([ContinuousVariable(str(i)) for i in range(X.shape[1])], self.parent_widget.data.domain.class_vars) data = Orange.data.Table(dom, X, Y) weights = ReliefF(n_iterations=100, k_nearest=self.k)(data) attrs = sorted( zip(weights, (x.name for x in self.parent_widget.data.domain.attributes) ), reverse=True) return [a for _, a in attrs]
def main(icon_spec): app = QApplication(sys.argv) main_window = QMainWindow() def sigint_handler(*args): main_window.close() signal.signal(signal.SIGINT, sigint_handler) # the timer enables triggering the sigint_handler signal_timer = QTimer() signal_timer.start(100) signal_timer.timeout.connect(lambda: None) tool_bar = QToolBar() main_window.addToolBar(Qt.TopToolBarArea, tool_bar) table_view = QTableView() table_view.setSelectionBehavior(QAbstractItemView.SelectRows) table_view.setSelectionMode(QAbstractItemView.SingleSelection) table_view.setSortingEnabled(True) main_window.setCentralWidget(table_view) proxy_model = QSortFilterProxyModel() proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive) proxy_model.setFilterKeyColumn(1) table_view.setModel(proxy_model) proxy_model.layoutChanged.connect(table_view.resizeRowsToContents) item_model = QStandardItemModel() proxy_model.setSourceModel(item_model) # get all icons and their available sizes QIcon.setThemeName("gnome") icons = [] all_sizes = set([]) for context, icon_names in icon_spec: for icon_name in icon_names: icon = QIcon.fromTheme(icon_name) sizes = [] for size in icon.availableSizes(): size = (size.width(), size.height()) sizes.append(size) all_sizes.add(size) sizes.sort() icons.append({ 'context': context, 'icon_name': icon_name, 'icon': icon, 'sizes': sizes, }) all_sizes = list(all_sizes) all_sizes.sort() # input field for filter def filter_changed(value): proxy_model.setFilterRegExp(value) table_view.resizeRowsToContents() filter_line_edit = QLineEdit() filter_line_edit.setMaximumWidth(200) filter_line_edit.setPlaceholderText('Filter name') filter_line_edit.setToolTip('Filter name optionally using regular expressions (' + QKeySequence(QKeySequence.Find).toString() + ')') filter_line_edit.textChanged.connect(filter_changed) tool_bar.addWidget(filter_line_edit) # actions to toggle visibility of available sizes/columns def action_toggled(index): column = 2 + index table_view.setColumnHidden(column, not table_view.isColumnHidden(column)) table_view.resizeColumnsToContents() table_view.resizeRowsToContents() signal_mapper = QSignalMapper() for i, size in enumerate(all_sizes): action = QAction('%dx%d' % size, tool_bar) action.setCheckable(True) action.setChecked(True) tool_bar.addAction(action) action.toggled.connect(signal_mapper.map) signal_mapper.setMapping(action, i) # set tool tip and handle key sequence tool_tip = 'Toggle visibility of column' if i < 10: digit = ('%d' % (i + 1))[-1] tool_tip += ' (%s)' % QKeySequence('Ctrl+%s' % digit).toString() action.setToolTip(tool_tip) signal_mapper.mapped.connect(action_toggled) # label columns header_labels = ['context', 'name'] for width, height in all_sizes: header_labels.append('%dx%d' % (width, height)) item_model.setColumnCount(len(header_labels)) item_model.setHorizontalHeaderLabels(header_labels) # fill rows item_model.setRowCount(len(icons)) for row, icon_data in enumerate(icons): # context item = QStandardItem(icon_data['context']) item.setFlags(item.flags() ^ Qt.ItemIsEditable) item_model.setItem(row, 0, item) # icon name item = QStandardItem(icon_data['icon_name']) item.setFlags(item.flags() ^ Qt.ItemIsEditable) item_model.setItem(row, 1, item) for index_in_all_sizes, size in enumerate(all_sizes): column = 2 + index_in_all_sizes if size in icon_data['sizes']: # icon as pixmap to keep specific size item = QStandardItem('') pixmap = icon_data['icon'].pixmap(size[0], size[1]) item.setData(pixmap, Qt.DecorationRole) item.setFlags(item.flags() ^ Qt.ItemIsEditable) item_model.setItem(row, column, item) else: # single space to be sortable against icons item = QStandardItem(' ') item.setFlags(item.flags() ^ Qt.ItemIsEditable) item_model.setItem(row, column, item) table_view.resizeColumnsToContents() # manually set row heights because resizeRowsToContents is not working properly for row, icon_data in enumerate(icons): if len(icon_data['sizes']) > 0: max_size = icon_data['sizes'][-1] table_view.setRowHeight(row, max_size[1]) # enable focus find (ctrl+f) and toggle columns (ctrl+NUM) def main_window_keyPressEvent(self, event, old_keyPressEvent=QMainWindow.keyPressEvent): if event.matches(QKeySequence.Find): filter_line_edit.setFocus() return if event.modifiers() == Qt.ControlModifier and event.key() >= Qt.Key_0 and event.key() <= Qt.Key_9: index = event.key() - Qt.Key_1 if event.key() == Qt.Key_0: index += 10 action = signal_mapper.mapping(index) if action: action.toggle() return old_keyPressEvent(self, event) main_window.keyPressEvent = new.instancemethod(main_window_keyPressEvent, table_view, None) # enable copy (ctrl+c) name of icon to clipboard def table_view_keyPressEvent(self, event, old_keyPressEvent=QTableView.keyPressEvent): if event.matches(QKeySequence.Copy): selection_model = self.selectionModel() if selection_model.hasSelection(): index = selection_model.selectedRows()[0] source_index = self.model().mapToSource(index) item = self.model().sourceModel().item(source_index.row(), 1) icon_name = item.data(Qt.EditRole) app.clipboard().setText(icon_name.toString()) return old_keyPressEvent(self, event) table_view.keyPressEvent = new.instancemethod(table_view_keyPressEvent, table_view, None) print 'Icon Theme: ', QIcon.themeName() print 'Theme Search Paths:' for item in QIcon.themeSearchPaths(): print item main_window.showMaximized() return app.exec_()
class dbmanagerUI(QMainWindow, ui_dbmanager.Ui_dbmanagerUI): """Main UI for MASAR database manager.""" def __init__(self): """""" super(dbmanagerUI, self).__init__() self.setupUi(self) self.statusbar.showMessage("Ready") exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit Masar Configuration Manager.') exitAction.triggered.connect(QtGui.qApp.quit) self.groupdatabasemenubar() #default database source, could be 0: SQLite, 1: MongoDB, and 2: MySQL self.dbsource = None self.defaultdbinfo = self._loadmasarconfig() self.usedefaultdb = True self.comboxboxSignalMapper = QtCore.QSignalMapper(self) self.comboxboxSignalMapper.mapped[QtGui.QWidget].connect( self.comboboxSignalMapperMapped) self.pushbuttonSignalMapper = QtCore.QSignalMapper(self) self.pushbuttonSignalMapper.mapped[QtGui.QWidget].connect( self.pushbuttonSignalMapperMapped) self.showpvbuttonSignalMapper = QtCore.QSignalMapper(self) self.showpvbuttonSignalMapper.mapped[QtGui.QWidget].connect( self.showpvbuttonSignalMapperMapped) self.choosepvbuttonSignalMapper = QtCore.QSignalMapper(self) self.choosepvbuttonSignalMapper.mapped[QtGui.QWidget].connect( self.choosepvbuttonSignalMapperMapped) self.currentselectedrow4config = -1 self.selectedsystem = "Others" # self.pvgrouptreeview = QTreeView() self.pvGroupTreeView.setSelectionBehavior(QAbstractItemView.SelectRows) self.pvgroupmodel = QStandardItemModel() # self.pvgroupmodel.setHorizontalHeaderLabels(['id', 'date', 'version', "description"]) self.pvgroupmodel.setHorizontalHeaderLabels(["PV Groups"]) self.pvGroupTreeView.setModel(self.pvgroupmodel) self.pvGroupTreeView.setUniformRowHeights(True) @QtCore.pyqtSlot(QtGui.QWidget) def comboboxSignalMapperMapped(self, comboBox): if self.masarConfigTableWidget.cellWidget( comboBox.row, comboBox.column + 1).isEnabled(): self.masarConfigTableWidget.cellWidget( comboBox.row, comboBox.column + 1).setEnabled(False) button = self.masarConfigTableWidget.cellWidget( comboBox.row, comboBox.column + 1) palette = QtGui.QPalette( button.palette()) # make a copy of the palette palette.setColor(QtGui.QPalette.ButtonText, QtGui.QColor('grey')) button.setPalette(palette) else: self.masarConfigTableWidget.cellWidget( comboBox.row, comboBox.column + 1).setEnabled(True) button = self.masarConfigTableWidget.cellWidget( comboBox.row, comboBox.column + 1) palette = QtGui.QPalette( button.palette()) # make a copy of the palette palette.setColor(QtGui.QPalette.ButtonText, QtGui.QColor('red')) button.setPalette(palette) @QtCore.pyqtSlot(QtGui.QWidget) def pushbuttonSignalMapperMapped(self, pushbutton): configstatus = str( self.masarConfigTableWidget.cellWidget( pushbutton.row, pushbutton.column - 1).currentText()) cid = str(self.masarConfigTableWidget.item(pushbutton.row, 0).text()) cname = str(self.masarConfigTableWidget.item(pushbutton.row, 1).text()) if self.updatemasarconfigstatus(configstatus, cid, configname=cname): palette = QtGui.QPalette( pushbutton.palette()) # make a copy of the palette palette.setColor(QtGui.QPalette.ButtonText, QtGui.QColor('grey')) pushbutton.setPalette(palette) pushbutton.setEnabled(False) @QtCore.pyqtSlot(QtGui.QWidget) def showpvbuttonSignalMapperMapped(self, showpvbutton): if self.newConfigTableWidget.item(showpvbutton.row, showpvbutton.column + 2) is None: raise RuntimeError("Unknown pv file") pvfilename = self.newConfigTableWidget.item( showpvbutton.row, showpvbutton.column + 2).text() if not os.path.isfile(pvfilename): raise RuntimeError( "Invalid pv file name for (row, col): (%s, %s)" % (showpvbutton.row, showpvbutton.column + 2)) text = ", ".join(np.loadtxt(str(pvfilename), dtype=str, comments="#")) if self.newConfigTableWidget.item(showpvbutton.row, 0) is not None: head = self.newConfigTableWidget.item(showpvbutton.row, 0).text() else: head = "" msg = QMessageBox(self, windowTitle='PVs for group %s' % head, text="The following PVs to be added:") msg.setDetailedText(text) msg.exec_() @QtCore.pyqtSlot(QtGui.QWidget) def choosepvbuttonSignalMapperMapped(self, chhosepvbutton): self.newConfigTableWidget.setItem( chhosepvbutton.row, chhosepvbutton.column + 1, QTableWidgetItem(QFileDialog.getOpenFileName(self, "Open File"))) def _loadmasarconfig(self): cf = ConfigParser.SafeConfigParser() cf.read([ os.path.expanduser('~/.masarservice.conf'), '/etc/masarservice.conf', 'masarservice.conf', "%s/masarservice.conf" % os.path.abspath(os.path.dirname(__file__)) ]) return cf def groupdatabasemenubar(self): """Group 3 Databases menu together to make selection exclusive.""" group = QtGui.QActionGroup(self) self.actionSQLite.setActionGroup(group) self.actionMongoDB.setActionGroup(group) self.actionMySQL.setActionGroup(group) def actionsqlitemenu(self): """Answer action when SQLite is selected.""" if self.actionSQLite.isChecked(): self.dbsource = 0 self.defaultsqlitedb() self.listPvGroupPushButton.setEnabled(True) def actionmongodbmenu(self): """Answer action when MongoDB is selected.""" if self.actionMongoDB.isChecked(): self.dbsource = 1 self.defaultmongodb() self.listPvGroupPushButton.setEnabled(False) def actionmysqlmenu(self): """Answer action when MySQL is selected.""" if self.actionMySQL.isChecked(): QMessageBox.warning(self, 'Warning', "MySQL support not implemented yet.") self.actionMySQL.setChecked(False) if self.dbsource == 0: self.actionSQLite.setChecked(True) elif self.dbsource == 1: self.actionMongoDB.setChecked(True) def showdefaultdbinfo(self): """""" if self.dbsource == 0: self.defaultsqlitedb() elif self.dbsource == 1: self.defaultmongodb() elif self.dbsource == 2: QMessageBox.warning(self, 'Warning', "MySQL support not implemented yet.") def defaultsqlitedb(self): """""" if self.defaultdbinfo.has_section("sqlite"): self.databaseDefault.setText( self.defaultdbinfo.get("sqlite", "database")) self.hostDefault.clear() self.portDefault.clear() self.userDefault.clear() def defaultmongodb(self): """""" if self.defaultdbinfo.has_section("mongodb"): self.databaseDefault.setText( self.defaultdbinfo.get("mongodb", "database")) self.hostDefault.setText(self.defaultdbinfo.get("mongodb", "host")) self.portDefault.setText(self.defaultdbinfo.get("mongodb", "port")) self.userDefault.setText( self.defaultdbinfo.get("mongodb", "username")) def getdatabasename(self): """""" self.database = self.databaseLineEdit.text() def getdatabaseport(self): """""" self.databaseport = self.databaseportLineEdit.text() def getdatabasehost(self): """""" self.databasehost = self.databaseHostLineEdit.text() def getdatabasepw(self): """""" self.databasepw = self.databasePwLineEdit.text() def showmasarconfigs(self): """""" result = None if self.dbsource == 0: # get data from sqlite if self.usedefaultdb: # masardb = str(self.databaseDefault.text()) masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: raise RuntimeError("Cannot find MASAR SQLite Database") import pymasarsqlite conn = pymasarsqlite.utils.connect() result = pymasarsqlite.service.retrieveServiceConfigs( conn, servicename="masar") pymasarsqlite.utils.close(conn) elif self.dbsource == 1: # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo mongoconn, collection = pymasarmongo.db.utils.conn(host=host, port=port, db=database) resultdict = pymasarmongo.pymasarmongo.pymasar.retrieveconfig( mongoconn, collection) pymasarmongo.db.utils.close(mongoconn) result = [['id', 'name', 'desc', 'date', 'version', 'status']] for res in resultdict: result.append([ res['configidx'], res['name'], res['desc'], res['created_on'], res['version'], res['status'] ]) # res['system'] if result is not None: self._setconfigtable(result) def choosedbsrc(self, bool): """Choose DB source""" if bool: self.usedefaultdb = True else: self.usedefaultdb = False def _setconfigtable(self, content): """""" # head = self.masarConfigTableWidget.horizontalHeader() self.masarConfigTableWidget.clearContents() # self.masarConfigTableWidget.setHorizontalHeaderLabels(head) if len(content) > 1: self.masarConfigTableWidget.setRowCount(len(content) - 1) n = 0 data = sorted(content[1:], key=itemgetter(0), reverse=True) for res in data: m = 0 for item in res: if not isinstance(item, basestring): item = str(item) if item: if m == 5: newitem = QtGui.QComboBox() newitem.addItem("active") newitem.addItem("inactive") if item == "active": newitem.setCurrentIndex(0) else: newitem.setCurrentIndex(1) newitem.row = n newitem.column = m self.masarConfigTableWidget.setCellWidget( n, m, newitem) self.comboxboxSignalMapper.setMapping( newitem, newitem) newitem.currentIndexChanged.connect( self.comboxboxSignalMapper.map) updatebutton = QtGui.QPushButton() updatebutton.setText("Update") updatebutton.setEnabled(False) updatebutton.row = n updatebutton.column = m + 1 self.pushbuttonSignalMapper.setMapping( updatebutton, updatebutton) self.masarConfigTableWidget.setCellWidget( n, m + 1, updatebutton) updatebutton.clicked.connect( self.pushbuttonSignalMapper.map) else: newitem = QTableWidgetItem(item) newitem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) self.masarConfigTableWidget.setItem(n, m, newitem) m += 1 n += 1 self.masarConfigTableWidget.resizeColumnsToContents() def updatemasarconfigstatus(self, configstatus, cid, configname=None): if self.dbsource == 0: # get data from sqlite if self.usedefaultdb: masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: raise RuntimeError("Cannot find MASAR SQLite Database") import pymasarsqlite conn = pymasarsqlite.utils.connect() pymasarsqlite.service.updateServiceConfigStatus( conn, cid, status=configstatus) pymasarsqlite.utils.save(conn) pymasarsqlite.utils.close(conn) elif self.dbsource == 1: # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo mongoconn, collection = pymasarmongo.db.utils.conn(host=host, port=port, db=database) pymasarmongo.pymasarmongo.pymasar.updateconfig(mongoconn, collection, configname, configidx=int(cid), status=configstatus) pymasarmongo.db.utils.close(mongoconn) return True def addnewpvgrouprow(self): """Add a new row to add pv group to MASAR configuration""" print("""Add a new row to add pv group to MASAR configuration""") currowcount = self.newConfigTableWidget.rowCount() self.newConfigTableWidget.setRowCount(currowcount + 1) showpvbutton = QtGui.QPushButton() showpvbutton.setText("Show PVs") showpvbutton.setEnabled(True) showpvbutton.row = currowcount showpvbutton.column = 2 self.showpvbuttonSignalMapper.setMapping(showpvbutton, showpvbutton) self.newConfigTableWidget.setCellWidget(currowcount, showpvbutton.column, showpvbutton) showpvbutton.clicked.connect(self.showpvbuttonSignalMapper.map) choosepvbutton = QtGui.QPushButton() choosepvbutton.setText("PV File") choosepvbutton.setEnabled(True) choosepvbutton.row = currowcount choosepvbutton.column = 3 self.choosepvbuttonSignalMapper.setMapping(choosepvbutton, choosepvbutton) self.newConfigTableWidget.setCellWidget(currowcount, choosepvbutton.column, choosepvbutton) choosepvbutton.clicked.connect(self.choosepvbuttonSignalMapper.map) def removepvgrouprow(self): """Remove selected pv group from the configuration to be added into MASAR database""" if self.currentselectedrow4config == -1: raise RuntimeError("No pv group selected.") rownametobedelete = self.newConfigTableWidget.item( self.currentselectedrow4config, 0) if rownametobedelete is not None: rownametobedelete = rownametobedelete.text() self.newConfigTableWidget.removeRow(self.currentselectedrow4config) if rownametobedelete is not None: print("Successfully delete pv group: ", rownametobedelete) else: print("Successfully delete row: ", self.currentselectedrow4config) self.currentselectedrow4config = -1 def savemasarsqlite(self): """""" # get data from sqlite if self.usedefaultdb: masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: QMessageBox.warning(self, "Warning", "Cannot find MASAR SQLite Database") return import pymasarsqlite conn = pymasarsqlite.utils.connect() existedresult = pymasarsqlite.service.retrieveServiceConfigs( conn, servicename="masar") newcfgdata = self._getnewconfigurationdata(existedresult) if newcfgdata is None: QMessageBox.warning( self, "Warning", "Not enough information for a new configuration.") return newcfgname = newcfgdata[0] desc = newcfgdata[1] msystem = newcfgdata[2] # config data format: [[name], [desc], [pv files]] cfgdata = newcfgdata[3] if newcfgname is None or msystem is None or newcfgdata is None: # Nothing to be added. QMessageBox.warning( self, "Warning", "No name or system is given, or empty configuration data.") return for i in range(len(cfgdata[0])): if cfgdata[0][i] is None: QMessageBox.warning(self, "Warning", "Wrong PV group name") return if cfgdata[2][i] is not None and os.path.isfile(cfgdata[2][i]): pvs = list(np.loadtxt(cfgdata[2][i], dtype=str, comments="#")) if len(pvs) > 0: for j, pv in enumerate(pvs): pvs[j] = pv.strip() pymasarsqlite.pvgroup.savePvGroup(conn, cfgdata[0][i], func=cfgdata[1][i]) pymasarsqlite.pvgroup.saveGroupPvs(conn, cfgdata[0][i], pvs) try: pymasarsqlite.service.saveServiceConfig(conn, "masar", newcfgname, configdesc=desc, system=msystem) pymasarsqlite.service.saveServicePvGroup(conn, newcfgname, cfgdata[0]) except Exception as e: QMessageBox.warning(self, "Error", e.message) return pymasarsqlite.utils.save(conn) QMessageBox.information( self, "Congratulation", "A new configuration has been added successfully.") pymasarsqlite.utils.close(conn) def savemasarmongodb(self): """""" # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo mongoconn, collection = pymasarmongo.db.utils.conn(host=host, port=port, db=database) existedresult = pymasarmongo.pymasarmongo.pymasar.retrieveconfig( mongoconn, collection) existedcfg = [] for res in existedresult: existedcfg.append([ res['configidx'], res['name'], res['desc'], res['created_on'], res['version'], res['status'] ]) newcfgdata = self._getnewconfigurationdata(existedcfg) if newcfgdata is None: # Nothing to be added. raise ValueError("Empty configuration.") newcfgname = newcfgdata[0] desc = newcfgdata[1] msystem = newcfgdata[2] # config data format: [[name], [desc], [pv files]] cfgdata = newcfgdata[3] pvs = [] for pvf in cfgdata[2]: if pvf is not None and os.path.isfile(pvf): pvs += list(np.loadtxt(pvf, dtype=str, comments="#")) if pvs: for i, pv in enumerate(pvs): pvs[i] = pv.strip() pymasarmongo.pymasarmongo.pymasar.saveconfig(mongoconn, collection, newcfgname, desc=desc, system=msystem, pvlist={"names": pvs}) QMessageBox.information( self, "Congratulation", "A new configuration has been added successfully.") else: QMessageBox.warning(self, "Warning", "No PVs available for the new configuration.") pymasarmongo.db.utils.close(mongoconn) def submitmasarconfig(self): """submit a new configuration to MASAR database""" if self.dbsource is None: QMessageBox.warning( self, "Warning", "Unknown database source.\nPlease select which database should be use." ) return if self.dbsource == 0: self.savemasarsqlite() elif self.dbsource == 1: self.savemasarmongodb() def _getnewconfigurationdata(self, existedresult): """""" newcfgname = self.newConfigurationLineEdit.text() if newcfgname is None or str(newcfgname) == "": QMessageBox.warning(self, "Warning", "Name of configuration is empty.") return None elif str(newcfgname) in np.array(existedresult)[:, 1]: QMessageBox.warning( self, "Warning", "Configuration (%s) exists already." % str(newcfgname)) return None else: newcfgname = str(newcfgname) desc = self.newConfigurationDescription.text() if str(desc) == "": desc = None else: desc = str(desc) msystem = str(self.systemComboBox.currentText()) if msystem == "Others": msystem = self.systemLineEdit.text() if msystem is None or str(msystem) == "": QMessageBox.warning( self, "Warning", "System for configuration (%s) not specified yet." % str(newcfgname)) return None else: msystem = str(msystem) pvgroups = self.newConfigTableWidget.rowCount() if pvgroups == 0: QMessageBox.warning( self, "Warning", "No PV founded for new configuration (%s)." % str(newcfgname)) return None pvgroupnames = [] pvgroupdescs = [] pvgroupfiles = [] for count in range(pvgroups): # Collect PV group name information if self.newConfigTableWidget.item(count, 0) is not None and str( self.newConfigTableWidget.item(count, 0).text()) != "": pvgname = str(self.newConfigTableWidget.item(count, 0).text()) if pvgname in pvgroupnames: QMessageBox.warning( self, "Warning", "Duplicated pv group name: %s." % str(pvgname)) return None pvgroupnames.append(pvgname) elif self.newConfigTableWidget.item(count, 4) is None or str( self.newConfigTableWidget.item(count, 4)) == "": continue elif self.dbsource == 1: pvgroupnames.append(None) else: QMessageBox.warning(self, "Warning", "Empty pv group name.") return None # reply = QMessageBox.question(self, "Message", # "pv group name not specified for row {}.\nContinue?".format(count), # QMessageBox.Yes | QMessageBox.No, QMessageBox.No) # if reply == QMessageBox.Yes: # pvgroupnames.append(None) # else: # return None # Collection PV group descriptions if self.newConfigTableWidget.item(count, 1) is not None: pvgroupdescs.append( str(self.newConfigTableWidget.item(count, 1).text())) else: pvgroupdescs.append(None) # PV files for the pv group. if self.newConfigTableWidget.item(count, 4) is not None: pvgroupfiles.append( str(self.newConfigTableWidget.item(count, 4).text())) else: pvgroupfiles.append(None) if pvgroupfiles: return newcfgname, desc, msystem, [ pvgroupnames, pvgroupdescs, pvgroupfiles ] else: return None def currentselectedrow(self, row, col): """Cache current selected row in MASAR configuration Table Widget.""" self.currentselectedrow4config = row def updateselectedsystem(self, system): """Update selected system if value changed""" self.selectedsystem = str(system) def updatesystemcombobox(self): """Update selected system if value changed""" self.systemComboBox.clear() if self.dbsource == 0: # get data from sqlite if self.usedefaultdb: # masardb = str(self.databaseDefault.text()) masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: raise RuntimeError("Cannot find MASAR SQLite Database") import pymasarsqlite conn = pymasarsqlite.utils.connect() result = pymasarsqlite.service.retrieveServiceConfigProps( conn, propname="system", servicename="masar") index = 0 if len(result) > 1: res = sorted(set(list(np.array(result[1:])[:, 3]))) #for res in result[1:]: self.systemComboBox.addItems(res) index = len(res) self.systemComboBox.addItem("Others") self.systemComboBox.setCurrentIndex(index) pymasarsqlite.utils.close(conn) elif self.dbsource == 1: # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo mongoconn, collection = pymasarmongo.db.utils.conn(host=host, port=port, db=database) result = pymasarmongo.pymasarmongo.pymasar.retrieveconfig( mongoconn, collection) pymasarmongo.db.utils.close(mongoconn) results = [] for res in result: if res["system"] not in results: results.append(res["system"]) res = sorted(set(results)) self.systemComboBox.addItems(res) index = len(res) self.systemComboBox.addItem("Others") self.systemComboBox.setCurrentIndex(index) def listpvgroups(self): """""" self.pvgroupmodel.clear() self.pvgroupmodel.setHorizontalHeaderLabels(["PV Groups"]) if self.dbsource == 0: # get data from sqlite if self.usedefaultdb: # masardb = str(self.databaseDefault.text()) masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: raise RuntimeError("Cannot find MASAR SQLite Database") import pymasarsqlite conn = pymasarsqlite.utils.connect() result = pymasarsqlite.pvgroup.retrievePvGroups(conn) if len(result) > 0: result = sorted(result, key=itemgetter(0), reverse=True) for res in result: parent1 = QStandardItem(res[1]) child1 = QStandardItem('id: {}'.format(res[0])) child2 = QStandardItem('description: {}'.format(res[2])) child3 = QStandardItem('date: {}'.format(res[3])) child4 = QStandardItem('version: {}'.format(res[4])) parent1.appendColumn([child1, child2, child3, child4]) self.pvgroupmodel.appendRow(parent1) selmod = self.pvGroupTreeView.selectionModel() index2 = self.pvgroupmodel.indexFromItem(child3) selmod.select( index2, QItemSelectionModel.Select | QItemSelectionModel.Rows) pymasarsqlite.utils.close(conn) self.pvGroupTreeView.setContextMenuPolicy(Qt.CustomContextMenu) self.pvGroupTreeView.clicked.connect(self.showpvsinpvgroup) # self.connect(self.pvGroupTreeView, # QtCore.SIGNAL("clicked(QModelIndex)"), # #QtCore.SIGNAL("customContextMenuRequested(const QPoint &)"), # self.doMenu) elif self.dbsource == 1: # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo def showpvsinpvgroup(self, point): if point.model().itemFromIndex(point).child(0) is None: return reply = QMessageBox.question( self, 'Message', "show all pvs belong to group {} ?".format( point.model().itemFromIndex(point).text()), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: pvgroupidx = int( str(point.model().itemFromIndex(point).child(0).text().split( ":")[1]).strip()) # msg = QMessageBox(self) msg = ShowPvMessageBox() msg.setWindowTitle('PVs for group {}'.format( point.model().itemFromIndex(point).text())) msg.setText("Click show details to see all pvs.") # windowTitle = 'PVs for group {}'.format(point.model().itemFromIndex(point).text()) if self.dbsource == 0: # get data from sqlite if self.usedefaultdb: # masardb = str(self.databaseDefault.text()) masardb = str(self.databaseDefault.toPlainText()) else: masardb = str(self.databaseLineEdit.text()) if masardb != "": os.environ["MASAR_SQLITE_DB"] = masardb else: raise RuntimeError("Cannot find MASAR SQLite Database") import pymasarsqlite conn = pymasarsqlite.utils.connect() result = pymasarsqlite.pvgroup.retrieveGroupPvs( conn, pvgroupidx) text = "\n".join(list(np.array(result)[:, 0])) msg.setDetailedText(text) msg.exec_() elif self.dbsource == 1: # get data from mongodb if self.usedefaultdb: database = str(self.databaseDefault.toPlainText()) host = str(self.hostDefault.toPlainText()) port = str(self.portDefault.toPlainText()) else: database = str(self.databaseLineEdit.text()) host = str(self.databaseHostLineEdit.text()) port = str(self.databasePortLineEdit.text()) import pymasarmongo
class GeoDetermineDlg(FlightPlanBaseDlg): HistoryDataP = [] HistoryDataBD = [] HistoryDataMV = [] def __init__(self, parent): FlightPlanBaseDlg.__init__(self, parent) self.setObjectName("HoldingRnavDlg") self.surfaceType = SurfaceTypes.GeoDetermine self.initParametersPan() self.setWindowTitle(SurfaceTypes.GeoDetermine) self.resize(540, 550) self.surfaceList = None self.date = QDate.currentDate() self.model = MagneticModel.WMM2010 geo = Geo() self.resultLayerList = [] self.resultPoint3d = None self.resultLat = None self.resultLon = None def uiStateInit(self): self.ui.grbMostCritical.setVisible(False) self.ui.grbResult_2.setVisible(False) self.ui.btnUpdateQA.setVisible(False) self.ui.btnUpdateQA_2.setVisible(False) self.ui.btnExportResult.setVisible(False) self.ui.btnEvaluate.setVisible(False) self.ui.btnPDTCheck.setVisible(False) self.ui.frm_cmbObstSurface.setVisible(False) self.ui.tabCtrlGeneral.removeTab(1) icon = QIcon() icon.addPixmap(QPixmap(("Resource/Calculator.bmp")), QIcon.Normal, QIcon.Off) self.ui.btnConstruct.setIcon(icon) self.ui.btnConstruct.setToolTip("Calculate") return FlightPlanBaseDlg.uiStateInit(self) def tblHistory_Click(self, modelIndex): if modelIndex != None: if self.parametersPanel.tabGeneral.currentIndex() == 0: dataList = GeoDetermineDlg.HistoryDataP[modelIndex.row()] self.parametersPanel.pnlStartPosP.Point3d = Point3D( float(dataList[1][1]), float(dataList[1][0])) self.parametersPanel.pnlVarStartP.Value = float(dataList[1][2]) self.parametersPanel.txtForwardTP.Value = float(dataList[1][3]) self.parametersPanel.txtForwardMP.Value = float(dataList[1][4]) self.parametersPanel.txtDistanceP.Value = Distance( float(dataList[1][5]), DistanceUnits.NM) self.parametersPanel.pnlVarFinishP.Value = float( dataList[1][9]) self.method_29_P() self.resultModelP.setItem(0, 0, QStandardItem(Captions.LATITUDE)) self.resultModelP.setItem(0, 1, QStandardItem(dataList[1][7])) self.resultModelP.setItem(1, 0, QStandardItem(Captions.LONGITUDE)) self.resultModelP.setItem(1, 1, QStandardItem(dataList[1][8])) self.resultModelP.setItem( 2, 0, QStandardItem(Captions.REVERSE_TRUE_BEARING)) self.resultModelP.setItem(2, 1, QStandardItem(dataList[1][10])) self.resultModelP.setItem( 3, 0, QStandardItem(Captions.REVERSE_MAGNETIC_BEARING)) self.resultModelP.setItem(3, 1, QStandardItem(dataList[1][11])) elif self.parametersPanel.tabGeneral.currentIndex() == 1: dataList = GeoDetermineDlg.HistoryDataBD[modelIndex.row()] self.parametersPanel.pnlStartPosBD.ID = dataList[1][0] self.parametersPanel.pnlStartPosBD.Point3d = Point3D( float(dataList[1][2]), float(dataList[1][1])) self.parametersPanel.pnlVarStartBD.Value = float( dataList[1][3]) self.parametersPanel.pnlFinishPosBD.ID = dataList[1][4] self.parametersPanel.pnlFinishPosBD.Point3d = Point3D( float(dataList[1][6]), float(dataList[1][5])) self.parametersPanel.pnlVarFinishBD.Value = float( dataList[1][7]) self.method_31_BD() self.resultModelBD.setItem( 0, 0, QStandardItem(Captions.FORWARD_TRUE_BEARING)) self.resultModelBD.setItem(0, 1, QStandardItem(dataList[1][8])) self.resultModelBD.setItem( 1, 0, QStandardItem(Captions.FORWARD_MAGNETIC_BEARING)) self.resultModelBD.setItem(1, 1, QStandardItem(dataList[1][9])) self.resultModelBD.setItem( 2, 0, QStandardItem(Captions.REVERSE_TRUE_BEARING)) self.resultModelBD.setItem(2, 1, QStandardItem(dataList[1][10])) self.resultModelBD.setItem( 3, 0, QStandardItem(Captions.REVERSE_MAGNETIC_BEARING)) self.resultModelBD.setItem(3, 1, QStandardItem(dataList[1][11])) self.resultModelBD.setItem( 2, 0, QStandardItem(Captions.DISTANCE_BETWEEN_POSITIONS)) self.resultModelBD.setItem(2, 1, QStandardItem(dataList[1][12])) self.resultModelBD.setItem( 3, 0, QStandardItem(Captions.DISTANCE_BETWEEN_POSITIONS)) self.resultModelBD.setItem(3, 1, QStandardItem(dataList[1][13])) else: dataList = GeoDetermineDlg.HistoryDataMV[modelIndex.row()] self.parametersPanel.pnlPositionMVD.Point3d = Point3D( float(dataList[1][1]), float(dataList[1][0])) self.parametersPanel.pnlPositionMVD.txtAltitudeM.setText( dataList[1][2]) self.parametersPanel.txtResult.Value = dataList[1][6] def calculateP(self): degree = None degree1 = None degree2 = None degree3 = None num = None result, degree, degree1 = self.parametersPanel.pnlStartPosP.method_3() if (result): # self.pnlVarStart.Value.smethod_17(); num1 = float(self.parametersPanel.pnlVarFinishP.Value) value = float(self.parametersPanel.txtForwardTP.Value) value1 = float(self.parametersPanel.txtForwardTP.Value) distance = self.parametersPanel.txtDistanceP.Value result, degree2, degree3, num = Geo.smethod_6( self.parametersPanel.cmbCalculationTypeP.SelectedItem, degree, degree1, value, distance) if (result): num2 = MathHelper.smethod_3(num - num1) self.method_29_P() self.resultPoint3d = Point3D(degree3, degree2) self.resultLat = degree2 self.resultLon = degree3 latStr = Degrees(degree2, None, None, DegreesType.Latitude).ToString() self.resultModelP.setItem(0, 0, QStandardItem(Captions.LATITUDE)) self.resultModelP.setItem(0, 1, QStandardItem(latStr)) lonStr = Degrees(degree3, None, None, DegreesType.Longitude).ToString() if String.Str2QString(lonStr).mid(0, 1) == "0": lonStr = String.Str2QString(lonStr).mid( 1, String.Str2QString(lonStr).length() - 1) self.resultModelP.setItem(1, 0, QStandardItem(Captions.LONGITUDE)) self.resultModelP.setItem(1, 1, QStandardItem(lonStr)) self.resultModelP.setItem( 2, 0, QStandardItem(Captions.REVERSE_TRUE_BEARING)) self.resultModelP.setItem(2, 1, QStandardItem(str(round(num, 4)))) self.resultModelP.setItem( 3, 0, QStandardItem(Captions.REVERSE_MAGNETIC_BEARING)) self.resultModelP.setItem(3, 1, QStandardItem(str(round(num2, 4)))) dataList = [] dataList.append([ "Latitude (Start)", "Longitude (Start)", "Variation (Start)", "Forward (° T)", "Forward (° M)", "Distance (nm)", "Distance (km)", "Latitude (Finish)", "Longitude (Finish)", "Variation (Finish)", "Reverse (° T)", "Reverse (° M)" ]) dataList.append([ str(degree), str(degree1), str(self.parametersPanel.pnlVarStartP.Value), str(self.parametersPanel.txtForwardTP.Value), str(self.parametersPanel.txtForwardMP.Value), str(distance.NauticalMiles), str(distance.Kilometres), str(degree2), str(degree3), str(self.parametersPanel.pnlVarFinishP.Value), str(round(num, 4)), str(round(num2, 4)) ]) GeoDetermineDlg.HistoryDataP.append(dataList) self.setDataInHistoryModel(dataList) self.method_28_P(degree2, degree3) def calculateBD(self): degree = None degree1 = None degree2 = None degree3 = None num = None result, degree, degree1 = self.parametersPanel.pnlStartPosBD.method_3() if (result): num2 = self.parametersPanel.pnlVarStartBD.Value result1, degree2, degree3 = self.parametersPanel.pnlFinishPosBD.method_3( ) if (result1): num3 = self.parametersPanel.pnlVarFinishBD.Value result2, distance, num, num1 = Geo.smethod_4( self.parametersPanel.cmbCalculationTypeBD.SelectedItem, degree, degree1, degree2, degree3) if define._units == QGis.Meters: QgisHelper.convertMeasureUnits(QGis.Degrees) distance = Distance( MathHelper.calcDistance( self.parametersPanel.pnlStartPosBD.Point3d, self.parametersPanel.pnlFinishPosBD.Point3d)) QgisHelper.convertMeasureUnits(QGis.Meters) else: distance = Distance( MathHelper.calcDistance( self.parametersPanel.pnlStartPosBD.Point3d, self.parametersPanel.pnlFinishPosBD.Point3d)) if result2: num4 = MathHelper.smethod_3(num - num2) num5 = MathHelper.smethod_3(num1 - num3) self.method_31_BD() self.resultModelBD.setItem( 0, 0, QStandardItem(Captions.FORWARD_TRUE_BEARING)) self.resultModelBD.setItem( 0, 1, QStandardItem(str(round(num, 4)))) self.resultModelBD.setItem( 1, 0, QStandardItem(Captions.FORWARD_MAGNETIC_BEARING)) self.resultModelBD.setItem( 1, 1, QStandardItem(str(round(num4, 4)))) self.resultModelBD.setItem( 2, 0, QStandardItem(Captions.REVERSE_TRUE_BEARING)) self.resultModelBD.setItem( 2, 1, QStandardItem(str(round(num1, 4)))) self.resultModelBD.setItem( 3, 0, QStandardItem(Captions.REVERSE_MAGNETIC_BEARING)) self.resultModelBD.setItem( 3, 1, QStandardItem(str(round(num5, 4)))) self.resultModelBD.setItem( 4, 0, QStandardItem(Captions.DISTANCE_BETWEEN_POSITIONS)) self.resultModelBD.setItem( 4, 1, QStandardItem( str(round(distance.NauticalMiles, 4)) + " nm")) self.resultModelBD.setItem( 5, 0, QStandardItem(Captions.DISTANCE_BETWEEN_POSITIONS)) self.resultModelBD.setItem( 5, 1, QStandardItem( str(round(distance.Kilometres, 4)) + " km")) dataList = [] dataList.append([ "ID (Start)", "Latitude (Start)", "Longitude (Start)", "Variation (Start)", "ID (Finish)", "Latitude (Finish)", "Longitude (Finish)", "Variation (Finish)", "Forward (° T)", "Forward (° M)", "Reverse (° T)", "Reverse (° M)", "Distance (nm)", "Distance (km)" ]) dataList.append([ self.parametersPanel.pnlStartPosBD.ID, str(degree), str(degree1), str(self.parametersPanel.pnlVarStartBD.Value), self.parametersPanel.pnlFinishPosBD.ID, str(degree2), str(degree3), str(self.parametersPanel.pnlVarFinishBD.Value), str(num), str(num4), str(round(num, 4)), str(round(num2, 4)), str(distance.NauticalMiles), str(distance.Kilometres) ]) GeoDetermineDlg.HistoryDataBD.append(dataList) self.setDataInHistoryModel(dataList) self.method_28_BD() def calculateMVD(self): degree = None degree1 = None degree2 = None result, degree, degree1 = self.parametersPanel.pnlPositionMVD.method_3( ) # position.method_1(out degree, out degree1); altitude = self.parametersPanel.pnlPositionMVD.Altitude() result, degree2 = Geo.smethod_7( degree, degree1, altitude, self.parametersPanel.cmbModel.SelectedIndex, self.parametersPanel.dtpDate.date()) if (result): self.parametersPanel.txtResult.Value = str(round( degree2, 4)) #.method_1(Formats.VariationFormat); date = self.parametersPanel.dtpDate.date() dataList = [] dataList.append([ "Latitude", "Longitude", "Altitude (m)", "Altitude (ft)", "Date", "Magnetic Model", "Magnetic Variation" ]) dataList.append([ str(degree), str(degree1), str(altitude.Metres), str(altitude.Feet), date.toString(), self.parametersPanel.cmbModel.SelectedItem, self.parametersPanel.txtResult.Value ]) GeoDetermineDlg.HistoryDataMV.append(dataList) self.setDataInHistoryModel(dataList) def autoCalcFinishMagVar(self): try: if self.parametersPanel.chbAutoFinishMagVar.Checked: finishPt = None finishLat = None finishLon = None degree3 = None num = None result, degree, degree1 = self.parametersPanel.pnlStartPosP.method_3( ) if (result): value = float(self.parametersPanel.txtForwardTP.Value) value1 = float(self.parametersPanel.txtForwardTP.Value) distance = self.parametersPanel.txtDistanceP.Value result1, degree2, degree3, num = Geo.smethod_6( self.parametersPanel.cmbCalculationTypeP.SelectedItem, degree, degree1, value, distance) if (result1): finishPt = Point3D(degree3, degree2) finishLat = degree2 finishLon = degree3 if finishPt != None and self.model != None and self.date != None: # result, degree, degree1 = self.parametersPanel.pnlStartPosP.method_3(); result2, degree2 = Geo.smethod_7(finishLat, finishLon, Altitude(0), self.model, self.date) if (result2): degree2 = round(degree2, 2) self.parametersPanel.pnlVarFinishP.Value = degree2 except: pass def btnConstruct_Click(self): # flag = FlightPlanBaseDlg.btnConstruct_Click(self) # if not flag: # return if self.parametersPanel.tabGeneral.currentIndex() == 0: self.autoCalcFinishMagVar() self.calculateP() elif self.parametersPanel.tabGeneral.currentIndex() == 1: self.calculateBD() else: self.calculateMVD() def initParametersPan(self): ui = Ui_GeoDetermine() self.parametersPanel = ui FlightPlanBaseDlg.initParametersPan(self) self.parametersPanel.pnlStartPosP = PositionPanel( self.parametersPanel.gbStartPosP, None, None, "Degree") # self.parametersPanel.pnlStartPosP.degreeFormat = "ddmmss.ssssH" self.parametersPanel.pnlStartPosP.alwwaysShowString = "Degree" # self.parametersPanel.pnlWaypoint.groupBox.setTitle("FAWP") self.parametersPanel.pnlStartPosP.btnCalculater.hide() self.parametersPanel.pnlStartPosP.hideframe_Altitude() # self.parametersPanel.pnlStartPosP.showframe_ID() self.parametersPanel.pnlStartPosP.setObjectName("pnlStartPosP") self.connect(self.parametersPanel.pnlStartPosP, SIGNAL("positionChanged"), self.autoCalcFinishMagVar) ui.verticalLayout_gbStartPosP.addWidget( self.parametersPanel.pnlStartPosP) self.parametersPanel.pnlVarStartP = DegreesBoxPanel(self) self.parametersPanel.pnlVarStartP.CaptionLabel = "Magnetic Variation" self.connect(self.parametersPanel.pnlVarStartP, SIGNAL("btnDegreeBoxPanel_clicked"), self.method_32_P) self.connect(self.parametersPanel.pnlVarStartP, SIGNAL("txtDegreeBox_textChanged"), self.txtDegreeBox_textChangedP) ui.verticalLayout_gbStartPosP.addWidget( self.parametersPanel.pnlVarStartP) self.parametersPanel.pnlVarFinishP = DegreesBoxPanel(self) self.parametersPanel.pnlVarFinishP.ButtonVisible = False self.parametersPanel.pnlVarFinishP.Enabled = False self.parametersPanel.pnlVarFinishP.CaptionLabel = "Magnetic Variation at Finish" ui.vLayout_grbParametersP.insertWidget( 1, self.parametersPanel.pnlVarFinishP) # self.connect(self.parametersPanel.pnlVarStartP, SIGNAL("btnDegreeBoxPanel_clicked"), self.method_32_P) self.parametersPanel.pnlStartPosBD = PositionPanel( self.parametersPanel.gbFinishPosBD, None, None, "Degree") # self.parametersPanel.pnlStartPosBD.groupBox.setTitle("FAWP") # self.parametersPanel.pnlStartPosBD.degreeFormat = "ddmmss.ssssH" self.parametersPanel.pnlStartPosBD.alwwaysShowString = "Degree" self.parametersPanel.pnlStartPosBD.btnCalculater.hide() self.parametersPanel.pnlStartPosBD.hideframe_Altitude() self.parametersPanel.pnlStartPosBD.showframe_ID() self.parametersPanel.pnlStartPosBD.setObjectName("pnlStartPosBD") ui.verticalLayout_gbStartPosBD.insertWidget( 0, self.parametersPanel.pnlStartPosBD) self.connect(self.parametersPanel.pnlStartPosBD, SIGNAL("positionChanged"), self.positionChangedStartBD) self.parametersPanel.pnlVarStartBD = DegreesBoxPanel(self) self.parametersPanel.pnlVarStartBD.CaptionLabel = "Magnetic Variation" # self.parametersPanel.pnlVarStartBD.Enabled = False self.connect(self.parametersPanel.pnlVarStartBD, SIGNAL("btnDegreeBoxPanel_clicked"), self.method_34_BD) # self.connect(self.parametersPanel.pnlVarStartBD, SIGNAL("txtDegreeBox_textChanged"), self.txtDegreeBox_textChangedP) ui.verticalLayout_gbStartPosBD.addWidget( self.parametersPanel.pnlVarStartBD) self.parametersPanel.pnlFinishPosBD = PositionPanel( self.parametersPanel.gbFinishPosBD, None, None, "Degree") # self.parametersPanel.pnlStartPosBD.groupBox.setTitle("FAWP") # self.parametersPanel.pnlFinishPosBD.degreeFormat = "ddmmss.ssssH" self.parametersPanel.pnlFinishPosBD.alwwaysShowString = "Degree" self.parametersPanel.pnlFinishPosBD.btnCalculater.hide() self.parametersPanel.pnlFinishPosBD.hideframe_Altitude() self.parametersPanel.pnlFinishPosBD.showframe_ID() self.parametersPanel.pnlFinishPosBD.setObjectName("pnlFinishPosBD") ui.verticalLayout_gbFinishPosBD.insertWidget( 0, self.parametersPanel.pnlFinishPosBD) self.connect(self.parametersPanel.pnlFinishPosBD, SIGNAL("positionChanged"), self.positionChangedFinishBD) self.parametersPanel.pnlVarFinishBD = DegreesBoxPanel(self) self.parametersPanel.pnlVarFinishBD.CaptionLabel = "Magnetic Variation" # self.parametersPanel.pnlVarFinishBD.Enabled = False self.connect(self.parametersPanel.pnlVarFinishBD, SIGNAL("btnDegreeBoxPanel_clicked"), self.method_36_BD) # self.connect(self.parametersPanel.pnlVarFinishBD, SIGNAL("txtDegreeBox_textChanged"), self.txtDegreeBox_textChangedP) ui.verticalLayout_gbFinishPosBD.addWidget( self.parametersPanel.pnlVarFinishBD) self.parametersPanel.pnlPositionMVD = PositionPanel( self.parametersPanel.tabGeoDetermineMV, None, None, "Degree") self.parametersPanel.pnlPositionMVD.groupBox.setTitle("Position") self.parametersPanel.pnlPositionMVD.alwwaysShowString = "Degree" self.parametersPanel.pnlPositionMVD.btnCalculater.hide() self.parametersPanel.pnlPositionMVD.setObjectName("pnlPositionMVD") ui.verticalLayout_3.insertWidget(0, self.parametersPanel.pnlPositionMVD) self.connect(self.parametersPanel.pnlPositionMVD, SIGNAL("positionChanged"), self.method_28_MVD) self.connect(self.parametersPanel.txtForwardTP, SIGNAL("Event_0"), self.txtForwardTP_textChanged) self.connect(self.parametersPanel.chbAutoFinishMagVar, SIGNAL("Event_0"), self.chbAutoFinishMagVar_clicked) self.connect(self.parametersPanel.txtDistanceP, SIGNAL("Event_0"), self.autoCalcFinishMagVar) self.connect(self.parametersPanel.txtForwardMP, SIGNAL("Event_0"), self.txtForwardMP_textChanged) self.parametersPanel.btnResultP.clicked.connect( self.btnResultP_clicked) self.parametersPanel.tabGeneral.currentChanged.connect( self.tabGeneral_CurrentChanged) self.parametersPanel.chbAutoVarBD.clicked.connect( self.chbAutoVarBD_clicked) self.parametersPanel.dtpDate.dateChanged.connect(self.method_28_MVD) self.connect(self.parametersPanel.cmbModel, SIGNAL("Event_0"), self.method_28_MVD) self.parametersPanel.btnDtpDate.clicked.connect( self.btnDtpDate_clicked) self.resultModelP = QStandardItemModel() self.parametersPanel.tblResultP.setModel(self.resultModelP) self.resultModelBD = QStandardItemModel() self.parametersPanel.tblResultBD.setModel(self.resultModelBD) self.ttt = 0 self.txtForwardTP_textChanged() self.setHistoryData() self.autoVarSet = False self.dateBD = QDate.currentDate() self.modelBD = MagneticModel.WMM2010 self.parametersPanel.btnResultBD.setVisible(False) self.parametersPanel.dtpDate.setDate(QDate.currentDate()) self.calendar = QCalendarWidget() self.calendar.clicked.connect(self.calendar_clicked) self.menu = QMenu() layout = QVBoxLayout(self.menu) layout.addWidget(self.calendar) def chbAutoFinishMagVar_clicked(self): if self.parametersPanel.chbAutoFinishMagVar.Checked: self.parametersPanel.pnlVarFinishP.Enabled = False else: self.parametersPanel.pnlVarFinishP.Enabled = True def calendar_clicked(self, date): self.parametersPanel.dtpDate.setDate(date) def btnDtpDate_clicked(self): rcRect = self.parametersPanel.btnDtpDate.geometry() ptPoint = rcRect.bottomLeft() self.menu.exec_(self.mapToGlobal(ptPoint)) def positionChangedStartBD(self): if (self.parametersPanel.chbAutoVarBD.isChecked() and self.autoVarSet): self.method_29_BD() self.method_31_BD() def positionChangedFinishBD(self): if (self.parametersPanel.chbAutoVarBD.isChecked() and self.autoVarSet): self.method_30_BD() self.method_31_BD() def chbAutoVarBD_clicked(self): if (self.parametersPanel.chbAutoVarBD.isChecked() and not self.autoVarSet): result, self.dateBD, self.modelBD = DlgMagneticVariationParameters.smethod_0( self.dateBD, self.modelBD) self.parametersPanel.chbAutoVarBD.setChecked(result) self.autoVarSet = self.parametersPanel.chbAutoVarBD.isChecked() if (self.parametersPanel.chbAutoVarBD.isChecked()): self.method_29_BD() self.method_30_BD() self.method_31_BD() def tabGeneral_CurrentChanged(self): if self.parametersPanel.tabGeneral.currentIndex() == 0: self.stdItemModelHistory.clear() if len(GeoDetermineDlg.HistoryDataP) > 0: self.setDataInHistoryModel(GeoDetermineDlg.HistoryDataP, True) pass elif self.parametersPanel.tabGeneral.currentIndex() == 1: self.stdItemModelHistory.clear() if len(GeoDetermineDlg.HistoryDataBD) > 0: self.setDataInHistoryModel(GeoDetermineDlg.HistoryDataBD, True) pass else: self.stdItemModelHistory.clear() if len(GeoDetermineDlg.HistoryDataMV) > 0: self.setDataInHistoryModel(GeoDetermineDlg.HistoryDataMV, True) pass def setHistoryData(self): if len(self.HistoryDataP) > 0: self.setDataInHistoryModel(GeoDetermineDlg.HistoryDataP, True) pass def btnResultP_clicked(self): self.resultModelP.clear() self.parametersPanel.pnlVarStartP.Value = self.parametersPanel.pnlVarFinishP.Value self.parametersPanel.pnlVarFinishP.Value = 0.0 self.parametersPanel.pnlStartPosP.Point3d = self.resultPoint3d def txtForwardTP_textChanged(self): if self.ttt == 0: self.ttt = 1 if self.ttt == 2: self.ttt = 0 if self.ttt == 1: try: value = float(self.parametersPanel.txtForwardTP.Value) self.parametersPanel.txtForwardMP.Value = MathHelper.smethod_3( value - float(self.parametersPanel.pnlVarStartP.Value)) self.autoCalcFinishMagVar() except: self.parametersPanel.txtForwardMP.Value = 0.0 def txtForwardMP_textChanged(self): if self.ttt == 0: self.ttt = 2 if self.ttt == 1: self.ttt = 0 if self.ttt == 2: try: value = float(self.parametersPanel.txtForwardMP.Value) self.parametersPanel.txtForwardTP.Value = MathHelper.smethod_3( value + float(self.parametersPanel.pnlVarStartP.Value)) except: self.parametersPanel.txtForwardTP.Value = 0.0 def txtDegreeBox_textChangedP(self): try: value = float(self.parametersPanel.txtForwardTP.Value) self.parametersPanel.txtForwardMP.Value = MathHelper.smethod_3( value - float(self.parametersPanel.pnlVarStartP.Value)) except: self.parametersPanel.txtForwardMP.Value = 0.0 def method_28_P(self, degrees_Lat, degrees_Lon): point3d = None point3d1 = None self.surfaceType = SurfaceTypes.GeoDeterminePosition flag = FlightPlanBaseDlg.btnConstruct_Click(self) if not flag: return if define._units == QGis.Meters: point3d0 = self.parametersPanel.pnlStartPosP.Point3d point3d = QgisHelper.CrsTransformPoint(point3d0.get_X(), point3d0.get_Y(), define._latLonCrs, define._xyCrs) point3d1 = QgisHelper.CrsTransformPoint(degrees_Lon, degrees_Lat, define._latLonCrs, define._xyCrs) else: point3d = self.parametersPanel.pnlStartPosP.Point3d point3d1 = Point3D(degrees_Lon, degrees_Lat) constructionLayer = None mapUnits = define._canvas.mapUnits() if self.parametersPanel.chbMarkPointsP.isChecked(): constructionLayer = AcadHelper.createVectorLayer( SurfaceTypes.GeoDeterminePosition + "_MarkPoint", QGis.Point) AcadHelper.setGeometryAndAttributesInLayer(constructionLayer, point3d) AcadHelper.setGeometryAndAttributesInLayer(constructionLayer, point3d1) # if mapUnits == QGis.Meters: # constructionLayer = QgsVectorLayer("point?crs=%s"%define._xyCrs.authid (), SurfaceTypes.GeoDeterminePosition + "_MarkPoint", "memory") # else: # constructionLayer = QgsVectorLayer("point?crs=%s"%define._latLonCrs.authid (), SurfaceTypes.GeoDeterminePosition + " MarkPoint", "memory") # # shpPath = "" # if define.obstaclePath != None: # shpPath = define.obstaclePath # elif define.xmlPath != None: # shpPath = define.xmlPath # else: # shpPath = define.appPath # er = QgsVectorFileWriter.writeAsVectorFormat(constructionLayer, shpPath + "/" + SurfaceTypes.GeoDeterminePosition + "_MarkPoint" + ".shp", "utf-8", constructionLayer.crs()) # constructionLayer = QgsVectorLayer(shpPath + "/" + SurfaceTypes.GeoDeterminePosition + "_MarkPoint" + ".shp", SurfaceTypes.GeoDeterminePosition + " MarkPoint", "ogr") # # constructionLayer.startEditing() # # feature = QgsFeature() # feature.setGeometry(QgsGeometry.fromPoint(point3d)) # constructionLayer.addFeature(feature) # feature.setGeometry(QgsGeometry.fromPoint(point3d1)) # constructionLayer.addFeature(feature) # constructionLayer.commitChanges() QgisHelper.appendToCanvas(define._canvas, [constructionLayer], SurfaceTypes.GeoDeterminePosition) self.resultLayerList.append(constructionLayer) if self.parametersPanel.chbDrawLineP.isChecked(): constructionLayer1 = AcadHelper.createVectorLayer( SurfaceTypes.GeoDeterminePosition + "_Line", QGis.Line) AcadHelper.setGeometryAndAttributesInLayer(constructionLayer1, [point3d, point3d1]) QgisHelper.appendToCanvas(define._canvas, [constructionLayer1], SurfaceTypes.GeoDeterminePosition) self.resultLayerList.append(constructionLayer1) def method_28_BD(self): point3d = None point3d1 = None self.surfaceType = SurfaceTypes.GeoDetermineBD flag = FlightPlanBaseDlg.btnConstruct_Click(self) if not flag: return if define._units == QGis.Meters: point3d0 = self.parametersPanel.pnlStartPosBD.Point3d point3dF0 = self.parametersPanel.pnlFinishPosBD.Point3d point3d = QgisHelper.CrsTransformPoint(point3d0.get_X(), point3d0.get_Y(), define._latLonCrs, define._xyCrs) point3d1 = QgisHelper.CrsTransformPoint(point3dF0.get_X(), point3dF0.get_Y(), define._latLonCrs, define._xyCrs) else: point3d = self.parametersPanel.pnlStartPosBD.Point3d point3d1 = self.parametersPanel.pnlFinishPosBD.Point3d constructionLayer = None mapUnits = define._canvas.mapUnits() if self.parametersPanel.chbMarkPointsBD.isChecked(): constructionLayer = AcadHelper.createVectorLayer( SurfaceTypes.GeoDetermineBD + "_MarkPoint", QGis.Point) AcadHelper.setGeometryAndAttributesInLayer(constructionLayer, point3d) AcadHelper.setGeometryAndAttributesInLayer(constructionLayer, point3d1) # if mapUnits == QGis.Meters: # constructionLayer = QgsVectorLayer("point?crs=%s"%define._xyCrs.authid (), SurfaceTypes.GeoDetermineBD + "_MarkPoint", "memory") # else: # constructionLayer = QgsVectorLayer("point?crs=%s"%define._latLonCrs.authid (), SurfaceTypes.GeoDetermineBD + " MarkPoint", "memory") # # shpPath = "" # if define.obstaclePath != None: # shpPath = define.obstaclePath # elif define.xmlPath != None: # shpPath = define.xmlPath # else: # shpPath = define.appPath # er = QgsVectorFileWriter.writeAsVectorFormat(constructionLayer, shpPath + "/" + QString(SurfaceTypes.GeoDetermineBD).replace(" ", "") + "_MarkPoint" + ".shp", "utf-8", constructionLayer.crs()) # constructionLayer = QgsVectorLayer(shpPath + "/" + QString(SurfaceTypes.GeoDetermineBD).replace(" ", "") + "_MarkPoint" + ".shp", SurfaceTypes.GeoDetermineBD + " MarkPoint", "ogr") # # constructionLayer.startEditing() # # # feature = QgsFeature() # feature.setGeometry(QgsGeometry.fromPoint(point3d)) # constructionLayer.addFeature(feature) # feature.setGeometry(QgsGeometry.fromPoint(point3d1)) # constructionLayer.addFeature(feature) # constructionLayer.commitChanges() QgisHelper.appendToCanvas(define._canvas, [constructionLayer], SurfaceTypes.GeoDetermineBD) self.resultLayerList.append(constructionLayer) if self.parametersPanel.chbDrawLineBD.isChecked(): constructionLayer = AcadHelper.createVectorLayer( SurfaceTypes.GeoDetermineBD + "_Line", QGis.Line) AcadHelper.setGeometryAndAttributesInLayer(constructionLayer, [point3d, point3d1]) QgisHelper.appendToCanvas(define._canvas, [constructionLayer], SurfaceTypes.GeoDetermineBD) self.resultLayerList.append(constructionLayer) def method_28_MVD(self): self.parametersPanel.txtResult.Value = "" def method_29_P(self): self.resultModelP.clear() self.resultModelP.setHorizontalHeaderLabels(["Type", "Value"]) def method_29_BD(self): degree = None degree1 = None degree2 = None if (self.parametersPanel.pnlStartPosBD.IsValid()): result, degree, degree1 = self.parametersPanel.pnlStartPosBD.method_3( ) result, degree2 = Geo.smethod_7(degree, degree1, Altitude(0), self.modelBD, self.dateBD) if (result): degree2 = round(degree2, 2) self.parametersPanel.pnlVarStartBD.Value = degree2 def method_30_BD(self): degree = None degree1 = None degree2 = None if (self.parametersPanel.pnlFinishPosBD.IsValid()): result, degree, degree1 = self.parametersPanel.pnlFinishPosBD.method_3( ) result, degree2 = Geo.smethod_7(degree, degree1, Altitude(0), self.modelBD, self.dateBD) if (result): degree2 = round(degree2, 2) self.parametersPanel.pnlVarFinishBD.Value = degree2 def method_31_BD(self): self.resultModelBD.clear() self.resultModelBD.setHorizontalHeaderLabels(["Type", "Value"]) def method_32_P(self): startPos = self.parametersPanel.pnlStartPosP.Point3d result, self.date, self.model = DlgMagneticVariationParameters.smethod_0( self.date, self.model) if self.parametersPanel.pnlStartPosP.IsValid() and result: result, degree, degree1 = self.parametersPanel.pnlStartPosP.method_3( ) result, degree2 = Geo.smethod_7(degree, degree1, Altitude(0), self.model, self.date) if (result): degree2 = round(degree2, 2) self.parametersPanel.pnlVarStartP.Value = degree2 try: self.parametersPanel.txtForwardMP.Value = MathHelper.smethod_3( float(self.parametersPanel.txtForwardTP.Value) - degree2) except: self.parametersPanel.txtForwardMP.Value = 0.0 self.method_29_P() def method_34_BD(self): startPos = self.parametersPanel.pnlStartPosBD.Point3d result, self.dateBD, self.modelBD = DlgMagneticVariationParameters.smethod_0( self.dateBD, self.modelBD) if self.parametersPanel.pnlStartPosBD.IsValid() and result: self.method_29_BD() self.method_31_BD() def method_36_BD(self): startPos = self.parametersPanel.pnlFinishPosBD.Point3d result, self.dateBD, self.modelBD = DlgMagneticVariationParameters.smethod_0( self.dateBD, self.modelBD) if self.parametersPanel.pnlFinishPosBD.IsValid() and result: self.method_30_BD() self.method_31_BD()
class Regression_PLOT_PyQt(QDialog): """ This calss return a PyQt GUI with a regression plot """ def __init__(self, Minerals=None, string=None, flag=None): super(Regression_PLOT_PyQt, self).__init__() if string is not None: self.stringK, self.stringG, self.stringRho, self.user_input = string else: self.stringK = None self.stringG = None self.stringRho = None self.user_input = False self.resize(1400, 600) self.Minerals = Minerals self.dirty = False #self.user_input = user_input self.Minerals.original_flag() self.Minerals.read_data() self.table = QTableView() self.model = QStandardItemModel(25, 7, self) self.model.setHorizontalHeaderLabels([ 'flag', 'Water Content', 'Iron Content', 'K (Gpa)', 'G (Gpa)', 'Rho (g/cm³)', 'Reference' ]) for i in range(len(self.Minerals.Flag)): a = self.Minerals.Return_original_data(i) for j in range(0, 7): item = QStandardItem(str(a[j])) self.model.setItem(i, j, item) if j != 0: item.setFlags(Qt.ItemIsEnabled) item.setBackground(QColor(211, 211, 211)) if flag is not None: self.Minerals.change_flag(flag) for i in range(len(self.Minerals.Flag)): item = QStandardItem(str(self.Minerals.Flag[i])) self.model.setItem(i, 0, item) self.table.setModel(self.model) self.button = QPushButton('Update and use in thermoelastic model') self.button.clicked.connect(self.Update) self.button.setAutoDefault(False) self.button1 = QPushButton('Add data file ') self.button1.clicked.connect(self.Export) self.button1.setAutoDefault(False) self.layout = QGridLayout() self.label = QLabel() self.label.setText(''' Please input equation, Water: water content (wt%) and Fe: iron content (mol%) for example -2.41*Water-30*Fe+81,K'=4.1, ''') self.Kinput_formula = QLineEdit() self.Ginput_formula = QLineEdit() self.Rhoinput_formula = QLineEdit() if self.stringK is not None: self.Kinput_formula.setText(self.stringK) self.Ginput_formula.setText(self.stringG) self.Rhoinput_formula.setText(self.stringRho) self.Userinput() else: self.Kinput_formula.setText( self.Minerals.Show_fit_function(self.Minerals.function_K()[0], self.Minerals.function_K()[1], "K'", error=False)) self.Ginput_formula.setText( self.Minerals.Show_fit_function(self.Minerals.function_G()[0], self.Minerals.function_G()[1], "G'", error=False)) self.Rhoinput_formula.setText( self.Minerals.Show_fit_function( self.Minerals.function_Rho()[0], self.Minerals.function_Rho()[1], '', error=False)) self.Kinput_formula.returnPressed.connect(self.Kformula) self.Ginput_formula.returnPressed.connect(self.Gformula) self.Rhoinput_formula.returnPressed.connect(self.Rhoformula) #self.connect(self.Kinput_formula,SIGNAL("returnPressed()"),self.Kformula) #self.connect(self.Ginput_formula,SIGNAL("returnPressed()"),self.Gformula) #self.connect(self.Rhoinput_formula,SIGNAL("returnPressed()"),self.Rhoformula) self.user_change_confrim = QPushButton('Change to user input') self.user_change_confrim.clicked.connect(self.Userinput) self.user_change_confrim.setAutoDefault(False) self.extension = QWidget() self.extensionLayout = QGridLayout() self.extensionLayout.setContentsMargins(0, 0, 0, 0) labelK = QLabel() labelK.setText('K<sub>0</sub>=') labelG = QLabel() labelG.setText('G<sub>0</sub>=') labelRho = QLabel() labelRho.setText('Rho<sub>0</sub>=') self.extensionLayout.addWidget(labelK, 0, 0, 1, 3) self.extensionLayout.addWidget(labelG, 1, 0, 1, 3) self.extensionLayout.addWidget(labelRho, 2, 0, 1, 3) self.extensionLayout.addWidget(self.Kinput_formula, 0, 1, 1, 3) self.extensionLayout.addWidget(self.Ginput_formula, 1, 1, 1, 3) self.extensionLayout.addWidget(self.Rhoinput_formula, 2, 1, 1, 3) self.extensionLayout.addWidget(self.user_change_confrim, 3, 0, 9, 4) self.extension.setLayout(self.extensionLayout) self.check_change = QCheckBox("user input") self.check_change.setChecked(False) self.check_change.toggled.connect(self.extension.setVisible) #self.PLOT(switch=True) self.PLOT() self.layout.addWidget(self.table, 0, 1, 1, 17) self.layout.addWidget(self.button, 2, 0, 1, 9) self.layout.addWidget(self.button1, 2, 9, 1, 9) self.layout.addWidget(self.check_change, 3, 0, 1, 1) self.layout.addWidget(self.label, 3, 3, 1, 5) self.layout.addWidget(self.extension, 4, 0, 1, 9) self.setLayout(self.layout) self.extension.hide() def Kformula(self): self.stringK = str(self.Kinput_formula.text()) self.K0 = np.array( re.findall(r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?", self.stringK)) return self.K0, self.stringK def Gformula(self): self.stringG = str(self.Ginput_formula.text()) self.G0 = np.array( re.findall(r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?", self.stringG)) return self.G0, self.stringG def Rhoformula(self): self.stringRho = str(self.Rhoinput_formula.text()) self.Rho0 = np.array( re.findall(r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?", self.stringRho)) return self.Rho0, self.stringRho def Userinput(self): self.Minerals.User_Change(self.Kformula(), self.Gformula(), self.Rhoformula()) self.user_input = True self.PLOT() def PLOT(self, switch=True): if self.dirty == False: #self.Minerals.Clean_content() params = [] for i in range(20): index = self.model.index(i, 0) try: aa = (float(self.model.itemData(index)[0])) #print (aa) params.append(aa) except: break #print (params) self.Minerals.Change_data_from_table(params) #print ('wf') else: self.model.setHorizontalHeaderLabels([ 'flag', 'Water Content', 'Iron Content', 'K (Gpa)', 'G (Gpa)', 'Rho (g/cm3)', 'Reference' ]) for i in range(len(self.Minerals.Flag)): #a=self.Minerals.Return_original_data(i) item = QStandardItem(str(self.Minerals.Flag[i])) self.model.setItem(i, 0, item) #============================================================================== # for j in range(1,7): # item = QStandardItem(str(a[j])) # self.model.setItem(i, j,item) # if j != 0: # item.setFlags(Qt.ItemIsEnabled) # item.setBackground(QColor(211,211,211)) #============================================================================== #print (self.Minerals.Change) if self.user_input == False: self.a, self.b, self.c = self.Minerals.PLOT(return_fig=False) #print (self.Minerals.number_of_data) self.Kinput_formula.setText( self.Minerals.Show_fit_function(self.Minerals.function_K()[0], self.Minerals.function_K()[1], "K'", error=False)) self.Ginput_formula.setText( self.Minerals.Show_fit_function(self.Minerals.function_G()[0], self.Minerals.function_G()[1], "G'", error=False)) self.Rhoinput_formula.setText( self.Minerals.Show_fit_function( self.Minerals.function_Rho()[0], self.Minerals.function_Rho()[1], '', error=False)) else: self.a, self.b, self.c = self.Minerals.PLOT_input_formula( return_fig=False) self.canvas1 = FigureCanvas3D(self.a) self.canvas2 = FigureCanvas3D(self.b) self.canvas3 = FigureCanvas3D(self.c) self.canvas1.mpl_connect('pick_event', self.onpick) self.canvas2.mpl_connect('pick_event', self.onpick) self.canvas3.mpl_connect('pick_event', self.onpick) self.toolbar1 = NavigationToolbar(self.canvas1, self) self.toolbar2 = NavigationToolbar(self.canvas2, self) self.toolbar3 = NavigationToolbar(self.canvas3, self) self.layout1_widget = QWidget() self.layout1 = QGridLayout(self.layout1_widget) self.layout1_widget.setFixedSize(600, 600) self.layout1.addWidget(self.canvas1, 0, 1, 5, 5) self.layout1.addWidget(self.toolbar1, 5, 1, 1, 5) self.layout1.addWidget(self.canvas2, 6, 1, 5, 5) self.layout1.addWidget(self.toolbar2, 11, 1, 1, 5) self.layout1.addWidget(self.canvas3, 12, 1, 5, 5) self.layout1.addWidget(self.toolbar3, 17, 1, 1, 5) self.layout.addWidget(self.layout1_widget, 0, 0, 1, 1) def onpick(self, event): try: for i in range(6): self.model.item(self.ind, i + 1).setBackground(QColor(211, 211, 211)) except: pass count = -1 for j in range(len((self.Minerals.Flag))): if self.Minerals.Flag[j] == 1: count += 1 if count == event.ind[0]: self.ind = j break #print (self.ind) #self.ind = event.ind for i in range(6): self.model.item(self.ind, i + 1).setBackground(QColor(111, 111, 111)) def Update(self): self.user_input = False self.dirty = False self.check_change.setChecked(False) self.PLOT() def Export(self): self.dirty = True dialog = TextEditor(name=self.Minerals.name) if dialog.exec_(): pass self.Minerals.read_data() self.PLOT() def ReturnString(self): aa = self.Minerals.Flag bb = str(int(aa[0])) for i in range(1, len(aa)): bb += str(int(aa[i])) return [self.stringK, self.stringG, self.stringRho, self.user_input], bb
def main(icon_spec): app = QApplication(sys.argv) main_window = QMainWindow() def sigint_handler(*args): main_window.close() signal.signal(signal.SIGINT, sigint_handler) # the timer enables triggering the sigint_handler signal_timer = QTimer() signal_timer.start(100) signal_timer.timeout.connect(lambda: None) tool_bar = QToolBar() main_window.addToolBar(Qt.TopToolBarArea, tool_bar) table_view = QTableView() table_view.setSelectionBehavior(QAbstractItemView.SelectRows) table_view.setSelectionMode(QAbstractItemView.SingleSelection) table_view.setSortingEnabled(True) main_window.setCentralWidget(table_view) proxy_model = QSortFilterProxyModel() proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive) proxy_model.setFilterKeyColumn(1) table_view.setModel(proxy_model) proxy_model.layoutChanged.connect(table_view.resizeRowsToContents) item_model = QStandardItemModel() proxy_model.setSourceModel(item_model) # get all icons and their available sizes QIcon.setThemeName("gnome") icons = [] all_sizes = set([]) for context, icon_names in icon_spec: for icon_name in icon_names: icon = QIcon.fromTheme(icon_name) sizes = [] for size in icon.availableSizes(): size = (size.width(), size.height()) sizes.append(size) all_sizes.add(size) sizes.sort() icons.append({ 'context': context, 'icon_name': icon_name, 'icon': icon, 'sizes': sizes, }) all_sizes = list(all_sizes) all_sizes.sort() # input field for filter def filter_changed(value): proxy_model.setFilterRegExp(value) table_view.resizeRowsToContents() filter_line_edit = QLineEdit() filter_line_edit.setMaximumWidth(200) filter_line_edit.setPlaceholderText('Filter name') filter_line_edit.setToolTip( 'Filter name optionally using regular expressions (' + QKeySequence(QKeySequence.Find).toString() + ')') filter_line_edit.textChanged.connect(filter_changed) tool_bar.addWidget(filter_line_edit) # actions to toggle visibility of available sizes/columns def action_toggled(index): column = 2 + index table_view.setColumnHidden(column, not table_view.isColumnHidden(column)) table_view.resizeColumnsToContents() table_view.resizeRowsToContents() signal_mapper = QSignalMapper() for i, size in enumerate(all_sizes): action = QAction('%dx%d' % size, tool_bar) action.setCheckable(True) action.setChecked(True) tool_bar.addAction(action) action.toggled.connect(signal_mapper.map) signal_mapper.setMapping(action, i) # set tool tip and handle key sequence tool_tip = 'Toggle visibility of column' if i < 10: digit = ('%d' % (i + 1))[-1] tool_tip += ' (%s)' % QKeySequence('Ctrl+%s' % digit).toString() action.setToolTip(tool_tip) signal_mapper.mapped.connect(action_toggled) # label columns header_labels = ['context', 'name'] for width, height in all_sizes: header_labels.append('%dx%d' % (width, height)) item_model.setColumnCount(len(header_labels)) item_model.setHorizontalHeaderLabels(header_labels) # fill rows item_model.setRowCount(len(icons)) for row, icon_data in enumerate(icons): # context item = QStandardItem(icon_data['context']) item.setFlags(item.flags() ^ Qt.ItemIsEditable) item_model.setItem(row, 0, item) # icon name item = QStandardItem(icon_data['icon_name']) item.setFlags(item.flags() ^ Qt.ItemIsEditable) item_model.setItem(row, 1, item) for index_in_all_sizes, size in enumerate(all_sizes): column = 2 + index_in_all_sizes if size in icon_data['sizes']: # icon as pixmap to keep specific size item = QStandardItem('') pixmap = icon_data['icon'].pixmap(size[0], size[1]) item.setData(pixmap, Qt.DecorationRole) item.setFlags(item.flags() ^ Qt.ItemIsEditable) item_model.setItem(row, column, item) else: # single space to be sortable against icons item = QStandardItem(' ') item.setFlags(item.flags() ^ Qt.ItemIsEditable) item_model.setItem(row, column, item) table_view.resizeColumnsToContents() # manually set row heights because resizeRowsToContents is not working properly for row, icon_data in enumerate(icons): if len(icon_data['sizes']) > 0: max_size = icon_data['sizes'][-1] table_view.setRowHeight(row, max_size[1]) # enable focus find (ctrl+f) and toggle columns (ctrl+NUM) def main_window_keyPressEvent(self, event, old_keyPressEvent=QMainWindow.keyPressEvent): if event.matches(QKeySequence.Find): filter_line_edit.setFocus() return if event.modifiers() == Qt.ControlModifier and event.key( ) >= Qt.Key_0 and event.key() <= Qt.Key_9: index = event.key() - Qt.Key_1 if event.key() == Qt.Key_0: index += 10 action = signal_mapper.mapping(index) if action: action.toggle() return old_keyPressEvent(self, event) main_window.keyPressEvent = new.instancemethod(main_window_keyPressEvent, table_view, None) # enable copy (ctrl+c) name of icon to clipboard def table_view_keyPressEvent(self, event, old_keyPressEvent=QTableView.keyPressEvent): if event.matches(QKeySequence.Copy): selection_model = self.selectionModel() if selection_model.hasSelection(): index = selection_model.selectedRows()[0] source_index = self.model().mapToSource(index) item = self.model().sourceModel().item(source_index.row(), 1) icon_name = item.data(Qt.EditRole) app.clipboard().setText(icon_name.toString()) return old_keyPressEvent(self, event) table_view.keyPressEvent = new.instancemethod(table_view_keyPressEvent, table_view, None) print 'Icon Theme: ', QIcon.themeName() print 'Theme Search Paths:' for item in QIcon.themeSearchPaths(): print item main_window.showMaximized() return app.exec_()
class ConfigDialog(BASE, WIDGET): def __init__(self, toolbox): super(ConfigDialog, self).__init__(None) self.setupUi(self) self.toolbox = toolbox self.groupIcon = QIcon() self.groupIcon.addPixmap(self.style().standardPixmap( QStyle.SP_DirClosedIcon), QIcon.Normal, QIcon.Off) self.groupIcon.addPixmap(self.style().standardPixmap( QStyle.SP_DirOpenIcon), QIcon.Normal, QIcon.On) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText(self.tr('Search...')) self.model = QStandardItemModel() self.tree.setModel(self.model) self.delegate = SettingDelegate() self.tree.setItemDelegateForColumn(1, self.delegate) self.searchBox.textChanged.connect(self.fillTree) self.fillTree() self.tree.expanded.connect(self.adjustColumns) def fillTree(self): self.items = {} self.model.clear() self.model.setHorizontalHeaderLabels([self.tr('Setting'), self.tr('Value')]) text = unicode(self.searchBox.text()) settings = ProcessingConfig.getSettings() rootItem = self.model.invisibleRootItem() priorityKeys = [self.tr('General'), self.tr('Models'), self.tr('Scripts')] for group in priorityKeys: groupItem = QStandardItem(group) icon = ProcessingConfig.getGroupIcon(group) groupItem.setIcon(icon) groupItem.setEditable(False) emptyItem = QStandardItem() emptyItem.setEditable(False) rootItem.insertRow(0, [groupItem, emptyItem]) for setting in settings[group]: if setting.hidden: continue if text == '' or text.lower() in setting.description.lower(): labelItem = QStandardItem(setting.description) labelItem.setIcon(icon) labelItem.setEditable(False) self.items[setting] = SettingItem(setting) groupItem.insertRow(0, [labelItem, self.items[setting]]) if text != '': self.tree.expand(groupItem.index()) providersItem = QStandardItem(self.tr('Providers')) icon = QIcon(os.path.join(pluginPath, 'images', 'alg.png')) providersItem.setIcon(icon) providersItem.setEditable(False) emptyItem = QStandardItem() emptyItem.setEditable(False) rootItem.insertRow(0, [providersItem, emptyItem]) for group in settings.keys(): if group in priorityKeys: continue groupItem = QStandardItem(group) icon = ProcessingConfig.getGroupIcon(group) groupItem.setIcon(icon) groupItem.setEditable(False) for setting in settings[group]: if setting.hidden: continue if text == '' or text.lower() in setting.description.lower(): labelItem = QStandardItem(setting.description) labelItem.setIcon(icon) labelItem.setEditable(False) self.items[setting] = SettingItem(setting) groupItem.insertRow(0, [labelItem, self.items[setting]]) emptyItem = QStandardItem() emptyItem.setEditable(False) providersItem.appendRow([groupItem, emptyItem]) self.tree.sortByColumn(0, Qt.AscendingOrder) self.adjustColumns() def accept(self): for setting in self.items.keys(): if isinstance(setting.value, bool): setting.value = self.items[setting].checkState() == Qt.Checked elif isinstance(setting.value, (float, int, long)): value = unicode(self.items[setting].text()) try: value = float(value) setting.value = value except ValueError: QMessageBox.critical(self, self.tr('Wrong value'), self.tr('Wrong parameter value:\n%1') % value) return else: setting.value = unicode(self.items[setting].text()) setting.save() Processing.updateAlgsList() QDialog.accept(self) def adjustColumns(self): self.tree.resizeColumnToContents(0) self.tree.resizeColumnToContents(1)
class SharedSqlQueries: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale UNUSED # locale = QSettings().value('locale/userLocale')[0:2] # locale_path = os.path.join( # self.plugin_dir, # 'i18n', # 'SharedSqlQueries_{}.qm'.format(locale)) # # if os.path.exists(locale_path): # self.translator = QTranslator() # self.translator.load(locale_path) # # if qVersion() > '4.3.3': # QCoreApplication.installTranslator(self.translator) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Shared SQL Queries') self.toolbar = self.iface.addToolBar(u'SharedSqlQueries') self.toolbar.setObjectName(u'SharedSqlQueries') #print "** INITIALIZING SharedSqlQueries" #self.dockwidget = None #combo of queries files self.comboxQueries = None self.config = None self.queriesFolder = None self.dbrequest = None self.selectedQueryPath = None self.pluginIsActive = False # init related to config file. Return False if no config.json has been found def init_config(self): #just once if self.config is not None: return True #config file (in plugin directory) : configpath = os.path.dirname(__file__) + '/config.json' try: self.config = JsonFile(configpath) except IOError: # copy default config json if it does not exist self.errorMessage(self.tr( u"No config.json file found ! A default one is created but you have to edit it (in your plugin directory)")) configpath_default = os.path.dirname(__file__) + '/config_default.json' copyfile(configpath_default, configpath) return False self.queriesFolder = self.config.value("queries_folder") #database self.dbrequest = Connection(self.config.value("bdpostgis")) return True # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass #return QCoreApplication.translate('SharedSqlQueries', message) return translate.tr(message) #simplier def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.toolbar.addAction(action) if add_to_menu: self.iface.addPluginToMenu( self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/SharedSqlQueries/icon.png' self.add_action( icon_path, text=self.tr(u'Shared SQL Queries'), callback=self.run, parent=self.iface.mainWindow()) #combo of queries files self.comboxQueries = QComboBox() self.comboxQueries.setMinimumHeight(27) self.comboxQueries.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) # its model : self.queriesModel = QStandardItemModel() self.comboxQueries.setModel(self.queriesModel) # and its view (treeview) : self.queriesView = QTreeView() self.queriesView.setHeaderHidden(True) self.queriesView.setMinimumHeight(300) setWidgetWidth(self.comboxQueries, 0, 0) #no visible self.comboxQueries.setView(self.queriesView) # capture last clicked query self.queriesView.activated.connect(self.querySelected) self.queriesView.pressed.connect(self.querySelected) self.toolbar.addWidget(self.comboxQueries) #Run query button self.buttonRunQuery = QPushButton(self.tr("Open")) setWidgetWidth(self.buttonRunQuery, 0, 0) #no visible self.buttonRunQuery.clicked.connect(self.runQuery) self.toolbar.addWidget(self.buttonRunQuery) #-------------------------------------------------------------------------- def onClosePlugin(self): """Cleanup necessary items here when plugin dockwidget is closed""" #print "** CLOSING SharedSqlQueries" # disconnects #self.dockwidget.closingPlugin.disconnect(self.onClosePlugin) self.pluginIsActive = False def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" #print "** UNLOAD SharedSqlQueries" for action in self.actions: self.iface.removePluginMenu( self.tr(u'Shared SQL Queries'), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar #-------------------------------------------------------------------------- def run(self): """Run method that loads and starts the plugin""" # look for config file (required at the first run) if not self.init_config(): # invalid config file return if not self.pluginIsActive: self.pluginIsActive = True #first init #print "** STARTING SharedSqlQueries" # dockwidget may not exist if: # first run of plugin # removed on close (see self.onClosePlugin method) #if self.dockwidget == None: # Create the dockwidget (after translation) and keep reference # self.dockwidget = SharedSqlQueriesDockWidget() # connect to provide cleanup on closing of dockwidget #self.dockwidget.closingPlugin.connect(self.onClosePlugin) # show the dockwidget #self.iface.addDockWidget(Qt.TopDockWidgetArea, self.dockwidget) #self.dockwidget.show() #Togle visibility of toolbar options (set width coz visible is not usable in toolbar) show_options = (self.comboxQueries.minimumWidth() == 0) if show_options: self.updateComboQueries() setWidgetWidth(self.comboxQueries, 300, 300) setWidgetWidth(self.buttonRunQuery, 0, 120) else: setWidgetWidth(self.comboxQueries, 0, 0) setWidgetWidth(self.buttonRunQuery, 0, 0) #display an error def errorMessage(self, message): self.iface.messageBar().pushMessage(self.tr(u"Error"), message, level=QgsMessageBar.CRITICAL) #read file in query folder and show them in combo tree view def updateComboQueries(self): self.queriesModel.clear() self.queriesModel.setHorizontalHeaderLabels(['Files']) item = QStandardItem(self.tr(u"Query File")) item.setSelectable(False) self.queriesModel.appendRow(item) # read directories with sql files for path, dirs, files in os.walk(self.queriesFolder): for rep in dirs: item = QStandardItem(rep) item.setData(rep, Qt.UserRole) item.setSelectable(False) self.queriesModel.appendRow(item) # in each directory, look for sql files for nomfich in glob.glob(self.queriesFolder + "/" + rep + "/*.sql"): fileName, fileExtension = os.path.splitext(os.path.basename(nomfich)) # one item found subitem = QStandardItem(fileName) subitem.setData(nomfich, Qt.UserRole) item.appendRow(subitem) #last selected query def querySelected(self, index): item = self.queriesModel.itemFromIndex(index) self.selectedQueryPath = item.data(Qt.UserRole) #run selected query def runQuery(self): #print self.comboxQueries.currentText() #print self.selectedQueryPath try: query = CustomSqlQuery(self.selectedQueryPath) except UnicodeDecodeError: self.errorMessage(self.tr(u"Query File is not UTF8 encoded ! Please convert it to UTF8 !")) return except SyntaxError as e: self.errorMessage(e.text) return except Exception as e: self.errorMessage(str(e)) return # open param dialog dialog = QueryParamDialog(self.iface, self.dbrequest, query, self.toolbar) if dialog.exec_() == QDialog.Accepted: if dialog.errorMessage != "": self.errorMessage(dialog.errorMessage) return # format query as a Qgis readable sql source sql = query.updateFinalSql() QgsMessageLog.logMessage(sql, "SharedSql", QgsMessageLog.INFO) # add the corresponding layer try: # save query in a memory layer if query.headerValue("layer storage") == "memory": layer = self.dbrequest.sqlAddMemoryLayer(sql, query.headerValue("layer name"), query.headerValue("gid"), query.headerValue("geom")) # save query directly as a sql layer elif query.headerValue("layer storage") == "source": layer = self.dbrequest.sqlAddLayer(sql, query.headerValue("layer name"), query.headerValue("gid"), query.headerValue("geom")) # save query in a file layer else: type = query.headerValue("layer storage").lower() driver = None if type == "geojson": driver = "GeoJSON" if type == "shp": driver = "ESRI Shapefile" if driver is None: self.errorMessage(self.tr(u"Unknown file type : ") + str(type)) return directory = query.headerValue("layer directory") if directory is None: self.errorMessage(self.tr(u"No layer directory parameter found in query !")) return name = query.headerValue("layer name") # new layer name and file name if file already exists filepath = directory + "/" + name + "." + type filecount = 1 new_name = name while os.path.exists(filepath): # file already exists filecount += 1 new_name = name + "_" + str(filecount) filepath = directory + "/" + new_name + "." + type name = new_name #wait cursor QApplication.setOverrideCursor(Qt.WaitCursor) # add new layer layer = self.dbrequest.sqlAddFileLayer(sql, driver, filepath, name, query.headerValue("gid"), query.headerValue("geom")) QApplication.setOverrideCursor(Qt.ArrowCursor) except SyntaxError as e: QApplication.setOverrideCursor(Qt.ArrowCursor) # sql is correct but does not fit QGIS requirement (like '%' char) self.errorMessage(self.tr(e.text)) return if layer is None: self.errorMessage(self.tr(u"Unable to add a layer corresponding to this query !") + sql) # sql which is used in layer query print makeSqlValidForLayer(sql) return # if there's a qml style file corresponding to the query, apply it to the newly added layer if os.path.exists(query.styleFilePath()): layer.loadNamedStyle(query.styleFilePath())