Beispiel #1
0
def read_from_file(uri: str) -> Tuple[QtXml.QDomDocument, str]:
    """Read a QGIS project (.qgs and .qgz) from a file path and returns d

    :param uri: path to the file
    :type uri: str

    :return: a tuple with XML document and the filepath.
    :rtype: Tuple[QtXml.QDomDocument, str]
    """
    doc = QtXml.QDomDocument()
    file = QFile(uri)
    if (file.exists() and file.open(QIODevice.ReadOnly | QIODevice.Text)
            and QFileInfo(file).suffix() == "qgs"):
        doc.setContent(file)
        project_path = uri

    elif file.exists() and (QFileInfo(file).suffix() == "qgz"):
        temporary_unzip = QTemporaryDir()
        temporary_unzip.setAutoRemove(False)
        with zipfile.ZipFile(uri, "r") as zip_ref:
            zip_ref.extractall(temporary_unzip.path())

        project_filename = QDir(temporary_unzip.path()).entryList(["*.qgs"])[0]
        project_path = os.path.join(temporary_unzip.path(), project_filename)
        xml = QFile(project_path)
        if xml.open(QIODevice.ReadOnly | QIODevice.Text):
            doc.setContent(xml)

    return doc, project_path
Beispiel #2
0
    def processAlgorithm(self, parameters, context, feedback):
        output_file = self.parameterAsFile(parameters, self.OUTPUT, context)

        # if no project file is specified, we create a temp file from the current project
        if not output_file:
            temp_dir = QTemporaryDir()
            temp_dir.setAutoRemove(False)
            output_file = os.path.join(temp_dir.path(),'temp_qgis_project')

        current_project = QgsProject.instance()

        # store the current path to restore it afterwards
        current_path = current_project.absoluteFilePath()
        # store the current use absolute path settings to restore it afterwards
        current_abs_path_setting = current_project.readBoolEntry('Paths','/Absolute', False)[0]

        # set use absolute path
        current_project.writeEntry('Paths','/Absolute', True)

        # write the project
        current_project.write(output_file)

        # retore initial settings
        current_project.writeEntry('Paths','/Absolute', current_abs_path_setting)
        current_project.setFileName(current_path)

        return {self.OUTPUT: output_file}
Beispiel #3
0
def read_from_database(uri: str,
                       project_registry) -> Tuple[QtXml.QDomDocument, str]:
    """Read a QGIS project stored into a (PostgreSQL) database.

    :param uri: connection string to QGIS project stored into a database.
    :type uri: str

    :return: a tuple with XML document and the filepath.
    :rtype: Tuple[QtXml.QDomDocument, str]
    """
    doc = QtXml.QDomDocument()
    # uri PG
    project_storage = project_registry.projectStorageFromUri(uri)

    temporary_zip = QTemporaryFile()
    temporary_zip.open()
    zip_project = temporary_zip.fileName()

    project_storage.readProject(uri, temporary_zip, QgsReadWriteContext())

    temporary_unzip = QTemporaryDir()
    temporary_unzip.setAutoRemove(False)
    with zipfile.ZipFile(zip_project, "r") as zip_ref:
        zip_ref.extractall(temporary_unzip.path())

    project_filename = QDir(temporary_unzip.path()).entryList(["*.qgs"])[0]
    project_path = os.path.join(temporary_unzip.path(), project_filename)
    xml = QFile(project_path)
    if xml.open(QIODevice.ReadOnly | QIODevice.Text):
        doc.setContent(xml)

    return doc, project_path
Beispiel #4
0
    def processAlgorithm(self, parameters, context, feedback):
        # This implementation writes to the project XML directly

        """
        Here is where the processing itself takes place.
        """

        # get the parameter values
        input_file = self.parameterAsFile(parameters, self.INPUT, context)
        old_layer_id = self.parameterAsString(parameters, self.OLD_LAYER_ID, context)
        new_layer = self.parameterAsLayer(parameters, self.NEW_LAYER, context)
        output_file = self.parameterAsFile(parameters, self.OUTPUT, context)

        # if the new layer is in memory, we need to save it temporarily somewhere
        if new_layer.dataProvider().name() == 'memory':
            t = QTemporaryDir()
            t.setAutoRemove(False)
            new_layer_source = os.path.join(t.path(),'t.gpkg')
            QgsVectorFileWriter.writeAsVectorFormat(new_layer,new_layer_source,"utf8",new_layer.crs(),"GPKG")
        else:
            new_layer_source = new_layer.source()

        tree = et.parse(input_file)
        root = tree.getroot()

        # Map Layers
        nodes = root.findall("projectlayers/maplayer[id='"+old_layer_id+"']/datasource")
        for node in nodes:
            node.text = new_layer_source
        if not nodes:
            feedback.reportError("No map layer with id {} found".format(old_layer_id))
        else:
            feedback.pushInfo("{} map layers replaced".format(len(nodes)))

        # Layer tree
        nodes = root.findall("layer-tree-group/layer-tree-layer[@id='"+old_layer_id+"']")
        for node in nodes:
            node.attrib['source'] = new_layer_source
        feedback.pushInfo("{} layers replaced in the tree".format(len(nodes)))

        # Legend
        nodes = root.findall("Layouts/Layout/LayoutItem/layer-tree-group/layer-tree-layer[@id='"+old_layer_id+"']")
        for node in nodes:
            node.attrib['source'] = new_layer_source
        feedback.pushInfo("{} layers replaced in layout legends the tree".format(len(nodes)))

        tree.write(output_file)

        # done !!
        return {self.OUTPUT: output_file}
Beispiel #5
0
    def processAlgorithm(self, parameters, context, feedback):

        # Get the parameter values

        input_source = self.parameterAsSource(parameters, self.INPUT, context)
        field_date = self.parameterAsString(parameters, self.FIELD_DATE,
                                            context)
        field_pressure = self.parameterAsString(parameters,
                                                self.FIELD_PRESSURE, context)
        field_rmax = self.parameterAsString(parameters, self.FIELD_RMAX,
                                            context)
        date_format = self.parameterAsString(parameters, self.DATE_FORMAT,
                                             context)
        output_wind = self.parameterAsOutputLayer(parameters, self.OUTPUT_WIND,
                                                  context)
        output_pressure = self.parameterAsOutputLayer(parameters,
                                                      self.OUTPUT_PRESSURE,
                                                      context)

        # Get the transformation

        sourceCrs = input_source.sourceCrs()
        destCrs = QgsCoordinateReferenceSystem(4326)
        crsTransform = QgsCoordinateTransform(sourceCrs, destCrs,
                                              context.transformContext())

        # Set input and output folders

        input_folder = QTemporaryDir()
        input_folder.setAutoRemove(False)
        input_folder = input_folder.path()

        output_folder = QTemporaryDir()
        output_folder.setAutoRemove(False)
        output_folder = output_folder.path()

        # debug

        input_folder = 'C:\\Users\\Olivier\\Desktop\\testinput'
        output_folder = 'C:\\Users\\Olivier\\Desktop\\testoutput'
        # base = os.path.dirname(os.path.abspath(__file__))
        # shutil.copy(os.path.join(base,'tcrm.ini'),os.path.join(input_folder,'tcrm.ini'))
        # shutil.copy(os.path.join(base,'tcrm.csv'),os.path.join(input_folder,'tcrm.csv'))

        # Load default config and adapt it

        config = configparser.RawConfigParser()
        config.read(
            os.path.join(os.path.dirname(os.path.abspath(__file__)),
                         'tcrm.ini'))

        extent = crsTransform.transform(input_source.sourceExtent())
        gridLimit = {
            'xMin': extent.xMinimum(),
            'xMax': extent.xMaximum(),
            'yMin': extent.yMinimum(),
            'yMax': extent.yMaximum()
        }
        config['Region']['gridLimit'] = str(gridLimit)
        config['Logging']['LogLevel'] = 'DEBUG'
        config['BDECK']['DateFormat'] = date_format

        # Write config and CSV to output folder
        input_ini = os.path.join(input_folder, 'tcrm.ini')
        ini_file = open(input_ini, 'w')
        config.write(ini_file)
        ini_file.close()

        input_csv = os.path.join(input_folder, 'tcrm.csv')
        csv_file = open(input_csv, 'w')

        features = sorted(input_source.getFeatures(),
                          key=lambda f: f.attribute(field_date))
        for f in features:
            point = f.geometry()
            point.transform(crsTransform)
            # we write the following columns as configured in ini
            line = '{skip},{num},{date},{skip},{skip},{lat},{lon},{skip},{pressure},{rmax}\n'.format(
                skip='SKIP',
                num=1,
                date=f.attribute(field_date),
                lat=point.asPoint().y(),
                lon=point.asPoint().x(),
                pressure=f.attribute(field_pressure),
                rmax=f.attribute(field_rmax),
            )
            csv_file.write(line)
        csv_file.close()

        # Run the TCRM model
        command = self.COMMAND_LINE.format(output_dir=output_folder,
                                           input_dir=input_folder,
                                           config_file='tcrm.ini')
        feedback.pushInfo("Running " + command)
        process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
        for line in process.stdout:
            feedback.pushInfo(line.decode('utf-8'))

        # Get the output filename
        output_netcdf = os.path.join(output_folder, 'windfield',
                                     'gust.001-00001.nc')
        assert (os.path.exists(output_netcdf))
        # output_vmax = output_netcdf+'.vmax.tif'
        # output_slp = output_netcdf+'.slp.tif'

        # Export the maximum winds
        command = 'gdal_translate -ot float32 -unscale -CO COMPRESS=deflate NETCDF:"{}":vmax {}'.format(
            output_netcdf, output_wind)
        feedback.pushInfo("Running " + command)
        subprocess.run(command, shell=True)

        # Export the sea level pressure
        command = 'gdal_translate -ot float32 -unscale -CO COMPRESS=deflate NETCDF:"{}":slp {}'.format(
            output_netcdf, output_pressure)
        feedback.pushInfo("Running " + command)
        subprocess.run(command, shell=True)

        QgsMessageLog.logMessage("Done !")

        return {
            self.OUTPUT_WIND: output_wind,
            self.OUTPUT_PRESSURE: output_pressure
        }