Newer
Older
elif colName == self.cnStyle:
self.mPlotSettings.sort(key=lambda sv: sv.color, reverse=r)
def rowCount(self, parent = QModelIndex()):
return len(self.mPlotSettings)
def removeRows(self, row, count , parent = QModelIndex()):
for tsd in toRemove:
self.endRemoveRows()
assert isinstance(plotStyle, TemporalProfile2DPlotStyle)
if plotStyle in self.mPlotSettings:
i = self.mPlotSettings.index(plotStyle)
return self.createIndex(i, 0)
else:
return QModelIndex()
def idx2plotStyle(self, index):
if index.isValid() and index.row() < self.rowCount():
return self.mPlotSettings[index.row()]
return None
def columnCount(self, parent = QModelIndex()):
def data(self, index, role = Qt.DisplayRole):
if role is None or not index.isValid():
return None
value = None
columnName = self.columnNames[index.column()]
if isinstance(plotStyle, TemporalProfile2DPlotStyle):
sensor = plotStyle.sensor()
#print(('data', columnName, role))
if role == Qt.DisplayRole:
if columnName == self.cnSensor:
if isinstance(sensor, SensorInstrument):
value = sensor.name()
else:
value = '<Select Sensor>'
elif columnName == self.cnExpression:
value = plotStyle.expression()
elif columnName == self.cnTemporalProfile:
tp = plotStyle.temporalProfile()
if isinstance(tp, TemporalProfile):
value = tp.name()
else:
value = 'undefined'
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
#elif role == Qt.DecorationRole:
# if columnName == self.cnStyle:
# value = plotStyle.createIcon(QSize(96,96))
elif role == Qt.CheckStateRole:
if columnName == self.cnTemporalProfile:
value = Qt.Checked if plotStyle.isVisible() else Qt.Unchecked
elif role == Qt.UserRole:
value = plotStyle
if columnName == self.cnSensor:
value = plotStyle.sensor()
elif columnName == self.cnExpression:
value = plotStyle.expression()
elif columnName == self.cnStyle:
value = plotStyle
elif columnName == self.cnTemporalProfile:
value == plotStyle.temporalProfile()
else:
value = plotStyle
#print(('get data',value))
return value
def setData(self, index, value, role=None):
if role is None or not index.isValid():
return False
#print(('Set data', index.row(), index.column(), value, role))
columnName = self.columnNames[index.column()]
result = False
plotStyle = self.idx2plotStyle(index)
if isinstance(plotStyle, TemporalProfile2DPlotStyle):
if role in [Qt.DisplayRole]:
if columnName == self.cnExpression:
plotStyle.setExpression(value)
result = True
elif columnName == self.cnStyle:
if isinstance(value, PlotStyle):
result = True
if role == Qt.CheckStateRole:
if columnName == self.cnTemporalProfile:
plotStyle.setVisibility(value == Qt.Checked)
result = True
if role == Qt.EditRole:
if columnName == self.cnExpression:
plotStyle.setExpression(value)
result = True
elif columnName == self.cnStyle:
plotStyle.copyFrom(value)
result = True
elif columnName == self.cnSensor:
plotStyle.setSensor(value)
result = True
elif columnName == self.cnTemporalProfile:
plotStyle.setTemporalProfile(value)
result = True
if result:
#save plot-style
self.dataChanged.emit(index, index)
return result
def savePlotSettings(self, sensorPlotSettings, index='DEFAULT'):
assert isinstance(sensorPlotSettings, TemporalProfile2DPlotStyle)
id = 'SPS.{}.{}'.format(index, sensorPlotSettings.sensor().id())
d = pickle.dumps(sensorPlotSettings)
SETTINGS.setValue(id, d)
def restorePlotSettings(self, sensor, index='DEFAULT'):
assert isinstance(sensor, SensorInstrument)
id = 'SPS.{}.{}'.format(index, sensor.id())
sensorPlotSettings = SETTINGS.value(id)
if sensorPlotSettings is not None:
try:
sensorPlotSettings = pickle.loads(sensorPlotSettings)
s = ""
except:
sensorPlotSettings = None
pass
if isinstance(sensorPlotSettings, TemporalProfile2DPlotStyle):
return sensorPlotSettings
else:
def flags(self, index):
if index.isValid():
columnName = self.columnNames[index.column()]
flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
flags = flags | Qt.ItemIsUserCheckable
if columnName in [self.cnTemporalProfile, self.cnSensor, self.cnExpression, self.cnStyle]: #allow check state
flags = flags | Qt.ItemIsEditable
return flags
#return item.qt_flags(index.column())
return Qt.NoItemFlags
def headerData(self, col, orientation, role):
if Qt is None:
return None
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
elif orientation == Qt.Vertical and role == Qt.DisplayRole:
return col
return None
class ProfileViewDockUI(QgsDockWidget, loadUI('profileviewdock.ui')):
def __init__(self, parent=None):
super(ProfileViewDockUI, self).__init__(parent)
self.setupUi(self)
#self.line.setVisible(False)
#self.listWidget.setVisible(False)

benjamin.jakimow@geo.hu-berlin.de
committed
self.baseTitle = self.windowTitle()
self.stackedWidget.currentChanged.connect(self.onStackPageChanged)
self.stackedWidget.setCurrentWidget(self.page2D)

benjamin.jakimow@geo.hu-berlin.de
committed
if OPENGL_AVAILABLE:
#from pyqtgraph.opengl import GLViewWidget
#self.plotWidget3D = GLViewWidget(parent=self.page3D)
self.plotWidget3D = ViewWidget3D(parent=self.frame3DPlot)
self.plotWidget3D.setObjectName('plotWidget3D')
size = self.labelDummy3D.size()
l.addWidget(self.plotWidget3D)
self.plotWidget3D.setSizePolicy(self.labelDummy3D.sizePolicy())
self.labelDummy3D.setVisible(False)
l.removeWidget(self.labelDummy3D)
self.plotWidget3D.setBaseSize(size)
self.splitter3D.setSizes([100, 100])
#pi = self.plotWidget2D.plotItem
#ax = DateAxis(orientation='bottom', showValues=True)
#pi.layout.addItem(ax, 3,2)

benjamin.jakimow@geo.hu-berlin.de
committed
self.TS = None
self.progressBar.setMinimum(0)
self.progressBar.setMaximum(100)
self.progressBar.setValue(0)
self.progressInfo.setText('')
self.pxViewModel2D = None
self.pxViewModel3D = None
self.tableView2DProfiles.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
self.tableView2DProfiles.setSortingEnabled(True)
self.tableViewTemporalProfiles.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
self.tableViewTemporalProfiles.setSortingEnabled(True)

benjamin.jakimow@geo.hu-berlin.de
committed
self.menuTPSaveOptions = QMenu()
self.menuTPSaveOptions.addAction(self.actionSaveTPCoordinates)
self.menuTPSaveOptions.addAction(self.actionSaveTPCSV)
self.menuTPSaveOptions.addAction(self.actionSaveTPVector)
self.btnSaveTemporalProfiles.setMenu(self.menuTPSaveOptions)
def onStackPageChanged(self, i):
w = self.stackedWidget.currentWidget()
title = self.baseTitle
if w == self.page2D:
title = '{} | 2D'.format(title)

benjamin.jakimow@geo.hu-berlin.de
committed
elif w == self.page3D:
title = '{} | 3D'.format(title)

benjamin.jakimow@geo.hu-berlin.de
committed
elif w == self.pagePixel:
title = '{} | Coordinates'.format(title)

benjamin.jakimow@geo.hu-berlin.de
committed
self.setWindowTitle(title)
NEXT_COLOR_HUE_DELTA_CON = 10
NEXT_COLOR_HUE_DELTA_CAT = 100
def nextColor(color, mode='cat'):
"""
Reuturns another color
:param color:
:param mode:
:return:
"""
assert mode in ['cat','con']
assert isinstance(color, QColor)
hue, sat, value, alpha = color.getHsl()
if mode == 'cat':
hue += NEXT_COLOR_HUE_DELTA_CAT
elif mode == 'con':
hue += NEXT_COLOR_HUE_DELTA_CON
if sat == 0:
sat = 255
value = 128
alpha = 255
s = ""
while hue > 360:
hue -= 360
return QColor.fromHsl(hue, sat, value, alpha)
class SpectralTemporalVisualization(QObject):
sigShowPixel = pyqtSignal(TimeSeriesDatum, QgsPoint, QgsCoordinateReferenceSystem)
"""
Signalizes to move to specific date of interest
"""
sigMoveToDate = pyqtSignal(np.datetime64)
def __init__(self, ui):
super(SpectralTemporalVisualization, self).__init__()
assert isinstance(ui, ProfileViewDockUI), 'arg ui of type: {} {}'.format(type(ui), str(ui))
self.ui = ui
import timeseriesviewer.pixelloader
if True or DEBUG:
timeseriesviewer.pixelloader.DEBUG = True
self.plot_initialized = False
self.plot2D = ui.plotWidget2D
self.plot2D.getViewBox().sigMoveToDate.connect(self.sigMoveToDate)
self.plot3D = ui.plotWidget3D
# pixel loader to load pixel values in parallel
self.pixelLoader = PixelLoader()
self.pixelLoader.sigPixelLoaded.connect(self.onPixelLoaded)
self.pixelLoader.sigLoadingStarted.connect(lambda: self.ui.progressInfo.setText('Start loading...'))
self.pixelLoader.sigLoadingStarted.connect(self.clear)
self.pixelLoader.sigLoadingFinished.connect(lambda : self.plot2D.enableAutoRange('x', False))
# temporal profile collection to store loaded values
self.tpCollection = TemporalProfileCollection()
self.tpCollectionListModel = TemporalProfileCollectionListModel(self.tpCollection)
self.ui.tableViewTemporalProfiles.setModel(self.tpCollection)
self.ui.tableViewTemporalProfiles.selectionModel().selectionChanged.connect(self.onTemporalProfileSelectionChanged)
self.ui.tableViewTemporalProfiles.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
#set the plot models for 2D
self.plotSettingsModel2D = PlotSettingsModel2D()
self.ui.tableView2DProfiles.setModel(self.plotSettingsModel2D)
self.ui.tableView2DProfiles.setSortingEnabled(False)
self.ui.tableView2DProfiles.selectionModel().selectionChanged.connect(self.onPlot2DSelectionChanged)
self.ui.tableView2DProfiles.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
self.delegateTableView2D = None #wil be set with connecting the TimeSeries
self.plotSettingsModel2D.sigDataChanged.connect(self.requestUpdate)
self.plotSettingsModel2D.rowsInserted.connect(self.onRowsInserted2D)
# set the plot models for 3D
self.plotSettingsModel3D = PlotSettingsModel3D()
self.ui.tableView3DProfiles.setModel(self.plotSettingsModel3D)
self.ui.tableView3DProfiles.setSortingEnabled(False)
self.ui.tableView2DProfiles.selectionModel().selectionChanged.connect(self.onPlot3DSelectionChanged)
self.ui.tableView3DProfiles.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
self.plotSettingsModel3D.rowsInserted.connect(self.onRowsInserted3D)
self.delegateTableView3D = None #will be set with connecting the TimeSeries
self.reset3DCamera()
# remove / add plot style
def on2DPlotStyleRemoved(plotStyles):
for plotStyle in plotStyles:
assert isinstance(plotStyle, PlotStyle)
for pi in plotStyle.mPlotItems:
self.plot2D.getPlotItem().removeItem(pi)
def on3DPlotStyleRemoved(plotStyles):
for plotStyle in plotStyles:
assert isinstance(plotStyle, TemporalProfile3DPlotStyle)
pass
# for pi in plotStyle.mPlotItems:
# self.plot2D.getPlotItem().removeItem(pi)
self.plotSettingsModel2D.sigPlotStylesRemoved.connect(on2DPlotStyleRemoved)
self.updateRequested = True
self.updateTimer = QTimer(self)
self.updateTimer.timeout.connect(self.onDataUpdate)
self.updateTimer.start(2000)
self.sigMoveToDate.connect(self.onMoveToDate)

benjamin.jakimow@geo.hu-berlin.de
committed
assert isinstance(TS, TimeSeries)
self.TS = TS
self.tpCollection.connectTimeSeries(self.TS)
self.delegateTableView2D = PlotSettingsModel2DWidgetDelegate(self.ui.tableView2DProfiles, self.TS, self.tpCollectionListModel)
self.delegateTableView2D.setItemDelegates(self.ui.tableView2DProfiles)
self.delegateTableView3D = PlotSettingsModel3DWidgetDelegate(self.ui.tableView3DProfiles, self.TS, self.tpCollectionListModel)
self.delegateTableView3D.setItemDelegates(self.ui.tableView3DProfiles)
def selected2DPlotStyles(self):
result = []
m = self.ui.tableView2DProfiles.model()
for idx in selectedModelIndices(self.ui.tableView2DProfiles):
result.append(m.idx2plotStyle(idx))
return result
def selectedTemporalProfiles(self):
result = []
m = self.ui.tableViewTemporalProfiles.model()
for idx in selectedModelIndices(self.ui.tableViewTemporalProfiles):
result.append(m.idx2tp(idx))
return result
m = self.ui.tableView2DProfiles.model()
m.removePlotStyles(plotStyles)
def removeTemporalProfiles(self, temporalProfiles):
m = self.ui.tableViewTemporalProfiles.model()
if isinstance(m, TemporalProfileCollection):
m.removeTemporalProfiles(temporalProfiles)
def createNewPlotStyle2D(self):
plotStyle = TemporalProfile2DPlotStyle(self.tpCollection[0])
plotStyle.sigExpressionUpdated.connect(self.updatePlot2D)
sensors = list(self.TS.Sensors.keys())
if len(sensors) > 0:
plotStyle.setSensor(sensors[0])
if len(self.plotSettingsModel2D) > 0:
lastStyle = self.plotSettingsModel2D[-1]
assert isinstance(lastStyle, TemporalProfile2DPlotStyle)
markerColor = nextColor(lastStyle.markerBrush.color())
plotStyle.markerBrush.setColor(markerColor)
self.plotSettingsModel2D.insertPlotStyles([plotStyle])
pdi = plotStyle.createPlotItem(self.plot2D)
assert isinstance(pdi, TemporalProfilePlotDataItem)
pdi.sigClicked.connect(self.onProfileClicked2D)
pdi.sigPointsClicked.connect(self.onPointsClicked2D)
self.plot2D.getPlotItem().addItem(pdi)
#self.plot2D.getPlotItem().addItem(pg.PlotDataItem(x=[1, 2, 3], y=[1, 2, 3]))
#plotItem.addDataItem(pdi)
#plotItem.plot().sigPlotChanged.emit(plotItem)
self.updatePlot2D()
def createNewPlotStyle3D(self):
l = len(self.tpCollection)
plotStyle = TemporalProfile3DPlotStyle()
if l > 0:
temporalProfile = self.tpCollection[0]
plotStyle.setTemporalProfile(temporalProfile)
self.plotSettingsModel3D.insertPlotStyles([plotStyle])
self.updatePlot3D()

benjamin.jakimow@geo.hu-berlin.de
committed
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
def onProfileClicked2D(self, pdi):
if isinstance(pdi, TemporalProfilePlotDataItem):
sensor = pdi.mPlotStyle.sensor()
tp = pdi.mPlotStyle.temporalProfile()
if isinstance(tp, TemporalProfile) and isinstance(sensor, SensorInstrument):
info = ['Sensor:{}'.format(sensor.name()),
'Coordinate:{}, {}'.format(tp.mCoordinate.x(), tp.mCoordinate.y())]
self.ui.tbInfo2D.setPlainText('\n'.join(info))
def onPointsClicked2D(self, pdi, spottedItems):
if isinstance(pdi, TemporalProfilePlotDataItem) and isinstance(spottedItems, list):
sensor = pdi.mPlotStyle.sensor()
tp = pdi.mPlotStyle.temporalProfile()
if isinstance(tp, TemporalProfile) and isinstance(sensor, SensorInstrument):
info = ['Sensor: {}'.format(sensor.name()),
'Coordinate: {}, {}'.format(tp.mCoordinate.x(), tp.mCoordinate.y())]
for item in spottedItems:
pos = item.pos()
x = pos.x()
y = pos.y()
date = num2date(x)
info.append('Date: {}\nValue: {}'.format(date, y))
self.ui.tbInfo2D.setPlainText('\n'.join(info))
def onTemporalProfileSelectionChanged(self, selected, deselected):

benjamin.jakimow@geo.hu-berlin.de
committed
nSelected = len(selected)
self.ui.actionRemoveTemporalProfile.setEnabled(nSelected > 0)
self.ui.btnSaveTemporalProfiles.setEnabled(nSelected > 0)
def onPlot2DSelectionChanged(self, selected, deselected):
self.ui.actionRemoveStyle2D.setEnabled(len(selected) > 0)
def onPlot3DSelectionChanged(self, selected, deselected):
self.ui.actionRemoveStyle3D.setEnabled(len(selected) > 0)
self.ui.actionRemoveStyle2D.setEnabled(False)
self.ui.actionRemoveTemporalProfile.setEnabled(False)
self.ui.btnAddStyle2D.setDefaultAction(self.ui.actionAddStyle2D)
self.ui.btnRemoveStyle2D.setDefaultAction(self.ui.actionRemoveStyle2D)
self.ui.btnAddStyle3D.setDefaultAction(self.ui.actionAddStyle3D)
self.ui.btnRemoveStyle3D.setDefaultAction(self.ui.actionRemoveStyle3D)
self.ui.actionAddStyle2D.triggered.connect(self.createNewPlotStyle2D)
self.ui.actionAddStyle3D.triggered.connect(self.createNewPlotStyle3D)
self.ui.btnRefresh2D.setDefaultAction(self.ui.actionRefresh2D)
self.ui.btnRefresh3D.setDefaultAction(self.ui.actionRefresh3D)
self.ui.btnRemoveTemporalProfile.setDefaultAction(self.ui.actionRemoveTemporalProfile)
self.ui.btnReset3DCamera.setDefaultAction(self.ui.actionReset3DCamera)
self.ui.actionRefresh2D.triggered.connect(self.updatePlot2D)
self.ui.actionRefresh3D.triggered.connect(self.updatePlot3D)

benjamin.jakimow@geo.hu-berlin.de
committed
self.ui.btnLoadProfile1.setDefaultAction(self.ui.actionLoadProfileRequest)
self.ui.btnLoadProfile2.setDefaultAction(self.ui.actionLoadProfileRequest)
self.ui.btnLoadProfile3.setDefaultAction(self.ui.actionLoadProfileRequest)
self.ui.actionRemoveStyle2D.triggered.connect(lambda:self.removePlotStyles2D(self.selected2DPlotStyles()))
self.ui.actionRemoveTemporalProfile.triggered.connect(lambda :self.removeTemporalProfiles(self.selectedTemporalProfiles()))
self.ui.actionReset3DCamera.triggered.connect(self.reset3DCamera)
self.tpCollection.sigMaxProfilesChanged.connect(self.ui.sbMaxTP.setValue)
self.ui.sbMaxTP.valueChanged.connect(self.tpCollection.setMaxProfiles)

benjamin.jakimow@geo.hu-berlin.de
committed
from timeseriesviewer.temporalprofiles2d import saveTemporalProfiles

benjamin.jakimow@geo.hu-berlin.de
committed
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
DEF_PATH = None
self.ui.actionSaveTPCoordinates.triggered.connect(
lambda: saveTemporalProfiles(self.tpCollection[:],
QFileDialog.getSaveFileName(
self.ui, 'Save Temporal Profile Coordinates',
DEF_PATH, 'ESRI Shapefile (*.shp);;Geopackage (*.gpkg);;Textfile (*.csv *.txt)'
), mode='coordinate'
)
)
self.ui.actionSaveTPCSV.triggered.connect(
lambda: saveTemporalProfiles(self.tpCollection[:],
QFileDialog.getSaveFileName(
self.ui, 'Save Temporal Profiles to Text File.',
DEF_PATH,
'Textfile (*.csv *.txt)'
), mode ='all'
)
)
self.ui.actionSaveTPVector.triggered.connect(
lambda: saveTemporalProfiles(self.tpCollection[:],
QFileDialog.getSaveFileName(
self.ui, 'Save Temporal Profiles to Vector File.',
DEF_PATH,
'ESRI Shapefile (*.shp);;Geopackage (*.gpkg)'
), mode = 'all'
)
)
#todo: self.ui.actionRemoveStyle2D.triggered.connect(self.plotSettingsModel.createPlotStyle)
def reset3DCamera(self, *args):
if OPENGL_AVAILABLE:
self.plot3D.resetCamera()
def onMoveToDate(self, date):
dt = np.asarray([np.abs(tsd.date - date) for tsd in self.TS])
i = np.argmin(dt)
self.sigMoveToTSD.emit(self.TS[i])
def onPixelLoaded(self, nDone, nMax, d):
self.ui.progressBar.setValue(nDone)
self.ui.progressBar.setMaximum(nMax)
if d.success():
t = 'Last loaded from {}.'.format(bn)
else:
t = 'Failed loading from {}.'.format(bn)
if d.info and d.info != '':
t += '({})'.format(d.info)
def requestUpdate(self, *args):
self.updateRequested = True
#next time
def onRowsInserted2D(self, parent, start, end):
model = self.ui.tableView2DProfiles.model()
if isinstance(model, PlotSettingsModel2D):
colExpression = model.columnIndex(model.cnExpression)
colStyle = model.columnIndex(model.cnStyle)
while start <= end:
idxExpr = model.createIndex(start, colExpression)
idxStyle = model.createIndex(start, colStyle)
self.ui.tableView2DProfiles.openPersistentEditor(idxExpr)
self.ui.tableView2DProfiles.openPersistentEditor(idxStyle)
start += 1
#self.TV.openPersistentEditor(model.createIndex(start, colStyle))
s = ""
def onRowsInserted3D(self, parent, start, end):
model = self.ui.tableView3DProfiles.model()
if isinstance(model, PlotSettingsModel3D):
colExpression = model.columnIndex(model.cnExpression)
colStyle = model.columnIndex(model.cnStyle)
while start <= end:
idxStyle = model.createIndex(start, colStyle)
idxExpr = model.createIndex(start, colExpression)
self.ui.tableView3DProfiles.openPersistentEditor(idxStyle)
self.ui.tableView3DProfiles.openPersistentEditor(idxExpr)
def onObservationClicked(self, plotDataItem, points):
for p in points:
tsd = p.data()
def clear(self):
def loadCoordinate(self, spatialPoints=None, LUT_bandIndices=None):
"""
Loads a temporal profile for a single or multiple geometries.
:param spatialPoints: SpatialPoint | [list-of-SpatialPoints]
"""
if not isinstance(self.plotSettingsModel2D, PlotSettingsModel2D):
#if not self.pixelLoader.isReadyToLoad():
# return False
assert isinstance(self.TS, TimeSeries)
#Get or create the TimeSeriesProfiles which will store the loaded values
tasks = []
TPs = []
theGeometries = []
# Define a which (new) bands need to be loaded for each sensor
if LUT_bandIndices is None:
LUT_bandIndices = dict()
for sensor in self.TS.Sensors:
LUT_bandIndices[sensor] = self.plotSettingsModel2D.requiredBandsIndices(sensor)
assert isinstance(LUT_bandIndices, dict)
for sensor in self.TS.Sensors:
assert sensor in LUT_bandIndices.keys()
#update new / existing points
if isinstance(spatialPoints, SpatialPoint):
spatialPoints = [spatialPoints]
for spatialPoint in spatialPoints:
assert isinstance(spatialPoint, SpatialPoint)
TP = self.tpCollection.fromSpatialPoint(spatialPoint)
if not isinstance(TP, TemporalProfile):
TP = TemporalProfile(self.TS, spatialPoint)
self.tpCollection.insertTemporalProfiles(TP, i=0)
if len(self.tpCollection) == 1:
if len(self.plotSettingsModel2D) == 0:
self.createNewPlotStyle2D()
if len(self.plotSettingsModel3D) == 0:
#todo: individual 3D style
pass
TPs.append(TP)
theGeometries.append(TP.mCoordinate)
TP_ids = [TP.mID for TP in TPs]
#each TSD is a Task
#a Task defines which bands are to be loaded
for tsd in self.TS:
#do not load from invisible TSDs
if not tsd.isVisible():
continue
#which bands do we need to load?
requiredIndices = set(LUT_bandIndices[tsd.sensor])
if len(requiredIndices) == 0:
continue
else:
s = ""
missingIndices = set()
for TP in TPs:
assert isinstance(TP, TemporalProfile)

benjamin.jakimow@geo.hu-berlin.de
committed
need2load = TP.missingBandIndices(tsd, requiredIndices=requiredIndices)
if len(missingIndices) > 0:
task = PixelLoaderTask(tsd.pathImg, theGeometries,
bandIndices=missingIndices,
temporalProfileIDs=TP_ids)
tasks.append(task)
if len(tasks) > 0:
aGoodDefault = 2 if len(self.TS) > 25 else 1
#self.pixelLoader.setNumberOfProcesses(SETTINGS.value('profileloader_threads', aGoodDefault))
if DEBUG:
print('Start loading for {} geometries from {} sources...'.format(
len(theGeometries), len(tasks)
))
self.pixelLoader.startLoading(tasks)
else:
if DEBUG:
print('Data for geometries already loaded')
if sensorView is None:
for sv in self.plotSettingsModel2D.items:
self.setData(sv)
else:
assert isinstance(sensorView, TemporalProfile2DPlotStyle)
self.setData2D(sensorView)
def onDataUpdate(self):
for plotSetting in self.plotSettingsModel2D:
assert isinstance(plotSetting, TemporalProfile2DPlotStyle)
tp = plotSetting.temporalProfile()
for pdi in plotSetting.mPlotItems:
assert isinstance(pdi, TemporalProfilePlotDataItem)
pdi.updateDataAndStyle()
if isinstance(tp, TemporalProfile) and plotSetting.temporalProfile().updated():

benjamin.jakimow@geo.hu-berlin.de
committed
plotSetting.temporalProfile().resetUpdatedFlag()
for i in self.plot2D.getPlotItem().dataItems:
i.updateItems()
notInit = [0, 1] == self.plot2D.getPlotItem().getAxis('bottom').range
if notInit:
for plotSetting in self.plotSettingsModel2D:
assert isinstance(plotSetting, TemporalProfile2DPlotStyle)
for pdi in plotSetting.mPlotItems:
assert isinstance(pdi, TemporalProfilePlotDataItem)
if pdi.xData.ndim == 0 or pdi.xData.shape[0] == 0:
continue
if x0 is None:
x0 = pdi.xData.min()
x1 = pdi.xData.max()
else:
x0 = min(pdi.xData.min(), x0)
x1 = max(pdi.xData.max(), x1)
if x0 is not None:
self.plot2D.getPlotItem().setXRange(x0, x1)
#self.plot2D.xAxisInitialized = True
@QtCore.pyqtSlot()
def updatePlot3D(self):
if OPENGL_AVAILABLE:
from pyqtgraph.opengl import GLViewWidget
from pyqtgraph.opengl.GLGraphicsItem import GLGraphicsItem
import pyqtgraph.opengl as gl
assert isinstance(self.plot3D, GLViewWidget)
# 1. ensure that data from all bands will be loaded
LUT_bandIndices = dict()
for sensor in self.TS.sensors():
assert isinstance(sensor, SensorInstrument)
LUT_bandIndices[sensor] = list(range(sensor.nb))
coordinates = []
for plotStyle3D in self.plotSettingsModel3D:
assert isinstance(plotStyle3D, TemporalProfile3DPlotStyle)
tp = plotStyle3D.temporalProfile()
if isinstance(tp, TemporalProfile):
coordinates.append(tp.mCoordinate)
if len(coordinates) > 0:
self.loadCoordinate(coordinates, LUT_bandIndices=LUT_bandIndices)
# 2. remove old plot items
# 3 add new plot items
for plotStyle3D in self.plotSettingsModel3D:
assert isinstance(plotStyle3D, TemporalProfile3DPlotStyle)
gli = plotStyle3D.createPlotItem(None)
if isinstance(gli, GLGraphicsItem):
# w.setBackgroundColor(QColor('black'))
# w.setCameraPosition(pos=(0.0, 0.0, 0.0), distance=1.)
#self.plot3D.addItem(self.ui.plotWidget3D.glGridItem)
self.plot3D.updateDataRanges()
self.plot3D.zoomToFull()
@QtCore.pyqtSlot()
def updatePlot2D(self):
if isinstance(self.plotSettingsModel2D, PlotSettingsModel2D):
pi = self.plot2D.getPlotItem()
piDataItems = pi.listDataItems()
for plotSetting in self.plotSettingsModel2D:
assert isinstance(plotSetting, TemporalProfile2DPlotStyle)
locations.add(plotSetting.temporalProfile().mCoordinate)
for pdi in plotSetting.mPlotItems:
assert isinstance(pdi, TemporalProfilePlotDataItem)
#for i in pi.dataItems:
# i.updateItems()
#self.plot2D.update()
#2. load pixel data
self.loadCoordinate(list(locations))
# https://github.com/pyqtgraph/pyqtgraph/blob/5195d9dd6308caee87e043e859e7e553b9887453/examples/customPlot.py
return
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
# prepare QGIS environment
if sys.platform == 'darwin':
PATH_QGS = r'/Applications/QGIS.app/Contents/MacOS'
os.environ['GDAL_DATA'] = r'/usr/local/Cellar/gdal/1.11.3_1/share'
else:
# assume OSGeo4W startup
PATH_QGS = os.environ['QGIS_PREFIX_PATH']
assert os.path.exists(PATH_QGS)
qgsApp = QgsApplication([], True)
QApplication.addLibraryPath(r'/Applications/QGIS.app/Contents/PlugIns')
QApplication.addLibraryPath(r'/Applications/QGIS.app/Contents/PlugIns/qgis')
qgsApp.setPrefixPath(PATH_QGS, True)
qgsApp.initQgis()
gb = QGroupBox()
gb.setTitle('Sandbox')
PL = PixelLoader()
if False:
files = ['observationcloud/testdata/2014-07-26_LC82270652014207LGN00_BOA.bsq',
'observationcloud/testdata/2014-08-03_LE72270652014215CUB00_BOA.bsq'
]
else:
from timeseriesviewer.utils import file_search
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
searchDir = r'H:\LandsatData\Landsat_NovoProgresso'
files = file_search(searchDir, '*227065*band4.img', recursive=True)
#files = files[0:3]
lyr = QgsRasterLayer(files[0])
coord = lyr.extent().center()
crs = lyr.crs()
l = QVBoxLayout()
btnStart = QPushButton()
btnStop = QPushButton()
prog = QProgressBar()
tboxResults = QPlainTextEdit()
tboxResults.setMaximumHeight(300)
tboxThreads = QPlainTextEdit()
tboxThreads.setMaximumHeight(200)
label = QLabel()
label.setText('Progress')
def showProgress(n,m,md):
prog.setMinimum(0)
prog.setMaximum(m)
prog.setValue(n)
info = []
for k, v in md.items():
info.append('{} = {}'.format(k,str(v)))
tboxResults.setPlainText('\n'.join(info))
#tboxThreads.setPlainText(PL.threadInfo())
qgsApp.processEvents()
PL.sigPixelLoaded.connect(showProgress)
btnStart.setText('Start loading')
btnStart.clicked.connect(lambda : PL.startLoading(files, coord, crs))
btnStop.setText('Cancel')
btnStop.clicked.connect(lambda: PL.cancelLoading())
lh = QHBoxLayout()
lh.addWidget(btnStart)
lh.addWidget(btnStop)
l.addLayout(lh)
l.addWidget(prog)
l.addWidget(tboxThreads)
l.addWidget(tboxResults)
gb.setLayout(l)
gb.show()
#rs.setBackgroundStyle('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #222, stop:1 #333);')
#rs.handle.setStyleSheet('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #282, stop:1 #393);')
qgsApp.exec_()
qgsApp.exitQgis()
if __name__ == '__main__':
import site, sys
qgsApp = utils.initQgisApplication(qgisDebug=True)
if False: #the ultimative test for floating point division correctness, at least on a DOY-level
date1 = np.datetime64('1960-12-31','D')
assert date1 == num2date(date2num(date1))
#1960 - 12 - 31
for year in range(1960, 2057):
for doy in range(1, daysPerYear(year)+1):
dt = datetime.timedelta(days=doy - 1)
date1 = np.datetime64('{}-01-01'.format(year)) + np.timedelta64(doy-1,'D')
date2 = datetime.date(year=year, month=1, day=1) + datetime.timedelta(days=doy-1)
assert date1 == num2date(date2num(date1), dt64=True), 'date1: {}'.format(date1)
assert date2 == num2date(date2num(date2), dt64=False), 'date2: {}'.format(date1)
STVis = SpectralTemporalVisualization(ui)
STVis.setTimeSeries(TS)
import example.Images
from timeseriesviewer import file_search
files = file_search(os.path.dirname(example.Images.__file__), '*.tif')
cpND = SpatialPoint(ext.crs(), 681151.214,-752388.476)
cp2 = SpatialPoint(ext.crs(), ext.center())
cp3 = SpatialPoint(ext.crs(), ext.center().x()+500, ext.center().y()+250)
STVis.loadCoordinate(cpND)
STVis.loadCoordinate(cp2)
STVis.loadCoordinate(cp3)
STVis.createNewPlotStyle2D()
def addProfile():
x0,y1 = ext.upperLeftPt()
x1,y0 = ext.lowerRightPt()
x = x0 + (x1 - x0) * np.random.sample()
y = y0 + (y1 - y0) * np.random.sample()
pt = SpatialPoint(ext.crs(), x, y)
STVis.loadCoordinate(pt)
btn = QPushButton('Add Profile')