Skip to content

Commit 3ecd63e

Browse files
authored
Cherries() (#236)
1 parent a169345 commit 3ecd63e

22 files changed

Lines changed: 230 additions & 30 deletions

.github/workflows/R-CMD-check.yml

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ jobs:
5151
config:
5252
- {os: windows-latest, r: 'release'}
5353
- {os: macOS-latest, r: 'release'}
54-
- {os: ubuntu-24.04, r: '3.6', rspm: "https://packagemanager.posit.co/cran/2022-04-01"}
55-
- {os: ubuntu-24.04, r: '4.0', rspm: "https://packagemanager.posit.co/cran/2022-04-01"}
54+
- {os: ubuntu-24.04, r: '3.6', rspm: "https://packagemanager.posit.co/cran/2022-10-11"}
55+
- {os: ubuntu-24.04, r: '4.0', rspm: "https://packagemanager.posit.co/cran/2022-10-11"}
5656
- {os: ubuntu-24.04, r: 'release', rspm: "https://packagemanager.posit.co/cran/__linux__/noble/latest"}
5757
- {os: ubuntu-24.04, r: 'devel', rspm: "https://packagemanager.posit.co/cran/__linux__/noble/latest"}
5858

@@ -86,7 +86,7 @@ jobs:
8686
fi
8787
echo "Current package version is now: $(grep "Version:" DESCRIPTION | awk '{print $2}')"
8888
shell: bash
89-
89+
9090
- name: Set up R
9191
uses: r-lib/actions/setup-r@v2
9292
with:
@@ -97,7 +97,6 @@ jobs:
9797
run: |
9898
sudo apt-get install texlive-latex-base texlive-fonts-recommended
9999
100-
101100
- name: Install system dependencies (R 3.x)
102101
if: matrix.config.r < '4.0'
103102
run: |
@@ -127,11 +126,6 @@ jobs:
127126
sed -i '1i#include <cstdint>' vdiffr-src/src/devSVG.cpp
128127
R CMD INSTALL --preclean --no-multiarch --with-keep.source vdiffr-src
129128
rm -rf vdiffr-src
130-
131-
- name: Show installed R packages
132-
run: |
133-
Rscript -e 'sessionInfo()'
134-
Rscript -e 'installed.packages()[, c("Package", "Version")]'
135129
136130
- name: Set up R dependencies (R 3.x)
137131
if: matrix.config.r < '4.0'
@@ -142,7 +136,7 @@ jobs:
142136
github::ms609/PlotTools@v0.3.1
143137
rcmdcheck@1.3.3
144138
waldo@0.4.0
145-
testthat@3.0.4
139+
testthat@3.1.5
146140
pkgload@1.2.4
147141
pkgdown@2.0.1
148142
bslib@0.3.1
@@ -161,32 +155,18 @@ jobs:
161155
needs: |
162156
check
163157
coverage
164-
165-
- name: Show installed R packages
166-
run: |
167-
Rscript -e 'sessionInfo()'
168-
Rscript -e 'installed.packages()[, c("Package", "Version")]'
169158
170159
- name: Set up R dependencies (Non-Windows)
171160
if: ${{runner.os != 'Windows' && matrix.config.r >= '4.0' }}
172161
uses: r-lib/actions/setup-r-dependencies@v2
173162
with:
174163
needs: |
175164
check
176-
extra-packages:
165+
extra-packages: |
166+
TreeDist=?ignore-before-r=4.0.0
167+
vdiffr=?ignore-before-r=4.0.0
177168
phangorn=?ignore-before-r=4.1.0
178-
179-
- name: Show installed R packages
180-
run: |
181-
Rscript -e 'sessionInfo()'
182-
Rscript -e 'installed.packages()[, c("Package", "Version")]'
183-
184-
- name: Debug package requirements
185-
run: |
186-
Rscript -e 'ip <- as.data.frame(installed.packages()[, c("Package","Version")]); print(ip[ip$Package %in% c("rmarkdown","knitr","xfun","htmltools","tinytex"), ])'
187-
Rscript -e 'deps <- tools::package_dependencies("htmltools", db = available.packages(), which = c("Depends","Imports","LinkingTo")); print(deps)'
188-
Rscript -e 'cat("rmarkdown DESCRIPTION:\n"); cat(readLines(system.file("DESCRIPTION", package = "rmarkdown")), sep="\n")'
189-
169+
190170
- name: Check package
191171
uses: r-lib/actions/check-r-package@v2
192172

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: TreeTools
22
Title: Create, Modify and Analyse Phylogenetic Trees
3-
Version: 1.16.1.9001
3+
Version: 1.16.1.9002
44
Authors@R: c(
55
person("Martin R.", 'Smith', role = c("aut", "cre", "cph"),
66
email = "martin.smith@durham.ac.uk",

NAMESPACE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ S3method(ApePostorder,multiPhylo)
3232
S3method(ApePostorder,phylo)
3333
S3method(ArtificialExtinction,matrix)
3434
S3method(ArtificialExtinction,phyDat)
35+
S3method(Cherries,numeric)
36+
S3method(Cherries,phylo)
3537
S3method(Cladewise,"NULL")
3638
S3method(Cladewise,list)
3739
S3method(Cladewise,matrix)
@@ -270,6 +272,7 @@ export(ArtEx)
270272
export(ArtificialExtinction)
271273
export(BalancedTree)
272274
export(CharacterInformation)
275+
export(Cherries)
273276
export(CladeSizes)
274277
export(Cladewise)
275278
export(CladisticInfo)

NEWS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
# TreeTools 1.16.1.9001` (development) #
1+
# TreeTools 1.16.1.9002` (development) #
22

3+
- `Cherries()` counts the cherries in a binary tree.
34
- New method `as.Splits.integer()`.
45
- Fix `RoguePlot(sort = TRUE)`
56
[Rogue#33](https://github.com/ms609/Rogue/issues/33).

R/Cherries.R

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#' Count cherries in a tree
2+
#'
3+
#' `Cherries()` counts the number of vertices in a binary tree whose children
4+
#' are both leaves.
5+
#'
6+
#' @param tree A binary tree, of class `phylo`; or a matrix corresponding to its
7+
#' edge matrix.
8+
#' @param nTip Number of leaves in tree.
9+
#' @return `Cherries()` returns an integer specifying the number of nodes whose
10+
#' children are both leaves.
11+
#' @family tree properties
12+
#' @template MRS
13+
#' @export
14+
Cherries <- function(tree, nTip) UseMethod("Cherries")
15+
16+
#' @rdname Cherries
17+
#' @export
18+
Cherries.phylo <- function(tree, nTip = NTip(tree)) {
19+
n_cherries_wrapper(tree[["edge"]][, 1], tree[["edge"]][, 2], nTip)
20+
}
21+
22+
#' @rdname Cherries
23+
#' @export
24+
Cherries.numeric <- function(tree, nTip) {
25+
if (is.null(dim(tree)) || dim(tree)[[2]] != 2) {
26+
stop("`tree` must be the edge matrix of a tree of class phylo")
27+
}
28+
n_cherries_wrapper(tree[, 1], tree[, 2], nTip)
29+
}

R/RcppExports.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ minimum_spanning_tree <- function(order) {
6969
.Call(`_TreeTools_minimum_spanning_tree`, order)
7070
}
7171

72+
n_cherries_wrapper <- function(parent, child, nTip) {
73+
.Call(`_TreeTools_n_cherries_wrapper`, parent, child, nTip)
74+
}
75+
7276
path_lengths <- function(edge, weight, init_nas) {
7377
.Call(`_TreeTools_path_lengths`, edge, weight, init_nas)
7478
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#ifndef TreeTools_n_cherries_
2+
#define TreeTools_n_cherries_
3+
4+
#include <memory> /* for std::unique_ptr */
5+
#include <stdexcept> /* for errors */
6+
#include <vector>
7+
8+
#include "assert.h" /* for ASSERT */
9+
10+
namespace TreeTools{
11+
12+
// Number of cherries in a binary phylogenetic tree
13+
inline int n_cherries(const int* parent,
14+
const int* child,
15+
const size_t n_edge,
16+
const int n_tip) {
17+
18+
const size_t n_node = n_edge / 2;
19+
std::unique_ptr<bool[]> internal(new bool[n_node]());
20+
21+
const bool unrooted = n_edge % 2;
22+
if (unrooted) {
23+
std::unique_ptr<bool[]> is_child(new bool[n_node + n_tip + 1]());
24+
25+
for (size_t ed = 0; ed < n_edge; ++ed) {
26+
is_child[child[ed]] = true;
27+
}
28+
29+
const int i_limit = n_tip + n_node + 1;
30+
int root_node = n_tip + 1;
31+
for (; root_node <= i_limit; ++root_node) {
32+
if (!is_child[root_node]) break;
33+
}
34+
35+
if (root_node == i_limit) {
36+
throw std::runtime_error("Tree must be acyclic"); // nocov
37+
}
38+
39+
bool root_internal_found = false;
40+
for (size_t ed = 0; ed < n_edge; ++ed) {
41+
const int child_i = child[ed];
42+
if (child_i > n_tip) {
43+
const int node = parent[ed];
44+
if (!root_internal_found && node == root_node) {
45+
root_internal_found = true;
46+
} else {
47+
internal[node - n_tip] = true;
48+
}
49+
}
50+
}
51+
52+
} else {
53+
for (size_t ed = 0; ed < n_edge; ++ed) {
54+
if (child[ed] > n_tip) {
55+
const size_t node_idx = parent[ed] - n_tip;
56+
internal[node_idx] = true;
57+
}
58+
}
59+
}
60+
61+
int n_cherries = 0;
62+
for (size_t i = 0; i < n_node; ++i) {
63+
if (!internal[i]) ++n_cherries;
64+
}
65+
return n_cherries;
66+
}
67+
68+
}
69+
70+
#endif

man/Cherries.Rd

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/ConsensusWithout.Rd

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/LongBranch.Rd

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)