Skip to content
Snippets Groups Projects
temporalprofiles.py 43.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
            self.mcnID = 'id'
            self.mcnCoordinate = 'Coordinate'
            self.mcnLoaded = 'Loading'
            self.mcnName = 'Name'
            self.mColumNames = [self.mcnName, self.mcnLoaded, self.mcnCoordinate]
    
            crs = QgsCoordinateReferenceSystem('EPSG:4862')
            uri = 'Point?crs={}'.format(crs.authid())
    
            self.TS = None
    
            self.mLocations = QgsVectorLayer(uri, 'LOCATIONS', 'memory')
    
            self.mTemporalProfiles = []
            self.mTPLookupSpatialPoint = {}
            self.mTPLookupID = {}
            self.mCurrentTPID = 0
            self.mMaxProfiles = 10
    
            self.nextID = 0
    
        def __len__(self):
            return len(self.mTemporalProfiles)
    
        def __iter__(self):
            return iter(self.mTemporalProfiles)
    
        def __getitem__(self, slice):
            return self.mTemporalProfiles[slice]
    
        def __contains__(self, item):
            return item in self.mTemporalProfiles
    
        def rowCount(self, parent=None, *args, **kwargs):
            return len(self.mTemporalProfiles)
    
        def columnCount(self, QModelIndex_parent=None, *args, **kwargs):
            return len(self.mColumNames)
    
        def idx2tp(self, index):
            if index.isValid() and index.row() < len(self.mTemporalProfiles) :
                return self.mTemporalProfiles[index.row()]
            return None
    
        def tp2idx(self, temporalProfile):
            assert isinstance(temporalProfile, TemporalProfile)
    
            if temporalProfile in self.mTemporalProfiles:
                row = self.mTemporalProfiles.index(temporalProfile)
                return self.createIndex(row, 0)
            else:
                return QModelIndex()
    
        def data(self, index, role = Qt.DisplayRole):
            if role is None or not index.isValid():
                return None
    
            value = None
            columnName = self.mColumNames[index.column()]
            TP = self.idx2tp(index)
            if not isinstance(TP, TemporalProfile):
                return None
            #self.mColumNames = ['id','coordinate','loaded']
            if role == Qt.DisplayRole:
                if columnName == self.mcnID:
                    value = TP.mID
                elif columnName == self.mcnName:
                    value = TP.name()
                elif columnName == self.mcnCoordinate:
                    value = '{}'.format(TP.mCoordinate)
                elif columnName == self.mcnLoaded:
                    nIs, nMax = TP.loadingStatus()
                    if nMax > 0:
                        value = '{}/{} ({:0.2f} %)'.format(nIs, nMax, float(nIs) / nMax * 100)
            elif role == Qt.EditRole:
                if columnName == self.mcnName:
                    value = TP.name()
            elif role == Qt.ToolTipRole:
                if columnName == self.mcnID:
                    value = 'ID Temporal Profile'
                elif columnName == self.mcnName:
                    value = TP.name()
                elif columnName == self.mcnCoordinate:
                    value = '{}'.format(TP.mCoordinate)
                elif columnName == self.mcnLoaded:
                    nIs, nMax = TP.loadingStatus()
                    value = '{}'.format(TP.mCoordinate)
            elif role == Qt.UserRole:
                value = TP
    
            return value
    
        def flags(self, index):
            if index.isValid():
                flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
    
                cName = self.mColumNames[index.column()]
                if cName == self.mcnName:
                    flags = flags | Qt.ItemIsEditable
    
                return flags
                #return item.qt_flags(index.column())
            return None
    
    
        def setData(self, index, value, role=None):
            if role is None or not index.isValid():
                return None
    
            cName = self.mColumNames[index.column()]
            TP = self.idx2tp(index)
            if isinstance(TP, TemporalProfile):
                if role == Qt.EditRole and cName == self.mcnName:
                    if len(value) == 0: #do not accept empty strings
                        return False
                    else:
                        TP.setName(value)
                    return True
    
            return False
    
        def headerData(self, col, orientation, role):
            if Qt is None:
                return None
            if role == Qt.DisplayRole:
                if orientation == Qt.Horizontal:
                    return self.mColumNames[col]
                elif orientation == Qt.Vertical:
                    return col
            return None
    
        def insertTemporalProfiles(self, temporalProfiles, i=None):
            if isinstance(temporalProfiles, TemporalProfile):
                temporalProfiles = [temporalProfiles]
    
            assert isinstance(temporalProfiles, list)
            for temporalProfile in temporalProfiles:
                assert isinstance(temporalProfile, TemporalProfile)
    
            if i is None:
                i = len(self.mTemporalProfiles)
    
    
            temporalProfiles = [t for t in temporalProfiles if t not in self]
            l = len(temporalProfiles)
    
            if l > 0:
    
                #remove older profiles
                self.prune(nMax=self.mMaxProfiles - l)
    
                self.beginInsertRows(QModelIndex(), i, i + l - 1)
    
                for temporalProfile in temporalProfiles:
                    assert isinstance(temporalProfile, TemporalProfile)
                    id = self.nextID
                    self.nextID += 1
                    temporalProfile.mID = id
                    self.mTemporalProfiles.insert(i, temporalProfile)
                    self.mTPLookupID[id] = temporalProfile
                    self.mTPLookupSpatialPoint[temporalProfile.mCoordinate] = temporalProfile
                    i += 1
                self.endInsertRows()
    
                self.sigTemporalProfilesAdded.emit(temporalProfiles)
    
    
        def temporalProfileFromGeometry(self, geometry):
            if geometry in self.mTPLookupSpatialPoint.keys():
                return self.mTPLookupSpatialPoint[geometry]
            else:
                return None
    
        def temporalProfileFromID(self, id):
            if id in self.mTPLookupID.keys():
                return self.mTPLookupID[id]
            else:
                return None
    
        def id(self, temporalProfile):
            """
            Returns the id of an TemporalProfile
            :param temporalProfile: TemporalProfile
            :return: id or None, inf temporalProfile is not part of this collections
            """
    
            for k, tp in self.mTPLookupID.items():
                if tp == temporalProfile:
                    return k
            return None
    
        def fromID(self, id):
    
            if id in self.mTPLookupID:
    
                return self.mTPLookupID[id]
            else:
                return None
    
        def fromSpatialPoint(self, spatialPoint):
    
            if spatialPoint in self.mTPLookupSpatialPoint:
    
                return self.mTPLookupSpatialPoint[spatialPoint]
            else:
                return None
    
        def removeTemporalProfiles(self, temporalProfiles):
            """
            Removes temporal profiles from this collection
            :param temporalProfile: TemporalProfile
            """
    
            if isinstance(temporalProfiles, TemporalProfile):
                temporalProfiles = [temporalProfiles]
            assert isinstance(temporalProfiles, list)
    
            temporalProfiles = [tp for tp in temporalProfiles if isinstance(tp, TemporalProfile) and tp in self.mTemporalProfiles]
    
            if len(temporalProfiles) > 0:
    
                def deleteFromDict(d, value):
                    assert isinstance(d, dict)
                    if value in d.values():
                        key = d.keys()[d.values().index(value)]
                        d.pop(key)
    
                for temporalProfile in temporalProfiles:
                    assert isinstance(temporalProfile, TemporalProfile)
                    idx = self.tp2idx(temporalProfile)
                    row = idx.row()
                    self.beginRemoveRows(QModelIndex(), row, row)
                    self.mTemporalProfiles.remove(temporalProfile)
    
                    deleteFromDict(self.mTPLookupID, temporalProfile)
                    deleteFromDict(self.mTPLookupSpatialPoint,  temporalProfile)
    
                    self.endRemoveRows()
                self.sigTemporalProfilesRemoved.emit(temporalProfiles)
    
    
        def connectTimeSeries(self, timeSeries):
            self.clear()
    
            if isinstance(timeSeries, TimeSeries):
                self.TS = timeSeries
                #for sensor in self.TS.Sensors:
                #    self.addSensor(sensor)
                #self.TS.sigSensorAdded.connect(self.addSensor)
                #self.TS.sigSensorRemoved.connect(self.removeSensor)
            else:
                self.TS = None
    
        def setMaxProfiles(self, n):
            """
            Sets the maximum number of temporal profiles to be stored in this container.
            :param n: number of profiles, must be >= 1
            """
            old = self.mMaxProfiles
    
            assert n >= 1
            if old != n:
                self.mMaxProfiles = n
    
                self.prune()
                self.sigMaxProfilesChanged.emit(self.mMaxProfiles)
    
    
    
        def prune(self, nMax=None):
    
            """
            Reduces the number of temporal profile to the value n defined with .setMaxProfiles(n)
            :return: [list-of-removed-TemporalProfiles]
            """
    
            if nMax is None:
                nMax = self.mMaxProfiles
    
            nMax = max(nMax, 0)
    
            toRemove = len(self) - nMax
            if toRemove > 0:
                toRemove = sorted(self[:], key=lambda p:p.mID)[0:toRemove]
                self.removeTemporalProfiles(toRemove)
    
    
    
    
    
    
        def getFieldDefn(self, name, values):
            if isinstance(values, np.ndarray):
                # add bands
                if values.dtype in [np.int8, np.int16, np.int32, np.int64,
                                    np.uint8, np.uint16, np.uint32, np.uint64]:
                    fType = QVariant.Int
                    fTypeName = 'integer'
                elif values.dtype in [np.float16, np.float32, np.float64]:
                    fType = QVariant.Double
                    fTypeName = 'decimal'
            else:
                raise NotImplementedError()
    
            return QgsField(name, fType, fTypeName)
    
        def setFeatureAttribute(self, feature, name, value):
            assert isinstance(feature, QgsFeature)
            assert isinstance(name, str)
    
            i = feature.indexFromName(name)
    
            assert i >= 0, 'Field "{}" does not exist'.format(name)
            field = feature.fields()[i]
            if field.isNumeric():
                if field.type() == QVariant.Int:
                    value = int(value)
                elif field.type() == QVariant.Double:
                    value = float(value)
                else:
                    raise NotImplementedError()
            feature.setAttribute(i, value)
    
        def sort(self, col, order):
            if self.rowCount() == 0:
                return
    
            self.layoutAboutToBeChanged.emit()
            colName = self.mColumNames[col]
            r = order != Qt.AscendingOrder
    
            if colName == self.mcnName:
                self.items.sort(key = lambda TP:TP.name(), reverse=r)
            elif colName == self.mcnCoordinate:
                self.items.sort(key=lambda TP: str(TP.mCoordinate), reverse=r)
            elif colName == self.mcnID:
                self.items.sort(key=lambda TP: TP.mID, reverse=r)
            elif colName == self.mcnLoaded:
                self.items.sort(key=lambda TP: TP.loadingStatus(), reverse=r)
            self.layoutChanged.emit()
    
    
        def addPixelLoaderResult(self, d):
            assert isinstance(d, PixelLoaderTask)
            if d.success():
    
                for TPid in d.temporalProfileIDs:
    
                    TP = self.temporalProfileFromID(TPid)
    
                    assert isinstance(TP, TemporalProfile)
                    TP.pullDataUpdate(d)
    
    
        def clear(self):
            #todo: remove TS Profiles
            #self.mTemporalProfiles.clear()
            #self.sensorPxLayers.clear()
            pass
    
    
    
    class TemporalProfileCollectionListModel(QAbstractListModel):
    
    
        def __init__(self, temporalProfileCollection, *args, **kwds):
    
            super(TemporalProfileCollectionListModel, self).__init__(*args, **kwds)
            assert isinstance(temporalProfileCollection, TemporalProfileCollection)
    
            self.mTPColl = temporalProfileCollection
            self.mTPColl.rowsAboutToBeInserted.connect(self.rowsAboutToBeInserted)
            self.mTPColl.rowsInserted.connect(self.rowsInserted.emit)
            #self.mTPColl.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved)
            self.mTPColl.rowsRemoved.connect(lambda : self.modelReset.emit())
    
    
        def idx2tp(self, *args, **kwds):
            return self.mTPColl.idx2tp(*args, **kwds)
    
        def tp2idx(self, *args, **kwds):
            return self.mTPColl.tp2idx(*args, **kwds)
    
        def flags(self, index):
            if index.isValid():
                flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
                return flags
                #return item.qt_flags(index.column())
            return Qt.NoItemFlags
    
        def rowCount(self, *args, **kwds):
            return self.mTPColl.rowCount(*args, **kwds)
    
    
        def data(self, index, role=Qt.DisplayRole):
            if role is None or not index.isValid():
                return None
    
    
    
            TP = self.mTPColl.idx2tp(index)
            value = None
            if isinstance(TP, TemporalProfile):
                if role == Qt.DisplayRole:
                    value = '{}'.format(TP.name())
                elif role == Qt.ToolTipRole:
                    value = '#{} "{}" {}'.format(TP.mID, TP.name(), TP.mCoordinate)
                elif role == Qt.UserRole:
                    value = TP
    
            return value