@@ -21,6 +21,10 @@ as.phyloData <- function(phy, unscaled=FALSE) {
21
21
if (is.null(phy $ node.label )) {
22
22
phy $ node.label <- paste(" Node" , 1 : Nnode(phy ), sep = ' ' )
23
23
}
24
+ if (is.null(phy $ edge.length )) {
25
+ unscaled <- TRUE
26
+ phy $ edge.length <- rep(NA , nrow(phy $ edge ))
27
+ }
24
28
25
29
# convert edge attributes into data frame
26
30
edges <- data.frame (
@@ -526,7 +530,7 @@ lines.phyloLayout <- function(obj, col='grey50', shade=TRUE, ...) {
526
530
# ' @param ...: additional graphical parameters passed to `text`
527
531
# '
528
532
# ' @export
529
- text.phyloLayout <- function (obj , label = ' t' , align = FALSE , cex.lab = 1 , ... ) {
533
+ text.phyloLayout <- function (obj , label = ' t' , align = FALSE , cex.lab = 1 , offset = 0 , ... ) {
530
534
531
535
# filter node data frame
532
536
tips <- obj $ nodes [obj $ nodes $ n.tips == 0 , ]
@@ -538,8 +542,8 @@ text.phyloLayout <- function(obj, label='t', align=FALSE, cex.lab=1, ...) {
538
542
if (obj $ layout == ' rectangular' | obj $ layout == ' slanted' ) {
539
543
if (is.element(label , c(' t' , ' b' ))) {
540
544
# draw tip labels
541
- x <- tips $ x
542
- if (align ) { x <- max(tips $ x ) }
545
+ x <- tips $ x + offset
546
+ if (align ) { x <- max(tips $ x ) + offset }
543
547
text(x = x , y = tips $ y , labels = paste0(' ' , tips $ label ),
544
548
adj = 0 , cex = cex.lab , ... )
545
549
}
@@ -557,10 +561,11 @@ text.phyloLayout <- function(obj, label='t', align=FALSE, cex.lab=1, ...) {
557
561
558
562
# equal angle layout draws zero-angle straight up
559
563
if (obj $ layout == ' equal.angle' ) tip $ angle <- pi / 2 - tip $ angle
560
- tip <- .rotate.label(tip , cex.lab )
564
+ tip <- .rotate.label(tip , offset )
561
565
562
566
text(x = tip $ x , y = tip $ y , labels = tip $ label ,
563
- srt = tip $ angle / pi * 180 , adj = 0 , cex = cex.lab , ... )
567
+ srt = tip $ angle / pi * 180 , adj = as.integer(tip $ rotated ),
568
+ cex = cex.lab , ... )
564
569
}
565
570
}
566
571
if (is.element(label , c(' i' , ' b' ))) {
@@ -569,10 +574,11 @@ text.phyloLayout <- function(obj, label='t', align=FALSE, cex.lab=1, ...) {
569
574
node <- internals [i , ]
570
575
571
576
if (obj $ layout == ' equal.angle' ) node $ angle <- pi / 2 - node $ angle
572
- node <- .rotate.label(node , cex.lab )
577
+ node <- .rotate.label(node , offset )
573
578
574
579
text(x = node $ x , y = node $ y , labels = node $ label ,
575
- srt = node $ angle / pi * 180 , adj = 0 , cex = cex.lab , ... )
580
+ srt = node $ angle / pi * 180 , adj = as.integer(node $ rotated ),
581
+ cex = cex.lab , ... )
576
582
}
577
583
}
578
584
}
@@ -588,26 +594,28 @@ text.phyloLayout <- function(obj, label='t', align=FALSE, cex.lab=1, ...) {
588
594
# '
589
595
# ' @param node: named vector, a row from the nodes data frame of a
590
596
# ' `phyloLayout` object.
597
+ # ' @param offset: amount to push label outward from origin
598
+ # '
591
599
# ' @return a named vector with updated `x`, `y`, `angle` and `label` values
592
600
# '
593
601
# ' @keywords internal
594
- .rotate.label <- function (node , cex.lab ) {
602
+ .rotate.label <- function (node , offset ) {
603
+ # slide label outward
604
+ node $ x <- node $ x + offset * cos(node $ angle )
605
+ node $ y <- node $ y + offset * sin(node $ angle )
606
+
595
607
h <- node $ angle %% (2 * pi )
596
608
if (h > 0.5 * pi && h < (1.5 * pi )) {
597
- # slide label outward
598
- w <- strwidth(node $ label , units = ' user' ) * cex.lab
599
- node $ x <- node $ x + w * cos(node $ angle )
600
- node $ y <- node $ y + w * sin(node $ angle )
601
-
602
609
# invert the label
603
610
node $ angle <- node $ angle + pi
604
-
605
611
# pad the label on the right
606
612
node $ label <- paste0(node $ label , ' ' )
613
+ node $ rotated <- TRUE
607
614
}
608
615
else {
609
616
# pad the label on the left
610
617
node $ label <- paste0(' ' , node $ label )
618
+ node $ rotated <- FALSE
611
619
}
612
620
node
613
621
}
@@ -745,11 +753,9 @@ draw.guidelines <- function(obj, lty=3, ...) {
745
753
# ' Generic function for drawing a grid of coloured or grey-scale
746
754
# ' rectangles corresponding to values in a matrix `z`. Rows in
747
755
# ' the matrix are assumed to correspond to tips of the tree.
748
- # ' Only rectangular or slanted tree layouts are supported. If
749
- # ' you want to annotate a circular (radial) layout, use `ringplot`.
750
756
# '
751
757
# ' @param obj: an S3 object of class `phyloLayout`
752
- # ' @param z: matrix, data to annotate
758
+ # ' @param z: matrix, data to annotate tips in order of *nodes*
753
759
# ' @param xlim: horizontal range of grid relative to current plot device.
754
760
# ' Note this function will call `xpd=NA` to permit drawing
755
761
# ' in margins.
@@ -768,41 +774,60 @@ image.phyloLayout <- function(obj, z, xlim, col=NA, border='white', xaxt='y', ..
768
774
col <- colorRampPalette(c(' firebrick' , ' dodgerblue' ))(max(z , na.rm = T ))
769
775
}
770
776
771
- tips <- obj $ edges [obj $ edges $ isTip , ]
777
+ # tips <- obj$edges[obj$edges$isTip, ]
778
+ tips <- obj $ nodes [obj $ nodes $ n.tips == 0 , ]
772
779
773
780
# check that z has the expected dimensions
774
781
if (nrow(z ) != nrow(tips )) {
775
782
stop(" Number of rows in matrix `z` does not match number of tips " ,
776
783
" in `phyloLayout` object: " , nrow(z ), " !=" , nrow(tips ))
777
784
}
778
- y <- tips $ y1
779
- x <- seq(xlim [1 ], xlim [2 ], length.out = ncol(z )+ 1 )
780
- dx <- (x [2 ]- x [1 ])/ 2
781
785
786
+ # draw the image
782
787
par(xpd = NA )
783
- offset <- max(tips $ x1 ) + max(strwidth(obj $ nodes $ label ))
784
-
785
- for (j in 1 : ncol(z )) {
786
- for (i in 1 : nrow(z )) {
787
- val <- z [i ,j ]
788
- if (is.na(val )) next
789
- rect(xleft = x [j ], xright = x [j + 1 ],
790
- ybottom = y [i ]- 0.5 , ytop = y [i ]+ 0.5 ,
791
- border = border , col = col [val ])
788
+
789
+ if (obj $ layout == ' rectangular' | obj $ layout == ' slanted' ) {
790
+ y <- tips $ y
791
+ x <- seq(xlim [1 ], xlim [2 ], length.out = ncol(z )+ 1 )
792
+ dx <- (x [2 ]- x [1 ])/ 2
793
+
794
+ for (j in 1 : ncol(z )) {
795
+ for (i in 1 : nrow(z )) {
796
+ val <- z [i ,j ]
797
+ if (is.na(val )) next
798
+ rect(xleft = x [j ], xright = x [j + 1 ],
799
+ ybottom = y [i ]- 0.5 , ytop = y [i ]+ 0.5 ,
800
+ border = border , col = col [val ])
801
+ }
802
+ }
803
+
804
+ # draw axis (override masking of labels)
805
+ if (xaxt != ' n' ) {
806
+ odds <- seq(1 , ncol(z ), 2 )
807
+ evens <- odds + 1
808
+ suppressWarnings({
809
+ axis(side = 1 , at = x [1 : ncol(z )]+ dx , labels = NA , ... )
810
+ axis(side = 1 , at = x [odds ]+ dx , labels = names(geno )[odds ], lwd = 0 , ... )
811
+ axis(side = 1 , at = x [evens ]+ dx , labels = names(geno )[evens ], lwd = 0 , ... )
812
+ })
792
813
}
793
814
}
794
-
795
- # draw axis (override masking of labels)
796
- if (xaxt != ' n' ) {
797
- odds <- seq(1 , ncol(z ), 2 )
798
- evens <- odds + 1
799
- suppressWarnings({
800
- axis(side = 1 , at = x [1 : ncol(z )]+ dx , labels = NA , ... )
801
- axis(side = 1 , at = x [odds ]+ dx , labels = names(geno )[odds ], lwd = 0 , ... )
802
- axis(side = 1 , at = x [evens ]+ dx , labels = names(geno )[evens ], lwd = 0 , ... )
803
- })
815
+ else if (obj $ layout == ' radial' ) {
816
+ angles <- tips $ angle
817
+ d.theta <- pi / nrow(tips )
818
+ r <- seq(xlim [1 ], xlim [2 ], length.out = ncol(z )+ 1 )
819
+ dr <- (r [2 ]- r [1 ])/ 2
820
+
821
+ for (j in 1 : ncol(z )) {
822
+ for (i in 1 : nrow(z )) {
823
+ val <- z [i ,j ]
824
+ if (is.na(val )) next
825
+ draw.arc(x = 0 , y = 0 , theta0 = angles [i ]- d.theta ,
826
+ theta1 = angles [i ]+ d.theta , r0 = r [j ], r1 = r [j + 1 ],
827
+ col = col [val ], border = border )
828
+ }
829
+ }
804
830
}
805
-
806
831
par(xpd = FALSE )
807
832
}
808
833
0 commit comments