cboettig commited on
Commit
7446924
·
1 Parent(s): c2fd183
Files changed (2) hide show
  1. .gitignore +55 -0
  2. app.R +45 -18
.gitignore ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # History files
2
+ .Rhistory
3
+ .Rapp.history
4
+
5
+ # Session Data files
6
+ .RData
7
+ .RDataTmp
8
+
9
+ # User-specific files
10
+ .Ruserdata
11
+
12
+ # Example code in package build process
13
+ *-Ex.R
14
+
15
+ # Output files from R CMD build
16
+ /*.tar.gz
17
+
18
+ # Output files from R CMD check
19
+ /*.Rcheck/
20
+
21
+ # RStudio files
22
+ .Rproj.user/
23
+
24
+ # produced vignettes
25
+ vignettes/*.html
26
+ vignettes/*.pdf
27
+
28
+ # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3
29
+ .httr-oauth
30
+
31
+ # knitr and R markdown default cache directories
32
+ *_cache/
33
+ /cache/
34
+
35
+ # Temporary files created by R markdown
36
+ *.utf8.md
37
+ *.knit.md
38
+
39
+ # R Environment Variables
40
+ .Renviron
41
+
42
+ # pkgdown site
43
+ docs/
44
+
45
+ # translation temp files
46
+ po/*~
47
+
48
+ # RStudio Connect folder
49
+ rsconnect/
50
+
51
+
52
+ *.parquet
53
+ *.tiff
54
+
55
+
app.R CHANGED
@@ -14,7 +14,12 @@ library(digest)
14
  library(stringr)
15
  library(shinybusy)
16
 
 
17
  duckdbfs::close_connection()
 
 
 
 
18
 
19
  css <-
20
  HTML(paste0("<link rel='stylesheet' type='text/css' ",
@@ -30,10 +35,11 @@ ui <- page_sidebar(
30
  titlePanel("Demo App"),
31
  shinybusy::add_busy_spinner(),
32
 
33
- p("
34
- Select a desired area with the draw tools on the map, then hit 'Set Area of Interest' to select.
 
35
  Then, enter your query in the text box below the map to count occurrences of your specified taxonomic group.
36
- Use the airplane button to sned your query. The computation may take a few minutes depending on the size and scale of
37
  the search.
38
  "),
39
 
@@ -91,7 +97,7 @@ Scroll to zoom, ctrl+click to pitch and rotate. Hitting the area button with no
91
  verbatimTextOutput("sql_code")
92
  ),
93
  accordion_panel(
94
- title = "Explain query",
95
  icon = fa("user", prefer_type = "solid"),
96
  textOutput("explanation")
97
  )
@@ -114,19 +120,19 @@ duckdb_secrets(Sys.getenv("MINIO_KEY"),
114
  "minio.carlboettiger.info")
115
 
116
  gbif <- open_dataset("s3://public-gbif/2024-10-01", tblname = "gbif")
117
- bounds <- ""
118
 
119
  # Define the server
120
  server <- function(input, output, session) {
121
  output$map <- renderMaplibre({
122
- m <- maplibre(center=c(-110, 38), zoom = 3, pitch = 0) |>
123
  add_draw_control() |>
124
- add_geocoder_control() #|>
125
- # set_projection("globe")
126
 
127
  m
128
  })
129
  observeEvent(input$get_features, {
 
 
130
 
131
  drawn_features <- get_drawn_features(mapboxgl_proxy("map"))
132
  if(nrow(drawn_features) > 0) {
@@ -139,7 +145,7 @@ observeEvent(input$get_features, {
139
 
140
 
141
  attach(as.list(bounds))
142
- gbif_aoi <- gbif |>
143
  dplyr::filter(between(decimallatitude, ymin, ymax),
144
  between(decimallongitude, xmin, xmax)) |>
145
  as_view("gbif_aoi")
@@ -195,27 +201,43 @@ observeEvent(input$get_features, {
195
  # cache the query
196
  query_id <- digest::digest(paste(response$query, bounds, collapse=""))
197
  data_url <- glue::glue("https://minio.carlboettiger.info/public-data/cache/{query_id}.h3j")
198
- output$url <- renderText(data_url)
199
 
200
- cache_parquet <- glue("{query_id}.parquet")
 
201
 
202
  # compute if not yet in chache
203
  status <- httr::status_code(httr::HEAD(data_url))
204
  if(status == 404) {
205
  print("Computing...")
206
  time <- bench::bench_time({
207
- agent_query(stream) |> write_dataset(cache_parquet)
 
 
208
  })
209
  print(time)
210
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
211
 
212
  # draw on map
213
  h3j <- glue("s3://public-data/cache/{query_id}.h3j")
214
- open_dataset(cache_parquet) |> to_h3j(h3j)
215
 
216
  # override previous map with drawn map
 
217
  output$map <- renderMaplibre({
218
- m <- maplibre(center=c(-110, 38), zoom = 3, pitch = 0, maxZoom = 9) |>
219
  add_h3j_source("h3j_source",
220
  url = data_url) |>
221
  add_fill_extrusion_layer(
@@ -223,19 +245,24 @@ observeEvent(input$get_features, {
223
  source = "h3j_source",
224
  tooltip = "count",
225
  fill_extrusion_color = interpolate(
226
- column = "count",
227
- values = c(0, 1000),
228
  stops = c("#430254", "#f83c70")
229
  ),
230
  fill_extrusion_height = list(
231
  "interpolate",
232
  list("linear"),
233
  list("zoom"),
234
- 0, 0, 1000,
235
- list("*", 10, list("get", "count"))
236
  ),
237
  fill_extrusion_opacity = 0.7
238
  )
 
 
 
 
 
239
  }) # close renderMaplibre
240
  }) # close observeEvent->get_features
241
  }) # close observeEvent->user_msg
 
14
  library(stringr)
15
  library(shinybusy)
16
 
17
+ # initialize a disk-backed database for the session
18
  duckdbfs::close_connection()
19
+ duckdbfs::cached_connection(tempfile())
20
+
21
+ duckdbfs::load_h3()
22
+ duckdbfs::load_spatial()
23
 
24
  css <-
25
  HTML(paste0("<link rel='stylesheet' type='text/css' ",
 
35
  titlePanel("Demo App"),
36
  shinybusy::add_busy_spinner(),
37
 
38
+ markdown("
39
+ Select a desired area with the draw tools on the map, using the search bar if desired.
40
+ Then hit **Set Area of Interest** to select.
41
  Then, enter your query in the text box below the map to count occurrences of your specified taxonomic group.
42
+ Use the airplane button to send your query. The computation may take a few minutes depending on the size and scale of
43
  the search.
44
  "),
45
 
 
97
  verbatimTextOutput("sql_code")
98
  ),
99
  accordion_panel(
100
+ title = HTML("<span, class='text-info'>Explain query</span>"),
101
  icon = fa("user", prefer_type = "solid"),
102
  textOutput("explanation")
103
  )
 
120
  "minio.carlboettiger.info")
121
 
122
  gbif <- open_dataset("s3://public-gbif/2024-10-01", tblname = "gbif")
 
123
 
124
  # Define the server
125
  server <- function(input, output, session) {
126
  output$map <- renderMaplibre({
127
+ m <- maplibre(center = c(-110, 38), zoom = 2, pitch = 0, maxZoom=9) |>
128
  add_draw_control() |>
129
+ add_geocoder_control()
 
130
 
131
  m
132
  })
133
  observeEvent(input$get_features, {
134
+ bounds <- ""
135
+ aoi_info <- NULL
136
 
137
  drawn_features <- get_drawn_features(mapboxgl_proxy("map"))
138
  if(nrow(drawn_features) > 0) {
 
145
 
146
 
147
  attach(as.list(bounds))
148
+ gbif |>
149
  dplyr::filter(between(decimallatitude, ymin, ymax),
150
  between(decimallongitude, xmin, xmax)) |>
151
  as_view("gbif_aoi")
 
201
  # cache the query
202
  query_id <- digest::digest(paste(response$query, bounds, collapse=""))
203
  data_url <- glue::glue("https://minio.carlboettiger.info/public-data/cache/{query_id}.h3j")
 
204
 
205
+ # use tempfile. we could use database tempdir
206
+ cache_parquet <- tempfile(glue("{query_id}"), fileext = ".parquet")
207
 
208
  # compute if not yet in chache
209
  status <- httr::status_code(httr::HEAD(data_url))
210
  if(status == 404) {
211
  print("Computing...")
212
  time <- bench::bench_time({
213
+ agent_query(stream) |>
214
+ mutate(log_count = log(count)) |>
215
+ write_dataset(cache_parquet)
216
  })
217
  print(time)
218
  }
219
+ cached_data <- open_dataset(cache_parquet)
220
+
221
+ # so we can scale color and height to max value
222
+ biggest <- cached_data |> summarise(max = max(log_count)) |> pull(max) |> first()
223
+
224
+ # so we can zoom to the selected data (choose random point)
225
+ aoi_info <- cached_data |>
226
+ head(1) |>
227
+ mutate(zoom = h3_get_resolution(h3id),
228
+ lat = h3_cell_to_lat(h3id),
229
+ lng = h3_cell_to_lng(h3id)) |>
230
+ collect()
231
+
232
 
233
  # draw on map
234
  h3j <- glue("s3://public-data/cache/{query_id}.h3j")
235
+ cached_data |> to_h3j(h3j)
236
 
237
  # override previous map with drawn map
238
+ # we should use set_h3j_source and set_layer on maplibre_proxy instead.
239
  output$map <- renderMaplibre({
240
+ m <- maplibre(center=c(-110, 38), zoom = 1, pitch = 0, maxZoom = 11) |>
241
  add_h3j_source("h3j_source",
242
  url = data_url) |>
243
  add_fill_extrusion_layer(
 
245
  source = "h3j_source",
246
  tooltip = "count",
247
  fill_extrusion_color = interpolate(
248
+ column = "log_count",
249
+ values = c(0, biggest),
250
  stops = c("#430254", "#f83c70")
251
  ),
252
  fill_extrusion_height = list(
253
  "interpolate",
254
  list("linear"),
255
  list("zoom"),
256
+ 0, 0, biggest,
257
+ list("*", 10000, list("get", "log_count"))
258
  ),
259
  fill_extrusion_opacity = 0.7
260
  )
261
+ if (!is.null(aoi_info)) {
262
+ m <- m |> fly_to(c(aoi_info$lng, aoi_info$lat), zoom = (aoi_info$zoom - 1))
263
+ }
264
+
265
+ m
266
  }) # close renderMaplibre
267
  }) # close observeEvent->get_features
268
  }) # close observeEvent->user_msg