toytree: Tree Manipulation, Plotting, and Evolutionary Analysis

repository·main·Indexed 41 days ago

https://github.com/eaton-lab/toytree

A lightweight Python library for parsing, visualizing, manipulating, and performing evolutionary analyses on tree object data. It provides tools for phylogenetic tree parsing via toytree.tree(), interactive SVG/HTML/JS visualizations, and a PCM module for trait simulation including Brownian motion, Ornstein-Uhlenbeck, and Early burst models. It also supports PGLS and PGLM response simulation, consensus tree inference from MultiTree objects, and ultrametric tree transformation.

Tokens
46.9K
Snippets
131
Records
189
Agent score
52%

What's inside toytree

  1. Overview of the toytree CLI

    main

    The toytree command-line interface is designed for two primary workflows:

    1. Single Command Execution: Running one specific command against a Newick or Nexus file.
    2. Shell Pipelines: Building pipelines where multiple toytree commands pass trees through stdin and stdout.

    Most commands follow the syntax of the corresponding Python API. You can access specific flag details for any command using toytree <command> -h.

  2. Overview of the toytree library

    main

    Toytree is a Python library designed for tree visualization and manipulation, optimized for interactive use within Jupyter notebooks. It provides an object-oriented interface for working with tree objects, combining modern graphical design with extensive manipulation capabilities.

    Key features include:

    • Tree Manipulation: Easily traversable class objects for operations like rooting and ordering.
    • Tree Statistics: Access to edge lengths and node heights.
    • Visualization: Beautiful 'out-of-the-box' figures with extensive customization using CSS semantics and pre-defined styles (e.g., coalescent, dark-mode).
    • Tree Comparisons: Support for cloud tree plotting and Robinson-Foulds calculations.
    • Interactivity: Interactive plots that allow raw data to be accessed via pop-ups.
    • Extensibility: Integration with toyplot for scatterplots, barplots, and colormapping.
  3. Overview of toytree features

    main

    Toytree is an object-oriented Python library designed for tree visualization, manipulation, and evolutionary analyses. It is optimized for interactive use in Jupyter notebooks and provides a minimalist graphical design framework. Key capabilities include:

    • style: High-quality tree drawings with minimal configuration.
    • customization: Exportable drawings in PDF, SVG, or HTML formats.
    • extendable: Ability to combine tree drawings with other plots like scatterplots or barplots.
    • io: Flexible parsing of tree data in newick, nexus, or extended NHX formats.
    • mod: Efficient algorithms for manipulating tree topology, rooting, and data.
    • distance: Calculation of distances between trees (e.g., RF) or nodes (e.g., paths).
    • enum: Enumeration of tree partitions (e.g., quartets, bipartitions) or tree space.
    • multitree: Analysis and visualization of tree sets (e.g., consensus, cloud_trees).
    • rtree: Efficient generation of random trees.
    • network: Parsing and plotting of phylogenetic networks.
  4. Overview of PCM trait simulation in toytree

    main

    The toytree.pcm module provides statistically well-defined trait simulators designed for two primary purposes:

    1. Providing useful trait simulators for end-users.
    2. Generating known-truth data to validate comparative methods in pcm.phylolinalg and pcm.traits.

    Every public simulator is designed to be compatible with specific downstream fitting methods and follows a consistent return type pattern.

  5. What is a MultiTree and how to use it

    main

    A MultiTree (or mtree) is a collection of ToyTree objects. It is useful for managing sets of trees, such as those generated from simulations or collected from different datasets. A MultiTree is both indexable and iterable, allowing you to access individual trees by index, slice them, or loop through them.

    Creating a MultiTree

    You can generate a MultiTree in several ways:

    1. From tree data: Create an mtree directly from a Newick string, a list of Newick strings, a URL, or a file path.
    2. From a collection of trees: Convert an existing list or collection of ToyTree objects into a MultiTree.
    3. From simulations: Generate random trees (e.g., coalescent trees) and wrap them in a MultiTree.

    Accessing trees in a MultiTree

    • Indexing: Use standard Python indexing to get a specific tree (e.g., mt[0]).
    • Slicing: Use slicing to get a subset of trees (e.g., mt[:3]).
    • Iteration: Use a for loop to iterate over the ToyTree objects within the MultiTree.
  6. What is a MultiTree and how to generate one

    main

    A MultiTree is a collection of ToyTree objects. It is useful for managing sets of trees, such as those generated from a coalescent simulation or a collection of phylogenetic trees.

    You can generate a MultiTree in two primary ways:

    1. From tree data: Create an mtree directly from a Newick string, a list of Newick strings, a URL, or a file path.
    2. From a collection of trees: Create a MultiTree by passing a list of existing ToyTree objects.

    Example of generating a MultiTree from a list of strings:

    import toytree
    
    # Create an mtree from a list of Newick strings
    mtree = toytree.mtree("((a,b),c);", "((a,c),b);")
    import toytree
    
    # Create an mtree from a list of Newick strings
    mtree = toytree.mtree("((a,b),c);", "((a,c),b);")
  7. What is a MultiTree?

    main
    A toytree.MultiTree is a collection of ToyTree objects. It is designed to represent sets of trees, such as bootstrap replicate samples or posterior distributions. Common operations performed on a MultiTree include consensus tree inference, computing discordance or distance statistics, and plotting tree grids or cloud trees.
  8. Choose a molecular clock model for ultrametricity

    main

    Select a method based on your biological assumptions:

    • clock: Strict clock. Assumes a single shared evolutionary rate across all branches. Validated and stable.
    • correlated: Correlated rates. Assumes ancestor-descendant autocorrelation in rates. Requires a pre-specified lam parameter.
    • uncorrelated_lognormal: UCLN. Recommended for continuous, independent lognormal rates. Requires a pre-specified lam parameter. Use this for most uncorrelated-rate analyses.
    • discrete: Discrete mixture. Used for compatibility with ape::chronos fractional-Poisson mixtures. Requires ncategories to be specified.
    • relaxed: Relaxed objective. Implemented only for parity with the ape::chronos Gamma-CDF convention. Not recommended for new analyses.

    Note on lam: ToyTree does not estimate lam automatically. You must supply it from external knowledge. For uncorrelated_lognormal, lam fixes dispersion via lam = 1 / (2 * sigma_log**2).

  9. Understand the Zero-length branch policy in UCLN validation

    main

    In the uncorrelated_lognormal (UCLN) validation, observed zero-length branches are treated as valid fractional-Poisson observations. They are passed to the objective function unchanged and are not rejected or replaced by an arbitrary positive floor (e.g., 1e-6).

    Using a floor can mask optimizer instability. Instead, every fit reports:

    • Counts of zero terminal and internal branches.
    • The overall fraction of zero branches.
    • The smallest positive branch length.
    • The ratio of the smallest positive branch to the positive median.

    Note on Inference: If a fit contains many exact zeros, it may indicate weak age-rate identifiability. You should only use a zero-rich fit for inference if the following diagnostics are all true:

    • converged
    • best_basin_replicated
    • solution_stable
  10. Understand the V11 fixed-lambda UCLN validation design

    main

    Version 11 evaluates the uncorrelated_lognormal estimator at a prespecified smoothing value rather than performing a lambda-selection study.

    Key Concepts

    • Penalty Calculation: For a simulated log-rate standard deviation sigma_log, the penalty is fixed as lam = 1 / (2 * sigma_log**2).
    • Implied Sigma: The returned implied_sigma_log is a deterministic interpretation of the fixed lambda, not an estimate from the fitted tree.
    • Observation Tracks: The validation tests three tracks:
      • expected-branch: Tests model-matched means.
      • fractional-Poisson: Tests the working observation model.
      • continuous-Gamma: Tests robustness to low continuous branch noise.

    Task Granularity and Caching

    Each dataset expands into independent cached tasks, including:

    • Four-start free-age fits and eight-start stress fits.
    • Fits with internal ages fixed to truth.
    • A four-start fit with calibration ages multiplied by one million (for the first replicate in every cell).

    Fit caches are written atomically and fingerprint the UCLN, clock initializer, shared optimizer utilities, runner, and configuration. The task cache is located under v11/cache-v11/ and is resumable but should remain untracked in version control.

  11. PGLS and PGLM response simulation

    main

    PGLS (Phylogenetic Generalized Least Squares)

    Generates data using the model: Y = X beta + epsilon, where epsilon ~ MVN(0, sigma2 * V_lambda). Important: The working tree is scaled to root height 1 before applying Pagel's lambda. Therefore, sigma2 represents residual variance on the normalized-tree covariance scale, not the original time scale.

    PGLM (Phylogenetic Generalized Linear Models)

    Uses a latent phylogenetic process:

    1. eta = X beta + epsilon (where epsilon ~ MVN(0, sigma2 * V_lambda))
    2. mu = inverse_link(eta)
    3. Y | mu ~ selected response family

    Supported families include: binomial-logit, Poisson-log, negative-binomial-log, Gamma-log/inverse, and beta-logit.

  12. Handle fit failures and usability diagnostics

    main

    When running ultrametric fits, you can control how failures are handled using the full and inplace parameters:

    • Default behavior (full=False): The process is 'fail-closed'. If the optimizer does not converge or diagnostics mark the solution as unstable, a ToytreeError is raised.
    • Diagnostic mode (full=True): The method returns the candidate tree even if the fit is unsuccessful. You must check the following attributes on the returned object:
      • fit_usable: A Boolean indicating if the optimizer converged and the solution is stable.
      • failure_reasons: A list containing the reasons why the fit was marked unusable.
    • In-place modification (inplace=True): If used in conjunction with full=True, the source tree is only modified if the fit passes the fit_usable check. If the fit fails, the source tree remains unchanged.