Nothing
### ============================================================================
### ============================================================================
### S3 methods
### karline+Thomas: from version 1.9, also possible to plot multiple
### outputs and to add observations.
### ============================================================================
### ============================================================================
### ============================================================================
### first some common functions
### ============================================================================
## =============================================================================
## Update range, taking into account neg values for log transformed values
## =============================================================================
Range <- function(Range, x, log) {
if ((log) & (!is.null(x)))
x[x <= 0] <- min(x[x > 0]) # remove zeros
return(range(Range, x, na.rm = TRUE) )
}
## =============================================================================
## Checking and expanding arguments in dots (...) with default
## =============================================================================
expanddots <- function (dots, default, n) {
dots <- if (is.null(dots)) default else dots
rep(dots, length.out = n)
}
# lists: e.g. xlim and ylim....
expanddotslist <- function (dots, n) {
if (is.null(dots)) return(dots)
dd <- if (!is.list(dots )) list(dots) else dots
rep(dd, length.out = n)
}
## =============================================================================
## Expanding arguments in dots (...)
## =============================================================================
repdots <- function(dots, n)
if (is.function(dots)) dots else rep(dots, length.out = n)
setdots <- function(dots, n) lapply(dots, repdots, n)
## =============================================================================
## Extracting element 'index' from dots (...)
## =============================================================================
extractdots <- function(dots, index) {
ret <- lapply(dots, "[", index)
ret <- lapply(ret, unlist) # flatten list
return(ret)
}
## =============================================================================
## Merge two observed data files; assumed that first column = 'x' and ignored
## =============================================================================
# from 3-columned format (what, where, value) to wide format...
convert2wide <- function(Data) {
cnames <- as.character(unique(Data[,1]))
MAT <- Data[Data[,1] == cnames[1], 2:3]
colnames.MAT <- c("x", cnames[1])
for ( ivar in cnames[-1]) {
sel <- Data[Data[,1] == ivar, 2:3]
nt <- cbind(sel[,1],
matrix(nrow = nrow(sel), ncol = ncol(MAT)-1, data = NA),
sel[,2])
MAT <- cbind(MAT, NA)
colnames(nt) <- colnames(MAT)
MAT <- rbind(MAT, nt)
colnames.MAT <- c(colnames.MAT, ivar)
}
colnames(MAT) <- colnames.MAT
return(MAT)
}
# merge two observed data sets in one
mergeObs <- function(obs, Newobs) {
if (! inherits(Newobs, c("data.frame", "matrix")))
stop ("the elements in 'obs' should be either a 'data.frame' or a 'matrix'")
if (is.character(Newobs[, 1]) | is.factor(Newobs[, 1]))
Newobs <- convert2wide(Newobs)
obsname <- colnames(obs)
## check if some observed variables in NewObs are already in obs
newname <- colnames(Newobs)[-1] # 1st column = x-var and ignored
ii <- which (newname %in% obsname)
if (length(ii) > 0)
obsname <- c(obsname, newname[-ii] )
else
obsname <- c(obsname, newname)
## padding with NA of the two datasets
O1 <- matrix(nrow = nrow(Newobs), ncol = ncol(obs), data = NA)
O1[ ,1] <- Newobs[, 1]
for (j in ii) { # observed data in common are put in correct position
jj <- which (obsname == newname[j])
O1[,jj] <- Newobs[, j+1]
}
O1 <- cbind(O1, Newobs[, -c(1, ii+1)] )
colnames(O1) <- obsname
nnewcol <- ncol(Newobs)-1 - length (ii) # number of new columns
if (nnewcol > 0) {
O2 <- matrix(nrow = nrow(obs), ncol = nnewcol, data = NA)
O2 <- cbind(obs, O2)
colnames(O2) <- obsname
} else O2 <- obs
obs <- rbind(O2, O1)
return(obs)
}
## =============================================================================
## Set the mfrow parameters and whether to "ask" for opening a new device
## =============================================================================
setplotpar <- function(ldots, nv, ask) {
nmdots <- names(ldots)
# nv = number of variables to plot
if (!any(match(nmdots, c("mfrow", "mfcol"), nomatch = 0))) {
nc <- min(ceiling(sqrt(nv)), 3)
nr <- min(ceiling(nv/nc), 3)
mfrow <- c(nr, nc)
} else if ("mfcol" %in% nmdots)
mfrow <- rev(ldots$mfcol)
else mfrow <- ldots$mfrow
if (! is.null(mfrow)) mf <- par(mfrow = mfrow)
## interactively wait if there are remaining figures
if (is.null(ask))
ask <- prod(par("mfrow")) < nv && dev.interactive()
return(ask)
}
## =============================================================================
## find a variable
## =============================================================================
selectvar <- function (Which, var, NAallowed = FALSE) {
if (!is.numeric(Which)) {
ln <- length(Which)
## the loop is necessary so as to keep ordering...
Select <- NULL
for ( i in 1:ln) {
ss <- which(Which[i] == var)
if (length(ss) ==0 & ! NAallowed)
stop("variable ", Which[i], " not in variable names")
else if (length(ss) == 0)
Select <- c(Select, NA)
else
Select <- c(Select, ss)
}
} else {
Select <- Which + 1 # "Select" now refers to the column number
if (max(Select) > length(var))
stop("index in 'which' too large: ", max(Select)-1)
if (min(Select) < 1)
stop("index in 'which' should be > 0")
}
return(Select)
}
### ============================================================================
### print a deSolve object
### ============================================================================
print.deSolve <- function(x, ...)
print(as.data.frame(x), ...)
### ============================================================================
### Create a histogram for a list of variables
### ============================================================================
hist.deSolve <- function (x, select = 1:(ncol(x)-1), which = select, ask = NULL,
subset = NULL, ...) {
t <- 1 # column with independent variable ("times")
varnames <- colnames(x)
Which <- selectvar(which, varnames)
np <- length(Which)
ldots <- list(...)
## Set par mfrow and ask
ask <- setplotpar(ldots, np, ask)
if (ask) {
oask <- devAskNewPage(TRUE)
on.exit(devAskNewPage(oask))
}
## expand all dots to np values (no defaults)
Dotmain <- setdots(ldots, np)
## different from default settings
Dotmain$main <- expanddots (ldots$main, varnames[Which], np)
Dotmain$xlab <- expanddots (ldots$xlab, varnames[t], np)
# Dotmain$xlab <- expanddots (ldots$xlab, "" , np)
## xlim and ylim are special: they are vectors or lists
xxlim <- expanddotslist(ldots$xlim, np)
yylim <- expanddotslist(ldots$ylim, np)
if (!missing(subset)){
e <- substitute(subset)
r <- eval(e, as.data.frame(x), parent.frame())
if (is.numeric(r)) {
isub <- r
} else {
if (!is.logical(r))
stop("'subset' must evaluate to logical or be a vector with integers")
isub <- r & !is.na(r)
}
} else isub <- TRUE
## plotting
for (ip in 1:np) {
ix <- Which[ip]
dotmain <- extractdots(Dotmain, ip)
if (! is.null(xxlim[[ip]])) dotmain$xlim <- xxlim[[ip]]
if (! is.null(yylim[[ip]])) dotmain$ylim <- yylim[[ip]]
do.call("hist", c(alist(x[isub, ix]), dotmain))
}
}
### ============================================================================
### Image, filled.contour and persp plots
### ============================================================================
image.deSolve <- function (x, select = NULL, which = select, ask = NULL,
add.contour = FALSE, grid = NULL, method = "image",
legend = FALSE, subset = NULL, ...) {
if (!missing(subset)){
e <- substitute(subset)
r <- eval(e, as.data.frame(x), parent.frame())
if (is.numeric(r)) {
isub <- r
} else {
if (!is.logical(r))
stop("'subset' must evaluate to logical or be a vector with integers")
isub <- r & !is.na(r)
}
} else isub <- TRUE
dimens <- attributes(x)$dimens
if (is.null(dimens))
stop("cannot make an image from deSolve output which is 0-dimensional")
else if (length(dimens) ==1) # 1-D
plot.ode1D(x, which, ask, add.contour, grid, method=method,
legend = legend, isub = isub, ...)
else if (length(dimens) ==2) # 2-D
plot.ode2D(x, which, ask, add.contour, grid, method=method,
legend = legend, isub = isub, ...)
else
stop("cannot make an image from deSolve output with more than 2 dimensions")
}
### ============================================================================
### Plot utilities for the S3 plot method, 0-D, 1-D, 2-D
### ============================================================================
## ============================================================================
## Observations cleanup
## ============================================================================
SetData <- function(obs) { ## check observed data
nobs <- 0
obs.pos <- NULL
obsname <- NULL
if (! is.null(obs)) {
if (!is.data.frame(obs) & is.list(obs)) { # a list with different data sets
Obs <- obs
obs <- Obs[[1]]
obs.pos <- matrix(nrow = 1, c(1, nrow(obs)))
if (! inherits(obs, c("data.frame", "matrix")))
stop ("'obs' should be either a 'data.frame' or a 'matrix'")
if (length(Obs) > 1)
for ( i in 2 : length(Obs)) {
obs <- mergeObs(obs, Obs[[i]])
obs.pos <- rbind(obs.pos, c(obs.pos[nrow(obs.pos), 2] +1, nrow(obs)))
}
obsname <- colnames(obs)
} else { # a data.frame or matrix
if (is.character(obs[, 1]) | is.factor(obs[, 1])) # long format - convert
obs <- convert2wide(obs)
obsname <- colnames(obs)
if (! inherits(obs, c("data.frame", "matrix")))
stop ("'obs' should be either a 'data.frame' or a 'matrix'")
obs.pos <- matrix(nrow = 1, c(1, nrow(obs)))
}
DD <- duplicated(obsname)
if (sum(DD) > 0)
obs <- mergeObs(obs[,!DD], cbind(obs[, 1], obs[, DD]))
nobs <- nrow(obs.pos)
}
return(list(dat = obs, pos = obs.pos, name = obsname, length = nobs))
}
## ============================================================================
## create several lists: x2: other deSolve objects,
## dotmain, dotpoints: remaining (plotting) parameters
## ============================================================================
splitdots <- function(ldots, varnames){
x2 <- list()
dots <- list()
nd <- 0
nother <- 0
ndots <- names(ldots)
if (length(ldots) > 0)
for ( i in 1:length(ldots))
if (inherits(ldots[[i]], "deSolve")) { # a deSolve object
x2[[nother <- nother + 1]] <- ldots[[i]]
names(x2)[nother] <- ndots[i]
# a list of deSolve objects
} else if (is.list(ldots[[i]]) & inherits(ldots[[i]][[1]], "deSolve")) {
for (j in 1:length(ldots[[i]])) {
x2[[nother <- nother+1]] <- ldots[[i]][[j]]
names(x2)[nother] <- names(ldots[[i]])[[j]]
}
} else if (! is.null(ldots[[i]])) { # a graphical parameter
dots[[nd <- nd+1]] <- ldots[[i]]
names(dots)[nd] <- ndots[i]
}
nmdots <- names(dots)
# check compatibility of all deSolve objects
if (nother > 0) {
for ( i in 1:nother) {
if (min(colnames(x2[[i]]) == varnames) == 0)
stop("'x' is not compatible with other deSolve objects - colnames not the same")
}
}
# plotting parameters : split in plot parameters and point parameters
plotnames <- c("xlab", "ylab", "xlim", "ylim", "main", "sub", "log", "asp",
"ann", "axes", "frame.plot", "panel.first", "panel.last",
"cex.lab", "cex.axis", "cex.main")
# plot.default parameters
ii <- names(dots) %in% plotnames
dotmain <- dots[ii]
# point parameters
ip <- !names(dots) %in% plotnames
dotpoints <- dots[ip]
list(points = dotpoints, main = dotmain, nother = nother, x2 = x2)
}
## =============================================================================
## Which variable in common between observed and selected variables
## =============================================================================
WhichVarObs <- function(Which, obs, nvar, varnames, remove1st = TRUE) {
if (is.null(Which) & is.null(obs$dat)) # All variables plotted
Which <- 1 : nvar
else if (is.null(Which)) { # All common variables in x and obs plotted
Which <- which(varnames %in% obs$name)
if (remove1st) Which <- Which[Which != 1] # remove first element (x-value)
Which <- varnames[Which] # names rather than numbers
}
return(Which)
}
## =============================================================================
## Update Obs with position of observed variable in x
## =============================================================================
updateObs <- function (obs, varnames, xWhich) {
if (obs$length > 0 ) {
obs$Which <- selectvar(varnames[xWhich], obs$name, NAallowed = TRUE)
obs$Which [ obs$Which > ncol(obs$dat)] <- NA
# if (nrow(obs$pos) != length(obs$Which))
# obs$pos <- matrix(nrow = length(obs$Which), ncol = ncol(obs$pos),
# byrow = TRUE, data =obs$pos[1,])
} else
obs$Which <- rep(NA, length(xWhich))
return(obs)
}
updateObs2 <- function (obs, varnames, xWhich) {
if (obs$length > 0 ) {
obs$Which <- selectvar(varnames[xWhich], obs$name, NAallowed = TRUE)
obs$Which [ obs$Which > ncol(obs$dat)] <- NA
if (nrow(obs$pos) != length(obs$Which))
obs$pos <- matrix(nrow = length(obs$Which), ncol = ncol(obs$pos),
byrow = TRUE, data =obs$pos[1,])
} else
obs$Which <- rep(NA, length(xWhich))
return(obs)
}
## =============================================================================
## Set range of a plot, depending on deSolve object and data...
## =============================================================================
SetRange <- function(lim, x, x2, isub, ix, obs, io, Log) {
nother <- length (x2)
if ( is.null (lim)) {
yrange <- Range(NULL, x[isub, ix], Log)
if (nother>0)
for (j in 1:nother)
yrange <- Range(yrange, x2[[j]][isub,ix], Log)
if (! is.na(io)) yrange <- Range(yrange, obs$dat[,io], Log)
} else
yrange <- lim
return(yrange)
}
## =============================================================================
## Add observed data to a plot
## =============================================================================
plotObs <- function (obs, io, xyswap = FALSE) {
oLength <- min(nrow(obs$pos), obs$length)
if (! xyswap) {
for (j in 1: oLength) {
i.obs <- obs$pos[j, 1] : obs$pos[j, 2]
if (length (i.obs) > 0)
do.call("points", c(alist(obs$dat[i.obs, 1], obs$dat[i.obs, io]),
extractdots(obs$par, j) ))
}
} else {
for (j in 1: oLength)
if (length (i.obs <- obs$pos[j, 1]:obs$pos[j, 2]) > 0)
do.call("points", c(alist(obs$dat[i.obs, io], obs$dat[i.obs, 1]),
extractdots(obs$par, j) ))
}
}
### ============================================================================
### Plotting 0-D variables
### ============================================================================
plot.deSolve <- function (x, ..., select = NULL, which = select, ask = NULL,
obs = NULL, obspar = list(), subset = NULL) {
t <- 1 # column with independent variable "times"
# Set the observed data
obs <- SetData(obs)
# variables to be plotted
varnames <- colnames(x)
Which <- WhichVarObs(which, obs, ncol(x) - 1, varnames)
# Position of variables to be plotted in "x"
xWhich <- selectvar(Which, varnames)
np <- length(xWhich)
# Position of variables in "obs" (NA = not observed)
obs <- updateObs(obs, varnames, xWhich)
obs$par <- lapply(obspar, repdots, obs$length)
# The ellipsis
ldots <- list(...)
# number of figures in a row and interactively wait if remaining figures
ask <- setplotpar(ldots, np, ask)
if (ask) {
oask <- devAskNewPage(TRUE)
on.exit(devAskNewPage(oask))
}
Dots <- splitdots(ldots, varnames)
nother <- Dots$nother
x2 <- Dots$x2
nx <- nother + 1 # total number of deSolve objects to be plotted
Dotmain <- setdots(Dots$main, np) # expand to np for each plot
# these are different from the default
Dotmain$xlab <- expanddots(ldots$xlab, varnames[t] , np)
Dotmain$ylab <- expanddots(ldots$ylab, "" , np)
Dotmain$main <- expanddots(ldots$main, varnames[xWhich], np)
# ylim and xlim can be lists and are at least two values
yylim <- expanddotslist(ldots$ylim, np)
xxlim <- expanddotslist(ldots$xlim, np)
Dotpoints <- setdots(Dots$points, nx) # expand all dots to nx values
# these are different from default
Dotpoints$type <- expanddots(ldots$type, "l", nx)
Dotpoints$lty <- expanddots(ldots$lty, 1:nx, nx)
Dotpoints$pch <- expanddots(ldots$pch, 1:nx, nx)
Dotpoints$col <- expanddots(ldots$col, 1:nx, nx)
Dotpoints$bg <- expanddots(ldots$bg, 1:nx, nx)
if (!missing(subset)){
e <- substitute(subset)
r <- eval(e, as.data.frame(x), parent.frame())
if (is.numeric(r)) {
isub <- r
} else {
if (!is.logical(r))
stop("'subset' must evaluate to logical or be a vector with integers")
isub <- r & !is.na(r)
}
} else {
isub <- TRUE
}
# LOOP for each output variable (plot)
for (ip in 1 : np) {
ix <- xWhich[ip] # position of variable in 'x'
io <- obs$Which[ip] # position of variable in 'obs'
# plotting parameters for deSolve output 1 (opens a plot)
dotmain <- extractdots(Dotmain, ip)
dotpoints <- extractdots(Dotpoints, 1) # 1st dotpoints
Xlog <- Ylog <- FALSE
if (! is.null(dotmain$log)) {
Ylog <- length(grep("y",dotmain$log))
Xlog <- length(grep("x",dotmain$log))
}
dotmain$ylim <- SetRange(yylim[[ip]], x, x2, isub, ix, obs, io, Ylog)
dotmain$xlim <- SetRange(xxlim[[ip]], x, x2, isub, t, obs, 1, Xlog)
# first deSolve object plotted (new plot created)
do.call("plot", c(alist(x[isub, t], x[isub, ix]), dotmain, dotpoints))
if (nother > 0) # if other deSolve outputs
for (j in 2:nx)
do.call("lines", c(alist(x2[[j-1]][isub, t], x2[[j-1]][isub, ix]),
extractdots(Dotpoints, j)) )
if (! is.na(io)) plotObs(obs, io) # add observed variables
}
}
## =============================================================================
## to draw a legend
## =============================================================================
drawlegend <- function (parleg, dots) {
Plt <- par(plt = parleg)
par(new = TRUE)
usr <- par("usr")
ix <- 1
minz <- dots$zlim[1]
maxz <- dots$zlim[2]
binwidth <- (maxz - minz)/64
iy <- seq(minz + binwidth/2, maxz - binwidth/2, by = binwidth)
iz <- matrix(iy, nrow = 1, ncol = length(iy))
image(ix, iy, iz, xaxt = "n", yaxt = "n", xlab = "",
ylab = "", col = dots$col)
do.call("axis", list(side = 4, mgp = c(3, 1, 0), las = 2))
par(plt = Plt)
par(usr = usr)
par(new = FALSE)
}
## =============================================================================
## to drape a color over a persp plot.
## =============================================================================
drapecol <- function (A,
col = colorRampPalette(c("#00007F", "blue", "#007FFF", "cyan",
"#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000"))(100),
NAcol = "white", Range = NULL)
{
nr <- nrow(A)
nc <- ncol(A)
ncol <- length(col)
AA <- 0.25 * (A[1:(nr - 1), 1:(nc - 1)] + A[1:(nr - 1), 2:nc] +
A[2:nr, 1:(nc - 1)] + A[2:nr, 2:nc])
if (is.null(Range))
Range <- range(A, na.rm = TRUE)
else {
AA[AA > Range[2]] <- Range[2]
AA[AA < Range[1]] <- Range[1]
}
Ar <- Range
rn <- Ar[2] - Ar[1]
ifelse(rn != 0, drape <- col[1 + trunc((AA - Ar[1])/rn *
(ncol - 1))], drape <- rep(col[1], ncol))
drape[is.na(drape)] <- NAcol
return(drape)
}
## =============================================================================
## Finding 1-D variables
## =============================================================================
select1dvar <- function (Which, var, att) {
if (is.null(att$map))
proddim <- prod(att$dimens)
else
proddim <- sum(!is.na(att$map))
ln <- length(Which)
csum <- cumsum(att$lengthvar) + 2
if (!is.numeric(Which)) {
# loop used to keep ordering...
Select <- NULL
for ( i in 1 : ln) {
ss <- which(Which[i] == var)
if (length(ss) == 0)
stop("variable ", Which[i], " not in variable names")
Select <- c(Select, ss)
}
} else {
Select <- Which # "Select now refers to the column number
if (max(Select) > length(var))
stop("index in 'which' too large")
if (min(Select) < 1)
stop("index in 'which' should be > 0")
}
istart <- numeric(ln)
istop <- numeric(ln)
for ( i in 1 : ln) {
if (Select[i] <= att$nspec) {
ii <- Select[i]
istart[i] <- (ii-1)*proddim + 2
istop[i] <- istart[i] + proddim - 1
} else {
ii <- Select[i] - att$nspec
istart[i] <- csum[ii]
istop[i] <- csum[ii+1]-1
}
if (istart[i] == istop[i])
stop ("variable ",Which[i], " is not a 1-D variable")
}
return(list(Which = Select, istart = istart, istop = istop))
}
## =============================================================================
## Finding 2-D variables
## =============================================================================
select2dvar <- function (Which, var, att) {
if (is.null(att$map))
proddim <- prod(att$dimens)
else
proddim <- sum(!is.na(att$map))
ln <- length(Which)
csum <- cumsum(att$lengthvar) + 2
if (!is.numeric(Which)) {
# loop to keep ordering...
Select <- NULL
for ( i in 1 : ln) {
ss <- which(Which[i] == var)
if (length(ss) == 0)
stop("variable ", Which[i], " not in variable names")
Select <- c(Select, ss)
}
} else {
Select <- Which # "Select now refers to the column number
if (max(Select) > length(var))
stop("index in 'which' too large")
if (min(Select) < 1)
stop("index in 'which' should be > 0")
}
istart <- numeric(ln)
istop <- numeric(ln)
dimens <- list()
for ( i in 1 : ln) {
if (Select[i] <= att$nspec) { # a state variable
ii <- Select[i]
istart[i] <- (ii-1)*proddim + 2
istop[i] <- istart[i] + proddim-1
dimens[[i]] <- att$dimens
} else {
ii <- Select[i] - att$nspec
istart[i] <- csum[ii]
istop[i] <- csum[ii+1]-1
ij <- which(names(att$dimvar) == var[Select[i]])
if (length(ij) == 0)
stop("variable ",var[Select]," is not two-dimensional")
dimens[[i]] <- att$dimvar[[ij]]
}
}
return(list(Which = Select, istart = istart, istop = istop, dim = dimens))
}
## =============================================================================
## Adding a vertical axis to a plot
## =============================================================================
DrawVerticalAxis <- function (dot, xmin) {
if (is.null(dot$xlim))
v <- xmin
else
v <- dot$xlim[1]
abline(h = dot$ylim[2])
abline(v = v)
axis(side = 2)
axis(side = 3, mgp = c(3,0.5,0))
}
### ============================================================================
### plotting 1-D variables as line plot, one for each time
### ============================================================================
plot.1D <- function (x, ... , select= NULL, which = select, ask = NULL,
obs = NULL, obspar = list(), grid = NULL,
xyswap = FALSE, delay = 0, vertical = FALSE,
subset = NULL) {
## Check settings of x
att <- attributes(x)
nspec <- att$nspec
dimens <- att$dimens
proddim <- prod(dimens)
if (length(dimens) != 1)
stop ("plot.1D only works for models solved with 'ode.1D'")
if ((ncol(x)- nspec*proddim) < 1)
stop("ncol of 'x' should be > 'nspec' * dimens if x is a vector")
# Set the observed data
obs <- SetData(obs)
# 1-D variable names
varnames <- if (! is.null(att$ynames))
att$ynames else 1:nspec
if (! is.null(att$lengthvar))
varnames <- c(varnames, names(att$lengthvar)[-1])
# variables to be plotted, common between obs and x
Which <- WhichVarObs(which, obs, nspec, varnames, remove1st = FALSE)
np <- length(Which)
Select <- select1dvar(Which, varnames, att)
xWhich <- Select$Which
# add Position of variables to be plotted in "obs"
obs <- updateObs (obs, varnames, xWhich)
obs$par <- lapply(obspar, repdots, obs$length) # karline: small bug fixed here
# the ellipsis
ldots <- list(...)
## number of figures in a row and interactively wait if remaining figures
ask <- setplotpar(ldots, np, ask)
if (ask) {
oask <- devAskNewPage(TRUE)
on.exit(devAskNewPage(oask))
}
Dots <- splitdots(ldots, colnames(x))
# for time-moving figures; number of plots should = mfrow settings
prodx <- prod(par("mfrow"))
if (np < prodx) eplot <- prodx - np else eplot <- 0
nother <- Dots$nother
x2 <- Dots$x2
nx <- nother + 1 # total number of deSolve objects to be plotted
Dotmain <- setdots(Dots$main, np) # expand to np for each plot
Dotpoints <- setdots(Dots$points, nx)
# These are different from defaulst
Dotmain$xlab <- expanddots(ldots$xlab, "x", np)
Dotmain$ylab <- expanddots(ldots$ylab, varnames[xWhich], np)
# xlim and ylim are special:
xxlim <- expanddotslist(ldots$xlim, np)
yylim <- expanddotslist(ldots$ylim, np)
xyswap <- rep(xyswap, length = np)
vertical <- rep(vertical, length = np)
grid <- expanddotslist(grid, np)
if (!missing(subset)){
e <- substitute(subset)
r <- eval(e, as.data.frame(x), parent.frame())
if (is.numeric(r)) {
isub <- r
} else {
if (!is.logical(r))
stop("'subset' must evaluate to logical or be a vector with integers")
isub <- which(r & !is.na(r))
}
} else {
isub <- 1:nrow(x)
}
# allow individual xlab and ylab (vectorized)
times <- x[isub,1]
Dotsmain <- expanddots(Dotmain$main, paste("time", times), length(times))
for (j in isub) {
for (ip in 1:np) {
istart <- Select$istart[ip]
istop <- Select$istop[ip]
io <- obs$Which[ip]
out <- x[j,istart:istop]
Grid <- grid[[ip]]
if (is.null(Grid))
Grid <- 1:length(out)
dotmain <- extractdots(Dotmain, ip)
dotpoints <- extractdots(Dotpoints, 1) # 1st one
dotmain$main <- Dotsmain[j]
if (vertical[ip]) { # overrules other settings; vertical profiles
xyswap[ip] <- TRUE
dotmain$axes <- FALSE
dotmain$xlab <- ""
dotmain$xaxs <- "i"
dotmain$yaxs <- "i"
}
Xlog <- Ylog <- FALSE
if (! is.null(dotmain$log)) {
Ylog <- length(grep("y",dotmain$log))
Xlog <- length(grep("x",dotmain$log))
}
if (! xyswap[ip]) {
if (! is.null(xxlim[[ip]]))
dotmain$xlim <- xxlim[[ip]]
dotmain$ylim <- SetRange(yylim[[ip]], x, x2, isub, istart:istop, obs, io, Ylog)
} else {
if (! is.null(yylim[[ip]]))
dotmain$ylim <- yylim[[ip]]
dotmain$xlim <- SetRange(xxlim[[ip]], x, x2, isub, istart:istop, obs, io, Xlog)
if (is.null(yylim[[ip]]) & xyswap[ip])
dotmain$ylim <- rev(range(Grid)) # y-axis
}
if (! xyswap[ip]) {
do.call("plot", c(alist(Grid, out), dotmain, dotpoints))
if (nother > 0) # if other deSolve outputs
for (jj in 2:nx)
do.call("lines", c(alist(Grid, x2[[jj-1]][j,istart:istop]),
extractdots(Dotpoints, jj)) )
if (! is.na(io))
plotObs(obs, io)
} else {
if (is.null(Dotmain$xlab[ip]) | is.null(Dotmain$ylab[ip])) {
dotmain$ylab <- Dotmain$xlab[ip]
dotmain$xlab <- Dotmain$ylab[ip]
}
do.call("plot", c(alist(out, Grid), dotmain, dotpoints))
if (nother > 0) # if other deSolve outputs
for (jj in 2:nx)
do.call("lines", c(alist(x2[[jj-1]][j,istart:istop], Grid),
extractdots(Dotpoints, jj)) )
if (vertical[ip]) DrawVerticalAxis(dotmain,min(out))
if (! is.na(io))
plotObs(obs, io, xyswap = TRUE)
}
} # end loop ip
if (eplot > 0)
for (i in 1:eplot) plot(0, type ="n", axes = FALSE, xlab="", ylab="")
if (delay > 0) Sys.sleep(0.001 * delay)
}
}
### ============================================================================
plot.ode1D <- function (x, which, ask, add.contour, grid,
method = "image", legend, isub = 1:nrow(x), ...) {
# Default color scheme
BlueRed <- colorRampPalette(c("#00007F", "blue", "#007FFF", "cyan",
"#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000"))
# if x is vector, check if there are enough columns ...
att <- attributes(x)
nspec <- att$nspec
dimens <- att$dimens
proddim <- prod(dimens)
if ((ncol(x)- nspec * proddim) < 1)
stop("ncol of 'x' should be > 'nspec' * dimens if x is a vector")
# variables to be plotted
if (is.null(which))
Which <- 1 : nspec
else
Which <- which
np <- length(Which)
varnames <- if (! is.null(att$ynames)) att$ynames else 1:nspec
if (! is.null(att$lengthvar))
varnames <- c(varnames, names(att$lengthvar)[-1])
Select <- select1dvar(Which, varnames, att)
Which <- Select$Which
ldots <- list(...)
# number of figures in a row and interactively wait if remaining figures
ask <- setplotpar(ldots, np, ask)
if (ask) {
oask <- devAskNewPage(TRUE)
on.exit(devAskNewPage(oask))
}
Dotmain <- setdots(ldots, np) # expand dots to np values (no defaults)
# different from the default
Dotmain$main <- expanddots(ldots$main, varnames[Which], np)
Dotmain$xlab <- expanddots(ldots$xlab, "times", np)
Dotmain$ylab <- expanddots(ldots$ylab, "", np)
# colors - different if persp, image or filled.contour
if (method == "persp")
dotscol <- ldots$col
else if (method == "filled.contour") {
dotscolorpalette <- if (is.null(ldots$color.palette))
BlueRed else ldots$color.palette
dotscol <- dotscolorpalette(100)
add.contour <- FALSE
legend <- FALSE
} else
if (is.null(ldots$col))
dotscol <- BlueRed(100) else dotscol <- ldots$col
Addcontour <- rep(add.contour, length = np)
# xlim, ylim and zlim are special:
xxlim <- expanddotslist(ldots$xlim, np)
yylim <- expanddotslist(ldots$ylim, np)
zzlim <- expanddotslist(ldots$zlim, np)
times <- x[isub,1]
if (legend) {
parplt <- par("plt") - c(0,0.07,0,0)
parleg <- c(parplt[2]+0.02, parplt[2]+0.05, parplt[3], parplt[4])
plt.or <- par(plt = parplt)
# on.exit(par(plt = plt.or))
}
# Check if grid is increasing...
if (! is.null(grid))
gridOK <- min(diff (grid)) >0
else
gridOK <- TRUE
if (! gridOK) grid <- rev(grid)
# for each output variable (plot)
for (ip in 1:np) {
# ix <- Which[ip]
istart <- Select$istart[ip]
istop <- Select$istop[ip]
if (gridOK)
out <- x[isub ,istart:istop]
else
out <- x[isub ,istop:istart]
dotmain <- extractdots(Dotmain, ip)
if (! is.null(xxlim)) dotmain$xlim <- xxlim[[ip]]
if (! is.null(yylim)) dotmain$ylim <- yylim[[ip]]
if (! is.null(zzlim))
dotmain$zlim <- zzlim[[ip]]
else
dotmain$zlim <- range(out, na.rm=TRUE)
List <- alist(z = out, x = times)
if (! is.null(grid)) List$y = grid
if (method == "persp") {
if (is.null(dotmain$zlim)) # this to prevent error when range = 0
if (diff(range(out, na.rm=TRUE)) == 0)
dotmain$zlim <- c(0, 1)
if (is.null(dotscol))
dotmain$col <- drapecol(out, col = BlueRed (100), Range = dotmain$zlim)
else
dotmain$col <- drapecol(out, col = dotscol, Range = dotmain$zlim)
} else if (method == "filled.contour")
dotmain$color.palette <- dotscolorpalette
else
dotmain$col <- dotscol
do.call(method, c(List, dotmain))
if (Addcontour[ip]) do.call("contour", c(List, add = TRUE))
if (legend) {
if (method == "persp")
if (is.null(dotscol))
dotmain$col <- BlueRed(100)
else
dotmain$col <- dotscol
if (is.null(dotmain$zlim)) dotmain$zlim <- range(out, na.rm=TRUE)
drawlegend(parleg, dotmain)
}
}
if (legend) {
par(plt = plt.or)
par(mar = par("mar")) # TRICK TO PREVENT R FROM SETTING DEFAULTPLOT = FALSE
}
}
### ============================================================================
### plotting 2-D variables
### ============================================================================
plot.ode2D <- function (x, which, ask, add.contour, grid, method = "image",
legend = TRUE, isub = 1:nrow(x), ...) {
# Default color scheme
BlueRed <- colorRampPalette(c("#00007F", "blue", "#007FFF", "cyan",
"#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000"))
# if x is vector, check if there are enough columns ...
att <- attributes(x)
nspec <- att$nspec
dimens <- att$dimens
proddim <- prod(dimens)
Mask <- att$map
map <- (! is.null(Mask))
if (!map & (ncol(x) - nspec*proddim) < 1)
stop("ncol of 'x' should be > 'nspec' * dimens if x is a vector")
# variables to be plotted
if (is.null(which))
Which <- 1:nspec
else
Which <- which
np <- length(Which)
varnames <- if (! is.null(att$ynames)) att$ynames else 1:nspec
if (! is.null(att$lengthvar))
varnames <- c(varnames, names(att$lengthvar)[-1])
Select <- select2dvar(Which,varnames,att)
Which <- Select$Which
ldots <- list(...)
Mtext <- ldots$mtext
ldots$mtext <- NULL
# number of figures in a row and interactively wait if remaining figures
Ask <- setplotpar(ldots, np, ask)
# here ask is always true by default...
if (is.null(ask)) ask <- TRUE
if (ask) {
oask <- devAskNewPage(TRUE)
on.exit(devAskNewPage(oask))
}
N <- np * nrow(x)
if (method == "filled.contour") {
add.contour <- FALSE
legend <- FALSE
}
Dotmain <- setdots(ldots, N) # expand dots to np values (no defaults)
# different from the default
Dotmain$main <- expanddots(ldots$main, varnames[Which], N)
Dotmain$xlab <- expanddots(ldots$xlab, "x" , N)
Dotmain$ylab <- expanddots(ldots$ylab, "y" , N)
if (method == "persp")
dotscol <- ldots$col
else if (method == "filled.contour") {
dotscolorpalette <- if (is.null(ldots$color.palette))
BlueRed else ldots$color.palette
dotscol <- dotscolorpalette(100)
add.contour <- FALSE
legend <- FALSE
} else if (is.null(ldots$col))
dotscol <- BlueRed(100) else dotscol <- ldots$col
dotslim <- ldots$zlim
xxlim <- expanddotslist(ldots$xlim, np)
yylim <- expanddotslist(ldots$ylim, np)
zzlim <- expanddotslist(ldots$zlim, np)
Addcontour <- rep(add.contour, length = np)
i <- 0
if (legend) {
parplt <- par("plt") - c(0, 0.05, 0, 0)
parleg <- c(parplt[2] + 0.02, parplt[2] + 0.05, parplt[3], parplt[4])
plt.or <- par(plt = parplt)
# on.exit(par(plt = plt.or))
}
x <- x[isub,]
if (length(isub) > 1 & sum (isub) == 1)
x <- matrix (nrow = 1, data =x)
if (! is.null(Mtext))
Mtext <- rep(Mtext, length.out = nrow(x))
for (nt in 1:nrow(x)) {
for (ip in 1:np) {
i <- i+1
istart <- Select$istart[ip]
istop <- Select$istop[ip]
if (map) {
out <- rep (NA, length = prod(Select$dim[[ip]]))
ii <- which (! is.na(Mask))
out[ii] <- x[nt, istart:istop]
} else
out <- x[nt, istart:istop]
dim(out) <- Select$dim[[ip]]
dotmain <- extractdots(Dotmain, i)
if (! is.null(xxlim)) dotmain$xlim <- xxlim[[ip]]
if (! is.null(yylim)) dotmain$ylim <- yylim[[ip]]
if (! is.null(zzlim))
dotmain$zlim <- zzlim[[ip]]
else {
dotmain$zlim <- range(out, na.rm=TRUE)
if (diff(dotmain$zlim ) == 0 )
dotmain$zlim[2] <- dotmain$zlim[2] +1
}
if (map) {
if (is.null(dotmain$zlim))
dotmain$zlim <- range(out, na.rm=TRUE)
out[is.na(out)] <- dotmain$zlim[1] - 0.01*max(1e-18,diff(dotmain$zlim))
dotmain$zlim [1] <- dotmain$zlim[1] - 0.01*max(1e-18,diff(dotmain$zlim))
}
List <- alist(z = out)
if (! is.null(grid)) {
List$x <- grid$x
List$y <- grid$y
}
if (method == "persp") {
if (is.null(dotmain$zlim))
if (diff(range(out, na.rm = TRUE)) == 0)
dotmain$zlim <- c(0, 1)
if (is.null(dotscol))
dotmain$col <- drapecol(out, col = BlueRed(100), Range = dotmain$zlim)
else
dotmain$col <- drapecol(out, col = dotscol, Range = dotmain$zlim)
} else if (method == "image") {
dotmain$col <- dotscol
if (map) dotmain$col <- c("black", dotmain$col)
} else if (method == "filled.contour")
dotmain$color.palette <- dotscolorpalette
do.call(method, c(List, dotmain))
drawbox <- ! method %in% c("persp", "filled.contour")
if (! is.null(ldots$frame.plot))
if (! ldots$frame.plot) drawbox <- FALSE
if (drawbox) box()
if (add.contour) do.call("contour", c(List, add = TRUE))
if (legend) {
if (method == "persp")
if (is.null(dotscol))
dotmain$col <- BlueRed(100)
else
dotmain$col <- dotscol
if (is.null(dotmain$zlim))
dotmain$zlim <- range(out, na.rm=TRUE)
drawlegend(parleg, dotmain)
}
}
if (! is.null(Mtext))
mtext(outer = TRUE, side = 3, Mtext[nt],
cex = 1.5, line = par("oma")[3]-1.5)
}
if (legend) {
par(plt = plt.or)
par(mar = par("mar")) # TRICK TO PREVENT R FROM SETTING DEFAULTPLOT = FALSE
}
# karline: ??? removed that... make it an argument?
# if (sum(par("mfrow") - c(1, 1)) == 0 )
# mtext(outer = TRUE, side = 3, paste("time ", x[nt, 1]),
# cex = 1.5, line = -1.5)
}
### ============================================================================
### Summaries of ode variables
### ============================================================================
summary.deSolve <- function(object, select = NULL, which = select,
subset = NULL, ...){
att <- attributes(object)
svar <- att$lengthvar[1] # number of state variables
lvar <- att$lengthvar[-1] # length of other variables
nspec <- att$nspec # for models solved with ode.1D, ode.2D
dimens <- att$dimens
if (is.null(svar)) svar <- att$dim[2]-1 # models solved as DLL
# variable names: information for state and ordinary variables is different
if (is.null(att$ynames))
if (is.null(dimens))
varnames <- colnames(object)[2:(svar+1)]
else
varnames <- 1:nspec
else
varnames <- att$ynames # this gives one name for multi-dimensional var.
if (length(lvar) > 0) {
lvarnames <- names(lvar)
if (is.null(lvarnames))
lvarnames <- (length(varnames)+1):(length(varnames)+length(lvar))
varnames <- c(varnames, lvarnames)
}
# length of state AND other variables
if (is.null(dimens)) # all 0-D state variables
lvar <- c(rep(1, len = svar), lvar)
else
lvar <- c(rep(prod(dimens), nspec), lvar) # multi-D state variables
if (!missing(subset)){
e <- substitute(subset)
r <- eval(e, as.data.frame(object), parent.frame())
if (is.numeric(r)) {
isub <- r
} else {
if (!is.logical(r))
stop("'subset' must evaluate to logical or be a vector with integers")
isub <- r & !is.na(r)
object <- object[isub,]
}
}
# summaries for all variables
Summ <- NULL
for (i in 1:length(lvar)) {
if (lvar[i] > 1) {
Select <- select1dvar(i, varnames, att)
out <- as.vector(object[, Select$istart:Select$istop])
} else {
Select <- selectvar(varnames[i], colnames(object), NAallowed = TRUE)
if (is.na(Select)) # trick for composite names, e.g. "A.x" rather than "A"
Select <- cumsum(lvar)[i]
out <- object[ ,Select]
}
Summ <- rbind(Summ, c(summary(out, ...), N = length(out), sd = sd(out)))
}
rownames(Summ) <- varnames # rownames or an extra column?
if (! is.null(which))
Summ <- Summ[which,]
data.frame(t(Summ)) # like this or not transposed?
}
### ============================================================================
### Subsets of ode variables
### ============================================================================
subset.deSolve <- function(x, subset = NULL, select = NULL,
which = select, arr = FALSE, ...) {
Which <- which # for compatibility between plot.deSolve and subset
if (arr & length(Which) > 1)
stop("cannot combine 'arr = TRUE' when more than one variable is selected")
if (missing(subset))
r <- TRUE
else {
e <- substitute(subset)
r <- eval(e, as.data.frame(x), parent.frame())
if (is.numeric(r)) {
isub <- r
} else {
if (!is.logical(r))
stop("'subset' must evaluate to logical or be a vector with integers")
r <- r & !is.na(r)
}
}
if (is.numeric(Which))
return(x[r ,Which+1])
if (is.null(Which))
return(x[r , -1]) # Default: all variables, except time
att <- attributes(x)
svar <- att$lengthvar[1] # number of state variables
lvar <- att$lengthvar[-1] # length of other variables
nspec <- att$nspec # for models solved with ode.1D, ode.2D
dimens <- att$dimens
if (arr & length(dimens) <= 1 )
warning("does not make sense to have 'arr = TRUE' when output is not 2D or 3D")
if (is.null(svar)) svar <- att$dim[2]-1 # models solved as DLL
if(is.null(nspec)) nspec <- svar
# variable names: information for state and ordinary variables is different
if (is.null(att$ynames))
if (is.null(dimens))
varnames <- colnames(x)[2:(svar+1)]
else
varnames <- 1:nspec
else
varnames <- att$ynames # this gives one name for multi-dimensional var.
varnames <- c("time",varnames)
if (length(lvar) > 0) {
lvarnames <- names(lvar)
if (is.null(lvarnames))
lvarnames <- (length(varnames)+1):(length(varnames)+length(lvar))
varnames <- c(varnames, lvarnames)
}
# length of state AND other variables
if (is.null(dimens)) # all 0-D state variables
lvar <- c(rep(1, len = svar), lvar)
else
lvar <- c(rep(prod(dimens), nspec), lvar) # multi-D state variables
cvar <- cumsum(c(1,lvar))
# Add selected variables to Out
Out <- NULL
for (iw in 1:length(Which)) {
i <- which (varnames == Which[iw])
if (length(i) == 0) {
i <- which (colnames(x) == Which[iw])
if (length(i) == 0)
stop ("cannot find variable ", Which[iw], " in output")
Out <- cbind(Out, x[,i])
} else {
if (is.null(i))
stop ("cannot find variable ", Which[iw], " in output")
istart <- 1
if (i > 1) istart <- cvar[i-1]+1
istop <- cvar[i]
Out <- cbind(Out, x[ ,istart:istop])
}
}
if (length(Which) == ncol(Out)) colnames(Out) <- Which
OO <- Out[r, ]
if(is.vector(OO)) OO <- matrix(ncol = ncol(Out), data = OO)
times <- x[r,1]
if (arr & length(dimens) > 1 & ncol(OO) == prod(dimens)) {
Nr <- nrow(OO)
OO <- array(dim = c(dimens, Nr) , data = t(OO))
}
attr(OO, "times") <- times
return(OO)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.