Beispiel #1
0
 def processAlgorithm(self, parameters, context, feedback):
     """
     Method that triggers the data processing algorithm.
     :param parameters: (dict) mapping from algorithms input's name to its
                        value.
     :param context: (QgsProcessingContext) execution's environmental info.
     :param feedback: (QgsProcessingFeedback) QGIS object to keep track of
                      algorithm's progress/status.
     :return: (dict) output mapping for identified flags.
     """
     layers, selected, silent, ratio = self.getParameters(
         parameters, context, feedback)
     if not layers:
         raise QgsProcessingException(self.tr("No layers were provided."))
     for layer in layers:
         if layer.featureCount() > 0:
             geomType = next(layer.getFeatures()).geometry().wkbType()
             break
     else:
         raise QgsProcessingException(self.tr("All layers are empty."))
     self.prepareFlagSink(parameters, layers[0], geomType, context)
     flags = dict()
     lh = LayerHandler()
     flagCount = 0
     # a step for each input + 1 for loading flags into sink
     multiStepFeedback = QgsProcessingMultiStepFeedback(
         len(layers) + 1, feedback)
     multiStepFeedback.setCurrentStep(0)
     for step, layer in enumerate(layers):
         if multiStepFeedback.isCanceled():
             break
         # running polygon slivers to purposely raise an exception if an
         # empty geometry is found
         multiStepFeedback.pushInfo(
             self.tr("Checking {0}...").format(layer.name()))
         slivers = lh.getPolygonSlivers(layer, ratio, selected, silent,
                                        multiStepFeedback)
         if slivers:
             # pushWarnign is only avalailable on 3.16.2+
             # multiStepFeedback.pushWarning(
             multiStepFeedback.pushDebugInfo(
                 self.tr("{0} slivers were found on {1}!")\
                     .format(len(slivers), layer.name())
             )
             flags[layer] = slivers
             flagCount += len(slivers)
         multiStepFeedback.setCurrentStep(step + 1)
     self.tr("Populating flags layer...")
     self.flagPolygonSlivers(flags, flagCount, multiStepFeedback)
     multiStepFeedback.setCurrentStep(step + 2)
     return {self.FLAGS: self.flag_id}
Beispiel #2
0
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        steps = len(parameters['INPUT'])
        feedback = QgsProcessingMultiStepFeedback(steps, model_feedback)

        results = {'OUTPUT': []}
        outputs = {'ClipRasterByMaskLayer': []}
        i = 0
        feedback.pushDebugInfo("OUTFOLDER: " + str(parameters['OUTFOLDER']))
        for filename in parameters['INPUT']:
            if os.path.isdir(str(parameters['OUTFOLDER'])):
                file, ext = os.path.splitext(os.path.basename(filename))
                outfilename = os.path.join(parameters['OUTFOLDER'],
                                           file + "_clipped" + ext)
            else:
                outfilename = QgsProcessing.TEMPORARY_OUTPUT
            # Clip raster by mask layer
            alg_params = {
                'ALPHA_BAND': False,
                'CROP_TO_CUTLINE': True,
                'DATA_TYPE': 0,
                'EXTRA': '',
                'INPUT': filename,
                'KEEP_RESOLUTION': False,
                'MASK': parameters['Masklayer'],
                'MULTITHREADING': False,
                'NODATA': None,
                'OPTIONS': '',
                'SET_RESOLUTION': False,
                'SOURCE_CRS': None,
                'TARGET_CRS': None,
                'X_RESOLUTION': None,
                'Y_RESOLUTION': None,
                'OUTPUT': outfilename
            }
            outputs['ClipRasterByMaskLayer'].append(
                processing.run('gdal:cliprasterbymasklayer',
                               alg_params,
                               context=context,
                               feedback=feedback,
                               is_child_algorithm=True))
            i = i + 1
            feedback.setCurrentStep(i)
            if feedback.isCanceled():
                return {}

        for clipresult in outputs['ClipRasterByMaskLayer']:
            results['OUTPUT'].append(clipresult['OUTPUT'])
        return results
Beispiel #3
0
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(2, model_feedback)
        results = {}
        outputs = {}

        indexequation = str(self.indexdefs['Index definitions']['Sentinel2'][list(self.indexdefs['Index definitions']['Sentinel2'].keys())[parameters['INDEX']]])
        vrtname = parameters['SentinelVrtLayer'].split('_',1)[0]
        indexequation = indexequation.replace("SentinelVRTLayer", vrtname)
        feedback.pushDebugInfo("indexequation: " + str(indexequation))
        # Raster calculator
        alg_params = {
            'CELLSIZE': 0,
            'CRS': 'ProjectCrs',
            'EXPRESSION': indexequation,
            'EXTENT': parameters['SentinelVrtLayer'],
            'LAYERS': parameters['SentinelVrtLayer'],
            'OUTPUT': parameters['OUTPUT']
        }
        feedback.pushDebugInfo(str(alg_params))
        outputs['RasterCalculator'] = processing.run('qgis:rastercalculator', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        results['OUTPUT'] = outputs['RasterCalculator']['OUTPUT']

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # Set layer style
        alg_params = {
            'INPUT': outputs['RasterCalculator']['OUTPUT'],
            'STYLE': parameters['LayerStyledefinition']
        }
        outputs['SetLayerStyle'] = processing.run('native:setlayerstyle', alg_params, context=context, feedback=feedback, is_child_algorithm=True)

        return results
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        results = {
            'OUTPUT': []
        }
        outputs = {}
        Bandlist = parameters['BANDS'].split(',')
        pattern = re.compile(parameters['MASK'])
        # Build virtual raster
        inputlist = list(parameters['INPUT'])
        inputlist.append("..last..")
        thisgroup = None
        group = 0
        for raster in inputlist:
            match = pattern.match(raster)
            if raster == "..last..":
                break
            if not match:
                continue
            if match.group(1) == thisgroup:
                continue
            thisgroup = match.group(1)
            group+=1
        feedback = QgsProcessingMultiStepFeedback(group, model_feedback)
        feedback.pushDebugInfo("inputlist: " + str(inputlist))
        filegroup = {}
        filelist = []
        vrtmap = {}
        thisgroup = None
        group=0
        for raster in inputlist:
            match = pattern.match(raster)
            if raster != "..last..":
                if not match:
                    continue
                feedback.pushDebugInfo("accepted: " + str(raster))
                if thisgroup==None:
                    thisgroup = match.group(1)
                if match.group(1) == thisgroup:
                    filegroup[match.group(2)] = raster
                    continue
            if feedback.isCanceled():
                return {}
            for i,band in enumerate(Bandlist):
                if band in filegroup.keys():
                    filelist.append(filegroup[band])
                    vrtmap[i+1]=(band, filegroup[band])
                else:
                    filelist.append(filelist[0])
                    vrtmap[i+1] = vrtmap[1]

            feedback.pushDebugInfo("thisgroup: " + str(thisgroup))
            feedback.pushDebugInfo("filegroup: " + str(filegroup))
            feedback.pushDebugInfo("filelist: " + str(filelist))
            feedback.pushDebugInfo("vrtmap: " + str(vrtmap))
            if thisgroup:
                group+=1
                outputs[thisgroup] = {}
                alg_params = {
                    'ADD_ALPHA': False,
                    'ASSIGN_CRS': None,
                    'EXTRA': '',
                    'INPUT': filelist,
                    'PROJ_DIFFERENCE': False,
                    'RESAMPLING': 0,
                    'RESOLUTION': 1,
                    'SEPARATE': True,
                    'SRC_NODATA': '',
                    'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
                }
                
                outputs[thisgroup]['BuildVirtualRaster'] = processing.run('gdal:buildvirtualraster', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
                outfilename = os.path.join(parameters['OUTFOLDER'], thisgroup+".vrt")
                outputs[thisgroup]['CustomVRT'] = self.buildCustomVrt(outfilename, outputs[thisgroup]['BuildVirtualRaster']['OUTPUT'], vrtmap)
                results['OUTPUT'].append(outputs[thisgroup]['CustomVRT'])
                feedback.setCurrentStep(group)
            if feedback.isCanceled():
                return {}
            if raster == "..last..":
                break
            thisgroup = match.group(1)
            filegroup.clear()
            filelist.clear()
            vrtmap.clear()
            filegroup[match.group(2)] = raster

        results['OUTFOLDER'] = parameters['OUTFOLDER']
        return results
    def processAlgorithm(self, parameters, context, model_feedback):
        results = {}
        outputs = {}
        inputrasters = []
        feedback = QgsProcessingMultiStepFeedback(1, model_feedback)
        filenamepattern = re.compile(parameters['FILENAMEMASK'])
        height = None
        width = None
        for raster in parameters['INPUT']:
            feedback.pushDebugInfo("layer: " + str(raster))
            match = filenamepattern.match(raster)
            if not match:
                layers = QgsProject.instance().mapLayersByName(raster[:13])
                if not layers:
                    continue
                layer = layers[0]
                filename = layer.dataProvider().dataSourceUri()
                match = filenamepattern.match(filename)
                if not match:
                    continue
            else:
                filename = raster
                layer = QgsRasterLayer(filename, match.group(1), "gdal")
                if not layer.isValid():
                    continue
            feedback.pushDebugInfo("size: " + str(layer.height()) + "x" +
                                   str(layer.width()))
            if height is None:
                height = layer.height()
            if width is None:
                width = layer.width()
            if layer.height() != height:
                continue
            if layer.width() != width:
                continue

            date = datetime.strptime(match.group(2), parameters['DATEFORMAT'])
            inputrasters.append({'date': date, 'filename': filename})
        feedback = QgsProcessingMultiStepFeedback(len(inputrasters),
                                                  model_feedback)

        def get_date(e):
            return e.get('date')

        inputrasters.sort(key=get_date)
        feedback.pushDebugInfo("inputrasters: " + str(inputrasters))
        previnput = None
        sumraster = None
        i = 0
        for inputraster in inputrasters:
            if previnput is None:
                previnput = inputraster
                if sumraster is None:
                    sumraster = self.nullraster(inputraster['filename'],
                                                parameters['OUTPUT'], context,
                                                feedback)['OUTPUT']
                continue
            delta = inputraster['date'] - previnput['date']
            outputs['CalcDaysOverLimit'] = self.adddaysoverthreshold(
                sumraster, previnput['filename'], inputraster['filename'],
                delta.days, parameters['THRESHOLD'], context, feedback)
            sumraster = outputs['CalcDaysOverLimit']['OUTPUT']
            previnput = inputraster
            i = i + 1
            feedback.setCurrentStep(i)
            if feedback.isCanceled():
                return {}
        results['OUTPUT'] = outputs['CalcDaysOverLimit']['OUTPUT']

        return results
Beispiel #6
0
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(4, model_feedback)
        outputs = {}
        self.doRenderer = False
        feedback.setProgressText(
            self.
            tr('Preprocessing input (fix geometries, explode lines and remove null geometries)'
               ))
        # Fix geometries
        alg_params = {
            'INPUT': parameters[self.INPUT],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['FixGeometries'] = processing.run('native:fixgeometries',
                                                  alg_params,
                                                  context=context,
                                                  feedback=feedback,
                                                  is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        # Explode lines
        alg_params = {
            'INPUT': outputs['FixGeometries']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['ExplodeLines'] = processing.run('native:explodelines',
                                                 alg_params,
                                                 context=context,
                                                 feedback=feedback,
                                                 is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        # Remove null geometries
        alg_params = {
            'INPUT': outputs['ExplodeLines']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['RemoveNullGeometries'] = processing.run(
            'native:removenullgeometries',
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True)

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        source = self.parameterAsSource(outputs['RemoveNullGeometries'],
                                        'OUTPUT', context)
        fields = source.fields()

        cluster_field = self.parameterAsString(parameters, self.CLUSTER_FIELD,
                                               context)
        compatibility = self.parameterAsDouble(parameters, self.COMPATIBILITY,
                                               context)
        cycles = self.parameterAsInt(parameters, self.CYCLES, context)
        iterations = self.parameterAsInt(parameters, self.ITERATIONS, context)
        initial_step_size = self.parameterAsDouble(parameters,
                                                   self.INITIAL_STEP_SIZE,
                                                   context)
        max_distance = self.parameterAsDouble(parameters, self.MAX_DISTANCE,
                                              context)
        self.max_distance = max_distance
        weight_field = self.parameterAsString(parameters, self.WEIGHT_FIELD,
                                              context)
        weight_field_index = None
        if weight_field != '':
            weight_field_index = fields.lookupField(weight_field)

        # Create edge list
        features = source.getFeatures(QgsFeatureRequest())
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        edges = []
        for current, feat in enumerate(features):
            if feedback.isCanceled(): break
            edges.append(Edge(feat, weight_field_index))

        # Create clusters
        clusters = []
        if cluster_field != '':
            # Arrange edges in clusters according to cluster-id
            labels = []
            for edge in edges:
                if feedback.isCanceled(): return {}
                labels.append(edge[cluster_field])
            feedback.pushDebugInfo(cluster_field)
            for l in range(0, len(labels) + 1):
                if feedback.isCanceled(): return {}
                clusters.append(list())
            for i, label in enumerate(labels):
                if feedback.isCanceled(): return {}
                if label >= 0:
                    clusters[label].append(edges[i])
                else:
                    clusters.append([edges[i]])
            for i, cluster in enumerate(clusters):
                if feedback.isCanceled(): return {}
                clusters[i] = EdgeCluster(cluster, initial_step_size,
                                          iterations, cycles, compatibility)
        else:
            # If clustering should not be used, create only one big cluster containing all edges
            clusters = [
                EdgeCluster(edges, initial_step_size, iterations, cycles,
                            compatibility)
            ]
        fields.append(QgsField('CLUSTER', QVariant.Int))
        cluster_index = fields.lookupField('CLUSTER')
        if max_distance > 0:
            self.doRenderer = True
            fields.append(QgsField('PATH', QVariant.Int))
            fields.append(QgsField('OVERLAP_COUNT', QVariant.Int))
            overlap_index = fields.lookupField('OVERLAP_COUNT')

        (sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                                    context, fields,
                                                    source.wkbType(),
                                                    source.sourceCrs())

        # Do edge-bundling (separately for all clusters)
        if max_distance == 0:
            feedback.setProgressText(
                self.tr('Compute Flow without merging lines'))
            for c, cl in enumerate(clusters):
                if feedback.isCanceled(): return {}
                if cl.E > 1:
                    cl.force_directed_eb(feedback)
            feedback.setCurrentStep(3)
            for id, cl in enumerate(clusters):
                if feedback.isCanceled(): return {}
                feedback.setProgress(100.0 * id / len(clusters))
                for e, edge in enumerate(cl.edges):
                    feat = QgsFeature()
                    feat.setGeometry(edge.geometry())
                    attr = edge.attributes()
                    attr.append(id)
                    feat.setAttributes(attr)
                    sink.addFeature(feat, QgsFeatureSink.FastInsert)
        else:
            feedback.setProgressText(
                self.tr('Compute Flow and try to merge lines'))
            for c, cl in enumerate(clusters):
                if feedback.isCanceled(): return {}
                if cl.E > 1:
                    cl.force_directed_eb(feedback)
            feedback.setCurrentStep(3)
            for id, cl in enumerate(clusters):
                if feedback.isCanceled(): return {}
                feedback.setProgressText(
                    "Segment lines for cluster {0}".format(id))
                cl.create_segments(weight_field_index, feedback)
                feedback.setProgressText(
                    "Collapse lines for cluster {0}".format(id))
                cl.collapse_lines(max_distance, feedback)
            fid = 0
            for id, cl in enumerate(clusters):
                if feedback.isCanceled(): return {}
                for e, edge in enumerate(cl.edges):
                    segments = cl.get_segments(edge)
                    for key, segment in segments.items():
                        feat = QgsFeature()
                        feat.setGeometry(segment.geometry())
                        attr = edge.attributes()
                        path_id = attr[0]
                        attr[0] = fid
                        attr.append(id)
                        attr.append(path_id)
                        attr.append(int(
                            segment.get_agg_weight()))  #Overlap count
                        feat.setAttributes(attr)
                        sink.addFeature(feat, QgsFeatureSink.FastInsert)
                        fid += 1

        return {self.OUTPUT: self.dest_id}