5

I have just started using PyQGIS and need to loop over parcels in a vector layer to clip a raster layer.

For each parcel, I want to generate a .tif file with the feature.id() in the filename. I will also be saving the attributes in a separate .csv/.txt file by the same name. Because of this, I can't run the script using the iterator in the GUI.

This is what I have come up with thus far:

raster = 'C:/Datasets/orthophotos/OMWRGB21VL_K14_K15/OMWRGB21_VL_K14_K15.tif'
Lbgbrprc = 'C:/Datasets/Landbouwgebruikspercelen/Landbouwgebruikspercelen_2020/Shapefile/Lbgbrprc20_SintNiklaas.shp'
Lbgbrprc = QgsVectorLayer(Lbgbrprc, 'landbouw', 'ogr')

params = {
    'ALPHA_BAND' : False,
    'CROP_TO_CUTLINE' : True,
    'DATA_TYPE' : 0,
    'EXTRA' : '',
    'INPUT' : raster,
    'KEEP_RESOLUTION' : False,
    'MULTITHREADING' : False,
    'NODATA' : None,
    'OPTIONS' : '',
    'SET_RESOLUTION' : False,
    'SOURCE_CRS' : QgsCoordinateReferenceSystem('EPSG:31370'),
    'TARGET_CRS' : QgsCoordinateReferenceSystem('EPSG:31370'),
    'X_RESOLUTION' : None,
    'Y_RESOLUTION' : None
}

request = QgsFeatureRequest()
for feature in Lbgbrprc.getFeatures(request):
    if int(feature.id()) < 5:
        print(type(feature)) # <class 'qgis._core.QgsFeature'>
        params['MASK'] = feature
        params['OUTPUT'] = 'C:/Output/ortho_Lbgbrprc/{}.tif'.format(feature.id())
        
        processing.run("gdal:cliprasterbymasklayer", params)

This is the error I get:

Could not load source layer for MASK: invalid value

I think the issue is that the 'MASK' parameter needs to be a QgsVectorLayer not a QgsFeature, which is what "feature" is now. How do I go about this?

1 Answer 1

9

Apparently, the type of Mask layer should be a [vector: polygon] i.e. QgsVectorLayer, see documentation.

Also, visible via processing.algorithmHelp("gdal:cliprasterbymasklayer"):

...
MASK: Mask layer

    Parameter type: QgsProcessingParameterFeatureSource

    Accepted data types:
        - str: layer ID
        - str: layer name
        - str: layer source
        - QgsProcessingFeatureSourceDefinition
        - QgsProperty
        - QgsVectorLayer
...

So, one shall modify this parameter:

params['MASK'] = feature

as was also mentioned by @MrXsquared to this:

params['MASK'] = Lbgbrprc.materialize(QgsFeatureRequest().setFilterFid(feature.id()))

Another option, that can be less resource-consuming, utilizes the QgsProcessingFeatureSourceDefinition class.

Input:

input

from os.path import abspath
from qgis import processing
from qgis.core import QgsProject

project_path = abspath('C:/Users/Taras/Downloads/GIS data/')

vector_layer = QgsProject.instance().mapLayersByName('Lbgbrprc21_selection')[0]
raster_layer = QgsProject.instance().mapLayersByName('OMWRGB14VL_K338z')[0]

params = {
    'ALPHA_BAND' : False,
    'CROP_TO_CUTLINE' : True,
    'DATA_TYPE' : 0,
    'EXTRA' : '',
    'INPUT' : raster_layer,
    'KEEP_RESOLUTION' : False,
    'MULTITHREADING' : False,
    'NODATA' : None,
    'OPTIONS' : '',
    'SET_RESOLUTION' : False,
    'SOURCE_CRS' : QgsCoordinateReferenceSystem('EPSG:31370'),
    'TARGET_CRS' : QgsCoordinateReferenceSystem('EPSG:31370'),
    'X_RESOLUTION' : None,
    'Y_RESOLUTION' : None
}

for feature in vector_layer.getFeatures():
    if int(feature.id()) < 5:
        vector_layer.select(feature.id())
        params['MASK'] = QgsProcessingFeatureSourceDefinition(vector_layer.id(), True)
        params['OUTPUT'] = f"{project_path}/{feature.id()}.tif"
        processing.run("gdal:cliprasterbymasklayer", params)
        vector_layer.removeSelection()

Outputs:

outputs


References:

7
  • Thank you so much! The first solution works. For the second approach, I get the error "Could not load source layer for MASK: landbouw_53536513_e03e_4466_bf80_58088bb4ac38 not found" Commented Jan 6, 2023 at 14:44
  • I just tested this with "native:countpointsinpolygon" and it works, with no errors. Maybe you can share a sample of your data?
    – Taras
    Commented Jan 8, 2023 at 12:19
  • I tried with a different polygon layer, I still get the same error. For now, I am working with the first solution, so my problem is fixed. Maybe when I learn more about pyQGIS, I will be able to see why I get that error. Thanks for all the help! Commented Jan 10, 2023 at 9:15
  • But can you share a sample of your data ? It shall work though. Please, do not forget about "What should I do when someone answers my question?"
    – Taras
    Commented Jan 10, 2023 at 13:18
  • I have uploaded a tiff file and a selection of the parcels to 1drv.ms/u/s!Ao2sPEougj-phzJjBa_F0crYACdM?e=U4bnlM Commented Jan 12, 2023 at 8:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.