diff --git a/01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary_updateGK.csv b/01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary_updateGK.csv index 92d4b8e..1fd73a0 100644 --- a/01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary_updateGK.csv +++ b/01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary_updateGK.csv @@ -1,4 +1,4 @@ -site,alternate_name,site_friendly,station_code,site_acronym,lat,long,start_date,end,wbid,location +site,alternate_name,site_friendly,station_code,site_acronym,Latitude,Longitude,start_date,end,wbid,location MICKLERS,N,Micklers,GTMMKNUT,MK,30.16073611,-81.36027778,,N,Lake,water_control DEPGL1,N,Guana Lake 1,GTMGL1NUT,GL1,30.1504,-81.3604,,N,Lake,open_water DEPGL2,N,Guana Lake 2,GTMGL2NUT,GL2,30.1161,-81.3511,,N,Lake,open_water diff --git a/01_Data_raw/Water_Quality/Guana_WQ/~$Guana_masterdata.xlsx b/01_Data_raw/Water_Quality/Guana_WQ/~$Guana_masterdata.xlsx new file mode 100644 index 0000000..5a93205 Binary files /dev/null and b/01_Data_raw/Water_Quality/Guana_WQ/~$Guana_masterdata.xlsx differ diff --git a/02_Cleaning_scripts/WIN_data_clean.R b/02_Cleaning_scripts/WIN_data_clean.R index 1182e36..383161c 100644 --- a/02_Cleaning_scripts/WIN_data_clean.R +++ b/02_Cleaning_scripts/WIN_data_clean.R @@ -9,7 +9,14 @@ library(tidyverse) GTMNERR <- st_read("03_Data_for_app/shapefiles_new/counties_GTMNERR.shp") # CRS: NAD83 / UTM zone 17N # WIN Data -gps_data <- read.csv("./01_Data_raw/Water_Quality/WIN/WIN_data_merged_20240501.csv") +gps_data <- read_csv("./01_Data_raw/Water_Quality/WIN/WIN_data_merged_20240501.csv") + +lookup_names <- read_csv("03_Data_for_app/WQ_lookup_names.csv") + +# Change column names so we can later merge this with other WQ data +recode_vec <- setNames(lookup_names$original_name, lookup_names$dashboard_name) +gps_data <- gps_data %>% + rename(any_of(recode_vec)) #### GTMNERR boundary and aquatic preserves #### @@ -41,7 +48,7 @@ bound_box <- st_bbox(st_sfc(pt1, pt3, pt4, pt2, crs = st_crs(GTMNERR))) # Filter GPS coordinates # Convert to sf object -gps_sf <- st_as_sf(gps_data, coords = c("Location_2", "Location_1"), crs = 4326) +gps_sf <- st_as_sf(gps_data, coords = c("Longitude", "Latitude"), crs = 4326) # Crop GPS points within the bounding box gps_cropped <- st_crop(gps_sf, bound_box) @@ -65,7 +72,7 @@ coordinates <- st_coordinates(gps_cropped) WIN_df <- cbind(WIN_df, coordinates) # Rename the coordinates columns if necessary -colnames(WIN_df)[(ncol(WIN_df)-1):ncol(WIN_df)] <- c("longitude", "latitude") +colnames(WIN_df)[(ncol(WIN_df)-1):ncol(WIN_df)] <- c("Longitude", "Latitude") #### Keep only columns with varying information #### # Function to remove columns with the same value in the whole column @@ -83,15 +90,17 @@ WIN_df <- remove_constant_columns(WIN_df) # Convert all columns to character before pivoting and retain the original row identifier WIN_df <- WIN_df %>% - select(-all_of(c("Station.ID", - "Station.Name", - "Org.Analyte.Name", - "DEP.Result.Value.Number", - "DEP.MDL", - "DEP.PQL", - "Org.Detection.Unit", - "Org.Result.Unit", - "Activity.End.Date.Time"))) %>% + select(-all_of(c("StationID", + "StationName", + "OrgAnalyteName", + "OrgResultValue", #GK: changed this from "DEPResultValueNumber", as I believe it is the DEP value we want to keep? + "DEPMDL", + "DEPPQL", + "OrgDetectionUnit", + "OrgResultUnit", + "ActivityEndDateTime"))) %>% + # Add a column to record the data source/provider + mutate(data_source = "WIN") %>% # or change this to DEP? mutate(across(everything(), as.character)) %>% mutate_all(~ na_if(., "")) %>% pivot_longer( @@ -108,4 +117,5 @@ WIN_df <- WIN_df %>% # "03_Data_for_app/Filtered_WIN_data_merged_20240501.csv", # row.names = FALSE) # Save the filtered data to a .RDs file + saveRDS(WIN_df, "03_Data_for_app/WIN.Rds") diff --git a/02_Cleaning_scripts/WQ_GTMNERR.R b/02_Cleaning_scripts/WQ_GTMNERR.R index 4010ff2..99c1a26 100644 --- a/02_Cleaning_scripts/WQ_GTMNERR.R +++ b/02_Cleaning_scripts/WQ_GTMNERR.R @@ -28,6 +28,13 @@ WQ_meta <- read_csv("01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary_up # Some stations have two codes due to a name change (see Word doc with metadata) # Don't remove +lookup_names <- read_csv("03_Data_for_app/WQ_lookup_names.csv") + +# Change column names so we can later merge this with other WQ data +recode_vec <- setNames(lookup_names$original_name, lookup_names$dashboard_name) +WQ <- WQ %>% + rename(any_of(recode_vec)) + ### 2. Check categorical values ------------------------------------------------ # Check station names, componentLong and componentShort (spelling etc) unique(WQ$StationCode) @@ -61,24 +68,23 @@ unique(WQ$Remark) # inconsistent... But there are some capital letters that names(WQ_meta)[names(WQ_meta) == "station_code"] <- "StationCode" WQ <- WQ %>% - left_join(WQ_meta) %>% - select(-Lat, -Long) + left_join(WQ_meta) # Stations missing from metadata: GL1.5, GL2.5 and GL3.5 -> added manually and # emailed Nikki -which(is.na(WQ$lat)) -which(is.na(WQ$long)) +which(is.na(WQ$Latitude)) +which(is.na(WQ$Longitude)) -WQ[which(is.na(WQ$lat)),] # duplicates?? Remove for now; emailed Nikki -WQ <- WQ[-which(is.na(WQ$lat)),] +WQ[which(is.na(WQ$Latitude)),] # duplicates?? Remove for now; emailed Nikki +WQ <- WQ[-which(is.na(WQ$Latitude)),] # Create a separate dataframe with only station info, not the data (makes map # too heavy) WQ_locations <- WQ %>% mutate(Year = year(SampleDate)) %>% - select(site_friendly, Year, site_acronym, lat, long, wbid, location) %>% - group_by(site_friendly, site_acronym, lat, long, wbid, location) %>% + select(site_friendly, Year, site_acronym, Latitude, Longitude, wbid, location) %>% + group_by(site_friendly, site_acronym, Latitude, Longitude, wbid, location) %>% summarize(maxYear = max(Year), minYear = min(Year)) %>% mutate(type = "Water quality", dataset = "Guana Water Quality Monitoring (GTMNERR)") @@ -86,7 +92,7 @@ WQ_locations <- WQ %>% WQ_data_available <- WQ %>% mutate(Year = year(SampleDate)) %>% select(StationCode, Year, SampleType, ComponentShort, ComponentLong, site_friendly, - site_acronym, lat, long, wbid, location) %>% + site_acronym, Latitude, Longitude, wbid, location) %>% distinct() ### 4. Save data --------------------------------------------------------------- diff --git a/02_Cleaning_scripts/WQ_WIN_merge.R b/02_Cleaning_scripts/WQ_WIN_merge.R new file mode 100644 index 0000000..9738bb5 --- /dev/null +++ b/02_Cleaning_scripts/WQ_WIN_merge.R @@ -0,0 +1,67 @@ +######################################################################## +########## NERRS Science Transfer project - GTMNERR ############# +######################################################################## + +# Geraldine Klarenberg, PhD +# gklarenberg@ufl.edu +# 12 August 2024 + +# Load packages +library(tidyverse) + +# Merge WIN and WQ data into one + +WIN <- readRDS("03_Data_for_app/WIN.Rds") +WQ_GTMNERR <- readRDS("03_Data_for_app/WQ.Rds") + +# Make WQ_GTMNERR long format as well, just like WIN +# Having a column for the dates is advisable though, as it is a separate data +# type. Update that later, not right now. + +# First make sure that every row has a UNID and also add a column for the data +# source / provider +WQ_GTMNERR <- WQ_GTMNERR %>% + mutate(data_source = "GTMNERR") %>% + arrange(UNID, StationCode, SampleDate, ComponentShort) + +for (i in 1:nrow(WQ_GTMNERR)){ + if (is.na(WQ_GTMNERR$UNID[i])){ + WQ_GTMNERR$UNID[i] <- WQ_GTMNERR$UNID[i-1] + 1 + } +} +# Check there are no duplicates +sum(duplicated(WQ_GTMNERR$UNID)) + +# Add a geometry column, to later use for clicking markers (we might change this) +WQ_GTMNERR <- st_as_sf(WQ_GTMNERR, coords = c("Longitude", "Latitude"), + crs = 4326, remove = FALSE) +# Turn back into dataframe with geometry as a column +WQ_GTMNERR <- as.data.frame(WQ_GTMNERR) + +WQ_GTMNERR_long <- WQ_GTMNERR %>% + mutate(across(everything(), as.character)) %>% + mutate_all(~ na_if(., "")) %>% + pivot_longer(cols = -UNID, + names_to = "variable", + values_to = "value") + +# How to deal with UNID when merging? Start counting anew (or add however far the +# one dataset is?) + +min(as.numeric(WQ_GTMNERR_long$UNID)) # 1 +max(as.numeric(WQ_GTMNERR_long$UNID)) # 5016 (used to be 17098?) + +min(as.numeric(WIN$RowID)) # 55135 +max(as.numeric(WIN$RowID)) # 3677602 +# Appears there will be no overlap. Merge. + +WQ_GTMNERR_long <- WQ_GTMNERR_long %>% + rename(RowID = UNID) + +WQ_all <- WIN %>% + full_join(WQ_GTMNERR_long) + +unique(WQ_all$variable) + +# Save data +saveRDS(WQ_all, "03_Data_for_app/WQ_all.Rds") diff --git a/03_Data_for_app/WIN.Rds b/03_Data_for_app/WIN.Rds index 001f3d9..f093579 100644 Binary files a/03_Data_for_app/WIN.Rds and b/03_Data_for_app/WIN.Rds differ diff --git a/03_Data_for_app/WQ.Rds b/03_Data_for_app/WQ.Rds index 37f790a..3b7dd4a 100644 Binary files a/03_Data_for_app/WQ.Rds and b/03_Data_for_app/WQ.Rds differ diff --git a/03_Data_for_app/WQ_all.Rds b/03_Data_for_app/WQ_all.Rds new file mode 100644 index 0000000..dc4b1c9 Binary files /dev/null and b/03_Data_for_app/WQ_all.Rds differ diff --git a/03_Data_for_app/WQ_locations.Rds b/03_Data_for_app/WQ_locations.Rds index 524f726..85e010a 100644 Binary files a/03_Data_for_app/WQ_locations.Rds and b/03_Data_for_app/WQ_locations.Rds differ diff --git a/03_Data_for_app/WQ_lookup_names.csv b/03_Data_for_app/WQ_lookup_names.csv new file mode 100644 index 0000000..95ac485 --- /dev/null +++ b/03_Data_for_app/WQ_lookup_names.csv @@ -0,0 +1,111 @@ +data_source,original_name,dashboard_name +WIN,Organization ID,OrganizationID +WIN,Monitoring Location ID,MonitoringLocationID +WIN,HUC12 Name,HUC12Name +WIN,Project ID,ProjectID +WIN,Activity ID,ActivityID +WIN,Activity Type,SampleType +WIN,Activity Start Date Time,SampleDate +WIN,Activity End Date Time,ActivityEndDateTime +WIN,Activity Time Zone,ActivityTimeZone +WIN,Media,Media +WIN,Matrix,Matrix +WIN,Sample Collection Type,SampleCollectionType +WIN,Sampling Agency Name,SamplingAgencyName +WIN,SampleCollectionEquipmentName,SampleCollectionEquipmentName +WIN,Activity Depth,ActivityDepth +WIN,Activity Depth Unit,ActivityDepthUnit +WIN,Relative Depth,RelativeDepth +WIN,Activity Top Depth,ActivityTopDepth +WIN,Activity Bottom Depth,ActivityBottomDepth +WIN,Activity Depth Top Bottom Unit,ActivityDepthTopBottomUnit +WIN,Total Depth,TotalDepth +WIN,Total Depth Unit,TotalDepthUnit +WIN,Activity Representative Ind,ActivityRepresentativeInd +WIN,Activity Comments,ActivityComments +WIN,Sampler Name,SamplerName +WIN,Field Blank Batch ID,FieldBlankBatchID +WIN,Equipment Blank Batch ID,EquipmentBlankBatchID +WIN,Trip Blank Batch ID,TripBlankBatchID +WIN,Master Activity ID,MasterActivityID +WIN,Activity Loaded Date,ActivityLoadedDate +WIN,Activity Updated Date,ActivityUpdatedDate +WIN,DEP Result ID,DEPResultID +WIN,Org Result ID,OrgResultID +WIN,DEP Analyte Group,DEPAnalyteGroup +WIN,DEP Analyte Name,ComponentLong +WIN,ADaPT Analyte ID,ADaPTAnalyteID +WIN,Org Analyte Name,OrgAnalyteName +WIN,Org Result Value,OrgResultValue +WIN,Org Result Unit,OrgResultUnit +WIN,Org MDL,OrgMDL +WIN,Org PQL,OrgPQL +WIN,Org Detection Unit,OrgDetectionUnit +WIN,DEP Result Value Number,Result +WIN,DEP Result Value Text,DEPResultValueText +WIN,DEP Result Unit,Unit +WIN,DEP MDL,DEPMDL +WIN,DEP PQL,DEPPQL +WIN,Value Qualifier,ValueQualifier +WIN,Sample Fraction,SampleFraction +WIN,Prep Method,PrepMethod +WIN,Preparation Date Time,PreparationDateTime +WIN,Preparation Time Zone,PreparationTimeZone +WIN,Analysis Method,AnalysisMethod +WIN,Analysis Date Time,AnalysisDateTime +WIN,Analysis Time Zone,AnalysisTimeZone +WIN,Lab ID,LabID +WIN,Lab Name,LabName +WIN,Lab Accreditation Authority,LabAccreditationAuthority +WIN,Result Comments,ResultComments +WIN,Lab Sample ID,LabSampleID +WIN,Method Batch ID,MethodBatchID +WIN,Analytical Batch ID,AnalyticalBatchID +WIN,Dilution,Dilution +WIN,Percent Moisture,PercentMoisture +WIN,Percent Recovery,PercentRecovery +WIN,Relative Percent Difference,RelativePercentDifference +WIN,Error,Error +WIN,Target Species,TargetSpecies +WIN,Finfish Size,FinfishSize +WIN,Finfish Unit,FinfishUnit +WIN,Result Value Type,ResultValueType +WIN,Statistical Base,StatisticalBase +WIN,Audit Censored Decisions,AuditCensoredDecisions +WIN,Result Loaded Date,ResultLoadedDate +WIN,Result Updated Date,ResultUpdatedDate +WIN,RowID,RowID +WIN,LocationID,LocationID +WIN,ProgramID,ProgramID +WIN,Station ID,StationID +WIN,Station Name,StationName +WIN,Station Type,StationType +WIN,County,County +WIN,Start Date,StartDate +WIN,End Date,EndDate +WIN,Location_1,Latitude +WIN,Location_2,Longitude +GTMNERR,UNID,UNID +GTMNERR,StationCode,StationCode +GTMNERR,SampleDate,SampleDate +GTMNERR,SampleType,SampleType +GTMNERR,Lat,Latitude +GTMNERR,Long,Longitude +GTMNERR,ComponentShort,ComponentShort +GTMNERR,ComponentLong,ComponentLong +GTMNERR,Result,Result +GTMNERR,Remark,Remark +GTMNERR,Flag,Flag +GTMNERR,Unit,Unit +GTMNERR,MRL,MRL +GTMNERR,MDL,MDL +GTMNERR,Dilution,Dilution +GTMNERR,PQL,PQL +GTMNERR,DateRecieved,DateRecieved +GTMNERR,DateAnalyzed,DateAnalyzed +GTMNERR,TestComments,TestComments +GTMNERR,AnalysisMethod,AnalysisMethod +GTMNERR,Lab ID,LabID +GTMNERR,Lab Accredidation Authority,LabAccredidationAuthority +GTMNERR,Laboratory,Laboratory +GTMNERR,RQ#,RQ# \ No newline at end of file diff --git a/03_Data_for_app/lookup_creation_manual.txt b/03_Data_for_app/lookup_creation_manual.txt new file mode 100644 index 0000000..54778df --- /dev/null +++ b/03_Data_for_app/lookup_creation_manual.txt @@ -0,0 +1,16 @@ +Guana Dashboard development +13 August 2024 + +For the water quality page, to streamline showing all the WQ data on one page, I manually created +a lookup table to change the headers of the separate files so they are the same. This way we can use +merge the datasets and use the existing functions on them. + +The headers comfr from the files App_dev/01_Data_raw/Water_Quality/WIN/WIN_data_merged_20240501.csv and +App_dev/01_Data_raw/Water_Quality/Guana_WQ/Guana_masterdata.xlsx. + +1. Copy-pasted the header names to App_dev/03_Data_for_app/WQ_lookup_names.csv and named the column original_name +2. Added a column data_sources with either WIN or GTMNERR +3. Created a column dashboard_name and copied all the names from original_name to it +4. For now (08/13/2024) I am only changing latitude, longitude, dates, sample type, components/analytes measured (DEP, not org). For visualization purposes. We can rename the rest later (analytes themselves will +also need to be renamed, as well as info on station names and types). +5. For the new names I also removed the spaces (because R inserts points there). \ No newline at end of file diff --git a/04_Tests/leaflet_test.R b/04_Tests/leaflet_test.R index c125916..baf9dd6 100644 --- a/04_Tests/leaflet_test.R +++ b/04_Tests/leaflet_test.R @@ -17,7 +17,7 @@ GTMNERR <- st_transform(GTMNERR, crs = 4326) # Leaflet uses EPSG 3857, change this # https://gis.stackexchange.com/questions/48949/epsg-3857-or-4326-for-web-mapping -epsg4326 <- leafletCRS(crsClass = "L.CRS.EPSG4326") +#epsg4326 <- leafletCRS(crsClass = "L.CRS.EPSG4326") # BUT! It actually seems that Leaflet does still want shapefiles in 4326, see # https://github.com/Leaflet/Leaflet/issues/4146 I also tried to change GTMNERR # to crs 3857 but that threw errors. See second paragraph here: @@ -27,11 +27,11 @@ m <- leaflet(data = GTMNERR, options = leafletOptions(#crs = epsg4326, minZoom = 9, maxZoom = 18)) %>% - #setView(lng=-81.347388, lat=30.075, zoom = 11) %>% + setView(lng=-81.289, lat=29.905, zoom = 11) %>% clearBounds() %>% addTiles() %>% # Add default OpenStreetMap map tiles - addPolygons(color = "purple", fill = NA) #%>% - #addMarkers(lng=-81.347388, lat=30.075, popup="Guana") + addPolygons(color = "purple", fill = NA) %>% + addMarkers(lng=-81.347388, lat=30.075, popup="Guana") m counties_select <- st_read("03_Data_for_app/shapefiles_new/counties_GTMNERR.shp") @@ -43,7 +43,7 @@ HAB_data_locations <- HAB_data %>% distinct() %>% st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326) -leaflet(options = leafletOptions(crs = epsg4326, minZoom = 9, maxZoom = 18)) %>% +leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% setView(lng=-81.347388, lat=30.075, zoom = 11) %>% # Base map addTiles() %>% # Add default OpenStreetMap map tiles @@ -56,10 +56,15 @@ leaflet(options = leafletOptions(crs = epsg4326, minZoom = 9, maxZoom = 18)) %>% highlightOptions = highlightOptions(color = "white", weight = 2, bringToFront = TRUE), group = "Counties", popup = ~NAME) %>% - addMarkers(data = HAB_data_locations, - popup = ~paste("Site: ", Site, "
", - "County: ", County), - group = "HAB") %>% + addAwesomeMarkers(icon = makeAwesomeIcon(icon = "flask", markerColor = "blue", library = "fa", + iconColor = "black"), #"", + data = HAB_data_locations, + #lng= rep(-81.347388, 34), lat = rep(30.075,34) + ) %>% + # addMarkers(data = HAB_data_locations, + # popup = ~paste("Site: ", Site, "
", + # "County: ", County), + # group = "HAB") %>% # # Layers control (turning layers on and off) addLayersControl(overlayGroups = c("Counties", "GTMNERR boundaries", "HAB"), options = layersControlOptions(collapsed = FALSE)) diff --git a/app.R b/app.R index 39efe18..13da537 100644 --- a/app.R +++ b/app.R @@ -1,40 +1,44 @@ -# This is the main app page, which will run and read in all the other pages -# and modules, and render the dashboard - -# Note: not necessary to load packages here: this all happens in global.R - -source("global.R") -source("functions.R") -source("modules/main_page.R") -source("modules/waterquality.R") -source("modules/algae.R") -source("modules/win.R") - -ui <- dashboardPage( - dashboardHeader(title = "Guana River Data Dashboard"), - dashboardSidebar( - sidebarMenu(id = "tabs", - menuItem("Main Page", tabName = "main_page", icon = icon("home")), - menuItem("Water Quality Data", tabName = "waterquality", icon = icon("link")), - menuItem("Harmful Algal Bloom Data", tabName = "algae", icon = icon("link")), - menuItem("Water Information Network", tabName = "win", icon = icon("bridge-water", lib="font-awesome")) - ) - ), - dashboardBody( - tabItems( - tabItem(tabName = "main_page", mainPageUI(id = "main_page")), - tabItem(tabName = "waterquality", WQPageUI(id = "waterquality")), - tabItem(tabName = "algae", HABPageUI(id = "algae")), - tabItem(tabName = "win", WINPageUI(id = "win")) - ) - ) -) - -server <- function(input, output, session) { - moduleServer(module = mainPageServer, id = "main_page", session = session) - WQPageServer("waterquality", parentSession = session) - HABPageServer("algae", parentSession = session) - WINPageServer("win", parentSession = session) -} - -shinyApp(ui, server) +# This is the main app page, which will run and read in all the other pages +# and modules, and render the dashboard + +# Note: not necessary to load packages here: this all happens in global.R + +source("global.R") +source("functions.R") +source("modules/main_page.R") +source("modules/waterquality.R") +source("modules/algae.R") +#source("modules/win.R") + +ui <- dashboardPage( + dashboardHeader(title = "Guana River Data Dashboard"), + dashboardSidebar( + sidebarMenu(id = "tabs", + menuItem("Main Page", tabName = "main_page", icon = icon("home")), + #menuItem("Water Quality Data", tabName = "waterquality", icon = icon("link")), + menuItem("Harmful Algal Bloom Data", tabName = "algae", icon = icon("microscope", lib = "font-awesome")), + menuItem("Water Quality Data", tabName = "waterquality", icon = icon("flask-vial", lib="font-awesome")), + menuItem("Water Level Data", tabName = "waterlevel", icon = icon("water", lib="font-awesome")), + menuItem("Fish, Shellfish & Other Aquatic Organisms Data", tabName = "shellfish", icon = icon("fish", lib="font-awesome")), + menuItem("Terrestrial Animal Data", tabName = "animal", icon = icon("paw", lib="font-awesome")), + menuItem("Vegetation Data", tabName = "animal", icon = icon("seedling", lib="font-awesome")) + ) + ), + dashboardBody( + tabItems( + tabItem(tabName = "main_page", mainPageUI(id = "main_page")), + #tabItem(tabName = "waterquality", WQPageUI(id = "waterquality")), + tabItem(tabName = "algae", HABPageUI(id = "algae")), + tabItem(tabName = "waterquality", WINPageUI(id = "waterquality")) + ) + ) +) + +server <- function(input, output, session) { + moduleServer(module = mainPageServer, id = "main_page", session = session) + #WQPageServer("waterquality", parentSession = session) + HABPageServer("algae", parentSession = session) + WINPageServer("waterquality", parentSession = session) +} + +shinyApp(ui, server) diff --git a/modules/main_page.R b/modules/main_page.R index f35ec56..14d5afc 100644 --- a/modules/main_page.R +++ b/modules/main_page.R @@ -1,3 +1,14 @@ +######################################################################## +########## NERRS Science Transfer project - GTMNERR ############# +######################################################################## + +# Geraldine Klarenberg, PhD +# gklarenberg@ufl.edu +# Created June 2024 +# Last updated: 12 August 2024 + +# This page shows a map, with a dropdown menu to pick types of +# datasets, as well as shapefiles for the area #### Get WIN data locations # I am putting this here right now, but I feel we should move this to a cleaning @@ -7,10 +18,10 @@ WIN_df <- readRDS("./03_Data_for_app/WIN.Rds") WIN_data_locations = WIN_df %>% filter(variable %in% c("geometry", - "HUC12.Name", - "Start.Date", - "latitude", - "longitude") + "HUC12Name", + "SampleDate", + "Latitude", + "Longitude") ) %>% select(c(RowID, variable, value)) %>% distinct(RowID, variable, value) %>% @@ -19,24 +30,32 @@ WIN_data_locations = WIN_df %>% values_from = value, values_fill = list(value = NA) ) %>% - distinct(geometry, HUC12.Name, Start.Date, latitude, longitude) %>% + distinct(geometry, HUC12Name, SampleDate, Latitude, Longitude) %>% mutate( - lat = as.numeric(latitude), - long = as.numeric(longitude), + SampleDate = ymd_hms(SampleDate), + Latitude = as.numeric(Latitude), + Longitude = as.numeric(Longitude), type = "Water quality", - dataset = "Watershed Information Network (DEP)" + dataset = "Watershed Information Network (DEP)", # Update this so we use data_source + minYear = min(year(SampleDate)), + maxYear = max(year(SampleDate)) ) %>% - select(-geometry, - latitude, -longitude) + select(-geometry, -SampleDate) #### WQ locations data ------------------------------------------------ WQ_data_locations <- readRDS("./03_Data_for_app/WQ_locations.Rds") # For now, for testing, make WQ_locations the dataframe to be used for filtering datasets_location <- full_join(WQ_data_locations, WIN_data_locations) -datasets_location <- st_as_sf(datasets_location, coords = c("long", "lat"), crs = 4326) +datasets_location <- st_as_sf(datasets_location, coords = c("Longitude", "Latitude"), crs = 4326) +datasets_location <- datasets_location[!duplicated(datasets_location),] + +color_palette <- colorFactor(palette = c("red", "goldenrod1"), #, "blue", "green" + domain = datasets_location$dataset) -color_palette <- colorFactor(palette = c("red"), #, "blue", "green", "purple" - domain = datasets_location$type) +#### HAB locations data ------------------------------------------------ +# Add this at some point so there is another dataset that shows up in the dropdown +# menu ### Define the UI ------------------------------------------------------------- mainPageUI <- function(id) { @@ -79,8 +98,8 @@ mainPageServer <- function(input, output, session) { # Create the map output$map <- renderLeaflet({ leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% - #setView(lng=-81.347388, lat=30.075, zoom = 11) %>% - clearBounds() %>% # centers map on all min/max coords + setView(-81.289, lat=29.905, zoom = 10) %>% + #clearBounds() %>% # centers map on all min/max coords # Base map addTiles() %>% # Add default OpenStreetMap map tiles # Polygons, add groups @@ -127,25 +146,28 @@ mainPageServer <- function(input, output, session) { observeEvent(input$datatype_selector, { # Filter data based on selected group filtered_data <- datasets_location[datasets_location$type == input$datatype_selector,] - + print(filtered_data) # Add markers to the map - commented out the popup bc this only works for WQ data print("Adding markers") leafletProxy(ns("map")) %>% clearMarkers() %>% - addCircleMarkers( - data = filtered_data, - color = ~color_palette(type), - opacity = 1, - fillOpacity = 0.5, - fillColor = ~color_palette(type), - fill = TRUE, - weight = 3, - radius = 8, - # popup = ~paste("Station: ", site_friendly, "
", - # "Location: ", wbid, "
", - # "Latest year of sampling: ", maxYear, "% + # addCircleMarkers( + # data = filtered_data, + # color = ~color_palette(dataset), + # opacity = 1, + # fillOpacity = 0.5, + # fillColor = ~color_palette(dataset), + # fill = TRUE, + # weight = 3, + # radius = 8, + # popup = ~paste("Station: ", site_friendly, "
", + # "Location: ", wbid, "
", + # "Latest year of sampling: ", maxYear, "% - st_as_sf(coords = c("long", "lat"), crs = 4326) +######################################################################## +########## NERRS Science Transfer project - GTMNERR ############# +######################################################################## -#### WQ data ------------------------------------------------ -WQ <- readRDS("./03_Data_for_app/WQ.Rds") +# Geraldine Klarenberg, PhD +# Email: gklarenberg@ufl.edu +# Christopher Marais +# Email: +# Last updated: 12 August 2024 -WQPageUI <- function(id) { - ns <- NS(id) # This is an important part to add to all sub pages so they use the - # correct sessions / ID's that connect the ui and server here +library(tidyverse) + +# import all WQ data for this page (WIN and Guana spreadsheet) +WQ_df <- readRDS("./03_Data_for_app/WQ_all.Rds") + +#### Process data further #### +# make datframe for map display and hover data +WQ_data_locations = WQ_df %>% + filter(variable %in% c("geometry", # we don't need this? + #"HUC12Name", # Changed for now (bc GTM WQ data does not have that variable) BUT we should also include a station name of some sort + "SampleDate", # changed, from StartDate - but also not necessary for locations + "Latitude", + "Longitude", + "data_source") + ) %>% + #select(c(RowID, variable, value)) %>% # not necessary + #distinct(RowID, variable, value) %>% # not necessary + pivot_wider( + names_from = variable, + values_from = value, + values_fill = list(value = NA) + ) %>% + distinct(Latitude, Longitude, data_source, geometry) %>% + mutate( + Latitude = as.numeric(Latitude), + Longitude = as.numeric(Longitude) + ) + +WQ_data_units = WQ_df %>% + filter(variable %in% c("ComponentLong", # some will be duplicated because they differ between the 2 sets + "Unit", "data_source") + ) %>% + #select(c(RowID, variable, value)) %>% + distinct(RowID, variable, value) %>% # strictly speaking also not necessary + pivot_wider( + names_from = variable, + values_from = value, + values_fill = list(value = NA), + values_fn = list(value = ~ first(.)) + ) %>% + distinct(ComponentLong, Unit, data_source) + +#### Functions #### +# make dataframe for click plots +filter_dataframe <- function(df, filter_value = NULL) { + if (!is.null(filter_value)) { + # Step 1: Identify the relevant RowIDs + relevant_row_ids <- df %>% + filter(value == filter_value) %>% + pull(RowID) + + # Step 2: Filter the entire dataframe to keep only rows with the relevant RowIDs + filtered_df <- df %>% + filter(RowID %in% relevant_row_ids) + } else { + # If no filter_value is provided, skip the filtering step + filtered_df <- df + } + + # Step 3: Create wide dataframe + wide_df <- filtered_df %>% + pivot_wider(names_from = variable, values_from = value) %>% + select(SampleDate, # we could also make these arguments for the function? + ComponentLong, + Result) %>% + pivot_wider(names_from = ComponentLong, + values_from = Result, + values_fn = list(Result = ~ mean(as.numeric(.), na.rm = TRUE))) %>% + mutate(SampleDate = ymd_hms(SampleDate)) %>% # + #mutate(SampleDate = str_extract(SampleDate, "[0-9]{4}-[0-9]{2}-[0-9]{2}")) %>% + #mutate(SampleDate = ymd(SampleDate)) %>% # these two lines are another option to only get ymd + mutate(across(-SampleDate, ~ as.numeric(.))) %>% + mutate(SampleDate = as.Date(SampleDate)) %>% + group_by(SampleDate) %>% + summarize(across(everything(), ~mean(.x, na.rm = TRUE))) %>% + select(where(~ n_distinct(.) > 2)) + + return(wide_df) +} + +# New function to create the dropdown +create_dropdown <- function(df, ns) { + column_names <- sort(colnames(df)[colnames(df) != "SampleDate"]) + print(paste("Creating dropdown with choices:", paste(column_names, collapse=", "))) + + selectInput( + inputId = ns("column_selector"), + label = "Select a Column", + choices = column_names, + selected = column_names[1] + ) +} + +# Modified create_plot function +create_plot <- function(df, units_df, loc_name = "GTMNERR", selected_column) { + print(paste("Creating plot for", selected_column)) + # Initialize the plot with the x-axis + fig <- plot_ly(df, x = ~SampleDate) + + # Get the column names except the one for the x-axis + column_names <- sort(colnames(df)[colnames(df) != "SampleDate"]) + + # Create a named vector for Y-axis titles + y_axis_titles <- setNames(units_df$Unit, units_df$ComponentLong) + + # Ensure selected_column is not NULL or empty + if (is.null(selected_column) || selected_column == "") { + selected_column <- column_names[1] + } + + # Loop through each column and add a trace + for (i in seq_along(column_names)) { + fig <- fig %>% + add_trace(y = df[[column_names[i]]], name = column_names[i], type = 'scatter', mode = 'lines', + showlegend = FALSE, + visible = if (column_names[i] == selected_column) TRUE else FALSE) + } + + # Customize the layout + fig <- fig %>% + layout(xaxis = list(title = 'Date'), + yaxis = list(title = y_axis_titles[selected_column]), + title = paste("Mean ", selected_column, " for ", loc_name)) + + return(fig) +} + + +#### Run the app #### +find_directory_of_file("app.R") + +# Updated UI in WINPageUI +WINPageUI <- function(id) { + ns <- NS(id) tagList( h2("Water Quality Data"), fluidRow( - # Map occupies 1st column - column(width = 7, leafletOutput(ns("map"), height=750)), # make sure to put the input inside ns() - # histogram occupies rows in the 2nd column - column(width = 5, plotOutput(ns("distPlot")), - sliderInput(ns("bins"), "Number of bins:", - min = 1, max = 50, value = 30) - ) + column(width = 7, leafletOutput(ns("map"), height="500px")), + column(width = 5, plotlyOutput(ns("plot"), height="500px")) + ), + fluidRow( + column(width = 12, uiOutput(ns("dropdown_ui"))) ), actionButton(inputId = ns("go_back"), label = "Back to Main Page") ) } -WQPageServer <- function(id, parentSession) { - moduleServer(id, function(input, output, session) { # this nested approach is - # necessary to be able to us the "back" button, otherwise Shiny cannot find - # the id for "tabs" +# Updated Server logic in WINPageServer +WINPageServer <- function(id, parentSession) { + moduleServer(id, function(input, output, session) { ns <- session$ns - - # Create the histogram - output$distPlot <- renderPlot({ - # generate bins based on input$bins from ui.R - x <- filter(WQ, ComponentShort == "ATEMP") %>% - select(Result) %>% - pull() - x <- as.numeric(x) # stop-gap measure because everything is characters - bins <- seq(min(x, na.rm = TRUE), max(x, na.rm = TRUE), - length.out = input$bins + 1 - ) - - # draw the histogram with the specified number of bins - hist(x, - breaks = bins, col = "darkgray", border = "white", - xlab = "Air temperature (degrees Celsius)", - main = "Histogram of air temperatures" - ) + + # Reactive value for the selected column + selected_column <- reactive({ + print(paste("Selected column changed to:", input$column_selector)) + input$column_selector }) - + + # Reactive value to track popup bubble state + popup_visible <- reactiveVal(FALSE) + + # Create the dropdown UI + output$dropdown_ui <- renderUI({ + print("Rendering dropdown UI") + df <- filter_dataframe(WQ_df) + create_dropdown(df, ns) + }) + + # Update plot when dropdown selection changes + observeEvent(selected_column(), { + print(paste("Updating plot for", selected_column())) + output$plot <- renderPlotly({ + df <- filter_dataframe(WQ_df) + create_plot(df, units_df = WQ_data_units, selected_column = selected_column()) + }) + }, ignoreInit = FALSE) + + # Default plot + output$plot <- renderPlotly({ + df <- filter_dataframe(WQ_df) + create_plot(df, units_df = WQ_data_units, selected_column = selected_column()) + }) + # Create the map output$map <- renderLeaflet({ leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% - # setView(lng=-81.347388, lat=30.075, zoom = 11) %>% - clearBounds() %>% # centers map on all min/max coords - # Base map - addTiles() %>% # Add default OpenStreetMap map tiles - # Polygons, add groups + clearBounds() %>% + addTiles() %>% addPolygons( data = GTMNERR, color = "purple", fill = NA, weight = 2, opacity = 1, group = "GTMNERR boundaries" @@ -69,32 +208,72 @@ WQPageServer <- function(id, parentSession) { color = "white", weight = 2, bringToFront = TRUE ), - group = "Counties", popup = ~NAME + group = "Counties", popup = ~NAME, layerId = ~NAME ) %>% - # addMarkers(data = HAB_data_locations, - # popup = ~paste("Site: ", Site, "
", - # "County: ", County), - # group = "HAB") %>% addMarkers( data = WQ_data_locations, - popup = ~ paste( - "Station: ", site_friendly, "
", - "Location: ", wbid, "
", - "Latest year of sampling: ", maxYear, ""#, #changed from HUC12Name + #"Start Date: ", SampleDate, "
" ), - group = "WQ" + group = "WQ", + layerId = ~geometry ) %>% - # # Layers control (turning layers on and off) addLayersControl( overlayGroups = c("Counties", "GTMNERR boundaries", "WQ"), options = layersControlOptions(collapsed = FALSE) ) %>% addMeasure(primaryLengthUnit = "miles", primaryAreaUnit = "sqmiles") }) - + + # Observe marker clicks + observeEvent(input$map_marker_click, { + click <- input$map_marker_click + if (!is.null(click)) { + clicked_id <- click$id + clicked_data <- WQ_data_locations %>% + filter(geometry == clicked_id) #GK: I don't think this is a great approach, as + # geometry is a specific "thing" for sf objects, so it has specific meaning. And + # that is not how we are using it here + + popup_visible(TRUE) + + output$plot <- renderPlotly({ + df <- filter_dataframe(WQ_df, filter_value = clicked_data$RowID) # Changed from HUC12.Name + create_plot(df, units_df = WQ_data_units, loc_name = clicked_data$RowID, selected_column = selected_column()) + }) + } + }) + + # Add observeEvent function for input$map_shape_click + observeEvent(input$map_shape_click, { + click <- input$map_shape_click + if (!is.null(click)) { + clicked_id <- click$id + clicked_data <- counties_select %>% + filter(NAME == clicked_id) + + popup_visible(TRUE) + + output$plot <- renderPlotly({ + df <- filter_dataframe(WQ_df, filter_value = clicked_data$NAME) + create_plot(df, units_df = WQ_data_units, loc_name = clicked_data$NAME, selected_column = selected_column()) + }) + } + }) + + # Observe map clicks to hide the popup + observeEvent(input$map_click, { + popup_visible(FALSE) + + # Default plot + output$plot <- renderPlotly({ + df <- filter_dataframe(WQ_df) + create_plot(df, units_df = WQ_data_units, selected_column = selected_column()) + }) + }) + observeEvent(input$go_back, { updateTabItems(session = parentSession, inputId = "tabs", selected = "main_page") }) }) -} \ No newline at end of file +} diff --git a/modules/waterquality2.R b/modules/waterquality2.R new file mode 100644 index 0000000..813c5bb --- /dev/null +++ b/modules/waterquality2.R @@ -0,0 +1,100 @@ +#### WQ locations data ------------------------------------------------ +WQ_locations <- readRDS("./03_Data_for_app/WQ_locations.Rds") +WQ_data_locations <- WQ_locations %>% + st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326) + +#### WQ data ------------------------------------------------ +WQ <- readRDS("./03_Data_for_app/WQ.Rds") + +WQPageUI <- function(id) { + ns <- NS(id) # This is an important part to add to all sub pages so they use the + # correct sessions / ID's that connect the ui and server here + tagList( + h2("Water Quality Data"), + fluidRow( + # Map occupies 1st column + column(width = 7, leafletOutput(ns("map"), height=750)), # make sure to put the input inside ns() + # histogram occupies rows in the 2nd column + column(width = 5, plotOutput(ns("distPlot")), + sliderInput(ns("bins"), "Number of bins:", + min = 1, max = 50, value = 30) + ) + ), + actionButton(inputId = ns("go_back"), label = "Back to Main Page") + ) +} + +WQPageServer <- function(id, parentSession) { + moduleServer(id, function(input, output, session) { # this nested approach is + # necessary to be able to us the "back" button, otherwise Shiny cannot find + # the id for "tabs" + ns <- session$ns + + # Create the histogram + output$distPlot <- renderPlot({ + # generate bins based on input$bins from ui.R + x <- filter(WQ, ComponentShort == "ATEMP") %>% + select(Result) %>% + pull() + x <- as.numeric(x) # stop-gap measure because everything is characters + bins <- seq(min(x, na.rm = TRUE), max(x, na.rm = TRUE), + length.out = input$bins + 1 + ) + + # draw the histogram with the specified number of bins + hist(x, + breaks = bins, col = "darkgray", border = "white", + xlab = "Air temperature (degrees Celsius)", + main = "Histogram of air temperatures" + ) + }) + + # Create the map + output$map <- renderLeaflet({ + leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% + # setView(lng=-81.347388, lat=30.075, zoom = 11) %>% + clearBounds() %>% # centers map on all min/max coords + # Base map + addTiles() %>% # Add default OpenStreetMap map tiles + # Polygons, add groups + addPolygons( + data = GTMNERR, color = "purple", fill = NA, + weight = 2, opacity = 1, group = "GTMNERR boundaries" + ) %>% + addPolygons( + data = counties_select, + color = "black", weight = 2, opacity = 1, + fill = TRUE, fillColor = "white", fillOpacity = 0.01, + highlightOptions = highlightOptions( + color = "white", weight = 2, + bringToFront = TRUE + ), + group = "Counties", popup = ~NAME + ) %>% + # addMarkers(data = HAB_data_locations, + # popup = ~paste("Site: ", Site, "
", + # "County: ", County), + # group = "HAB") %>% + addMarkers( + data = WQ_data_locations, + popup = ~ paste( + "Station: ", site_friendly, "
", + "Location: ", wbid, "
", + "Latest year of sampling: ", maxYear, "% + # # Layers control (turning layers on and off) + addLayersControl( + overlayGroups = c("Counties", "GTMNERR boundaries", "WQ"), + options = layersControlOptions(collapsed = FALSE) + ) %>% + addMeasure(primaryLengthUnit = "miles", primaryAreaUnit = "sqmiles") + }) + + observeEvent(input$go_back, { + updateTabItems(session = parentSession, inputId = "tabs", selected = "main_page") + }) + }) +} \ No newline at end of file diff --git a/modules/win.R b/modules/win.R deleted file mode 100644 index 53cf4b2..0000000 --- a/modules/win.R +++ /dev/null @@ -1,261 +0,0 @@ -# import data for this page -WIN_df <- readRDS("./03_Data_for_app/WIN.Rds") - -#### Process data further #### -# make datframe for map display and hover data -WIN_data_locations = WIN_df %>% - filter(variable %in% c("geometry", - "HUC12.Name", - "Start.Date", - "latitude", - "longitude") - ) %>% - select(c(RowID, variable, value)) %>% - distinct(RowID, variable, value) %>% - pivot_wider( - names_from = variable, - values_from = value, - values_fill = list(value = NA) - ) %>% - distinct(geometry, HUC12.Name, Start.Date, latitude, longitude) %>% - mutate( - latitude = as.numeric(latitude), - longitude = as.numeric(longitude) - ) - -WIN_data_units = WIN_df %>% - filter(variable %in% c("DEP.Analyte.Name", - "DEP.Result.Unit") - ) %>% - select(c(RowID, variable, value)) %>% - distinct(RowID, variable, value) %>% - pivot_wider( - names_from = variable, - values_from = value, - values_fill = list(value = NA), - values_fn = list(value = ~ first(.)) - ) %>% - distinct(DEP.Analyte.Name, DEP.Result.Unit) - -#### Functions #### -# make dataframe for click plots -filter_dataframe <- function(df, filter_value = NULL) { - if (!is.null(filter_value)) { - # Step 1: Identify the relevant RowIDs - relevant_row_ids <- df %>% - filter(value == filter_value) %>% - pull(RowID) - - # Step 2: Filter the entire dataframe to keep only rows with the relevant RowIDs - filtered_df <- df %>% - filter(RowID %in% relevant_row_ids) - } else { - # If no filter_value is provided, skip the filtering step - filtered_df <- df - } - - # Step 3: Create wide dataframe - wide_df <- filtered_df %>% - pivot_wider(names_from = variable, values_from = value) %>% - select(Activity.Start.Date.Time, - DEP.Analyte.Name, - Org.Result.Value) %>% - pivot_wider(names_from = DEP.Analyte.Name, - values_from = Org.Result.Value, - values_fn = list(Org.Result.Value = ~ mean(as.numeric(.), na.rm = TRUE))) %>% - mutate(Activity.Start.Date.Time = ymd_hms(Activity.Start.Date.Time)) %>% - mutate(across(-Activity.Start.Date.Time, ~ as.numeric(.))) %>% - mutate(Activity.Start.Date.Time = as.Date(Activity.Start.Date.Time)) %>% - group_by(Activity.Start.Date.Time) %>% - summarize(across(everything(), ~mean(.x, na.rm = TRUE))) %>% - select(where(~ n_distinct(.) > 2)) - - return(wide_df) -} - -# New function to create the dropdown -create_dropdown <- function(df, ns) { - column_names <- sort(colnames(df)[colnames(df) != "Activity.Start.Date.Time"]) - print(paste("Creating dropdown with choices:", paste(column_names, collapse=", "))) - - selectInput( - inputId = ns("column_selector"), - label = "Select a Column", - choices = column_names, - selected = column_names[1] - ) -} - -# Modified create_plot function -create_plot <- function(df, units_df, loc_name = "GTMNERR", selected_column) { - print(paste("Creating plot for", selected_column)) - # Initialize the plot with the x-axis - fig <- plot_ly(df, x = ~Activity.Start.Date.Time) - - # Get the column names except the one for the x-axis - column_names <- sort(colnames(df)[colnames(df) != "Activity.Start.Date.Time"]) - - # Create a named vector for Y-axis titles - y_axis_titles <- setNames(units_df$DEP.Result.Unit, units_df$DEP.Analyte.Name) - - # Ensure selected_column is not NULL or empty - if (is.null(selected_column) || selected_column == "") { - selected_column <- column_names[1] - } - - # Loop through each column and add a trace - for (i in seq_along(column_names)) { - fig <- fig %>% - add_trace(y = df[[column_names[i]]], name = column_names[i], type = 'scatter', mode = 'lines', - visible = if (column_names[i] == selected_column) TRUE else FALSE) - } - - # Customize the layout - fig <- fig %>% - layout(xaxis = list(title = 'Date'), - yaxis = list(title = y_axis_titles[selected_column]), - title = paste("Mean ", selected_column, " for ", loc_name)) - - return(fig) -} - - -#### Run the app #### -find_directory_of_file("app.R") - -# Updated UI in WINPageUI -WINPageUI <- function(id) { - ns <- NS(id) - tagList( - h2("Water Information Network"), - fluidRow( - column(width = 7, leafletOutput(ns("map"), height="500px")), - column(width = 5, plotlyOutput(ns("plot"), height="500px")) - ), - fluidRow( - column(width = 12, uiOutput(ns("dropdown_ui"))) - ), - actionButton(inputId = ns("go_back"), label = "Back to Main Page") - ) -} - -# Updated Server logic in WINPageServer -WINPageServer <- function(id, parentSession) { - moduleServer(id, function(input, output, session) { - ns <- session$ns - - # Reactive value for the selected column - selected_column <- reactive({ - print(paste("Selected column changed to:", input$column_selector)) - input$column_selector - }) - - # Reactive value to track popup bubble state - popup_visible <- reactiveVal(FALSE) - - # Create the dropdown UI - output$dropdown_ui <- renderUI({ - print("Rendering dropdown UI") - df <- filter_dataframe(WIN_df) - create_dropdown(df, ns) - }) - - # Update plot when dropdown selection changes - observeEvent(selected_column(), { - print(paste("Updating plot for", selected_column())) - output$plot <- renderPlotly({ - df <- filter_dataframe(WIN_df) - create_plot(df, units_df = WIN_data_units, selected_column = selected_column()) - }) - }, ignoreInit = FALSE) - - # Default plot - output$plot <- renderPlotly({ - df <- filter_dataframe(WIN_df) - create_plot(df, units_df = WIN_data_units, selected_column = selected_column()) - }) - - # Create the map - output$map <- renderLeaflet({ - leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% - clearBounds() %>% - addTiles() %>% - addPolygons( - data = GTMNERR, color = "purple", fill = NA, - weight = 2, opacity = 1, group = "GTMNERR boundaries" - ) %>% - addPolygons( - data = counties_select, - color = "black", weight = 2, opacity = 1, - fill = TRUE, fillColor = "white", fillOpacity = 0.01, - highlightOptions = highlightOptions( - color = "white", weight = 2, - bringToFront = TRUE - ), - group = "Counties", popup = ~NAME, layerId = ~NAME - ) %>% - addMarkers( - data = WIN_data_locations, - popup = ~ paste("Station Name: ", HUC12.Name, "
", - "Start Date: ", Start.Date, "
" - ), - group = "WIN", - layerId = ~geometry - ) %>% - addLayersControl( - overlayGroups = c("Counties", "GTMNERR boundaries", "WIN"), - options = layersControlOptions(collapsed = FALSE) - ) %>% - addMeasure(primaryLengthUnit = "miles", primaryAreaUnit = "sqmiles") - }) - - # Observe marker clicks - observeEvent(input$map_marker_click, { - click <- input$map_marker_click - if (!is.null(click)) { - clicked_id <- click$id - clicked_data <- WIN_data_locations %>% - filter(geometry == clicked_id) - - popup_visible(TRUE) - - output$plot <- renderPlotly({ - df <- filter_dataframe(WIN_df, filter_value = clicked_data$HUC12.Name) - create_plot(df, units_df = WIN_data_units, loc_name = clicked_data$HUC12.Name, selected_column = selected_column()) - }) - } - }) - - # Add observeEvent function for input$map_shape_click - observeEvent(input$map_shape_click, { - click <- input$map_shape_click - if (!is.null(click)) { - clicked_id <- click$id - clicked_data <- counties_select %>% - filter(NAME == clicked_id) - - popup_visible(TRUE) - - output$plot <- renderPlotly({ - df <- filter_dataframe(WIN_df, filter_value = clicked_data$NAME) - create_plot(df, units_df = WIN_data_units, loc_name = clicked_data$NAME, selected_column = selected_column()) - }) - } - }) - - # Observe map clicks to hide the popup - observeEvent(input$map_click, { - popup_visible(FALSE) - - # Default plot - output$plot <- renderPlotly({ - df <- filter_dataframe(WIN_df) - create_plot(df, units_df = WIN_data_units, selected_column = selected_column()) - }) - }) - - observeEvent(input$go_back, { - updateTabItems(session = parentSession, inputId = "tabs", selected = "main_page") - }) - }) -}