#' @title Plot annual time series
#'
#' @author Chantelle Layton
#'
#' @description Creates a time-series of annual time series in the format that is used
#' for
#'
#' @param x a vector indicating the times of observations
#' @param y a vector indicating the observations
#' @param ysc a vector indicating observations used for scorecard, ignored if `plotScorecard = FALSE`
#' @param xlim Optional limit for x axis
#' @param ylim Optional limit for y axis
#' @param xlab Logical indicating whether to label the x axis
#' @param ylabel Logical indicating whether to label the y axis
#' @param yaxs Logical indicating whether to have a labelled y-axis
#' @param plotSd Logical indicating whether to add +/- 0.5 standard deviation lines on plot of
#' the annual anomaly over the defined climatology period.
#' @param climatologyYears Vector of length two indicating the climatology years, ignored if
#' `plotSd = FALSE`.
#' @param plotPoints Logical indicating whether or not to plot points on top of line
#' @param plotRunningAvg Logical indicating whether or not to plot a 5 year running average
#' @param plotLmTrend Logical indicating whether or not to print out results of a linear regression
#' on the plot
#' @param lmResults A `lm` format object, if `plotLmTrend = FALSE`, ignored.
#' @param plotClimatologyMean Logical indicating whether or not to print out the climatology mean.
#' @param climatologyMean A numeric value, if `plotClimatologyMean = FALSE`, ignored.
#' @param plotScorecard Logical indicating whether or not to plot scorecard on side = 1.
#' @param scorecardLines Logical indicating whether or not to put vertical lines on scorecard.
#' @param scorecardLabels Logical indicating whether or not to print `ysc` values in scorecard.
#' @param scorecardSeparation Value used to denote the separation between the main plot and scorecard.
#' Suggested to use `par('cin')[2]` (default) and play with that value. If closer is desired, decrease.
#' @param scorecardWidth Value used to denote the width of the scorecard. Suggested to use
#' `par('cin')[2]` (default) and play with that value. If wider is desired, increase.
#'
#' @details The current format of the figure is for the 2019 research document. Any changes in the future
#' will be reflected in the code with comments, and here.
#'
#' \itemize{
#' \item{2019 - Annual anomalies are plotted with a grey line and a 5-year running mean plotted over top in black.
#' Thick dashed horizonal lines of the standard deviation of the annual climatology are added. Code has
#' been written to ensure that at least one century is labelled.}
#' }
#'
#' @importFrom stats lm
#' @importFrom stats sd
#' @importFrom stats coef
#' @importFrom graphics plot
#' @importFrom graphics abline
#' @importFrom graphics axis
#' @importFrom graphics lines
#' @importFrom graphics mtext
#' @importFrom graphics points
#' @importFrom graphics legend
#'
#' @export
#'
plotAnnualAnomaly <- function(x, y, ysc, xlim, ylim, xlab = TRUE, climatologyYears, ylabel = TRUE,
plotSd = TRUE, yaxs = TRUE, plotPoints = TRUE, plotRunningAvg = TRUE,
plotLmTrend = FALSE, lmResults,
plotClimatologyMean = FALSE, climatologyMean,
plotScorecard = FALSE, scorecardLines = TRUE, scorecardLabels = TRUE,
scorecardSeparation = par('cin')[2], scorecardWidth = par('cin')[2]){
data("anomalyColors")
okbreaks <- anomalyColors$breaks <= 3.5
okcol <- anomalyColors$breaks < 3.5
anomalyColors[['breaks']] <- anomalyColors[['breaks']][okbreaks]
anomalyColors[['colors']] <- anomalyColors[['colors']][okcol]
# need to extend the top half, keep adding dark red
addBreaks <- seq(4.0, 5.5, 0.5)
anomalyColors[['breaks']] <- c(anomalyColors[['breaks']], addBreaks)
anomalyColors[['colors']] <- c(anomalyColors[['colors']], rep(anomalyColors[['colors']][length(anomalyColors[['colors']])], length(addBreaks)))
# need to extend the bottom half, just keep adding the dark blue
addBreaks <- seq(-5.5, -4.0, 0.5)
anomalyColors[['breaks']] <- c(addBreaks, anomalyColors[['breaks']])
anomalyColors[['colors']] <- c(rep(anomalyColors[['colors']][1], length(addBreaks)), anomalyColors[['colors']])
is.even <- function(x) x %% 2 == 0
# ylabel
L <- '['
R <- ']'
ylab <- getAnomalyLabel(item = 'temperatureAnomaly', sep = "")
# xlim
# set it if not given
xlimGiven <- !missing(xlim)
if(!xlimGiven){
xlim <- range(x, na.rm = TRUE)
}
# ylim
# set it if not given
ylimGiven <- !missing(ylim)
if(!ylimGiven){
ylim <- range(y, na.rm = TRUE)
}
if(plotScorecard){
xlim <- xlim + c(-0.5, 1.0) # to make the beginning and end nice
# plot bottom scorecard first, some code taken from drawPalette()
# set up margins
omai <- par("mai")
mai <- rep(0, 4)
# arguments for paletteCalculations
# scorecardSeparation
# set it if not given
separationGiven <- !missing(scorecardSeparation)
if(!separationGiven){
scorecardSeparation <- par('cin')[2]
}
widthGiven <- !missing(scorecardWidth)
if(!separationGiven){
scorecardWidth <- par('cin')[2]
}
pos <- 1
debug <- 3
zlab <- ""
pc <- paletteCalculations(separation = scorecardSeparation, width = scorecardWidth,
maidiff=mai, pos=pos,
zlab=zlab, debug=debug-1)
# plot
z <- matrix(data = ysc, nrow = length(x), ncol = 1)
zy <- 1
# plot it
barxlim <- xlim #+ c(-1, 1)
par(mai = ifelse(pc$mai1 > 0, pc$mai1, 0))
image(x = x, y = zy, z = z,
xlim = barxlim,
axes = FALSE, xlab="", ylab="",
col = anomalyColors[['colors']],
breaks = anomalyColors[['breaks']])
rect(par("usr")[1],par("usr")[3],par("usr")[2],par("usr")[4],col = "lightgray")
image(x = x, y = zy, z = z,
xlim = barxlim,
axes = FALSE, xlab="", ylab="",
col = anomalyColors[['colors']],
breaks = anomalyColors[['breaks']],
add = TRUE)
box()
## add vertical lines to separate years
if(scorecardLines) {lapply(x, function(k) lines(x = rep(k, 2) + 0.5, y = c(0, 1) + 0.5))}
# axis and labels
## annual
if(scorecardLabels) {
textcol <- rep('black', length(ysc))
whitetext <- ysc <= -3.0 | (ysc >= 3.0 & ysc < 3.5)
whitetext[is.na(whitetext)] <- FALSE
annualtextat <- x
if(any(!whitetext)) text(x = annualtextat[!whitetext == TRUE & !is.na(ysc)], y = 1, labels = sprintf('%.1f', ysc[!whitetext == TRUE & !is.na(ysc)]), col = 'black', cex = 0.8, srt = 90)
if(any(whitetext)) text(x = annualtextat[whitetext == TRUE], y = 1, labels = sprintf('%.1f', ysc[whitetext == TRUE & !is.na(ysc)]), col = 'white', cex = 0.8, srt = 90)
}
# x-axis, x-axis labels
if(abs(diff(xlim)) > 10){
xat <- seq(round(xlim[1], digits = -1), round(xlim[2], digits = -1), 10) # tick every decade
centuries <- c(1800, 1900, 2000)
okcentury <- centuries %in% xat
centuryIdx <- unlist(lapply(centuries[okcentury], function(k) which(k == xat)))
# if centuryIdx[1] is even, start xlabel idx at 2, if odd, at 1
xlabels <- seq(ifelse(is.even(centuryIdx[1]), 2, 1), length(xat), 2) # label every second decade, make sure centuries are labelled
axis(side = 1, at = xat, labels = FALSE)
if(xlab){
#axis(side = 1, at = xat[xlabels], labels = xat[xlabels])
axis(side = 1, at = xat, labels = xat) # try this for now
}
} else {
xat <- pretty(xlim)
if(xlab){
axis(side = 1, at = xat)
} else {
axis(side = 1, at = xat, labels = FALSE)
}
}
# reset mai, prep for primary plot
par(new=TRUE, mai=pc$mai2)
par(mar = par('mar') * c(0, 1, 1, 1) + c(4.5, 0, 0, 0)) # have to change first term of second addition if changes made to colorbar height
}
plot(x = x,
y = y, col = 'white',
lwd = 0.6,
type = 'n',
xaxs = ifelse(plotScorecard, 'i', 'r'),
xlim = xlim, ylim = ylim,
xaxt = 'n', yaxt = 'n',
xlab = '', ylab = '')
#...)
# x-axis, x-axis labels
if(!plotScorecard) {
if(abs(diff(xlim)) > 10){
xat <- seq(round(xlim[1], digits = -1), round(xlim[2], digits = -1), 10) # tick every decade
centuries <- c(1800, 1900, 2000)
okcentury <- centuries %in% xat
centuryIdx <- unlist(lapply(centuries[okcentury], function(k) which(k == xat)))
# if centuryIdx[1] is even, start xlabel idx at 2, if odd, at 1
xlabels <- seq(ifelse(is.even(centuryIdx[1]), 2, 1), length(xat), 2) # label every second decade, make sure centuries are labelled
axis(side = 1, at = xat, labels = FALSE)
if(xlab){
#axis(side = 1, at = xat[xlabels], labels = xat[xlabels])
axis(side = 1, at = xat, labels = xat) # try this for now
}
} else {
xat <- pretty(xlim)
if(xlab){
axis(side = 1, at = xat)
} else {
axis(side = 1, at = xat, labels = FALSE)
}
}
}
# y-axis, y-axis labels, y-axis label
if(yaxs){
{if(diff(ylim) < 20){ # kind of bad logic
yat <- seq(round(ylim[1], digits = 0), round(ylim[2], digits = 0), 1) # label every one
} else {
yat <- pretty(ylim)
}
}
axis(side = 2, at = yat, labels = yat)
}
if(ylabel) mtext(text = ylab, side = 2, line = 2, cex = 4/5)
# grid
# ugh, function grid() not working when nx and ny given
abline(v = xat, col = 'lightgray', lty = 'dotted')
if(yaxs) abline(h = yat, col = 'lightgray', lty = 'dotted')
# replot initial lines so its over the grid
if(plotPoints){
lines(x = x, y = y, col = 'black')
points(x = x, y = y, pch = 21, col = 'black', bg = 'white')
} else {
lines(x = x, y = y, col = 'black', lty = 2)
}
# add additional stuff to plot
# climatology standard deviation
if(plotSd){
okclim <- x >= climatologyYears[1] & x <= climatologyYears[2]
aasd <- sd(y[okclim], na.rm = TRUE)
#{if(diff(ylim) > 20) { # commented out this if else statement 20200402
cmean <- mean(y[okclim], na.rm = TRUE)
abline(h = cmean, lty = 1, lwd = 2)
abline(h = (aasd/2) + cmean, lty = 2, lwd = 2)
abline(h = (-aasd/2) + cmean, lty = 2, lwd = 2)
#} else {
# abline(h = 0)
# abline(h = aasd/2, lty = 2, lwd = 2)
# abline(h = -aasd/2, lty = 2, lwd = 2)
#}
#}
}
# replot initial lines so its over the grid and sd lines
if(plotPoints){
lines(x = x, y = y, col = 'black')
points(x = x, y = y, pch = 21, col = 'black', bg = 'white')
} else {
lines(x = x, y = y, col = 'black', lty = 2)
}
# 5 year running mean filter
if(plotRunningAvg){
aafilt <- stats::filter(y, rep(0.2, 5), method = 'convolution', sides = 2)
lines(x = x, y = aafilt, lwd = 2)
}
if(plotLmTrend){
slope <- sprintf('%.1f', round(unname(coef(lmResults)[2]) * 100, 1))
slope <- ifelse(Sys.getenv('LANG') == 'fr', gsub('\\.', ',', slope), slope) # comma instead of period for french
unit <- bquote(degree * 'C')
yearlab <- gettext('years', domain = 'R-csasAtlPhys')
legendText <- bquote(.(slope) * .(unit) * ' / 100 ' * .(yearlab))
legend('bottomright', legend = legendText, bty = 'n', cex = 1.2)
}
if(plotClimatologyMean){
unit <- bquote(degree * 'C')
meanlab <- gettext('Mean', domain = 'R-csasAtlPhys')
climMean <- sprintf('%.2f', climatologyMean)
legend('bottomleft', legend = bquote(.(meanlab)*' = ' * .(climMean) * .(unit)), bty = 'n')
}
}
#' @title Plot monthly time series
#'
#' @author Chantelle Layton
#'
#' @description Creates a time-series plot of annual temperature anomaly in the style required for
#' AZMP reporting.
#'
#' @param x a vector indicating the times of observations
#' @param y a vector indicating the observations
#' @param xlim Optional limit for x axis
#' @param ylim Optional limit for y axis
#' @param xlab Logical indicating whether to label the x axis
#' @param climatologyYears Vector of length two indicating the climatology years
#' @param ylabel Logical indicating whether to label the y axis
#' @param plotSd Logical indicating whether to add +/- 0.5 standard deviation lines on plot of
#' the annual anomaly over the defined climatology period.
#' @param yaxs Logical indicating whether to have a labelled y-axis
#' @param plotPoints Logical indicating whether or not to plot data as points, or as lines with lty = 2.
#'
#' @details The current format of the figure is for a specific user. It is similar in nature to
#' plotAnnualAnomaly, but is behind in development as it is not frequently used.
#'
#' @importFrom stats sd
#' @importFrom graphics axis.POSIXct
#' @importFrom graphics plot
#' @importFrom graphics abline
#' @importFrom graphics axis
#' @importFrom graphics lines
#' @importFrom graphics mtext
#' @importFrom graphics points
#' @importFrom graphics legend
#'
#' @export
plotMonthlyAnomaly <- function(x, y, xlim, ylim, xlab = TRUE, climatologyYears, ylabel = TRUE,
plotSd = TRUE, yaxs = TRUE, plotPoints = TRUE){
is.even <- function(x) x %% 2 == 0
# ylabel
L <- '['
R <- ']'
ylab <- bquote('Temperature Anomaly ' * .(L) * degree * "C" * .(R))
# xlim
# set it if not given
xlimGiven <- !missing(xlim)
if(!xlimGiven){
xlim <- range(as.numeric(names(x)), na.rm = TRUE)
}
# ylim
# set it if not given
ylimGiven <- !missing(ylim)
if(!ylimGiven){
ylim <- range(x, na.rm = TRUE)
}
plot(x = x,
y = y, col = 'white',
lwd = 0.6,
type = 'n',
xlim = as.POSIXct(paste(xlim, c(01, 12), c(01, 31), sep = '/'), tz = 'UTC'),
ylim = ylim,
xaxt = 'n', yaxt = 'n',
xlab = '', ylab = '')
#...)
# x-axis, x-axis labels
xat <- seq(round(xlim[1], digits = -1), round(xlim[2], digits = -1), 10) # tick every decade
centuries <- c(1800, 1900, 2000)
okcentury <- centuries %in% xat
centuryIdx <- unlist(lapply(centuries[okcentury], function(k) which(k == xat)))
# if centuryIdx[1] is even, start xlabel idx at 2, if odd, at 1
xlabels <- seq(ifelse(is.even(centuryIdx[1]), 2, 1), length(xat), 2) # label every second decade, make sure centuries are labelled
axis(side = 1, at = as.POSIXct(paste(xat, '01', '01', sep = '/'), tz = 'UTC'), labels = FALSE)
if(xlab){
axis.POSIXct(side = 1,
at = as.POSIXct(paste(xat[xlabels], '01', '01', sep = '/'), tz = 'UTC'),
labels = TRUE,
format = '%Y')
}
# y-axis, y-axis labels, y-axis label
if(yaxs){
{if(diff(ylim) < 20){ # kind of bad logic
yat <- seq(round(ylim[1], digits = 0), round(ylim[2], digits = 0), 1) # label every one
} else {
yat <- pretty(ylim)
}
}
axis(side = 2, at = yat, labels = yat)
}
if(ylabel) mtext(text = ylab, side = 2, line = 2, cex = 4/5)
# grid
# ugh, function grid() not working when nx and ny given
abline(v = as.POSIXct(paste(xat, '01', '01', sep = '/'), tz = 'UTC'), col = 'lightgray', lty = 'dotted')
if(yaxs) abline(h = yat, col = 'lightgray', lty = 'dotted')
# replot initial lines so its over the grid
if(plotPoints){
lines(x = x, y = y, col = 'black')
points(x = x, y = y, pch = 21, col = 'black', bg = 'white')
} else {
lines(x = x, y = y, col = 'black', lty = 2)
}
# add additional stuff to plot
# climatology standard deviation
if(plotSd){
okclim <- as.numeric(names(x)) >= climatologyYears[1] & as.numeric(names(x)) <= climatologyYears[2]
aasd <- sd(x[okclim], na.rm = TRUE)
{if(diff(ylim) > 20) {
cmean <- mean(x[okclim], na.rm = TRUE)
abline(h = cmean, lty = 1, lwd = 2)
abline(h = (aasd/2) + cmean, lty = 2, lwd = 2)
abline(h = (-aasd/2) + cmean, lty = 2, lwd = 2)
} else {
abline(h = 0)
abline(h = aasd/2, lty = 2, lwd = 2)
abline(h = -aasd/2, lty = 2, lwd = 2)
}
}
}
}
#' @title Plot monthly bar plots
#'
#' @description This plotting method for air temperature data plots bar plots
#' for monthly anomalies and is colour coded based on normalized monthly
#' anomalies
#'
#' @param df a data.frame containing at least year, month, anomaly, and normalizedAnomaly.
#' @param ylim a vector of length 2 indicating the range for the y-axis
#' @param years vector of length two indicating the range of years for climatology
#' @param plotYear a vector indicating which years to plot. Can be a vector of length one, indicating
#' to plot only one year, or of length two, indicating a range of years to plot
#' @param yearLabel logical expression indicating whether or not to label the plotYears
#' @param yearLabelSide which side the yearLabel should be placed, (1 = bottom, 3 = top)
#' @param drawPalette logical expression indicating whether or not to draw a palette
#' @param xaxt logical expression indicating whether or not to label x-axis
#' @param ylabel logical exptression indicating whether or not to label y-axis labels
#' @param mar vector of length 4 indicating the margins of the plot
#'
#' @author Chantelle Layton
#'
#' @importFrom graphics barplot
#' @importFrom graphics box
#' @importFrom graphics par
#' @importFrom grDevices rgb
#' @importFrom oce colormap
#' @importFrom oce drawPalette
#'
#' @export
plotMonthlyBar <- function(df, ylim, years, plotYear, yearLabel = FALSE, yearLabelSide, drawPalette = TRUE, xaxt = TRUE, ylabel = TRUE, mar){
is.even <- function(x) x %% 2 == 0
# ylabel
L <- '['
R <- ']'
ylab <- getAnomalyLabel('temperatureAnomaly')
# The blue-red colormap with ranges -3.5 to +3.5 standard deviations
rgbcol <- c(c(157,0,0),c(230,0,0),c(255,51,51),c(255,102,102),c(255,151,151),c(255,202,202),c(255,255,255),
c(255,255,255),c(202,202,255),c(151,151,255),c(102,102,255),c(51,51,255),c(0,0,230),c(0,0,157))
rgbcol <- matrix(rgbcol, nrow=length(rgbcol)/3, ncol=3, byrow=TRUE)
rgbcol <- rgbcol[seq(nrow(rgbcol),1,-1),]
# Make the RGB colors, but don't make a colorRamp
anomalyCols <- rgb(red=rgbcol[,1], green=rgbcol[,2], blue=rgbcol[,3], maxColorValue = 255)
anomalyBreaks <- seq(-3.5, 3.5, 0.5)
# ylim
# set it if not given
ylimGiven <- !missing(ylim)
if(!ylimGiven){
ylim <- range(df[['anomaly']], na.rm = TRUE)
}
# subset the data based on plotYear
dfs <- df[df[['year']] %in% plotYear, ]
# add any missing months
expectedYearMonth <- do.call('rbind',lapply(plotYear, function(k) data.frame(year = rep(k, 12), month = as.numeric(1:12))))
expectedData <- dfs[nrow(dfs) + 1:nrow(expectedYearMonth), !names(dfs) %in% c('year', 'month')]
expectedDf <- cbind(expectedYearMonth, expectedData)
okaddexpected <- !mapply(function(year,month) month %in% dfs[['month']][dfs[['year']] == year],
expectedDf[['year']],
expectedDf[['month']])
dfu <- rbind(dfs, expectedDf[okaddexpected, ])
# create colour map based on normalized values
cm <- colormap(z = dfu[['normalizedAnomaly']], breaks = anomalyBreaks, col = anomalyCols)
# now plot
if(drawPalette){
drawPalette(colormap = cm, zlab = ' ', cex = 1)
}
marGiven <- !missing(mar)
if(!marGiven){
mar <- c(3.5, 3.5, 1, 1)
}
par(mar=mar)
barplot(dfu[['anomaly']], col = cm$zcol,
ylim = ylim, xlim = c(0, length(dfu[['anomaly']])),
axisnames = FALSE, axes = FALSE,
space = 0, offset = 0, width = 1, # to tighten up bars
xaxs = 'i')
# axes
# x-axis
# label every third month
monthTick <- 1:nrow(dfu)
monthAt <- seq(1, nrow(dfu), 2)
monthLabels <- substring(month.abb[dfu[['month']]], 1, 1)[monthAt]
{if(xaxt){ # if xaxt is not given
axis(1, at = monthTick - 0.5, labels = FALSE) # subtract 0.5 from monthAt to be center of bar
mtext(text = monthLabels, side = 1, line = 0.5, at = monthAt - 0.5, cex = 3/5)
} else {
axis(1, at = monthTick - 0.5, labels = FALSE)
}}
if(yearLabel){
if(length(plotYear) == 1){
mtext(text = plotYear, side = yearLabelSide, line = 1)
} else {
yrs <- plotYear[1]:plotYear[2]
mtext(text = '|', side = yearLabelSide, at = 12 * (seq(1, length(yrs)-1,1)), cex = 3/5, line = 1.5)
mtext(text = yrs, side = yearLabelSide, at = 6 + 12 * seq(0, length(yrs) - 1, 1), cex = 3/5, line = 1.5)
#mtext(text = plotYear[2], side = yearLabelSide, at = 18, cex = 4/5)
}
}
abline(v = monthAt- 0.5, col = 'lightgrey', lty = 2)
if(length(plotYear) == 2) {
yrs <- plotYear[1]:plotYear[2]
abline(v = 12 * (seq(1, length(yrs)-1,1)))
}
#axis(3, at = monthAt - 0.5, labels = FALSE)
# y - axis
# regardless of ylim, label every second value
yat <- seq(ylim[1], ylim[2], 2)
ylabels <- yat
axis(2, at = yat, labels = ylabels)
abline(h = yat, col = 'lightgrey', lty = 2)
if(ylabel){mtext(text = ylab, side = 2, line = 2, cex = 4/5)}
# make it pretty
abline(h = 0)
box()
barplot(dfu[['anomaly']], col = cm$zcol,
ylim = ylim, xlim = c(0, length(dfu[['anomaly']])),
axisnames = FALSE, axes = FALSE,
space = 0, offset = 0, width = 1, # to tighten up bars
add = TRUE)
if(drawPalette) mtext(side = 4, text = getAnomalyLabel('normalizedAnomaly'), line = 4, cex = 4/5)
}
#' @title Plot annual stacked bar plot
#'
#' @description This function will plot a stacked bar plot that has negative and
#' positive values. It also has the option to plot the average of values provided.
#'
#' @param x a vector indicating what the columns represent for \code{z}
#' @param y a vector indicating what the rows represent for \code{z}
#' @param z a matrix with the columns being the x-axis and the rows being items
#' that wish to be stacked.
#' @param zsc a vector of normalized values of z for the scorecard, ignored if `plotScorecard = FALSE`
#' @param plotAverage a logical value indicating whether or not to add the average value
#' from matrix z.
#' @param ylab1 name for the y-axis on side 2, default is \code{NULL}
#' @param ylab2 name for the y-axis on side 4 if \code{plotAverage = TRUE}, ignored otherwise, default is
#' \code{NULL}.
#' @param xlabels Logical indicating if the x-axis ticks should be annotated.
#' @param ylim1 limits for the y-axis on side 2, if not supplied, it will be inferred from \code{z}
#' @param ylim2 limits for the y-axis on side 4 if \code{plotAverage = TRUE}, ignored otherwise. If not
#' supplied, it will be inferred from the data.
#' @param ncol supplied to legend, the number of columns in which to set the legend items, default is 1.
#' @param hclpalette Name of an `hcl.colors` palette. Names can be found by doing `hcl.pals()`, default is
#' a sequential palette, 'Viridis'.
#' @param legendLocation Character string, valid choices are `inside` or `outside`. Indicating if the
#' legend should be place `inside` the plot window (default), or `outside` of the plot window on the right
#' hand side.
#' @param legendInset Vector of two values to control placement of legend, see `?legend` for details, when
#' `legendLocation = 'outside'`.
#' @param plotScorecard Logical indicating whether or not to plot scorecard on side = 1.
#' @param scorecardLines Logical indicating whether or not to put vertical lines on scorecard.
#' @param scorecardLabels Logical indicating whether or not to print `ysc` values in scorecard.
#' @param scorecardSeparation Value used to denote the separation between the main plot and scorecard.
#' Suggested to use `par('cin')[2]` (default) and play with that value. If closer is desired, decrease.
#' @param scorecardWidth Value used to denote the width of the scorecard. Suggested to use
#' `par('cin')[2]` (default) and play with that value. If wider is desired, increase.
#'
#' @author Chantelle Layton
#'
#' @importFrom graphics legend
#'
#' @export
#'
plotStackedBarplot <- function(x, y, z, zsc, plotAverage = TRUE, ylab1 = NULL, ylab2 = NULL,
xaxtlabels = TRUE,
ylim1, ylim2, ncol = 1, hclpalette = 'Viridis', legendLocation = 'inside',
legendInset = c(-0.38, 0),
plotScorecard = FALSE, scorecardLines = TRUE, scorecardLabels = TRUE,
scorecardSeparation = par('cin')[2], scorecardWidth = par('cin')[2]){
mround <- function(x, base) {base * round(x/base)}
is.even <- function(x) x %% 2 == 0
# check to see if ylim1 is given
if(missing(ylim1)){
ylim1 <- range(apply(z, 2, sum, na.rm = TRUE), na.rm = TRUE)
}
# test barplot to get x values for scorecard so they line up
# first do the positive values
bpset <- barplot(z, ylim = ylim1, col = col, xaxt = 'n',
#legend = y, args.legend = list(x = 'topleft', bty = 'n'),
xaxs = 'i',
border = NA,
cex.axis = cexaxis, plot = FALSE)
# x-axis at and labels
# need to do some fudging when close to decade ending
stackedx <- c(x, x[length(x)] + 1)
xlim <- mround(range(stackedx),5)
if(diff(xlim) > 50){
xat <- seq(round(xlim[1], digits = -1), round(xlim[2], digits = -1), 10) # tick every decade
centuries <- c(1800, 1900, 2000)
okcentury <- centuries %in% xat
centuryIdx <- unlist(lapply(centuries[okcentury], function(k) which(k == xat)))
# if centuryIdx[1] is even, start xlabel idx at 2, if odd, at 1
xlabels <- seq(ifelse(is.even(centuryIdx[1]), 2, 1), length(xat), 2) # label every second decade, make sure centuries are labelled
okIdxLab <- unlist(lapply(xat[xlabels], function(k) which(k == stackedx)))
okIdxAt <- unlist(lapply(xat, function(k) which(k == stackedx)))
} else {
xat <- pretty(xlim)
okIdxAt <- okIdxLab <- unlist(lapply(xat, function(k) which(k == stackedx)))
}
if(plotScorecard){
ysc <- zsc
data("anomalyColors")
# need to extend the bottom half, just keep adding the dark blue
addBreaks <- seq(-5.5, -4.0, 0.5)
anomalyColors[['breaks']] <- c(addBreaks, anomalyColors[['breaks']])
anomalyColors[['colors']] <- c(rep(anomalyColors[['colors']][1], length(addBreaks)), anomalyColors[['colors']])
xlim <- range(bpset) + diff(bpset)[1]/2 * c(-1, 1)
# plot bottom scorecard first, some code taken from drawPalette()
# set up margins
omai <- par("mai")
mai <- rep(0, 4)
# arguments for paletteCalculations
# scorecardSeparation
# set it if not given
separationGiven <- !missing(scorecardSeparation)
if(!separationGiven){
scorecardSeparation <- par('cin')[2]
}
widthGiven <- !missing(scorecardWidth)
if(!separationGiven){
scorecardWidth <- par('cin')[2]
}
pos <- 1
debug <- 3
zlab <- ""
pc <- paletteCalculations(separation = scorecardSeparation, width = scorecardWidth,
maidiff=mai, pos=pos,
zlab=zlab, debug=debug-1)
# plot
zm <- matrix(data = ysc, nrow = length(x), ncol = 1)
zy <- 1
# plot it
barxlim <- xlim #+ c(-1, 1)
par(mai = ifelse(pc$mai1 > 0, pc$mai1, 0))
image(x = bpset, y = zy, z = zm,
xlim = barxlim,
axes = FALSE, xlab="", ylab="",
col = anomalyColors[['colors']],
breaks = anomalyColors[['breaks']])
rect(par("usr")[1],par("usr")[3],par("usr")[2],par("usr")[4],col = "lightgray")
image(x = bpset, y = zy, z = zm,
xlim = barxlim,
axes = FALSE, xlab="", ylab="",
col = anomalyColors[['colors']],
breaks = anomalyColors[['breaks']],
add = TRUE)
box()
## add vertical lines to separate years
bpsetdiff <- diff(bpset)[1]
if(scorecardLines) {lapply(bpset, function(k) lines(x = rep(k, 2) + bpsetdiff/2, y = c(0, 1) + 0.5))}
# axis and labels
## annual
if(scorecardLabels) {
textcol <- rep('black', length(ysc))
whitetext <- ysc <= -3.0 | (ysc >= 3.0 & ysc < 3.5)
whitetext[is.na(whitetext)] <- FALSE
annualtextat <- bpset
if(any(!whitetext)) text(x = annualtextat[!whitetext == TRUE & !is.na(ysc)], y = 1, labels = sprintf('%.1f', ysc[!whitetext == TRUE & !is.na(ysc)]), col = 'black', cex = 0.8, srt = 90)
if(any(whitetext)) text(x = annualtextat[whitetext == TRUE], y = 1, labels = sprintf('%.1f', ysc[whitetext == TRUE & !is.na(ysc)]), col = 'white', cex = 0.8, srt = 90)
}
# x-axis, x-axis labels
axis(side = 1, at = bpset[okIdxAt], labels = FALSE)
if(xaxtlabels) axis(side = 1, at = bpset[okIdxLab], labels = stackedx[okIdxLab])
# reset mai, prep for primary plot
par(new=TRUE, mai=pc$mai2)
par(mar = par('mar') * c(0, 1, 1, 1) + c(4.5, 0, 0, 0)) # have to change first term of second addition if changes made to colorbar height
}
# get colors
col <- hcl.colors(n = dim(z)[1], palette = hclpalette)
# have to split up the matrix into negative and positive
zPos <- z
zPos[zPos < 0] <- 0
zPos[is.na(zPos)] <- 0
zNeg <- z
zNeg[zNeg > 0] <- 0
zNeg[is.na(zNeg)] <- 0
cexaxis <- 0.8
bppos <- barplot(zPos, ylim = ylim1, col = col, xaxt = 'n',
#legend = y, args.legend = list(x = 'topleft', bty = 'n'),
xaxs = 'i',
border = NA,
cex.axis = cexaxis)
# need to set up the nice xaxis labels using some information from the bar plot
# this will be used again below when actually labelling the x-axis, but some information
# is needed to do dotted guidelines
bp <- c(bppos, bppos[length(bppos)] + mean(diff(bppos)))
# horizontal and vertical guidelines
hline <- pretty(ylim1)
# positive will include zero
abline(h = hline[hline >= 0], lty = 'dotted', col = 'lightgrey')
abline(v = bp[okIdxAt], lty = 'dotted', col = 'lightgrey')
# negative values
bpneg <- barplot(zNeg, ylim = ylim1, col = col, xaxt = 'n',
border = NA, cex.axis = cexaxis, add = TRUE)
abline(h = hline[hline < 0], lty = 'dotted', col = 'lightgrey')
abline(v = bp[okIdxAt], lty = 'dotted', col = 'lightgrey')
# add neg bar plot again to get things on top of guidelines
bpneg <- barplot(zNeg, ylim = ylim1, col = col, xaxt = 'n',
border = NA, add = TRUE, cex.axis = cexaxis)
# add the bar plot back on top to get things on top of the guidelines
if(legendLocation == 'inside'){
legendArgs <- list(x = 'topleft', bty = 'n', ncol = ncol)
legend <- y
} else {
legendArgs <- NULL
legend <- NULL
}
barplot(zPos, ylim = ylim1, col = col, xaxt = 'n',
legend = legend, args.legend = legendArgs,
border = NA, add = TRUE,
cex.axis = cexaxis)
box()
if(!plotScorecard){
axis(side = 1, at = bpset[okIdxAt], labels = FALSE)
if(xaxtlabels) {axis(side = 1, at = bpset[okIdxLab], labels = stackedx[okIdxLab])}
}
# add legend if legendLocation == 'outside'
if(legendLocation == 'outside'){
par(xpd=TRUE)
legend("topright", inset = legendInset, legend = y, col = col, pch = 15, box.col = 'white')
par(xpd=FALSE)
}
if(plotAverage){
par(new = TRUE)
mtanom <- apply(z, 2, mean, na.rm = TRUE)
# check if ylim2 given
if(missing(ylim2)){
ylim2 <- range(mtanom, na.rm = TRUE)
}
usr <- par('usr')
xr <- (usr[2] - usr[1]) / 27
xlim <- c(usr[1] + xr, usr[2] - xr)
plot(bp[1:(length(bp)-1)], as.vector(mtanom), type = 'l',
ylim = ylim2 , xlim = xlim, lwd = 1,
axes = FALSE, bty = 'n', xlab = '', ylab = '')
axis(side = 4, cex.axis = cexaxis)
legend('topright', lty = 1, col = 'black',
bty = 'n',
legend = gettext('average', domain = 'R-csasAtlPhys'))
box()
}
if(!is.null(ylab1)) {mtext(side = 2, text = ylab1, line = 2)}
if(plotAverage & !is.null(ylab2)) mtext(side = 4, text = ylab2, line = 2)
}
#' @title Plot station locations
#'
#' @description Plots station locations at the top of plots using the points function
#'
#' @param distance a numerical vector indicating the distance
#' @param plabel a numerical vector indication the placement of the labels
#' @param distanceOffset a numerical value indicating the value to add and subtract from distace that will plot a line, default value is NULL
#' @param cex a numerical value indicating the magnification
#' @param pch a numerical value indicating the symbol
#' @param col a character string indicating the color
#'
#' @author Chantelle Layton
#'
#' @importFrom graphics par
#' @importFrom graphics points
#' @export
plotStationLocations <- function(distance, plabel, distanceOffset = NULL, cex = 9/10, pch = 25, col = 'black'){
par(xpd = NA)
points(distance, rep(plabel, length(distance)), pch = pch, bg = col, col = col, cex = cex)
if(!is.null(distanceOffset)){
lines(distance + c(-distanceOffset, distanceOffset), rep(plabel, 2), lty = 1, col = col, cex = cex)
}
par(xpd = FALSE)
}
#' @title Plot monthly timeseries with anomaly bar
#'
#' @description Creates a time series plot with the monthly anomaly and annual
#' anomaly scorecard below.
#'
#' @details This is the plot style that is used in many of Peter Galbraith's
#' research documents. Was translated to R in efforts to better represent
#' some data.
#'
#' @param xYear a numeric vector of the associated year
#' @param xMonth a numeric vector of the associated month
#' @param y a numeric vector of the associated year month value
#' @param yAnomaly a numeric vector of the associated anomaly year month value
#' @param yNormalizedAnomaly a numeric vector of the associated normalized anomaly with xYear and xMonth
#' @param xAnnualAnomaly a numeric vector of the year for the annual anomaly
#' @param yAnnualAnomaly a numeric vector of the annual anomaly
#' @param plotAnnual a logical value indicating if the annual anomaly should be shown in the scorecard bar, default is `TRUE`
#' @param xClimatology a numeric vector of the months for the monthly climatology
#' @param yClimatology a numeric vector of the climatology values for associated month
#' @param sdClimatology a numeric vector of the standard deviation for the associated month
#' @param xlim the x limits (x1, x2) of the plot
#' @param ylim the y limits (y1, y2) of the plot
#' @param anomalyColors a list that contains the colors and breaks of the desired color bar for the anomaly scorecard
#' @param scorecardSeparation Value used to denote the separation between the main plot and scorecard.
#' Suggested to use `par('cin')[2]` as a starting point and play with that value. If closer is desired, decrease.
#' @param scorecardWidth Value used to denote the width of the scorecard. Suggested to use
#' `par('cin')[2]` as a starting point and play with that value. If wider is desired, increase.
#'
#' @author Chantelle Layton
#'
#' @importFrom graphics image
#' @importFrom graphics polygon
#' @importFrom graphics text
#' @importFrom graphics rect
#'
#' @export
plotMonthlyTimeseriesWAnomalyBar <- function(xYear, xMonth, y, yAnomaly, yNormalizedAnomaly,
xAnnualAnomaly, yAnnualAnomaly, plotAnnual = TRUE,
xClimatology, yClimatology, sdClimatology,
xlim, ylim, anomalyColors,
scorecardSeparation=par('cin')[2]/2 + 0.1 - 0.05 - 0.0125,
scorecardWidth=par('cin')[2] + 0.2 - 0.05 - 0.0125){
# 1. set arguments if missing
if(missing(xlim)){
xlim <- range(xMonth)
}
if(missing(ylim)){
ylim <- range(y)
}
# 2. construct climatology polygon
uyear <- unique(xYear)
uyear <- c(uyear, max(uyear) + 1) # add the next year for boundary
x1 <- as.POSIXct(paste(unlist(lapply(uyear, rep, times = 12)) , 1:12, '15', sep = '-'), tz = 'UTC')
x2 <- as.POSIXct(paste(unlist(lapply(rev(uyear), rep, times = 12)), 12:1, '15', sep = '-'), tz = 'UTC')
xpoly <- c(x1, x2)
y1 <- rep(yClimatology - (sdClimatology/2), times = length(uyear))
y2 <- rep(rev(yClimatology + (sdClimatology/2)), times = length(uyear))
ypoly <- c(y1, y2)
# for debugging polygon
# ok <- (as.POSIXlt(xpoly)$year + 1900) %in% c(max(uyear) - 2, max(uyear) - 1)
# xpolyb <- xpoly[ok]
# ypolyb <- ypoly[ok]
# plot bottom scorecard first, some code taken from drawPalette()
# set up margins
omai <- par("mai")
mai <- rep(0, 4)
# arguments for paletteCalculations
pos <- 1
debug <- 3
zlab <- ""
pc <- paletteCalculations(separation = scorecardSeparation,
width = scorecardWidth,
maidiff=mai, pos=pos, zlab=zlab, debug=debug-1)
# plot
time <- as.POSIXct(paste(xYear, xMonth, '15', sep = '-'), tz = 'UTC')
palette <- time # this is x
# don't think I need colormap calls b/c image does it.
#cm <- colormap(z = yAnomaly, breaks = anomalyColors[['breaks']], col = anomalyColors[['colors']], missingColor = 'lightgray')
#col <- cm$zcol
uxYear <- unique(xYear)
zannual <- NULL
for(iy in 1:length(uxYear)){
lookyear <- uxYear[iy]
ok <- xYear == lookyear
nmon <- length(xMonth[ok])
okannual <- xAnnualAnomaly == lookyear
aa <- yAnnualAnomaly[okannual]
if(any(okannual)){
annualadd <- rep(yAnnualAnomaly[okannual], nmon)
} else {
annualadd <- rep(NA, nmon)
}
zannual <- c(zannual, annualadd)
}
#zannual <- unlist(lapply(yAnnualAnomaly, rep, 12))
if(plotAnnual){
z <- matrix(nrow = length(time), ncol = 2)
z[, 2] <- yAnomaly
#z[, 1] <- zannual[1:length(time)] # watch this
z[, 1] <- zannual
zy <- c(1,2)
} else { # only monthly
z <- matrix(nrow = length(time), ncol = 1)
z[,1] <- yAnomaly
zy <- 1
}
#col[is.na(col)] <- 'lightgray'
# plot it
par(mai = ifelse(pc$mai1 > 0, pc$mai1, 0))
image(x = palette, y = zy, z = z,
xlim = xlim,
axes = FALSE, xlab="", ylab="",
col = anomalyColors[['colors']],
breaks = anomalyColors[['breaks']])
rect(par("usr")[1],par("usr")[3],par("usr")[2],par("usr")[4],col = "lightgray")
image(x = palette, y = zy, z = z,
xlim = xlim,
axes = FALSE, xlab="", ylab="",
col = anomalyColors[['colors']],
breaks = anomalyColors[['breaks']],
add = TRUE)
box()
# axis and labels
at <- seq(xlim[1], xlim[2], by = 'month')
#abline(v = at)
lapply(at, function(k) lines(x = rep(k, 2), y = c(ifelse(plotAnnual, 1, 0), ifelse(plotAnnual, 2, 1)) + 0.5)) # vertical lines for monthly
abline(h = 1.5) # separate monthly and annual
# month axis labels
lapply(at[as.POSIXlt(at)$mon + 1 == 1], function(k) lines(x = rep(k, 2), y = c(0, 1) + 0.5))
label <- rep(substring(month.abb, 1, 1), 2)
xlimyear <- as.POSIXlt(xlim)$year + 1900
labelat <- unlist(lapply(xlimyear, function(k) as.POSIXct(paste(k, 1:12, '16', sep = '-'), tz = 'UTC')))
axis(side=1, at= at, labels= FALSE, mgp=c(2.5, 0.7, 0))
axis(side = 1, at = labelat, labels = label, mgp=c(2.5, 0.7, 0), tick = FALSE, line = -0.7)
# year axis labels
bigtickat <- unlist(lapply(xlimyear[2:length(xlimyear)], function(k) as.POSIXct(paste(k, '01', '01', sep = '-'), tz = 'UTC')))
axis(side = 1, at = bigtickat, labels = FALSE, mgp=c(2.5, 0.7, 0), tck = -0.6)
yearlabelat <- as.POSIXct(paste(xlimyear, '07', '02', sep = '-'), tz = 'UTC')
axis(side = 1, labels = xlimyear, at = yearlabelat, mgp = c(2.5, 0.7, 0), tck = FALSE)
# put numbers in boxes
## monthly
textcol <- rep('black', length(yAnomaly))
whitetext <- yAnomaly <= -3.0 | (yAnomaly >= 3.0 & yAnomaly < 3.5)
whitetext[is.na(whitetext)] <- FALSE
if(any(!whitetext)) text(x = palette[!whitetext == TRUE & !is.na(yAnomaly)], y = ifelse(plotAnnual, 2, 1), labels = sprintf('%.1f', yAnomaly[!whitetext == TRUE & !is.na(yAnomaly)]), col = 'black', srt = 90, cex = 0.8)
if(any(whitetext)) text(x = palette[whitetext == TRUE & !is.na(yAnomaly)], y = ifelse(plotAnnual, 2, 1), labels = sprintf('%.1f', yAnomaly[whitetext == TRUE & !is.na(yAnomaly)]), col = 'white', srt = 90, cex = 0.8)
## annual
if(plotAnnual){
textcol <- rep('black', length(yAnnualAnomaly))
whitetext <- yAnnualAnomaly <= -3.0 | (yAnnualAnomaly >= 3.0 & yAnnualAnomaly < 3.5)
whitetext[is.na(whitetext)] <- FALSE
annualtextat <- as.POSIXct(paste(xAnnualAnomaly, '07', '02', sep = '-'), tz = 'UTC')
if(any(!whitetext)) text(x = annualtextat[!whitetext == TRUE & !is.na(yAnnualAnomaly)], y = 1, labels = sprintf('%.1f', yAnnualAnomaly[!whitetext == TRUE & !is.na(yAnnualAnomaly)]), col = 'black', cex = 0.8)
if(any(whitetext)) text(x = annualtextat[whitetext == TRUE], y = 1, labels = sprintf('%.1f', yAnnualAnomaly[whitetext == TRUE & !is.na(yAnnualAnomaly)]), col = 'white', cex = 0.8)
}
# reset mai, prep for primary plot
par(new=TRUE, mai=pc$mai2)
# monthly plot with climatology
par(mar = par('mar') * c(0, 1, 1, 1) + c(5.5, 0, 0, 0)) # have to change first term of second addition if changes made to colorbar height
#time <- as.POSIXct(paste(d[['data']][['year']], d[['data']][['month']], '15', sep = '-'), tz = 'UTC')
plot(time, y,
xlim = xlim, ylim = ylim,
xaxs = 'i',
xaxt = 'n', yaxt = 'n',
xlab = '', ylab = '',
type = 'l')
abline(v = at[seq(1, length(at), 2)], lty = 2, col = 'lightgrey')
axis(2)
abline(h = pretty(ylim), lty = 2, col = 'lightgrey')
polygon(x = xpoly, y = ypoly,
density = NA,
col = 'lightblue')
lines(time, y)
box()
# for debugging polygon
# polygon(x = xpolyb, y = ypolyb,
# density = NA,
# col = 'lightblue')
# points(x = xpolyb,
# y = ypolyb)
# text(x = xpolyb,
# y = ypolyb,
# labels = 1:length(xpolyb))
}
#' @title palette calculations
#' @param separation a numeric value
#' @param width a numeric value
#' @param pos a numeric value indicating the side
#' @param zlab a character
#' @param maidiff a numeric value
#' @param debug a numeric value
#' @importFrom graphics frame
#' @importFrom oce oceDebug
paletteCalculations <- function(separation=par('cin')[2]/2 + 0.1 - 0.05 - 0.0125, # changed this, orig when just 1 it was 0.1/2
width=par('cin')[2] + 0.2 - 0.05 - 0.0125, # changed this, orig when just 1 it was 0.1
pos=4,
zlab, maidiff=c(0, 0, 0, 0),
debug=getOption("oceDebug"))
{
# NOTE from CL : many of the comments below are from imagep.R from the oce package, so disregard if trying to debug this
# code, this function is for use in plotMonthlyTimeseriesWAnomalyBar
## This returns a list with the following entries:
## mai0 = before this call
## mai1 = just before plotting palette (i.e. lots of white space on one side)
## mai1f = set before plotting fullpage palette
## mai2 = ready for post-palette drawing (i.e. good for a diagram beside palette)
if (!(pos %in% 1:4))
stop("'pos' must be 1, 2, 3 or 4")
oceDebug(debug, "paletteCalculations(separation=", separation,
", width=", width, ", pos=", pos,
", zlab=", if (missing(zlab)) "(missing)" else zlab,
", maidiff=c(", paste(maidiff, collapse=","), ")",
", debug=", debug, ") {\n", sep="", style="bold", unindent=1)
haveZlab <- !missing(zlab) && !is.null(zlab) && sum(nchar(zlab)) > 0
## 2014-04-02 {
## Below, we will be using e.g. par('mai') to find margins. If the user
## is employing layout(), the call will not give the right answer until the plot
## has been established or initialized (not sure on right term). So, we use
## a trick: call frame() to establish/initialize the plot, then call
## plot(new=TRUE) to prevent advancing to the next panel of the layout.
## A secondary trick is also required: we set to zero margins before
## calling frame(), because otherwise there can be a "figure margins
## too large" error from frame(), if the layout is tight.
omar <- par('mar')
par(mar=rep(0, 4))
frame()
par(mar=omar)
par(new=TRUE)
## OK, done with the trick now. PS: the long comments given here
## are a result of persistent problems with large-margin errors,
## and I don't want this new approach to get lost in code.
## } 2014-04-02
lineHeight <- par("cin")[2] # character height in inches
oceDebug(debug, "lineHeight:", lineHeight, "from cin\n")
oceDebug(debug, "par('csi'):", par('csi'), "\n")
tickSpace <- abs(par("tcl")) * lineHeight # inches (not sure on this)
textSpace <- 1.25 * (lineHeight + if (haveZlab) lineHeight else 0)
figureWidth <- par("fin")[1]
figureHeight <- par("fin")[2]
oceDebug(debug, "figureWidth:", format(figureWidth, digits=2), "in\n")
oceDebug(debug, "figureHeight:", format(figureHeight, digits=2), "in\n")
oceDebug(debug, "tickSpace:", tickSpace, "in\n")
oceDebug(debug, "textSpace:", textSpace, "in\n")
pc <- list(mai0=par('mai'))
pc$mai1 <- pc$mai0
pc$mai1f <- pc$mai0
pc$mai2 <- pc$mai0
##P <- separation + width
P <- width
A <- tickSpace + textSpace
if (pos == 1) {
## alter top and bottom margins
pc$mai1[1] <- A
pc$mai1[3] <- figureHeight - P - A
pc$mai1f[2] <- 0
pc$mai1f[4] <- A
pc$mai2[1] <- P + A + pc$mai0[1]
pc$mai2[3] <- pc$mai0[3]
} else if (pos == 2) {
## alter left and right margins
pc$mai1[2] <- A
pc$mai1[4] <- figureWidth - P - A
pc$mai1f[4] <- 0
pc$mai1f[2] <- A
pc$mai2[2] <- P + A + pc$mai0[2]
pc$mai2[4] <- pc$mai0[4]
} else if (pos == 3) {
## alter top and bottom margins
pc$mai1[1] <- figureHeight - P - A
pc$mai1[3] <- A
pc$mai1f[1] <- 0
pc$mai1f[3] <- A
pc$mai2[1] <- pc$mai0[1]
pc$mai2[3] <- P + A + pc$mai0[3]
} else if (pos == 4) {
## DEVELOPER: work here first since it's the common case
## alter left and right margins
pc$mai1[2] <- figureWidth - P - A
pc$mai1[4] <- A
pc$mai1f[2] <- 0
pc$mai1f[4] <- A
pc$mai2[2] <- pc$mai0[2]
pc$mai2[4] <- P + A + pc$mai0[4]
} else {
stop("pos must be in 1:4") # never reached
}
## Adjust palette margins (mai1); FIXME: should this also alter mai2?
pc$mai1 <- pc$mai1 + maidiff
pc$mai1f <- pc$mai1f + maidiff
oceDebug(debug, "pc$mail1: ", paste(round(pc$mai1, 2), sep=" "), "\n")
oceDebug(debug, "pc$mailf: ", paste(round(pc$mai1f, 2), sep=" "), "\n")
oceDebug(debug, "} # paletteCalculations\n", style="bold", sep="", unindent=1)
pc
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.