Rev 5266 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
### Copyright (C) 2001-2006 Deepayan Sarkar <Deepayan.Sarkar@R-project.org>###### This file is part of the lattice package for R.### It is made available under the terms of the GNU General Public### License, version 2, or at your option, any later version,### incorporated herein by reference.###### This program is distributed in the hope that it will be### useful, but WITHOUT ANY WARRANTY; without even the implied### warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR### PURPOSE. See the GNU General Public License for more### details.###### You should have received a copy of the GNU General Public### License along with this program; if not, write to the Free### Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,### MA 02110-1301, USA## retrieve last saved (while printing) trellis objecttrellis.last.object <- function(warn = TRUE, ...){ans <- get("last.object", envir = .LatticeEnv)if (is.null(ans)) {warning("No trellis object currently saved")return(invisible())}if (warn && !lattice.getStatus("current.plot.saved"))warning("currently saved object is not the last one plotted")update(ans, ...)}## Not all arguments to xyplot etc can be supplied to## update.trellis. Generally speaking, anything that needs to change## the data within each panel is a no-no. Everything else is## technically game, though implementation might be## problematic. Here's a list of arguments that should work (list## currently based on xyplot, may need to be updated later)## panel## aspect = "fill",## as.table = FALSE,## between,## key,## auto.key = FALSE,## layout,## main,## page,## par.strip.text,## prepanel,## scales, one of the problematic ones## skip,## strip,## strip.left,## sub,## xlab,## xlim,## ylab,## ylim,## par.settings,## ..., these should probably be added to the list of common panel arguments## There is also the possibility of some update arguments that may not## necessarily be valid arguments to xyplot etc (although we might## change that). Currently these would be the perm and index arguments## controlling reordering of conditioning variables and their levels.update.trellis <-function(object,panel,aspect,as.table,between,key,auto.key,legend,layout,main,page,par.strip.text,prepanel,scales, #one of the problematic onesskip,strip,strip.left,sub,xlab,xlim,ylab,ylim,par.settings,plot.args,lattice.options,index.cond,perm.cond,...){## modify call to reflect updateupcall <- match.call()nm <- names(upcall)if (!is.null(nm)){nm <- nm[nm != "" & nm != "object"]if (length(nm) == 0){## FIXME: drop this message before release## cat("nothing to update with")return(object)}object$call[nm] <- upcall[nm]}have.xlim <- !missing(xlim) ## needed laterhave.ylim <- !missing(ylim)## deal with the non-problematic stuff firstif (!missing(as.table)){if (is.logical(as.table)) object$as.table <- as.tableelse warning("Inappropriate value of 'as.table'")}if (!missing(between)){if ("x" %in% names(between)) object$x.between <- between$xif ("y" %in% names(between)) object$y.between <- between$y}if (!missing(layout)){object$layout <- layout}if (!missing(main)) object$main <- mainif (!missing(sub)) object$sub <- subif (!missing(xlab)) object$xlab <- xlabif (!missing(ylab)) object$ylab <- ylabif (!missing(page)) object$page <- pageif (!missing(par.strip.text)){## this only overwrites earlier things, leaves alone those## that are not specified explicitlyif (is.list(par.strip.text))object$par.strip.text <- updateList(object$par.strip.text, par.strip.text)else warning("'par.strip.text' must be a list")}if (!missing(skip)) object$skip <- skipif (!missing(strip)){if (is.logical(strip)) {if (strip) object$strip <- strip.defaultelse object$strip <- FALSE}else object$strip <- strip}if (!missing(strip.left)){if (is.logical(strip.left)) {if (strip.left) object$strip.left <- strip.custom(horizontal = FALSE)else object$strip.left <- FALSE}else object$strip.left <- strip.left}if (!missing(par.settings)){## this only overwrites earlier things, leaves alone those## that are not specified explicitlyif (is.list(par.settings))object$par.settings <- updateList(object$par.settings, par.settings)else warning("'par.settings' must be a list")}if (!missing(plot.args)){## this only overwrites earlier things, leaves alone those## that are not specified explicitlyif (is.list(plot.args))object$plot.args <- updateList(object$plot.args, plot.args)else warning("'plot.args' must be a list")}if (!missing(lattice.options)){## this only overwrites earlier things, leaves alone those## that are not specified explicitlyif (is.list(lattice.options))object$lattice.options <- updateList(object$lattice.options, lattice.options)else warning("'lattice.options' must be a list")}## during construction of trellis objects, perm.cond and## index.cond are calculated by the cond.orders function. We could## do that here as well, but the perm.cond is really too trivial## to bother. cond.orders() is called is index.cond is## non-missing, and then it becomes important that perm.cond is## processed first (in case it it non-missing as well).if (!missing(perm.cond)){if (is.null(perm.cond))object$perm.cond <- seq_len(length(object$condlevels))else if (all(sort(perm.cond) == object$perm.cond))object$perm.cond <- perm.condelse stop("Invalid value of 'perm.cond'")}if (!missing(index.cond)){object$index.cond <- index.condcond.ord <- cond.orders(object)object[names(cond.ord)] <- cond.ord}dots <- list(...)if (length(dots) > 0){##print(dots) ## for debugging, remove laterobject$panel.args.common <- updateList(object$panel.args.common, dots)}if (!missing(panel)){panel <-if (is.function(panel)) panelelse if (is.character(panel)) get(panel)else eval(panel)if (as.character(object$call[[1]]) == "splom")object$panel.args.common$panel <- panelelse object$panel <- panel}## the slightly complicated stuffif (!missing(legend)){if (is.null(legend)) object$legend <- NULLelse object$legend <- updateList(object$legend, legend)}if (!missing(key)){object$legend <-updateList(object$legend,construct.legend(legend = NULL, key = key))}if (!missing(auto.key)){if (!is.null(object$legend))message("Note: 'auto.key' ignored since legend already present.\nUse 'update(..., legend = NULL)' to remove existing legend(s)")else{groups <- object$panel.args.common$groupsif (!is.null(groups) && (is.list(auto.key) || (is.logical(auto.key) && auto.key))){object$legend <-list(list(fun = "drawSimpleKey",args =updateList(list(text = levels(as.factor(groups))),if (is.list(auto.key)) auto.key else list())))object$legend[[1]]$x <- object$legend[[1]]$args$xobject$legend[[1]]$y <- object$legend[[1]]$args$yobject$legend[[1]]$corner <- object$legend[[1]]$args$cornernames(object$legend) <-if (any(c("x", "y", "corner") %in% names(object$legend[[1]]$args)))"inside"else"top"if (!is.null(object$legend[[1]]$args$space))names(object$legend) <- object$legend[[1]]$args$space}}}relationChanged <- FALSEif (!missing(scales))## FIXME: this needs special handling for cloud, but leave that for later{if (is.character(scales)) scales <- list(relation = scales)xscales <- scales$xyscales <- scales$yzscales <- scales$zscales$x <- NULLscales$y <- NULLscales$z <- NULLif (is.character(xscales)) xscales <- list(relation = xscales)if (is.character(yscales)) yscales <- list(relation = yscales)if (is.character(zscales)) zscales <- list(relation = zscales)if (!is.null(scales$log) || !is.null(xscales$log) || !is.null(yscales$log) || !is.null(zscales$log)){warning("log scales cannot be changed via 'update'")scales$log <- NULLxscales$log <- NULLyscales$log <- NULLzscales$log <- NULL}if (is.logical(scales$alternating)) scales$alternating <- if (scales$alternating) c(1,2) else 1if (is.logical(xscales$alternating)) xscales$alternating <- if (xscales$alternating) c(1,2) else 1if (is.logical(yscales$alternating)) yscales$alternating <- if (yscales$alternating) c(1,2) else 1## cannot possibly make sense for zfor (nm in c("tck", "cex", "rot")){scales[[nm]] <- rep(scales[[nm]], length.out = 2)xscales[[nm]] <- rep(xscales[[nm]], length.out = 2)yscales[[nm]] <- rep(yscales[[nm]], length.out = 2)zscales[[nm]] <- rep(zscales[[nm]], length.out = 2)}if (!is.null(scales$limits)){have.xlim <- TRUEhave.ylim <- TRUE##have.zlim <- TRUExlim <- scales$limitsylim <- scales$limits##zlim <- scales$limits}if (!is.null(xscales$limits)){have.xlim <- TRUExlim <- xscales$limits}if (!is.null(yscales$limits)){have.ylim <- TRUEylim <- yscales$limits}if (!is.null(scales$relation) || !is.null(xscales$relation) || !is.null(yscales$relation))relationChanged <- TRUEobject$x.scales[names(scales)] <- scalesobject$y.scales[names(scales)] <- scalesobject$z.scales[names(scales)] <- scalesobject$x.scales[names(xscales)] <- xscalesobject$y.scales[names(yscales)] <- yscalesobject$z.scales[names(zscales)] <- zscalesif (object$x.scales$relation == "same" && (is.list(object$x.scales$at) || is.list(object$x.scales$lab)))stop("the at and labels components of scales may not be lists when relation = same")if (object$y.scales$relation == "same" && (is.list(object$y.scales$at) || is.list(object$y.scales$lab)))stop("the at and labels components of scales may not be lists when relation = same")}## difficult stuff# aspect# prepanel,# scales, #one of the problematic ones# xlim,# ylim,## stuff that may need recalculation of limits and aspect ratiorecalculateLimits <- have.xlim || have.ylim || relationChangedif (!missing(aspect)){if (is.numeric(aspect)){object$aspect.ratio <- aspectobject$aspect.fill <- FALSE}else if (is.character(aspect)){if (aspect == "fill") object$aspect.fill <- TRUEelse if (aspect == "xy"){object$aspect.fill <- FALSEobject$aspect.ratio <- "xy" ## guaranteed to be modified belowrecalculateLimits <- TRUE}else if (aspect == "iso"){object$aspect.fill <- FALSEobject$aspect.ratio <- "iso" ## guaranteed to be modified belowrecalculateLimits <- TRUE}else warning(gettextf("Unrecognized value of 'aspect': '%s'", as.character(aspect)))}else warning("Invalid value of 'aspect'")}if (!missing(prepanel)){recalculateLimits <- TRUEprepanel <-if (is.function(prepanel)) prepanelelse if (is.character(prepanel)) get(prepanel)else eval(prepanel)}else prepanel <- object$prepanelif (recalculateLimits){prepanel.def <- object$prepanel.defaultlaa <- limits.and.aspect(prepanel.default.function = prepanel.def,prepanel = prepanel,have.xlim = have.xlim,xlim = xlim,have.ylim = have.ylim,ylim = ylim,x.relation = object$x.scales$relation,y.relation = object$y.scales$relation,panel.args.common = object$panel.args.common,panel.args = object$panel.args,aspect = object$aspect.ratio)##...) ## extra arguments for prepanel (for qqmathline)object[names(laa)] <- laa}object}## `subsetting': shortcut to updating index.cond"[.trellis" <- function(x, i, j, ..., drop = FALSE){## call update.trellis with a suitable 'index.cond' argumentocall <- match.call()[-2] # removes 'x'ocall[[1]] <- quote(base::list)if (!missing(drop)){if (drop) warning("'drop=TRUE' ignored")ocall$drop <- NULL}indices <- rep(list(TRUE), length.out = length(x$condlevels))if (!missing(i)) {indices[[1]] <- iocall$i <- NULL}if (!missing(j)) {indices[[2]] <- jocall$j <- NULL}## set missing args in ocall to TRUE before evaluatingif (length(ocall) > 1){emptyArgs <-sapply(as.list(ocall[-1]),function(x) (typeof(x) == "symbol" &&as.character(x) == ""))ocall[1L + which(emptyArgs)] <- quote(TRUE)dots <- eval.parent(ocall)indices[-c(1, 2)] <- dots}original.levs <- lapply(sapply(x$condlevels, length), seq)stopifnot(length(original.levs) == length(indices))current.levs <-mapply("[", original.levs, x$index.cond,SIMPLIFY = FALSE)new.levs <-mapply("[", current.levs, indices,SIMPLIFY = FALSE)if (any(sapply(new.levs, function(x) any(is.na(x)))))stop("Invalid indices")update(x, index.cond = new.levs)}## ## Old version. Failed with## ## bar <- function(i) { foo[,,,i] }## ## bar(1)## "[.trellis" <- function(x, i, j, ..., drop = FALSE)## {## ## index.cond <-## ocall <- match.call()## tmp <- as.list(ocall)[-(1:2)]## isj <- "j" %in% names(tmp)## isi <- "i" %in% names(tmp)## if (drop)## {## warning("'drop=TRUE' ignored")## tmp$drop <- NULL## }## len <-## if (length(dim(x)) == 1) 1## else length(tmp) + (1 - isj) + (1 - isi)## indices <- rep(list(TRUE), length.out = len)## if (isi)## {## indices[[1]] <- tmp$i## tmp <- tmp[-1]## }## if (isj)## {## indices[[2]] <- tmp$j## tmp <- tmp[-1]## }## if (len > 2)## {## keep <-## sapply(tmp,## function(x)## typeof(x) == "symbol" && as.character(x) == "")## tmp[keep] <- list(TRUE)## indices[-(1:2)] <- tmp## }## indices <- lapply(indices, eval)## original.levs <- lapply(sapply(x$condlevels, length), seq)## stopifnot(length(original.levs) == len)## current.levs <-## mapply("[", original.levs, x$index.cond,## SIMPLIFY = FALSE)## new.levs <-## mapply("[", current.levs, indices,## SIMPLIFY = FALSE)## if (any(sapply(new.levs, function(x) any(is.na(x)))))## stop("Invalid indices")## update(x, index.cond = new.levs)## }t.trellis <- function(x){stopifnot(length(dim(x)) == 2)update(x, perm.cond = rev(x$perm.cond))}