Getting started with qgisprocess
Jannes Muenchow & Floris Vanderhaeghe
Last
update: 2024-02-21
Last run: 2024-10-07
Source: Last run: 2024-10-07
vignettes/qgisprocess.Rmd
qgisprocess.Rmd
For a very short introduction to qgisprocess, visit the homepage.
Here you will learn about package configuration, about basic usage illustrated by two examples, and how to pipe results into a next geoprocessing step.
Setting up the system
qgisprocess is basically a wrapper around the
standalone command line tool qgis_process
.
Therefore, you need to have installed QGIS on your system as well as
third-party providers such as GRASS GIS and SAGA to access and run all
geoalgorithms provided through qgis_process
from within
R.
The package is meant to support current QGIS releases, i.e. both the latest and the long-term release. Although older QGIS releases are not officially supported, qgisprocess might work with QGIS versions >=3.16. Download instructions for all platforms are available at https://download.qgis.org/.
To facilitate using qgisprocess, we have created a docker image that already comes with the needed software packages. You can pull it from Github’s container registry by running:
For a more detailed introduction on how to get started with docker, please refer to https://github.com/geocompx/docker.
Package configuration
Since qgisprocess depends on the command line tool
qgis_process
, it already tries to detect
qgis_process
on your system when it is being loaded, and
complains if it cannot find it.
library("qgisprocess")
#> QGIS version: 3.38.3-Grenoble
#> Having access to 362 algorithms from 4 QGIS processing providers.
#> Run `qgis_configure(use_cached_data = TRUE)` to reload cache and get more details.
#> >>> Run `qgis_enable_plugins()` to enable 3 disabled plugins and access
#> their algorithms: grassprovider, processing,
#> processing_saga_nextgen
When loading qgisprocess for the first time, it will
cache among others the path to qgis_process
, the QGIS
version and the list of known algorithms. When loading
qgisprocess in later R sessions, the cache file is read
instead for speed-up, on condition that it is still valid. Therefore,
usually you don’t have to do any configuration yourself, unless there’s
a message telling you to do so.
If you are interested in the details about this process, e.g. how
qgisprocess detected qgis_process
, run
qgis_configure(use_cached_data = TRUE)
.
qgis_configure(use_cached_data = TRUE)
#> Checking configuration in cache file (/home/runner/.cache/R-qgisprocess/cache-0.4.1.9000.rds)
#> Checking cached QGIS version with version reported by 'qgis_process' ...
#> QGIS versions match! (3.38.3-Grenoble)
#> Checking cached QGIS plugins (and state) with those reported by 'qgis_process' ...
#> QGIS plugins match! (0 processing provider plugin(s) enabled)
#>
#> >>> Run `qgis_enable_plugins()` to enable 3 disabled plugins and access
#> their algorithms: grassprovider, processing,
#> processing_saga_nextgen
#>
#> Restoring configuration from '/home/runner/.cache/R-qgisprocess/cache-0.4.1.9000.rds'
#> QGIS version: 3.38.3-Grenoble
#> Using 'qgis_process' in the system PATH.
#> >>> If you need another installed QGIS instance, run `qgis_configure()`;
#> see `?qgis_configure` if you need to preset the path of 'qgis_process'.
#> Using JSON for output serialization.
#> Using JSON for input serialization.
#> 0 out of 3 available processing provider plugins are enabled.
#> Having access to 362 algorithms from 4 QGIS processing providers.
#> Use qgis_algorithms(), qgis_providers(), qgis_plugins(), qgis_path() and
#> qgis_version() to inspect the cache environment.
If needed the cache will be rebuilt automatically upon loading the
package. This is the case when the QGIS version or the location of the
qgis_process
command-line utility has changed,
user-settings (e.g. the option qgisprocess.path
) have been
altered or a changed state of the processing provider plugins (enabled
vs. disabled) has been detected.
Rebuilding the cache can be triggered manually by running
qgis_configure()
(its default is
use_cached_data = FALSE
).
To determine the location of qgis_process
,
qgis_configure()
first checks if the R option
qgisprocess.path
or the global environment variable
R_QGISPROCESS_PATH
has been set. This already indicates
that you can specify one of these settings in case
qgis_process
has not been installed in one of the most
common locations or if there are multiple QGIS versions available. If
this is the case, set
options(qgisprocess.path = '/path/to/qgis_process')
or set
the environment variable (e.g. in .Renviron
) and run
qgis_configure()
. Under Windows make sure to indicate the
path to the qgis_process-qgis.bat
file, e.g.,
# specify path to QGIS installation on Windows
options(qgisprocess.path = "C:/Program Files/QGIS 3.28/bin/qgis_process-qgis.bat")
# or use the QGIS nightly version (if installed via OSGeo4W)
# options(qgisprocess.path = "C:/OSGeo4W64/bin/qgis_process-qgis-dev.bat")
qgis_configure() # or use library(qgisprocess) if package was not loaded yet
Assuming that package loading or qgis_configure()
ran
successfully, we can check which QGIS version our system is running (it
takes this from the cache):
qgis_version()
#> [1] "3.38.3-Grenoble"
Next, let’s check which plugins are at our disposal:
qgis_plugins()
#> # A tibble: 3 × 2
#> name enabled
#> <chr> <lgl>
#> 1 grassprovider FALSE
#> 2 processing FALSE
#> 3 processing_saga_nextgen FALSE
Since we will use GRASS GIS and SAGA later on, you must have GRASS GIS and SAGA version > 7 installed on your system. You also need to install the third-party plugin ‘SAGA Next Generation’ in the QGIS GUI. The GRASS provider plugin is already built-in in QGIS.
Then, let’s enable both plugins:
qgis_enable_plugins(c("grassprovider", "processing_saga_nextgen"))
Now, let’s list all available providers including available third-party applications:
qgis_providers()
#> # A tibble: 6 × 3
#> provider provider_title algorithm_count
#> <chr> <chr> <int>
#> 1 gdal GDAL 56
#> 2 grass GRASS 307
#> 3 qgis QGIS 42
#> 4 3d QGIS (3D) 1
#> 5 native QGIS (native c++) 263
#> 6 sagang SAGA Next Gen 509
This tells us that we can also use the third-party providers GDAL, GRASS and SAGA through the QGIS interface.
Basic usage
First example
To get the complete overview of available (cached) geoalgorithms, run:
algs <- qgis_algorithms()
algs
#> # A tibble: 1,178 × 24
#> provider provider_title algorithm algorithm_id algorithm_title
#> <chr> <chr> <chr> <chr> <chr>
#> 1 3d QGIS (3D) 3d:tessellate tessellate Tessellate
#> 2 gdal GDAL gdal:aspect aspect Aspect
#> 3 gdal GDAL gdal:assignprojection assignproje… Assign project…
#> 4 gdal GDAL gdal:buffervectors buffervecto… Buffer vectors
#> 5 gdal GDAL gdal:buildvirtualraster buildvirtua… Build virtual …
#> 6 gdal GDAL gdal:buildvirtualvector buildvirtua… Build virtual …
#> 7 gdal GDAL gdal:cliprasterbyextent cliprasterb… Clip raster by…
#> 8 gdal GDAL gdal:cliprasterbymaskla… cliprasterb… Clip raster by…
#> 9 gdal GDAL gdal:clipvectorbyextent clipvectorb… Clip vector by…
#> 10 gdal GDAL gdal:clipvectorbypolygon clipvectorb… Clip vector by…
#> # ℹ 1,168 more rows
#> # ℹ 19 more variables: provider_can_be_activated <lgl>,
#> # provider_is_active <lgl>, provider_long_name <chr>, provider_version <chr>,
#> # provider_warning <chr>, can_cancel <lgl>, deprecated <lgl>, group <chr>,
#> # has_known_issues <lgl>, help_url <chr>, requires_matching_crs <lgl>,
#> # short_description <chr>, tags <list>, default_raster_file_extension <chr>,
#> # default_vector_file_extension <chr>, …
For a directed search, use qgis_search_algorithms()
:
qgis_search_algorithms(algorithm = "buffer", group = "[Vv]ector")
#> # A tibble: 10 × 5
#> provider provider_title group algorithm algorithm_title
#> <chr> <chr> <chr> <chr> <chr>
#> 1 gdal GDAL Vector geoprocessing gdal:bufferv… Buffer vectors
#> 2 gdal GDAL Vector geoprocessing gdal:oneside… One side buffer
#> 3 grass GRASS Vector (v.*) grass:v.buff… v.buffer
#> 4 native QGIS (native c++) Vector geometry native:buffer Buffer
#> 5 native QGIS (native c++) Vector geometry native:buffe… Variable width…
#> 6 native QGIS (native c++) Vector geometry native:multi… Multi-ring buf…
#> 7 native QGIS (native c++) Vector geometry native:singl… Single sided b…
#> 8 native QGIS (native c++) Vector geometry native:taper… Tapered buffers
#> 9 native QGIS (native c++) Vector geometry native:wedge… Create wedge b…
#> 10 sagang SAGA Next Gen Vector general sagang:shape… Shapes buffer
Since we have also installed GRASS GIS and SAGA, over 1000
geoalgorithms are at our disposal. To find out about a specific
geoalgorithm and a description of its arguments, use
qgis_show_help()
, e.g.:
qgis_show_help("native:buffer")
## Buffer (native:buffer)
##
## ----------------
## Description
## ----------------
## This algorithm computes a buffer area for all the features in an input layer, using a fixed or dynamic distance.
##
## The segments parameter controls the number of line segments to use to approximate a quarter circle when creating rounded offsets.
##
## ...
To find out the arguments of a specific geoalgorithm, run:
qgis_get_argument_specs("native:buffer")
#> # A tibble: 9 × 6
#> name description qgis_type default_value available_values acceptable_values
#> <chr> <chr> <chr> <list> <list> <list>
#> 1 INPUT Input layer source <NULL> <NULL> <chr [1]>
#> 2 DISTAN… Distance distance <int [1]> <NULL> <chr [3]>
#> 3 SEGMEN… Segments number <int [1]> <NULL> <chr [3]>
#> 4 END_CA… End cap st… enum <int [1]> <chr [3]> <chr [2]>
#> 5 JOIN_S… Join style enum <int [1]> <chr [3]> <chr [2]>
#> 6 MITER_… Miter limit number <int [1]> <NULL> <chr [3]>
#> 7 DISSOL… Dissolve r… boolean <lgl [1]> <NULL> <chr [4]>
#> 8 SEPARA… Keep disjo… boolean <lgl [1]> <NULL> <chr [4]>
#> 9 OUTPUT Buffered sink <NULL> <NULL> <chr [1]>
And finally run it with qgis_run_algorithm()
:
# if needed, first install spDataLarge:
# remotes::install_github("Nowosad/spDataLarge")
data("random_points", package = "spDataLarge")
result <- qgis_run_algorithm("native:buffer", INPUT = random_points, DISTANCE = 50)
#> Argument `SEGMENTS` is unspecified (using QGIS default value).
#> Using `END_CAP_STYLE = "Round"`
#> Using `JOIN_STYLE = "Round"`
#> Argument `MITER_LIMIT` is unspecified (using QGIS default value).
#> Argument `DISSOLVE` is unspecified (using QGIS default value).
#> Argument `SEPARATE_DISJOINT` is unspecified (using QGIS default value).
#> Using `OUTPUT = qgis_tmp_vector()`
As a convenience to the user, qgis_run_algorithm()
reports all unspecified and automatically chosen arguments. If you want
to have even more information on what is going on in the background, set
.quiet
to FALSE
. The result
object is of class qgis_result
and contains the path to the
output file created by qgis_process
(when not explicitly
setting an output filepath, qgisprocess creates it
automatically for you). The output filepath can be extracted with
qgis_extract_output()
. qgis_result
objects are
of type list
which, aside from the geoprocessing result,
also contain debugging information about the used algorithm, input
arguments and messages from the processing step. See
?qgis_result_status
for various convenience functions to
extract all of this information easily from qgis_result
objects.
For QGIS 3.24 and later, qgis_run_algorithm()
passes the
input arguments to QGIS as a JSON string. The JSON input string is also
included in qgis_result
objects. Moreover, the user can
specify input arguments directly as JSON in
qgis_run_algorithm()
. That is useful since input parameters
can be copied from the QGIS GUI as JSON. This will be demonstrated in a
separate tutorial.
# inspect the result object
class(result)
#> [1] "qgis_result"
names(result)
#> [1] "OUTPUT" ".algorithm" ".args" ".raw_json_input"
#> [5] ".processx_result"
result # only prints the output element(s)
#> <Result of `qgis_run_algorithm("native:buffer", ...)`>
#> List of 1
#> $ OUTPUT: 'qgis_outputVector' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c3ed3c578.gpkg"
To read in the QGIS output and visualize it, we can run:
library("sf")
library("mapview")
# attach QGIS output
# either do it "manually":
buf <- read_sf(qgis_extract_output(result, "OUTPUT"))
# or use the st_as_sf.qgis_result method:
buf <- sf::st_as_sf(result)
# plot your result
mapview(buf, col.regions = "blue") +
mapview(random_points, col.regions = "red", cex = 3)
You can convert each QGIS algorithm into an R function with
qgis_function()
. So using our buffer example from above, we
could also run:
# create a function
qgis_buffer <- qgis_function("native:buffer")
# run the function
result <- qgis_buffer(INPUT = random_points, DISTANCE = 50)
This is basically what package qgis is doing for each available QGIS function while also providing an R help file for each function. Hence, if you prefer running QGIS with callable R functions, check it out.
Second example
As a second example, let’s have a look at how to do raster processing
running GRASS GIS in the background. To compute various terrain
attributes of a digital elevation model, we can use
grass:r.slope.aspect
.
Note: in QGIS versions < 3.36, the processing provider was
still called grass7
(even though this provider works with
GRASS GIS 8). So if you have an older QGIS version, you must
name the algorithms as grass7:r.slope.aspect
etc.
qgis_get_description()
(also included in
qgis_show_help()
) gives us the general description of the
algorithm.
qgis_get_description("grass:r.slope.aspect")
#> grass:r.slope.aspect
#> "Generates raster layers of slope, aspect, curvatures and partial derivatives from a elevation raster layer."
We can find out about the arguments again with the help of
qgis_get_argument_specs()
.
qgis_get_argument_specs("grass:r.slope.aspect")
#> # A tibble: 21 × 6
#> name description qgis_type default_value available_values acceptable_values
#> <chr> <chr> <chr> <list> <list> <list>
#> 1 eleva… Elevation raster <NULL> <NULL> <chr [1]>
#> 2 format Format for… enum <int [1]> <chr [2]> <chr [2]>
#> 3 preci… Type of ou… enum <int [1]> <chr [3]> <chr [2]>
#> 4 -a Do not ali… boolean <lgl [1]> <NULL> <chr [4]>
#> 5 -e Compute ou… boolean <lgl [1]> <NULL> <chr [4]>
#> 6 -n Create asp… boolean <lgl [1]> <NULL> <chr [4]>
#> 7 zscale Multiplica… number <dbl [1]> <NULL> <chr [3]>
#> 8 min_s… Minimum sl… number <dbl [1]> <NULL> <chr [3]>
#> 9 slope Slope rasterDe… <NULL> <NULL> <chr [1]>
#> 10 aspect Aspect rasterDe… <NULL> <NULL> <chr [1]>
#> # ℹ 11 more rows
qgis_get_output_specs()
shows the different outputs that
will be calculated:
qgis_get_output_specs("grass:r.slope.aspect")
#> # A tibble: 9 × 3
#> name description qgis_output_type
#> <chr> <chr> <chr>
#> 1 aspect Aspect outputRaster
#> 2 dx First order partial derivative dx (E-W slope) outputRaster
#> 3 dxx Second order partial derivative dxx outputRaster
#> 4 dxy Second order partial derivative dxy outputRaster
#> 5 dy First order partial derivative dy (N-S slope) outputRaster
#> 6 dyy Second order partial derivative dyy outputRaster
#> 7 pcurvature Profile curvature outputRaster
#> 8 slope Slope outputRaster
#> 9 tcurvature Tangential curvature outputRaster
Now let us calculate the terrain attributes.
library("terra")
# attach digital elevation model from Mt. Mongón (Peru)
dem <- rast(system.file("raster/dem.tif", package = "spDataLarge"))
# if not already done, enable the GRASS GIS plugin
# qgis_enable_plugins("grassprovider")
info <- qgis_run_algorithm(alg = "grass:r.slope.aspect", elevation = dem)
Just printing the info
object shows which output files
have been made:
info
#> <Result of `qgis_run_algorithm("grass:r.slope.aspect", ...)`>
#> List of 9
#> $ aspect : 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c66cc587d.tif"
#> $ dx : 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301cb713f6f.tif"
#> $ dxx : 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c586fa0c.tif"
#> $ dxy : 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c5a9eb3e9.tif"
#> $ dy : 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c4770f3a6.tif"
#> $ dyy : 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c59c6c94b.tif"
#> $ pcurvature: 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c337543ad.tif"
#> $ slope : 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c53d72e11.tif"
#> $ tcurvature: 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c6ebd7312.tif"
Combine these output rasters as a multi-layered
SpatRaster
object and plot it:
# just keep the names of output rasters
nms <- qgis_get_output_specs("grass:r.slope.aspect")$name
# read in the output rasters
r <- info[nms] |>
unlist() |>
rast() |>
as.numeric()
names(r) <- nms
# plot the output
plot(r)
An alternative way to combine the rasters is given below.
r <- lapply(info[nms], \(x) as.numeric(qgis_as_terra(x))) |>
rast()
Since we now have many terrain attributes at our disposal, let us
take the opportunity to add their values to points laying on top of them
with the help of the SAGA algorithm
sagang:addrastervaluestopoints
.
qgis_get_argument_specs("sagang:addrastervaluestopoints")
#> # A tibble: 4 × 6
#> name description qgis_type default_value available_values acceptable_values
#> <chr> <chr> <chr> <list> <list> <list>
#> 1 SHAPES Points source <NULL> <NULL> <chr [1]>
#> 2 GRIDS Grids multilay… <NULL> <NULL> <list [0]>
#> 3 RESULT Result vectorDe… <NULL> <NULL> <chr [1]>
#> 4 RESAMP… Resampling enum <int [1]> <chr [4]> <chr [2]>
The GRIDS
argument is of type multilayer. To pass
multiple layers to one argument, you can either repeat the corresponding
argument as often as needed …
rp_tp <- qgis_run_algorithm(
"sagang:addrastervaluestopoints",
SHAPES = random_points,
GRIDS = qgis_extract_output(info, "aspect"),
GRIDS = qgis_extract_output(info, "slope"),
GRIDS = qgis_extract_output(info, "tcurvature"),
RESAMPLING = 0)
#> Using `RESULT = qgis_tmp_vector()`
… or you can pass to it all needed layers in one list. One could use
the list()
command but it is recommendended to use the
qgis_list_input()
function which is more robust, and
therefore will also support non-JSON-input configurations (e.g. QGIS
< 3.24).
rp_tp <- qgis_run_algorithm(
"sagang:addrastervaluestopoints",
SHAPES = random_points,
GRIDS = qgis_list_input(
qgis_extract_output(info, "aspect"),
qgis_extract_output(info, "slope"),
qgis_extract_output(info, "tcurvature")
),
RESAMPLING = 0)
To verify that it worked, read in the output.
sf::st_as_sf(rp_tp)
#> Simple feature collection with 100 features and 5 fields
#> Geometry type: POINT
#> Dimension: XYZ
#> Bounding box: xmin: 795551.4 ymin: 8932370 xmax: 797242.3 ymax: 8934800
#> z_range: zmin: 0 zmax: 0
#> Projected CRS: WGS 84 / UTM zone 17S
#> # A tibble: 100 × 6
#> id spri file301c66cc587d file301c53d72e11 file301c6ebd7312
#> <int> <int> <dbl> <dbl> <dbl>
#> 1 1 4 251. 6.80 0.0000292
#> 2 2 4 79.7 4.60 -0.00206
#> 3 3 3 290. 6.35 -0.00129
#> 4 4 2 88.8 7.74 0.00108
#> 5 5 4 341. 15.0 -0.000439
#> 6 6 5 276. 16.0 -0.0000909
#> 7 7 6 272. 9.09 -0.000245
#> 8 8 2 300. 4.62 -0.000846
#> 9 9 3 68.9 13.3 -0.00115
#> 10 10 3 101. 12.6 0.00151
#> # ℹ 90 more rows
#> # ℹ 1 more variable: geom <POINT [m]>
Piping
qgis_process
does not lend itself naturally to piping
because its first argument is the name of a geoalgorithm instead of a
data object. qgis_run_algorithm_p()
circumvents this by
accepting a .data
object as its first argument, and pipes
this data object into the first argument of a geoalgorithm assuming that
the specified geoalgorithm needs a data input object as its first
argument.
system.file("longlake/longlake_depth.gpkg", package = "qgisprocess") |>
qgis_run_algorithm_p("native:buffer", DISTANCE = 50)
#> Argument `SEGMENTS` is unspecified (using QGIS default value).
#> Using `END_CAP_STYLE = "Round"`
#> Using `JOIN_STYLE = "Round"`
#> Argument `MITER_LIMIT` is unspecified (using QGIS default value).
#> Argument `DISSOLVE` is unspecified (using QGIS default value).
#> Argument `SEPARATE_DISJOINT` is unspecified (using QGIS default value).
#> Using `OUTPUT = qgis_tmp_vector()`
#> <Result of `qgis_run_algorithm("native:buffer", ...)`>
#> List of 1
#> $ OUTPUT: 'qgis_outputVector' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c2f774fa9.gpkg"
If .data
is a qgis_result
object,
qgis_run_algorithm_p()
automatically tries to select an
element named OUTPUT
. However, if the output has another
name (e.g., DEM_PREPROC
as in the example below) or if
there are multiple output elements to choose from (e.g.,
sagang:sagawetnessindex
has four output rasters, check with
qgis_outputs("sagang:sagawetnessindex")
), you can specify
the wanted output object via the .select
argument. Please
note that we make sure that temporary output raster files, i.e., all
output rasters we do not specifically name ourselves, should use SAGA’s
native raster file format by setting the
qgisprocess.tmp_raster_ext
option to .sdat
.
Using the default raster output format .tif
might lead to
trouble depending on the installed versions of third-party packages
(GDAL, SAGA, etc.).
dem <- system.file("raster/dem.tif", package = "spDataLarge")
# in case you need to enable the SAGA next generation algorithms, run the following line:
# qgis_enable_plugins("processing_saga_nextgen")
oldopt <- options(qgisprocess.tmp_raster_ext = ".sdat")
qgis_run_algorithm(algorithm = "sagang:sinkremoval", DEM = dem,
METHOD = 1) |>
qgis_run_algorithm_p("sagang:sagawetnessindex", .select = "DEM_PREPROC")
#> Argument `SINKROUTE` is unspecified (using QGIS default value).
#> Using `DEM_PREPROC = qgis_tmp_raster()`
#> Argument `THRESHOLD` is unspecified (using QGIS default value).
#> Argument `THRSHEIGHT` is unspecified (using QGIS default value).
#> Argument `WEIGHT` is unspecified (using QGIS default value).
#> Using `AREA = qgis_tmp_raster()`
#> Using `SLOPE = qgis_tmp_raster()`
#> Using `AREA_MOD = qgis_tmp_raster()`
#> Using `TWI = qgis_tmp_raster()`
#> Argument `SUCTION` is unspecified (using QGIS default value).
#> Using `AREA_TYPE = "[0] total catchment area"`
#> Using `SLOPE_TYPE = "[0] local slope"`
#> Argument `SLOPE_MIN` is unspecified (using QGIS default value).
#> Argument `SLOPE_OFF` is unspecified (using QGIS default value).
#> Argument `SLOPE_WEIGHT` is unspecified (using QGIS default value).
#> <Result of `qgis_run_algorithm("sagang:sagawetnessindex", ...)`>
#> List of 4
#> $ AREA : 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c5a80adc5.sdat"
#> $ AREA_MOD: 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301ce54213e.sdat"
#> $ SLOPE : 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c77cdac34.sdat"
#> $ TWI : 'qgis_outputRaster' chr "/tmp/RtmpqO0cLr/file301c2a30d394/file301c42c6668.sdat"
When piping, qgis_run_algorithm_p()
automatically cleans
up after you by deleting intermediate results. This avoids cluttering
your system when running geoalgorithms on large spatial data files. To
turn off this behavior, set .clean
to
FALSE
.
Of course, you can also pipe to qgis_run_algorithm()
by
manually extracting the OUTPUT
object and redirecting it to
the appropriate input argument of the next processing step. This avoids
ambiguity and allows for greater flexibility though it might not be as
convenient as qgis_run_algorithm_p()
. For example,
intermediate results remain on disk for the duration of your R session,
unless you manually call qgis_clean_result()
on a result
object.
result <- qgis_run_algorithm(algorithm = "sagang:sinkremoval", DEM = dem,
METHOD = 1) |>
qgis_extract_output("DEM_PREPROC") |>
qgis_run_algorithm(algorithm = "sagang:sagawetnessindex",
DEM = _)
#> Argument `SINKROUTE` is unspecified (using QGIS default value).
#> Using `DEM_PREPROC = qgis_tmp_raster()`
#> Argument `THRESHOLD` is unspecified (using QGIS default value).
#> Argument `THRSHEIGHT` is unspecified (using QGIS default value).
#> Argument `WEIGHT` is unspecified (using QGIS default value).
#> Using `AREA = qgis_tmp_raster()`
#> Using `SLOPE = qgis_tmp_raster()`
#> Using `AREA_MOD = qgis_tmp_raster()`
#> Using `TWI = qgis_tmp_raster()`
#> Argument `SUCTION` is unspecified (using QGIS default value).
#> Using `AREA_TYPE = "[0] total catchment area"`
#> Using `SLOPE_TYPE = "[0] local slope"`
#> Argument `SLOPE_MIN` is unspecified (using QGIS default value).
#> Argument `SLOPE_OFF` is unspecified (using QGIS default value).
#> Argument `SLOPE_WEIGHT` is unspecified (using QGIS default value).
# or using an anonymous function
# result <- qgis_run_algorithm(algorithm = "sagang:sinkremoval", DEM = dem,
# METHOD = 1) |>
# (\(x) qgis_run_algorithm(algorithm = "sagang:sagawetnessindex",
# DEM = x$DEM_PREPROC[1])) ()
# set the default output raster format to .tif again
options(oldopt)