I have converted a graphic model into a script. I want to expend this script and would like to store the result of the Reprojected Algorithm as a layer so as to get the output layers extent.
I am using QgsVectorLayer
class to create a vector layer from the result of the algorithm. When I am checking if the layer is valid, the layer is invalid. How can I convert a result of the processing algorithm as a valid vector layer, from which I can extract the extent with .extent()
method.
Code Snippet:
# Reproject layer
alg_params = {
'INPUT': parameters['areaboundary'],
'OPERATION': '',
'TARGET_CRS': QgsCoordinateReferenceSystem('EPSG:4326'),
'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
}
outputs['ReprojectLayer'] = processing.run('native:reprojectlayer', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
feedback.setCurrentStep(1)
if feedback.isCanceled():
return {}
feedback.pushInfo(str(outputs['ReprojectLayer']['OUTPUT']))
area_layer = QgsVectorLayer(outputs['ReprojectLayer']['OUTPUT'], 'Reprojected', 'memory')
if not area_layer.isValid():
feedback.pushInfo('not valid')
else:
QgsProject.instance().addMapLayer(area_layer)
Full Script:
from qgis.core import QgsProcessing, QgsVectorLayer
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingParameterFeatureSink
from qgis.core import QgsCoordinateReferenceSystem
import processing
class DownloadSoil(QgsProcessingAlgorithm):
def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterVectorLayer('areaboundary', 'Area Boundary', types=[QgsProcessing.TypeVectorPolygon], defaultValue=None))
self.addParameter(QgsProcessingParameterFeatureSink('Swapped', 'Swapped', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))
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(3, model_feedback)
results = {}
outputs = {}
# Reproject layer
alg_params = {
'INPUT': parameters['areaboundary'],
'OPERATION': '',
'TARGET_CRS': QgsCoordinateReferenceSystem('EPSG:4326'),
'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
}
outputs['ReprojectLayer'] = processing.run('native:reprojectlayer', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
feedback.setCurrentStep(1)
if feedback.isCanceled():
return {}
feedback.pushInfo(str(outputs['ReprojectLayer']['OUTPUT']))
area_layer = QgsVectorLayer(outputs['ReprojectLayer']['OUTPUT'], 'Reprojected', 'memory')
if not area_layer.isValid():
feedback.pushInfo('not valid')
else:
QgsProject.instance().addMapLayer(area_layer)
feedback.pushInfo(str(area_layer.sourceName()))
xmin = area_layer.extent().xMinimum()
ymin = area_layer.extent().yMinimum()
xmax = area_layer.extent().xMaximum()
ymax = area_layer.extent().yMaximum()
feedback.pushInfo(str(ymin))
requestURL = 'https://sdmdataaccess.sc.egov.usda.gov/Spatial/SDMWGS84GEOGRAPHIC.wfs?SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=MapunitPoly&SRSNAME=EPSG:4326&BBOX=' + str(xmin) + ',' + str(ymin) + ',' + str(xmax) + ',' + str(ymax)
feedback.pushInfo(requestURL)
# Download file
alg_params = {
'URL': requestURL,
'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
}
outputs['DownloadFile'] = processing.run('native:filedownloader', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
feedback.setCurrentStep(2)
if feedback.isCanceled():
return {}
# Swap X and Y coordinates
alg_params = {
'INPUT': outputs['DownloadFile']['OUTPUT'],
'OUTPUT': parameters['Swapped']
}
outputs['SwapXAndYCoordinates'] = processing.run('native:swapxy', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
results['Swapped'] = outputs['SwapXAndYCoordinates']['OUTPUT']
return results
def name(self):
return 'Download Soil'
def displayName(self):
return 'Download Soil'
def group(self):
return 'Test Models'
def groupId(self):
return 'Test Models'
def createInstance(self):
return DownloadSoil()
Best Answer
native:reprojectlayer
is executed as child algorithm. PyQGIS states in https://github.com/qgis/QGIS/blob/c5a56d6f83e08b77967326add5ad215e3a0c948e/python/plugins/processing/tools/general.py#L110 that:This means that the result of the
native:reprojectlayer
is a string with the layer id and the ownership of this layer is of theQgsProcessingContext
in use during algorithm execution. To get access to the layer, one possible way would be to take back its ownership usingQgsProcessingContenxt.takeResultLayer(%layer_id%)
The short example hereafter takes back the ownership of the layer and pushes the information about the extent to the log of the algorithm:A sketch of the output is presented in the following picture:![enter image description here](https://i.stack.imgur.com/Cd3jq.png)
A more extensive example of how to use the
takeResultLayer()
is given directly in the implementation of PyQGIS is e.g., [%qgis_install_dir%\python\plugins\processing\core\Processing.py:151-176]. I hope this helps you!