Skip to content
Snippets Groups Projects
timeseries.py 70.1 KiB
Newer Older
  • Learn to ignore specific revisions
  •             _wl = 0.5 * wlMin + wlMax
                candidates.append((_band, _wl, _wlu))
    
            if len(candidates) == ds.RasterCount:
                candidates = sorted(candidates, key=lambda t: t[0])
    
                wlu = candidates[0][2]
                wlu = LUT_WAVELENGTH_UNITS[wlu]
                wl = [c[1] for c in candidates]
                return wl, wlu
        return None, None
    
    def extractWavelengths(ds):
        """
        Returns the wavelength and wavelength units
        :param ds: gdal.Dataset
        :return: (float [list-of-wavelengths], str with wavelength unit)
        """
    
        if isinstance(ds, QgsRasterLayer):
    
            if ds.dataProvider().name() == 'gdal':
                uri = ds.source()
                return extractWavelengths(gdal.Open(uri))
            else:
    
                md = [l.split('=') for l in str(ds.metadata()).splitlines() if 'wavelength' in l.lower()]
    
                wl = wlu = None
                for kv in md:
                    key, value = kv
                    key = key.lower()
                    value = value.strip()
    
                    if key == 'wavelength':
                        tmp = re.findall(r'\d*\.\d+|\d+', value) #find floats
                        if len(tmp) == 0:
                            tmp = re.findall(r'\d+', value) #find integers
                        if len(tmp) == ds.bandCount():
                            wl = [float(w) for w in tmp]
    
                    if key == 'wavelength units':
                        wlu = value
    
                        if wlu in LUT_WAVELENGTH_UNITS.keys():
                            wlu = LUT_WAVELENGTH_UNITS[wlu]
    
                    if isinstance(wl, list) and isinstance(wlu, str):
                        return wl, wlu
    
        elif isinstance(ds, gdal.Dataset):
    
            def testWavelLengthInfo(wl, wlu)->bool:
                return isinstance(wl, list) and len(wl) == ds.RasterCount and isinstance(wlu, str) and wlu in LUT_WAVELENGTH_UNITS.keys()
    
            # try band-specific metadata
            wl, wlu = extractWavelengthsFromGDALMetaData(ds)
            if testWavelLengthInfo(wl, wlu):
                return wl, wlu
    
            # try internal locations with XML info
            # SPOT DIMAP
            if 'xml:dimap' in ds.GetMetadataDomainList():
                md = ds.GetMetadata_Dict('xml:dimap')
                for key in md.keys():
                    dom = QDomDocument()
                    dom.setContent(key + '=' + md[key])
                    wl, wlu = extractWavelengthsFromDIMAPXML(ds, dom)
                    if testWavelLengthInfo(wl, wlu):
                        return wl, wlu
    
            # try separate XML files
            xmlReaders = [extractWavelengthsFromDIMAPXML, extractWavelengthsFromRapidEyeXML]
            for path in ds.GetFileList():
                if re.search(r'\.xml$', path, re.I) and not re.search(r'\.aux.xml$', path, re.I):
                    dom = QDomDocument()
                    with open(path, encoding='utf-8') as f:
                        dom.setContent(f.read())
    
                    if dom.hasChildNodes():
                        for xmlReader in xmlReaders:
                            wl, wlu = xmlReader(ds, dom)
                            if testWavelLengthInfo(wl, wlu):
                                return wl, wlu
    
        return None, None
    
    class TimeSeriesDock(QgsDockWidget, loadUI('timeseriesdock.ui')):
    
        """
        QgsDockWidget that shows the TimeSeries
        """
        def __init__(self, parent=None):
    
            super(TimeSeriesDock, self).__init__(parent)
    
            self.setupUi(self)
    
            #self.progressBar.setMinimum(0)
            #self.setProgressInfo(0, 100, 'Add images to fill time series')
            #self.progressBar.setValue(0)
            #self.progressInfo.setText(None)
            self.frameFilters.setVisible(False)
    
            self.mTimeSeries = None
            self.mSelectionModel = None
    
    
        def initActions(self, parent):
    
            from eotimeseriesviewer.main import TimeSeriesViewerUI
            assert isinstance(parent, TimeSeriesViewerUI)
            self.btnAddTSD.setDefaultAction(parent.actionAddTSD)
            self.btnRemoveTSD.setDefaultAction(parent.actionRemoveTSD)
            self.btnLoadTS.setDefaultAction(parent.actionLoadTS)
            self.btnSaveTS.setDefaultAction(parent.actionSaveTS)
            self.btnClearTS.setDefaultAction(parent.actionClearTS)
    
    
    
        def showTSD(self, tsd:TimeSeriesDate):
    
            assert isinstance(self.timeSeriesTreeView, TimeSeriesTreeView)
            assert isinstance(self.mTSProxyModel, QSortFilterProxyModel)
    
            tsd.setVisibility(True)
    
            assert isinstance(self.mTimeSeries, TimeSeries)
            idxSrc = self.mTimeSeries.tsdToIdx(tsd)
    
            if isinstance(idxSrc, QModelIndex):
                idx2 = self.mTSProxyModel.mapFromSource(idxSrc)
                if isinstance(idx2, QModelIndex):
                    self.timeSeriesTreeView.setCurrentIndex(idx2)
                    self.timeSeriesTreeView.scrollTo(idx2, QAbstractItemView.PositionAtCenter)
    
    
        def updateSummary(self):
    
    
            if isinstance(self.mTimeSeries, TimeSeries):
                if len(self.mTimeSeries) == 0:
    
                    info = 'Empty TimeSeries. Please add source images.'
    
                else:
                    nDates = self.mTimeSeries.rowCount()
                    nSensors = len(self.mTimeSeries.sensors())
                    nImages = len(list(self.mTimeSeries.sources()))
    
                    info = '{} dates, {} sensors, {} source images'.format(nDates, nSensors, nImages)
            else:
                info = ''
            self.summary.setText(info)
    
        def onSelectionChanged(self, *args):
            """
    
            Slot to react on user-driven changes of the selected TimeSeriesDate rows.
    
            """
    
            self.btnRemoveTSD.setEnabled(
                isinstance(self.mSelectionModel, QItemSelectionModel) and
                len(self.mSelectionModel.selectedRows()) > 0)
    
        def selectedTimeSeriesDates(self)->list:
            """
    
            Returns the TimeSeriesDate selected by a user.
            :return: [list-of-TimeSeriesDate]
    
    Benjamin Jakimow's avatar
    Benjamin Jakimow committed
            results = []
    
            if isinstance(self.mSelectionModel, QItemSelectionModel):
    
    Benjamin Jakimow's avatar
    Benjamin Jakimow committed
                for idx in self.mSelectionModel.selectedRows():
                    tsd = self.mTSProxyModel.data(idx, Qt.UserRole)
                    if isinstance(tsd, TimeSeriesSource):
                        tsd = tsd.timeSeriesDate()
                    if isinstance(tsd, TimeSeriesDate) and tsd not in results:
                        results.append(tsd)
            return results
    
        def timeSeries(self)->TimeSeries:
            """
            Returns the connected TimeSeries
            :return: TimeSeries
            """
            return self.mTimeSeries
    
    
        def setTimeSeries(self, TS:TimeSeries):
            """
            Sets the TimeSeries to be shown in the TimeSeriesDockUI
            :param TS: TimeSeries
            """
            from eotimeseriesviewer.timeseries import TimeSeries
            if isinstance(TS, TimeSeries):
                self.mTimeSeries = TS
                self.mTSProxyModel = QSortFilterProxyModel(self)
                self.mTSProxyModel.setSourceModel(self.mTimeSeries)
                self.mSelectionModel = QItemSelectionModel(self.mTSProxyModel)
                self.mSelectionModel.selectionChanged.connect(self.onSelectionChanged)
    
    
                self.timeSeriesTreeView.setModel(self.mTSProxyModel)
                self.timeSeriesTreeView.setSelectionModel(self.mSelectionModel)
    
                for c in range(self.mTSProxyModel.columnCount()):
                    self.timeSeriesTreeView.header().setSectionResizeMode(c, QHeaderView.ResizeToContents)
                self.mTimeSeries.rowsInserted.connect(self.updateSummary)
                #self.mTimeSeries.dataChanged.connect(self.updateSummary)
                self.mTimeSeries.rowsRemoved.connect(self.updateSummary)
                #TS.sigLoadingProgress.connect(self.setProgressInfo)
    
            self.onSelectionChanged()
    
    
    
    
    
    
    
    Benjamin Jakimow's avatar
    Benjamin Jakimow committed
    if __name__ == '__main__':
    
    Benjamin Jakimow's avatar
    Benjamin Jakimow committed
    
    
        print(convertMetricUnit(100, 'cm', 'm'))
        print(convertMetricUnit(1, 'm', 'um'))