Nothing
################
# plot.QTLprof #
################
#' plot QTL profile
#'
#' Plots the -log10(p-val) profile of a QTL analysis or a genome-wide
#' genetic effect plot using package ggplot2.
#'
#' The user can plot regular QTL profiles (\code{gen.eff = FALSE}) with
#' -log10(p-val) plotted against genetic position or genome-wide genetic
#' effects plots (\code{gen.eff = TRUE}). To plot the genome-wide genetic
#' effects, the SIM and CIM QTL profile must have been computed with
#' \code{plot.gen.eff = TRUE}.
#'
#' The genome-wide genetic effects plots is a visualisation of the significance
#' of the QTL effect per cross or per parents along the genome. For a
#' cross-specific QTL profile (\code{Q.eff = "cr"}): Blue color means
#' that the allele coming from parent A(1) increases the phenotypic value and
#' parent B(2) decreases it and red that parent A(1) decreases the trait and
#' parent B(2) increases it.
#'
#' For a parental (\code{Q.eff = "par"}) or an ancestral model
#' (\code{Q.eff = "anc"}), the results are given per parents. The significance
#' of the effect must be interpreted as a deviation with respect to the
#' reference of each connected part. The reference allele is always defined as
#' the most frequent one. Blue (Red) colour means a signicative negative
#' (positive) effect with respect to the reference of the connected part.
#'
#' The reference parental allele can change at each position according to the
#' segregation rate. The parent are plotted from the top to the bottom according
#' to the number of time their allele is set as reference. Therefore
#' interpretation of the genetic effect plot should be done with caution.
#' In that case, the plot should be taken as a rough indication of the signal
#' distribution.
#'
#' The colour intensity increase with the significance of the effect (p-val).
#' The p-val are transformed into a color code (z). If p-val c [0.00001; 0.05]:
#' z = -log10(p-val). If p-val < 0.00001: z=6. This scale allows to plot
#' only the significant effects (p-val <= 0.05) and prevent the color scale to
#' be determine by highly significant values (p-val < 0.00001). The colours red
#' (positive) and blue (negative) correspond to the sign of the QTL effect.
#'
#' For both type of plot, the user can pass a list of cofactors or QTL position
#' to the argument \code{QTL}. These positions will be drawn on the graph using
#' dotted lines.
#'
#' @param x Object of class \code{QTLprof} returned by the function
#' \code{\link{mpp_SIM}} or \code{\link{mpp_CIM}}.
#'
#' @param gen.eff \code{Logical}. Specify the type of plot.
#' If \code{gen.eff = FALSE}, standard QTL profile. If \code{gen.eff = TRUE},
#' genome-wide genetic effect plot. In that case, the \code{QTLprof} object in
#' \code{x} must have been calculated with argument \code{plot.gen.eff = TRUE}.
#' Default = FALSE.
#'
#' @param mppData An object of class \code{mppData}. Only required if
#' \code{gen.eff = TRUE}.
#'
#' @param Q.eff \code{Character} expression indicating the assumption concerning
#' the QTL effects: 1) "cr" for cross-specific; 2) "par" for parental
#' effects; 3) "anc" for ancestral effects. Only required if
#' \code{gen.eff = TRUE}
#'
#' @param QTL Optional argument. List of QTL positions. Object of class
#' \code{QTLlist} representing a list of selected position obtained with the
#' function \code{\link{QTL_select}} or two columns numeric matrix with the
#' chromosome and the position in cM. These positions will be drawn on the
#' graph. Default = NULL.
#'
#' @param type \code{Character} expression indicating the type of plot should be
#' drawn: "l" for lines , "h" for vertical bar. Default = "l".
#'
#' @param main Title of the graph. Default = "QTL profile".
#'
#' @param threshold \code{Numeric} QTL significance threshold value draw on
#' the plot. Default = 3.
#'
#' @param text.size \code{Numeric} value specifying the size of graph axis text
#' elements. Default = 18.
#'
#' @param ... Ignored.
#'
#' @author Vincent Garin
#'
#' @seealso
#'
#' \code{\link{mpp_SIM}}, \code{\link{mpp_CIM}}, \code{\link{QTL_select}}
#'
#' @examples
#'
#' data(mppData)
#'
#' SIM <- mpp_SIM(mppData = mppData)
#' QTL <- QTL_select(SIM)
#' plot(x = SIM, QTL = QTL)
#'
#' SIM <- mpp_SIM(mppData = mppData, Q.eff = "cr", plot.gen.eff = TRUE)
#' QTL <- QTL_select(SIM)
#' plot(x = SIM, gen.eff = TRUE, mppData = mppData, Q.eff = "cr", QTL = QTL)
#'
#' @export
#'
plot.QTLprof <- function(x, gen.eff = FALSE, mppData, Q.eff, QTL = NULL,
type = "l", main = "QTL profile", threshold = 3,
text.size = 18, ...)
{
if(!inherits(x, "QTLprof")){stop("'x' is not of class ", dQuote("QTLprof"))}
if(!gen.eff){ # Regular QTL profile.
chr <- x$chr
pos.cM <- x$pos.cM
log10pval <- x$log10pval
Qprof <- data.frame(chr, pos.cM, log10pval)
# QTL positions
if(!is.null(QTL)){
if(inherits(QTL, "QTLlist")){
pos.Q <- QTL[, c(2, 4)]
} else{
if(!((is.matrix(QTL)) & (dim(QTL)[2] == 2) & (is.numeric(QTL)))){
stop("'QTL' must be a two columns numeric matrix with ",
"chromosome, and marker position")
}
pos.Q <- data.frame(QTL)
colnames(pos.Q) <- c("chr", "pos.cM")
}
}
if(is.null(QTL)){ # no QTL info given
if (type == "l") {
ggplot(Qprof, aes(x = pos.cM, y = log10pval, group = chr)) + geom_line() +
facet_wrap(nrow = 1, ~ chr, scales = "free_x") +
geom_hline(yintercept = threshold, colour = "red") + theme_bw() +
xlab("position [cM]") + ylab("-log10(p.val)") +
ggtitle(main) +
theme(axis.title.x = element_text(size=text.size),
axis.title.y = element_text(size=text.size),
axis.text.x = element_text(size=text.size),
axis.text.y = element_text(size = text.size),
plot.title = element_text(size=(text.size + 4)),
strip.text.x = element_text(size=text.size))
} else if (type == "h") {
ggplot(Qprof, aes(x = pos.cM, xend = pos.cM, y = 0, yend = log10pval,
group = chr)) + geom_segment() +
facet_wrap(nrow = 1, ~ chr, scales = "free_x") +
geom_hline(yintercept = threshold, colour = "red") +
theme_bw() + xlab("position [cM]") + ylab("-log10(p.val)") +
ggtitle(main) +
theme(axis.title.x = element_text(size=text.size),
axis.title.y = element_text(size=text.size),
axis.text.x = element_text(size=text.size),
axis.text.y = element_text(size = text.size),
plot.title = element_text(size=(text.size + 4)),
strip.text.x = element_text(size=text.size))
}
} else { # QTL info given
if (type == "l") {
ggplot(Qprof, aes(x = pos.cM, y = log10pval, group = chr)) + geom_line() +
facet_wrap(nrow = 1, ~ chr, scales = "free_x") +
geom_vline(aes(xintercept = pos.cM), pos.Q, linetype = "longdash",
colour = "black") +
geom_hline(yintercept = threshold, colour = "red") + theme_bw() +
xlab("position [cM]") + ylab("-log10(p.val)") +
ggtitle(main) +
theme(axis.title.x = element_text(size=text.size),
axis.title.y = element_text(size=text.size),
axis.text.x = element_text(size=text.size),
axis.text.y = element_text(size = text.size),
plot.title = element_text(size=(text.size + 4)),
strip.text.x = element_text(size=text.size))
} else if (type == "h") {
ggplot(Qprof, aes(x = pos.cM, xend = pos.cM, y = 0, yend = log10pval,
group = chr)) + geom_segment() +
facet_wrap(nrow = 1, ~ chr, scales = "free_x") +
geom_vline(aes(xintercept = pos.cM), pos.Q, linetype = "longdash",
colour = "black") +
geom_hline(yintercept = threshold, colour = "red") +
theme_bw() + xlab("position [cM]") + ylab("-log10(p.val)") +
ggtitle(main) +
theme(axis.title.x = element_text(size=text.size),
axis.title.y = element_text(size=text.size),
axis.text.x = element_text(size=text.size),
axis.text.y = element_text(size = text.size),
plot.title = element_text(size=(text.size + 4)),
strip.text.x = element_text(size=text.size))
}
}
} else { # Genome-wide genetic effect plot.
if(!(Q.eff %in% c("cr", "par", "anc"))){
stop("'Q.eff' must be ", dQuote("cr"), ', ', dQuote("par"), ', ',
dQuote("anc"), ' or ', dQuote("biall"))
}
n.eff <- dim(x)[2] - 5
if(n.eff == 0) {
stop("'x' does not contain any QTL p-value information. ",
"Use plot.gen.eff = TRUE, when you compute the QTL profile")
}
# 2. order columns within connected parts
#########################################
if((Q.eff == "par") || (Q.eff == "anc")){
# determine the connected parts
con.part <- design_connectivity(par_per_cross = mppData$par.per.cross,
plot_des = FALSE)
len.con <- unlist(lapply(X = con.part, FUN = function(x) length(x)))
con.part <- con.part[names(sort(len.con, decreasing = FALSE))]
allele_order <- c()
pval <- data.frame(row.names = 1:dim(x)[1])
ref.ind <- length(con.part) + 1
for(i in seq_along(con.part)){
con.part_i <- con.part[[i]]
# subset results of the connected part
pval_i <- x[, con.part_i]
# order according to number of reference values
all.ref <- apply(X = pval_i, MARGIN = 2,
FUN = function(x) sum(x == 1))
pval <- cbind.data.frame(pval, pval_i[, names(sort(all.ref))])
allele_ord_i <- names(sort(all.ref))
allele_ord_i <- c(paste(allele_ord_i, paste0("(c", (ref.ind-i),")"),
sep = "\n"))
allele_order <- c(allele_order, allele_ord_i)
}
# Rename x
x <- cbind(x[, 1:5], pval)
y.names <- allele_order
}
# 2. elements for the plot
##########################
### 2.1 list of QTL
if(!is.null(QTL)){
stopifnot(inherits(QTL, "QTLlist"))
pos.Q <- QTL[, c(2, 4)]
}
### 2.2 colour code from -5 red to 5 blue
z <- c(apply(X = x[, 6:dim(x)[2]], MARGIN = c(1, 2),
FUN = color.code))
### 2.3 cross or parent indicator and chromosome
y <- factor(rep(1:n.eff, each = dim(x)[1]))
chr <- rep(x$chr, n.eff)
### 2.4 genetic map positions in cM with width between two positions.
x.pos <- rep(x$pos.cM, n.eff)
w <- tapply(X = x$pos.cM, INDEX = x$chr,
FUN = function(x) c(diff(x), 1))
w <- unlist(w)
w <- rep(w, n.eff)
pos.cM <- x$pos.cM
y_lab <- "parents"
### 2.5 legend for the y-axis (cross or parents)
if(Q.eff == "cr") {
cross.names <- unique(mppData$cross.ind)
par.cross.names <- paste0("(", mppData$par.per.cross[, 2],
"x", mppData$par.per.cross[, 3], ")")
y.names <- paste(cross.names, par.cross.names, sep = "\n")
y_lab <- "crosses"
}
### 2.6 gather data for the plot
data <- data.frame(x.pos, y, z, chr, w)
# 3. plot
#########
if(is.null(QTL)){ # no QTL position given
pl <- ggplot(data, aes(x.pos, y, z = z))
pl + geom_tile(aes(fill = z, width = w)) +
facet_wrap(nrow = 1, ~ chr, scales = "free_x") +
scale_fill_gradient2(limits = c(-6, 6), low = "blue", mid = "white",
high = "red") +
theme_bw() + xlab("position [cM]") + ylab(y_lab) +
scale_y_discrete(labels = y.names) + ggtitle(main) +
theme(axis.title.x = element_text(size=text.size),
axis.title.y = element_text(size=text.size),
axis.text.x = element_text(size=text.size),
axis.text.y = element_text(size = text.size),
plot.title = element_text(size=(text.size+4)),
strip.text.x = element_text(size=text.size),
legend.title = element_text(size=(text.size-2)),
legend.text = element_text(size=(text.size-2)))
} else { # QTL position given
pl <- ggplot(data, aes(x.pos, y, z = z))
pl + geom_tile(aes(fill = z, width = w)) +
facet_wrap(nrow = 1, ~ chr, scales = "free_x") +
scale_fill_gradient2(limits = c(-6, 6), low = "blue", mid = "white",
high = "red") +
geom_vline(aes(xintercept = pos.cM), pos.Q, linetype = "longdash") +
theme_bw() + xlab("position [cM]") + ylab(y_lab) +
scale_y_discrete(labels = y.names) + ggtitle(main) +
theme(axis.title.x = element_text(size=text.size),
axis.title.y = element_text(size=text.size),
axis.text.x = element_text(size=text.size),
axis.text.y = element_text(size = text.size),
plot.title = element_text(size=(text.size+4)),
strip.text.x = element_text(size=text.size),
legend.title = element_text(size=(text.size-2)),
legend.text = element_text(size=(text.size-2)))
}
}
}
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.