Skip to content
Snippets Groups Projects
plot_global.R 7.3 KiB
Newer Older
Jannes Breier's avatar
Jannes Breier committed
#' Plot global LPJmL array
#'
#' Plot global LPJmL array to file (if file argument is given) or screen (else).
#'    type argument controls plot type: (exponential, linear, or manual legend).
#'    Depending on this more parameters are required.
#'    Data plot ranges:
#'      exp: c(-2^pow2max,-2^-pow2min,0,2^-pow2min,2^pow2max)
#'      lin: c(min,max)
#'      man: brks
Jannes Breier's avatar
Jannes Breier committed
#'    colors for pos and neg values can be given, default is Blues for the
#'    positive and Reds for the negative numbers 0-range (from 2^-pow2min to
#'    2^pow2min) is white.
#'    The negatives can be omitted by setting only_pos=TRUE, in case there are
#'    only pos values.
#'
#' @param data array with data to plot in LPJmL specific array c(67420)
#' @param file character string for location/file to save plot to, if not 
#'             supplied, the plot is displayed to screen (default: NULL)
Jannes Breier's avatar
Jannes Breier committed
#' @param title character string title for plot
#' @param pow2max for exponential legend: upper (positive) end of data range to
#'                plot (2^pow2max)
#' @param pow2min for exponential legend: smallest positive number to be
#'                distinguished from 0 (2^-pow2min)
#' @param max for linear legend: upper end of data range to plot (0 is placed
#'            symmetrically between min and max, if onlypos = FALSE)
#' @param min for linear legend: lower end of data range to plot (0 is placed
#'            symmetrically between min and max, if onlypos = FALSE)
#' @param col_pos color palette for the positives
#' @param col_neg color palette for the negatives
#' @param type string indicating whether to plot manual (man),
#'             exponential (exp) or linear (lin) legend (default: exp).
Jannes Breier's avatar
Jannes Breier committed
#'             man requires: parameters brks and palette defined,
#'             exp requires: parameters pow2min and pow2max given defined,
#'             lin requires: parameters min and max defined
Jannes Breier's avatar
Jannes Breier committed
#' @param legendtitle character string legend title
#' @param leg_yes boolean whether to show legend (default: TRUE)
#' @param n_legend_ticks (default: 20)
#' @param min_0 (default: 0.01)
Jannes Breier's avatar
Jannes Breier committed
#' @param only_pos boolean to show only positive half of legend (default: FALSE)
#' @param eps boolean whether to write eps file instead of PNG (default: FALSE)
#'
#' @examples
#' \dontrun{
#'   data = biocol_data$biocol[,"2015"]),
#'   file = "BioCol_absolute_2015.png",
#'   type = "exp",
#'   pow2min = 0,
#'   pow2max = 12,
#'   legendtitle = "GtC",
#'   leg_yes = TRUE,
#'   only_pos = FALSE,
Jannes Breier's avatar
Jannes Breier committed
#' }
#'
Jannes Breier's avatar
Jannes Breier committed
#' @export
plot_global <- function(data,
                        file = NULL,
Jannes Breier's avatar
Jannes Breier committed
                        title = "",
                        pow2min = NULL,
                        pow2max = NULL,
Jannes Breier's avatar
Jannes Breier committed
                        min = NULL,
                        max = NULL,
                        brks = NULL,
                        palette = NULL,
Jannes Breier's avatar
Jannes Breier committed
                        col_pos = "GnBu",
                        type = "exp",
                        col_neg = "YlOrRd",
                        legendtitle = "",
                        leg_yes = TRUE,
                        only_pos = FALSE,
                        n_legend_ticks = 20,
                        min_0 = 0.01,
                        eps = FALSE) {
  if (!is.null(file)) {
    if (eps) {
      file <- strsplit(file, ".", fixed = TRUE)[[1]]
Jannes Breier's avatar
Jannes Breier committed
      file <- paste(c(file[seq_len(length(file) - 1)], "eps"), collapse = ".")
Jannes Breier's avatar
Jannes Breier committed

      grDevices::ps.options(family = c("Helvetica"), pointsize = 18)
Jannes Breier's avatar
Jannes Breier committed
      grDevices::postscript(file,
        horizontal = FALSE, onefile = FALSE, width = 22,
        height = 8.5, paper = "special"
      )
Jannes Breier's avatar
Jannes Breier committed
      grDevices::png(file,
        width = 7.25, height = 3.5, units = "in", res = 300,
        pointsize = 6, type = "cairo"
      )
Jannes Breier's avatar
Jannes Breier committed

  if (only_pos) {
    if (type == "exp") {
      if (is.null(pow2max) | is.null(pow2min)) {
        stop("For exponental legend, pow2min and pow2max need to be specified.")
      }
      # actual brks and ticks
      legendticks <- c(0, 2^seq(pow2min, pow2max, 1))
      # just for displaying an equally sized legend
      brks <- c(seq(pow2min, pow2max, length.out = length(legendticks)))
    } else if (type == "lin") {
      if (is.null(max) | is.null(min)) {
        stop("For linear legend, min and max need to be specified.")
      }
      legendticks <- seq(min, max, length.out = n_legend_ticks)
Jannes Breier's avatar
Jannes Breier committed
      brks <- legendticks
    }
    palette <- c(
      "white",
      grDevices::colorRampPalette(RColorBrewer::brewer.pal(9, col_pos))(length(legendticks) - 2) # nolint
    )
  } else {
    if (type == "exp" || type == "lin") {
      if (type == "exp") {
        if (is.null(pow2max) | is.null(pow2min)) {
          stop("For exponental legend, pow2min and pow2max need to be specified.")
        }
        legendticks <- c(
          -(2^seq(pow2max, pow2min, -1)), 2^seq(pow2min, pow2max, 1)
        )
        brks <- seq(-pow2max, pow2max, length.out = length(legendticks))
      } else if (type == "lin") {
        if (is.null(max) | is.null(min)) {
          stop("For linear legend, min and max need to be specified.")
        }
Jannes Breier's avatar
Jannes Breier committed
        if (n_legend_ticks %% 2 == 0) {
          n_legend_ticks <- n_legend_ticks + 1
        }
Jannes Breier's avatar
Jannes Breier committed
        legendticks <- c(
          seq(min, 0, length.out = n_legend_ticks),
          seq(0, max, length.out = n_legend_ticks)
        )
        legendticks[c(n_legend_ticks, (n_legend_ticks + 1))] <- c(-min_0, min_0)
        brks <- legendticks
Jannes Breier's avatar
Jannes Breier committed
      }
      palette <- c(
        rev(
          grDevices::colorRampPalette(RColorBrewer::brewer.pal(9, col_neg))(length(legendticks) / 2 - 1) # nolint
        ),
        "white",
        grDevices::colorRampPalette(RColorBrewer::brewer.pal(9, col_pos))(length(legendticks) / 2 - 1) # nolint
Jannes Breier's avatar
Jannes Breier committed
      )
    } else { # type == man
      if (only_pos) stop("Manual breaks and palette, but conflicting parameter
              only_pos == TRUE defined. Aborting.")
      legendticks <- brks
Jannes Breier's avatar
Jannes Breier committed
    }
  }
  data[data < legendticks[1]] <- legendticks[1]
  data[data > legendticks[length(legendticks)]] <- (
    legendticks[length(legendticks)]
  )

  ra <- terra::rast(ncols = 720, nrows = 360)
Jannes Breier's avatar
Jannes Breier committed
  range <- range(data)
  ra[terra::cellFromXY(ra, cbind(lon, lat))] <- data
  extent <- terra::ext(c(-180, 180, -60, 90))
Jannes Breier's avatar
Jannes Breier committed

  if (leg_yes) {
Jannes Breier's avatar
Jannes Breier committed
    graphics::par(
      bty = "n", oma = c(0, 0, 0, 3), mar = c(0, 0, 0, 0),
      xpd = TRUE
    )
Jannes Breier's avatar
Jannes Breier committed
  } else {
Jannes Breier's avatar
Jannes Breier committed
    graphics::par(
      bty = "n", oma = c(0, 0, 0, 0), mar = c(0, 0, 0, 0),
      xpd = TRUE
    )
Jannes Breier's avatar
Jannes Breier committed
  }
Jannes Breier's avatar
Jannes Breier committed
  terra::plot(ra,
    ext = extent, breaks = legendticks, col = palette, main = title,
    legend = FALSE, axes = FALSE
  )
  maps::map("world", add = TRUE, res = 0, lwd = 0.1, ylim = c(-60, 90))
Jannes Breier's avatar
Jannes Breier committed
  title(title, line = -1)
  if (leg_yes) {
    if (type == "exp") {
      fields::image.plot(
        legend.only = TRUE, zlim = c(-pow2max, pow2max), col = palette,
        useRaster = FALSE, breaks = brks, lab.breaks = round(legendticks, 2),
        legend.shrink = 0.7,
        legend.args = list(legendtitle, side = 3, font = 2, line = 1),
        smallplot = c(0.975, 0.99, 0.1, 0.9)
Jannes Breier's avatar
Jannes Breier committed
      )
Jannes Breier's avatar
Jannes Breier committed
    } else { # manual plotting
Jannes Breier's avatar
Jannes Breier committed
      fields::image.plot(
        legend.only = TRUE, zlim = range(brks), col = palette,
Jannes Breier's avatar
Jannes Breier committed
        useRaster = FALSE, breaks = brks, lab.breaks = round(legendticks, 2),
        legend.shrink = 0.7,
Jannes Breier's avatar
Jannes Breier committed
        legend.args = list(legendtitle, side = 3, font = 2, line = 1)
      )
    }
  }

  if (!is.null(file)) {
    grDevices::dev.off()
  }
Jannes Breier's avatar
Jannes Breier committed
}