diff --git a/example/Images/__init__.py b/example/Images/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..85fa7c9a6f20c424b4a453563955cd63736d93a3 --- /dev/null +++ b/example/Images/__init__.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +""" +This file is auto-generated. +Do not edit manually, as changes might get overwritten. +""" +__author__ = "auto-generated by make\make.py" +__date__ = "2017-02-17T11:36:22" + +import sys, os + +thisDir = os.path.dirname(__file__) +# File path attributes: +# Raster files: +Img_2012_04_07_LE72270652012098EDC00_BOA = os.path.join(thisDir,r'2012-04-07_LE72270652012098EDC00_BOA.bsq') +Img_2012_04_23_LE72270652012114EDC00_BOA = os.path.join(thisDir,r'2012-04-23_LE72270652012114EDC00_BOA.bsq') +Img_2012_05_09_LE72270652012130EDC00_BOA = os.path.join(thisDir,r'2012-05-09_LE72270652012130EDC00_BOA.bsq') +Img_2012_05_25_LE72270652012146EDC00_BOA = os.path.join(thisDir,r'2012-05-25_LE72270652012146EDC00_BOA.bsq') +Img_2012_06_10_LE72270652012162EDC00_BOA = os.path.join(thisDir,r'2012-06-10_LE72270652012162EDC00_BOA.bsq') +Img_2012_06_26_LE72270652012178EDC00_BOA = os.path.join(thisDir,r'2012-06-26_LE72270652012178EDC00_BOA.bsq') +Img_2012_07_12_LE72270652012194EDC00_BOA = os.path.join(thisDir,r'2012-07-12_LE72270652012194EDC00_BOA.bsq') +Img_2012_07_28_LE72270652012210EDC00_BOA = os.path.join(thisDir,r'2012-07-28_LE72270652012210EDC00_BOA.bsq') +Img_2012_08_29_LE72270652012242CUB00_BOA = os.path.join(thisDir,r'2012-08-29_LE72270652012242CUB00_BOA.bsq') +Img_2012_09_14_LE72270652012258EDC00_BOA = os.path.join(thisDir,r'2012-09-14_LE72270652012258EDC00_BOA.bsq') +Img_2012_09_30_LE72270652012274CUB00_BOA = os.path.join(thisDir,r'2012-09-30_LE72270652012274CUB00_BOA.bsq') +Img_2012_10_16_LE72270652012290CUB00_BOA = os.path.join(thisDir,r'2012-10-16_LE72270652012290CUB00_BOA.bsq') +Img_2012_11_01_LE72270652012306CUB02_BOA = os.path.join(thisDir,r'2012-11-01_LE72270652012306CUB02_BOA.bsq') +Img_2013_02_05_LE72270652013036CUB00_BOA = os.path.join(thisDir,r'2013-02-05_LE72270652013036CUB00_BOA.bsq') +Img_2013_05_12_LE72270652013132CUB00_BOA = os.path.join(thisDir,r'2013-05-12_LE72270652013132CUB00_BOA.bsq') +Img_2013_05_20_LC82270652013140LGN01_BOA = os.path.join(thisDir,r'2013-05-20_LC82270652013140LGN01_BOA.bsq') +Img_2013_06_05_LC82270652013156LGN00_BOA = os.path.join(thisDir,r'2013-06-05_LC82270652013156LGN00_BOA.bsq') +Img_2013_06_21_LC82270652013172LGN00_BOA = os.path.join(thisDir,r'2013-06-21_LC82270652013172LGN00_BOA.bsq') +Img_2013_06_29_LE72270652013180CUB08_BOA = os.path.join(thisDir,r'2013-06-29_LE72270652013180CUB08_BOA.bsq') +Img_2013_07_07_LC82270652013188LGN00_BOA = os.path.join(thisDir,r'2013-07-07_LC82270652013188LGN00_BOA.bsq') +Img_2013_07_15_LE72270652013196CUB00_BOA = os.path.join(thisDir,r'2013-07-15_LE72270652013196CUB00_BOA.bsq') +Img_2013_07_23_LC82270652013204LGN00_BOA = os.path.join(thisDir,r'2013-07-23_LC82270652013204LGN00_BOA.bsq') +Img_2013_07_31_LE72270652013212CUB00_BOA = os.path.join(thisDir,r'2013-07-31_LE72270652013212CUB00_BOA.bsq') +Img_2013_08_08_LC82270652013220LGN00_BOA = os.path.join(thisDir,r'2013-08-08_LC82270652013220LGN00_BOA.bsq') +Img_2013_08_16_LE72270652013228CUB00_BOA = os.path.join(thisDir,r'2013-08-16_LE72270652013228CUB00_BOA.bsq') +Img_2013_08_24_LC82270652013236LGN00_BOA = os.path.join(thisDir,r'2013-08-24_LC82270652013236LGN00_BOA.bsq') +Img_2013_09_01_LE72270652013244CUB00_BOA = os.path.join(thisDir,r'2013-09-01_LE72270652013244CUB00_BOA.bsq') +Img_2013_09_09_LC82270652013252LGN00_BOA = os.path.join(thisDir,r'2013-09-09_LC82270652013252LGN00_BOA.bsq') +Img_2013_09_17_LE72270652013260CUB01_BOA = os.path.join(thisDir,r'2013-09-17_LE72270652013260CUB01_BOA.bsq') +Img_2013_10_03_LE72270652013276CUB00_BOA = os.path.join(thisDir,r'2013-10-03_LE72270652013276CUB00_BOA.bsq') +Img_2013_10_11_LC82270652013284LGN00_BOA = os.path.join(thisDir,r'2013-10-11_LC82270652013284LGN00_BOA.bsq') +Img_2013_12_06_LE72270652013340CUB00_BOA = os.path.join(thisDir,r'2013-12-06_LE72270652013340CUB00_BOA.bsq') +Img_2013_12_14_LC82270652013348LGN00_BOA = os.path.join(thisDir,r'2013-12-14_LC82270652013348LGN00_BOA.bsq') +Img_2014_01_15_LC82270652014015LGN00_BOA = os.path.join(thisDir,r'2014-01-15_LC82270652014015LGN00_BOA.bsq') +Img_2014_03_20_LC82270652014079LGN00_BOA = os.path.join(thisDir,r'2014-03-20_LC82270652014079LGN00_BOA.bsq') +Img_2014_04_21_LC82270652014111LGN00_BOA = os.path.join(thisDir,r'2014-04-21_LC82270652014111LGN00_BOA.bsq') +Img_2014_04_29_LE72270652014119CUB00_BOA = os.path.join(thisDir,r'2014-04-29_LE72270652014119CUB00_BOA.bsq') +Img_2014_05_07_LC82270652014127LGN00_BOA = os.path.join(thisDir,r'2014-05-07_LC82270652014127LGN00_BOA.bsq') +Img_2014_05_15_LE72270652014135CUB00_BOA = os.path.join(thisDir,r'2014-05-15_LE72270652014135CUB00_BOA.bsq') +Img_2014_05_23_LC82270652014143LGN00_BOA = os.path.join(thisDir,r'2014-05-23_LC82270652014143LGN00_BOA.bsq') +Img_2014_05_31_LE72270652014151CUB00_BOA = os.path.join(thisDir,r'2014-05-31_LE72270652014151CUB00_BOA.bsq') +Img_2014_06_08_LC82270652014159LGN00_BOA = os.path.join(thisDir,r'2014-06-08_LC82270652014159LGN00_BOA.bsq') +Img_2014_06_16_LE72270652014167CUB00_BOA = os.path.join(thisDir,r'2014-06-16_LE72270652014167CUB00_BOA.bsq') +Img_2014_06_24_LC82270652014175LGN00_BOA = os.path.join(thisDir,r'2014-06-24_LC82270652014175LGN00_BOA.bsq') +Img_2014_07_02_LE72270652014183CUB00_BOA = os.path.join(thisDir,r'2014-07-02_LE72270652014183CUB00_BOA.bsq') +Img_2014_07_10_LC82270652014191LGN00_BOA = os.path.join(thisDir,r'2014-07-10_LC82270652014191LGN00_BOA.bsq') +Img_2014_07_18_LE72270652014199CUB00_BOA = os.path.join(thisDir,r'2014-07-18_LE72270652014199CUB00_BOA.bsq') +Img_2014_07_26_LC82270652014207LGN00_BOA = os.path.join(thisDir,r'2014-07-26_LC82270652014207LGN00_BOA.bsq') +Img_2014_08_03_LE72270652014215CUB00_BOA = os.path.join(thisDir,r'2014-08-03_LE72270652014215CUB00_BOA.bsq') +Img_2014_08_11_LC82270652014223LGN00_BOA = os.path.join(thisDir,r'2014-08-11_LC82270652014223LGN00_BOA.bsq') +Img_2014_08_19_LE72270652014231CUB00_BOA = os.path.join(thisDir,r'2014-08-19_LE72270652014231CUB00_BOA.bsq') +Img_2014_08_27_LC82270652014239LGN00_BOA = os.path.join(thisDir,r'2014-08-27_LC82270652014239LGN00_BOA.bsq') +Img_2014_09_04_LE72270652014247CUB00_BOA = os.path.join(thisDir,r'2014-09-04_LE72270652014247CUB00_BOA.bsq') +Img_2014_09_12_LC82270652014255LGN00_BOA = os.path.join(thisDir,r'2014-09-12_LC82270652014255LGN00_BOA.bsq') +Img_2014_09_20_LE72270652014263CUB00_BOA = os.path.join(thisDir,r'2014-09-20_LE72270652014263CUB00_BOA.bsq') +Img_2014_09_28_LC82270652014271LGN00_BOA = os.path.join(thisDir,r'2014-09-28_LC82270652014271LGN00_BOA.bsq') +Img_2014_10_06_LE72270652014279CUB00_BOA = os.path.join(thisDir,r'2014-10-06_LE72270652014279CUB00_BOA.bsq') +Img_2014_10_14_LC82270652014287LGN00_BOA = os.path.join(thisDir,r'2014-10-14_LC82270652014287LGN00_BOA.bsq') +Img_2014_11_07_LE72270652014311CUB00_BOA = os.path.join(thisDir,r'2014-11-07_LE72270652014311CUB00_BOA.bsq') +Img_2014_11_15_LC82270652014319LGN00_BOA = os.path.join(thisDir,r'2014-11-15_LC82270652014319LGN00_BOA.bsq') +Img_2014_12_17_LC82270652014351LGN00_BOA = os.path.join(thisDir,r'2014-12-17_LC82270652014351LGN00_BOA.bsq') +Img_2015_01_02_LC82270652015002LGN00_BOA = os.path.join(thisDir,r'2015-01-02_LC82270652015002LGN00_BOA.bsq') +Img_2015_01_10_LE72270652015010CUB00_BOA = os.path.join(thisDir,r'2015-01-10_LE72270652015010CUB00_BOA.bsq') +Img_2015_01_18_LC82270652015018LGN00_BOA = os.path.join(thisDir,r'2015-01-18_LC82270652015018LGN00_BOA.bsq') +Img_2015_02_03_LC82270652015034LGN00_BOA = os.path.join(thisDir,r'2015-02-03_LC82270652015034LGN00_BOA.bsq') +Img_2015_02_27_LE72270652015058CUB04_BOA = os.path.join(thisDir,r'2015-02-27_LE72270652015058CUB04_BOA.bsq') +Img_2015_03_15_LE72270652015074CUB00_BOA = os.path.join(thisDir,r'2015-03-15_LE72270652015074CUB00_BOA.bsq') +Img_2015_03_23_LC82270652015082LGN00_BOA = os.path.join(thisDir,r'2015-03-23_LC82270652015082LGN00_BOA.bsq') +Img_2015_03_31_LE72270652015090CUB00_BOA = os.path.join(thisDir,r'2015-03-31_LE72270652015090CUB00_BOA.bsq') +Img_2015_04_08_LC82270652015098LGN00_BOA = os.path.join(thisDir,r'2015-04-08_LC82270652015098LGN00_BOA.bsq') +Img_2015_04_24_LC82270652015114LGN00_BOA = os.path.join(thisDir,r'2015-04-24_LC82270652015114LGN00_BOA.bsq') +Img_2015_05_10_LC82270652015130LGN00_BOA = os.path.join(thisDir,r'2015-05-10_LC82270652015130LGN00_BOA.bsq') +Img_2015_05_18_LE72270652015138CUB00_BOA = os.path.join(thisDir,r'2015-05-18_LE72270652015138CUB00_BOA.bsq') +Img_2015_05_26_LC82270652015146LGN00_BOA = os.path.join(thisDir,r'2015-05-26_LC82270652015146LGN00_BOA.bsq') +Img_2015_06_03_LE72270652015154CUB00_BOA = os.path.join(thisDir,r'2015-06-03_LE72270652015154CUB00_BOA.bsq') +Img_2015_06_11_LC82270652015162LGN00_BOA = os.path.join(thisDir,r'2015-06-11_LC82270652015162LGN00_BOA.bsq') +Img_2015_06_19_LE72270652015170CUB00_BOA = os.path.join(thisDir,r'2015-06-19_LE72270652015170CUB00_BOA.bsq') +Img_2015_06_27_LC82270652015178LGN00_BOA = os.path.join(thisDir,r'2015-06-27_LC82270652015178LGN00_BOA.bsq') +Img_2015_07_13_LC82270652015194LGN00_BOA = os.path.join(thisDir,r'2015-07-13_LC82270652015194LGN00_BOA.bsq') +Img_2015_07_21_LE72270652015202CUB00_BOA = os.path.join(thisDir,r'2015-07-21_LE72270652015202CUB00_BOA.bsq') +Img_2015_07_29_LC82270652015210LGN00_BOA = os.path.join(thisDir,r'2015-07-29_LC82270652015210LGN00_BOA.bsq') +Img_2015_08_06_LE72270652015218CUB00_BOA = os.path.join(thisDir,r'2015-08-06_LE72270652015218CUB00_BOA.bsq') +Img_2015_08_14_LC82270652015226LGN00_BOA = os.path.join(thisDir,r'2015-08-14_LC82270652015226LGN00_BOA.bsq') +Img_2015_08_22_LE72270652015234CUB00_BOA = os.path.join(thisDir,r'2015-08-22_LE72270652015234CUB00_BOA.bsq') +Img_2015_08_30_LC82270652015242LGN00_BOA = os.path.join(thisDir,r'2015-08-30_LC82270652015242LGN00_BOA.bsq') +Img_2015_09_07_LE72270652015250ASN00_BOA = os.path.join(thisDir,r'2015-09-07_LE72270652015250ASN00_BOA.bsq') +Img_2015_09_15_LC82270652015258LGN00_BOA = os.path.join(thisDir,r'2015-09-15_LC82270652015258LGN00_BOA.bsq') +Img_2015_09_23_LE72270652015266ASN00_BOA = os.path.join(thisDir,r'2015-09-23_LE72270652015266ASN00_BOA.bsq') +Img_2015_10_01_LC82270652015274LGN00_BOA = os.path.join(thisDir,r'2015-10-01_LC82270652015274LGN00_BOA.bsq') +Img_2015_10_09_LE72270652015282ASN00_BOA = os.path.join(thisDir,r'2015-10-09_LE72270652015282ASN00_BOA.bsq') +Img_2015_10_17_LC82270652015290LGN00_BOA = os.path.join(thisDir,r'2015-10-17_LC82270652015290LGN00_BOA.bsq') +Img_2015_10_25_LE72270652015298ASN00_BOA = os.path.join(thisDir,r'2015-10-25_LE72270652015298ASN00_BOA.bsq') +Img_2015_11_02_LC82270652015306LGN00_BOA = os.path.join(thisDir,r'2015-11-02_LC82270652015306LGN00_BOA.bsq') +Img_2015_11_10_LE72270652015314ASN00_BOA = os.path.join(thisDir,r'2015-11-10_LE72270652015314ASN00_BOA.bsq') +re_2012_06_12 = os.path.join(thisDir,r're_2012-06-12.bsq') +re_2012_07_24 = os.path.join(thisDir,r're_2012-07-24.bsq') +re_2012_07_25 = os.path.join(thisDir,r're_2012-07-25.bsq') +re_2012_08_05 = os.path.join(thisDir,r're_2012-08-05.bsq') +re_2012_09_06 = os.path.join(thisDir,r're_2012-09-06.bsq') +re_2013_05_18 = os.path.join(thisDir,r're_2013-05-18.bsq') +re_2014_06_12 = os.path.join(thisDir,r're_2014-06-12.bsq') +re_2014_06_25 = os.path.join(thisDir,r're_2014-06-25.bsq') +re_2014_08_08 = os.path.join(thisDir,r're_2014-08-08.bsq') +re_2014_08_10 = os.path.join(thisDir,r're_2014-08-10.bsq') +re_2014_08_17 = os.path.join(thisDir,r're_2014-08-17.bsq') +re_2014_08_20 = os.path.join(thisDir,r're_2014-08-20.bsq') +re_2014_08_23 = os.path.join(thisDir,r're_2014-08-23.bsq') +re_2014_08_25 = os.path.join(thisDir,r're_2014-08-25.bsq') +re_2014_08_26 = os.path.join(thisDir,r're_2014-08-26.bsq') +re_2014_10_10 = os.path.join(thisDir,r're_2014-10-10.bsq') +re_2015_06_13 = os.path.join(thisDir,r're_2015-06-13.bsq') +re_2015_06_19 = os.path.join(thisDir,r're_2015-06-19.bsq') +re_2015_07_13 = os.path.join(thisDir,r're_2015-07-13.bsq') +re_2015_07_17 = os.path.join(thisDir,r're_2015-07-17.bsq') +re_2015_07_30 = os.path.join(thisDir,r're_2015-07-30.bsq') +re_2015_08_04 = os.path.join(thisDir,r're_2015-08-04.bsq') +re_2015_08_10 = os.path.join(thisDir,r're_2015-08-10.bsq') +re_2015_09_18 = os.path.join(thisDir,r're_2015-09-18.bsq') + + + +# self-test to check each file path attribute +for a in dir(sys.modules[__name__]): + v = getattr(sys.modules[__name__], a) + if type(v) == str and os.path.isabs(v): + if not os.path.exists(v): + sys.stderr.write('Missing package attribute file: {}={}'.format(a, v)) + +# cleanup +del thisDir, a, v \ No newline at end of file diff --git a/example/__init__.py b/example/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fef66b5a2a716b02ab2baa874dc451f6ec8d472a --- /dev/null +++ b/example/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python \ No newline at end of file diff --git a/make/make.py b/make/make.py index e0cd4883d729d737f99f4a48eec0e5e6e3a0e5fb..675208f1869c853b8c4d4a7d6444cca936cde8b6 100644 --- a/make/make.py +++ b/make/make.py @@ -17,6 +17,69 @@ from timeseriesviewer import DIR_UI, file_search jp = os.path.join +def createFilePackage(dirData): + import numpy as np + from timeseriesviewer import DIR_REPO + pathInit = jp(dirData, '__init__.py') + code = ['#!/usr/bin/env python', + '"""', + 'This file is auto-generated.', + 'Do not edit manually, as changes might get overwritten.', + '"""', + '__author__ = "auto-generated by {}"'.format(os.path.relpath(__file__, DIR_REPO)), + '__date__ = "{}"'.format(np.datetime64('now')), + '', + 'import sys, os', + '', + 'thisDir = os.path.dirname(__file__)', + '# File path attributes:', + ] + files = file_search(dirData, '*', recursive=True) + + filePathAttributes = set() + def addFiles(files, comment=None, numberPrefix='File'): + if len(files) > 0: + if comment: + code.append('# '+comment) + for f in files: + an, ext = os.path.splitext(os.path.basename(f)) + if re.search('^\d', an): + an = numberPrefix+an + an = re.sub(r'[-.]', '_',an) + + assert an not in filePathAttributes + relpath = os.path.relpath(f, dirData) + code.append("{} = os.path.join(thisDir,r'{}')".format(an, relpath)) + filePathAttributes.add(an) + code.append('\n') + + raster = [f for f in files if re.search('.*\.(bsq|bip|bil|tif|tiff)$', f)] + vector = [f for f in files if re.search('.*\.(shp|kml|kmz)$', f)] + + addFiles(raster, 'Raster files:', numberPrefix='Img_') + addFiles(vector, 'Vector files:', numberPrefix='Shp_') + + #add self-test for file existence + if len(filePathAttributes) > 0: + code.extend( + [ + "", + "# self-test to check each file path attribute", + "for a in dir(sys.modules[__name__]):", + " v = getattr(sys.modules[__name__], a)", + " if type(v) == str and os.path.isabs(v):" , + " if not os.path.exists(v):", + " sys.stderr.write('Missing package attribute file: {}={}'.format(a, v))", + "", + "# cleanup", + "del thisDir ", + ] + ) + + open(pathInit, 'w').write('\n'.join(code)) + print('Created '+pathInit) + + def getDOMAttributes(elem): assert isinstance(elem, QDomElement) values = dict() @@ -374,6 +437,8 @@ def createCreditsHTML(): if __name__ == '__main__': icondir = jp(DIR_UI, *['icons']) pathQrc = jp(DIR_UI,'resources.qrc') + from timeseriesviewer import DIR_EXAMPLES + if False: from qgis import * from qgis.core import * @@ -393,7 +458,8 @@ if __name__ == '__main__': qgsApp.setPrefixPath(PATH_QGS, True) qgsApp.initQgis() - pathDirTestData = r'C:\Users\geo_beja\Repositories\QGIS_Plugins\SenseCarbonTSViewer\example' + + pathDirTestData = os.path.join(DIR_EXAMPLES,'Images') #path Novo Progresso site L7/L8/RE time series #pathTS = r'C:\Users\geo_beja\Repositories\QGIS_Plugins\SenseCarbonTSViewer\make\testdata_sources2.txt' pathTS = r'C:\Users\geo_beja\Repositories\QGIS_Plugins\SenseCarbonTSViewer\make\testdata_sources.txt' @@ -406,6 +472,11 @@ if __name__ == '__main__': createTestData(pathDirTestData, pathTS,subset, crs, drv='ENVI') exit(0) + if True: + + # update __init__.py of testdata directories + d = pathDirTestData = os.path.join(DIR_EXAMPLES,'Images') + createFilePackage(d) if False: createCreditsHTML() diff --git a/timeseriesviewer/main.py b/timeseriesviewer/main.py index 954ccf83e1dfd8dc6c7ab122815c86bbebe272b1..5a8747c52df0b667cc3cbbb4ab11999c5c248240 100644 --- a/timeseriesviewer/main.py +++ b/timeseriesviewer/main.py @@ -83,10 +83,18 @@ class SpatialExtent(QgsRectangle): crs = mapCanvas.mapSettings().destinationCrs() return SpatialExtent(crs, extent) + @staticmethod + def fromMapLayer(lyr): + assert isinstance(lyr, QgsMapLayer) + extent = lyr.extent() + crs = lyr.crs() + return SpatialExtent(crs, extent) + + def __init__(self, crs, *args): - assert isinstance(crs, QgsCoordinateReferenceSystem) - super(SpatialExtent, self).__init__(*args) - self.mCrs = crs + assert isinstance(crs, QgsCoordinateReferenceSystem) + super(SpatialExtent, self).__init__(*args) + self.mCrs = crs def setCrs(self, crs): assert isinstance(crs, QgsCoordinateReferenceSystem) @@ -222,34 +230,89 @@ class QgisTsvBridge(QObject): def instance(): return QgisTsvBridge._instance - def __init__(self, iface, TSV_UI): + def __init__(self, iface, TSV): super(QgisTsvBridge, self).__init__() assert QgisTsvBridge._instance is None + assert isinstance(TSV, TimeSeriesViewer) assert isinstance(iface, QgisInterface) self.iface = iface - self.ui = TSV_UI + self.TSV = TSV + self.ui = self.TSV.ui + self.SpatTempVis = self + self.syncBlocked = False + from timeseriesviewer.ui.widgets import TimeSeriesViewerUI assert isinstance(self.ui, TimeSeriesViewerUI) self.cbQgsVectorLayer = self.ui.dockRendering.cbQgsVectorLayer self.gbQgsVectorLayer = self.ui.dockRendering.gbQgsVectorLayer self.qgsMapCanvas = self.iface.mapCanvas() + assert isinstance(self.qgsMapCanvas, QgsMapCanvas) + + self.qgsMapCanvas.extentsChanged.connect(self.syncTsvWithQgs) + self.qgsMapCanvas.destinationCrsChanged.connect(self.syncTsvWithQgs) + assert isinstance(self.cbQgsVectorLayer, QgsMapLayerComboBox) assert isinstance(self.gbQgsVectorLayer, QgsCollapsibleGroupBox) - assert isinstance(self.qgsMapCanvas, QgsMapCanvas) - - self.cbSyncQgsMapCenter = self.ui.dockNavigation.cbSyncQgsMapCenter - self.cbSyncQgsMapExtent = self.ui.dockNavigation.cbSyncQgsMapExtent - self.cbSyncQgsCRS = self.ui.dockNavigation.cbSyncQgsCRS - for cb in [self.cbSyncQgsMapCenter, self.cbSyncQgsMapExtent, self.cbSyncQgsCRS]: - assert isinstance(cb, QCheckBox) - self.cbSyncQgsMapExtent.clicked.connect(lambda : self.onSpatialSyncChanged()) + self.TSV.spatialTemporalVis.sigSpatialExtentChanged.connect(self.syncQgsWithTsv) self.cbQgsVectorLayer.layerChanged.connect(self.onQgsVectorLayerChanged) - def onSpatialSyncChanged(self): - dprint('QgisTsvBridge: spatial sync changed') - s = "" + + def syncTsvWithQgs(self, *args): + if self.syncBlocked: + return + syncState = self.ui.dockNavigation.qgsSyncState() + if any(syncState.values()): + self.syncBlocked = True + print(('# QGIS -> TSV#', syncState)) + self.syncBlocked = True + QTimer.singleShot(500, lambda: self.unblock()) + tsvExt = self.TSV.spatialTemporalVis.extent + qgsExt = SpatialExtent.fromMapCanvas(self.qgsMapCanvas) + newExtent = self.newExtent(tsvExt, syncState, qgsExt) + self.TSV.spatialTemporalVis.setSpatialExtent(newExtent) + self.syncBlocked = False + + pass + + + def syncQgsWithTsv(self, spatialExtent): + + if self.syncBlocked: + return + + + syncState = self.ui.dockNavigation.qgsSyncState() + if any(syncState.values()): + print(('# TSV -> QGIS #', syncState)) + self.syncBlocked = True + QTimer.singleShot(500, lambda: self.unblock()) + tsvExt = self.TSV.spatialTemporalVis.extent + qgsExt = SpatialExtent.fromMapCanvas(self.qgsMapCanvas) + newExtent = self.newExtent(qgsExt, syncState, tsvExt) + self.qgsMapCanvas.setDestinationCrs(newExtent.crs()) + self.qgsMapCanvas.setExtent(newExtent) + self.syncBlocked = False + + #QTimer.singleShot(500, lambda : self.unblock()) + def unblock(self): + self.syncBlocked = False + + def newExtent(self, oldExtent, syncState, newExtent): + + crs = newExtent.crs() if syncState['crs'] else oldExtent.crs() + extent = oldExtent + if syncState['extent']: + extent = newExtent.toCrs(crs) + elif syncState['center']: + import copy + extent = copy.copy(oldExtent) + extent.setCenter(newExtent.center(), newExtent.crs()) + + return extent + + def onQgsVectorLayerChanged(self, lyr): dprint('QgisTsvBridge: selected Qgs Vector layer changed') s = "" @@ -386,7 +449,7 @@ class MapView(QObject): class TimeSeriesDatumView(QObject): - sigExtentsChanged = pyqtSignal(SpatialExtent) + sigSpatialExtentChanged = pyqtSignal(SpatialExtent) sigRenderProgress = pyqtSignal(int,int) sigLoadingStarted = pyqtSignal(MapView, TimeSeriesDatum) sigLoadingFinished = pyqtSignal(MapView, TimeSeriesDatum) @@ -476,11 +539,11 @@ class TimeSeriesDatumView(QObject): canvas = TsvMapCanvas(self, mapView, parent=self.ui) canvas.setFixedSize(self.subsetSize) - canvas.extentsChanged.connect(lambda : self.sigExtentsChanged.emit(canvas.spatialExtent())) + canvas.extentsChanged.connect(lambda : self.sigSpatialExtentChanged.emit(canvas.spatialExtent())) canvas.renderStarting.connect(lambda : self.sigLoadingStarted.emit(mapView, self.TSD)) canvas.mapCanvasRefreshed.connect(lambda: self.sigLoadingFinished.emit(mapView, self.TSD)) canvas.sigShowProfiles.connect(mapView.sigShowProfiles.emit) - + canvas.sigSpatialExtentChanged.connect(mapView.sigSpatialExtentChanged.emit) self.mapCanvases[mapView] = canvas self.L.insertWidget(self.wOffset + i, canvas) @@ -505,6 +568,7 @@ class SpatialTemporalVisualization(QObject): sigLoadingFinished = pyqtSignal(TimeSeriesDatumView, MapView) sigShowProfiles = pyqtSignal(QgsPoint, QgsCoordinateReferenceSystem) sigShowMapLayerInfo = pyqtSignal(dict) + sigSpatialExtentChanged = pyqtSignal(SpatialExtent) def __init__(self, timeSeriesViewer): assert isinstance(timeSeriesViewer, TimeSeriesViewer) @@ -518,10 +582,12 @@ class SpatialTemporalVisualization(QObject): self.dockMapViews = self.ui.dockMapViews self.MVC = MapViewCollection(self) self.MVC.sigShowProfiles.connect(self.sigShowProfiles.emit) + self.timeSeriesDateViewCollection = TimeSeriesDateViewCollection(self) self.timeSeriesDateViewCollection.sigResizeRequired.connect(self.adjustScrollArea) self.timeSeriesDateViewCollection.sigLoadingStarted.connect(self.ui.dockRendering.addStartedWork) self.timeSeriesDateViewCollection.sigLoadingFinished.connect(self.ui.dockRendering.addFinishedWork) + self.timeSeriesDateViewCollection.sigSpatialExtentChanged.connect(self.onSpatialExtentChanged) self.TS.sigTimeSeriesDatesAdded.connect(self.timeSeriesDateViewCollection.addDates) self.TS.sigTimeSeriesDatesRemoved.connect(self.timeSeriesDateViewCollection.removeDates) #add dates, if already existing @@ -578,10 +644,13 @@ class SpatialTemporalVisualization(QObject): #todo: remove views def setSpatialExtent(self, extent): - self.extent = extent if extent: self.timeSeriesDateViewCollection.setSpatialExtent(extent) + self.onSpatialExtentChanged(extent) + def onSpatialExtentChanged(self, extent): + self.extent = extent + self.sigSpatialExtentChanged.emit(extent) def navigateToTSD(self, TSD): assert isinstance(TSD, TimeSeriesDatum) @@ -608,6 +677,7 @@ class TimeSeriesDateViewCollection(QObject): sigLoadingStarted = pyqtSignal(MapView, TimeSeriesDatum) sigLoadingFinished = pyqtSignal(MapView, TimeSeriesDatum) sigShowProfiles = pyqtSignal(QgsPoint, QgsCoordinateReferenceSystem) + sigSpatialExtentChanged = pyqtSignal(QgsRectangle) def __init__(self, STViz): assert isinstance(STViz, SpatialTemporalVisualization) @@ -665,10 +735,17 @@ class TimeSeriesDateViewCollection(QObject): def setFocusView(self, tsd): self.focusView = tsd + def onSpatialExtentChanged(self, extent): + for tsdview in self.orderedViews(): + tsdview.setSpatialExtent(extent) + self.sigSpatialExtentChanged.emit(extent) + def setSpatialExtent(self, extent): for tsdview in self.orderedViews(): tsdview.setSpatialExtent(extent) + + def orderedViews(self): #returns the if self.focusView is not None: @@ -703,7 +780,7 @@ class TimeSeriesDateViewCollection(QObject): tsdView = TimeSeriesDatumView(tsd, self, self.STViz.MVC, parent=self.ui) tsdView.setSubsetSize(self.subsetSize) - tsdView.sigExtentsChanged.connect(self.setSpatialExtent) + tsdView.sigSpatialExtentChanged.connect(self.onSpatialExtentChanged) tsdView.sigLoadingStarted.connect(self.sigLoadingStarted.emit) tsdView.sigLoadingFinished.connect(self.sigLoadingFinished.emit) tsdView.sigVisibilityChanged.connect(lambda: self.STViz.adjustScrollArea()) @@ -857,9 +934,6 @@ class MapViewCollection(QObject): btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) - def setSpatialExtent(self, extent): - for mv in self.mapViewsDefinitions: - mv.setSpatialExtent(extent) def showMapViewDefinition(self, mapViewDefinition): assert mapViewDefinition in self.mapViewsDefinitions @@ -916,10 +990,6 @@ class TimeSeriesViewer: from timeseriesviewer.ui.widgets import TimeSeriesViewerUI self.ui = TimeSeriesViewerUI() - if iface: - import timeseriesviewer - timeseriesviewer.QGIS_TSV_BRIDGE = QgisTsvBridge(iface, self.ui) - self.ui.setQgsLinkWidgets() #init empty time series self.TS = TimeSeries() @@ -948,7 +1018,7 @@ class TimeSeriesViewer: self.spatialTemporalVis.sigShowProfiles.connect(self.spectralTemporalVis.loadCoordinate) self.spectralTemporalVis.sigMoveToTSD.connect(self.spatialTemporalVis.navigateToTSD) - D.dockNavigation.sigSpatialExtentChanged.connect(self.spatialTemporalVis.setSpatialExtent) + D.dockNavigation.sigSetSpatialExtent.connect(self.spatialTemporalVis.setSpatialExtent) self.ValidatorPxX = QIntValidator(0,99999) self.ValidatorPxY = QIntValidator(0,99999) @@ -994,6 +1064,11 @@ class TimeSeriesViewer: self.canvasCrs = QgsCoordinateReferenceSystem() + if iface: + import timeseriesviewer + timeseriesviewer.QGIS_TSV_BRIDGE = QgisTsvBridge(iface, self) + self.ui.setQgsLinkWidgets() + def loadImageFiles(self, files): assert isinstance(files, list) @@ -1223,6 +1298,8 @@ def showRGBData(data): def run_tests(): + + if False: pathImg = r'O:\SenseCarbonProcessing\BJ_NOC\01_RasterData\00_VRTs\02_Cutted\2014-07-26_LC82270652014207LGN00_BOA.vrt' diff --git a/timeseriesviewer/tests.py b/timeseriesviewer/tests.py index 6c9b1d5d708d05fc70b01b03155717174b12bd7f..440093a1e3eb96cd9c20f5ce3dc81287a602039a 100644 --- a/timeseriesviewer/tests.py +++ b/timeseriesviewer/tests.py @@ -57,6 +57,94 @@ def test_gui(): return pass +class QgisFake(QgisInterface): + + def __init__(self, *args): + super(QgisFake, self).__init__(*args) + + self.canvas = QgsMapCanvas() + self.canvas.blockSignals(False) + print(self.canvas) + self.canvas.setCrsTransformEnabled(True) + self.canvas.setCanvasColor(Qt.black) + self.canvas.extentsChanged.connect(self.testSlot) + self.layerTreeView = QgsLayerTreeView() + self.rootNode =QgsLayerTreeGroup() + self.treeModel = QgsLayerTreeModel(self.rootNode) + self.layerTreeView.setModel(self.treeModel) + self.bridge = QgsLayerTreeMapCanvasBridge(self.rootNode, self.canvas) + self.bridge.setAutoSetupOnFirstLayer(True) + self.ui = QMainWindow() + mainFrame = QFrame() + + self.ui.setCentralWidget(mainFrame) + self.ui.setWindowTitle('Fake QGIS') + l = QHBoxLayout() + l.addWidget(self.layerTreeView) + l.addWidget(self.canvas) + mainFrame.setLayout(l) + self.ui.setCentralWidget(mainFrame) + self.lyrs = [] + self.createActions() + + def testSlot(self, *args): + #print('--canvas changes--') + s = "" + + def addVectorLayer(selfpath, basename, providerkey): + pass + + def addRasterLayer(self, path, baseName=''): + l = QgsRasterLayer(path, loadDefaultStyleFlag=True) + self.lyrs.append(l) + QgsMapLayerRegistry.instance().addMapLayer(l, True) + self.rootNode.addLayer(l) + self.bridge.setCanvasLayers() + return + + cnt = len(self.canvas.layers()) + + self.canvas.setLayerSet([QgsMapCanvasLayer(l)]) + l.dataProvider() + if cnt == 0: + self.canvas.mapSettings().setDestinationCrs(l.crs()) + self.canvas.setExtent(l.extent()) + from timeseriesviewer.main import SpatialExtent + + spatialExtent = SpatialExtent.fromMapLayer(l) + #self.canvas.blockSignals(True) + self.canvas.setDestinationCrs(spatialExtent.crs()) + self.canvas.setExtent(spatialExtent) + #self.blockSignals(False) + self.canvas.refresh() + + self.canvas.refresh() + + def createActions(self): + m = self.ui.menuBar().addAction('Add Vector') + m = self.ui.menuBar().addAction('Add Raster') + + def mapCanvas(self): + return self.canvas + +def test_qgisbridge(): + from timeseriesviewer.main import TimeSeriesViewer + from timeseriesviewer import PATH_EXAMPLE_TIMESERIES + + fakeQGIS = QgisFake() + + S = TimeSeriesViewer(fakeQGIS) + S.ui.show() + S.run() + + fakeQGIS.ui.show() + import example.Images + fakeQGIS.addRasterLayer(example.Images.Img_2014_08_03_LE72270652014215CUB00_BOA) + S.loadImageFiles([example.Images.Img_2014_01_15_LC82270652014015LGN00_BOA]) + s = "" + + + def test_component(): pass @@ -84,7 +172,8 @@ if __name__ == '__main__': qgsApp.initQgis() #run tests - if True: test_gui() + if True: test_qgisbridge() + if False: test_gui() if False: test_component() diff --git a/timeseriesviewer/ui/docks.py b/timeseriesviewer/ui/docks.py index 83daa54d0c8e2ecdaa6e097b4acf06e7ae3a4d2a..d689a3eb8d2e6f6a683a7578527be612ce67a54b 100644 --- a/timeseriesviewer/ui/docks.py +++ b/timeseriesviewer/ui/docks.py @@ -106,21 +106,32 @@ class NavigationDockUI(TsvDockWidgetBase, load('navigationdock.ui')): #default: disable QgsSync box self.gbSyncQgs.setEnabled(False) - self.btnCrs.crsChanged.connect(self.sigCrsChanged.emit) + self.btnCrs.crsChanged.connect(self.sigSetCrs.emit) self.btnCrs.crsChanged.connect(self.onCrsUpdated) - self.cbSyncQgsMapExtent.clicked.connect(self.qgsSyncStateChanged) - self.cbSyncQgsMapCenter.clicked.connect(self.qgsSyncStateChanged) - self.cbSyncQgsCRS.clicked.connect(self.qgsSyncStateChanged) + self.syncStateWidgets = [self.cbSyncQgsMapExtent, self.cbSyncQgsMapCenter, self.cbSyncQgsCRS] self.spatialExtentWidgets = [self.spinBoxExtentCenterX, self.spinBoxExtentCenterY, self.spinBoxExtentWidth, self.spinBoxExtentHeight] + for sb in self.spatialExtentWidgets: - sb.valueChanged.connect(lambda: self.sigSpatialExtentChanged.emit(self.spatialExtent())) + sb.valueChanged.connect(self.onExtentDefinitionChanges) + for cb in self.syncStateWidgets: + cb.clicked.connect(self.onExtentDefinitionChanges) + self.connectTimeSeries(None) + def onExtentDefinitionChanges(self): + if self.cbSyncQgsMapExtent.isChecked(): + self.cbSyncQgsMapCenter.setEnabled(False) + self.cbSyncQgsMapCenter.setChecked(True) + else: + self.cbSyncQgsMapCenter.setEnabled(True) + + self.sigSetSpatialExtent.emit(self.spatialExtent()) + def connectTimeSeries(self, TS): self.TS = TS self.timeSeriesInitialized = False @@ -137,14 +148,17 @@ class NavigationDockUI(TsvDockWidgetBase, load('navigationdock.ui')): if not self.timeSeriesInitialized: self.setSpatialExtent(self.TS.getMaxSpatialExtent(self.crs())) self.timeSeriesInitialized = True - self.sigSpatialExtentChanged.emit(self.spatialExtent()) + self.sigSetSpatialExtent.emit(self.spatialExtent()) - def qgsSyncStateChanged(self, *args): - s = "" + def qgsSyncState(self): + return {'center':self.cbSyncQgsMapCenter.isChecked(), + 'extent':self.cbSyncQgsMapExtent.isChecked(), + 'crs':self.cbSyncQgsCRS.isChecked()} + - sigCrsChanged = pyqtSignal(QgsCoordinateReferenceSystem) + sigSetCrs = pyqtSignal(QgsCoordinateReferenceSystem) def setCrs(self, crs): assert isinstance(crs, QgsCoordinateReferenceSystem) self.btnCrs.setCrs(crs) @@ -157,8 +171,9 @@ class NavigationDockUI(TsvDockWidgetBase, load('navigationdock.ui')): def onCrsUpdated(self, crs): self.gbCrs.setTitle(crs.authid()) self.textBoxCRSInfo.setPlainText(crs.toWkt()) + self.sigSetCrs.emit(self.crs()) - sigSpatialExtentChanged = pyqtSignal(SpatialExtent) + sigSetSpatialExtent = pyqtSignal(SpatialExtent) def spatialExtent(self): crs = self.crs() @@ -192,7 +207,7 @@ class NavigationDockUI(TsvDockWidgetBase, load('navigationdock.ui')): self._blockSignals(states) if extent != old: - self.sigSpatialExtentChanged.emit(extent) + self.sigSetSpatialExtent.emit(extent) def _blockSignals(self, widgets, block=True): states = dict() diff --git a/timeseriesviewer/ui/widgets.py b/timeseriesviewer/ui/widgets.py index 3dd4258b8fd53f0570bd2e5f929b028fb6b90c31..2381f27627c36d5099777534d636e8cbe1d29240 100644 --- a/timeseriesviewer/ui/widgets.py +++ b/timeseriesviewer/ui/widgets.py @@ -43,10 +43,11 @@ class TsvScrollArea(QScrollArea): class TsvMapCanvas(QgsMapCanvas): - + from timeseriesviewer.main import SpatialExtent saveFileDirectories = dict() #sigRendererChanged = pyqtSignal(QgsRasterRenderer) sigShowProfiles = pyqtSignal(QgsPoint, QgsCoordinateReferenceSystem) + sigSpatialExtentChanged = pyqtSignal(SpatialExtent) def __init__(self, tsdView, mapView, parent=None): super(TsvMapCanvas, self).__init__(parent=parent) @@ -62,7 +63,8 @@ class TsvMapCanvas(QgsMapCanvas): self.setCanvasColor(SETTINGS.value('CANVAS_BACKGROUND_COLOR', QColor(0, 0, 0))) self.setContextMenuPolicy(Qt.DefaultContextMenu) - self.qgsInteraction = QgisTsvBridge.instance() + self.extentsChanged.connect(lambda : self.sigSpatialExtentChanged.emit(self.spatialExtent())) + #self.scrollAreaContent = tsdView.TSDVC.STViz.targetLayout.parentWidget() #self.viewport = tsdView.TSDVC.STViz.targetLayout.parentWidget().parentWidget()