Spaces:
Sleeping
Sleeping
:bird:
Browse files- .gitignore +55 -0
- 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 |
-
|
34 |
-
Select a desired area with the draw tools on the map,
|
|
|
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
|
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 =
|
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 |
-
|
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 |
-
|
|
|
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) |>
|
|
|
|
|
208 |
})
|
209 |
print(time)
|
210 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
|
212 |
# draw on map
|
213 |
h3j <- glue("s3://public-data/cache/{query_id}.h3j")
|
214 |
-
|
215 |
|
216 |
# override previous map with drawn map
|
|
|
217 |
output$map <- renderMaplibre({
|
218 |
-
m <- maplibre(center=c(-110, 38), zoom =
|
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 = "
|
227 |
-
values = c(0,
|
228 |
stops = c("#430254", "#f83c70")
|
229 |
),
|
230 |
fill_extrusion_height = list(
|
231 |
"interpolate",
|
232 |
list("linear"),
|
233 |
list("zoom"),
|
234 |
-
0, 0,
|
235 |
-
list("*",
|
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
|