MazamaScience / AirFireModeling

Utilities to ease merging of USFS AirFire model output and monitoring data.
0 stars 0 forks source link

raster_spaghettiPlot() fails with rasterBricks #35

Closed jonathancallahan closed 4 years ago

jonathancallahan commented 4 years ago

I think this has to do with the lake of a name for use in the legend.

We have to have a way to name things if the raster parameter is a RasterBrick object.

Probably just allowing a rasterName parameter and checking that this is specified if raster is a RasterBrick.


Reproducible error

library(AirFireModeling)
setModelDataDir('~/Data/BlueSky')

# Creating PWFSLSmoke ws_monitor objects requires:
library(MazamaSpatialUtils)
PWFSLSmoke:::initializeMazamaSpatialUtils()

# Portland, Oregon
longitude <- -122.68
latitude <- 45.52

models <- bluesky_findModels(longitude, latitude)

# Load model data
rasterList <- raster_load(
  modelName = c("PNW-1.33km", "PNW-4km"),
  modelRun = 2019100900,
  xlim = c(-125, -115),
  ylim = c(42, 50)
)

raster_spaghettiPlot(
  rasterList[[1]],
  longitude = longitude,
  latitude = latitude,
  radius = 10, # km
  rasterName = "DUMMY"
)
Converting raster to ws_monitor ...
Error in UseMethod("select_") : 
  no applicable method for 'select_' applied to an object of class "NULL"
In addition: Warning message:
In if (stringr::str_detect(class(monitorList), "Raster*")) { :
  the condition has length > 1 and only the first element will be used
tabrasel commented 4 years ago

I found two issues here:

  1. The first had to do with the argument passed to the internal .meltTargetMonitor() function. This function expects a single ws_monitor as a parameter, and should be called differently depending on whether monitorList is an actual list of ws_montors or is a single ws_monitor object itself:
# Create ggplot dataframes
if ( stringr::str_detect(class(monitorList), 'Raster*') ) {
  df <- .meltTargetMonitor(monitorList)
} else {
  df <- lapply(monitorList, .meltTargetMonitor) %>%
    dplyr::bind_rows()
}

However, it doesn't look like the stringr::str_detect(class(monitorList), 'Raster*') condition tests this properly, since in either case it returns false and runs the else block. Now this is fine when monitorList is an actual list of RasterBricks, but it breaks when monitorList is a single ws_monitor because the lapply() call tries to apply .meltTargetMonitor() to the contents of each of monitorList's contents (meta and data). Therefore it can't find some of the data it expects.

So to solve that issue, I think we just need to change how we determine what monitorList is: An actual list of ws_monitors, or a single ws_monitor itself. Everything works just fine in the latter case when the non-else block is run instead.

I'll try: stringr::str_detect(class(monitorList), 'ws_monitor')

  1. Unfortunately, there was still a problem. When a single RasterBrick is given as a parameter to the spaghettiPlot function and converted to a ws_monitor it's meta$modelName is in the form of "DUMMY_525bf68f1703b6ad" instead of "PNW.1.33km_2019100900_ea97e70f44eaed44". Therefore the .meltTargetMonitor() function is not able to remove the string pattern from the modelName:
# Melt the data
moltenTargetDist <-
  monitorList$meta %>%
  dplyr::select(.data$monitorID, .data$targetDistance) %>%
  reshape2::melt(id.vars = 'monitorID') %>%
  dplyr::mutate(variable = .data$monitorID, 'monitorID' = NULL) %>%
  dplyr::mutate(modelName = stringr::str_remove(.data$variable, '_.+_.+'))

This makes all the model entries in the ggplot data unique, and tries to render a facet for each one (there could be hundreds!). All that's needed to fix this is change the pattern to '_.+' so it's works for both versions of modelName.

jonathancallahan commented 4 years ago

Love the detailed explanation!

Thanks for tackling and solving this one.

On Mon, Jul 13, 2020 at 1:24 PM Tate Brasel notifications@github.com wrote:

I found two issues here:

  1. The first had to do with the argument passed to the internal .meltTargetMonitor() function. This function expects a single ws_monitor as a parameter, and should be called differently depending on whether monitorList is an actual list of ws_montors or is a single ws_monitor object itself:

Create ggplot dataframes

if ( stringr::str_detect(class(monitorList), 'Raster*') ) { df <- .meltTargetMonitor(monitorList) } else { df <- lapply(monitorList, .meltTargetMonitor) %>% dplyr::bind_rows() }

However, it doesn't look like the stringr::str_detect(class(monitorList), 'Raster') condition tests this properly, since in either case it returns false and runs the else block. Now this is fine when monitorList is an actual list of RasterBricks, but it breaks when monitorList is a single ws_monitor* because the lapply() call tries to apply .meltTargetMonitor() to the contents of each of monitorList's contents (meta and data). Therefore it can't find some of the data it expects.

So to solve that issue, I think we just need to change how we determine what monitorList is: An actual list of ws_monitors, or a single ws_monitor itself. Everything works just fine in the latter case when the non-else block is run instead.

I'll try: stringr::str_detect(class(monitorList), 'ws_monitor')

  1. Unfortunately, there was still a problem. When a single RasterBrick is given as a parameter to the spaghettiPlot function and converted to a ws_monitor it's meta$modelName is in the form of "DUMMY_525bf68f1703b6ad" instead of "PNW.1.33km_2019100900_ea97e70f44eaed44". Therefore the .meltTargetMonitor() function is not able to remove the string pattern from the modelName:

Melt the data

moltenTargetDist <- monitorList$meta %>% dplyr::select(.data$monitorID, .data$targetDistance) %>% reshape2::melt(id.vars = 'monitorID') %>% dplyr::mutate(variable = .data$monitorID, 'monitorID' = NULL) %>% dplyr::mutate(modelName = stringr::strremove(.data$variable, '.+_.+'))

This makes all the model entries in the ggplot data unique, and tries to render a facet for each one (there could be hundreds!). All that's needed to fix this is change the pattern to '_.+' so it's works for both versions of modelName.

— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub https://github.com/MazamaScience/AirFireModeling/issues/35#issuecomment-657772572, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFYN5OKDPFCBNLOGW5H7DTR3NUQ5ANCNFSM4N2OGKXA .

-- Jonathan Callahan, PhD Mazama Science 206-708-5028 mazamascience.com