7 Composite all PPIs

With all the preprocessing done, we can now make composites of the PPIs to ‘solve’ the overlapping areas of the Den Helder and Herwijnen radars. While we’re at it, we will also render out these composites for VIR, to visualise the en-masse take-off of birds.

7.2 Generating the composite PPIs

We will loop over all the Herwijnen and Den Helder PPIs we have generated so far to create composite PPIs for all included parameters. We generate these composites at a 500m, 1000m and 2000m resolution to later test at which resolution the models perform best. Additionally we will save the composites as a bunch of .png files that we can then use separately or inclued in the animated GIF below.

source("R/comp_ppi.R")
hrw_ppis <- Sys.glob(file.path("data/processed/final-ppis", "*NL62*"))
dhl_ppis <- Sys.glob(file.path("data/processed/final-ppis", "*NL61*"))

generate_composites <- function(hrw_ppis, dhl_ppis, res, maxrange, output_dir_ppi, output_dir_vis) {
  basemap <- NULL
  
  for (i in seq_along(hrw_ppis)) {
    ppi_hrw <- readRDS(hrw_ppis[i])
    print(hrw_ppis[i])
    ppi_dhl <- readRDS(dhl_ppis[i])
    print(dhl_ppis[i])
    
    # Set all columns to NA if further than maxrange from radar
    ppi_hrw$data@data[ppi_hrw$data@data$dist_radar > maxrange, ] <- NA
    ppi_dhl$data@data[ppi_dhl$data@data$dist_radar > maxrange, ] <- NA
    
    params <- c("VIR", "VID", "R", "overlap", "eta_sum", "eta_sum_expected", "dist_radar", "class", "land",
                "urban", "agricultural", "semiopen", "forests", "wetlands", "waterbodies", "dist_urban", "human_pop",
                "wb_area_id", "wb_area_nr", "ptt_route", "wb_area_ha", "wb_total_biomass", "ptt_total_biomass", "total_biomass", 
                "wb_weighted_mean_weight", "ptt_weighted_mean_weight", "weighted_mean_weight",
                "wb_total_crs", "ptt_total_crs", "total_crs",
                "wb_weighted_mean_crs", "ptt_weighted_mean_crs", "weighted_mean_crs",
                "wb_total_birds", "ptt_total_birds", "total_birds")
    # All mean methods except for factors and urban area (set to max), because we want to strictly filter out fireworks
    methods <- c("mean", "mean", "mean", "mean", "mean", "mean", "min", "min", "min",
                 "max", "mean", "mean", "mean", "mean", "mean", "mean", "mean", 
                 "factor", "factor", "factor", "factor", "mean", "mean", "mean",
                 "mean", "mean", "mean", 
                 "mean", "mean", "mean",
                 "mean", "mean", "mean",
                 "mean", "mean", "mean")
    cppi <- comp_ppi(list(ppi_hrw, ppi_dhl), param = params, method = methods, res = c(res, res), coverage = "count")
    
    # Set rain and background pixels to NA
    cppi$data$VIR[cppi$data$class < 2] <- NA
    
    # Add coordinates
    coords_cppi <- raster::coordinates(cppi$data)
    cppi$data$x <- coords_cppi[, 1]
    cppi$data$y <- coords_cppi[, 2]
    
    # Add pixel ID
    cppi$data@data %>%
      mutate(pixel = row_number()) -> cppi$data@data
    
    # Solve different factors
    solve_factors <- function(x) {
      r <- x[1]
      if (is.na(x[1]) && is.na(x[2])) { r <- NA }
      if (is.na(x[1]) && !is.na(x[2])) { r <- x[2] }
      if (!is.na(x[1]) && is.na(x[2])) { r <- x[1] }
      if (!is.na(x[1]) && !is.na(x[2])) {
        if (x[1] != x[2]) {
          r <- NA
        } else {
          r <- x[1]
        }
      }
      r
    }
    
    for (j in which(methods == "factor")) {
      cppi$data@data[params[j]] <- apply(cppi$data@data[params[j]], 1, solve_factors)
    }
    
    saveRDS(cppi, file = paste(output_dir_ppi, res, "m/", strftime(ppi_hrw$datetime, format = "%Y%m%d%H%M"), ".RDS", sep = ""))
    
    if (i == 1) {
      basemap <- download_basemap(cppi, alpha = 0.3)
    }
    
    cppi$data$VIR <- log10(cppi$data$VIR)
    cppi$data$VIR[is.na(cppi$data$VIR)] <- 0
    
    bioRad::map(cppi, map = basemap, radar_size = 1, xlim = c(3.1, 6.8), ylim = c(51, 54), zlim = c(0, 4.5),
                palette = viridis(256, option = "viridis", alpha = 0.6)) +
      labs(title = "Fireworks NYE 2017-2018",
           subtitle = paste(ppi_hrw$datetime, ' UTC', sep = ""))

    ggsave(paste(output_dir_vis, res, "m/", strftime(ppi_hrw$datetime, format = "%Y%m%d%H%M"), ".png", sep = ""))
  }
}

r <- lapply(c(500, 1000, 2000), function(x) { generate_composites(hrw_ppis, dhl_ppis, res = x, maxrange = 66000,
                                                                  output_dir_ppi = "data/processed/composite-ppis/",
                                                                  output_dir_vis = "data/plots/vir-ppis/")})

We should also generate the composite PPIs for the baseline PPIs using the same procedure.

hrw_ppis <- Sys.glob(file.path("data/processed/final-ppis-baseline", "NLHRW*"))
dhl_ppis <- Sys.glob(file.path("data/processed/final-ppis-baseline", "NLDHL*"))

extract_dt <- function(filepath) {
  file <- basename(filepath)
  str_split(basename(file), "_")[[1]][3]
}
hrw_dts <- unlist(lapply(hrw_ppis, extract_dt))
dhl_dts <- unlist(lapply(dhl_ppis, extract_dt))

hrw_selection <- sort(hrw_ppis[hrw_dts %in% dhl_dts])
dhl_selection <- sort(dhl_ppis[dhl_dts %in% hrw_dts])

r <- lapply(c(500, 1000, 2000), function(x) { generate_composites(
  hrw_selection, dhl_selection, res = x, maxrange = 66000,
  output_dir_ppi = "data/processed/composite-ppis-baseline/",
  output_dir_vis = "data/plots/vir-ppis-baseline/")})

7.3 Visualising the composites

In order to run this comparatively simple conversion to a GIF of the PPIs, it may be necessary to increase the memory available to ImageMagick by changing the memory policy in /etc/ImageMagick-6/policy.xml. Additionally, we will reduce the resolution of the animated GIF and we’ll stick to the 1000m resolution PPIs.

width <- 800

composites <- list.files(path = "data/plots/vir-ppis/1000m/", pattern = "*.png", full.names = TRUE)

process_image <- function(img_path) {
  image_read(img_path) %>%
    image_resize(geometry_size_pixels(width = width)) %>%
    image_write(path = paste(tools::file_path_sans_ext(img_path), ".jpeg", sep = ""), format = "jpeg")
}

for (file in list.files(path = "data/plots/vir-ppis/", pattern = "*.png", full.names = TRUE)) {
  process_image(file)
}

list.files(path = "data/plots/vir-ppis/", pattern = "*.jpeg", full.names = T) %>%
  purrr::map(image_read) %>%
  image_join() %>%
  image_animate(fps = 2) %>%
  image_write("data/plots/vir-ppis/NYE-2017-2018.gif")