Skip to content
Snippets Groups Projects
make.py 19 KiB
Newer Older
Benjamin Jakimow's avatar
Benjamin Jakimow committed
#from qgis import *
#from qgis.core import *
#from qgis.gui import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtSvg import *
from PyQt5.QtXml import *
Benjamin Jakimow's avatar
Benjamin Jakimow committed
from osgeo import gdal
Benjamin Jakimow's avatar
Benjamin Jakimow committed
from timeseriesviewer import DIR_UI, DIR_REPO
from timeseriesviewer.utils import file_search, jp
def createFilePackage(dirData, recursive=True):
    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=recursive)

    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))
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                if re.search(r'^\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')

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    raster = [f for f in files if re.search(r'.*\.(bsq|bip|bil|tif|tiff)$', f)]
    vector = [f for f in files if re.search(r'.*\.(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, a, v ",
        ]
        )

    open(pathInit, 'w').write('\n'.join(code))
    print('Created '+pathInit)


def getDOMAttributes(elem):
    assert isinstance(elem, QDomElement)
    values = dict()
    attributes = elem.attributes()
    for a in range(attributes.count()):
        attr = attributes.item(a)
        values[str(attr.nodeName())] = attr.nodeValue()
    return values

def createTestData(dirTestData, pathTS, subsetRectangle, crs, drv=None):
    lines = open(pathTS).readlines()
    import tempfile, random
    from timeseriesviewer.main import TimeSeries, TimeSeriesDatum
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    from qgis.core import QgsRectangle, QgsPoint, QgsPointXY, QgsCoordinateReferenceSystem

    max_offset = 0 #in %


    assert isinstance(subsetRectangle, QgsRectangle)
    assert isinstance(crs, QgsCoordinateReferenceSystem)
    TS = TimeSeries()
    TS.loadFromFile(pathTS)

    sw = subsetRectangle.width()
    sh = subsetRectangle.height()

    max_offset_x = sw / 100 * max_offset
    max_offset_y = sw / 100 * max_offset
    center = subsetRectangle.center()

    if not os.path.exists(dirTestData):
        os.mkdir(dirTestData)
    dirImages = os.path.join(dirTestData, 'Images')
    if not os.path.exists(dirImages):
        os.mkdir(dirImages)
    def random_offset():
        offset_x = random.randrange(-max_offset_x, max_offset_x) if max_offset_x > 0 else 0
        offset_y = random.randrange(-max_offset_y, max_offset_y) if max_offset_y > 0 else 0
        return offset_x, offset_y

    drvMEM = gdal.GetDriverByName('MEM')

    from timeseriesviewer.main import transformGeometry
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    for TSD in TS.mTSDs:
        assert isinstance(TSD, TimeSeriesDatum)

        UL = QgsPointXY(subsetRectangle.xMinimum() + ox,
                      subsetRectangle.yMaximum() + oy)
        LR = QgsPointXY(subsetRectangle.xMaximum() + ox,
                      subsetRectangle.yMinimum() + oy)
        UL = transformGeometry(UL, crs, TSD.crs)
        LR = transformGeometry(LR, crs, TSD.crs)
        BBOX = QgsRectangle(UL, LR)
        if not BBOX.intersects(TSD.getBoundingBox()):
            print('Please note: no intersection with BBOX: '+TSD.pathImg)
        #crop src dataset to BBOX
        #for this we use GDAL
        filesToCopy = [f for f in [TSD.pathImg, TSD.pathMsk] if f is not None and os.path.exists(f)]
        for pathSrc in filesToCopy:
            dsSrc = gdal.Open(pathSrc)
            assert isinstance(dsSrc, gdal.Dataset)
            proj = dsSrc.GetProjection()
            trans = list(dsSrc.GetGeoTransform())
            trans[0] = UL.x()
            trans[3] = UL.y()
            nsDst = int(BBOX.width() / TSD.lyrImg.rasterUnitsPerPixelX())
            nlDst = int(BBOX.height() / TSD.lyrImg.rasterUnitsPerPixelY())
            dsDst = drvMEM.Create('', nsDst, nlDst, dsSrc.RasterCount, eType = dsSrc.GetRasterBand(1).DataType)
            assert isinstance(dsDst, gdal.Dataset)
            dsDst.SetProjection(proj)
            dsDst.SetGeoTransform(trans)
            wo = gdal.WarpOptions()
            r = gdal.Warp(dsDst, dsSrc)
            assert r > 0

            drvDst = gdal.GetDriverByName(drv) if drv is not None else dsSrc.GetDriver()
            #try to retireve an extension
            pathDst = os.path.join(dirImages, os.path.splitext(os.path.basename(pathSrc))[0])
            ext = drvDst.GetMetadata_Dict().get('DMD_EXTENSION','')
            if ext == '':
                ext = LUT_EXT.get(drvDst.ShortName, '')
            if not pathDst.endswith(ext):
                pathDst += ext
            print('Write {}'.format(pathDst))
            drvDst.CreateCopy(pathDst, dsDst)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
def compile_rc_files(ROOT, targetDir=None):
    #find ui files
    ui_files = file_search(ROOT, '*.ui', recursive=True)
    qrcs = set()

    doc = QDomDocument()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    reg = re.compile(r'(?<=resource=")[^"]+\.qrc(?=")')

    for ui_file in ui_files:
        pathDir = os.path.dirname(ui_file)
        doc.setContent(QFile(ui_file))
        includeNodes = doc.elementsByTagName('include')
        for i in range(includeNodes.count()):
            attr = getDOMAttributes(includeNodes.item(i).toElement())
            if 'location' in attr.keys():
                print((ui_file, str(attr['location'])))
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                qrcs.add((pathDir, str(attr['location'])))

    #compile Qt resource files
    #resourcefiles = file_search(ROOT, '*.qrc', recursive=True)
    resourcefiles = list(qrcs)
    assert len(resourcefiles) > 0

    shell_cmds = []
    subprocess_args = []
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    for root_dir, f in resourcefiles:
        #dn = os.path.dirname(f)
        pathQrc = os.path.normpath(jp(root_dir, f))
        if not os.path.exists(pathQrc):
            print('Resource file does not exist: {}'.format(pathQrc))
            continue
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        bn = os.path.basename(pathQrc)

        if isinstance(targetDir, str):
            dn = targetDir
        else:
            dn = os.path.dirname(pathQrc)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        bn = os.path.splitext(bn)[0]
        pathPy = os.path.join(dn, bn+'.py' )
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        cmd = 'pyrcc5 -o {} {}'.format(pathPy, pathQrc)
        print(cmd)
        os.system(cmd)
def fileNeedsUpdate(file1, file2):
    if not os.path.exists(file2):
        return True
    else:
        if not os.path.exists(file1):
            return True
        else:
            return os.path.getmtime(file1) > os.path.getmtime(file2)

def svg2png(pathDir, overwrite=False, mode='INKSCAPE', filterFile=None):
    """
    Converts SVG files into PNG raster images
    :param pathDir:
    :param overwrite:
    :param mode:
    :return:
    """
    assert mode in ['INKSCAPE', 'WEBKIT', 'SVG']

    svgs = file_search(pathDir, '*.svg')
    if filterFile is not None:
        print('use file filter')
        lines = open(filterFile).readlines()
        lines = [l.strip() for l in lines]
        lines = [l for l in lines if not l.startswith('#') or len(l) == 0]
        svgs = [f for f in svgs if
                f in lines or os.path.basename(f) in lines]

    if len(svgs) == 0:
        print('No SVGs to convert')
        return
    for pathSvg in svgs:
        dn = os.path.dirname(pathSvg)
        bn, _ = os.path.splitext(os.path.basename(pathSvg))
        pathPng = jp(dn, bn+'.png')

        if mode == 'SVG':
            renderer = QSvgRenderer(pathSvg)
            doc_size = renderer.defaultSize() # size in px
            img = QImage(doc_size, QImage.Format_ARGB32)
            #img.fill(0xaaA08080)
            painter = QPainter(img)
            renderer.render(painter)
            painter.end()
            if overwrite or not os.path.exists(pathPng):
                img.save(pathPng, quality=100)
            del painter, renderer
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            """
            elif mode == 'WEBKIT':
                page = QWebPage()
                frame = page.mainFrame()
                f = QFile(pathSvg)
                if f.open(QFile.ReadOnly | QFile.Text):
                    textStream = QTextStream(f)
                    svgData = textStream.readAll()
                    f.close()
    
                qba = QByteArray(str(svgData))
                frame.setContent(qba,"image/svg+xml")
                page.setViewportSize(frame.contentsSize())
    
                palette = page.palette()
                background_color = QColor(50,0,0,50)
                palette.setColor(QPalette.Window, background_color)
                brush = QBrush(background_color)
                palette.setBrush(QPalette.Window, brush)
                page.setPalette(palette)
    
                img = QImage(page.viewportSize(), QImage.Format_ARGB32)
                img.fill(background_color) #set transparent background
                painter = QPainter(img)
                painter.setBackgroundMode(Qt.OpaqueMode)
                #print(frame.renderTreeDump())
                frame.render(painter)
                painter.end()
    
                if overwrite or not os.path.exists(pathPng):
                    print('Save {}...'.format(pathPng))
                    img.save(pathPng, quality=100)
                del painter, frame, img, page
                s  =""
            """
            if fileNeedsUpdate(pathSvg, pathPng):
                if sys.platform == 'darwin':
                    cmd = ['inkscape']
                else:
                    dirInkscape = r'C:\Program Files\Inkscape'
                    assert os.path.isdir(dirInkscape)
                    cmd = [jp(dirInkscape,'inkscape')]
                cmd.append('--file={}'.format(pathSvg))
                cmd.append('--export-png={}'.format(pathPng))
                from subprocess import PIPE
                p = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
                output, err = p.communicate()
                rc = p.returncode
                print('Saved {}'.format(pathPng))
                if err != '':
                    buggySvg.append((pathSvg, err))

    if len(buggySvg) > 0:
        six._print('SVG Errors')
        for t in buggySvg:
            pathSvg, error = t
            six._print(pathSvg, error, file=sys.stderr)
    s = ""
def file2qrc(icondir, pathQrc, qrcPrefix='timeseriesviewer', fileExtension='.png'):
    pathQrc = os.path.abspath(pathQrc)
    dirQrc = os.path.dirname(pathQrc)
    app = QApplication([])
    assert os.path.exists(pathQrc)

    #create the new RCC
    doc = QDomDocument('RCC')
    if str(doc.toString()) == '':
        doc.appendChild(doc.createElement('RCC'))
    root = doc.documentElement()
    fileOfInterest = set()
    #add files that are already included in the QRC file
    fileNodes = doc.elementsByTagName('file')
    for i in range(fileNodes.count()):
        fileNode = fileNodes.item(i).toElement()

        file = str(fileNode.childNodes().item(0).nodeValue())
        #if file.lower().endswith(fileExtension):
        fileOfInterest.add(file)
        if fileNode.hasAttributes():
            attributes = {}
            for i in range(fileNode.attributes().count()):
                attr = fileNode.attributes().item(i).toAttr()
                attributes[str(attr.name())] = str(attr.value())
            fileAttributes[file] = attributes

    #add new files from the icondir
    for f in  file_search(icondir, '*'+fileExtension):
        file = os.path.relpath(f, dirQrc).replace('\\','/')
        fileOfInterest.add(file)
    fileOfInterest = sorted(list(fileOfInterest))
    def elementsByTagAndProperties(elementName, attributeProperties, rootNode=None):
        assert isinstance(elementName, str)
        assert isinstance(attributeProperties, dict)
        if rootNode is None:
            rootNode = doc
        resourceNodes = rootNode.elementsByTagName(elementName)
        nodeList = []
        for i in range(resourceNodes.count()):
            resourceNode = resourceNodes.item(i).toElement()
            for aName, aValue in attributeProperties.items():
                if resourceNode.hasAttribute(aName):
                    if aValue != None:
                        assert isinstance(aValue, str)
                        if str(resourceNode.attribute(aName)) == aValue:
                            nodeList.append(resourceNode)
                    else:
                        nodeList.append(resourceNode)
    resourceNodes = elementsByTagAndProperties('qresource', {'prefix':qrcPrefix})

    if len(resourceNodes) == 0:
        resourceNode = doc.createElement('qresource')
        root.appendChild(resourceNode)
        resourceNode.setAttribute('prefix', qrcPrefix)
    elif len(resourceNodes) == 1:
        resourceNode = resourceNodes[0]
        raise NotImplementedError('Multiple resource nodes')

    #remove childs, as we have all stored in list pngFiles
    childs = resourceNode.childNodes()
    while not childs.isEmpty():
        node = childs.item(0)
        node.parentNode().removeChild(node)

    #insert new childs
    for file in fileOfInterest:
        node = doc.createElement('file')
        attributes = fileAttributes.get(file)
        if attributes:
            for k, v in attributes.items():
                node.setAttribute(k,v)
            s = 2
        node.appendChild(doc.createTextNode(file))
        resourceNode.appendChild(node)
        print(file)
def updateMetadataTxt():
    #see http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/plugins.html#plugin-metadata
    #for required metatags
    pathDst = jp(DIR_REPO, 'metadata.txt')
    pathAboutPlugin = jp(DIR_REPO, 'ABOUT_Plugin.html')
    qgis = timeseriesviewer.utils.initQgisApplication()

    import timeseriesviewer, collections
    md = collections.OrderedDict()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    with open(pathDst) as f:
        for line in f.readlines():
            parts = line.split('=')
            if len(parts) >= 2:
                md[parts[0]] = '='.join(parts[1:])

    #update/set new metadata
    md['name'] = timeseriesviewer.TITLE
    md['description'] = timeseriesviewer.DESCRIPTION.strip()
    md['about'] = timeseriesviewer.ABOUT.strip()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    md['version'] = timeseriesviewer.__version__.strip()
    md['author'] = r"Benjamin Jakimow, Geomatics Lab, Humboldt-Universität zu Berlin"
    md['email'] = "benjamin.jakimow@geo.hu-berlin.de"
    #md['changelog'] =
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    with open(pathAboutPlugin, 'r', encoding='utf-8') as f:
        aboutText =f.read()
        aboutText=aboutText.replace('\n','')

    md['experimental'] = "False"
    md['deprecated'] = "False"
    md['tags'] = "remote sensing, raster, time series"
Benjamin Jakimow's avatar
Benjamin Jakimow committed
    md['homepage'] = timeseriesviewer.HOMEPAGE
    md['repository'] = timeseriesviewer.HOMEPAGE
    md['tracker'] = timeseriesviewer.HOMEPAGE + '/issues'
    md['icon'] = r'timeseriesviewer/icon.png'
    md['category'] = 'Raster'

    lines = ['[general]']
    for k, line in md.items():
        lines.append('{}={}'.format(k, line))
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    with open(pathDst, 'w', encoding='utf-8') as f:
        f.writelines('\n'.join(lines))
        f.flush()

Benjamin Jakimow's avatar
Benjamin Jakimow committed
def make_pb_tool_cfg():
    pathPBToolCgf = r''

    lines = open(pathPBToolCgf).readlines()

    #main_dialog:


Benjamin Jakimow's avatar
Benjamin Jakimow committed
def copyQGISRessourceFile():
    if sys.platform == 'darwin':
        pathQGISRepo = r'/Users/benjamin.jakimow/Repositories/QGIS'
    else:
        pathQGISRepo = r'C:\Users\geo_beja\Repositories\QGIS'
Benjamin Jakimow's avatar
Benjamin Jakimow committed

    assert os.path.isdir(pathQGISRepo)
    dirTarget = os.path.join(DIR_REPO, *['qgisresources'])
    os.makedirs(dirTarget, exist_ok=True)
    compile_rc_files(pathQGISRepo, targetDir=dirTarget)


    #qrcFiles = file_search(pathQGISRepo, '*.qrc')

    #for qrcFile in qrcFiles:




def checkFileHeader():


    hdr = """
    # -*- coding: utf-8 -*-
    \"\"\"
    /***************************************************************************
                                  EO Time Series Viewer
                                  -------------------
            begin                : 2017-08-04
            git sha              : $Format:%H$
            copyright            : (C) 2017 by HU-Berlin
            email                : benjamin.jakimow@geo.hu-berlin.de
     ***************************************************************************/

    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/
    \"\"\"
    """
    # noinspection PyPep8Naming

    root = jp(DIR_REPO, 'timeseriesviewer')
    pyFiles = file_search(root, '*.py')

    for path in pyFiles:
        file = open(path, 'r', encoding='utf8')
        lines = file.readlines()
        file.close()

        lineFirstImport = None
        for i in range(len(lines)):
            if re.search('^[ ]*import ', lines[i]):
                lineFirstImport = i
                break

        if isinstance(lineFirstImport, int) and lineFirstImport < 50:
            pass


if __name__ == '__main__':
    if True:
        compile_rc_files(DIR_UI)