diff --git a/.gitignore b/.gitignore index e0032c0b..5f7b6b6b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ .Ruserdata MA Report Generation/data/ -MA Report Generation/output/ Coastal_Wetlands/output Coral/output Nekton/output diff --git a/MA Report Generation/CoastalWetlands.R b/MA Report Generation/CoastalWetlands.R deleted file mode 100644 index 377d97d4..00000000 --- a/MA Report Generation/CoastalWetlands.R +++ /dev/null @@ -1,386 +0,0 @@ -## Coastal Wetlands - -out_dir_cw <- "output/Data/CoastalWetlands" - -param_file <- "SpeciesRichness" - -data <- fread(cw_file_in, sep="|", header=TRUE, stringsAsFactors=FALSE, - na.strings=c("NULL","","NA")) - -# Only interested in Percent Cover measurements -data <- data[data$ParameterName=="Percent Cover - Species Composition"] -# Make species group name uniform -data$SpeciesGroup1[data$SpeciesGroup1=="Marsh Succulents"] <- "Marsh succulents" -# Only keep data rows that are Marsh, Marsh succulents, and Mangroves and assoc. -data <- data[SpeciesGroup1=="Marsh"| - SpeciesGroup1=="Marsh succulents"| - SpeciesGroup1=="Mangroves and associate", ] -setnames(data, "SpeciesGroup1", "SpeciesGroup") -# Create ParameterName Column -data$ParameterName <- "Species Richness" -parameter <- "Species Richness" - -# Sets units for species richness -unit <- "# of species" -data$ParameterUnits <- unit - -# Replace instances where NA values imported as blank character string or as "NA" -# data <- replace(data, data=="", NA) -# data <- replace(data, data=="NA", NA) - -# Remove rows with missing ManagedAreaName -data <- data[!is.na(data$ManagedAreaName),] -data <- data[data$ManagedAreaName!="NA",] -# Remove rows with missing GenusName -data <- data[!is.na(data$GenusName),] -# Remove rows with missing SpeciesName -data <- data[!is.na(data$SpeciesName),] -# Remove rows with missing Months -data <- data[!is.na(data$Month),] -# Remove rows with missing Years -data <- data[!is.na(data$Year),] -# Set ResultValue to be a number value -data$ResultValue <- as.numeric(data$ResultValue) -# Remove rows where ResultValue is 0 -data <- data[data$ResultValue!=0,] -# Remove duplicate rows -data <- data[data$MADup==1,] -# Create variable that combines the genus and species name -data$gensp <- paste(data$GenusName, data$SpeciesName, sep=" ") -# Corrects Managed Area names to be consistent with official names -data$ManagedAreaName[data$ManagedAreaName=="Apalachicola Bay"] <- - "Apalachicola Bay Aquatic Preserve" -data$ManagedAreaName[data$ManagedAreaName=="Big Bend Seagrasses"] <- - "Big Bend Seagrasses Aquatic Preserve" -data$ManagedAreaName[data$ManagedAreaName=="Cockroach Bay"] <- - "Cockroach Bay Aquatic Preserve" -data$ManagedAreaName[data$ManagedAreaName=="Guana River Marsh"] <- - "Guana River Marsh Aquatic Preserve" -data$ManagedAreaName[data$ManagedAreaName=="Guana Tolomato Matanzas NERR"] <- - "Guana Tolomato Matanzas National Estuarine Research Reserve" - -# Create Species Richness values for groups of unique combinations of -# ManagedAreaName, ProgramID, ProgramName, ProgramLocationID, and SampleDate. -data <- data %>% - group_by(ManagedAreaName, ProgramID, ProgramName, ProgramLocationID, - SampleDate, SpeciesGroup) %>% - summarise(ParameterName=parameter, - Year=unique(Year), Month=unique(Month), - SpeciesRichness=length(unique(gensp))) - -# Adds AreaID for each managed area by combining the MA_All datatable to the -# data based on ManagedAreaName -data <- merge.data.frame(MA_All[,c("AreaID", "ManagedAreaName")], - data, by="ManagedAreaName", all=TRUE) - -# Writes this data that is used by the rest of the script to a text file -fwrite(data, paste0(out_dir_cw,"/CoastalWetlands_", param_file, "_UsedData.txt"), - sep="|") - -# Makes sure SampleDate is being stored as a Date object -data$SampleDate <- as.Date(data$SampleDate) - -# Creates a variable with the names of all the managed areas that contain -# species observations -MA_Include <- unique(data$ManagedAreaName[!is.na(data$SpeciesRichness)]) - -# Puts the managed areas in alphabetical order -MA_Include <- MA_Include[order(MA_Include)] - -#create global CoastalWetland MA_Include for use in ReportRender.R -cw_managed_areas <- MA_Include - -# Determines the number of managed areas used -n <- length(MA_Include) - -################ -### MA STATS ### -################ - -# Create summary statistics for each managed area based on Year and Month -# intervals. -MA_YM_Stats <- data %>% - group_by(AreaID, ManagedAreaName, Year, Month, SpeciesGroup) %>% - summarize(ParameterName=parameter, - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) -# Puts the data in order based on ManagedAreaName, Year, then Month -MA_YM_Stats <- as.data.table(MA_YM_Stats[order(MA_YM_Stats$ManagedAreaName, - MA_YM_Stats$Year, - MA_YM_Stats$Month), ]) -# Writes summary statistics to file -fwrite(MA_YM_Stats, paste0(out_dir_cw,"/CoastalWetlands_", param_file, - "_MA_MMYY_Stats.txt"), sep="|") -# Removes variable storing data to improve computer memory -rm(MA_YM_Stats) - -# Create summary statistics for each managed area based on Year intervals -MA_Y_Stats <- data %>% - group_by(AreaID, ManagedAreaName, Year, SpeciesGroup) %>% - summarize(ParameterName=parameter, - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) -# Puts the data in order based on ManagedAreaName then Year -MA_Y_Stats <- as.data.table(MA_Y_Stats[order(MA_Y_Stats$ManagedAreaName, - MA_Y_Stats$Year), ]) -# Writes summary statistics to file -fwrite(MA_Y_Stats, paste0(out_dir_cw,"/CoastalWetlands_", param_file, - "_MA_Yr_Stats.txt"), sep="|") - -MA_Y_Stats_cw <- MA_Y_Stats - -# Create summary statistics for each managed area based on Month intervals. -MA_M_Stats <- data %>% - group_by(AreaID, ManagedAreaName, Month, SpeciesGroup) %>% - summarize(ParameterName=parameter, - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) -# Puts the data in order based on ManagedAreaName then Month -MA_M_Stats <- as.data.table(MA_M_Stats[order(MA_M_Stats$ManagedAreaName, - MA_M_Stats$Month), ]) -# Writes summary statistics to file -fwrite(MA_M_Stats, paste0(out_dir_cw,"/CoastalWetlands_", param_file, - "_MA_Mo_Stats.txt"), sep="|") -# Removes variable storing data to improve computer memory -rm(MA_M_Stats) - -# Create summary overall statistics for each managed area. -MA_Ov_Stats <- data %>% - group_by(AreaID, ManagedAreaName, SpeciesGroup) %>% - summarize(ParameterName=parameter, - N_Years=length(unique(na.omit(Year))), - EarliestYear=min(Year), - LatestYear=max(Year), - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) -# Puts the data in order based on ManagedAreaName -MA_Ov_Stats <- as.data.table(MA_Ov_Stats[order(MA_Ov_Stats$ManagedAreaName), ]) -# Creates Year_MinRichness and Year_MaxRichness columns -MA_Ov_Stats$Year_MinRichness <- NA -MA_Ov_Stats$Year_MaxRichness <- NA - -# Loops through each ManagedAreaName. -# Determines what year the minimum and maximum species richness occurred -for(m in 1:nrow(MA_Ov_Stats)){ - # Stores ManagedAreaName for this row - man <- MA_Ov_Stats$ManagedAreaName[m] - - # Skips to next row if there are no data for this combination - if(MA_Ov_Stats$N_Data[m]==0){ - next - } - # Gets subset of data from MA_Y_Stats (yearly summary stats) with this - # ManagedAreaName - ds <- MA_Y_Stats[MA_Y_Stats$ManagedAreaName==man,] - # Gets the minimum and maximum Mean (yearly averages) - min <- min(ds$Mean) - max <- max(ds$Mean) - #Determines what years those minimum and maximum values occured - year_min <- ds$Year[ds$Mean==min] - year_max <- ds$Year[ds$Mean==max] - # Stores the occurrence years of the minimum and maximum into the overall - # stats for this row - MA_Ov_Stats$Year_MinRichness[m] <- year_min - MA_Ov_Stats$Year_MaxRichness[m] <- year_max -} -# Replaces blank ProgramIDs with NA (missing values) -MA_Ov_Stats$ProgramIDs <- replace(MA_Ov_Stats$ProgramIDs, - MA_Ov_Stats$ProgramIDs=="", NA) -MA_Ov_Stats$Programs <- replace(MA_Ov_Stats$Programs, - MA_Ov_Stats$Programs=="", NA) -# Write overall statistics to file -fwrite(MA_Ov_Stats, paste0(out_dir_cw,"/CoastalWetlands_", param_file, - "_MA_Overall_Stats.txt"), sep="|") -# Removes entries from the overall statistics that do not have data. -# Based on presence or absence of EarliestYear -MA_Ov_Stats <- MA_Ov_Stats[!is.na(MA_Ov_Stats$EarliestYear), ] - -MA_Ov_Stats_cw <- MA_Ov_Stats - -# Defines standard plot theme: black and white, no major or minor grid lines, -# Arial font. Title is centered, size 12, and blue (hex coded). Subtitle is -# centered, size 10, and blue (hex coded). Legend title is size 10 and the -# legend is left-justified. X-axis title is size 10 and the margins are padded -# at the top and bottom to give more space for angled axis labels. Y-axis title -# is size 10 and margins are padded on the right side to give more space for -# axis labels. Axis labels are size 10 and the x-axis labels are rotated -45 -# degrees with a horizontal justification that aligns them with the tick mark -plot_theme <- theme_bw() + - theme(panel.grid.major = element_blank(), - panel.grid.minor = element_blank(), - text=element_text(family="Arial"), - plot.title=element_text(hjust=0.5, size=12, color="#314963"), - plot.subtitle=element_text(hjust=0.5, size=10, color="#314963"), - legend.title=element_text(size=10), - legend.text.align = 0, - axis.title.x = element_text(size=10, margin = margin(t = 5, r = 0, - b = 10, l = 0)), - axis.title.y = element_text(size=10, margin = margin(t = 0, r = 10, - b = 0, l = 0)), - axis.text=element_text(size=10), - axis.text.x=element_text(angle = -45, hjust = 0)) - -# Color palette for SEACAR -color_palette <- c("#005396", "#0088B1", "#00ADAE", "#65CCB3", "#AEE4C1", - "#FDEBA8", "#F8CD6D", "#F5A800", "#F17B00") - -# Defines and sets variable with standardized group colors for plots -group_colors <- c("Marsh"=color_palette[1], - "Marsh succulents"=color_palette[2], - "Mangroves and associate"=color_palette[3]) - -# Defines and sets variable with standardized group shapes for plots -group_shapes <- c("Marsh"=21, - "Marsh succulents"=22, - "Mangroves and associate"=24) - -## Plotting function for use in ReportTemplate.Rmd ## - -plot_cw <- function(ma, MA_Ov_Stats = "MA_Ov_Stats_cw", MA_Y_Stats = "MA_Y_Stats_cw"){ - - # Gets data for target managed area - plot_data <- MA_Y_Stats[MA_Y_Stats$ManagedAreaName==ma] - # Determines most recent year with available data for managed area - t_max <- max(MA_Ov_Stats$LatestYear[MA_Ov_Stats$ManagedAreaName== - ma]) - # Determines earliest recent year with available data for managed area - t_min <- min(MA_Ov_Stats$EarliestYear[MA_Ov_Stats$ManagedAreaName== - ma]) - # Determines how many years of data are present - t <- t_max-t_min - - # Creates break intervals for plots based on number of years of data - if(t>=30){ - # Set breaks to every 10 years if more than 30 years of data - brk <- -10 - }else if(t<30 & t>=10){ - # Set breaks to every 5 years if between 30 and 10 years of data - brk <- -5 - }else if(t<10 & t>=4){ - # Set breaks to every 2 years if between 10 and 4 years of data - brk <- -2 - }else if(t<4 & t>=2){ - # Set breaks to every year if between 4 and 2 years of data - brk <- -1 - }else if(t<2){ - # Set breaks to every year if less than 2 years of data - brk <- -1 - # Sets t_max to be 1 year greater and t_min to be 1 year lower - # Forces graph to have at least 3 tick marks - t_max <- t_max+1 - t_min <- t_min-1 - } - # Determine range of data values for the managed area - y_range <- max(plot_data$Mean) - min(plot_data$Mean) - - # Determines lower bound of y-axis based on data range. Set based on - # relation of data range to minimum value. Designed to set lower boundary - # to be 10% of the data range below the minimum value - y_min <- if(min(plot_data$Mean)-(0.1*y_range)<0){ - # If 10% of the data range below the minimum value is less than 0, - # set as 0 - y_min <- 0 - } else { - # Otherwise set minimum bound as 10% data range below minimum value - y_min <- min(plot_data$Mean)-(0.1*y_range) - } - - # Sets upper bound of y-axis to be 10% of the data range above the - # maximum value. - y_max <- max(plot_data$Mean)+(0.1*y_range) - - # Determines what combination of groups are present for managed area - # and subsets color and shape scheme to be used by plots. - # Used so only group combinations present for managed area appear in - # the legend. - group_colors_plot <- group_colors[unique(plot_data$SpeciesGroup)] - group_shapes_plot <- group_shapes[unique(plot_data$SpeciesGroup)] - - # Creates plot object using plot_data. - # Data is plotted as symbols with connected lines. - p1 <- ggplot(data=plot_data, group=as.factor(SpeciesGroup)) + - geom_line(aes(x=Year, y=Mean, color=as.factor(SpeciesGroup)), - size=0.75, alpha=1) + - geom_point(aes(x=Year, y=Mean, fill=as.factor(SpeciesGroup), - shape=as.factor(SpeciesGroup)), size=2, - color="#333333", alpha=1) + - labs(title="Coastal Wetlands Species Richness", - subtitle=ma, - x="Year", y="Richness (# of species)", - fill="Species group", color="Species group", - shape="Species group") + - scale_x_continuous(limits=c(t_min-0.25, t_max+0.25), - breaks=seq(t_max, t_min, brk)) + - scale_y_continuous(limits=c(y_min, y_max), - breaks=pretty_breaks(n=5)) + - scale_fill_manual(values=group_colors_plot) + - scale_color_manual(values=group_colors_plot) + - scale_shape_manual(values=group_shapes_plot) + - plot_theme - # Sets file name of plot created - outname <- paste0("CoastalWetlands_", param_file, "_", - gsub(" ", "", ma), ".png") - # Saves plot as a png image - # png(paste0(out_dir_cw, "/Figures/", outname), - # width = 8, - # height = 4, - # units = "in", - # res = 200) - # print(p1) - # dev.off() - - # Creates a data table object to be shown underneath plots in report - ResultTable <- - MA_Ov_Stats[MA_Ov_Stats$ManagedAreaName==ma,] - # Removes location, species group, and parameter information because it is - # in plot labels - ResultTable <- ResultTable[,-c("AreaID", "ManagedAreaName", - "ProgramIDs", "Programs", "ParameterName")] - # Renames StandardDeviation to StDev to save horizontal space - ResultTable <- ResultTable %>% - rename("StDev"="StandardDeviation") - # Converts all non-integer values to 2 decimal places for space - ResultTable$Min <- round(ResultTable$Min, digits=2) - ResultTable$Max <- round(ResultTable$Max, digits=2) - ResultTable$Median <- round(ResultTable$Median, digits=2) - ResultTable$Mean <- round(ResultTable$Mean, digits=2) - ResultTable$StDev <- round(ResultTable$StDev, digits=2) - # Stores as plot table object - t1 <- ggtexttable(ResultTable, rows = NULL, - theme=ttheme(base_size=7)) - # Combines plot and table into one figure - print(ggarrange(p1, t1, ncol=1, heights=c(0.85, 0.15))) - cat(" \n") -} \ No newline at end of file diff --git a/MA Report Generation/Coral.R b/MA Report Generation/Coral.R deleted file mode 100644 index e2743ce0..00000000 --- a/MA Report Generation/Coral.R +++ /dev/null @@ -1,737 +0,0 @@ -library(knitr) -library(data.table) -library(dplyr) -library(lubridate) -library(ggplot2) -library(scales) -library(tidyr) -library(gridExtra) -library(hrbrthemes) -library(nlme) -library(ggpubr) - -data <- fread(coral_file_in, sep="|", header=TRUE, stringsAsFactors=FALSE, - na.strings=c("NULL","","NA")) -data2 <- data - -params_to_plot <- c("PercentCover", "SpeciesRichness") - - -###################### -### DATA FILTERING ### -###################### - -if("PercentCover" %in% params_to_plot){ - - out_dir <- "output/Data/Coral/PercentCover" - param_name <- "PercentCover" - param_file <- "PC" - seed <- 42 - - # Only keep data for Percent Cover - data <- data[data$ParameterName=="Percent Cover - Species Composition"] - - # Simplify ParameterName to Percent Cover - data$ParameterName <- "Percent Cover" - parameter <- "Percent Cover" - - # Sets units for percent cover - unit <- "%" - data$ParameterUnits <- unit - - # Remove any rows that are not corals - data <- data[SpeciesGroup1=="Octocoral"| - SpeciesGroup1=="Milleporans"| - SpeciesGroup1=="Scleractinian", ] - # Remove rows with missing ManagedAreaName - data <- data[!is.na(data$ManagedAreaName),] - data <- data[data$ManagedAreaName!="NA",] - # Remove rows with missing GenusName - data <- data[!is.na(data$GenusName),] - # Remove rows with missing SpeciesName - data <- data[!is.na(data$SpeciesName),] - # Remove rows with missing Months - data <- data[!is.na(data$Month),] - # Remove rows with missing Years - data <- data[!is.na(data$Year),] - # Remove rows with missing SpeciesGroup1 - data <- data[!is.na(data$SpeciesGroup1),] - # Remove rows with missing ResultValue - data <- data[!is.na(data$ResultValue),] - # Remove rows with missing SampleDate - data <- data[!is.na(data$SampleDate),] - # Remove duplicate rows - data <- data[data$MADup==1,] - # Create variable that combines the genus and species name - data$gensp <- paste(data$GenusName, data$SpeciesName, sep=" ") - # Corrects Managed Area names to be consistent with official names - data$ManagedAreaName[data$ManagedAreaName=="Florida Keys NMS"] <- - "Florida Keys National Marine Sanctuary" - data$ManagedAreaName[data$ManagedAreaName== - "Biscayne Bay-Cape Florida to Monroe County Line"] <- - "Biscayne Bay-Cape Florida to Monroe County Line Aquatic Preserve" - data$ManagedAreaName[data$ManagedAreaName=="Coupon Bight"] <- - "Coupon Bight Aquatic Preserve" - data$ManagedAreaName[data$ManagedAreaName=="Coral ECA"] <- - "Southeast Florida Coral Reef Ecosystem Conservation Area" - - # Adds AreaID for each managed area by combining the MA_All datatable to the - # data based on ManagedAreaName - data <- merge.data.frame(MA_All[,c("AreaID", "ManagedAreaName")], - data, by=c("AreaID", "ManagedAreaName"), all=TRUE) - ############### - ## SUM STATS ## - ############### - - # Create summary statistics for each managed area based on Year and Month - # intervals. - MA_YM_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName, Year, Month) %>% - dplyr::summarize(ParameterName=parameter, - N_Data=length(na.omit(ResultValue)), - Min=min(ResultValue), - Max=max(ResultValue), - Median=median(ResultValue), - Mean=mean(ResultValue), - StandardDeviation=sd(ResultValue), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName, Year, then Month - MA_YM_Stats <- as.data.table(MA_YM_Stats[order(MA_YM_Stats$ManagedAreaName, - MA_YM_Stats$Year, - MA_YM_Stats$Month), ]) - # Writes summary statistics to file - fwrite(MA_YM_Stats, paste0(out_dir,"/Coral_", param_file, - "_MA_MMYY_Stats.txt"), sep="|") - # Removes variable storing data to improve computer memory - rm(MA_YM_Stats) - - # Create summary statistics for each managed area based on Year intervals - MA_Y_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName, Year) %>% - dplyr::summarize(ParameterName=parameter, - N_Data=length(na.omit(ResultValue)), - Min=min(ResultValue), - Max=max(ResultValue), - Median=median(ResultValue), - Mean=mean(ResultValue), - StandardDeviation=sd(ResultValue), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName then Year - MA_Y_Stats <- as.data.table(MA_Y_Stats[order(MA_Y_Stats$ManagedAreaName, - MA_Y_Stats$Year), ]) - # Writes summary statistics to file - fwrite(MA_Y_Stats, paste0(out_dir,"/Coral_", param_file, - "_MA_Yr_Stats.txt"), sep="|") - - # Create summary statistics for each managed area based on Month intervals. - MA_M_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName, Month) %>% - dplyr::summarize(ParameterName=parameter, - N_Data=length(na.omit(ResultValue)), - Min=min(ResultValue), - Max=max(ResultValue), - Median=median(ResultValue), - Mean=mean(ResultValue), - StandardDeviation=sd(ResultValue), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName then Month - MA_M_Stats <- as.data.table(MA_M_Stats[order(MA_M_Stats$ManagedAreaName, - MA_M_Stats$Month), ]) - # Writes summary statistics to file - fwrite(MA_M_Stats, paste0(out_dir,"/Coral_", param_file, - "_MA_Mo_Stats.txt"), sep="|") - # Removes variable storing data to improve computer memory - rm(MA_M_Stats) - - # Create summary overall statistics for each managed area. - MA_Ov_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName) %>% - dplyr::summarize(ParameterName=parameter, - N_Years=length(unique(na.omit(Year))), - SufficientData=ifelse(N_Years>=5, TRUE, FALSE), - EarliestYear=min(Year), - LatestYear=max(Year), - N_Data=length(na.omit(ResultValue)), - Min=min(ResultValue), - Max=max(ResultValue), - Median=median(ResultValue), - Mean=mean(ResultValue), - StandardDeviation=sd(ResultValue), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName - MA_Ov_Stats <- as.data.table(MA_Ov_Stats[order(MA_Ov_Stats$ManagedAreaName), ]) - - # Replaces blank ProgramIDs with NA (missing values) - MA_Ov_Stats$ProgramIDs <- replace(MA_Ov_Stats$ProgramIDs, - MA_Ov_Stats$ProgramIDs=="", NA) - MA_Ov_Stats$Programs <- replace(MA_Ov_Stats$Programs, - MA_Ov_Stats$Programs=="", NA) - # Write overall statistics to file - fwrite(MA_Ov_Stats, paste0(out_dir,"/Coral_", param_file, - "_MA_Overall_Stats.txt"), sep="|") - # Creates a variable with the names of all the managed areas that contain - # species observations - MA_Include <- unique(MA_Ov_Stats$ManagedAreaName[!is.na(MA_Ov_Stats$Mean)& - MA_Ov_Stats$SufficientData== - TRUE]) - - # Puts the managed areas in alphabetical order - MA_Include <- MA_Include[order(MA_Include)] - - # Determines the number of managed areas used - n <- length(MA_Include) - - coral_pc_MA_Include <- MA_Include - - ############### - ##### LME ##### - ############### - - # Creates blank data frame with number of rows defined by how many managed areas - # are going to be analyzed - lme_stats <- data.frame(matrix(ncol = 5, nrow = n)) - # Sets column names for blank data frame - colnames(lme_stats) <- c("AreaID", "ManagedAreaName", "LME_Intercept", - "LME_Slope", "LME_p") - - # Begins to loop through each managed area for analysis - for(i in 1:n){ - # Gets data for current managegd area - lme_data <- data[data$ManagedAreaName==MA_Include[i],] - # Perform LME for relation between ResultValue and Year for current managed area - AnyCoral<-lme(ResultValue ~ Year, - random =~1|ProgramLocationID, - na.action = na.omit, - data = lme_data) - # Store information and model fits in appropriate row of data frame - lme_stats$AreaID[i] <- unique(lme_data$AreaID) - lme_stats$ManagedAreaName[i] <- MA_Include[i] - lme_stats$LME_Intercept[i] <- AnyCoral$coefficients$fixed[1] - lme_stats$LME_Slope[i] <- AnyCoral$coefficients$fixed[2] - lme_stats$LME_p[i] <- anova(AnyCoral)$p[2] - - # Clears temporary variables for memory - rm(lme_data) - (AnyCoral) - } - - # Merges LME stats with overall stats to complete stats for each managed area - lme_stats <- merge.data.frame(MA_Ov_Stats[,-c("Programs", "ProgramIDs")], - lme_stats, by=c("AreaID", "ManagedAreaName"), all=TRUE) - - # Puts the data in order based on ManagedAreaName - lme_stats <- as.data.frame(lme_stats[order(lme_stats$ManagedAreaName), ]) - - # Write lme statistics to file - fwrite(lme_stats, paste0(out_dir,"/Coral_", param_file, - "_LME_Stats.txt"), sep="|") - - # Gets lower x and y values based on LME fit to use in plot - lme_plot <- lme_stats %>% - dplyr::group_by(AreaID, ManagedAreaName) %>% - dplyr::summarize(x=EarliestYear, - y=LME_Slope*x+LME_Intercept) - # Gets upper x and y values based on LME fit to use in plot - lme_plot2 <- lme_stats %>% - dplyr::group_by(AreaID, ManagedAreaName) %>% - dplyr::summarize(x=LatestYear, - y=LME_Slope*x+LME_Intercept) - # Merges LME fit values for plot into one data frame - lme_plot <- bind_rows(lme_plot, lme_plot2) - rm(lme_plot2) - # Puts LME plot data fram in alphabetical order by managed area - lme_plot <- as.data.frame(lme_plot[order(lme_plot$ManagedAreaName), ]) - lme_plot <- lme_plot[!is.na(lme_plot$y),] - - # unqiue data filename for later access - data_pc <- data - lme_plot_pc <- lme_plot - MA_Ov_Stats_pc <- MA_Ov_Stats - -} - - -if("SpeciesRichness" %in% params_to_plot){ - - out_dir <- "output/Data/Coral/SpeciesRichness" - param_name <- "SpeciesRichness" - param_file <- "SpeciesRichness" - - # Only keep data for Presence of grazers and reef-dependent species - data <- data2[data2$ParameterName=="Presence - Grazers and Reef Dependent Species"] - - # Create ParameterName Column - data$ParameterName <- "Species Richness" - parameter <- "Species Richness" - title_param <- "Species Richness - Grazers and Reef-Dependent Species" - - # Sets units for species richness - unit <- "# of species" - data$ParameterUnits <- unit - - # Remove rows with missing ManagedAreaName - data <- data[!is.na(data$ManagedAreaName),] - data <- data[data$ManagedAreaName!="NA",] - # Remove rows with missing GenusName - data <- data[!is.na(data$GenusName),] - # Remove rows with missing SpeciesName - data <- data[!is.na(data$SpeciesName),] - # Remove rows with missing Months - data <- data[!is.na(data$Month),] - # Remove rows with missing Years - data <- data[!is.na(data$Year),] - # Remove rows with missing SpeciesGroup1 - data <- data[!is.na(data$SpeciesGroup1),] - # Remove rows with invasive species - data <- data[data$SpeciesGroup1!="Invasive",] - # Set ResultValue to be a number value - data$ResultValue <- as.numeric(data$ResultValue) - # Remove rows where ResultValue is 0 and missing - data <- data[data$ResultValue!=0,] - data <- data[!is.na(data$ResultValue),] - # Remove duplicate rows - data <- data[data$MADup==1,] - # Create variable that combines the genus and species name - data$gensp <- paste(data$GenusName, data$SpeciesName, sep=" ") - # Corrects Managed Area names to be consistent with official names - data$ManagedAreaName[data$ManagedAreaName=="Florida Keys NMS"] <- - "Florida Keys National Marine Sanctuary" - data$ManagedAreaName[data$ManagedAreaName== - "Biscayne Bay-Cape Florida to Monroe County Line"] <- - "Biscayne Bay-Cape Florida to Monroe County Line Aquatic Preserve" - data$ManagedAreaName[data$ManagedAreaName=="Coupon Bight"] <- - "Coupon Bight Aquatic Preserve" - data$ManagedAreaName[data$ManagedAreaName=="Coral ECA"] <- - "Southeast Florida Coral Reef Ecosystem Conservation Area" - - # Create Species Richness values for groups of unique combinations of - # ManagedAreaName, ProgramID, ProgramName, ProgramLocationID, and SampleDate. - data <- data[data$ResultValue==1] %>% - dplyr::group_by(ManagedAreaName, ProgramID, ProgramName, ProgramLocationID, - SampleDate) %>% - dplyr::summarise(ParameterName=parameter, - Year=unique(Year), Month=unique(Month), - SpeciesRichness=length(unique(gensp))) - - # Adds AreaID for each managed area by combining the MA_All datatable to the - # data based on ManagedAreaName - data <- merge.data.frame(MA_All[,c("AreaID", "ManagedAreaName")], - data, by="ManagedAreaName", all=TRUE) - - # Writes this data that is used by the rest of the script to a text file - fwrite(data, paste0(out_dir,"/Coral_", param_file, "_UsedData.txt"), - sep="|") - - # Makes sure SampleDate is being stored as a Date object - data$SampleDate <- as.Date(data$SampleDate) - - # Creates a variable with the names of all the managed areas that contain - # species observations - MA_Include <- unique(data$ManagedAreaName[!is.na(data$SpeciesRichness)]) - - # Puts the managed areas in alphabetical order - MA_Include <- MA_Include[order(MA_Include)] - - coral_sr_MA_Include <- MA_Include - - # Determines the number of managed areas used - n <- length(MA_Include) - - ##################### - ### SUMMARY STATS ### - ##################### - - # Create summary statistics for each managed area based on Year and Month - # intervals. - MA_YM_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName, Year, Month) %>% - dplyr::summarize(ParameterName=parameter, - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName, Year, then Month - MA_YM_Stats <- as.data.table(MA_YM_Stats[order(MA_YM_Stats$ManagedAreaName, - MA_YM_Stats$Year, - MA_YM_Stats$Month), ]) - # Writes summary statistics to file - fwrite(MA_YM_Stats, paste0(out_dir,"/Coral_", param_file, - "_MA_MMYY_Stats.txt"), sep="|") - # Removes variable storing data to improve computer memory - rm(MA_YM_Stats) - - # Create summary statistics for each managed area based on Year intervals - MA_Y_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName, Year) %>% - dplyr::summarize(ParameterName=parameter, - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName then Year - MA_Y_Stats <- as.data.table(MA_Y_Stats[order(MA_Y_Stats$ManagedAreaName, - MA_Y_Stats$Year), ]) - # Writes summary statistics to file - fwrite(MA_Y_Stats, paste0(out_dir,"/Coral_", param_file, - "_MA_Yr_Stats.txt"), sep="|") - - # Create summary statistics for each managed area based on Month intervals. - MA_M_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName, Month) %>% - dplyr::summarize(ParameterName=parameter, - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName then Month - MA_M_Stats <- as.data.table(MA_M_Stats[order(MA_M_Stats$ManagedAreaName, - MA_M_Stats$Month), ]) - # Writes summary statistics to file - fwrite(MA_M_Stats, paste0(out_dir,"/Coral_", param_file, - "_MA_Mo_Stats.txt"), sep="|") - # Removes variable storing data to improve computer memory - rm(MA_M_Stats) - - # Create summary overall statistics for each managed area. - MA_Ov_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName) %>% - dplyr::summarize(ParameterName=parameter, - N_Years=length(unique(na.omit(Year))), - EarliestYear=min(Year), - LatestYear=max(Year), - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName - MA_Ov_Stats <- as.data.table(MA_Ov_Stats[order(MA_Ov_Stats$ManagedAreaName), ]) - # Creates Year_MinRichness and Year_MaxRichness columns - MA_Ov_Stats$Year_MinRichness <- NA - MA_Ov_Stats$Year_MaxRichness <- NA - - # Loops through each ManagedAreaName. - # Determines what year the minimum and maximum species richness occurred - for(m in 1:nrow(MA_Ov_Stats)){ - # Stores ManagedAreaName for this row - man <- MA_Ov_Stats$ManagedAreaName[m] - - # Skips to next row if there are no data for this combination - if(MA_Ov_Stats$N_Data[m]==0){ - next - } - # Gets subset of data from MA_Y_Stats (yearly summary stats) with this - # ManagedAreaName - ds <- MA_Y_Stats[MA_Y_Stats$ManagedAreaName==man,] - # Gets the minimum and maximum Mean (yearly averages) - min <- min(ds$Mean) - max <- max(ds$Mean) - #Determines what years those minimum and maximum values occured - year_min <- ds$Year[ds$Mean==min] - year_max <- ds$Year[ds$Mean==max] - # Stores the occurrence years of the minimum and maximum into the overall - # stats for this row - MA_Ov_Stats$Year_MinRichness[m] <- year_min - MA_Ov_Stats$Year_MaxRichness[m] <- year_max - } - # Replaces blank ProgramIDs with NA (missing values) - MA_Ov_Stats$ProgramIDs <- replace(MA_Ov_Stats$ProgramIDs, - MA_Ov_Stats$ProgramIDs=="", NA) - MA_Ov_Stats$Programs <- replace(MA_Ov_Stats$Programs, - MA_Ov_Stats$Programs=="", NA) - # Write overall statistics to file - fwrite(MA_Ov_Stats, paste0(out_dir,"/Coral_", param_file, - "_MA_Overall_Stats.txt"), sep="|") - # Removes entries from the overall statistics that do not have data. - # Based on presence or absence of EarliestYear - MA_Ov_Stats <- MA_Ov_Stats[!is.na(MA_Ov_Stats$EarliestYear), ] - - MA_Y_Stats_sr <- MA_Y_Stats - MA_Ov_Stats_sr <- MA_Ov_Stats - -} - -###################### -### START PLOTTING ### -###################### - -plot_theme <- theme_bw() + - theme(panel.grid.major = element_blank(), - panel.grid.minor = element_blank(), - text=element_text(family="Arial"), - plot.title=element_text(hjust=0.5, size=12, color="#314963"), - plot.subtitle=element_text(hjust=0.5, size=10, color="#314963"), - legend.title=element_text(size=10), - legend.text.align = 0, - axis.title.x = element_text(size=10, margin = margin(t = 5, r = 0, - b = 10, l = 0)), - axis.title.y = element_text(size=10, margin = margin(t = 0, r = 10, - b = 0, l = 0)), - axis.text=element_text(size=10), - axis.text.x=element_text(angle = -45, hjust = 0)) - -# Create jitter object that sets the height and width -# Sets seed to be reproducible -plot_jitter <- position_jitter(width = 0.2, height = 0.2, seed=seed) -# Color palette for SEACAR -color_palette <- c("#005396", "#0088B1", "#00ADAE", "#65CCB3", "#AEE4C1", - "#FDEBA8", "#F8CD6D", "#F5A800", "#F17B00") - -########################## -### PLOTTING FUNCTIONS ### -########################## - -plot_coral_pc <- function(ma, data = "data_pc", lme_plot = "lme_plot_pc", MA_Ov_Stats = "MA_Ov_Stats_pc"){ - # Gets data for target managed area - plot_data <- data[data$ManagedAreaName==ma,] - - lme_plot_data <- lme_plot[lme_plot$ManagedAreaName==ma,] - # Determines most recent year with available data for managed area - t_max <- max(MA_Ov_Stats$LatestYear[MA_Ov_Stats$ManagedAreaName== - ma]) - # Determines earliest recent year with available data for managed area - t_min <- min(MA_Ov_Stats$EarliestYear[MA_Ov_Stats$ManagedAreaName== - ma]) - # Determines how many years of data are present - t <- t_max-t_min - - # Creates break intervals for plots based on number of years of data - if(t>=30){ - # Set breaks to every 10 years if more than 30 years of data - brk <- -10 - }else if(t<30 & t>=10){ - # Set breaks to every 5 years if between 30 and 10 years of data - brk <- -5 - }else if(t<10 & t>=4){ - # Set breaks to every 2 years if between 10 and 4 years of data - brk <- -2 - }else if(t<4 & t>=2){ - # Set breaks to every year if between 4 and 2 years of data - brk <- -1 - }else if(t<2){ - # Set breaks to every year if less than 2 years of data - brk <- -1 - # Sets t_max to be 1 year greater and t_min to be 1 year lower - # Forces graph to have at least 3 tick marks - t_max <- t_max+1 - t_min <- t_min-1 - } - # Determine range of data values for the managed area - y_range <- max(plot_data$ResultValue) - min(plot_data$ResultValue) - - # Sets y_min to be -1 - y_min <- -1 - - # Sets upper bound of y-axis to be 10% of the data range above the - # maximum value. - y_max <- max(plot_data$ResultValue)+(0.1*y_range) - - - # Creates plot object using plot_data. - # Data is plotted as a point pot with jitter to show concentrations - # that overlap. LME fit is plotted as a line - p1 <- ggplot(data=plot_data) + - geom_point(aes(x=Year, y=ResultValue), - position=plot_jitter, shape=21, size=2, - color="#333333", fill="#cccccc", alpha=1) + - geom_line(data=lme_plot_data, aes(x=x, y=y), - color="#000099", size=2, alpha=0.8) + - labs(title="Coral Percent Cover", - subtitle=ma, - x="Year", y="Percent cover (%)") + - scale_x_continuous(limits=c(t_min-0.25, t_max+0.25), - breaks=seq(t_max, t_min, brk)) + - scale_y_continuous(limits=c(y_min, y_max), - breaks=pretty_breaks(n=5)) + - plot_theme - # Sets file name of plot created - outname <- paste0("Coral_", param_file, "_", gsub(" ", "", ma), - ".png") - # # Saves plot as a png image - # png(paste0(out_dir, "/Figures/", outname), - # width = 8, - # height = 4, - # units = "in", - # res = 200) - # print(p1) - # dev.off() - - # Creates a data table object to be shown underneath plots in report - ResultTable <- - lme_stats[lme_stats$ManagedAreaName==ma,] - # Removes location, and parameter information because it is in plot - # labels - ResultTable <- select(ResultTable, -c("AreaID", "ManagedAreaName", - "ParameterName")) - # Renames StandardDeviation to StDev to save horizontal space - ResultTable <- ResultTable %>% - dplyr::rename("StDev"="StandardDeviation") - # Converts all non-integer values to 2 decimal places for space - ResultTable$Min <- round(ResultTable$Min, digits=2) - ResultTable$Max <- round(ResultTable$Max, digits=2) - ResultTable$Median <- round(ResultTable$Median, digits=2) - ResultTable$Mean <- round(ResultTable$Mean, digits=2) - ResultTable$StDev <- round(ResultTable$StDev, digits=2) - ResultTable$LME_Intercept <- round(ResultTable$LME_Intercept, digits=2) - ResultTable$LME_Slope <- round(ResultTable$LME_Slope, digits=2) - ResultTable$LME_p <- round(ResultTable$LME_p, digits=4) - # Stores as plot table object - t1 <- ggtexttable(ResultTable, rows = NULL, - theme=ttheme(base_size=7)) %>% - tab_add_footnote(text="LME_p < 0.00005 appear as 0 due to rounding.", - size=10, face="italic") - # Combines plot and table into one figure - print(ggarrange(p1, t1, ncol=1, heights=c(0.85, 0.15))) - - # Add extra space at the end to prevent the next figure from being too - # close. Does not add space after last plot - if(i!=n){ - cat("\n \n \n \n") - } -} - -plot_coral_sr <- function(ma, MA_Y_Stats = "MA_Y_Stats_sr", MA_Ov_Stats = "MA_Ov_Stats_sr"){ - # Gets data for target managed area - plot_data <- MA_Y_Stats[MA_Y_Stats$ManagedAreaName==ma] - # Determines most recent year with available data for managed area - t_max <- max(MA_Ov_Stats$LatestYear[MA_Ov_Stats$ManagedAreaName== - ma]) - # Determines earliest recent year with available data for managed area - t_min <- min(MA_Ov_Stats$EarliestYear[MA_Ov_Stats$ManagedAreaName== - ma]) - # Determines how many years of data are present - t <- t_max-t_min - - # Creates break intervals for plots based on number of years of data - if(t>=30){ - # Set breaks to every 10 years if more than 30 years of data - brk <- -10 - }else if(t<30 & t>=10){ - # Set breaks to every 5 years if between 30 and 10 years of data - brk <- -5 - }else if(t<10 & t>=4){ - # Set breaks to every 2 years if between 10 and 4 years of data - brk <- -2 - }else if(t<4 & t>=2){ - # Set breaks to every year if between 4 and 2 years of data - brk <- -1 - }else if(t<2){ - # Set breaks to every year if less than 2 years of data - brk <- -1 - # Sets t_max to be 1 year greater and t_min to be 1 year lower - # Forces graph to have at least 3 tick marks - t_max <- t_max+1 - t_min <- t_min-1 - } - # Determine range of data values for the managed area - y_range <- max(plot_data$Mean) - min(plot_data$Mean) - - # Determines lower bound of y-axis based on data range. Set based on - # relation of data range to minimum value. Designed to set lower boundary - # to be 10% of the data range below the minimum value - y_min <- if(min(plot_data$Mean)-(0.1*y_range)<0){ - # If 10% of the data range below the minimum value is less than 0, - # set as 0 - y_min <- 0 - } else { - # Otherwise set minimum bound as 10% data range below minimum value - y_min <- min(plot_data$Mean)-(0.1*y_range) - } - - # Sets upper bound of y-axis to be 10% of the data range above the - # maximum value. - y_max <- max(plot_data$Mean)+(0.1*y_range) - - - # Creates plot object using plot_data. - # Data is plotted as symbols with connected lines. - p1 <- ggplot(data=plot_data) + - geom_line(aes(x=Year, y=Mean), color=color_palette[1], - size=0.75, alpha=1) + - geom_point(aes(x=Year, y=Mean), fill=color_palette[1], - shape=21, size=2, color="#333333", alpha=1) + - labs(title="Grazers and Reef-Dependent Species Richness", - subtitle=ma, - x="Year", y="Richness (# of species)") + - scale_x_continuous(limits=c(t_min-0.25, t_max+0.25), - breaks=seq(t_max, t_min, brk)) + - scale_y_continuous(limits=c(y_min, y_max), - breaks=pretty_breaks(n=5)) + - plot_theme - # Sets file name of plot created - outname <- paste0("Coral_", param_file, "_", gsub(" ", "", ma), - ".png") - # Saves plot as a png image - # png(paste0(out_dir, "/Figures/", outname), - # width = 8, - # height = 4, - # units = "in", - # res = 200) - # print(p1) - # dev.off() - - # Creates a data table object to be shown underneath plots in report - ResultTable <- - MA_Ov_Stats[MA_Ov_Stats$ManagedAreaName==ma,] - # Removes location, and parameter information because it is in plot - # labels - ResultTable <- ResultTable[,-c("AreaID", "ManagedAreaName", - "ProgramIDs", "Programs", "ParameterName")] - # Renames StandardDeviation to StDev to save horizontal space - ResultTable <- ResultTable %>% - dplyr::rename("StDev"="StandardDeviation") - # Converts all non-integer values to 2 decimal places for space - ResultTable$Min <- round(ResultTable$Min, digits=2) - ResultTable$Max <- round(ResultTable$Max, digits=2) - ResultTable$Median <- round(ResultTable$Median, digits=2) - ResultTable$Mean <- round(ResultTable$Mean, digits=2) - ResultTable$StDev <- round(ResultTable$StDev, digits=2) - # Stores as plot table object - t1 <- ggtexttable(ResultTable, rows = NULL, - theme=ttheme(base_size=7)) - # Combines plot and table into one figure - print(ggarrange(p1, t1, ncol=1, heights=c(0.85, 0.15))) - - # Add extra space at the end to prevent the next figure from being too - # close. Does not add space after last plot - if(i!=n){ - cat("\n \n \n \n") - } -} - -coral_managed_areas <- unique(c(coral_pc_MA_Include, coral_sr_MA_Include)) \ No newline at end of file diff --git a/MA Report Generation/Nekton.R b/MA Report Generation/Nekton.R deleted file mode 100644 index df405d0d..00000000 --- a/MA Report Generation/Nekton.R +++ /dev/null @@ -1,380 +0,0 @@ -library(knitr) -library(data.table) -library(dplyr) -library(lubridate) -library(ggplot2) -library(scales) -library(tidyr) -library(gridExtra) -library(ggpubr) -library(scales) - -#This script is designed to only determine species richness from the Nekton presence data -param_name <- "Presence" - -#Sets abbreviation or label to be used in file names -param_file <- "SpeciesRichness" - -# output path for data files -nek_data_out <- "output/Data/Nekton" - -#Import data from nekton file -data <- fread(nekton_file_in, sep="|", header=TRUE, stringsAsFactors=FALSE, - na.strings=c("NULL","","NA")) - -################# -### FILTERING ### -################# - -# Filter data for the desired parameter -data <- data[data$ParameterName==param_name, ] - -if (param_name=="Presence"){ - parameter <- "Species Richness" -} -# Makes sure EffortCorrection is numeric value -data$EffortCorrection_100m2 <- as.numeric(data$EffortCorrection_100m2) - -# Remove any data with missing EffortCorrection values -data <- data[!is.na(data$EffortCorrection_100m2),] - -# Only keep data that has non-zero EffortCorrection values -data <- data[data$EffortCorrection_100m2!=0,] - -# Remove any data with missing ResultValue entries -data <- data[!is.na(data$ResultValue),] - -# Create Species Richness values for groups of unique combinations of -# ManagedAreaName, ProgramID, ProgramName, ProgramLocationID, SampleDate, -# GearType, and GearSize_m. -data <- data %>% - group_by(ManagedAreaName, ProgramID, ProgramName, ProgramLocationID, - SampleDate, GearType, GearSize_m) %>% - dplyr::summarize(ParameterName=parameter, - Year=unique(Year), Month=unique(Month), - N_Species=sum(ResultValue), - EffortCorrection_100m2=as.numeric(unique(EffortCorrection_100m2)), - SpeciesRichness=N_Species/unique(EffortCorrection_100m2)) - -# Adds AreaID for each managed area by combining the MA_All datatable to the -# data based on ManagedAreaName -data <- merge.data.frame(MA_All[,c("AreaID", "ManagedAreaName")], - data, by="ManagedAreaName", all=TRUE) - -# Writes this data that is used by the rest of the script to a text file -fwrite(data, paste0(nek_data_out,"/Nekton_", param_file, "_UsedData.txt"), sep="|") - -# Makes sure SampleDate is being stored as a Date object -data$SampleDate <- as.Date(data$SampleDate) - -# Creates a variable with the names of all the managed areas that contain -# species observations -MA_Include <- unique(data$ManagedAreaName[!is.na(data$N_Species)]) - -# Puts the managed areas in alphabetical order -MA_Include <- MA_Include[order(MA_Include)] - -# Determines the number of managed areas used -n <- length(MA_Include) - -################## -#### MA STATS #### -################## - -# Create summary statistics for each managed area based on Year and Month -# intervals, and each gear type and size. -MA_YM_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName, Year, Month, GearType, GearSize_m) %>% - dplyr::summarize(ParameterName=parameter, - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) -# Puts the data in order based on ManagedAreaName, Year, Month, then GearSize -MA_YM_Stats <- as.data.table(MA_YM_Stats[order(MA_YM_Stats$ManagedAreaName, - MA_YM_Stats$Year, - MA_YM_Stats$Month, - MA_YM_Stats$GearSize_m), ]) -# Writes summary statistics to file -fwrite(MA_YM_Stats, paste0(nek_data_out,"/Nekton_", param_file, - "_MA_MMYY_Stats.txt"), sep="|") -# Removes variable storing data to improve computer memory -rm(MA_YM_Stats) - -# Create summary statistics for each managed area based on Year intervals, -# and each gear type and size. -MA_Y_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName, Year, GearType, GearSize_m) %>% - dplyr::summarize(ParameterName=parameter, - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) -# Puts the data in order based on ManagedAreaName, Year, then GearSize -MA_Y_Stats <- as.data.table(MA_Y_Stats[order(MA_Y_Stats$ManagedAreaName, - MA_Y_Stats$Year, - MA_Y_Stats$GearSize_m), ]) - -MA_Y_Stats <- na.omit(MA_Y_Stats) - -nekton_managed_areas <- unique(MA_Y_Stats$ManagedAreaName) - -# Writes summary statistics to file -fwrite(MA_Y_Stats, paste0(nek_data_out,"/Nekton_", param_file, - "_MA_Yr_Stats.txt"), sep="|") - -MA_Y_Stats_nek <- MA_Y_Stats - - -# Create summary statistics for each managed area based on Month intervals, -# and each gear type and size. -MA_M_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName, Month, GearType, GearSize_m) %>% - dplyr::summarize(ParameterName=parameter, - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) -# Puts the data in order based on ManagedAreaName, Month, then GearSize -MA_M_Stats <- as.data.table(MA_M_Stats[order(MA_M_Stats$ManagedAreaName, - MA_M_Stats$Month, - MA_M_Stats$GearSize_m), ]) -# Writes summary statistics to file -fwrite(MA_M_Stats, paste0(nek_data_out,"/Nekton_", param_file, - "_MA_Mo_Stats.txt"), sep="|") -# Removes variable storing data to improve computer memory -rm(MA_M_Stats) - -# Create summary overall statistics for each managed area based each gear type -# and size. -MA_Ov_Stats <- data %>% - dplyr::group_by(AreaID, ManagedAreaName, GearType, GearSize_m) %>% - dplyr::summarize(ParameterName=parameter, - N_Years=length(unique(na.omit(Year))), - EarliestYear=min(Year), - LatestYear=max(Year), - N_Data=length(na.omit(SpeciesRichness)), - Min=min(SpeciesRichness), - Max=max(SpeciesRichness), - Median=median(SpeciesRichness), - Mean=mean(SpeciesRichness), - StandardDeviation=sd(SpeciesRichness), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) -# Puts the data in order based on ManagedAreaName then GearSize -MA_Ov_Stats <- as.data.table(MA_Ov_Stats[order(MA_Ov_Stats$ManagedAreaName, - MA_Ov_Stats$GearSize_m), ]) - -MA_Ov_Stats <- na.omit(MA_Ov_Stats) -# Creates Year_MinRichness and Year_MaxRichness columns -MA_Ov_Stats$Year_MinRichness <- NA -MA_Ov_Stats$Year_MaxRichness <- NA - -# Loops through each ManagedAreaName, GearType, and GearSize_m. -# determines what year the minimum and maximum species richness occurred -for(m in 1:nrow(MA_Ov_Stats)){ - # Stores ManagedAreaName, GearType, and GearSize_m for this row - man <- MA_Ov_Stats$ManagedAreaName[m] - gear <- MA_Ov_Stats$GearType[m] - size <- MA_Ov_Stats$GearSize_m[m] - # Skips to next row if there are no data for this combination - if(MA_Ov_Stats$N_Data[m]==0){ - next - } - # Gets subset of data from MA_Y_Stats (yearly summary stats) with this - # combination of ManagedAreaName, GearType, and GearSize_m - ds <- MA_Y_Stats[MA_Y_Stats$ManagedAreaName==man & - MA_Y_Stats$GearType==gear & - MA_Y_Stats$GearSize_m==size,] - # Gets the minimum and maximum Mean (yearly averages) - min <- min(ds$Mean) - max <- max(ds$Mean) - #Determines what years those minimum and maximum values occured - year_min <- ds$Year[ds$Mean==min] - year_max <- ds$Year[ds$Mean==max] - # Stores the occurrence years of the minimum and maximum into the overall - # stats for this row - MA_Ov_Stats$Year_MinRichness[m] <- year_min - MA_Ov_Stats$Year_MaxRichness[m] <- year_max -} -# Replaces blank ProgramIDs with NA (missing values) -MA_Ov_Stats$ProgramIDs <- replace(MA_Ov_Stats$ProgramIDs, - MA_Ov_Stats$ProgramIDs=="", NA) -MA_Ov_Stats$Programs <- replace(MA_Ov_Stats$Programs, - MA_Ov_Stats$Programs=="", NA) -# Write overall statistics to file -fwrite(MA_Ov_Stats, paste0(nek_data_out,"/Nekton_", param_file, - "_MA_Overall_Stats.txt"), sep="|") -# Removes entries from the overall statistics that do not have data. -# Based on presence or absence of EarliestYear -MA_Ov_Stats <- MA_Ov_Stats[!is.na(MA_Ov_Stats$EarliestYear), ] - -MA_Ov_Stats_nek <- MA_Ov_Stats - -# Defines standard plot theme: black and white, no major or minor grid lines, -# Arial font. Title is centered, size 12, and blue (hex coded). Subtitle is -# centered, size 10, and blue (hex coded). Legend title is size 10 and the -# legend is left-justified. X-axis title is size 10 and the margins are padded -# at the top and bottom to give more space for angled axis labels. Y-axis title -# is size 10 and margins are padded on the right side to give more space for -# axis labels. Axis labels are size 10 and the x-axis labels are rotated -45 -# degrees with a horizontal justification that aligns them with the tick mark -plot_theme <- theme_bw() + - theme(panel.grid.major = element_blank(), - panel.grid.minor = element_blank(), - text=element_text(family="Arial"), - plot.title=element_text(hjust=0.5, size=12, color="#314963"), - plot.subtitle=element_text(hjust=0.5, size=10, color="#314963"), - legend.title=element_text(size=10), - legend.text.align = 0, - axis.title.x = element_text(size=10, margin = margin(t = 5, r = 0, - b = 10, l = 0)), - axis.title.y = element_text(size=10, margin = margin(t = 0, r = 10, - b = 0, l = 0)), - axis.text=element_text(size=10), - axis.text.x=element_text(angle = -45, hjust = 0)) - -# Color palette for SEACAR -color_palette <- c("#005396", "#0088B1", "#00ADAE", "#65CCB3", "#AEE4C1", "#FDEBA8", "#F8CD6D", "#F5A800", "#F17B00") - -# Defines and sets variable with standardized gear colors for plots -gear_colors <- c("Trawl (4.8 m)"=color_palette[1], - "Trawl (6.1 m)"=color_palette[2], - "Seine (183 m)"=color_palette[3]) - -# Defines and sets variable with standardized gear shapes for plots -gear_shapes <- c("Trawl (4.8 m)"=21, - "Trawl (6.1 m)"=22, - "Seine (183 m)"=24) - -plot_nekton <- function(ma, MA_Y_Stats = "MA_Y_Stats_nek", MA_Ov_Stats = "MA_Ov_Stats_nek"){ - # Gets data for target managed area - plot_data <- MA_Y_Stats[MA_Y_Stats$ManagedAreaName==ma] - - if(nrow(plot_data) > 0){ - # Gets the gear type(s) present for the managed area. - # Combine type and size into one label for plots - plot_data$GearType_Plot <- paste0(plot_data$GearType, " (", - plot_data$GearSize_m, " m)") - # Determines most recent year with available data for managed area - t_max <- max(MA_Ov_Stats$LatestYear[MA_Ov_Stats$ManagedAreaName== - ma]) - # Determines earliest recent year with available data for managed area - t_min <- min(MA_Ov_Stats$EarliestYear[MA_Ov_Stats$ManagedAreaName== - ma]) - # Determines how many years of data are present - t <- t_max-t_min - - # Creates break intervals for plots based on number of years of data - if(t>=30){ - # Set breaks to every 10 years if more than 30 years of data - brk <- -10 - }else if(t<30 & t>=10){ - # Set breaks to every 5 years if between 30 and 10 years of data - brk <- -5 - }else if(t<10 & t>=4){ - # Set breaks to every 2 years if between 10 and 4 years of data - brk <- -2 - }else if(t<4 & t>=2){ - # Set breaks to every year if between 4 and 2 years of data - brk <- -1 - }else if(t<2){ - # Set breaks to every year if less than 2 years of data - brk <- -1 - # Sets t_max to be 1 year greater and t_min to be 1 year lower - # Forces graph to have at least 3 tick marks - t_max <- t_max+1 - t_min <- t_min-1 - } - # Determine range of data values for the managed area - y_range <- max(plot_data$Mean) - min(plot_data$Mean) - - # Determines lower bound of y-axis based on data range. Set based on - # relation of data range to minimum value. Designed to set lower boundary - # to be 10% of the data range below the minimum value - y_min <- if(min(plot_data$Mean)-(0.1*y_range)<0){ - # If 10% of the data range below the minimum value is less than 0, - # set as 0 - y_min <- 0 - } else { - # Otherwise set minimum bound as 10% data range below minimum value - y_min <- min(plot_data$Mean)-(0.1*y_range) - } - - # Sets upper bound of y-axis to be 10% of the data range above the - # maximum value. - y_max <- max(plot_data$Mean)+(0.1*y_range) - - # Determines what combination of gear are present for managed area - # and subsets color and shape scheme to be used by plots. - # Used so only gear combinations present for managed area appear in - # the legend. - gear_colors_plot <- gear_colors[unique(plot_data$GearType_Plot)] - gear_shapes_plot <- gear_shapes[unique(plot_data$GearType_Plot)] - - # Creates plot object using plot_data and grouping by the plot gear types. - # Data is plotted as symbols with connected lines. - p1 <- ggplot(data=plot_data, group=as.factor(GearType_Plot)) + - geom_line(aes(x=Year, y=Mean, color=as.factor(GearType_Plot)), - size=0.75, alpha=1) + - geom_point(aes(x=Year, y=Mean, fill=as.factor(GearType_Plot), - shape=as.factor(GearType_Plot)), size=2, - color="#333333", alpha=1) + - labs(title="Nekton Species Richness", - subtitle=ma, - x="Year", y=bquote('Richness (species/100'*~m^{2}*')'), - fill="Gear type", color="Gear type", shape="Gear type") + - scale_x_continuous(limits=c(t_min-0.25, t_max+0.25), - breaks=seq(t_max, t_min, brk)) + - scale_y_continuous(limits=c(y_min, y_max), - breaks=pretty_breaks(n=5)) + - scale_fill_manual(values=gear_colors_plot) + - scale_color_manual(values=gear_colors_plot) + - scale_shape_manual(values=gear_shapes_plot) + - plot_theme - - # Creates a data table object to be shown underneath plots in report - ResultTable <- MA_Ov_Stats[MA_Ov_Stats$ManagedAreaName==ma,] - - # Removes location, gear, and parameter information because it is in plot - # labels - ResultTable <- ResultTable[,-c("AreaID", "ManagedAreaName", - "ProgramIDs", "Programs", "GearType_Plot", - "ParameterName")] - # Renames StandardDeviation to StDev to save horizontal space - ResultTable <- ResultTable %>% - dplyr::rename("StDev"="StandardDeviation") - # Converts all non-integer values to 2 decimal places for space - ResultTable$Min <- round(ResultTable$Min, digits=2) - ResultTable$Max <- round(ResultTable$Max, digits=2) - ResultTable$Median <- round(ResultTable$Median, digits=2) - ResultTable$Mean <- round(ResultTable$Mean, digits=2) - ResultTable$StDev <- round(ResultTable$StDev, digits=2) - # Stores as plot table object - t1 <- ggtexttable(ResultTable, rows = NULL, - theme=ttheme(base_size=7)) - # Combines plot and table into one figure - combined_fig <- ggarrange(p1, t1, ncol=1, heights=c(0.85, 0.15)) - print(combined_fig) - } -} \ No newline at end of file diff --git a/MA Report Generation/ReportRender.R b/MA Report Generation/ReportRender.R index cac175e7..cc0e4b5d 100644 --- a/MA Report Generation/ReportRender.R +++ b/MA Report Generation/ReportRender.R @@ -48,7 +48,7 @@ MA_All <- fread("data/ManagedArea.csv", sep = ",", header = TRUE, stringsAsFacto #Imports SEACAR data file path information as variable "seacar_data_location" source("scripts/SEACAR_data_location.R") -files <- list.files(seacar_data_location, full=TRUE) +files <- list.files(seacar_data_location, full.names=TRUE) hab_files <- str_subset(files, "All_") cw_file_in <- str_subset(hab_files, "CW") @@ -85,6 +85,9 @@ source("scripts/SAV-Functions.R") source("scripts/Coral.R") ############################ +seacar_palette <- c("#005396", "#0088B1", "#00ADAE", "#65CCB3", "#AEE4C1", + "#FDEBA8", "#F8CD6D", "#F5A800", "#F17B00") + ################ ## file names ## # Pulls file names from discrete and cont. file list .txt rendered during .RDS object creation diff --git a/MA Report Generation/SAV-Functions.R b/MA Report Generation/SAV-Functions.R deleted file mode 100644 index 2d6f43c1..00000000 --- a/MA Report Generation/SAV-Functions.R +++ /dev/null @@ -1,115 +0,0 @@ -library(mgcv) - -############################## -### SAV PLOTTING FUNCTIONS ### -############################## - -#Managed areas that should have Halophila species combined: -ma_halspp <- c("Banana River", "Indian River-Malabar to Vero Beach", "Indian River-Vero Beach to Ft. Pierce", "Jensen Beach to Jupiter Inlet", - "Loxahatchee River-Lake Worth Creek", "Mosquito Lagoon", "Biscayne Bay", "Florida Keys NMS") - -files <- list.files(here::here("output/Figures/BB/")) #get file list -trendplots <- stringr::str_subset(files, "_trendplot") #identify map file -trendplots <- stringr::str_subset(trendplots, "_BBpct_") - -mods <- list.files(here::here("output/models/")) -models2 <- str_subset(mods, paste0(str_sub(trendplots[1], 1, str_locate_all(trendplots[1], "_")[[1]][2]))) - -malist <- c() -for(pl in trendplots){ - ma_p <- str_split(pl, "_")[[1]][3] - malist <- append(malist, ma_p) -} - -failedmodslist <- readRDS(here::here("output/models/failedmodslist.rds")) - -find_exact_matches <- function(pattern, filenames) { - regex <- paste0("(_|^)", pattern, "(_|$)") - matched_files <- str_subset(filenames, regex) - return(matched_files) -} - -plot_sav_trendplot <- function(ma_abrev){ - if(ma_abrev %in% malist){ - plot_file <- lapply(ma_abrev, find_exact_matches, filenames = trendplots) - plot <- readRDS(here::here(paste0("output/Figures/BB/", plot_file))) - print(plot) - } -} - -barplots <- stringr::str_subset(files, "_barplot") #identify map file - -malist2 <- c() -for(pl in barplots){ - ma_p <- str_split(pl, "_")[[1]][3] - malist2 <- append(malist2, ma_p) -} - - -plot_sav_barplot <- function(ma_abrev){ - if(ma_abrev %in% malist2){ - plot_file <- lapply(ma_abrev, find_exact_matches, filenames = barplots) - plot <- readRDS(here::here(paste0("output/Figures/BB/", plot_file))) - print(plot) - } -} - -sav_managed_areas <- unique(c(malist, malist2)) - -# GAM prediction function -get_gam_preds <- function(model, new_data){ - pred <- predict(model, newdata=new_data, type="link", se.fit=TRUE) - upper_bound <- pred$fit + (1.96 * pred$se.fit) - lower_bound <- pred$fit - (1.96 * pred$se.fit) - return(list(fit=pred$fit, upper=upper_bound, lower=lower_bound)) -} - -# Plot GAM function -plot_sav_gam <- function(ma_short){ - - ma_data <- SAV4 %>% filter(ManagedAreaName==ma_short) - - if(i %in% ma_halspp){ - species <- unique(ma_data$analysisunit) - au_col <- "analysisunit" - } else { - species <- unique(ma_data$analysisunit_halid) - au_col <- "analysisunit_halid" - } - - gam_models <- list() - - for (s in species){ - ma_data_species <- ma_data %>% filter(!!sym(au_col) == s) - gam_model <- gam(BB_pct ~ s(relyear), data = ma_data_species, family = gaussian()) - gam_models[[s]] <- gam_model - } - - xlims <- range(ma_data$relyear, na.rm = TRUE) - ylims <- range(ma_data$BB_pct, na.rm = TRUE) - - plot(NULL, xlim=xlims, ylim=ylims, xlab = "Year", ylab = "BB_pct", type = "n") - colors <- rainbow(length(species)) - - sp_to_skip <- c("Drift algae", "Total seagrass", "Attached algae") - inc_sp <- list() - - for (i in 1:length(species)){ - sp <- species[i] - time_range <- seq(min(ma_data$relyear, na.rm = TRUE), max(ma_data$relyear, na.rm = TRUE), length.out = 100) - - if(sp %in% sp_to_skip) { - next - } else { - preds <- get_gam_preds(gam_models[[sp]], data.frame(relyear = time_range)) - - lines(time_range, preds$fit, col=colors[i], lty=i) - - polygon(c(time_range, rev(time_range)), c(preds$lower, rev(preds$upper)), col=alpha(colors[i], 0.2), border=NA) - - inc_sp <- c(inc_sp, sp) - } - } - - legend("topright", legend=inc_sp, col=colors, lty=1:length(inc_sp)) -} diff --git a/MA Report Generation/SAV.R b/MA Report Generation/SAV.R deleted file mode 100644 index 29fecfcf..00000000 --- a/MA Report Generation/SAV.R +++ /dev/null @@ -1,818 +0,0 @@ -# Script to load SAV data for reports -library(brms) -library(broom.mixed) -library(tidybayes) -library(bayesplot) -library(sf) -library(gtable) -library(grid) -library(gridExtra) -library(tictoc) -library(nlme) -library(colorspace) -library(here) -library(patchwork) -library(extrafont) -library(magick) -library(dplyr) - -SAV <- fread(sav_file_in, sep = "|", header = TRUE, stringsAsFactors = FALSE, - na.strings=c("NULL","","NA")) -SAV <- SAV[!is.na(ResultValue), ] - -# Create data columns based on old parameter results to make script run -SAV$BB <- NA -SAV$mBB <- NA -SAV$PC <- NA -SAV$PO <- NA -SAV$SC <- NA -SAV$PA <- NA - -# Fill created columns with values based on parameter names -SAV$BB[SAV$ParameterName=="Braun Blanquet Score"] <- - SAV$ResultValue[SAV$ParameterName=="Braun Blanquet Score"] - -SAV$mBB[SAV$ParameterName=="Modified Braun Blanquet Score"] <- - SAV$ResultValue[SAV$ParameterName=="Modified Braun Blanquet Score"] - -SAV$PC[SAV$ParameterName=="Percent Cover"] <- - SAV$ResultValue[SAV$ParameterName=="Percent Cover"] - -SAV$PO[SAV$ParameterName=="Percent Occurrence"] <- - SAV$ResultValue[SAV$ParameterName=="Percent Occurrence"] - -SAV$SC[SAV$ParameterName=="Shoot Count"] <- - SAV$ResultValue[SAV$ParameterName=="Shoot Count"] - -SAV$PA[SAV$ParameterName=="Presence/Absence"] <- - SAV$ResultValue[SAV$ParameterName=="Presence/Absence"] - -#Rename "Total_SAV" to "Total SAV" -SAV$CommonIdentifier[SAV$CommonIdentifier=="Total_SAV"] <- "Total SAV" - -# Create a list of n years available for each managed area -SAV_sum <- SAV %>% group_by(ManagedAreaName) %>% summarize(n_yr = length(unique(Year)), yrs = list(sort(unique(Year)))) - -# Filtering and subsetting -SAV2 <- subset(SAV, !is.na(SAV$BB) | !is.na(SAV$mBB) | !is.na(SAV$PC) | !is.na(SAV$PO)) -SAV2 <- SAV2 %>% filter(BB >= 0 & BB <= 5 | is.na(BB)) -SAV2 <- SAV2 %>% filter(mBB >= 0 & mBB <= 5 | is.na(mBB)) -SAV2 <- SAV2 %>% filter(PC >= 0 & PC <= 100 | is.na(PC)) -SAV2 <- SAV2 %>% filter(PO >= 0 & PO <= 100 | is.na(PO)) -SAV2 <- SAV2 %>% filter(Month %in% c(4:10)) -setDT(SAV2) - -SAV2[!is.na(BB), BB_all := fcase(BB == 0, 0, - BB > 0 & BB <= 1, 1, - BB > 1, round(BB))] -SAV2[!is.na(mBB), BB_all := fcase(mBB == 0, 0, - mBB > 0 & mBB <= 1, 1, - mBB > 1, round(mBB))] -SAV2[!is.na(PC), BB_all := fcase(PC == 0, 0, - PC > 0 & PC <= (2.5 + (15-2.5)/2), 1, - PC <= (2.5 + (15-2.5) + (37.5-15)/2), 2, - PC <= (2.5 + (15-2.5) + (37.5-15) + (62.5 - 37.5)/2), 3, - PC <= (2.5 + (15-2.5) + (37.5-15) + (62.5 - 37.5) + (87.5 - 62.5)/2), 4, - PC > (2.5 + (15-2.5) + (37.5-15) + (62.5 - 37.5) + (87.5 - 62.5)/2), 5)] - - -#Replaces two blocks of code above by using the BB_all variable to create all estimates at once. -SAV2[!is.na(BB_all), BB_pct := fcase(BB_all == 0, 0, - BB_all > 0 & BB_all <= 0.1, rescale(BB_all, from=c(0, 0.1), to=c(0,0.02)), #Added by SRD 8/31/2021 - BB_all > 0.1 & BB_all <= 0.5, rescale(BB_all, from=c(0.1, 0.5), to=c(0.02,0.1)), - BB_all > 0.5 & BB_all <= 1, rescale(BB_all, from=c(0.5,1), to=c(0.1,2.5)), - BB_all > 1 & BB_all <= 2, rescale(BB_all, from=c(1,2), to=c(2.5,15)), - BB_all > 2 & BB_all <= 3, rescale(BB_all, from=c(2,3), to=c(15,37.5)), - BB_all > 3 & BB_all <= 4, rescale(BB_all, from=c(3,4), to=c(37.5,62.5)), - BB_all > 4 & BB_all <= 5, rescale(BB_all, from=c(4,5), to=c(62.5,87.5)))] - -SAV2[, BB_pct := as.numeric(BB_pct)] -SAV2[, BB_all := as.ordered(BB_all)] -SAV2[!is.na(PO), method := "Percent Occurrence"] -SAV2[!is.na(BB), method := "Braun Blanquet"] -SAV2[!is.na(mBB), method := "Modified Braun Blanquet"] -SAV2[!is.na(PC), method := "Percent Cover"] - -SAV2[!is.na(BB_all), PA := ifelse(BB_all == 0, 0, 1)] -SAV2[!is.na(PO), PA := ifelse(PO == 0, 0, 1)] - -SAV2[, relyear := Year - min(Year)] - -SAV3 <- SAV2 %>% filter(SpeciesGroup1 == "Seagrass" | SpeciesGroup1 == "Macroalgae") - -#Temporary fix to programs 570 and 571 - Group 1 should be "Total seagrass" instead of "Total SAV" -SAV3[ProgramID %in% c(570, 571) & CommonIdentifier == "Total SAV", CommonIdentifier := "Total seagrass"] - -#Temporary fix to cases where analysisunit is NA but CommonIdentifier is "Drift Algae" (and Drift_Attached is also NA); ~6,000 records -SAV3[CommonIdentifier == "Drift algae", Drift_Attached := "Drift"] - -species_reject <- c("All", "NA", - "Vallisneria americana", "Najas guadalupensis", - "Hydrilla verticillata", "Potamogeton pusillus", - "Zannichellia palustris") -SAV3[, `:=` (analysisunit_halid = ifelse(CommonIdentifier %in% species_reject, NA, - ifelse(str_detect(CommonIdentifier, "Halophila") & is.na(SpeciesName), "Unidentified Halophila", - ifelse(SpeciesGroup1 == "Seagrass", CommonIdentifier, Drift_Attached))), - analysisunit = ifelse(CommonIdentifier %in% species_reject, NA, - ifelse(str_detect(CommonIdentifier, "Halophila"), "Halophila spp.", - ifelse(SpeciesGroup1 == "Seagrass", CommonIdentifier, Drift_Attached))))] -SAV3[!is.na(Drift_Attached), `:=` (analysisunit_halid = paste0(analysisunit_halid, " algae"), - analysisunit = paste0(analysisunit, " algae"))] - -SAV4 <- subset(SAV3, !is.na(SAV3$analysisunit)) - -############################### -### SAV Plotting Functions #### -############################### - -# declaring addfits function which plots Percent Cover models on a single plot -addfits <- function(models, plot_i, param) { - # aucol determines whether analysisunit or analysisunit_halid is used - aucol <- as.name(names(plot_i$data)[1]) - # empty data frame to fill with regression data - regression_data <- data.frame() - plot_data <- data.frame() - - for (i in seq_along(models)) { - # finding model name, calling previously created model variable - model_name <- models[[i]] - model <- get(model_name) - - # selecting for Total SAV and Total Seagrass to apply aesthetic conditions later - is_ToSa <- grepl("ToSa", model_name) - is_ToSe <- grepl("ToSe", model_name) - exclude <- c("DrAl") - - # declaring species & managed area of each model - species <- unique(model$data[[aucol]]) - managed_area <- unique(model$data$ManagedAreaName) - - #extract p-value - p_val <- summary(model)$tTab[2,5] - - # exclude Drift algae from model plots - if(!grepl(paste(exclude, collapse='|'), model_name)) { - - linetypes <- "solid" - size <- 1 - alpha <- 1 - #alpha <- if (p_val <= 0.05) 1 else 0.8 - - # filter dataframe for managed_area & species - species_data <- SAV4 %>% - filter(ManagedAreaName == managed_area, - !is.na({{p}}), - {{ aucol }} == species) - - # plot_dat <- plotdat %>% - # filter({{ aucol }} == species) - - # create predicted values variable for each model - predicted_values <- predict(model, level = 0, newdata = species_data) - - # separate significant values - significant <- if (p_val <=0.05) TRUE else FALSE - - # Add predicted values to the regression_data dataframe, with species & relyear - regression_data <- rbind(regression_data, data.frame( - relyear = species_data$relyear, - fit = predicted_values, - species = unique(species_data[[aucol]]), - significance = significant)) - - # in case we separate Total SAV and Total seagrass and treat them differently - #if (is_ToSa || is_ToSe) {} else {} - # regression_data <- regression_data %>% - # filter(!species %in% c("Total SAV", "Total seagrass")) - - # Plot all other species - plot_i <- plot_i + - geom_line(data = regression_data, - aes(x = relyear, y = fit, color=species, linetype=factor(significance)), - size=size, alpha=alpha, inherit.aes = FALSE) + - # geom_bar(data = plot_dat, aes(x=relyear, y=npt), stat = "identity") + - scale_linetype_manual(name=NULL, - values=c("TRUE" = "solid", "FALSE" = "dotdash"), - labels=c("TRUE" = "Significant", "FALSE" = "Not significant")) + - # setting order of the legends, color first - guides(color = guide_legend(order=1), - linetype = guide_legend(order=2)) - } - } - - # creating color scale so names line up correctly in legend - species_list <- c("") - - for (l in plot_i[["layers"]]) { - new_species <- unique(l$data$species[!l$data$species %in% species_list]) - if (length(new_species) > 0) { - species_list <- append(species_list, new_species) - } - } - - # ordering species list to match spcols, with Total SAV & Total seagrass at bottom, otherwise alphabetical (Hal spp. at top) - species_list <- species_list[order(match(species_list, names(spcols)))] - - # determining if scientific or common names - species_labels <- modify_species_labels(species_list) - - plot_i <- plot_i + scale_color_manual(values = subset(spcols, names(spcols) %in% species_list), - breaks = species_list, - labels = species_labels) - - return(plot_i) -} - -# function to modify species labels prior to plotting (sci vs common names) -modify_species_labels <- function(species_list) { - if(usenames == "common") { - lab <- str_replace(species_list, "Unidentified Halophila", "Halophila, unk.") - } else { - lab <- sapply(species_list, function(name) { - match_idx <- match(name, spp_common) - if (!is.na(match_idx)) { - return(spp[match_idx]) - } - return(name) - }) - lab <- str_replace(lab, "Unidentified Halophila", "Halophila, unk.") - } - return(lab) -} - -## Choose which analyses to run, default is both trend and barplots -Analyses <- c("BB_pct", "PC", "PA") - -#Empty data.table to house names of any failed models generated below. -failedmods <- data.table(model = character(), - error = character()) - -############################### -### SAV Data Prep & Summary ### -############################### - -#Create a table of the proportion of present SAV types by managed area and year -props_halid <- SAV4 %>% - filter(str_detect(analysisunit_halid, "Total|Drift|spp\\.", negate = TRUE), !is.na(PA)) %>% - group_by(ManagedAreaName, analysisunit_halid, relyear) %>% - summarize(n_P = sum(PA), ntot_PA = n(), prop_P = n_P/ntot_PA) - -props <- SAV4 %>% - filter(str_detect(analysisunit, "Total|Drift|decipiens|engelmannii|johnsonii|Unidentified", negate = TRUE), !is.na(PA)) %>% - group_by(ManagedAreaName, analysisunit, relyear) %>% summarize(n_P = sum(PA), ntot_PA = n(), prop_P = n_P/ntot_PA) - -setDT(props_halid) -setDT(props) - -for(m in unique(props_halid$ManagedAreaName)){ - props_halid[ManagedAreaName == m, `:=` (n_allsp_P = sum(n_P), sp_prop = n_P/sum(n_P), sp_pct = (n_P/sum(n_P)) * 100), by = c("relyear")] -} -for(m in unique(props$ManagedAreaName)){ - props[ManagedAreaName == m, `:=` (n_allsp_P = sum(n_P), sp_prop = n_P/sum(n_P), sp_pct = (n_P/sum(n_P)) * 100), by = c("relyear")] -} - -setnames(props_halid, "analysisunit_halid", "analysisunit") -props2 <- distinct(rbind(props_halid, props)) -setorder(props2, ManagedAreaName, relyear, analysisunit) -props <- props2 - -spcollist <- c("#005396","#005396", - "#0088B1", - "#00ADAE", - "#65CCB3", - "#AEE4C1", - "#FDEBA8", - "#F8CD6D", - "#F5A800", - "#F17B00", - "#900667", - "#000099") - -spp <- c("Halophila spp.","Unidentified Halophila","Halophila johnsonii","Syringodium filiforme","Halophila decipiens","Halodule wrightii", - "Halophila engelmannii","Thalassia testudinum","Ruppia maritima","Attached algae", "Total SAV", "Total seagrass") - -spp_common <- c("Halophila spp.", "Unidentified Halophila", "Johnson's seagrass", "Manatee grass", "Paddle grass", - "Shoal grass", "Star grass", "Turtle grass", "Widgeon grass", "Attached algae", "Total SAV", "Total seagrass") - -usenames <- "common" #alternative is "scientific" - -spcols <- setNames(spcollist, spp_common) - -SAV4[, `:=` (analysisunit_halid = fcase(analysisunit_halid == "Thalassia testudinum", "Turtle grass", - analysisunit_halid == "Syringodium filiforme", "Manatee grass", - analysisunit_halid == "Halodule wrightii", "Shoal grass", - analysisunit_halid == "Ruppia maritima", "Widgeon grass", - analysisunit_halid == "Halophila decipiens", "Paddle grass", - analysisunit_halid == "Halophila engelmannii", "Star grass", - analysisunit_halid == "Halophila johnsonii", "Johnson's seagrass", - analysisunit_halid == "Unidentified Halophila", "Unidentified Halophila", - analysisunit_halid == "Halophila spp.", "Halophila spp.", - analysisunit_halid == "Total seagrass", "Total seagrass", - analysisunit_halid == "Attached algae", "Attached algae", - analysisunit_halid == "Drift algae", "Drift algae", - analysisunit_halid == "Total SAV", "Total SAV"), - analysisunit = fcase(analysisunit == "Thalassia testudinum", "Turtle grass", - analysisunit == "Syringodium filiforme", "Manatee grass", - analysisunit == "Halodule wrightii", "Shoal grass", - analysisunit == "Ruppia maritima", "Widgeon grass", - analysisunit == "Halophila decipiens", "Paddle grass", - analysisunit == "Halophila engelmannii", "Star grass", - analysisunit == "Halophila johnsonii", "Johnson's seagrass", - analysisunit == "Unidentified Halophila", "Unidentified Halophila", - analysisunit == "Halophila spp.", "Halophila spp.", - analysisunit == "Total seagrass", "Total seagrass", - analysisunit == "Attached algae", "Attached algae", - analysisunit == "Drift algae", "Drift algae", - analysisunit == "Total SAV", "Total SAV"))] - -props[, analysisunit := fcase(analysisunit == "Thalassia testudinum", "Turtle grass", - analysisunit == "Syringodium filiforme", "Manatee grass", - analysisunit == "Halodule wrightii", "Shoal grass", - analysisunit == "Ruppia maritima", "Widgeon grass", - analysisunit == "Halophila decipiens", "Paddle grass", - analysisunit == "Halophila engelmannii", "Star grass", - analysisunit == "Halophila johnsonii", "Johnson's seagrass", - analysisunit == "Unidentified Halophila", "Unidentified Halophila", - analysisunit == "Halophila spp.", "Halophila spp.", - analysisunit == "Attached algae", "Attached algae")] - -props <- props[, analysisunit := factor(analysisunit, levels = c("Unidentified Halophila", - "Halophila spp.", - "Johnson's seagrass", - "Manatee grass", - "Paddle grass", - "Shoal grass", - "Star grass", - "Turtle grass", - "Widgeon grass", - "Attached algae"))] - -# prcollist <- hcl.colors(n = length(unique(SAV4$ProgramID)), palette = "viridis") -prcollist_a <- sequential_hcl(length(unique(SAV4$ProgramName)), palette = "YlOrRd") -prcollist_b <- sequential_hcl(length(unique(SAV4$ProgramName)), palette = "YlGnBu", rev = TRUE) -prcollist <- append(prcollist_a[which(seq(1, length(prcollist_a)) %% 2 == 0)], - prcollist_b[which(seq(1, length(prcollist_b)) %% 2 != 0)]) -prcollist <- rev(prcollist) -set.seed(4691) -progs <- sample(sort(unique(SAV4$ProgramName))) -prcols <- setNames(prcollist, progs) - -parameters <- data.table(column = c(as.name("BB_pct"), as.name("PC"), as.name("PA")), - name = c("Median percent cover", "Visual percent cover", "Frequency of occurrence"), - type = c("BBpct", "PC", "PA")) - -plot_theme <- theme_bw() + - theme(panel.grid.major = element_blank(), - panel.grid.minor = element_blank(), - text = element_text(family = "Arial"), - # title = element_text(face="bold"), - plot.title = element_text(hjust = 0.5, size = 12, color = "#314963"), - plot.subtitle = element_text(hjust = 0.5, size = 10, color = "#314963"), - legend.title = element_text(size = 10), - legend.text.align = 0, - axis.title.x = element_text(size = 10, margin = margin(t = 5, r = 0, - b = 10, l = 0)), - axis.title.y = element_text(size = 10, margin = margin(t = 0, r = 10, - b = 0, l = 0)), - axis.text = element_text(size = 10), - axis.text.x = element_text(angle = -45, hjust = 0)) - -#Managed areas that should have Halophila species combined: -ma_halspp <- c("Banana River", "Indian River-Malabar to Vero Beach", "Indian River-Vero Beach to Ft. Pierce", "Jensen Beach to Jupiter Inlet", - "Loxahatchee River-Lake Worth Creek", "Mosquito Lagoon", "Biscayne Bay", "Florida Keys NMS") - -#save summary stats file -stats_pct <- SAV4[ManagedAreaName %in% ma_halspp, ] %>% - group_by(ManagedAreaName, analysisunit) %>% - summarize(ParameterName="Median percent cover (from BB scores)", - N_Programs=length(unique(ProgramID)), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', '), - N_Data=length(BB_pct[!is.na(BB_pct)]), - N_Years=length(unique(Year[!is.na(Year) & !is.na(BB_pct)])), - EarliestYear=min(Year[!is.na(BB_pct)]), - LatestYear=max(Year[!is.na(BB_pct)]), - SufficientData=ifelse(N_Data>0 & N_Years>=5, TRUE, FALSE)) -stats_pct2 <- SAV4[ManagedAreaName %in% setdiff(unique(SAV4$ManagedAreaName), ma_halspp), ] %>% - group_by(ManagedAreaName, analysisunit_halid) %>% - summarize(ParameterName="Median percent cover (from BB scores)", - N_Programs=length(unique(ProgramID)), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', '), - N_Data=length(BB_pct[!is.na(BB_pct)]), - N_Years=length(unique(Year[!is.na(Year) & !is.na(BB_pct)])), - EarliestYear=min(Year[!is.na(BB_pct)]), - LatestYear=max(Year[!is.na(BB_pct)]), - SufficientData=ifelse(N_Data>0 & N_Years>=5, TRUE, FALSE)) -setDT(stats_pct2) -setnames(stats_pct2, "analysisunit_halid", "analysisunit") -stats_pct <- distinct(rbind(stats_pct, stats_pct2)) -setcolorder(stats_pct, c("ManagedAreaName", "analysisunit")) -setDT(stats_pct) -stats_pct[N_Years == 0, `:=` (EarliestYear = NA, LatestYear = NA)] -stats_pct$ProgramIDs -data.table::fwrite(stats_pct, "output/Data/SAV/SAV_BBpct_Stats.txt", sep = "|") - -stats_pa <- SAV4[ManagedAreaName %in% ma_halspp, ] %>% - group_by(ManagedAreaName, analysisunit) %>% - summarize(ParameterName="Frequency of occurrence", - N_Programs=length(unique(ProgramID)), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', '), - N_Data=length(PA[!is.na(PA)]), - N_Years=length(unique(Year[!is.na(Year) & !is.na(PA)])), - EarliestYear=min(Year[!is.na(PA)]), - LatestYear=max(Year[!is.na(PA)]), - SufficientData=ifelse(N_Data>0 & N_Years>=5, TRUE, FALSE)) -stats_pa2 <- SAV4[ManagedAreaName %in% setdiff(unique(SAV4$ManagedAreaName), ma_halspp), ] %>% - group_by(ManagedAreaName, analysisunit_halid) %>% - summarize(ParameterName="Frequency of occurrence", - N_Programs=length(unique(ProgramID)), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', '), - N_Data=length(PA[!is.na(PA)]), - N_Years=length(unique(Year[!is.na(Year) & !is.na(PA)])), - EarliestYear=min(Year[!is.na(PA)]), - LatestYear=max(Year[!is.na(PA)]), - SufficientData=ifelse(N_Data>0 & N_Years>=5, TRUE, FALSE)) -setDT(stats_pa2) -setnames(stats_pa2, "analysisunit_halid", "analysisunit") -stats_pa <- distinct(rbind(stats_pa, stats_pa2)) -setcolorder(stats_pa, c("ManagedAreaName", "analysisunit")) -setDT(stats_pa) -stats_pa[N_Years == 0, `:=` (EarliestYear = NA, LatestYear = NA)] - -statpardat <- list("BB_pct" = stats_pct, "PA" = stats_pa) -openxlsx::write.xlsx(statpardat, here::here(paste0("output/Data/SAV/SAV_BBpct_PA_Stats_", Sys.Date(), ".xlsx")), colNames = c(TRUE, TRUE), colWidths = c("auto", "auto"), firstRow = c(TRUE, TRUE)) - -###################### -#### START SCRIPT #### -###################### - -sav_ma_include <- list() - -n <- 0 -seed <- 352 -set.seed(seed) - -for(p in parameters$column){ - cat(paste0("\nStarting indicator: ", p, "\n")) - - #List managed areas with at least 5 years of data - nyears <- SAV4[!is.na(eval(p)) & !is.na(analysisunit), ] %>% group_by(ManagedAreaName, analysisunit) %>% summarize(type = paste0(p), nyr = length(unique(Year))) - nyears2 <- SAV4[!is.na(eval(p)) & !is.na(analysisunit_halid), ] %>% group_by(ManagedAreaName, analysisunit_halid) %>% summarize(type = paste0(p), nyr = length(unique(Year))) - setDT(nyears2) - setnames(nyears2, "analysisunit_halid", "analysisunit") - nyears <- distinct(rbind(nyears, nyears2)) - ma_include <- unique(subset(nyears, nyears$nyr >= 5)$ManagedAreaName) - # sav_ma_include <- rbind(ma_include, sav_ma_include) - - #For each managed area, make sure there are multiple levels of BB scores per species; remove ones that don't from further consideration. - for(i in ma_include){ - - cat(paste0("\nStarting MA: ", i, "\n")) - - if(i %in% ma_halspp){ - species <- subset(nyears, nyears$ManagedAreaName == i & nyears$nyr >= 5 & analysisunit %in% c("Attached algae", "Drift algae", "Halophila spp.", "Manatee grass", - "Shoal grass", "Total seagrass", "Total SAV", "Turtle grass", - "Widgeon grass", "Syringodium filiforme", "Halodule wrightii", "Thalassia testudinum", - "Ruppia maritima"))$analysisunit - } else{ - species <- subset(nyears, nyears$ManagedAreaName == i & nyears$nyr >= 5 & analysisunit %in% c("Attached algae", "Drift algae", "Unidentified Halophila", - "Johnson's seagrass", "Manatee grass", "Paddle grass", - "Shoal grass", "Star grass", "Total seagrass", "Total SAV", - "Turtle grass", "Widgeon grass", "Syringodium filiforme", - "Halodule wrightii", "Thalassia testudinum","Ruppia maritima"))$analysisunit - } - - models <- c() - - #Create data.tables to hold model results for managed area i---------------------------------------------------- - lmemodresults <- data.table(managed_area = character(), - species = character(), - filename = character(), - effect = character(), - group = character(), - term = character(), - estimate = numeric(), - std.error = numeric(), - df = numeric(), - statistic = numeric(), - p.value = numeric()) - - - #In case model doesn't converge on the first try, attempt each model up to 5 times before moving on - for(j in species){ - - cat(paste0("\n Starting species: ", j, "\n")) - - if(paste0(p) %in% c("BB_pct", "PC") & ("BB_pct" %in% Analyses | "PC" %in% Analyses)){ - - formula_j <- as.formula(paste0(p, " ~ relyear")) - - set.seed(seed + n) - if(j %in% setdiff(unique(SAV4$analysisunit_halid), unique(SAV4$analysisunit))){ - model_j <- try(lme(formula_j, - random = list(SiteIdentifier = ~relyear), - control = list(msMaxIter = 1000, msMaxEval = 1000, sing.tol=1e-20), - na.action = na.omit, - data = SAV4[ManagedAreaName == i & !is.na(eval(p)) & analysisunit_halid == j, ]), - silent = TRUE) - n <- n + 1 - x <- 0 - - while(class(model_j) == "try-error" & x < 5){ - if(x %% 25 == 0) print(paste0(" Model failed, starting attempt ", x, " of 5")) - - set.seed(seed + n) - model_j <- try(lme(formula_j, - random = list(SiteIdentifier = ~relyear), - control = list(msMaxIter = 1000, msMaxEval = 1000, sing.tol=1e-20), - na.action = na.omit, - data = SAV4[ManagedAreaName == i & !is.na(eval(p)) & analysisunit_halid == j, ]), - silent = TRUE) - n <- n + 1 - x <- x + 1 - } - } else{ - model_j <- try(lme(formula_j, - random = list(SiteIdentifier = ~relyear), - control = list(msMaxIter = 1000, msMaxEval = 1000, sing.tol=1e-20), - na.action = na.omit, - data = SAV4[ManagedAreaName == i & !is.na(eval(p)) & analysisunit == j, ]), - silent = TRUE) - n <- n + 1 - x <- 0 - - while(class(model_j) == "try-error" & x < 5){ - if(x %% 25 == 0) print(paste0(" Model failed, starting attempt ", x, " of 5")) - - set.seed(seed + n) - model_j <- try(lme(formula_j, - random = list(SiteIdentifier = ~relyear), - control = list(msMaxIter = 1000, msMaxEval = 1000, sing.tol=1e-20), - na.action = na.omit, - data = SAV4[ManagedAreaName == i & !is.na(eval(p)) & analysisunit == j, ]), - silent = TRUE) - n <- n + 1 - x <- x + 1 - } - } - - - #Individual model objects are needed for plotting all species together - ##This allows get(model) functionality within addfits function - eval(call("<-", as.name(paste0(gsub('\\b(\\pL)\\pL{2,}|.', '\\U\\1', i, perl = TRUE), - "_", - gsub('\\b(\\p{Lu}\\p{Ll})|.','\\1', str_to_title(j), perl = TRUE))), - model_j)) - - #Save the model object as .rds - saveRDS(model_j, here::here(paste0("output/models/SAV_", parameters[column == p, type], "_", - gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), - ifelse(stringr::str_detect(i, "NERR"), "ERR_lme_", - ifelse(stringr::str_detect(i, "NMS"), "MS_lme_", "AP_lme_")), - gsub('\\b(\\p{Lu}\\p{Ll})|.','\\1', str_to_title(j), perl = TRUE), - ".rds"))) - - print(paste0(" Model object saved: ", - gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), - "_", - gsub('\\b(\\p{Lu}\\p{Ll})|.','\\1', str_to_title(j), perl = TRUE))) - - #record lme model results------------------------------------------------------ - if(class(try(eval(as.name(paste0(gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), "_", gsub('\\b(\\p{Lu}\\p{Ll})|.','\\1', str_to_title(j), perl = TRUE)))), silent = TRUE)) != "try-error"){ - models <- append(models, as.name(paste0(gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), "_", gsub('\\b(\\p{Lu}\\p{Ll})|.','\\1', str_to_title(j), perl = TRUE)))) - modj_i <- setDT(broom.mixed::tidy(eval(as.name(paste0(gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), "_", gsub('\\b(\\p{Lu}\\p{Ll})|.','\\1', str_to_title(j), perl = TRUE)))))) - modj_i[, `:=` (managed_area = ifelse(stringr::str_detect(i, "NERR"), paste0(str_sub(i, 1, -6), " National Estuarine Research Reserve"), - ifelse(stringr::str_detect(i, "NMS"), paste0(str_sub(i, 1, -5), " National Marine Sanctuary"), paste0(i, " Aquatic Preserve"))), - species = j, - filename = paste0("SAV_", parameters[column == p, type], "_", gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), - ifelse(stringr::str_detect(i, "NERR"), "ERR_lme_", - ifelse(stringr::str_detect(i, "NMS"), "MS_lme_", "AP_lme_")), - gsub('\\b(\\p{Lu}\\p{Ll})|.','\\1', str_to_title(j), perl = TRUE), ".rds"))] - lmemodresults <- rbind(lmemodresults, modj_i) - - } else{ - failedmod <- data.table(model = paste0("SAV_", parameters[column == p, type], "_", - gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), - ifelse(stringr::str_detect(i, "NERR"), "ERR_lme_", - ifelse(stringr::str_detect(i, "NMS"), "MS_lme_", "AP_lme_")), - gsub('\\b(\\p{Lu}\\p{Ll})|.','\\1', str_to_title(j), perl = TRUE), ".rds"), - error = model_j[1]) - - failedmods <- rbind(failedmods, failedmod) - - modj_i <- data.table(managed_area = ifelse(stringr::str_detect(i, "NERR"), paste0(str_sub(i, 1, -6), " National Estuarine Research Reserve"), - ifelse(stringr::str_detect(i, "NMS"), paste0(str_sub(i, 1, -5), " National Marine Sanctuary"), paste0(i, " Aquatic Preserve"))), - species = j, - filename = paste0("SAV_", parameters[column == p, type], "_", gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), - ifelse(stringr::str_detect(i, "NERR"), "ERR_lme_", - ifelse(stringr::str_detect(i, "NMS"), "MS_lme_", "AP_lme_")), - gsub('\\b(\\p{Lu}\\p{Ll})|.','\\1', str_to_title(j), perl = TRUE), ".rds"), - effect = NA, - group = NA, - term = NA, - estimate = NA, - std.error = NA, - df = NA, - statistic = NA, - p.value = NA) - lmemodresults <- rbind(lmemodresults, modj_i) - } - } - } - - ###### TREND PLOTS ##### - if(paste0(p) %in% c("BB_pct", "PC") & ("BB_pct" %in% Analyses | "PC" %in% Analyses)){ - #Summarize # points per category - - if(i %in% ma_halspp){ - plotdat <- SAV4[ManagedAreaName == i & !is.na(eval(p)), ] %>% group_by(analysisunit, Year, relyear, eval(p)) %>% summarise(npt = n()) - } else{ - plotdat <- SAV4[ManagedAreaName == i & !is.na(eval(p)), ] %>% group_by(analysisunit_halid, Year, relyear, eval(p)) %>% summarise(npt = n()) - } - setDT(plotdat) - setnames(plotdat, "eval(p)", "data") - aucol <- names(plotdat[,1]) - - #split modeled vs unmodeled data - modeledsp <- c() - for(u in seq_along(models)){ - name_u <- fcase(str_detect(paste0(models[[u]]), "_ShGr"), "Shoal grass", - str_detect(paste0(models[[u]]), "_TuGr"), "Turtle grass", - str_detect(paste0(models[[u]]), "_MaGr"), "Manatee grass", - str_detect(paste0(models[[u]]), "_WiGr"), "Widgeon grass", - str_detect(paste0(models[[u]]), "_PaGr"), "Paddle grass", - str_detect(paste0(models[[u]]), "_StGr"), "Star grass", - str_detect(paste0(models[[u]]), "_JoSe"), "Johnson's seagrass", - str_detect(paste0(models[[u]]), "_UnHa"), "Unidentified Halophila", - str_detect(paste0(models[[u]]), "_HaSp"), "Halophila spp.", - str_detect(paste0(models[[u]]), "_ToSe"), "Total seagrass", - str_detect(paste0(models[[u]]), "_AtAl"), "Attached algae", - str_detect(paste0(models[[u]]), "_DrAl"), "Drift algae", - str_detect(paste0(models[[u]]), "_To"), "Total SAV") - modeledsp <- append(modeledsp, name_u) - } - - miny <- c() - for(v in seq_along(models)){ - miny_v <- try(predict(eval(models[[v]]), level = 0), silent = TRUE) - if(class(miny_v) == "try-error") next - miny <- append(miny, min(miny_v)) - } - miny <- ifelse(floor(min(miny)) < 0, floor(min(miny)), 0) - - # Scale x-axis data - breaks_seq <- seq(from = min(plotdat$relyear), - to = max(plotdat$relyear), - by = 3) - labels_seq <- seq(from = min(plotdat$Year), - to = max(plotdat$Year), - by = 3) - - #create base plot of seagrass percent cover data over time for managed area i - plot_i <- ggplot(data = droplevels(plotdat), - aes(x = relyear, y = data)) + - labs(title = parameters[column == p, name], - subtitle = ifelse(stringr::str_detect(i, "NERR"), paste0(str_sub(i, 1, -6), " National Estuarine Research Reserve"), - ifelse(stringr::str_detect(i, "NMS"), paste0(str_sub(i, 1, -5), " National Marine Sanctuary"), paste0(i, " Aquatic Preserve"))), - x = "Year", - y = parameters[column == p, name], - color = "Species model projections", - linetype = "Significance") + - plot_theme + - ylim(miny, 100) + - scale_x_continuous(breaks = breaks_seq, labels = labels_seq) + - scale_colour_manual(values = spcols) - - if(length(models) > 0){ - #make sure that no failed models slipped through - classes <- lapply(models, function(x) class(eval(x))) - models <- models[classes != "try-error"] - - plot_i <- addfits(models, plot_i, p) - } - - #Save the plot object as .rds - saveRDS(plot_i, here::here(paste0("output/Figures/BB/SAV_", parameters[column == p, type], "_", - ifelse(stringr::str_detect(i, "NERR"), - paste0(str_sub(gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), 1, -2), "NERR_trendplot.rds"), - ifelse(stringr::str_detect(i, "NMS"), - paste0(str_sub(gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), 1, -2), "NMS_trendplot.rds"), - paste0(gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), "AP_trendplot.rds")))))) - - #Save the results table objects as .rds - saveRDS(lmemodresults, here::here(paste0("output/tables/SAV/SAV_", parameters[column == p, type], "_", - ifelse(stringr::str_detect(i, "NERR"), - paste0(str_sub(gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), 1, -2), "NERR_lmeresults.rds"), - ifelse(stringr::str_detect(i, "NMS"), - paste0(str_sub(gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), 1, -2), "NMS_lmeresults.rds"), - paste0(gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), "AP_lmeresults.rds")))))) - } - - ###### BAR PLOTS ###### - if(paste0(p) == "PA" & "PA" %in% Analyses){ - #Bar chart of proportions by analysisunit - breaks <- c(seq(min(SAV4[ManagedAreaName == i & !is.na(PA), relyear]), - max(SAV4[ManagedAreaName == i & !is.na(PA), relyear]), - by = 2)) - yrlist <- sort(unique(SAV4$Year)) - - labels <- c() - for(b in breaks){ - labels <- append(labels, yrlist[b + 1]) - } - - if(i %in% ma_halspp){ - - bpdat <- props[ManagedAreaName == i & !is.na(analysisunit) & str_detect(analysisunit, "decipiens|engelmannii|johnsonii|Unidentified|Star|Paddle|Johnson", negate = TRUE), ] - - sp_list <- unique(bpdat$analysisunit) - sp_list <- sp_list[order(match(sp_list, names(spcols)))] - - # add color scale, determining if scientific or common names - sp_labels <- modify_species_labels(sp_list) - - barplot_sp <- ggplot(data = bpdat, aes(x = relyear, y = sp_pct, fill = analysisunit)) + - geom_col(color = "grey20") + - scale_x_continuous(breaks = breaks, labels = labels) + - plot_theme + - labs(title = parameters[column == p, name], subtitle = paste0(ifelse(stringr::str_detect(i, "NERR"), paste0(str_sub(i, 1, -6), " National Estuarine Research Reserve"), - ifelse(stringr::str_detect(i, "NMS"), paste0(str_sub(i, 1, -5), " National Marine Sanctuary"), paste0(i, " Aquatic Preserve")))), - fill = "Species", - x = "Year", - y = "Occurrence frequency (%)") + - theme(axis.text.x = element_text(angle = 45, hjust = 1)) + - scale_color_manual(values = subset(spcols, names(spcols) %in% sp_list), - labels = sp_labels, - aesthetics = c("color", "fill")) - } else{ - - bpdat <- props[ManagedAreaName == i & !is.na(analysisunit) & analysisunit != "Halophila spp.", ] - - sp_list <- unique(bpdat$analysisunit) - sp_list <- sp_list[order(match(sp_list, names(spcols)))] - - # add color scale, determining if scientific or common names - sp_labels <- modify_species_labels(sp_list) - - barplot_sp <- ggplot(data = bpdat, aes(x = relyear, y = sp_pct, fill = analysisunit)) + - geom_col(color = "grey20") + - scale_x_continuous(breaks = breaks, labels = labels) + - plot_theme + - labs(title = parameters[column == p, name], subtitle = paste0(ifelse(stringr::str_detect(i, "NERR"), paste0(str_sub(i, 1, -6), " National Estuarine Research Reserve"), - ifelse(stringr::str_detect(i, "NMS"), paste0(str_sub(i, 1, -5), " National Marine Sanctuary"), paste0(i, " Aquatic Preserve")))), - fill = "Species", - x = "Year", - y = "Occurrence frequency (%)") + - theme(axis.text.x = element_text(angle = 45, hjust = 1)) + - scale_color_manual(values = subset(spcols, names(spcols) %in% sp_list), - labels = sp_labels, - aesthetics = c("color", "fill")) - } - - saveRDS(barplot_sp, here::here(paste0("output/Figures/BB/SAV_", parameters[column == p, type], "_", - gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), - ifelse(stringr::str_detect(i, "NERR"), "ERR_barplot_sp", - ifelse(stringr::str_detect(i, "NMS"), "MS_barplot_sp", "AP_barplot_sp")), - ".rds"))) - } - - print(paste0(" Plot objects and results tables saved: ", - gsub('\\b(\\pL)\\pL{2,}|.','\\U\\1', i, perl = TRUE), - "_", - gsub('\\b(\\p{Lu}\\p{Ll})|.','\\1', str_to_title(j), perl = TRUE))) - } -} - -#Save failedmodslist----------------------------------------------------- -saveRDS(failedmods, here::here("output/models/failedmodslist.rds")) - -#Get rid of eval(p)'s from plot file mappings--------------------------------------- -files <- list.files(here::here("output/Figures/BB/")) #get file list -files <- str_subset(files, ".rds") #exclude non-.RDS files - -filesupdated <- list() -for(f in seq_along(files)){ - file_f <- readRDS(here::here(paste0("output/Figures/BB/", files[f]))) - if(paste0(as_label(file_f$mapping$y)) == "eval(p)"){ - file_f$mapping$y <- parameters[name %in% file_f$labels$y, column][[1]] - saveRDS(file_f, here::here(paste0("output/Figures/BB/", files[f]))) - rm(file_f) - filesupdated <- append(filesupdated, files[f]) - } else { - rm(file_f) - } - if(round((f/length(files))*100, 1) %% 10 == 0){ - print(paste0(round((f/length(files))*100), "% done!")) - } -} \ No newline at end of file diff --git a/MA Report Generation/WQ_Continuous.R b/MA Report Generation/WQ_Continuous.R deleted file mode 100644 index 367b67bb..00000000 --- a/MA Report Generation/WQ_Continuous.R +++ /dev/null @@ -1,196 +0,0 @@ -cont_params_short <- c( - "DO", - "DOS", - "pH", - "Sal", - "Turb", - "TempW" -) - -# extract region for each MA to determine which cont. file to load -region <- MA_All %>% filter(ManagedAreaName == ma) %>% pull(Region) - -# Cont. Data exports do not contain full parameter names or units -# Create dataframe containing that info -cont_params_long <- c("Dissolved Oxygen","Dissolved Oxygen Saturation","pH", - "Salinity","Turbidity","Water Temperature") -cont_param_units <- c("mg/L","%","pH","ppt","NTU","Degrees C") - -cont_param_df <- data.frame(param_short = cont_params_short, - parameter = cont_params_long, - unit = cont_param_units) - -################# -### FUNCTIONS ### -################# - -# Provides a table for stations with Cont. Data -# and which stations passed the tests -station_count_table <- function(cont_data){ - - # create frame to show available stations - # show how many are included/excluded in the report - stations <- cont_data %>% - filter(ManagedAreaName == ma) %>% - distinct(ProgramLocationID, ProgramName, Use_In_Analysis) - - # table - stations_table <- kable(stations, - format="simple", - caption=paste0("Number of Continuous Stations in ", ma)) %>% - kable_styling(latex_options="scale_down", - position = "center") - - print(stations_table) - cat(" \n\n") - - # n stations total, n stations included (Use_In_Analysis) - n_stations <- nrow(stations) - n_stations_inc <- nrow(stations[stations$Use_In_Analysis==TRUE, ]) - - # print text statement - cat(paste0("There are ", n_stations, " stations in ", ma, ". \n\n")) - cat(paste0(n_stations_inc, " out of ", n_stations, " are included in this report.")) - cat(" \n\n") -} - -# For loading continuous data -# Load Data Table Function -load_cont_data_table <- function(param, region, table) { - - # Declaring RDS file list of respective tables - files <- list.files(here::here("output/tables/cont"),pattern = "\\.rds$") - file_path <- paste0("_",param,"_", region,"_", table) - - # subset file list to select desired table RDS file - table_file <- paste0("output/tables/cont/",str_subset(files, file_path)) - - # importing RDS files - df <- readRDS(table_file) - - return(df) -} - -# Unified continuous plotting function -plot_cont <- function(p, y_labels, parameter, cont_data) { - data <- cont_data %>% filter(ManagedAreaName == ma) - - Mon_YM_Stats <- as.data.frame(load_cont_data_table(p, region, "Mon_YM_Stats")) - skt_stats <- as.data.frame(load_cont_data_table(p, region, "skt_stats")) - - skt_stats <- skt_stats %>% - filter(ManagedAreaName==ma) - - # Checking for missing values - Mon_YM_Stats <- Mon_YM_Stats %>% - filter(ManagedAreaName == ma & ParameterName == parameter) - - ### SKT STATS ### - # Gets x and y values for starting point for trendline - KT.Plot <- skt_stats %>% - group_by(MonitoringID) %>% - summarize(x=decimal_date(EarliestSampleDate), - y=(x-EarliestYear)*SennSlope+SennIntercept) - # Gets x and y values for ending point for trendline - KT.Plot2 <- skt_stats %>% - group_by(MonitoringID) %>% - summarize(x=decimal_date(LastSampleDate), - y=(x-EarliestYear)*SennSlope+SennIntercept) - # Combines the starting and endpoints for plotting the trendline - KT.Plot <- bind_rows(KT.Plot, KT.Plot2) - rm(KT.Plot2) - KT.Plot <- as.data.table(KT.Plot[order(KT.Plot$MonitoringID), ]) - KT.Plot <- KT.Plot[!is.na(KT.Plot$y),] - - # unique monitoring location IDs for each managed area - MonIDs <- unique(data$MonitoringID) - n <- length(MonIDs) - - if (length(MonIDs) == 0){ - print("There are no monitoring locations that qualify.") - } else { - # Begins looping through each monitoring location - for (id in MonIDs) { - - ################## - ### TRENDPLOTS ### - ################## - - # Gets data to be used in plot for monitoring location - plot_data <- Mon_YM_Stats[Mon_YM_Stats$MonitoringID==id,] - - if (nrow(plot_data) > 0) { - # Gets trendline data for monitoring location - KT.plot_data <- KT.Plot[KT.Plot$MonitoringID==id,] - #Determine max and min time (Year) for plot x-axis - t_min <- min(plot_data$Year) - t_max <- max(plot_data$YearMonthDec) - t_max_brk <- as.integer(round(t_max, 0)) - t <- t_max-t_min - min_RV <- min(plot_data$Mean) - # Creates break intervals for plots based on number of years of data - if(t>=30){ - # Set breaks to every 10 years if more than 30 years of data - brk <- -10 - }else if(t<30 & t>=10){ - # Set breaks to every 5 years if between 30 and 10 years of data - brk <- -5 - }else if(t<10 & t>=4){ - # Set breaks to every 2 years if between 10 and 4 years of data - brk <- -2 - }else if(t<4 & t>=2){ - # Set breaks to every year if between 4 and 2 years of data - brk <- -1 - }else if(t<2){ - # Set breaks to every year if less than 2 years of data - brk <- -1 - # Sets t_max to be 1 year greater and t_min to be 1 year lower - # Forces graph to have at least 3 tick marks - t_max <- t_max+1 - t_min <- t_min-1 - } - # Get name of managed area - MA_name <- skt_stats$ManagedAreaName[skt_stats$MonitoringID==id] - # Get program location name - Mon_name <- paste0(skt_stats$ProgramID[skt_stats$MonitoringID==id], - "\n", skt_stats$ProgramName[skt_stats$MonitoringID==id], "\n", - skt_stats$ProgramLocationID[skt_stats$MonitoringID==id]) - mon_name_short <- skt_stats$ProgramLocationID[skt_stats$MonitoringID==id] - # Create plot object with data and trendline - p1 <- ggplot(data=plot_data, - aes(x=YearMonthDec, y=Mean)) + - geom_point(shape=21, size=3, color="#333333", fill="#cccccc", - alpha=0.75) + - geom_line(data=KT.plot_data, aes(x=x, y=y), - color="#000099", size=1.2, alpha=0.7) + - labs(title=paste0(MA_name, "\n", Mon_name), - subtitle=parameter, - x="Year", y=y_labels) + - scale_x_continuous(limits=c(t_min-0.25, t_max+0.25), - breaks=seq(t_max_brk, t_min, brk)) + - plot_theme - - # Creates ResultTable to display statistics below plot - ResultTable <- skt_stats[skt_stats$MonitoringID==id, ] %>% - select(RelativeDepth, N_Data, N_Years, Median, Independent, tau, p, - SennSlope, SennIntercept, ChiSquared, pChiSquared, Trend) - # Create table object - t1 <- ggtexttable(ResultTable, rows=NULL, - theme=ttheme(base_size=10)) %>% - tab_add_footnote(text="p < 0.00005 appear as 0 due to rounding.\n - SennIntercept is intercept value at beginning of - record for monitoring location", - size=10, face="italic") - - ### Monitoring Station Name Label ### - mon_title <- glue("### {mon_name_short}") - cat(mon_title, "\n\n") - - # Arrange and display plot and statistic table - print(ggarrange(p1, t1, ncol=1, heights=c(0.85, 0.15))) - # Add extra space at the end to prevent the next figure from being too close - cat("\n \n \n") - } - } - } - } \ No newline at end of file diff --git a/MA Report Generation/WQ_Discrete.R b/MA Report Generation/WQ_Discrete.R deleted file mode 100644 index f010a8f6..00000000 --- a/MA Report Generation/WQ_Discrete.R +++ /dev/null @@ -1,524 +0,0 @@ -library(stringr) -library(dplyr) -library(data.table) -library(ggplot2) -library(grid) -library(kableExtra) - -all_depths <- c("Surface","Bottom","All") -all_activities <- c("Field","Lab","All") -all_params_short <- c( - "ChlaC", - "Chla", - "CDOM", - "DO", - "DOS", - "pH", - "Sal", - "Secchi", - "TN", - "TP", - "TSS", - "Turb", - "TempW" -) - -############################ -######## FUNCTIONS ######### -############################ - -# function of parameter, activity type, depth, with specified filetype -# retrieves RDS filepath to be loaded -get_files <- function(p, a, d, filetype) { - - # Declaring RDS file list of respective tables - files <- list.files(here::here("output/tables/disc"),pattern = "\\.rds$") - - # "data" contains overall data for each param, regardless of depth/activity - if (filetype == "data") { - pattern <- paste0(p,"_",filetype) - - } else { - pattern <- paste0(p,"_",a,"_",d,"_",filetype) - } - # subset directory files for given pattern - file_return <- str_subset(files, pattern) - return(file_return) -} - -#function to check the number of managed areas for each p,a,d combination -n_managedareas <- function(p, a, d) { - # Declaring n value as count of managed areas - # return 0 if unable to load file (activity/depth combo not available for that param) - n <- tryCatch( - { - ma_file <- get_files(p, a, d, "MA_Include") - ma_inclusion <- readRDS(paste0("output/tables/disc/", ma_file)) - n <- length(ma_inclusion) - rm(ma_inclusion) - n - }, - error = function(e) { - 0 - }, - warning = function(w) { - 0 - } - ) - return(n) -} - -#function to make a list of managed area names -get_managed_area_names <- function(p, a, d) { - ma_list <- with( - readRDS(paste0("output/tables/disc/",get_files(p, a, d, "MA_MMYY"))), - { - unique(ManagedAreaName) - } - ) - return(list(ma_list)) -} - -#results list to record managed areas for each combination -results_list <- list() - -for (param in all_params_short) { - if (param == "Secchi"){ - depth <- "Surface" - } else { - depth <- "All" - } - - # Choosing which analyses to plot, when to combine - if (param == "ChlaC" | - param == "Chla" | - param == "CDOM" | - param == "TN" | - param == "TP") {activity = "Lab"} else if ( - param == "DO" | - param == "DOS" | - param == "pH" | - param == "Secchi" | - param == "TempW") {activity = "Field"} else if ( - param == "Sal" | - param == "TSS" | - param == "Turb") {activity = "All"} - - n <- n_managedareas(param, activity, depth) - - if (n > 0) { - print(n) - managed_area_names <- get_managed_area_names(param, activity, depth) - - # Concatenate the managed area names into a single character vector - concatenated_names <- unlist(managed_area_names) - - # Create a data frame for the current combination - result_df <- data.frame(Parameter = param, - Depth = depth, - Activity = activity, - ManagedAreaName = paste(concatenated_names)) - - # Append the result data frame to the list - results_list <- c(results_list, list(result_df)) - rm(result_df, concatenated_names, managed_area_names, n) - - } else { - print(0) - } -} - -# Bind the list of data frames using bind_rows() -managed_area_df <- bind_rows(results_list) - -disc_managed_areas <- unique(managed_area_df$ManagedAreaName) - -## Setting plot theme for plots -plot_theme <- theme_bw() + - theme(panel.grid.major = element_blank(), - panel.grid.minor = element_blank(), - text=element_text(family="Arial"), - plot.title=element_text(hjust=0.5, size=12, color="#314963"), - plot.subtitle=element_text(hjust=0.5, size=10, color="#314963"), - legend.title=element_text(size=10), - legend.text.align = 0, - axis.title.x = element_text(size=10, margin = margin(t = 5, r = 0, - b = 10, l = 0)), - axis.title.y = element_text(size=10, margin = margin(t = 0, r = 10, - b = 0, l = 0)), - axis.text=element_text(size=10), - axis.text.x=element_text(angle = -45, hjust = 0)) - - -## Load Data Table Function -## For loading discrete data -load_data_table <- function(p, a="All", d="All", table) { - - # Declaring RDS file list of respective tables - files <- list.files(here::here("output/tables/disc"),pattern = "\\.rds$") - - if (table == "data") { - filename_string <- paste0(p,"_",table) - } else { - filename_string <- paste0(p,"_",a,"_",d,"_",table) - } - - # subset file list to select desired table RDS file - table_file <- paste0("output/tables/disc/",str_subset(files, filename_string)) - - # importing RDS files - df <- lapply(table_file, readRDS) - - return(df) -} - -## Kendall-Tau Trendlines Plot function ## -plot_trendlines <- function(p, a, d, activity_label, depth_label, y_labels, parameter, data) { - cat(" \n") - cat(glue("**Discrete Seasonal Kendall-Tau Trend Analysis**"), " \n") - - MA_YM_Stats <- as.data.frame(load_data_table(p, a, d, "MA_MMYY_Stats")) - skt_stats <- as.data.frame(load_data_table(p, a, d, "skt_stats")) - - ### SKT STATS ### - # Gets x and y values for starting point for trendline - KT.Plot <- skt_stats %>% - dplyr::group_by(ManagedAreaName) %>% - dplyr::summarize(x=decimal_date(EarliestSampleDate), - y=(x-EarliestYear)*SennSlope+SennIntercept) - # Gets x and y values for ending point for trendline - KT.Plot2 <- skt_stats %>% - dplyr::group_by(ManagedAreaName) %>% - dplyr::summarize(x=decimal_date(LastSampleDate), - y=(x-EarliestYear)*SennSlope+SennIntercept) - # Combines the starting and endpoints for plotting the trendline - KT.Plot <- bind_rows(KT.Plot, KT.Plot2) - rm(KT.Plot2) - KT.Plot <- as.data.table(KT.Plot[order(KT.Plot$ManagedAreaName), ]) - KT.Plot <- KT.Plot[!is.na(KT.Plot$y),] - - # Checking for missing values - check_ym <- MA_YM_Stats %>% - filter(ManagedAreaName == ma) - - if (nrow(check_ym) == 0) { - invisible() - # print("error") - } else { - # Gets data to be used in plot for managed area - plot_data <- MA_YM_Stats[MA_YM_Stats$ManagedAreaName==ma,] - - # Gets trendline data for managed area - KT.plot_data <- KT.Plot[KT.Plot$ManagedAreaName==ma,] - - #Determine max and min time (Year) for plot x-axis - t_min <- min(plot_data$Year) - t_max <- max(plot_data$YearMonthDec) - t_max_brk <- as.integer(round(t_max, 0)) - t <- t_max-t_min - min_RV <- min(plot_data$Mean) - - # Sets break intervals based on the number of years spanned by data - if(t>=30){ - brk <- -10 - }else if(t<30 & t>=10){ - brk <- -5 - }else if(t<10 & t>=4){ - brk <- -2 - }else if(t<4){ - brk <- -1 - } - - # Create plot object with data and trendline - p1 <- ggplot(data=plot_data, - aes(x=YearMonthDec, y=Mean)) + - # geom_line(size=0.75, color="#333333", alpha=0.6) + - geom_point(shape=21, size=3, color="#333333", fill="#cccccc", - alpha=0.75) + - geom_line(data=KT.plot_data, aes(x=x, y=y), - color="#000099", size=1.2, alpha=0.7) + - labs(title=paste0(parameter,", ",activity_label, ", ",depth_label), - subtitle=ma, - x="Year", y=y_labels) + - scale_x_continuous(limits=c(t_min-0.25, t_max+0.25), - breaks=seq(t_max_brk, t_min, brk)) + - plot_theme - # Creates ResultTable to display statistics below plot - ResultTable <- skt_stats[skt_stats$ManagedAreaName==ma, ] %>% - select(RelativeDepth, N_Data, N_Years, Median, Independent, tau, p, - SennSlope, SennIntercept, ChiSquared, pChiSquared, Trend) - # Create table object - t1 <- ggtexttable(ResultTable, rows=NULL, - theme=ttheme(base_size=10)) %>% - tab_add_footnote(text="p < 0.00005 appear as 0 due to rounding.\n - SennIntercept is intercept value at beginning of - record for monitoring location", - size=10, face="italic") - # Arrange and display plot and statistic table - print(ggarrange(p1, t1, ncol=1, heights=c(0.85, 0.15))) - # Add extra space at the end to prevent the next figure from being too - # close. - cat(" \n") - - # Included Programs - program_table <- data %>% - filter(ManagedAreaName == ma) %>% - group_by(ProgramID) %>% - mutate(YearMin = min(Year), - YearMax = max(Year), - N_Data = length(ResultValue)) %>% - distinct(ProgramID, ProgramName, N_Data, YearMin, YearMax) %>% - select(ProgramID, ProgramName, N_Data, YearMin, YearMax) %>% - arrange(desc(N_Data)) - - program_kable <- kable(program_table %>% select(-ProgramName), - format="simple", - caption=paste0("Programs contributing data for ", parameter)) - - print(program_kable) - cat(" \n") - - # program names listed below (accounting for long names) - program_ids <- unique(program_table$ProgramID) - - cat("\n **Program names:** \n \n") - - # Display ProgramName below data table - for (p_id in program_ids) { - p_name <- program_table %>% filter(ProgramID == p_id) %>% pull(ProgramName) - cat(paste0("*",p_id,"*", " - ",p_name, " \n")) - } - - cat(" \n") - - rm(plot_data, program_kable, program_table) - rm(MA_YM_Stats) - # rm(KT.Plot) - rm(skt_stats) - } -} - -## Boxplots function ## -plot_boxplots <- function(p, a, d, activity_label, depth_label, y_labels, parameter, data) { - # data <- as.data.frame(load_data_table(p, a, d, "data")) - - plot_title <- paste0(parameter,", ",activity_label, ", ",depth_label) - - # Determine upper and lower bounds of time for x-axis - plot_data <- data[data$Include==TRUE & - data$ManagedAreaName==ma,] - # plot_data <- data[data$ManagedAreaName==ma,] - year_lower <- min(plot_data$Year) - year_upper <- max(plot_data$Year) - - # Determine upper and lower bounds of ResultValue for y-axis - min_RV <- min(plot_data$ResultValue) - mn_RV <- mean(plot_data$ResultValue[plot_data$ResultValue < - quantile(data$ResultValue, 0.98)]) - sd_RV <- sd(plot_data$ResultValue[plot_data$ResultValue < - quantile(data$ResultValue, 0.98)]) - # Sets x- and y-axis scale - x_scale <- ifelse(year_upper - year_lower > 30, 10, 5) - y_scale <- mn_RV + 4 * sd_RV - - ##Year plots - # Create plot object for auto-scaled y-axis plot - p1 <- ggplot(data=plot_data, - aes(x=Year, y=ResultValue, group=Year)) + - geom_boxplot(color="#333333", fill="#cccccc", outlier.shape=21, - outlier.size=3, outlier.color="#333333", - outlier.fill="#cccccc", outlier.alpha=0.75) + - labs(subtitle="By Year", - x="Year", y=y_labels) + - scale_x_continuous(limits=c(year_lower - 1, year_upper + 1), - breaks=rev(seq(year_upper, - year_lower, -x_scale))) + - plot_theme - - p4 <- ggplot(data=plot_data, - aes(x=YearMonthDec, y=ResultValue, - group=YearMonth, color=as.factor(Month))) + - geom_boxplot(fill="#cccccc", outlier.size=1.5, outlier.alpha=0.75) + - labs(subtitle="By Year and Month", - x="Year", y=y_labels, color="Month") + - scale_x_continuous(limits=c(year_lower - 1, year_upper + 1), - breaks=rev(seq(year_upper, - year_lower, -x_scale))) + - plot_theme + - theme(legend.position="none") - - # Month Plots - # Create plot object for auto-scaled y-axis plot - p7 <- ggplot(data=plot_data, - aes(x=Month, y=ResultValue, - group=Month, fill=as.factor(Month))) + - geom_boxplot(color="#333333", outlier.shape=21, outlier.size=3, - outlier.color="#333333", outlier.alpha=0.75) + - labs(subtitle="By Month", - x="Month", y=y_labels, fill="Month") + - scale_x_continuous(limits=c(0, 13), breaks=seq(3, 12, 3)) + - plot_theme + - theme(legend.position="none", - axis.text.x=element_text(angle = 0, hjust = 1)) - - set <- ggarrange(p1 + rremove("ylab"), p4 + rremove("ylab"), p7 + rremove("ylab"), ncol=1) - - p0 <- ggplot() + labs(title=plot_title, - subtitle=ma) + - plot_theme + - theme(panel.border=element_blank(), panel.grid.major=element_blank(), - panel.grid.minor=element_blank(), axis.line=element_blank()) - - annotate_figure(p0, left = textGrob(y_labels, rot = 90, vjust = 1, gp = gpar(cex = 1.3))) - - # Arrange title on plots - Yset <- ggarrange(p0, set, ncol=1, heights=c(0.07, 1)) - Yset_annotated <- annotate_figure(Yset, - left = text_grob(y_labels, rot = 90, family = "Arial", size = 10)) - - print(Yset_annotated) - - rm(plot_data) - rm(p1, p4, p7, p0, Yset, Yset_annotated) -} - -## VQ Summary Barplot ## -plot_vq_barplot <- function(p, a, d, activity_label, depth_label, y_labels, parameter, data) { - - VQ_Summary <- as.data.frame(load_data_table(p, a, d, "VQSummary")) - - # Filter and subset dataframe for managed area - ma_vq_summary <- VQ_Summary %>% filter(ManagedAreaName == ma) - - # VQSummary conditions for qualifying VQ values - vq_condition <- ma_vq_summary$N_H !=0 | ma_vq_summary$N_I != 0 | ma_vq_summary$N_Q != 0 | ma_vq_summary$N_S != 0 | ma_vq_summary$N_U != 0 - - # apply VQ_conditions to subset dataframe - filtered_vq <- ma_vq_summary[vq_condition, ] - - # check to see if there are any qualifying VQ values, if not, skip - if (nrow(filtered_vq) != 0) { - - # select respective perc_vq columns - plot_data <- filtered_vq %>% - dplyr::select(Year, N_Total, N_H, perc_H, N_I, perc_I, N_Q, perc_Q, N_S, perc_S, N_U, perc_U) %>% - dplyr::mutate_if(is.numeric, round, 2) - - # show only relevant columns for table display - plot_data <- plot_data %>% - dplyr::select(-where(~ all(. == 0))) - - # convert data format to "long" for plotting - plot_data_long <- tidyr::pivot_longer(plot_data, - cols = starts_with("perc_"), - names_to = "Category", - values_to = "Percentage") - - # remove values when their VQ not included - plot_data_long <- plot_data_long %>% - dplyr::filter(Percentage != 0) - - # set year bounds for upper and lower - year_lower <- min(plot_data_long$Year) - year_upper <- max(plot_data_long$Year) - - # Use similar x-scaling to previous charts # may change - x_scale <- ifelse(year_upper - year_lower > 30, 10, - ifelse(year_upper == year_lower, 1, 3)) - - # set title label - lab_title <- paste0("Percentage Distribution of Value Qualifiers by year for ", d," Depths - ", parameter) - - # plot results - vq_plot <- ggplot(plot_data_long, aes(x=Year, y=Percentage, fill=Category)) + - geom_bar(stat = "identity", position="stack") + - labs(title = lab_title, - subtitle = paste(ma), - x = "Year", - y = "Percentage") + - ylim(0, 100) + - scale_x_continuous(limits=c(year_lower - 1, year_upper + 1), - breaks=rev(seq(year_upper, - year_lower, -x_scale))) + - scale_fill_manual(values=c("#00ADAE","#65CCB3","#AEE4C1","#FDE8A8","#F8CD6D"), - breaks=c("perc_H","perc_I","perc_Q","perc_S","perc_U"), - labels=c("H", "I", "Q", "S", "U")) + - plot_theme - - # print plots - print(vq_plot) - - # Replace 0 values with NA, to be modified to empty string with kable function - plot_data[plot_data == 0] <- NA - options(knitr.kable.NA = "") - - # add text table beneath plot - vq_table <- kable(plot_data, - format="simple", - digits = 1, - caption=paste0("Value Qualifiers for ", parameter)) %>% - kable_styling(latex_options="scale_down", - position = "center") - - cat(" \n") - print(vq_table) - - # list of programs with VQ data - vq <- data %>% - filter(Include==TRUE, ManagedAreaName==ma, ValueQualifier!="NA") %>% - select(ProgramID, ProgramName) - - vq_program_id <- unique(vq$ProgramID) - - cat("\n **Programs containing Value Qualified data:** \n \n") - - # Display ProgramName below data table - for (p_id in vq_program_id) { - p_name <- unlist(unique(vq %>% filter(ProgramID == p_id) %>% select(ProgramName))) - cat(paste0("*",p_id,"*", " - ",p_name, " \n")) - } - - cat(" \n") - - # add description for each VQ shown - vq <- list("N_H","N_I","N_Q","N_S","N_U") - vq_desc <- list("H - Value based on field kit determiniation; results may not be accurate. - This code shall be used if a field screening test (e.g., field gas chromatograph data, - immunoassay, or vendor-supplied field kit) was used to generate the value and the field - kit or method has not been recognized by the Department as equivalent to laboratory methods.", - - "I - The reported value is greater than or equal to the laboratory method detection - limit but less than the laboratory practical quantitation limit.", - - "Q - Sample held beyond the accepted holding time. This code shall be used if the value is derived - from a sample that was prepared or analyzed after the approved holding time restrictions for sample - preparation or analysis.", - - "S - Secchi disk visible to bottom of waterbody. The value reported is the depth of the waterbody - at the location of the Secchi disk measurement.", - - "U - Indicates that the compound was analyzed for but not detected. This symbol shall be used to indicate - that the specified component was not detected. The value associated with the - qualifier shall be the laboratory method detection limit. Unless requested by the client, - less than the method detection limit values shall not be reported ") - - vq_list <- setNames(as.list(vq_desc), vq) - - cat(" \n") - cat("**Value Qualifiers** \n \n") - cat(" \n") - - # loop to add description if the corresponding VQ is listed above - for (vq in names(vq_list)) { - if (vq %in% names(plot_data)) { - cat(unlist(vq_list[vq]), sep = '\n') - cat("\n") - } - } - - rm(VQ_Summary, filtered_vq, plot_data, plot_data_long, vq_plot) - } else { - cat(paste0("There are no qualifying Value Qualifiers for ", parameter, " in ", ma)) - cat("\n \n \n") - } -} \ No newline at end of file diff --git a/MA Report Generation/WQ_Discrete_Data_Creation.R b/MA Report Generation/WQ_Discrete_Data_Creation.R deleted file mode 100644 index 2b40f8a2..00000000 --- a/MA Report Generation/WQ_Discrete_Data_Creation.R +++ /dev/null @@ -1,725 +0,0 @@ -# The purpose of this script is to generate modular .Rds files for each relevant combination of -# parameter, relative depth, and activity type for discrete WC data. -# Originally created by J.E. Panzik (jepanzik@usf.edu) for SEACAR -# Modified by T.G. Hill (Tyler.Hill@FloridaDEP.gov) in August, 2023 - - -## WHEN RUNNING IN RSTUDIO: -## Set working directory to "Source File Location" in "Session" menu -Start_time <- Sys.time() - -#Load libraries -library(data.table) -library(knitr) -library(readr) -library(dplyr) -library(lubridate) -library(rstudioapi) -library(tictoc) -library(ggplot2) -library(ggpubr) -library(scales) -library(EnvStats) -library(tidyr) -library(kableExtra) - -# Gets directory of this script and sets it as the working directory -wd <- dirname(getActiveDocumentContext()$path) -setwd(wd) - -tic() -#Sets whether to run documents with plots or not (APP_Plots==TRUE to include plots) -APP_Plots <- TRUE - -#Set output directory -out_dir <- "output" - -#Set number of unique years a location must have to be considered for analysis -suff_years <- 10 - -#Sets the list of parameter names to cycle through. This can be edited to limit the number of parameters. -#Easiest way to edit is to comment out undesired parameters. -#If only one parameter is desired, comment out all other parameters and delete comma after remaining parameter -all_params <- c( - "Chlorophyll_a_corrected_for_pheophytin", - "Chlorophyll_a_uncorrected_for_pheophytin", - "Colored_dissolved_organic_matter_CDOM", - "Dissolved_Oxygen", - "Dissolved_Oxygen_Saturation", - "pH", - "Salinity", - "Secchi_Depth", - "Total_Nitrogen", - "Total_Phosphorus", - "Total_Suspended_Solids_TSS", - "Turbidity", - "Water_Temperature" -) - -#Sets the list of parameter abbreviation names to cycle through. This can be edited to limit the number of parameters. -#Easiest way to edit is to comment out undesired parameters. -#If only one parameter is desired, comment out all other parameters and delete comma after remaining parameter -all_params_short <- c( - "ChlaC", - "Chla", - "CDOM", - "DO", - "DOS", - "pH", - "Sal", - "Secchi", - "TN", - "TP", - "TSS", - "Turb", - "TempW" -) - -#Sets the list of relative depths to cycle through. This can be edited to limit the number of depths. -#If only one depth is desired, comment out the other depth and delete comma after remaining depth -all_depths <- c( - "Surface", - "Bottom", - "All" -) - -#Sets the list of activity types to cycle through. This can be edited to limit the number of types. -#If only one type is desired, comment out the other type and delete comma after remaining type -all_activity <- c( - "Field", - "Lab", - "All" -) - -#Loads data file with list on managed area names and corresponding area IDs and short names -MA_All <- fread("data/ManagedArea.csv", sep = ",", header = TRUE, stringsAsFactors = FALSE, - na.strings = "") - -# Creates folders for outputs -folder_paths <- c("output/tables/disc") -for (path in folder_paths) {if(!dir.exists(path)){dir.create(path)}} - -# Defines standard plot theme: black and white, no major or minor grid lines, -# Arial font. Title is centered, size 12, and blue (hex coded). Subtitle is -# centered, size 10, and blue (hex coded). Legend title is size 10 and the -# legend is left-justified. X-axis title is size 10 and the margins are padded -# at the top and bottom to give more space for angled axis labels. Y-axis title -# is size 10 and margins are padded on the right side to give more space for -# axis labels. Axis labels are size 10 and the x-axis labels are rotated -45 -# degrees with a horizontal justification that aligns them with the tick mark -plot_theme <- theme_bw() + - theme(panel.grid.major = element_blank(), - panel.grid.minor = element_blank(), - text=element_text(family="Arial"), - plot.title=element_text(hjust=0.5, size=12, color="#314963"), - plot.subtitle=element_text(hjust=0.5, size=10, color="#314963"), - legend.title=element_text(size=10), - legend.text.align = 0, - axis.title.x = element_text(size=10, margin = margin(t = 5, r = 0, - b = 10, l = 0)), - axis.title.y = element_text(size=10, margin = margin(t = 0, r = 10, - b = 0, l = 0)), - axis.text=element_text(size=10), - axis.text.x=element_text(angle = 60, hjust = 1)) - -disc_file_list <- list() - -#Starts for loop that cycles through each parameter -for (j in 1:length(all_params)){ - param_name <- all_params[j] - param_abrev <- all_params_short[j] - print(paste0("Starting parameter: ", param_name)) - #Gets the file with the filename containing the desired parameter - file_in <- list.files("data/disc", pattern=param_name, full=TRUE) - - #Since Dissolved_Oxygen will return both Dissolved_Oxygen and Dissolved_Oxygen_Saturation, - #the if statement removes the entry for Dissolved_Oxygen_Saturation when trying to get Dissolved_Oxygen - if(param_name=="Dissolved_Oxygen" & length(grep("Saturation", file_in))>0){ - file_in <- file_in[-grep("Saturation", file_in)] - } - - # shortened filenames for display in report - file_short <- sub("data/disc/", "", file_in) - # append filenames to disc_file_list - disc_file_list[[param_abrev]] <- file_short - - # output directory (discrete) - out_dir_tables <- paste0(out_dir, "/tables/disc") - - #Starts for loop that cycles through each depth - for (depth in all_depths){ - #Because secchi depth is does not have a bottom measurement, this statement skips - #Secchi depth for bottom - if (param_name=="Secchi_Depth" & (depth=="Bottom" | depth=="All")){ - next - } - - #Starts for loop that cycles through activity types. - for (activity in all_activity){ - #Skips Field loops for parameters that only have Lab measurements - if ((param_name=="Chlorophyll_a_corrected_for_pheophytin" | - param_name=="Chlorophyll_a_uncorrected_for_pheophytin" | - param_name=="Colored_dissolved_organic_matter_CDOM" | - param_name=="Total_Nitrogen" | - param_name=="Total_Phosphorus" | - param_name=="Total_Suspended_Solids_TSS") & activity=="Field") { - next - #Skips Lab loops for parameters that only have Field measurements - } else if ((param_name=="Dissolved_Oxygen" | - param_name=="Dissolved_Oxygen_Saturation" | - param_name=="pH" | - param_name=="Secchi_Depth" | - param_name=="Water_Temperature") & activity=="Lab") { - next - } else if ((param_name=="Chlorophyll_a_corrected_for_pheophytin" | - param_name=="Chlorophyll_a_uncorrected_for_pheophytin" | - param_name=="Colored_dissolved_organic_matter_CDOM" | - param_name=="Dissolved_Oxygen" | - param_name=="Dissolved_Oxygen_Saturation" | - param_name=="pH" | - param_name=="Secchi_Depth" | - param_name=="Total_Nitrogen" | - param_name=="Total_Phosphorus" | - param_name=="Water_Temperature") & activity=="All") { - next - } - - ########################### - ### BEGIN DATA CREATION ### - ########################### - - ################### - ### FILE IMPORT ### - ################### - - data <- fread(file_in, sep="|", header=TRUE, stringsAsFactors=FALSE, - select=c("ManagedAreaName", "ProgramID", "ProgramName", - "ProgramLocationID", "SampleDate", "Year", "Month", - "RelativeDepth", "ActivityType", "ParameterName", - "ResultValue", "ParameterUnits", "ValueQualifier", - "SEACAR_QAQCFlagCode", "Include"), - na.strings=c("NULL","","NA")) - - parameter <- unique(data$ParameterName) - unit <- unique(data$ParameterUnits) - cat(paste("The data file(s) used:", file_short, sep="\n")) - - ################# - ### FILTERING ### - ################# - - # Removes data rows with missing ResultValue - data <- data[!is.na(data$ResultValue),] - # Changes "Sample" to "Lab" for ActivityType - data$ActivityType <- gsub("Sample", "Lab", data$ActivityType) - - # Gets data for the specific activity type if it is not All - if(activity!="All"){ - data <- data[grep(activity, data$ActivityType),] - } - - # Changes RelativeDepth to Bottom for the QAQC flag 12Q that indicates - # measurements are both surface and bottom if the relative depth is bottom - if(depth=="Bottom"){ - data$RelativeDepth[grep("12Q", data$SEACAR_QAQCFlagCode[ - data$RelativeDepth=="Surface"])] <- "Bottom" - } - # Removes missing RelativeDepth data and data for RelativeDepth not of interest - # from all parameters except Secchi_Depth - if(param_name!="Secchi_Depth" & depth!="All"){ - data <- data[!is.na(data$RelativeDepth),] - data <- data[data$RelativeDepth==depth,] - } - - # Removes data rows that have "Blank" as an ActivityType - if(length(grep("Blank", data$ActivityType))>0){ - data <- data[-grep("Blank", data$ActivityType),] - } - - # Removes data rows with ResultValue below 0, or -2 for Water_Temperature - if(param_name=="Water_Temperature"){ - data <- data[data$ResultValue>=-2,] - } else{ - data <- data[data$ResultValue>=0,] - } - # Changes Include to be either TRUE or FALSE - data$Include <- as.logical(data$Include) - # Changes Include to be TRUE for ProgramID 476 if it had the H value qualifier - data$Include[grep("H", data$ValueQualifier[data$ProgramID==476])] <- TRUE - # Change Include to be FALSE for Secchi_Depth with U value qualifier - if(param_name=="Secchi_Depth"){ - data$Include[grep("U", data$ValueQualifier)] <- FALSE - } - # Gets AreaID for data by merging data with the managed area list - data <- merge.data.frame(MA_All[,c("AreaID", "ManagedAreaName")], - data, by="ManagedAreaName", all=TRUE) - # Creates function to checks managed area for at least 2 years of - # continuous consecutive data - DiscreteConsecutiveCheck <- function(con_data){ - # Gets AreaIDs - IDs <- unique(con_data$AreaID[con_data$Include==TRUE & - !is.na(con_data$Include)]) - # Loops through each AreaID - for(i in 1:length(IDs)) { - # Gets list of Years for AreaID - Years <- unique(con_data$Year[con_data$AreaID==IDs[i] & - con_data$Include==TRUE & - !is.na(con_data$Include)]) - # Puts Years in order - Years <- Years[order(Years)] - # If there are fewer than 2 years, skip to next AreaID - if(length(Years)<2) { - next - } - # Starts loop to make sure there are at least 2 consecutive years - # with consecutive months of data - for(j in 2:length(Years)) { - # If adjacent year entries are not 1 year apart, skip to the - # next set of year entries - if(Years[j]-Years[j-1]!=1) { - next - } - # Gets the list of months from the first year - Months1 <- unique(con_data$Month[ - con_data$AreaID==IDs[i] & - con_data$Year==Years[j-1] & - con_data$Include==TRUE & - !is.na(con_data$Include)]) - # Gets list of months for the second year - Months2 <- unique(con_data$Month[ - con_data$AreaID==IDs[i] & - con_data$Year==Years[j] & - con_data$Include==TRUE & - !is.na(con_data$Include)]) - # If there are more than 2 months shared between the two - # years, the AreaID passes the check and is stored - if(length(intersect(Months1, Months2))>=2) { - # Creates variable for stored AreaID if it - # doesn't exist - if(exists("consecutive")==FALSE){ - consecutive <- IDs[i] - break - # Adds to variable for storing AreaID if does exist - } else{ - consecutive <- append(consecutive, IDs[i]) - break - } - } - } - } - # After going through all AreaID, return variable with list of all - # that pass - return(consecutive) - } - # Stores the AreaID that pass the consecutive year check - consMonthIDs <- DiscreteConsecutiveCheck(data) - - # Creates data frame with summary for each managed area - MA_Summ <- data %>% - group_by(AreaID, ManagedAreaName) %>% - summarize(ParameterName=parameter, - RelativeDepth=depth, - ActivityType=activity, - N_Data=length(ResultValue[Include==TRUE & !is.na(ResultValue)]), - N_Years=length(unique(Year[Include==TRUE & !is.na(Year)])), - EarliestYear=min(Year[Include==TRUE & N_Data!=0]), - LatestYear=max(Year[Include==TRUE & N_Data!=0]), - EarliestSampleDate=min(SampleDate[Include==TRUE]), - LastSampleDate=max(SampleDate[Include==TRUE]), - ConsecutiveMonths=ifelse(unique(AreaID) %in% - consMonthIDs==TRUE, TRUE, FALSE), - # Determines if monitoring location is sufficient for analysis - # based on having more than 0 data entries, more than the - # sufficient number of year, and the consecutive month criteria - SufficientData=ifelse(N_Data>0 & N_Years>=suff_years & - ConsecutiveMonths==TRUE, TRUE, FALSE), - Median=median(ResultValue[Include==TRUE & N_Data!=0], na.rm=TRUE)) - - MA_Summ$ConsecutiveMonths <- NULL - # Creates column in data that determines how many years from the start for each - # managed area - data <- data %>% - group_by(AreaID, ManagedAreaName) %>% - mutate(YearFromStart=Year-min(Year)) - # Adds SufficientData column to data table based on managed area - data <- merge.data.frame(data, MA_Summ[,c("ManagedAreaName", "SufficientData")], - by="ManagedAreaName") - # Creates Use_In_Analysis column for data that is determined if the row has - # Include value of TRUE and SufficientData value of TRUE - data$Use_In_Analysis <- ifelse(data$Include==TRUE & data$SufficientData==TRUE, - TRUE, FALSE) - # Rearranges the summary data frame columns to be AreaID, ManagedAreaName, - # ParameterName RelativeDepth, ActivityType, SufficientData, everything else - MA_Summ <- MA_Summ %>% - select(AreaID, ManagedAreaName, ParameterName, RelativeDepth, ActivityType, - SufficientData, everything()) - # Puts summary data in order based on managed area - MA_Summ <- as.data.frame(MA_Summ[order(MA_Summ$ManagedAreaName), ]) - # Put SampleDate as date object - data$SampleDate <- as.Date(data$SampleDate) - # Creates character object for Month and Year - data$YearMonth <- paste0(data$Month, "-", data$Year) - # Creates variable that puts year and month into a decimal year format - data$YearMonthDec <- data$Year + ((data$Month-0.5) / 12) - # Converts ampleDate to a decimal date - data$DecDate <- decimal_date(data$SampleDate) - - # Get list of and number of managed areas that are to be used in analysis - MA_Include <- MA_Summ$ManagedAreaName[MA_Summ$SufficientData==TRUE] - - saveRDS(MA_Include, file = paste0(out_dir_tables,"/WC_Discrete_", param_abrev, "_", activity, "_", depth, "_MA_Include.rds")) - - ################################# - # MA_Include <- MA_Include[c(1,2)] - ################################# - - n <- length(MA_Include) - # Get list of and number of managed areas that are excluded from analysis - MA_Exclude <- MA_Summ[MA_Summ$N_Years<10 & MA_Summ$N_Years>0,] - MA_Exclude <- MA_Exclude[,c("ManagedAreaName", "N_Years")] - z <- nrow(MA_Exclude) - - ################################ - ### DETERMING ValueQualifers ### - ################################ - - # Find out how much total data exists and how much passed the initial filters - total <- length(data$Include) - pass_filter <- length(data$Include[data$Include==TRUE]) - # Get the number and percentage of data entries impacted by value qualifier H - count_H <- length(grep("H", data$ValueQualifier[data$ProgramID==476])) - perc_H <- 100*count_H/length(data$ValueQualifier) - # Get the number and percentage of data entries impacted by value qualifier I - count_I <- length(grep("I", data$ValueQualifier)) - perc_I <- 100*count_I/length(data$ValueQualifier) - # Get the number and percentage of data entries impacted by value qualifier Q - count_Q <- length(grep("Q", data$ValueQualifier)) - perc_Q <- 100*count_Q/length(data$ValueQualifier) - # Get the number and percentage of data entries impacted by value qualifier S - count_S <- length(grep("S", data$ValueQualifier)) - perc_S <- 100*count_S/length(data$ValueQualifier) - # Get the number and percentage of data entries impacted by value qualifier U - count_U <- length(grep("U", data$ValueQualifier)) - perc_U <- 100*count_U/length(data$ValueQualifier) - # Copy ValueQualifier to a new VQ_Plot to create codes for plots - data$VQ_Plot <- data$ValueQualifier - # Determine if data with value qualifier H should be included for plots based - # on the parameter being observed - inc_H <- ifelse(param_name=="pH" | param_name=="Dissolved_Oxygen" | - param_name=="Dissolved_Oxygen_Saturation", TRUE, FALSE) - # Loops through conditions to determine what indicators to include in plots. - # If H should be included - if (inc_H==TRUE){ - # Remove any Value qualifiers that aren't H or U - data$VQ_Plot <- gsub("[^HU]+", "", data$VQ_Plot) - # Standardize order of qualifiers. Puts UH as HU - data$VQ_Plot <- gsub("UH", "HU", data$VQ_Plot) - # Remove anything from ValueQualifier that isn't U from programs and that - # aren't ProgramID 476 - data$VQ_Plot[na.omit(data$ProgramID!=476)] <- - gsub("[^U]+", "", data$VQ_Plot[na.omit(data$ProgramID!=476)]) - # Changes blank character strings to NA - data$VQ_Plot[data$VQ_Plot==""] <- NA - # Prints the number and percentage of H, I, Q, U value qualifiers - cat(paste0("Number of Measurements: ", total, - ", Number Passed Filter: ", pass_filter, "\n", - "Program 476 H Codes: ", count_H, " (", round(perc_H, 6), "%)\n", - "I Codes: ", count_I, " (", round(perc_I, 6), "%)\n", - "Q Codes: ", count_Q, " (", round(perc_Q, 6), "%)\n", - "U Codes: ", count_U, " (", round(perc_U, 6), "%)")) - # If Parameter is Secchi_Depth - } else if (param_name=="Secchi_Depth") { - # Count the number of S ValueQualifier - count_S <- length(grep("S", data$ValueQualifier)) - # Get percentage of S ValueQualifier - perc_S <- 100*count_S/length(data$ValueQualifier) - # Remove anything from ValueQualifier that isn't S or U - data$VQ_Plot <- gsub("[^SU]+", "", data$VQ_Plot) - # Change all ValueQualifier that are US to be US, standardizes codes - data$VQ_Plot <- gsub("US", "SU", data$VQ_Plot) - # Sets any blank character ValueQualifier to be NA - data$VQ_Plot[data$VQ_Plot==""] <- NA - # Prints the number and percentage of I, Q, S, U - cat(paste0("Number of Measurements: ", total, - ", Number Passed Filter: ", pass_filter, "\n", - "I Codes: ", count_I, " (", round(perc_I, 6), "%)\n", - "Q Codes: ", count_Q, " (", round(perc_Q, 6), "%)\n", - "S Codes: ", count_S, " (", round(perc_S, 6), "%)\n", - "U Codes: ", count_U, " (", round(perc_U, 6), "%)")) - # For all other scenarios - } else{ - # Remove all ValueQualifier except U - data$VQ_Plot <- gsub("[^U]+", "", data$VQ_Plot) - # Sets any blank character ValueQualifier to be NA - data$VQ_Plot[data$VQ_Plot==""] <- NA - # Prints the number and percentage of I, Q, U - cat(paste0("Number of Measurements: ", total, - ", Number Passed Filter: ", pass_filter, "\n", - "I Codes: ", count_I, " (", round(perc_I, 6), "%)\n", - "Q Codes: ", count_Q, " (", round(perc_Q, 6), "%)\n", - "U Codes: ", count_U, " (", round(perc_U, 6), "%)")) - } - # Creates a data table that summarizes the number and percentage of - # ValueQualifier H, I, Q, S, and U for each managed area each year - data_summ <- data %>% - group_by(AreaID, ManagedAreaName, Year) %>% - summarize(ParameterName=parameter, - RelativeDepth=depth, - ActivityType=activity, - N_Total=length(ResultValue), - N_AnalysisUse=length(ResultValue[Use_In_Analysis==TRUE]), - N_H=length(grep("H", ValueQualifier[ProgramID==476])), - perc_H=100*N_H/length(ValueQualifier), - N_I=length(grep("I", ValueQualifier)), - perc_I=100*N_I/length(ValueQualifier), - N_Q=length(grep("Q", ValueQualifier)), - perc_Q=100*N_Q/length(ValueQualifier), - N_S=length(grep("S", ValueQualifier)), - perc_S=100*N_S/length(ValueQualifier), - N_U=length(grep("U", ValueQualifier)), - perc_U=100*N_U/length(ValueQualifier)) - # Orders the data table rows based on managed area name - data_summ <- as.data.table(data_summ[order(data_summ$ManagedAreaName, - data_summ$Year), ]) - # Writes the ValueQualifier summary to a RDS file - print("Saving data_summ.rds") - saveRDS(data_summ, file = paste0(out_dir_tables,"/WC_Discrete_", param_abrev, "_", activity, "_", depth, "_VQSummary.rds")) - - rm(data_summ) - - ############################### - ### MANAGED AREA STATISTICS ### - ############################### - - # Create summary statistics for each managed area based on Year and Month - # intervals. - MA_YM_Stats <- data[data$Use_In_Analysis==TRUE, ] %>% - group_by(AreaID, ManagedAreaName, Year, Month) %>% - summarize(ParameterName=parameter, - RelativeDepth=depth, - ActivityType=activity, - N_Data=length(ResultValue), - Min=min(ResultValue), - Max=max(ResultValue), - Median=median(ResultValue), - Mean=mean(ResultValue), - StandardDeviation=sd(ResultValue), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName, Year, then Month - MA_YM_Stats <- as.data.table(MA_YM_Stats[order(MA_YM_Stats$ManagedAreaName, - MA_YM_Stats$Year, - MA_YM_Stats$Month), ]) - - # Get year from start for each managed area to be used in SKT analysis - MA_YM_Stats <- MA_YM_Stats %>% - group_by(AreaID, ManagedAreaName) %>% - mutate(YearFromStart=Year-min(Year)) - # Create decimal value of year and month values - MA_YM_Stats$YearMonthDec <- MA_YM_Stats$Year + ((MA_YM_Stats$Month-0.5) / 12) - - # Writes summary statistics to file - print("Saving MA_YM_Stats.rds") - saveRDS(MA_YM_Stats, file = paste0(out_dir_tables,"/WC_Discrete_", param_abrev, "_", activity, "_", depth, "_MA_MMYY_Stats.rds")) - - # Create summary statistics for each managed area based on Year intervals. - MA_Y_Stats <- data[data$Use_In_Analysis==TRUE, ] %>% - group_by(AreaID, ManagedAreaName, Year) %>% - summarize(ParameterName=parameter, - RelativeDepth=depth, - ActivityType=activity, - N_Data=length(ResultValue), - Min=min(ResultValue), - Max=max(ResultValue), - Median=median(ResultValue), - Mean=mean(ResultValue), - StandardDeviation=sd(ResultValue), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName then Year - MA_Y_Stats <- as.data.table(MA_Y_Stats[order(MA_Y_Stats$ManagedAreaName, - MA_Y_Stats$Year), ]) - # Writes summary statistics to file - - print("Saving MA_Y_Stats.rds") - saveRDS(MA_Y_Stats, file = paste0(out_dir_tables,"/WC_Discrete_", param_abrev, "_", activity, "_", depth, "_MA_Yr_Stats.rds")) - rm(MA_Y_Stats) - - # Create summary statistics for each managed area based on Month intervals. - MA_M_Stats <- data[data$Use_In_Analysis==TRUE, ] %>% - group_by(AreaID, ManagedAreaName, Month) %>% - summarize(ParameterName=parameter, - RelativeDepth=depth, - ActivityType=activity, - N_Data=length(ResultValue), - Min=min(ResultValue), - Max=max(ResultValue), - Median=median(ResultValue), - Mean=mean(ResultValue), - StandardDeviation=sd(ResultValue), - Programs=paste(sort(unique(ProgramName), decreasing=FALSE), - collapse=', '), - ProgramIDs=paste(sort(unique(ProgramID), decreasing=FALSE), - collapse=', ')) - # Puts the data in order based on ManagedAreaName then Month - MA_M_Stats <- as.data.table(MA_M_Stats[order(MA_M_Stats$ManagedAreaName, - MA_M_Stats$Month), ]) - # Writes summary statistics to file - - print("Saving MA_M_Stats.rds") - saveRDS(MA_M_Stats, file = paste0(out_dir_tables,"/WC_Discrete_", param_abrev, "_", activity, "_", depth, "_MA_Mo_Stats.rds")) - rm(MA_M_Stats) - - ################################# - ### MONITORING LOCATION STATS ### - ################################# - - # Gets summary statistics for monitoring locations, which are defined as unique - # combinations of ManagedAreaName, ProgramID, And ProgramLocationID - Mon_Stats <- data[data$Use_In_Analysis==TRUE, ] %>% - group_by(AreaID, ManagedAreaName, ProgramID, ProgramName, - ProgramLocationID) %>% - summarize(ParameterName=parameter, - RelativeDepth=depth, - ActivityType=activity, - EarliestSampleDate=min(SampleDate), - LastSampleDate=max(SampleDate), - N_Data=length(ResultValue), - Min=min(ResultValue), - Max=max(ResultValue), - Median=median(ResultValue), - Mean=mean(ResultValue), - StandardDeviation=sd(ResultValue)) - # Order data rows by ManagedAreaName, ProgramName, ProgramID, then - # ProgramLocationID - Mon_Stats <- as.data.table(Mon_Stats[order(Mon_Stats$ManagedAreaName, - Mon_Stats$ProgramName, - Mon_Stats$ProgramID, - Mon_Stats$ProgramLocationID), ]) - # Write summary statistics to file - print("Saving Mon_Stats.rds") - saveRDS(Mon_Stats, file = paste0(out_dir_tables,"/WC_Discrete_", param_abrev, "_", activity, "_", depth, "_MonLoc_Stats.rds")) - rm(Mon_Stats) - - #################### - ### SKT ANALYSIS ### - #################### - - # List for column names - c_names <- c("AreaID", "ManagedAreaName", "Independent", "tau", "p", - "SennSlope", "SennIntercept", "ChiSquared", "pChiSquared", "Trend") - - skt_stats <- data.frame(matrix(ncol = length(c_names), nrow = n)) - - colnames(skt_stats) <- c_names - # Determines if there are any managed areas to analyze - if(n==0){ - print("There are no managed areas that qualify.") - } else{ - # Starts cycling through managed areas to determine seasonal Kendall Tau - for (i in 1:n) { - # Gets the number of rows of data for the managed area - data_SKT <- MA_YM_Stats[MA_YM_Stats$ManagedAreaName==MA_Include[i], ] - x <- nrow(data_SKT) - # Perform analysis if there is more than 1 row - if (x>0) { - # Store the managed area summary statistics to be used in - # trend analysis - SKT.med <- MA_Summ$Median[MA_Summ$ManagedAreaName==MA_Include[i]] - SKT.minYr <- MA_Summ$EarliestYear[MA_Summ$ManagedAreaName==MA_Include[i]] - SKT.maxYr <- MA_Summ$LatestYear[MA_Summ$ManagedAreaName==MA_Include[i]] - SKT.ind <- TRUE - SKT <- kendallSeasonalTrendTest(y=data_SKT$Mean, - season=data_SKT$Month, - year=data_SKT$YearFromStart, - independent.obs=SKT.ind) - if(is.na(SKT$estimate[1])==TRUE){ - SKT.ind <- FALSE - SKT <- kendallSeasonalTrendTest(y=data_SKT$Mean, - season=data_SKT$Month, - year=data_SKT$YearFromStart, - independent.obs=SKT.ind) - } - skt_stats$AreaID[i] <- - MA_Summ$AreaID[MA_Summ$ManagedAreaName==MA_Include[i]] - skt_stats$ManagedAreaName[i] <- - MA_Summ$ManagedAreaName[MA_Summ$ManagedAreaName==MA_Include[i]] - skt_stats$Independent[i] <- SKT.ind - skt_stats$tau[i] <- SKT$estimate[1] - skt_stats$p[i] <- SKT$p.value[2] - skt_stats$SennSlope[i] <- SKT$estimate[2] - skt_stats$SennIntercept[i] <- SKT$estimate[3] - skt_stats$ChiSquared[i] <- SKT$statistic[1] - skt_stats$pChiSquared[i] <- SKT$p.value[1] - # If the p value is less than 5% and the slope is greater than 10% of the - # median value, the trend is large (2). - if (skt_stats$p[i] < .05 & abs(skt_stats$SennSlope[i]) > - abs(SKT.med) / 10.) { - skt_stats$Trend[i] <- 2 - - # If the p value is less than 5% and the slope is less than 10% of the - # median value, there is a trend (1). - }else if (skt_stats$p[i] < .05 & abs(skt_stats$SennSlope[i]) < - abs(SKT.med) / 10.) { - skt_stats$Trend[i] <- 1 - - # Otherwise, there is no trend (0) - }else { - skt_stats$Trend[i] <- 0 - } - # Sets the sign of the trend based on Senn Slope direction - if (skt_stats$SennSlope[i] <= 0) { - skt_stats$Trend[i] <- -skt_stats$Trend[i] - } - } - } - - # Stores as data frame - skt_stats <- as.data.frame(skt_stats) - - } - # Clears unused variables - rm(SKT, data_SKT, x, SKT.med, SKT.minYr, SKT.maxYr, SKT.ind) - # Combines the skt_stats with MA_Summ - skt_stats <- merge.data.frame(MA_Summ, skt_stats, - by=c("AreaID","ManagedAreaName"), all=TRUE) - - skt_stats <- as.data.table(skt_stats[order(skt_stats$ManagedAreaName), ]) - - # Sets variables to proper format and rounds values if necessary - skt_stats$tau <- round(as.numeric(skt_stats$tau), digits=4) - skt_stats$p <- format(round(as.numeric(skt_stats$p), digits=4), - scientific=FALSE) - skt_stats$SennSlope <- as.numeric(skt_stats$SennSlope) - skt_stats$SennIntercept <- as.numeric(skt_stats$SennIntercept) - skt_stats$ChiSquared <- round(as.numeric(skt_stats$ChiSquared), digits=4) - skt_stats$pChiSquared <- round(as.numeric(skt_stats$pChiSquared), digits=4) - skt_stats$Trend <- as.integer(skt_stats$Trend) - - # Writes combined statistics to file - print("Saving SKT_stats.rds") - - saveRDS(skt_stats, file = paste0(out_dir_tables,"/WC_Discrete_", param_abrev, "_", activity, "_", depth, "_skt_stats.rds")) - saveRDS(select(skt_stats, -c(EarliestSampleDate)), file = paste0(out_dir_tables,"/WC_Discrete_", param_abrev, "_", activity, "_", depth, "_KendallTau_Stats.rds")) - } - } - - # Removes data rows with no ResultValue (created by merging with MA_All) - data <- data[!is.na(data$ResultValue),] - - # saveRDS(KT.Plot, file = paste0(out_dir_tables,"/WC_Discrete_", param_abrev, "_KT_Plot.rds")) - saveRDS(data, file = paste0(out_dir_tables,"/WC_Discrete_", param_abrev, "_data.rds")) -} - -disc_file_list_df <- bind_rows(disc_file_list) -fwrite(disc_file_list_df, "output/tables/disc/disc_file_list.txt", sep='|') - -toc() -End_time <- Sys.time() - -print(Start_time) -print(End_time) \ No newline at end of file diff --git a/MA Report Generation/output/Reports/HTML/BBSAP_Report.html b/MA Report Generation/output/Reports/HTML/BBSAP_Report.html new file mode 100644 index 00000000..d8d8931d --- /dev/null +++ b/MA Report Generation/output/Reports/HTML/BBSAP_Report.html @@ -0,0 +1,5855 @@ + + + + +
+ + + + + + + + +Threshold filters, following the guidance of Florida Department of +Environmental Protection’s (FDEP) Division of Environmental +Assessment and Restoration (DEAR) are used to exclude specific +results values from the SEACAR Analysis. Based on the threshold filters, +Quality Assurance / Quality Control (QAQC) Flags are inserted +into the SEACAR_QAQCFlagCode and +SEACAR_QAQC_Description columns of the export data. The +Include column indicates whether the QAQC Flag will +also indicate that data are excluded from analysis. No data are excluded +from the data export, but the analysis scripts can use the +Include column to exclude data (1 to include, 0 to +exclude).
+Parameter Name | +Units | +Low Threshold | +High Threshold | +Sensor Type | +
---|---|---|---|---|
Dissolved Oxygen | +mg/L | +0 | +50 | +YSI EXOs | +
Dissolved Oxygen | +mg/L | +0 | +50 | +Analysis Only - 2022-04-04 | +
Dissolved Oxygen | +mg/L | +0 | +50 | +6600 Series | +
Salinity | +ppt | +0 | +70 | +6600 Series | +
Salinity | +ppt | +0 | +70 | +YSI EXOs | +
Salinity | +ppt | +0 | +70 | +Analysis Only - 2022-04-04 | +
Water Temperature | +Degrees C | +-5 | +45 | +YSI EXOs | +
Water Temperature | +Degrees C | +-5 | +45 | +Analysis Only - 2022-04-04 | +
Water Temperature | +Degrees C | +-5 | +45 | +6600 Series | +
pH | +pH | +2 | +14 | +Analysis Only - 2022-04-04 | +
pH | +pH | +2 | +14 | +6600 Series | +
pH | +pH | +2 | +14 | +YSI EXOs | +
Dissolved Oxygen Saturation | +% | +0 | +500 | +YSI EXOs | +
Dissolved Oxygen Saturation | +% | +0 | +500 | +6600 Series | +
Dissolved Oxygen Saturation | +% | +0 | +500 | +Analysis Only - 2022-04-04 | +
Specific Conductivity | +mS/cm | +0 | +100 | +6600 Series | +
Specific Conductivity | +mS/cm | +0 | +200 | +YSI EXOs | +
Turbidity | +NTU | +0 | +4000 | +YSI EXOs | +
Turbidity | +NTU | +0 | +1000 | +6600 Series | +
Turbidity | +NTU | +0 | +4000 | +Analysis Only - 2022-04-04 | +
Parameter Name | +Units | +Low Threshold | +High Threshold | +
---|---|---|---|
Dissolved Oxygen | +mg/L | +0.000001 | +22 | +
Salinity | +ppt | +0 | +70 | +
Water Temperature | +Degrees C | +3 | +40 | +
pH | ++ | 2 | +13 | +
Dissolved Oxygen Saturation | +% | +0.000001 | +310 | +
Specific Conductivity | +mS/cm | +0.005000001 | +100 | +
Turbidity | +NTU | +0 | +- | +
Total Suspended Solids (TSS) | +mg/L | +0 | +- | +
Chlorophyll a uncorrected for pheophytin | +ug/L | +0 | +- | +
Chlorophyll a corrected for pheophytin | +ug/L | +0 | +- | +
Secchi Depth | +m | +0.000001 | +50 | +
Light Extinction Coefficient | +m^1 | +0 | +- | +
Colored dissolved organic matter, CDOM | +PCU | +0 | +- | +
Fluorescent dissolved organic matter, FDOM | +QSE | +0 | +- | +
Total Nitrogen | +mg/L | +0 | +- | +
Total Kjeldahl Nitrogen TKN | +mg/L | +0 | +- | +
NO2+3 Filtered | +mg/L | +0 | +- | +
NH4 Filtered | +mg/L | +0 | +- | +
Total Phosphorus | +mg/L | +0 | +- | +
PO4 Filtered | +mg/L | +0 | +- | +
Ammonia- Un-ionized (NH3) | +mg/L | +0 | +- | +
Nitrate (N) | +mg/L | +0 | +- | +
Nitrite (N) | +mg/L | +0 | +- | +
Nitrogen, organic | +mg/L | +0 | +- | +
SEACAR QAQC Description | +Include | +SEACAR QAQCFlagCode | +
---|---|---|
Exceeds Maximum threshold. Not verified in raw +data | +No | +2Q | +
Exceeds Maximum threshold. Verified in raw data | +No | +3Q | +
Below Minimum threshold. Not verified in raw data | +No | +4Q | +
Below Minimum threshold. Verified in raw data | +No | +5Q | +
Within threshold tolerance | +Yes | +6Q | +
No defined thresholds for this parameter | +Yes | +7Q | +
Value qualifier codes included within the data are used to exclude +certain results from the analysis. The data are retained in the data +export files, but the analysis uses the Include column to +filter the results.
+STORET and WIN value qualifier codes
+Value qualifier codes from STORET and WIN data are +examined with the database and used to populate the Include +column in data exports.
+Qualifier Source | +Value Qualifier | +Include | +MDL | +Description | +
---|---|---|---|---|
STORET-WIN | +H | +No | +0 | +Value based on field kit determination; results may not +be accurate | +
STORET-WIN | +J | +No | +0 | +Estimated value | +
STORET-WIN | +V | +No | +0 | +Analyte was detected at or above method detection +limit | +
STORET-WIN | +Y | +No | +0 | ++ |
Discrete Water Quality Value Qualifiers
+The following value qualifiers are highlighted in the Discrete Water +Quality section of this report. An exception is made for Program +476 - Charlotte Harbor Estuaries Volunteer Water Quality +Monitoring Network and data flagged with Value Qualifier +H are included for this program only.
+H - Value based on field kit determiniation; results +may not be accurate. This code shall be used if a field screening test +(e.g., field gas chromatograph data, immunoassay, or vendor-supplied +field kit) was used to generate the value and the field kit or method +has not been recognized by the Department as equivalent to laboratory +methods.
+I - The reported value is greater than or equal to +the laboratory method detection limit but less than the laboratory +practical quantitation limit.
+Q - Sample held beyond the accepted holding time. +This code shall be used if the value is derived from a sample that was +prepared or analyzed after the approved holding time restrictions for +sample preparation or analysis.
+S - Secchi disk visible to bottom of waterbody. The +value reported is the depth of the waterbody at the location of the +Secchi disk measurement.
+U - Indicates that the compound was analyzed for but +not detected. This symbol shall be used to indicate that the specified +component was not detected. The value associated with the qualifier +shall be the laboratory method detection limit. Unless requested by the +client, less than the method detection limit values shall not be +reported
+Systemwide Monitoring Program (SWMP) value qualifier +codes
+Value qualifier codes from the SWMP continuous program are +examined with the database and used to populate the Include +column in data exports. SWMP Qualifier Codes are indicated by +QualifierSource=SWMP.
+Qualifier Source | +Value Qualifier | +Include | +Description | +
---|---|---|---|
SWMP | +-1 | +Yes | +Optional parameter not collected | +
SWMP | +-2 | +No | +Missing data | +
SWMP | +-3 | +No | +Data rejected due to QA/QC | +
SWMP | +-4 | +No | +Outside low sensor range | +
SWMP | +-5 | +No | +Outside high sensor range | +
SWMP | +0 | +Yes | +Passed initial QA/QC checks | +
SWMP | +1 | +No | +Suspect data | +
SWMP | +2 | +Yes | +Reserved for future use | +
SWMP | +3 | +Yes | ++ |
SWMP | +4 | +Yes | +Historical: Pre-auto QA/QC | +
SWMP | +5 | +Yes | +Corrected data | +
The water column habitat extends from the surface of all water bodies +to the bottom sediments and encompasses the different features found in +the water at different depths (National Oceanographic Center, 2016). The +water column habitat must be viewed in relation to its +interconnectedness with other habitats. A healthy water column is an +integral component in ensuring a healthy marine and coastal ecosystem. +Having a flourishing marine and coastal ecosystem in Florida is +necessary to support a strong economy. The health of the water column is +dependent upon factors as diverse as land use (e.g., agriculture, +mining, forestry practices); human population growth; emissions, (e.g., +power plants, automobiles, wastewater); climate (e.g., rainfall, +temperature, winds and currents); and decadal trends (e.g., El Niño/La +Niña, Atlantic Multidecadal Oscillation, climate change).
+The water column is composed of various physical, chemical and +biological features, and only a small number of them are adequately +monitored. Features of the water column that are monitored are used as +indicators of the water column health and help assess the status of +other habitats. These indicators include nutrient concentrations +(nitrogen and phosphorus); water quality (dissolved oxygen, temperature, +salinity and pH); water clarity (Secchi depth, turbidity, chlorophyll-a +and colored dissolved organic matter); and nekton (fish, +macroinvertebrates and megafauna).
+Indicators must have a minimum of five to ten years, depending on the +habitat, of data within the geographic range of the analysis to be +included in the analysis. Ten years of data are required for discrete +parameters, and five years of data are required for continuous +parameters. If there are insufficient years of data, the number of years +of data available will be noted and labeled as “insufficient data to +conduct analysis”. Further, for the preferred Seasonal Kendall-Tau test, +there must be data from at least two months in common across at least +two consecutive years within the RCP managed area being analyzed. Values +that pass both of these tests will be included in the analysis and be +labeled as Use_In_Analysis = TRUE. Any that +fail either test will be excluded from the analyses and labeled as +Use_In_Analysis = FALSE.
+The following files were used in the discrete analysis:
+Combined_WQ_WC_NUT_Chlorophyll_a_corrected_for_pheophytin-2024-Feb-22.txt
Combined_WQ_WC_NUT_Chlorophyll_a_uncorrected_for_pheophytin-2024-Feb-22.txt
Combined_WQ_WC_NUT_Colored_dissolved_organic_matter_CDOM-2024-Feb-22.txt
Combined_WQ_WC_NUT_Dissolved_Oxygen-2024-Feb-22.txt
Combined_WQ_WC_NUT_Dissolved_Oxygen_Saturation-2024-Feb-22.txt
Combined_WQ_WC_NUT_pH-2024-Feb-22.txt
Combined_WQ_WC_NUT_Salinity-2024-Feb-22.txt
Combined_WQ_WC_NUT_Secchi_Depth-2024-Feb-22.txt
Combined_WQ_WC_NUT_Total_Nitrogen-2024-Feb-22.txt
Combined_WQ_WC_NUT_Total_Phosphorus-2024-Feb-22.txt
Combined_WQ_WC_NUT_Total_Suspended_Solids_TSS-2024-Feb-22.txt
Combined_WQ_WC_NUT_Turbidity-2024-Feb-22.txt
Combined_WQ_WC_NUT_Water_Temperature-2024-Feb-22.txt
Chlorophyll-a is monitored as a measure of +microalgae growing in the water. Algae are a natural part of coastal and +aquatic ecosystems but in excess can cause poor water quality and +clarity, and decreased levels of dissolved oxygen.
+Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Chlorophyll a,
+Corrected for Pheophytin
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +3918 | +1995 | +2023 | +
514 | +212 | +2020 | +2023 | +
540 | +131 | +2017 | +2022 | +
477 | +129 | +2019 | +2022 | +
103 | +10 | +2020 | +2021 | +
Program names:
+5002 - Florida STORET / WIN
+514 - Florida LAKEWATCH Program
+540 - Shellfish Harvest Area Classification Program
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
Value Qualifiers
+Year | +N_Total | +N_I | +perc_I | +N_Q | +perc_Q | +N_U | +perc_U | +
---|---|---|---|---|---|---|---|
1999 | +99 | +5 | +5.0 | ++ | + | 10 | +10.1 | +
2000 | +93 | +2 | +2.1 | ++ | + | 46 | +49.5 | +
2001 | +100 | +4 | +4.0 | +3 | +3.0 | +42 | +42.0 | +
2002 | +121 | +4 | +3.3 | +8 | +6.6 | +61 | +50.4 | +
2003 | +53 | +1 | +1.9 | +2 | +3.8 | +52 | +98.1 | +
2004 | +64 | ++ | + | 6 | +9.4 | +61 | +95.3 | +
2005 | +70 | +9 | +12.9 | ++ | + | 45 | +64.3 | +
2006 | +81 | +4 | +4.9 | ++ | + | 73 | +90.1 | +
2007 | +46 | +13 | +28.3 | ++ | + | 19 | +41.3 | +
2008 | +50 | +27 | +54.0 | ++ | + | 13 | +26.0 | +
2009 | +65 | +34 | +52.3 | ++ | + | 22 | +33.9 | +
2010 | +82 | +37 | +45.1 | ++ | + | 35 | +42.7 | +
2011 | +197 | +78 | +39.6 | ++ | + | 23 | +11.7 | +
2012 | +167 | +60 | +35.9 | ++ | + | 33 | +19.8 | +
2013 | +198 | +41 | +20.7 | +22 | +11.1 | +76 | +38.4 | +
2014 | +238 | +43 | +18.1 | +17 | +7.1 | +82 | +34.5 | +
2015 | +203 | +31 | +15.3 | +14 | +6.9 | +83 | +40.9 | +
2016 | +253 | +40 | +15.8 | +13 | +5.1 | +102 | +40.3 | +
2017 | +297 | +85 | +28.6 | +1 | +0.3 | +49 | +16.5 | +
2018 | +365 | +88 | +24.1 | ++ | + | 33 | +9.0 | +
2019 | +220 | +42 | +19.1 | ++ | + | 32 | +14.6 | +
2020 | +228 | +58 | +25.4 | +18 | +7.9 | +83 | +36.4 | +
2021 | +317 | +100 | +31.6 | +28 | +8.8 | +102 | +32.2 | +
2022 | +310 | +78 | +25.2 | +22 | +7.1 | +131 | +42.3 | +
2023 | +125 | +36 | +28.8 | +3 | +2.4 | +24 | +19.2 | +
Note: 1I - Reported +value is greater than or equal to lab method detection limit, but less +than quantitation limit 2Q - Sample held +beyond the accepted holding time 3U - +Compound was analyzed for but not detected
+Programs containing Value Qualified data:
+5002 - Florida STORET / WIN
+514 - Florida LAKEWATCH Program
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+540 - Shellfish Harvest Area Classification Program
Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Chlorophyll a,
+Uncorrected for Pheophytin
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +4917 | +1990 | +2023 | +
514 | +499 | +2001 | +2023 | +
103 | +260 | +2000 | +2021 | +
540 | +131 | +2017 | +2022 | +
477 | +129 | +2019 | +2022 | +
118 | +8 | +2000 | +2006 | +
115 | +7 | +2000 | +2004 | +
5008 | +1 | +2021 | +2021 | +
Program names:
+5002 - Florida STORET / WIN
+514 - Florida LAKEWATCH Program
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
+540 - Shellfish Harvest Area Classification Program
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+118 - National Aquatic Resource Surveys, National Coastal
+Condition Assessment
+115 - Environmental Monitoring Assessment Program
+5008 - Project COAST (Coastal Assessment Team) - Springs Coast
+Ecosystem Region
Value Qualifiers
+Year | +N_Total | +N_I | +perc_I | +N_Q | +perc_Q | +N_U | +perc_U | +
---|---|---|---|---|---|---|---|
2007 | +157 | ++ | + | + | + | 8 | +5.1 | +
2008 | +131 | +1 | +0.8 | ++ | + | 16 | +12.2 | +
2009 | +121 | +28 | +23.1 | ++ | + | 11 | +9.1 | +
2010 | +211 | +44 | +20.9 | +1 | +0.5 | +27 | +12.8 | +
2011 | +182 | +43 | +23.6 | ++ | + | 9 | +5.0 | +
2012 | +127 | +29 | +22.8 | ++ | + | 10 | +7.9 | +
2013 | +146 | +37 | +25.3 | +16 | +11.0 | +37 | +25.3 | +
2014 | +150 | +36 | +24.0 | +16 | +10.7 | +50 | +33.3 | +
2015 | +149 | +41 | +27.5 | +15 | +10.1 | +51 | +34.2 | +
2016 | +250 | +51 | +20.4 | +13 | +5.2 | +64 | +25.6 | +
2017 | +382 | +65 | +17.0 | +1 | +0.3 | +24 | +6.3 | +
2018 | +448 | +63 | +14.1 | ++ | + | 16 | +3.6 | +
2019 | +277 | +33 | +11.9 | ++ | + | 22 | +7.9 | +
2020 | +237 | +51 | +21.5 | +15 | +6.3 | +48 | +20.2 | +
2021 | +535 | +65 | +12.2 | +29 | +5.4 | +104 | +19.4 | +
2022 | +318 | +77 | +24.2 | +22 | +6.9 | +115 | +36.2 | +
2023 | +125 | +23 | +18.4 | +3 | +2.4 | +21 | +16.8 | +
Note: 1I - Reported +value is greater than or equal to lab method detection limit, but less +than quantitation limit 2Q - Sample held +beyond the accepted holding time 3U - +Compound was analyzed for but not detected
+Programs containing Value Qualified data:
+5002 - Florida STORET / WIN
+514 - Florida LAKEWATCH Program
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+540 - Shellfish Harvest Area Classification Program
Colored Dissolved Organic Matter (CDOM) +occurs naturally in every water body. It is made up of mainly plant +material, algae and bacteria. The composition is determined by its +source; plants, soil, algae, and wastewater are common sources.
+Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Colored Dissolved
+Organic Matter
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +1332 | +2014 | +2023 | +
514 | +828 | +2001 | +2023 | +
477 | +159 | +2017 | +2023 | +
540 | +99 | +2017 | +2019 | +
5008 | +30 | +2021 | +2023 | +
Program names:
+5002 - Florida STORET / WIN
+514 - Florida LAKEWATCH Program
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+540 - Shellfish Harvest Area Classification Program
+5008 - Project COAST (Coastal Assessment Team) - Springs Coast
+Ecosystem Region
Value Qualifiers
+Year | +N_Total | +N_I | +perc_I | +N_Q | +perc_Q | +N_U | +perc_U | +
---|---|---|---|---|---|---|---|
2017 | +74 | +7 | +9.5 | +1 | +1.4 | +1 | +1.4 | +
2018 | +106 | +2 | +1.9 | ++ | + | + | + |
2019 | +60 | +6 | +10.0 | +2 | +3.3 | +2 | +3.3 | +
2020 | +452 | +6 | +1.3 | +14 | +3.1 | +8 | +1.8 | +
2021 | +523 | +8 | +1.5 | +32 | +6.1 | +12 | +2.3 | +
2022 | +503 | +10 | +2.0 | +11 | +2.2 | +16 | +3.2 | +
2023 | +50 | +7 | +14.0 | +5 | +10.0 | +2 | +4.0 | +
Note: 1I - Reported +value is greater than or equal to lab method detection limit, but less +than quantitation limit 2Q - Sample held +beyond the accepted holding time 3U - +Compound was analyzed for but not detected
+Programs containing Value Qualified data:
+477 - Suwannee River Water Management District Water
+Resource Monitoring Program
+514 - Florida LAKEWATCH Program
+540 - Shellfish Harvest Area Classification Program
+5002 - Florida STORET / WIN
Dissolved Oxygen (DO) is a key indicator of +water quality. Oxygen enters surface waters by air-sea gas exchange, by +wind action, or as a byproduct of aquatic plant photosynthesis. The +actual quantity of DO in aquatic environments is dependent on the above +processes as well as water temperature and salinity.
+Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Dissolved
+Oxygen
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +93356 | +1989 | +2023 | +
69 | +42800 | +1996 | +2017 | +
95 | +955 | +1985 | +2018 | +
103 | +158 | +2003 | +2021 | +
477 | +156 | +2019 | +2023 | +
540 | +121 | +2017 | +2022 | +
60 | +78 | +1986 | +2015 | +
115 | +38 | +1991 | +2004 | +
5008 | +30 | +2021 | +2023 | +
118 | +7 | +2000 | +2006 | +
Program names:
+5002 - Florida STORET / WIN
+69 - Fisheries-Independent Monitoring (FIM) Program
+95 - Harmful Algal Bloom Marine Observation Network
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+540 - Shellfish Harvest Area Classification Program
+60 - Southeast Area Monitoring and Assessment Program (SEAMAP)
+- Gulf of Mexico Fall & Summer Shrimp/Groundfish Survey
+115 - Environmental Monitoring Assessment Program
+5008 - Project COAST (Coastal Assessment Team) - Springs Coast
+Ecosystem Region
+118 - National Aquatic Resource Surveys, National Coastal
+Condition Assessment
Value Qualifiers
+Year | +N_Total | +N_Q | +perc_Q | +
---|---|---|---|
2014 | +6787 | +1 | +0 | +
Note: 1Q - Sample held +beyond the accepted holding time
+Programs containing Value Qualified data:
+5002 - Florida STORET / WIN
+Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Dissolved Oxygen
+Saturation
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +1086 | +1999 | +2023 | +
477 | +156 | +2019 | +2023 | +
5008 | +30 | +2021 | +2023 | +
95 | +3 | +2016 | +2018 | +
Program names:
+5002 - Florida STORET / WIN
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+5008 - Project COAST (Coastal Assessment Team) - Springs Coast
+Ecosystem Region
+95 - Harmful Algal Bloom Marine Observation Network
There are no qualifying Value Qualifiers for Dissolved Oxygen +Saturation in Big Bend Seagrasses Aquatic Preserve
+The pH of water is the measure of how acidic or +basic the water body is on a scale of 0-14, with lower readings +indicating acidic and higher readings indicating basic, and a pH of 7 +being neutral. Florida’s natural waters fall between 6.5 and 8.5 on this +scale. A water body’s pH can change due to precipitation, geology, +vegetation, water pollution and air pollution.
+Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for pH
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +51551 | +1989 | +2023 | +
69 | +42723 | +1996 | +2017 | +
95 | +591 | +1964 | +2018 | +
477 | +160 | +2012 | +2023 | +
103 | +156 | +2003 | +2021 | +
540 | +85 | +2017 | +2022 | +
115 | +38 | +1991 | +2004 | +
5008 | +30 | +2021 | +2023 | +
Program names:
+5002 - Florida STORET / WIN
+69 - Fisheries-Independent Monitoring (FIM) Program
+95 - Harmful Algal Bloom Marine Observation Network
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
+540 - Shellfish Harvest Area Classification Program
+115 - Environmental Monitoring Assessment Program
+5008 - Project COAST (Coastal Assessment Team) - Springs Coast
+Ecosystem Region
There are no qualifying Value Qualifiers for pH in Big Bend +Seagrasses Aquatic Preserve
+Salinity is a measure of the amount of salt in the +water. In estuarine ecosystems, salinity is influenced by precipitation, +evaporation, surface-water inputs, and exchange with coastal waters.
+Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Salinity
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +97269 | +1990 | +2023 | +
69 | +42940 | +1996 | +2017 | +
560 | +1374 | +2003 | +2023 | +
95 | +1069 | +1964 | +2018 | +
477 | +137 | +2014 | +2022 | +
540 | +132 | +2017 | +2022 | +
60 | +78 | +1986 | +2015 | +
118 | +51 | +2015 | +2021 | +
115 | +38 | +1991 | +2004 | +
103 | +5 | +2003 | +2004 | +
Program names:
+5002 - Florida STORET / WIN
+69 - Fisheries-Independent Monitoring (FIM) Program
+560 - Big Bend Seagrasses & Nature Coast Aquatic Preserves
+- Seagrass Monitoring
+95 - Harmful Algal Bloom Marine Observation Network
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+540 - Shellfish Harvest Area Classification Program
+60 - Southeast Area Monitoring and Assessment Program (SEAMAP)
+- Gulf of Mexico Fall & Summer Shrimp/Groundfish Survey
+118 - National Aquatic Resource Surveys, National Coastal
+Condition Assessment
+115 - Environmental Monitoring Assessment Program
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
There are no qualifying Value Qualifiers for Salinity in Big Bend +Seagrasses Aquatic Preserve
+Secchi depth is a measure of the transparency or +clarity of the water by a device called a Secchi disk. A Secchi disk is +a black and white disk that is lowered into the water on a cord. The +Secchi depth is the depth at which the disk can no longer be seen. The +deeper the Secchi depth, the greater the water clarity.
+Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Secchi Depth
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
69 | +42930 | +1996 | +2017 | +
514 | +2081 | +1993 | +2023 | +
5002 | +1996 | +1999 | +2023 | +
477 | +155 | +2019 | +2023 | +
103 | +47 | +2020 | +2021 | +
115 | +21 | +1991 | +2004 | +
5008 | +15 | +2021 | +2022 | +
60 | +9 | +1986 | +2014 | +
Program names:
+69 - Fisheries-Independent Monitoring (FIM) Program
+514 - Florida LAKEWATCH Program
+5002 - Florida STORET / WIN
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
+115 - Environmental Monitoring Assessment Program
+5008 - Project COAST (Coastal Assessment Team) - Springs Coast
+Ecosystem Region
+60 - Southeast Area Monitoring and Assessment Program (SEAMAP)
+- Gulf of Mexico Fall & Summer Shrimp/Groundfish Survey
Value Qualifiers
+Year | +N_Total | +N_S | +perc_S | +
---|---|---|---|
2013 | +2794 | +5 | +0.2 | +
2014 | +2797 | +29 | +1.0 | +
2015 | +2759 | +34 | +1.2 | +
2016 | +2790 | +69 | +2.5 | +
2017 | +2813 | +42 | +1.5 | +
2018 | +150 | +17 | +11.3 | +
2019 | +66 | +21 | +31.8 | +
2020 | +178 | +68 | +38.2 | +
2021 | +268 | +75 | +28.0 | +
2022 | +210 | +100 | +47.6 | +
2023 | +47 | +29 | +61.7 | +
Note: 1S - Secchi disk +visible to bottom of waterbody
+Programs containing Value Qualified data:
+5002 - Florida STORET / WIN
+514 - Florida LAKEWATCH Program
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
Nitrogen and Phosphorous are key +nutrients that provide nourishment essential for the growth and +maintenance of aquatic plants and animals; however, excess nutrients can +cause harmful algal blooms and other water quality concerns. Nutrients +enter water bodies several ways, including runoff from rain events and +atmospheric deposition from natural and industrial sources.
+Total Nitrogen Calculation:
+The logic for calculated Total Nitrogen was provided by Kevin +O’Donnell and colleagues at FDEP (with the help of Jay Silvanima, +Watershed Monitoring Section). The following logic is used, in this +order, based on the availability of specific nitrogen components.
+Additional Information:
+ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +5383 | +1990 | +2023 | +
514 | +2163 | +1993 | +2023 | +
540 | +131 | +2017 | +2022 | +
103 | +44 | +2000 | +2006 | +
115 | +5 | +2000 | +2004 | +
5008 | +1 | +2021 | +2021 | +
477 | +1 | +2017 | +2017 | +
Program names:
+5002 - Florida STORET / WIN
+514 - Florida LAKEWATCH Program
+540 - Shellfish Harvest Area Classification Program
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
+115 - Environmental Monitoring Assessment Program
+5008 - Project COAST (Coastal Assessment Team) - Springs Coast
+Ecosystem Region
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
Value Qualifiers
+Year | +N_Total | +N_Q | +perc_Q | +
---|---|---|---|
2013 | +283 | +13 | +4.6 | +
2014 | +324 | +28 | +8.6 | +
2015 | +283 | +18 | +6.4 | +
2016 | +310 | +7 | +2.3 | +
2019 | +273 | +10 | +3.7 | +
2020 | +149 | +25 | +16.8 | +
2021 | +224 | +24 | +10.7 | +
2022 | +210 | +3 | +1.4 | +
Note: 1Q - Sample held +beyond the accepted holding time
+Programs containing Value Qualified data:
+514 - Florida LAKEWATCH Program
+5002 - Florida STORET / WIN
Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Total
+Phosphorus
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +3447 | +1992 | +2023 | +
514 | +2169 | +1993 | +2023 | +
103 | +169 | +2000 | +2021 | +
477 | +159 | +2017 | +2023 | +
540 | +131 | +2017 | +2022 | +
115 | +5 | +2000 | +2004 | +
5008 | +1 | +2021 | +2021 | +
Program names:
+5002 - Florida STORET / WIN
+514 - Florida LAKEWATCH Program
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+540 - Shellfish Harvest Area Classification Program
+115 - Environmental Monitoring Assessment Program
+5008 - Project COAST (Coastal Assessment Team) - Springs Coast
+Ecosystem Region
Value Qualifiers
+Year | +N_Total | +N_I | +perc_I | +N_Q | +perc_Q | +N_U | +perc_U | +
---|---|---|---|---|---|---|---|
1999 | +138 | ++ | + | 1 | +0.7 | ++ | + |
2000 | +171 | +2 | +1.2 | ++ | + | 2 | +1.2 | +
2001 | +222 | +7 | +3.1 | ++ | + | + | + |
2002 | +248 | +4 | +1.6 | ++ | + | + | + |
2003 | +187 | +10 | +5.3 | ++ | + | + | + |
2005 | +223 | +13 | +5.8 | ++ | + | 1 | +0.4 | +
2006 | +232 | +18 | +7.8 | ++ | + | 3 | +1.3 | +
2007 | +173 | +3 | +1.7 | ++ | + | + | + |
2010 | +178 | +11 | +6.2 | ++ | + | 1 | +0.6 | +
2011 | +298 | +41 | +13.8 | ++ | + | + | + |
2012 | +257 | +8 | +3.1 | ++ | + | + | + |
2014 | +283 | +4 | +1.4 | ++ | + | + | + |
2015 | +242 | +5 | +2.1 | +3 | +1.2 | ++ | + |
2016 | +289 | +10 | +3.5 | ++ | + | + | + |
2017 | +400 | +13 | +3.2 | ++ | + | + | + |
2018 | +453 | +21 | +4.6 | ++ | + | 1 | +0.2 | +
2019 | +290 | +13 | +4.5 | +10 | +3.5 | ++ | + |
2020 | +222 | +13 | +5.9 | +30 | +13.5 | ++ | + |
2021 | +396 | +13 | +3.3 | +20 | +5.0 | +1 | +0.2 | +
2022 | +266 | +18 | +6.8 | +3 | +1.1 | +1 | +0.4 | +
2023 | +128 | +5 | +3.9 | ++ | + | + | + |
Note: 1I - Reported +value is greater than or equal to lab method detection limit, but less +than quantitation limit 2Q - Sample held +beyond the accepted holding time 3U - +Compound was analyzed for but not detected
+Programs containing Value Qualified data:
+514 - Florida LAKEWATCH Program
+5002 - Florida STORET / WIN
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
Total Suspended Solids (TSS) are solid +particles suspended in water that exceed 2 microns in size and can be +trapped by a filter.
+Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Total Suspended
+Solids
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +2816 | +1990 | +2023 | +
477 | +20 | +2021 | +2023 | +
103 | +12 | +2020 | +2021 | +
Program names:
+5002 - Florida STORET / WIN
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
Value Qualifiers
+Year | +N_Total | +N_I | +perc_I | +N_Q | +perc_Q | +N_U | +perc_U | +
---|---|---|---|---|---|---|---|
1998 | +44 | ++ | + | + | + | 9 | +20.4 | +
1999 | +88 | ++ | + | 2 | +2.3 | +33 | +37.5 | +
2000 | +149 | +1 | +0.7 | ++ | + | 63 | +42.3 | +
2001 | +146 | +4 | +2.7 | ++ | + | 77 | +52.7 | +
2002 | +84 | +11 | +13.1 | ++ | + | 65 | +77.4 | +
2003 | +73 | +12 | +16.4 | ++ | + | 60 | +82.2 | +
2004 | +63 | +10 | +15.9 | +1 | +1.6 | +53 | +84.1 | +
2005 | +79 | +16 | +20.2 | ++ | + | 60 | +76.0 | +
2006 | +101 | +22 | +21.8 | ++ | + | 67 | +66.3 | +
2007 | +60 | +4 | +6.7 | ++ | + | 54 | +90.0 | +
2008 | +63 | +9 | +14.3 | ++ | + | 54 | +85.7 | +
2009 | +74 | +21 | +28.4 | +5 | +6.8 | +53 | +71.6 | +
2010 | +75 | +34 | +45.3 | ++ | + | 40 | +53.3 | +
2011 | +197 | +96 | +48.7 | ++ | + | 29 | +14.7 | +
2012 | +83 | +63 | +75.9 | ++ | + | 18 | +21.7 | +
2013 | +86 | +68 | +79.1 | ++ | + | 16 | +18.6 | +
2014 | +103 | +58 | +56.3 | ++ | + | 42 | +40.8 | +
2015 | +92 | +50 | +54.4 | ++ | + | 42 | +45.6 | +
2016 | +147 | +119 | +81.0 | +1 | +0.7 | +25 | +17.0 | +
2017 | +105 | +73 | +69.5 | ++ | + | 27 | +25.7 | +
2018 | +53 | +38 | +71.7 | +1 | +1.9 | +15 | +28.3 | +
2019 | +27 | +19 | +70.4 | ++ | + | 6 | +22.2 | +
2020 | +50 | +24 | +48.0 | ++ | + | 20 | +40.0 | +
2021 | +91 | +36 | +39.6 | +1 | +1.1 | +40 | +44.0 | +
2022 | +141 | +52 | +36.9 | ++ | + | 87 | +61.7 | +
2023 | +36 | +19 | +52.8 | ++ | + | 15 | +41.7 | +
Note: 1I - Reported +value is greater than or equal to lab method detection limit, but less +than quantitation limit 2Q - Sample held +beyond the accepted holding time 3U - +Compound was analyzed for but not detected
+Programs containing Value Qualified data:
+5002 - Florida STORET / WIN
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
Turbidity results from suspended solids in the +water, including silts, clays, tannins, industrial wastes, sewage and +plankton, which are all factors that contribute to how clouded or murky +a water column is. Turbidity is caused by soil erosion, excess +nutrients, pollutants, and physical forces such as winds, currents and +bottom feeders.
+Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Turbidity
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +42389 | +1990 | +2023 | +
477 | +314 | +2017 | +2023 | +
103 | +116 | +2005 | +2021 | +
540 | +35 | +2019 | +2022 | +
Program names:
+5002 - Florida STORET / WIN
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
+540 - Shellfish Harvest Area Classification Program
Value Qualifiers
+Year | +N_Total | +N_I | +perc_I | +N_Q | +perc_Q | +N_U | +perc_U | +
---|---|---|---|---|---|---|---|
1999 | +1704 | ++ | + | 1 | +0.1 | ++ | + |
2000 | +1960 | ++ | + | 1 | +0.0 | ++ | + |
2001 | +2054 | ++ | + | + | + | 1 | +0.0 | +
2002 | +2030 | ++ | + | 2 | +0.1 | +2 | +0.1 | +
2004 | +2199 | ++ | + | 4 | +0.2 | ++ | + |
2005 | +1931 | ++ | + | 2 | +0.1 | ++ | + |
2006 | +2312 | ++ | + | 2 | +0.1 | ++ | + |
2007 | +2481 | ++ | + | 2 | +0.1 | +1 | +0.0 | +
2008 | +2698 | ++ | + | 1 | +0.0 | ++ | + |
2010 | +2025 | ++ | + | 5 | +0.2 | +2 | +0.1 | +
2012 | +732 | ++ | + | + | + | 1 | +0.1 | +
2013 | +95 | ++ | + | 1 | +1.0 | +1 | +1.0 | +
2014 | +165 | +10 | +6.1 | +4 | +2.4 | ++ | + |
2015 | +148 | +10 | +6.8 | +4 | +2.7 | +1 | +0.7 | +
2016 | +1169 | +14 | +1.2 | +4 | +0.3 | ++ | + |
2017 | +1503 | +7 | +0.5 | ++ | + | 2 | +0.1 | +
2019 | +140 | +3 | +2.1 | +2 | +1.4 | +1 | +0.7 | +
2020 | +202 | +16 | +7.9 | ++ | + | 13 | +6.4 | +
2021 | +325 | +9 | +2.8 | ++ | + | 13 | +4.0 | +
2022 | +265 | +61 | +23.0 | +4 | +1.5 | +18 | +6.8 | +
2023 | +114 | +28 | +24.6 | ++ | + | 1 | +0.9 | +
Note: 1I - Reported +value is greater than or equal to lab method detection limit, but less +than quantitation limit 2Q - Sample held +beyond the accepted holding time 3U - +Compound was analyzed for but not detected
+Programs containing Value Qualified data:
+5002 - Florida STORET / WIN
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+540 - Shellfish Harvest Area Classification Program
Temperature determines the capacity of water to hold +oxygen. Cooler water can hold more dissolved oxygen because water +molecules are more tightly packed, making it harder for oxygen to +escape. Additionally, as water temperature increases, fish and other +aquatic organisms become more active and consume oxygen at a faster +rate.
+Seasonal Kendall-Tau Trend Analysis
+
+Map showing location of Discrete sampling sites for Water
+Temperature
+
+The bubble size on the above plots reflects the amount of data available
+at each sampling site
ProgramID | +N_Data | +YearMin | +YearMax | +
---|---|---|---|
5002 | +99762 | +1989 | +2023 | +
69 | +42962 | +1996 | +2017 | +
95 | +1165 | +1964 | +2018 | +
103 | +158 | +2003 | +2021 | +
477 | +156 | +2019 | +2023 | +
540 | +133 | +2017 | +2022 | +
60 | +78 | +1986 | +2015 | +
115 | +38 | +1991 | +2004 | +
5008 | +30 | +2021 | +2023 | +
Program names:
+5002 - Florida STORET / WIN
+69 - Fisheries-Independent Monitoring (FIM) Program
+95 - Harmful Algal Bloom Marine Observation Network
+103 - EPA STOrage and RETrieval Data Warehouse (STORET)
+477 - Suwannee River Water Management District Water Resource
+Monitoring Program
+540 - Shellfish Harvest Area Classification Program
+60 - Southeast Area Monitoring and Assessment Program (SEAMAP)
+- Gulf of Mexico Fall & Summer Shrimp/Groundfish Survey
+115 - Environmental Monitoring Assessment Program
+5008 - Project COAST (Coastal Assessment Team) - Springs Coast
+Ecosystem Region
There are no qualifying Value Qualifiers for Water Temperature in Big +Bend Seagrasses Aquatic Preserve
+ +The following files were used in the continuous analysis:
+Combined_WQ_WC_NUT_cont_Dissolved_Oxygen_NW-2024-Feb-22.txt
Combined_WQ_WC_NUT_cont_Dissolved_Oxygen_Saturation_NW-2024-Feb-22.txt
Combined_WQ_WC_NUT_cont_pH_NW-2024-Feb-22.txt
Combined_WQ_WC_NUT_cont_Salinity_NW-2024-Feb-22.txt
Combined_WQ_WC_NUT_cont_Turbidity_NW-2024-Feb-22.txt
Combined_WQ_WC_NUT_cont_Water_Temperature_NW-2024-Feb-22.txt
+Map showing Continuous Water Quality Monitoring sampling locations
+within the boundaries of Big Bend Seagrasses Aquatic Preserve. Sites
+marked as Use In Analysis are featured in this report.
National Water Information System (7)
+
National Water Information System (7)
+
National Water Information System (7)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Station | +N_Data | +N_Years | +Period of Record | +Median | +tau | +SennIntercept | +SennSlope | +p | +
---|---|---|---|---|---|---|---|---|
02313700 | +1113 | +5 | +2019 - 2023 | +6.5 | +-0.09 | +6.65 | +-0.02 | +0.7787 | +
02323566 | +1298 | +9 | +2015 - 2023 | +1.1 | +-0.13 | +0.89 | +-0.08 | +0.0448 | +
02326526 | +1312 | +8 | +2016 - 2023 | +9.3 | +-0.06 | +9.38 | +0.05 | +0.6979 | +
2313700 | +397 | +2 | +2022 - 2023 | +5.8 | +- | +- | +- | +- | +
2323566 | +350 | +2 | +2022 - 2023 | +1.2 | +- | +- | +- | +- | +
2326526 | +392 | +2 | +2022 - 2023 | +9.7 | +- | +- | +- | +- | +
BBSDB | +184327 | +10 | +2007 - 2016 | +7.3 | +-0.05 | +7.46 | +-0.01 | +0.6066 | +
BBSSK | +134287 | +10 | +2004 - 2015 | +7.1 | +0.28 | +6.6 | +0.09 | +0.0023 | +
BBSST | +111411 | +5 | +2019 - 2023 | +6.9 | +-0.14 | +6.72 | +-0.02 | +0.3964 | +
BBSSW | +182327 | +8 | +2009 - 2016 | +6.2 | +0 | +6 | +0 | +1.0000 | +
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Station | +N_Data | +N_Years | +Period of Record | +Median | +tau | +SennIntercept | +SennSlope | +p | +
---|---|---|---|---|---|---|---|---|
BBSDB | +183530 | +10 | +2007 - 2016 | +97.6 | +-0.30 | +100.88 | +-0.81 | +0.0003 | +
BBSSK | +134196 | +10 | +2004 - 2015 | +91.8 | +0.12 | +93.37 | +0.36 | +0.2612 | +
BBSST | +114465 | +5 | +2019 - 2023 | +93.3 | +0.13 | +91.37 | +0.64 | +0.3964 | +
BBSSW | +182158 | +8 | +2009 - 2016 | +75.8 | +-0.05 | +79.14 | +-0.25 | +0.6835 | +
National Water Information System (7)
+
National Water Information System (7)
+
National Water Information System (7)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Station | +N_Data | +N_Years | +Period of Record | +Median | +tau | +SennIntercept | +SennSlope | +p | +
---|---|---|---|---|---|---|---|---|
02313700 | +1047 | +5 | +2019 - 2023 | +7.6 | +0.04 | +7.62 | +0.03 | +0.2234 | +
02323566 | +1238 | +9 | +2015 - 2023 | +7.2 | +-0.14 | +7.19 | +0 | +0.1310 | +
02326526 | +1139 | +8 | +2016 - 2023 | +8.2 | +0.22 | +8.01 | +0.05 | +0.0233 | +
2313700 | +354 | +2 | +2022 - 2023 | +7.5 | +- | +- | +- | +- | +
2323566 | +357 | +2 | +2022 - 2023 | +7.1 | +- | +- | +- | +- | +
2326526 | +386 | +2 | +2022 - 2023 | +8.2 | +- | +- | +- | +- | +
BBSDB | +250183 | +10 | +2007 - 2016 | +8.1 | +-0.28 | +8.17 | +-0.02 | +0.0004 | +
BBSSK | +168278 | +10 | +2004 - 2015 | +8.1 | +-0.37 | +8.28 | +-0.04 | +0.0000 | +
BBSST | +121092 | +5 | +2019 - 2023 | +8.0 | +0.16 | +7.95 | +0.02 | +0.3533 | +
BBSSW | +224733 | +8 | +2009 - 2016 | +7.6 | +-0.29 | +7.8 | +-0.06 | +0.0017 | +
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Station | +N_Data | +N_Years | +Period of Record | +Median | +tau | +SennIntercept | +SennSlope | +p | +
---|---|---|---|---|---|---|---|---|
291652083064100 | +123 | +1 | +2000 - 2000 | +19.0 | +- | +- | +- | +- | +
BBSDB | +265544 | +10 | +2007 - 2016 | +30.6 | +-0.53 | +33.78 | +-0.75 | +0.0000 | +
BBSSK | +178356 | +10 | +2004 - 2015 | +29.6 | +-0.22 | +30.77 | +-0.21 | +0.0197 | +
BBSST | +121984 | +5 | +2019 - 2023 | +28.6 | +0.21 | +26.79 | +0.5 | +0.1594 | +
BBSSW | +221696 | +8 | +2009 - 2016 | +7.5 | +-0.23 | +10.39 | +-0.65 | +0.0160 | +
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Station | +N_Data | +N_Years | +Period of Record | +Median | +tau | +SennIntercept | +SennSlope | +p | +
---|---|---|---|---|---|---|---|---|
BBSDB | +224613 | +10 | +2007 - 2016 | +1 | +0.49 | +1.47 | +1.22 | +0.0000 | +
BBSSK | +165043 | +10 | +2004 - 2015 | +5 | +0.11 | +6.35 | +0.30 | +0.1867 | +
BBSST | +125246 | +5 | +2019 - 2023 | +4 | +-0.15 | +6.58 | +-0.57 | +0.3149 | +
BBSSW | +202699 | +8 | +2009 - 2016 | +6 | +-0.35 | +12.41 | +-0.99 | +0.0001 | +
National Water Information System (7)
+
National Water Information System (7)
+
National Water Information System (7)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Big Bend Seagrasses Aquatic Preserves Continuous Water Quality
+Monitoring (471)
+
Station | +N_Data | +N_Years | +Period of Record | +Median | +tau | +SennIntercept | +SennSlope | +p | +
---|---|---|---|---|---|---|---|---|
02313700 | +1030 | +5 | +2019 - 2023 | +25.00 | +-0.04 | +24.75 | +0.03 | +0.9195 | +
02323566 | +1332 | +9 | +2015 - 2023 | +22.70 | +0.47 | +22.51 | +0.04 | +0.0000 | +
02323592 | +478 | +2 | +2022 - 2023 | +21.70 | +- | +- | +- | +- | +
02326526 | +1261 | +8 | +2016 - 2023 | +22.00 | +-0.02 | +23.14 | +0.04 | +0.5177 | +
02326550 | +475 | +2 | +2022 - 2023 | +20.80 | +- | +- | +- | +- | +
2313700 | +338 | +2 | +2022 - 2023 | +27.40 | +- | +- | +- | +- | +
2323566 | +364 | +2 | +2022 - 2023 | +22.80 | +- | +- | +- | +- | +
2326526 | +335 | +2 | +2022 - 2023 | +24.00 | +- | +- | +- | +- | +
291652083064100 | +92 | +1 | +2000 - 2000 | +18.35 | +- | +- | +- | +- | +
BBSDB | +265988 | +10 | +2007 - 2016 | +23.20 | +0.08 | +22.34 | +0.04 | +0.2922 | +
BBSSK | +179213 | +10 | +2004 - 2015 | +21.70 | +-0.33 | +25.19 | +-0.37 | +0.0002 | +
BBSST | +128489 | +5 | +2019 - 2023 | +23.60 | +0.16 | +24.34 | +0.15 | +0.3149 | +
BBSSW | +227996 | +8 | +2009 - 2016 | +23.70 | +0.02 | +23.09 | +0.01 | +0.9025 | +
The data file used is: +All_SAV_Parameters-2024-Feb-23.txt
+Submerged aquatic vegetation (SAV) refers +to plants and plant-like macroalgae species that live entirely +underwater. The two primary categories of SAV inhabiting +Florida estuaries are benthic macroalgae and +seagrasses. They often grow together in dense beds or meadows +that carpet the seafloor. Macroalgae include multicellular +species of green, red and brown algae that often live attached to the +substrate by a holdfast. They tend to grow quickly and can tolerate +relatively high nutrient levels, making them a threat to seagrasses and +other benthic habitats in areas with poor water quality. In contrast, +seagrasses are grass-like, vascular, flowering plants that are +attached to the seafloor by extensive root systems. Seagrasses +occur throughout the coastal areas of Florida, including protected bays +and lagoons as well as deeper offshore waters on the continental shelf. +Seagrasses have taken advantage of the broad, shallow shelf and +clear water to produce two of the most extensive seagrass beds anywhere +in continental North America.
+Percent Cover measures the fraction of an area of +seafloor that is covered by SAV, usually estimated by evaluating +multiple small areas of seafloor. Percent cover is often estimated for +total SAV, individual types of vegetation (seagrass, attached algae, +drift algae) and individual species.
+Frequency of Occurrence was calculated as the number +of times a taxon was observed in a year divided by the number of +sampling events, multiplied by 100. Analysis is conducted at the quadrat +level and is inclusive of all quadrats (i.e., quadrats evaluated using +Braun-Blanquet, modified Braun-Blanquet, and percent cover.”
+Turtle grass (Thalassia testudinum) is the +largest of the Florida seagrasses, with longer, thicker blades and +deeper root structures than any of the other seagrasses. It is +considered a climax seagrass species.
+Shoal grass (Halodule wrightii) is an early +colonizer of vegetated areas and usually grows in water too shallow for +other species except widgeon grass. It can often tolerate +larger salinity ranges than other seagrass species. Shoal grass +is characterized by thin, flat blades, that are narrower than turtle +grass blades.
+Manatee grass (Syringodium filiforme) is +easily recognizable because its leaves are thin and cylindrical instead +of the flat, ribbon-like form shared by many other seagrass species. The +leaves can grow up to half a meter in length. Manatee grass is +usually found in mixed seagrass beds or small, dense monospecific +patches.
+Widgeon grass (Ruppia maritima) grows in +both fresh and salt water and is widely distributed throughout Florida’s +estuaries in less saline areas, particularly in inlets along the east +coast. This species resembles shoal grass in certain +environments but can be identified by the pointed tips of its +leaves.
+Three species of Halophila spp. are found in Florida - +Star grass (Halophila engelmannii), +Paddle grass (Halophila decipiens), and +Johnson’s seagrass (Halophila johnsonii). +These are smaller, more fragile seagrasses than other Florida species +and are considered ephemeral. They grow along a single long rhizome, +with short blades. These species are not well-studied, although surveys +are underway to define their ecological roles.
+Star grass, Paddle grass, and Johnson’s +seagrass will be grouped together and listed as Halophila +spp. in the following managed areas. This is because several +surveys did not specify to the species level:
+Banana River Aquatic Preserve
Indian River-Malabar to Vero Beach Aquatic Preserve
Indian River-Vero Beach to Ft. Pierce Aquatic Preserve
Jensen Beach to Jupiter Inlet Aquatic Preserve
Loxahatchee River-Lake Worth Creek Aquatic Preserve
Mosquito Lagoon Aquatic Preserve
Biscayne Bay Aquatic Preserve
Florida Keys National Marine Sanctuary
+Maps showing the temporal scope of SAV sampling sites within the
+boundaries of Big Bend Seagrasses Aquatic Preserve by Program
+name.
Sampling locations by Program:
+
+Map showing SAV sampling sites within the boundaries of Big Bend
+Seagrasses Aquatic Preserve. The point size reflects the number of
+samples at a given sampling site.
N_Data | +YearMin | +YearMax | +Collection Method | +Sample Locations | +
---|---|---|---|---|
537 | +2012 | +2018 | +Modified Braun Blanquet | +195 | +
N_Data | +YearMin | +YearMax | +Collection Method | +Sample Locations | +
---|---|---|---|---|
21887 | +2000 | +2023 | +Modified Braun Blanquet | +125 | +
2637 | +2022 | +2023 | +Percent Cover | +99 | +
+Generalized additive models for each species in Big Bend Seagrasses
+Aquatic Preserve. Species must have at least 10 years of data to be
+evaluated.
Drift algae, Total seagrass, Attached +algae, and Total SAV are excluded from the analyses.
+Managed Area reports are available in both PDF and HTML format. The +GitHub Repository is located here
+Managed.Area | +HTML | +|
---|---|---|
Alligator Harbor Aquatic Preserve | ++ | AHAP_Report.pdf | +
Apalachicola Bay Aquatic Preserve | ++ | ABAP_Report.pdf | +
Apalachicola National Estuarine Research Reserve | ++ | ANERR_Report.pdf | +
Banana River Aquatic Preserve | ++ | BRAP_Report.pdf | +
Big Bend Seagrasses Aquatic Preserve | +BBSAP_Report.html | +BBSAP_Report.pdf | +
Biscayne Bay Aquatic Preserve | ++ | BBAP_Report.pdf | +
Biscayne Bay-Cape Florida to Monroe County Line Aquatic +Preserve | ++ | BBCFMCAP_Report.pdf | +
Boca Ciega Bay Aquatic Preserve | ++ | BCBAP_Report.pdf | +
Cape Haze Aquatic Preserve | ++ | CHAP_Report.pdf | +
Cape Romano-Ten Thousand Islands Aquatic Preserve | ++ | CRTTIAP_Report.pdf | +
Cockroach Bay Aquatic Preserve | ++ | CKRBAP_Report.pdf | +
Southeast Florida Coral Reef Ecosystem Conservation +Area | ++ | CRCP_Report.pdf | +
Coupon Bight Aquatic Preserve | ++ | CBAP_Report.pdf | +
Estero Bay Aquatic Preserve | ++ | EBAP_Report.pdf | +
Florida Keys National Marine Sanctuary | ++ | FKNMS_Report.pdf | +
Fort Clinch State Park Aquatic Preserve | ++ | FCAP_Report.pdf | +
Fort Pickens State Park Aquatic Preserve | ++ | FPAP_Report.pdf | +
Gasparilla Sound-Charlotte Harbor Aquatic Preserve | ++ | GSCHAP_Report.pdf | +
Guana River Marsh Aquatic Preserve | ++ | GRMAP_Report.pdf | +
Guana Tolomato Matanzas National Estuarine Research +Reserve | ++ | GTMNERR_Report.pdf | +
Indian River-Malabar to Vero Beach Aquatic +Preserve | ++ | IRMVBAP_Report.pdf | +
Indian River-Vero Beach to Ft. Pierce Aquatic +Preserve | ++ | IRVBFPAP_Report.pdf | +
Jensen Beach to Jupiter Inlet Aquatic Preserve | ++ | JBJIAP_Report.pdf | +
Lemon Bay Aquatic Preserve | ++ | LBAP_Report.pdf | +
Lignumvitae Key Aquatic Preserve | ++ | LKAP_Report.pdf | +
Loxahatchee River-Lake Worth Creek Aquatic +Preserve | ++ | LRLWCAP_Report.pdf | +
Matlacha Pass Aquatic Preserve | ++ | MPAP_Report.pdf | +
Mosquito Lagoon Aquatic Preserve | ++ | MLAP_Report.pdf | +
Nassau River-St. Johns River Marshes Aquatic +Preserve | ++ | NRSJRAP_Report.pdf | +
North Fork St. Lucie Aquatic Preserve | ++ | NFSLRAP_Report.pdf | +
Pellicer Creek Aquatic Preserve | ++ | PCRAP_Report.pdf | +
Pine Island Sound Aquatic Preserve | ++ | PISAP_Report.pdf | +
Pinellas County Aquatic Preserve | ++ | PCAP_Report.pdf | +
Rocky Bayou State Park Aquatic Preserve | ++ | RBSPAP_Report.pdf | +
Rookery Bay Aquatic Preserve | ++ | RBAP_Report.pdf | +
Rookery Bay National Estuarine Research Reserve | ++ | RBNERR_Report.pdf | +
St. Andrews State Park Aquatic Preserve | ++ | SBAP_Report.pdf | +
St. Joseph Bay Aquatic Preserve | ++ | SJBAP_Report.pdf | +
St. Martins Marsh Aquatic Preserve | ++ | SMMAP_Report.pdf | +
Terra Ceia Aquatic Preserve | ++ | TCAP_Report.pdf | +
Tomoka Marsh Aquatic Preserve | ++ | TMAP_Report.pdf | +
Yellow River Marsh Aquatic Preserve | ++ | YRMAP_Report.pdf | +
Nature Coast Aquatic Preserve | ++ | NCAP_Report.pdf | +