The BioDT Recreational Potential Model for Scotland

Worked example

Authors
Affiliation

Joe Marsh Rossney

UK Centre for Ecology & Hydrology

Maddalena Tigli

Chris Andrews

Jan Dick

Simon Rolph

Published

June 24, 2025

Modified

June 24, 2025

Abstract

This notebook demonstrates basic usage of the Recreational Potential model. It is assumed that the user is familiar with installing R packages, executing lines of R code in interactive sessions, and running R scripts.

Getting started

The Recreational Potential model has been developed on recent (2025) versions of R — specifically versions 4.4.2 up to 4.5.0. We cannot guarantee that it will work for versions of R outside of this range.

The following command tells you what version is currently active:

# Ideally this should be between 4.4.2 and 4.5.0
R.version.string
[1] "R version 4.5.0 (2025-04-11)"

Certain C++ libraries are required for the model to work, most importantly related to GDAL. See the terra documentation for guidance.

It is recommended to perform the following steps using an R environment managed by renv.

Ensure you have either remotes or devtools installed (using e.g. install.packages or renv::install).

install.packages("remotes")
The following package(s) will be installed:
- remotes [2.5.0]
These packages will be installed into "~/github.com/BioDT/ces-recreation-reports/renv/library/linux-ubuntu-jammy/R-4.5/x86_64-pc-linux-gnu".

# Installing packages --------------------------------------------------------
- Installing remotes ...                        OK [linked from cache]
Successfully installed 1 package in 4.4 milliseconds.

Now install the package itself. We will target version 1.0.1

remotes::install_github("BioDT/uc-ces-recreation", ref="v1.0")
Using GitHub PAT from the git credential store.
Skipping install of 'biodt.recreation' from a github remote, the SHA1 (c5f60e30) has not changed since last install.
  Use `force = TRUE` to force installation

Next, you will need to download the input data. The total size is over 2GB, so it is important to set the timeout option to something generous.

options(timeout=1200)
biodt.recreation::download_data()
Skipping download of SLSRA since /home/joe/github.com/BioDT/ces-recreation-reports/renv/library/linux-ubuntu-jammy/R-4.5/x86_64-pc-linux-gnu/biodt.recreation/extdata/rasters/Scotland/SLSRA.tif already exists.
Skipping download of FIPS_N since /home/joe/github.com/BioDT/ces-recreation-reports/renv/library/linux-ubuntu-jammy/R-4.5/x86_64-pc-linux-gnu/biodt.recreation/extdata/rasters/Scotland/FIPS_N.tif already exists.
Skipping download of FIPS_I since /home/joe/github.com/BioDT/ces-recreation-reports/renv/library/linux-ubuntu-jammy/R-4.5/x86_64-pc-linux-gnu/biodt.recreation/extdata/rasters/Scotland/FIPS_I.tif already exists.
Skipping download of Water since /home/joe/github.com/BioDT/ces-recreation-reports/renv/library/linux-ubuntu-jammy/R-4.5/x86_64-pc-linux-gnu/biodt.recreation/extdata/rasters/Scotland/Water.tif already exists.
Where are the files?

Do not be alarmed if you cannot see any new files appearing in your working directory. When download_data is called without arguments, the data will be downloaded to the default location which is inside the directory in which the package is installed (under the subdirectory extdata/rasters/Scotland/). You may not know where on your filesystem packages are installed, but that’s ok — the package knows where to look for these files.

The preset personas

We first demonstrate the RP Model applied to an area surrounding the Bush estate near Edinburgh2 using two contrasting personas:

  1. Hard Recreationalist: this persona values remote, challenging environments and avoids built-up or highly managed areas.
  2. Soft Recreationalist: this persona values tranquil, accessible landscapes and natural water features, and avoids steep or harsh terrain.

The resulting maps will illustrate how different preferences lead to different areas being highlighted for recreational value.

These personas are provided in the model as ‘presets’; users may customise them or simply use them out-of-the-box.

First, let’s save ourselves some typing of biodt.recreation::<function> by exposing all of the functions in the biodt.recreation namespace.

library(biodt.recreation)

Now we will load the Hard Recreationalist and Soft Recreationalist personas from the presets file.

persona_file <- get_preset_persona_file()

hard_recreationalist <- load_persona(persona_file, "Hard_Recreationalist")
Loading persona 'Hard_Recreationalist' from file '/home/joe/github.com/BioDT/ces-recreation-reports/renv/library/linux-ubuntu-jammy/R-4.5/x86_64-pc-linux-gnu/biodt.recreation/extdata/personas/presets.csv'
soft_recreationalist <- load_persona(persona_file, "Soft_Recreationalist")
Loading persona 'Soft_Recreationalist' from file '/home/joe/github.com/BioDT/ces-recreation-reports/renv/library/linux-ubuntu-jammy/R-4.5/x86_64-pc-linux-gnu/biodt.recreation/extdata/personas/presets.csv'

The tab panel below is helpful for inspecting and comparing the two preset personas.

Show definition of persona_table and persona_hist
persona_table <- function(persona) {

  # Construct named vector of persona descriptions
  config <- load_config()
  descriptions <- stats::setNames(config$Description, config$Name)

  # Align order (just in case)
  descriptions <- descriptions[names(persona)]

  # Construct data.frame from the two named vectors
  df <- data.frame(
    Item = names(persona),
    Description = as.vector(descriptions),
    Score = as.vector(persona)
  )

  # Convert dataframe to HTML table
  knitr::kable(df)
}

persona_hist <- function(persona) {

  # Make 2x2 grid for histograms
  par(mfrow = c(2, 2))

  for (component in c("SLSRA", "FIPS_N", "FIPS_I", "Water")) {

    # Scores for this component
    persona_subset <- persona[grep(paste0("^", component), names(persona))]

    # Construct histogram with 11 equally space bins centred on
    # the integers 0, 1, ..., 10.
    hist(
      persona_subset,
      main=component,
      breaks=seq(-0.5, 10.5, by=1),
      xlab="Score",
      ylab="Frequency"
    )
  }
}
persona_hist(hard_recreationalist)

persona_table(hard_recreationalist)
Item Description Score
FIPS_I_LocalPathNetwork_2 Path 5
FIPS_I_NationalCycleNetwork_1 On Road: Paved Surface 2
FIPS_I_NationalCycleNetwork_2 Traffic Free: Unpaved Surface 8
FIPS_I_NationalCycleNetwork_3 Traffic Free: Paved Surface 6
FIPS_I_NationalCycleNetwork_4 On Road: Unpaved Surface 7
FIPS_I_RoadsTracks_1 Motorway 0
FIPS_I_RoadsTracks_2 A Road 0
FIPS_I_RoadsTracks_3 B Road 0
FIPS_I_RoadsTracks_4 Minor or local road 0
FIPS_I_RoadsTracks_5 Access roads or Track 0
FIPS_N_Landform_1 Foothills 7
FIPS_N_Landform_10 Rock Walls 10
FIPS_N_Landform_11 Uplands 7
FIPS_N_Landform_12 Valley sides 7
FIPS_N_Landform_13 Valley bottom 3
FIPS_N_Landform_14 Built-up areas 1
FIPS_N_Landform_15 Saltings 0
FIPS_N_Landform_16 Hummocks, mounds or moraines 3
FIPS_N_Landform_2 Mountains 10
FIPS_N_Landform_3 Terraces 5
FIPS_N_Landform_4 Flood plain 1
FIPS_N_Landform_5 Beaches or Dunes 7
FIPS_N_Landform_6 Rocks or Scree 6
FIPS_N_Landform_7 Depressions 1
FIPS_N_Landform_8 Hills 6
FIPS_N_Landform_9 Lowlands 3
FIPS_N_Slope_1 No slope 1
FIPS_N_Slope_2 Gentle slope 1
FIPS_N_Slope_3 Medium slope 2
FIPS_N_Slope_4 Steep slope 4
FIPS_N_Slope_5 Very steep slope 7
FIPS_N_Slope_6 Extremely steep slope 8
FIPS_N_Soil_1 Peat or Organic 6
FIPS_N_Soil_2 Mineral 2
SLSRA_CP_2 Country Park 1
SLSRA_HNV_2 Designated High Nature Value (HNV) farmland 4
SLSRA_LCM_1 Alpine and subalpine grassland 8
SLSRA_LCM_10 Dry grassland 5
SLSRA_LCM_11 Freshwater 7
SLSRA_LCM_12 Inland cliffs, rock pavements and outcrops 10
SLSRA_LCM_13 Lines of trees, small planted woodlands, early-stage woodland and coppice 2
SLSRA_LCM_14 Littoral sediment or saltmarsh 2
SLSRA_LCM_15 Mesic grassland 4
SLSRA_LCM_16 Mixed deciduous and coniferous woodland 5
SLSRA_LCM_17 Non-native coniferous plantation 2
SLSRA_LCM_18 Raised and blanket bog 1
SLSRA_LCM_19 Riverine and fen scrubs 2
SLSRA_LCM_2 Arable land and market gardens 2
SLSRA_LCM_20 Rock cliffs, ledges and shores 10
SLSRA_LCM_21 Scots pine woodland 7
SLSRA_LCM_22 Screes 5
SLSRA_LCM_23 Seasonally wet and wet grassland 5
SLSRA_LCM_24 Temperate montane scrub 7
SLSRA_LCM_25 Temperate shrub heathland 7
SLSRA_LCM_26 Valley mires, poor fens and transition mires 1
SLSRA_LCM_27 Windthrown woodland 1
SLSRA_LCM_28 Woodland fringes and clearings and tall forb stands 1
SLSRA_LCM_3 Arctic, alpine and subalpine scrub 8
SLSRA_LCM_4 Bare field or exposed soil 1
SLSRA_LCM_5 Base-rich fens and calcareous spring mires 2
SLSRA_LCM_6 Broadleaved deciduous woodland 7
SLSRA_LCM_7 Built-up area 1
SLSRA_LCM_8 Coastal dunes and sandy shore 7
SLSRA_LCM_9 Coastal shingle 3
SLSRA_NNR_2 National Nature Reserve (NNR) 6
SLSRA_NP_2 National Park 10
SLSRA_NR_2 Nature Reserve 3
SLSRA_RP_2 Regional Park 2
SLSRA_RSPB_2 Royal Society for the Protection of Birds (RSPB) Reserve 1
SLSRA_SAC_2 Special Area of Conservation (SAC) 3
SLSRA_SPA_2 Special Protection Area (SPA) 3
SLSRA_SSSI_2 Site of Special Scientific Interest (SSSI) 2
SLSRA_SWT_2 Scottish Wildlife Trust Reserve 2
SLSRA_WLA_2 Wild Land Areas 7
Water_Lakes_1 Pond 1
Water_Lakes_2 Lochan 3
Water_Lakes_3 Small Lochs 5
Water_Lakes_4 Medium Lochs 4
Water_Lakes_5 Large Lochs 7
Water_Lakes_6 Major Lochs 7
Water_Rivers_1 Minor river or tributary 3
Water_Rivers_2 Unnamed minor stream or tributary 3
Water_Rivers_3 Major river or tributary 7
Water_Rivers_4 Named minor stream or tributary 3
Water_Rivers_5 Lake 5
Water_Rivers_6 Tidal river or estuary 4
Water_Rivers_7 Canal 3
persona_hist(soft_recreationalist)

persona_table(soft_recreationalist)
Item Description Score
FIPS_I_LocalPathNetwork_2 Path 7
FIPS_I_NationalCycleNetwork_1 On Road: Paved Surface 5
FIPS_I_NationalCycleNetwork_2 Traffic Free: Unpaved Surface 6
FIPS_I_NationalCycleNetwork_3 Traffic Free: Paved Surface 10
FIPS_I_NationalCycleNetwork_4 On Road: Unpaved Surface 5
FIPS_I_RoadsTracks_1 Motorway 0
FIPS_I_RoadsTracks_2 A Road 0
FIPS_I_RoadsTracks_3 B Road 3
FIPS_I_RoadsTracks_4 Minor or local road 5
FIPS_I_RoadsTracks_5 Access roads or Track 8
FIPS_N_Landform_1 Foothills 8
FIPS_N_Landform_10 Rock Walls 1
FIPS_N_Landform_11 Uplands 7
FIPS_N_Landform_12 Valley sides 2
FIPS_N_Landform_13 Valley bottom 7
FIPS_N_Landform_14 Built-up areas 1
FIPS_N_Landform_15 Saltings 0
FIPS_N_Landform_16 Hummocks, mounds or moraines 3
FIPS_N_Landform_2 Mountains 4
FIPS_N_Landform_3 Terraces 3
FIPS_N_Landform_4 Flood plain 2
FIPS_N_Landform_5 Beaches or Dunes 9
FIPS_N_Landform_6 Rocks or Scree 1
FIPS_N_Landform_7 Depressions 1
FIPS_N_Landform_8 Hills 4
FIPS_N_Landform_9 Lowlands 8
FIPS_N_Slope_1 No slope 9
FIPS_N_Slope_2 Gentle slope 8
FIPS_N_Slope_3 Medium slope 6
FIPS_N_Slope_4 Steep slope 4
FIPS_N_Slope_5 Very steep slope 3
FIPS_N_Slope_6 Extremely steep slope 1
FIPS_N_Soil_1 Peat or Organic 3
FIPS_N_Soil_2 Mineral 5
SLSRA_CP_2 Country Park 8
SLSRA_HNV_2 Designated High Nature Value (HNV) farmland 5
SLSRA_LCM_1 Alpine and subalpine grassland 2
SLSRA_LCM_10 Dry grassland 3
SLSRA_LCM_11 Freshwater 9
SLSRA_LCM_12 Inland cliffs, rock pavements and outcrops 3
SLSRA_LCM_13 Lines of trees, small planted woodlands, early-stage woodland and coppice 6
SLSRA_LCM_14 Littoral sediment or saltmarsh 4
SLSRA_LCM_15 Mesic grassland 5
SLSRA_LCM_16 Mixed deciduous and coniferous woodland 9
SLSRA_LCM_17 Non-native coniferous plantation 7
SLSRA_LCM_18 Raised and blanket bog 5
SLSRA_LCM_19 Riverine and fen scrubs 4
SLSRA_LCM_2 Arable land and market gardens 4
SLSRA_LCM_20 Rock cliffs, ledges and shores 6
SLSRA_LCM_21 Scots pine woodland 9
SLSRA_LCM_22 Screes 1
SLSRA_LCM_23 Seasonally wet and wet grassland 5
SLSRA_LCM_24 Temperate montane scrub 3
SLSRA_LCM_25 Temperate shrub heathland 7
SLSRA_LCM_26 Valley mires, poor fens and transition mires 3
SLSRA_LCM_27 Windthrown woodland 1
SLSRA_LCM_28 Woodland fringes and clearings and tall forb stands 3
SLSRA_LCM_3 Arctic, alpine and subalpine scrub 2
SLSRA_LCM_4 Bare field or exposed soil 1
SLSRA_LCM_5 Base-rich fens and calcareous spring mires 5
SLSRA_LCM_6 Broadleaved deciduous woodland 9
SLSRA_LCM_7 Built-up area 3
SLSRA_LCM_8 Coastal dunes and sandy shore 10
SLSRA_LCM_9 Coastal shingle 6
SLSRA_NNR_2 National Nature Reserve (NNR) 7
SLSRA_NP_2 National Park 10
SLSRA_NR_2 Nature Reserve 6
SLSRA_RP_2 Regional Park 4
SLSRA_RSPB_2 Royal Society for the Protection of Birds (RSPB) Reserve 6
SLSRA_SAC_2 Special Area of Conservation (SAC) 6
SLSRA_SPA_2 Special Protection Area (SPA) 5
SLSRA_SSSI_2 Site of Special Scientific Interest (SSSI) 3
SLSRA_SWT_2 Scottish Wildlife Trust Reserve 3
SLSRA_WLA_2 Wild Land Areas 3
Water_Lakes_1 Pond 5
Water_Lakes_2 Lochan 3
Water_Lakes_3 Small Lochs 3
Water_Lakes_4 Medium Lochs 5
Water_Lakes_5 Large Lochs 7
Water_Lakes_6 Major Lochs 10
Water_Rivers_1 Minor river or tributary 4
Water_Rivers_2 Unnamed minor stream or tributary 1
Water_Rivers_3 Major river or tributary 8
Water_Rivers_4 Named minor stream or tributary 2
Water_Rivers_5 Lake 8
Water_Rivers_6 Tidal river or estuary 7
Water_Rivers_7 Canal 7

Computing Recreational Potential

We will now compare results in the ‘example’ region of interest (the Bush estate).

bbox <- get_example_bbox()

To compute Recreational Potential, as well as each individual component, we use the compute_potential function.

layers_hr <- compute_potential(hard_recreationalist, bbox)
Selected an area of 3.1e+07 m^2 .
layers_sr <- compute_potential(soft_recreationalist, bbox)
Selected an area of 3.1e+07 m^2 .

This returns a raster with 5 named layers.

  1. SLSRA
  2. FIPS_N
  3. FIPS_I
  4. Water
  5. Recreational_Potential

To plot all layers together we could simply call terra::plot(layers). However, here we will separate the components plot from the RP plot.

#Set the colour palette for the heatmaps
palette <- terra::map.pal("bgyr")

First, the component layers.

terra::panel(terra::subset(layers_hr, 1:4), nc=2, col=palette)

terra::panel(terra::subset(layers_sr, 1:4), nc=2, col=palette)

Next, the Recreational Potential layers.

terra::plot(layers_hr$Recreational_Potential, col=palette)

terra::plot(layers_sr$Recreational_Potential, col=palette)

Defining a region of interest

A rectangular region of interest can be easily constructed using terra::ext by passing a vector of coordinates (xmin, xmax, ymin, ymax).3

xmin <- 300000
xmax <- 310000
ymin <- 700000
ymax <- 710000
bbox <- terra::ext(c(xmin, xmax, ymin, ymax))

Let’s visualise this area on a map of Scotland.

Scotland <- terra::vect(
  system.file(
    "extdata", "shapefiles", "Scotland", "Scotland.shp", package="biodt.recreation"
  )
)

terra::plot(Scotland)
terra::plot(bbox, border = "red", add = TRUE)

Editing a persona

Creating or editing personas is far easier using the Shiny app, some spreadsheet software, or even just a text editor. However, for completeness, we demonstrate how to edit a persona dynamically within R.

Let’s say we want to modify the Hard Recreationalist persona to better fit an off-road cyclist who does not want to cycle straight up a mountain. We will edit the slope scores and the cycle path scores.

# Note that assignment + edit in R automatically results in a copy!
custom_persona <- hard_recreationalist

custom_persona[["FIPS_I_NationalCycleNetwork_1"]] <- 5  # on-road, paved
custom_persona[["FIPS_I_NationalCycleNetwork_2"]] <- 10 # traffic-free, unpaved
custom_persona[["FIPS_I_NationalCycleNetwork_3"]] <- 10 # traffic-free, paved
custom_persona[["FIPS_I_NationalCycleNetwork_4"]] <- 10 # on-road, unpaved
custom_persona[["FIPS_I_RoadsTracks_5"]] <- 8  # access roads / tracks

custom_persona[["FIPS_N_Slope_1"]] <- 7  # no slope
custom_persona[["FIPS_N_Slope_2"]] <- 8  # gentle
custom_persona[["FIPS_N_Slope_3"]] <- 6  # medium
custom_persona[["FIPS_N_Slope_4"]] <- 4  # steep
custom_persona[["FIPS_N_Slope_5"]] <- 2  # very steep
custom_persona[["FIPS_N_Slope_6"]] <- 1  # extremely steep

We can calculate the RP values as before and compare the results.

layers_hr <- compute_potential(hard_recreationalist, bbox)
Selected an area of 1.0e+08 m^2 .
layers_custom <- compute_potential(custom_persona, bbox)
Selected an area of 1.0e+08 m^2 .
terra::panel(terra::subset(layers_hr, 1:4), nc=2, col=palette)

terra::panel(terra::subset(layers_custom, 1:4), nc=2, col=palette)

terra::plot(layers_hr$Recreational_Potential, col=palette)

terra::plot(layers_custom$Recreational_Potential, col=palette)

Interactive plots

To create a simple interactive plot is very easy using terra::plet.

terra::plet(layers_custom, 1:5, col=palette, tiles="Esri.WorldImagery", shared=TRUE)

You can explore different background tiles over at https://leaflet-extras.github.io/leaflet-providers/preview/.

Access to code & data

Code for the Recreational Potential model is available as an R Package hosted on GitHub at https://github.com/BioDT/uc-ces-recreation. These reports relate specifically to the version 1.0 release, which is also available on Zenodo at https://doi.org/10.5281/zenodo.15705544.

The model requires some input data that is too large to be bundled in with the package, but which can be downloaded from Dropbox after package installation using biodt.recreation::download_data(). This data is also included in the Zenodo listing.

The source for these documents and this website can be found at https://github.com/BioDT/ces-recreation-reports.

Funding

Funding for OpenNESS came from the European Community’s Seventh Framework Programme (FP7/2007-2013) under grant agreement no 308428, OpenNESS Project (Operationalisation of Natural Capital and Ecosystem Services: From Concepts to Real-world Applications.)

Funding for BioDT came from the European Union’s Horizon Europe Research and Innovation Programme under grant agreement No 101057437 (BioDT project, https://doi.org/10.3030/101057437). Views and opinions expressed are those of the author(s) only and do not necessarily reflect those of the European Union or the European Commission. Neither the European Union nor the European Commission can be held responsible for them.

Funding for SPEAK came from the Natural Environment Research Council – Growing Shoots Partnership and application co-creation bursary. NE/Y005805/1 _Growing Shoots.

CRediT statement

JMR: software; visualisation; writing. MT: software; visualisation; writing. CA: conceptualisation; data curation; funding acquisition; software. JD: conceptualisation; funding acquisition; project administration. SR: funding acquisition; software.

Acknowledgements

We wish to acknowledge significant contributions to a previous version of the Recreational Potential model by Will Bolton. JMR would also like to thank Tomáš Martinovič for assisting with understanding the requirements of BioDT.

We are very grateful to all the participants of the SPEAK project which this output is based on including: Alastair Leaver, Alice MacSporran, Brian Cassidy, Chris Pollock, David Giles, Jean Cowie, Joanna Gilliatt, Justyna Olszewska, Laura Taylor, Maddi Bunker, Rebecca MacLennan, S Mayes, Shaila Rao, Steve MacKinnon and Tom Gebbie, Active Stirling. We are equally grateful to an additional 18 participants who preferred to remain anonymous.

Correspondence

  • {jand,chan}@ceh.ac.uk for enquiries relating to the BioDT or SPEAK projects, or ongoing and future work.

  • chan@ceh.ac.uk for enquiries relating to the data sources and QGIS processing.

  • {joemar,madtig}@ceh.ac.uk for enquiries relating to the code and anything else appearing in the technical supplement and/or developer’s report.

  • simrol@ceh.ac.uk for enquiries relating to the biodiversity component of the BioDT project.

Footnotes

  1. Since future updates to the code may be incompatible with this notebook, we will target the specific version released at the time this notebook was written.↩︎

  2. This is where the UK Centre for Ecology & Hydrology is based.↩︎

  3. A region of interest may also be given by a path to a shapefile.↩︎

Reuse

Citation

BibTeX citation:
@report{ukceh2025,
  author = {Marsh Rossney, Joe and Tigli, Maddalena and Andrews,
    Christopher and Dick, Jan and Rolph, Simon},
  publisher = {Zenodo},
  title = {Reports on the {BioDT} {Recreational} {Potential} {Model} for
    {Scotland}},
  version = {1.0},
  date = {2025-06},
  url = {https://doi.org/10.5281/zenodo.15715070},
  doi = {10.5281/zenodo.15715070},
  langid = {en},
  abstract = {These reports describe the BioDT Recreational Potential
    Model for Scotland (1.0), at the end of the BioDT project in June
    2025.}
}
For attribution, please cite this work as:
Marsh Rossney, J., Tigli, M., Andrews, C., Dick, J., & Rolph, S. (2025). Reports on the BioDT Recreational Potential Model for Scotland (Version 1.0). Zenodo. https://doi.org/10.5281/zenodo.15715070