Skip to contents

As the ever growing R package environment can be a rough terrain to navigate and find the appropriate tools to achieve one’s goals, this vignette is meant to point out some ways to overcome initial problems with visualizing neutral landscape models or more general raster data. This is probably a heavily biased view on packages and functions and I am sure there are other good R packages out there to achieve the same (if so - feel free to point that out to me and I will include it!). However, I am also sure this collection can at least be a kickstart for quickly visualizing your results and help you to communicate them.

Static plots

landscapetools

landscapetools function show_landscape was developed to help users to adhere to some standards concerning color scales and typography. This means for example that by default the viridis color scale is applied which makes your plots easier to read by those with colorblindness.

library("NLMR")
library("landscapetools")

landscape <- nlm_mosaictess(200, 200, germs = 444)

# default theme
show_landscape(landscape)

plot of chunk unnamed-chunk-1

# ... chose another color scale from viridis ("E" = cividis)
show_landscape(landscape, viridis_scale = "E")

plot of chunk unnamed-chunk-1

# ... chose any other scale:
# show_landscape returns a ggplot2 object, so you can follow your usual ggplot2
# workflow and change the color, axis labels, ...
library(ggplot2)
library(pals)
show_landscape(landscape)  + 
  scale_fill_gradientn(colours=pals::parula(100)) + # parula color scale
  theme_void() +  # minimal theme
  guides(fill = FALSE) # remove legend

plot of chunk unnamed-chunk-1

rasterVis

rasterVis also offers some convenience functions to plot raster, for example:

library("NLMR")
library("rasterVis")

landscape <- nlm_mosaictess(200, 200, germs = 444)

levelplot(landscape, , margin = FALSE)

plot of chunk unnamed-chunk-2

Another nice function from rasterVis is gplot(), a wrapper to use ggplot2 with raster data without reshaping your data as long data.frame:

library("NLMR")
library("rasterVis")

landscape <- nlm_mosaictess(200, 200, germs = 444)

gplot(landscape) + 
  geom_tile(aes(fill = value)) + 
  coord_equal()

plot of chunk unnamed-chunk-3

ggplot2

If you want to start from scratch with ggplot2:

library("NLMR")
library("raster")
library("ggplot2")

landscape <- nlm_mosaictess(200, 200, germs = 444)

# transform to long format for ggplot2
landscape_long <- as.data.frame(landscape, xy = TRUE)

# plot with ggplot2
ggplot(landscape_long, aes(x,y)) + 
  geom_tile(aes(fill = layer)) + 
  coord_equal()

plot of chunk unnamed-chunk-4

raster + plot()

… if you are in a lot of hurry, raster itself also has a plot method for raster:

library("NLMR")
library("raster")

landscape <- nlm_mosaictess(200, 200, germs = 444)

plot(landscape)

plot of chunk unnamed-chunk-5

Perspective plot

library("raster")
library("NLMR")
landscape <- nlm_fbm(ncol = 50, nrow = 50, fract_dim = 1.3)
## 'RandomFields' will NOT use OMP
## The package 'RandomFieldsUtils' has been compiled without appropriate SIMD/AVX2 flags. So, calculations can be slow. If the package is recompiled with the necessary flags, the calculations might be faster.
## R should be restarted after re-compiling. The argument 'install.control' might be used to run the re-compilation without asking and to pass further arguments to 'install.packages', e.g., 'RFoptions(install.control=list(verbose=TRUE))'
## To avoid this feedback, set 'RFoptions(install="no")' or 'RFoptions(install="install")' before calling any other function of 'RandomFieldsUtils'.
## 
## RandomFieldsUtils sees SSE2,  but not GPU, AVX2, AVX,OMP.
## 
## 
## Or call 'RFoptions(install="no")' after loading to avoid being asked again.
## Searching for tar balls... 
## The following package will be re-installed:
##  RandomFieldsUtils_1.1.0 from cran
persp(landscape,
      exp=0.5,
      maxpixels = 5000,
      theta = 125,
      phi=45,
      xlab="Longitude",
      ylab="Latitude",
      zlab="Z",
      shade = 0.45)

plot of chunk unnamed-chunk-6

Contour plots

library("NLMR")
library("rasterVis")

landscape <- nlm_mpd(ncol = 50, nrow = 50, roughness = 0.6)


contourplot(landscape,
            pretty = TRUE) 

plot of chunk unnamed-chunk-7

levelplot(landscape,
          contour = TRUE,
          pretty = TRUE)

plot of chunk unnamed-chunk-7

Interactive plots

rgl + rasterVis

library("rgl")
library("rasterVis")
library("viridis")
library("NLMR")
landscape <- nlm_mpd(ncol = 100, nrow = 100, roughness = 0.6)

plot3D(landscape,
       zfac=2,
       lit=FALSE,
       col=colorRampPalette(magma(11)))

rglwidget()

plot of chunk unnamed-chunk-8

highcharter + plotly

library("highcharter")
library("magrittr")
library("plotly")
library("NLMR")

# create a NLM to work with
landscape <- nlm_mosaicfield(ncol = 100, nrow = 100, n = 20)

# coerce to matrix
landscape_matrix <- raster::as.matrix(landscape)

# plot interactive graph
hchart(landscape_matrix) %>%
  # changing default color
  hc_colorAxis(stops = color_stops(colors = viridis::inferno(10))) %>%
  hc_exporting(
    enabled = TRUE
  )

plot of chunk unnamed-chunk-9

# With plotly we can combine the interactive approach with the 3D Visualization
plot_ly(z = as.matrix(landscape_matrix), type = "surface", colors = viridis::magma(8))

plot of chunk unnamed-chunk-9

rayshader

library(rayshader)
library(NLMR)
library(raster)
library(rgl)

set.seed(123)

landscape <- nlm_mpd(1000, 1000, roughness = 0.6, rescale = FALSE) * 500
landscape <- raster::focal(landscape, w=matrix(1, 31, 31), mean, pad = TRUE, padValue=0)
landscape <- raster::as.matrix(landscape)

shadow = ray_shade(landscape,
                   zscale=1,
                   lambert=FALSE)
amb = ambient_shade(landscape,
                    zscale=1,
                    sunbreaks = 15, 
                    maxsearch = 100)

landscape %>%
  sphere_shade(zscale=5,texture = "imhof1") %>% 
  add_water(detect_water(landscape, min_area = 4000)) %>%
  add_shadow(shadow,0.7) %>%
  add_shadow(amb) %>%
  add_shadow(lamb_shade(landscape)) %>%
  plot_3d(landscape,
          zscale=5,
          fov=0,
          theta=-45,
          phi=45,
          windowsize=c(1200,1200),
          zoom=1.2,
          water=TRUE, 
          wateralpha = 0.8,
          watercolor = "lightblue",
          waterlinecolor = "white",
          waterlinealpha = 0.3,
          solid = FALSE) 

library(rayshader)
library(NLMR)
library(raster)
library(rgl)

set.seed(123)

landscape <- nlm_mpd(1000, 1000, roughness = 0.6, rescale = FALSE) * 500
landscape <- raster::focal(landscape, w=matrix(1, 31, 31), mean, pad = TRUE, padValue=0)
landscape <- raster::as.matrix(landscape)

shadow = ray_shade(landscape,
                   zscale=1,
                   lambert=FALSE)
amb = ambient_shade(landscape,
                    zscale=1,
                    sunbreaks = 15, 
                    maxsearch = 100)

landscape %>%
  sphere_shade(zscale=5,texture = "imhof1") %>% 
  add_water(detect_water(landscape, min_area = 4000)) %>%
  add_shadow(shadow,0.7) %>%
  add_shadow(amb) %>%
  add_shadow(lamb_shade(landscape)) %>%
  plot_3d(landscape,
          zscale = 5,
          fov = 0,
          theta = -45,
          phi = 45,
          windowsize = c(1200, 1200),
          zoom = 1.2,
          water = TRUE,
          wateralpha = 0.8,
          watercolor = "lightblue",
          waterlinecolor = "white",
          waterlinealpha = 0.3,
          solid = TRUE,
          solidcolor = "grey75")

render_depth(
  focallength = 30,
  fstop = 2,
  bokehshape = "hex",
  bokehintensity = 5,
  progbar = FALSE
)

plot of chunk unnamed-chunk-11