Skip to content

Instantly share code, notes, and snippets.

@nmatzke
Last active May 27, 2019 22:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nmatzke/a40dc1291115072889c81e416953edad to your computer and use it in GitHub Desktop.
Save nmatzke/a40dc1291115072889c81e416953edad to your computer and use it in GitHub Desktop.
require("ape")
# print tree in hierarchical format
#######################################################
# prt
#######################################################
#' Print tree in table format
#'
#' Learning and using APE's tree structure can be difficult and confusing because much of the information is
#' implicit. This function prints the entire
#' tree to a table, and makes much of the implicit information explicit. It is not particularly fast, but
#' it is useful.
#'
#' See \url{http://ape.mpl.ird.fr/ape_development.html} for the official documentation of R tree objects.
#'
#' @param t A \code{\link[ape]{phylo}} tree object.
#' @param printflag Should the table be printed to screen? Default TRUE.
#' @param relabel_nodes Manually renumber the internal nodes, if desired. Default FALSE.
#' @param time_bp_digits The number of digits to print in the time_bp (time before present) column. Default=7.
#' @param add_root_edge Should a root edge be added? Default \code{TRUE}.
#' @param get_tipnames Should the list of tipnames descending from each node be printed as a string in another column?
#' This is slow-ish, but useful for matching up nodes between differing trees. Default \code{FALSE}.
#' @param fossils_older_than Tips that are older than \code{fossils_older_than} will be marked as \code{TRUE} in a column called \code{fossil}.
#' @param silence_warnings Suppress warnings about missing branchlengths (prt makes each branchlength equal 1)
#' This is not currently set to 0, because Newick files can have slight precision issues etc. that mean not all tips quite come to zero. You
#' can attempt to fix this with \code{\link{average_tr_tips}} (but make sure you do not inappropriately average in fossils!!).
#' @return \code{dtf} A \code{\link[base]{data.frame}} holding the table. (Similar to the printout of a \code{\link[phylobase]{phylo4}} object.)
#' @export
#' @seealso \code{\link[ape]{phylo}}, \code{\link{average_tr_tips}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://ape.mpl.ird.fr/ape_development.html}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
#'
prt <- function(t, printflag=TRUE, relabel_nodes = FALSE, time_bp_digits=7, add_root_edge=TRUE, get_tipnames=FALSE, fossils_older_than=0.6, silence_warnings=FALSE)
{
defaults='
#wd = "/drives/GDrive/__classes/BIOSCI210/lab3_genome_size/"
#setwd(wd)
library(ape)
# Read a Newick-formatted phylogeny file (which has been subset to birds and mammals
# found in the table) to an APE tree object
#trfn = "birds_mammals_subset_tree.newick"
#tr = read.tree(trfn)
# Example tree string
trstr = "(((((Hsapiens:0.4,Hneander:0.4):4.6,Ardi:0.4):1.0,Pan:6.0):1.0,Gorilla:7.0):6.0,Pongo:13.0);"
tr = read.tree(file="", text=trstr)
trtable1 = prt(tr)
trtable2 = prt(t=tr, printflag=FALSE, relabel_nodes=TRUE, get_tipnames=TRUE, fossils_older_than=0.000001)
t = tr
printflag=TRUE;
relabel_nodes = FALSE;
time_bp_digits=7;
add_root_edge=TRUE;
get_tipnames=FALSE;
fossils_older_than=0.6
silence_warnings=FALSE
'
if (class(t) != "phylo")
{
txt = paste0("STOP ERROR IN prt(): the input 't' must be of class 'phylo'. You had class(t)='", class(t), "'.")
cat("\n\n")
cat(txt)
cat("\n\n")
stop(txt)
} # END if (class(t) != "phylo")
# assemble beginning table
# check if internal node labels exist
if ("node.label" %in% attributes(t)$names == FALSE)
{
rootnum = get_nodenum_structural_root(t)
new_node_labels = paste("inNode", rootnum:(rootnum+t$Nnode-1), sep="")
t$node.label = new_node_labels
}
# or manually relabel the internal nodes, if desired
if (relabel_nodes == TRUE)
{
rootnum = get_nodenum_structural_root(t)
new_node_labels = paste("inNode", rootnum:(rootnum+t$Nnode-1), sep="")
t$node.label = new_node_labels
}
labels = c(t$tip.label, t$node.label)
ordered_nodenames = get_nodenums(t)
#nodenums = 1:length(labels)
node.types1 = rep("tip", length(t$tip.label))
node.types2 = rep("internal", length(t$node.label))
node.types2[1] = "root"
node.types = c(node.types1, node.types2)
# These are the index numbers of the edges below each node
parent_branches = get_indices_where_list1_occurs_in_list2(ordered_nodenames, t$edge[,2])
# Error check for branchlengths
edgelength_NULL_warning = FALSE
if (is.null(t$edge.length))
{
edgelength_NULL_warning = TRUE
txt = paste0("\n\nWARNING: 'brlen_to_parent = t$edge.length[parent_branches]'...produced NULL as a result. This is probably a parsimony tree/cladogram with no branchlengths.\nprt() is inserting '1' for each branchlength. You may or may not want this. THESE ARE NOT REAL BRANCHLENGTHS AND NEITHER THE BRANCHLENGTHS NOR THE DERIVED 'TIMES' ETC SHOULD BE USED!!! You have been warned!\n\n")
if (silence_warnings == FALSE)
{
cat(txt)
}
t$edge.length =rep(1, times=length(parent_branches))
} # END if (is.null(brlen_to_parent))
#parent_edges = parent_branches
brlen_to_parent = t$edge.length[parent_branches]
parent_nodes = t$edge[,1][parent_branches]
daughter_nodes = lapply(ordered_nodenames, get_daughters, t)
# print out the structural root, if desired
root_nodenum = get_nodenum_structural_root(t)
tmpstr = paste("prt(t): root_nodenum=", root_nodenum, "\n", sep="")
prflag(tmpstr, printflag=printflag)
levels_for_nodes = unlist(lapply(ordered_nodenames, get_level, t))
#tmplevel = get_level(23, t)
#print(tmplevel)
#height above root
hts_at_end_of_branches_aka_at_nodes = t$edge.length
hts_at_end_of_branches_aka_at_nodes = get_all_node_ages(t)
h = hts_at_end_of_branches_aka_at_nodes
# times before present, below (ultrametric!) tips
# numbers are positive, i.e. in millions of years before present
# i.e. mybp, Ma
times_before_present = get_max_height_tree(t) - h
# fill in the ages of each node for the edges
edge_ages = t$edge
edge_ages[,1] = h[t$edge[,1]] # bottom of branch
edge_ages[,2] = h[t$edge[,2]] # top of branch
# fill in the times before present of each node for the edges
edge_times_bp = t$edge
edge_times_bp[,1] = times_before_present[t$edge[,1]] # bottom of branch
edge_times_bp[,2] = times_before_present[t$edge[,2]] # top of branch
# If desired, get the list of all tipnames descended from a node, in alphabetical order
if (get_tipnames == TRUE)
{
# Make the empty list
list_of_clade_members_lists = rep(list(NA), length(ordered_nodenames))
# Tips have only one descendant
list_of_clade_members_lists[1:length(t$tip.label)] = t$tip.label
list_of_clade_members_lists
nontip_nodenums = (length(t$tip.label)+1) : length(ordered_nodenames)
if (length(nontip_nodenums) > 1)
{
# More than 1 node
nontip_nodenames = ordered_nodenames[nontip_nodenums]
nontip_cladelists = sapply(X=nontip_nodenames, FUN=get_all_daughter_tips_of_a_node, t=t)
nontip_cladelists
nontip_cladelists_alphabetical = sapply(X=nontip_cladelists, FUN=sort)
nontip_cladelists_alphabetical
nontip_cladelists_alphabetical_str = sapply(X=nontip_cladelists_alphabetical, FUN=paste, collapse=",")
nontip_cladelists_alphabetical_str
# Store the results
list_of_clade_members_lists[nontip_nodenums] = nontip_cladelists_alphabetical_str
list_of_clade_members_lists
} else {
# Just one node
nontip_nodenames = ordered_nodenames[nontip_nodenums]
nontip_cladelists = sapply(X=nontip_nodenames, FUN=get_all_daughter_tips_of_a_node, t=t)
nontip_cladewords = unlist(sapply(X=nontip_cladelists, FUN=strsplit, split=","))
nontip_cladelists_alphabetical = sort(nontip_cladewords)
nontip_cladelists_alphabetical
nontip_cladelists_alphabetical_str = paste(nontip_cladelists_alphabetical, collapse=",", sep="")
nontip_cladelists_alphabetical_str
# Store the results
list_of_clade_members_lists[nontip_nodenums] = nontip_cladelists_alphabetical_str
list_of_clade_members_lists
}
}
# Add fossils TRUE/FALSE column. You can turn this off with fossils_older_than=NULL.
fossils = times_before_present > fossils_older_than
# Obviously, internal nodes are irrelevant and should be NA
tmpnodenums = (length(t$tip.label)+1) : ( length(t$tip.label) + t$Nnode )
fossils[tmpnodenums] = NA
if (get_tipnames == FALSE)
{
# Don't put in the list of clade names
tmpdtf = cbind(1:length(ordered_nodenames), ordered_nodenames, levels_for_nodes, node.types, parent_branches, brlen_to_parent, parent_nodes, daughter_nodes, h, times_before_present, fossils, labels)
dtf = as.data.frame(tmpdtf, row.names=NULL)
# nd = node
# edge.length is the same as brlen_2_parent
names(dtf) = c("node", "ord_ndname", "node_lvl", "node.type", "parent_br", "edge.length", "ancestor", "daughter_nds", "node_ht", "time_bp", "fossils", "label")
# convert the cols from class "list" to some natural class
dtf = unlist_dtf_cols(dtf, printflag=FALSE)
} else {
# Put in the list of clade names
tmpdtf = cbind(1:length(ordered_nodenames), ordered_nodenames, levels_for_nodes, node.types, parent_branches, brlen_to_parent, parent_nodes, daughter_nodes, h, round(times_before_present, digits=time_bp_digits), fossils, labels, list_of_clade_members_lists)
dtf = as.data.frame(tmpdtf, row.names=NULL)
# nd = node
# edge.length is the same as brlen_2_parent
#print(names(names(dtf)))
#print(c("node", "ord_ndname", "node_lvl", "node.type", "parent_br", "edge.length", "ancestor", "daughter_nds", "node_ht", "time_bp", "fossils", "label", "tipnames"))
names(dtf) = c("node", "ord_ndname", "node_lvl", "node.type", "parent_br", "edge.length", "ancestor", "daughter_nds", "node_ht", "time_bp", "fossils", "label", "tipnames")
# convert the cols from class "list" to some natural class
dtf = unlist_dtf_cols(dtf, printflag=FALSE)
}
# Add the root edge, if desired
# (AND, only if t$root.edge exists)
if ( (add_root_edge == TRUE) && (!is.null(t$root.edge)) )
{
root_row_TF = dtf$node.type == "root"
root_edge_length = t$root.edge
# Stick in this edge length
dtf$edge.length[root_row_TF] = root_edge_length
# Add the root edge length to all node heights
dtf$node_ht = dtf$node_ht + root_edge_length
}
# print if desired
prflag(dtf, printflag=printflag)
if ((edgelength_NULL_warning == TRUE) && (printflag == TRUE))
{
txt = paste0("\n\nWARNING: 'brlen_to_parent = t$edge.length[parent_branches]'...produced NULL as a result. This is probably a parsimony tree/cladogram with no branchlengths.\nprt() is inserting '1' for each branchlength. You may or may not want this. THESE ARE NOT REAL BRANCHLENGTHS AND NEITHER THE BRANCHLENGTHS NOR THE DERIVED 'TIMES' ETC SHOULD BE USED!!! You have been warned!\n\n")
if (silence_warnings == FALSE)
{
cat(txt)
}
} # END if (edgelength_NULL_warning == TRUE)
#tree_strings = c()
#root_str = get_node_info(root_nodenum, t)
return(dtf)
} # END prt()
#######################################################
# unlist_dtf_cols
#######################################################
#' Unlist the columns in a data.frame
#'
#' Utility function. What it says.
#'
#' @param dtf Input \code{\link[base]{data.frame}}
#' @param printflag Print the results if TRUE.
#' @return \code{dtf} The data.frame, hopefully without lists for columns
#' @export
#' @seealso \code{\link[base]{unlist}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' \url{https://code.google.com/p/lagrange/}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
unlist_dtf_cols <- function(dtf, printflag=FALSE)
{
# Sometimes cbind makes each column a list, this can screw up use/searching of
# the column later on.
# Unlist each column...
for (i in 1:ncol(dtf))
{
tmpstr = paste("unlisting col: ", names(dtf)[i], "...", sep="")
prflag(tmpstr, printflag=printflag)
# catch a possible error from unlisting
# the number of rows needs to stay the same!!
tmpcol = unlist(dtf[, i])
if (length(tmpcol) != length(dtf[, i]))
{
tmpstr = paste("...failed! unlist(col) length=", length(tmpcol), "; nrow(dtf) = ", nrow(dtf), sep="")
prflag(tmpstr, printflag=printflag)
}
else
{
dtf[, i] = tmpcol
tmpstr = paste(" ", " ", sep="")
prflag(tmpstr, printflag=printflag)
}
}
#dtf2 = adf(dtf)
return(dtf)
}
# NOTE!!! THESE MATCH FUNCTIONS JUST RETURN THE *FIRST* MATCH, *NOT* ALL MATCHES
# (argh)
# return indices in 2nd list matching the first list
# It WILL return one match for each item in the list, though...
#######################################################
# get_indices_where_list1_occurs_in_list2
#######################################################
#' Return (first!) indices in second list matching the first list
#'
#' This function will return one match (the first) for each item in the list; i.e. the second-list
#' index for each item in the first list. Only the first hit in the second list is returned.
#'
#' This is used by \code{\link{prt}}.
#'
#' @param list1 The first list.
#' @param list2 The second list list.
#' @return \code{match_indices} The match indices.
#' @export
#' @seealso \code{\link{prt}}, \code{\link[base]{LETTERS}}, \code{\link{get_indices_where_list1_occurs_in_list2_noNA}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' list1 = c("N", "I", "C", "K")
#' list2 = LETTERS
#' get_indices_where_list1_occurs_in_list2(list1, list2)
get_indices_where_list1_occurs_in_list2 <- function(list1, list2)
{
match_indices = match(list1, list2)
return(match_indices)
}
#######################################################
# get_nodenums
#######################################################
#' Get the unique node numbers in a tree
#'
#' This is a utility function for \code{\link{get_nodenum_structural_root}}.
#'
#' @param t A tree object in \code{\link[ape]{phylo}} format.
#' @return \code{ordered_nodenames} The node numbers, in order.
#' @export
#' @seealso \code{\link[ape]{phylo}}, \code{\link{get_nodenum_structural_root}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' blah = 1
# this returns the NUMBERS identifying each node
get_nodenums <- function(t)
{
# get just the unique node numbers from the edge list (left column: start node; right column: end node):
nodenames = unique(c(t$edge))
ordered_nodenames = nodenames[order(nodenames)]
return(ordered_nodenames)
}
#######################################################
# get_nodenum_structural_root
#######################################################
#' Gets the root node
#'
#' This function gets the root node by finding the node not in the descendants list (edge[,2]). This
#' may be more reliable than e.g. assuming length(tr$tip.label)+1.
#'
#' @param t A tree object in \code{\link[ape]{phylo}} format.
#' @param print_nodenum Print the node numbers as you go through the list? Default FALSE.
#' @return \code{root_nodenums_list}
#' @export
#' @seealso \code{\link[ape]{phylo}}, \code{\link{get_nodenums}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' blah=1
#'
get_nodenum_structural_root <- function(t, print_nodenum=FALSE)
{
#numnodes = length(t$tip.label) + length(t$node.label)
#ordered_nodes = 1:length(numnodes)
ordered_nodes = get_nodenums(t)
root_nodenums_list = c()
for (n in 1:length(ordered_nodes))
{
tmpnode = ordered_nodes[n]
if (tmpnode %in% t$edge[,2])
{
blah = TRUE
}
else
{
if (print_nodenum == TRUE)
{
cat("get_nodenum_structural_root(): Root nodenum = ", tmpnode, sep="")
}
root_nodenums_list = c(root_nodenums_list, tmpnode)
}
}
return(root_nodenums_list)
}
#######################################################
# get_all_node_ages
#######################################################
#' Get the ages of all the nodes in the tree (above the root)
#'
#' A utility function. Use of \code{\link[ape]{dist.nodes}} may be slow.
#'
#' @param obj An ape phylo object
#' @return \code{TF_tips} The age (from the root) of each node.
#' @export
#' @seealso \code{\link{prt}}, \code{\link{chainsaw2}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
get_all_node_ages <- function(obj)
{
node_ages = dist.nodes(obj)[get_nodenum_structural_root(obj), ]
return(node_ages)
}
#######################################################
# get_daughters
#######################################################
#' Get all the direct daughters nodes of a node
#'
#' @param nodenum The node number to get the daughters of
#' @param t An ape phylo object
#' @return \code{daughter_nodenums} List of the daughter node numbers
#' @export
#' @seealso \code{\link{findall}}, \code{\link{chainsaw2}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
get_daughters <- function(nodenum, t)
{
daughter_edgenums = findall(nodenum, t$edge[,1])
daughter_nodenums = t$edge[,2][daughter_edgenums]
return(daughter_nodenums)
}
# Get indices of all matches to a list
#######################################################
# findall
#######################################################
#' Get indices of all matches to a list
#'
#' Just a handy shortcut function
#'
#' @param what The item to find
#' @param inlist The list to search in
#' @return \code{matching_indices} List of the matching indices
#' @export
#' @seealso \code{\link{get_daughters}}, \code{\link{chainsaw2}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
findall <- function(what, inlist)
{
TFmatches = inlist == what
indices = 1:length(inlist)
matching_indices = indices[TFmatches]
return(matching_indices)
}
#######################################################
# prflag
#######################################################
#' Utility function to conditionally print intermediate results
#'
#' Just a handy shortcut function, allowing other functions to optionally
#' print, depending on the value of \code{printflag}.
#'
#' @param x What to print.
#' @param printflag If TRUE, do the printing
#' @return nothing
#' @export
#' @seealso \code{\link{get_daughters}}, \code{\link{chainsaw2}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
prflag <- function(x, printflag=TRUE)
{
# A standard function to print (or not) certain variables,
# based on a master printflag
# This avoids having to comment in/out various code chunks
# while debugging.
if (printflag == TRUE)
{
# CAT instead of PRINT if it's a string or numeric
if (is.character(x))
{
cat(x, "\n", sep="")
}
if (is.numeric(x))
{
cat(x, "\n", sep="")
} else {
print(x)
}
}
else
{
pass="BLAH"
}
}
#######################################################
# get_level
#######################################################
#' Get a node's level in the tree
#'
#' Finds how many nodes deep a node is.
#'
#' @param nodenum The node number to get the parent of
#' @param t An ape phylo object
#' @param tmplevel A starting level (the function is recursive)
#' @return \code{tmplevel} The level of the node.
#' @export
#' @seealso \code{\link{prt}}, \code{\link{chainsaw2}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
get_level <- function(nodenum, t, tmplevel=0)
{
parent_nodenum = get_parent(nodenum, t)
if (is.na(parent_nodenum))
{
#tmplevel = 0
return(tmplevel)
}
else
{
#print(paste("parent_nodenum: ", parent_nodenum, " level: ", tmplevel, sep=""))
tmplevel = tmplevel + 1
tmplevel = get_level(parent_nodenum, t, tmplevel)
return(tmplevel)
}
# If an error occurs
return(NA)
}
#######################################################
# get_parent
#######################################################
#' Get the direct parent node of a node
#'
#' @param nodenum The node number to get the parent of
#' @param t An ape phylo object
#' @return \code{parent_nodenum}The parent node number
#' @export
#' @seealso \code{\link{findall}}, \code{\link{chainsaw2}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
get_parent <- function(nodenum, t)
{
matching_edges = findall(nodenum, t$edge[,2])
parent_nodenum = t$edge[,1][matching_edges][1]
return(parent_nodenum)
}
#######################################################
# get_max_height_tree
#######################################################
#' Get the maximum age of all the nodes (above the root)
#'
#' I.e., the distance of the highest node above the root. A utility function.
#' Use of \code{\link[ape]{dist.nodes}} may be slow.
#'
#' @param obj An ape phylo object
#' @return \code{max_height} The age (from the root) of the highest node.
#' @export
#' @seealso \code{\link{prt}}, \code{\link{chainsaw2}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
get_max_height_tree <- function(obj)
{
max_height = max(get_node_ages_of_tips(obj))
return(max_height)
}
#######################################################
# get_node_ages_of_tips
#######################################################
#' Get the ages of each tip above the root
#'
#' A utility function.
#'
#' @param obj An ape phylo object
#' @return \code{TF_tips} The age (from the root) of each tip.
#' @export
#' @seealso \code{\link{prt}}, \code{\link{chainsaw2}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
get_node_ages_of_tips <- function(obj)
{
TF_tips = get_TF_tips(obj)
root_node_num = get_nodenum_structural_root(obj)
dists_from_root = dist.nodes(obj)[root_node_num, ]
node_ages_of_tips = dists_from_root[TF_tips]
return(node_ages_of_tips)
}
#######################################################
# get_TF_tips
#######################################################
#' Get TRUE/FALSE for nodes being tips
#'
#' A utility function that returns \code{TRUE}/\code{FALSE} for whether or not each node is a tip.
#'
#' @param obj An ape phylo object
#' @return \code{TF_tips} The \code{TRUE}/\code{FALSE} list for each tip.
#' @export
#' @seealso \code{\link{prt}}, \code{\link{chainsaw2}}, \code{\link{match_list1_in_list2}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
get_TF_tips <- function(obj)
{
# Get TF for nodes being tips
# BIG CHANGE?
#TF_tips = match_list1_in_list2(1:length(dists_from_root), obj$tip.label)
TF_tips = match_list1_in_list2(1:length(obj$edge), 1:length(obj$tip.label))
#TF_tips = obj$tip.label[TF_tips_indices]
return(TF_tips)
}
# return matching TRUE/FALSE values
# list1 (.e.g. a big list) TRUE if it is found in list2 (e.g. a smaller list)
#######################################################
# match_list1_in_list2
#######################################################
#' Return TRUE for list1 items when they occur in list2
#'
#' Return matching TRUE/FALSE values. E.g. list1 (e.g. a big list) TRUE if it is found
#' in list2 (e.g. a smaller list)
#'
#' Utility function for %in%, when one's brain gets confused.
#'
#' @param list1 The list of things you want to check
#' @param list2 The list of things you want to check against
#' @return \code{matchlist} The TRUE/FALSE list for list1
#' @export
#' @seealso \code{\link[base]{match}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' \url{https://code.google.com/p/lagrange/}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
match_list1_in_list2 <- function(list1, list2)
{
matchlist = list1 %in% list2
return(matchlist)
}
#######################################################
# get_all_daughter_tips_of_a_node
#######################################################
#' Get all the daughter tips of a node
#'
#' Like it says. Utility function.
#'
#' @param nodenum The node to find
#' @param t A \code{\link[ape]{phylo}} tree object.
#' @return \code{temp_tips} The list of daughter tipnodes
#' @export
#' @seealso \code{\link{add_to_downpass_labels}}, \code{\link[ape]{extract.clade}}
#' @note Go BEARS!
#' @author Nicholas J. Matzke \email{matzke@@berkeley.edu}
#' @references
#' \url{http://phylo.wikidot.com/matzke-2013-international-biogeography-society-poster}
#' @bibliography /Dropbox/_njm/__packages/BioGeoBEARS_setup/BioGeoBEARS_refs.bib
#' @cite Matzke_2012_IBS
#' @examples
#' test=1
#'
get_all_daughter_tips_of_a_node <- function(nodenum, t)
{
# If it's a tip node, just return that tip label
if (nodenum <= length(t$tip.label))
{
temp_tips = t$tip.label[nodenum]
} else {
subtree = extract.clade(t, nodenum)
temp_tips = subtree$tip.label
} # END if (nodenum <= length(t$tip.label))
return(temp_tips)
} # END get_all_daughter_tips_of_a_node()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment