diff --git a/app/storm_report.qmd b/app/storm_report.qmd new file mode 100644 index 0000000..53ca17b --- /dev/null +++ b/app/storm_report.qmd @@ -0,0 +1,210 @@ +--- +title: "`r params$storm_name` `r params$storm_year` STORM REPORT" +subtitle: "Generated on: `r Sys.Date()`" +format: + pdf: + theme: cosmo +execute: + warning: false + message: false +params: + storm_basin: AL + storm_year: 1900 + storm_name: GALVESTON +--- + +```{r setup} +#| echo: false + +library(ggplot2) +library(sf) +library(rnaturalearth) +library(dplyr) + +source(file = "queries.R") + +storm <- list( + storm_basin = params$storm_basin, + storm_year = params$storm_year, + storm_name = params$storm_name +) + +unique_lfs <- get_unique_lf_ids(storm) + +storm_track <- get_hurdat_track(storm) +``` + +```{r track_map} +#| echo: false +#| fig-width: 10 +#| fig-height: 8 + + # Add color and category classification + storm_track <- storm_track %>% + mutate( + hurricane_category = case_when( + storm_status == "HU" & windspeed >= 64 & windspeed <= 82 ~ 1, + storm_status == "HU" & windspeed >= 83 & windspeed <= 95 ~ 2, + storm_status == "HU" & windspeed >= 96 & windspeed <= 112 ~ 3, + storm_status == "HU" & windspeed >= 113 & windspeed <= 136 ~ 4, + storm_status == "HU" & windspeed >= 137 ~ 5, + ), + status_label = case_when( + storm_status == "TD" ~ "Tropical Depression (TD)", + storm_status == "TS" ~ "Tropical Storm (TS)", + hurricane_category == 1 ~ "Hurricane Category 1", + hurricane_category == 2 ~ "Hurricane Category 2", + hurricane_category == 3 ~ "Hurricane Category 3", + hurricane_category == 4 ~ "Hurricane Category 4", + hurricane_category == 5 ~ "Hurricane Category 5", + storm_status == "EX" ~ "Extratropical Cyclone (EX)", + storm_status == "SD" ~ "Subtropical Depression (SD)", + storm_status == "SS" ~ "Subtropical Storm (SS)", + storm_status %in% c("LO", "WV", "DB") ~ "Low/Wave/Disturbance", + TRUE ~ "Missing Data" + ), + line_color = case_when( + storm_status == "TD" ~ "#2AFF00", + storm_status == "TS" ~ "#FFD020", + hurricane_category == 1 ~ "#FF4343", + hurricane_category == 2 ~ "#FF6FFF", + hurricane_category == 3 ~ "#FF23D3", + hurricane_category == 4 ~ "#C916FF", + hurricane_category == 5 ~ "#FFFFFF", + storm_status == "EX" ~ "#202020", + storm_status == "SD" ~ "#0055FF", + storm_status == "SS" ~ "#6CE2FF", + storm_status %in% c("LO", "WV", "DB") ~ "#A1A1A1", + TRUE ~ "#FF5C00" + ) + ) %>% + arrange(datetime) + + # Create ordered factor for legend + storm_track$status_label <- factor( + storm_track$status_label, + levels = c( + "Tropical Depression (TD)", + "Tropical Storm (TS)", + "Hurricane Category 1", + "Hurricane Category 2", + "Hurricane Category 3", + "Hurricane Category 4", + "Hurricane Category 5", + "Extratropical Cyclone (EX)", + "Subtropical Depression (SD)", + "Subtropical Storm (SS)", + "Low/Wave/Disturbance", + "Missing Data" + ) + ) + + world <- ne_countries(scale = "medium", returnclass = "sf") + states <- ne_states(returnclass = "sf") + + min_lon_range <- range(-100, -40) + min_lat_range <- range(10, 50) + + #lon_range <- range(storm_track$lon) + #lat_range <- range(storm_track$lat) + #lon_padding <- diff(lon_range) * 0.1 + #lat_padding <- diff(lat_range) * 0.1 + + p <- ggplot() + + geom_sf(data = world, fill = "#E5E5E5", color = "#999999", size = 0.3) + + geom_sf(data = states, fill = NA, color = "#CCCCCC", size = 0.2) + + #coord_sf( + #xlim = c(lon_range[1] - lon_padding, lon_range[2] + lon_padding), + #ylim = c(lat_range[1] - lat_padding, lat_range[2] + lat_padding), + #expand = FALSE + #) + + coord_sf( + xlim = c(min_lon_range[1], min_lon_range[2]), + ylim = c(min_lat_range[1], min_lat_range[2]), + expand = FALSE + ) + + theme_minimal() + + theme( + panel.background = element_rect(fill = "#D4E6F1"), + panel.grid.major = element_line(color = "#BBBBBB", size = 0.2), + legend.position = "right", + legend.key.size = unit(0.4, "cm"), + legend.text = element_text(size = 8) + ) + + if (nrow(storm_track) >= 2) { + for (i in 1:(nrow(storm_track) - 1)) { + segment_data <- storm_track[i:(i + 1), ] + p <- p + + geom_path( + data = segment_data, + aes(x = lon, y = lat), + color = storm_track$line_color[i], + size = 1 + ) + } + } + + p <- p + + geom_point( + data = storm_track, + aes(x = lon, y = lat, color = status_label), + size = 1.5 + ) + + landfall_data <- storm_track %>% + filter(record_identifier == "L") + + if (nrow(landfall_data) > 0) { + landfall_data <- landfall_data %>% + mutate(rmw_degrees = rmw_meters / 111320) + + p <- p + + geom_point( + data = landfall_data, + aes(x = lon, y = lat), + color = landfall_data$line_color, + size = 4, + shape = 19 + ) + + geom_point( + data = landfall_data, + aes(x = lon, y = lat), + color = landfall_data$line_color, + size = landfall_data$rmw_degrees * 100, + shape = 1, + stroke = 1.5, + alpha = 0.5 + ) + } + + color_values <- c( + "Tropical Depression (TD)" = "#2AFF00", + "Tropical Storm (TS)" = "#FFD020", + "Hurricane Category 1" = "#FF4343", + "Hurricane Category 2" = "#FF6FFF", + "Hurricane Category 3" = "#FF23D3", + "Hurricane Category 4" = "#C916FF", + "Hurricane Category 5" = "#FFFFFF", + "Extratropical Cyclone (EX)" = "#202020", + "Subtropical Depression (SD)" = "#0055FF", + "Subtropical Storm (SS)" = "#6CE2FF", + "Low/Wave/Disturbance" = "#A1A1A1", + "Missing Data" = "#FF5C00" + ) + + p <- p + + scale_color_manual( + name = "Storm Status", + values = color_values, + breaks = names(color_values), + drop = FALSE + ) + + labs( + title = paste(params$storm_name, params$storm_year), + x = "Longitude", + y = "Latitude" + ) + + print(p) +``` \ No newline at end of file