Newer
Older
# -*- coding: utf-8 -*-
"""
/***************************************************************************
EnMAPBox
A QGIS plugin
EnMAP-Box V3
-------------------
begin : 2015-08-20
git sha : $Format:%H$
copyright : (C) 2015 by HU-Berlin
email : bj@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. *
* *
***************************************************************************/
"""
import os, sys, re, fnmatch, collections, copy, traceback, six
from qgis.core import *
#os.environ['PATH'] += os.pathsep + r'C:\OSGeo4W64\bin'
from osgeo import gdal, ogr, osr, gdal_array

Benjamin Jakimow
committed
#import console.console_output
#console.show_console()
#sys.stdout = console.console_output.writeOut()
#sys.stderr = console.console_output.writeOut()

Benjamin Jakimow
committed
print('Can not find QGIS instance')

Benjamin Jakimow
committed

Benjamin Jakimow
committed
import code
import codecs
from timeseriesviewer import jp, mkdir, DIR_SITE_PACKAGES, file_search, dprint
site.addsitedir(DIR_SITE_PACKAGES)
#I don't know why, but this is required to run this in QGIS
#todo: still required?
path = os.path.abspath(jp(sys.exec_prefix, '../../bin/pythonw.exe'))
if os.path.exists(path):
multiprocessing.set_executable(path)
sys.argv = [ None ]
#ensure that required non-standard modules are available
import pyqtgraph as pg

benjamin.jakimow@geo.hu-berlin.de
committed
@staticmethod
def fromMapCanvas(mapCanvas):
assert isinstance(mapCanvas, QgsMapCanvas)
extent = mapCanvas.extent()
crs = mapCanvas.mapSettings().destinationCrs()
return SpatialExtent(crs, extent)
def __init__(self, crs, *args):
assert isinstance(crs, QgsCoordinateReferenceSystem)
super(SpatialExtent, self).__init__(*args)
self.mCrs = crs
def setCrs(self, crs):
assert isinstance(crs, QgsCoordinateReferenceSystem)
self.mCrs = crs
def crs(self):
return self.mCrs
def toCrs(self, crs):
assert isinstance(crs, QgsCoordinateReferenceSystem)
if self.mCrs != crs:
trans = QgsCoordinateTransform(self.mCrs, crs)
box = trans.transformBoundingBox(box)
return SpatialExtent(crs, box)
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
def __copy__(self):
return SpatialExtent(self.crs(), QgsRectangle(self))
def combineExtentWith(self, *args):
if args is None:
return
elif isinstance(args[0], SpatialExtent):
extent2 = args[0].toCrs(self.crs())
self.combineExtentWith(QgsRectangle(extent2))
else:
super(SpatialExtent, self).combineExtentWith(*args)
def setCenter(self, centerPoint, crs=None):
if crs and crs != self.crs():
trans = QgsCoordinateTransform(crs, self.crs())
centerPoint = trans.transform(centerPoint)
delta = centerPoint - self.center()
self.setXMaximum(self.xMaximum() + delta.x())
self.setXMinimum(self.xMinimum() + delta.x())
self.setYMaximum(self.yMaximum() + delta.y())
self.setYMinimum(self.yMinimum() + delta.y())
def __cmp__(self, other):
if other is None: return 1
def __eq__(self, other):
s = ""
def __sub__(self, other):
raise NotImplementedError()
def __mul__(self, other):
raise NotImplementedError()

benjamin.jakimow@geo.hu-berlin.de
committed
def upperLeft(self):
return self.xMinimum(), self.yMaximum()
def lowerRight(self):
return self.xMaximum(), self.yMinimum()
def __repr__(self):
return '{} {} {}'.format(self.upperLeft(), self.lowerRight(), self.crs().authid())
from timeseriesviewer.ui.widgets import *
from timeseriesviewer.timeseries import TimeSeries, TimeSeriesDatum, SensorInstrument
columnames = ['date','sensor','ns','nl','nb','image','mask']
def __init__(self, TS, parent=None, *args):
super(QAbstractTableModel, self).__init__()
assert isinstance(TS, TimeSeries)
self.TS = TS
def rowCount(self, parent = QModelIndex()):
return len(self.TS)
def columnCount(self, parent = QModelIndex()):
return len(self.columnames)
def removeRows(self, row, count , parent=QModelIndex()):
self.beginRemoveRows(parent, row, row+count-1)
toRemove = self._data[row:row+count]
for i in toRemove:
self._data.remove(i)
self.endRemoveRows()
def getDateFromIndex(self, index):
if index.isValid():
i = index.row()
if i >= 0 and i < len(self.TS):
return self.TS.getTSDs()[i]
def getTimeSeriesDatumFromIndex(self, index):
if index.isValid():
i = index.row()
if i >= 0 and i < len(self.TS):
return None
value = None
ic_name = self.columnames[index.column()]
TSD = self.getTimeSeriesDatumFromIndex(index)
keys = list(TSD.__dict__.keys())
if role == Qt.DisplayRole or role == Qt.ToolTipRole:
if ic_name == 'name':
value = os.path.basename(TSD.pathImg)
elif ic_name == 'sensor':
if role == Qt.ToolTipRole:
value = TSD.sensor.getDescription()
else:
value = str(TSD.sensor)
elif ic_name == 'date':
value = '{}'.format(TSD.date)
elif ic_name == 'image':
value = TSD.pathImg
elif ic_name == 'mask':
value = TSD.pathMsk
elif ic_name in keys:
value = TSD.__dict__[ic_name]
else:
s = ""
elif role == Qt.BackgroundColorRole:
value = None
elif role == Qt.UserRole:
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
return value
#def flags(self, index):
# return Qt.ItemIsEnabled
def flags(self, index):
if index.isValid():
item = self.getTimeSeriesDatumFromIndex(index)
cname = self.columnames[index.column()]
if cname.startswith('d'): #relative values can be edited
flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable
else:
flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
return flags
#return item.qt_flags(index.column())
return None
def headerData(self, col, orientation, role):
if Qt is None:
return None
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.columnames[col]
elif orientation == Qt.Vertical and role == Qt.DisplayRole:
return col
return None
QAbstractItemModel.__init__(self)
#self.rootItem = TreeItem[]
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
def index(self, row, column, parent = QModelIndex()):
if not parent.isValid():
parentItem = self.rootItem
else:
parentItem = parent.internalPointer()
childItem = parentItem.child(row)
if childItem:
return self.createIndex(row, column, childItem)
else:
return QModelIndex()
def setData(self, index, value, role = Qt.EditRole):
if role == Qt.EditRole:
row = index.row()
return False
return False
def data(self, index, role=Qt.DisplayRole):
data = None
if role == Qt.DisplayRole or role == Qt.EditRole:
data = 'sampletext'
return data
def flags(self, QModelIndex):
return Qt.ItemIsSelectable
def rowCount(self, index=QModelIndex()):
#---------------------------------------------------------------------------
def columnCount(self, index=QModelIndex()):
return 1
class TimeSeriesDatumViewManager(QObject):
def __init__(self, timeSeriesViewer):
assert isinstance(timeSeriesViewer, TimeSeriesViewer)
super(TimeSeriesDatumViewManager, self).__init__()
self.TSV = timeSeriesViewer
self.TSDViews = list()

benjamin.jakimow@geo.hu-berlin.de
committed
self.bandViewMananger = self.TSV.bandViewManager
self.bandViewMananger.sigBandViewAdded.connect(self.addBandView)
self.bandViewMananger.sigBandViewRemoved.connect(self.removeBandView)
self.bandViewMananger.sigBandViewVisibility.connect(self.setBandViewVisibility)

benjamin.jakimow@geo.hu-berlin.de
committed
self.setSpatialExtent(self.TSV.TS.getMaxSpatialExtent())

benjamin.jakimow@geo.hu-berlin.de
committed
self.initTimeSeries(self.TSV.TS)
self.L = self.TSV.ui.scrollAreaSubsetContent.layout()
self.setSubsetSize(QSize(100,50))

benjamin.jakimow@geo.hu-berlin.de
committed
def activateMapTool(self, key):
for tsdv in self.TSDViews:
tsdv.activateMapTool(key)
def setSubsetSize(self, size):
assert isinstance(size, QSize)
self.subsetSize = size
for tsdv in self.TSDViews:
tsdv.setSubsetSize(size)
self.adjustScrollArea()

benjamin.jakimow@geo.hu-berlin.de
committed
def redraw(self):
for tsdv in self.TSDViews:
tsdv.redraw()
def adjustScrollArea(self):
m = self.L.contentsMargins()
n = len(self.TSDViews)
if n > 0:
refTSDView = self.TSDViews[0]
size = refTSDView.ui.size()
w = n * size.width() + (n-1) * (m.left()+ m.right())
h = max([refTSDView.ui.minimumHeight() + m.top() + m.bottom(),
self.TSV.ui.scrollAreaSubsets.height()-25])
self.L.parentWidget().setFixedSize(w,h)

benjamin.jakimow@geo.hu-berlin.de
committed
def initTimeSeries(self, TS):

benjamin.jakimow@geo.hu-berlin.de
committed
self.TS.sigTimeSeriesDatesAdded.connect(self.createTSDViews)
def setMaxTSDViews(self, n=-1):
self.nMaxTSDViews = n
#todo: remove views

benjamin.jakimow@geo.hu-berlin.de
committed
def setSpatialExtent(self, extent):
if extent:
assert isinstance(extent, SpatialExtent)
tsdviews = sorted(self.TSDViews, key=lambda t:t.TSD)
for tsdview in tsdviews:
tsdview.setSpatialExtent(extent)
def navToDOI(self, TSD):
assert isinstance(TSD, TimeSeriesDatum)
#get widget related to TSD
tsdviews = [t for t in self.TSDViews if t.TSD == TSD]
if len(tsdviews) > 0:
i = self.TSDViews.index(tsdviews[0])+1.5
n = len(self.TSDViews)
scrollBar = self.TSV.ui.scrollAreaSubsets.horizontalScrollBar()
smin = scrollBar.minimum()
smax = scrollBar.maximum()
v = smin + (smax - smin) * float(i) / n
scrollBar.setValue(int(round(v)))
def setBandViewVisibility(self, bandView, isVisible):
assert isinstance(bandView, BandView)
assert isinstance(isVisible, bool)
for tsdv in self.TSDViews:

benjamin.jakimow@geo.hu-berlin.de
committed
tsdv.setBandViewVisibility(bandView, isVisible)
def addBandView(self, bandView):
assert isinstance(bandView, BandView)
w = self.L.parentWidget()
w.setUpdatesEnabled(False)
for tsdv in self.TSDViews:
tsdv.ui.setUpdatesEnabled(False)
for tsdv in self.TSDViews:
tsdv.insertBandView(bandView)
for tsdv in self.TSDViews:
tsdv.ui.setUpdatesEnabled(True)
w.setUpdatesEnabled(True)
def removeBandView(self, bandView):
assert isinstance(bandView, BandView)
for tsdv in self.TSDViews:
tsdv.removeBandView(bandView)

benjamin.jakimow@geo.hu-berlin.de
committed
def createTSDViews(self, timeSeriesDates):
for TSD in timeSeriesDates:
assert isinstance(TSD, TimeSeriesDatum)
tsdView = TimeSeriesDatumView(TSD)
tsdView.setSubsetSize(self.subsetSize)
tsdView.sigExtentsChanged.connect(self.setSpatialExtent)
for i, bandView in enumerate(self.bandViewMananger):
tsdView.insertBandView(bandView)
if self.extent:
tsdView.setSpatialExtent(self.extent)
self.addTSDView(tsdView)

benjamin.jakimow@geo.hu-berlin.de
committed
assert isinstance(TSD, TimeSeriesDatum)
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
tsdvs = [tsdv for tsdv in self.TSDViews if tsdv.TSD == TSD]
assert len(tsdvs) == 1
self.removeTSDView(tsdvs[0])
def removeTSDView(self, TSDV):
assert isinstance(TSDV, TimeSeriesDatumView)
self.TSDViews.remove(TSDV)
def addTSDView(self, TSDV):
assert isinstance(TSDV, TimeSeriesDatumView)
if len(self.TSDViews) < 10:
pass
bisect.insort(self.TSDViews, TSDV)
TSDV.ui.setParent(self.L.parentWidget())
self.L.addWidget(TSDV.ui)
self.adjustScrollArea()
#self.TSV.ui.scrollAreaSubsetContent.update()
#self.TSV.ui.scrollAreaSubsets.update()
s = ""

Benjamin Jakimow
committed
class BandView(QObject):

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

benjamin.jakimow@geo.hu-berlin.de
committed
#sigBandViewVisibility = pyqtSignal(bool)
sigHideBandView = pyqtSignal()
sigShowBandView = pyqtSignal()
sigTitleChanged = pyqtSignal(str)

Benjamin Jakimow
committed
def __init__(self, recommended_bands=None, parent=None, showSensorNames=True):
super(BandView, self).__init__()

benjamin.jakimow@geo.hu-berlin.de
committed
self.ui = MapViewUI(parent)

benjamin.jakimow@geo.hu-berlin.de
committed
self.setVisibility(True)

benjamin.jakimow@geo.hu-berlin.de
committed
self.ui.actionRemoveBandView.triggered.connect(lambda: self.sigRemoveBandView.emit(self))

benjamin.jakimow@geo.hu-berlin.de
committed
self.ui.sigHideBandView.connect(lambda : self.sigHideBandView.emit())
self.ui.sigShowBandView.connect(lambda: self.sigShowBandView.emit())
self.sensorViews = collections.OrderedDict()
self.mShowSensorNames = showSensorNames

benjamin.jakimow@geo.hu-berlin.de
committed
def setVisibility(self, isVisible):
self.ui.setVisibility(isVisible)
def visibility(self):
return self.ui.visibility()
def setTitle(self, title):
self.ui.labelViewName.setText(title)

benjamin.jakimow@geo.hu-berlin.de
committed
self.sigTitleChanged.emit(self.ui.labelViewName.text())
def title(self):
return self.ui.labelViewName.text()
def showSensorNames(self, b):
assert isinstance(b, bool)
self.mShowSensorNames = b
for s,w in self.sensorViews.items():
w.showSensorName(b)
def removeSensor(self, sensor):
assert type(sensor) is SensorInstrument
if sensor in self.sensorViews.keys():
self.sensorViews[sensor].close()
self.sensorViews.pop(sensor)
return True
else:
return False
def hasSensor(self, sensor):
assert type(sensor) is SensorInstrument
return sensor in self.sensorViews.keys()

benjamin.jakimow@geo.hu-berlin.de
committed
w = MapViewRenderSettings(sensor)
w.showSensorName(False)

benjamin.jakimow@geo.hu-berlin.de
committed
l = self.ui.layout()
i = l.count()
l.insertWidget(i, w.ui)
class BandViewManager(QObject):
sigSensorAdded = pyqtSignal(SensorInstrument)
sigSensorRemoved = pyqtSignal(SensorInstrument)
sigBandViewAdded = pyqtSignal(BandView)
sigBandViewRemoved = pyqtSignal(BandView)
def __init__(self, timeSeriesViewer):
assert isinstance(timeSeriesViewer, TimeSeriesViewer)
super(BandViewManager, self).__init__()
self.TSV = timeSeriesViewer
self.bandViews = []

benjamin.jakimow@geo.hu-berlin.de
committed
self.bandViewButtons = dict()
self.recentBandViewDefinition = None
def removeSensor(self, sensor):
assert isinstance(sensor, SensorInstrument)
removed = False
for view in self.bandViews:
removed = removed and view.removeSensor(sensor)
if removed:
self.sigSensorRemoved(sensor)
def createBandView(self):

benjamin.jakimow@geo.hu-berlin.de
committed
btnList = self.TSV.ui.BVButtonList
btn = QToolButton(btnList)
btnList.layout().insertWidget(btnList.layout().count() - 1, btn)
bandView = BandView(parent=self.TSV.ui.scrollAreaBandViewsContent, showSensorNames=False)
bandView.sigRemoveBandView.connect(self.removeBandView)

benjamin.jakimow@geo.hu-berlin.de
committed
bandView.sigShowBandView.connect(lambda : self.sigBandViewVisibility.emit(bandView, bandView.visibility()))
bandView.sigHideBandView.connect(lambda: self.sigBandViewVisibility.emit(bandView, bandView.visibility()))
bandView.sigTitleChanged.connect(btn.setText)

benjamin.jakimow@geo.hu-berlin.de
committed
#bandView.setTitle('#{}'.format(len(self)))

benjamin.jakimow@geo.hu-berlin.de
committed
self.bandViewButtons[bandView] = btn
self.bandViews.append(bandView)
for sensor in self.TSV.TS.Sensors:
bandView.addSensor(sensor)

benjamin.jakimow@geo.hu-berlin.de
committed
btn.clicked.connect(lambda : self.showBandViewDefinition(bandView))
self.refreshBandViewTitles()
self.sigBandViewAdded.emit(bandView)
def removeBandView(self, bandView):
assert isinstance(bandView, BandView)

benjamin.jakimow@geo.hu-berlin.de
committed
btn = self.bandViewButtons[bandView]
btnList = self.TSV.ui.BVButtonList

benjamin.jakimow@geo.hu-berlin.de
committed
self.bandViewButtons.pop(bandView)
bandView.ui.setVisible(False)
btn.setVisible(False)
btnList.layout().removeWidget(btn)
self.TSV.BVP.removeWidget(bandView.ui)
bandView.ui.close()

benjamin.jakimow@geo.hu-berlin.de
committed
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
btn.close()
self.refreshBandViewTitles()
self.sigBandViewRemoved.emit(bandView)
def refreshBandViewTitles(self):
for i, bandView in enumerate(self.bandViews):
bandView.setTitle('#{}'.format(i + 1))
def showBandViewDefinition(self, bandView):
assert bandView in self.bandViews
if self.recentBandViewDefinition == bandView:
return
l = self.TSV.BVP
assert l.rowCount() == 2
assert l.columnCount() == 2
toRemove = l.itemAtPosition(0,0)
if toRemove:
oldBandViewUI = toRemove.widget()
oldBandViewUI.setVisible(False)
l.removeWidget(oldBandViewUI)
l.addWidget(bandView.ui, 0,0)
bandView.ui.setVisible(True)
self.recentBandViewDefinition = bandView
print(('show ', l.itemAtPosition(0,0).widget().labelViewName.text()))
def setBandViewVisibility(self, bandView, isVisible):
assert isinstance(bandView, BandView)
assert isinstance(isVisible, bool)
def __len__(self):
return len(self.bandViews)
def __iter__(self):
return iter(self.bandViews)
def __getitem__(self, key):
return self.bandViews[key]
def __contains__(self, bandView):
return bandView in self.bandViews
class TimeSeriesDatumView(QObject):

benjamin.jakimow@geo.hu-berlin.de
committed
sigExtentsChanged = pyqtSignal(SpatialExtent)
def __init__(self, TSD, parent=None):
super(TimeSeriesDatumView, self).__init__()
self.L = self.ui.layout()
self.wOffset = self.L.count()-1

benjamin.jakimow@geo.hu-berlin.de
committed
def activateMapTool(self, key):
for c in self.bandViewCanvases.values():
c.activateMapTool(key)
def setBandViewVisibility(self, bandView, isVisible):
self.bandViewCanvases[bandView].setVisible(isVisible)

benjamin.jakimow@geo.hu-berlin.de
committed
def setSpatialExtent(self, spatialExtent):
assert isinstance(spatialExtent, SpatialExtent)

benjamin.jakimow@geo.hu-berlin.de
committed
c.setSpatialExtent(spatialExtent)
def setSubsetSize(self, size):
assert isinstance(size, QSize)
assert size.width() > 5 and size.height() > 5
self.subsetSize = size
m = self.L.contentsMargins()
self.ui.labelTitle.setFixedWidth(size.width())
self.ui.line.setFixedWidth(size.width())
#apply new subset size to existing canvases
c.setFixedSize(size)
self.ui.setFixedWidth(size.width() + 2*(m.left() + m.right()))
n = len(self.bandViewCanvases)
#todo: improve size forecast
self.ui.setMinimumHeight((n+1) * size.height())
def setTimeSeriesDatum(self, TSD):
assert isinstance(TSD, TimeSeriesDatum)
self.TSD = TSD
self.ui.labelTitle.setText(str(TSD.date))
c.setLayer(self.TSD.pathImg)
def removeBandView(self, bandView):

benjamin.jakimow@geo.hu-berlin.de
committed
canvas = self.bandViewCanvases.pop(bandView)

benjamin.jakimow@geo.hu-berlin.de
committed
def redraw(self):
for c in self.bandViewCanvases.values():
c.refreshAllLayers()
def insertBandView(self, bandView, i=-1):
assert isinstance(bandView, BandView)

benjamin.jakimow@geo.hu-berlin.de
committed
if len(self.bandViewCanvases) != len(self.bandViewOrder):
s = ""

benjamin.jakimow@geo.hu-berlin.de
committed
canvas = MapViewMapCanvas(self.ui)
canvas.setLayer(self.TSD.pathImg)
canvas.setFixedSize(self.subsetSize)

benjamin.jakimow@geo.hu-berlin.de
committed
canvas.extentsChanged.connect(lambda : self.sigExtentsChanged.emit(canvas.spatialExtent()))
self.bandViewCanvases[bandView] = canvas
self.bandViewOrder.insert(i, bandView)
self.L.insertWidget(self.wOffset + i, canvas)
def __lt__(self, other):
return self.TSD < other.TSD
class RenderJob(object):
def __init__(self, TSD, renderer, destinationId=None):
assert isinstance(TSD, TimeSeriesDatum)
assert isinstance(renderer, QgsRasterRenderer)
self.TSD = TSD
self.renderer = renderer
self.destinationId = destinationId
def __eq__(self, other):
if not isinstance(other, RenderJob):
return False
return self.TSD == other.TSD and \
self.renderer == other.renderer and \
self.destinationId == other.destinationId

benjamin.jakimow@geo.hu-berlin.de
committed
list2str = lambda ll : '\n'.join([str(l) for l in ll])

benjamin.jakimow@geo.hu-berlin.de
committed
class QgsInstanceInteraction(QObject):

benjamin.jakimow@geo.hu-berlin.de
committed
def __init__(self, iface, TSV_UI):
super(QgsInstanceInteraction, self).__init__()

benjamin.jakimow@geo.hu-berlin.de
committed
self.iface = iface
self.ui = TSV_UI
self.cbVectorLayer = TSV_UI.cbQgsVectorLayer

benjamin.jakimow@geo.hu-berlin.de
committed
def extent(self):

benjamin.jakimow@geo.hu-berlin.de
committed
def center(self):
s = ""

benjamin.jakimow@geo.hu-berlin.de
committed
def crs(self):
s = ""

benjamin.jakimow@geo.hu-berlin.de
committed
def getVectorLayerRepresentation(self):
if self.ui.gbQgsVectorLayer.isChecked():
lyr = self.cbVectorLayer.currentLayer()
alpha = self.ui.sliderQgsVectorTransparency.value()
return lyr
else:
return None
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
"""
# Save reference to the QGIS interface
from timeseriesviewer.ui.widgets import TimeSeriesViewerUI

benjamin.jakimow@geo.hu-berlin.de
committed
self.ui = TimeSeriesViewerUI()
if iface:
import timeseriesviewer
timeseriesviewer.QGIS_TSV_BRIDGE = QgsInstanceInteraction(iface, self.ui)
self.ui.setQgsLinkWidgets()
#init empty time series
self.TS = TimeSeries()
self.hasInitialCenterPoint = False

benjamin.jakimow@geo.hu-berlin.de
committed
self.TS.sigTimeSeriesDatesAdded.connect(self.datesAdded)
#init TS model
TSM = TimeSeriesTableModel(self.TS)
D = self.ui
self.ICP = D.scrollAreaSubsetContent.layout()
D.scrollAreaBandViewsContent.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
self.BVP = self.ui.scrollAreaBandViewsContent.layout()
D.tableView_TimeSeries.setModel(TSM)
D.tableView_TimeSeries.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
self.bandViewManager = BandViewManager(self)
self.timeSeriesViewManager = TimeSeriesDatumViewManager(self)
self.ValidatorPxX = QIntValidator(0,99999)
self.ValidatorPxY = QIntValidator(0,99999)
#connect actions with logic
#D.btn_showPxCoordinate.clicked.connect(lambda: self.showSubsetsStart())

benjamin.jakimow@geo.hu-berlin.de
committed
D.actionSelectCenter.triggered.connect(lambda : self.timeSeriesViewManager.activateMapTool('selectCenter'))
D.actionSelectArea.triggered.connect(lambda : self.timeSeriesViewManager.activateMapTool('selectArea'))
D.actionZoomMaxExtent.triggered.connect(lambda : self.zoomTo('maxExtent'))
D.actionZoomPixelScale.triggered.connect(lambda: self.zoomTo('pixelScale'))
D.actionZoomIn.triggered.connect(lambda: self.timeSeriesViewManager.activateMapTool('zoomIn'))
D.actionZoomOut.triggered.connect(lambda: self.timeSeriesViewManager.activateMapTool('zoomOut'))
D.actionPan.triggered.connect(lambda: self.timeSeriesViewManager.activateMapTool('pan'))
D.actionAddBandView.triggered.connect(self.bandViewManager.createBandView)
D.actionAddTSD.triggered.connect(self.ua_addTSImages)
D.actionRemoveTSD.triggered.connect(self.removeTimeSeriesDates)

benjamin.jakimow@geo.hu-berlin.de
committed
D.actionRedraw.triggered.connect(self.timeSeriesViewManager.redraw)
D.actionLoadTS.triggered.connect(self.loadTimeSeries)
D.actionClearTS.triggered.connect(self.clearTimeSeries)
D.actionSaveTS.triggered.connect(self.ua_saveTSFile)
D.actionAddTSExample.triggered.connect(self.ua_loadExampleTS)

benjamin.jakimow@geo.hu-berlin.de
committed
#connect buttons with actions
D.btnClearLabelList.clicked.connect(D.tbCollectedLabels.clear)

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_())
D.actionFirstTSD.triggered.connect(lambda: self.setDOISliderValue('first'))
D.actionLastTSD.triggered.connect(lambda: self.setDOISliderValue('last'))
D.actionNextTSD.triggered.connect(lambda: self.setDOISliderValue('next'))
D.actionPreviousTSD.triggered.connect(lambda: self.setDOISliderValue('previous'))
D.sliderDOI.valueChanged.connect(self.setDOI)
D.actionSetSubsetSize.triggered.connect(lambda : self.timeSeriesViewManager.setSubsetSize(
self.ui.subsetSize()))

benjamin.jakimow@geo.hu-berlin.de
committed
D.actionSetExtent.triggered.connect(lambda: self.timeSeriesViewManager.setSpatialExtent(self.ui.spatialExtent()))
self.canvasCrs = QgsCoordinateReferenceSystem()

benjamin.jakimow@geo.hu-berlin.de
committed
def zoomTo(self, key):
if key == 'maxExtent':
ext = self.TS.getMaxSpatialExtent(self.ui.crs())
self.timeSeriesViewManager.setSpatialExtent(ext)
elif key == 'pixelScale':
s = ""
def setDOISliderValue(self, key):
ui = self.ui
v = ui.sliderDOI.value()
if key == 'first':
v = ui.sliderDOI.minimum()
elif key == 'last':
v = ui.sliderDOI.maximum()
elif key =='next':
v = min([v+1,ui.sliderDOI.maximum()])
elif key =='previous':
v = max([v - 1, ui.sliderDOI.minimum()])
ui.sliderDOI.setValue(v)
def setDOI(self, i):

benjamin.jakimow@geo.hu-berlin.de
committed
assert i <= len(self.TS)
def icon(self):
return TimeSeriesViewer.icon()
D = self.ui

benjamin.jakimow@geo.hu-berlin.de
committed
l = len(self.TS.data)
D.sliderDOI.setMaximum(l)
#get meaningfull tick intervall
for tickInterval in [1,5,10,25,50,100,200]:
if (D.sliderDOI.size().width() / float(l) * tickInterval) > 5:
break
D.sliderDOI.setTickInterval(tickInterval)
if not self.hasInitialCenterPoint:
if len(self.TS.data) > 0:
extent = self.TS.getMaxSpatialExtent(self.canvasCrs)
self.timeSeriesViewManager.setSubsetSize(self.ui.subsetSize())
self.timeSeriesViewManager.setSpatialExtent(extent)
self.ui.setSpatialExtent(extent)
self.hasInitialCenterPoint = True
if len(self.bandViewManager) == 0:
# add two empty band-views by default

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

benjamin.jakimow@geo.hu-berlin.de
committed
def loadTimeSeries(self, path=None, n_max=None):
if path is None or path is False:
path = QFileDialog.getOpenFileName(self.ui, 'Open Time Series file', '')
if os.path.exists(path):
M = self.ui.tableView_TimeSeries.model()
def ua_saveTSFile(self):
path = QFileDialog.getSaveFileName(self.ui, caption='Save Time Series file')
if path is not None:
self.TS.saveToFile(path)
def ua_loadExampleTS(self):
from timeseriesviewer import PATH_EXAMPLE_TIMESERIES
if not os.path.exists(PATH_EXAMPLE_TIMESERIES):
QMessageBox.information(self.ui, 'File not found', '{} - this file describes an exemplary time series.'.format(path_example))

benjamin.jakimow@geo.hu-berlin.de
committed
self.loadTimeSeries(path=PATH_EXAMPLE_TIMESERIES)

benjamin.jakimow@geo.hu-berlin.de
committed
self.qgsCanvas.setMapTool(self.RectangleMapTool)

benjamin.jakimow@geo.hu-berlin.de
committed
self.qgsCanvas.setMapTool(self.PointMapTool)

benjamin.jakimow@geo.hu-berlin.de
committed
def setSpatialSubset(self, spatialExtent):
#keep specified CRS but translate extent
oldExtent = self.ui.spatialExtent()

benjamin.jakimow@geo.hu-berlin.de
committed
self.timeSeriesViewManager.setSpatialExtent(extent)

benjamin.jakimow@geo.hu-berlin.de
committed
def ua_TSprogress(self, v_min, v, v_max):
assert v_min <= v and v <= v_max
P = self.ui.progressBar
if P.minimum() != v_min or P.maximum() != v_max:
P.setRange(v_min, v_max)
else:
s = ""
P.setValue(v)

benjamin.jakimow@geo.hu-berlin.de
committed
def datesAdded(self, dates):
assert isinstance(dates, list)
self.ui.tableView_TimeSeries.resizeColumnsToContents()

benjamin.jakimow@geo.hu-berlin.de
committed
self.timeseriesChanged()
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
# 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
return QCoreApplication.translate('EnMAPBox', message)
def ua_addTSD_to_QGIS(self, TSD, bands):
"""Removes the plugin menu item and icon """
self.iface.removeToolBarIcon(self.action)
self.ui.show()

Benjamin Jakimow
committed
def scrollToDate(self, date_of_interest):

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 showSubset(self, renderJob, pixmap):
assert isinstance(renderJob, RenderJob)
chipLabel = self.CHIPWIDGETS[renderJob.TSD][renderJob.destinationId]
chipLabel.setPixmap(pixmap)
chipLabel.setFixedSize(pixmap.size())
chipLabel.update()
s = ""
def ua_collect_date(self, ICL, event):
if self.ui.rb_labeling_activate.isChecked():
txt = self.ui.tb_labeling_text.toPlainText()
reg = re.compile('\d{4}-\d{2}-\d{2}', re.I | re.MULTILINE)
dates = set([np.datetime64(m) for m in reg.findall(txt)])
doi = ICL.TSD.getDate()
if event.button() == Qt.LeftButton:
elif event.button() == Qt.MiddleButton and doi in dates:
dates.remove(doi)
dates = sorted(list(dates))
txt = ' '.join([d.astype(str) for d in dates])
self.ui.tb_labeling_text.setText(txt)
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()
def ua_addTSImages(self, files=None):
if files is None:
files = QFileDialog.getOpenFileNames()
if files:
M = self.ui.tableView_TimeSeries.model()
M.beginResetModel()
self.TS.addFiles(files)
M.endResetModel()
M = self.ui.tableView_TimeSeries.model()
M.beginResetModel()
self.TS.clear()
M.endResetModel()
def removeTimeSeriesDates(self, TSDs=None):
if TSDs is None:
TSDs = self.getSelectedTSDs()
assert isinstance(TSDs,list)
M = self.ui.tableView_TimeSeries.model()
self.TS.removeDates(TSDs)
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
def showRGBData(data):
def run_tests():
if False:
pathImg = r'O:\SenseCarbonProcessing\BJ_NOC\01_RasterData\00_VRTs\02_Cutted\2014-07-26_LC82270652014207LGN00_BOA.vrt'
pathMsk = r'O:\SenseCarbonProcessing\BJ_NOC\01_RasterData\00_VRTs\02_Cutted\2014-07-26_LC82270652014207LGN00_Msk.vrt'
if False:
TSD = TimeSeriesDatum(pathImg)
TSD.setMask(pathMsk)
c = [670949.883,-786288.771]
w_x = w_y = 1000 #1km box
srs = TSD.getSpatialReference()
ring = ogr.Geometry(ogr.wkbLinearRing)
import itertools
for x,y in itertools.product([1000, -1000], repeat=2):
ring.AddPoint(c[0]+x, c[1]+y)
ring.AssignSpatialReference(srs)
bb = ogr.Geometry(ogr.wkbPolygon)
bb.AddGeometry(ring)
bb.AssignSpatialReference(srs)
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
def getChip3d_OLD(chips, r,g,b, range_r, range_g, range_b):
nl, ns = chips[r].shape
a3d = np.ndarray((3,nl,ns), dtype='float')
rgb_idx = [r,g,b]
ranges = [range_r, range_g, range_b]
for i, rgb_i in enumerate(rgb_idx):
range = ranges[i]
data = chips[rgb_i].astype('float')
data -= range[0]
data *= 255./range[1]
a3d[i,:] = data
np.clip(a3d, 0, 255, out=a3d)
return a3d.astype('uint8')
range_r = [0,500]
range_g = [0,500]
range_b = [0,500]
bands = [3,2,1]
#chipData = TSD.readSpatialChip(bb,bands=bands )
#main.addNumpy(getChip3d(chipData, bands, (range_r, range_g, range_b)))
dirSrcLS = r'O:\SenseCarbonProcessing\BJ_NOC\01_RasterData\00_VRTs\02_Cutted'
filesImgLS = file_search(dirSrcLS, '2014*_BOA.vrt')
filesMsk = file_search(dirSrcLS, '2014*_Msk.vrt')
TS = TimeSeries(imageFiles=filesImgLS, maskFiles=filesMsk)
app=PyQt4.Qt.QApplication([])
dirSrcLS = r'\\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT'
dirSrcRE = r'\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs'
filesImgRE = file_search(dirSrcRE, '*.vrt', recursive=True)
#filesMsk = file_search(dirSrc, '2014*_Msk.vrt')
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_addTSMasks(files=filesMsk)
#S.ua_addView(bands=[4,5,3])
if False:
import qgis.core
# supply path to where is your qgis installed
#QgsApplication.setPrefixPath("/Applications/QGIS_2.12.app/Contents/MacOS/QGIS", True)
# load providers
QgsApplication.initQgis()
a = QgsApplication([], True)
dirSrcLS = r'O:\SenseCarbonProcessing\BJ_NOC\01_RasterData\00_VRTs\02_Cutted'
filesImgLS = file_search(dirSrcLS, '2014*_BOA.vrt')
filesMsk = file_search(dirSrcLS, '2014*_Msk.vrt')
S.ua_addTSImages(files=filesImgLS)
S.ua_addTSMasks(files=filesMsk)
if __name__ == '__main__':