The function is.binary.tree is obsolete (before being deprecated)

Background

The function is.binary.tree has been introduced in ape 0.2 (September 2002). In ape 4.0 (November 2016), is.binary has been made a generic function with methods for the classes "phylo" (is.binary.phylo) and "multiPhylo" (is.binary.multiPhylo), both being exported in ape's NAMESPACE file.

Why is it important?

This change has made is.binary.tree obsolete. However, several packages use this function, so it is not possible to remove it now.

On the other hand, the class "tree" is defined in the package of the same name. So the function currently in ape may create issues if someone wants to define an is.binary method for the class "tree".

The situation

In March 2019, I found that 25 packages on CRAN use is.binary.tree. Recently (May 2020), this number has dropped to 14. The table below list the occurrences of this function in the code of these packages (in the R/ directory of the sources on CRAN), the file names, and the line numbers.

Package File Line Code
1 adiv optimEH.R 9 if(is.binary.tree(phyl.phylo))\r"
2 adiv orisaved.R 16 if(is.binary.tree(phyl.phylo))\r"
3 geiger diversitree.R 209 \t## ape is.binary.tree() can let a few nasties through - for\r"
4 geiger diversitree.R 212 \tif ( bifurcating && (!is.binary.tree(tree) ||\r"
5 geiger likelihood.R 47 \tif(!is.binary.tree(phy)) stop(\"'phy' is not fully dichotomous.\")"
6 geiger likelihood.R 288 if(ct$binary) if(!is.binary.tree(phy)) stop(\"'phy' should be a binary tree\")"
7 ggrasp ggrasp.cluster.R 277 if (!is.binary.tree(nj_tree))"
8 ggrasp ggrasp.create.R 65 \t\tis.binary <- is.binary.tree;"
9 jackalope create_haplotypes.R 124 if (!ape~~is.binary.tree(phy)) {"
10 mvMORPH pruning.r 8 if(!is.binary.tree(tree)) tree <- multi2di(tree, random=FALSE)"
11 pez shape.R 111 #' @importFrom ape is.binary.tree"
12 pez shape.R 165 if(!is.binary.tree(data$phy) & \"colless\" %in% names(functions))"
13 phyext2 phyext2.R 555 \tif(!is.binary.tree(tr))\r"
14 phylocurve fast_geomorph_functions.R 197 if (!is.binary.tree(phy)) \r"
15 phylocurve fast_geomorph_functions.R 411 if (!is.binary.tree(tree)) \r"
16 phylocurve fast_geomorph_functions.R 435 if (!is.binary.tree(tree)) {\r"
17 phylocurve phylocurve.R 4 if(!is.binary.tree(original_tree)) phy <- reorder(multi2di(phy),\"postorder\") else\r"
18 phylocurve phylocurve.R 30 if(!is.binary.tree(original_tree))\r"
19 phylocurve phylocurve.R 50 if(!is.binary.tree(original_tree)) phy <- reorder(multi2di(phy),\"postorder\") else\r"
20 phylocurve phylocurve.R 98 if(!is.binary.tree(original_tree))\r"
21 phylocurve phylocurve.R 856 if(!is.binary.tree(tree))\r"
22 phylocurve phylocurve.R 1251 if(!is.binary.tree(model$evo.model.args$tree)) FLAG <- TRUE else FLAG <- FALSE\r"
23 phyloTop phyloCheck.R 25 if(!is.binary.tree(tree)||!is.rooted(tree)) {\r"
24 phyloTop phyloCheck.R 29 if(!is.binary.tree(tree)||!is.rooted(tree)) {stop(\"Unable to coerce the tree to be binary and rooted.\")}\r
25 rase rase_source.r 752 if (!is.binary.tree(tree)) {"
26 RPANDA MC.rescale.R 7 \tif(!is.binary.tree(phylo)){stop(\"tree must not contain any polytomies\")}"
27 RPANDA MC.rescale_geog.R 13 if(!is.binary.tree(phylo)){stop(\"tree must not contain any polytomies\")}"
28 Rphylip Rphylip.R 2834 \tif(!is.binary.tree(tree)){\r"
29 RRphylo RRphylo.R 13 #' @importFrom ape multi2di Ntip is.binary.tree Nnode dist.nodes drop.tip subtrees nodelabels\r"
30 RRphylo RRphylo.R 129 if (is.binary.tree(tree))\r"
31 RRphylo RRphylo.R 140 if (is.binary.tree(tree) == FALSE)\r"
32 RRphylo RRphylo.R 149 if (is.binary.tree(tree) == FALSE)\r"
33 RRphylo RRphylo.R 174 if (is.binary.tree(tree) == FALSE) {\r"
34 RRphylo RRphylo.R 245 if (is.binary.tree(tree) == FALSE) {\r"
35 RRphylo StableTraitsR.R 48 if (is.binary.tree(tree)) t <- tree else t <- multi2di(tree,random=FALSE)\r"
36 RRphylo StableTraitsR.R 64 if (is.binary.tree(tree)==FALSE){\r"
37 TKF MinSqTree.R 46 if(!is.binary.tree(stree)){"


Additionally, the NAMESPACE file of the following packages will eventually need to be adjusted since it includes is.binary.tree in the list of imported functions:

adiv
pez
phyext2
rase
Rphylip
RRphylo
TKF

What to do?

In all cases, the simplest thing to do is to replace is.binary.tree by is.binary.phylo.

If you think that your code may be called with trees and/or list of trees (for instance, in a future version), then you may use is.binary.

There is no timeline to implement this change. Once done and you have released a new version of your package on CRAN, you may drop me a message, but that's not an obligation since I have to check all reverse dependencies of ape before submitting a new version to CRAN.

After all packages on CRAN will have implemented this change, is.binary.tree will be changed in the following release of ape to give a warning, so that it will still work in the same way but a new package on CRAN will not be able to use it.

Then, the next following release of ape will have is.binary.tree deprecated (i.e., giving an error with a message pointing to the correct function). Finally, the function might be removed in a future release.
Updated: May 7, 2020
Crédits | Legal notice