Commit 89979e62 authored by Benjamin Jakimow's avatar Benjamin Jakimow
Browse files

added mimedata.py

refactoring (import statements)
parent 6ae49c21
[general]
name=EO Time Series Viewer
description=A QGIS Plugin to visualize multi-sensor remote-sensing time-series data.
version=0.5.201805141051
version=0.5.201805141058
qgisMinimumVersion=3.0
author=Benjamin Jakimow, Geomatics Lab, Humboldt-Universität zu Berlin
about=The EO Time Series Viewer is developed at Humboldt-Universität zu Berlin. Born in the SenseCarbon project, it was funded by the German Aerospace Centre (DLR) and granted by the Federal Ministry of Education and Research (BMBF, grant no. 50EE1254). Since 2017 it is developed under contract by the German Research Centre for Geosciences (GFZ) as part of the EnMAP Core Science Team activities (www.enmap.org), funded by DLR and granted by the Federal Ministry of Economic Affairs and Energy (BMWi, grant no. 50EE1529).
......
......@@ -23,7 +23,7 @@
import os, sys, fnmatch, site, re, site
VERSION = '0.5.201805141051'
VERSION = '0.5.201805141058'
LICENSE = 'GNU GPL-3'
TITLE = 'EO Time Series Viewer'
DESCRIPTION = 'A QGIS Plugin to visualize multi-sensor remote-sensing time-series data.'
......
......@@ -23,46 +23,13 @@ import os, collections
import numpy as np
from qgis.core import *
from qgis.gui import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *
from timeseriesviewer.utils import loadUI, SpatialExtent, SpatialPoint, createCRSTransform, geo2px
from timeseriesviewer.trees import *
class LoadWorker(QObject):
sigValueLoaded = pyqtSignal(str, dict)
sigLoadingStarted = pyqtSignal(int)
sigLoadingFinished = pyqtSignal()
def __init__(self, parent=None):
super(LoadWorker, self).__init__(parent)
def doWork(self, theUris, thePointWkt, theCrsDefinition):
spatialPoint = QgsGeometry.fromWkt(thePointWkt)
assert spatialPoint.wkbType() == QgsWKBTypes.Point
crs = QgsCoordinateReferenceSystem(theCrsDefinition)
assert isinstance(crs, QgsCoordinateReferenceSystem)
if len(theUris) > 0:
self.sigLoadingStarted.emit(len(theUris))
for uri in theUris:
values = CursorLocationValues.fromDataSource(spatialPoint, uri)
#values might be expressed as dict or list
self.sigValueLoaded.emit(uri, values)
self.sigLoadingFinished.emit()
class SourceValueSet(object):
def __init__(self, source, crs, geoCoordinate):
assert isinstance(geoCoordinate, QgsPointXY)
......
from qgis.core import *
from qgis.gui import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *
from osgeo import gdal
from timeseriesviewer.ui.docks import TsvDockWidgetBase, loadUI
......
......@@ -378,7 +378,7 @@ class MapCanvasLayerModel(QAbstractTableModel):
continue
if isinstance(mapLayer, QgsVectorLayer) and provider != 'ogr':
continue
if isinstance(mapLayer, QgsMapLayer) or type(mapLayer) in [str, unicode]:
if isinstance(mapLayer, QgsMapLayer) or isinstance(mapLayer, str):
li = MapLayerInfo(mapLayer, isVisible=isVisible, provider=provider)
assert isinstance(li, MapLayerInfo)
......@@ -982,14 +982,14 @@ class CanvasBoundingBoxItem(QgsGeometryRubberBand):
ext = SpatialExtent.fromMapCanvas(canvas)
ext = ext.toCrs(self.canvas.mapSettings().destinationCrs())
geom = QgsPolygonV2()
geom = QgsPolygon()
assert geom.fromWkt(ext.asWktPolygon())
self.mCanvasExtents[canvas] = (ext, geom)
self.refreshExtents()
def refreshExtents(self):
multi = QgsMultiPolygonV2()
multi = QgsPolygon()
if self.mShow:
for canvas, t in self.mCanvasExtents.items():
ext, geom = t
......
......@@ -23,13 +23,9 @@
from qgis import *
from qgis.core import *
from qgis.gui import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtXml import *
from PyQt5.QtXmlPatterns import *
import six
import xml.etree
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *
from qgis.core import *
from timeseriesviewer import SETTINGS
......@@ -274,8 +270,8 @@ if __name__ == '__main__':
import site, sys
#add site-packages to sys.path as done by enmapboxplugin.py
from timeseriesviewer import sandbox
qgsApp = sandbox.initQgisEnvironment()
from timeseriesviewer.utils import initQgisApplication
qgsApp = initQgisApplication()
import example.Images
lyr1 = QgsRasterLayer(example.Images.Img_2012_05_09_LE72270652012130EDC00_BOA)
......@@ -288,13 +284,13 @@ if __name__ == '__main__':
l = QHBoxLayout()
canvas1 = QgsMapCanvas()
canvas1.setWindowTitle('Canvas1')
canvas1.setLayerSet([QgsMapCanvasLayer(lyr1)])
canvas1.setLayers([QgsRasterLayer(lyr1)])
canvas1.setExtent(lyr1.extent())
mt = CursorLocationMapTool(canvas1)
canvas1.setMapTool(mt)
canvas2 = QgsMapCanvas()
canvas2.setWindowTitle('Canvas2')
canvas2.setLayerSet([QgsMapCanvasLayer(lyr2)])
canvas2.setLayers([QgsRasterLayer(lyr2)])
canvas2.setExtent(lyr2.extent())
canvas3 = QgsMapCanvas()
canvas3.setWindowTitle('Canvas3')
......
from qgis.core import *
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtXml import *
import re
from qgis.gui import *
MDF_DOCKTREEMODELDATA = 'application/enmapbox.docktreemodeldata'
MDF_DOCKTREEMODELDATA_XML = 'dock_tree_model_data'
MDF_DATASOURCETREEMODELDATA = 'application/enmapbox.datasourcetreemodeldata'
MDF_DATASOURCETREEMODELDATA_XML = 'data_source_tree_model_data'
MDF_LAYERTREEMODELDATA = 'application/qgis.layertreemodeldata'
MDF_LAYERTREEMODELDATA_XML = 'layer_tree_model_data'
MDF_PYTHON_OBJECTS = 'application/enmapbox/objectreference'
MDF_SPECTRALPROFILE = 'application/enmapbox/spectralprofile'
MDF_SPECTRALLIBRARY = 'application/enmapbox/spectrallibrary'
MDF_URILIST = 'text/uri-list'
MDF_TEXT_HTML = 'text/html'
MDF_TEXT_PLAIN = 'text/plain'
def attributesd2dict(attributes):
d = {}
assert isinstance(attributes, QDomNamedNodeMap)
for i in range(attributes.count()):
attribute = attributes.item(i)
d[attribute.nodeName()] = attribute.nodeValue()
return d
def fromLayerList(mapLayers):
"""
Converts a list of QgsMapLayers into a QMimeData object
:param mapLayers: [list-of-QgsMapLayers]
:return: QMimeData
"""
for lyr in mapLayers:
assert isinstance(lyr, QgsMapLayer)
tree = QgsLayerTree()
mimeData = QMimeData()
urls = []
for l in mapLayers:
tree.addLayer(l)
urls.append(QUrl.fromLocalFile(l.source()))
doc = QDomDocument()
context = QgsReadWriteContext()
node = doc.createElement(MDF_LAYERTREEMODELDATA_XML)
doc.appendChild(node)
for c in tree.children():
c.writeXml(node, context)
mimeData.setData(MDF_LAYERTREEMODELDATA, doc.toByteArray())
return mimeData
def toLayerList(mimeData):
"""
Extracts a layer-tree-group from a QMimeData
:param mimeData: QMimeData
:return: QgsLayerTree
"""
supported = [MDF_LAYERTREEMODELDATA, MDF_DATASOURCETREEMODELDATA]
assert isinstance(mimeData, QMimeData)
newMapLayers = []
if MDF_LAYERTREEMODELDATA in mimeData.formats():
doc = QDomDocument()
doc.setContent(mimeData.data(MDF_LAYERTREEMODELDATA))
xml = doc.toString()
node = doc.firstChildElement(MDF_LAYERTREEMODELDATA_XML)
context = QgsReadWriteContext()
#context.setPathResolver(QgsProject.instance().pathResolver())
layerTree = QgsLayerTree.readXml(node, context)
lt = QgsLayerTreeGroup.readXml(node, context)
#layerTree.resolveReferences(QgsProject.instance(), True)
registeredLayers = QgsProject.instance().mapLayers()
attributesLUT= {}
childs = node.childNodes()
for i in range(childs.count()):
child = childs.at(i).toElement()
if child.tagName() == 'layer-tree-layer':
attributesLUT[child.attribute('id')] = attributesd2dict(child.attributes())
for treeLayer in layerTree.findLayers():
assert isinstance(treeLayer, QgsLayerTreeLayer)
mapLayer = treeLayer.layer()
if isinstance(mapLayer, QgsMapLayer):
s = ""
if not isinstance(mapLayer, QgsMapLayer):
id = treeLayer.layerId()
if id in registeredLayers.keys():
mapLayer = registeredLayers[id]
elif id in attributesLUT.keys():
attributes = attributesLUT[id]
if attributes['providerKey'] == 'gdal':
mapLayer = QgsRasterLayer(attributes['source'])
elif attributes['providerKey'] == 'ogr':
mapLayer = QgsVectorLayer(attributes['source'])
else:
s = ""
if isinstance(mapLayer, QgsMapLayer):
mapLayer.setName(attributes['name'])
if isinstance(mapLayer, QgsMapLayer):
newMapLayers.append(mapLayer)
elif MDF_URILIST in mimeData.formats():
pass
else:
s = ""
return newMapLayers
def textToByteArray(text):
"""
Converts input into a QByteArray
:param text: bytes or str
:return: QByteArray
"""
if isinstance(text, QDomDocument):
return textToByteArray(text.toString())
else:
data = QByteArray()
data.append(text)
return data
def textFromByteArray(data):
"""
Decodes a QByteArray into a str
:param data: QByteArray
:return: str
"""
assert isinstance(data, QByteArray)
s = data.data().decode()
return s
......@@ -120,8 +120,6 @@ class QgisFake(QgisInterface):
self.bridge.setCanvasLayers()
s = ""
def legendInterface(self):
QgsLegendInterface
def addRasterLayer(self, path, baseName=''):
l = QgsRasterLayer(path, os.path.basename(path))
......
......@@ -23,8 +23,9 @@
import sys, os
from qgis.core import *
from qgis.gui import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *
from timeseriesviewer.timeseries import TimeSeries, TimeSeriesDatum, SensorInstrument
......
......@@ -20,26 +20,27 @@
"""
#see http://python-future.org/str_literals.html for str issue discussion
from future.utils import text_to_native_str
import os, re, tempfile, pickle, copy, shutil
from collections import OrderedDict
from qgis.core import *
from qgis.gui import *
import pyqtgraph as pg
from pyqtgraph import functions as fn
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *
import numpy as np
from osgeo import gdal, gdal_array
from timeseriesviewer.utils import geo2px, px2geo, SpatialExtent, SpatialPoint, loadUI, settings
from timeseriesviewer.virtualrasters import describeRawFile
from timeseriesviewer.models import Option, OptionListModel
from timeseriesviewer.utils import *
from timeseriesviewer.virtualrasters import *
from timeseriesviewer.models import *
import timeseriesviewer.mimedata as mimedata
FILTERS = 'ENVI Spectral Library (*.esl *.sli);;CSV Table (*.csv)'
def gdalDataset(pathOrDataset, eAccess=gdal.GA_ReadOnly):
"""
......@@ -198,7 +199,7 @@ class SpectralLibraryTableView(QTableView):
else:
index = self.indexAt(event.pos())
if mimeData.hasFormat(MimeDataHelper.MDF_SPECTRALLIBRARY):
if mimeData.hasFormat(mimedata.MDF_SPECTRALLIBRARY):
self.model().dropMimeData(mimeData, event.dropAction(), index.row(), index.column(), index.parent())
event.accept()
......@@ -208,12 +209,12 @@ class SpectralLibraryTableView(QTableView):
def dragEnterEvent(self, event):
assert isinstance(event, QDragEnterEvent)
if event.mimeData().hasFormat(MimeDataHelper.MDF_SPECTRALLIBRARY):
if event.mimeData().hasFormat(mimedata.MDF_SPECTRALLIBRARY):
event.accept()
def dragMoveEvent(self, event):
assert isinstance(event, QDragMoveEvent)
if event.mimeData().hasFormat(MimeDataHelper.MDF_SPECTRALLIBRARY):
if event.mimeData().hasFormat(mimedata.MDF_SPECTRALLIBRARY):
event.accept()
s = ""
......@@ -876,7 +877,7 @@ class EnviSpectralLibraryIO(SpectralLibraryIO):
for key, value in hdr.items():
if isinstance(value, list):
value = u','.join(v for v in value)
ds.SetMetadataItem(key, text_to_native_str(value), 'ENVI')
ds.SetMetadataItem(key, value, 'ENVI')
ds.FlushCache()
return ds
......@@ -962,7 +963,7 @@ class EnviSpectralLibraryIO(SpectralLibraryIO):
class SpectralLibraryPanel(QgsDockWidget):
sigLoadFromMapRequest = None
def __init__(self, parent=None):
super(SpectralLibraryPanel, self).__init__(parent)
self.setWindowTitle('Spectral Library')
......@@ -1005,8 +1006,8 @@ class SpectralLibraryVectorLayer(QgsVectorLayer):
self.addAttribute(field)
self.commitChanges()
self.mSpeclib.sigProfilesAdded.connect(self.onProfilesAdded)
self.mSpeclib.sigProfilesRemoved.connect(self.onProfilesRemoved)
self.mSpeclib.sigProfilesAdded[list].connect(self.onProfilesAdded)
self.mSpeclib.sigProfilesRemoved[list].connect(self.onProfilesRemoved)
self.onProfilesAdded(self.mSpeclib[:])
def onProfilesAdded(self, profiles):
......@@ -1102,6 +1103,10 @@ class SpectralLibrary(QObject):
return None
sigProfilesAdded = pyqtSignal([list], [list, list])
sigProfilesRemoved = pyqtSignal([list], [list, list])
sigNameChanged = pyqtSignal(str)
def __init__(self, parent=None, profiles=None):
super(SpectralLibrary, self).__init__(parent)
......@@ -1110,9 +1115,6 @@ class SpectralLibrary(QObject):
if profiles is not None:
self.mProfiles.extend(profiles[:])
sigNameChanged = pyqtSignal(str)
def setName(self, name):
if name != self.mName:
self.mName = name
......@@ -1125,7 +1127,6 @@ class SpectralLibrary(QObject):
assert isinstance(speclib, SpectralLibrary)
self.addProfiles([p for p in speclib])
sigProfilesAdded = pyqtSignal(list)
def addProfile(self, profile):
self.addProfiles([profile])
......@@ -1137,8 +1138,11 @@ class SpectralLibrary(QObject):
if index is None:
index = len(self.mProfiles)
self.mProfiles[index:index] = to_add
self.sigProfilesAdded.emit(to_add)
return to_add
indices = [self.mProfiles.index(p) for p in to_add]
self.sigProfilesAdded[list].emit(to_add)
self.sigProfilesAdded[list, list].emit(to_add, indices)
def extractProfileList(self, profiles):
if isinstance(profiles, SpectralProfile):
......@@ -1208,7 +1212,7 @@ class SpectralLibrary(QObject):
s = ""
sigProfilesRemoved = pyqtSignal(list)
def removeProfiles(self, profiles):
"""
Removes profiles from this ProfileSet
......@@ -1216,12 +1220,19 @@ class SpectralLibrary(QObject):
:return: [list-of-remove profiles] (only profiles that existed in this set before)
"""
to_remove = self.extractProfileList(profiles)
to_remove = [p for p in to_remove if p in self.mProfiles]
indices_to_remove = sorted([self.mProfiles.index(p) for p in to_remove if p in self.mProfiles], reverse=True)
to_remove = [self.mProfiles[i] for i in indices_to_remove]
if len(to_remove) > 0:
for p in to_remove:
self.mProfiles.remove(p)
self.sigProfilesRemoved.emit(to_remove)
return to_remove
self.sigProfilesRemoved[list].emit(to_remove)
self.sigProfilesRemoved[list, list].emit(to_remove, indices_to_remove)
s = ""
def yRange(self):
minY = min([min(p.yValues()) for p in self.mProfiles])
......@@ -1284,7 +1295,7 @@ class SpectralLibrary(QObject):
return False
for p1, p2 in zip(self.__iter__(), other.__iter__()):
if p1 != p2:
if not p1.isEqual(p2):
return False
return True
......@@ -1302,7 +1313,7 @@ class SpectralLibraryTableViewModel(QAbstractTableModel):
self.style = QColor('white')
self.checkState = Qt.Unchecked
def __init__(self, parent=None):
def __init__(self, speclib=None, parent=None):
super(SpectralLibraryTableViewModel, self).__init__(parent)
self.cIndex = '#'
......@@ -1317,8 +1328,42 @@ class SpectralLibraryTableViewModel(QAbstractTableModel):
self.mAttributeColumns = []
self.mSpecLib = SpectralLibrary()
self.mProfileWrappers = OrderedDict()
if speclib is None:
speclib = SpectralLibrary()
assert isinstance(speclib, SpectralLibrary)
self.mSpecLib = speclib
self.mSpecLib.sigProfilesAdded[list, list].connect(self.onProfilesAdded)
self.mSpecLib.sigProfilesRemoved[list,list].connect(self.onProfilesRemoved)
self.mProfileWrappers = list() #contains a wrapper for each SpectralProfile
self.mProfileWrapperLUT = {}
#add existing spectral profiles
l = len(self.mSpecLib)
if l > 0:
self.onProfilesAdded(self.mSpecLib[:], range(l))
def onProfilesAdded(self, profiles, indices):
for p, i in zip(profiles, indices):
assert self.mSpecLib[i] == p
self.beginInsertRows(QModelIndex(), i, i)
w = SpectralLibraryTableViewModel.ProfileWrapper(p)
self.mProfileWrappers.insert(i, w)
self.mProfileWrapperLUT[p]=w
self.endInsertRows()
s = ""
def onProfilesRemoved(self, profiles, indices):
for i, p in zip(indices, profiles):
idx = self.profile2idx(p)
assert idx.row() == i
self.beginRemoveRows(QModelIndex(), i, i)
w = self.mProfileWrapperLUT[p]
self.mProfileWrappers.remove(w)
self.mProfileWrapperLUT.pop(p)
self.endRemoveRows()
def addAttribute(self, name, i = None):
assert isinstance(name, str)
......@@ -1349,42 +1394,23 @@ class SpectralLibraryTableViewModel(QAbstractTableModel):
def insertProfiles(self, profiles, i=None):
if isinstance(profiles, SpectralLibrary):
profiles = profiles[:]
if not isinstance(profiles, list):
profiles = [profiles]
profiles = [p for p in profiles if isinstance(p, SpectralProfile)]
l = len(profiles)
if l > 0:
if i is None:
i = len(self.mSpecLib)
self.beginInsertRows(QModelIndex(), i, i + len(profiles) - 1)
self.mSpecLib.addProfiles(profiles, i)
self.endInsertRows()
self.mSpecLib.addProfiles(profiles, index=i)
for p in profiles:
self.mProfileWrappers[p] = SpectralLibraryTableViewModel.ProfileWrapper(p)
# update attribute columns
#self.mAttributeColumns = sorted(list(set(self.mAttributeColumns + self.mSpecLib.metadataAttributes())))
def removeProfiles(self, profiles):
if isinstance(profiles, SpectralLibrary):
profiles = profiles[:]
profiles = [p for p in profiles if isinstance(p, SpectralProfile) and p in self.mSpecLib]
removed = []
for p in profiles:
idx = self.profile2idx(p)
self.beginRemoveRows(QModelIndex(), idx.row(), idx.row())
self.mSpecLib.removeProfiles([p])
self.endRemoveRows()
removed.append(p)
for p in profiles:
self.mProfileWrappers.pop(p)
self.mSpecLib.removeProfiles(profiles)
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
......@@ -1428,50 +1454,62 @@ class SpectralLibraryTableViewModel(QAbstractTableModel):
self.layoutChanged.emit()
def rowCount(self, parentIdx=None, *args, **kwargs):
return len(self.mSpecLib)
return len(self.mProfileWrappers)
def columnCount(self, QModelIndex_parent=None, *args, **kwargs):
return len(self.columnNames())
def profile2idx(self, profile):
assert isinstance(profile, SpectralProfile)
#return self.createIndex(self.mSpecLib.index(profile), 0)
#pw = self.mProfileWrappers[profile]