R/plot_fieldmean.R

Defines functions plot_fieldmean

# plotting function for fieldmean_plot
plot_fieldmean <- function(variable,
                           infile,
                           infile2,
						   infile3,
                           country_code,
                           climate_year_start,
                           climate_year_end,
                           show_extreme_climate_years,
                           climatology_until_eoy,
                           animation_pace,
                           output_format,
                           language,
                           out_dir,
                           temp_dir,
                           start_date,
                           end_date,
                           freeze_animation,
                           outfile_name,
                           adjustAccumulation,
                           dwd_logo,
                           verbose) {
  # Make sure that any user settings are reset when the function exits
  # This is a requirement by CRAN
  oldpar <- graphics::par(no.readonly = TRUE)
  # Warning: In graphics::par(oldpar) : par(new) ohne Plot aufgerufen
  on.exit(suppressWarnings(graphics::par(oldpar)))

  # Compute some parameters from arguments
  start_doy <- as.numeric(format(start_date, format = "%j"))
  finish_doy <- as.numeric(format(end_date, format = "%j"))
  if (is_leap_year(as.numeric(format(as.Date(start_date),"%Y")))) {
    start_doy <- ifelse(start_doy >= 60, start_doy - 1, start_doy)
  }
  if (is_leap_year(as.numeric(format(as.Date(end_date),"%Y")))) {
    finish_doy <- ifelse(finish_doy >= 60, finish_doy - 1, finish_doy)
  }
  country_name <- get_country_name(country_code, language = language)

  # Dimensions of pic
  pic.width <- 500
  pic.height <- 500

  # CMSAF logo
  # Size and location of the logo
  logo.size <- 0.4
  logo.x <- 0.81
  logo.y <- 0.06

  logo_cmsaf_path <- system.file(
    "extdata",
    "CMSAF_logo.png",
    package = "cmsafvis",
    mustWork = TRUE
  )
  logo_cmsaf <- png::readPNG(logo_cmsaf_path)
  dims <- dim(logo_cmsaf)[1:2]
  AR <- dims[1] / dims[2]  * pic.width / pic.height


  # DWD Logo
  if(dwd_logo){
    # Size and location of the logo
    logo.size2 <- 0.1
    logo.x2 <- 0.92
    logo.y2 <- 0.22

    logo_dwd_path <- system.file(
      "extdata",
      "DWD_logo.png",
      package = "cmsafvis",
      mustWork = TRUE
    )
    logo_dwd <- png::readPNG(logo_dwd_path)
    dims2 <- dim(logo_dwd)[1:2]
    AR2 <- dims2[1] / dims2[2]  * pic.width / pic.height
  }
  
  # line thickness
  lwd1 <- 5
  lwd2 <- 2

  temp_dir_acc <- temp_dir

  #set language
  data_year <- format(end_date, "%Y")

  plot_title <- get_title(
    variable = variable,
    language = language,
    year = data_year
  )
  plot_title <- paste0(plot_title, " (", country_name, ")")
  ylab_text <- get_axis_label(variable, language)

  date_format_string <- ifelse(language == "deu", "%d.%m.%Y", "%Y-%m-%d")

  legend_text <- paste0(
    get_climatology_word(language),
    " (",
    climate_year_start,
    "-",
    climate_year_end,
    ")"
  )

  input <- infile
  input2 <- infile2
  
  # Get full time range of infile
  id <- ncdf4::nc_open(infile3)
    date_time <- as.Date(cmsafops::get_time(ncdf4::ncatt_get(id, "time", "units")$value, ncdf4::ncvar_get(id, "time")))
    firstyear <- format(min(date_time), "%Y")
    lastyear  <- format(max(date_time), "%Y")
	lastyear  <- as.character(as.numeric(lastyear) - 1)
  ncdf4::nc_close(id)

  # read in netcdf data
  # read in annual mean
  nc_mean <- ncdf4::nc_open(input)
  var_clima <- ncdf4::ncvar_get(nc_mean, variable)
  ncdf4::nc_close(nc_mean)

  # read in current data
  nc_current <- ncdf4::nc_open(input2)
  var_current <- ncdf4::ncvar_get(nc_current, variable)
  ncdf4::nc_close(nc_current)

  dates <- seq(
    as.Date(paste(data_year, 1, 1, sep = "-")),
    as.Date(paste(data_year, 12, 31, sep = "-")),
    by = "day"
  )
  # Remove Feb 29 in leap year.
  if (length(dates) == 366) {
    dates <- dates[-60]
  }

  # Preparing data
  if (start_doy > 1 || !climatology_until_eoy) {
    plot_stop <- finish_doy
  } else {
    plot_stop <- 365
  }

  duration <- length(var_current)
  climate_duration <- plot_stop - start_doy + 1

  var_current_to_plot <- var_current
  var_climate_to_plot <- var_clima[start_doy:plot_stop]

  if (start_doy > 1 && adjustAccumulation) {
    # If data was accumulated and we don't plot starting from January 1st, the data doesn't start at 0.
    # We correct this by subtracting the value of the first date from alle dates.
    var_current_to_plot <- var_current_to_plot - rep(var_current[1], duration)
    var_climate_to_plot <- var_climate_to_plot - rep(var_climate_to_plot[1], climate_duration)
  }

  ############################################################################################
  # plot var_2018_graphic

  if (output_format == "graphic") {

    picpath <- out_dir
    picout <- file.path(picpath, outfile_name)

    limit <- -Inf

    # start loop over all years and read in netcdf data for annual sum of var
	for (climate_year in seq(from = firstyear, to = lastyear, by = 1)) {
      input <- add_ncdf_ext(construct_filename(variable,
                                               climate_year,
                                               country_code,
                                               "fldmean"))
      input <- file.path(temp_dir_acc, input)
      nc_fieldmean <- ncdf4::nc_open(input)
      var_ensemble <- ncdf4::ncvar_get(nc_fieldmean, variable)
      ncdf4::nc_close(nc_fieldmean)

      # Cut the data
      var_ensemble <- var_ensemble[start_doy:finish_doy]

      # Remove accumulation of previous dates
      if (start_doy > 1 && adjustAccumulation) {
        var_ensemble <- var_ensemble - rep(var_ensemble[1], climate_duration)
      }

      assign(paste0(variable, "_acc_", climate_year), var_ensemble)  # TODO use matrix: tmp = matrix(nrow = length(climate_year_end:climate_year_end), ncol = climate_duration, dimnames = list(climate_year_start:climate_year_end))

      # Compute y limit dependent on accumulation process
      if (adjustAccumulation) {
        limit <- max(limit, c(var_ensemble[length(var_ensemble)], var_current[length(var_current)]))
      } else {
        limit <- max(limit, max(c(var_ensemble, var_current), na.rm = TRUE))
      }
    }

    limit_y <- signif(ceiling(limit + limit/15), digits = 2)

    grDevices::png(
      picout,
      width = pic.width,
      height = pic.height,
      units = "px",
      pointsize = 12
    )

    #######################graphics::par(cex = 1.2,oma = c(0,0,0,0),mar = c(2,5,3,2))
    #graphics::par(cex = 1.2,oma = c(0,0,0,0),mar = c(2,5,3,1))
    plot_length <- length(start_doy:plot_stop)

    graphics::par(
      cex = 1.2,
      oma = c(0, 0, 0, 0),
      mar = c(2.2, 4, 3.5, 2),
      mgp = c(3, 1, 0)
    )

    set_time_locale(language)
    tryCatch(
      graphics::plot(
        dates[start_doy:plot_stop],
        var_climate_to_plot,
        type = "l",
        lwd = lwd1,
        xlab = "",
        ylab = ylab_text,
        main = plot_title,
        cex.lab = 1.2,
        ylim = c(0, limit_y),
        cex.main = 1.2
      ),
      finally = {set_time_locale("")}
    )

    # Variables for adding max/min end value to plot
    yearMaxEndValue <- -Inf
    yearMaxEnd <- NULL
    yearMinEndValue <- Inf
    yearMinEnd <- NULL

    # For the min year y position take the min value at 90%
    yearMinPosIndex <- round(plot_length*0.9)
    yearMinPosValue <- Inf

    # start loop to plot all years of climatology
	for (climate_year in seq(from = firstyear, to = lastyear, by = 1)) {
      dat <- get(paste0(variable, "_acc_", climate_year))

      set_time_locale(language)
      tryCatch(
        graphics::lines(
          dates[start_doy:plot_stop],
          dat,
          col = "grey",
          lwd = lwd2
        ),
        finally = {set_time_locale("")}
      )

      # Determine min and max end values
      if (dat[plot_length] > yearMaxEndValue) {
        yearMaxEndValue <- dat[plot_length]
        yearMaxEnd <- climate_year
      }
      if (dat[plot_length] < yearMinEndValue) {
        yearMinEndValue <- dat[plot_length]
        yearMinEnd <- climate_year
      }
      if (dat[yearMinPosIndex] < yearMinPosValue) {
        yearMinPosValue <- dat[yearMinPosIndex]
      }
    }

    set_time_locale(language)

    tryCatch({
      graphics::lines(
        dates[start_doy:plot_stop],
        var_climate_to_plot,
        col = "black",
        lwd = lwd1
      )
      graphics::lines(
        dates[start_doy:finish_doy],
        var_current_to_plot,
        col = "red",
        lwd = lwd1
      )},
      finally = {set_time_locale("")}
    )

    graphics::legend(
      "topleft",
      legend = c(legend_text, data_year),
      col = c("black", "red"),
      lwd = 4,
      cex = 1.0
    )

    graphics::par(usr = c(0, 1, 0, 1))
    size <- logo.size
    x <- logo.x
    y <- logo.y
    graphics::rasterImage(logo_cmsaf,
                          x - (size / 2),
                          y - (AR * size / 2),
                          x + (size / 2),
                          y + (AR * size / 2),
                          interpolate = TRUE)

    if (dwd_logo){
      size <- logo.size2
      x <- logo.x2
      y <- logo.y2
    
      graphics::rasterImage(logo_dwd,
                          x - (size / 2),
                          y - (AR2 * size / 2),
                          x + (size / 2),
                          y + (AR2 * size / 2),
                          interpolate = TRUE)
    }

    if (show_extreme_climate_years && adjustAccumulation) {
      y_val_max <- yearMaxEndValue/limit_y
      y_val_min <- yearMinPosValue/limit_y

      graphics::text(x = 0.9, y = y_val_max, labels = yearMaxEnd, col = "darkgrey")
      graphics::text(x = 0.9, y = y_val_min, labels = yearMinEnd, pos = 1, col = "darkgrey")
    }


    grDevices::dev.off()

    if (verbose) {
      message(paste("Image has been created at", normalizePath(picout)))
    }
  }

  ###########################################################################################################################

  if (output_format == "animation") {
    viddir <- out_dir
    vidout <- file.path(viddir, outfile_name)

    nr_frozen_frames <- 100

    if (verbose) {
      pb <- progress::progress_bar$new(
        format = "Creating animation [:bar] :percent eta: :eta",
        total = duration + ifelse(freeze_animation, nr_frozen_frames, 0),
        clear = TRUE,
        callback = function(x) {message("Created animation")}
      )
    }

    animation::saveVideo(
      video.name = vidout,
      img.name = "Rplot",
      other.opts = "-pix_fmt yuv420p -loglevel warning",  # See 'other.opts' of ?animation::saveVideo
      interval = animation_pace,
      ani.height = pic.height,
      ani.width = pic.width,
      units = "px",
      autobrowse = FALSE,  # means that the output file isn't opened automatically
      verbose = FALSE,
      expr = {
        for (i in 1:duration) {

          limit <- -Inf

          # start loop over all years and read in netcdf data for annual sum of var
		  for (climate_year in seq(from = firstyear,
                                   to = lastyear,
                                   by = 1)) {
            input <- add_ncdf_ext(construct_filename(variable,
                                                     climate_year,
                                                     country_code,
                                                     "fldmean"))
            input <- file.path(temp_dir_acc, input)

            nc_fieldmean <- ncdf4::nc_open(input)
            var_ensemble <- ncdf4::ncvar_get(nc_fieldmean, variable)
            ncdf4::nc_close(nc_fieldmean)

            # Cut data
            var_ensemble <- var_ensemble[start_doy:finish_doy]

            # Remove previous accumulation if required
            if (start_doy > 1 && adjustAccumulation) {
              var_ensemble <- var_ensemble - rep(var_ensemble[1], climate_duration)
            }

            assign(paste0(variable, "_acc_", climate_year), var_ensemble)

            # Compute y limit dependent on accumulation process
            if (adjustAccumulation) {
              limit <- max(limit, var_ensemble[length(var_ensemble)])
            } else {
              limit <- max(limit, max(var_ensemble, na.rm = TRUE))
            }
          }

          limit_y <- signif(ceiling(limit + limit/15), digits = 2)
          plot_length <- plot_stop - start_doy + 1

          corr_date <- start_doy + i - 1

          graphics::par(
            cex = 1.2,
            oma = c(0, 0, 0, 0),
            mar = c(2.2, 4, 3.5, 2),
            mgp = c(3, 1, 0)
          )

          set_time_locale(language)
          tryCatch(
            graphics::plot(
              dates[start_doy:plot_stop],
              var_climate_to_plot,
              type = "l",
              lwd = lwd1,
              xlab = "",
              ylab = ylab_text,
              main = plot_title,
              cex.lab = 1.2,
              ylim = c(0, limit_y),
              cex.main = 1.2
            ),
            finally = {set_time_locale("")}
          )

          # Variables for adding max/min end value to plot
          yearMaxEndValue <- -Inf
          yearMaxEnd <- NULL
          yearMinEndValue <- Inf
          yearMinEnd <- NULL

          # For the min year y position take the min value at 90%
          yearMinPosIndex <- round(plot_length*0.9)
          yearMinPosValue <- Inf

		  for (climate_year in seq(from = firstyear,
                                   to = lastyear,
                                   by = 1)) {
            dat <- get(paste0(variable, "_acc_", climate_year))

            set_time_locale(language)
            tryCatch(
              graphics::lines(
                dates[start_doy:plot_stop],
                dat,
                col = "grey",
                lwd = lwd2
              ),
              finally = {set_time_locale("")}
            )

            # Determine min and max end values
            if (dat[plot_length] > yearMaxEndValue) {
              yearMaxEndValue <- dat[plot_length]
              yearMaxEnd <- climate_year
            }
            if (dat[plot_length] < yearMinEndValue) {
              yearMinEndValue <- dat[plot_length]
              yearMinEnd <- climate_year
            }
            if (dat[yearMinPosIndex] < yearMinPosValue) {
              yearMinPosValue <- dat[yearMinPosIndex]
            }
          }

          var_current_seq <- var_current_to_plot[1:i]

          set_time_locale(language)
          tryCatch({
            graphics::lines(
              dates[start_doy:plot_stop],
              var_climate_to_plot,
              col = "black",
              lwd = lwd1
            )
            graphics::lines(
              dates[start_doy:corr_date],
              var_current_seq,
              col = "red",
              lwd = lwd1
            )},
            finally = {set_time_locale("")}
          )

          gaa <- format(dates[corr_date], format = date_format_string)

          graphics::legend(
            "topleft",
            legend = c(legend_text, gaa),
            col = c("black", "red"),
            lwd = 4,
            cex = 1.0
          )

          graphics::par(usr = c(0, 1, 0, 1))
          size <- logo.size
          x <- logo.x
          y <- logo.y
          graphics::rasterImage(logo_cmsaf,
                                x - (size / 2),
                                y - (AR * size / 2),
                                x + (size / 2),
                                y + (AR * size / 2),
                                interpolate = TRUE)

          if (dwd_logo){
            size <- logo.size2
            x <- logo.x2
            y <- logo.y2
          
            graphics::rasterImage(logo_dwd,
                                x - (size / 2),
                                y - (AR2 * size / 2),
                                x + (size / 2),
                                y + (AR2 * size / 2),
                                interpolate = TRUE)
          }

          if (show_extreme_climate_years && adjustAccumulation) {
            y_val_max <- yearMaxEndValue/limit_y
            y_val_min <- yearMinPosValue/limit_y

            graphics::text(x = 0.9, y = y_val_max, labels = yearMaxEnd, col = "darkgrey")
            graphics::text(x = 0.9, y = y_val_min, labels = yearMinEnd, pos = 1,  col = "darkgrey")
          }

          if (verbose) {
            pb$tick()
          }
        } # end of "daily" loop
        if (freeze_animation) {
          for (k in 1:nr_frozen_frames) {

            limit <- -Inf

			for (climate_year in seq(from = firstyear,
                                     to = lastyear,
                                     by = 1)) {
              input <- add_ncdf_ext(construct_filename(variable,
                                                       climate_year,
                                                       country_code,
                                                       "fldmean"))
              input <- file.path(temp_dir_acc, input)
              nc_fieldmean <- ncdf4::nc_open(input)
              var_ensemble <- ncdf4::ncvar_get(nc_fieldmean, variable)
              ncdf4::nc_close(nc_fieldmean)

              # Cut the data
              var_ensemble <- var_ensemble[start_doy:finish_doy]

              # Remove previous accumulation if required
              if (start_doy > 1 && adjustAccumulation) {
                var_ensemble <- var_ensemble - rep(var_ensemble[1], climate_duration)
              }

              assign(paste0(variable, "_acc_", climate_year), var_ensemble)

              # Compute y limit dependent on accumulation process
              if (adjustAccumulation) {
                limit <- max(limit, var_ensemble[length(var_ensemble)])
              } else {
                limit <- max(limit, max(var_ensemble, na.rm = TRUE))
              }
            }

            limit_y <- signif(ceiling(limit + limit/15), digits = 2)

            graphics::par(
              cex = 1.2,
              oma = c(0, 0, 0, 0),
              mar = c(2.2, 4, 3.5, 2),
              mgp = c(3, 1, 0)
            )

            set_time_locale(language)
            tryCatch(
              graphics::plot(
                dates[start_doy:plot_stop],
                var_climate_to_plot,
                type = "l",
                lwd = lwd1,
                xlab = "",
                ylab = ylab_text,
                main = plot_title,
                cex.lab = 1.2,
                ylim = c(0, limit_y),
                cex.main = 1.2
              ),
              finally = {set_time_locale("")}
            )

            # start loop to plot all years of climatology
			for (climate_year in seq(from = firstyear,
                                     to = lastyear,
                                     by = 1)) {
              dat <- get(paste0(variable, "_acc_", climate_year))

              set_time_locale(language)
              tryCatch(
                graphics::lines(
                  dates[start_doy:plot_stop],
                  dat,
                  col = "grey",
                  lwd = lwd2
                ),
                finally = {set_time_locale("")}
              )
            }

            set_time_locale(language)
            tryCatch({
              graphics::lines(
                dates[start_doy:plot_stop],
                var_climate_to_plot,
                col = "black",
                lwd = lwd1
              )
              graphics::lines(
                dates[start_doy:corr_date],
                var_current_to_plot,
                col = "red",
                lwd = lwd1
              )},
              finally = {set_time_locale("")}
            )

            graphics::legend(
              "topleft",
              legend = c(legend_text, data_year),
              col = c("black", "red"),
              lwd = 4,
              cex = 1.0
            )

            graphics::par(usr = c(0, 1, 0, 1))
            size <- logo.size
            x <- logo.x
            y <- logo.y
            graphics::rasterImage(logo_cmsaf,
                                  x - (size / 2),
                                  y - (AR * size / 2),
                                  x + (size / 2),
                                  y + (AR * size / 2),
                                  interpolate = TRUE)

            if (dwd_logo){
              size <- logo.size2
              x <- logo.x2
              y <- logo.y2

              graphics::rasterImage(
                logo_dwd,
                x - (size / 2),
                y - (AR2 * size / 2),
                x + (size / 2),
                y + (AR2 * size / 2),
                interpolate = TRUE
              )
            }

            if (show_extreme_climate_years && adjustAccumulation) {
              y_val_max <- yearMaxEndValue/limit_y
              y_val_min <- yearMinPosValue/limit_y

              graphics::text(x = 0.9, y = y_val_max, labels = yearMaxEnd, col = "darkgrey")
              graphics::text(x = 0.9, y = y_val_min, labels = yearMinEnd, pos = 1, col = "darkgrey")
            }

            if (verbose) {
              pb$tick()
            }
          } # end of for frames
        } # end of if freeze_animation
      } # end of saveVideo expr
    ) # end of saveVideo
  } #end of if

  # Print stats
  if (verbose) {
    dat_max <- get(paste0(variable, "_acc_", yearMaxEnd))
    dat_min <- get(paste0(variable, "_acc_", yearMinEnd))
    titles <- c("Analyzed year", "Climatology", "Maximum valued year", "Minimum valued year")

    standout_years <- c(format(start_date, format = "%Y"),
                        paste(climate_year_start, climate_year_end, sep = " - "),
                        yearMaxEnd,
                        yearMinEnd)

    standout_values <- c(var_current_to_plot[length(var_current_to_plot)],
                         var_climate_to_plot[length(var_current_to_plot)],
                         dat_max[length(var_current_to_plot)],
                         dat_min[length(var_current_to_plot)])

    final_values <- data.frame(title = titles, years = standout_years, value = standout_values)
    
	ranking.values <- ranking(out_dir, variable, country_code, firstyear, lastyear, finish_doy)
    calc.parameters.monitor.climate(final_values, ranking.values)
  
    # Print message
    if (adjustAccumulation) {
      message("Significant values at the final time period:")
      print(final_values)
    }
  }
}

Try the cmsafvis package in your browser

Any scripts or data that you put into this service are public.

cmsafvis documentation built on July 3, 2024, 5:07 p.m.