Newer
Older
"""
Constructor of the widget
"""
super(DateTimePlotWidget, self).__init__(parent, viewBox=DateTimeViewBox())
axisItems={'bottom':DateTimeAxis(orientation='bottom')},
self.setCentralItem(self.plotItem)
self.xAxisInitialized = False
class PlotSettingsModel(QAbstractTableModel):
#sigSensorAdded = pyqtSignal(SensorPlotSettings)
sigVisibilityChanged = pyqtSignal(TemporalProfilePlotStyle)
sigDataChanged = pyqtSignal(TemporalProfilePlotStyle)
regBandKey = re.compile("(?<!\w)b\d+(?!\w)", re.IGNORECASE)
regBandKeyExact = re.compile('^' + regBandKey.pattern + '$', re.IGNORECASE)
def __init__(self, temporalProfileCollection, plotWidget, parent=None, *args):
#assert isinstance(tableView, QTableView)
super(PlotSettingsModel, self).__init__(parent=parent)
assert isinstance(temporalProfileCollection, TemporalProfileCollection)
self.cnID = 'ID'
self.cnSensor = 'sensor'
self.cnExpression = LABEL_DN
self.cnStyle = 'style'
self.cnTemporalProfile = 'px'
self.columNames = [self.cnTemporalProfile, self.cnSensor, self.cnStyle, self.cnExpression]
self.mPlotSettings = []
self.mPlotDataItems = []
#assert isinstance(plotWidget, DateTimePlotWidget)
self.mPlotWidget = plotWidget
self.sortColumnIndex = 0
self.sortOrder = Qt.AscendingOrder
assert isinstance(self.tpCollection.TS, TimeSeries)
#self.tpCollection.TS.sigSensorAdded.connect(self.addPlotItem)
#self.tpCollection.TS.sigSensorRemoved.connect(self.removeSensor)
self.sort(0, Qt.AscendingOrder)
self.dataChanged.connect(self.signaler)
def __iter__(self):
return iter(self.mPlotSettings)

benjamin.jakimow@geo.hu-berlin.de
committed
def __getitem__(self, slice):
return self.mPlotSettings[slice]
def __contains__(self, item):
return item in self.mPlotSettings
def testSlot(self, *args):
print(('TESTSLOT', args))
def columnIndex(self, name):
return self.columNames.index(name)
def signaler(self, idxUL, idxLR):
if idxUL.isValid():
plotStyle = self.idx2plotStyle(idxUL)
cname = self.columNames[idxUL.column()]
if cname in [self.cnSensor,self.cnStyle]:
self.sigVisibilityChanged.emit(plotStyle)
if cname in [self.cnExpression]:
self.sigDataChanged.emit(plotStyle)
def requiredBandsIndices(self, sensor):
"""
Returns the band indices required to calculate the values for
the different PlotStyle expressions making use of sensor
:param sensor: SensorInstrument for which the band indices are to be returned.
:return: [list-of-band-indices]
"""
bandIndices = set()
assert isinstance(sensor, SensorInstrument)
for p in [p for p in self.mPlotSettings if p.sensor() == sensor]:
assert isinstance(p, TemporalProfilePlotStyle)
expression = p.expression()
#remove leading & tailing "
bandKeys = PlotSettingsModel.regBandKey.findall(expression)
for bandIndex in [bandKey2bandIndex(key) for key in bandKeys]:

benjamin.jakimow@geo.hu-berlin.de
committed
def insertPlotStyles(self, plotStyles, i=None):
"""
Inserts PlotStyle
:param plotStyles: TemporalProfilePlotStyle | [list-of-TemporalProfilePlotStyle]
:param i: index to insert, defaults to the last list position
"""
if isinstance(plotStyles, TemporalProfilePlotStyle):
plotStyles = [plotStyles]
assert isinstance(plotStyles, list)
for plotStyle in plotStyles:
assert isinstance(plotStyle, TemporalProfilePlotStyle)

benjamin.jakimow@geo.hu-berlin.de
committed
self.beginInsertRows(QModelIndex(), i, i + len(plotStyles)-1)
for j, plotStyle in enumerate(plotStyles):
assert isinstance(plotStyle, TemporalProfilePlotStyle)
self.mPlotSettings.insert(i+j, plotStyle)
self.endInsertRows()
def removePlotStyles(self, plotStyles):
"""
Removes PlotStyle instances
:param plotStyles: TemporalProfilePlotStyle | [list-of-TemporalProfilePlotStyle]
"""
if isinstance(plotStyles, PlotStyle):
plotStyles = [plotStyles]
assert isinstance(plotStyles, list)
for plotStyle in plotStyles:
assert isinstance(plotStyle, PlotStyle)
if plotStyle in self.mPlotSettings:
idx = self.plotStyle2idx(plotStyle)
self.beginRemoveRows(QModelIndex(), idx.row(),idx.row())
self.mPlotSettings.remove(plotStyle)
self.endRemoveRows()
def sort(self, col, order):
if self.rowCount() == 0:
return
colName = self.columnames[col]
r = order != Qt.AscendingOrder
#self.beginMoveRows(idxSrc,
if colName == self.cnSensor:
self.mPlotSettings.sort(key = lambda sv:sv.sensor().name(), reverse=r)
elif colName == self.cnExpression:
self.mPlotSettings.sort(key=lambda sv: sv.expression(), reverse=r)
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()
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
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
columnName = self.columNames[index.column()]
plotStyle = self.idx2plotStyle(index)
if isinstance(plotStyle, TemporalProfilePlotStyle):
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:
value = plotStyle.temporalProfile().name()
#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))

benjamin.jakimow@geo.hu-berlin.de
committed
if value is None:
return False
result = False
plotStyle = self.idx2plotStyle(index)
if isinstance(plotStyle, TemporalProfilePlotStyle):
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'):
return
#todo
assert isinstance(sensorPlotSettings, TemporalProfilePlotStyle)
#todo: avoid dumps
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, TemporalProfilePlotStyle):
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)
self.stackedWidget.setCurrentWidget(self.page2D)
if OPENGL_AVAILABLE:
l = self.labelDummy3D.parentWidget().layout()
l.removeWidget(self.labelDummy3D)
from pyqtgraph.opengl import GLViewWidget
l.addWidget(self.plotWidget3D)
#pi = self.plotWidget2D.plotItem
#ax = DateAxis(orientation='bottom', showValues=True)
#pi.layout.addItem(ax, 3,2)
self.baseTitle = self.windowTitle()
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)
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
def date2sse(date): # returns seconds since epoch
if isinstance(date, np.datetime64):
date = date.astype(datetime.datetime)
return time.mktime(date.timetuple())
def sse2date(secondsSinceEpoch):
return time.localtime(secondsSinceEpoch)
def dateDOY(date):
if isinstance(date, np.datetime64):
date = date.astype(datetime.date)
return date.timetuple().tm_yday
def daysPerYear(year):
if isinstance(year, np.datetime64):
year = year.astype(datetime.date)
if isinstance(year, datetime.date):
year = year.timetuple().tm_year
return dateDOY(datetime.date(year=year, month=12, day=31))
def date2num(d):
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
#kindly taken from https://stackoverflow.com/questions/6451655/python-how-to-convert-datetime-dates-to-decimal-years
if isinstance(d, np.datetime64):
d = d.astype(datetime.datetime)
assert isinstance(d, datetime.date)
yearDuration = daysPerYear(d)
yearElapsed = d.timetuple().tm_yday
fraction = float(yearElapsed) / float(yearDuration)
return float(d.year) + fraction
def num2date(n, dt64=True):
n = float(n)
year = int(n)
fraction = n - year
yearDuration = daysPerYear(year)
yearElapsed = fraction * yearDuration
import math
doy = round(yearElapsed)
date = datetime.date(year, 1, 1) + datetime.timedelta(days=doy-1)
if dt64:
return np.datetime64(date)
else:
date
#return np.datetime64('{:04}-01-01'.format(year), 'D') + np.timedelta64(int(yearElapsed), 'D')
def depr_date2num(d):
d2 = d.astype(datetime.datetime)
o = d2.toordinal()
#assert d == num2date(o)
return o
if n < 1:
n = 1
return np.datetime64('{:04}-{:02}-{:02}'.format(d.year,d.month,d.day), 'D')
class TemporalProfile(QObject):
_mNextID = 0
@staticmethod
def nextID():
n = TemporalProfile._mNextID
TemporalProfile._mNextID += 1
return n
def __init__(self, timeSeries, spatialPoint):
super(TemporalProfile, self).__init__()
assert isinstance(spatialPoint, SpatialPoint)
self.mUpdated = False
self.mName = '#{}'.format(self.mID)
self.mLoaded = self.mLoadedMax = 0
self.initMetadata()
self.updateLoadingStatus()
def initMetadata(self):
for tsd in self.mTimeSeries:
assert isinstance(tsd, TimeSeriesDatum)
meta = {'doy':tsd.doy,
'date':str(tsd.date)}
sigNameChanged = pyqtSignal(str)
def setName(self, name):
if name != self.mName:
self.mName = name
self.sigNameChanged.emit(self.mName)
def name(self):
return self.mName
def plot(self):
import pyqtgraph as pg
for sensor in self.mTimeSeries.sensors():
assert isinstance(sensor, SensorInstrument)
plotStyle = TemporalProfilePlotStyle(self)
plotStyle.setSensor(sensor)
pi = TemporalProfilePlotDataItem(plotStyle)
pi.setClickable(True)
pw = pg.plot(title=self.name())
pw.getPlotItem().addItem(pi)
pi.setColor('green')
pg.QAPP.exec_()
assert isinstance(tsd, TimeSeriesDatum)
assert isinstance(values, dict)
if tsd not in self.mData.keys():
self.mData[tsd] = {}
self.mData[tsd].update(values)
self.updateLoadingStatus()
self.mUpdated = True
def resetUpdated(self):
self.mUpdated = False
def updated(self):
return self.mUpdated
def qgsFieldFromKeyValue(self, key, value):
t = type(value)
if t in [int, float] or np.isreal(value):
fLen = 0
fPrec = 0
fComm = ''
fType = ''
f = QgsField(key, QVariant.Double, 'double', 40, 5)
else:
f = QgsField(key, QVariant.String, 'text', 40, 5)
return f
def dataFromExpression(self, sensor, expression, dateType='date'):
assert dateType in ['date','doy']
x = []
y = []
if not isinstance(expression, QgsExpression):
expression = QgsExpression(expression)
assert isinstance(expression, QgsExpression)
expression = QgsExpression(expression)
fields = QgsFields()
sensorTSDs = sorted([tsd for tsd in self.mData.keys() if tsd.sensor == sensor])
for tsd in sensorTSDs:
data = self.mData[tsd]
for k, v in data.items():
if v is not None and fields.fieldNameIndex(k) == -1:
fields.append(self.qgsFieldFromKeyValue(k, v))
for i, tsd in enumerate(sensorTSDs):
assert isinstance(tsd, TimeSeriesDatum)
data = self.mData[tsd]
context = QgsExpressionContext()
scope = QgsExpressionContextScope()
f = QgsFeature()
f.setFields(fields)
f.setValid(True)
if v is None:
continue
idx = f.fieldNameIndex(k)
field = f.fields().field(idx)
if field.typeName() == 'text':
v = str(v)
else:
v = float(v)
scope.setFeature(f)
context.appendScope(scope)
#value = expression.evaluatePrepared(f)
value = expression.evaluate(context)
if value in [None, NULL]:
s = ""
else:
if dateType == 'date':
x.append(date2num(tsd.date))
elif dateType == 'doy':
x.append(tsd.doy)
y.append(value)
#return np.asarray(x), np.asarray(y)
return x, y
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
def data(self, tsd):
assert isinstance(tsd, TimeSeriesDatum)
if self.hasData(tsd):
return self.mData[tsd]
else:
return {}
def loadingStatus(self):
"""
Returns the loading status in terms of single pixel values.
nLoaded = sum of single band values
nLoadedMax = potential maximum of band values that might be loaded
:return: (nLoaded, nLoadedMax)
"""
return self.mLoaded, self.mLoadedMax
def updateLoadingStatus(self):
"""
Calculates and the loading status in terms of single pixel values.
nMax is the sum of all bands over each TimeSeriesDatum and Sensors
"""
self.mLoaded = self.mLoadedMax
for tsd in self.mTimeSeries:
assert isinstance(tsd, TimeSeriesDatum)
self.mLoadedMax += tsd.sensor.nb
if self.hasData(tsd):
self.mLoaded += len([k for k in self.mData[tsd].keys() if k.startswith('b')])
def hasData(self,tsd):
assert isinstance(tsd, TimeSeriesDatum)
return tsd in self.mData.keys()
def __repr__(self):
return 'TemporalProfile {}'.format(self.mCoordinate)
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
if DEBUG:
import timeseriesviewer.pixelloader
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.TV.setSortingEnabled(False)
self.plot2D = ui.plotWidget2D
self.plot2D.getPlotItem().getViewBox().sigMoveToDate.connect(self.sigMoveToDate)
self.plot2D.getPlotItem().getAxis('bottom').setLabel(LABEL_TIME)
self.plot2D.getPlotItem().getAxis('left').setLabel(LABEL_DN)
self.plot3D = ui.plotWidget3D
self.plot3D.setCameraPosition(distance=50)
## Add a grid to the view
if OPENGL_AVAILABLE:
import pyqtgraph.opengl as gl
self.glGridItem = gl.GLGridItem()
self.glGridItem.scale(2, 2, 1)
self.glGridItem.setDepthValue(10) # draw grid after surfaces since they may be translucent
self.glPlotDataItem = []
self.plot3D.addItem(self.glGridItem)
self.tpCollection = TemporalProfileCollection()
self.tpCollectionListModel = TemporalProfileCollectionListModel(self.tpCollection)
self.ui.tableViewTemporalProfiles.setModel(self.tpCollection)
self.ui.cbTemporalProfile3D.setModel(self.tpCollectionListModel)
#self.pxCollection.sigPixelAdded.connect(self.requestUpdate)
#self.pxCollection.sigPixelRemoved.connect(self.clear)
self.plotSettingsModel = None
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.sigMoveToDate.connect(self.onMoveToDate)
self.initActions()
def createNewPlotStyle(self):
l = len(self.tpCollection)
if l > 0:
temporalProfile = self.tpCollection[0]
plotStyle = TemporalProfilePlotStyle(temporalProfile)
plotStyle.sigExpressionUpdated.connect(self.updatePlot2D)
sensors = self.TS.Sensors.keys()
if len(sensors) > 0:
plotStyle.setSensor(sensors[0])
self.plotSettingsModel.insertPlotStyles([plotStyle])
pdi = plotStyle.createPlotItem(self.plot2D)
assert isinstance(pdi, TemporalProfilePlotDataItem)
self.plot2D.getPlotItem().addItem(pdi)
#self.plot2D.getPlotItem().addItem(pg.PlotDataItem(x=[1, 2, 3], y=[1, 2, 3]))
#plotItem.plot().sigPlotChanged.emit(plotItem)
self.updatePlot2D()
def initActions(self):
self.ui.btnAddView.setDefaultAction(self.ui.actionAddView)
self.ui.btnRemoveView.setDefaultAction(self.ui.actionRemoveView)
self.ui.btnRefresh2D.setDefaultAction(self.ui.actionRefresh2D)
self.ui.btnRefresh3D.setDefaultAction(self.ui.actionRefresh3D)
self.ui.actionRefresh2D.triggered.connect(self.updatePlot2D)
self.ui.actionRefresh3D.triggered.connect(self.updatePlot3D)
self.ui.actionAddView.triggered.connect(self.createNewPlotStyle)
#todo: self.ui.actionRemoveView.triggered.connect(self.plotSettingsModel.createPlotStyle)
def setTimeSeries(self, TS):
assert isinstance(TS, TimeSeries)
self.TS = TS
self.plotSettingsModel = PlotSettingsModel(self.tpCollection, self.plot2D, parent=self)
self.plotSettingsModel.sigVisibilityChanged.connect(self.setVisibility)
self.plotSettingsModel.sigDataChanged.connect(self.requestUpdate)
self.plotSettingsModel.rowsInserted.connect(self.onRowsInserted)
# self.plotSettingsModel.modelReset.connect(self.updatePersistantWidgets)
self.TV.setModel(self.plotSettingsModel)
self.delegate = PlotSettingsWidgetDelegate(self.TV, self.TS, self.tpCollectionListModel)
self.delegate.setItemDelegates(self.TV)
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)
if DEBUG:
print(t)
# QgsApplication.processEvents()
def requestUpdate(self, *args):
self.updateRequested = True
#next time
def updatePersistentWidgets(self):

benjamin.jakimow@geo.hu-berlin.de
committed
model = self.TV.model()
if isinstance(model, PlotSettingsModel):
colExpression = model.columnIndex(model.cnExpression)
colStyle = model.columnIndex(model.cnStyle)

benjamin.jakimow@geo.hu-berlin.de
committed
for row in range(model.rowCount()):
idxExpr = model.createIndex(row, colExpression)
idxStyle = model.createIndex(row, colStyle)
#self.TV.openPersistentEditor(idxExpr)
#self.TV.openPersistentEditor(idxStyle)

benjamin.jakimow@geo.hu-berlin.de
committed
#self.TV.openPersistentEditor(model.createIndex(start, colStyle))
s = ""
def onRowsInserted(self, parent, start, end):
model = self.TV.model()
if isinstance(model, PlotSettingsModel):
colExpression = model.columnIndex(model.cnExpression)
colStyle = model.columnIndex(model.cnStyle)
while start <= end:
idxExpr = model.createIndex(start, colExpression)
idxStyle = model.createIndex(start, colStyle)
self.TV.openPersistentEditor(idxExpr)
self.TV.openPersistentEditor(idxStyle)
start += 1
#self.TV.openPersistentEditor(model.createIndex(start, colStyle))
s = ""
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.plotSettingsModel, PlotSettingsModel):
return False
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.plotSettingsModel.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)
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)
existingBandKeys = [k for k in TP.data(tsd).keys() if PlotSettingsModel.regBandKeyExact.search(k)]
existingBandIndices = set([bandKey2bandIndex(k) for k in existingBandKeys])
need2load = requiredIndices.difference(existingBandIndices)
missingIndices = missingIndices.union(need2load)
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, TemporalProfilePlotStyle)
self.setVisibility2D(sensorPlotStyle)
def setVisibility2D(self, sensorPlotStyle):
self.plot2D.update()
if sensorView is None:
for sv in self.plotSettingsModel.items:
self.setData(sv)
else:
assert isinstance(sensorView, TemporalProfilePlotStyle)
self.setData2D(sensorView)
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
def onDataUpdate(self):
for plotSetting in self.plotSettingsModel:
assert isinstance(plotSetting, TemporalProfilePlotStyle)
if plotSetting.temporalProfile().updated():
for pdi in plotSetting.mPlotItems:
assert isinstance(pdi, TemporalProfilePlotDataItem)
pdi.updateDataAndStyle()
plotSetting.temporalProfile().resetUpdated()
for i in self.plot2D.getPlotItem().dataItems:
i.updateItems()
if not self.plot2D.xAxisInitialized:
x0 = x1 = None
for plotSetting in self.plotSettingsModel:
assert isinstance(plotSetting, TemporalProfilePlotStyle)
for pdi in plotSetting.mPlotItems:
assert isinstance(pdi, TemporalProfilePlotDataItem)
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: