Newer
Older
if isinstance(mapCanvas, MapCanvas):
tsd = mapCanvas.tsd()
if not hasattr(self, 'cntSpectralProfile'):
self.cntSpectralProfile = 0
profiles = SpectralProfile.fromMapCanvas(mapCanvas, spatialPoint)
if isinstance(tsd, TimeSeriesDate):
profiles2 = []
sl = self.spectralLibrary()
if isinstance(sl, SpectralLibrary):
for p in profiles:
self.cntSpectralProfile += 1
assert isinstance(p, SpectralProfile)
p2 = p.copyFieldSubset(fields=sl.fields())
p2.setName('Profile {} {}'.format(self.cntSpectralProfile, tsd.mDate))
p2.setAttribute('date', '{}'.format(tsd.mDate))
p2.setAttribute('doy', int(tsd.mDOY))
p2.setAttribute('sensor', tsd.mSensor.name())
profiles2.append(p2)
self.ui.dockSpectralLibrary.SLW.setCurrentSpectra(profiles2)
elif mapToolKey == MapTools.CursorLocation:
self.ui.dockCursorLocation.loadCursorLocation(spatialPoint, mapCanvas)
else:
s = ""
pass
def messageBar(self)->QgsMessageBar:
"""
Returns the QgsMessageBar that is used to show messages in the TimeSeriesViewer UI.
:return: QgsMessageBar
"""

Benjamin Jakimow
committed
return self.ui.mMapWidget.messageBar()
def loadTimeSeriesDefinition(self, path:str=None, n_max:int=None, runAsync=True):
"""
Loads a time series definition file
:param path:
:param n_max:
:return:
"""
if not (isinstance(path, str) and os.path.isfile(path)):
defFile = s.value('file_ts_definition')
defDir = None
if defFile is not None:
defDir = os.path.dirname(defFile)
filters = "CSV (*.csv *.txt);;" + \
"All files (*.*)"
path, filter = QFileDialog.getOpenFileName(caption='Load Time Series definition', directory=defDir, filter=filters)
if path is not None and os.path.exists(path):
self.clearTimeSeries()
progressDialog = self._createProgressDialog()
self.mTimeSeries.loadFromFile(path, n_max=n_max, progressDialog=progressDialog, runAsync=runAsync)

Benjamin Jakimow
committed
def createMapView(self, name:str=None)->MapView:

Benjamin Jakimow
committed
Creates a new MapView.
:return: MapView
return self.ui.dockMapViews.createMapView(name=name)
def mapViews(self)->typing.List[MapView]:
"""
Returns all MapViews
:return: [list-of-MapViews]
"""
return self.ui.dockMapViews[:]
def icon(self)->QIcon:
"""
Returns the EO Time Series Viewer icon
:return: QIcon
"""
import eotimeseriesviewer
return eotimeseriesviewer.icon()
def temporalProfiles(self)->list:
"""
Returns collected temporal profiles
:return: [list-of-TemporalProfiles]
"""
return self.spectralTemporalVis.temporalProfileLayer()[:]
def logMessage(self, message:str, tag:str, level):
"""
"""
if tag == LOG_MESSAGE_TAG and level in [Qgis.Critical, Qgis.Warning]:
self.messageBar().pushMessage(tag, message, level)
def onSensorAdded(self, sensor:SensorInstrument):
knownName = eotsvSettings.sensorName(sensor.id())
sensor.sigNameChanged.connect(lambda *args, s=sensor: self.onSensorNameChanged(sensor))
if isinstance(knownName, str) and len(knownName) > 0:
sensor.setName(knownName)
else:
self.onSensorNameChanged(sensor) # save the sensor name to the settings
def onSensorNameChanged(self, sensor:SensorInstrument):
# save changed names to settings
from eotimeseriesviewer.settings import saveSensorName
if sensor in self.sensors():
saveSensorName(sensor)

benjamin.jakimow@geo.hu-berlin.de
committed
def onTimeSeriesChanged(self, *args):
if not self.mSpatialMapExtentInitialized:
if len(self.mTimeSeries) > 0:
if len(self.ui.dockMapViews) == 0:
self.ui.dockMapViews.createMapView()
extent = self.timeSeries().maxSpatialExtent()
if isinstance(extent, SpatialExtent):
self.ui.dockMapViews.setCrs(extent.crs())
self.ui.mMapWidget.setSpatialExtent(extent)
self.mSpatialMapExtentInitialized = True
else:
self.mSpatialMapExtentInitialized = False
print('Failed to calculate max. spatial extent of TimeSeries with length {}'.format(len(self.timeSeries())))
lastDate = self.ui.mMapWidget.currentDate()
if lastDate:
tsd = self.timeSeries().findDate(lastDate)
else:
tsd = self.timeSeries()[0]
self.setCurrentDate(tsd)

benjamin.jakimow@geo.hu-berlin.de
committed

benjamin.jakimow@geo.hu-berlin.de
committed
if len(self.mTimeSeries) == 0:

benjamin.jakimow@geo.hu-berlin.de
committed
self.mSpatialMapExtentInitialized = False
def mapWidget(self)->MapWidget:
"""
Returns the MapWidget that contains all map canvases.
:return: MapWidget
"""

Benjamin Jakimow
committed
return self.ui.mMapWidget
def saveTimeSeriesDefinition(self):
defFile = s.value('FILE_TS_DEFINITION')
if defFile is not None:
defFile = os.path.dirname(defFile)
filters = "CSV (*.csv *.txt);;" + \
"All files (*.*)"
path, filter = QFileDialog.getSaveFileName(caption='Save Time Series definition', filter=filters, directory=defFile)
path = self.mTimeSeries.saveToFile(path)
if path is not None:
s.setValue('FILE_TS_DEFINITION', path)
def loadTimeSeriesStack(self):
from eotimeseriesviewer.stackedbandinput import StackedBandInputDialog
d = StackedBandInputDialog(parent=self.ui)
if d.exec_() == QDialog.Accepted:
self.addTimeSeriesImages(writtenFiles)
def loadExampleTimeSeries(self, n:int=None, loadAsync=True):

Benjamin Jakimow
committed
"""
Loads an example time series
:param n: int, max. number of images to load. Useful for developer test-cases
"""
import example.Images
exampleDataDir = os.path.dirname(example.__file__)
rasterFiles = list(file_search(exampleDataDir, '*.tif', recursive=True))
vectorFiles = list(file_search(exampleDataDir, re.compile(r'.*\.(gpkg|shp)$'), recursive=True))

Benjamin Jakimow
committed
if isinstance(n, bool) or not isinstance(n, int):

Benjamin Jakimow
committed
n = min(n, len(rasterFiles))

Benjamin Jakimow
committed
n = max(1, n)
self.addTimeSeriesImages(rasterFiles[0:n], loadAsync=loadAsync)
if len(vectorFiles) > 0:
self.addVectorData(vectorFiles)
for lyr in QgsProject.instance().mapLayers().values():
if isinstance(lyr, QgsVectorLayer) and lyr.source() in vectorFiles:
renderer = lyr.renderer()
if lyr.geometryType() == QgsWkbTypes.PolygonGeometry and isinstance(renderer, QgsSingleSymbolRenderer):
renderer = renderer.clone()
symbol = renderer.symbol()
if isinstance(symbol, QgsFillSymbol):
symbol.setOpacity(0.25)
lyr.setRenderer(renderer)
s = ""
def timeSeries(self)->TimeSeries:
"""
Returns the TimeSeries instance.
:return: TimeSeries
"""
return self.mTimeSeries
# noinspection PyMethodMayBeStatic
def tr(self, message):
"""Get the translation for a string using Qt translation API.
We implement this ourselves since we do not inherit QObject.
:param message: String for translation.
:type message: str, QString
:returns: Translated version of message.
:rtype: QString
"""
# noinspection PyTypeChecker,PyArgumentList,PyCallByClass

benjamin.jakimow@geo.hu-berlin.de
committed
return QCoreApplication.translate('HUBTSV', message)
"""Removes the plugin menu item and icon """
self.iface.removeToolBarIcon(self.action)
def clearLayoutWidgets(self, L):
if L is not None:
while L.count():
w = L.takeAt(0)
if w.widget():
w.widget().deleteLater()

Benjamin Jakimow
committed
QApplication.processEvents()
def addVectorData(self, files=None)->list:
"""
Adds vector data
:param files: vector layer sources
:return: [list-of-QgsVectorLayers]
"""
vectorLayers = []
defDir = s.value('DIR_FILESEARCH')

Benjamin Jakimow
committed
filters = QgsProviderRegistry.instance().fileVectorFilters()
files, filter = QFileDialog.getOpenFileNames(directory=defDir, filter=filters)

benjamin.jakimow@geo.hu-berlin.de
committed

Benjamin Jakimow
committed
if len(files) > 0 and os.path.exists(files[0]):
dn = os.path.dirname(files[0])
s.setValue('DIR_FILESEARCH', dn)
if files:
from eotimeseriesviewer.mapvisualization import MapView

Benjamin Jakimow
committed
from .externals.qps.layerproperties import subLayers

Benjamin Jakimow
committed
for f in files:
vectorLayers.extend(subLayers(QgsVectorLayer(f)))
if len(vectorLayers) > 0:
QgsProject.instance().addMapLayers(vectorLayers)
for mapView in self.mapViews():
assert isinstance(mapView, MapView)
for l in vectorLayers:
mapView.addLayer(l)

Benjamin Jakimow
committed
def addTimeSeriesImages(self, files: list, loadAsync=True):
"""
Adds images to the time series
:param files:
"""

Benjamin Jakimow
committed
if files is None:
s = settings()
filters = QgsProviderRegistry.instance().fileRasterFilters()
files, filter = QFileDialog.getOpenFileNames(directory=defDir, filter=filters)
if len(files) > 0 and os.path.exists(files[0]):
dn = os.path.dirname(files[0])
progressDialog = self._createProgressDialog()
progressDialog.setRange(0, len(files))
progressDialog.setLabelText('Start loading {} images....'.format(len(files)))
self.mTimeSeries.addSources(files, progressDialog=progressDialog, runAsync=loadAsync)
self.mTimeSeries.beginResetModel()
self.mTimeSeries.clear()
self.mTimeSeries.endResetModel()
class SaveAllMapsDialog(QDialog, loadUI('saveallmapsdialog.ui')):
def __init__(self, parent=None):
super(SaveAllMapsDialog, self).__init__(parent)
self.setupUi(self)
self.setWindowTitle('Save Maps')
assert isinstance(self.fileWidget, QgsFileWidget)
assert isinstance(self.cbFileType, QComboBox)
self.fileWidget.setStorageMode(QgsFileWidget.GetDirectory)
formats = [('Portable Network Graphics (*.png)', 'PNG'),
('Joint Photographic Experts Group (*.jpg)', 'JPG'),
('Windows Bitmap (*.bmp)', 'BMP'),
('Portable Bitmap (*.pbm)', 'PBM'),
('Portable Graymap (*.pgm)', 'PGM'),
('Portable Pixmap (*.ppm)', 'PPM'),
('X11 Bitmap (*.xbm)', 'XBM'),
('X11 Pixmap (*.xpm)', 'XPM'),
]
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
for t in formats:
self.cbFileType.addItem(t[0], userData=t[1])
self.fileWidget.fileChanged.connect(self.validate)
self.buttonBox.button(QDialogButtonBox.Save).clicked.connect(lambda : self.setResult(QDialog.Accepted))
self.buttonBox.button(QDialogButtonBox.Cancel).clicked.connect(lambda : self.setResult(QDialog.Rejected))
self.validate()
def validate(self, *args):
b = os.path.isdir(self.directory())
self.buttonBox.button(QDialogButtonBox.Save).setEnabled(b)
def setDirectory(self, path:str):
assert os.path.isdir(path)
self.fileWidget.setFilePath(path)
def directory(self)->str:
"""
Returns the selected directory
:return: str
"""
return self.fileWidget.filePath()
def fileType(self)->str:
"""
Returns the selected file type
:return:
"""
return self.cbFileType.currentData(Qt.UserRole)
def disconnect_signal(signal):
while True:
try:
signal.disconnect()
except TypeError:
break