3. Edit an existing tool

The PCRaster User Scripts that have now been added to your Processing Toolbox can be edited. We can use one as an example and modify it for our own tool.

An easy one to modify is the mapaverage tool.

1. Right-click on the mapaverage tool and choose Edit Script... from the context menu.

Let's modify the script so it will calculate the Normalized Difference Vegetation Index from two raster layers.

The equation for NDVI is:

NDVI = (NIR - Red) / (NIR + Red)

NIR = near infrared band
Red = red band

It results in a raster with values between -1 and 1. Cells larger than 0 represent increasing biomass.

It is good practice to only import the functions that you need. Here we can delete many from the example.

2. Edit the functions that need from PCRaster so that we only have readmap, setclone and report.

  • readmap is to read the rasters from disk with the path provided by the user.
  • setclone is to make sure that all rasters have the same dimensions for map algebra. We'll set the clone to the first raster that is loaded.
  • report is needed to write the result of the calculation to disk, using the path provided by the user.
3. Under the imports from QGIS you can remove QgsProcessingParameterNumber.

4. In line 31 change the class name to ndviAlgorithm
5. Since we have two input rasters, we need to copy line 32 and change the variables as below:

6. In line 43 we need to use the name of the algorithm defined in step 4:

7. In line 53 we need to give a identification name for the algorithm. We can only use lower case alphanumeric characters and no spaces. Here we use ndvi:

8. In line 60 we define the name of the tool that is presented to the user.  Let's change it to "Calculate NDVI":

9. Line 67 defines the group name for the Processing Toolbox section. We keep it as is, so our tool will be added under the PCRaster User Scripts.

10. Line 77 defines the group ID. We also leave this as it is.

11. Lines 79 - 94 define the help string that will be presented in the tool dialog. Change it to the text below that describes the algorithm, the required inputs and outputs.

12. Lines 97 - 116 define how the inputs and outputs are defined through the dialog of the tool.  We need to change it, because we have two input raster layers: INPUT_RED and INPUT_NIR, defined in lines 32 and 33 respectively. With self.tr we can add the string that the user sees in the dialog. Also change the string for the output in the dialog. The lines should read like this now:

13. Lines 124 - 138 finally contain the calculation. Change it to the script below:

Some explanation for this part:
  • self.parameterAsRasterLayer(parameters, self.INPUT_RED, context) reads the raster layer information for the red band selected by the user and this goes into the input_red variable.
  • Same is done for input_nir in line 126 and the output_raster in line 127.
  • In line 128 we use the PCRaster setclone function to set the clone/mask for the map algebra calculations to the properties of the the first raster (input_red). setclone needs the path to the raster., which is the string returned by input_red.dataProvider().dataSourceUri().
  • In lines 129 and 130 we read the red and NIR band repectively from disk, using the readmap function and the path (same method as in line 128 to get the path). The variables InputRed and InputNIR are now the PCRaster maps that we can use in the calculation.
  • In line 131 we calculate NDVI and store the PCRaster map in the variable OutputNDVI.
  • In line 132 we assign the path of the output file, as defined in the dialog by the user, to the variable outputFilePath.
  • In line 134 the result is written to disk using the PCRaster report function that needs the name of the variable and the path of the output file.
  • Line 138 returns the result dictionary entry so it is opened in the QGIS map canvas.
14. Click the Save Cript As. button an save it as pcraster_ndvi.py in the profile folder. Make sure you're not overwriting the mapaverage script!

Now you can find your new NDVI tool in the Processing Toolbox:

Next we'll debug errors.