Skip to content
Snippets Groups Projects
plot_global.R 8.22 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
Fabian Stenzel's avatar
Fabian Stenzel committed
#' @param brks breaks for manual plotting type (type=man) default: NULL
#' @param palette palette for manual plotting type (type=man) default: NULL
#' @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.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,
                        extent = NULL,
                        country_borders = TRUE,
                        eps = FALSE,
                        cex = 1) {
  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"
      )
  if (!is.null(min)) {
    if (min == 0) only_pos <- TRUE
  }
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)
Jannes Breier's avatar
Jannes Breier committed
    )
  } else {
    if (type == "exp" || type == "lin") {
      if (type == "exp") {
        if (is.null(pow2max) | is.null(pow2min)) {
          stop("For exponental legend, pow2min and pow2max are required.")
        }
        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)
        grDevices::colorRampPalette(
          RColorBrewer::brewer.pal(9, col_pos)
        )(length(legendticks) / 2 - 1)
Jannes Breier's avatar
Jannes Breier committed
      )
    } else { # type == man
      if (is.null(palette)) {
        message("Manual breaks, but not palette given, using default.")
        palette <- grDevices::colorRampPalette(
          RColorBrewer::brewer.pal(9, col_pos)
        )(length(brks) - 1)
      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))] <- c(data)
  if (is.null(extent)) extent <- terra::ext(c(-180, 180, -60, 90))
Jannes Breier's avatar
Jannes Breier committed

  if (leg_yes) {
    oma_p <- c(0, 0, 0, 3)
Jannes Breier's avatar
Jannes Breier committed
  } else {
    oma_p <- c(0, 0, 0, 0)
Jannes Breier's avatar
Jannes Breier committed
  }
  #withr::with_par(new = list(
  #  bty = "n", oma = oma_p, mar = c(0, 0, 0, 0), xpd = TRUE
  #), {
  if (leg_yes){
    terra::plot(ra,
      ext = extent, breaks = legendticks, col = palette, main = title,
      legend = TRUE, axes = FALSE, type = "continuous", cex.main = cex,
      plg = list(cex = cex)
  } else{
    terra::plot(ra,
      ext = extent, breaks = legendticks, col = palette, main = title,
      legend = FALSE, axes = FALSE, type = "continuous", cex.main = cex,
      plg = list(cex = cex)
    )
  }

    if (country_borders) maps::map("world", add = TRUE, res = 0, lwd = 0.1, ylim = c(-60, 90))
    #title(title, cex = cex) #line = -1)
    if (F) {
      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)
        )
      } else { # manual plotting
        fields::image.plot(
          legend.only = TRUE, zlim = range(brks), 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)
        )
      }
Jannes Breier's avatar
Jannes Breier committed
    }
    if (!is.null(file)) {
      grDevices::dev.off()
    }
Jannes Breier's avatar
Jannes Breier committed
}