Upload 2 files
Browse files- depth_interactive_map_alpha.R +168 -9
- styles.css +3 -0
depth_interactive_map_alpha.R
CHANGED
|
@@ -107,12 +107,44 @@ GRAVES_PAL <- c("#fee5d9", "#fcae91", "#fb6a4a",
|
|
| 107 |
"#de2d26", "#a50f15", "#67000d") # Reds 6
|
| 108 |
INFRA_PAL <- c("#ffffe5", "#f7fcb9", "#d9f0a3",
|
| 109 |
"#addd8e", "#78c679", "#238443") # YlGn 6
|
| 110 |
-
OCVED_PAL <- c("#
|
| 111 |
-
"#
|
| 112 |
GED_PAL <- c("#f1eef6", "#d0d1e6", "#a6bddb",
|
| 113 |
"#67a9cf", "#2b8cbe", "#045a8d") # PuBu 6
|
| 114 |
FOSAS_PAL <- c("#ffffd4", "#fee391", "#fec44f",
|
| 115 |
"#fe9929", "#d95f0e", "#993404") # YlOrBr 6
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
|
| 117 |
# Infrastructure point categories -- grouped from the raw "category" field
|
| 118 |
# (Shelter / restaurant / Government / lodging / Legal/NGO / Food / charity /
|
|
@@ -149,13 +181,16 @@ GRID_LAYER_CFG <- list(
|
|
| 149 |
"fosas-choro" = "fosas",
|
| 150 |
"remesas-choro" = "remesas",
|
| 151 |
"pam-choro" = "pam",
|
|
|
|
|
|
|
| 152 |
"migrants-pts" = "migrants",
|
| 153 |
"graves-pts" = "graves",
|
| 154 |
"infra-pts" = "infra",
|
| 155 |
"ocved-pts" = "ocved",
|
| 156 |
"ged-pts" = "ged"
|
| 157 |
)
|
| 158 |
-
|
|
|
|
| 159 |
|
| 160 |
ENVIPE_COLS <- list(
|
| 161 |
"insecurity" = list(col = "insecurity_perc", breaks = c(40, 55, 65, 75, 85)),
|
|
@@ -300,6 +335,49 @@ WEB_SQL_TEMPLATES <- list(
|
|
| 300 |
FROM dim_pam_mun GROUP BY CVEGEO) p
|
| 301 |
ON c.CVEGEO = p.CVEGEO",
|
| 302 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 303 |
src_fosas =
|
| 304 |
"SELECT c.municipio, c.entidad, c.CVEGEO,
|
| 305 |
COALESCE(CAST(f.fosas_total AS INTEGER), 0) AS fosas_total,
|
|
@@ -498,9 +576,12 @@ web_sql_grid_unified <- function(niv, has_fosas, limit = NULL, simplify_tol = 0.
|
|
| 498 |
CAST(c.secuestro AS DOUBLE) AS secuestro,
|
| 499 |
CAST(c.trafico_menores AS DOUBLE) AS trafico_menores,
|
| 500 |
CAST(c.trata_personas AS DOUBLE) AS trata_personas,
|
|
|
|
| 501 |
COALESCE(CAST(d.desap_rate AS DOUBLE), 0) AS desap_per_100k{fosas_cols},
|
| 502 |
COALESCE(r.giim_mun, 'No aplica') AS giim_mun,
|
| 503 |
COALESCE(CAST(p.pam_total AS INTEGER), 0) AS pam_n,
|
|
|
|
|
|
|
| 504 |
COALESCE(pts.migrants_n, 0) AS migrants_n,
|
| 505 |
COALESCE(pts.graves_n, 0) AS graves_n,
|
| 506 |
COALESCE(pts.ocved_n, 0) AS ocved_n,
|
|
@@ -511,6 +592,7 @@ web_sql_grid_unified <- function(niv, has_fosas, limit = NULL, simplify_tol = 0.
|
|
| 511 |
LEFT JOIN {desap_sub} d ON g.CVEGEO = d.CVEGEO{fosas_join}
|
| 512 |
LEFT JOIN dim_remesas_mun r ON g.CVEGEO = r.CVEGEO
|
| 513 |
LEFT JOIN {pam_sub} p ON g.CVEGEO = p.CVEGEO
|
|
|
|
| 514 |
LEFT JOIN pts_src pts ON g.codigo = pts.codigo{limit_clause}"
|
| 515 |
)
|
| 516 |
}
|
|
@@ -580,7 +662,8 @@ ddb_minmax <- function(con, tbl, col, filter_zero = TRUE) {
|
|
| 580 |
crime = lapply(CRIME_COLS, function(info)
|
| 581 |
qbq("crime_mun", info$col, length(CRIME_STEP_PAL))),
|
| 582 |
desap = qbq("dim_desap_mun", "final_desap_nl_per_100k", length(DESAP_PAL)),
|
| 583 |
-
pam = qbq("dim_pam_mun", "pam_n", length(PAM_PAL))
|
|
|
|
| 584 |
),
|
| 585 |
# Actual min/max per layer's primary column -- powers the legend labels.
|
| 586 |
# Dynamic sub-types (crime/envipe/fosas) cache the DEFAULT sub-type only;
|
|
@@ -589,6 +672,7 @@ ddb_minmax <- function(con, tbl, col, filter_zero = TRUE) {
|
|
| 589 |
crime = ddb_minmax(con, "crime_mun", "homicidio", TRUE),
|
| 590 |
desap = ddb_minmax(con, "dim_desap_mun", "final_desap_nl_per_100k", TRUE),
|
| 591 |
pam = ddb_minmax(con, "dim_pam_mun", "pam_n", TRUE),
|
|
|
|
| 592 |
fosas = ddb_minmax(con, "dim_fosas_mun", "fosas_total", TRUE),
|
| 593 |
envipe = ddb_minmax(con, "state_polygons", "perception_insecurity_perc", FALSE)
|
| 594 |
)
|
|
@@ -685,7 +769,8 @@ WEB_SPEC <- list(
|
|
| 685 |
migrants = MIGRANTS_PAL, graves = GRAVES_PAL, infra = INFRA_PAL,
|
| 686 |
ocved = OCVED_PAL, ged = GED_PAL,
|
| 687 |
giim = GIIM_COLORS, bar_ramp = BAR_RAMP,
|
| 688 |
-
infra_cats = INFRA_CATS
|
|
|
|
| 689 |
),
|
| 690 |
|
| 691 |
crime_cols = CRIME_COLS,
|
|
@@ -718,6 +803,9 @@ WEB_SPEC <- list(
|
|
| 718 |
list(id = "pam-choro", type = "fill", src = "src_pam",
|
| 719 |
geom = "polygon", color = "pam_qstep", value = "pam_n",
|
| 720 |
opacity = 0.7, visible = FALSE),
|
|
|
|
|
|
|
|
|
|
| 721 |
list(id = "fosas-choro", type = "fill", src = "src_fosas",
|
| 722 |
geom = "polygon", color = "fosas_step", value = "fosas_total",
|
| 723 |
opacity = 0.65, visible = FALSE, requires = "dim_fosas_mun"),
|
|
@@ -802,7 +890,13 @@ WEB_SPEC <- list(
|
|
| 802 |
label = "Railway network",
|
| 803 |
tooltip = "Railway lines used by migrants, including freight routes known as 'La Bestia'.",
|
| 804 |
legend = list(type = "line", color = "#9E2A3A", label = "Railway", dashed = TRUE)),
|
| 805 |
-
list(kind = "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 806 |
)),
|
| 807 |
list(id = "vulnerability", label = "Vulnerability", open = FALSE, items = list(
|
| 808 |
list(kind = "layer", value = "infra-pts",
|
|
@@ -1233,6 +1327,29 @@ LUCIDE_JS <- tags$head(
|
|
| 1233 |
}
|
| 1234 |
}
|
| 1235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1236 |
// -- Side panel toggle (sigma / network / sparkles tab rail) ---------------
|
| 1237 |
function togglePanel(name) {
|
| 1238 |
var panel = document.getElementById('panel-' + name);
|
|
@@ -2027,6 +2144,15 @@ ui <- page_fillable(
|
|
| 2027 |
title = "Toggle 2D / 3D",
|
| 2028 |
HTML('<i data-lucide="box" style="width:16px;height:16px;stroke-width:2"></i>')),
|
| 2029 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2030 |
# Guided tour replay
|
| 2031 |
tags$button(class = "nav-btn", type = "button",
|
| 2032 |
onclick = "startTour()",
|
|
@@ -2305,6 +2431,7 @@ server <- function(input, output, session) {
|
|
| 2305 |
state = FALSE, routes = FALSE, via = FALSE,
|
| 2306 |
migrants = FALSE, graves = FALSE, infra = FALSE,
|
| 2307 |
ocved = FALSE, ged = FALSE,
|
|
|
|
| 2308 |
grid4 = FALSE, grid5 = FALSE, grid6 = FALSE
|
| 2309 |
)
|
| 2310 |
|
|
@@ -2417,14 +2544,30 @@ server <- function(input, output, session) {
|
|
| 2417 |
count_step_expr("pam_n", breaks, PAM_PAL)
|
| 2418 |
}
|
| 2419 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2420 |
# Return the fill-color expression for a given original layer ID
|
| 2421 |
-
grid_color_expr <- function(orig_lid, crime_type, fosas_type = "fosas"
|
|
|
|
| 2422 |
switch(orig_lid,
|
| 2423 |
"crime-choro" = crime_qstep_expr(crime_type),
|
| 2424 |
"desap-choro" = desap_qstep_expr(),
|
| 2425 |
"fosas-choro" = fosas_step_expr(fosas_type),
|
| 2426 |
"remesas-choro" = giim_match_expr(),
|
| 2427 |
"pam-choro" = pam_qstep_expr(),
|
|
|
|
|
|
|
| 2428 |
"migrants-pts" = count_step_expr("migrants_n", c(1, 5, 20, 50, 100), MIGRANTS_PAL),
|
| 2429 |
"graves-pts" = count_step_expr("graves_n", c(1, 2, 5, 15, 30), GRAVES_PAL),
|
| 2430 |
"infra-pts" = count_step_expr("infra_n", c(1, 3, 8, 20, 50), INFRA_PAL),
|
|
@@ -2442,6 +2585,7 @@ server <- function(input, output, session) {
|
|
| 2442 |
"desap-choro" = isTRUE(lazy_added$desap),
|
| 2443 |
"remesas-choro" = isTRUE(lazy_added$remesas),
|
| 2444 |
"pam-choro" = isTRUE(lazy_added$pam),
|
|
|
|
| 2445 |
"fosas-choro" = isTRUE(lazy_added$fosas),
|
| 2446 |
"envipe-state" = isTRUE(lazy_added$state),
|
| 2447 |
"routes-lines" = isTRUE(lazy_added$routes),
|
|
@@ -2520,7 +2664,7 @@ server <- function(input, output, session) {
|
|
| 2520 |
show <- grid_on && orig_lid %in% active && niv == nivel
|
| 2521 |
prx <- prx |> set_paint_property(grid_id, "fill-opacity", if (show) 0.65 else 0)
|
| 2522 |
if (show) {
|
| 2523 |
-
expr <- grid_color_expr(orig_lid, crime_type, fosas_type)
|
| 2524 |
if (!is.null(expr))
|
| 2525 |
prx <- prx |> set_paint_property(grid_id, "fill-color", expr)
|
| 2526 |
}
|
|
@@ -2765,6 +2909,15 @@ server <- function(input, output, session) {
|
|
| 2765 |
fill_opacity = 0, tooltip = grid_tooltip) |>
|
| 2766 |
add_fill_layer(id = paste0("grid-ged-n", niv), source = src,
|
| 2767 |
fill_color = count_step_expr("ged_n", c(1, 3, 10, 30, 80), GED_PAL),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2768 |
fill_opacity = 0, tooltip = grid_tooltip)
|
| 2769 |
m
|
| 2770 |
}
|
|
@@ -3106,6 +3259,12 @@ server <- function(input, output, session) {
|
|
| 3106 |
fill_color = pam_qstep_expr(), fill_opacity = 0.7,
|
| 3107 |
tooltip = list("concat", "<b>", list("get","municipio"), "</b>",
|
| 3108 |
"<br>Irregular migration events: ", list("to-string", list("get","pam_n")))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3109 |
if (!grid_on && "fosas-choro" %in% active && has_fosas_tbl)
|
| 3110 |
lazy_add_fill("fosas", "src_fosas", "fosas-choro", function(prx, d)
|
| 3111 |
prx |> add_fill_layer("fosas-choro", source = d,
|
|
@@ -3117,7 +3276,7 @@ server <- function(input, output, session) {
|
|
| 3117 |
lazy_add_fill("state", "src_state", "envipe-state", function(prx, d)
|
| 3118 |
prx |> add_fill_layer("envipe-state", source = d,
|
| 3119 |
fill_color = step_expr("insecurity_perc", c(40,55,65,75,85), ENVIPE_PAL),
|
| 3120 |
-
fill_opacity = 0.
|
| 3121 |
tooltip = list("concat", "<b>", list("get","desc_entidad"), "</b>",
|
| 3122 |
"<br>Insecurity: ", list("to-string", list("get","insecurity_perc")), "%",
|
| 3123 |
"<br>Dark figures: ", list("to-string", list("get","dark_figures_perc")), "%")))
|
|
|
|
| 107 |
"#de2d26", "#a50f15", "#67000d") # Reds 6
|
| 108 |
INFRA_PAL <- c("#ffffe5", "#f7fcb9", "#d9f0a3",
|
| 109 |
"#addd8e", "#78c679", "#238443") # YlGn 6
|
| 110 |
+
OCVED_PAL <- c("#f1eef6", "#d0d1e6", "#a6bddb",
|
| 111 |
+
"#67a9cf", "#2b8cbe", "#045a8d") # PuBu 6
|
| 112 |
GED_PAL <- c("#f1eef6", "#d0d1e6", "#a6bddb",
|
| 113 |
"#67a9cf", "#2b8cbe", "#045a8d") # PuBu 6
|
| 114 |
FOSAS_PAL <- c("#ffffd4", "#fee391", "#fec44f",
|
| 115 |
"#fe9929", "#d95f0e", "#993404") # YlOrBr 6
|
| 116 |
+
POP_PAL <- c("#f7fcf0", "#e0f3db", "#ccebc5",
|
| 117 |
+
"#a8ddb5", "#7bccc4", "#4eb3d3",
|
| 118 |
+
"#2b8cbe") # GnBu 7 (Exposure)
|
| 119 |
+
PATP_PAL <- c("#fff7f3", "#fde0dd", "#fcc5c0",
|
| 120 |
+
"#fa9fb5", "#f768a1", "#c51b8a") # RdPu 6 (Vulnerability)
|
| 121 |
+
POBREZA_PAL <- c("#feebe2", "#fbb4b9", "#f768a1",
|
| 122 |
+
"#c51b8a", "#7a0177", "#49006a") # RdPu 6 (deep, poverty)
|
| 123 |
+
|
| 124 |
+
# Categorical palettes for the two non-numeric patp sub-types. Stable colour-blind
|
| 125 |
+
# safe Set2-style hues; keys must match the truncated label list in setPATPType().
|
| 126 |
+
PATP_RURAL_PROBLEM_PAL <- c(
|
| 127 |
+
"Sociales y económicos" = "#66c2a5",
|
| 128 |
+
"Carencia o deficiencia en servicios básicos" = "#fc8d62",
|
| 129 |
+
"Caminos, transportes y telecomunicaciones" = "#8da0cb",
|
| 130 |
+
"Inseguridad, delincuencia y adicciones" = "#e78ac3",
|
| 131 |
+
"Carencia o deficiencia en la infraestructura educativa y de salud"= "#a6d854",
|
| 132 |
+
"Municipios sin localidades objetivo" = "#ffd92f",
|
| 133 |
+
"Sin problema" = "#e5c494",
|
| 134 |
+
"Falta de información / Otro problema" = "#b3b3b3",
|
| 135 |
+
"Riesgos ambientales" = "#1f78b4",
|
| 136 |
+
"Problema no definido" = "#cab2d6"
|
| 137 |
+
)
|
| 138 |
+
PATP_DELITO_PAL <- c(
|
| 139 |
+
"El patrimonio" = "#e41a1c",
|
| 140 |
+
"otros bienes" = "#377eb8",
|
| 141 |
+
"La vida y la Integridad corporal" = "#4daf4a",
|
| 142 |
+
"múltiples bienes" = "#984ea3",
|
| 143 |
+
"La familia" = "#ff7f00",
|
| 144 |
+
"Sin delito" = "#a6cee3",
|
| 145 |
+
"La libertad y la seguridad sexual" = "#b15928",
|
| 146 |
+
"Libertad personal" = "#6a3d9a"
|
| 147 |
+
)
|
| 148 |
|
| 149 |
# Infrastructure point categories -- grouped from the raw "category" field
|
| 150 |
# (Shelter / restaurant / Government / lodging / Legal/NGO / Food / charity /
|
|
|
|
| 181 |
"fosas-choro" = "fosas",
|
| 182 |
"remesas-choro" = "remesas",
|
| 183 |
"pam-choro" = "pam",
|
| 184 |
+
"envipe-state" = "envipe", # ENVIPE now also paints per grid cell
|
| 185 |
+
"pop-choro" = "pop",
|
| 186 |
"migrants-pts" = "migrants",
|
| 187 |
"graves-pts" = "graves",
|
| 188 |
"infra-pts" = "infra",
|
| 189 |
"ocved-pts" = "ocved",
|
| 190 |
"ged-pts" = "ged"
|
| 191 |
)
|
| 192 |
+
# envipe-state is no longer a NON_GRID_LAYER -- it now appears on the grid too.
|
| 193 |
+
NON_GRID_LAYERS <- c("routes-lines", "viaferrea-lines")
|
| 194 |
|
| 195 |
ENVIPE_COLS <- list(
|
| 196 |
"insecurity" = list(col = "insecurity_perc", breaks = c(40, 55, 65, 75, 85)),
|
|
|
|
| 335 |
FROM dim_pam_mun GROUP BY CVEGEO) p
|
| 336 |
ON c.CVEGEO = p.CVEGEO",
|
| 337 |
|
| 338 |
+
src_population =
|
| 339 |
+
"SELECT municipio, entidad, CVEGEO,
|
| 340 |
+
CAST(poblacion AS DOUBLE) AS poblacion,
|
| 341 |
+
wkt
|
| 342 |
+
FROM crime_mun
|
| 343 |
+
WHERE poblacion IS NOT NULL",
|
| 344 |
+
|
| 345 |
+
# patp: dim_patp_mun stores numeric values as VARCHAR; TRY_CAST converts
|
| 346 |
+
# the 'n.d.' sentinels (and other non-numeric strings) to NULL.
|
| 347 |
+
src_patp =
|
| 348 |
+
"SELECT c.municipio, c.entidad, c.CVEGEO,
|
| 349 |
+
TRY_CAST(p.t_part AS DOUBLE) AS t_part,
|
| 350 |
+
TRY_CAST(p.t_ocup AS DOUBLE) AS t_ocup,
|
| 351 |
+
TRY_CAST(p.pr AS DOUBLE) AS pr,
|
| 352 |
+
CAST(p.ind_conec AS DOUBLE) AS ind_conec,
|
| 353 |
+
p.pr_pred_loc_rur,
|
| 354 |
+
p.delitos_fc_b_j_a,
|
| 355 |
+
c.wkt
|
| 356 |
+
FROM crime_mun c
|
| 357 |
+
LEFT JOIN dim_patp_mun p ON c.CVEGEO = p.CVEGEO",
|
| 358 |
+
|
| 359 |
+
src_pobreza =
|
| 360 |
+
"SELECT c.municipio, c.entidad, c.CVEGEO,
|
| 361 |
+
CAST(pob.pobreza_pct AS DOUBLE) AS pobreza_pct,
|
| 362 |
+
CAST(pob.pobreza_ext_pct AS DOUBLE) AS pobreza_ext_pct,
|
| 363 |
+
CAST(pob.pobreza_mod_pct AS DOUBLE) AS pobreza_mod_pct,
|
| 364 |
+
CAST(pob.vul_carencia_pct AS DOUBLE) AS vul_carencia_pct,
|
| 365 |
+
CAST(pob.vul_ingreso_pct AS DOUBLE) AS vul_ingreso_pct,
|
| 366 |
+
CAST(pob.no_pobre_no_vul_pct AS DOUBLE) AS no_pobre_no_vul_pct,
|
| 367 |
+
CAST(pob.rezago_edu_pct AS DOUBLE) AS rezago_edu_pct,
|
| 368 |
+
CAST(pob.caren_salud_pct AS DOUBLE) AS caren_salud_pct,
|
| 369 |
+
CAST(pob.caren_seg_social_pct AS DOUBLE) AS caren_seg_social_pct,
|
| 370 |
+
CAST(pob.caren_vivienda_pct AS DOUBLE) AS caren_vivienda_pct,
|
| 371 |
+
CAST(pob.caren_serv_basicos_pct AS DOUBLE) AS caren_serv_basicos_pct,
|
| 372 |
+
CAST(pob.caren_alimentacion_pct AS DOUBLE) AS caren_alimentacion_pct,
|
| 373 |
+
CAST(pob.min_1_carencia_pct AS DOUBLE) AS min_1_carencia_pct,
|
| 374 |
+
CAST(pob.min_3_carencias_pct AS DOUBLE) AS min_3_carencias_pct,
|
| 375 |
+
CAST(pob.ing_inf_lp_pct AS DOUBLE) AS ing_inf_lp_pct,
|
| 376 |
+
CAST(pob.ing_inf_lpe_pct AS DOUBLE) AS ing_inf_lpe_pct,
|
| 377 |
+
c.wkt
|
| 378 |
+
FROM crime_mun c
|
| 379 |
+
LEFT JOIN dim_pobreza_mun pob ON c.CVEGEO = pob.CVEGEO",
|
| 380 |
+
|
| 381 |
src_fosas =
|
| 382 |
"SELECT c.municipio, c.entidad, c.CVEGEO,
|
| 383 |
COALESCE(CAST(f.fosas_total AS INTEGER), 0) AS fosas_total,
|
|
|
|
| 576 |
CAST(c.secuestro AS DOUBLE) AS secuestro,
|
| 577 |
CAST(c.trafico_menores AS DOUBLE) AS trafico_menores,
|
| 578 |
CAST(c.trata_personas AS DOUBLE) AS trata_personas,
|
| 579 |
+
CAST(c.poblacion AS DOUBLE) AS poblacion,
|
| 580 |
COALESCE(CAST(d.desap_rate AS DOUBLE), 0) AS desap_per_100k{fosas_cols},
|
| 581 |
COALESCE(r.giim_mun, 'No aplica') AS giim_mun,
|
| 582 |
COALESCE(CAST(p.pam_total AS INTEGER), 0) AS pam_n,
|
| 583 |
+
CAST(s.perception_insecurity_perc AS DOUBLE) AS insecurity_perc,
|
| 584 |
+
CAST(s.dark_figures_perc AS DOUBLE) AS dark_figures_perc,
|
| 585 |
COALESCE(pts.migrants_n, 0) AS migrants_n,
|
| 586 |
COALESCE(pts.graves_n, 0) AS graves_n,
|
| 587 |
COALESCE(pts.ocved_n, 0) AS ocved_n,
|
|
|
|
| 592 |
LEFT JOIN {desap_sub} d ON g.CVEGEO = d.CVEGEO{fosas_join}
|
| 593 |
LEFT JOIN dim_remesas_mun r ON g.CVEGEO = r.CVEGEO
|
| 594 |
LEFT JOIN {pam_sub} p ON g.CVEGEO = p.CVEGEO
|
| 595 |
+
LEFT JOIN state_polygons s ON s.CVE_ENT = SUBSTR(g.CVEGEO, 1, 2)
|
| 596 |
LEFT JOIN pts_src pts ON g.codigo = pts.codigo{limit_clause}"
|
| 597 |
)
|
| 598 |
}
|
|
|
|
| 662 |
crime = lapply(CRIME_COLS, function(info)
|
| 663 |
qbq("crime_mun", info$col, length(CRIME_STEP_PAL))),
|
| 664 |
desap = qbq("dim_desap_mun", "final_desap_nl_per_100k", length(DESAP_PAL)),
|
| 665 |
+
pam = qbq("dim_pam_mun", "pam_n", length(PAM_PAL)),
|
| 666 |
+
pop = qbq("crime_mun", "poblacion", length(POP_PAL))
|
| 667 |
),
|
| 668 |
# Actual min/max per layer's primary column -- powers the legend labels.
|
| 669 |
# Dynamic sub-types (crime/envipe/fosas) cache the DEFAULT sub-type only;
|
|
|
|
| 672 |
crime = ddb_minmax(con, "crime_mun", "homicidio", TRUE),
|
| 673 |
desap = ddb_minmax(con, "dim_desap_mun", "final_desap_nl_per_100k", TRUE),
|
| 674 |
pam = ddb_minmax(con, "dim_pam_mun", "pam_n", TRUE),
|
| 675 |
+
pop = ddb_minmax(con, "crime_mun", "poblacion", TRUE),
|
| 676 |
fosas = ddb_minmax(con, "dim_fosas_mun", "fosas_total", TRUE),
|
| 677 |
envipe = ddb_minmax(con, "state_polygons", "perception_insecurity_perc", FALSE)
|
| 678 |
)
|
|
|
|
| 769 |
migrants = MIGRANTS_PAL, graves = GRAVES_PAL, infra = INFRA_PAL,
|
| 770 |
ocved = OCVED_PAL, ged = GED_PAL,
|
| 771 |
giim = GIIM_COLORS, bar_ramp = BAR_RAMP,
|
| 772 |
+
infra_cats = INFRA_CATS,
|
| 773 |
+
pop = POP_PAL
|
| 774 |
),
|
| 775 |
|
| 776 |
crime_cols = CRIME_COLS,
|
|
|
|
| 803 |
list(id = "pam-choro", type = "fill", src = "src_pam",
|
| 804 |
geom = "polygon", color = "pam_qstep", value = "pam_n",
|
| 805 |
opacity = 0.7, visible = FALSE),
|
| 806 |
+
list(id = "pop-choro", type = "fill", src = "src_population",
|
| 807 |
+
geom = "polygon", color = "pop_qstep", value = "poblacion",
|
| 808 |
+
opacity = 0.7, visible = FALSE),
|
| 809 |
list(id = "fosas-choro", type = "fill", src = "src_fosas",
|
| 810 |
geom = "polygon", color = "fosas_step", value = "fosas_total",
|
| 811 |
opacity = 0.65, visible = FALSE, requires = "dim_fosas_mun"),
|
|
|
|
| 890 |
label = "Railway network",
|
| 891 |
tooltip = "Railway lines used by migrants, including freight routes known as 'La Bestia'.",
|
| 892 |
legend = list(type = "line", color = "#9E2A3A", label = "Railway", dashed = TRUE)),
|
| 893 |
+
list(kind = "layer", value = "pop-choro",
|
| 894 |
+
label = "Municipal population (CONAPO 2020)",
|
| 895 |
+
tooltip = "Estimated total population per municipality (CONAPO 2020 projection). Higher values shown in deeper blue-green.",
|
| 896 |
+
legend = list(type = "ramp", pal = "pop", unit = " people")),
|
| 897 |
+
list(kind = "soon", label = "Foreign population"),
|
| 898 |
+
list(kind = "soon", label = "PATP indicators (t_ocup, t_part, pr, ind_conec, pr_pred_loc_rur, delitos_fc_b_j_a)"),
|
| 899 |
+
list(kind = "soon", label = "CONEVAL pobreza indicators (16 %-cols)")
|
| 900 |
)),
|
| 901 |
list(id = "vulnerability", label = "Vulnerability", open = FALSE, items = list(
|
| 902 |
list(kind = "layer", value = "infra-pts",
|
|
|
|
| 1327 |
}
|
| 1328 |
}
|
| 1329 |
|
| 1330 |
+
// -- Map hover-tooltip on/off ----------------------------------------------
|
| 1331 |
+
// Hides the maplibre popup that mapgl attaches to layers with tooltip = ...
|
| 1332 |
+
// Visual-only: layers stay interactive (click, draw, etc.); only the hover
|
| 1333 |
+
// text is suppressed via CSS when 'tooltips-off' is set on <body>.
|
| 1334 |
+
function toggleMapTooltips() {
|
| 1335 |
+
var on = !document.body.classList.contains('tooltips-off');
|
| 1336 |
+
document.body.classList.toggle('tooltips-off', on);
|
| 1337 |
+
var btn = document.getElementById('tooltip-toggle-btn');
|
| 1338 |
+
if (btn) {
|
| 1339 |
+
btn.classList.toggle('active', !on);
|
| 1340 |
+
btn.setAttribute('aria-pressed', String(!on));
|
| 1341 |
+
btn.setAttribute('title', on ? 'Tooltips off (click to enable)' : 'Tooltips on (click to disable)');
|
| 1342 |
+
var icon = btn.querySelector('i');
|
| 1343 |
+
if (icon) icon.setAttribute('data-lucide', on ? 'message-square-off' : 'message-square');
|
| 1344 |
+
if (window.lucide) lucide.createIcons();
|
| 1345 |
+
}
|
| 1346 |
+
// Force-hide any popup that's currently open
|
| 1347 |
+
document.querySelectorAll('.maplibregl-popup').forEach(function(p) {
|
| 1348 |
+
if (on) p.style.display = 'none';
|
| 1349 |
+
else p.style.display = '';
|
| 1350 |
+
});
|
| 1351 |
+
}
|
| 1352 |
+
|
| 1353 |
// -- Side panel toggle (sigma / network / sparkles tab rail) ---------------
|
| 1354 |
function togglePanel(name) {
|
| 1355 |
var panel = document.getElementById('panel-' + name);
|
|
|
|
| 2144 |
title = "Toggle 2D / 3D",
|
| 2145 |
HTML('<i data-lucide="box" style="width:16px;height:16px;stroke-width:2"></i>')),
|
| 2146 |
|
| 2147 |
+
# Tooltip on/off toggle -- hides the map hover popup when disabled
|
| 2148 |
+
tags$button(id = "tooltip-toggle-btn", class = "nav-btn active",
|
| 2149 |
+
type = "button",
|
| 2150 |
+
onclick = "toggleMapTooltips()",
|
| 2151 |
+
`aria-label` = "Toggle map hover tooltips",
|
| 2152 |
+
`aria-pressed` = "true",
|
| 2153 |
+
title = "Tooltips on (click to disable)",
|
| 2154 |
+
HTML('<i data-lucide="message-square" style="width:16px;height:16px;stroke-width:2" aria-hidden="true"></i>')),
|
| 2155 |
+
|
| 2156 |
# Guided tour replay
|
| 2157 |
tags$button(class = "nav-btn", type = "button",
|
| 2158 |
onclick = "startTour()",
|
|
|
|
| 2431 |
state = FALSE, routes = FALSE, via = FALSE,
|
| 2432 |
migrants = FALSE, graves = FALSE, infra = FALSE,
|
| 2433 |
ocved = FALSE, ged = FALSE,
|
| 2434 |
+
pop = FALSE,
|
| 2435 |
grid4 = FALSE, grid5 = FALSE, grid6 = FALSE
|
| 2436 |
)
|
| 2437 |
|
|
|
|
| 2544 |
count_step_expr("pam_n", breaks, PAM_PAL)
|
| 2545 |
}
|
| 2546 |
|
| 2547 |
+
pop_qstep_expr <- function() {
|
| 2548 |
+
breaks <- qb$pop %||% c(5000, 25000, 100000, 250000, 500000, 1000000)
|
| 2549 |
+
step_expr("poblacion", breaks, POP_PAL)
|
| 2550 |
+
}
|
| 2551 |
+
|
| 2552 |
+
# Envipe on the GRID: each grid cell carries its containing state's
|
| 2553 |
+
# insecurity_perc / dark_figures_perc (joined via SUBSTR(CVEGEO, 1, 2) on the
|
| 2554 |
+
# grid query). The sub-type radio swaps the column the step expression reads.
|
| 2555 |
+
envipe_grid_expr <- function(envipe_type = "insecurity") {
|
| 2556 |
+
info <- ENVIPE_COLS[[envipe_type]] %||% ENVIPE_COLS[["insecurity"]]
|
| 2557 |
+
step_expr(info$col, info$breaks, ENVIPE_PAL)
|
| 2558 |
+
}
|
| 2559 |
+
|
| 2560 |
# Return the fill-color expression for a given original layer ID
|
| 2561 |
+
grid_color_expr <- function(orig_lid, crime_type, fosas_type = "fosas",
|
| 2562 |
+
envipe_type = "insecurity") {
|
| 2563 |
switch(orig_lid,
|
| 2564 |
"crime-choro" = crime_qstep_expr(crime_type),
|
| 2565 |
"desap-choro" = desap_qstep_expr(),
|
| 2566 |
"fosas-choro" = fosas_step_expr(fosas_type),
|
| 2567 |
"remesas-choro" = giim_match_expr(),
|
| 2568 |
"pam-choro" = pam_qstep_expr(),
|
| 2569 |
+
"pop-choro" = pop_qstep_expr(),
|
| 2570 |
+
"envipe-state" = envipe_grid_expr(envipe_type),
|
| 2571 |
"migrants-pts" = count_step_expr("migrants_n", c(1, 5, 20, 50, 100), MIGRANTS_PAL),
|
| 2572 |
"graves-pts" = count_step_expr("graves_n", c(1, 2, 5, 15, 30), GRAVES_PAL),
|
| 2573 |
"infra-pts" = count_step_expr("infra_n", c(1, 3, 8, 20, 50), INFRA_PAL),
|
|
|
|
| 2585 |
"desap-choro" = isTRUE(lazy_added$desap),
|
| 2586 |
"remesas-choro" = isTRUE(lazy_added$remesas),
|
| 2587 |
"pam-choro" = isTRUE(lazy_added$pam),
|
| 2588 |
+
"pop-choro" = isTRUE(lazy_added$pop),
|
| 2589 |
"fosas-choro" = isTRUE(lazy_added$fosas),
|
| 2590 |
"envipe-state" = isTRUE(lazy_added$state),
|
| 2591 |
"routes-lines" = isTRUE(lazy_added$routes),
|
|
|
|
| 2664 |
show <- grid_on && orig_lid %in% active && niv == nivel
|
| 2665 |
prx <- prx |> set_paint_property(grid_id, "fill-opacity", if (show) 0.65 else 0)
|
| 2666 |
if (show) {
|
| 2667 |
+
expr <- grid_color_expr(orig_lid, crime_type, fosas_type, envipe_type)
|
| 2668 |
if (!is.null(expr))
|
| 2669 |
prx <- prx |> set_paint_property(grid_id, "fill-color", expr)
|
| 2670 |
}
|
|
|
|
| 2909 |
fill_opacity = 0, tooltip = grid_tooltip) |>
|
| 2910 |
add_fill_layer(id = paste0("grid-ged-n", niv), source = src,
|
| 2911 |
fill_color = count_step_expr("ged_n", c(1, 3, 10, 30, 80), GED_PAL),
|
| 2912 |
+
fill_opacity = 0, tooltip = grid_tooltip) |>
|
| 2913 |
+
# Population per grid cell -- breaks come from cached crime_mun.poblacion quantiles
|
| 2914 |
+
add_fill_layer(id = paste0("grid-pop-n", niv), source = src,
|
| 2915 |
+
fill_color = pop_qstep_expr(),
|
| 2916 |
+
fill_opacity = 0, tooltip = grid_tooltip) |>
|
| 2917 |
+
# ENVIPE on grid -- each cell carries its state's insecurity_perc (from
|
| 2918 |
+
# the JOIN on state_polygons by CVE_ENT in web_sql_grid_unified).
|
| 2919 |
+
add_fill_layer(id = paste0("grid-envipe-n", niv), source = src,
|
| 2920 |
+
fill_color = envipe_grid_expr("insecurity"),
|
| 2921 |
fill_opacity = 0, tooltip = grid_tooltip)
|
| 2922 |
m
|
| 2923 |
}
|
|
|
|
| 3259 |
fill_color = pam_qstep_expr(), fill_opacity = 0.7,
|
| 3260 |
tooltip = list("concat", "<b>", list("get","municipio"), "</b>",
|
| 3261 |
"<br>Irregular migration events: ", list("to-string", list("get","pam_n")))))
|
| 3262 |
+
if (!grid_on && "pop-choro" %in% active)
|
| 3263 |
+
lazy_add_fill("pop", "src_population", "pop-choro", function(prx, d)
|
| 3264 |
+
prx |> add_fill_layer("pop-choro", source = d,
|
| 3265 |
+
fill_color = pop_qstep_expr(), fill_opacity = 0.7,
|
| 3266 |
+
tooltip = list("concat", "<b>", list("get","municipio"), "</b>",
|
| 3267 |
+
"<br>Population: ", list("to-string", list("get","poblacion")))))
|
| 3268 |
if (!grid_on && "fosas-choro" %in% active && has_fosas_tbl)
|
| 3269 |
lazy_add_fill("fosas", "src_fosas", "fosas-choro", function(prx, d)
|
| 3270 |
prx |> add_fill_layer("fosas-choro", source = d,
|
|
|
|
| 3276 |
lazy_add_fill("state", "src_state", "envipe-state", function(prx, d)
|
| 3277 |
prx |> add_fill_layer("envipe-state", source = d,
|
| 3278 |
fill_color = step_expr("insecurity_perc", c(40,55,65,75,85), ENVIPE_PAL),
|
| 3279 |
+
fill_opacity = 0.5,
|
| 3280 |
tooltip = list("concat", "<b>", list("get","desc_entidad"), "</b>",
|
| 3281 |
"<br>Insecurity: ", list("to-string", list("get","insecurity_perc")), "%",
|
| 3282 |
"<br>Dark figures: ", list("to-string", list("get","dark_figures_perc")), "%")))
|
styles.css
CHANGED
|
@@ -2429,3 +2429,6 @@ button.mapbox-gl-draw_uncombine { display: none !important; }
|
|
| 2429 |
.driver-popover .driver-popover-close-btn {
|
| 2430 |
color: var(--c-text-dim);
|
| 2431 |
}
|
|
|
|
|
|
|
|
|
|
|
|
| 2429 |
.driver-popover .driver-popover-close-btn {
|
| 2430 |
color: var(--c-text-dim);
|
| 2431 |
}
|
| 2432 |
+
|
| 2433 |
+
/* Tooltip toggle: hide maplibre popups when body.tooltips-off is set */
|
| 2434 |
+
body.tooltips-off .maplibregl-popup { display: none !important; }
|