Nothing
# ldheatmap - Plots measures of pairwise linkage disequilibria for SNPs
# Copyright (C) 2004 J.Shin, S. Blay, N. Lewin-Koh, J.Graham, B.McNeney
# To cite LDheatmap in publications use:
# Shin J-H, Blay S, McNeney B and Graham J (2006). LDheatmap: An R
# Function for Graphical Display of Pairwise Linkage Disequilibria
# Between Single Nucleotide Polymorphisms. J Stat Soft, 16 Code Snippet 3
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###########################################################################
#' @name LDheatmap
#' @aliases LDheatmap
#' @title This function produces a pairwise LD plot.
#' @description \code{LDheatmap()} is used to produce a graphical display, as a heat map,
#' of pairwise linkage disequilibrium (LD) measurements for SNPs.
#' The heat map is a false color image in the upper-left diagonal of a square plot.
#' Optionally, a line parallel to the diagonal of the image indicating
#' the physical or genetic map positions of the SNPs may be added, along
#' with text reporting the total length of the genomic region considered.
#'
#' @param hap R object of hapSummary or hapResult class.
#' @param gff annotations
#' @param Chr,start,end,geneID chromosome, start and end position, gene ID for
#' extract annotation in target range.
#' @param distances A character string to specify whether the provided map locations
#' are in physical or genetic distances.
#' If \code{distances = "physical"} (default), the text describing the total
#' length of the region will be \dQuote{Physical Length:XXkb} where XX is the
#' length of the region in kilobases. If \code{distances = "genetic"}, the
#' text will be \dQuote{Genetic Map Length:YYcM} where YY is
#' the length of the region in centiMorgans.
#' If \code{gdat} is an object of class LDheatmap,
#' \code{distances} is taken from \code{gdat}.
#'
#' @param LDmeasure A character string specifying the measure of LD
#' - either allelic correlation \eqn{r^2} or Lewontin's
#' |D\eqn{'}|; default = \code{"r"} for \eqn{r^2};
#' type \code{"D'"} for |D\eqn{'}|. This argument is ignored when the user has already
#' supplied calculated LD measurements through \code{gdat} (i.e., when \code{gdat}
#' is a matrix of pairwise LD measurements or an object of class \code{"LDheatmap"}).
#'
#' @param title A character string for the main title of the plot.
#' Default is \dQuote{Pairwise LD}.
#' @param add.map If \code{TRUE} (default) a diagonal line indicating
#' the physical or genetic map positions of the SNPs will be added to
#' the plot, along with text indicating the total length of the
#' genetic region.
#' @param map.height the height of gene map, default is 0.02
#' @param colorLegend If \code{TRUE} (default) the color legend is drawn.
#' @param geneMapLocation A numeric value specifying the position of the line
#' parallel to the diagonal of the matrix; the larger the value, the
#' farther it lies from the matrix diagonal. Ignored when \code{add.map = FALSE}.
#' @param geneMapLabelX A numeric value specifying the x-coordinate
#' of the text indicating the total length of the genomic region
#' being considered. Ignored when \code{add.map = FALSE}.
#' @param geneMapLabelY A numeric value specifying the y-coordinate
#' of the text indicating the total length of the genomic region
#' being considered. Ignored when \code{add.map = FALSE}.
#' @param color A range of colors to be used for drawing the heat map. Default
#' is \code{grDevices::colorRampPalette(c("red", "grey"))(30)}.
#' @param color_gmodel,color_snp,color_snpname the color of gene model and snp and snp names respectively, default as grey80.
#' @param cex_snpname the size of snp names/labels
#' @param newpage If \code{TRUE} (default), the heat map will be drawn on a new page.
#' @param name A character string specifying the name of the LDheatmap
#' graphical object (\code{grob}) to be produced.
#' @param SNP.name a logical vector indicated wherther display SNP names using positions.
#' @param vp.name A character string specifying the name of the viewport
#' @param snpmarks_height the height of snp marks, if set as NULL, nothing will display on gene model
#' where the heat map is going to be drawn.
#' @param pop If \code{TRUE}, the viewport where the heat map is drawn is
#' \code{pop}ped (i.e. removed) from the viewport tree after drawing.
#' Default = \code{FALSE}.
#' @param text If \code{TRUE}, the LD measurements are printed on each cell.
#' @importFrom genetics is.genotype LD nallele as.genotype
#' @details
#' The input object \code{gdat} can be a data frame of \code{genotype} objects
#' (a data structure from the \pkg{genetics} package), a \code{SnpMatrix} object
#' (a data structure from the \pkg{snpStats} package), or
#' any square matrix with values between 0 and 1 inclusive.
#' LD computation is much faster for \code{SnpMatrix} objects than for
#' \code{genotype} objects.
#' In the case of a matrix of LD values between 0 and 1,
#' the values above the diagonal will be plotted.
#' In the display of LD, SNPs appear in the order supplied by the
#' user as the horizontal and vertical coordinates are increased
#' and one moves along the off-diagonal line, from the bottom-left
#' to the top-right corner. To achieve this, the conventions of
#' the \code{image()} function have been adopted, in which horizontal
#' coordinates correspond to the rows of the matrix and vertical coordinates
#' correspond to columns, and vertical coordinates are indexed in increasing
#' order from bottom to top.
#' See the package vignette \code{LDheatmap} for more examples and details
#' of the implementation. Examples of adding ``tracks'' of genomic
#' annotation above a flipped heatmap are in the package vignette
#' \code{addTracks}.
#'
#'
#' @return An object of class \code{"LDheatmap"} which contains the following components:
#' \item{LDmatrix}{ The matrix of pairwise LD measurements plotted in the heat map. }
#' \item{LDheatmapGrob}{ A grid graphical object (grob) representing the produced heat map. }
#' \item{heatmapVP}{ The viewport in which the heat map is drawn. See \link[grid:viewport]{viewport}.}
#' \item{genetic.distances}{The vector of the supplied physical or
#' genetic map locations, or the vector of equispaced marker distances
#' when no distance vector is supplied.}
#' \item{distances}{ A character string specifying whether the provided map
#' distances are physical or genetic. }
#' \item{color}{ The range of colors used for drawing the heat map. }
#' The \code{grob} \code{LDheatmapGrob} has three \code{grob}s as its children (components).
#' They are listed below along with their own children and respectively represent
#' the color image with main title, genetic map and color key of the heat map:
#' \code{"heatMap"} - \code{"heatmap"}, \code{"title"};
#' \code{"geneMap"} - \code{"diagonal"}, \code{"segments"},
#' \code{"title"}, \code{"symbols"}, \code{"SNPnames"}; and
#' \code{"Key"} - \code{"colorKey"}, \code{"title"}, \code{"labels"},
#' \code{"ticks"}, \code{"box"}.
#'
#' @references Shin J-H, Blay S, McNeney B and Graham J (2006). LDheatmap:
#' An R Function for Graphical Display of Pairwise Linkage
#' Disequilibria Between Single Nucleotide Polymorphisms.
#' Journal of Statistical Software, \bold{16} Code Snippet 3
#'
#' @note The produced heat map can be modified in two ways.
#' First, it is possible to edit \emph{interactively} the grob components of the heat map,
#' by using the function \code{\link[grid:grid.edit]{grid.edit}};
#' the function will not work if there is no
#' open graphical device showing the heat map.
#' Alternatively, the user can use the function
#' \code{\link[grid:grid.edit]{editGrob}} and work with
#' the grob \code{LDheatmapGrob} returned by \code{LDheatmap}.
#' See Examples for usage.
#' \code{LDheatmap()} uses \code{\link[grid:Grid]{Grid}}, which
#' does not respond to \code{par()} settings.
#' Hence modifying \code{par()} settings of \code{mfrow} and \code{mfcol}
#' will not work with \code{LDheatmap()}. The Examples section shows how to
#' display multiple heat maps on one plot without the use
#' of \code{par()}.
#'
#'
#' @examples # Pass LDheatmap a SnpMatrix object
#' data(geneHapR_test)
#' plot_LDheatmap(hap = hapResult,
#' gff = gff,
#' Chr = hapResult[1,2],
#' start = 4000, end = 8200)
#' @export
plot_LDheatmap <- function (hap,
gff,
Chr,
start,
end,
geneID = NULL,
distances = "physical",
LDmeasure = "r",
title = "Pairwise LD",
add.map = TRUE,
map.height = 1,
colorLegend = TRUE,
geneMapLocation = 0.15,
geneMapLabelX = NULL,
geneMapLabelY = NULL,
SNP.name = TRUE,
color = NULL,
color_gmodel = "grey",
color_snp = "grey",
color_snpname = "grey40",
cex_snpname = 0.8,
snpmarks_height = NULL,
newpage = TRUE,
name = "ldheatmap",
vp.name = NULL,
pop = FALSE,
text = FALSE) {
# TO remove flip option
flip = TRUE
if (inherits(hap, "hapResult")) {
gdat <- data.frame(hap)
if(base::isFALSE(SNP.name)) SNP.name <- NULL else
if(isTRUE(SNP.name))
SNP.name <- t(hap[4, -c(1, ncol(hap))])[, 1]
genetic.distances <-
suppressWarnings(as.numeric(gdat[2, ])) %>%
na.omit()
gdat <- gdat[-c(1:4),-c(1, ncol(gdat))]
for (i in seq_len(ncol(gdat))) {
gdat[, i] <- sapply(gdat[, i],
function(x) {
if (stringr::str_detect(x, "[|]")) {
stringr::str_replace(x, "[|]", "/")
} else {
paste0(x, "/", x)
}
}) %>% unlist()
gdat[, i] <- genetics::as.genotype(gdat[, i])
}
} else
return("Use hapResult instead of hapSummary")
LDheatmap(
gdat,
gff = gff,
Chr = Chr,
start = start,
end = end,
geneID = geneID,
genetic.distances = genetic.distances,
distances = distances,
LDmeasure = LDmeasure,
title = title,
add.map = add.map,
map.height = map.height,
colorLegend = colorLegend,
geneMapLocation = geneMapLocation,
geneMapLabelX = geneMapLabelX,
geneMapLabelY = geneMapLabelY,
SNP.name = SNP.name,
color = color,
color_gmodel = color_gmodel,
color_snp = color_snp,
color_snpname = color_snpname,
cex_snpname = cex_snpname,
snpmarks_height = snpmarks_height,
newpage = newpage,
name = "ldheatmap",
vp.name = vp.name,
pop = pop,
flip = flip,
text = text
)
}
#' @import grid
#' @importFrom graphics plot.new
LDheatmap <- function (gdat,
gff,
Chr,
start,
end,
geneID,
genetic.distances = NULL,
distances = "physical",
LDmeasure = LDmeasure,
title = "Pairwise LD",
add.map = TRUE,
map.height = 0.02,
colorLegend = TRUE,
geneMapLocation = 0.15,
geneMapLabelX = NULL,
geneMapLabelY = NULL,
SNP.name = NULL,
color = NULL,
color_gmodel = color_gmodel,
color_snp = color_snp,
color_snpname = color_snpname,
cex_snpname = cex_snpname,
snpmarks_height = snpmarks_height,
newpage = TRUE,
name = "ldheatmap",
vp.name = NULL,
pop = FALSE,
flip = TRUE,
text = FALSE)
{
# requireNamespace("grid")
# Draw the Color Key
if (is.null(color)) {
color <- grDevices::colorRampPalette(c("red","blue", "grey20"))(30)
} else if (length(color) < 10) {
color <- grDevices::colorRampPalette(c(color))(30)
}
# adds a genetic map to the heatmap plot along the diagonal
# This part only identifies if the genemap will need to be flipped, does not do anything else yet
if (is.null(flip)) {
flip <- FALSE
}
## Calculate or extract LDmatrix, then stored in LDMatrix as an upper triangular matrix
# using a data.frame
if (inherits(gdat, "data.frame")) {
for (i in 1:ncol(gdat)) {
if (!genetics::is.genotype(gdat[, i]))
stop("column ", i, " is not a genotype object\n")
}
## Exclude SNPs with more or less than 2 alleles:
gvars <-
unlist(sapply(gdat, function(x)
genetics::nallele(x) == 2))
if (any(!gvars))
warning(
"Only bi-alleles supported,",
"Variables with less or more than 2 allels will be omitted."
)
if (sum(gvars) < 2)
stop("Variants number is less than two after removed non-bialleles")
genetic.distances <- genetic.distances[gvars]
gdat <- gdat[gvars]
## Sort data in ascending order of SNPs map position:
if (!is.vector(genetic.distances))
{
stop("Distance should be in the form of a vector")
}
o <- order(genetic.distances)
genetic.distances <- genetic.distances[o]
gdat <- gdat[, o]
myLD <- genetics::LD(gdat)
if (LDmeasure == "r")
LDmatrix <- myLD[[LDmeasure]] ^ 2
else
if (LDmeasure == "D'")
LDmatrix <- abs(myLD[[LDmeasure]])
else
stop("Invalid LD measurement, choose r or D'.")
}
## Draw the heat map
heatmapVP <-
grid::viewport(
width = unit(.8, "snpc"),
height = unit(.8, "snpc"),
name = vp.name
)
flipVP <-
grid::viewport(
width = unit(.8, "snpc"),
height = unit(.8, "snpc"),
y = 0.6,
angle = -45,
name = "flipVP"
)
# Colour selection scaling
if (color[1] == "blueToRed")
color = rainbow(20,
start = 4 / 6,
end = 0,
s = .7)[20:1]
if (newpage)
grid::grid.newpage()
mybreak <- 0:length(color) / length(color)
imgLDmatrix <- LDmatrix
# Flip or not, determines way data is read into the display
byrow <- ifelse(flip, FALSE, TRUE) #FALSE if flip = TRUE
colcut <-
as.character(cut(
1 - imgLDmatrix,
mybreak,
labels = as.character(color),
include.lowest = TRUE
))
# Determines if colour is done as an integer or as a colour code, updates accordingly
if (is.numeric(color))
colcut <- as.integer(colcut)
ImageRect <-
makeImageRect(dim(LDmatrix)[1], dim(LDmatrix)[2], colcut, name = "heatmap", byrow)
# Controls text placement
ImageText <- NULL
if (text)
ImageText <-
makeImageText(dim(LDmatrix)[1],
dim(LDmatrix)[2],
round(imgLDmatrix, digits = 2),
name = "heatmaptext")
title <-
grid::textGrob(title,
0.5,
1.05,
gp = grid::gpar(cex = 1.0),
name = "title")
if (flip) {
ImageRect <- grid::editGrob(ImageRect, vp = flipVP)
if (text) {
# Added flip = TRUE parameter to better utilize makeImageText() in the flipped case
ImageText <-
makeImageText(
dim(LDmatrix)[1],
dim(LDmatrix)[2],
round(imgLDmatrix, digits = 2),
name = "heatmaptext",
flip = TRUE
)
textVal <- ImageText
ImageText <-
grid::editGrob(
ImageText,
vp = flipVP,
rot = 0,
just = c("right", "top")
)
}
}
# Updates heatmap in the gTree
heatMap <-
grid::gTree(children = grid::gList(ImageRect, ImageText, title),
name = "heatMap")
# Draw a diagonal line indicating the physical or genetic map positions of the SNPs
nsnps <- ncol(LDmatrix)
step <- 1 / (nsnps - 1)
SNP.name <- names(SNP.name)
p <- paste0("X", SNP.name)
ind <- match(p, row.names(LDmatrix), nomatch = 0)
geneMapVP <- NULL
if (flip)
geneMapVP <- flipVP
geneMap <-
LDheatmapMapNew.add (
nsnps,
genetic.distances = genetic.distances,
geneMapLocation = geneMapLocation,
add.map = add.map,
geneMapLabelX = geneMapLabelX,
geneMapLabelY = geneMapLabelY,
distances = distances,
vp = geneMapVP,
SNP.name = SNP.name,
ind = ind,
color_gmodel = color_gmodel,
color_snp = color_snp,
color_snpname = color_snpname,
cex_snpname = cex_snpname,
snpmarks_height = snpmarks_height,
flip = flip,
gff = gff,
Chr = Chr,
start = start,
end = end,
geneID = geneID,
map.height = map.height
)
# Draw the Color Key
if (colorLegend)
Key <- LDheatmapLegend.add(color, LDmeasure, heatmapVP)
else
Key <- NULL
# Assemble the heatmap, genetic map and color key into a grob and draw it
LDheatmapGrob <- grid::gTree(
children = grid::gList(heatMap, geneMap, Key),
vp = heatmapVP,
name = name,
cl = "ldheatmap"
)
grid::grid.draw(LDheatmapGrob)
if (pop) {
grid::downViewport(heatmapVP$name)
grid::popViewport()
} #pop the heat map viewport
ldheatmap <-
list(
LDmatrix = LDmatrix,
LDheatmapGrob = LDheatmapGrob,
heatmapVP = heatmapVP,
flipVP = geneMapVP,
genetic.distances = genetic.distances,
distances = distances,
color = color
)
class(ldheatmap) <- "LDheatmap"
invisible(ldheatmap)
} # function LDheatmap ends
preDrawDetails.ldheatmap <- function(x) {
fontsize <-
grid::convertX(unit(1 / 20, "grobwidth", grid::rectGrob()), "points")
grid::pushViewport(grid::viewport(gp = grid::gpar(fontsize = fontsize)))
}
postDrawDetails.ldheatmap <- function(x) {
grid::popViewport()
}
preDrawDetails.symbols <- function(x) {
fontsize <-
grid::convertX(unit(1 / 20, "grobwidth", grid::rectGrob()), "points")
grid::pushViewport(grid::viewport(gp = grid::gpar(fontsize = fontsize)))
}
postDrawDetails.symbols <- function(x) {
grid::popViewport()
}
# Functions below are used in conjunction with LDHeatmap.R
# Provide supporting functionality for major function
makeImageRect <- function(nrow, ncol, cols, name, byrow = TRUE) {
xx <- (1:ncol) / ncol
yy <- (1:nrow) / nrow
# Creates coordinate pairs, repeating either column numbers (if byrow = TRUE) or row numbers (if byrow = FALSE) to force that type of fill
if (byrow) {
right <- rep(xx, nrow)
top <- rep(yy, each = ncol)
} else {
right <- rep(xx, each = nrow)
top <- rep(yy, ncol)
}
grid::rectGrob(
x = right,
y = top,
width = 1 / ncol,
height = 1 / nrow,
just = c("right", "top"),
gp = grid::gpar(col = NA, fill = cols),
name = name
)
}
makeImageText <- function(nrow, ncol, cols, name, flip = FALSE) {
cols <- as.character(cols)
cols[is.na(cols)] <- ""
cols <- paste(" ", cols)
xx <- (1:ncol) / ncol
yy <- (1:nrow) / nrow
# Need to fill cells in different order, as was done to generate image
if (flip) {
right <- rep(xx, each = nrow)
top <- rep(yy, ncol)
}
else{
right <- rep(xx, nrow)
top <- rep(yy, each = ncol)
}
grid::textGrob(
cols,
x = right,
y = top,
gp = grid::gpar(cex = 0.3),
just = c("right", "top"),
name = name
)
}
LDheatmapLegend.add <- function(color, LDmeasure, vp) {
ImageRect <-
makeImageRect(2, length(color), cols = c(rep(NA, length(color)), color[length(color):1]),
"colorKey")
keyVP <-
grid::viewport(
x = 1.1,
y = -.10,
height = .10,
width = .5,
just = c("right", "bottom"),
name = "keyVP"
)
#Adding the label 'Color key'
if (LDmeasure == "r") {
ttt <- expression(paste(R ^ 2, " Color Key"))
} else {
ttt <- "D' Color Key"
}
title <-
grid::textGrob(
ttt,
x = 0.5,
y = 1.25,
name = "title",
gp = grid::gpar(cex = 0.7)
)
#Adding labels to the color key
labels <-
grid::textGrob(
paste(0.2 * 0:5),
x = 0.2 * 0:5,
y = 0.25,
gp = grid::gpar(cex = 0.6),
name = "labels"
)
#Drawing ticks at the bottom axis of the color key
ticks <-
grid::segmentsGrob(
x0 = c(0:5) * 0.2 ,
y0 = rep(0.4, 6),
x1 = c(0:5) * 0.2 ,
y1 = rep(0.5, 6),
name = "ticks"
)
#Drawing a box around the color key
box <-
grid::linesGrob(
x = c(0, 0, 1, 1, 0),
y = c(0.5, 1, 1, 0.5, 0.5),
name = "box"
)
key <-
grid::gTree(
children = grid::gList(ImageRect, title, labels, ticks, box),
name = "Key",
vp = keyVP
)
key
}
LDheatmapMapNew.add <- function(nsnps,
add.map,
map.height = 0.02,
genetic.distances,
geneMapLocation = 0.15,
geneMapLabelX = NULL,
geneMapLabelY = NULL,
distances = "physical",
vp = NULL,
SNP.name = NULL,
ind = 0,
color_gmodel = color_gmodel,
color_snp = color_snp,
color_snpname = color_snpname,
cex_snpname = cex_snpname,
snpmarks_height = snpmarks_height,
flip = FALSE,
gff,
Chr,
start,
end,
geneID) {
snp <- ((1:nsnps - 1) + 0.5) / nsnps
#####################
if (add.map) {
# min.dist: the minimum coordinate of SNPs or start position
# max.dist: the maximum coordinate of SNPs or start position
# total.dist: the distance between min.dist and max.dist
if (missing(start) | missing(end)) {
min.dist <- min(genetic.distances)
max.dist <- max(genetic.distances)
} else{
min.dist <- min(genetic.distances, start, end)
max.dist <- max(genetic.distances, start, end)
}
total.dist <- max.dist - min.dist
if (flip)
geneMapLocation <-
(-geneMapLocation) # geneMapLocation gets flipped, reflects the gene bar
# Drawing the diagonal line
i <- 0.01
# seq.x <- c(0.5 * geneMapLocation + 1 / (nsnps * 2),
# 1 + 0.5 * geneMapLocation - 1 / (nsnps * 2))
# seq.y <- c(-0.5 * geneMapLocation + 1 / (nsnps * 2),
# 1 - 0.5 * geneMapLocation - 1 / (nsnps * 2))
seq.x <- c(0.5 * geneMapLocation + 1 / (nsnps * 2),
1 + 0.5 * geneMapLocation + 1 / (nsnps * 2))
seq.y <- c(-0.5 * geneMapLocation - 1 / (nsnps * 2),
1 - 0.5 * geneMapLocation - 1 / (nsnps * 2))
diagonal <-
grid::linesGrob(
seq.x,
seq.y,
gp = grid::gpar(lty = 1, col = color_snp),
name = "diagonal",
vp = vp
) # we draw the line with linesGrob, based on geneMapLocation seq
xs <- ys <- c()
w <- map.height
# the input dataset contains Chromosome name, annotations,
# and add the gene map/model
if (!missing(Chr) & !missing(gff) & add.map) {
gene <- GenomicRanges::GRanges(Chr,
IRanges::IRanges(start = min.dist,
end = max.dist))
gff <- gff[gff %over% gene]
type <- tolower(gff$type)
probe1 <-
stringr::str_detect(type, "cds") | stringr::str_detect(type, "utr")
gff <- gff[probe1]
if (!is.null(geneID)) {
ids <- tolower(gff$ID)
nms <- tolower(gff$Name)
geneID <- tolower(geneID)
probe2 <-
stringr::str_detect(nms, geneID) | stringr::str_detect(ids, geneID)
gff <- gff[probe2]
}
gff$Parent <- unlist(gff$Parent)
strand <- unique(gff@strand)[1]
ps <- unique(gff$Parent)
for (p in seq_len(length(ps))) {
# p: the number of transcripts
# w: the gene model height
# v: the relative height of CDS and non-CDS region
# x1,x1: the position of exon edge1
# x2,y2:the position of exon edge2
# r1,r2: the relative position on gene map
gffp <- gff[gff$Parent == ps[p]]
for (i in seq_len(length(gffp@ranges))) {
start <- gffp@ranges[i]@start
wid <- gffp@ranges[i]@width
end <- start + wid
r1 <- (start - min.dist) / total.dist
r2 <- (end - min.dist) / total.dist
x1 <- seq.x[1] + (seq.x[2] - seq.x[1]) * r1
x2 <- seq.x[1] + (seq.x[2] - seq.x[1]) * r2
y1 <- seq.y[1] + (seq.y[2] - seq.y[1]) * r1
y2 <- seq.y[1] + (seq.y[2] - seq.y[1]) * r2
if (stringr::str_detect(tolower(gff$type[i]), "cds"))
v <- 1
else
v <- 1 / 2
xsp <-
c(x1 - w * v, x1 + w * v, x2 + w * v, x2 - w * v) - w * (p * 3 - 1.5)
ysp <-
c(y1 + w * v, y1 - w * v, y2 - w * v, y2 + w * v) + w * (p * 3 - 1.5)
xs <- c(xs, xsp, NA)
ys <- c(ys, ysp, NA)
}
xsp <-
c(seq.x[1] - 0.002,
seq.x[1] + 0.002,
seq.x[2] + 0.002,
seq.x[2] - 0.002)
ysp <-
c(seq.y[1] + 0.002,
seq.y[1] - 0.002,
seq.y[2] - 0.002,
seq.y[2] + 0.002)
xs <- c(xs, NA, xsp - w * (p * 3 - 1.5), NA)
ys <- c(ys, NA, ysp + w * (p * 3 - 1.5), NA)
}
xs <- xs + 0.2 * geneMapLocation + 1 / (nsnps * 2)
ys <- ys - 0.2 * geneMapLocation - 1 / (nsnps * 2)
} else
gmodel <- NULL
## Adding line segments to the plot: (point1 <- > point2)
## point1: relative position of a SNP on the scaled line
## point2: position of that SNP on the LD image
regionx <- seq.x[1] +
((genetic.distances - min.dist) / total.dist) * (seq.x[2] -
seq.x[1])
regiony <- seq.y[1] +
((genetic.distances - min.dist) / total.dist) * (seq.y[2] -
seq.y[1])
## Adding the text indicating Physical length of the region under study
if (distances == "physical")
mapLabel <-
paste("Physical Length:", round((total.dist / 1000), 1),
"kb", sep = "")
else
mapLabel <-
paste("Genetic Map Length:", round(total.dist, 1), "cM", sep = "")
if (strand == "+")
mapLabel <- paste0(mapLabel, "\n5' -> 3'")
else
mapLabel <- paste0(mapLabel, "\n3' <- 5'")
if (!flip) {
if (is.null(geneMapLabelY))
geneMapLabelY <- 0.3
if (is.null(geneMapLabelX))
geneMapLabelX <- 0.5
}
else {
if (is.null(geneMapLabelY))
geneMapLabelY <- 0.8
if (is.null(geneMapLabelX))
geneMapLabelX <- 0.4
}
title <- grid::textGrob(
mapLabel,
geneMapLabelX - w * length(ps) * 4,
geneMapLabelY + w * length(ps) * 4,
gp = grid::gpar(cex = 0.9),
just = "left",
name = "title"
)
## Labelling some SNPs
if (!is.null(SNP.name) && (any(ind != 0))) {
if (flip) {
length_SNP_name <- max(nchar(SNP.name))
long_SNP_name <-
paste(rep(8, length_SNP_name), collapse = "")
name_gap <-
grid::convertWidth(grid::grobWidth(grid::textGrob(long_SNP_name)),
"npc",
valueOnly = TRUE)
diagonal <-
grid::linesGrob(
seq.x - name_gap,
seq.y + name_gap,
gp = grid::gpar(lty = 1),
name = "diagonal",
vp = vp
)
segments <-
segmentsGrob(
snp - name_gap,
snp + name_gap,
regionx - name_gap,
regiony + name_gap,
name = "segments",
vp = vp
)
## Adding SNP line segments to the plot: (point1 <- > point2)
## point1: relative position of a SNP on the scaled line
## point2: relative position of a SNP on the gene model
if(is.null(snpmarks_height))
snpmarks <- NULL else
snpmarks <-
grid::segmentsGrob(
x0 = regionx - name_gap,
y0 = regiony + name_gap,
x1 = regionx - w * (p * 3 + 2) - snpmarks_height,
y1 = regiony + w * (p * 3 + 2) + snpmarks_height,
name = "snpmarks",
vp = vp,
gp = gpar(col = color_snp)
)
############################################
# Bug: symbols was set to NULL here for some reason
symbols <- grid::pointsGrob(
snp[ind] - name_gap,
snp[ind] + name_gap,
pch = "",
gp = grid::gpar(
cex = 0.25,
bg = "blue",
col = "blue"
),
name = "symbols",
vp = vp
)
############################################
# Figure out exact necessary coefficient for regionx and regiony with name_gap
SNPnames <-
grid::textGrob(
SNP.name,
just = -0.1,
rot = -45,
snp[ind] - name_gap,
# the position of SNP names
snp[ind] + name_gap,
# the position of SNP names
gp = grid::gpar(cex = cex_snpname, col = color_snpname),
name = "SNPnames",
vp = vp
)
# Think of better reason to use the +0.5
# snp[ind], snp[ind], gp = grid::gpar(cex = 0.6, col = "blue"), name = "SNPnames", vp = vp)
title <-
grid::editGrob(title,
y = unit(geneMapLabelY + name_gap + 0.05, "npc"))
# gene model
if ((!is.null(xs)) & (!is.null(ys)))
gmodel <- grid::polygonGrob(
x = xs - name_gap,
y = ys + name_gap,
gp = gpar(fill = color_gmodel, lty = 0),
vp = vp
)
}
geneMap <-
grid::gTree(
children = grid::gList(
diagonal,
segments,
title,
gmodel,
snpmarks,
symbols,
SNPnames
),
name = "geneMap"
)
}
} else # if(add.map) end
# do not display gene model nor gene map
# but display only snp names
if (!add.map && !is.null(SNP.name) && (any(ind != 0))) {
geneMap <- grid::textGrob(
paste(" ", SNP.name),
just = "left",
rot = -45,
snp[ind] - name_gap,
snp[ind] + name_gap,
gp = grid::gpar(cex = cex_snpname, col = color_snpname),
name = "SNPnames"
)
if (flip)
geneMap <- grid::editGrob(geneMap, vp = vp)
} else
geneMap <- NULL
geneMap
}
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.