Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 37 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ where `/path/to` the path to where BEAST is installed. For Windows, use

For CCD1 based point estimates select `MAP (CCD1)` from the drop down box in the GUI, or use `CCD1` instead of `CCD0` for the command line version.

### Phylogenetic Entropy, Rogue & Skeleton Analysis
### AppLauncher Tools

The CCD package has three tools (small apps) to compute the phylogenetic entropy of a tree set, compute rogues scores for each clade, and conduct a skeleton analysis
that can each be executed with BEAST's AppLauncher.
The CCD package comes with a set of tools (small apps) that can each be executed with BEAST's AppLauncher.
Note that the given trees *need to be binary* and are assumed to be rooted; they are typically given by a NEXUS `.tree` file, but a list of Newick strings also works.
For more information on the concepts see the [paper](https://www.biorxiv.org/content/10.1101/2024.09.25.615070v1)
When a tool finishes, it prints the reference(s) to cite for the method it implements; this is written to stderr, so it does not interfere with results written to stdout.
For more information on the concepts behind the entropy, rogue and skeleton tools see the [paper](https://www.biorxiv.org/content/10.1101/2024.09.25.615070v1)
and for further information and example data see the [research paper repository](https://github.com/CompEvol/CCD-Research/tree/main/skeletonsAndRogues).


Expand All @@ -101,6 +101,22 @@ It has three parameters:
- `ccdType`: either `CCD0`, `CCD1`, or `CCD2` (default: `CCD0`)


#### Dissonance

The tool `DissonanceCalculator` computes the phylogenetic entropy (via CCD0) of one or more tree sets and, with the `dissonance` flag, also reports a dissonance value for each of them.
The dissonance is computed by splitting a tree set into its first and second half and subtracting the mean entropy of the two halves from the entropy of the whole set.
It is thus a diagnostic *within* a single tree set and not a comparison *between* the given tree files.
```
/path/to/applauncher DissonanceCalculator -trees /path/to/treeInputFile.trees -burnin 10 -dissonance true
```
The app has the following parameters:
- `trees`: trees file to analyse; can be given more than once to process several tree sets in one run
- `burnin`: percentage of trees to be used as burn-in (integer, default: `10%`)
- `dissonance`: `true` to also compute the dissonance of each tree set (default: `false`)
- `summarise`: `true` to print the mean and standard deviation of the entropies across all given tree sets (default: `false`)
- `quiet`: `true` to only output the entropy (and dissonance) values and nothing else (default: `false`)


#### Rogue Analysis

A rogue analysis computes a **rogue score** for each clade, including each taxon, based on a given posterior sample of *binary* trees and some parameters and prints it to a csv file.
Expand Down Expand Up @@ -147,17 +163,25 @@ If you further specify an output file, then the given tree set will be reduced/f
- `out`: reduced tree output file; the given tree set will not be filtered if not specified
- `exclude`: file name of text file containing taxa to exclude from filtering - can be comma, tab or newline delimited

### Credible Level Evaluation
#### Credible Level Evaluation

The credible level of a tree within a credible CCD or a probability-based credible set (on a CCD) can be computed with the following tool.
The **credible level** of a tree is the probability mass of the smallest credible set containing it,
that is, the smallest α for which the tree lies in an α credible set.
The tool `TreeCredibleLevel` computes it, together with the probability of the tree, from a CCD estimated from a posterior tree sample.
```
/path/to/applauncher TreeCredibleLevel -trees /path/to/treeInputFile.trees -tree /path/to/treeInputFile.tree(s) -burnin 10 -out path/to/outputTreeFile
/path/to/applauncher TreeCredibleLevel -trees /path/to/treeInputFile.trees -tree /path/to/testTreeFile.tree -burnin 10 -out path/to/outputFile
```
The app has the following parameters:
- `trees`: trees file to construct CCD with and analyse (required)
- `trees`: trees file to construct the CCD with (required)
- `tree`: tree file containing the tree for which the probability and credible level are computed (required); only the first tree is used
- `out`: output file (required); the probability of the tree is written to the first line and its credible level to the second
- `burnin`: percentage of trees to be used as burn-in (integer, default: `10%`)
- `ccdType`: either `CCD0` or `CCD1` or `CCD2` (default: `CCD1`)
- `tree`: tree for which the credible level is computed
- `method`: whether to use probability-based method (`probability`, default) or a credible CCD (`credibleCCD`)
For the probability-based method the following two parameters can be set:
- `numsamples`: the number of trees sampled from the CCD to compute the credible level thresholds (default: `10000`)
- `ccdType`: either `CCD0`, `CCD1`, or `CCD2` (default: `CCD0`)
- `method`: whether to use the probability-based method (`probability`, default) or a credible CCD (`credibleCCD`)
- `quiet`: `true` to only output the credible level and nothing else (default: `false`)

For the probability-based method one further parameter can be set:
- `numsamples`: the number of trees sampled from the CCD to compute the credible level thresholds (default: `100000`)

Both methods are described in the [credible sets paper](https://doi.org/10.1093/molbev/msag141):
Klawitter J, Drummond AJ (2026), *Bayesian credible sets for phylogenetic tree topologies with applications to coverage analysis and cross-model comparison*, Molecular Biology and Evolution 43(7), msag141.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.release>25</maven.compiler.release>

<beast.version>2.8.0-beta7</beast.version>
<beast.version>2.8.0-beta8</beast.version>
<javafx.version>25.0.2</javafx.version>
<beast.module>beast.base</beast.module>
<beast.main>beast.base.minimal.BeastMain</beast.main>
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/ccd/tools/CCDSampler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ccd.tools;

import beast.base.core.Citation;
import beast.base.core.Description;
import beast.base.core.Input;
import beast.base.core.Log;
Expand All @@ -19,6 +20,9 @@
import ccd.model.HeightSettingStrategy;
import ccd.model.KRegCCD;

@Citation(value = "Berling and Klawitter et al. (2025). PLOS Computational Biology.\n" +
"Accurate Bayesian phylogenetic point estimation using a tree distribution parameterized by clade probabilities.",
DOI = "https://doi.org/10.1371/journal.pcbi.1012789")
@Description("Allows to sample from a CCD{0,1} based on a input set of trees")
public class CCDSampler extends Runnable {
final public Input<TreeFile> treeInput = new Input<>("trees", "trees file to construct CCD with and analyse", Input.Validate.REQUIRED);
Expand Down Expand Up @@ -67,6 +71,8 @@ public void run() throws Exception {
bufferedOutputWriter.newLine();
}
}

CCDToolUtil.printCitations(this);
}

public static void main(String[] args) throws Exception {
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/ccd/tools/CCDToolUtil.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package ccd.tools;

import beast.base.core.Citable;
import beast.base.core.Citation;
import beast.base.core.Input;
import beast.base.core.Log;
import beastfx.app.treeannotator.TreeAnnotator;
Expand All @@ -14,6 +16,7 @@
import ccd.model.RegCCD;

import java.io.IOException;
import java.util.List;

/**
* Static methods provided for tools {@link beastfx.app.tools.Application} in the CCD package
Expand Down Expand Up @@ -110,4 +113,30 @@ public static AbstractCCD getCCDTypeByName(TreeAnnotator.MemoryFriendlyTreeSet t
}
return ccd;
}

/**
* Print the {@link Citation}s of the given tool, if it has any, in the style used by
* TreeAnnotator. Output goes to {@link Log#warning} (stderr) so that it does not interfere
* with results written to stdout.
*
* @param tool the tool whose citations are printed
*/
public static void printCitations(Citable tool) {
List<Citation> citations = tool.getCitationList();
if (citations.isEmpty()) {
return;
}

StringBuilder buf = new StringBuilder();
buf.append("\n======================================================\n");
buf.append("Please cite the following when using these results:\n");
for (Citation citation : citations) {
buf.append("\n").append(citation.value()).append("\n");
if (!citation.DOI().isEmpty()) {
buf.append(citation.DOI()).append("\n");
}
}
buf.append("======================================================");
Log.warning(buf.toString());
}
}
9 changes: 7 additions & 2 deletions src/main/java/ccd/tools/DissonanceCalculator.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ccd.tools;

import beast.base.core.Citation;
import beast.base.core.Description;
import beast.base.core.Input;
import beast.base.core.Log;
Expand All @@ -13,6 +14,9 @@
import java.util.ArrayList;
import java.util.List;

@Citation(value = "Klawitter, Bouckaert and Drummond (2024). bioRxiv.\n" +
"Skeletons in the forest: using entropy-based rogue detection on Bayesian phylogenetic tree distributions.",
DOI = "https://doi.org/10.1101/2024.09.25.615070")
@Description("Calculates the phylogenetic entropies of the posterior tree distribution (estimated via CCD0s) of given tree sets")
public class DissonanceCalculator extends beast.base.inference.Runnable {
final public Input<List<TreeFile>> treeInput = new Input<>("trees", "trees to include in dissonance calculation", new ArrayList<>());
Expand All @@ -32,7 +36,7 @@ public void run() throws Exception {

long start = System.currentTimeMillis();
if (!quiet) {
Log.info("# Starting Entropy Calculator");
Log.info("# Starting Dissonance Calculator");
}

List<Double> entropies = new ArrayList<>();
Expand Down Expand Up @@ -115,11 +119,12 @@ public void run() throws Exception {
long end = System.currentTimeMillis();
if (!quiet) {
Log.info("Done in " + (end - start) / 1000.0 + " seconds");
CCDToolUtil.printCitations(this);
}
}

public static void main(String[] args) throws Exception {
new Application(new DissonanceCalculator(), "Entropy Calculator", args);
new Application(new DissonanceCalculator(), "Dissonance Calculator", args);
}

}
8 changes: 8 additions & 0 deletions src/main/java/ccd/tools/EntropyCalculator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.ArrayList;
import java.util.List;

import beast.base.core.Citation;
import beast.base.core.Description;
import beast.base.core.Input;
import beast.base.core.Log;
Expand All @@ -14,6 +15,9 @@
import ccd.model.AbstractCCD;
import ccd.model.CCDType;

@Citation(value = "Klawitter, Bouckaert and Drummond (2024). bioRxiv.\n" +
"Skeletons in the forest: using entropy-based rogue detection on Bayesian phylogenetic tree distributions.",
DOI = "https://doi.org/10.1101/2024.09.25.615070")
@Description("Calculates the phylogenetic entropy of the posterior tree distribution")
public class EntropyCalculator extends beast.base.inference.Runnable {
// input
Expand Down Expand Up @@ -64,6 +68,10 @@ public void run() throws Exception {
}
k++;
}

if (verboseInput.get()) {
CCDToolUtil.printCitations(this);
}
}

public static void main(String[] args) throws Exception {
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/ccd/tools/RogueAnalysis.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ccd.tools;

import beast.base.core.Citation;
import beast.base.core.Description;
import beast.base.core.Input;
import beast.base.core.Input.Validate;
Expand All @@ -23,6 +24,9 @@
import java.util.Arrays;
import java.util.Map;

@Citation(value = "Klawitter, Bouckaert and Drummond (2024). bioRxiv.\n" +
"Skeletons in the forest: using entropy-based rogue detection on Bayesian phylogenetic tree distributions.",
DOI = "https://doi.org/10.1101/2024.09.25.615070")
@Description("Analyse the clades in a CCD for given trees based on their clade rogue score (based on entropy)")
public class RogueAnalysis extends Runnable {

Expand Down Expand Up @@ -141,6 +145,8 @@ public void run() throws Exception {
createNexusTreeFile(infoOutputFileName, tree);

Log.warning("Done");

CCDToolUtil.printCitations(this);
}

private boolean cladeConditionSatisfied(Clade clade, int maxCladeSize, double minProbability) {
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/ccd/tools/SkeletonAnalysis.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ccd.tools;


import beast.base.core.Citation;
import beast.base.core.Description;
import beast.base.core.Input;
import beast.base.core.Input.Validate;
Expand Down Expand Up @@ -30,6 +31,9 @@

import static ccd.algorithms.RogueDetection.TerminationStrategy.*;

@Citation(value = "Klawitter, Bouckaert and Drummond (2024). bioRxiv.\n" +
"Skeletons in the forest: using entropy-based rogue detection on Bayesian phylogenetic tree distributions.",
DOI = "https://doi.org/10.1101/2024.09.25.615070")
@Description("Analyses the skeleton of a CCD for given trees based on the total rogue scores (based on entropy)")
public class SkeletonAnalysis extends Runnable {
// input
Expand Down Expand Up @@ -145,6 +149,8 @@ public void run() throws Exception {
RogueDetection.annotateRoguePlacements(ccd, lastCCD, rogues, tree);
System.out.println("The resulting annotated tree is: ");
System.out.println(tree.getRoot().toNewick());

CCDToolUtil.printCitations(this);
}

/* Extracted code that filters source treeset. */
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/ccd/tools/TreeCredibleLevel.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ccd.tools;

import beast.base.core.Citation;
import beast.base.core.Description;
import beast.base.core.Input;
import beast.base.core.Log;
Expand All @@ -21,6 +22,9 @@

import static ccd.algorithms.credibleSets.ProbabilityBasedCredibleSetComputer.DEFAULT_NUM_SAMPLES;

@Citation(value = "Klawitter and Drummond (2026). Molecular Biology and Evolution 43(7), msag141.\n" +
"Bayesian credible sets for phylogenetic tree topologies with applications to coverage analysis and cross-model comparison.",
DOI = "https://doi.org/10.1093/molbev/msag141")
@Description("Compute probability and credible level of given tree in CCD of given tree set")
public class TreeCredibleLevel extends beast.base.inference.Runnable {
// input
Expand Down Expand Up @@ -99,6 +103,7 @@ public void run() throws Exception {

if (!quiet) {
Log.info("Done.");
CCDToolUtil.printCitations(this);
}
}

Expand Down
2 changes: 2 additions & 0 deletions version.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,7 @@
<packageapp description="Entropy Calculator" class="ccd.tools.EntropyCalculator" args=""/>
<packageapp description="Skeleton Analysis" class="ccd.tools.SkeletonAnalysis" args=""/>
<packageapp description="Rogue Analysis" class="ccd.tools.RogueAnalysis" args=""/>
<packageapp description="Dissonance Calculator" class="ccd.tools.DissonanceCalculator" args=""/>
<packageapp description="Tree Credible Level" class="ccd.tools.TreeCredibleLevel" args=""/>

</package>