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.columNames[index.column()]
plotStyle = self.idx2plotStyle(index)
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))
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():
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.pixelLoader = PixelLoader()
self.pixelLoader.sigPixelLoaded.connect(self.onPixelLoaded)
self.pixelLoader.sigLoadingStarted.connect(lambda: self.ui.progressInfo.setText('Start loading...'))
self.plot_initialized = False
self.ui.tableView2DProfiles.setSortingEnabled(False)
self.ui.tableView2DProfiles.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)

benjamin.jakimow@geo.hu-berlin.de
committed
# self.mSelectionModel.currentChanged.connect(self.onCurrentSelectionChanged)
self.plot2D = ui.plotWidget2D
self.plot2D.getViewBox().sigMoveToDate.connect(self.sigMoveToDate)
self.plot3D = ui.plotWidget3D
## Add a grid to the view
if OPENGL_AVAILABLE:
import pyqtgraph.opengl as gl
self.glGridItem = gl.GLGridItem()
self.glGridItem.setDepthValue(10) # draw grid after surfaces since they may be translucent
self.glPlotDataItems = [self.glGridItem]
self.plot3D.addItem(self.glGridItem)
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)
#self.ui.cbTemporalProfile3D.setModel(self.tpCollectionListModel)
#self.pxCollection.sigPixelAdded.connect(self.requestUpdate)
#self.pxCollection.sigPixelRemoved.connect(self.clear)
self.pixelLoader.sigLoadingStarted.connect(self.clear)
self.pixelLoader.sigLoadingFinished.connect(lambda : self.plot2D.enableAutoRange('x', False))
# self.VIEW.setItemDelegateForColumn(3, PointStyleDelegate(self.VIEW))
self.plotData2D = dict()
self.plotData3D = dict()
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
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
def removePlotStyles(self, plotStyles):
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
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
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)
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.removePlotStyles(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
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
from timeseriesviewer.temporalprofiles import saveTemporalProfiles
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.setCameraPosition((0,0,0), distance=10, elevation=10)
assert isinstance(TS, TimeSeries)
self.TS = TS
self.plotSettingsModel2D = PlotSettingsModel2D(self.tpCollection, self.plot2D, parent=self)
self.plotSettingsModel2D.sigVisibilityChanged.connect(self.setVisibility)
self.plotSettingsModel2D.sigDataChanged.connect(self.requestUpdate)
self.plotSettingsModel2D.rowsInserted.connect(self.onRowsInserted2D)
# self.plotSettingsModel.modelReset.connect(self.updatePersistantWidgets)
self.ui.tableView2DProfiles.setModel(self.plotSettingsModel2D)
self.ui.tableView2DProfiles.selectionModel().selectionChanged.connect(self.onPlot2DSelectionChanged)
self.delegateTableView2D = PlotSettingsModel2DWidgetDelegate(self.ui.tableView2DProfiles, self.TS, self.tpCollectionListModel)
self.delegateTableView2D.setItemDelegates(self.ui.tableView2DProfiles)
self.plotSettingsModel3D = PlotSettingsModel3D()
self.plotSettingsModel3D.connectTimeSeries(self.TS)
self.plotSettingsModel3D.rowsInserted.connect(self.onRowsInserted3D)
self.ui.tableView3DProfiles.setModel(self.plotSettingsModel3D)
self.ui.tableView3DProfiles.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
#self.tableView2DProfilesSelectionModel.selectionChanged.connect(self.onPlot2DSelectionChanged)
#self.tableView2DProfilesSelectionModel.setSelectionModel(self.mSelectionModel)
self.delegateTableView3D = PlotSettingsModel3DWidgetDelegate(self.ui.tableView3DProfiles, self.TS, self.tpCollectionListModel)
self.delegateTableView3D.setItemDelegates(self.ui.tableView3DProfiles)
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):
colStyle = model.columnIndex(model.cnStyle)
while start <= end:
idxStyle = model.createIndex(start, colStyle)
self.ui.tableView3DProfiles.openPersistentEditor(idxStyle)
start += 1
def onObservationClicked(self, plotDataItem, points):
for p in points:
tsd = p.data()
def clear(self):
#first remove from pixelCollection
self.plotData2D.clear()
self.plotData3D.clear()
pi = self.plot2D.getPlotItem()
plotItems = pi.listDataItems()
for p in plotItems:
p.clear()
p.update()
if len(self.TS) > 0:
rng = [self.TS[0].date, self.TS[-1].date]
rng = [date2num(d) for d in rng]
self.plot2D.getPlotItem().setRange(xRange=rng)
if self.plot3D:
pass
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')
def setVisibility(self, sensorPlotStyle):
assert isinstance(sensorPlotStyle, TemporalProfile2DPlotStyle)
self.setVisibility2D(sensorPlotStyle)
def setVisibility2D(self, sensorPlotStyle):
self.plot2D.update()
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)
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
# 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
for gli in self.glPlotDataItems:
if gli in self.plot3D.items:
self.plot3D.removeItem(gli)
del self.glPlotDataItems[:]
# 3 add new plot items
for plotStyle3D in self.plotSettingsModel3D:
assert isinstance(plotStyle3D, TemporalProfile3DPlotStyle)
gli = plotStyle3D.createPlotItem(None)
if isinstance(gli, GLGraphicsItem):
self.glPlotDataItems.append(gli)
for i, item in enumerate(self.glPlotDataItems):
self.plot3D.addItem(item)
# self.glGridItem.scale(0.1,0.1,0.1, local=False)
# w.setBackgroundColor(QColor('black'))
# w.setCameraPosition(pos=(0.0, 0.0, 0.0), distance=1.)
self.plot3D.addItem(self.glGridItem)
self.plot3D.update()
@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
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
# 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
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
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
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
from timeseriesviewer import utils
qgsApp = utils.initQgisApplication()
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)