diff --git a/qgis_add_ins.py b/qgis_add_ins.py index 9fac5d7f7c8fcb54a26b69578cc2e9b9b4679185..08df48bb1d96b7b41d083ccb4207d91b872be15e 100644 --- a/qgis_add_ins.py +++ b/qgis_add_ins.py @@ -3,8 +3,11 @@ from qgis.gui import * import qgis from PyQt4.QtCore import * from PyQt4.QtGui import * +from PyQt4.QtXml import * +from PyQt4.QtXmlPatterns import * import six - +import xml.etree +from qgis.core import * def add_QgsRasterLayer(iface, path, rgb): if iface: @@ -33,6 +36,63 @@ def add_QgsRasterLayer(iface, path, rgb): s = "" +paste_test = """ + <!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'> +<qgis version="2.12.3-Lyon"> + <pipe> + <rasterrenderer opacity="1" alphaBand="-1" blueBand="1" greenBand="2" type="multibandcolor" redBand="3"> + <rasterTransparency/> + <redContrastEnhancement> + <minValue>2803.02</minValue> + <maxValue>6072.21</maxValue> + <algorithm>StretchToMinimumMaximum</algorithm> + </redContrastEnhancement> + <greenContrastEnhancement> + <minValue>5103.86</minValue> + <maxValue>7228.58</maxValue> + <algorithm>StretchToMinimumMaximum</algorithm> + </greenContrastEnhancement> + <blueContrastEnhancement> + <minValue>5992.32</minValue> + <maxValue>7718.33</maxValue> + <algorithm>StretchToMinimumMaximum</algorithm> + </blueContrastEnhancement> + </rasterrenderer> + <brightnesscontrast brightness="0" contrast="0"/> + <huesaturation colorizeGreen="128" colorizeOn="0" colorizeRed="255" colorizeBlue="128" grayscaleMode="0" saturation="0" colorizeStrength="100"/> + <rasterresampler maxOversampling="2"/> + </pipe> + <blendMode>0</blendMode> +</qgis> + """ + +def paste_band_settings(txt): + + result = None + try: + import xml.etree.ElementTree as ET + tree = ET.fromstring(txt) + + renderer = tree.find('*/rasterrenderer') + if renderer is not None: + bands = list() + ranges = list() + for c in ['red','green','blue']: + name = c + 'Band' + if name not in renderer.attrib.keys(): + return result + + bands.append(int(renderer.attrib[name])) + v_min = float(renderer.find(c+'ContrastEnhancement/minValue').text) + v_max = float(renderer.find(c+'ContrastEnhancement/maxValue').text) + ranges.append((v_min, v_max)) + + result = (bands, ranges) + except: + pass + + return result + class PointMapTool(QgsMapToolEmitPoint): @@ -138,3 +198,14 @@ class RectangleMapTool(QgsMapToolEmitPoint): #def deactivate(self): # super(RectangleMapTool, self).deactivate() #self.deactivated.emit() + + + +def tests(): + + print(paste_band_settings(paste_test)) + print(paste_band_settings('foo')) + +if __name__ == '__main__': + tests() + print('Done') \ No newline at end of file diff --git a/sensecarbon_tsv.py b/sensecarbon_tsv.py index 7a1bb8f0a1ac8d6cca1e5060c5d3cd3802bd39db..f01971b0bdb61eb8cf540b7248fe9de2b2ebf192 100644 --- a/sensecarbon_tsv.py +++ b/sensecarbon_tsv.py @@ -140,7 +140,7 @@ class TimeSeriesTableModel(QAbstractTableModel): def data(self, index, role = Qt.DisplayRole): - if role is None or Qt is None or index.isValid() == False: + if role is None or not index.isValid(): return None @@ -256,7 +256,8 @@ class BandView(object): assert type(TS) is TimeSeries self.representation = collections.OrderedDict() self.TS = TS - self.TS.sensorAdded.connect(self.initSensor) + self.TS.sensorAdded.connect(self.checkSensors) + self.TS.changed.connect(self.checkSensors) self.Sensors = self.TS.Sensors @@ -266,6 +267,17 @@ class BandView(object): + def checkSensors(self): + represented_sensors = set(self.representation.keys()) + ts_sensors = set(self.TS.Sensors.keys()) + + to_add = ts_sensors - represented_sensors + to_remove = represented_sensors - ts_sensors + for S in to_remove: + self.representation[S].close() + self.representation.pop(S) + for S in to_add: + self.initSensor(S) def initSensor(self, sensor, recommended_bands=None): @@ -291,14 +303,19 @@ class BandView(object): def getRanges(self, sensor): - return self.getWidget(sensor).getRanges() + return self.getWidget(sensor).getRGBSettings()[1] + + def getBands(self, sensor): + return self.getWidget(sensor).getRGBSettings()[0] + + + def getRGBSettings(self, sensor): + return self.getWidget(sensor).getRGBSettings() def getWidget(self, sensor): assert type(sensor) is SensorConfiguration return self.representation[sensor] - def getBands(self, sensor): - return self.getWidget(sensor).getBands() def useMaskValues(self): @@ -466,7 +483,9 @@ class TimeSeries(QObject): def saveToFile(self, path): - import time + if path is None or len(path) == 0: + return + lines = [] lines.append('#Time series definition file: {}'.format(np.datetime64('now').astype(str))) lines.append('#<image path>[;<mask path>]') @@ -657,7 +676,8 @@ class TimeSeries(QObject): S = TSD.sensor self.Sensors[S].remove(TSD) self.data.pop(TSD, None) - + if len(self.Sensors[S]) == 0: + self.Sensors.pop(S) if not _quiet: self.changed.emit() @@ -1029,7 +1049,12 @@ class TimeSeriesDatum(object): regYYYYDOY = re.compile(r'(19|20)\d{5}') regYYYYMMDD = re.compile(r'(19|20)\d{2}-\d{2}-\d{2}') regYYYY = re.compile(r'(19|20)\d{2}') + def parseAcquisitionDate(text): + match = regLandsatSceneID.search(text) + if match: + id = match.group() + return getDateTime64FromYYYYDOY(id[9:16]) match = regYYYYMMDD.search(text) if match: return np.datetime64(match.group()) @@ -1313,16 +1338,30 @@ class SenseCarbon_TSV: D.btn_selectByCoordinate.clicked.connect(self.ua_selectByCoordinate) D.btn_selectByRectangle.clicked.connect(self.ua_selectByRectangle) D.btn_addBandView.clicked.connect(lambda :self.ua_addBandView()) + D.btn_addTSImages.clicked.connect(lambda :self.ua_addTSImages()) D.btn_addTSMasks.clicked.connect(lambda :self.ua_addTSMasks()) - D.btn_removeTSD.clicked.connect(lambda : self.ua_removeTSD(None)) - D.btn_removeTS.clicked.connect(self.ua_clear_TS) - D.btn_loadTSFile.clicked.connect(self.ua_loadTSFile) D.btn_saveTSFile.clicked.connect(self.ua_saveTSFile) D.btn_addTSExample.clicked.connect(self.ua_loadExampleTS) + + D.actionAdd_Images.triggered.connect(lambda :self.ua_addTSImages()) + D.actionAdd_Masks.triggered.connect(lambda :self.ua_addTSMasks()) + D.actionLoad_Time_Series.triggered.connect(self.ua_loadTSFile) + D.actionSave_Time_Series.triggered.connect(self.ua_saveTSFile) + D.actionLoad_Example_Time_Series.triggered.connect(self.ua_loadExampleTS) + D.actionAbout.triggered.connect( \ + lambda: QMessageBox.about(self.dlg, 'SenseCarbon TimeSeriesViewer', 'A viewer to visualize raster time series data')) + + D.btn_removeTSD.clicked.connect(lambda : self.ua_removeTSD(None)) + D.btn_removeTS.clicked.connect(self.ua_clear_TS) + + D.spinBox_ncpu.setRange(0, multiprocessing.cpu_count()) + + + # Declare instance attributes self.actions = [] #self.menu = self.tr(u'&EnMAP-Box') @@ -1370,14 +1409,14 @@ class SenseCarbon_TSV: D = self.dlg D.tableView_TimeSeries.setModel(TSM) D.tableView_TimeSeries.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) - D.cb_centerdate.setModel(TSM) - D.cb_centerdate.setModelColumn(0) - D.cb_centerdate.currentIndexChanged.connect(self.scrollToDate) + D.cb_doi.setModel(TSM) + D.cb_doi.setModelColumn(0) + D.cb_doi.currentIndexChanged.connect(self.scrollToDate) def ua_loadTSFile(self, path=None): if path is None or path is False: - path = QFileDialog.getOpenFileName(self.dlg, 'Open Time Series file') + path = QFileDialog.getOpenFileName(self.dlg, 'Open Time Series file', '') if os.path.exists(path): @@ -1421,7 +1460,7 @@ class SenseCarbon_TSV: else: self.canvas_srs.ImportFromWkt(srs) - self.dlg.tb_srs_info.setPlainText(self.canvas_srs.ExportToProj4()) + self.dlg.tb_bb_srs.setPlainText(self.canvas_srs.ExportToProj4()) def ua_selectBy_Response(self, geometry, srs_wkt): D = self.dlg @@ -1492,7 +1531,7 @@ class SenseCarbon_TSV: self.dlg.spinBox_coordinate_x.setValue(0.5*(xmin+xmax)) self.dlg.spinBox_coordinate_y.setValue(0.5*(ymin+ymax)) s = "" - self.dlg.cb_centerdate.setCurrentIndex(int(len(self.TS) / 2)) + self.dlg.cb_doi.setCurrentIndex(int(len(self.TS) / 2)) self.dlg.tableView_TimeSeries.resizeColumnsToContents() def check_enabled(self): @@ -1635,7 +1674,7 @@ class SenseCarbon_TSV: - def scrollToDate(self, date): + def scrollToDate(self, date_of_interest): QApplication.processEvents() HBar = self.dlg.scrollArea_imageChips.horizontalScrollBar() TSDs = list(self.CHIPWIDGETS.keys()) @@ -1643,17 +1682,19 @@ class SenseCarbon_TSV: return #get date INDEX that is closest to requested date - if type(date) is str: - date = np.datetime64(date) - if type(date) is not np.datetime64: - s = "" - assert type(date) is np.datetime64, 'type is: '+str(type(date)) + if type(date_of_interest) is str: + date_of_interest = np.datetime64(date_of_interest) - i_doi = TSDs.index(sorted(TSDs, key=lambda TSD: abs(date - TSD.getDate()))[0]) - scrollValue = int(float(i_doi+1) / len(TSDs) * HBar.maximum()) + if type(date_of_interest) is np.datetime64: + i_doi = TSDs.index(sorted(TSDs, key=lambda TSD: abs(date_of_interest - TSD.getDate()))[0]) + else: + i_doi = date_of_interest - HBar.setValue(scrollValue) + step = int(float(HBar.maximum()) / (len(TSDs)+1)) + HBar.setSingleStep(step) + HBar.setPageStep(step*5) + HBar.setValue(i_doi * step) def ua_showPxCoordinate_start(self): @@ -1690,12 +1731,12 @@ class SenseCarbon_TSV: #get the dates of interes dates_of_interest = list() - centerTSD = D.cb_centerdate.itemData(D.cb_centerdate.currentIndex()) - if centerTSD is None: + doiTSD = D.cb_doi.itemData(D.cb_doi.currentIndex()) + if doiTSD is None: idx = int(len(self.TS)/2) - centerTSD = D.cb_centerdate.itemData(idx) - D.cb_centerdate.setCurrentIndex(idx) - centerDate = centerTSD.getDate() + doiTSD = D.cb_doi.itemData(idx) + D.cb_doi.setCurrentIndex(idx) + centerDate = doiTSD.getDate() allDates = self.TS.getObservationDates() i_doi = allDates.index(centerDate) @@ -1760,6 +1801,8 @@ class SenseCarbon_TSV: cnt_chips += 1 + self.dlg.scrollArea_imageChip_content.update() + self.scrollToDate(centerDate) s = "" @@ -1805,46 +1848,47 @@ class SenseCarbon_TSV: TSD, chipData = results self.ImageChipBuffer.addDataCube(TSD, chipData) - assert TSD in self.CHIPWIDGETS.keys() - - for imgChipLabel, bandView in zip(self.CHIPWIDGETS[TSD], self.BAND_VIEWS): - #imgView.clear() - #imageLabel.setScaledContents(True) - - #rgb = self.ImageChipBuffer.getChipRGB(TSD, bandView) - array = self.ImageChipBuffer.getChipArray(TSD, bandView, mode = 'bgr') - qimg = pg.makeQImage(array, copy=True, transpose=False) - - #rgb2 = rgb.transpose([1,2,0]).copy('C') - #qImg = qimage2ndarray.array2qimage(rgb2) - #img = QImage(rgb2.data, nl, ns, QImage.Format_RGB888) - - pxMap = QPixmap.fromImage(qimg).scaled(imgChipLabel.size(), Qt.KeepAspectRatio) - imgChipLabel.setPixmap(pxMap) - imgChipLabel.update() - #imgView.setPixmap(pxMap) - #imageLabel.update() - #imgView.adjustSize() - #pxmap = QPixmap.fromImage(qimg) - # - - """ - pxmapitem = QGraphicsPixmapItem(pxmap) - if imgChipLabel.scene() is None: - imgChipLabel.setScene(QGraphicsScene()) - else: - imgChipLabel.scene().clear() + if TSD not in self.CHIPWIDGETS.keys(): + six.print_('TSD {} does not exist in CHIPBUFFER'.format(TSD), file=sys.stderr) + else: + for imgChipLabel, bandView in zip(self.CHIPWIDGETS[TSD], self.BAND_VIEWS): + #imgView.clear() + #imageLabel.setScaledContents(True) + + #rgb = self.ImageChipBuffer.getChipRGB(TSD, bandView) + array = self.ImageChipBuffer.getChipArray(TSD, bandView, mode = 'bgr') + qimg = pg.makeQImage(array, copy=True, transpose=False) + + #rgb2 = rgb.transpose([1,2,0]).copy('C') + #qImg = qimage2ndarray.array2qimage(rgb2) + #img = QImage(rgb2.data, nl, ns, QImage.Format_RGB888) + + pxMap = QPixmap.fromImage(qimg).scaled(imgChipLabel.size(), Qt.KeepAspectRatio) + imgChipLabel.setPixmap(pxMap) + imgChipLabel.update() + #imgView.setPixmap(pxMap) + #imageLabel.update() + #imgView.adjustSize() + #pxmap = QPixmap.fromImage(qimg) + # + + """ + pxmapitem = QGraphicsPixmapItem(pxmap) + if imgChipLabel.scene() is None: + imgChipLabel.setScene(QGraphicsScene()) + else: + imgChipLabel.scene().clear() - scene = imgChipLabel.scene() - scene.addItem(pxmapitem) + scene = imgChipLabel.scene() + scene.addItem(pxmapitem) - imgChipLabel.fitInView(scene.sceneRect(), Qt.KeepAspectRatio) - """ + imgChipLabel.fitInView(scene.sceneRect(), Qt.KeepAspectRatio) + """ - pass - self.ICP.layout().update() - self.dlg.scrollArea_imageChip_content.update() - s = "" + pass + self.ICP.layout().update() + self.dlg.scrollArea_imageChip_content.update() + s = "" pass @@ -2060,7 +2104,8 @@ def run_tests(): filesImgLS = file_search(dirSrcLS, '20*_BOA.vrt') filesImgRE = file_search(dirSrcRE, '*.vrt', recursive=True) #filesMsk = file_search(dirSrc, '2014*_Msk.vrt') - S.ua_addTSImages(files=filesImgLS[0:3]) + S.ua_addTSImages(files=filesImgLS[0:2]) + S.ua_addTSImages(files=filesImgRE[0:2]) #S.ua_addTSImages(files=filesImgLS) #S.ua_addTSImages(files=filesImgRE) #S.ua_loadExampleTS() diff --git a/sensecarbon_tsv_gui_base.ui b/sensecarbon_tsv_gui_base.ui index a6a5f7bdb3d2e4ef687916a8c63117382af6ff22..a58e98df7b9c1a2f96fdc483b3fadcf4f99cc8dd 100644 --- a/sensecarbon_tsv_gui_base.ui +++ b/sensecarbon_tsv_gui_base.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>898</width> - <height>926</height> + <height>947</height> </rect> </property> <property name="windowTitle"> @@ -88,7 +88,7 @@ <bool>true</bool> </property> <property name="currentIndex"> - <number>0</number> + <number>1</number> </property> <widget class="QWidget" name="tab_console"> <attribute name="title"> @@ -249,19 +249,6 @@ </property> </widget> </item> - <item> - <widget class="QPushButton" name="bnt_removeBandView"> - <property name="maximumSize"> - <size> - <width>150</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>PushButton</string> - </property> - </widget> - </item> <item> <spacer name="verticalSpacer"> <property name="orientation"> @@ -299,8 +286,8 @@ <rect> <x>0</x> <y>0</y> - <width>81</width> - <height>28</height> + <width>754</width> + <height>204</height> </rect> </property> <property name="sizePolicy"> @@ -363,6 +350,16 @@ </property> </widget> </item> + <item row="1" column="1"> + <widget class="QPushButton" name="btn_selectByRectangle"> + <property name="toolTip"> + <string>Selects the image subset from QGIS.</string> + </property> + <property name="text"> + <string>Select subset by rectangle</string> + </property> + </widget> + </item> <item row="2" column="0"> <widget class="QLabel" name="label_3"> <property name="toolTip"> @@ -415,27 +412,42 @@ </property> </widget> </item> - <item row="5" column="0"> - <widget class="QLabel" name="label_2"> + <item row="4" column="0"> + <widget class="QLabel" name="label_7"> + <property name="toolTip"> + <string>Spatial Reference System (SRS) of center coordinate</string> + </property> <property name="text"> - <string>size x</string> + <string>SRS</string> </property> </widget> </item> - <item row="6" column="0"> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>size y</string> + <item row="4" column="1"> + <widget class="QPlainTextEdit" name="tb_bb_srs"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>50</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>50</height> + </size> + </property> + <property name="readOnly"> + <bool>true</bool> </property> </widget> </item> - <item row="1" column="1"> - <widget class="QPushButton" name="btn_selectByRectangle"> - <property name="toolTip"> - <string>Selects the image subset from QGIS.</string> - </property> + <item row="5" column="0"> + <widget class="QLabel" name="label_2"> <property name="text"> - <string>Select subset by rectangle</string> + <string>size x</string> </property> </widget> </item> @@ -458,6 +470,13 @@ </property> </widget> </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>size y</string> + </property> + </widget> + </item> <item row="6" column="1"> <widget class="QDoubleSpinBox" name="doubleSpinBox_subset_size_y"> <property name="suffix"> @@ -477,26 +496,6 @@ </property> </widget> </item> - <item row="4" column="1"> - <widget class="QPlainTextEdit" name="tb_srs_info"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_7"> - <property name="toolTip"> - <string>Spatial Reference System (SRS) of center coordinate</string> - </property> - <property name="text"> - <string>SRS</string> - </property> - </widget> - </item> </layout> </widget> </item> @@ -511,110 +510,11 @@ <property name="title"> <string>Chip Rendering</string> </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="6" column="0"> - <widget class="QLabel" name="label_6"> - <property name="text"> - <string>First date</string> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QSpinBox" name="spinBox_ncpu"> - <property name="toolTip"> - <string>Number of CPUs used for parallel image chip calculation</string> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QSpinBox" name="spinBox_chipsize_max"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>0</height> - </size> - </property> - <property name="toolTip"> - <string>Max. length of an image chip on screen.</string> - </property> - <property name="suffix"> - <string>px</string> - </property> - <property name="minimum"> - <number>20</number> - </property> - <property name="maximum"> - <number>1000</number> - </property> - <property name="singleStep"> - <number>10</number> - </property> - <property name="value"> - <number>200</number> - </property> - </widget> - </item> - <item row="6" column="1" colspan="2"> - <widget class="QComboBox" name="cb_centerdate"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_11"> - <property name="text"> - <string>max. size </string> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>#cpu</string> - </property> - </widget> - </item> - <item row="4" column="2"> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0"> - <widget class="QRadioButton" name="rb_showEntireTS"> - <property name="text"> - <string>Entire Time Series</string> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QRadioButton" name="rb_showTimeWindow"> - <property name="toolTip"> - <string>Select </string> - </property> - <property name="text"> - <string>Time Window:</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="2" column="0" rowspan="2" colspan="3"> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <item row="2" column="0" colspan="2"> <widget class="QFrame" name="frame_timewindow"> <property name="enabled"> <bool>false</bool> @@ -682,6 +582,95 @@ </layout> </widget> </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>max. size </string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QSpinBox" name="spinBox_chipsize_max"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string>Max. length of an image chip on screen.</string> + </property> + <property name="suffix"> + <string>px</string> + </property> + <property name="minimum"> + <number>20</number> + </property> + <property name="maximum"> + <number>1000</number> + </property> + <property name="singleStep"> + <number>10</number> + </property> + <property name="value"> + <number>200</number> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>#cpu</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QSpinBox" name="spinBox_ncpu"> + <property name="toolTip"> + <string>Number of CPUs used for parallel image chip calculation</string> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>DOI</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QComboBox" name="cb_doi"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QRadioButton" name="rb_showTimeWindow"> + <property name="toolTip"> + <string>Select </string> + </property> + <property name="text"> + <string>Time Window around DOI</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QRadioButton" name="rb_showEntireTS"> + <property name="text"> + <string>Entire Time Series</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> </layout> </widget> </item> @@ -723,6 +712,34 @@ </layout> </widget> </widget> + <widget class="QMenuBar" name="menuBar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>898</width> + <height>21</height> + </rect> + </property> + <widget class="QMenu" name="menuFiles"> + <property name="title"> + <string>Files</string> + </property> + <addaction name="actionAdd_Images"/> + <addaction name="actionAdd_Masks"/> + <addaction name="actionLoad_Time_Series"/> + <addaction name="actionSave_Time_Series"/> + <addaction name="actionLoad_Example_Time_Series"/> + </widget> + <widget class="QMenu" name="menuAbout"> + <property name="title"> + <string>Help</string> + </property> + <addaction name="actionAbout"/> + </widget> + <addaction name="menuFiles"/> + <addaction name="menuAbout"/> + </widget> <action name="actionSelectCoordinate"> <property name="text"> <string>selectCoordinate</string> @@ -738,6 +755,36 @@ <string>Add View</string> </property> </action> + <action name="actionAdd_Images"> + <property name="text"> + <string>Add Images</string> + </property> + </action> + <action name="actionAdd_Masks"> + <property name="text"> + <string>Add Masks</string> + </property> + </action> + <action name="actionLoad_Time_Series"> + <property name="text"> + <string>Load Time Series</string> + </property> + </action> + <action name="actionSave_Time_Series"> + <property name="text"> + <string>Save Time Series</string> + </property> + </action> + <action name="actionLoad_Example_Time_Series"> + <property name="text"> + <string>Load Time Series Example</string> + </property> + </action> + <action name="actionAbout"> + <property name="text"> + <string>About</string> + </property> + </action> </widget> <resources> <include location="resources.qrc"/> diff --git a/tsv_widgets.py b/tsv_widgets.py index 08468ad791a2580415b457abf08091545b85f938..d92d01779ff318d881b9b9660862cbe476586ac4 100644 --- a/tsv_widgets.py +++ b/tsv_widgets.py @@ -24,7 +24,7 @@ from PyQt4 import uic from PyQt4.QtCore import * from PyQt4.QtGui import * -import sys +import sys, re, os sys.path.append(os.path.dirname(__file__)) @@ -37,6 +37,7 @@ def loadFormClass(name_ui): FORM_CLASS_BANDVIEWSETTINGS = loadFormClass('bandviewsettings_widget_base.ui') FORM_CLASS_IMAGECHIPVIEWSETTINGS = loadFormClass('imagechipviewsettings_widget_base.ui') + class ImageChipViewSettings(QGroupBox, FORM_CLASS_IMAGECHIPVIEWSETTINGS): #define signals @@ -119,21 +120,59 @@ class ImageChipViewSettings(QGroupBox, FORM_CLASS_IMAGECHIPVIEWSETTINGS): s = "" pass - def getBands(self): + def setRGBSettings(self, bands_and_ranges): + bands, ranges = bands_and_ranges + assert len(bands) == 3 + assert len(ranges) == 3 + for range in ranges: + assert len(range) == 2 and range[0] <= range[1] + + #copy values only if all bands fit to this sensor + for b in bands: + if b > self.SensorConfiguration.nb: + return + + self.cb_r.setCurrentIndex(bands[0]-1) + self.cb_g.setCurrentIndex(bands[1]-1) + self.cb_b.setCurrentIndex(bands[2]-1) + + self.tb_range_r_min.setText(str(ranges[0][0])) + self.tb_range_g_min.setText(str(ranges[1][0])) + self.tb_range_b_min.setText(str(ranges[2][0])) + + self.tb_range_r_max.setText(str(ranges[0][1])) + self.tb_range_g_max.setText(str(ranges[1][1])) + self.tb_range_b_max.setText(str(ranges[2][1])) + + + def getRGBSettings(self): bands = [self.cb_r.currentIndex()+1, \ self.cb_g.currentIndex()+1, \ self.cb_b.currentIndex()+1] - return bands - def getRanges(self): range_r = [float(self.tb_range_r_min.text()), float(self.tb_range_r_max.text())] range_g = [float(self.tb_range_g_min.text()), float(self.tb_range_g_max.text())] range_b = [float(self.tb_range_b_min.text()), float(self.tb_range_b_max.text())] - return (range_r, range_g, range_b) + ranges = (range_r, range_g, range_b) - def getSettings(self): + return bands, ranges + + def contextMenuEvent(self, event): + menu = QMenu() + + #add general options + + #add QGIS specific options + txt = QApplication.clipboard().text() + if re.search('<!DOCTYPE(.|\n)*rasterrenderer.*type="multibandcolor"', txt) is not None: + import qgis_add_ins + action = menu.addAction('Paste style') + action.setToolTip('Uses the QGIS raster layer style to specify band selection and band value ranges.') + action.triggered.connect(lambda : self.setRGBSettings(qgis_add_ins.paste_band_settings(txt))) + + + menu.exec_(event.globalPos()) - s = "" class BandViewSettings(QGroupBox, FORM_CLASS_BANDVIEWSETTINGS): @@ -216,20 +255,15 @@ class BandViewSettings(QGroupBox, FORM_CLASS_BANDVIEWSETTINGS): s = "" pass - def getBands(self): + def getRGBSettings(self): bands = [self.cb_r.currentIndex()+1, \ self.cb_g.currentIndex()+1, \ self.cb_b.currentIndex()+1] - return bands - def getRanges(self): range = [float(self.tb_range_min.text()), float(self.tb_range_max.text())] - #provide a range for each channel - return (range, range, range) + ranges = (range, range, range) - def getSettings(self): - - s = "" + return bands, ranges if __name__ == '__main__':