liamrevell / phytools

GNU General Public License v3.0
207 stars 56 forks source link

object 'last_plot.phylo' not found & Error in seq.default(0, length = n) #79

Open Cactusolo opened 4 years ago

Cactusolo commented 4 years ago

Hi,

I have large tree and I plan to use arc.cladelabels function to highlight those bigger clades. My script worked smaller dataset, but when I used for larger dataset. The MAC gives error: Error in get("last_plot.phylo", envir = .PlotPhyloEnv) : object 'last_plot.phylo' not found

On Linux machine, it gives error:

Error in seq.default(0, length = n) : 'length.out' must be a non-negative number

Not sure, what's going wrong when scale up.

Thanks!

Miao

> packageVersion("phytools") [1] ‘0.7.70’

my script: r``` m(list=ls()) library("phytools") tree <- read.tree("./husge_phylogeny.tre") tree2 <- ladderize(tree) tree2 <- ips::fixNodes(tree2)

plotTree(tree2,type="fan", fsize=0.0002, xlim=c(-6.1,6.1), lwd =0.1) clade <- unique(sapply(strsplit(tree2$tip.label, "_"), "[", 1)) #clade coded in the tree tips color = grDevices::colors()[grep('gr(a|e)y', grDevices::colors(), invert = T)] colx <- sample(color, length(clade))

for(i in 1:length(clade)){ order <- clade[i] if(length(grep(order, tree2$tip.label))==1){ node <- grep(order, tree2$tip.label) arc.cladelabels(tree2, order, node=node, orientation="horizontal",ln.offset=1.02,lab.offset=0.9, mark.node=FALSE, cex=0.5)

print(paste(order, ",", node, sep=""))

}else{ node <- findMRCA(tree2, tree2$tip.label[grep(order, tree2$tip.label)])

print(paste(order, ",", node, sep=""))

arc.cladelabels(tree2, order, node, lwd=2, ln.offset=1.02, lab.offset=1.05, col=colx[i], cex=0.8)

} }

JakoboEU commented 2 years ago

I am getting the same error with a tree with 5000+ tips.

plot(cte, type="fan", outline=FALSE, fsize=c(0.01, 1), lwd = c(0.1, 1))
arc.cladelabels(text='Clade', node=19890, ln.offset=1.1, lab.offset=1.16)

The trace looks like

7.| stop("'length.out' must be a non-negative number")
6.| seq.default(0, length = n)
5.| seq(0, length = n)
4.| draw.arc.0(x = 0, y = 0, radius = 124.574682331, angle1 = -Inf, angle2 = Inf, n = 0.05, col = "black", lwd = 1, lend = "round")
3.| do.call("draw.arc.0", c(args[i, ], ...))
2.| draw.arc(x = 0, y = 0, radius = ln.offset * h, deg1 = min(deg), deg2 = max(deg), lwd = lwd, col = col, lend = lend, n = n)
1.| arc.cladelabels(text = "Clade", node = 19890, ln.offset = 1.1, lab.offset = 1.16)
JakoboEU commented 2 years ago

I copy and pasted the function from https://github.com/liamrevell/phytools/blob/6c9f388b9943dac0dc25bba4671bc563361c0e5f/R/utilities.R

The issue appears to be in this piece of code, I am afraid I am not the greatest R coder or debugger. It looks like deg has zero length.

d<-getDescendants(tree,node)
d<-sort(d[d<=Ntip(tree)])
deg<-atan(obj$yy[d]/obj$xx[d])*180/pi
ii<-intersect(which(obj$yy[d]>=0),which(obj$xx[d]<0))
deg[ii]<-180+deg[ii]
ii<-intersect(which(obj$yy[d]<0),which(obj$xx[d]<0))
deg[ii]<-180+deg[ii]
ii<-intersect(which(obj$yy[d]<0),which(obj$xx[d]>=0))
deg[ii]<-360+deg[ii]

draw.arc(x=0,y=0,radius=ln.offset*h,deg1=min(deg),deg2=max(deg),lwd=lwd,col=col,lend=lend,n=n)
Warning in min(deg) : no non-missing arguments to min; returning Inf
Warning in max(deg) : no non-missing arguments to max; returning -Inf
Warning in draw.arc.0(x = 0, y = 0, radius = 124.574682331, angle1 = -Inf,  :
  NAs introduced by coercion to integer range
Error in seq.default(0, length = n) : 
  'length.out' must be a non-negative number
JakoboEU commented 2 years ago

Managed to fix these with two changes.

  1. Make sure the tree is passed as an argument to arc.cladelabels
  2. Need to handle deg containing nulls. Therefore the calls to min, max, median, and range inside arc.cladelabels all need the na.rm = T argument.

Modified function to be:

library(plotrix)
arc.cladelabels.fixed <- function(tree=NULL,text,node=NULL,ln.offset=1.02,
    lab.offset=1.06,cex=1,orientation="curved",...){
    obj<-get("last_plot.phylo",envir=.PlotPhyloEnv)
    if(obj$type!="fan") stop("method works only for type=\"fan\"")
    h<-max(sqrt(obj$xx^2+obj$yy^2))
    if(hasArg(mark.node)) mark.node<-list(...)$mark.node
    else mark.node<-TRUE
    if(hasArg(interactive)) interactive<-list(...)$interactive
    else {
        if(is.null(node)) interactive<-TRUE
        else interactive<-FALSE
    }
    if(interactive) node<-getnode()
    if(hasArg(lwd)) lwd<-list(...)$lwd
    else lwd<-par()$lwd
    if(hasArg(col)) col<-list(...)$col
    else col<-par()$col
    if(hasArg(lend)) lend<-list(...)$lend
    else lend<-par()$lend
    if(hasArg(clockwise)) clockwise<-list(...)$clockwise
    else clockwise<-TRUE
    if(hasArg(n)) n<-list(...)$n
    else n<-0.05
    if(mark.node) points(obj$xx[node],obj$yy[node],pch=21,
        bg="red")
    if(is.null(tree)){
        tree<-list(edge=obj$edge,tip.label=1:obj$Ntip,
            Nnode=obj$Nnode)
        class(tree)<-"phylo"
    }
    d<-getDescendants(tree,node)
    d<-sort(d[d<=Ntip(tree)])

    deg<-atan(obj$yy[d]/obj$xx[d])*180/pi

    ii<-intersect(which(obj$yy[d]>=0),which(obj$xx[d]<0))
    deg[ii]<-180+deg[ii]

    ii<-intersect(which(obj$yy[d]<0),which(obj$xx[d]<0))
    deg[ii]<-180+deg[ii]

    ii<-intersect(which(obj$yy[d]<0),which(obj$xx[d]>=0))
    deg[ii]<-360+deg[ii]

    deg1 <- min(deg, na.rm = T)
    deg2 <- max(deg, na.rm = T)
    draw.arc(x=0,y=0,radius=ln.offset*h,deg1=deg1, deg2=deg2,lwd=lwd,col=col,lend=lend,n=n)

    if(orientation=="curved")
        arctext(text, radius=lab.offset*h, middle=mean(range(deg * pi/180, na.rm = T)), cex=cex, clockwise=clockwise)
    else if(orientation=="horizontal") {
      deg_med <- median(deg, na.rm = T)
        x0<-lab.offset * cos(deg_med*pi/180)*h
        y0<-lab.offset * sin(deg_med*pi/180)*h
        text(x=x0,y=y0,label=text,
        adj=c(if(x0>=0) 0 else 1,if(y0>=0) 0 else 1),
        offset=0,cex=cex)
    }
}

Then call this as:

plot(cte, type="fan", outline=FALSE, fsize=c(0.01, 1), lwd = c(0.1, 1))
arc.cladelabels.fixed(text = 'family', node = 19890, ln.offset=1.1, lab.offset=1.16, tree = tree, orientation="curved")