#install.packages("leaflet")
library(leaflet)
## Warning: package 'leaflet' was built under R version 4.5.3
# Install packages once if needed:
# install.packages(c("sf", "tidyverse", "leaflet", "htmlwidgets"))

library(sf)
## Linking to GEOS 3.13.1, GDAL 3.11.0, PROJ 9.6.0; sf_use_s2() is TRUE
library(tidyverse)
## Warning: package 'ggplot2' was built under R version 4.5.3
## Warning: package 'dplyr' was built under R version 4.5.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.1     ✔ readr     2.1.5
## ✔ forcats   1.0.1     ✔ stringr   1.5.2
## ✔ ggplot2   4.0.3     ✔ tibble    3.3.0
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.1.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(leaflet)
library(htmlwidgets)
leaflet() |>
  addTiles() |>
  setView(
    lng = -115.55,
    lat = 33.00,
    zoom = 9
  )
#install.packages("terra")
library(terra)
## Warning: package 'terra' was built under R version 4.5.3
## terra 1.9.34
## 
## Attaching package: 'terra'
## The following object is masked from 'package:tidyr':
## 
##     extract
#install.packages("geodata")
library(geodata)
## Warning: package 'geodata' was built under R version 4.5.3
library(geodata)

# Download the Imperial County boundary
imperial <- gadm(
  country = "USA",
  level = 2,
  path = "data"
)

imperial <- imperial[imperial$NAME_2 == "Imperial", ]

imperial
## class       : SpatVector
## geometry    : polygons
## dimensions  : 1, 13  (geometries, attributes)
## extent      : -116.1063, -114.4603, 32.61827, 33.43729  (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat WGS 84 (EPSG:4326)
## names       :      GID_2 GID_0       COUNTRY   GID_1     NAME_1 NL_NAME_1   NAME_2 VARNAME_2 NL_NAME_2 TYPE_2   (and 3 more)
## type        :      <chr> <chr>         <chr>   <chr>      <chr>     <chr>    <chr>     <chr>     <chr>  <chr>
## values      : USA.5.13_1   USA United States USA.5_1 California        NA Imperial        NA        NA County
library(sf)
imperial_sf <- st_as_sf(imperial)

plot(imperial_sf)
## Warning: plotting the first 9 out of 13 attributes; use max.plot = 13 to plot
## all

# Get monthly TerraClimate maximum temperature data
library(geodata)

climate <- worldclim_global(
  var = "tmax",
  res = 10,
  path = "data"
)
library(terra)

# Check what we currently have available
list.files("data", recursive = TRUE)
##  [1] "climate/wc2.1_10m/wc2.1_10m_tmax_01.tif"
##  [2] "climate/wc2.1_10m/wc2.1_10m_tmax_02.tif"
##  [3] "climate/wc2.1_10m/wc2.1_10m_tmax_03.tif"
##  [4] "climate/wc2.1_10m/wc2.1_10m_tmax_04.tif"
##  [5] "climate/wc2.1_10m/wc2.1_10m_tmax_05.tif"
##  [6] "climate/wc2.1_10m/wc2.1_10m_tmax_06.tif"
##  [7] "climate/wc2.1_10m/wc2.1_10m_tmax_07.tif"
##  [8] "climate/wc2.1_10m/wc2.1_10m_tmax_08.tif"
##  [9] "climate/wc2.1_10m/wc2.1_10m_tmax_09.tif"
## [10] "climate/wc2.1_10m/wc2.1_10m_tmax_10.tif"
## [11] "climate/wc2.1_10m/wc2.1_10m_tmax_11.tif"
## [12] "climate/wc2.1_10m/wc2.1_10m_tmax_12.tif"
## [13] "gadm/gadm41_USA_2_pk.rds"
#install.packages("daymetr")
library(daymetr)
## Warning: package 'daymetr' was built under R version 4.5.3
imperial_lat <- 33.04
imperial_lon <- -115.48

daymet_data <- download_daymet(
  lat = imperial_lat,
  lon = imperial_lon,
  start = 2005,
  end = 2021,
  internal = TRUE
)
## Downloading DAYMET data for: Daymet at 33.04/-115.48 latitude/longitude !
## Done !
head(daymet_data)
## $site
## [1] "Daymet"
## 
## $tile
## [1] 11013
## 
## $latitude
## [1] 33.04
## 
## $longitude
## [1] -115.48
## 
## $altitude
## [1] -46
## 
## $tile
## [1] 11013
head(daymet_data)
## $site
## [1] "Daymet"
## 
## $tile
## [1] 11013
## 
## $latitude
## [1] 33.04
## 
## $longitude
## [1] -115.48
## 
## $altitude
## [1] -46
## 
## $tile
## [1] 11013
names(daymet_data)
## [1] "site"      "tile"      "latitude"  "longitude" "altitude"  "tile"     
## [7] "data"
head(daymet_data$data)
##   year yday dayl..s. prcp..mm.day. srad..W.m.2. swe..kg.m.2. tmax..deg.c.
## 1 2005    1 35507.18          0.00       267.91            0        18.85
## 2 2005    2 35538.23          0.00       283.30            0        18.89
## 3 2005    3 35571.82          6.14       103.33            0        13.58
## 4 2005    4 35607.95          2.37       125.44            0        13.82
## 5 2005    5 35646.58          0.00       283.98            0        15.95
## 6 2005    6 35687.68          0.00       260.39            0        14.94
##   tmin..deg.c. vp..Pa.
## 1         7.01  361.47
## 2         6.02  336.01
## 3         8.11  940.23
## 4         7.13  840.63
## 5         3.18  357.33
## 6         3.85  418.26
names(daymet_data$data)
## [1] "year"          "yday"          "dayl..s."      "prcp..mm.day."
## [5] "srad..W.m.2."  "swe..kg.m.2."  "tmax..deg.c."  "tmin..deg.c." 
## [9] "vp..Pa."
library(tidyverse)
annual_temp <- daymet_data$data |>
  group_by(year) |>
  summarise(
    mean_tmax = mean(tmax..deg.c., na.rm = TRUE)
  )

annual_temp
## # A tibble: 17 × 2
##     year mean_tmax
##    <int>     <dbl>
##  1  2005      32.0
##  2  2006      32.5
##  3  2007      32.3
##  4  2008      32.3
##  5  2009      32.3
##  6  2010      31.3
##  7  2011      32.0
##  8  2012      32.9
##  9  2013      32.4
## 10  2014      33.1
## 11  2015      32.9
## 12  2016      33.1
## 13  2017      33.1
## 14  2018      32.7
## 15  2019      31.2
## 16  2020      33.4
## 17  2021      33.2
annual_temp <- annual_temp |>
  mutate(
    mean_tmax_F = mean_tmax * 9/5 + 32
  )

annual_temp
## # A tibble: 17 × 3
##     year mean_tmax mean_tmax_F
##    <int>     <dbl>       <dbl>
##  1  2005      32.0        89.7
##  2  2006      32.5        90.5
##  3  2007      32.3        90.2
##  4  2008      32.3        90.2
##  5  2009      32.3        90.1
##  6  2010      31.3        88.4
##  7  2011      32.0        89.5
##  8  2012      32.9        91.2
##  9  2013      32.4        90.2
## 10  2014      33.1        91.7
## 11  2015      32.9        91.1
## 12  2016      33.1        91.6
## 13  2017      33.1        91.6
## 14  2018      32.7        90.9
## 15  2019      31.2        88.2
## 16  2020      33.4        92.2
## 17  2021      33.2        91.8
ggplot(annual_temp, aes(x = year, y = mean_tmax_F)) +
  geom_line() +
  geom_point() +
  labs(
    title = "Annual Mean Daily Maximum Temperature",
    subtitle = "Imperial County, California — Daymet location",
    x = "Year",
    y = "Temperature (°F)"
  ) +
  theme_minimal()

library(leaflet)

leaflet() |>
  addTiles() |>
  setView(
    lng = -115.48,
    lat = 33.04,
    zoom = 8
  )
imperial_sf
## Simple feature collection with 1 feature and 13 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: -116.1063 ymin: 32.61827 xmax: -114.4603 ymax: 33.43729
## Geodetic CRS:  WGS 84
##        GID_2 GID_0       COUNTRY   GID_1     NAME_1 NL_NAME_1   NAME_2
## 1 USA.5.13_1   USA United States USA.5_1 California      <NA> Imperial
##   VARNAME_2 NL_NAME_2 TYPE_2 ENGTYPE_2 CC_2   HASC_2
## 1      <NA>      <NA> County    County <NA> US.CA.IM
##                         geometry
## 1 POLYGON ((-114.7206 32.7179...
#install.packages("FedData")
library(FedData)
## Warning: package 'FedData' was built under R version 4.5.3
## You have loaded FedData v4.
## As of FedData v4 we have retired
## dependencies on the `sp` and `raster` packages.
## All functions in FedData v4 return `terra` (raster)
## or `sf` (vector) objects by default, and there may be
## other breaking changes.
library(leaflet)
library(htmlwidgets)

annual_temp$label <- paste0(
  annual_temp$year,
  ": ",
  round(annual_temp$mean_tmax_F, 1),
  " °F"
)

m <- leaflet() |>
  addTiles() |>
  setView(
    lng = -115.48,
    lat = 33.04,
    zoom = 8
  ) |>
  addCircleMarkers(
    lng = -115.48,
    lat = 33.04,
    radius = 15,
    popup = annual_temp$label[1]
  )

m
library(leaflet)

# Create one map layer for each year
m <- leaflet() |>
  addTiles() |>
  setView(
    lng = -115.48,
    lat = 33.04,
    zoom = 8
  )

for (i in seq_len(nrow(annual_temp))) {
  
  m <- m |>
    addCircleMarkers(
      lng = -115.48,
      lat = 33.04,
      radius = 15,
      layerId = paste0("year_", annual_temp$year[i]),
      group = as.character(annual_temp$year[i]),
      label = paste0(
        annual_temp$year[i], ": ",
        round(annual_temp$mean_tmax_F[i], 1), " °F"
      ),
      popup = paste0(
        "<b>Year:</b> ", annual_temp$year[i],
        "<br><b>Mean daily maximum:</b> ",
        round(annual_temp$mean_tmax_F[i], 1), " °F"
      )
    )
}

m |>
  addLayersControl(
    overlayGroups = as.character(annual_temp$year),
    options = layersControlOptions(collapsed = FALSE)
  )
library(leaflet)

# Create one map layer for each year
m <- leaflet() |>
  addTiles() |>
  setView(
    lng = -115.48,
    lat = 33.04,
    zoom = 8
  )

for (i in seq_len(nrow(annual_temp))) {
  
  m <- m |>
    addCircleMarkers(
      lng = -115.48,
      lat = 33.04,
      radius = 15,
      layerId = paste0("year_", annual_temp$year[i]),
      group = as.character(annual_temp$year[i]),
      label = paste0(
        annual_temp$year[i], ": ",
        round(annual_temp$mean_tmax_F[i], 1), " °F"
      ),
      popup = paste0(
        "<b>Year:</b> ", annual_temp$year[i],
        "<br><b>Mean daily maximum:</b> ",
        round(annual_temp$mean_tmax_F[i], 1), " °F"
      )
    )
}

m |>
  addLayersControl(
    overlayGroups = as.character(annual_temp$year),
    options = layersControlOptions(collapsed = FALSE)
  )
library(leaflet)
library(htmlwidgets)

# Temperature values
years <- annual_temp$year
temps <- round(annual_temp$mean_tmax_F, 1)

# Start a fresh map
slider_map <- leaflet() |>
  addTiles() |>
  setView(
    lng = -115.48,
    lat = 33.04,
    zoom = 8
  ) |>
  addCircleMarkers(
    lng = -115.48,
    lat = 33.04,
    radius = 12,
    color = "red",
    fillColor = "red",
    fillOpacity = 0.8
  )

# Add slider control
slider_map <- htmlwidgets::onRender(
  slider_map,
  sprintf(
    "
    function(el, x) {

      var years = [%s];
      var temps = [%s];

      var control = L.control({position: 'bottomleft'});

      control.onAdd = function(map) {

        var div = L.DomUtil.create('div', 'info');

        div.style.background = 'white';
        div.style.padding = '10px';
        div.style.borderRadius = '6px';

        div.innerHTML =
          '<b>Year: <span id=\"selectedYear\">' + years[0] + '</span></b><br>' +
          '<span id=\"selectedTemp\">' + temps[0] + ' °F</span><br>' +
          '<input id=\"tempSlider\" type=\"range\" ' +
          'min=\"0\" max=\"' + (years.length - 1) + '\" ' +
          'value=\"0\" step=\"1\" style=\"width:250px\">';

        return div;
      };

      control.addTo(map);

      setTimeout(function() {

        var slider = document.getElementById('tempSlider');
        var yearText = document.getElementById('selectedYear');
        var tempText = document.getElementById('selectedTemp');

        slider.addEventListener('input', function() {

          var i = Number(this.value);

          yearText.innerHTML = years[i];
          tempText.innerHTML = temps[i] + ' °F';

        });

      }, 200);
    }
    ",
    paste(years, collapse = ","),
    paste(temps, collapse = ",")
  )
)

slider_map
library(leaflet)
library(htmlwidgets)

years <- annual_temp$year
temps <- annual_temp$mean_tmax_F

# Temperature color function
temp_color <- function(t) {
  if (t < 89) {
    "blue"
  } else if (t < 91) {
    "orange"
  } else {
    "red"
  }
}

slider_map <- leaflet() |>
  addTiles() |>
  setView(
    lng = -115.48,
    lat = 33.04,
    zoom = 8
  ) |>
  addCircleMarkers(
    lng = -115.48,
    lat = 33.04,
    radius = 20,
    color = temp_color(temps[1]),
    fillColor = temp_color(temps[1]),
    fillOpacity = 0.7,
    popup = paste0(
      "<b>Year:</b> ", years[1],
      "<br><b>Mean maximum temperature:</b> ",
      round(temps[1], 1), " °F"
    )
  )

slider_map
#install.packages("leaflet.extras2")
library(leaflet.extras2)
## Warning: package 'leaflet.extras2' was built under R version 4.5.3
library(leaflet)
library(leaflet.extras2)

# Make a date for each annual observation
annual_temp$date <- as.Date(
  paste0(annual_temp$year, "-01-01")
)

# Build the map
time_map <- leaflet() |>
  addTiles() |>
  setView(
    lng = -115.48,
    lat = 33.04,
    zoom = 8
  ) |>
  addCircleMarkers(
    lng = -115.48,
    lat = 33.04,
    radius = 18,
    fillOpacity = 0.8,
    color = "red",
    fillColor = "red",
    popup = paste0(
      "<b>Year:</b> ", annual_temp$year,
      "<br><b>Mean maximum temperature:</b> ",
      round(annual_temp$mean_tmax_F, 1),
      " °F"
    )
  )

time_map
library(terra)

# Create a temperature raster for Imperial County
# using the WorldClim maximum-temperature data we already downloaded

tmax_files <- list.files(
  "data",
  pattern = "tmax.*\\.tif$",
  recursive = TRUE,
  full.names = TRUE
)

tmax_files
##  [1] "data/climate/wc2.1_10m/wc2.1_10m_tmax_01.tif"
##  [2] "data/climate/wc2.1_10m/wc2.1_10m_tmax_02.tif"
##  [3] "data/climate/wc2.1_10m/wc2.1_10m_tmax_03.tif"
##  [4] "data/climate/wc2.1_10m/wc2.1_10m_tmax_04.tif"
##  [5] "data/climate/wc2.1_10m/wc2.1_10m_tmax_05.tif"
##  [6] "data/climate/wc2.1_10m/wc2.1_10m_tmax_06.tif"
##  [7] "data/climate/wc2.1_10m/wc2.1_10m_tmax_07.tif"
##  [8] "data/climate/wc2.1_10m/wc2.1_10m_tmax_08.tif"
##  [9] "data/climate/wc2.1_10m/wc2.1_10m_tmax_09.tif"
## [10] "data/climate/wc2.1_10m/wc2.1_10m_tmax_10.tif"
## [11] "data/climate/wc2.1_10m/wc2.1_10m_tmax_11.tif"
## [12] "data/climate/wc2.1_10m/wc2.1_10m_tmax_12.tif"
library(terra)

tmax <- rast(tmax_files)

tmax
## class       : SpatRaster
## size        : 1080, 2160, 12  (nrow, ncol, nlyr)
## resolution  : 0.1666667, 0.1666667  (x, y)
## extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat WGS 84 (EPSG:4326)
## sources     : wc2.1_10m_tmax_01.tif
##               wc2.1_10m_tmax_02.tif
##               wc2.1_10m_tmax_03.tif
##               ... and 9 more sources
## names       : wc2.1~ax_01, wc2.1~ax_02, wc2.1~ax_03, wc2.1~ax_04, wc2.1~ax_05, wc2.1~ax_06, ...
## min values  :     -42.419,   -39.58325,  -53.400002,  -59.548749,    -59.8395,  -60.360001, ...
## max values  :      42.157,     40.2645,    41.48825,    43.17525,     44.8155,     46.6155, ...
# Make sure the county and raster use the same coordinate system
imperial_sf <- st_transform(imperial_sf, crs(tmax))

# Convert county boundary to a terra vector
imperial_vect <- vect(imperial_sf)

# Crop and mask the temperature raster to Imperial County
tmax_imperial <- crop(tmax, imperial_vect)
tmax_imperial <- mask(tmax_imperial, imperial_vect)

# Display the first month's temperature surface
plot(
  tmax_imperial[[1]],
  main = "Imperial County — Maximum Temperature"
)

lines(imperial_vect)

library(leaflet)

# Temperature range in our data
min_temp <- floor(min(annual_temp$mean_tmax_F, na.rm = TRUE))
max_temp <- ceiling(max(annual_temp$mean_tmax_F, na.rm = TRUE))

# Red/orange/yellow heat palette
heat_palette <- colorNumeric(
  palette = c("#FFFFCC", "#FED976", "#FD8D3C", "#E31A1C", "#800026"),
  domain = c(min_temp, max_temp)
)

heat_map <- leaflet() |>
  addProviderTiles("CartoDB.Positron") |>
  setView(
    lng = -115.48,
    lat = 33.04,
    zoom = 8
  ) |>
  
  # Temperature point
  addCircleMarkers(
    lng = -115.48,
    lat = 33.04,
    radius = 18,
    color = "black",
    weight = 2,
    fillColor = heat_palette(annual_temp$mean_tmax_F[1]),
    fillOpacity = 0.9,
    popup = paste0(
      "<b>Imperial County Daymet location</b><br>",
      "<b>Year:</b> ", annual_temp$year[1], "<br>",
      "<b>Mean daily maximum:</b> ",
      round(annual_temp$mean_tmax_F[1], 1), " °F"
    )
  ) |>
  
  # Temperature legend
  addLegend(
    position = "bottomright",
    pal = heat_palette,
    values = annual_temp$mean_tmax_F,
    title = "Mean Daily Maximum<br>Temperature (°F)",
    opacity = 0.9
  ) |>
  
  # Explanation box
  addControl(
    html = paste0(
      "<div style='background:white; padding:12px; ",
      "border-radius:6px; max-width:320px; ",
      "box-shadow:0 1px 5px rgba(0,0,0,0.4);'>",
      "<b>What am I looking at?</b><br>",
      "This map shows the mean daily maximum temperature ",
      "for the Daymet observation location in Imperial County.<br><br>",
      "<b>Color scale:</b> yellow indicates cooler temperatures; ",
      "orange and red indicate progressively hotter temperatures.<br><br>",
      "<b>Important:</b> This point represents one Daymet grid location, ",
      "not the temperature across the entire county.",
      "</div>"
    ),
    position = "topright"
  )

heat_map
# Temperature anomaly relative to 2005

baseline <- annual_temp$mean_tmax_F[annual_temp$year == 2005]

annual_temp <- annual_temp |>
  mutate(
    anomaly_F = mean_tmax_F - baseline
  )

ggplot(
  annual_temp,
  aes(x = year, y = anomaly_F)
) +
  
  # Zero = 2005 baseline
  geom_hline(
    yintercept = 0,
    linewidth = 1
  ) +
  
  # Year-by-year anomaly
  geom_col(
    aes(fill = anomaly_F > 0)
  ) +
  
  # Trend line
  geom_smooth(
    method = "lm",
    se = TRUE,
    color = "black",
    linewidth = 1
  ) +
  
  scale_fill_manual(
    values = c(
      "TRUE" = "#D73027",
      "FALSE" = "#4575B4"
    ),
    labels = c(
      "TRUE" = "Warmer than 2005",
      "FALSE" = "Cooler than 2005"
    ),
    name = ""
  ) +
  
  labs(
    title = "Annual Temperature Anomaly",
    subtitle = "Imperial County, California — Daymet observation location",
    x = "Year",
    y = "Difference from 2005 mean maximum temperature (°F)",
    caption = "Positive values indicate warmer annual mean daily maximum temperatures than the 2005 baseline."
  ) +
  
  theme_minimal() +
  
  theme(
    legend.position = "bottom",
    plot.title = element_text(face = "bold", size = 16),
    plot.subtitle = element_text(size = 11)
  )
## `geom_smooth()` using formula = 'y ~ x'