-
Benjamin Jakimow authoredBenjamin Jakimow authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
sensorvisualization.py 10.96 KiB
# -*- coding: utf-8 -*-
"""
/***************************************************************************
EO Time Series Viewer
-------------------
begin : 2015-08-20
git sha : $Format:%H$
copyright : (C) 2017 by HU-Berlin
email : benjamin.jakimow@geo.hu-berlin.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
# noinspection PyPep8Naming
import sys, os
from qgis.core import *
from qgis.gui import *
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *
from eotimeseriesviewer.timeseries import TimeSeries, SensorInstrument, TimeSeriesDate, TimeSeriesSource
from eotimeseriesviewer.utils import loadUI
class SensorDockUI(QgsDockWidget, loadUI('sensordock.ui')):
def __init__(self, parent=None):
super(SensorDockUI, self).__init__(parent)
self.setupUi(self)
self.TS = None
def setTimeSeries(self, timeSeries):
from eotimeseriesviewer.timeseries import TimeSeries
from eotimeseriesviewer.sensorvisualization import SensorTableModel
assert isinstance(timeSeries, TimeSeries)
self.TS = timeSeries
self.mSensorModel = SensorTableModel(self.TS)
self.mSortedModel = QSortFilterProxyModel()
self.mSortedModel.setSourceModel(self.mSensorModel)
self.sensorView.setModel(self.mSortedModel)
self.sensorView.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
s = ""
class SensorTableModel(QAbstractTableModel):
def __init__(self, TS, parent=None, *args):
super(SensorTableModel, self).__init__()
assert isinstance(TS, TimeSeries)
# define column names
self.mCN_Name = "Name"
self.mCN_Band = "Band"
self.mCN_Dates = "Dates"
self.mCN_Images = "Images"
self.mCN_WL = "Wavelength"
self.mCN_ID = "ID"
self.mColumNames = [self.mCN_Name, self.mCN_Band, self.mCN_Dates, self.mCN_Images,
self.mCN_WL, self.mCN_ID]
self.TS = TS
self.TS.sigSensorAdded.connect(self.addSensor)
self.TS.sigSensorRemoved.connect(self.removeSensor)
self.TS.sigTimeSeriesDatesAdded.connect(self.onTimeSeriesSourceChanges)
self.TS.sigTimeSeriesDatesRemoved.connect(self.onTimeSeriesSourceChanges)
self.mSensors = []
for s in self.TS.sensors():
self.addSensor(s)
def onTimeSeriesSourceChanges(self, timeSeriesDates:list):
"""
Reaction on changes in the time series data sources
:param timeSeriesDates: list
"""
sensors = set()
for tsd in timeSeriesDates:
assert isinstance(tsd, TimeSeriesDate)
sensors.add(tsd.sensor())
for sensor in sensors:
self.updateSensor(sensor)
def addSensor(self, sensor:SensorInstrument):
"""
Adds a sensor
:param sensor: SensorInstrument
"""
assert isinstance(sensor, SensorInstrument)
i = self.rowCount()
self.beginInsertRows(QModelIndex(),i,i)
self.mSensors.append(sensor)
sensor.sigNameChanged.connect(lambda *args, sensor=sensor: self.updateSensor(sensor))
self.endInsertRows()
def updateSensor(self, sensor:SensorInstrument):
assert isinstance(sensor, SensorInstrument)
if sensor in self.mSensors:
tl = self.getIndexFromSensor(sensor)
br = self.createIndex(tl.row(), self.columnCount()-1)
self.dataChanged.emit(tl, br)
def removeSensor(self, sensor:SensorInstrument):
"""
Removes a SensorInstrument
:param sensor: SensorInstrument
"""
assert isinstance(sensor, SensorInstrument)
if sensor in self.mSensors:
i = self.mSensors.index(sensor)
self.beginRemoveRows(QModelIndex(), i, i)
self.mSensors.remove(sensor)
self.endRemoveRows()
def rowCount(self, parent = QModelIndex()):
return len(self.mSensors)
def removeRows(self, row, count , parent=QModelIndex()):
self.beginRemoveRows(parent, row, row+count-1)
toRemove = self.mSensors[row:row + count]
for tsd in toRemove:
self.mSensors.remove(tsd)
self.endRemoveRows()
def getIndexFromSensor(self, sensor)->QModelIndex:
return self.createIndex(self.mSensors.index(sensor), 0)
def getSensorFromIndex(self, index)->SensorInstrument:
if index.isValid():
return self.mSensors[index.row()]
return None
def columnCount(self, parent = QModelIndex()):
return len(self.mColumNames)
def data(self, index, role = Qt.DisplayRole):
if role is None or not index.isValid():
return None
value = None
columnName = self.mColumNames[index.column()]
sensor = self.getSensorFromIndex(index)
assert isinstance(sensor, SensorInstrument)
if role in [Qt.DisplayRole, Qt.EditRole]:
if columnName == self.mCN_Name:
value = sensor.name()
elif columnName == self.mCN_Band:
value = str(sensor.nb)
elif columnName == self.mCN_Images:
n = 0
for tsd in self.TS.tsds(sensor=sensor):
assert isinstance(tsd, TimeSeriesDate)
n += len(tsd.sources())
value = n
elif columnName == self.mCN_Dates:
value = len(self.TS.tsds(sensor=sensor))
elif columnName == self.mCN_ID:
value = sensor.id()
elif columnName == self.mCN_WL:
if sensor.wl is None or sensor.wl.ndim == 0:
value = 'undefined'
else:
value = ','.join([str(w) for w in sensor.wl])
if sensor.wlu is not None:
value += '[{}]'.format(sensor.wlu)
elif role == Qt.CheckStateRole:
if columnName == self.mCN_Name:
value = None
elif role == Qt.UserRole:
value = sensor
return value
def setData(self, index, value, role=None):
if role is None or not index.isValid():
return None
columnName = self.mColumNames[index.column()]
sensor = self.getSensorFromIndex(index)
assert isinstance(sensor, SensorInstrument)
b = False
if role == Qt.EditRole and columnName == self.mCN_Name:
if len(value) == 0: #do not accept empty strings
b = False
else:
sensor.setName(str(value))
b = True
#data changed will be emitted via signal from sensor in updateSensor
return b
def flags(self, index):
if index.isValid():
columnName = self.mColumNames[index.column()]
flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
if columnName in [self.mCN_Name]: #allow check state
flags = flags | Qt.ItemIsUserCheckable | Qt.ItemIsEditable
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.mColumNames[col]
elif orientation == Qt.Vertical and role == Qt.DisplayRole:
return col + 1
return None
class SensorListModel(QAbstractListModel):
def __init__(self, TS, parent=None, *args):
super(SensorListModel, self).__init__()
assert isinstance(TS, TimeSeries)
self.TS = TS
self.TS.sigSensorAdded.connect(self.insertSensor)
self.TS.sigSensorRemoved.connect(self.removeSensor)
self.mSensors = []
self.sortColumnIndex = 0
self.sortOrder = Qt.AscendingOrder
for s in self.TS.sensors():
self.insertSensor(s)
def insertSensor(self, sensor, i=None):
assert isinstance(sensor, SensorInstrument)
if i is None:
i = len(self.mSensors)
self.beginInsertRows(QModelIndex(), i, i)
self.mSensors.insert(i, sensor)
self.endInsertRows()
def removeSensor(self, sensor):
assert isinstance(sensor, SensorInstrument)
if sensor in self.mSensors:
i = self.mSensors.index(sensor)
self.beginRemoveRows(QModelIndex(), i, i)
self.mSensors.remove(sensor)
self.endRemoveRows()
def sort(self, col, order):
if self.rowCount() == 0:
return
self.layoutAboutToBeChanged.emit()
r = order != Qt.AscendingOrder
self.mSensors.sort(key = lambda s:s.name(), reverse=r)
self.layoutChanged.emit()
def rowCount(self, parent = QModelIndex()):
return len(self.mSensors)
def removeRows(self, row, count , parent=QModelIndex()):
self.beginRemoveRows(parent, row, row+count-1)
toRemove = self.mSensors[row:row + count]
for tsd in toRemove:
self.mSensors.remove(tsd)
self.endRemoveRows()
def sensor2idx(self, sensor):
assert isinstance(sensor, SensorInstrument)
return self.createIndex(self.mSensors.index(sensor), 0)
def idx2sensor(self, index):
assert isinstance(index, QModelIndex)
if index.isValid():
return self.mSensors[index.row()]
return None
def data(self, index, role = Qt.DisplayRole):
if role is None or not index.isValid():
return None
value = None
sensor = self.idx2sensor(index)
assert isinstance(sensor, SensorInstrument)
if role == Qt.DisplayRole:
value = sensor.name()
elif role == Qt.UserRole:
value = sensor
return value
def flags(self, index):
if index.isValid():
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