diff --git a/make/screenshots.py b/make/screenshots.py index 168a72d186406a73bbd1dac6218710322c89cd65..fa8cd1b4faab3e5b4f95953deca261e5651012d9 100644 --- a/make/screenshots.py +++ b/make/screenshots.py @@ -55,7 +55,7 @@ assert isinstance(mv1, MapView) assert isinstance(mv2, MapView) mv1.setTitle('True Color') mv2.setTitle('Short-Wave IR') - +TSV.spatialTemporalVis.adjustScrollArea() #set True Color Bands for sensor in [sensorLS, sensorRE]: rendering = mv1.sensorWidget(sensor) @@ -86,6 +86,9 @@ renderer.setGreenBand(4) renderer.setBlueBand(3) rendering.setRasterRenderer(renderer) +mv1.refreshMapView() +mv2.refreshMapView() + center = TSV.TS.getMaxSpatialExtent().spatialCenter() from timeseriesviewer.mapcanvas import MapTools @@ -94,14 +97,21 @@ TSV.onShowProfile(center, mv1.mapCanvases()[0], MapTools.CursorLocation) TSV.ui.dockSpectralLibrary.setAddCurrentSpectraToSpeclibMode(True) + #collect exemplary profiles + +import random +n = len(mv1.mapCanvases()) +dx = random.sample(range(-500, 500, 30), n) +dy = random.sample(range(-500, 500, 20), n) for i, mc in enumerate(mv1.mapCanvases()): + + coordinate = SpatialPoint(center.crs(), center.x()+dx[i], center.y() + dy[i]) TSV.onShowProfile(center, mc, MapTools.SpectralProfile) if i == 10: break - ps2D_LS_NDVI = TSV.spectralTemporalVis.createNewPlotStyle2D() ps2D_RE_NDVI = TSV.spectralTemporalVis.createNewPlotStyle2D() @@ -173,6 +183,7 @@ for dockWidget in TSV.ui.findChildren(QDockWidget): if name == 'spectralLibraryPanel': dockWidget.resize(QSize(800, 250)) + makePNG(dockWidget, name) if name == 'temporalProfilePanel': diff --git a/test/test_spectrallibraries.py b/test/test_spectrallibraries.py index f11f34f99099af1dde747f7c4d73ffcf5d8ea51f..4c3a3705d32bc352998b1491cfeeef99dd3b1a38 100644 --- a/test/test_spectrallibraries.py +++ b/test/test_spectrallibraries.py @@ -322,7 +322,6 @@ class TestInit(unittest.TestCase): fieldName = 'newField' sp.setMetadata(fieldName, 'foo', addMissingFields=True) sl = SpectralLibrary() - sl.startEditing() sl.addAttribute(createQgsField(fieldName, '')) sl.commitChanges() @@ -331,17 +330,19 @@ class TestInit(unittest.TestCase): sl = SpectralLibrary() sl.addProfiles(sp) - sl = SpectralLibrary() self.assertTrue(fieldName not in sl.fieldNames()) + self.assertTrue(len(sl) == 0) sl.addProfiles(sp, addMissingFields=False) self.assertTrue(fieldName not in sl.fieldNames()) + self.assertTrue(len(sl) == 1) sl = SpectralLibrary() self.assertTrue(fieldName not in sl.fieldNames()) sl.addProfiles(sp, addMissingFields=True) self.assertTrue(fieldName in sl.fieldNames()) + self.assertTrue(len(sl) == 1) p = sl[0] self.assertIsInstance(p, SpectralProfile) self.assertEqual(p.metadata(fieldName), sp.metadata(fieldName)) @@ -383,10 +384,31 @@ class TestInit(unittest.TestCase): v.show() def test_speclibWidget(self): + + speclib = self.createSpeclib() + p = SpectralLibraryWidget() + p.addSpeclib(speclib) + p.show() + + self.assertEqual(p.speclib(), speclib) + p = SpectralLibraryWidget() - p.addSpeclib(self.SPECLIB) p.show() + cs = [speclib[0], speclib[3], speclib[-1]] + p.setAddCurrentSpectraToSpeclibMode(False) + p.setCurrentSpectra(cs) + self.assertTrue(len(p.speclib()) == 0) + p.addCurrentSpectraToSpeclib() + self.assertTrue(len(p.speclib()) == len(cs)) + self.assertEqual(p.speclib()[:], cs) + + p.speclib().removeProfiles(p.speclib()[:]) + self.assertTrue(len(p.speclib()) == 0) + + p.setAddCurrentSpectraToSpeclibMode(True) + p.setCurrentSpectra(cs) + self.assertTrue(len(p.speclib()) == len(cs)) def test_plotWidget(self): diff --git a/timeseriesviewer/main.py b/timeseriesviewer/main.py index d399574ef98c6b6a757c506f1510df9226ba87e9..9cd17637a2c2a7dd41c3b6ac6dfc856c288bb5dd 100644 --- a/timeseriesviewer/main.py +++ b/timeseriesviewer/main.py @@ -470,6 +470,18 @@ class TimeSeriesViewer(QgisInterface, QObject): D.dockSpectralLibrary.SLW.sigLoadFromMapRequest.connect(D.actionIdentifySpectralProfile.trigger) + from timeseriesviewer.spectrallibraries import createQgsField + newFields = QgsFields() + newFields.append(createQgsField('date', '')) + newFields.append(createQgsField('sensorname', '')) + + D.dockSpectralLibrary.speclib().addMissingFields(newFields) + names = D.dockSpectralLibrary.speclib().fieldNames() + for name in ['sensorname', 'date']: + iFrom = names.index(name) + D.dockSpectralLibrary.SLW.tableViewSpeclib.horizontalHeader().moveSection(iFrom, 1) + + s = "" def initQGISConnection(self): @@ -508,9 +520,9 @@ class TimeSeriesViewer(QgisInterface, QObject): for p in profiles: assert isinstance(p, SpectralProfile) p.setName('Profile {} {}'.format(self.cntSpectralProfile, tsd.date)) - p.setMetadata(u'date', u'{}'.format(tsd.date)) - p.setMetadata(u'sensorname', u'{}'.format(tsd.sensor.name())) - p.setMetadata(u'sensorid', u'{}'.format(tsd.sensor.id())) + p.setMetadata(u'date', u'{}'.format(tsd.date), addMissingFields=True) + p.setMetadata(u'sensorname', u'{}'.format(tsd.sensor.name()) , addMissingFields=True) + p.setMetadata(u'sensorid', u'{}'.format(tsd.sensor.id()), addMissingFields=True) self.cntSpectralProfile += 1 self.ui.dockSpectralLibrary.SLW.setCurrentSpectra(profiles) diff --git a/timeseriesviewer/mapvisualization.py b/timeseriesviewer/mapvisualization.py index 8c9da339e5adfe3c0ca577c12b61cb6a47e5c2b8..f46ba9ac76648bb409fa148949eda27098e7e5dc 100644 --- a/timeseriesviewer/mapvisualization.py +++ b/timeseriesviewer/mapvisualization.py @@ -87,6 +87,7 @@ class MapViewUI(QFrame, loadUI('mapviewdefinition.ui')): #w = MapViewSensorSettings(sensor) w = MapViewRenderSettings(sensor) + #sizePolicy = QSizePolicy(QSize) #w.ui. #l = self.renderSettingsLayout @@ -1135,11 +1136,17 @@ class MapView(QObject): def title(self): return self.ui.tbName.text() - def refreshMapView(self, *args): + def refreshMapView(self, sensor=None): + + if isinstance(sensor, SensorInstrument): + sensorSettings = [self.mSensorViews[sensor]] + else: + #update all sensors + sensorSettings = self.mSensorViews.values() - for renderSettings in self.mSensorViews.values(): - assert isinstance(renderSettings, MapViewRenderSettings) - renderSettings.applyStyle() + for renderSetting in sensorSettings: + assert isinstance(renderSetting, MapViewRenderSettings) + renderSetting.applyStyle() #for mapCanvas in self.mapCanvases(): # assert isinstance(mapCanvas, MapCanvas) @@ -1248,6 +1255,7 @@ class MapView(QObject): #w.showSensorName(False) w = self.ui.addSensor(sensor) + w.sigRendererChanged.connect(lambda s=sensor : self.refreshMapView(sensor=s)) #w.sigSensorRendererChanged.connect(self.onSensorRenderingChanged) self.mSensorViews[sensor] = w s ="" @@ -1318,6 +1326,7 @@ class MapViewRenderSettings(QgsCollapsibleGroupBox, loadUI('mapviewrendersetting LUT_RENDERER[QgsSingleBandGrayRenderer]=SingleBandGrayRendererWidget LUT_RENDERER[QgsPalettedRasterRenderer] = PalettedRendererWidget + sigRendererChanged = pyqtSignal() def __init__(self, sensor, parent=None): """Constructor.""" super(MapViewRenderSettings, self).__init__(parent) @@ -1724,6 +1733,7 @@ class DatumView(QObject): mapCanvas.setObjectName('MapCanvas {} {}'.format(mapView.title(), self.TSD.date)) mapCanvas.blockSignals(True) mapCanvas.setMapView(mapView) + mapCanvas.setTSD(self.TSD) self.registerMapCanvas(mapView, mapCanvas) @@ -1771,7 +1781,7 @@ class DatumView(QObject): assert isinstance(mapCanvas, MapCanvas) assert isinstance(mapView, MapView) self.mMapCanvases[mapView] = mapCanvas - + mapCanvas.setVisible(mapView.isVisible()) #mapView.sigTitleChanged.connect(lambda title : mapCanvas.setSaveFileName('{}_{}'.format(self.TSD.date, title))) @@ -2543,6 +2553,8 @@ class MapViewCollectionDock(QgsDockWidget, loadUI('mapviewdock.ui')): if isinstance(nextShown, MapView): self.setCurrentMapView(nextShown) + for mapView in mapViews: + self.sigMapViewAdded.emit(mapView) def updateButtons(self, *args): b = len(self.mMapViews) > 0 @@ -2566,7 +2578,7 @@ class MapViewCollectionDock(QgsDockWidget, loadUI('mapviewdock.ui')): mapView.sigShowProfiles.connect(self.sigShowProfiles) self.mMapViews.addMapView(mapView) - self.sigMapViewAdded.emit(mapView) + #self.sigMapViewAdded.emit(mapView) return mapView @@ -2698,6 +2710,7 @@ if __name__ == '__main__': else: w = MapViewRenderSettings(TS.sensors()[0]) + w.show() w.setRasterRenderer(w.rasterRenderer()) #renderer2 = w.rasterRenderer() diff --git a/timeseriesviewer/profilevisualization.py b/timeseriesviewer/profilevisualization.py index 59c498a35bcee3b30280672fc644d0d84cc5e6e1..5b720344dfed71bf706a2cc4ed72c9f18960d0e8 100644 --- a/timeseriesviewer/profilevisualization.py +++ b/timeseriesviewer/profilevisualization.py @@ -1389,7 +1389,7 @@ class SpectralTemporalVisualization(QObject): for plotStyle in plotStyles: assert isinstance(plotStyle, PlotStyle) for pi in plotStyle.mPlotItems: - self.plot2D.getPlotItem().removeItem(pi) + self.plot2D.plotItem().removeItem(pi) def on3DPlotStyleRemoved(plotStyles): toRemove = [] @@ -1526,7 +1526,7 @@ class SpectralTemporalVisualization(QObject): assert isinstance(pdi, TemporalProfilePlotDataItem) pdi.sigClicked.connect(self.onProfileClicked2D) pdi.sigPointsClicked.connect(self.onPointsClicked2D) - self.plot2D.getPlotItem().addItem(pdi) + self.plot2D.plotItem.addItem(pdi) #self.plot2D.getPlotItem().addItem(pg.PlotDataItem(x=[1, 2, 3], y=[1, 2, 3])) #plotItem.addDataItem(pdi) #plotItem.plot().sigPlotChanged.emit(plotItem) @@ -1952,11 +1952,11 @@ class SpectralTemporalVisualization(QObject): plotSetting.temporalProfile().resetUpdatedFlag() - for i in self.plot2D.getPlotItem().dataItems: + for i in self.plot2D.plotItem.dataItems: i.updateItems() - notInit = [0, 1] == self.plot2D.getPlotItem().getAxis('bottom').range + notInit = [0, 1] == self.plot2D.plotItem.getAxis('bottom').range if notInit: x0 = x1 = None for plotSetting in self.plotSettingsModel2D: @@ -1973,7 +1973,7 @@ class SpectralTemporalVisualization(QObject): x1 = max(pdi.xData.max(), x1) if x0 is not None: - self.plot2D.getPlotItem().setXRange(x0, x1) + self.plot2D.plotItem().setXRange(x0, x1) #self.plot2D.xAxisInitialized = True @QtCore.pyqtSlot() diff --git a/timeseriesviewer/spectrallibraries.py b/timeseriesviewer/spectrallibraries.py index ca7f5955b2ac106989b93cb2d010fe7104c7cd97..00e5049e355e9c0f54317b74fa723be0d5e53a24 100644 --- a/timeseriesviewer/spectrallibraries.py +++ b/timeseriesviewer/spectrallibraries.py @@ -49,6 +49,13 @@ HIDDEN_ATTRIBUTE_PREFIX = '__serialized__' CURRENT_SPECTRUM_STYLE = PlotStyle() CURRENT_SPECTRUM_STYLE.linePen.setStyle(Qt.SolidLine) CURRENT_SPECTRUM_STYLE.linePen.setColor(Qt.green) + + +DEFAULT_SPECTRUM_STYLE = PlotStyle() +DEFAULT_SPECTRUM_STYLE.linePen.setStyle(Qt.SolidLine) +DEFAULT_SPECTRUM_STYLE.linePen.setColor(Qt.white) + + #CURRENT_SPECTRUM_STYLE.linePen #pdi.setPen(fn.mkPen(QColor('green'), width=3)) def gdalDataset(pathOrDataset, eAccess=gdal.GA_ReadOnly): @@ -741,7 +748,7 @@ class SpectralProfile(QgsFeature): self.setXUnit(xUnit) self.setYUnit(yUnit) - self.setStyle(PlotStyle()) + self.setStyle(DEFAULT_SPECTRUM_STYLE) def fieldNames(self): @@ -894,6 +901,21 @@ class SpectralProfile(QgsFeature): def yUnit(self): return self.metadata('y_unit', None) + def copyFieldSubset(self, fields): + + sp = SpectralProfile(fields=fields) + + fieldsInCommon = [field for field in sp.fields() if field in self.fields()] + + sp.setGeometry(self.geometry()) + sp.setId(self.id()) + + for field in fieldsInCommon: + assert isinstance(field, QgsField) + i = sp.fieldNameIndex(field.name()) + sp.setAttribute(i, self.attribute(field.name())) + return sp + def clone(self): sp = SpectralProfile(fields=self.fields()) @@ -1612,6 +1634,13 @@ class SpectralLibraryPanel(QgsDockWidget): self.SLW = SpectralLibraryWidget(self) self.setWidget(self.SLW) + + def speclib(self): + return self.SLW.speclib() + + def setCurrentSpectra(self, listOfSpectra): + self.SLW.setCurrentSpectra(listOfSpectra) + def setAddCurrentSpectraToSpeclibMode(self, b: bool): self.SLW.setAddCurrentSpectraToSpeclibMode(b) @@ -1756,7 +1785,11 @@ class SpectralLibrary(QgsVectorLayer): b = self.isEditable() self.startEditing() - self.addFeatures(profiles) + + if not addMissingFields: + profiles = [p.copyFieldSubset(self.fields()) for p in profiles] + + assert self.addFeatures(profiles) saveEdits(self, leaveEditable=b) def removeProfiles(self, profiles): @@ -2195,6 +2228,37 @@ class SpectralLibraryPlotWidget(PlotWidget): #if self.mModel.rowCount() > 0: # self.onRowsInserted(self.mModel.index(0,0), 0, self.mModel.rowCount()) + def onMouseMoved2D(self, evt): + pos = evt[0] ## using signal proxy turns original arguments into a tuple + + plotItem = self.getPlotItem() + if plotItem.sceneBoundingRect().contains(pos): + vb = plotItem.vb + assert isinstance(vb, DateTimeViewBox) + mousePoint = vb.mapSceneToView(pos) + x = mousePoint.x() + if x >= 0: + y = mousePoint.y() + date = num2date(x) + doy = dateDOY(date) + plotItem.vb.updateCurrentDate(num2date(x, dt64=True)) + self.mInfoLabelCursor.setText('DN {:0.2f}\nDate {}\nDOY {}'.format( + mousePoint.y(), date, doy), + color=self.mInfoColor) + + s = self.size() + pos = QPointF(s.width(), 0) + self.mInfoLabelCursor.setVisible(vb.mActionShowCursorValues.isChecked()) + self.mInfoLabelCursor.setPos(pos) + + b = vb.mActionShowCrosshair.isChecked() + self.mCrosshairLineH.setVisible(b) + self.mCrosshairLineV.setVisible(b) + self.mCrosshairLineH.pen.setColor(self.mInfoColor) + self.mCrosshairLineV.pen.setColor(self.mInfoColor) + self.mCrosshairLineV.setPos(mousePoint.x()) + self.mCrosshairLineH.setPos(mousePoint.y()) + def speclib(self): if not isinstance(self.mModel, SpectralLibraryTableModel): @@ -2598,7 +2662,7 @@ class SpectralLibraryWidget(QFrame, loadUI('spectrallibrarywidget.ui')): self.mCurrentSpectra.clear() self.mCurrentSpectra.extend(listOfSpectra) - if self.actionSaveCurrentProfiles.isChecked() and len(self.mCurrentSpectra) > 0: + if self.actionAddCurrentProfilesAutomatically.isChecked() and len(self.mCurrentSpectra) > 0: self.addCurrentSpectraToSpeclib() #this will change the speclib and add each new profile automatically to the plot else: