diff --git a/doc/source/img/autogenerated/cursorLocationInfoPanel.png b/doc/source/img/autogenerated/cursorLocationInfoPanel.png deleted file mode 100644 index b70b3a27d6c5be634446545c34b8b7af3f796f39..0000000000000000000000000000000000000000 Binary files a/doc/source/img/autogenerated/cursorLocationInfoPanel.png and /dev/null differ diff --git a/doc/source/img/autogenerated/mapViewPanel.png b/doc/source/img/autogenerated/mapViewPanel.png deleted file mode 100644 index 22c082743d76187b3b0860b179781cf8487ff816..0000000000000000000000000000000000000000 Binary files a/doc/source/img/autogenerated/mapViewPanel.png and /dev/null differ diff --git a/doc/source/img/autogenerated/sensorPanel.png b/doc/source/img/autogenerated/sensorPanel.png deleted file mode 100644 index f1782e8910161cc919d6af11a5f316b685c0b526..0000000000000000000000000000000000000000 Binary files a/doc/source/img/autogenerated/sensorPanel.png and /dev/null differ diff --git a/doc/source/img/autogenerated/spectralLibraryPanel.png b/doc/source/img/autogenerated/spectralLibraryPanel.png deleted file mode 100644 index 5cf8b9eb7a2255823b110cac3a1456b6db1e209c..0000000000000000000000000000000000000000 Binary files a/doc/source/img/autogenerated/spectralLibraryPanel.png and /dev/null differ diff --git a/doc/source/img/autogenerated/systemInfoPanel.png b/doc/source/img/autogenerated/systemInfoPanel.png deleted file mode 100644 index d083b6ef72e25a2d7ba763a04f8991df91eaeab4..0000000000000000000000000000000000000000 Binary files a/doc/source/img/autogenerated/systemInfoPanel.png and /dev/null differ diff --git a/doc/source/img/autogenerated/temporalProfilePanel.page2D.png b/doc/source/img/autogenerated/temporalProfilePanel.page2D.png deleted file mode 100644 index d6f4d57b90b6ef24776ec2db1c03bf96c3dca35a..0000000000000000000000000000000000000000 Binary files a/doc/source/img/autogenerated/temporalProfilePanel.page2D.png and /dev/null differ diff --git a/doc/source/img/autogenerated/temporalProfilePanel.page3D.png b/doc/source/img/autogenerated/temporalProfilePanel.page3D.png deleted file mode 100644 index 4519618179ec9a5bf6db307a2643c0069a8f7860..0000000000000000000000000000000000000000 Binary files a/doc/source/img/autogenerated/temporalProfilePanel.page3D.png and /dev/null differ diff --git a/doc/source/img/autogenerated/temporalProfilePanel.pagePixel.png b/doc/source/img/autogenerated/temporalProfilePanel.pagePixel.png deleted file mode 100644 index 0027601b1551cd0db72a6fbfaa84c0a2c0650632..0000000000000000000000000000000000000000 Binary files a/doc/source/img/autogenerated/temporalProfilePanel.pagePixel.png and /dev/null differ diff --git a/doc/source/img/autogenerated/timeseriesPanel.png b/doc/source/img/autogenerated/timeseriesPanel.png deleted file mode 100644 index 2d2cbab15dc88452685309873f02b565a80d9aa8..0000000000000000000000000000000000000000 Binary files a/doc/source/img/autogenerated/timeseriesPanel.png and /dev/null differ diff --git a/eotimeseriesviewer/main.py b/eotimeseriesviewer/main.py index 5c9b96b04e6e7463b5c978b30a246444576a901e..eac5caa6ea19203b9e33063a43ca847cdf6639ec 100644 --- a/eotimeseriesviewer/main.py +++ b/eotimeseriesviewer/main.py @@ -435,18 +435,8 @@ class TimeSeriesViewer(QgisInterface, QObject): self.ui.actionShowCrosshair.toggled.connect(self.spatialTemporalVis.setCrosshairVisibility) self.ui.actionExportMapsToImages.triggered.connect(lambda :self.exportMapsToImages()) - def onActionIdentifyTemporalProfile(): - self.ui.actionIdentify.trigger() - self.ui.optionIdentifyTemporalProfile.setChecked(True) - - self.spectralTemporalVis.ui.actionLoadProfileRequest.triggered.connect(onActionIdentifyTemporalProfile) - - def onActionIdentifySpectralProfile(): - self.ui.actionIdentify.trigger() - self.ui.optionIdentifySpectralProfile.setChecked(True) - - self.ui.dockSpectralLibrary.SLW.actionSelectProfilesFromMap.triggered.connect(onActionIdentifySpectralProfile) - + self.spectralTemporalVis.ui.actionLoadProfileRequest.triggered.connect(self.activateIdentifyTemporalProfileMapTool) + self.ui.dockSpectralLibrary.SLW.actionSelectProfilesFromMap.triggered.connect(self.activateIdentifySpectralProfileMapTool) # connect buttons with actions self.ui.actionAbout.triggered.connect(lambda: AboutDialogUI(self.ui).exec_()) @@ -501,8 +491,26 @@ class TimeSeriesViewer(QgisInterface, QObject): toolButton.setPopupMode(QToolButton.MenuButtonPopup) - def exportMapsToImages(self, path=None, format='PNG'): + def activateIdentifyTemporalProfileMapTool(self, *args): + """ + Activates the collection of temporal profiles + """ + self.ui.actionIdentify.trigger() + self.ui.optionIdentifyTemporalProfile.setChecked(True) + def activateIdentifySpectralProfileMapTool(self, *args): + """ + Activates the collection of spectral profiles + """ + self.ui.actionIdentify.trigger() + self.ui.optionIdentifySpectralProfile.setChecked(True) + + def exportMapsToImages(self, path=None, format='PNG'): + """ + Exports the map canvases to local images. + :param path: directory to save the images in + :param format: rastr format, e.g. 'PNG' or 'JPG' + """ from .mapcanvas import MapCanvas from .mapvisualization import MapView from .settings import Keys, setValue, value @@ -610,7 +618,7 @@ class TimeSeriesViewer(QgisInterface, QObject): assert isinstance(tsd, TimeSeriesDatum) self.spatialTemporalVis.navigateToTSD(tsd) self.ui.dockTimeSeries.showTSD(tsd) - # todo: move TableViews to as well + def mapCanvases(self)->list: @@ -834,7 +842,10 @@ class TimeSeriesViewer(QgisInterface, QObject): self.spectralTemporalVis.loadCoordinate(spatialPoint) elif mapToolKey == MapTools.SpectralProfile: - tsd = self.spatialTemporalVis.DVC.tsdFromMapCanvas(mapCanvas) + tsd = None + from .mapcanvas import MapCanvas + if isinstance(mapCanvas, MapCanvas): + tsd = mapCanvas.tsd() if not hasattr(self, 'cntSpectralProfile'): self.cntSpectralProfile = 0 @@ -1047,8 +1058,22 @@ class TimeSeriesViewer(QgisInterface, QObject): self.addTimeSeriesImages(rasterFiles[0:n]) if len(vectorFiles) > 0: + + # make polygons transparent + self.addVectorData(vectorFiles) + for lyr in QgsProject.instance().mapLayers().values(): + if isinstance(lyr, QgsVectorLayer) and lyr.source() in vectorFiles: + renderer = lyr.renderer() + if lyr.geometryType() == QgsWkbTypes.PolygonGeometry and isinstance(renderer, QgsSingleSymbolRenderer): + renderer = renderer.clone() + symbol = renderer.symbol() + if isinstance(symbol, QgsFillSymbol): + symbol.setOpacity(0.25) + lyr.setRenderer(renderer) + s = "" + @@ -1135,7 +1160,7 @@ class TimeSeriesViewer(QgisInterface, QObject): for l in vectorLayers: mapView.addLayer(l) - break #add to first mapview only + break # add to first mapview only diff --git a/eotimeseriesviewer/mapcanvas.py b/eotimeseriesviewer/mapcanvas.py index a306fbbf4e2e11830bd50c839f597da992c77c92..7d0882ac2ad64c4305e3dd120cf08d339d0aa50b 100644 --- a/eotimeseriesviewer/mapcanvas.py +++ b/eotimeseriesviewer/mapcanvas.py @@ -439,8 +439,12 @@ class MapCanvas(QgsMapCanvas): sourceLayer = SensorProxyLayer(source, sensor=self.tsd().sensor()) sourceLayer.setName(lyr.name()) sourceLayer.setCustomProperty('eotsv/sensorid', self.tsd().sensor().id()) - renderer = lyr.renderer().clone() - sourceLayer.setRenderer(renderer) + try: + renderer = lyr.renderer() + if isinstance(renderer, QgsRasterRenderer): + sourceLayer.setRenderer(renderer.clone()) + except Exception as exR: + s = "" assert isinstance(sourceLayer, QgsRasterLayer) expected.append(sourceLayer) else: @@ -484,10 +488,12 @@ class MapCanvas(QgsMapCanvas): for px in [px for px in self.mMapView.layers() if isinstance(px, SensorProxyLayer)]: for l in self.layers(): if isinstance(l, SensorProxyLayer) and l.sensor() == px.sensor(): - renderer = px.renderer().clone() - renderer.setInput(l.dataProvider()) - l.setRenderer(renderer) - + try: + renderer = px.renderer().clone() + renderer.setInput(l.dataProvider()) + l.setRenderer(renderer) + except Exception as ex: + s = "" pass diff --git a/eotimeseriesviewer/mapvisualization.py b/eotimeseriesviewer/mapvisualization.py index b87c4e7dff9a51095775f103bba823a11f69e8e4..588f88bfd474c3b9f01883bb9f47a9ae7a7df4b6 100644 --- a/eotimeseriesviewer/mapvisualization.py +++ b/eotimeseriesviewer/mapvisualization.py @@ -548,6 +548,7 @@ class MapView(QFrame, loadUIFormClass(jp(DIR_UI, 'mapview.ui'))): assert isinstance(sensor, SensorInstrument) if sensor not in self.sensors(): dummyLayer = sensor.proxyLayer() + assert isinstance(dummyLayer.renderer(), QgsRasterRenderer) dummyLayer.rendererChanged.connect(lambda sensor=sensor: self.onSensorRendererChanged(sensor)) #QgsProject.instance().addMapLayer(dummyLayer) @@ -1026,8 +1027,6 @@ class MapViewListModel(QAbstractListModel): super(MapViewListModel, self).__init__(parent) self.mMapViewList = [] - - def addMapView(self, mapView): i = len(self.mMapViewList) self.insertMapView(i, mapView) @@ -1470,25 +1469,18 @@ class MapViewDock(QgsDockWidget, loadUI('mapviewdock.ui')): def setCurrentMapView(self, mapView): - assert isinstance(mapView, MapView) and mapView in self.mMapViews - idx = self.stackedWidget.indexOf(mapView.ui) - if idx >= 0: - self.stackedWidget.setCurrentIndex(idx) - self.cbMapView.setCurrentIndex(self.mMapViews.mapView2idx(mapView).row()) - + assert isinstance(mapView, MapView) and mapView in self.mapViews() + self.toolBox.setCurrentWidget(mapView) self.updateTitle() def updateTitle(self, *args): # self.btnToggleMapViewVisibility.setChecked(mapView) mapView = self.currentMapView() if isinstance(mapView, MapView): - if mapView in self.mMapViews: - i = str(self.mMapViews.mapView2idx(mapView).row()+1) - else: - i = '' - #title = '{} | {} "{}"'.format(self.baseTitle, i, mapView.title()) - title = '{} | {}'.format(self.baseTitle, i) - self.setWindowTitle(title) + title = '{} | {}'.format(self.baseTitle, mapView.title()) + else: + title = self.baseTitle + self.setWindowTitle(title) def currentMapView(self): w = self.toolBox.currentWidget() diff --git a/eotimeseriesviewer/timeseries.py b/eotimeseriesviewer/timeseries.py index 0fd23f45fcd207108e28352c85cfdb3b06f3e7b1..9b65ca15940bfd6003ee6e0ebdec215408c5ea69 100644 --- a/eotimeseriesviewer/timeseries.py +++ b/eotimeseriesviewer/timeseries.py @@ -1067,7 +1067,7 @@ class TimeSeries(QAbstractItemModel): def tsd(self, date: np.datetime64, sensor)->TimeSeriesDatum: """ - Returns the TimeSeriesDatum identified by ate nd sensorID + Returns the TimeSeriesDatum identified by date and sensorID :param date: :param sensor: SensorInstrument | str with sensor id :return: diff --git a/eotimeseriesviewer/ui/timeseriesviewer.ui b/eotimeseriesviewer/ui/timeseriesviewer.ui index 4d2692bfda813badfe5fc9c5290a193564257783..a5ea9d93ddd73c1eca47d995c69b176fd34e482e 100644 --- a/eotimeseriesviewer/ui/timeseriesviewer.ui +++ b/eotimeseriesviewer/ui/timeseriesviewer.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>887</width> - <height>178</height> + <height>157</height> </rect> </property> <property name="windowTitle"> @@ -74,7 +74,7 @@ <item> <widget class="MapViewScrollArea" name="scrollAreaSubsets"> <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>1</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -103,7 +103,7 @@ <x>0</x> <y>0</y> <width>885</width> - <height>90</height> + <height>69</height> </rect> </property> <property name="sizePolicy"> @@ -882,7 +882,7 @@ <property name="iconVisibleInMenu"> <bool>false</bool> </property> - <property name="shortcutVisibleInContextMenu"> + <property name="shortcutVisibleInContextMenu" stdset="0"> <bool>true</bool> </property> </action> diff --git a/make/deploy.py b/make/deploy.py index 173526d413da0bd5ea1d26347e9fe35d714afb7a..9eeb261f06f843656ec56dd5515ef8ec0d96c7b8 100644 --- a/make/deploy.py +++ b/make/deploy.py @@ -316,7 +316,7 @@ def build(): f.close() # copy CHANGELOG to doc/source/changelog.rst - updateShpinxChangelog() + updateSphinxChangelog() # 5. create a zip print('Create zipfile...') @@ -345,7 +345,7 @@ def build(): print('Finished') -def updateShpinxChangelog(): +def updateSphinxChangelog(): from eotimeseriesviewer import PATH_CHANGELOG with open(PATH_CHANGELOG, 'r') as f: # replace (#1) with (https://bitbucket.org/jakimowb/eo-time-series-viewer/issues/1) @@ -570,5 +570,5 @@ def uploadDeveloperPlugin(): if __name__ == "__main__": - updateShpinxChangelog() + updateSphinxChangelog() #build() \ No newline at end of file diff --git a/make/screenshots.py b/make/screenshots.py index 7dca032ecd0c72392f0c4b369da88acf6d105b8a..ac438ef841f37a478203976dda7576a0422a9743 100644 --- a/make/screenshots.py +++ b/make/screenshots.py @@ -6,7 +6,7 @@ from qgis.gui import * from qgis.PyQt.QtWidgets import * from qgis.PyQt.QtCore import * from qgis.PyQt.QtGui import * -from tests import initQgisApplication +from eotimeseriesviewer.tests import initQgisApplication app = initQgisApplication() from eotimeseriesviewer.utils import * from eotimeseriesviewer.main import TimeSeriesViewer @@ -17,13 +17,17 @@ from eotimeseriesviewer import DIR_REPO, DIR_QGIS_RESOURCES #DIR_SCREENSHOTS = jp(DIR_REPO, 'screenshots') -DIR_SCREENSHOTS = jp(DIR_REPO, 'doc/source/img/autogenerated.{}', sys.platform) +DIR_SCREENSHOTS = jp(DIR_REPO, 'doc/source/img/autogenerated.{}'.format(sys.platform)) os.makedirs(DIR_SCREENSHOTS, exist_ok=True) +DATE_OF_INTEREST = np.datetime64('2014-07-02') +TSV = TimeSeriesViewer() +TSV.show() +TSV.spatialTemporalVis.setMapSize(QSize(300, 150)) +QApplication.processEvents() -TSV = TimeSeriesViewer(None) #set up example settings from example.Images import Img_2014_04_21_LC82270652014111LGN00_BOA, re_2014_06_25 @@ -48,21 +52,28 @@ else: y = -751853.6488464196 center = SpatialPoint(center.crs(), x, y) + + dx = 500 -extent = SpatialExtent(center.crs(), center.x()-dx, center.y()-dx, center.x()+dx, center.y() + dx) -extent = SpatialExtent(center.crs(), 681519.46197612234391272, -752814.23602663306519389, 683369.92926584207452834, -750963.76873691333457828) +#extent = SpatialExtent(center.crs(), center.x()-dx, center.y()-dx, center.x()+dx, center.y() + dx) +#extent = SpatialExtent(center.crs(), 681519.46197612234391272, -752814.23602663306519389, 683369.92926584207452834, -750963.76873691333457828) + +extent = TSV.timeSeries()[0].spatialExtent() + date = np.datetime64('2014-08-01') TSV.spatialTemporalVis.setSpatialExtent(extent) -dt = np.asarray([np.abs(tsd.date - date) for tsd in TSV.mTimeSeries]) +dt = np.asarray([np.abs(tsd.date() - date) for tsd in TSV.timeSeries()]) i = np.argmin(dt) -TSV.spatialTemporalVis.navigateToTSD(TSV.mTimeSeries[i]) +TSV.spatialTemporalVis.navigateToTSD(TSV.timeSeries()[i]) + +QApplication.processEvents() -#TS.loadImageFiles([Img_2014_04_21_LC82270652014111LGN00_BOA, re_2014_06_25]) +# TS.loadImageFiles([Img_2014_04_21_LC82270652014111LGN00_BOA, re_2014_06_25]) toHide = ['2014-07-18', '2014-08-08', '2014-08-10', '2014-08-23', '2014-08-25', '2014-08-03', '2014-07-26', '2014-07-10'] -for tsd in TSV.mTimeSeries: +for tsd in TSV.timeSeries(): assert isinstance(tsd, TimeSeriesDatum) - if str(tsd.mDate) in toHide: + if str(tsd.date()) in toHide: tsd.setVisibility(False) sensorLS = None @@ -71,11 +82,11 @@ sensorPL = None for sensor in TSV.mTimeSeries.sensors(): assert isinstance(sensor, SensorInstrument) - if sensor.id() == '6b30.0m0.49;0.56;0.66;0.84;1.65;2.2um': + if sensor.id() == '[6, 30.0, 30.0, 3, [0.49, 0.56, 0.66, 0.84, 1.65, 2.2], "um"]': sensor.setName('Landsat') sensorLS = sensor continue - if sensor.id() == '5b5.0m': + if sensor.id() == '[5, 5.0, 5.0, 2, null, null]': sensor.setName('RapidEye') sensorRE = sensor continue @@ -89,6 +100,7 @@ for sensor in TSV.mTimeSeries.sensors(): assert isinstance(sensorLS, SensorInstrument) assert isinstance(sensorRE, SensorInstrument) +QApplication.processEvents() #add second MapView TSV.createMapView() @@ -100,63 +112,68 @@ assert isinstance(mv2, MapView) mv1.setTitle('True Color') mv2.setTitle('Short-Wave IR') TSV.spatialTemporalVis.adjustScrollArea() -#set True Color Bands -for sensor in TSV.mTimeSeries.sensors(): - rendering = mv1.sensorWidget(sensor) - assert isinstance(rendering, MapViewRenderSettings) - renderer = rendering.rasterRenderer() - assert isinstance(renderer, QgsMultiBandColorRenderer) - renderer.setRedBand(3) - renderer.setGreenBand(2) - renderer.setBlueBand(1) - rendering.setRasterRenderer(renderer) - -#set swIR-nIR-R Bands -if isinstance(sensorLS, SensorInstrument): - rendering = mv2.sensorWidget(sensorLS) - assert isinstance(rendering, MapViewRenderSettings) - renderer = rendering.rasterRenderer() - assert isinstance(renderer, QgsMultiBandColorRenderer) - renderer.setRedBand(4) - renderer.setGreenBand(5) - renderer.setBlueBand(3) - rendering.setRasterRenderer(renderer) - -if isinstance(sensorRE, SensorInstrument): - rendering = mv2.sensorWidget(sensorRE) - assert isinstance(rendering, MapViewRenderSettings) - renderer = rendering.rasterRenderer() - assert isinstance(renderer, QgsMultiBandColorRenderer) - renderer.setRedBand(5) - renderer.setGreenBand(4) - renderer.setBlueBand(3) - rendering.setRasterRenderer(renderer) - -if isinstance(sensorPL, SensorInstrument): - rendering = mv2.sensorWidget(sensorPL) - assert isinstance(rendering, MapViewRenderSettings) - renderer = rendering.rasterRenderer() - assert isinstance(renderer, QgsMultiBandColorRenderer) - renderer.setRedBand(4) - renderer.setGreenBand(3) - renderer.setBlueBand(2) - rendering.setRasterRenderer(renderer) - -mv1.refreshMapView() -mv2.refreshMapView() - -#activate Crosshair + +if True: + # set True Color Bands + for sensor in TSV.timeSeries().sensors(): + lyr = mv1.sensorProxyLayer(sensor) + assert isinstance(lyr, SensorProxyLayer) + renderer = lyr.renderer().clone() + assert isinstance(renderer, QgsMultiBandColorRenderer) + renderer.setRedBand(3) + renderer.setGreenBand(2) + renderer.setBlueBand(1) + lyr.setRenderer(renderer) + +if True: + # set swIR-nIR-R Bands + for sensor in TSV.timeSeries().sensors(): + assert isinstance(sensor, SensorInstrument) + lyr = mv2.sensorProxyLayer(sensor) + if isinstance(lyr, SensorProxyLayer): + renderer = lyr.renderer().clone() + assert isinstance(renderer, QgsMultiBandColorRenderer) + + if lyr.sensor() == sensorLS: + renderer.setRedBand(4) + renderer.setGreenBand(5) + renderer.setBlueBand(3) + elif lyr.sensor() == sensorRE: + renderer.setRedBand(5) + renderer.setGreenBand(4) + renderer.setBlueBand(3) + + lyr.setRenderer(renderer) + + +tsd = [tsd for tsd in TSV.timeSeries() if tsd.date() == DATE_OF_INTEREST][0] +TSV.showTimeSeriesDatum(tsd) + +for c in TSV.mapCanvases(): + assert isinstance(c, MapCanvas) + c.timedRefresh() + c.waitWhileRendering() + + + +# activate Crosshair TSV.spatialTemporalVis.setCrosshairVisibility(True) from eotimeseriesviewer.mapcanvas import MapTools TSV.onShowProfile(center, mv1.mapCanvases()[0], MapTools.CursorLocation) -#load data from other locations +# load data from other locations + +TSV.activateIdentifySpectralProfileMapTool() +TSV.activateIdentifyTemporalProfileMapTool() + -TSV.ui.dockSpectralLibrary.setAddCurrentSpectraToSpeclibMode(True) +#QApplication.processEvents() +#TSV.spatialTemporalVis.timedCanvasRefresh(force=True) -#collect exemplary profiles + +# collect exemplary profiles import random n = len(mv1.mapCanvases()) @@ -209,10 +226,18 @@ def makePNG(widget, name): widgetScreenshot(widget, path) # makePNG(TS.ui, 'mainGUI') -TSV.show() -TSV.ui.resize(QSize(1000,600)) + +TSV.ui.resize(QSize(1000, 600)) + QApplication.processEvents() +widget = TSV.ui +makePNG(widget, 'maingui') + +widget = TSV.spatialTemporalVis.scrollArea.viewport() +makePNG(widget, 'mapViews') + + for dockWidget in TSV.ui.findChildren(QDockWidget): assert isinstance(dockWidget, QDockWidget) #dockWidget.setFloating(True) @@ -227,12 +252,7 @@ for dockWidget in TSV.ui.findChildren(QDockWidget): if name == 'mapViewPanel': dockWidget.setCurrentMapView(mv1) - dockWidget.gbMapProperties.setCollapsed(True) - dockWidget.gbMapProperties.update() - mv1.ui.gbVectorRendering.setCollapsed(True) - mv1.ui.gbVectorRendering.setChecked(False) - mv1.ui.update() - dockWidget.resize(QSize(300, 600)) + #dockWidget.resize(QSize(300, 600)) dockWidget.update() makePNG(dockWidget, name)