Skip to content
Snippets Groups Projects
test_timeseries.py 16.3 KiB
Newer Older
"""Tests QGIS plugin init."""

import os
import unittest
import example
import example.Images
from osgeo import gdal, ogr, osr
Benjamin Jakimow's avatar
Benjamin Jakimow committed
from eotimeseriesviewer.utils import file_search
from eotimeseriesviewer.tests import TestObjects
from eotimeseriesviewer.timeseries import *
from eotimeseriesviewer.tests import initQgisApplication
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
QAPP = initQgisApplication()
SHOW_GUI = False and os.environ.get('CI') is None
import eotimeseriesviewer.settings

s = eotimeseriesviewer.settings.settings()
s.clear()
s.sync()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
s = ""
class TestInit(unittest.TestCase):
    def createTestDatasets(self):

        vsiDir = '/vsimem/tmp'
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        from eotimeseriesviewer.temporalprofiles import date2num
        ns = 50
        nl = 100

        r1 = np.arange('2000-01-01', '2005-06-14', step=np.timedelta64(16, 'D'), dtype=np.datetime64)
        r2 = np.arange('2000-01-01', '2005-06-14', step=np.timedelta64(8, 'D'), dtype=np.datetime64)
        drv = gdal.GetDriverByName('ENVI')

        crs = osr.SpatialReference()
        crs.ImportFromEPSG(32633)

        assert isinstance(drv, gdal.Driver)
        datasets = []

        for i, r in enumerate([r1, r2]):
            p = '{}tmpstack{}.bsq'.format(vsiDir, i+1)

            ds = drv.Create(p, ns, nl, len(r), eType=gdal.GDT_Float32)
            assert isinstance(ds, gdal.Dataset)

            ds.SetProjection(crs.ExportToWkt())

            dateString = ','.join([str(d) for d in r])
            dateString = '{{{}}}'.format(dateString)
            ds.SetMetadataItem('wavelength', dateString, 'ENVI')

            for b, date in enumerate(r):
                decimalYear = date2num(date)

                band = ds.GetRasterBand(b+1)
                assert isinstance(band, gdal.Band)
                band.Fill(decimalYear)
            ds.FlushCache()
            datasets.append(p)





        return datasets


    def createTimeSeries(self)->TimeSeries:

        files = list(file_search(os.path.dirname(example.__file__), '*.tif', recursive=True))
        TS = TimeSeries()
        self.assertIsInstance(TS, TimeSeries)
        TS.addSources(files)
        self.assertTrue(len(TS) > 0)
        return TS

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def test_sensorids(self):

        configs = [(6, 30, 30, gdal.GDT_Byte, [1, 2, 3, 4, 5, 6], None),
                   (6, 10, 20, gdal.GDT_CFloat32, [1, 2, 3, 4, 5, 6], 'index'),
                   (6, 30, 30, gdal.GDT_UInt32, [1, 2, 3, 323, 23., 3.4], 'Micrometers'),
                   (6, 30, 30, gdal.GDT_Int32, None, None),
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        ]

        for conf in configs:
            #nb:int, px_size_x:float, px_size_y:float, dt:int, wl:list, wlu:str
            print(conf)
            self.assertIsInstance(sensorID(*conf), str, msg='Unable to create sensorID from "{}"'.format(str(conf)))
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            sid = sensorID(*conf)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            c2 = sensorIDtoProperties(sid)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            self.assertListEqual(list(conf), list(c2))
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    def test_TimeSeriesDate(self):

        file = example.Images.Img_2014_03_20_LC82270652014079LGN00_BOA

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        tss = TimeSeriesSource.create(file)
        tss2 = TimeSeriesSource.create(example.Images.Img_2014_07_02_LE72270652014183CUB00_BOA)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        sensor = SensorInstrument(tss.sid())

        tsd = TimeSeriesDate(None, tss.date(), sensor)
        tsd2 = TimeSeriesDate(None, tss.date(), sensor)
        self.assertIsInstance(tsd, TimeSeriesDate)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.assertEqual(tsd, tsd2)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.assertEqual(tsd.sensor(), sensor)
        self.assertEqual(len(tsd), 0)
        tsd.addSource(tss)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.assertEqual(len(tsd), 1)

        self.assertTrue(tsd.year() == 2014)
        self.assertTrue(tsd.doy() == 79)
        self.assertIsInstance(tsd.decimalYear(), float)
        self.assertTrue(tsd.decimalYear() >= 2014 and tsd.decimalYear() < 2015)
Benjamin Jakimow's avatar
Benjamin Jakimow committed


        self.assertIsInstance(tsd, QAbstractTableModel)
        for r in range(len(tsd)):
            for i in range(len(TimeSeriesDate.ColumnNames)):
                value = tsd.data(tsd.createIndex(r, i), role=Qt.DisplayRole)

        TV = QTableView()
        TV.setModel(tsd)
        TV.show()

        if SHOW_GUI:
            QAPP.exec_()

    def test_TimeSeriesSource(self):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        wcs = r'dpiMode=7&identifier=BGS_EMODNET_CentralMed-MCol&url=http://194.66.252.155/cgi-bin/BGS_EMODnet_bathymetry/ows?VERSION%3D1.1.0%26coverage%3DBGS_EMODNET_CentralMed-MCol'

        p = r'Q:\Processing_BJ\01_Data\level2_overview\20180629_SEN2B_BOA.vrt'
        if os.path.isfile(p):
            tss = TimeSeriesSource.create(p)
            self.assertIsInstance(tss, TimeSeriesSource)

        p = r'Q:\Processing_BJ\99_OSARIS_Testdata\Loibl-2019-OSARIS-Ala-Archa\Amplitudes\20151207--20151231-amplitude.grd'
        if os.path.isfile(p):
            tss = TimeSeriesSource.create(p)
            self.assertIsInstance(tss, TimeSeriesSource)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if False:
            webSources = [QgsRasterLayer(wcs, 'test', 'wcs')]

            for src in webSources:
                tss = TimeSeriesSource.create(src)
                self.assertIsInstance(tss, TimeSeriesSource)


        sources = [example.Images.Img_2014_03_20_LC82270652014079LGN00_BOA,
                   gdal.Open(example.Images.Img_2014_03_20_LC82270652014079LGN00_BOA),
                   QgsRasterLayer(example.Images.Img_2014_03_20_LC82270652014079LGN00_BOA)
                   ]

        ref = None
        for src in sources:

            tss = TimeSeriesSource.create(src)
            self.assertIsInstance(tss.spatialExtent(), SpatialExtent)
            self.assertIsInstance(tss, TimeSeriesSource)

            if not isinstance(ref, TimeSeriesSource):
                ref = tss
            else:
                self.assertTrue(ref == tss)
                self.assertTrue(ref.sid() == tss.sid())

Benjamin Jakimow's avatar
Benjamin Jakimow committed
            mdui = tss.qgsMimeDataUtilsUri()
            self.assertIsInstance(mdui, QgsMimeDataUtils.Uri)

            lyr, b = mdui.rasterLayer('')
            self.assertTrue(b)
            self.assertIsInstance(lyr, QgsRasterLayer)
            self.assertTrue(lyr.isValid())
Benjamin Jakimow's avatar
Benjamin Jakimow committed

        import pickle, json

        dump = pickle.dumps(tss)
        tss2 = pickle.loads(dump)
        self.assertIsInstance(tss2, TimeSeriesSource)
        self.assertEqual(tss, tss2)

        json = tss.json()
        self.assertIsInstance(json, str)
        tss3 = TimeSeriesSource.fromJson(json)
        self.assertIsInstance(tss3, TimeSeriesSource)
        self.assertEqual(tss, tss3)


    def test_sensorMatching(self):





        testDir = r'Q:\Processing_BJ\99_EOTSV_RapidEye'
        if os.path.isdir(testDir):
            sensors = set()
            files = list(file_search(testDir, re.compile(r'.*RE.*\d+\.tif$'), recursive=True))
            tssList = []
            for file in files:
                tss = TimeSeriesSource.create(file)
                self.assertIsInstance(tss, TimeSeriesSource)
                sid = tss.sid()
                sensor = SensorInstrument(sid)
                self.assertIsInstance(sensor, SensorInstrument)
                sensors.add(sensor)
                tssList.append(tss)

            TS = TimeSeries()
            TS.setSensorMatching(SensorMatching.PX_DIMS)
            TS.addSources(files, runAsync=False)
            self.assertTrue(len(TS.sensors()) == 1)

            TS = TimeSeries()
            TS.setSensorMatching(SensorMatching.PX_DIMS | SensorMatching.NAME | SensorMatching.WL)
            TS.addSources(files, runAsync=False)
            self.assertTrue(len(TS.sensors()) == len(sensors))



            s = ""


    def test_datetimeprecision(self):

        img1 = TestObjects.inMemoryImage()
        img2 = TestObjects.inMemoryImage()
        self.assertIsInstance(img1, gdal.Dataset)
        self.assertIsInstance(img2, gdal.Dataset)
        t0 = np.datetime64('now')

        pairs = [('2018-12-23T14:40:48', '2018-12-23T14:40:47', DateTimePrecision.Minute),
                 ('2018-12-23T14:40', '2018-12-23T14:39', DateTimePrecision.Hour),
                 ('2018-12-23T14:40:48', '2018-12-23T14:40:47', DateTimePrecision.Day),
                 ('2018-12-23', '2018-12-22', DateTimePrecision.Week),
                 ('2018-12-23', '2018-12-01', DateTimePrecision.Month),
                 ('2018-12-23', '2018-11-01', DateTimePrecision.Year),
                 ]
        for p in pairs:
            t1, t2, precision = p
            img1.SetMetadataItem('acquisition time', t1)
            img2.SetMetadataItem('acquisition time', t2)
            TS = TimeSeries()
            self.assertIsInstance(TS, TimeSeries)
            self.assertTrue(TS.mDateTimePrecision == DateTimePrecision.Original)
            TS.addSources([img1, img2])
            self.assertTrue(len(TS) == 2)

            TS = TimeSeries()
            TS.setDateTimePrecision(precision)
            TS.addSources([img1, img2])
            self.assertTrue(len(TS) == 1)

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def test_multisource_tsd(self):

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        p1 = TestObjects.inMemoryImage()
        p2 = TestObjects.inMemoryImage()

        sources = [p1, p2]
        for p in sources:
            p.SetMetadataItem('acquisition_date', '2014-04-01')
            s = ""

        tssList = [TimeSeriesSource.create(p) for p in sources]

        TS = TimeSeries()
        self.assertTrue(len(TS) == 0)

        TS.addSources(tssList)
        self.assertTrue(len(TS) == 1)

        tsd = TS[0]
        self.assertIsInstance(tsd, TimeSeriesDate)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.assertTrue(len(tsd.sources()) == 2)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        paths = TestObjects.createMultiSourceTimeSeries()
        TS = TimeSeries()
        TS.addSources(paths)
        srcUris = TS.sourceUris()
        self.assertTrue(len(srcUris) == len(paths))
        self.assertTrue(len(TS) == 0.5 * len(paths))
        self.assertTrue(len(TS) == 0.5 * len(srcUris))
    def test_timeseries_loadasync(self):

        files = list(file_search(os.path.dirname(example.__file__), '*.tif', recursive=True))

        w = QgsTaskManagerWidget(QgsApplication.taskManager())
        w.show()

        TS = TimeSeries()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        TS.addSources(files, nWorkers=1)

        while QgsApplication.taskManager().countActiveTasks() > 0 or len(TS.mTasks) > 0:
            QCoreApplication.processEvents()

        if SHOW_GUI:
            QAPP.exec_()

    def test_timeseries(self):

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        files = list(file_search(os.path.dirname(example.__file__), '*.tif', recursive=True))
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        removedDates = []
        addedSensors = []
        removedSensors = []
        sourcesChanged = []
        self.assertIsInstance(TS, TimeSeries)
        self.assertIsInstance(TS, QAbstractItemModel)

        TS.sigTimeSeriesDatesAdded.connect(lambda dates: addedDates.extend(dates))
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        TS.sigTimeSeriesDatesRemoved.connect(lambda dates: removedDates.extend(dates))
        #TS.sigSourcesChanged.connect(lambda tsd: sourcesChanged.append(tsd))
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        TS.sigSensorAdded.connect(lambda sensor: addedSensors.append(sensor))
        TS.sigSensorRemoved.connect(lambda sensor:removedSensors.append(sensor))
        TS.addSources(files)

        counts = dict()
        for i, tsd in enumerate(TS):
            self.assertIsInstance(tsd, TimeSeriesDate)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            sensor = tsd.sensor()
            if sensor not in counts.keys():
                counts[sensor] = 0
            counts[sensor] = counts[sensor] + 1

        self.assertEqual(len(files), len(TS))
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.assertEqual(len(addedDates), len(TS))
        self.assertTrue(len(TS) > 0)
        self.assertEqual(TS.columnCount(), len(TS.mColumnNames))
        self.assertEqual(TS.rowCount(), len(TS))
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.assertEqual(len(removedDates), 0)
        self.assertTrue(len(addedSensors) == 2)

        self.assertIsInstance(TS.maxSpatialExtent(), SpatialExtent)

        sensor = TS.sensors()[0]
        self.assertIsInstance(sensor, SensorInstrument)
        self.assertTrue(sensor == TS.sensor(sensor.id()))
        TS.removeSensor(sensor)
        self.assertEqual(counts[sensor], len(removedDates))

        extent = TS.maxSpatialExtent()
        self.assertIsInstance(extent, SpatialExtent)
        paths = [r'Y:\Pleiades\GFIO_Gp13_Novo_SO16018091-4-01_DS_PHR1A_201703031416139_FR1_PX_W056S07_0906_01636\TPP1600581943\IMG_PHR1A_PMS_001\DIM_PHR1A_PMS_201703031416139_ORT_2224693101-001.XML'
                ,r'Y:\Pleiades\GFIO_Gp13_Novo_SO16018091-4-01_DS_PHR1A_201703031416139_FR1_PX_W056S07_0906_01636\TPP1600581943\IMG_PHR1A_PMS_001\IMG_PHR1A_PMS_201703031416139_ORT_2224693101-001_R1C1.JP2'
                    ]
        for p in paths:
            if not os.path.isfile(p):
                continue
            ds = gdal.Open(p)
            self.assertIsInstance(ds, gdal.Dataset)
            band = ds.GetRasterBand(1)
            self.assertIsInstance(band, gdal.Band)
            tss = TimeSeriesSource(ds)
            self.assertIsInstance(tss, TimeSeriesSource)
            self.assertEqual(tss.mWLU, r'μm')
            self.assertListEqual(tss.mWL, [0.775, 0.867, 1.017, 1.315])

        s = ""
        from example.Images import re_2014_06_25
        paths = [r'Y:\RapidEye\3A\2135821_2014-06-25_RE2_3A_328202\2135821_2014-06-25_RE2_3A_328202.tif']

        for p in paths:
            if not os.path.isfile(p):
                continue
            ds = gdal.Open(p)
            self.assertIsInstance(ds, gdal.Dataset)
            band = ds.GetRasterBand(1)
            self.assertIsInstance(band, gdal.Band)


            tss = TimeSeriesSource(ds)
            self.assertIsInstance(tss, TimeSeriesSource)

            # see https://www.satimagingcorp.com/satellite-sensors/other-satellite-sensors/rapideye/
            wlu = r'nm'
            wl = [0.5 * (440 + 510),
                  0.5 * (520 + 590),
                  0.5 * (630 + 685),
                  0.5 * (760 + 850),
                  0.5 * (760 - 850)
                  ]
            self.assertEqual(tss.mWLU, wlu)
            self.assertListEqual(tss.mWL, wl)

    def test_sentinel2(self):

        p = r'Q:\Processing_BJ\01_Data\Sentinel\T21LXL\S2A_MSIL1C_20161221T141042_N0204_R110_T21LXL_20161221T141040.SAFE\MTD_MSIL1C.xml'
        dsC = gdal.Open(p)
        self.assertIsInstance(dsC, gdal.Dataset)
        for item in dsC.GetSubDatasets():
            path = item[0]
            ds = gdal.Open(path)
            gt =  ds.GetGeoTransform()
            self.assertIsInstance(ds, gdal.Dataset)
            band = ds.GetRasterBand(1)
            self.assertIsInstance(band, gdal.Band)
            wlu = ds.GetRasterBand(1).GetMetadata_Dict()['WAVELENGTH_UNIT']
            wl = [float(ds.GetRasterBand(b+1).GetMetadata_Dict()['WAVELENGTH']) for b in range(ds.RasterCount)]

            tss = TimeSeriesSource(ds)
            self.assertIsInstance(tss, TimeSeriesSource)
            self.assertEqual(tss.mWLU, wlu)
            self.assertEqual(tss.mWL, wl)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        tss = TimeSeriesSource.create(example.Images.Img_2014_01_15_LC82270652014015LGN00_BOA)
        self.assertIsInstance(tss, TimeSeriesSource)

        sensor = SensorInstrument(tss.sid())

        sensor2 = SensorInstrument(tss.sid())
        self.assertIsInstance(sensor, SensorInstrument)
        self.assertTrue(sensor == sensor2)
        sensor2.setName('foobar')
        self.assertTrue(sensor == sensor2)

        self.assertIsInstance(sensor2.id(), str)

        lyr = sensor.proxyLayer()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.assertIsInstance(lyr, QgsRasterLayer)
    def test_TimeSeriesTreeModel(self):

        TS = TimeSeries()
        self.assertIsInstance(TS, QAbstractItemModel)
        sources = TestObjects.createMultiSourceTimeSeries()
        TS.addSources(sources[0:1])
        self.assertTrue(len(TS) == 1)
        TS.addSources(sources[1:2])
        self.assertTrue(len(TS) == 1)
        self.assertTrue(len(TS[0]) == 2)
        self.assertTrue(TS.rowCount(TS.index(0, 0)) == 2)
        TS.addSources(sources[2:])
        self.assertEqual(len(TS), TS.rowCount())
        M = QSortFilterProxyModel()
        M.setSourceModel(TS)
        TV = QTreeView()
        TV.setSortingEnabled(True)
        TV.setModel(M)
        TV.show()

        if SHOW_GUI:
            QAPP.exec_()

    def test_TimeSeriesDock(self):

        TS = TimeSeries()
        TS.addSources(TestObjects.createMultiSourceTimeSeries())

        dock.setTimeSeries(TS)
        dock.show()

        if SHOW_GUI:
            QAPP.exec_()


if __name__ == '__main__':
    unittest.main()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

QAPP.quit()