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
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 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)))
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 OWCorrelations(OWWidget): name = "Correlations" description = "Calculate correlation" icon = "icons/correlation.svg" inputs = [("Data", Table, 'set_data')] outputs = [("Correlations", Table), ("Variables", AttributeList)] def __init__(self): super().__init__() self.data = None self.pairwise_correlations = True self.correlations_type = 0 self.selected_index = None self.changed_flag = False self.auto_commit = True self.splitter_state = None self.corr_graph = CorrelationsGraph(self) self.mainArea.layout().addWidget(self.corr_graph.plot_widget) self.resize(1000, 500) # TODO better size handling gui.radioButtonsInBox( self.controlArea, self, "correlations_type", ("Pairwise Pearson correlation", "Pairwise Spearman correlation"), box="Correlations", callback=self.on_corr_type_change) self.corr_table = CorrelationsTableView() self.corr_model = QStandardItemModel() self.corr_table.setModel(self.corr_model) self.controlArea.layout().addWidget(self.corr_table) self.corr_table.selectionModel().selectionChanged.connect( self.on_table_selection_change) @property def target_variable(self): if self.data: return self.data.domain.class_var else: return None def on_corr_type_change(self): """Do necessary actions after correlation type change. Clear computed data, set selected by user variables and finally commit(_if) changes. """ if self.data is not None: curr_selection = self.selected_vars self.clear_computed() self.run() if curr_selection: try: self.set_selected_vars(*curr_selection) except Exception as ex: import traceback traceback.print_exc() self.commit_if() def on_table_selection_change(self, selected, deselected): indexes = self.corr_table.selectionModel().selectedIndexes() if indexes: index = indexes[0] i, j = index.row(), index.column() if self.correlations_type == 2 and \ is_continuous(self.target_variable): j = len(self.var_names) - 1 vars = [self.cont_vars[i], self.cont_vars[j]] self.corr_graph.update_data(vars[0], vars[1], i, j) else: vars = None self.selected_vars = vars self.send("Variables", vars) def clear_computed(self): """Clear computed data.""" self.corr_model.clear() self.set_all_pairwise_matrix(None) self.set_target_correlations(None, None) def set_selected_vars(self, x, y): """Set selected by user variable(s).""" x = self.cont_vars.index(x) y = self.cont_vars.index(y) if self.correlations_type == 2: y = 0 model = self.corr_model sel_model = self.corr_table.selectionModel() sel_model.select(model.index(x, y), QItemSelectionModel.ClearAndSelect) def set_data(self, data): """ Check if data has enough continuous variables. Update data, correlation type, correlation graph and commit changes. """ self.clear() self.information() self.data = data if data is None: return if len(list(filter(lambda x: x.is_continuous, data.domain))) >= 2: self.set_variables_list(data) self.selected_index = None self.corr_graph.set_data(data) if self.selected_index is None or \ any(n in self.data.domain for n in self.selected_index): self.selected_index = self.var_names[:2] self.run() else: self.data = None self.information("Need data with at least 2 continuous variables.") self.commit_if() self.send("Correlations", Table(data)) def clear(self): """ Clear all widget data. """ self.data = None self.selected_vars = None self.clear_graph() def clear_graph(self): self.corr_graph._clear_plot_widget() self.corr_graph.set_data(None, None) self.corr_graph.replot() def set_variables_list(self, data): ''' :param data: data :return: sets cont_vars and var_names ''' vars = list(data.domain.variables) vars = [v for v in vars if v.is_continuous] self.cont_vars = vars self.var_names = [v.name for v in vars] def run(self): """ Start data matrix creation. """ if self.correlations_type < 2: if self.correlations_type == 0: matrix = pairwise_pearson_correlations(self.data, self.cont_vars) elif self.correlations_type == 1: matrix = pairwise_spearman_correlations( self.data, self.cont_vars) self.set_all_pairwise_matrix(matrix) elif self.target_variable and self.target_variable.is_continuous: vars = [v for v in self.cont_vars if v != self.target_variable] p_corr = target_pearson_correlations(self.data, vars, self.target_variable) s_corr = target_spearman_correlations(self.data, vars, self.target_variable) correlations = [list(t) for t in zip(p_corr, s_corr)] self.set_target_correlations(correlations, vars) def set_all_pairwise_matrix(self, matrix): """ Set data matrix to correlations model and resize table. """ self.matrix = matrix if matrix is not None: for i, row in enumerate(matrix): for j, e in enumerate(row): item = QStandardItem() if i != j: item.setData(str(round(e, 5)), Qt.DisplayRole) else: item.setData(QColor(192, 192, 192), Qt.BackgroundRole) self.corr_model.setItem(i, j, item) vars = self.cont_vars header = [v.name for v in vars] self.corr_model.setVerticalHeaderLabels(header) self.corr_model.setHorizontalHeaderLabels(header) self.corr_table.resizeColumnsToContents() self.corr_table.resizeRowsToContents() self.corr_table.updateGeometry() def set_target_correlations(self, correlations, vars=None): self.target_correlations = correlations if correlations is not None: for i, row in enumerate(correlations): for j, c in enumerate(row): item = QStandardItem() item.setData(c, Qt.DisplayRole) self.corr_model.setItem(i, j, item) if vars is None: vars = self.cont_vars v_header = [v.name for v in vars] h_header = ["Pearson", "Spearman"] self.corr_model.setVerticalHeaderLabels(v_header) self.corr_model.setHorizontalHeaderLabels(h_header) self.corr_table.resizeColumnsToContents() self.corr_table.resizeRowsToContents() QTimer.singleShot(100, self.corr_table.updateGeometry) def commit_if(self): if self.auto_commit: self.commit() else: self.changed_flag = True def commit(self): table = None if self.data is not None: if self.correlations_type == 2 and self.target_variable and \ self.target_variable.is_continuous: pearson = ContinuousVariable.make("Pearson") spearman = ContinuousVariable.make("Spearman") row_name = StringVariable.make("Variable") domain = Orange.data.Domain([pearson, spearman], metas=[row_name]) table = Orange.data.Table(domain, self.target_correlations) for inst, name in zip(table, self.var_names): inst[row_name] = name self.send("Correlations", table) def selection_changed(self): # TODO FIX IT pass
class DoProfile(QWidget): def __init__(self, iface, dockwidget1 , tool1 , plugin, parent = None): QWidget.__init__(self, parent) self.profiles = None #dictionary where is saved the plotting data {"l":[l],"z":[z], "layer":layer1, "curve":curve1} self.xAxisSteps = None self.xAxisStepType = "numeric" self.iface = iface self.tool = tool1 self.dockwidget = dockwidget1 self.pointstoDraw = None self.plugin = plugin #init scale widgets self.dockwidget.sbMaxVal.setValue(0) self.dockwidget.sbMinVal.setValue(0) self.dockwidget.sbMaxVal.setEnabled(False) self.dockwidget.sbMinVal.setEnabled(False) self.dockwidget.sbMinVal.valueChanged.connect(self.reScalePlot) self.dockwidget.sbMaxVal.valueChanged.connect(self.reScalePlot) #**************************** function part ************************************************* # remove layers which were removed from QGIS def removeClosedLayers(self, model1): qgisLayerNames = [] for i in range(0, self.iface.mapCanvas().layerCount()): qgisLayerNames.append(self.iface.mapCanvas().layer(i).name()) for i in range(0 , model1.rowCount()): layerName = model1.item(i,2).data(Qt.EditRole) if not layerName in qgisLayerNames: self.plugin.removeLayer(i) self.removeClosedLayers(model1) break def calculatePointProfile(self, point, model, library): self.model = model self.library = library statName = self.getPointProfileStatNames()[0] self.removeClosedLayers(model) if point == None: return PlottingTool().clearData(self.dockwidget, model, library) self.profiles = [] #creating the plots of profiles for i in range(0 , model.rowCount()): self.profiles.append( {"layer": model.item(i,3).data(Qt.EditRole) } ) self.profiles[i][statName] = [] self.profiles[i]["l"] = [] layer = self.profiles[i]["layer"] if layer: try: ident = layer.dataProvider().identify(point, QgsRaster.IdentifyFormatValue ) except: ident = None else: ident = None #if ident is not None and ident.has_key(choosenBand+1): if ident is not None: self.profiles[i][statName] = ident.results().values() self.profiles[i]["l"] = ident.results().keys() self.setXAxisSteps() PlottingTool().attachCurves(self.dockwidget, self.profiles, model, library) PlottingTool().reScalePlot(self.dockwidget, self.profiles, model, library) self.setupTableTab(model) def getPointProfileStatNames(self): return ["value"] # The code is based on the approach of ZonalStatistics from Processing toolbox def calculatePolygonProfile(self, geometry, crs, model, library): self.model = model self.library = library self.removeClosedLayers(model) if geometry is None or geometry.isEmpty(): return PlottingTool().clearData(self.dockwidget, model, library) self.profiles = [] #creating the plots of profiles for i in range(0 , model.rowCount()): self.profiles.append( {"layer": model.item(i,3).data(Qt.EditRole) } ) self.profiles[i]["l"] = [] for statistic in self.getPolygonProfileStatNames(): self.profiles[i][statistic] = [] # Get intersection between polygon geometry and raster following ZonalStatistics code rasterDS = gdal.Open(self.profiles[i]["layer"].source(), gdal.GA_ReadOnly) geoTransform = rasterDS.GetGeoTransform() cellXSize = abs(geoTransform[1]) cellYSize = abs(geoTransform[5]) rasterXSize = rasterDS.RasterXSize rasterYSize = rasterDS.RasterYSize rasterBBox = QgsRectangle(geoTransform[0], geoTransform[3] - cellYSize * rasterYSize, geoTransform[0] + cellXSize * rasterXSize, geoTransform[3]) rasterGeom = QgsGeometry.fromRect(rasterBBox) memVectorDriver = ogr.GetDriverByName('Memory') memRasterDriver = gdal.GetDriverByName('MEM') intersectedGeom = rasterGeom.intersection(geometry) ogrGeom = ogr.CreateGeometryFromWkt(intersectedGeom.exportToWkt()) bbox = intersectedGeom.boundingBox() xMin = bbox.xMinimum() xMax = bbox.xMaximum() yMin = bbox.yMinimum() yMax = bbox.yMaximum() (startColumn, startRow) = self.mapToPixel(xMin, yMax, geoTransform) (endColumn, endRow) = self.mapToPixel(xMax, yMin, geoTransform) width = endColumn - startColumn height = endRow - startRow if width == 0 or height == 0: return srcOffset = (startColumn, startRow, width, height) newGeoTransform = ( geoTransform[0] + srcOffset[0] * geoTransform[1], geoTransform[1], 0.0, geoTransform[3] + srcOffset[1] * geoTransform[5], 0.0, geoTransform[5], ) # Create a temporary vector layer in memory memVDS = memVectorDriver.CreateDataSource('out') memLayer = memVDS.CreateLayer('poly', crs, ogr.wkbPolygon) ft = ogr.Feature(memLayer.GetLayerDefn()) ft.SetGeometry(ogrGeom) memLayer.CreateFeature(ft) ft.Destroy() # Rasterize it rasterizedDS = memRasterDriver.Create('', srcOffset[2], srcOffset[3], 1, gdal.GDT_Byte) rasterizedDS.SetGeoTransform(newGeoTransform) gdal.RasterizeLayer(rasterizedDS, [1], memLayer, burn_values=[1]) rasterizedArray = rasterizedDS.ReadAsArray() for bandNumber in range(1, rasterDS.RasterCount+1): rasterBand = rasterDS.GetRasterBand(bandNumber) noData = rasterBand.GetNoDataValue() if noData is None: noData = np.nan scale = rasterBand.GetScale() if scale is None: scale = 1.0 offset = rasterBand.GetOffset() if offset is None: offset = 0.0 srcArray = rasterBand.ReadAsArray(*srcOffset) srcArray = srcArray*scale+offset masked = np.ma.MaskedArray(srcArray, mask=np.logical_or.reduce(( srcArray == noData, np.logical_not(rasterizedArray), np.isnan(srcArray)))) self.profiles[i]["l"].append(bandNumber) self.profiles[i]["count"].append(float(masked.count())) self.profiles[i]["max"].append(float(masked.max())) self.profiles[i]["mean"].append(float(masked.mean())) self.profiles[i]["median"].append(float(np.ma.median(masked))) self.profiles[i]["min"].append(float(masked.min())) self.profiles[i]["range"].append(float(masked.max()) - float(masked.min())) self.profiles[i]["std"].append(float(masked.std())) self.profiles[i]["sum"].append(float(masked.sum())) self.profiles[i]["unique"].append(np.unique(masked.compressed()).size) self.profiles[i]["var"].append(float(masked.var())) memVDS = None rasterizedDS = None rasterDS = None self.setXAxisSteps() PlottingTool().attachCurves(self.dockwidget, self.profiles, model, library) PlottingTool().reScalePlot(self.dockwidget, self.profiles, model, library) self.setupTableTab(model) def getPolygonProfileStatNames(self): return ["count", "max", "mean", "median", "min", "range", "std", "sum", "unique", "var"] def setXAxisSteps(self): if self.xAxisSteps == None: self.changeXAxisStepType("numeric") return elif self.xAxisSteps[0] == "Timesteps": self.changeXAxisStepType("numeric") for profile in self.profiles: stepsNum = len(profile["l"]) startTime = self.xAxisSteps[1] step = self.xAxisSteps[2] stepType = self.xAxisSteps[3] useNetcdfTime = self.xAxisSteps[4] if stepType == "years": stepType = "days" step = step * 365 elif stepType == "months": stepType = "days" step = step * 365/12 profile["l"] = [] if useNetcdfTime and (profile["layer"].source().startswith("NETCDF:") or profile["layer"].source().endswith(".nc")): try: import netCDF4 if profile["layer"].source().startswith("NETCDF:"): filename = re.match('NETCDF:\"(.*)\":.*$', profile["layer"].source()).group(1) else: filename = profile["layer"].source() nc = netCDF4.Dataset(filename, mode='r') profile["l"] = netCDF4.num2date(nc.variables["time"][:], units = nc.variables["time"].units, calendar = nc.variables["time"].calendar) nc.close() except ImportError: text = "Temporal/Spectral Profile Tool: netCDF4 module is required to read NetCDF " + \ "time dimension. Please use pip install netCDF4" self.iface.messageBar().pushWidget(self.iface.messageBar().createMessage(text), QgsMessageBar.WARNING, 5) profile["l"] = [] except KeyError: text = "Temporal/Spectral Profile Tool: NetCDF file does not have " + \ "time dimension." self.iface.messageBar().pushWidget(self.iface.messageBar().createMessage(text), QgsMessageBar.WARNING, 5) nc.close() profile["l"] = [] if profile["l"] == []: for i in range(stepsNum): timedeltaParams = {stepType: step*i} profile["l"].append(startTime + timedelta(**timedeltaParams)) self.changeXAxisStepType("timedate") else: for profile in self.profiles: # Truncate the profiles to the minimum of the length of each profile # or length of provided x-axis steps stepsNum = min(len(self.xAxisSteps), len(profile["l"])) profile["l"] = self.xAxisSteps[:stepsNum] for stat in profile.keys(): if stat == "l" or stat == "layer": continue profile[stat] = profile[stat][:stepsNum] # If any x-axis step is a NaN then remove the corresponding # value from profile nans = [i for i, x in enumerate(profile["l"]) if math.isnan(x)] for stat in profile.keys(): if stat == "layer": continue profile[stat] = [x for i, x in enumerate(profile[stat]) if i not in nans] self.changeXAxisStepType("numeric") def changeXAxisStepType(self, newType): if self.xAxisStepType == newType: return else: self.xAxisStepType = newType PlottingTool().resetAxis(self.dockwidget, self.library) def mapToPixel(self, mX, mY, geoTransform): (pX, pY) = gdal.ApplyGeoTransform( gdal.InvGeoTransform(geoTransform), mX, mY) return (int(pX), int(pY)) def setupTableTab(self, model1): #*********************** TAble tab ************************************************* try: #Reinitializing the table tab self.VLayout = self.dockwidget.scrollAreaWidgetContents.layout() while 1: child = self.VLayout.takeAt(0) if not child: break child.widget().deleteLater() except: self.VLayout = QVBoxLayout(self.dockwidget.scrollAreaWidgetContents) self.VLayout.setContentsMargins(9, -1, -1, -1) #Setup the table tab self.groupBox = [] self.profilePushButton = [] self.tableView = [] self.verticalLayout = [] for i in range(0 , model1.rowCount()): self.groupBox.append( QGroupBox(self.dockwidget.scrollAreaWidgetContents) ) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.groupBox[i].sizePolicy().hasHeightForWidth()) self.groupBox[i].setSizePolicy(sizePolicy) self.groupBox[i].setMinimumSize(QSize(0, 150)) self.groupBox[i].setMaximumSize(QSize(16777215, 350)) self.groupBox[i].setTitle(QApplication.translate("GroupBox" + str(i), self.profiles[i]["layer"].name(), None, QApplication.UnicodeUTF8)) self.groupBox[i].setObjectName("groupBox" + str(i)) self.verticalLayout.append( QVBoxLayout(self.groupBox[i]) ) self.verticalLayout[i].setObjectName("verticalLayout") #The table self.tableView.append( QTableView(self.groupBox[i]) ) self.tableView[i].setObjectName("tableView" + str(i)) font = QFont("Arial", 8) columns = len(self.profiles[i]["l"]) rowNames = self.profiles[i].keys() rowNames.remove("layer") # holds the QgsMapLayer instance rowNames.remove("l") # holds the band number rows = len(rowNames) self.mdl = QStandardItemModel(rows+1, columns) self.mdl.setVerticalHeaderLabels(["band"] + rowNames) for j in range(columns): self.mdl.setData(self.mdl.index(0, j, QModelIndex()), str(self.profiles[i]["l"][j])) self.mdl.setData(self.mdl.index(0, j, QModelIndex()), font ,Qt.FontRole) for k in range(rows): self.mdl.setData(self.mdl.index(k+1, j, QModelIndex()), str(self.profiles[i][rowNames[k]][j])) self.mdl.setData(self.mdl.index(k+1, j, QModelIndex()), font ,Qt.FontRole) #self.tableView[i].setVerticalHeaderLabels(rowNames) self.tableView[i].verticalHeader().setDefaultSectionSize(18) self.tableView[i].horizontalHeader().setDefaultSectionSize(60) self.tableView[i].setModel(self.mdl) self.verticalLayout[i].addWidget(self.tableView[i]) self.horizontalLayout = QHBoxLayout() #the copy to clipboard button self.profilePushButton.append( QPushButton(self.groupBox[i]) ) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.profilePushButton[i].sizePolicy().hasHeightForWidth()) self.profilePushButton[i].setSizePolicy(sizePolicy) self.profilePushButton[i].setText(QApplication.translate("GroupBox", "Copy to clipboard", None, QApplication.UnicodeUTF8)) self.profilePushButton[i].setObjectName(str(i)) self.horizontalLayout.addWidget(self.profilePushButton[i]) self.horizontalLayout.addStretch(0) self.verticalLayout[i].addLayout(self.horizontalLayout) self.VLayout.addWidget(self.groupBox[i]) QObject.connect(self.profilePushButton[i], SIGNAL("clicked()"), self.copyTable) def copyTable(self): #Writing the table to clipboard in excel form nr = int( self.sender().objectName() ) self.clipboard = QApplication.clipboard() text = "band" rowNames = self.profiles[nr].keys() rowNames.remove("layer") rowNames.remove("l") for name in rowNames: text += "\t"+name text += "\n" for i in range( len(self.profiles[nr]["l"]) ): text += str(self.profiles[nr]["l"][i]) for j in range(len(rowNames)): text += "\t" + str(self.profiles[nr][rowNames[j]][i]) text += "\n" self.clipboard.setText(text) def reScalePlot(self, param): # called when a spinbox value changed if type(param) != float: # don't execute it twice, for both valueChanged(int) and valueChanged(str) signals return if self.dockwidget.sbMinVal.value() == self.dockwidget.sbMaxVal.value() == 0: # don't execute it on init return PlottingTool().reScalePlot(self.dockwidget, self.profiles, self.model, self.library, autoMode = False)