Nothing
#######################################################################
# #
# Package: onemap #
# #
# File: draw_map2.R #
# Contains: draw_map2 #
# #
# Written by Getulio Caixeta Ferreira #
# copyright (c) 2018, Getulio C Ferreira #
# #
# First version: 12/12/2018 #
# Last update: 12/12/2018 #
# License: GNU General Public License version 2 (June, 1991) or later #
# #
#######################################################################
##' Draw a linkage map
##'
##' Provides a simple draw of a linkage map.
##'
##'@importFrom graphics segments
##'@importFrom grDevices bmp dev.off jpeg pdf png postscript tiff
##'
##' @param ... map(s). Object(s) of class \code{sequence} and/or \code{data.frame}. If \code{data.frame}, it must have two columns: column 1: marker id; column 2: position (cM) (\code{numeric}).
##' @param tag name(s) of the marker(s) to highlight. If "all", all markers will be highlighted. Default is \code{NULL}.
##' @param id logical. If \code{TRUE} (default), shows name(s) of tagged marker(s).
##' @param pos logical. If \code{TRUE} (default), shows position(s) of tagged marker(s).
##' @param cex.label the magnification used for label(s) of tagged marker(s). If \code{NULL} (default), the cex will be automatically calculated to avoid overlapping.
##' @param main an overall title for the plot. Default is \code{NULL}.
##' @param group.names name(s) to identify the group(s). If \code{NULL} (default), the name(s) of the sequence(s) will be used.
##' @param centered logical. If \code{TRUE}, the group(s) will be aligned in the center. If \code{FALSE} (default), the group(s) will be aligned at the top.
##' @param y.axis logical. If \code{TRUE} (default), shows y axis. If centered = \code{TRUE}, the y axis will always be hidden.
##' @param space numerical. Spacing between groups. If \code{NULL} (default), the spacing will be automatically calculated to avoid overlapping.
##' @param col.group the color used for group(s).
##' @param col.mark the color used for marker(s).
##' @param col.tag the color used for highlighted marker(s) and its/theirs label(s).
##' @param output the name of the output file. The file format can be specified by adding its extension. Available formats: 'bmp', 'jpeg', 'png', 'tiff', 'pdf' and 'eps' (default).
##' @param verbose If \code{TRUE}, print tracing information.
##'
##' @return ggplot graphic with genetic map draw
##'
##' @author Getulio Caixeta Ferreira, \email{getulio.caifer@@gmail.com}
##' @keywords rqtl
##' @examples
##'
##' \donttest{
##' data("onemap_example_out")
##' twopt <- rf_2pts(onemap_example_out)
##' lg<-group(make_seq(twopt, "all"))
##' seq1<-make_seq(order_seq(input.seq= make_seq(lg,1),twopt.alg = "rcd"), "force")
##' seq2<-make_seq(order_seq(input.seq= make_seq(lg,2),twopt.alg = "rcd"), "force")
##' seq3<-make_seq(order_seq(input.seq= make_seq(lg,3),twopt.alg = "rcd"), "force")
##' draw_map2(seq1,seq2,seq3,tag = c("M1","M2","M3","M4","M5"),
##' output = paste0(tempfile(), ".png"))
##'
##' }
##'@export
draw_map2<-function(...,tag=NULL,id=TRUE,pos =TRUE,cex.label=NULL,
main=NULL,group.names=NULL,centered=FALSE,y.axis=TRUE,
space=NULL,col.group=NULL,col.mark=NULL,col.tag=NULL,output=NULL, verbose = TRUE){
#check input
input<-list(...)
if(length(input)==0) stop("argument '...' missing, with no default")
map.data<-list()
for(i in seq(input)) map.data<-c(map.data, if(inherits(input[[i]], "list")) input[[i]] else input[i])
if(!all(sapply(map.data, function(x) (inherits(x, c("sequence","data.frame")))))) stop(paste("\nObject '",seq(map.data)[!sapply(map.data, function(x) (inherits(x, c("sequence", "data.frame"))))],"' is not an object of class 'sequence' or 'data.frame",sep=""))
# reset par after exit
oldpar <- par(no.readonly = TRUE)
on.exit(par(oldpar))
#sequence to data.frame
for(i in seq_along(map.data)){
if(inherits(map.data[[i]], "sequence")){
if(is.character(map.data[[i]]$data.name)){
if (!map.data[[i]]$data.name %in% ls(.GlobalEnv)) stop(paste("Object data missing:", map.data[[i]]$data.name))
map.data[[i]]$data.name <- get(map.data[[i]]$data.name, envir = .GlobalEnv)
}
map.data[[i]] <- data.frame(marker=colnames(map.data[[i]]$data.name$geno)[map.data[[i]]$seq.num], pos=c(0,cumsum(kosambi(map.data[[i]]$seq.rf))), chr=i)
} else {map.data[[i]] <- cbind(map.data[[i]], chr=i)}
}
#check data.frame
for(i in seq_along(map.data)){
if(ncol(map.data[[i]]) != 3) stop(paste("\n", names(map.data)[i],"has incorrect number of columns."))
if(any(duplicated(map.data[[i]][,1]))) stop(paste("\n", names(map.data)[i],"has duplicated marker names."))
if(!is.numeric(map.data[[i]][,2])) stop(paste("\n", names(map.data)[i],", position column (2) must be numeric"))
colnames(map.data[[i]]) <- c("marker", "pos", "chr")
map.data[[i]]$marker <- as.character(map.data[[i]]$marker)
map.data[[i]] <- map.data[[i]][order(map.data[[i]]$pos),]
}
nchr<-length(map.data)
max.pos<-ceiling(max(do.call("rbind",map.data)$pos)/10)*10
for(i in seq_along(map.data))map.data[[i]]$coord<--map.data[[i]]$pos*100/max.pos
if(is.null(main)) main<-""
if(is.null(group.names)) group.names <- seq(map.data)
if(is.null(tag)) pos <- id <- FALSE
if("all"%in%tag) tag<-unique(unlist(lapply(map.data,function(x) x$marker),use.names = FALSE))
if(is.null(space)) space<-1+pos+id
if(centered==TRUE){
for(i in seq_along(map.data)){map.data[[i]]$coord<-map.data[[i]]$coord-(100+min(map.data[[i]]$coord))/2}
y.axis<-FALSE
}
if(y.axis==TRUE){
yl<-"Distance (cM)"
mleft<-5
} else {
yl<-""
mleft<-1
}
if(is.null(col.group)) col.group<-"grey85"
if(is.null(col.mark)) col.mark<-"#cc662f"
if(is.null(col.tag)) col.tag<-"#003350"
# Split output
if(is.null(output)){
output.dir <- tempdir()
output <- "map"
output.ext <- "eps"
} else {
output.dir <- dirname(output)
if(!dir.exists(output.dir)) stop("\nInvalid directory")
output <- basename(output)
}
if(length(grep("[.]", output)) > 0){
output.split <- unlist(strsplit(output, "[.]"))
output.ext <- output.split[length(output.split)]
output<-paste(output.split[1:(length(output.split)-1)],collapse = ".")
} else output.ext <- "eps"
if(!(output.ext %in% c("bmp","jpeg","png","tiff","pdf","eps"))){
output.ext<-"eps"
}
n<-0
if(paste(output,output.ext,sep = ".")%in%list.files(output.dir)){
repeat{
n<-n+1
output2<-paste(output,"(",n,")",sep = "")
if(paste(output2,output.ext,sep = ".")%in%list.files(output.dir)==FALSE){
output<-output2
break
}
}
}
# Preparing plot area
file_path <- file.path(output.dir, paste(output, paste0(".",output.ext),sep=""))
if(output.ext=="bmp"){
bmp(file_path,height = 15,width = nchr*(1+space)+(mleft+1)/2,res = 300,units = "cm")
} else if(output.ext=="jpeg"){
jpeg(file_path,height = 15,width = nchr*(1+space)+(mleft+1)/2,res = 300,units = "cm")
} else if(output.ext=="png"){
png(file_path,height = 15,width = nchr*(1+space)+(mleft+1)/2,res = 300,units = "cm")
} else if(output.ext=="tiff"){
tiff(file_path,height = 15,width = nchr*(1+space)+(mleft+1)/2,res = 300,units = "cm")
} else if(output.ext=="pdf"){
pdf(file_path,height = 15/2.54,width = (nchr*(1+space)+(mleft+1)/2)/2.54)
} else if(output.ext=="eps"){
postscript(file_path,height = 15/2.54,width = (nchr*(1+space)+(mleft+1)/2)/2.54,paper = "special",horizontal = FALSE,onefile = FALSE)
}
par(mar=c(1,mleft,2,1))
plot(NA,NA,xlim=c(0,nchr*(1+space)),ylim = c(-100,5),type = "n",axes = FALSE,ylab = yl,main=main)
text(seq((1+space)/2,(nchr-.5)*(1+space),1+space),5,group.names)
if(y.axis==TRUE){
axis(2,at=seq(0,-100, -1000/max.pos),labels = seq(0,max.pos, 10), las = 2)
}
#Drawing Group(s)
segments(seq((1+space)/2,(nchr-.5)*(1+space),1+space),tapply(do.call("rbind",map.data)$coord,do.call("rbind",map.data)$chr,max),
seq((1+space)/2,(nchr-.5)*(1+space),1+space),tapply(do.call("rbind",map.data)$coord,do.call("rbind",map.data)$chr,min),
lwd = 20,col = col.group)
segments((do.call("rbind",map.data)$chr-.5)*(1+space)-.25,do.call("rbind",map.data)$coord,
(do.call("rbind",map.data)$chr-.5)*(1+space)+.25,do.call("rbind",map.data)$coord,
lwd = 2,col = col.mark)
#Labeling
tag.data<-do.call("rbind",map.data)[do.call("rbind",map.data)$marker%in%tag,]
tag.data$coord2<-tag.data$coord
tag.data<-split(tag.data,tag.data$chr)
if(length(tag.data)>0){
if(is.null(cex.label)){
if(max(table(do.call("rbind",tag.data)$chr))<=30){cex.label<-1
} else{cex.label=30/max(table(do.call("rbind",tag.data)$chr))}
}
if(length(tag.data)>0){
dif.min<--floor(1000/3*cex.label)/100
for(i in seq_along(tag.data)){
if(nrow(tag.data[[i]])>30/cex.label){tag.data[[i]]$coord2<-seq(0,-100,-100/(nrow(tag.data[[i]])-1))
} else{
repeat{
dif<-round(diff(tag.data[[i]]$coord2),2)
over.dif.min<-c(dif>dif.min,FALSE)
if(TRUE%in%over.dif.min){
tag.data[[i]]$coord2[c(over.dif.min)]<-tag.data[[i]]$coord2[c(over.dif.min)]+(-dif.min+dif[over.dif.min])/2
tag.data[[i]]$coord2[c(FALSE,over.dif.min[-length(over.dif.min)])]<-tag.data[[i]]$coord2[c(FALSE,over.dif.min[-length(over.dif.min)])]-(-dif.min+dif[over.dif.min])/2
} else break
}
repeat{
if(TRUE%in%(tag.data[[i]]$coord2>0)){
dif<-round(diff(tag.data[[i]]$coord2),2)
over.dif.min<-(dif<dif.min)
next.spot<-(1:length(over.dif.min))[over.dif.min][1]
if(length(next.spot)==0){tag.data[[i]]$coord2<-tag.data[[i]]$coord2-tag.data[[i]]$coord2[1]
} else if(is.na(next.spot)){tag.data[[i]]$coord2<-tag.data[[i]]$coord2-tag.data[[i]]$coord2[1]
} else tag.data[[i]]$coord2[1:next.spot]<-tag.data[[i]]$coord2[1:next.spot]-min(c(tag.data[[i]]$coord2[1],dif.min-dif[next.spot]))
}
if(TRUE%in%(tag.data[[i]]$coord2>0)==FALSE) break
}
repeat{
if(TRUE%in%(tag.data[[i]]$coord2<(-100))){
dif<-round(diff(tag.data[[i]]$coord2),2)
over.dif.min<-(dif<dif.min)
next.spot<-(1:length(over.dif.min))[over.dif.min][length((1:length(over.dif.min))[over.dif.min])]+1
if(length(next.spot)==0){tag.data[[i]]$coord2<-tag.data[[i]]$coord2-100-tag.data[[i]]$coord2[length(tag.data[[i]]$coord2)]
} else if(is.na(next.spot)){tag.data[[i]]$coord2<-tag.data[[i]]$coord2-100-tag.data[[i]]$coord2[length(tag.data[[i]]$coord2)]
} else tag.data[[i]]$coord2[length(tag.data[[i]]$coord2):next.spot]<-tag.data[[i]]$coord2[length(tag.data[[i]]$coord2):next.spot]+min(c(-100-tag.data[[i]]$coord2[length(tag.data[[i]]$coord2)],dif.min-dif[next.spot-1]))
}
if(TRUE%in%(tag.data[[i]]$coord2<(-100))==FALSE) break
}
}
}
}
tag.data<-do.call("rbind",tag.data)
segments((tag.data$chr-.5)*(1+space)-.25,tag.data$coord,
(tag.data$chr-.5)*(1+space)+.25,tag.data$coord,lwd = 2,col = col.tag)
if(id==TRUE){
segments((tag.data$chr-.5)*(1+space)+.275,tag.data$coord,
(tag.data$chr-.5)*(1+space)+.5,tag.data$coord2,lwd = .5,col = col.tag)
text((tag.data$chr-.5)*(1+space)+.4,tag.data$coord2,
pos = 4,tag.data$marker,col = col.tag,cex = cex.label)
}
if(pos==TRUE){
segments((tag.data$chr-.5)*(1+space)-.275,tag.data$coord,
(tag.data$chr-.5)*(1+space)-.5,tag.data$coord2,lwd = .5,col = col.tag)
text((tag.data$chr-.5)*(1+space)-.4,tag.data$coord2,
pos = 2,round(tag.data$pos,1),col = col.tag,cex = cex.label)
}
}
dev.off()
if(verbose) {
cat("Completed\nOutput file: ")
cat(file_path)
}
}
##end of file
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.