rstudio / leaflet

R Interface to Leaflet Maps
http://rstudio.github.io/leaflet/
Other
805 stars 509 forks source link

Dependency issue while running leaflet at background using "callr" package #744

Open JWusagi opened 3 years ago

JWusagi commented 3 years ago

Hi there

Not sure if it's fair to log this issue here as it relates to two packages - leaflet and callr. I have a Shiny App that allows users play with coloured interactive map (by leaflet). Every time user changes settings, the map takes around 1 minute to load. Therefore I'm looking to load the map in background so that users can do other works in the App in the meantime. I used callr::r_bg() for background loading:

leafletMap_call = function(input1,  # define the leaflet map as a function with inputs as variables first 
                           input2)
{
#i need to load the package here again as callr runs the codes in a new R process
  library(leaflet) 
  library(RColorBrewer)

#codes defining colour scheme 
..........

#run the leaflet map
mapX = leaflet(data=input1)%>%  
  addProviderTiles("CartoDB.PositronNoLabels") %>%
  addProviderTiles("CartoDB.PositronOnlyLabels", 
                   group = "map_city_labels")%>%  
  addPolygons(color='white', opacity=0.2,
              fill=TRUE, fillColor = ~colorPal(Variable), fillOpacity=0.55, weight=0.01, smoothFactor=0.8,
              highlightOptions = highlightOptions(color = "darkred", weight = 2, bringToFront = TRUE),
              popup = paste("LSOA code: ", input1$lsoa11cd, "<br>",
                            "LSOA name: :", input1$lsoa11nm, "<br>"), 
              group = "LSOA_polygons")%>%
  addLayersControl(baseGroups = "CartoDB.PositronNoLabels", 
                   overlayGroups = c("map_city_labels",
                                     "LSOA_polygons"))%>%
  addLegend(colors = LSOA_col, labels=legend_label,  opacity = 0.7, title = "Title 1", position = "topleft")

return(mapX)
}

#run the function in background
mapX_background = r_bg(func=leafletMap_call,
                       arg=list(input1=xxx1,
                                input2=xxx2))
mapX_background$wait()
mapX_background$get_result()

Then I got the following error:

> mapX_background$get_result()
Error in copyDependencyToDir(dep, libdir, FALSE) : 
  Can't copy dependency files that don't exist: '/var/folders/sw/jbqsqm0x5vj_mkt38dmrl1jh0000gn/T//RtmpwG2ckU/leaflet-providers_1.9.0.js'

However, the error only exists when I include the addProviderTiles() commend, and everything goes OK if I only load the polygons without the background map with rivers, roads, city names, etc. Therefore, I'm considering whether there is a dependency/connection to an online centralised system that I need to bring to the callr::r_bg() command.

Sorry for bothering - but I'm wondering if anyone get any idea on possible solutions? If this is not the right place for this questions, please shout and I'll log it somewhere else.

Many thanks, Jie

jcheng5 commented 3 years ago

I'm not that surprised that doesn't work; the dependency files are created in the temp directory of the callr child R process, and when the child process finishes executing, the temp files are deleted.

Usually everything from leaflet() on down doesn't take very long. Do you know what part of your code is taking a long time to run? (If not, running under profvis would help)

JWusagi commented 3 years ago

I'm not that surprised that doesn't work; the dependency files are created in the temp directory of the callr child R process, and when the child process finishes executing, the temp files are deleted.

Usually everything from leaflet() on down doesn't take very long. Do you know what part of your code is taking a long time to run? (If not, running under profvis would help)

Hi Joe

I can only say thanks so much for the reminder.. Indeed, you are right that there are some lines of codes slow down the whole process, which I can run them in the global environment! Now it's perfectly solved.

I was just too rush in writing all the codes and therefore didn't do performance optimisation well.

Thanks again, Jie

edwardlavender commented 1 year ago

I noticed a similar error when trying to save and later reload leaflet maps that use addProviderTiles(). In this case the motivation was to include a leaflet map as a 'dataset' in an R package/shiny app without having to create the map within the shiny app itself (which is slower & requires other dependencies, as well as leaflet, in this particular case). Are there any suggested work arounds for this?

Here is a reproducible example run in RStudio:

library(leaflet)
library(magrittr)

# Make map with addTiles()
l1 <-
  leaflet() %>%
  addTiles()

# Make map with addProviderTiles()
l2 <-
  leaflet() %>%
  addProviderTiles(provider = providers$Stamen.TonerLite)

# Save maps
saveRDS(l1, "l1.rds")
saveRDS(l2, "l2.rds")

# Restart session & reload maps
rstudioapi::restartSession()
readRDS("l1.rds") # success
readRDS("l2.rds") # failure
# > Error in copyDependencyToDir(dep, libdir, FALSE) :
# >   Can't copy dependency files that don't exist: ...
andtheWings commented 1 year ago

Another scenario where this comes up is if you try to generate, then load a map (using addProviderTiles()) in a targets pipeline.