setGeneric("plot_splines_data",
function(object,data,...) { standardGeneric("plot_splines_data")})
#' Plotting splines
#'
#'@param data matrix containing the data to be plotted, where each row of the
#' data provided will be plotted as a separate plot. If missing, will rely on
#' data in \code{assay(object)}
#'@inheritParams DE_timecourse
#'@param colors vector, optional, default NULL. Vector of colors
#'@param smooth boolean, optional, default: FALSE. Whether to smooth the
#' centroids or not.
#'@param mar vector of margins to set the space around each plot (see
#' \code{\link{par}})
#'@param legend boolean whether to include a legend (default:TRUE)
#'@param legendArgs list of arguments to be passed to legend command (if
#' \code{legend=TRUE})
#'@param simpleY boolean, if true, will plot all genes on same y-axis and
#' minimize the annotation of the y axis to only label the axis in the exterior
#' plots (the x-axis is always assumed to be the same across all plots and will
#' always be simplified)
#'@param scale_centroid determines whether the centroid data given in
#' \code{centroid} should be rescaled to match that of the data
#' (\code{"toData"}), or the data scaled to match that of centroid
#' (\code{"toCentroid"}), or simply plotted as is (\code{"none"}).
#'@param subset_conditions list if provided, only plots the subset of conditions
#' provided. Else, plots all conditions
#'@param centroid numeric vector (or matrix of 1 row) with data to use to fit
#' the splines. If \code{NULL}, the splines plotted will be from the data.
#'@param subset_data list if provided, only plots the subset of data (ie, the
#' rows) provided. Can be any valid vector for subsetting a matrix. See
#' details.
#'@param mfrow a vector of integers of length 2 defining the grid of plots to be
#' created (see \code{\link{par}}). If missing, the function will set a value.
#'@param addToPlot A function that will be called after the plotting, allowing
#' the user to add more to the plot.
#'@param xlab label for the x-axis
#'@param ylab label for the y-axis
#' @param xaxis Logical, whether to add x-axis labels to plot (if FALSE can be manually created by user with call to addToPlot)
#' @param yaxis Logical, whether to add y-axis labels to plot (if FALSE can be manually created by user with call to addToPlot)
#'@param ... arguments to be passed to the individual plot commands (Will be
#' sent to all plot commands)
#' @details If \code{data} is NULL, the data plotted will be from
#' \code{assay(object)}, after log-transformation if
#' \code{log_transform(object)=TRUE}.
#' @details If \code{centroid} is missing, then splines will be estimated (per
#' group) for the the data in \code{data} -- separately for each row of
#' \code{data}. If \code{centroid} is provided, this data will be used to plot
#' a spline function, and this same spline will be plotted for each row of
#' \code{data}. This is useful, for example, in plotting cluster centroids
#' over a series of genes.
#' @details If the user set \code{log_transform=TRUE} in the creation of the
#' \code{Moanin} object, the data will be log transformed before plotting and
#' calculating the spline fits.
#'@return This function creates a plot and does not return anything to the user.
#' @examples
#' # First, load some data and create a moanin model
#' data(exampleData)
#' moanin <- create_moanin_model(data=testData,meta=testMeta,
#' degrees_of_freedom=6)
#'
#' # The moanin model contains all the information for plotting purposes. The
#' # plot_splines_data will automatically fit the splines from the
#' # information contained in the moanin model
#' genes <- c("NM_001042489", "NM_008725")
#' plot_splines_data(moanin, subset_data=genes,
#' mfrow=c(2, 2))
#' # By default, same axis for all genes. Can change with 'simpleY=FALSE'
#' plot_splines_data(moanin, subset_data=genes,
#' smooth=TRUE, mfrow=c(2,2), simpleY=FALSE)
#'
#' # The splines can also be smoothed
#' plot_splines_data(moanin, subset_data=genes,
#' smooth=TRUE, mfrow=c(2, 2))
#' # You can provide different data (on same subjects),
#' # instead of data in moanin object
#' # (in which case moanin just provides grouping information)
#' plot_splines_data(moanin, data=1/assay(moanin), subset_data=genes,
#' smooth=TRUE, mfrow=c(2, 2))
#'
#' # You can also provide data to use for fitting splines to argument
#' # "centroid". This is helpful for overlaying centroids or predicted data
#' # Here we do a silly example, just to demonstrate syntax,
#' # where we use the data from the first gene as our centroid to fit a
#' # spline estimate, but plot data from genes 3-4
#' plot_splines_data(moanin, centroid=assay(moanin[1,]), subset_data=3:4,
#' smooth=TRUE, mfrow=c(2,2))
#' @export
#' @name plot_splines_data
#' @aliases plot_splines_data,Moanin,matrix-method
#' @importFrom graphics axis plot.new plot.window
#' @importFrom methods new
#' @importFrom viridis viridis
setMethod("plot_splines_data",c("Moanin","matrix"),
function(object, data, colors=NULL, smooth=FALSE,
legend=TRUE, legendArgs=NULL,
subset_conditions=NULL,
subset_data=NULL,
simpleY=TRUE, centroid=NULL,
scale_centroid=c("toData","toCentroid","none"),
mar=c(2.5, 2.5, 3.0, 1.0),
mfrow=NULL, addToPlot=NULL, ylab="", xaxis=TRUE,
yaxis=TRUE, xlab="Time",...){
scale_centroid <- match.arg(scale_centroid)
check_data_meta(data=data,object=object)
if(!is.null(centroid)){
check_data_meta(data=centroid,object=object)
if(!is.null(dim(centroid)) && nrow(centroid)>1){
stop("Centroid must be a single vector (or matrix of 1 row) to data, for fitting the functional form")
}
}
if(!is.null(subset_data) ) data <- data[subset_data, ,drop=FALSE]
n_observations <- dim(data)[1]
### Work out the mfrow/number of plots and check makes sense
n_plots <- if(legend) n_observations+1 else n_observations
if(!is.null(mfrow)){
if(length(mfrow) != 2){
msg <- sprintf(
paste0("Invalid value for argument mfrow.",
"Should be a vector of length 2.",
"A vector of length %s was provided.", length(mfrow)))
stop(msg)
}
if(mfrow[1]*mfrow[2] < n_plots){
msg <- sprintf(
paste0(
"Invalid value for argument mfrow. Should result in ",
"grid for at least %s plots (including a plot for the ",
"legend, if legend=TRUE)"),
n_plots)
stop(msg)
}
}else{
if(n_plots <= 3){
mfrow <- c(n_plots, 1)
}else if(n_plots <= 6){
mfrow <- c(ceiling(n_plots / 2), 2)
}else if(n_plots <= 12){
mfrow <- c(ceiling(n_plots / 3), 3)
}else{
nrow <- round(n_plots ** 0.5)
ncol <- ceiling(n_plots / nrow)
mfrow=c(ncol, nrow)
}
}
graphics::par(mfrow=mfrow, mar=mar)
bottomPlots <- seq(to=n_observations, by=1, length=mfrow[2])
sidePlots <- seq(from=1, to=n_observations, by=mfrow[2])
## For legend:
if(is.null(colors)){
groups <- levels(group_variable(object))
colors <- viridis::viridis(length(groups))
names(colors) <- groups
}
plot_names <- row.names(data)
name <- NULL
if(!is.null(centroid)){
if(scale_centroid=="toData"){
centroid <- align_data_onto_centroid(data, centroid,
returnType="centroid")
}
if(scale_centroid=="toCentroid"){
data <- align_data_onto_centroid(data, centroid, returnType="data")
}
if(scale_centroid %in% c("toCentroid","none")){
#make it a matrix
centroid <- matrix(centroid, nrow=nrow(data),ncol=length(centroid),
byrow=TRUE)
}
}
## Fix up the y-axis range
if("ylim" %in% names(list(...))){
ylim <- list(...)$ylim
}
else ylim <- NULL
if(simpleY & is.null(ylim)){
# use same y-axis range
yrange <- range(data)
}
else{
if(!is.null(ylim)) yrange <- ylim
else yrange <- NULL
}
# Now plot the different data
for(i in seq_len(n_observations)){
if(!is.null(plot_names)){
name <- plot_names[i]
}
xaxt<-if(!i %in% bottomPlots & xaxis) "n" else "s"
if("xaxt" %in% names(list(...))) xaxt<-list(...)$xaxt
yaxt<-if(!i %in% bottomPlots & yaxis) "n" else "s"
if("yaxt" %in% names(list(...))) yaxt<-list(...)$yaxt
plot_centroid_individual(
data=data[i, ], centroid=if(is.null(centroid)) centroid else centroid[i,],
object[i,], colors=colors,
smooth=smooth,
subset_conditions=subset_conditions,
main=name, yrange=yrange,
xaxt=xaxt,
yaxt=yaxt,
xlab=xlab,ylab=ylab,...)
if(is.function(addToPlot)){
addToPlot()
}
if(!i %in% bottomPlots & xaxis){
axis(1, labels=FALSE)
}
if(!i %in% sidePlots & simpleY & yaxis){
axis(2, labels=FALSE)
}
}
if(legend){
plot.new()
plot.window(
xlim=c(0,1),
ylim=c(0,1),
bty="n",
xaxt="n",
yaxt="n")
if(!is.null(subset_conditions)){
colors <- colors[names(colors) %in% subset_conditions]
}
do.call(
"legend",
c(list(x="center",
legend=names(colors),
fill=colors, bty="n"),
legendArgs))
}
}
)
#' @aliases plot_splines_data,Moanin,numeric-method
#' @rdname plot_splines_data
#' @export
setMethod("plot_splines_data",c("Moanin","numeric"),
function(object, data, ...){
plot_splines_data(object,data=matrix(data,nrow=1),...)
}
)
#' @aliases plot_splines_data,Moanin,data.frame-method
#' @rdname plot_splines_data
#' @export
setMethod("plot_splines_data",c("Moanin","data.frame"),
function(object, data, ...){
plot_splines_data(object,data=data.matrix(data),...)
}
)
#' @aliases plot_splines_data,Moanin,DataFrame-method
#' @rdname plot_splines_data
#' @export
setMethod("plot_splines_data",c("Moanin","DataFrame"),
function(object, data, ...){
plot_splines_data(object,data=data.matrix(data),...)
}
)
#' @aliases plot_splines_data,Moanin,missing-method
#' @rdname plot_splines_data
#' @export
setMethod("plot_splines_data",c("Moanin","missing"),
function(object, data, ...){
data<-get_log_data(object)
plot_splines_data(object,data=data,...)
}
)
# centroid and data are vectors
# moanin_model will separate them into groups...
plot_centroid_individual <- function(data, centroid, moanin_model,
colors, smooth=FALSE,
subset_conditions=NULL,yrange=NULL,...){
if(is.null(data)){
data=as.vector(get_log_data(moanin_model))
}
if(is.null(centroid)) centroid<-data
if(!inherits(moanin_model,"Moanin"))
stop("Internal coding error: expecting Moanin class")
gpVar <- group_variable_name(moanin_model)
tpVar <- time_variable_name(moanin_model)
groups <- levels(group_variable(moanin_model))
if(!is.null(subset_conditions)){
if(!all(subset_conditions %in% groups)){
msg <- paste0(
"subset_conditions argument given by user does not match names",
" of groups.")
stop(msg)
}else{
groups <- subset_conditions
}
}
xrange <- range(time_variable(moanin_model))
if(inherits(centroid,"DataFrame")) centroid<-as.matrix(centroid)
if(is.null(dim(centroid))) centroid <- t(as.matrix(centroid))
if(is.null(yrange)){
yrangeCentroid <- range(centroid[, group_variable(moanin_model) %in% groups])
yrangeData <- range(data[group_variable(moanin_model) %in% groups])
yrange <- range(c(yrangeCentroid,yrangeData))
}
graphics::plot(xrange, yrange, type="n", ...)
if(smooth){
# FIXME this is supposed to be on the fitted lines, but I'm not able
# to get this to work fine in R.
meta_prediction <- create_meta_prediction(moanin_model)
centroid_fitted <- fit_predict_splines(
centroid, moanin_model,
meta_prediction=meta_prediction)
}else{
centroid_fitted <- fit_predict_splines(
centroid, moanin_model)
}
# scatter points for values
for(i in seq_along(groups)){
group <- groups[i]
color <- colors[group]
# Start by individual points
mask <- group_variable(moanin_model) == group
time <- time_variable(moanin_model)[mask]
indx <- order(time)
graphics::lines(time[indx], data[mask][indx], type="p",
col=color, pch=16,
lwd=0)
if(smooth){
mask <- meta_prediction[,gpVar] == group
time <- meta_prediction[,tpVar][mask]
indx <- order(time)
}
graphics::lines(time[indx], centroid_fitted[mask][indx], type="l",
col=color, lwd=1)
}
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.