I just added the method to fix some ancestral states during ML ancestral
state estimation for continuous characters that I used in
contMap
and previously described in
the
pages of this blog to the phytools function fastAnc.
Interested readers can look at the update
here,
and it can also be obtained by updating phytools from GitHub.
Here's a quick example for simulated data in which the internal states are known:
library(phytools)
## simulate a tree
tree<-pbtree(n=26,tip.label=LETTERS)
plotTree(tree)
## simulate data for tips & nodes
xa<-fastBM(tree,internal=TRUE)
a<-xa[as.character(1:tree$Nnode+Ntip(tree))]
a ## simulated ancestral states
## 27 28 29 30 31 32
## 0.00000000 -0.56601239 -0.14105673 -1.19661359 -1.66581973 -0.93686310
## 33 34 35 36 37 38
## -0.97710948 -2.14034585 -0.53578250 0.09301371 -0.46628240 -0.94499655
## 39 40 41 42 43 44
## -1.56438497 0.24762819 -2.29351327 -1.04066230 -1.40266486 -2.00346322
## 45 46 47 48 49 50
## 0.08526085 0.28998116 1.42932620 1.77921782 1.58183599 1.31419370
## 51
## -1.16905491
x<-xa[tree$tip.label] ## simulated tip data
x
## A B C D E F
## 0.5683050 -1.5702611 -0.6006650 -0.8855694 -2.3290004 -2.2543046
## G H I J K L
## 0.2865251 -0.7192771 -1.2468277 -1.5512149 0.1103867 0.5530111
## M N O P Q R
## -2.4353686 -2.5456411 -1.3246120 -0.7733470 -1.4208267 -0.1892435
## S T U V W X
## 0.6573859 1.3248485 1.7718648 1.9577381 1.3256986 0.9330483
## Y Z
## -1.5227223 -0.7031367
## visualize
obj<-contMap(tree,x,anc.states=a,plot=FALSE)
plot(obj)
Now let's proceed to estimate ancestral states - first with no known states, then with some, then (in the trivial case) with all:
## first with no internal state data
anc1<-fastAnc(tree,x,CI=TRUE)
anc1
## Ancestral character estimates using fastAnc:
## 27 28 29 30 31 32 33
## -0.458331 -0.555336 -0.531588 -0.613868 -0.944556 -1.006013 -1.299123
## 34 35 36 37 38 39 40
## -2.246533 -0.306729 -0.248593 -0.687350 -0.724508 -1.116524 -1.087959
## 41 42 43 44 45 46 47
## -2.407758 -0.965980 -1.127005 -1.085506 0.054002 0.370668 1.315666
## 48 49 50 51
## 1.616995 1.585510 1.231706 -0.886161
##
## Lower & upper 95% CIs:
## lower upper
## 27 -1.732581 0.815918
## 28 -1.618844 0.508172
## 29 -1.568306 0.505131
## 30 -1.680216 0.452481
## 31 -1.940270 0.051157
## 32 -1.984038 -0.027989
## 33 -2.253199 -0.345047
## 34 -2.587840 -1.905225
## 35 -1.420263 0.806805
## 36 -1.348681 0.851494
## 37 -1.331019 -0.043681
## 38 -1.280478 -0.168539
## 39 -1.587909 -0.645139
## 40 -2.170496 -0.005422
## 41 -2.909779 -1.905736
## 42 -1.978196 0.046235
## 43 -1.928715 -0.325295
## 44 -1.771882 -0.399130
## 45 -0.966783 1.074788
## 46 -0.593459 1.334794
## 47 0.864155 1.767176
## 48 1.310525 1.923465
## 49 1.317635 1.853386
## 50 0.829624 1.633787
## 51 -1.607091 -0.165230
## now with 8 (of 25) internal nodes known
anc.states<-sample(a,8)
anc.states
## 37 44 49 28 30 39
## -0.4662824 -2.0034632 1.5818360 -0.5660124 -1.1966136 -1.5643850
## 47 34
## 1.4293262 -2.1403459
anc2<-fastAnc(tree,x,CI=TRUE,anc.states=anc.states)
anc2
## Ancestral character estimates using fastAnc:
## 27 28 29 30 31 32 33
## -0.462569 -0.566012 -0.626395 -1.196614 -1.243811 -1.227162 -1.383056
## 34 35 36 37 38 39 40
## -2.140346 -0.324441 -0.199393 -0.466282 -0.779036 -1.564385 -1.262843
## 41 42 43 44 45 46 47
## -2.418075 -1.243738 -1.710369 -2.003463 0.083770 0.411412 1.429326
## 48 49 50 51
## 1.631835 1.581836 1.294140 -0.880376
##
## Lower & upper 95% CIs:
## lower upper
## 27 -1.419954 0.494815
## 28 -0.566012 -0.566012
## 29 -1.133676 -0.119115
## 30 -1.196614 -1.196614
## 31 -2.136108 -0.351515
## 32 -2.181969 -0.272355
## 33 -2.388912 -0.377201
## 34 -2.140346 -2.140346
## 35 -1.385475 0.736594
## 36 -1.326371 0.927585
## 37 -0.466282 -0.466282
## 38 -1.195829 -0.362243
## 39 -1.564385 -1.564385
## 40 -2.354270 -0.171416
## 41 -2.965873 -1.870277
## 42 -2.295524 -0.191951
## 43 -2.441551 -0.979187
## 44 -2.003463 -2.003463
## 45 -1.002757 1.170297
## 46 -0.615960 1.438785
## 47 1.429326 1.429326
## 48 1.379314 1.884356
## 49 1.581836 1.581836
## 50 0.948393 1.639887
## 51 -1.666475 -0.094277
It's probably worth noting that for any node with a fixed state the 95% CI has a width of zero - just as we'd expect.
Finally:
anc3<-fastAnc(tree,x,CI=TRUE,anc.states=a)
anc3
## Ancestral character estimates using fastAnc:
## 27 28 29 30 31 32 33
## 0.000000 -0.566012 -0.141057 -1.196614 -1.665820 -0.936863 -0.977109
## 34 35 36 37 38 39 40
## -2.140346 -0.535783 0.093014 -0.466282 -0.944997 -1.564385 0.247628
## 41 42 43 44 45 46 47
## -2.293513 -1.040662 -1.402665 -2.003463 0.085261 0.289981 1.429326
## 48 49 50 51
## 1.779218 1.581836 1.314194 -1.169055
##
## Lower & upper 95% CIs:
## lower upper
## 27 0.000000 0.000000
## 28 -0.566012 -0.566012
## 29 -0.141057 -0.141057
## 30 -1.196614 -1.196614
## 31 -1.665820 -1.665820
## 32 -0.936863 -0.936863
## 33 -0.977109 -0.977109
## 34 -2.140346 -2.140346
## 35 -0.535783 -0.535783
## 36 0.093014 0.093014
## 37 -0.466282 -0.466282
## 38 -0.944997 -0.944997
## 39 -1.564385 -1.564385
## 40 0.247628 0.247628
## 41 -2.293513 -2.293513
## 42 -1.040662 -1.040662
## 43 -1.402665 -1.402665
## 44 -2.003463 -2.003463
## 45 0.085261 0.085261
## 46 0.289981 0.289981
## 47 1.429326 1.429326
## 48 1.779218 1.779218
## 49 1.581836 1.581836
## 50 1.314194 1.314194
## 51 -1.169055 -1.169055
## now
plot(a,anc1$ace,xlab="true states",ylab="estimated states",
main="No internal nodes fixed") ## no internal node information
lines(c(min(par()$usr[c(1,3)]),max(par()$usr[c(2,4)])),
c(min(par()$usr[c(1,3)]),max(par()$usr[c(2,4)])),
lty="dashed") ## 1:1 line
plot(a,anc2$ace,xlab="true states",ylab="estimated states",
main="Some internal nodes fixed") ## some internal node information
lines(c(min(par()$usr[c(1,3)]),max(par()$usr[c(2,4)])),
c(min(par()$usr[c(1,3)]),max(par()$usr[c(2,4)])),
lty="dashed") ## 1:1 line
plot(a,anc3$ace,xlab="true states",ylab="estimated states",
main="All internal nodes fixed") ## all internal node information
lines(c(min(par()$usr[c(1,3)]),max(par()$usr[c(2,4)])),
c(min(par()$usr[c(1,3)]),max(par()$usr[c(2,4)])),
lty="dashed") ## 1:1 line
That's it.
No comments:
Post a Comment
Note: due to the very large amount of spam, all comments are now automatically submitted for moderation.