# shforce.R
# 02/05/2016
#' @title Shiny application for viewing Atlantis forcings data
#'
#' @description
#'A shiny application that displays water exchanges, salinity and temperature data
#' from the netCDF files used as forcings for an Atlantis run.
#'
#' To run this application a list object must first be generated using
#' \code{\link[shinyrAtlantis]{make.sh.forcings.object}} (see Examples).
#'
#' The \emph{Connections} tab displays the number of neighbouring water layers that each
#' water layer in a chosen box exchanges water. Use this tab to check that all water layers in
#' boxes exchange with at least one other water layer.
#'
#' The \emph{Exchanges} tab allows the user to display the exchanges read into Atlantis
#' (Raw) and all exchanges associated with a box (All). Atlantis only reads in a
#' single exchange value associated with a pair of box layers, however this exchange
#' influences flow for both box layers. Use the (All) tab to see all flows
#' associated with a box. An option is available to plot either
#' raw exchange values or their sign, and whether box numbering is displayed.
#' Exchanges are also presented in a table.
#'
#' The \emph{Horizontal flows} tab provides visualisation of the horizontal flow field at
#' each water layer. This flow is \emph{approximate} as it is calculated
#' using only exchanges at a single layer, however some horizontal flow may occur
#' from horizontal exchanges at the other layers. The length of the arrow only provides
#' a guide to flow speed.
#'
#' The \emph{Vertical flows} tab provides net vertical fluxes for each water layer in
#' a box. An option is available to plot either
#' raw exchange values or their sign, and whether box numbering is displayed.
#' Exchanges (per unit area per time step) are also presented in a table.
#'
#' The \emph{Time-series} tab allows the user to examine all water exchanges from a
#' specified water layer. As vertical exchanges are often much greater than horizontal
#' exchanges an option is available to suppress plotting of vertical exchanges.
#' This plot can take some time to generate so a checkbox is provided to
#' enable the plot.
#'
#' The \emph{Temperature} and \emph{Salinity} tabs provide spatial and time-series
#' plots. Tabular versions of the data are also presented.
#'
#' @param input.object An R list object generated from \code{\link[shinyrAtlantis]{make.sh.forcings.object}}.
#'
#' @return An object of class 'shiny.appobj' see \code{\link[shiny]{shinyApp}}.
#'
#' @examples
#' \dontrun{
#' exchange.file <- "GBR108_hydro.nc"
#' salinity.file <- "GBR108_salt.nc"
#' temperature.file <- "GBR108_temp.nc"
#' bgm.file <- "gbr_box_03012012.bgm"
#' cum.depth <- c(0,5,10,20,50,100,200,3000) # cumulative water layer depths
#'
#' input.object <- make.sh.forcings.object(
#' bgm.file = bgm.file,
#' exchange.file = exchange.file,
#' cum.depth = cum.depth,
#' temperature.file = temperature.file,
#' salinity.file = salinity.file
#' )
#' sh.forcings(input.object)
#' }
#' @export
#' @importFrom ggplot2 facet_wrap geom_point geom_segment geom_line annotate scale_fill_gradient2 scale_color_manual arrow element_text
#' @importFrom dplyr left_join select
#' @importFrom grid unit
sh.forcings <- function(input.object){
# create HTML text for viewing on help tab
txtHelp <- "<h3>Summary</h3>"
txtHelp <- paste(txtHelp, "<p>This program displays data from the .nc files used to provide the time-series of forcings for an <b>Atlantis</b> run.</p>")
txtHelp <- paste(txtHelp, "<h3>Details</h3>")
txtHelp <- paste(txtHelp, "<p>Plots have a zoom feature. Draw a box and double click to zoom into the box. Double click to reset zoom.</p>")
txtHelp <- paste(txtHelp, "<p>There are two numberings of layers. Atlantis assumes layer 0 is immediately above the sediment, which means that Atlantis layers do not correspond between boxes that differ in the number of water layers. For plotting the surface layer is always set to 1 and layers correspond with depth from the surface.</p>")
txtHelp <- paste(txtHelp, "<p>For the exchange plots gold cells depict the focal box and focal layer provided by the user.</p>")
txtHelp <- paste(txtHelp, "<p>For the connections plot gold cells depict box layers that are not linked to any other boxes. Check that these boxes are not isolated throughout the time series.</p>")
txtHelp <- paste(txtHelp, "<p>Plotting the time-series can be slow so it is initially disabled. It is best to disable plotting the time series when investigating other aspects of the exchange data.</p>")
txtHelp <- paste(txtHelp, "<p>The exhange tabs allow plotting of the raw exchange values or the sign of the exchanges. Plotting the signs rather than the raw values helps to show which layers are connected.</p>")
txtHelp <- paste(txtHelp, "<p>Note that the 2-D flows are approximate and should only be used as a guide of flow direction.</p>")
dt = input.object$t[2]-input.object$t[1] # time step
# extract elements from input parameter
numboxes <- input.object$numboxes
numlayers <- input.object$numlayers
numdests <- input.object$numdests
numtimes <- input.object$numtimes
time <- input.object$t
box.data <- input.object$box.data
box.data$numlayers[is.na(box.data$numlayers)] <- 0
cum.depth <- input.object$cum.depth
# create side bar text describing depth layers
txt.depths <- "<h5>Layer depths</h5><p>"
for (i in 2:length(cum.depth)) {
txt.depths <- paste(txt.depths, as.character(i-1), ": ",
as.character(cum.depth[i]), "m<br>", sep = "")
}
txt.depths <- paste(txt.depths, "</p>", sep = "")
# create useful global arrays
exchange.links <- array(0, dim = c(numboxes, numlayers,
numboxes, numlayers))
# exchange.value: [i1,j1,i2,j2] = net flow from (i1,j1) to (i2,j2)
exchange.value <- array(NA, dim = c(numboxes, numlayers, numboxes, numlayers))
exchange.TS <- array(NA, dim = c(numtimes, numboxes, numlayers))
vert.dir <- array(NA, dim = c(numboxes, numlayers))
# calculate the depths of each water layer
layer.depth <- rep(0, numlayers)
for (i in 1:(length(cum.depth)-1)){
layer.depth[i] <- cum.depth[i+1] - cum.depth[i]
}
# create a mapping from plotting layer to Atalantis layer
plot.to.Atlantis <- array(0, dim = c(numboxes, numlayers))
for (i in 1:numboxes) {
for (j in 1:numlayers) {
plot.to.Atlantis[i,j] <- box.data$numlayers[i]-j+1
if (plot.to.Atlantis[i,j] < 1) {
plot.to.Atlantis[i,j] <- numlayers + plot.to.Atlantis[i,j]
}
}
}
# estimate total box face lengths that connect pairs of boxes
min.length <- array(0, dim = c(numboxes, numboxes))
for (i in 1:numboxes) {
for (j in 1:numboxes) {
min.length[i,j] <- min(sqrt(box.data$area[i]), sqrt(box.data$area[j]))
}
}
plotHeight3D <- paste(as.character(250 * ((numlayers - 1) %/% 3 + 1)),
"px", sep = "") # calculate a reasonable overall plot size for 3D plots
shinyApp(
# USER INPUT FUNCTION
ui = navbarPage(
title = "Atlantis forcings viewer",
# -- Connections --
tabPanel("Connections",
sidebarLayout(
sidebarPanel(width = 2,
numericInput(inputId = "NI.Connections", label = "Time (days)",
min = dt, max = max(input.object$t),
value = input.object$t[1], step = dt),
checkboxInput(inputId = "CI.BoxIDConnections", label = "Show box IDs",
value = FALSE)
),
mainPanel(
plotOutput("plotConnections",
height = plotHeight3D,
dblclick = "plotConnections_dblclick",
brush = brushOpts(
id = "plotConnections_brush",
resetOnNew = TRUE
)
),
HTML("<p>Number of box layers connected with the focal box layer. Plot layer 1 is the surface layer. Gold cells do not exchange water with any other boxes. Grey cells do not contain water.</p>"),
hr(),
DT::dataTableOutput("table.Connections")
)
)
),
# -- Exchanges (raw values) --
navbarMenu("Exchanges",
tabPanel("Raw",
sidebarLayout(
sidebarPanel(width = 2,
selectInput(inputId = "SI.Box", label = "Focal box",
choices = 0:(numboxes-1)),
selectInput(inputId = "SI.Level", label = "Plotted layer\n(surface = layer 1)",
choices = 1:box.data$numlayers[1]),
numericInput(inputId = "NI.Time", label = "Time (days)",
min = min(input.object$t), max = max(input.object$t),
value = input.object$t[1], step = dt),
checkboxInput(inputId = "CI.Raw", label = "Plot raw values",
value = FALSE),
checkboxInput(inputId = "CI.BoxID", label = "Show box IDs",
value = FALSE)
),
mainPanel(
fluidRow(
plotOutput("plotExchange",
height = plotHeight3D,
dblclick = "plotExchange_dblclick",
brush = brushOpts(
id = "plotExchange_brush",
resetOnNew = TRUE
)
)
),
HTML("<p>Positive values indicate flow from the focal (gold) cell to the destination cell, and vice-versa. Numbers in the panel headers indicate the plotted depth layer (layer 1 is the surface layer).</p>"),
hr(),
DT::dataTableOutput("table.Exchange")
)
)
),
# -- Exchanges (all values) --
tabPanel("All",
sidebarLayout(
sidebarPanel(width = 2,
selectInput(inputId = "SI.Box.all", label = "Focal box",
choices = 0:(numboxes-1)),
selectInput(inputId = "SI.Level.all", label = "Plotted layer\n(surface = layer 1)",
choices = 1:box.data$numlayers[1]),
numericInput(inputId = "NI.Time.all", label = "Time (days)",
min = min(input.object$t), max = max(input.object$t),
value = input.object$t[1], step = dt),
checkboxInput(inputId = "CI.Raw.all", label = "Plot raw values",
value = FALSE),
checkboxInput(inputId = "CI.BoxID.all", label = "Show box IDs",
value = FALSE)
),
mainPanel(
plotOutput("plotExchange.all",
height = plotHeight3D,
dblclick = "plotExchange.all_dblclick",
brush = brushOpts(
id = "plotExchange.all_brush",
resetOnNew = TRUE
)
),
HTML("<p>Positive values indicate flow from the focal (gold) cell to the destination cell, and vice-versa. Flow is from red to gold to blue.</p><p>Numbers in the panel headers indicate the plotted depth layer (layer 1 is the surface layer).</p>"),
hr(),
DT::dataTableOutput("table.Exchange.all")
)
)
)
),
# -- Horizontal flows --
tabPanel("Horizontal flows",
sidebarLayout(
sidebarPanel(width = 2,
numericInput(inputId = "NI.Flows", label = "Time (days)",
min = dt, max = max(input.object$t),
value = input.object$t[1], step = dt),
checkboxInput(inputId = "CI.BoxIDFlows", label = "Show box IDs",
value = FALSE)
),
mainPanel(
HTML("<p><b>Please be patient as these plots may take some time to generate.</b></p>"),
plotOutput("plotFlows",
height = plotHeight3D,
dblclick = "plotFlows_dblclick",
brush = brushOpts(
id = "plotFlows_brush",
resetOnNew = TRUE
)
),
HTML("<p>Directions of horizontal flow are only approximate. Layer 1 is the surface layer.</p><p>Flows in and out of the deepest layer of box 0 are ignored as it is a dummy location.</p>")
)
)
),
# -- Vertical flows --
tabPanel("Vertical flows",
sidebarLayout(
sidebarPanel(width = 2,
numericInput(inputId = "NI.Vert", label = "Time (days)",
min = dt, max = max(input.object$t),
value = input.object$t[1], step = dt),
checkboxInput(inputId = "CI.Vert", label = "Plot raw values",
value = FALSE),
checkboxInput(inputId = "CI.BoxIDVert", label = "Show box IDs",
value = FALSE)
),
mainPanel(
plotOutput("plotVert",
height = plotHeight3D,
dblclick = "plotVert_dblclick",
brush = brushOpts(
id = "plotVert_brush",
resetOnNew = TRUE
)
),
HTML("<p>Layer 1 is the surface layer. Positive values indicate upward flow.</p>"),
hr(),
DT::dataTableOutput("table.Vert")
)
)
),
# -- Time Series --
tabPanel("Time-series",
sidebarLayout(
sidebarPanel(width = 2,
checkboxInput(inputId = "CI.Enable", label = "Enable plotting",
value = FALSE),
selectInput(
inputId = "SI.BoxTS",
label = "Focal box",
choices = 0:(input.object$numboxes-1)
),
selectInput(
inputId = "SI.LevelTS",
label = "Plotted layer\n(surface = layer 1)",
choices = 1:box.data$numlayers[1]
),
checkboxInput(
inputId = "CI.ExcludeVert",
label = "Exclude vertical",
value = FALSE
)
),
mainPanel(
HTML("<p><b>Please be patient as this plot may take some time to generate.</b></p>"),
plotOutput("plotTimeSeries",
height = "450px",
dblclick = "plotTimeSeries_dblclick",
brush = brushOpts(
id = "plotTimeSeries_brush",
resetOnNew = TRUE
)
),
HTML("<p>Positive values indicate that exchange is out of the focal box. Layer 1 is the surface layer. Horizontal exchanges can often be resolved by removing the vertical exchanges from the plot.</p>")
)
)
),
# -- Temperature --
navbarMenu("Temperature",
tabPanel("Spatial",
sidebarLayout(
sidebarPanel(width = 2,
numericInput(inputId = "NI.Temp", label = "Time (days)",
min = dt, max = max(input.object$t),
value = input.object$t[1], step = dt),
checkboxInput(inputId = "CI.BoxIDTemp", label = "Show box IDs",
value = FALSE)
),
mainPanel(
plotOutput("plotTemp",
height = plotHeight3D,
dblclick = "plotTemp_dblclick",
brush = brushOpts(
id = "plotTemp_brush",
resetOnNew = TRUE
)
),
hr(),
DT::dataTableOutput("table.Temp")
)
)
),
tabPanel("Temporal",
sidebarLayout(
sidebarPanel(width = 2,
selectInput(inputId = "SI.TempTS", label = "Focal box",
choices = 0:(numboxes-1), selected = 0),
h5("Box attributes"),
htmlOutput("txtTempAtt")
),
mainPanel(
plotOutput("plotTempTS",
height = "450px",
dblclick = "plotTempTS_dblclick",
brush = brushOpts(
id = "plotTempTS_brush",
resetOnNew = TRUE
)
),
HTML("<p>Layer 1 is the surface layer. Bottom water layer and sediment layer may have the same temperature.</p>"),
hr(),
DT::dataTableOutput("table.TempTS")
)
)
)
),
# -- Salinity --
navbarMenu("Salinity",
tabPanel("Spatial",
sidebarLayout(
sidebarPanel(width = 2,
numericInput(inputId = "NI.Salt", label = "Time (days)",
min = dt, max = max(input.object$t),
value = input.object$t[1], step = dt),
checkboxInput(inputId = "CI.BoxIDSalt", label = "Show box IDs",
value = FALSE)
),
mainPanel(
plotOutput("plotSalt",
height = plotHeight3D,
dblclick = "plotSalt_dblclick",
brush = brushOpts(
id = "plotSalt_brush",
resetOnNew = TRUE
)
),
hr(),
DT::dataTableOutput("table.Salt")
)
)
),
tabPanel("Temporal",
sidebarLayout(
sidebarPanel(width = 2,
selectInput(inputId = "SI.SaltTS", label = "Focal box",
choices = 0:(numboxes-1), selected = 0),
h5("Box attributes"),
htmlOutput("txtSaltAtt")
),
mainPanel(
plotOutput("plotSaltTS",
height = "450px",
dblclick = "plotSaltTS_dblclick",
brush = brushOpts(
id = "plotSaltTS_brush",
resetOnNew = TRUE
)
),
HTML("<p>Layer 1 is the surface layer. Bottom water layer and sediment layer may have the same salinity.</p>"),
hr(),
DT::dataTableOutput("table.SaltTS")
)
)
)
),
# -- Help --
tabPanel("Help",
fluidPage(
HTML(txtHelp)
)
),
# -- Exit --
tabPanel(
actionButton("exitButton", "Exit")
)
),
# SERVER FUNCTION
server = function(input, output, session) {
values <- reactiveValues()
values$TempAtt <- ""
values$SaltAtt <- ""
# reactive variables used to set plot ranges
rangesExchange <- reactiveValues(x = NULL, y = NULL)
rangesExchange.all <- reactiveValues(x = NULL, y = NULL)
rangesTimeSeries <- reactiveValues(x = NULL, y = NULL)
rangesConnections <- reactiveValues(x = NULL, y = NULL)
rangesFlows <- reactiveValues(x = NULL, y = NULL)
rangesVert <- reactiveValues(x = NULL, y = NULL)
rangesTemp <- reactiveValues(x = NULL, y = NULL)
rangesSalt <- reactiveValues(x = NULL, y = NULL)
# -- Update sub-selections
observe({
i <- as.integer(input$SI.Box)
updateSelectInput(session, "SI.Level",
choices = 1:box.data$numlayers[i+1])
})
observe({
i <- as.integer(input$SI.Box.all)
updateSelectInput(session, "SI.Level.all",
choices = 1:box.data$numlayers[i+1])
})
observe({
i <- as.integer(input$SI.BoxTS)
updateSelectInput(session, "SI.LevelTS",
choices = 1:box.data$numlayers[i+1])
})
# -- Validate user entries
observe({
if (input$NI.Time < min(input.object$t) |
input$NI.Time > max(input.object$t)) {
updateNumericInput(session, "NI.Time",
value = input.object$t[1])
}
})
observe({
if (input$NI.Time.all < min(input.object$t) |
input$NI.Time.all > max(input.object$t)) {
updateNumericInput(session, "NI.Time.all",
value = input.object$t[1])
}
})
# -- register brush events for zooming in and out
observeEvent(input$plotExchange_dblclick, {
brush <- input$plotExchange_brush
if (!is.null(brush)) {
rangesExchange$x <- c(brush$xmin, brush$xmax)
rangesExchange$y <- c(brush$ymin, brush$ymax)
} else {
rangesExchange$x <- NULL
rangesExchange$y <- NULL
}
})
observeEvent(input$plotExchange.all_dblclick, {
brush <- input$plotExchange.all_brush
if (!is.null(brush)) {
rangesExchange.all$x <- c(brush$xmin, brush$xmax)
rangesExchange.all$y <- c(brush$ymin, brush$ymax)
} else {
rangesExchange.all$x <- NULL
rangesExchange.all$y <- NULL
}
})
observeEvent(input$plotConnections_dblclick, {
brush <- input$plotConnections_brush
if (!is.null(brush)) {
rangesConnections$x <- c(brush$xmin, brush$xmax)
rangesConnections$y <- c(brush$ymin, brush$ymax)
} else {
rangesConnections$x <- NULL
rangesConnections$y <- NULL
}
})
observeEvent(input$plotFlows_dblclick, {
brush <- input$plotFlows_brush
if (!is.null(brush)) {
rangesFlows$x <- c(brush$xmin, brush$xmax)
rangesFlows$y <- c(brush$ymin, brush$ymax)
} else {
rangesFlows$x <- NULL
rangesFlows$y <- NULL
}
})
observeEvent(input$plotVert_dblclick, {
brush <- input$plotVert_brush
if (!is.null(brush)) {
rangesVert$x <- c(brush$xmin, brush$xmax)
rangesVert$y <- c(brush$ymin, brush$ymax)
} else {
rangesVert$x <- NULL
rangesVert$y <- NULL
}
})
observeEvent(input$plotTimeSeries_dblclick, {
brush <- input$plotTimeSeries_brush
if (!is.null(brush)) {
rangesTimeSeries$x <- c(brush$xmin, brush$xmax)
rangesTimeSeries$y <- c(brush$ymin, brush$ymax)
} else {
rangesTimeSeries$x <- NULL
rangesTimeSeries$y <- NULL
}
})
observeEvent(input$plotTemp_dblclick, {
brush <- input$plotTemp_brush
if (!is.null(brush)) {
rangesTemp$x <- c(brush$xmin, brush$xmax)
rangesTemp$y <- c(brush$ymin, brush$ymax)
} else {
rangesTemp$x <- NULL
rangesTemp$y <- NULL
}
})
observeEvent(input$plotSalt_dblclick, {
brush <- input$plotSalt_brush
if (!is.null(brush)) {
rangesSalt$x <- c(brush$xmin, brush$xmax)
rangesSalt$y <- c(brush$ymin, brush$ymax)
} else {
rangesSalt$x <- NULL
rangesSalt$y <- NULL
}
})
# register change in box
observeEvent(input$SI.TempTS, {
focal.box <- as.integer(input$SI.TempTS)
values$TempAtt <- paste("<p>Water layers: ",
as.character(box.data$numlayers[focal.box+1]), "</p><p>",
"Depth: ", as.character(-box.data$z[focal.box+1]), "m</p>", txt.depths,
sep = "")
})
observeEvent(input$SI.SaltTS, {
focal.box <- as.integer(input$SI.SaltTS)
values$SaltAtt <- paste("<p>Water layers: ",
as.character(box.data$numlayers[focal.box+1]), "</p><p>",
"Depth: ", as.character(-box.data$z[focal.box+1]), "m</p>", txt.depths,
sep = "")
})
# display box attributes for temperature time series
output$txtTempAtt <- renderUI({
HTML(values$TempAtt)
})
# display box attributes for temperature time series
output$txtSaltAtt <- renderUI({
HTML(values$SaltAtt)
})
# -- Connections -- Plot
output$plotConnections <- renderPlot({
# calculate the time index of the data matrices
t <- round((input$NI.Connections - input.object$t[1]) / dt, digits = 0) + 1
exchange.links[ , , , ] <- 0
for (i in 1:numboxes) {
for (j in 1:numlayers) {
for (k in 1:numdests) {
if (!is.na(input.object$exchange[k,j,i,t])) {
dest.i <- input.object$dest.box[k,j,i,t] + 1
dest.j <- input.object$dest.layer[k,j,i,t] + 1
if (!is.na(dest.i) & !is.na(dest.j)) {
if (!((i == dest.i) & (j == dest.j))) { # only consider adjacent boxes
exchange.links[i,j,dest.i,dest.j] <- exchange.links[i,j,dest.i,dest.j] + 1
exchange.links[dest.i,dest.j,i,j] <- exchange.links[dest.i,dest.j,i,j] + 1
}
}
}
}
}
}
total.links <- array(0, dim = c(numboxes, numlayers))
for (i in 1:numboxes) {
for (j in 1:numlayers) { # surface to bottom
total.links[i,j] <- sum(exchange.links[i,j, , ], na.rm = TRUE)
}
}
df <- data.frame(boxid = 0:(numboxes-1), numlayers = box.data$numlayers,
total.links)
layer.names <- rep("x", numlayers)
for (i in 1:numlayers) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[3:(numlayers+2)] <- layer.names
tmp <- numlayers+2
df <- tidyr::gather(df, layer, links, 3:tmp)
df$layer <- sort(rep(0:(numlayers-1), numboxes))
df$dest.plot.layer <- df$numlayers - df$layer
df$dest.plot.layer[df$dest.plot.layer < 1] <-
numlayers + df$dest.plot.layer[df$dest.plot.layer < 1]
df$links[df$layer >= df$numlayers] <- NA
df.plot <- dplyr::left_join(input.object$map.vertices, df, by = "boxid")
df.unconnected <- df.plot %>% dplyr::filter(is.na(links))
gg <- ggplot(data = df.plot,
aes(x = x, y = y, group = boxid, fill = links)) +
geom_polygon(colour = "grey25", size = 0.25, na.rm = TRUE) +
scale_fill_gradient(low = "white", high = "#de2d26", na.value="grey", limits = c(0,max(df.plot$links))) +
labs(fill = "Connecting\nbox\nlayers") +
facet_wrap( ~ dest.plot.layer, ncol = 3) +
theme_bw() + xlab("") + ylab("") +
theme(plot.background = element_blank()) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL) +
coord_cartesian(xlim = rangesConnections$x, ylim = rangesConnections$y)
gg <- gg + geom_polygon(data = df.unconnected, mapping = aes(x = x, y = y, group = boxid), inherit.aes = FALSE, fill = "gold", size = 0.25, na.rm = TRUE)
if (input$CI.BoxIDConnections) { # add box id
gg <- gg + geom_text(data = input.object$box.data, mapping = aes(x = x.in, y = y.in, label = boxid), size = 2.5, inherit.aes = FALSE)
}
gg
})
# -- Connections -- Table
output$table.Connections <- DT::renderDataTable({
# calculate the time index of the data matrices
t <- round((input$NI.Connections - input.object$t[1]) / dt, digits = 0) + 1
exchange.links[ , , , ] <- 0
for (i in 1:numboxes) {
for (j in 1:numlayers) {
for (k in 1:numdests) {
if (!is.na(input.object$exchange[k,j,i,t])) {
dest.i <- input.object$dest.box[k,j,i,t] + 1
dest.j <- input.object$dest.layer[k,j,i,t] + 1
if (!is.na(dest.i) & !is.na(dest.j)) {
if (!((i == dest.i) & (j == dest.j))) { # only consider adjacent boxes
exchange.links[i,j,dest.i,dest.j] <- exchange.links[i,j,dest.i,dest.j] + 1
exchange.links[dest.i,dest.j,i,j] <- exchange.links[dest.i,dest.j,i,j] + 1
}
}
}
}
}
}
total.links <- array(0, dim = c(numboxes, numlayers))
for (i in 1:numboxes) {
for (j in 1:numlayers) { # surface to bottom
total.links[i,j] <- sum(exchange.links[i,j, , ], na.rm = TRUE)
}
}
df <- data.frame(boxid = 0:(numboxes-1), numlayers = box.data$numlayers,
total.links)
layer.names <- rep("x", numlayers)
for (i in 1:numlayers) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[3:(numlayers+2)] <- layer.names
tmp <- numlayers+2
df <- tidyr::gather(df, layer, links, 3:tmp)
df$layer <- sort(rep(0:(numlayers-1), numboxes))
df$dest.plot.layer <- df$numlayers - df$layer
df$dest.plot.layer[df$dest.plot.layer < 1] <-
numlayers + df$dest.plot.layer[df$dest.plot.layer < 1]
df$links[df$layer >= df$numlayers] <- NA
df <- df %>% dplyr::filter(!is.na(links))
df <- df[c(1,2,3,5,4)] # reorder columns
DT::datatable(df, rownames = FALSE,
colnames = c('box', 'water layers', 'layer (Atlantis)', 'layer (plotting)', 'number of links'),
caption = "Number of linked box layers excluding self exchanges.")
})
# -- Exchange -- Plot
output$plotExchange <- renderPlot({
focal.box <- as.integer(input$SI.Box) # 1:numboxes
focal.plot.layer <- as.integer(input$SI.Level) # 1 is surface
# convert plotting layer to Atlantis layer
focal.Atlantis.layer <- box.data$numlayers[focal.box+1] -
focal.plot.layer # 0 is the layer above the sediment
t <- round(as.integer((input$NI.Time - time[1]) / dt), digits = 0) + 1
tmp.exchange <- input.object$exchange[ , focal.Atlantis.layer+1,
focal.box+1, t]
keep <- which(!is.na(tmp.exchange))
tmp.exchange <- tmp.exchange[keep]
if (!input$CI.Raw) {
tmp.exchange <- sign(tmp.exchange) # remove magnitude
}
tmp.dest.box <- input.object$dest.box[ , focal.Atlantis.layer+1,
focal.box+1, t][keep]
tmp.dest.layer <- input.object$dest.layer[ , focal.Atlantis.layer+1,
focal.box+1, t][keep]
tmp.numlayers <- box.data$numlayers[keep]
boxid <- rep(0:(numboxes-1), numlayers)
layer <- sort(rep(1:numlayers, numboxes)) - 1
exch <- rep(0, length(boxid))
df <- data.frame(boxid, numlayers = rep(box.data$numlayers, numlayers),
dest.Atlantis.layer = layer, exch)
for (i in 1:length(tmp.exchange)) {
indx <- tmp.dest.layer[i]*numboxes + tmp.dest.box[i] + 1
df$exch[indx] <- tmp.exchange[i]
}
df$dest.plot.layer <- df$numlayers - df$dest.Atlantis.layer
df$dest.plot.layer[df$dest.plot.layer < 1] <-
numlayers +
df$dest.plot.layer[df$dest.plot.layer < 1]
df$exch[df$dest.plot.layer > df$numlayers] <- NA
df.plot <- dplyr::left_join(input.object$map.vertices, df, by = "boxid")
df.plot$boxid <- factor(df.plot$boxid)
df.focal <- dplyr::filter(df.plot,
boxid == focal.box & dest.plot.layer == focal.plot.layer) %>%
select(boxid, dest.plot.layer, x, y)
gg <- ggplot(data = df.plot,
aes(x = x, y = y, group = boxid, fill = exch)) +
geom_polygon(colour = "black", size = 0.25, na.rm = TRUE) +
scale_fill_gradient2(low = "#e6550d", high = "#3182bd", mid = "white", midpoint=0, na.value="grey75") +
labs(fill = "value") +
facet_wrap( ~ dest.plot.layer, ncol = 3) +
theme_bw() + xlab("") + ylab("") +
coord_cartesian(xlim = rangesExchange$x, ylim = rangesExchange$y) +
theme(plot.background = element_blank()) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL)
gg <- gg + geom_polygon(data = df.focal, mapping = aes(x = x, y = y, group = boxid), inherit.aes = FALSE, fill = "gold", size = 0.25, na.rm = TRUE)
if (input$CI.BoxID) { # add box ids
gg <- gg + geom_text(data = box.data, mapping = aes(x = x.in, y = y.in, label = boxid), size = 2.5)
}
gg
})
# -- Exchange -- Table
output$table.Exchange <- DT::renderDataTable({
focal.box <- as.integer(input$SI.Box) # 1:numboxes
focal.plot.layer <- as.integer(input$SI.Level) # 1 is surface
# convert plotting layer to Atlantis layer
focal.Atlantis.layer <- box.data$numlayers[focal.box+1] -
focal.plot.layer # 0 is the layer above the sediment
t <- round(as.integer((input$NI.Time - time[1]) / dt), digits = 0) + 1
tmp.exchange <- input.object$exchange[ , focal.Atlantis.layer+1,
focal.box+1, t]
keep <- which(!is.na(tmp.exchange))
tmp.exchange <- tmp.exchange[keep]
tmp.dest.box <- input.object$dest.box[ , focal.Atlantis.layer+1,
focal.box+1, t][keep]
tmp.dest.layer <- input.object$dest.layer[ , focal.Atlantis.layer+1,
focal.box+1, t][keep]
tmp.numlayers <- box.data$numlayers[tmp.dest.box+1]
df.Exchange <- data.frame(dest.box = tmp.dest.box,
numlayers = tmp.numlayers,
dest.Atlantis.layer = tmp.dest.layer,
dest.plot.layer = tmp.numlayers - tmp.dest.layer,
Exchange = tmp.exchange)
DT::datatable(df.Exchange, rownames = FALSE,
colnames = c('box', 'water layers', 'layer (Atlantis)', 'layer (plotting)',
'volume exchanged (m^3)'))
})
# -- Exchange (all) -- Plot
output$plotExchange.all <- renderPlot({
focal.box <- as.integer(input$SI.Box.all) # 1:numboxes
focal.plot.layer <- as.integer(input$SI.Level.all) # 1 is surface
# convert plotting layer to Atlantis layer
focal.Atlantis.layer <- box.data$numlayers[focal.box+1] -
focal.plot.layer # 0 is the layer above the sediment
t <- round(as.integer((input$NI.Time.all - time[1]) / dt), digits = 0) + 1
exchange.value[ , , , ] <- 0.0
for (i in 1:numboxes) {
for (j in 1:numlayers) {
for (k in 1:numdests) {
if (!is.na(input.object$exchange[k,j,i,t])) {
dest.i <- input.object$dest.box[k,j,i,t] + 1
dest.j <- input.object$dest.layer[k,j,i,t] + 1
if (!is.na(dest.i) & !is.na(dest.j)) {
exchange.value[i,j,dest.i,dest.j] <-
input.object$exchange[k,j,i,t] # from i to dest
exchange.value[dest.i,dest.j,i,j] <-
-input.object$exchange[k,j,i,t] # from dest to i
}
}
}
}
}
if (!input$CI.Raw.all) {
exchange.value <- sign(exchange.value) # remove magnitude
}
boxid <- rep(0:(numboxes-1), numlayers)
layer <- sort(rep(1:numlayers, numboxes)) - 1
exch <- rep(0, length(boxid))
df <- data.frame(boxid, numlayers = box.data$numlayers, layer,
dest.Atlantis.layer = layer, exch)
for (i in 1:dim(exchange.value)[3]) { # destination box + 1
for (j in 1:dim(exchange.value)[4]) { # destination layer + 1
if (!is.na(exchange.value[focal.box+1,focal.Atlantis.layer+1,i,j])) {
indx <- i + numboxes*(j-1)
df$exch[indx] <- exchange.value[focal.box+1,
focal.Atlantis.layer+1,i,j]
}
}
}
df$dest.plot.layer <- df$numlayers - df$dest.Atlantis.layer
df$dest.plot.layer[df$dest.plot.layer < 1] <-
numlayers + df$dest.plot.layer[df$dest.plot.layer < 1]
df$exch[df$dest.plot.layer > df$numlayers] <- NA
df.plot <- dplyr::left_join(input.object$map.vertices, df, by = "boxid")
df.plot$boxid <- factor(df.plot$boxid)
df.focal <- dplyr::filter(
df.plot,
boxid == focal.box,
dest.plot.layer == focal.plot.layer
) %>%
dplyr::select(boxid, dest.plot.layer, x, y)
gg <- ggplot(data = df.plot,
aes(x = x, y = y, group = boxid, fill = exch)) +
geom_polygon(colour = "grey25", size = 0.25, na.rm = TRUE) +
scale_fill_gradient2(low = "#e6550d", high = "#3182bd", mid = "white", midpoint=0, na.value="grey75") +
labs(fill = "value") +
facet_wrap( ~ dest.plot.layer, ncol = 3) +
theme_bw() + xlab("") + ylab("") +
coord_cartesian(xlim = rangesExchange.all$x, ylim = rangesExchange.all$y) +
theme(plot.background = element_blank()) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL)
gg <- gg + geom_polygon(data = df.focal, mapping = aes(x = x, y = y, group = boxid), inherit.aes = FALSE, fill = "gold", size = 0.25, na.rm = TRUE)
if (input$CI.BoxID.all) { # add box id
gg <- gg + geom_text(data = input.object$box.data, mapping = aes(x = x.in, y = y.in, label = boxid), size = 2.5)
}
gg
})
# -- Exchange (all) -- Table
output$table.Exchange.all <- DT::renderDataTable({
focal.box <- as.integer(input$SI.Box.all) # 1:numboxes
focal.plot.layer <- as.integer(input$SI.Level.all) # 1 is surface
# convert plotting layer to Atlantis layer
focal.Atlantis.layer <- box.data$numlayers[focal.box+1] -
focal.plot.layer # 0 is the layer above the sediment
t <- round(as.integer((input$NI.Time.all - time[1]) / dt), digits = 0) + 1
exchange.value[ , , , ] <- 0.0
for (i in 1:numboxes) {
for (j in 1:numlayers) {
for (k in 1:numdests) {
if (!is.na(input.object$exchange[k,j,i,t])) {
dest.i <- input.object$dest.box[k,j,i,t] + 1
dest.j <- input.object$dest.layer[k,j,i,t] + 1
if (!is.na(dest.i) & !is.na(dest.j)) {
exchange.value[i,j,dest.i,dest.j] <-
input.object$exchange[k,j,i,t] # from i to dest
exchange.value[dest.i,dest.j,i,j] <-
-input.object$exchange[k,j,i,t] # from dest to i
}
}
}
}
}
boxid <- rep(0:(numboxes-1), numlayers)
layer <- sort(rep(1:numlayers, numboxes)) - 1
exch <- rep(0, length(boxid))
df <- data.frame(boxid, numlayers = box.data$numlayers,
dest.Atlantis.layer = layer, dest.plot.layer = layer, exch)
for (i in 1:dim(exchange.value)[3]) { # destination box + 1
for (j in 1:dim(exchange.value)[4]) { # destination layer + 1
if (!is.na(exchange.value[focal.box+1,focal.Atlantis.layer+1,i,j])) {
indx <- i + numboxes*(j-1)
df$exch[indx] <- exchange.value[focal.box+1,
focal.Atlantis.layer+1,i,j]
}
}
}
df$dest.plot.layer <- df$numlayers - df$dest.Atlantis.layer
df$dest.plot.layer[df$dest.plot.layer < 1] <-
numlayers + df$dest.plot.layer[df$dest.plot.layer < 1]
df$exch[df$dest.plot.layer > df$numlayers] <- NA
DT::datatable(dplyr::filter(df, exch != 0), rownames = FALSE,
colnames = c('box', 'water layers', 'layer (Atlantis)', 'layer (plotting)', 'volume exchanged (m^3)'))
})
# -- Time-series -- plot
output$plotTimeSeries <- renderPlot({
if (input$CI.Enable) {
focal.box <- as.integer(input$SI.BoxTS) # 1:numboxes
focal.plot.layer <- as.integer(input$SI.LevelTS) # 1 is surface
# convert plotting layer to Atlantis layer
focal.Atlantis.layer <- box.data$numlayers[focal.box+1] -
focal.plot.layer # 0 is the layer above the sediment
# dest.layer[dest.layer < 0] <- NA
# dest.layer[dest.layer >= numlayers] <- NA
for (ts in 1:numtimes) {
exchange.value[ , , ,] <- NA
for (i in 1:numboxes) {
for (j in 1:numlayers) {
for (k in 1:numdests) {
if (!is.na(input.object$exchange[k,j,i,ts])) {
dest.i <- input.object$dest.box[k,j,i,ts] + 1
dest.j <- input.object$dest.layer[k,j,i,ts] + 1
if (!is.na(dest.i) & !is.na(dest.j)) {
exchange.value[i,j,dest.i,dest.j] <-
input.object$exchange[k,j,i,ts] # from i to dest
exchange.value[dest.i,dest.j,i,j] <-
-input.object$exchange[k,j,i,ts] # from dest to i
}
}
}
}
}
exchange.TS[ts, , ] <- exchange.value[focal.box+1, focal.Atlantis.layer+1, , ]
}
ts <- NULL # input.object$t
box.layer <- NULL
exch <- NULL
for (i in 1:numboxes) {
for (j in 1:numlayers) { # j-1 = Atlantis layer
if (!all(is.na(exchange.TS[ ,i,j]))) {
if (!input$CI.ExcludeVert) {
box.level <- paste(i-1,box.data$numlayers[i]-(j-1),sep = ".")
ts <- c(ts, input.object$t)
box.layer <- c(box.layer, rep(box.level,numtimes))
exch <- c(exch, exchange.TS[ ,i,j])
} else {
if (i != (focal.box+1)) {
box.level <- paste(i-1,box.data$numlayers[i]-(j-1),sep = ".")
ts <- c(ts, input.object$t)
box.layer <- c(box.layer, rep(box.level,numtimes))
exch <- c(exch, exchange.TS[ ,i,j])
}
}
}
}
}
df.plot <- data.frame(ts, box.layer, exch)
df.plot <- df.plot[complete.cases(df.plot),]
ggplot(data = df.plot, aes(x = ts, y = exch, color = box.layer)) +
geom_point(size = 0.35) + geom_line() +
xlab("Time (days)") + ylab("Exchange (m^3)") +
coord_cartesian(xlim = rangesTimeSeries$x, ylim = rangesTimeSeries$y) +
theme_bw()
} else {
df.plot <- data.frame(x = 0, y = 0)
ggplot(data = df.plot, aes(x = x, y = y)) +
theme_bw() + xlab("") + ylab("") +
annotate("text", x = 0, y = 0, size = 5, colour = "red",
label = "Plot is not enabled.\nCheck the enable box to plot.\nNote that it may take a few minutes to generate the plot.") +
theme(
plot.background = element_blank(),
plot.title=element_text(colour="red")
) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL)
}
})
# -- Horizontal flows -- Plot
output$plotFlows <- renderPlot({
t <- round(as.integer((input$NI.Flows - time[1]) / dt), digits = 0) + 1
exchange.value <- array(0.0, dim = c(numboxes, numlayers,
numboxes, numlayers))
for (i in 1:numboxes) {
for (j in 1:numlayers) {
for (k in 1:numdests) {
if (!is.na(input.object$exchange[k,j,i,t])) {
dest.i <- input.object$dest.box[k,j,i,t] + 1
dest.j <- input.object$dest.layer[k,j,i,t] + 1
if (!is.na(dest.i) & !is.na(dest.j)) {
exchange.value[i,j,dest.i,dest.j] <-
input.object$exchange[k,j,i,t] /
(layer.depth[j]*min.length[i,dest.i]) # from i to dest
exchange.value[dest.i,dest.j,i,j] <-
-input.object$exchange[k,j,i,t] /
(layer.depth[j]*min.length[i,dest.i]) # from dest to i
}
}
}
}
}
boxes <- 1:numboxes
dx <- array(data = 0.0, dim = c(numboxes,numlayers))
dy <- array(data = 0.0, dim = c(numboxes,numlayers))
max.length <- 0.0
for (i in boxes) {
xf <- box.data$x.in[i]
yf <- box.data$y.in[i]
for (j in 1:numlayers) { # plot layer
j.f.A <- plot.to.Atlantis[i,j]
for (i.dest in boxes[which(boxes!=i)]) {
xd <- box.data$x.in[i.dest]
yd <- box.data$y.in[i.dest]
j.d.A <- plot.to.Atlantis[i.dest,j]
dx[i,j] <- dx[i,j] + exchange.value[i,j.f.A,i.dest,j.d.A] *
(xd - xf) / sqrt((xd-xf)*(xd-xf) + (yd-yf)*(yd-yf))
dy[i,j] <- dy[i,j] + exchange.value[i,j.f.A,i.dest,j.d.A] *
(yd - yf) / sqrt((xd-xf)*(xd-xf) + (yd-yf)*(yd-yf))
}
# remove exchange from the deepest layer of boxid = 0
if (j == box.data$numlayers[1]) { # deepest layer of box 0
j.d.A <- plot.to.Atlantis[1,j] # Atlantis layer of box 0
dx[i,j] <- dx[i,j] - exchange.value[i,j.f.A,1,j.d.A] *
(xd - xf) / sqrt((xd-xf)*(xd-xf) + (yd-yf)*(yd-yf))
dy[i,j] <- dy[i,j] - exchange.value[i,j.f.A,1,j.d.A] *
(yd - yf) / sqrt((xd-xf)*(xd-xf) + (yd-yf)*(yd-yf))
}
if ((i == 1) & (j == box.data$numlayers[1])) { # deepest layer of box 0
dx[i,j] <- 0.0 # remove deepest layer of box 0
dy[i,j] <- 0.0
}
vec.length <- sqrt(dx[i,j]*dx[i,j] + dy[i,j]*dy[i,j])
if (vec.length > max.length) { # find the longest vector calculated
max.length <- vec.length
}
}
}
map.size <- sqrt((max(box.data$x.in) - min(box.data$x.in)) *
(max(box.data$x.in) - min(box.data$x.in)) +
(max(box.data$y.in) - min(box.data$y.in)) *
(max(box.data$y.in) - min(box.data$y.in)))
scalar <- 0.1*map.size / max.length # longest arrow is 10% of map
dx <- scalar*dx
dy <- scalar*dy
# create vector map
layer <- NULL
x.in <- NULL
y.in <- NULL
xend <- NULL
yend <- NULL
tmp.xend <- rep(0,numboxes)
tmp.yend <- rep(0,numboxes)
for (j in 1:numlayers) {
layer <- c(layer, rep(j, numboxes))
x.in <- c(x.in, box.data$x.in)
y.in <- c(y.in, box.data$y.in)
for (i in 1:numboxes) {
tmp.xend[i] <- box.data$x.in[i] + dx[i,j]
tmp.yend[i] <- box.data$y.in[i] + dy[i,j]
}
xend <- c(xend, tmp.xend)
yend <- c(yend, tmp.yend)
}
df.test <- data.frame(layer, x.in, y.in, xend, yend)
df.test <- df.test %>% mutate(len = sqrt((xend-x.in)*(xend-x.in) +
(yend-y.in)*(yend-y.in))) %>%
dplyr::filter(len > 0)
boxid <- rep(0:(numboxes-1), numlayers)
layer <- sort(rep(1:numlayers, numboxes))
df <- data.frame(boxid, numlayers = box.data$numlayers, layer = layer)
df.plot <- dplyr::left_join(input.object$map.vertices, df, by = "boxid")
df.plot$boxid <- factor(df.plot$boxid)
df.plot <- df.plot %>% mutate(water.present = (layer <= numlayers))
df.plot$numlayers<- factor(df.plot$numlayers)
gg <- ggplot(data = df.plot,
aes(x = x, y = y, group = boxid, fill = water.present)) +
geom_polygon(colour = "grey85", size = 0.25) +
geom_segment(data = df.test,
aes(x = x.in, y = y.in, xend = xend, yend = yend),
arrow = arrow(length = unit(0.2,"cm")),
inherit.aes = FALSE) +
facet_wrap( ~ layer, ncol = 3) +
labs(fill = "Water\npresent") +
scale_fill_manual(values=c("wheat1", "lightskyblue")) +
theme_bw() + xlab("") + ylab("") +
theme(plot.background = element_blank()) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL) +
coord_cartesian(xlim = rangesFlows$x, ylim = rangesFlows$y)
if (input$CI.BoxIDFlows) {
gg <- gg + geom_text(data = input.object$box.data, mapping = aes(x = x.in, y = y.in, label = boxid), size = 2.5, inherit.aes = FALSE)
}
gg
})
# -- Vertical exchanges -- Plot
output$plotVert <- renderPlot({
t <- round(as.integer((input$NI.Vert - time[1]) / dt), digits = 0) + 1
exchange.value[ , , , ] <- 0.0
for (i in 1:numboxes) {
for (j in 1:numlayers) {
for (k in 1:numdests) {
if (!is.na(input.object$exchange[k,j,i,t])) {
dest.i <- input.object$dest.box[k,j,i,t] + 1
dest.j <- input.object$dest.layer[k,j,i,t] + 1 # Atlantis layer
if (!is.na(dest.i) & !is.na(dest.j)) {
exchange.value[i,j,dest.i,dest.j] <-
input.object$exchange[k,j,i,t] # from i to dest
exchange.value[dest.i,dest.j,i,j] <-
-input.object$exchange[k,j,i,t] # from dest to i
}
}
}
}
}
vert.dir[ , ] <- 0.0 # second index is Atlantis layer
for (i in 1:numboxes) { # boxid = i-1
for (j in 1:numlayers) { # j is Atlantis layer
if ((j - 1) > 0) { # a box above
if (!is.na(exchange.value[i,j-1,i,j])) { # exchange is provided
vert.dir[i,j] <- exchange.value[i,j-1,i,j] / box.data$area[i] # + is down
}
}
if ((j + 1) < numlayers) { # a box below
if (!is.na(exchange.value[i,j,i,j+1])) { # exchange is provided
if (is.na(vert.dir[i,j])) { # no exchange into this box yet
vert.dir[i,j] <- exchange.value[i,j,i,j+1] / box.data$area[i] # + is down
} else {
vert.dir[i,j] <- vert.dir[i,j] + exchange.value[i,j,i,j+1] / box.data$area[i]
}
}
}
}
}
if (!input$CI.Vert) {
vert.dir <- sign(vert.dir) # + is down (this is currently not used)
}
df <- data.frame(boxid = 0:(numboxes-1), area = box.data$area,
numlayers = box.data$numlayers, vert.dir)
layer.names <- rep("x", numlayers)
for (i in 1:numlayers) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[4:(numlayers+3)] <- layer.names
tmp <- numlayers+3
df <- tidyr::gather(df, layer, vert, 4:tmp)
df$layer <- sort(rep(0:(numlayers-1), numboxes))
df$dest.plot.layer <- df$numlayers - df$layer
df$dest.plot.layer[df$dest.plot.layer < 1] <-
numlayers + df$dest.plot.layer[df$dest.plot.layer < 1]
df$vert[df$layer >= df$numlayers] <- NA
df.plot <- dplyr::left_join(input.object$map.vertices, df, by = "boxid")
gg <- ggplot(data = df.plot,
aes(x = x, y = y, group = boxid, fill = vert)) +
geom_polygon(colour = "grey25", size = 0.25, na.rm = TRUE) +
scale_fill_gradient2(low = "#e6550d", high = "#3182bd", mid = "white", midpoint=0, na.value="grey75") +
labs(fill = "Vertical\nexchange\n(m/time step)") +
facet_wrap( ~ dest.plot.layer, ncol = 3) +
theme_bw() + xlab("") + ylab("") +
theme(plot.background = element_blank()) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL) +
coord_cartesian(xlim = rangesVert$x, ylim = rangesVert$y)
if (input$CI.BoxIDVert) { # add box id
gg <- gg + geom_text(data = input.object$box.data, mapping = aes(x = x.in, y = y.in, label = boxid), size = 2.5, inherit.aes = FALSE)
}
gg
})
# -- Vertical exchanges -- Table
output$table.Vert <- DT::renderDataTable({
t <- round(as.integer((input$NI.Vert - time[1]) / dt), digits = 0) + 1
exchange.value[ , , , ] <- 0.0
for (i in 1:numboxes) {
for (j in 1:numlayers) {
for (k in 1:numdests) {
if (!is.na(input.object$exchange[k,j,i,t])) {
dest.i <- input.object$dest.box[k,j,i,t] + 1
dest.j <- input.object$dest.layer[k,j,i,t] + 1
if (!is.na(dest.i) & !is.na(dest.j)) {
exchange.value[i,j,dest.i,dest.j] <-
input.object$exchange[k,j,i,t] # from i to dest
exchange.value[dest.i,dest.j,i,j] <-
-input.object$exchange[k,j,i,t] # from dest to i
}
}
}
}
}
vert.dir[ , ] <- 0.0
for (i in 1:numboxes) {
for (j in 1:numlayers) { # surface to bottom
if ((j - 1) > 0) { # a box above
if (!is.na(exchange.value[i,j-1,i,j])) { # exchange is provided
vert.dir[i,j] <- exchange.value[i,j-1,i,j] / box.data$area[i] # + is up
}
}
if ((j + 1) < numlayers) { # a box below
if (!is.na(exchange.value[i,j,i,j+1])) { # exchange is provided
if (is.na(vert.dir[i,j])) { # no exchange into this box yet
vert.dir[i,j] <- exchange.value[i,j,i,j+1] / box.data$area[i] # + is up
} else {
vert.dir[i,j] <- vert.dir[i,j] + exchange.value[i,j,i,j+1] / box.data$area[i]
}
}
}
}
}
df <- data.frame(boxid = 0:(numboxes-1), area = box.data$area,
numlayers = box.data$numlayers, vert.dir)
layer.names <- rep("x", numlayers)
for (i in 1:numlayers) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[4:(numlayers+3)] <- layer.names
tmp <- numlayers+3
df <- tidyr::gather(df, layer, vert, 4:tmp)
df$layer <- sort(rep(0:(numlayers-1), numboxes))
df$dest.plot.layer <- df$numlayers - df$layer
df$dest.plot.layer[df$dest.plot.layer < 1] <-
numlayers + df$dest.plot.layer[df$dest.plot.layer < 1]
df$vert[df$layer >= df$numlayers] <- NA
df <- df %>% dplyr::filter(!is.na(vert))
df <- df[c(1,2,3,4,6,5)] # reorder columns
DT::datatable(df, rownames = FALSE,
colnames = c('box', 'area', 'water layers', 'layer (Atlantis)', 'layer (plotting)', 'vertical exchange'),
caption = "Vertical exchanges (m^3 / box area). Positive values indicate upward flow.")
})
# -- Temperature -- Plot (Spatial)
output$plotTemp <- renderPlot({
# browser()
# calculate the time index of the data matrices
t <- round((input$NI.Temp - input.object$t[1]) / dt, digits = 0) + 1
if (!is.null(input.object$temperature)) {
df <- data.frame(boxid = 0:(numboxes-1), numlayers = box.data$numlayers,
t(input.object$temperature[ , ,t]))
layer.names <- rep("x", numlayers+1)
for (i in 1:(numlayers+1)) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[3:(numlayers+3)] <- layer.names
tmp <- numlayers+3
df <- tidyr::gather(df, layer, temperature, 3:tmp)
df$layer <- sort(rep(0:numlayers, numboxes))
df$dest.plot.layer <- ifelse(df$layer == numlayers,
"sediment", df$numlayers - df$layer)
df$temperature[df$dest.plot.layer < 1] <- NA
df$temperature[df$numlayers == 0] <- NA
df$dest.plot.layer[df$dest.plot.layer < 1] <- numlayers +
as.integer(df$dest.plot.layer[df$dest.plot.layer < 1])
df.plot <- dplyr::left_join(input.object$map.vertices, df, by = "boxid")
df.plot$dest.plot.layer <- paste0( 'Layer - ',df.plot$dest.plot.layer)
gg <- ggplot(data = df.plot,
aes(x = x, y = y, group = boxid, fill = temperature)) +
geom_polygon(colour = "grey25", size = 0.25, na.rm = TRUE) +
scale_fill_gradient(low = "lightblue1", high = "#de2d26", na.value="wheat1") +
labs(fill = "Celcius") +
facet_wrap( ~ dest.plot.layer, ncol = 3) +
theme_bw(base_size = 18) + xlab("") + ylab("") +
theme(plot.background = element_blank()) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL) +
coord_cartesian(xlim = rangesTemp$x, ylim = rangesTemp$y)
if (input$CI.BoxIDTemp) { # add box id
gg <- gg + geom_text(data = input.object$box.data, mapping = aes(x = x.in, y = y.in, label = boxid), size = 2.5, inherit.aes = FALSE)
}
# browser()
# png('/home/por07g/Documents/Projects/Salish_Sea/Documents/Report/spatial_temp.png', width = 1200, heigh = 900)
gg
# dev.off()
} else {
df <- data.frame(x = 0, y = 0)
ggplot(data = df, aes(x = x, y = y)) +
ggtitle("No Temperature data provided") +
theme_bw() + xlab("") + ylab("") +
theme(
plot.background = element_blank(),
plot.title=element_text(colour="red")
) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL)
}
})
# -- Temperature -- Table (Spatial)
output$table.Temp <- DT::renderDataTable({
# calculate the time index of the data matrices
t <- round((input$NI.Temp - input.object$t[1]) / dt, digits = 0) + 1
if (!is.null(input.object$temperature)) {
df <- data.frame(boxid = 0:(numboxes-1), numlayers = box.data$numlayers,
t(input.object$temperature[ , ,t]))
layer.names <- rep("x", numlayers+1)
for (i in 1:(numlayers+1)) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[3:(numlayers+3)] <- layer.names
tmp <- numlayers+3
df <- tidyr::gather(df, layer, temperature, 3:tmp)
df$layer <- sort(rep(0:numlayers, numboxes))
df$dest.plot.layer <- ifelse(df$layer == numlayers,
"sediment", df$numlayers - df$layer)
df$temperature[df$dest.plot.layer < 1] <- NA
df$dest.plot.layer[df$dest.plot.layer < 1] <- numlayers +
as.integer(df$dest.plot.layer[df$dest.plot.layer < 1])
df <- df[c(1,2,3,5,4)] # change order of columns
df <- df[df$numlayers > 0, ]
df <- df[!((df$layer != numlayers) & (df$layer >= df$numlayers)), ]
DT::datatable(df, rownames = FALSE,
colnames = c('box', 'water layers', 'layer (Atlantis)', 'layer (plotting)', 'temperature'),
caption = "Temperature (Celcius).")
}
})
# -- Temperature -- Plot (Time-series)
output$plotTempTS <- renderPlot({
focal.box <- as.integer(input$SI.TempTS) # 1:numboxes
if (!is.null(input.object$temperature)) {
df <- data.frame(time = time,
t(input.object$temperature[ , focal.box+1, ]))
layer.names <- rep("x", numlayers+1)
for (i in 1:(numlayers+1)) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[2:(numlayers+2)] <- layer.names
df <- tidyr::gather(df, layer, temperature, 2:(numlayers+2))
df$layer <- sort(rep(0:numlayers, numtimes))
df$dest.plot.layer <- ifelse(df$layer == numlayers,
"sediment", box.data$numlayers[focal.box+1] - df$layer)
df$temperature[df$dest.plot.layer < 1] <- NA
df$temperature[df$numlayers == 0] <- NA
df$dest.plot.layer[df$dest.plot.layer < 1] <- numlayers +
as.integer(df$dest.plot.layer[df$dest.plot.layer < 1])
plot.cols <- c(colorRampPalette(c("#fcbba1", "#99000d"))( numlayers ),"black")
p <- ggplot(data = df,
aes(x = time, y = temperature, color = dest.plot.layer)) +
geom_line(na.rm = TRUE) +
geom_point(na.rm = TRUE) +
scale_color_manual(values=plot.cols) +
ylab("Temperature (Celcius)") + xlab("Time (days)") +
labs(color = "Plot layer") +
theme_bw(base_size = 18)
} else {
df <- data.frame(x = 0, y = 0)
p <- ggplot(data = df, aes(x = x, y = y)) +
ggtitle("No temperature data provided") +
theme_bw() + xlab("") + ylab("") +
theme(
plot.background = element_blank(),
plot.#TODO: itle=element_text(colour="red")
) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL)
}
## browser()
## png('/home/por07g/Documents/Projects/Salish_Sea/Documents/Report/temporal_temp.png', width = 1200, heigh = 900)
## p
## dev.off()
})
# -- Temperature -- Table (Time-series)
output$table.TempTS <- DT::renderDataTable({
focal.box <- as.integer(input$SI.TempTS) # 1:numboxes
if (!is.null(input.object$temperature)) {
df <- data.frame(time = time,
t(input.object$temperature[ , focal.box+1, ]))
layer.names <- rep("x", numlayers+1)
for (i in 1:(numlayers+1)) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[2:(numlayers+2)] <- layer.names
df <- tidyr::gather(df, layer, temperature, 2:(numlayers+2))
df$layer <- sort(rep(0:numlayers, numtimes))
df$dest.plot.layer <- ifelse(df$layer == numlayers,
"sediment", box.data$numlayers[focal.box+1] - df$layer)
df$temperature[df$dest.plot.layer < 1] <- NA
df$temperature[df$numlayers == 0] <- NA
df$dest.plot.layer[df$dest.plot.layer < 1] <- numlayers +
as.integer(df$dest.plot.layer[df$dest.plot.layer < 1])
df <- df[ , c(1,2,4,3)]
df <- df[!((df$layer != numlayers) &
(df$layer >= box.data$numlayers[focal.box+1])), ]
DT::datatable(df, rownames = FALSE,
colnames = c('time', 'layer (Atlantis)', 'layer (plotting)', 'temperature'),
caption = "Temperature (Celcius).")
}
})
# -- Salinity -- Plot (Spatial)
output$plotSalt <- renderPlot({
# calculate the time index of the data matrices
t <- round((input$NI.Salt - input.object$t[1]) / dt, digits = 0) + 1
df <- data.frame(boxid = 0:(numboxes-1), numlayers = box.data$numlayers,
t(input.object$salinity[ , ,t]))
layer.names <- rep("x", numlayers+1)
for (i in 1:(numlayers+1)) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[3:(numlayers+3)] <- layer.names
tmp <- numlayers+3
df <- tidyr::gather(df, layer, salinity, 3:tmp)
df$layer <- sort(rep(0:numlayers, numboxes))
df$dest.plot.layer <- ifelse(df$layer == numlayers,
"sediment", df$numlayers - df$layer)
df$salinity[df$dest.plot.layer < 1] <- NA
df$salinity[df$numlayers == 0] <- NA
df$dest.plot.layer[df$dest.plot.layer < 1] <- numlayers +
as.integer(df$dest.plot.layer[df$dest.plot.layer < 1])
df.plot <- dplyr::left_join(input.object$map.vertices, df, by = "boxid")
df.plot$dest.plot.layer <- paste0( 'Layer - ',df.plot$dest.plot.layer)
gg <- ggplot(data = df.plot,
aes(x = x, y = y, group = boxid, fill = salinity)) +
geom_polygon(colour = "grey25", size = 0.25, na.rm = TRUE) +
scale_fill_gradient(low = "lightblue1", high = "#de2d26", na.value="wheat1") +
labs(fill = "g/kg") +
facet_wrap( ~ dest.plot.layer, ncol = 3) +
theme_bw(base_size = 18) + xlab("") + ylab("") +
theme(plot.background = element_blank()) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL) +
coord_cartesian(xlim = rangesSalt$x, ylim = rangesSalt$y)
if (input$CI.BoxIDSalt) { # add box id
gg <- gg + geom_text(data = input.object$box.data, mapping = aes(x = x.in, y = y.in, label = boxid), size = 2.5, inherit.aes = FALSE)
}
#browser()
#png('/home/por07g/Documents/Projects/Salish_Sea/Documents/Report/spatial_salt.png', width = 1200, heigh = 900)
gg
#dev.off()
})
# -- Salinity -- Table (Spatial)
output$table.Salt <- DT::renderDataTable({
# calculate the time index of the data matrices
t <- round((input$NI.Salt - input.object$t[1]) / dt, digits = 0) + 1
df <- data.frame(boxid = 0:(numboxes-1), numlayers = box.data$numlayers,
t(input.object$salinity[ , ,t]))
layer.names <- rep("x", numlayers+1)
for (i in 1:(numlayers+1)) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[3:(numlayers+3)] <- layer.names
tmp <- numlayers+3
df <- tidyr::gather(df, layer, salinity, 3:tmp)
df$layer <- sort(rep(0:numlayers, numboxes))
df$dest.plot.layer <- ifelse(df$layer == numlayers,
"sediment", df$numlayers - df$layer)
df$temperature[df$dest.plot.layer < 1] <- NA
df$dest.plot.layer[df$dest.plot.layer < 1] <- numlayers +
as.integer(df$dest.plot.layer[df$dest.plot.layer < 1])
df <- df[c(1,2,3,5,4)] # change order of columns
df <- df[df$numlayers > 0, ]
df <- df[!((df$layer != numlayers) & (df$layer >= df$numlayers)), ]
DT::datatable(df, rownames = FALSE,
colnames = c('box', 'water layers', 'layer (Atlantis)', 'layer (plotting)', 'salinity'),
caption = "Salinity (g/kg).")
})
# -- Salinity -- Plot (Time-series)
output$plotSaltTS <- renderPlot({
focal.box <- as.integer(input$SI.SaltTS) # 1:numboxes
if (!is.null(input.object$salinity)) {
df <- data.frame(time = time,
t(input.object$salinity[ , focal.box+1, ]))
layer.names <- rep("x", numlayers+1)
for (i in 1:(numlayers+1)) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[2:(numlayers+2)] <- layer.names
df <- tidyr::gather(df, layer, salinity, 2:(numlayers+2))
df$layer <- sort(rep(0:numlayers, numtimes))
df$dest.plot.layer <- ifelse(df$layer == numlayers,
"sediment", box.data$numlayers[focal.box+1] - df$layer)
df$salinity[df$dest.plot.layer < 1] <- NA
df$salinity[df$numlayers == 0] <- NA
df$dest.plot.layer[df$dest.plot.layer < 1] <- numlayers +
as.integer(df$dest.plot.layer[df$dest.plot.layer < 1])
plot.cols <- c(colorRampPalette(c("#fcbba1", "#99000d"))( numlayers ),"black")
gg <- ggplot(data = df,
aes(x = time, y = salinity, color = dest.plot.layer)) +
geom_line(na.rm = TRUE) +
geom_point(na.rm = TRUE) +
scale_color_manual(values=plot.cols) +
ylab("Salinity (g/kg)") + xlab("Time (days)") +
labs(color = "Plot layer") +
theme_bw(base_size = 18)
} else {
df <- data.frame(x = 0, y = 0)
gg <- ggplot(data = df, aes(x = x, y = y)) +
ggtitle("No salinity data provided") +
theme_bw() + xlab("") + ylab("") +
theme(
plot.background = element_blank(),
plot.title=element_text(colour="red")
) +
scale_y_continuous(breaks=NULL) + scale_x_continuous(breaks=NULL)
}
#browser()
#png('/home/por07g/Documents/Projects/Salish_Sea/Documents/Report/temporal_salt.png', width = 1200, heigh = 900)
gg
#dev.off()
})
# -- Salinity -- Table (Time-series)
output$table.SaltTS <- DT::renderDataTable({
focal.box <- as.integer(input$SI.SaltTS) # 1:numboxes
if (!is.null(input.object$salinity)) {
df <- data.frame(time = time,
t(input.object$salinity[ , focal.box+1, ]))
layer.names <- rep("x", numlayers+1)
for (i in 1:(numlayers+1)) {
layer.names[i] <- paste("l", as.character(i-1), sep = "")
}
names(df)[2:(numlayers+2)] <- layer.names
df <- tidyr::gather(df, layer, salinity, 2:(numlayers+2))
df$layer <- sort(rep(0:numlayers, numtimes))
df$dest.plot.layer <- ifelse(df$layer == numlayers,
"sediment", box.data$numlayers[focal.box+1] - df$layer)
df$salinity[df$dest.plot.layer < 1] <- NA
df$salinity[df$numlayers == 0] <- NA
df$dest.plot.layer[df$dest.plot.layer < 1] <- numlayers +
as.integer(df$dest.plot.layer[df$dest.plot.layer < 1])
df <- df[ , c(1,2,4,3)]
df <- df[!((df$layer != numlayers) &
(df$layer >= box.data$numlayers[focal.box+1])), ]
DT::datatable(df, rownames = FALSE,
colnames = c('time', 'layer (Atlantis)', 'layer (plotting)', 'salinity'),
caption = "Salinity (g/kg).")
}
})
observeEvent(input$exitButton, {
stopApp()
})
}
)
}
# +==========================================================+
# | make.map.object.frc : collect data for displaying maps |
# +==========================================================+
make.map.object.frc <- function(bgm.file, cum.depth){
bgm <- readLines(bgm.file) # read in the geometry file
numboxes <- 0
j <- grep(pattern = "nbox", x = bgm, value = FALSE) # file row(s)
if (length(j) > 0) { # found rows with nbox
jnew <- NULL
for (jj in 1:length(j)) {
# Valid row is when tmplt is the first entry and second is a number
text.split <- unlist(str_split(
gsub(pattern = "[\t ]+", x = bgm[j[jj]], replacement = " "), " "))
if (text.split[1] == "nbox") {
jnew <- c(jnew,j[jj]) # add the row that satisfies the criteria
}
}
j <- jnew # use this list of rows as they are valid
if (length(j) == 1) { # a single row is found
text.split <- unlist(str_split(
gsub(pattern = "[\t ]+", x = bgm[j], replacement = " "), " "))
numboxes <- as.numeric(text.split[2])
}
}
# Extract the box vertices
map.vertices <- data.frame()
for(i in 1:numboxes){
txt.find <- paste("box", i - 1, ".vert", sep = "")
j <- grep(txt.find, bgm)
for (jj in 1:length(j)) {
text.split <- unlist(str_split(
gsub(pattern = "[\t ]+", x = bgm[j[jj]], replacement = " "), " "))
if (text.split[1] == txt.find) {
map.vertices <- rbind(map.vertices, cbind(i - 1, as.numeric(text.split[2]),
as.numeric(text.split[3])))
}
}
}
names(map.vertices) <- c("boxid", "x", "y")
# find the depths and areas, and identify island boxes
box.indices <- rep(0, numboxes)
for(i in 1:numboxes){ # box depth
box.indices[i] <- grep(paste("box", i - 1, ".botz", sep = ""), bgm)
}
z.tmp <- strsplit(bgm[box.indices], "\t")
z <- as.numeric(sapply(z.tmp,`[`,2))
box.data <- data.frame(boxid = 0:(numboxes-1), z = z)
box.data <- mutate(box.data, is.island = (z >= 0.0))
for(i in 1:numboxes){ # box area
box.indices[i] <- grep(paste("box", i - 1, ".area", sep = ""), bgm)
}
a.tmp <- strsplit(bgm[box.indices], "\t")
a <- as.numeric(sapply(a.tmp,`[`,2))
box.data$area <- a
box.data <- mutate(box.data, volume = -z*area)
# read in the internal coordinates from bgm file
box.indices <- rep(0, numboxes)
x.in <- rep(0, numboxes)
y.in <- rep(0, numboxes)
for(i in 1:numboxes){
j <- grep(paste("box", i - 1, ".inside", sep = ""), bgm)
text.split <- unlist(str_split(
gsub(pattern = "[\t ]+", x = bgm[j], replacement = " "), " "))
x.in[i] <- as.numeric(text.split[2])
y.in[i] <- as.numeric(text.split[3])
}
box.data$x.in <- x.in # add internal y-location
box.data$y.in <- y.in # add internal y-location
box.data$boxid <- factor(box.data$boxid) # make boxid a factor
# calculate the number of water layers per box base don cumulative depths
# CHECK THIS IS CORRECT: boxid = 21, index = 21 (6 but should be 5)
z <- -box.data$z # convert depths so depth below surface is positive
z <- pmax(0,z) # remove depths above the surface
z <- pmin(z, max(cum.depth)) # don't alow depth to be greater than max depth
box.numlayers <- rep(0, length(z)) # vector containing number of water layers
for (i in 1: length(z)) {
box.numlayers[i] <- sum(z[i] > cum.depth)
}
box.data$numlayers <- box.numlayers # add the vector to box.data
return(list(
map.vertices = map.vertices,
box.data = box.data)
)
}
# +===================================================================+
# | make.exchanges.object.frc : collect exchanges data from nc file |
# +===================================================================+
make.exchanges.object.frc <- function(exchange.file) {
nc.exchange.out <- nc_open(exchange.file) # open .nc file
t <- ncvar_get(nc.exchange.out, "t")
exchange <- ncvar_get(nc.exchange.out, "exchange") # keep raw values
dest.box <- ncvar_get(nc.exchange.out, "dest_b") # keep raw values
dest.layer <- ncvar_get(nc.exchange.out, "dest_k") # keep raw values
nc_close(nc.exchange.out)
numboxes <- dim(exchange)[3] # number of boxes
t <- t / (60*60*24) # convert seconds to days
numlayers <- dim(exchange)[2] # number of depth layers
numdests <- dim(exchange)[1] # number of destinations
numtimes <- dim(exchange)[4] # number of time points
return(list(
t = t,
numdests = numdests,
numlayers = numlayers,
numboxes = numboxes,
numtimes = numtimes,
exchange = exchange,
dest.box = dest.box,
dest.layer = dest.layer
))
}
# +=================================================================+
# | make.salinity.object.frc : collect salinity data from nc file |
# +=================================================================+
make.salinity.object.frc <- function(salinity.file) {
nc.salinity.out <- nc_open(salinity.file) # open .nc file
salinity <- ncvar_get(nc.salinity.out, "salinity") # keep raw values
nc_close(nc.salinity.out)
return(salinity)
}
# +======================================================================+
# | make.temperature.object.frc : collect temperature data from nc file |
# +======================================================================+
make.temperature.object.frc <- function(temperature.file) {
nc.temperature.out <- nc_open(temperature.file) # open .nc file
temperature <- ncvar_get(nc.temperature.out, "temperature") # keep raw values
nc_close(nc.temperature.out)
return(temperature)
}
# +==========================================================================+
# | make.sh.exchange.object : collect forcing data to display in shiny app |
# +==========================================================================+
#' @title Function that generates an object used by sh.forcings
#'
#' @description
#' Takes data from a box geometry file and a vector of cumulative water layer
#' depths, as well as netCDF files of: exchanges, salinity and temperature,
#' and generates a list object that is the parameter to \code{\link[shinyrAtlantis]{sh.forcings}} (see Examples).
#'
#' @param bgm.file Box geometry model (.bgm) file used by Atlantis that defines box boundaries and depths.
#' @param exchange.file NetCDF (.nc) file containing water exchanges between box layers.
#' @param cum.depth Vector of depths (starting at 0) that delineate the depths of the water layers for the model.
#' @param temperature.file NetCDF (.nc) file containing time-series of temperature values for each water layer in each box. This parameter is not required.
#' @param salinity.file NetCDF (.nc) file containing time-series of salinity values for each water layer in each box. This parameter is not required.
#'
#' @return R list object used by \code{\link[shinyrAtlantis]{sh.forcings}}.
#'
#' @examples
#' \dontrun{
#' exchange.file <- "GBR108_hydro.nc"
#' salinity.file <- "GBR108_salt.nc"
#' temperature.file <- "GBR108_temp.nc"
#' bgm.file <- "gbr_box_03012012.bgm"
#' cum.depth <- c(0,5,10,20,50,100,200,3000) # cumulative water layer depths
#'
#' input.object <- make.sh.forcings.object(
#' bgm.file = bgm.file,
#' exchange.file = exchange.file,
#' cum.depth = cum.depth,
#' temperature.file = temperature.file,
#' salinity.file = salinity.file
#' )
#' sh.forcings(input.object)
#' }
#' @export
make.sh.forcings.object <- function(bgm.file, exchange.file, cum.depth,
temperature.file = NULL, salinity.file = NULL) {
cat("-- Extracting map data\n")
map.object <- make.map.object.frc(bgm.file, cum.depth)
cat("-- Extracting data (this may take a while)\n")
flux.object <- make.exchanges.object.frc(exchange.file)
if (!is.null(temperature.file)) {
cat("-- Extracting temperature data\n")
temperature <- make.temperature.object.frc(temperature.file)
} else {
cat("-- No temperature file provided\n")
temperature <- NULL
}
if (!is.null(salinity.file)) {
cat("-- Extracting salinity data\n")
salinity <- make.salinity.object.frc(salinity.file)
} else {
cat("-- No salinity file provided\n")
salinity <- NULL
}
return(list(
cum.depth = cum.depth,
map.vertices = map.object$map.vertices,
box.data = map.object$box.data,
numboxes = flux.object$numboxes,
numlayers = flux.object$numlayers,
numdests = flux.object$numdests,
numtimes = flux.object$numtimes,
t = flux.object$t,
exchange = flux.object$exchange,
dest.layer = flux.object$dest.layer,
dest.box = flux.object$dest.box,
temperature = temperature,
salinity = salinity
))
}
# Some examples of generating lists from data and viewing the data
# setwd("~/Documents/Projects/Fisheries/Atlantis/Models/GBR/Input")
# exchange.file <- "GBR108_hydro.nc"
# salinity.file <- "GBR108_salt.nc"
# temperature.file <- "GBR108_temp.nc"
# bgm.file <- "gbr_box_03012012.bgm"
# cum.depth <- c(0,5,10,20,50,100,200,3000)
# setwd("~/Documents/Projects/Fisheries/Atlantis/Forcings Tool/GHHP/")
# exchange.file <- "Gladstone305_6HourHYdro.nc"
# bgm.file <- "GHHP_xy_v2.bgm"
# cum.depth <- c(0,5,10,20,250)
# setwd("~/Documents/Projects/Fisheries/Atlantis/Models/JFRE")
# exchange.file <- "JFRE_hydro.nc"
# salinity.file <- "JFRE_salt.nc"
# temperature.file <- "JFRE_temp.nc"
# bgm.file <- "JFRE_xy.bgm"
# cum.depth <- c(0,20,50,150,250,400,650,1000,4300)
# input.object <- make.sh.forcings.object(
# bgm.file = bgm.file,
# exchange.file = exchange.file,
# cum.depth = cum.depth,
# temperature.file = temperature.file,
# salinity.file = salinity.file
# )
#
# sh.forcings(input.object)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.