Newer
Older
# -*- coding: utf-8 -*-
"""
/***************************************************************************

Benjamin Jakimow
committed
EO Time Series Viewer
copyright : (C) 2017 by HU-Berlin
email : benjamin.jakimow@geo.hu-berlin.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
# noinspection PyPep8Naming

benjamin.jakimow@geo.hu-berlin.de
committed
from qgis.core import *

benjamin.jakimow@geo.hu-berlin.de
committed
import os, sys, re, fnmatch, collections, copy, traceback, six, multiprocessing

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
File "D:\Programs\OSGeo4W\apps\Python27\lib\multiprocessing\managers.py", line
528, in start
self._address = reader.recv()
EOFError

benjamin.jakimow@geo.hu-berlin.de
committed
see https://github.com/pyinstaller/pyinstaller/wiki/Recipe-Multiprocessing
see https://github.com/CleanCut/green/issues/103

benjamin.jakimow@geo.hu-berlin.de
committed
"""

Benjamin Jakimow
committed

benjamin.jakimow@geo.hu-berlin.de
committed
path = os.path.abspath(os.path.join(sys.exec_prefix, '../../bin/pythonw.exe'))

benjamin.jakimow@geo.hu-berlin.de
committed
if os.path.exists(path):
multiprocessing.set_executable(path)
sys.argv = [ None ]

benjamin.jakimow@geo.hu-berlin.de
committed
import qgis.utils
from timeseriesviewer.utils import *
from timeseriesviewer import jp, mkdir, DIR_SITE_PACKAGES, messageLog
from timeseriesviewer.timeseries import *
from timeseriesviewer.profilevisualization import SpectralTemporalVisualization
import numpy as np

benjamin.jakimow@geo.hu-berlin.de
committed
DEBUG = False
#ensure that required non-standard modules are available
import pyqtgraph as pg
class QgisTsvBridge(QObject):
#Class to control interactions between TSV and the running QGIS instance
_instance = None
@staticmethod
def instance():
if QgisTsvBridge._instance is None:
QgisTsvBridge._instance = QgisTsvBridge()
return QgisTsvBridge._instance
@staticmethod

benjamin.jakimow@geo.hu-berlin.de
committed
def qgisInstance():
if qgis.utils is not None and isinstance(qgis.utils.iface, QgisInterface):

benjamin.jakimow@geo.hu-berlin.de
committed
return qgis.utils.iface
else:
return None
@staticmethod
def addMapLayers(mapLayers, checkDuplicates=False):
iface = QgisTsvBridge.qgisInstance()
if iface:
existingSources = [lyr.source() for lyr in iface.mapCanvas().layers()]
for ml in mapLayers:
assert isinstance(ml, QgsMapLayer)
src = ml.source()

benjamin.jakimow@geo.hu-berlin.de
committed
if checkDuplicates and src in existingSources:
continue
if isinstance(ml, QgsRasterLayer):

benjamin.jakimow@geo.hu-berlin.de
committed
iface.addRasterLayer(src)
if isinstance(ml, QgsVectorLayer):

benjamin.jakimow@geo.hu-berlin.de
committed
iface.addVectorLayer(src, os.path.basename(src), ml.providerType())

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
sigQgisProjectClosed = pyqtSignal()

benjamin.jakimow@geo.hu-berlin.de
committed
def __init__(self, parent=None):
assert QgisTsvBridge._instance is None, 'Can not instantiate QgsTsvBridge twice'

benjamin.jakimow@geo.hu-berlin.de
committed
super(QgisTsvBridge, self).__init__(parent)

benjamin.jakimow@geo.hu-berlin.de
committed
self.ui = None
self.SpatTempVis = None
def isValid(self):
return isinstance(self.iface, QgisInterface) and isinstance(self.TSV, TimeSeriesViewer)
def connect(self,TSV):

benjamin.jakimow@geo.hu-berlin.de
committed
iface = QgisTsvBridge.qgisInstance()
if iface:
self.iface = iface
self.TSV = TSV
self.ui = self.TSV.ui
self.SpatTempVis = self

benjamin.jakimow@geo.hu-berlin.de
committed
from timeseriesviewer.ui.docks import RenderingDockUI
assert isinstance(self.ui, TimeSeriesViewerUI)
assert isinstance(self.ui.dockRendering, RenderingDockUI)
self.ui.dockRendering.sigQgisInteractionRequest.connect(self.onQgisInteractionRequest)

benjamin.jakimow@geo.hu-berlin.de
committed
self.ui.dockRendering.enableQgisInteraction(True)

benjamin.jakimow@geo.hu-berlin.de
committed
#self.cbQgsVectorLayer = self.ui.dockRendering.cbQgsVectorLayer
#self.gbQgsVectorLayer = self.ui.dockRendering.gbQgsVectorLayer
self.qgsMapCanvas = self.iface.mapCanvas()
assert isinstance(self.qgsMapCanvas, QgsMapCanvas)

benjamin.jakimow@geo.hu-berlin.de
committed
#assert isinstance(self.cbQgsVectorLayer, QgsMapLayerComboBox)
#assert isinstance(self.gbQgsVectorLayer, QgsCollapsibleGroupBox)

benjamin.jakimow@geo.hu-berlin.de
committed
else:
return False

benjamin.jakimow@geo.hu-berlin.de
committed
def addLayersToQGIS(self, mapLayers, noDuplicates=False):
QgisTsvBridge.addMapLayers(mapLayers, checkDuplicates=noDuplicates)
def onQgisInteractionRequest(self, request):
assert isinstance(self.qgsMapCanvas, QgsMapCanvas)
extQgs = SpatialExtent.fromMapCanvas(self.qgsMapCanvas)
assert isinstance(self.TSV, TimeSeriesViewer)
extTsv = self.TSV.spatialTemporalVis.spatialExtent()
assert request in ['tsvCenter2qgsCenter',
'tsvExtent2qgsExtent',
'qgisCenter2tsvCenter',
'qgisExtent2tsvExtent']
if request == 'tsvCenter2qgsCenter':
center = SpatialPoint.fromSpatialExtent(extTsv)
center = center.toCrs(extQgs.crs())
if center:
self.qgsMapCanvas.setCenter(center)
self.qgsMapCanvas.refresh()
if request == 'qgisCenter2tsvCenter':
center = SpatialPoint.fromSpatialExtent(extQgs)
center = center.toCrs(extTsv.crs())
if center:
self.TSV.spatialTemporalVis.setSpatialCenter(center)

benjamin.jakimow@geo.hu-berlin.de
committed
if self.ui.dockRendering.cbLoadCenterPixelProfile.isChecked():
self.TSV.spectralTemporalVis.loadCoordinate(center)
if request == 'tsvExtent2qgsExtent':
extent = extTsv.toCrs(extQgs.crs())
if extent:
self.qgsMapCanvas.setExtent(extent)
self.qgsMapCanvas.refresh()
if request == 'qgisExtent2tsvExtent':
extent = extQgs.toCrs(extTsv.crs())
if extent:
self.TSV.spatialTemporalVis.setSpatialExtent(extent)

benjamin.jakimow@geo.hu-berlin.de
committed
if self.ui.dockRendering.cbLoadCenterPixelProfile.isChecked():
self.TSV.spectralTemporalVis.loadCoordinate(extent.spatialCenter())

benjamin.jakimow@geo.hu-berlin.de
committed
class TimeSeriesViewerUI(QMainWindow,
loadUI('timeseriesviewer.ui')):
sigQgsSyncChanged = pyqtSignal(bool, bool, bool)
def __init__(self, parent=None):
"""Constructor."""
super(TimeSeriesViewerUI, self).__init__(parent)
# Set up the user interface from Designer.
# After setupUI you can access any designer object by doing
# self.<objectname>, and you can use autoconnect slots - see
# http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
# #widgets-and-dialogs-with-auto-connect
self.setupUi(self)
self.addActions(self.findChildren(QAction))
from timeseriesviewer import TITLE, icon
self.setWindowIcon(icon())
#set button default actions -> this will show the action icons as well
#I don't know why this is not possible in the QDesigner when QToolButtons are
#placed outside a toolbar
import timeseriesviewer.ui.docks as docks
area = None
def addDockWidget(dock):
"""
shortcut to add a created dock and return it
:param dock:
:return:
"""
self.addDockWidget(area, dock)
return dock
area = Qt.LeftDockWidgetArea

Benjamin Jakimow
committed
#self.dockRendering = addDockWidget(docks.RenderingDockUI(self))
if DEBUG:
from timeseriesviewer.labeling import LabelingDockUI
self.dockLabeling = addDockWidget(LabelingDockUI(self))
self.dockLabeling.setHidden(True)
from timeseriesviewer.sensorvisualization import SensorDockUI
self.dockSensors = addDockWidget(SensorDockUI(self))
from timeseriesviewer.mapvisualization import MapViewCollectionDock
self.dockMapViews = addDockWidget(MapViewCollectionDock(self))
from timeseriesviewer.cursorlocationvalue import CursorLocationInfoDock
self.dockCursorLocation = addDockWidget(CursorLocationInfoDock(self))

Benjamin Jakimow
committed
#self.tabifyDockWidget(self.dockMapViews, self.dockRendering)
self.tabifyDockWidget(self.dockSensors, self.dockCursorLocation)

benjamin.jakimow@geo.hu-berlin.de
committed
area = Qt.BottomDockWidgetArea
#from timeseriesviewer.mapvisualization import MapViewDockUI
#self.dockMapViews = addDockWidget(MapViewDockUI(self))
self.dockTimeSeries = addDockWidget(TimeSeriesDockUI(self))
from timeseriesviewer.profilevisualization import ProfileViewDockUI
self.dockProfiles = addDockWidget(ProfileViewDockUI(self))
from timeseriesviewer.spectrallibraries import SpectralLibraryPanel
self.dockSpectralLibrary = addDockWidget(SpectralLibraryPanel(self))
self.tabifyDockWidget(self.dockTimeSeries, self.dockSpectralLibrary)
self.tabifyDockWidget(self.dockTimeSeries, self.dockProfiles)

benjamin.jakimow@geo.hu-berlin.de
committed
area = Qt.RightDockWidgetArea

benjamin.jakimow@geo.hu-berlin.de
committed
from timeseriesviewer.systeminfo import SystemInfoDock
self.dockSystemInfo = addDockWidget(SystemInfoDock(self))
self.dockSystemInfo.setVisible(False)
for dock in self.findChildren(QDockWidget):
if len(dock.actions()) > 0:
s = ""
self.menuPanels.addAction(dock.toggleViewAction())
self.dockTimeSeries.raise_()
#self.dockMapViews.btnAddMapView.setDefaultAction(self.actionAddMapView)
self.restoreSettings()
def restoreSettings(self):
from timeseriesviewer import SETTINGS
s = ""
def _blockSignals(self, widgets, block=True):
states = dict()
if isinstance(widgets, dict):
for w, block in widgets.items():
states[w] = w.blockSignals(block)
else:
for w in widgets:
states[w] = w.blockSignals(block)
return states
sigSubsetSizeChanged = pyqtSignal(QSize)
def setSubsetSize(self, size, blockSignal=False):
old = self.subsetSize()
w = [self.spinBoxSubsetSizeX, self.spinBoxSubsetSizeY]
if blockSignal:
states = self._blockSignals(w, True)
self.spinBoxSubsetSizeX.setValue(size.width())
self.spinBoxSubsetSizeY.setValue(size.height())
self._setUpdateBehaviour()
if blockSignal:
self._blockSignals(states)
elif old != size:
self.sigSubsetSizeChanged(size)
def setProgress(self, value, valueMax=None, valueMin=0):
p = self.progressBar
if valueMin is not None and valueMin != self.progessBar.minimum():
p.setMinimum(valueMin)
if valueMax is not None and valueMax != self.progessBar.maximum():
p.setMaximum(valueMax)
self.progressBar.setValue(value)
Qgis.Info:'INFO',
Qgis.Critical:'INFO',
Qgis.Warning:'WARNING',
Qgis.Success:'SUCCESS',
}

benjamin.jakimow@geo.hu-berlin.de
committed
def showMessage(message, title, level):
v = QgsMessageViewer()
v.setTitle(title)
#print('DEBUG MSG: {}'.format(message))
v.setMessage(message, QgsMessageOutput.MessageHtml \
if message.startswith('<html>')
else QgsMessageOutput.MessageText)
v.showMessage(True)
class TimeSeriesViewer(QgisInterface, QObject):
_instance = None
@staticmethod
def instance():
return TimeSeriesViewer._instance
def __init__(self, iface):
"""Constructor.
:param iface: An interface instance that will be passed to this class
which provides the hook by which you can manipulate the QGIS
application at run time.
:type iface: QgsInterface
"""
assert TimeSeriesViewer.instance() is None
QObject.__init__(self)
QgisInterface.__init__(self)
QApplication.processEvents()
self.ui = TimeSeriesViewerUI()

Benjamin Jakimow
committed
if isinstance(iface, QgisInterface):
self.iface = iface

Benjamin Jakimow
committed
self.initQGISInterface()

Benjamin Jakimow
committed
#init empty time series
self.TS = TimeSeries()

benjamin.jakimow@geo.hu-berlin.de
committed
self.mSpatialMapExtentInitialized = False
self.TS.sigTimeSeriesDatesAdded.connect(self.onTimeSeriesChanged)
D = self.ui
#self.ICP = D.scrollAreaSubsetContent.layout()
#D.scrollAreaMapViews.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
#self.BVP = self.ui.scrollAreaMapViews.layout()
D.dockTimeSeries.setTimeSeries(self.TS)
D.dockSensors.setTimeSeries(self.TS)
self.spectralTemporalVis = SpectralTemporalVisualization(D.dockProfiles)

benjamin.jakimow@geo.hu-berlin.de
committed
self.spectralTemporalVis.pixelLoader.sigLoadingFinished.connect(
lambda dt: self.ui.dockSystemInfo.addTimeDelta('Pixel Profile', dt))
assert isinstance(self, TimeSeriesViewer)

benjamin.jakimow@geo.hu-berlin.de
committed
from timeseriesviewer.mapvisualization import SpatialTemporalVisualization
self.spatialTemporalVis = SpatialTemporalVisualization(self)

Benjamin Jakimow
committed
#self.spatialTemporalVis.sigLoadingStarted.connect(self.ui.dockRendering.addStartedWork)
#self.spatialTemporalVis.sigLoadingFinished.connect(self.ui.dockRendering.addFinishedWork)
#self.spatialTemporalVis.sigShowProfiles.connect(self.spectralTemporalVis.loadCoordinate)

Benjamin Jakimow
committed
self.spatialTemporalVis.sigShowProfiles.connect(self.onShowProfile)

Benjamin Jakimow
committed
self.ui.dockMapViews.sigCrsChanged.connect(self.spatialTemporalVis.setCrs)
self.ui.dockMapViews.sigMapSizeChanged.connect(self.spatialTemporalVis.setMapSize)
self.ui.dockMapViews.sigMapCanvasColorChanged.connect(self.spatialTemporalVis.setBackgroundColor)
self.spatialTemporalVis.sigCRSChanged.connect(self.ui.dockMapViews.setCrs)
self.spatialTemporalVis.sigMapSizeChanged.connect(self.ui.dockMapViews.setMapSize)
self.spectralTemporalVis.sigMoveToTSD.connect(self.spatialTemporalVis.navigateToTSD)

benjamin.jakimow@geo.hu-berlin.de
committed
self.spectralTemporalVis.ui.actionLoadProfileRequest.triggered.connect(D.actionIdentifyTemporalProfile.trigger)
from timeseriesviewer.mapcanvas import MapTools
D.actionMoveCenter.triggered.connect(lambda : self.spatialTemporalVis.setMapTool(MapTools.MoveToCenter))
#D.actionSelectArea.triggered.connect(lambda : self.spatialTemporalVis.activateMapTool('selectArea'))
D.actionZoomMaxExtent.triggered.connect(lambda : self.spatialTemporalVis.setMapTool(MapTools.ZoomFull))
D.actionZoomPixelScale.triggered.connect(lambda: self.spatialTemporalVis.setMapTool(MapTools.ZoomPixelScale))
D.actionZoomIn.triggered.connect(lambda: self.spatialTemporalVis.setMapTool(MapTools.ZoomIn))
D.actionZoomOut.triggered.connect(lambda: self.spatialTemporalVis.setMapTool(MapTools.ZoomOut))
D.actionPan.triggered.connect(lambda: self.spatialTemporalVis.setMapTool(MapTools.Pan))
D.actionIdentifyTemporalProfile.triggered.connect(lambda: self.spatialTemporalVis.setMapTool(MapTools.TemporalProfile))
D.actionIdentifySpectralProfile.triggered.connect(lambda: self.spatialTemporalVis.setMapTool(MapTools.SpectralProfile))
D.actionIdentifyCursorLocationValues.triggered.connect(lambda: self.spatialTemporalVis.setMapTool(MapTools.CursorLocation))
D.dockCursorLocation.sigLocationRequest.connect(D.actionIdentifyCursorLocationValues.trigger)
from timeseriesviewer.cursorlocationvalue import CursorLocationInfoModel
D.dockCursorLocation.mLocationInfoModel.setNodeExpansion(CursorLocationInfoModel.ALWAYS_EXPAND)
#D.actionIdentifyMapLayers.triggered.connect(lambda: self.spatialTemporalVis.activateMapTool('identifyMapLayers'))
D.actionAddMapView.triggered.connect(self.spatialTemporalVis.MVC.createMapView)
D.actionAddTSD.triggered.connect(lambda : self.addTimeSeriesImages())

Benjamin Jakimow
committed
D.actionAddVectorData.triggered.connect(lambda : self.addVectorData())
D.actionRemoveTSD.triggered.connect(lambda: self.TS.removeDates(self.ui.dockTimeSeries.selectedTimeSeriesDates()))
D.actionRefresh.triggered.connect(self.spatialTemporalVis.refresh)
D.actionLoadTS.triggered.connect(self.loadTimeSeriesDefinition)
D.actionClearTS.triggered.connect(self.clearTimeSeries)
D.actionSaveTS.triggered.connect(self.saveTimeSeriesDefinition)
D.actionAddTSExample.triggered.connect(self.loadExampleTimeSeries)
D.actionShowCrosshair.toggled.connect(self.spatialTemporalVis.setShowCrosshair)

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
from timeseriesviewer.ui.widgets import AboutDialogUI, PropertyDialogUI

benjamin.jakimow@geo.hu-berlin.de
committed
D.actionAbout.triggered.connect(lambda: AboutDialogUI(self.ui).exec_())
D.actionSettings.triggered.connect(lambda : PropertyDialogUI(self.ui).exec_())
import webbrowser
from timeseriesviewer import URL_DOCUMENTATION
D.actionShowOnlineHelp.triggered.connect(lambda : webbrowser.open(URL_DOCUMENTATION))

Benjamin Jakimow
committed
D.dockSpectralLibrary.SLW.sigLoadFromMapRequest.connect(D.actionIdentifySpectralProfile.trigger)
def initQGISConnection(self):
self.ui.actionImportExtent.triggered.connect(lambda: self.spatialTemporalVis.setSpatialExtent(SpatialExtent.fromMapCanvas(self.iface.mapCanvas())))
self.ui.actionExportExtent.triggered.connect(lambda: self.iface.mapCanvas().setExtent(self.spatialTemporalVis.spatialExtent().toCrs(self.iface.mapCanvas().mapSettings().destinationCrs())))
self.ui.actionExportCenter.triggered.connect(lambda: self.iface.mapCanvas().setCenter(self.spatialTemporalVis.spatialExtent().spatialCenter()))
self.ui.actionImportCenter.triggered.connect(lambda: self.spatialTemporalVis.setSpatialCenter(SpatialPoint.fromMapCanvasCenter(self.iface.mapCanvas())))

Benjamin Jakimow
committed
def initQGISInterface(self):
"""
Initialize the QGIS Interface in case the EO TSV was not started from a QGIS GUI Instance
"""
self.iface = self
qgis.utils.iface = self
def onShowProfile(self, spatialPoint, mapCanvas, mapToolKey):
#self.spatialTemporalVis.sigShowProfiles.connect(self.spectralTemporalVis.loadCoordinate)
assert isinstance(spatialPoint, SpatialPoint)
assert isinstance(mapCanvas, QgsMapCanvas)
from timeseriesviewer.mapcanvas import MapTools
assert mapToolKey in MapTools.mapToolKeys()
if mapToolKey == MapTools.TemporalProfile:
self.spectralTemporalVis.loadCoordinate(spatialPoint)
elif mapToolKey == MapTools.SpectralProfile:
from timeseriesviewer.spectrallibraries import SpectralProfile
tsd = self.spatialTemporalVis.DVC.tsdFromMapCanvas(mapCanvas)
profiles = SpectralProfile.fromMapCanvas(mapCanvas, spatialPoint)
#add metadata
if isinstance(tsd, TimeSeriesDatum):
for p in profiles:
assert isinstance(p, SpectralProfile)
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()))
self.ui.dockSpectralLibrary.SLW.setCurrentSpectra(profiles)
elif mapToolKey == MapTools.CursorLocation:
self.ui.dockCursorLocation.loadCursorLocation(spatialPoint, mapCanvas)
else:
s = ""
pass
def messageBar(self):
return self.ui.messageBar
def loadImageFiles(self, files):
assert isinstance(files, list)
self.TS.addFiles(files)
def loadTimeSeriesDefinition(self, path=None, n_max=None):
defFile = s.value('file_ts_definition')
defDir = None
if defFile is not None:
filters = "CSV (*.csv *.txt);;" + \
"All files (*.*)"
path, filter = QFileDialog.getOpenFileName(caption='Load Time Series definition', directory=defDir, filters=filters)
if path is not None and os.path.exists(path):
M = self.ui.dockTimeSeries.tableView_TimeSeries.model()
M.beginResetModel()
self.clearTimeSeries()
self.TS.loadFromFile(path, n_max=n_max)
M.endResetModel()
def createMapView(self):
self.spatialTemporalVis.createMapView()
def mapViews(self):
return self.spatialTemporalVis.MVC[:]
def zoomTo(self, key):

benjamin.jakimow@geo.hu-berlin.de
committed
ext = self.TS.getMaxSpatialExtent(self.ui.dockRendering.crs())
elif key == 'zoomPixelScale':
extent = self.spatialTemporalVis.spatialExtent()

benjamin.jakimow@geo.hu-berlin.de
committed
#calculate in web-mercator for metric distances
crs = self.spatialTemporalVis.crs()
crsWMC = QgsCoordinateReferenceSystem('EPSG:3857')
extentWMC = extent.toCrs(crsWMC)
pxSize = max(self.TS.getPixelSizes(), key= lambda s :s.width())

benjamin.jakimow@geo.hu-berlin.de
committed
canvasSize = self.spatialTemporalVis.subsetSize()
f = 0.05
width = f * canvasSize.width() * pxSize.width() # width in map units
height = f * canvasSize.height() * pxSize.height()

benjamin.jakimow@geo.hu-berlin.de
committed
ext = SpatialExtent(crsWMC, 0, 0, width, height)
ext.setCenter(extentWMC.center())
#return to original CRS
ext = ext.toCrs(crs)
else:
raise NotImplementedError(key)
self.spatialTemporalVis.setSpatialExtent(ext)
def icon(self):
return TimeSeriesViewer.icon()
def logMessage(self, message, tag, level):
m = message.split('\n')
if '' in message.split('\n'):
m = m[0:m.index('')]
m = '\n'.join(m)

benjamin.jakimow@geo.hu-berlin.de
committed
if DEBUG: print(message)

benjamin.jakimow@geo.hu-berlin.de
committed
if not re.search('timeseriesviewer', m):
if level in [Qgis.Critical, Qgis.Warning]:

benjamin.jakimow@geo.hu-berlin.de
committed
if False:
widget = self.ui.messageBar.createMessage(tag, message)
button = QPushButton(widget)
button.setText("Show")
button.pressed.connect(lambda: showMessage(message, '{}'.format(tag), level))
widget.layout().addWidget(button)
self.ui.messageBar.pushWidget(widget, level, SETTINGS.value('MESSAGE_TIMEOUT', 10))
else:
self.ui.messageBar.pushMessage(tag, message, level=level)

benjamin.jakimow@geo.hu-berlin.de
committed
print(u'{}({}): {}'.format(tag, level, message))

benjamin.jakimow@geo.hu-berlin.de
committed
def onTimeSeriesChanged(self, *args):

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
if not self.mSpatialMapExtentInitialized:

benjamin.jakimow@geo.hu-berlin.de
committed
if len(self.TS.data) > 0:
if len(self.spatialTemporalVis.MVC) == 0:
# add two empty band-views by default
self.spatialTemporalVis.createMapView()
self.spatialTemporalVis.createMapView()
extent = self.TS.getMaxSpatialExtent()

benjamin.jakimow@geo.hu-berlin.de
committed
self.spatialTemporalVis.setCrs(extent.crs())
self.spatialTemporalVis.setSpatialExtent(extent)

benjamin.jakimow@geo.hu-berlin.de
committed
self.mSpatialMapExtentInitialized = True

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
if len(self.TS.data) == 0:

benjamin.jakimow@geo.hu-berlin.de
committed
self.mSpatialMapExtentInitialized = False
def saveTimeSeriesDefinition(self):
defFile = s.value('FILE_TS_DEFINITION')
if defFile is not None:
defFile = os.path.dirname(defFile)
filters = "CSV (*.csv *.txt);;" + \
"All files (*.*)"
path, filter = QFileDialog.getSaveFileName(caption='Save Time Series definition', filter=filters, directory=defFile)
if path is not None:
s.setValue('FILE_TS_DEFINITION', path)
def loadExampleTimeSeries(self):
import example.Images
files = file_search(os.path.dirname(example.Images.__file__), '*.tif')
self.addTimeSeriesImages(files)

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
# noinspection PyMethodMayBeStatic
def tr(self, message):
"""Get the translation for a string using Qt translation API.
We implement this ourselves since we do not inherit QObject.
:param message: String for translation.
:type message: str, QString
:returns: Translated version of message.
:rtype: QString
"""
# noinspection PyTypeChecker,PyArgumentList,PyCallByClass

benjamin.jakimow@geo.hu-berlin.de
committed
return QCoreApplication.translate('HUBTSV', message)
"""Removes the plugin menu item and icon """
self.iface.removeToolBarIcon(self.action)

benjamin.jakimow@geo.hu-berlin.de
committed
#QApplication.processEvents()
self.ui.show()

Benjamin Jakimow
committed

Benjamin Jakimow
committed
QApplication.processEvents()
HBar = self.ui.scrollArea_imageChips.horizontalScrollBar()
TSDs = list(self.CHIPWIDGETS.keys())
if len(TSDs) == 0:

Benjamin Jakimow
committed
return
#get date INDEX that is closest to requested date
if type(date_of_interest) is str:
date_of_interest = np.datetime64(date_of_interest)
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

Benjamin Jakimow
committed
step = int(float(HBar.maximum()) / (len(TSDs)+1))
HBar.setSingleStep(step)
HBar.setPageStep(step*5)
HBar.setValue(i_doi * step)

Benjamin Jakimow
committed
def clearLayoutWidgets(self, L):
if L is not None:
while L.count():
w = L.takeAt(0)
if w.widget():
w.widget().deleteLater()

Benjamin Jakimow
committed
QApplication.processEvents()

Benjamin Jakimow
committed
def addVectorData(self, files=None):
defDir = s.value('DIR_FILESEARCH')

Benjamin Jakimow
committed
filters = QgsProviderRegistry.instance().fileVectorFilters()
files, filter = QFileDialog.getOpenFileNames(directory=defDir, filter=filters)

benjamin.jakimow@geo.hu-berlin.de
committed

Benjamin Jakimow
committed
if len(files) > 0 and os.path.exists(files[0]):
dn = os.path.dirname(files[0])
s.setValue('DIR_FILESEARCH', dn)
if files:
vectorLayers = []
for f in files:
try:
l = QgsVectorLayer(f, os.path.basename(f))
vectorLayers.append(l)
except Exception as ex:
pass
QgsProject.instance().addMapLayers(vectorLayers)
def addTimeSeriesImages(self, files=None):
if files is None:
s = settings()

Benjamin Jakimow
committed
"""
filters = "GeoTiff (*.tif *.tiff *.gtiff);;"+ \
"ENVI Images (*.bsq *.bil *.bip);;" + \

benjamin.jakimow@geo.hu-berlin.de
committed
"JPEG (*.jpg *.jpeg *.jp2 *.j2k);;"+\
"All files (*.*)"

Benjamin Jakimow
committed
"""
filters = QgsProviderRegistry.instance().fileRasterFilters()
files, filter = QFileDialog.getOpenFileNames(directory=defDir, filter=filters)
if len(files) > 0 and os.path.exists(files[0]):
dn = os.path.dirname(files[0])
M = self.ui.dockTimeSeries.tableView_TimeSeries.model()
M.beginResetModel()
self.TS.clear()
M.endResetModel()
def getSelectedTSDs(self):
TV = self.ui.tableView_TimeSeries
TVM = TV.model()
return [TVM.getTimeSeriesDatumFromIndex(idx) for idx in TV.selectionModel().selectedRows()]
def disconnect_signal(signal):
while True:
try:
signal.disconnect()
except TypeError:
break

benjamin.jakimow@geo.hu-berlin.de
committed
def main():
# add site-packages to sys.path as done by enmapboxplugin.py

benjamin.jakimow@geo.hu-berlin.de
committed
from timeseriesviewer.utils import initQgisApplication

benjamin.jakimow@geo.hu-berlin.de
committed
qgsApp = initQgisApplication()

benjamin.jakimow@geo.hu-berlin.de
committed
ts = TimeSeriesViewer(None)
ts.run()
#ts.loadExampleTimeSeries()
if False:
from example import exampleEvents
lyr = QgsVectorLayer(exampleEvents, 'Events', 'ogr', True)
lyr2 = QgsVectorLayer(exampleEvents, 'Events2', 'ogr', True)
QgsProject.instance().addMapLayers([lyr, lyr2])
mapView = ts.mapViews()[0]
from timeseriesviewer.mapvisualization import MapView
assert isinstance(mapView, MapView)
#mapView.setVectorLayer(lyr)

benjamin.jakimow@geo.hu-berlin.de
committed
# ts.createMapView()

benjamin.jakimow@geo.hu-berlin.de
committed
# close QGIS
qgsApp.exec_()

benjamin.jakimow@geo.hu-berlin.de
committed
qgsApp.exitQgis()
if __name__ == '__main__':

benjamin.jakimow@geo.hu-berlin.de
committed
import timeseriesviewer.__main__ as m
m.run()