Skip to content

Commit 1f536bf

Browse files
committed
wip
1 parent 1c4111a commit 1f536bf

5 files changed

Lines changed: 179 additions & 111 deletions

File tree

app.R

Lines changed: 84 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ ui <- page_sidebar(
3333
sidebar = sidebar(
3434
width = 300,
3535
card(
36-
card_header("Areas"),
36+
card_header("Area selector"),
3737
radioButtons(
3838
"layer_selection",
3939
NULL,
@@ -56,8 +56,7 @@ ui <- page_sidebar(
5656
card(
5757
card_header("Biodiversity"),
5858
chat_ui("chat", placeholder = "hummingbirds"),
59-
actionLink("get_richness", "get sp richness"),
60-
actionLink("clear_richness", "🧹")
59+
actionLink("clear_richness", "🧹 clear richness")
6160
),
6261

6362
br(),
@@ -104,20 +103,44 @@ server <- function(input, output, session) {
104103
taxa_selections <- taxonomicSelectorServer("taxa_selector")
105104

106105
# Dynamic variables:
107-
layer_filter <- reactiveVal(NULL)
106+
layer_filter <- reactiveVal(NULL) # active layer filter (maplibre filter)
107+
taxa_filter <- reactiveVal(NULL) # active species filter (list)
108+
active_feature <- reactiveVal(NULL) # active polygon
108109
selected_feature <- reactiveVal(NULL)
109-
taxa_filter <- reactiveVal(NULL)
110110

111-
observeEvent(input$chat_user_input, {
112-
taxa_selected <- txt_to_taxa(input$chat_user_input)
113-
#print(taxa_selected)
114-
taxa_filter(taxa_selected)
115-
chat_append("chat", "done")
116-
})
111+
# Waterfall strategy to determine feature
112+
get_active_feature <- function(input) {
113+
gdf <- active_feature()
114+
115+
if (is_empty(gdf)) {
116+
print("No feature selected, checking for drawing")
117+
gdf <- get_drawn_features(maplibre_proxy("map"))
118+
}
119+
if (is_empty(gdf)) {
120+
print("No drawing found, checking geocoder")
121+
gdf <- geocoder_to_gdf(input$map_geocoder)
122+
}
123+
if (is_empty(gdf)) {
124+
print("No geocoder, getting current bbox")
125+
bbox <- input$map_bbox
126+
print(bbox)
127+
if (!is.null(bbox)) {
128+
gdf <- get_polygon_bbox(bbox)
129+
}
130+
}
131+
132+
if (is_empty(gdf)) {
133+
warning("No selection found, using default!")
134+
return(spData::us_states)
135+
}
136+
137+
gdf
138+
}
139+
117140
# Set up the map:
118141
output$map <- renderMaplibre({
119142
m <- mapgl::maplibre(
120-
zoom = 1,
143+
zoom = 2,
121144
center = c(-80, 20),
122145
maxZoom = input$max_zoom
123146
)
@@ -138,7 +161,7 @@ server <- function(input, output, session) {
138161
m |> add_countries()
139162
})
140163

141-
# React to layer selection
164+
# Update map to show selected layer (polygons)
142165
observeEvent(input$layer_selection, {
143166
proxy <- maplibre_proxy("map")
144167

@@ -160,7 +183,25 @@ server <- function(input, output, session) {
160183
proxy |> set_filter(input$layer_selection, layer_filter())
161184
})
162185

163-
# React to selected feature
186+
# Observe chat input
187+
observeEvent(input$chat_user_input, {
188+
taxa_selected <- txt_to_taxa(input$chat_user_input)
189+
chat_append("chat", "done")
190+
191+
# optionally - store the selection as global variable for future reactions
192+
taxa_filter(taxa_selected)
193+
194+
# we can react right away, computing richness and updating map
195+
gdf <- get_richness(
196+
poly = get_active_feature(input),
197+
zoom = as.integer(input$map_zoom),
198+
taxa_selections = taxa_selected
199+
)
200+
maplibre_proxy("map") |>
201+
add_richness(gdf)
202+
})
203+
204+
# Zoom into selected feature, move down a layer, show resulting child features
164205
observeEvent(input$map_feature_click, {
165206
# NOTE: This reacts to drawing features too
166207

@@ -185,14 +226,6 @@ server <- function(input, output, session) {
185226
return()
186227
}
187228

188-
# record info about currently selected feature
189-
selected_feature(list(
190-
name = name,
191-
layer = x$layer,
192-
config = config,
193-
properties = x$properties
194-
))
195-
196229
# Set the filter to focus on the clicked feature only
197230
layer_filter(list(
198231
"==",
@@ -211,60 +244,31 @@ server <- function(input, output, session) {
211244
selected = config$next_layer
212245
)
213246

214-
# Optional logging to console
215-
print(paste(
216-
"Activating",
217-
config$next_layer,
218-
"and filtering",
219-
config$filter_column,
220-
"=",
221-
selected
222-
))
247+
lazy_gdf <- activate_from_config(x$properties$id, config)
248+
active_feature(lazy_gdf) # can a lazy feature be global var?
223249
}
224250
})
225251

226-
observeEvent(input$get_richness, {
227-
# do nothing if no feature is selected? Alternately grab screen?
228-
x <- selected_feature()
229-
if (is.null(x)) {
230-
warning("select a feature first")
231-
return()
232-
}
233-
234-
# selected_feature() must return these. make this more robust
235-
id <- x$properties$id
236-
zoom <- as.integer(input$map_zoom)
237-
poly <- open_dataset(x$config$parquet)
238-
239-
# FIXME abstract this into selected_feature() behavior.
240-
if ("id" %in% colnames(poly)) {
241-
poly <- poly |>
242-
filter(.data[["id"]] == !!id)
243-
}
244-
if ("geometry" %in% colnames(poly)) {
245-
poly <- poly |> rename(geom = geometry)
246-
}
247-
248-
selected_taxa <- taxa_filter()
249-
250-
print(selected_taxa)
252+
#logging helper
253+
print_selections <- function() {
251254
print(paste(
252255
"Computing biodiversity for",
253-
x$name,
256+
digest::digest(active_feature()),
254257
"at zoom",
255-
zoom,
258+
as.integer(input$map_zoom),
256259
"for taxa:",
257-
paste(selected_taxa, collapse = ":")
260+
paste(taxa_filter(), collapse = ":")
258261
))
262+
}
263+
264+
observeEvent(input$get_richness, {
259265
gdf <- get_richness(
260-
poly = poly,
261-
zoom = zoom,
262-
taxa_selections = selected_taxa
266+
poly = get_active_feature(input),
267+
zoom = as.integer(input$map_zoom),
268+
taxa_selections = taxa_filter()
263269
)
264270

265-
print(paste(nrow(gdf), "features"))
266271
maplibre_proxy("map") |>
267-
clear_layer(x$config$next_layer) |>
268272
add_richness(gdf)
269273
})
270274

@@ -276,34 +280,24 @@ server <- function(input, output, session) {
276280
observeEvent(input$get_features, {
277281
print("Extracting drawn features")
278282

279-
drawn_features <- get_drawn_features(maplibre_proxy("map"))
280-
print(drawn_features)
283+
gdf <- get_drawn_features(maplibre_proxy("map"))
284+
active_feature(gdf)
285+
print(gdf)
281286
})
282287

283288
observeEvent(input$current_bbox, {
284289
gdf <- get_polygon_bbox(input$map_bbox)
285-
activate_polygon(gdf, name = "gdf")
286-
# Should we grab polygons from active layer inside bbox?
287-
# Could allow for better cache behavior
290+
active_feature(gdf)
291+
# Should we grab polygons from active layer inside bbox instead to cache?
288292
})
289293

290294
# Ex: Get POINT data from geocoder (OSM)
291-
# could then react by operating on hex or some containing polygon
292295
observeEvent(input$map_geocoder$result, {
293-
temp <- tempfile(fileext = ".geojson")
294-
output <- list(
295-
type = "FeatureCollection",
296-
features = input$map_geocoder$result$features
297-
)
298-
jsonlite::write_json(
299-
output,
300-
temp,
301-
auto_unbox = TRUE
302-
)
303-
geo <- sf::st_read(temp)
296+
gdf <- geocoder_to_gdf(input$map_geocoder)
297+
# active_feature(gdf)
304298

305-
# get parent polygon from active layer via duckdbfs st_contains
306-
print(geo)
299+
# Get value of various layers based on containing hex of given zoom
300+
print(gdf)
307301
})
308302

309303
observeEvent(input$clear_richness, {
@@ -312,7 +306,13 @@ server <- function(input, output, session) {
312306

313307
# Manual taxonomic controls
314308
observeEvent(taxa_selections$filter_trigger(), {
315-
taxa_filter(taxa_selections$selections())
309+
gdf <- get_richness(
310+
poly = get_active_feature(input),
311+
zoom = as.integer(input$map_zoom),
312+
taxa_selections = taxa_selections$selections()
313+
)
314+
maplibre_proxy("map") |>
315+
add_richness(gdf)
316316
})
317317

318318
# Toggle draw controls

data-layers.R

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ add_richness_2d <- function(map, gdf) {
113113

114114
# lazy data.frame versions
115115

116-
current_drawing_parquet <- file.path(tempdir(), "current_drawing.geojson")
116+
current_drawing_parquet <- file.path(tempdir(), "current_drawing.parquet")
117117
# Define layer configuration
118118
layer_config <- list(
119119
country_layer = list(
@@ -158,6 +158,7 @@ layer_config <- list(
158158
current_drawing = list(
159159
clear_filter = FALSE,
160160
parquet = current_drawing_parquet
161-
)
161+
),
162+
none = list(add_layer = function(map, ...) map, clear_filter = TRUE)
162163
)
163164
# Should richness be included?

taxa-filter.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ taxonomicSelectorServer <- function(id) {
150150
})
151151

152152
# Filter button action - return a reactive that signals when to apply filter
153-
filter_trigger <- reactiveVal(0)
153+
filter_trigger <- reactiveVal(NULL)
154154
observeEvent(input$apply_filter, {
155155
filter_trigger(filter_trigger() + 1)
156156
})

test-data.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ poly <- open_dataset(
1717
select(id, division_id, geom = geometry)
1818

1919

20-
20+
z = sf::st_sf(sf::st_as_sfc(st_bbox(c(xmin = 180, ymin = -89.99, xmax = 180, ymax = 89.99), crs=4326)))
21+
get_h3_aoi(z)
2122

2223

2324
dest <- glue::glue("s3://public-data/cache/biodiversity/nevada-all-z5-v1.h3j")

0 commit comments

Comments
 (0)