##! # plot.sem # # Renders a path diagram image in the current plot. # # Example: # library(sem) # semfit <- sem(ram, S, N) # plot(semfit) # # Requirements: # This depends on the package 'sem' and the package 'rgdal' for its full functioning. # This also utilizes the external web API service provided by Google. See http://code.google.com/intl/en/apis/chart/docs/gallery/graphviz.html # Tested with R 2.11.1 , sem 0.9-21 , rgdal 0.6-29 . # # @varsion 1.0 # @date 2010-03-02 # @author Masashi Nakanishi # @license GPL2 # plot.sem(model, file=NULL, graphics.fmt=c("png", "gif"), # engine=c("dot", "neato", "twopi", "circo", "fdp"), # size, write.file=TRUE, plot=TRUE, ...) # # @param model a 'sem' object returned by sem::sem(). # @param file character. A filepath to the image file to be generated. If NULL (default), a temporary file is used. # @param graphics.fmt character. File format of the generated image. "png" (default) or "gif". # @param engine character. A name of GraphViz layout programs. Default is "dot". See http://www.graphviz.org/ # @param size size of the generated image file. When a character string, specify the width and height in pixels in "x" form. # When a numeric vector, width is the first element, height the second, in inches. The actual pixels are computed under assuming 96 dpi. # If not specified, image size is automatically determined. # @param write.file if FALSE, no image file is generated, and plot is ignored. One of the goals will be the test use with the return value. # @param plot if FALSE, no plotting is tried, and then the package 'rgdal' is no longer required. # @param ... passed to sem::path.diagram() # @return list of some internal values, such as DOT language expression, API request URL, so on. FALSE if required packages do not exist. plot.sem <- function(model, file=NULL, graphics.fmt=c("png", "gif"), engine=c("dot", "neato", "twopi", "circo", "fdp"), size, write.file=TRUE, plot=TRUE, ...) { if (!suppressPackageStartupMessages(require("sem"))) return(invisible(FALSE)) graphics.fmt <- match.arg(graphics.fmt) engine <- match.arg(engine) if (!("sem" %in% class(model))) stop("argument 'model' must be a object with class 'sem'") if (!is.null(file) && !is.character(file)) stop("argument 'file' must be a character string or NULL") pd <- match.call() if (any((i <- match(c("plot", "write.file", "graphics.fmt", "engine"), names(pd), 0L)) > 0L)) pd <- pd[-i] if (length(i <- grep("^(f(i(le?)?)?)?$", names(pd))[-1L])) pd <- pd[-i] if (missing(size)) { size <- "" } else if (is.character(size)) { if (length(size) == 0 || !grepl("^\\d+x\\d+$", size[1])) stop("character argument 'size' must be in the form 'x'") size <- paste("&chs=", size, sep="") pd <- pd[-match("size", names(pd))] } else if (is.numeric(size)) { if (length(size) < 2) stop("numeric argument 'size' must have at least 2 elements") size <- paste("&chs=", size[1] * 96, "x", size[2] * 96, sep="") # 96 dpi } else { stop("type of argument 'size' is invalid") } pd[[1L]] <- as.name("path.diagram") sink(conn <- textConnection("dot", open="w", local=TRUE)) on.exit({ sink(); close(conn) }) eval(pd, parent.frame()) sink(); close(conn); on.exit() viz <- paste("http://chart.apis.google.com/chart?cht=gv%3A", engine, "&chof=", graphics.fmt, size, "&chl=", URLencode(paste(dot, collapse=""), reserved=TRUE), sep="") if (write.file) { filename <- if (is.null(file)) tempfile("plot.sem-") else file download.file(viz, filename, mode="wb", quiet=TRUE) if (is.null(file)) on.exit(unlink(filename)) if (plot) { if (!suppressPackageStartupMessages(require("rgdal"))) return(invisible(FALSE)) h <- GDAL.open(filename) if (is.null(file)) on.exit({ GDAL.close(h); unlink(filename) }) else on.exit(GDAL.close(h)) displayDataset(h) } } return(invisible(list(dot=paste(dot, collapse="\n"), request.url=viz, file=if (write.file) filename else NULL, graphics.fmt=graphics.fmt, path.diagram=pd))) }