├── .coveragerc ├── .github └── workflows │ ├── main.yml │ └── python-publish.yml ├── .readthedocs.yaml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── citation.cff ├── examples ├── align_tips.png ├── bad_tree.nw ├── basic_plot.png ├── basic_plot_box.png ├── basic_tree.nw ├── big_tree.nw ├── bold.png ├── colours.png ├── from_string.png ├── height.png ├── labels.png ├── layered.png ├── nobranchlengths.png ├── nobranchlengths_ali.png ├── primates.nw ├── primates_mixed.nw ├── rev_align_tips.png ├── reversed.png ├── tree_pos.png ├── width.png ├── xpos.png └── ypos.png ├── man ├── Makefile ├── conf.py ├── contents.rst ├── index.md ├── pages │ ├── detailed.md │ ├── examples │ │ ├── align_tips.png │ │ ├── basic_plot.png │ │ ├── basic_plot_box.png │ │ ├── bold.png │ │ ├── colours.png │ │ ├── from_string.png │ │ ├── height.png │ │ ├── labels.png │ │ ├── layered.png │ │ ├── nobranchlengths.png │ │ ├── nobranchlengths_ali.png │ │ ├── primates.nw │ │ ├── rev_align_tips.png │ │ ├── reversed.png │ │ ├── tree_pos.png │ │ ├── width.png │ │ ├── xpos.png │ │ └── ypos.png │ ├── functions.rst │ ├── installation.md │ ├── matplotlib.md │ ├── parameters.md │ ├── quickstart.md │ └── testing.md └── requirements.txt ├── plot_phylo ├── __init__.py ├── _version.py └── plot_phylo.py ├── pyproject.toml ├── requirements.txt ├── setup.cfg ├── setup.py └── tests ├── test_get_boxes_data.py ├── test_images ├── align_tips_basic_tree.png ├── align_tips_big_tree.png ├── align_tips_primates.png ├── basic_basic_tree.png ├── basic_big_tree.png ├── basic_primates.png ├── bold_basic_tree.png ├── bold_big_tree.png ├── bold_primates.png ├── branch_lengths_basic_tree.png ├── branch_lengths_big_tree.png ├── branch_lengths_primates.png ├── col_dict_basic_tree.png ├── col_dict_big_tree.png ├── col_dict_primates.png ├── font_size_basic_tree.png ├── font_size_big_tree.png ├── font_size_primates.png ├── label_dict_basic_tree.png ├── label_dict_big_tree.png ├── label_dict_primates.png ├── line_col_basic_tree.png ├── line_col_big_tree.png ├── line_col_primates.png ├── line_width_basic_tree.png ├── line_width_big_tree.png ├── line_width_primates.png ├── outgroup_basic_tree.png ├── outgroup_big_tree.png ├── outgroup_primates.png ├── rev_align_tips_basic_tree.png ├── rev_align_tips_big_tree.png ├── rev_align_tips_primates.png ├── rev_align_tips_reverse_basic_tree.png ├── rev_align_tips_reverse_big_tree.png ├── rev_align_tips_reverse_primates.png ├── reverse_basic_tree.png ├── reverse_big_tree.png ├── reverse_primates.png ├── scale_bar_basic_tree.png ├── scale_bar_big_tree.png ├── scale_bar_primates.png ├── scale_bar_width_basic_tree.png ├── scale_bar_width_big_tree.png ├── scale_bar_width_primates.png ├── show_axis_basic_tree.png ├── show_axis_big_tree.png ├── show_axis_primates.png ├── show_support_basic_tree.png ├── show_support_big_tree.png ├── show_support_primates.png ├── xpos_ypos_basic_tree.png ├── xpos_ypos_big_tree.png └── xpos_ypos_primates.png ├── test_objects ├── draw_tree__basic_tree.pickle ├── draw_tree__big_tree.pickle ├── draw_tree__primates.pickle ├── draw_tree_align_tips_basic_tree.pickle ├── draw_tree_align_tips_big_tree.pickle ├── draw_tree_align_tips_primates.pickle ├── draw_tree_appearance_basic_tree.pickle ├── draw_tree_appearance_big_tree.pickle ├── draw_tree_appearance_primates.pickle ├── draw_tree_branch_lengths_basic_tree.pickle ├── draw_tree_branch_lengths_big_tree.pickle ├── draw_tree_branch_lengths_primates.pickle ├── draw_tree_depth_basic_tree.pickle ├── draw_tree_depth_big_tree.pickle ├── draw_tree_depth_primates.pickle ├── draw_tree_outgroup_basic_tree.pickle ├── draw_tree_outgroup_big_tree.pickle ├── draw_tree_outgroup_primates.pickle ├── draw_tree_rev_align_tips_basic_tree.pickle ├── draw_tree_rev_align_tips_big_tree.pickle ├── draw_tree_rev_align_tips_primates.pickle ├── draw_tree_rev_align_tips_reverse_basic_tree.pickle ├── draw_tree_rev_align_tips_reverse_big_tree.pickle ├── draw_tree_rev_align_tips_reverse_primates.pickle ├── draw_tree_reverse_basic_tree.pickle ├── draw_tree_reverse_big_tree.pickle ├── draw_tree_reverse_primates.pickle ├── draw_tree_scale_bar_basic_tree.pickle ├── draw_tree_scale_bar_big_tree.pickle ├── draw_tree_scale_bar_primates.pickle ├── draw_tree_scale_bar_width_basic_tree.pickle ├── draw_tree_scale_bar_width_big_tree.pickle ├── draw_tree_scale_bar_width_primates.pickle ├── draw_tree_show_axis_basic_tree.pickle ├── draw_tree_show_axis_big_tree.pickle ├── draw_tree_show_axis_primates.pickle ├── draw_tree_xpos_ypos_basic_tree.pickle ├── draw_tree_xpos_ypos_big_tree.pickle ├── draw_tree_xpos_ypos_primates.pickle ├── rev_align__basic_tree.pickle ├── rev_align__big_tree.pickle ├── rev_align__primates.pickle ├── rev_align_appearance_basic_tree.pickle ├── rev_align_appearance_big_tree.pickle ├── rev_align_appearance_primates.pickle ├── rev_align_branch_lengths_basic_tree.pickle ├── rev_align_branch_lengths_big_tree.pickle ├── rev_align_branch_lengths_primates.pickle ├── rev_align_depth_basic_tree.pickle ├── rev_align_depth_big_tree.pickle ├── rev_align_depth_primates.pickle ├── rev_align_outgroup_basic_tree.pickle ├── rev_align_outgroup_big_tree.pickle ├── rev_align_outgroup_primates.pickle ├── rev_align_reverse_basic_tree.pickle ├── rev_align_reverse_big_tree.pickle ├── rev_align_reverse_primates.pickle ├── rev_align_scale_bar_basic_tree.pickle ├── rev_align_scale_bar_big_tree.pickle ├── rev_align_scale_bar_primates.pickle ├── rev_align_scale_bar_width_basic_tree.pickle ├── rev_align_scale_bar_width_big_tree.pickle ├── rev_align_scale_bar_width_primates.pickle ├── rev_align_show_axis_basic_tree.pickle ├── rev_align_show_axis_big_tree.pickle ├── rev_align_show_axis_primates.pickle ├── rev_align_xpos_ypos_basic_tree.pickle ├── rev_align_xpos_ypos_big_tree.pickle └── rev_align_xpos_ypos_primates.pickle ├── test_plot_phylo.py └── test_plot_phylo_data.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = plot_phylo 3 | omit = tests/*, build/*, dist/*, */__init__.py, */_version.py 4 | 5 | [report] 6 | show_missing = True 7 | 8 | [html] 9 | directory = htmlcov 10 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | # We can specify which Github events will trigger a CI build 4 | on: push 5 | 6 | # now define a single job 'build' (but could define more) 7 | jobs: 8 | 9 | build: 10 | 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: [ ubuntu-latest, macos-latest, windows-latest ] 15 | python-version: [ 3.8, 3.9, '3.10', 3.11, 3.12 ] 16 | include: # python 7 sometimes requires legacy versions 17 | - python-version: "3.6" 18 | os: "macos-13" 19 | - python-version: "3.6" 20 | os: "windows-latest" 21 | - python-version: "3.7" 22 | os: "macos-13" 23 | - python-version: "3.7" 24 | os: "ubuntu-22.04" 25 | - python-version: "3.7" 26 | os: "windows-latest" 27 | fail-fast: false 28 | # a job is a seq of steps 29 | steps: 30 | 31 | # Next we need to checkout out repository, and set up Python 32 | # A 'name' is just an optional label shown in the log - helpful to clarify progress - and can be anything 33 | - name: Checkout repository 34 | uses: actions/checkout@v2 35 | 36 | - name: Set up Python 37 | uses: actions/setup-python@v4 38 | with: 39 | python-version: ${{ matrix.python-version }} 40 | 41 | - name: Install Python dependencies 42 | run: | 43 | python3 -m pip install --upgrade pip 44 | pip install -r requirements.txt 45 | pip install pytest flake8 46 | pip3 install -e . 47 | 48 | - name: Install xvfb (for Linux) 49 | if: runner.os == 'Linux' 50 | run: | 51 | sudo apt-get update 52 | sudo apt-get install -y xvfb 53 | - name: Lint with flake8 54 | run: | 55 | # stop the build if there are Python syntax errors or undefined names 56 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 57 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 58 | flake8 . --count --exit-zero --max-complexity=20 --max-line-length=127 --statistics 59 | - name: Run tests (for Linux) 60 | if: runner.os == 'Linux' 61 | run: xvfb-run pytest 62 | 63 | - name: Run tests (for macOS and Windows) 64 | if: runner.os != 'Linux' 65 | run: pytest 66 | 67 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.x' 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install build 33 | - name: Build package 34 | run: python -m build 35 | - name: Publish package 36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 37 | with: 38 | user: __token__ 39 | password: ${{ secrets.PYPI_KEY }} 40 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the OS, Python version and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.12" 13 | # You can also specify other tool versions: 14 | # nodejs: "19" 15 | # rust: "1.64" 16 | # golang: "1.19" 17 | 18 | # Build documentation in the "docs/" directory with Sphinx 19 | sphinx: 20 | configuration: man/conf.py 21 | 22 | # Optionally build your docs in additional formats such as PDF and ePub 23 | # formats: 24 | # - pdf 25 | # - epub 26 | 27 | # Optional but recommended, declare the Python requirements required 28 | # to build your documentation 29 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 30 | python: 31 | install: 32 | - requirements: man/requirements.txt -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | We as members, contributors, and leaders pledge to make participation in our 7 | community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, caste, color, religion, or sexual 11 | identity and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the overall 27 | community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery, and sexual attention or advances of 32 | any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email address, 36 | without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies when 55 | an individual is officially representing the community in public spaces. 56 | Examples of representing our community include using an official email address, 57 | posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. 59 | 60 | ## Enforcement 61 | 62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 63 | reported to the community leaders responsible for enforcement at 64 | [INSERT CONTACT METHOD]. 65 | All complaints will be reviewed and investigated promptly and fairly. 66 | 67 | All community leaders are obligated to respect the privacy and security of the 68 | reporter of any incident. 69 | 70 | ## Enforcement Guidelines 71 | 72 | Community leaders will follow these Community Impact Guidelines in determining 73 | the consequences for any action they deem in violation of this Code of Conduct: 74 | 75 | ### 1. Correction 76 | 77 | **Community Impact**: Use of inappropriate language or other behavior deemed 78 | unprofessional or unwelcome in the community. 79 | 80 | **Consequence**: A private, written warning from community leaders, providing 81 | clarity around the nature of the violation and an explanation of why the 82 | behavior was inappropriate. A public apology may be requested. 83 | 84 | ### 2. Warning 85 | 86 | **Community Impact**: A violation through a single incident or series of 87 | actions. 88 | 89 | **Consequence**: A warning with consequences for continued behavior. No 90 | interaction with the people involved, including unsolicited interaction with 91 | those enforcing the Code of Conduct, for a specified period of time. This 92 | includes avoiding interactions in community spaces as well as external channels 93 | like social media. Violating these terms may lead to a temporary or permanent 94 | ban. 95 | 96 | ### 3. Temporary Ban 97 | 98 | **Community Impact**: A serious violation of community standards, including 99 | sustained inappropriate behavior. 100 | 101 | **Consequence**: A temporary ban from any sort of interaction or public 102 | communication with the community for a specified period of time. No public or 103 | private interaction with the people involved, including unsolicited interaction 104 | with those enforcing the Code of Conduct, is allowed during this period. 105 | Violating these terms may lead to a permanent ban. 106 | 107 | ### 4. Permanent Ban 108 | 109 | **Community Impact**: Demonstrating a pattern of violation of community 110 | standards, including sustained inappropriate behavior, harassment of an 111 | individual, or aggression toward or disparagement of classes of individuals. 112 | 113 | **Consequence**: A permanent ban from any sort of public interaction within the 114 | community. 115 | 116 | ## Attribution 117 | 118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 119 | version 2.1, available at 120 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 121 | 122 | Community Impact Guidelines were inspired by 123 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 124 | 125 | For answers to common questions about this code of conduct, see the FAQ at 126 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 127 | [https://www.contributor-covenant.org/translations][translations]. 128 | 129 | [homepage]: https://www.contributor-covenant.org 130 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 131 | [Mozilla CoC]: https://github.com/mozilla/diversity 132 | [FAQ]: https://www.contributor-covenant.org/faq 133 | [translations]: https://www.contributor-covenant.org/translations 134 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to plot_phylo 2 | 3 | I appreciate your interest in contributing to this project. Please take a moment to review the following guidelines. 4 | 5 | ## Ways to Contribute 6 | 7 | You can contribute to plot_phylo in the following ways: 8 | 9 | - Reporting bugs 10 | - Submitting feature requests 11 | - Forking the repository and improving the code 12 | - Improving documentation 13 | 14 | If contributing to plot_phylo, please ensure that you 15 | 16 | * Add any new functionality to the README.md documentation, following the style of the rest of the document. 17 | * Edit function docstrings to include any new variables and include docstrings in the same style for any new functions. 18 | * Add comments to describe how your code works. 19 | * Edit the unit tests to include any new functionality. 20 | * Run unit tests as described [here](https://plot-phylo.readthedocs.io/en/latest/pages/testing.html) and ensure that they pass and that coverage is 100%. 21 | * Check the code is pep8 compliant. 22 | 23 | If you're unsure about any of these steps, please raise an issue and I can help you. 24 | 25 | ## Continuous Integration 26 | I use GitHub Actions for continuous integration to ensure code quality. You can view the configuration [here](https://github.com/KatyBrown/plot_phylo/blob/main/.github/workflows/main.yml). 27 | 28 | ## Code of Conduct 29 | 30 | Please review our Code of Conduct before participating. Be kind and respectful to fellow contributors. 31 | 32 | ## License 33 | 34 | By contributing to plot_phylo, you agree that your contributions will be licensed under the MIT License. 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Katherine Brown, Duncan Cross 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Tests Passing](https://github.com/KatyBrown/plot_phylo/actions/workflows/main.yml/badge.svg)
2 | [![Documentation Status](https://readthedocs.org/projects/plot-phylo/badge/?version=latest)](https://plot-phylo.readthedocs.io/en/latest/?badge=latest)
3 | [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
4 | ![Python Version from PEP 621 TOML](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2FKatyBrown%2Fplot_phylo%2Frefs%2Fheads%2Fmain%2Fpyproject.toml)
5 | [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.13871592.svg)](https://doi.org/10.5281/zenodo.13871592)
6 | [![pyOpenSci Peer-Reviewed](https://pyopensci.org/badges/peer-reviewed.svg)](https://github.com/pyOpenSci/software-review/issues/issue-number) 7 | 8 | # plot_phylo 9 | 10 | ![Illustration](./examples/layered.png "Illustration") 11 | 12 | This module allows the user to plot a phylogenetic tree on an existing matplotlib axis. 13 | 14 | This means that: 15 | * Phylogenies can be incorporated into existing plots. 16 | * Annotations can be added using standard matplotlib functionality. 17 | * Plots can be output in png, pdf, svg or tiff formats. 18 | * Automatically generated and updated figures can include phylogenies 19 | 20 | Full documentation is available via [ReadTheDocs](https://plot-phylo.readthedocs.io/en/latest/index.html). 21 | 22 | The module depends on the [ETE Toolkit](http://etetoolkit.org/), an excellent existing Python framework for analysing and visualising phylogenetic trees, plus the [matplotlib](https://matplotlib.org/) visualisation library. It is designed to make generating complex figures incorporating phylogenies easier, as matplotlib plotting functions can be used on top of the basic tree. 23 | 24 | 25 | ## Installation 26 | 27 | **Requirements** 28 | 29 | * python >= 3.6 30 | * matplotlib >= 2.1.1 31 | * ete3 >= 3.1.0 32 | 33 | The module can be installed using pip 34 | 35 | `pip install plot_phylo` 36 | 37 | You can also download the latest release [here](https://github.com/KatyBrown/plot_phylo/releases/latest) 38 | 39 | Or clone the GitHub repository directly. 40 | 41 | `git clone git@github.com:KatyBrown/plot_phylo.git` 42 | 43 | ## Quick Start 44 | For detailed usage instructions, visit our [ReadTheDocs page](https://plot-phylo.readthedocs.io/en/latest/index.html). 45 | 46 | To draw a phylogeny under the default settings onto a blank figure. 47 | 48 | ``` 49 | import matplotlib.pyplot as plt 50 | import plot_phylo 51 | 52 | # Create an empty plot, 8in (width) by 10in (height) - matplotlib 53 | f = plt.figure(figsize=(8, 10)) 54 | 55 | # Add an axis - matplotlib 56 | ax = plt.subplot() 57 | 58 | # Plot the tree on this axis, using the default settings - plot_phylo 59 | results = plot_phylo.plot_phylo("examples/primates.nw", ax) 60 | 61 | # Save the tree - matplotlib 62 | plt.savefig("examples/basic_plot.png", bbox_inches='tight') 63 | ``` 64 | 65 | 66 | ## Cite 67 | 68 | If you use this repository in your work, please cite: 69 | 70 | Brown, K (2024) plot_phylo. https://github.com/KatyBrown/plot_phylo 71 | 72 | ## Continuous Integration 73 | I use GitHub Actions for continuous integration to ensure code quality. You can view the configuration [here](https://github.com/KatyBrown/plot_phylo/blob/main/.github/workflows/main.yml). 74 | -------------------------------------------------------------------------------- /citation.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | message: "If you use this repository in your work, please cite:" 3 | authors: 4 | - family-names: Brown 5 | given-names: Katy 6 | orcid: 0000-0002-8400-6922 7 | title: "plot_phylo" 8 | version: v0.0.11 9 | identifiers: 10 | - type: doi 11 | value: https://doi.org/10.5281/zenodo.13871592 12 | date-released: 2024-10-01 13 | url: "https://github.com/KatyBrown/plot_phylo" 14 | -------------------------------------------------------------------------------- /examples/align_tips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/align_tips.png -------------------------------------------------------------------------------- /examples/bad_tree.nw: -------------------------------------------------------------------------------- 1 | (A,B)C,D -------------------------------------------------------------------------------- /examples/basic_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/basic_plot.png -------------------------------------------------------------------------------- /examples/basic_plot_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/basic_plot_box.png -------------------------------------------------------------------------------- /examples/basic_tree.nw: -------------------------------------------------------------------------------- 1 | (((A,B)Z,C)Y,D)X; -------------------------------------------------------------------------------- /examples/big_tree.nw: -------------------------------------------------------------------------------- 1 | (((((((Allenopithecus_nigroviridis:0.065816, 2 | ((((((Cercopithecus_albogularis:0.013860,Cercopithecus_mitis:0.012114) 3 | 0.78:0.006600,Cercopithecus_nictitans:0.018792):0.013276, 4 | ((Cercopithecus_ascanius:0.008514,((Cercopithecus_cephus:0.001405, 5 | Cercopithecus_cephus_cephus:0.001305,Cercopithecus_cephus_ngottoensis:0.002081) 6 | 0.86:0.004399,Cercopithecus_erythrotis:0.008788)0.8:0.005502)0.8:0.004157, 7 | ((Cercopithecus_erythrogaster:0.000837, 8 | Cercopithecus_erythrogaster_erythrogaster:0.000919):0.004550, 9 | Cercopithecus_petaurista:0.006993):0.005431)0.86:0.016914)0.86:0.006369, 10 | (((((Cercopithecus_campbelli:0.001195,Cercopithecus_campbelli_lowei:0.001165) 11 | :0.006492,Cercopithecus_mona:0.014817)0.97:0.004305, 12 | (Cercopithecus_pogonias:0.010357,Cercopithecus_wolfi:0.010889):0.009444) 13 | :0.017547,(Cercopithecus_diana:0.021581,Cercopithecus_neglectus:0.036458) 14 | 0.51:0.002075):0.008361,Cercopithecus_hamlyni:0.044664)0.98:0.003859) 15 | 0.86:0.012020,((((Cercopithecus_lhoesti:0.014574,Cercopithecus_preussi:0.014924) 16 | :0.007247,Cercopithecus_solatus:0.020943)0.97:0.020680, 17 | Erythrocebus_patas:0.038673)0.8:0.003442,(((Chlorocebus_aethiops:0.008915, 18 | Chlorocebus_tantalus:0.009454):0.001636,(Chlorocebus_pygerythrus:0.004865, 19 | Chlorocebus_pygerythrus_cynosurus:0.004894):0.004945):0.010377, 20 | Chlorocebus_sabaeus:0.015210):0.026133)0.86:0.006077):0.009691, 21 | Miopithecus_talapoin:0.046434):0.001875)0.95:0.014993, 22 | (((((Cercocebus_agilis:0.003645,Cercocebus_galeritus:0.003935):0.015647, 23 | (Cercocebus_torquatus:0.001283,Cercocebus_torquatus_atys:0.000566) 24 | :0.020729):0.006580,(Mandrillus_leucophaeus:0.017471, 25 | Mandrillus_sphinx:0.018965):0.010307):0.031762, 26 | (((Lophocebus_albigena:0.004945,Lophocebus_aterrimus:0.003614):0.025255, 27 | Theropithecus_gelada:0.025377):0.005307,(((((Papio_anubis:0.005398, 28 | Papio_hamadryas:0.007828)0.79:0.002231,Papio_papio:0.012680)0.95:0.002545, 29 | Papio_cynocephalus:0.010235)0.99:0.004391,Papio_ursinus:0.011973):0.007851, 30 | Rungwecebus_kipunji:0.014553):0.008976):0.031669):0.008593, 31 | ((((Macaca_arctoides:0.022651,(Macaca_assamensis:0.018141, 32 | (Macaca_radiata:0.011489,Macaca_sinica:0.010875)0.97:0.003050)0.64:0.006345) 33 | 0.63:0.005197,((((((Macaca_brunnescens:0.013158,Macaca_ochreata:0.010245) 34 | :0.006461,Macaca_maura:0.020732):0.003432,Macaca_tonkeana:0.011691) 35 | 0.82:0.001666,Macaca_hecki:0.012052)0.82:0.001485,(Macaca_nigra:0.018941, 36 | Macaca_nigrescens:0.012369):0.002158):0.005032, 37 | (((((Macaca_leonina:0.007691,Macaca_nemestrina_siberu:0.008702)0.6:0.001016, 38 | Macaca_nemestrina_leonina:0.016715):0.004060,Macaca_pagensis:0.023514) 39 | :0.004315,Macaca_silenus:0.017416):0.007441, 40 | Macaca_nemestrina:0.013445):0.006656):0.020308, 41 | (Macaca_cyclopis:0.005307,Macaca_fuscata:0.009086):0.013362)0.57:0.006759, 42 | ((Macaca_fascicularis:0.026909,Macaca_mulatta:0.022634):0.006799, 43 | (Macaca_munzala:0.018582,Macaca_thibetana:0.023711)0.63:0.011192)0.6:0.001485) 44 | 0.95:0.012457,Macaca_sylvanus:0.043875)0.95:0.028682)0.95:0.014824) 45 | :0.046493,(((((Colobus_angolensis:0.000125, 46 | Colobus_angolensis_palliatus:0.000105):0.020989,(Colobus_guereza:0.011442, 47 | (Colobus_polykomos:0.000982,Colobus_vellerosus:0.002608):0.010667) 48 | :0.007269):0.014119,Colobus_satanas:0.032119):0.035146, 49 | ((Piliocolobus_badius:0.024063,((Piliocolobus_foai:0.022262, 50 | (Piliocolobus_pennantii:0.002940,Piliocolobus_preussi:0.002641):0.019300) 51 | :0.005072,((Piliocolobus_gordonorum:0.006356,Piliocolobus_kirkii:0.005124) 52 | :0.007611,((Piliocolobus_rufomitratus:0.007720, 53 | Piliocolobus_tephrosceles:0.006869):0.002891, 54 | Piliocolobus_tholloni:0.006978):0.006439):0.012551)0.99:0.004559) 55 | :0.031248,Procolobus_verus:0.047511):0.009894):0.016190, 56 | ((((Nasalis_larvatus:0.051034,(Pygathrix_cinerea:0.002499, 57 | Pygathrix_nemaeus:0.001834):0.060762)0.99:0.005543, 58 | (((Rhinopithecus_avunculus:0.017014,Rhinopithecus_roxellana:0.007028) 59 | 0.99:0.007293,Rhinopithecus_brelichi:0.010579)0.71:0.004421, 60 | Rhinopithecus_bieti:0.017198):0.031706):0.014196, 61 | (((Semnopithecus_entellus:0.019652,Trachypithecus_johnii:0.022593)0.94:0.006480, 62 | ((Trachypithecus_geei:0.001274,Trachypithecus_pileatus:0.002279):0.009016, 63 | Trachypithecus_vetulus:0.025246)0.56:0.005831):0.041104, 64 | ((((Trachypithecus_auratus:0.007990,Trachypithecus_germaini:0.008893) 65 | 0.66:0.002498,Trachypithecus_cristatus:0.005572):0.015606, 66 | Trachypithecus_obscurus:0.017118)0.98:0.006719, 67 | (((Trachypithecus_delacouri:0.005478,(Trachypithecus_francoisi:0.006483, 68 | Trachypithecus_poliocephalus:0.002673):0.010527)0.97:0.003697, 69 | Trachypithecus_laotum:0.006360):0.008411,Trachypithecus_phayrei:0.021237) 70 | 0.98:0.005935):0.031403):0.007808)0.86:0.003543, 71 | (Presbytis_comata:0.036913,Presbytis_melalophos:0.029364):0.047027) 72 | :0.016653):0.048916):0.086552,((Bunopithecus_hoolock:0.031110, 73 | ((((((Hylobates_agilis:0.014406,Hylobates_klossii:0.015010):0.005782, 74 | Hylobates_moloch:0.020550,Hylobates_muelleri:0.017599)0.96:0.001746, 75 | Hylobates_lar:0.016494):0.003994,Hylobates_pileatus:0.018978) 76 | :0.017010,Symphalangus_syndactylus:0.030998)0.8:0.004654, 77 | ((Nomascus_concolor:0.009294,(Nomascus_gabriellae:0.005583, 78 | (Nomascus_leucogenys:0.003795,Nomascus_siki:0.001677):0.002317) 79 | :0.006525):0.005662,Nomascus_nasutus:0.016713):0.024799) 80 | 0.52:0.006066):0.060820,((((Gorilla_beringei:0.000360, 81 | Gorilla_gorilla_graueri:0.000345):0.011260, 82 | Gorilla_gorilla_gorilla:0.013629):0.028212,((Homo_sapiens:0.004478, 83 | Homo_sapiens_neanderthalensis:0.002006):0.035475,(Pan_paniscus:0.012528, 84 | ((Pan_troglodytes_schweinfurthii:0.001361,Pan_troglodytes_troglodytes:0.001940) 85 | :0.003177,(Pan_troglodytes_vellerosus:0.002714, 86 | Pan_troglodytes_verus:0.002822):0.003344):0.006133):0.019348) 87 | :0.015261):0.036137,(Pongo_abelii:0.019928,Pongo_pygmaeus:0.021940) 88 | :0.064721):0.027204):0.064662):0.094920, 89 | ((((((Alouatta_belzebul:0.015587,(Alouatta_palliata:0.010239, 90 | Alouatta_pigra:0.010328):0.014362)0.53:0.003321,(Alouatta_caraya:0.012809, 91 | (Alouatta_sara:0.010545,Alouatta_seniculus:0.012970)0.98:0.004310)0.99:0.005028) 92 | 0.78:0.004743,Alouatta_guariba:0.008782):0.037322, 93 | (((Ateles_belzebuth:0.007819,(Ateles_fusciceps:0.005704, 94 | Ateles_geoffroyi:0.014156)0.96:0.004359)0.63:0.004381,Ateles_paniscus:0.009993) 95 | :0.034141,(Brachyteles_arachnoides:0.011287,Lagothrix_lagotricha:0.012368) 96 | :0.032861):0.027579):0.022124,((((((Aotus_azarai:0.000135, 97 | Aotus_azarai_boliviensis:0.000151):0.001661,Aotus_infulatus:0.003446) 98 | :0.004772,Aotus_nigriceps:0.007302):0.014604, 99 | ((Aotus_brumbacki:0.002009,Aotus_vociferans:0.002558):0.010875, 100 | Aotus_nancymaae:0.016228)0.92:0.002961,((Aotus_lemurinus:0.001878, 101 | Aotus_trivirgatus:0.001054)0.97:0.000668,Aotus_lemurinus_griseimembra:0.000924) 102 | :0.009297):0.055058,(((Callimico_goeldii:0.076481, 103 | ((((Callithrix_argentata:0.006271,Callithrix_emiliae:0.001912)0.66:0.002737, 104 | (Callithrix_humeralifera:0.005291,Callithrix_mauesi:0.003621):0.007525) 105 | :0.017031,Callithrix_pygmaea:0.027061):0.013382, 106 | (Callithrix_aurita:0.025467,(Callithrix_geoffroyi:0.004585, 107 | (Callithrix_jacchus:0.001363,(Callithrix_kuhli:0.007830, 108 | Callithrix_penicillata:0.002379)0.99:0.002090)0.93:0.003304):0.011924) 109 | :0.015503):0.037810):0.011944, 110 | (Leontopithecus_chrysomelas:0.003481,(Leontopithecus_chrysopygus:0.003547, 111 | Leontopithecus_rosalia:0.005081):0.007293):0.080225)0.99:0.004992, 112 | ((((Saguinus_bicolor:0.018180,(Saguinus_midas:0.006711,Saguinus_niger:0.016352) 113 | :0.014474)0.99:0.022551,((Saguinus_geoffroyi:0.004858, 114 | Saguinus_oedipus:0.006707):0.028025,Saguinus_leucopus:0.060456) 115 | 0.77:0.008026)0.96:0.010259,(Saguinus_imperator:0.017040, 116 | Saguinus_mystax:0.040198)0.93:0.028754)0.87:0.018197, 117 | ((Saguinus_fuscicollis:0.003201,Saguinus_fuscicollis_melanoleucus:0.002369) 118 | 0.96:0.033887,Saguinus_tripartitus:0.010934)0.57:0.023244)0.99:0.028999) 119 | :0.035446)0.99:0.004629,((((Cebus_albifrons:0.001063, 120 | Cebus_olivaceus:0.004049)0.93:0.004414,Cebus_capucinus:0.018662):0.024918, 121 | (Cebus_apella:0.016152,Cebus_xanthosternos:0.020026):0.014667) 122 | :0.069328,(Saimiri_boliviensis:0.011358,((Saimiri_oerstedii:0.008268, 123 | Saimiri_sciureus:0.007335)0.75:0.001495,Saimiri_ustus:0.010762)0.53:0.003319) 124 | :0.120384):0.011930):0.012600):0.011861, 125 | (((Cacajao_calvus:0.008953,Cacajao_melanocephalus:0.012109, 126 | Chiropotes_satanas:0.011244)0.91:0.028074,(Pithecia_irrorata:0.034176, 127 | Pithecia_pithecia:0.013701)0.68:0.029634):0.041692, 128 | (((Callicebus_donacophilus:0.020386,(Callicebus_hoffmannsi:0.015942, 129 | Callicebus_moloch:0.009425):0.010470):0.021386, 130 | Callicebus_personatus:0.040442)0.95:0.020255,Callicebus_torquatus:0.035529) 131 | :0.041722):0.012517):0.167153):0.162404, 132 | ((Tarsius_bancanus:0.080699,Tarsius_syrichta:0.084065):0.039296, 133 | (Tarsius_dentatus:0.006828,Tarsius_lariang:0.014282):0.088597) 134 | :0.167909):0.024775,(((((((Allocebus_trichotis:0.078279, 135 | ((((Microcebus_berthae:0.005920,(Microcebus_griseorufus:0.041207, 136 | Microcebus_murinus:0.016437):0.013261):0.011019, 137 | Microcebus_myoxinus:0.010012)0.6:0.005334, 138 | (((((((Microcebus_bongolavensis:0.004322,Microcebus_ravelobensis:0.005136) 139 | :0.013717,Microcebus_danfossi:0.013735):0.009083, 140 | Microcebus_macarthurii:0.023469):0.009893,Microcebus_tavaratra:0.027595) 141 | 0.76:0.002850,Microcebus_jollyae:0.022892)0.97:0.003475, 142 | (Microcebus_mittermeieri:0.017277,(Microcebus_rufus:0.007219, 143 | Microcebus_simmonsi:0.010541):0.005362)0.57:0.001463)0.81:0.002670, 144 | ((Microcebus_lokobensis:0.001641,Microcebus_sambiranensis:0.001470) 145 | :0.011092,Microcebus_mamiratra:0.015885):0.007721):0.008733, 146 | Microcebus_lehilahytsara:0.008179):0.052497,(Mirza_coquereli:0.000847, 147 | Mirza_zaza:0.000534):0.079910):0.017206):0.036861, 148 | ((Cheirogaleus_crossleyi:0.044155,Cheirogaleus_major:0.032682):0.018292, 149 | Cheirogaleus_medius:0.052283):0.048822):0.032901, 150 | ((((((((Lepilemur_aeeclis:0.002036,Lepilemur_mitsinjoensis:0.021906) 151 | 0.97:0.003956,Lepilemur_edwardsi:0.018488)0.96:0.010099, 152 | Lepilemur_randrianasoli:0.014555)0.96:0.004313,(Lepilemur_hubbardorum:0.011342, 153 | Lepilemur_ruficaudatus:0.008856):0.009237)0.96:0.014181, 154 | Lepilemur_leucopus:0.036100)0.96:0.010323,((((Lepilemur_ankaranensis:0.011054, 155 | Lepilemur_dorsalis:0.010395)0.87:0.002036,Lepilemur_sahamalazensis:0.014032) 156 | :0.013674,Lepilemur_septentrionalis:0.027641):0.010267, 157 | ((Lepilemur_manasamody:0.008173,Lepilemur_otto:0.008277)0.96:0.013927, 158 | Lepilemur_microdon:0.020449)0.96:0.008283)0.96:0.008388):0.032540, 159 | (Lepilemur_mustelinus:0.001281,Lepilemur_seali:0.002320):0.061597) 160 | :0.074353,(Phaner_furcifer:0.000205,Phaner_furcifer_pallescens:0.000214) 161 | :0.145436):0.017959):0.017696,((Archaeolemur_majori:0.104604, 162 | Indri_indri:0.060595)0.55:0.018716,((((Avahi_cleesei:0.006862, 163 | Avahi_occidentalis:0.007624)0.59:0.001352,Avahi_unicolor:0.006083) 164 | :0.028253,Avahi_laniger:0.031231):0.058600, 165 | (((Propithecus_coquereli:0.002901,Propithecus_tattersalli:0.004434) 166 | :0.015089,(Propithecus_deckenii:0.001886,Propithecus_verreauxi:0.004016) 167 | :0.013398):0.012331,(Propithecus_diadema:0.007121, 168 | Propithecus_edwardsi:0.002797):0.024681):0.036451)0.95:0.018741) 169 | :0.038006)0.99:0.013212,(((Eulemur_coronatus:0.022785, 170 | ((((((Eulemur_fulvus_albifrons:0.001415,Eulemur_fulvus_sanfordi:0.001102) 171 | :0.002176,(Eulemur_fulvus_fulvus:0.000606, 172 | Eulemur_fulvus_mayottensis:0.001497):0.003124):0.005568, 173 | (Eulemur_fulvus_albocollaris:0.003826,Eulemur_fulvus_collaris:0.004830) 174 | :0.005450):0.008709,Eulemur_rubriventer:0.019121)0.71:0.001645, 175 | (Eulemur_fulvus_rufus:0.022882,Eulemur_mongoz:0.010986):0.010930) 176 | :0.007215,(Eulemur_macaco_flavifrons:0.010375, 177 | Eulemur_macaco_macaco:0.007914):0.012571)0.74:0.003619):0.041910, 178 | (((Hapalemur_aureus:0.028340,((((Hapalemur_griseus:0.000184, 179 | Hapalemur_griseus_meridionalis:0.002911):0.005525, 180 | Hapalemur_griseus_occidentalis:0.001983):0.003136, 181 | Hapalemur_griseus_alaotrensis:0.008788)0.9:0.001673, 182 | Hapalemur_griseus_griseus:0.002835):0.025442):0.014357, 183 | Hapalemur_simus:0.043406)0.98:0.006411,Lemur_catta:0.034858):0.026148) 184 | :0.022025,(Varecia_rubra:0.008226,Varecia_variegata_variegata:0.004268) 185 | :0.091121):0.045718):0.074221, 186 | Daubentonia_madagascariensis:0.206530):0.035687, 187 | ((((Arctocebus_aureus:0.002153,Arctocebus_calabarensis:0.007092):0.081288, 188 | Perodicticus_potto:0.089044):0.066707,((Loris_lydekkerianus:0.003166, 189 | Loris_tardigradus:0.004631):0.118705,((((Nycticebus_bengalensis:0.001537, 190 | Nycticebus_coucang:0.001595):0.004504,Nycticebus_menagensis:0.021267) 191 | :0.005041,Nycticebus_javanicus:0.010613):0.029946, 192 | Nycticebus_pygmaeus:0.038061):0.073681):0.049750):0.012686, 193 | (((((Euoticus_elegantulus:0.017868,Galago_matschiei:0.013979):0.021645, 194 | (Galago_gallarum:0.010936,(Galago_moholi:0.006862,Galago_senegalensis:0.005593) 195 | 0.67:0.006937)0.98:0.013060):0.035739,(Galago_granti:0.007914, 196 | Galagoides_zanzibaricus:0.008976):0.031630):0.015599, 197 | (Galago_alleni:0.037953,(Otolemur_crassicaudatus:0.006368, 198 | Otolemur_garnettii:0.002019):0.036960):0.021160):0.017438, 199 | Galagoides_demidoff:0.070753):0.075670):0.159023):0.044877); -------------------------------------------------------------------------------- /examples/bold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/bold.png -------------------------------------------------------------------------------- /examples/colours.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/colours.png -------------------------------------------------------------------------------- /examples/from_string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/from_string.png -------------------------------------------------------------------------------- /examples/height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/height.png -------------------------------------------------------------------------------- /examples/labels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/labels.png -------------------------------------------------------------------------------- /examples/layered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/layered.png -------------------------------------------------------------------------------- /examples/nobranchlengths.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/nobranchlengths.png -------------------------------------------------------------------------------- /examples/nobranchlengths_ali.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/nobranchlengths_ali.png -------------------------------------------------------------------------------- /examples/primates.nw: -------------------------------------------------------------------------------- 1 | ((((((Cercopithecus neglectus:0.089332,Macaca mulatta:0.086881)1:0.046493,Colobus angolensis:0.135485)1:0.086552,((Hylobates lar:0.042152,Nomascus leucogenys:0.043098)0.52:0.066886,((Gorilla gorilla:0.041841,(Homo sapiens:0.039953,Pan troglodytes:0.030598)1:0.015261)1:0.036137,Pongo abelii:0.084649)1:0.027204)1:0.064662)1:0.094920,((Lagothrix lagotricha:0.094932,Saimiri boliviensis:0.156272)1:0.011861,Chiropotes satanas:0.093527)1:0.167153)1:0.162404,Tarsius syrichta:0.291270)1:0.024775,(Lemur catta:0.238657,(Loris tardigradus:0.185772,Galago moholi:0.171305)1:0.159023)1:0.044877):0.01; -------------------------------------------------------------------------------- /examples/primates_mixed.nw: -------------------------------------------------------------------------------- 1 | ((((((Cercopithecus neglectus:0.089332,Macaca mulatta:0.086881)1:0.046493,Colobus angolensis:0.335485)1:0.086552,((Hylobates lar:0.042152,Nomascus leucogenys:0.043098)0.52:0.066886,((Pan troglodytes:0.051841,(Homo sapiens:0.039953,Gorilla gorilla:0.020598)1:0.015261)1:0.036137,Pongo abelii:0.084649)1:0.027204)1:0.064662)1:0.094920,((Lagothrix lagotricha:0.094932,Chiropotes satanas:0.156272)1:0.011861,Saimiri boliviensis:0.193527)1:0.167153)1:0.162404,Tarsius syrichta:0.291270)1:0.024775,(Lemur catta:0.238657,(Loris tardigradus:0.185772,Galago moholi:0.171305)1:0.159023)1:0.044877):0.01; -------------------------------------------------------------------------------- /examples/rev_align_tips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/rev_align_tips.png -------------------------------------------------------------------------------- /examples/reversed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/reversed.png -------------------------------------------------------------------------------- /examples/tree_pos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/tree_pos.png -------------------------------------------------------------------------------- /examples/width.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/width.png -------------------------------------------------------------------------------- /examples/xpos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/xpos.png -------------------------------------------------------------------------------- /examples/ypos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/examples/ypos.png -------------------------------------------------------------------------------- /man/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /man/conf.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import sphinx_rtd_theme 4 | sys.path.insert(0, "../plot_phylo") 5 | sys.path.insert(0, os.path.abspath("..")) 6 | autodoc_mock_imports = ['ete3'] 7 | # -- Project information ----------------------------------------------------- 8 | 9 | project = 'plot_phylo' 10 | copyright = '2024 Katy Brown, Duncan Cross' 11 | author = 'Katy Brown, Duncan Cross' 12 | 13 | # The full version, including alpha/beta/rc tags 14 | release = '0.1.6' 15 | 16 | 17 | # -- General configuration --------------------------------------------------- 18 | 19 | # Add any Sphinx extension module names here, as strings. They can be 20 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 21 | # ones. 22 | extensions = ['recommonmark', 'sphinx_markdown_tables', 'sphinx.ext.autodoc'] 23 | 24 | # Add any paths that contain templates here, relative to this directory. 25 | templates_path = ['_templates'] 26 | 27 | # List of patterns, relative to source directory, that match files and 28 | # directories to ignore when looking for source files. 29 | # This pattern also affects html_static_path and html_extra_path. 30 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 31 | 32 | source_suffix = ['.rst', '.md'] 33 | 34 | root_doc = 'contents' 35 | 36 | # -- Options for HTML output ------------------------------------------------- 37 | 38 | # The theme to use for HTML and HTML Help pages. See the documentation for 39 | # a list of builtin themes. 40 | # 41 | html_theme = "sphinx_rtd_theme" 42 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 43 | 44 | # Add any paths that contain custom static files (such as style sheets) here, 45 | # relative to this directory. They are copied after the builtin static files, 46 | # so a file named "default.css" will overwrite the builtin "default.css". 47 | html_static_path = ['_static'] 48 | -------------------------------------------------------------------------------- /man/contents.rst: -------------------------------------------------------------------------------- 1 | plot_phylo 2 | ========== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | index.md 8 | pages/installation.md 9 | pages/testing.md 10 | pages/quickstart.md 11 | pages/parameters.md 12 | pages/matplotlib.md 13 | pages/functions.rst 14 | pages/detailed.md 15 | -------------------------------------------------------------------------------- /man/index.md: -------------------------------------------------------------------------------- 1 | # plot_phylo 2 | ![Illustration](pages/examples/layered.png "Illustration") 3 | 4 | This module allows the user to plot a phylogenetic tree on an existing matplotlib axis. 5 | 6 | This means that: 7 | * Phylogenies can be incorporated into existing plots. 8 | * Annotations can be added using standard matplotlib functionality. 9 | * Plots can be output in png, pdf, svg or tiff formats. 10 | * Automatically generated and updated figures can include phylogenies 11 | 12 | 1. [Installation](pages/installation.md) 13 | 2. [Testing](pages/testing.md) 14 | 3. [Quick Start](pages/quickstart.md) 15 | 4. [Parameters](pages/parameters.md) 16 | 5. [Incorporating Matplotlib Elements](pages/matplotlib.md) 17 | 6. [Functions](pages/functions.html) 18 | 7. [Detailed Example](pages/detailed.md) 19 | 20 | The module depends on the [ETE Toolkit](http://etetoolkit.org/), an excellent existing Python framework for analysing and visualising phylogenetic trees, plus the [matplotlib](https://matplotlib.org/) visualisation library. 21 | -------------------------------------------------------------------------------- /man/pages/detailed.md: -------------------------------------------------------------------------------- 1 | # Detailed Example 2 | This detailed example shows how `plot_phylo` can be combined with matplotlib and basic Python to draw complex plots. 3 | 4 | ``` 5 | # Build the blank figure 6 | f = plt.figure(figsize=(15, 10)) 7 | ax = plt.subplot(1, 1, 1) 8 | 9 | # Set the x and y axis limits 10 | ax.set_xlim(2, 122) 11 | ax.set_ylim(9, 21) 12 | ypos_val = 10 13 | 14 | # Define colours for specific nodes 15 | colours = {'Gorilla gorilla': '#e21c0c', 'Pan troglodytes': '#0c57e2', 'Saimiri boliviensis': '#338c3e', 16 | 'Chiropotes satanas': '#dc9d0c'} 17 | 18 | # Draw the left tree 19 | results_left = plot_phylo.plot_phylo("primates.nw", 20 | ax, xpos=5, ypos=ypos_val, width=15, 21 | show_axis=False, show_support=False, 22 | font_size=16, col_dict=colours, 23 | rev_align_tips=True) 24 | 25 | # Draw the right tree 26 | results_right = plot_phylo.plot_phylo("primates_mixed.nw", 27 | ax, xpos=105, ypos=10, width=15, 28 | show_axis=False, show_support=False, 29 | reverse=True, 30 | font_size=16, col_dict=colours, 31 | rev_align_tips=True) 32 | 33 | # Using matplotlib and basic Python functionality on the returned dictionaries from hereforward 34 | 35 | # Connection between trees 36 | 37 | # Find the labels which differ between trees 38 | links = [] 39 | for r1 in results_left: 40 | # Find the index of each label in the tree 41 | ind1 = results_left[r1]['index'] 42 | ind2 = results_right[r1]['index'] 43 | 44 | # If they differ, store them 45 | if ind1 != ind2: 46 | links.append(r1) 47 | 48 | for link in links: 49 | # Retrieve the positions of the non-matched labels 50 | left_box = results_left[link] 51 | right_box = results_right[link] 52 | 53 | # Get the position of the labels in each tree 54 | left_x = left_box['xmax'] + 1 55 | left_y = left_box['ymid'] 56 | 57 | right_x = right_box['xmin'] - 1 58 | right_y = right_box['ymid'] 59 | 60 | # Plot the points on the left tree 61 | ax.scatter(left_x, left_y, color=colours[link]) 62 | 63 | # Plot the points on the right tree 64 | ax.scatter(right_x, right_y, color=colours[link]) 65 | 66 | # Connect the two points 67 | ax.plot([left_x, right_x], [left_y, right_y], color=colours[link]) 68 | 69 | # Box highlighting great apes 70 | # Define which species are great apes 71 | great_apes = ['Gorilla gorilla', 'Pan troglodytes', 'Homo sapiens', 'Pongo abelii'] 72 | ga_pos = [] 73 | 74 | # Store the positions of the great ape labels 75 | for nam, box in results_left.items(): 76 | if nam in great_apes: 77 | ga_pos.append(box['ymin']) 78 | ga_pos.append(box['ymax']) 79 | 80 | # Draw the grey box. 15.5 is based on visually inspecting the axis. 81 | ax.fill_between([15.5, box['xmax']], min(ga_pos), max(ga_pos), color='lightgrey') 82 | 83 | # Additional labels 84 | # Add the Tree 1 and Tree 2 labels, using figure co-ordinates 85 | f.text(0.2, 0.85, 'Tree 1', ha='center', fontsize=16, fontweight='bold') 86 | f.text(0.8, 0.85, 'Tree 2', ha='center', fontsize=16, fontweight='bold') 87 | 88 | # Add the overall title 89 | f.suptitle("Primate Phylogeny", fontsize=24, y=0.92) 90 | 91 | # Save 92 | f.savefig("examples/layered.png", bbox_inches='tight') 93 | ``` 94 | 95 | ![Detailed Example](./examples/layered.png "Detailed Example") 96 | -------------------------------------------------------------------------------- /man/pages/examples/align_tips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/align_tips.png -------------------------------------------------------------------------------- /man/pages/examples/basic_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/basic_plot.png -------------------------------------------------------------------------------- /man/pages/examples/basic_plot_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/basic_plot_box.png -------------------------------------------------------------------------------- /man/pages/examples/bold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/bold.png -------------------------------------------------------------------------------- /man/pages/examples/colours.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/colours.png -------------------------------------------------------------------------------- /man/pages/examples/from_string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/from_string.png -------------------------------------------------------------------------------- /man/pages/examples/height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/height.png -------------------------------------------------------------------------------- /man/pages/examples/labels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/labels.png -------------------------------------------------------------------------------- /man/pages/examples/layered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/layered.png -------------------------------------------------------------------------------- /man/pages/examples/nobranchlengths.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/nobranchlengths.png -------------------------------------------------------------------------------- /man/pages/examples/nobranchlengths_ali.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/nobranchlengths_ali.png -------------------------------------------------------------------------------- /man/pages/examples/primates.nw: -------------------------------------------------------------------------------- 1 | ((((((Cercopithecus neglectus:0.089332,Macaca mulatta:0.086881)1:0.046493,Colobus angolensis:0.135485)1:0.086552,((Hylobates lar:0.042152,Nomascus leucogenys:0.043098)0.52:0.066886,((Gorilla gorilla:0.041841,(Homo sapiens:0.039953,Pan troglodytes:0.030598)1:0.015261)1:0.036137,Pongo abelii:0.084649)1:0.027204)1:0.064662)1:0.094920,((Lagothrix lagotricha:0.094932,Saimiri boliviensis:0.156272)1:0.011861,Chiropotes satanas:0.093527)1:0.167153)1:0.162404,Tarsius syrichta:0.291270)1:0.024775,(Lemur catta:0.238657,(Loris tardigradus:0.185772,Galago moholi:0.171305)1:0.159023)1:0.044877):0.01; -------------------------------------------------------------------------------- /man/pages/examples/rev_align_tips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/rev_align_tips.png -------------------------------------------------------------------------------- /man/pages/examples/reversed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/reversed.png -------------------------------------------------------------------------------- /man/pages/examples/tree_pos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/tree_pos.png -------------------------------------------------------------------------------- /man/pages/examples/width.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/width.png -------------------------------------------------------------------------------- /man/pages/examples/xpos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/xpos.png -------------------------------------------------------------------------------- /man/pages/examples/ypos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/man/pages/examples/ypos.png -------------------------------------------------------------------------------- /man/pages/functions.rst: -------------------------------------------------------------------------------- 1 | Functions 2 | ====================== 3 | 4 | .. automodule:: plot_phylo.plot_phylo 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /man/pages/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | **Requirements** 4 | 5 | * python >= 3.6 6 | * matplotlib >= 2.1.1 7 | * ete3 >= 3.1.0 8 | 9 | The module can be installed using pip 10 | 11 | `pip install plot_phylo` 12 | 13 | You can also download the latest release [here](https://github.com/KatyBrown/plot_phylo/releases/latest) 14 | 15 | Or clone the GitHub repository directly. 16 | 17 | `git clone https://github.com/KatyBrown/plot_phylo.git` 18 | 19 | If cloning directly, matplotlib and ete3 need to be installed, e.g. via pip or conda. 20 | 21 | 22 | -------------------------------------------------------------------------------- /man/pages/matplotlib.md: -------------------------------------------------------------------------------- 1 | # Adding Matplotlib Elements to your Tree 2 | One of the main advantages of this module is that, as plots are generated using matplotlib and added to an active axis, other elements of matplotlib plots can be incorporated - the plot remains activate and can be edited. 3 | 4 | The plot_phylo function returns a dictionary where the keys are the tip labels and the values are the boundaries of the text boxes containing the tip labels, in axis units. 5 | 6 | For example, the first few items in the list returned from the function call above are as follows: 7 | 8 | 9 | ``` 10 | {'Cercopithecus neglectus': {'index': 0, 11 | 'xmin': 9.656, 12 | 'xmax': 16.336, 13 | 'ymin': 9.882, 14 | 'ymax': 10.118, 15 | 'ymid': 10.0, 16 | 'xmid': 12.883}, 17 | 'Macaca mulatta': {'index': 1, 18 | 'xmin': 9.609, 19 | 'xmax': 14.2, 20 | 'ymin': 9.215, 21 | 'ymax': 9.452, 22 | 'ymid': 9.333, 23 | 'xmid': 12.101}, 24 | 'Colobus angolensis': {'index': 2, 25 | 'xmin': 9.649, 26 | 'xmax': 15.016, 27 | 'ymin': 8.548, 28 | 'ymax': 8.785, 29 | 'ymid': 8.667, 30 | 'xmid': 12.883}, 31 | ... 32 | ``` 33 | 34 | `xmin`, `xmid` and `xmax` are the positions of the left, centre and right of the tip label text on the x-axis. 35 | 36 | `ymin`, `ymid` and `ymax` are the positions of the bottom, centre and top of the tip label text on the y-axis. 37 | 38 | `ind` is the position of this label on the tree, reading from top to bottom, starting at 0. 39 | 40 | For example, for the first list item, Cercopithecus neglectus is the tip label. On the plot, this label spans positions 9.656 to 16.336 on the x-axis and 9.882 to 10.118 on the y axis. It is at position 0 in the tree. 41 | 42 | 43 | Providing these positions allows the user to add annotations etc. to the tip labels using matplotlib after drawing the plot. 44 | 45 | For example, here, the boundary box is of the first tip label is marked on the tree. 46 | 47 | ``` 48 | f = plt.figure(figsize=(8, 10)) 49 | a = plt.subplot() 50 | 51 | # To use the text positions, the axis limits should be explicitly 52 | # specified before the plot is drawn 53 | 54 | plt.xlim(-2, 20) 55 | plt.ylim(-2, 11) 56 | 57 | # Draw the tree 58 | results = plot_phylo.plot_phylo("examples/primates.nw", a) 59 | 60 | # Retrieve the first result - for C. neglectus 61 | c_neg_results = results['Cercopithecus neglectus'] 62 | 63 | # Plot these points on the axis 64 | # Bottom left 65 | plt.scatter(c_neg_results['xmin'], c_neg_results['ymin'], color='green', s=15) 66 | # Top left 67 | plt.scatter(c_neg_results['xmin'], c_neg_results['ymax'], color='red', s=15) 68 | # Bottom right 69 | plt.scatter(c_neg_results['xmax'], c_neg_results['ymin'], color='blue', s=15) 70 | # Top right 71 | plt.scatter(c_neg_results['xmax'], c_neg_results['ymax'], color='orange', s=15) 72 | 73 | # Save 74 | f.savefig("examples/basic_plot_box.png", bbox_inches='tight') 75 | 76 | ``` 77 | ![Basic tree with box](./examples/basic_plot_box.png "Basic tree with box") 78 | 79 | -------------------------------------------------------------------------------- /man/pages/parameters.md: -------------------------------------------------------------------------------- 1 | # Usage and Parameters 2 | 3 | Detailed descriptions of all parameters are provided below. 4 | 5 | *Required* 6 | 7 | * [tree](#tree) - tree file 8 | * [ax](#ax) - matplotlib axis 9 | 10 | *Positioning the plot on the axis* 11 | 12 | * [xpos](#xpos) - x-axis position 13 | * [ypos](#ypos) - y-axis position 14 | * [height](#height) - tree height 15 | * [width](#width) - tree width 16 | 17 | *Visualisation options* 18 | 19 | * [show_axis](#show-axis) - show x and y axis on plot 20 | * [show_support](#show-support) - show branch support 21 | * [align_tips](#align-tips) - left align tip labels 22 | * [rev_align_tips](#rev-align-tips) - right align tip labels 23 | * [branch_lengths](#branch-lengths) - scale branch lengths 24 | * [scale_bar](#scale-bar) - show scale bar 25 | * [scale_bar_width](#scale-bar-width) - set scale bar width 26 | * [reverse](#reverse) - mirror the tree, show root on right side 27 | * [outgroup](#outgroup) - set the outgroup 28 | * [col_dict](#col-dict) - set tip label colours 29 | * [label_dict](#label-dict) - relabel tips 30 | * [font_size](#font-size) - set font size 31 | * [line_col](#line-col) - set line colour 32 | * [line_width](#line-width) - set line width 33 | * [bold](#bold) - highlight tip labels in bold 34 | 35 | The primate tree used in these examples is from the [10K trees](https://10ktrees.nunn-lab.org/) project and is illustrative only. 36 | 37 | 38 | 39 | ## Required 40 | ### `tree` 41 | (`str`, Required) 42 | 43 | Either the path to a newick formatted tree or a string containing a newick formatted tree. 44 | 45 | e.g. 46 | A string containing a newick formatted tree 47 | 48 | ``` 49 | # Store the newick data as a string 50 | tree = "((A:0.1,B:0.2)0.5,C:0.3)0.95:0.1;" 51 | 52 | # Generate a matplotlib figure 53 | f = plt.figure(figsize=(5, 5)) 54 | 55 | # Add an axis 56 | ax = plt.subplot() 57 | 58 | # Set the axis limits 59 | ax.set_xlim(-1, 15) 60 | ax.set_ylim(-5, 11) 61 | 62 | # Visualise the tree 63 | results = plot_phylo.plot_phylo(tree, ax) 64 | 65 | # Save the image 66 | f.savefig("examples/from_string.png", bbox_inches='tight') 67 | 68 | ``` 69 | ![from_string](examples/from_string.png) 70 | 71 | A file containing a newick formatted tree, such as [primates.nw](https://raw.githubusercontent.com/KatyBrown/plot_phylo/main/examples/primates.nw). 72 | 73 | ``` 74 | # Generate a matplotlib figure 75 | f = plt.figure(figsize=(8, 10)) 76 | 77 | # Add an axis 78 | ax = plt.subplot() 79 | 80 | # Plot the tree on this axis, `examples/primates.nw` is the path to the tree 81 | results = plot_phylo.plot_phylo("examples/primates.nw", ax) 82 | 83 | # Save the image 84 | plt.savefig("examples/basic_plot.png", bbox_inches='tight') 85 | 86 | ``` 87 | ![Basic Tree](./examples/basic_plot.png "Basic Tree") 88 | 89 | ### `ax` 90 | (`matplotlib.axes._axes.Axes`, Required) 91 | 92 | An open matplotlib ax object where the tree will be plotted. Required. 93 | 94 | To generate a basic plot with a single subplot: 95 | ``` 96 | import matplotlib.pyplot as plt 97 | 98 | # Make an empty figure 99 | my_figure = plt.figure() 100 | 101 | # Add an empty subplot 102 | my_subplot = my_figure.add_subplot(111) 103 | ``` 104 | 105 | The object `my_subplot` is then passed to plot phylo and the tree will be plotted onto this axis. 106 | 107 | ``` 108 | results = plot_phylo.plot_phylo("examples/primates.nw", my_subplot) 109 | ``` 110 | 111 | More details about using matplotlib via this object oriented interface are available [here](https://www.tutorialspoint.com/matplotlib/matplotlib_object_oriented_interface.htm). 112 | 113 | The advantage of this approach is that you can continue to add features to this plot directly using matplotlib or incorporate your phylogeny into an existing plot. 114 | 115 | ## Positioning the Plot 116 | Using the `xpos`, `ypos`, `height` and `width` parameters, the exact location of the tree within the axis can be specified. 117 | 118 | **`xpos`** defines the position of the most ancestral node in the tree on the x-axis, excluding the root. In the example tree, this is the split between the bottom three species (lemur, loris and galago) and the remaining primates. 119 | 120 | **`ypos`** defines the position of the bottom branch of the tree, on the y-axis. In the example tree, this is the branch leading to *Galago moholi*. 121 | 122 | **`width`** defines the width of the tree, excluding tip labels, in x-axis units. A tree with a `width` of 10 and and `xpos` of 5 will span from positions 5 to 15 on the x axis. 123 | 124 | **`height`** defines the height of the tree, excluding tip labels, in y-axis units. A tree with a `height` of 10 and and `ypos` of 5 will span from positions 5 to 15 on the y axis. 125 | 126 | For example: 127 | 128 | ``` 129 | # Draw the plot and set the axis limits 130 | f = plt.figure(figsize=(8, 10)) 131 | ax = plt.subplot() 132 | ax.set_xlim(0, 60) 133 | ax.set_ylim(0, 20) 134 | 135 | # Set values for xpos, ypos, height and width 136 | xpos_val = 25 137 | ypos_val = 10 138 | height_val = 5 139 | width_val = 20 140 | 141 | # Run the plot_phylo function with these values 142 | results = plot_phylo.plot_phylo("examples/primates.nw", ax, xpos=xpos_val, ypos=ypos_val, height=height_val, width=width_val, show_axis=True, branch_lengths=False) 143 | 144 | # Annotate these points on the tree using matplotlib functions 145 | # Mark the bottom left corner 146 | ax.scatter(xpos_val, ypos_val, color='red', zorder=2) 147 | 148 | # Bottom right corner 149 | ax.scatter(xpos_val + width_val, ypos_val, color='blue', zorder=2) 150 | 151 | # Top left corner 152 | ax.scatter(xpos_val, ypos_val+height_val, color='green', zorder=2) 153 | 154 | # Top right corner 155 | ax.scatter(xpos_val+width_val, ypos_val+height_val, color='orange', zorder=2) 156 | 157 | # Draw a box around this region 158 | ax.plot([xpos_val, 159 | xpos_val+width_val, 160 | xpos_val+width_val, 161 | xpos_val, 162 | xpos_val], 163 | [ypos_val, 164 | ypos_val, 165 | ypos_val+height_val, 166 | ypos_val+height_val, 167 | ypos_val], color='lightgrey', zorder=1) 168 | 169 | plt.savefig("examples/tree_pos.png", bbox_inches='tight') 170 | 171 | ``` 172 | ![Position](./examples/tree_pos.png "Position") 173 | 174 | ### `xpos` 175 | (`float`, Default 0) 176 | 177 | Desired position of the root of the tree on the x axis, in axis units. 178 | 179 | ### `ypos` 180 | (`float`, Default 0) 181 | 182 | Desired position of the bottom of the tree on the y axis, in axis units. 183 | 184 | ### `height` 185 | (`float`, Default 10) 186 | Desired height of the tree, in axis units. Regardless of the height of the axis, the tree with span from `ypos` to `ypos + height`. 187 | 188 | ### `width` 189 | (`float`, Default 10) 190 | 191 | Desired width of the tree, in axis units. Default 10. 192 | 193 | ## Visualisation Options 194 | ### `show_axis` 195 | (`bool`, Default False) 196 | 197 | Show the axis lines and ticks on the output tree. 198 | 199 | ### `show_support` 200 | (`bool`, Default False) 201 | 202 | Display branch support on the internal nodes of the tree. 203 | 204 | ### `align_tips` 205 | (`bool`, Default False) 206 | 207 | If True, the tip labels will be horizontally aligned rather than positioned at the tips of the branches. By default, they are left-aligned for a standard tree and right-aligned for a mirrored tree (reverse=True) 208 | 209 | With `align_tips=True` 210 | ``` 211 | f = plt.figure(figsize=(8, 10)) 212 | ax = plt.subplot() 213 | results = plot_phylo.plot_phylo("examples/primates.nw", ax, align_tips=True) 214 | plt.savefig("examples/align_tips.png", bbox_inches='tight') 215 | ``` 216 | 217 | ![Aligned Tip Labels](./examples/align_tips.png "Aligned Tip Labels") 218 | 219 | ### `rev_align_tips` 220 | (`bool`, Default False) 221 | 222 | If True the tip labels are right-aligned if reverse=False and left-aligned if reverse=True. 223 | 224 | With `rev_align_tips=True` 225 | 226 | ``` 227 | f = plt.figure(figsize=(8, 10)) 228 | ax = plt.subplot() 229 | 230 | # For reverse aligned tip labels the axis limits need to be specified in advance 231 | ax.set_xlim(-1, 12) 232 | 233 | results = plot_phylo.plot_phylo("examples/primates.nw", ax, rev_align_tips=True) 234 | plt.savefig("examples/rev_align_tips.png", bbox_inches='tight') 235 | ``` 236 | ![Reverse Aligned Tip Labels](./examples/rev_align_tips.png "Reverse Aligned Tip Labels") 237 | 238 | ### `branch_lengths` 239 | (`bool`, Default True) 240 | 241 | If True, the branch lengths provided in the tree are used, otherwise all branches are fixed to the same length. The align tips function can be used in the same way regardless of whether branch lengths are used. 242 | 243 | With `branch_lengths=False`: 244 | 245 | ``` 246 | f = plt.figure(figsize=(8, 10)) 247 | 248 | ax = plt.subplot() 249 | ax.set_xlim(-1, 20) 250 | # ylim is set explicitly before drawing the plot 251 | ax.set_ylim(-1, 10) 252 | 253 | results = plot_phylo.plot_phylo("examples/primates.nw", ax, branch_lengths=False) 254 | 255 | # Save the tree - matplotlib 256 | plt.savefig("examples/nobranchlengths.png", bbox_inches='tight') 257 | ``` 258 | ![No branch lengths](./examples/nobranchlengths.png "No branch lengths") 259 | 260 | With `branch_lengths=False` and `align_tips=True`: 261 | 262 | ``` 263 | f = plt.figure(figsize=(8, 10)) 264 | 265 | ax = plt.subplot() 266 | ax.set_xlim(-1, 20) 267 | # ylim is set explicitly before drawing the plot 268 | ax.set_ylim(-1, 10) 269 | 270 | results = plot_phylo.plot_phylo("examples/primates.nw", ax, branch_lengths=False, align_tips=True) 271 | 272 | # Save the tree - matplotlib 273 | plt.savefig("examples/nobranchlengths_ali.png", bbox_inches='tight') 274 | ``` 275 | ![No branch lengths aligned](./examples/nobranchlengths_ali.png "No branch lengths aligned") 276 | 277 | ### `scale_bar` 278 | (`bool`, Default True) 279 | 280 | If True and branch_lengths is True, draw a scale bar. 281 | 282 | ### `scale_bar_width` 283 | (`float`, Default None) 284 | 285 | Width of scale bar in axis units. If not specified, the scale bar will be 1/4 of the width of the tree. 286 | 287 | ### `reverse` 288 | (`bool`, Default False) 289 | * 290 | If True, mirror the tree on the y-axis, showing the root on the right-hand side. 291 | 292 | With `reverse=True`: 293 | 294 | ``` 295 | f = plt.figure(figsize=(8, 10)) 296 | ax = plt.subplot() 297 | results = plot_phylo.plot_phylo("examples/primates.nw", ax, reverse=True) 298 | plt.savefig("examples/reversed.png", bbox_inches='tight') 299 | ``` 300 | 301 | ![Mirrored Tree](./examples/reversed.png "Mirrored Tree") 302 | 303 | ### `outgroup` 304 | (`str`, Default None) 305 | 306 | Specifies a leaf to set as the outgroup, must be identical to the name in the tree file. 307 | 308 | ### `col_dict` 309 | (`dict`, Default {}) 310 | 311 | User provided dictionary with tip labels as keys and colours (in any [format accepted by matplotlib](https://matplotlib.org/stable/users/explain/colors/colors.html) as values. If this is not specified all labels will be black, if only some labels are specified all others will be black. 312 | 313 | With `col_dict={'Macaca mulatta': 'orange, 'Gorilla gorilla': 'blue'}`: 314 | 315 | ``` 316 | f = plt.figure(figsize=(8, 10)) 317 | ax = plt.subplot() 318 | results = plot_phylo.plot_phylo("examples/primates.nw", ax, col_dict={'Macaca mulatta': 'orange', 'Gorilla gorilla': 'blue'}) 319 | plt.savefig("examples/colours.png", bbox_inches='tight') 320 | ``` 321 | 322 | ![Coloured tip labels](./examples/colours.png "Coloured tip labels") 323 | 324 | 325 | ### `label_dict` 326 | (`dict`, Default {}) 327 | 328 | User provided dictionary with current tip labels as keys and desired 329 | tip labels as values. If this is not specified all labels will be as specified in the newick, if some labels are specified all others will match the newick. 330 | 331 | With `label_dict={'Macaca mulatta': 'Rhesus macaque, 'Homo sapiens': 'human'}`: 332 | 333 | ``` 334 | f = plt.figure(figsize=(8, 10)) 335 | ax = plt.subplot() 336 | results = plot_phylo.plot_phylo("examples/primates.nw", ax, label_dict={'Macaca mulatta': 'Rhesus macaque', 'Homo sapiens': 'human'}, 337 | col_dict={'Macaca mulatta': 'orange', 'Homo sapiens': 'blue'}) 338 | plt.savefig("examples/labels.png", bbox_inches='tight') 339 | ``` 340 | 341 | ![Renamed tips](./examples/labels.png "Coloured tip labels") 342 | 343 | 344 | ### `font_size` 345 | (`int`, Default 10) 346 | 347 | Font size for tip labels. Branch support and scale bar labels will be two sizes smaller. 348 | 349 | ### `line_col` 350 | (`str` or `tuple`, Default 'black') 351 | 352 | Line colour, in any [format accepted by matplotlib](https://matplotlib.org/stable/users/explain/colors/colors.html). 353 | 354 | ### `line_width` 355 | (`float`, Default 2) 356 | 357 | Line width. 358 | 359 | ### `bold` 360 | (`list`, Default `[]`) 361 | 362 | A list of sequence names to show in bold. If sequences are renamed using `label_dict`, provide the original names. 363 | 364 | With `bold=['Homo sapiens']`: 365 | ``` 366 | f = plt.figure(figsize=(8, 10)) 367 | ax = plt.subplot() 368 | results = plot_phylo.plot_phylo("%s/examples/primates.nw" % path, ax, bold=['Homo sapiens']) 369 | plt.savefig("examples/bold.png", bbox_inches='tight') 370 | ``` 371 | 372 | ![Bold](./examples/bold.png "Bold") 373 | -------------------------------------------------------------------------------- /man/pages/quickstart.md: -------------------------------------------------------------------------------- 1 | # Quick Start 2 | 3 | To draw a phylogeny under the default settings onto a blank figure. 4 | 5 | ``` 6 | import matplotlib.pyplot as plt 7 | import plot_phylo 8 | 9 | # Create an empty plot, 8in (width) by 10in (height) - matplotlib 10 | f = plt.figure(figsize=(8, 10)) 11 | 12 | # Add an axis - matplotlib 13 | ax = plt.subplot() 14 | 15 | # Plot the tree on this axis, using the default settings - plot_phylo 16 | results = plot_phylo.plot_phylo("examples/primates.nw", ax) 17 | 18 | # Save the tree - matplotlib 19 | plt.savefig("examples/basic_plot.png", bbox_inches='tight') 20 | ``` 21 | 22 | The output of this function is: 23 | ![Basic Tree](./examples/basic_plot.png "Basic Tree") -------------------------------------------------------------------------------- /man/pages/testing.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | To run unit tests, please install the software [as instructed](./installation.md), including the prerequisites. 4 | 5 | You will also need to install [pytest](https://docs.pytest.org/en/stable/) version >= 7.4.4. 6 | 7 | To run all tests, in the root directory of the GitHub repository, run the command `pytest`. -------------------------------------------------------------------------------- /man/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx>=5.0 2 | sphinx-rtd-theme>=1.0.0 3 | recommonmark>=0.0.1 4 | sphinx_markdown_tables>=0.0.1 5 | -------------------------------------------------------------------------------- /plot_phylo/__init__.py: -------------------------------------------------------------------------------- 1 | from plot_phylo.plot_phylo import * 2 | 3 | __author__ = 'Katy Brown, Duncan Cross' 4 | -------------------------------------------------------------------------------- /plot_phylo/_version.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.1.11" 2 | -------------------------------------------------------------------------------- /plot_phylo/plot_phylo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import ete3 3 | 4 | 5 | def plot_phylo(tree, ax, 6 | xpos=0, 7 | ypos=0, 8 | width=10, 9 | height=10, 10 | show_axis=False, 11 | show_support=True, 12 | align_tips=False, 13 | rev_align_tips=False, 14 | branch_lengths=True, 15 | scale_bar=True, 16 | scale_bar_width=None, 17 | reverse=False, 18 | outgroup=None, 19 | col_dict={}, 20 | label_dict={}, 21 | font_size=10, 22 | line_col='black', 23 | line_width=1, 24 | bold=[]): 25 | ''' 26 | Parameters 27 | ---------- 28 | tree : str 29 | Either the path to a newick formatted tree or a string containing 30 | a newick formatted tree. Required. 31 | ax : matplotlib.axes._axes.Axes, 32 | An open matplotlib ax object where the tree will be plotted. Required. 33 | xpos : float 34 | Desired position of the root node of the tree on the x axis of ax, 35 | in axis units. Default 0. 36 | ypos : float 37 | Desired position of the bottom of the tree on the y axis of ax, 38 | in axis units. Default 0. 39 | height : float 40 | Desired height of the tree, in axis units. Default 10. 41 | width : float 42 | Desired width of the tree, in axis units. Default 10. 43 | show_axis : bool 44 | Show the axis on the output tree. Default True. This can be toggled 45 | later directly on the matplotlib ax. 46 | show_support : bool 47 | Display branch support on the internal nodes of the tree. Default 48 | False. 49 | align_tips : bool 50 | If True, the tip labels will be aligned rather than positioned at 51 | the end of the branches. Default False. 52 | rev_align_tips: bool 53 | If True the tip labels are right aligned 54 | if reverse=False and left aligned if reverse=True. 55 | branch_lengths : bool 56 | If True, the branch lengths provided in the tree are used, 57 | otherwise all branches are fixed to the same length. Default True. 58 | scale_bar: bool 59 | If True and branch_lengths is True, draw a scale bar. 60 | scale_bar_width: float 61 | Width of scale bar in axis units. If not specified, the scale bar 62 | will be 1/4 of the width of the tree. 63 | reverse: bool 64 | If True, reverse the tree on the y-axis, showing the root on the right 65 | hand side. Default False. 66 | outgroup: str 67 | Leaf to use as an outgroup, must be identical to the name of the 68 | leaf in the tree file. 69 | col_dict : dict 70 | User provided dictionary with tip labels as keys and colours 71 | (in any format accepted by matplotlib 72 | https://matplotlib.org/stable/users/explain/colors/colors.html 73 | as values. If this is not 74 | specified all labels will be black, if only some labels are specified 75 | all others will be black. 76 | label_dict : TYPE, optional 77 | User provided dictionary with current tip labels as keys and desired 78 | tip labels as values. If this is not specified all labels 79 | will be as specified in the newick, if some labels are specified 80 | all others will match the newick. 81 | font_size : int 82 | Font size for tip labels. Default 10. 83 | line_col : str or tuple 84 | Line colour, in any format allowed by matplotlib 85 | https://matplotlib.org/stable/users/explain/colors/colors.html. 86 | Default is black. 87 | line_width : float 88 | Line width. Default 2. 89 | bold: list 90 | List of tip labels to show in bold. 91 | 92 | 93 | Returns 94 | ------- 95 | ps : list 96 | List of lists - ordered as tip labels, tip label text objects, 97 | alignment lines (if aligned). All are in the same order. 98 | ''' 99 | # Read the tree 100 | try: 101 | T = ete3.Tree(tree) 102 | except ete3.parser.newick.NewickError: 103 | try: 104 | # Allows for trees with named internal nodes 105 | T = ete3.Tree(tree, format=1) 106 | except ete3.parser.newick.NewickError as e: 107 | raise RuntimeError(f"Error in parsing Newick format: {e}") 108 | if outgroup and outgroup in set(T.get_leaf_names()): 109 | T.set_outgroup(outgroup) 110 | 111 | # Define dictionaries for colours and labels if not provided 112 | for nam in T.get_leaf_names(): 113 | if nam not in label_dict: 114 | label_dict[nam] = nam 115 | if nam not in col_dict: 116 | col_dict[nam] = 'black' 117 | # Dictionary to pass apperance params to the plotting function 118 | appearance = {'font_size': font_size, 119 | 'line_col': line_col, 120 | 'line_width': line_width, 121 | 'col_dict': col_dict, 122 | 'label_dict': label_dict, 123 | 'show_support': show_support, 124 | 'bold': bold} 125 | 126 | # Calculate the total height and width of the original tree 127 | # in terms of number of nodes, total branch length, number of tips 128 | maxdist = ((T.get_farthest_leaf(topology_only=True)[1], 129 | T.get_farthest_leaf(topology_only=False)[1], 130 | len(T))) 131 | 132 | # Without branch lengths the tree has a root which appears at position -1, 133 | # so shift the tree over by one unit 134 | if not branch_lengths: 135 | xpos += 1 136 | width -= 2 137 | elif align_tips: 138 | width -= 1 139 | 140 | if reverse: 141 | xpos = -xpos 142 | # Call the main function. The second and third returns are used 143 | # internally when the function is called recursively but 144 | # are not needed by the user 145 | 146 | _, _, ps = draw_tree(T, ax, 147 | x=xpos, 148 | y=-ypos-height, 149 | x0=xpos, 150 | ps=[], 151 | height=height, 152 | width=width, 153 | depth=maxdist, 154 | align_tips=align_tips, 155 | rev_align_tips=rev_align_tips, 156 | branch_lengths=branch_lengths, 157 | reverse=reverse, 158 | appearance=appearance) 159 | 160 | if rev_align_tips: 161 | ps = reverse_align(ax, ps, reverse) 162 | # Hide axis 163 | if not show_axis: 164 | ax.set_axis_off() 165 | if scale_bar and branch_lengths: 166 | if not reverse: 167 | draw_scale_bar(ax, width, height, maxdist, xpos, ypos, 168 | scale_bar_width=scale_bar_width, 169 | appearance=appearance) 170 | else: 171 | draw_scale_bar(ax, width, height, maxdist, -xpos, ypos, 172 | scale_bar_width=scale_bar_width, 173 | appearance=appearance) 174 | textobj = [p[1] for p in ps] 175 | return (get_boxes(ax, textobj)) 176 | 177 | 178 | def get_boxes(ax, texts): 179 | ''' 180 | Converts a list of text objects to their co-ordinates on the axis in 181 | axis units. 182 | 183 | Parameters 184 | ---------- 185 | ax : matplotlib.axes._axes.Axes, 186 | An open matplotlib ax object where the tree will be plotted. 187 | texts : list 188 | A list of matplotlib.pyplot.text objects representing the tip 189 | labels from the tree and their metadata. 190 | 191 | Returns 192 | ------- 193 | boxpos : dict 194 | A dictionary of dictionaries where the top level keys are the tip 195 | labels. Within each subdictionary the key value pairs are 196 | index (position in the tree starting from the top) and the minimum, 197 | maximum and central position of the text box on the x and y axis, 198 | as index, xmin, xmid, xmax and ymin, ymid and ymax. 199 | 200 | ''' 201 | boxpos = dict() 202 | # Iterate through the tip labels 203 | for i, txt in enumerate(texts): 204 | # Get the position of the boxes containing the labels, convert to axis 205 | # units 206 | box = ax.transData.inverted().transform(txt.get_window_extent( 207 | ax.figure.canvas.get_renderer())) 208 | nam = txt.get_text().strip() 209 | # Build the dictionary 210 | boxpos[nam] = dict() 211 | boxpos[nam]['index'] = i 212 | boxpos[nam]['xmin'] = box[0][0].round(3) 213 | boxpos[nam]['xmax'] = box[1][0].round(3) 214 | boxpos[nam]['ymin'] = box[0][1].round(3) 215 | boxpos[nam]['ymax'] = box[1][1].round(3) 216 | boxpos[nam]['ymid'] = (box[0][1] + (( 217 | box[1][1] - box[0][1]) / 2)).round(3) 218 | boxpos[nam]['xmid'] = ( 219 | box[0][0] + ((box[1][0] - box[0][1]) / 2)).round(3) 220 | 221 | return (boxpos) 222 | 223 | 224 | def draw_tree(tree, ax, 225 | x=0, 226 | y=0, 227 | x0=0, 228 | ps=[], 229 | height=10, 230 | width=10, 231 | depth=None, 232 | align_tips=False, 233 | rev_align_tips=False, 234 | branch_lengths=True, 235 | reverse=False, 236 | appearance={}): 237 | ''' 238 | Plot a phylogenetic tree in matplotlib 239 | 240 | Parameters 241 | ---------- 242 | tree : ete3.Tree 243 | ete3 Tree object 244 | ax : matplotlib.axes._axes.Axes 245 | An open matplotlib ax object 246 | x : float 247 | Current position on x axis. 248 | y : float 249 | Current position on y axis. 250 | ps: list 251 | Used internally, list of tip labels and x and y positions 252 | height: float 253 | Height of the tree in axis units 254 | width: float 255 | Width of the tree in axis units 256 | depth: tuple(float, float, float) 257 | Total height and width of the original tree in terms of number of 258 | nodes, total branch length, number of tips 259 | align_tips: bool 260 | If True, the tip labels will be aligned rather than positioned at 261 | the end of the branches. Default False. 262 | rev_align_tips: bool 263 | If True the tip labels are right aligned 264 | if reverse=False and left aligned if reverse=True. 265 | branch_lengths: bool 266 | If True, use the branch lengths provided in the tree, otherwise fix 267 | all branches to the same length. Default True. 268 | reverse: bool 269 | If True, reverse the tree on the y-axis, showing the root on the right 270 | hand side. Default False. 271 | appearance: dict 272 | Dictionary of parameters specifying the appearance of the tree. 273 | 274 | Returns 275 | ------- 276 | y float 277 | Position of previous node on y axis. 278 | ym float 279 | Position of current node on y axis. 280 | ps list 281 | List of lists - ordered as tip labels, tip label text objects, 282 | alignment lines (if aligned). All are in the same order. 283 | ''' 284 | # This is the increment for the position of each terminal node on 285 | # the y axis. 286 | # The number of nodes - 1 is used because one branch will be at position 0 287 | yint = height / (depth[2] - 1) 288 | 289 | # td is the branch length - if the branch_lengths parameter is False 290 | # it is set to 1 291 | 292 | # If the branch lengths are used, the total width of the tree is in 293 | # the tree branch units, otherwise it's the total number of nodes from 294 | # the root to the farthest branch 295 | 296 | # textinc stops the tip labels from being immediately next to the tips 297 | 298 | if branch_lengths: 299 | td = tree.dist 300 | tot_width = depth[1] 301 | 302 | else: 303 | td = 1 304 | tot_width = depth[0] + 1 305 | 306 | # This interval is used to scale the interval for each node 307 | # so the total tree width matches the value specified 308 | xint = width / tot_width 309 | 310 | if tree.is_leaf(): 311 | 312 | # Position of the node tip 313 | x_tip_pos = x - (xint * td) 314 | 315 | # x_ali_pos is used to align the tips if align_tips is specified 316 | # x_text_pos is the position of the text - if the tips are aligned 317 | # the text is also aligned 318 | if align_tips or rev_align_tips: 319 | x_ali_pos = (tot_width * xint) + x0 + 1 320 | x_text_pos = x_ali_pos 321 | else: 322 | x_ali_pos = None 323 | x_text_pos = x 324 | xmax = (tot_width * xint) 325 | if reverse: 326 | x_tip_pos = xmax - x_tip_pos 327 | x_text_pos = xmax - x_text_pos 328 | if x_ali_pos is not None: 329 | x_ali_pos = xmax - x_ali_pos 330 | x = xmax - x 331 | hali = 'right' 332 | else: 333 | hali = 'left' 334 | # Plot the tip label 335 | if tree.name in appearance['bold']: 336 | bold = 'bold' 337 | else: 338 | bold = 'normal' 339 | textpos = ax.text(x_text_pos, -y, 340 | " %s " % appearance['label_dict'][tree.name], 341 | color=appearance['col_dict'][tree.name], 342 | fontsize=appearance['font_size'], 343 | va='center', ha=hali, fontweight=bold) 344 | 345 | # Plot the branch to the tip 346 | ax.plot([x, x_tip_pos], [-y, -y], 347 | color=appearance['line_col'], 348 | lw=appearance['line_width']) 349 | 350 | # Add an extra line to the aligned tips if align_tips is specified 351 | if align_tips or rev_align_tips: 352 | line = ax.plot([x, x_ali_pos], [-y, -y], 353 | color=appearance['line_col'], alpha=0.2, 354 | ls="--", 355 | lw=appearance['line_width']) 356 | ps.append([tree.name, textpos, line]) 357 | else: 358 | ps.append([tree.name, textpos]) 359 | 360 | # Store the tip label and the position of the tip on the x and y axis 361 | 362 | return (y+yint, y, ps) 363 | 364 | else: 365 | # This section draws the lines for the non-terminal nodes 366 | 367 | # For each tree, all of the children are visited and the function 368 | # is recursively called 369 | for c in tree.children: 370 | # Scale by the branch length if branch_lengths is specified 371 | if branch_lengths: 372 | tdc = c.dist 373 | else: 374 | tdc = 1 375 | 376 | # The position of the node on the x axis 377 | x_vert_pos = x + (tdc * xint) 378 | 379 | # returns y - the bottom position of all the labels so far 380 | # cym - the middle of the previous node on the y axis 381 | 382 | y, cym, ps = draw_tree(c, ax, x_vert_pos, y, 383 | x0=x0, ps=ps, 384 | height=height, 385 | width=width, 386 | depth=depth, 387 | align_tips=align_tips, 388 | rev_align_tips=rev_align_tips, 389 | branch_lengths=branch_lengths, 390 | reverse=reverse, 391 | appearance=appearance) 392 | 393 | # y1 and y2 are the top and bottom positions of the current 394 | # child node on the y axis, respectively 395 | # Gives the extent of the vertical line for this segment 396 | 397 | if c is tree.children[0]: 398 | y1 = cym 399 | elif c is tree.children[-1]: 400 | y2 = cym 401 | 402 | # midpoint of node on y axis 403 | ym = (y1 + y2)/2 404 | 405 | if reverse: 406 | xmax = (tot_width * xint) 407 | x = xmax - x 408 | 409 | # Draw the lines 410 | # Vertical line 411 | ax.plot([x, x], [-y1, -y2], 412 | color=appearance['line_col'], 413 | lw=appearance['line_width']) 414 | 415 | # Horizontal line - each node draws the one line that 416 | # projects towards its parent so x is the position of the 417 | # vertical line and x-(td*xint) is one increment back 418 | # towards the root 419 | 420 | if not reverse: 421 | ax.plot([x, x-(td*xint)], [-ym, -ym], 422 | color=appearance['line_col'], 423 | lw=appearance['line_width']) 424 | else: 425 | ax.plot([x, x+(td*xint)], [-ym, -ym], 426 | color=appearance['line_col'], 427 | lw=appearance['line_width']) 428 | 429 | # Add branch support if specified 430 | # TODO - currently lands on top of the branches if branch_lengths 431 | # is switched on 432 | if appearance['show_support']: 433 | if not reverse: 434 | ax.text(x, -ym, " %.2f" % tree.support, ha='left', 435 | va='center', fontsize=appearance['font_size']-2) 436 | else: 437 | ax.text(x, -ym, "%.2f " % tree.support, ha='right', 438 | va='center', fontsize=appearance['font_size']-2) 439 | 440 | return (y, ym, ps) 441 | 442 | 443 | def reverse_align(ax, ps, reverse): 444 | ''' 445 | Realigns the text in the tip labels so that for a standard tree, the 446 | text is right aligned, for a mirrored tree (root on the right), the 447 | text is left aligned. Only used when tip labels are set to be aligned. 448 | 449 | This has to happen once the whole plot is drawn as the limits 450 | of the text only exist once the text exists. 451 | 452 | Parameters 453 | ---------- 454 | ax : matplotlib.axes._axes.Axes 455 | An open matplotlib ax object 456 | ps : list 457 | List of lists - ordered as tip labels, tip label text objects, 458 | alignment lines (if aligned). All are in the same order. 459 | reverse: bool 460 | If True, reverse the tree on the y-axis, showing the root on the right 461 | hand side. Default False. 462 | 463 | Returns 464 | ------- 465 | ps_new : list 466 | List of lists - ordered as tip labels, tip label text objects, 467 | alignment lines (if aligned). All are in the same order. Updated 468 | based on new alignment. 469 | ''' 470 | 471 | x_extremes = [] 472 | ys = [] 473 | # Used to determine which x co-ordinates to take depending on the 474 | # tree orientation 475 | if reverse: 476 | indi = 0 477 | else: 478 | indi = 1 479 | for pnam, ptext, pline in ps: 480 | # Get the data units of the box which encloses the text 481 | box = ax.transData.inverted().transform( 482 | ptext.get_window_extent(renderer=ax.figure.canvas.get_renderer())) 483 | # Get the rightmost point of the text box (regular tree) 484 | # or the leftmost (reversed tree) 485 | x_extreme = box[indi][0] 486 | x_extremes.append(x_extreme) 487 | 488 | # Store the y axis positions 489 | ys.append(box[1][1]) 490 | 491 | if not reverse: 492 | # For right alignment, take the rightmost x point 493 | maxi = max(x_extremes) 494 | else: 495 | # For left alignment, take the leftmost x point 496 | maxi = min(x_extremes) 497 | alis = ['left', 'right'] 498 | 499 | ps_new = [] 500 | for i, p in enumerate(ps): 501 | # Move the text to the right position 502 | p[1].set_position([maxi, ys[i]]) 503 | 504 | # Get the current left end of the dotted alignment line 505 | oldline = p[2][0].get_xdata()[0] 506 | 507 | # Left or right align the text 508 | p[1].set_horizontalalignment(alis[indi]) 509 | 510 | # Get the updated text position limits 511 | pbox = ax.transData.inverted().transform(p[1].get_window_extent( 512 | renderer=ax.figure.canvas.get_renderer())) 513 | 514 | # Move the dotted line to hit the new text position 515 | # int(not indi) swaps 0 for 1 516 | p[2][0].set_xdata([pbox[int(not indi)][0], oldline]) 517 | 518 | # Set the y axis position 519 | p[1].set_verticalalignment('center') 520 | 521 | # Store the new values 522 | ps_new.append(p) 523 | return (ps_new) 524 | 525 | 526 | def draw_scale_bar(ax, width, height, depth, left, bottom, 527 | scale_bar_width=None, 528 | appearance={'font_size': 10}): 529 | ''' 530 | Adds a scale bar to the tree - only when branch lengths are specified. 531 | 532 | The default length is 0.25 * total tree width, or it can be specified 533 | using scale_bar_width. 534 | 535 | Parameters 536 | ---------- 537 | ax : matplotlib.axes._axes.Axes 538 | An open matplotlib ax object 539 | 540 | height : float 541 | Height of the tree, in axis units. 542 | width : float 543 | Width of the tree, in axis units. 544 | depth: tuple(float, float, float) 545 | Total height and width of the original tree in terms of number of 546 | nodes, total branch length, number of tips 547 | bottom: float 548 | The bottom position of the tree on the y axis 549 | scale_bar_width: float 550 | The desired width of the scale bar, if not specified 551 | tree width * 0.25 is used 552 | appearance: dict 553 | Dictionary of parameters specifying the appearance of the tree. 554 | ''' 555 | # depth[1] - total width of the tree in tree units 556 | # width - total width of tree in axis units 557 | # xint - width of one tree unit in axis units 558 | xint = width / depth[1] 559 | 560 | # Distance from x axis to start the scale bar 561 | # 10% of total tree width 562 | interx = width * 0.1 563 | 564 | # Distance on y axis to extend the bracket ends on the scale bar 565 | # 10% of the height of one node 566 | intery = (height / depth[2]) * 0.1 567 | bottom -= (height / depth[2]) 568 | # scale_bar_width = total width of scale bar in axis units 569 | if not scale_bar_width: 570 | scale_bar_width = width * 0.25 571 | 572 | # Convert the scale bar width to tree units 573 | scale = scale_bar_width / xint 574 | 575 | # Draw the horizontal line 576 | ax.plot([left+interx, left+interx+scale_bar_width], 577 | [bottom, bottom], color='black') 578 | 579 | # Bracket the ends of the scale bar with small vertical lines 580 | ax.plot([left+interx, left+interx], 581 | [bottom-intery, bottom+intery], color='black') 582 | ax.plot([left+interx+scale_bar_width, left+interx+scale_bar_width], 583 | [bottom-intery, bottom+intery], color='black') 584 | 585 | # Add the scale text 586 | ax.text(left+interx+(scale_bar_width/2), bottom+intery, "%.3f" % scale, 587 | va='bottom', ha='center', fontsize=appearance['font_size']-2) 588 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", 3 | "wheel"] 4 | build-backend = "setuptools.build_meta" 5 | 6 | [project] 7 | name = "plot-phylo" 8 | dynamic = ["version"] 9 | description = "This module allows the user to plot a phylogenetic tree on an existing matplotlib axis." 10 | readme = "README.md" 11 | license = { text = "MIT License" } 12 | keywords = ["phylogenetics", 13 | "matplotlib"] 14 | authors = [{name = "Katy Brown", email = "kab84@cam.ac.uk"}] 15 | maintainers = [{name = "Katy Brown", email = "kab84@cam.ac.uk"}] 16 | dependencies = ["ete3 >= 3.1.0", 17 | "matplotlib >= 2.1.1"] 18 | requires-python = ">=3.6" 19 | 20 | [project.urls] 21 | Documentation = "https://plot-phylo.readthedocs.io" 22 | Repository = "https://github.com/KatyBrown/plot_phylo" 23 | "Bug Tracker" = "https://github.com/KatyBrown/plot_phylo/issues" 24 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib>=2.1.1 2 | ete3>=3.1.0 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | license_files = LICENSE -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import setuptools 3 | import re 4 | 5 | with open("README.md", "r") as fh: 6 | long_description = fh.read() 7 | 8 | VERSIONFILE = "plot_phylo/_version.py" 9 | verstrline = open(VERSIONFILE, "rt").read() 10 | VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]" 11 | mo = re.search(VSRE, verstrline, re.M) 12 | if mo: 13 | verstr = mo.group(1) 14 | else: 15 | raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,)) 16 | 17 | setuptools.setup( 18 | name='plot_phylo', 19 | version=verstr, 20 | author="Katy Brown, Duncan Cross", 21 | author_email="kab84@cam.ac.uk", 22 | description="Module to draw a phylogenetic tree using matplotlib", 23 | long_description=long_description, 24 | long_description_content_type="text/markdown", 25 | url="https://github.com/KatyBrown/plot_phylo", 26 | packages=setuptools.find_packages(), 27 | package_dir={'plot_phylo': 'plot_phylo'}, 28 | install_requires=['matplotlib', 'ete3'], 29 | scripts=['plot_phylo/plot_phylo.py'], 30 | classifiers=[ 31 | "Programming Language :: Python :: 3", 32 | "License :: OSI Approved :: MIT License", 33 | "Operating System :: OS Independent"] 34 | ) 35 | -------------------------------------------------------------------------------- /tests/test_get_boxes_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import matplotlib.pyplot as plt 3 | 4 | f1 = plt.figure() 5 | a1 = f1.add_subplot(1, 1, 1) 6 | 7 | f2 = plt.figure() 8 | a2 = f2.add_subplot(1, 2, 1) 9 | a2.set_xlim(0, 100) 10 | a2.set_ylim(0, 100) 11 | 12 | f3 = plt.figure() 13 | a3 = f3.add_subplot(1, 2, 1) 14 | a3.set_xlim(0, 100) 15 | a3.set_ylim(0, 100) 16 | 17 | test_get_boxes_axes = [a1, a2, a3] 18 | 19 | text11 = a1.text(0, 1, "hello") 20 | text12 = a1.text(2, 3, "goodbye") 21 | text13 = a1.text(10, 20, "outside text") 22 | 23 | text21 = a2.text(0, 90, "text1") 24 | text22 = a2.text(20, 30, "text2") 25 | text23 = a2.text(10, 20, "text3") 26 | 27 | text31 = a3.text(0, 90, "text1", fontsize=20) 28 | text32 = a3.text(20, 30, "", fontsize=10) 29 | text33 = a3.text(10, 20, "~*~", fontsize=2) 30 | 31 | test_get_boxes_texts = [[text11, text12, text13], 32 | [text21, text22, text23], 33 | [text31, text32, text33]] 34 | 35 | b1 = {'hello': {'index': 0, 36 | 'xmin': 0.0, 37 | 'xmax': 0.0, 38 | 'ymin': 1.0, 39 | 'ymax': 1.0, 40 | 'ymid': 1.0, 41 | 'xmid': -0.0}, 42 | 'goodbye': {'index': 1, 43 | 'xmin': 2.0, 44 | 'xmax': 2.0, 45 | 'ymin': 3.0, 46 | 'ymax': 3.0, 47 | 'ymid': 3.0, 48 | 'xmid': 2.0}, 49 | 'outside text': {'index': 2, 50 | 'xmin': 10.0, 51 | 'xmax': 10.0, 52 | 'ymin': 20.0, 53 | 'ymax': 20.0, 54 | 'ymid': 20.0, 55 | 'xmid': 5.0}} 56 | 57 | b2 = {'text1': {'index': 0, 58 | 'xmin': 0.0, 59 | 'xmax': 16.0, 60 | 'ymin': 89.0, 61 | 'ymax': 93.0, 62 | 'ymid': 91.0, 63 | 'xmid': -37.0}, 64 | 'text2': {'index': 1, 65 | 'xmin': 20.0, 66 | 'xmax': 36.0, 67 | 'ymin': 29.0, 68 | 'ymax': 33.0, 69 | 'ymid': 31.0, 70 | 'xmid': 23.0}, 71 | 'text3': {'index': 2, 72 | 'xmin': 10.0, 73 | 'xmax': 26.0, 74 | 'ymin': 19.0, 75 | 'ymax': 23.0, 76 | 'ymid': 21.0, 77 | 'xmid': 13.0}} 78 | 79 | 80 | b3 = {'text1': {'index': 0, 81 | 'xmin': 0.0, 82 | 'xmax': 32.0, 83 | 'ymin': 88.0, 84 | 'ymax': 96.0, 85 | 'ymid': 92.0, 86 | 'xmid': -28.0}, 87 | '': {'index': 1, 88 | 'xmin': 20.0, 89 | 'xmax': 20.0, 90 | 'ymin': 30.0, 91 | 'ymax': 30.0, 92 | 'ymid': 30.0, 93 | 'xmid': 15.0}, 94 | '~*~': {'index': 2, 95 | 'xmin': 10.0, 96 | 'xmax': 13.0, 97 | 'ymin': 20.0, 98 | 'ymax': 21.0, 99 | 'ymid': 20.0, 100 | 'xmid': 6.0}} 101 | 102 | test_get_boxes_results = [b1, b2, b3] 103 | -------------------------------------------------------------------------------- /tests/test_images/align_tips_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/align_tips_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/align_tips_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/align_tips_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/align_tips_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/align_tips_primates.png -------------------------------------------------------------------------------- /tests/test_images/basic_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/basic_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/basic_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/basic_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/basic_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/basic_primates.png -------------------------------------------------------------------------------- /tests/test_images/bold_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/bold_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/bold_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/bold_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/bold_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/bold_primates.png -------------------------------------------------------------------------------- /tests/test_images/branch_lengths_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/branch_lengths_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/branch_lengths_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/branch_lengths_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/branch_lengths_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/branch_lengths_primates.png -------------------------------------------------------------------------------- /tests/test_images/col_dict_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/col_dict_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/col_dict_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/col_dict_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/col_dict_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/col_dict_primates.png -------------------------------------------------------------------------------- /tests/test_images/font_size_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/font_size_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/font_size_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/font_size_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/font_size_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/font_size_primates.png -------------------------------------------------------------------------------- /tests/test_images/label_dict_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/label_dict_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/label_dict_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/label_dict_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/label_dict_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/label_dict_primates.png -------------------------------------------------------------------------------- /tests/test_images/line_col_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/line_col_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/line_col_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/line_col_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/line_col_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/line_col_primates.png -------------------------------------------------------------------------------- /tests/test_images/line_width_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/line_width_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/line_width_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/line_width_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/line_width_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/line_width_primates.png -------------------------------------------------------------------------------- /tests/test_images/outgroup_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/outgroup_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/outgroup_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/outgroup_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/outgroup_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/outgroup_primates.png -------------------------------------------------------------------------------- /tests/test_images/rev_align_tips_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/rev_align_tips_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/rev_align_tips_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/rev_align_tips_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/rev_align_tips_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/rev_align_tips_primates.png -------------------------------------------------------------------------------- /tests/test_images/rev_align_tips_reverse_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/rev_align_tips_reverse_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/rev_align_tips_reverse_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/rev_align_tips_reverse_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/rev_align_tips_reverse_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/rev_align_tips_reverse_primates.png -------------------------------------------------------------------------------- /tests/test_images/reverse_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/reverse_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/reverse_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/reverse_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/reverse_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/reverse_primates.png -------------------------------------------------------------------------------- /tests/test_images/scale_bar_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/scale_bar_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/scale_bar_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/scale_bar_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/scale_bar_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/scale_bar_primates.png -------------------------------------------------------------------------------- /tests/test_images/scale_bar_width_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/scale_bar_width_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/scale_bar_width_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/scale_bar_width_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/scale_bar_width_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/scale_bar_width_primates.png -------------------------------------------------------------------------------- /tests/test_images/show_axis_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/show_axis_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/show_axis_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/show_axis_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/show_axis_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/show_axis_primates.png -------------------------------------------------------------------------------- /tests/test_images/show_support_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/show_support_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/show_support_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/show_support_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/show_support_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/show_support_primates.png -------------------------------------------------------------------------------- /tests/test_images/xpos_ypos_basic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/xpos_ypos_basic_tree.png -------------------------------------------------------------------------------- /tests/test_images/xpos_ypos_big_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/xpos_ypos_big_tree.png -------------------------------------------------------------------------------- /tests/test_images/xpos_ypos_primates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_images/xpos_ypos_primates.png -------------------------------------------------------------------------------- /tests/test_objects/draw_tree__basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree__basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree__big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree__big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree__primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree__primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_align_tips_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_align_tips_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_align_tips_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_align_tips_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_align_tips_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_align_tips_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_appearance_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_appearance_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_appearance_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_appearance_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_appearance_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_appearance_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_branch_lengths_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_branch_lengths_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_branch_lengths_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_branch_lengths_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_branch_lengths_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_branch_lengths_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_depth_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_depth_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_depth_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_depth_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_depth_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_depth_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_outgroup_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_outgroup_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_outgroup_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_outgroup_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_outgroup_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_outgroup_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_rev_align_tips_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_rev_align_tips_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_rev_align_tips_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_rev_align_tips_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_rev_align_tips_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_rev_align_tips_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_rev_align_tips_reverse_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_rev_align_tips_reverse_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_rev_align_tips_reverse_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_rev_align_tips_reverse_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_rev_align_tips_reverse_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_rev_align_tips_reverse_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_reverse_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_reverse_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_reverse_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_reverse_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_reverse_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_reverse_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_scale_bar_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_scale_bar_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_scale_bar_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_scale_bar_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_scale_bar_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_scale_bar_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_scale_bar_width_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_scale_bar_width_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_scale_bar_width_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_scale_bar_width_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_scale_bar_width_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_scale_bar_width_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_show_axis_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_show_axis_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_show_axis_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_show_axis_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_show_axis_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_show_axis_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_xpos_ypos_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_xpos_ypos_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_xpos_ypos_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_xpos_ypos_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/draw_tree_xpos_ypos_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/draw_tree_xpos_ypos_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align__basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align__basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align__big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align__big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align__primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align__primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_appearance_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_appearance_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_appearance_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_appearance_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_appearance_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_appearance_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_branch_lengths_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_branch_lengths_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_branch_lengths_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_branch_lengths_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_branch_lengths_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_branch_lengths_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_depth_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_depth_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_depth_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_depth_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_depth_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_depth_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_outgroup_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_outgroup_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_outgroup_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_outgroup_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_outgroup_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_outgroup_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_reverse_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_reverse_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_reverse_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_reverse_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_reverse_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_reverse_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_scale_bar_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_scale_bar_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_scale_bar_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_scale_bar_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_scale_bar_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_scale_bar_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_scale_bar_width_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_scale_bar_width_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_scale_bar_width_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_scale_bar_width_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_scale_bar_width_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_scale_bar_width_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_show_axis_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_show_axis_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_show_axis_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_show_axis_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_show_axis_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_show_axis_primates.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_xpos_ypos_basic_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_xpos_ypos_basic_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_xpos_ypos_big_tree.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_xpos_ypos_big_tree.pickle -------------------------------------------------------------------------------- /tests/test_objects/rev_align_xpos_ypos_primates.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KatyBrown/plot_phylo/9f6ddbc27105c6f8747ddd8d3ed436c595f0e342/tests/test_objects/rev_align_xpos_ypos_primates.pickle -------------------------------------------------------------------------------- /tests/test_plot_phylo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import matplotlib.pyplot as plt 3 | import matplotlib 4 | import plot_phylo 5 | import pytest 6 | from test_plot_phylo_data import (test_plot_phylo_vars, 7 | test_plot_phylo_list, 8 | test_plot_phylo_nams, 9 | test_draw_tree_vars, 10 | test_draw_tree_list, 11 | test_draw_tree_nams, 12 | test_rev_align_vars, 13 | test_rev_align_list, 14 | test_rev_align_nams) 15 | from test_get_boxes_data import (test_get_boxes_axes, 16 | test_get_boxes_texts, 17 | test_get_boxes_results) 18 | import ete3 19 | import pickle 20 | import os 21 | import shutil 22 | import numpy as np 23 | matplotlib.use('Agg') 24 | 25 | 26 | def compare_images(f1, f2, tol): 27 | f1arr = matplotlib.image.imread(f1) 28 | f2arr = matplotlib.image.imread(f2) 29 | 30 | f1arr_sub = f1arr[500:1500, 500:1500, :] 31 | f2arr_sub = f2arr[500:1500, 500:1500, :] 32 | return np.allclose(f1arr_sub, f2arr_sub, atol=tol) 33 | 34 | 35 | def compare_floats(float1, float2, tolerance=0.05): 36 | abs_diff = abs(float1 - float2) 37 | return abs_diff <= (tolerance * abs(float2)) 38 | 39 | 40 | # Tests all parameters with plot_phylo with three different trees 41 | @pytest.mark.parametrize(test_plot_phylo_vars, 42 | test_plot_phylo_list, 43 | ids=test_plot_phylo_nams) 44 | @pytest.mark.parametrize("tree, ylim", [["examples/primates.nw", 11], 45 | ["examples/basic_tree.nw", 5], 46 | ['examples/big_tree.nw', 300]]) 47 | def test_plot_phylo_params(xpos, 48 | ypos, 49 | width, 50 | show_axis, 51 | show_support, 52 | align_tips, 53 | rev_align_tips, 54 | branch_lengths, 55 | scale_bar, 56 | scale_bar_width, 57 | reverse, 58 | outgroup, 59 | col_dict, 60 | label_dict, 61 | font_size, 62 | line_col, 63 | line_width, 64 | bold, 65 | expected_figure, 66 | ID, tree, ylim): 67 | 68 | tree_stem = tree.split("/")[-1].split(".")[0] 69 | 70 | f = plt.figure(figsize=(10, 20)) 71 | a = f.add_subplot(111) 72 | a.set_xlim(-10, 20) 73 | a.set_ylim(-1, ylim) 74 | plot_phylo.plot_phylo(tree=tree, ax=a, 75 | xpos=xpos, 76 | ypos=ypos, 77 | width=width, 78 | height=ylim-1, 79 | show_axis=show_axis, 80 | show_support=show_support, 81 | align_tips=align_tips, 82 | rev_align_tips=rev_align_tips, 83 | branch_lengths=branch_lengths, 84 | scale_bar=scale_bar, 85 | scale_bar_width=scale_bar_width, 86 | reverse=reverse, 87 | outgroup=outgroup, 88 | col_dict=col_dict, 89 | label_dict=label_dict, 90 | font_size=font_size, 91 | line_col=line_col, 92 | line_width=line_width, 93 | bold=bold) 94 | try: 95 | os.mkdir("test_temp") 96 | except FileExistsError: 97 | pass 98 | plt.savefig("test_temp/%s_%s.png" % (ID, tree_stem), bbox_inches='tight', 99 | dpi=200) 100 | plt.close('all') 101 | 102 | exp = expected_figure.replace(".png", "_%s.png" % tree_stem) 103 | # Compare the Matplotlib figures as images 104 | result = compare_images("test_temp/%s_%s.png" % (ID, tree_stem), 105 | exp, tol=10) 106 | shutil.rmtree("test_temp") 107 | # Assert that the images are similar 108 | assert result 109 | 110 | 111 | @pytest.mark.parametrize(test_draw_tree_vars, 112 | test_draw_tree_list, 113 | ids=test_draw_tree_nams) 114 | @pytest.mark.parametrize("tree, ylim", [["examples/primates.nw", 11], 115 | ["examples/basic_tree.nw", 5], 116 | ['examples/big_tree.nw', 300]]) 117 | def test_draw_tree_params(x, 118 | y, 119 | x0, 120 | ps, 121 | width, 122 | depth, 123 | align_tips, 124 | rev_align_tips, 125 | branch_lengths, 126 | reverse, 127 | appearance, 128 | expected, 129 | ID, 130 | tree, 131 | ylim): 132 | 133 | try: 134 | T = ete3.Tree(tree) 135 | except ete3.parser.newick.NewickError: 136 | try: 137 | # Allows for trees with named internal nodes 138 | T = ete3.Tree(tree, format=1) 139 | except ete3.parser.newick.NewickError as e: 140 | raise RuntimeError(f"Error in parsing Newick format: {e}") 141 | tree_stem = tree.split("/")[-1].split(".")[0] 142 | 143 | f = plt.figure(figsize=(10, 20)) 144 | a = f.add_subplot(111) 145 | a.set_xlim(-10, 20) 146 | a.set_ylim(-1, ylim) 147 | for nam in T.get_leaf_names(): 148 | if nam not in appearance['label_dict']: 149 | appearance['label_dict'][nam] = nam 150 | if nam not in appearance['col_dict']: 151 | appearance['col_dict'][nam] = 'black' 152 | 153 | test_obj = plot_phylo.draw_tree(tree=T, ax=a, 154 | x=x, 155 | y=y, 156 | x0=x0, 157 | ps=ps, 158 | height=ylim-1, 159 | width=width, 160 | depth=depth, 161 | align_tips=align_tips, 162 | rev_align_tips=rev_align_tips, 163 | branch_lengths=branch_lengths, 164 | reverse=reverse, 165 | appearance=appearance) 166 | plt.close() 167 | ytest = round(test_obj[0], 2) 168 | y2test = round(test_obj[1], 2) 169 | test_dat = [ytest, y2test] 170 | for v in test_obj[2]: 171 | row = [v[0]] 172 | x, y = v[1].get_position() 173 | row += [round(x, 2), round(y, 2)] 174 | row += [v[1].get_text()] 175 | test_dat += row 176 | e0 = expected.replace(".pickle", "_%s.pickle" % tree_stem) 177 | expected_obj = pickle.load(open(e0, "rb")) 178 | ll = 0 179 | for z1, z2 in zip(expected_obj, test_dat): 180 | if isinstance(z1, str): 181 | if z1 == z2: 182 | ll += 1 183 | else: 184 | if compare_floats(z1, z2): 185 | ll += 1 186 | assert ll == len(expected_obj) 187 | 188 | 189 | @pytest.mark.parametrize(test_rev_align_vars, 190 | test_rev_align_list, 191 | ids=test_rev_align_nams) 192 | @pytest.mark.parametrize("tree, ylim", [["examples/primates.nw", 11], 193 | ["examples/basic_tree.nw", 5], 194 | ['examples/big_tree.nw', 300]]) 195 | def test_reverse_align_params(x, 196 | y, 197 | x0, 198 | width, 199 | depth, 200 | branch_lengths, 201 | reverse, 202 | appearance, 203 | expected, 204 | ID, 205 | tree, 206 | ylim): 207 | try: 208 | T = ete3.Tree(tree) 209 | except ete3.parser.newick.NewickError: 210 | try: 211 | # Allows for trees with named internal nodes 212 | T = ete3.Tree(tree, format=1) 213 | except ete3.parser.newick.NewickError as e: 214 | raise RuntimeError(f"Error in parsing Newick format: {e}") 215 | tree_stem = tree.split("/")[-1].split(".")[0] 216 | 217 | f = plt.figure(figsize=(10, 20)) 218 | a = f.add_subplot(111) 219 | a.set_xlim(-10, 19) 220 | a.set_ylim(-1, ylim) 221 | for nam in T.get_leaf_names(): 222 | if nam not in appearance['label_dict']: 223 | appearance['label_dict'][nam] = nam 224 | if nam not in appearance['col_dict']: 225 | appearance['col_dict'][nam] = 'black' 226 | 227 | _, _, ps = plot_phylo.draw_tree(tree=T, ax=a, 228 | x=x, 229 | y=y, 230 | x0=x0, 231 | ps=[], 232 | height=ylim-1, 233 | width=width, 234 | depth=depth, 235 | align_tips=True, 236 | rev_align_tips=True, 237 | branch_lengths=branch_lengths, 238 | reverse=reverse, 239 | appearance=appearance) 240 | plt.close() 241 | reverse = plot_phylo.reverse_align(a, ps, True) 242 | 243 | e0 = expected.replace(".pickle", "_%s.pickle" % tree_stem) 244 | 245 | test_dat = [] 246 | for v0, v1, v2 in reverse: 247 | row = [v0] 248 | x, y = v1.get_position() 249 | row += [round(x, 2), round(y, 2)] 250 | row += [v1.get_text()] 251 | for w in v2: 252 | x2 = [round(z, 2) for z in w.get_xdata()] 253 | y2 = [round(z, 2) for z in w.get_ydata()] 254 | row += x2 255 | row += y2 256 | test_dat += row 257 | expected_obj = pickle.load(open(e0, "rb")) 258 | ll = 0 259 | for z1, z2 in zip(expected_obj, test_dat): 260 | if isinstance(z1, str): 261 | if z1 == z2: 262 | ll += 1 263 | else: 264 | if compare_floats(z1, z2): 265 | ll += 1 266 | assert ll == len(expected_obj) 267 | 268 | 269 | @pytest.mark.parametrize("ax, texts, expected_result", 270 | list(zip(test_get_boxes_axes, 271 | test_get_boxes_texts, 272 | test_get_boxes_results))) 273 | def test_get_boxes(ax, texts, expected_result): 274 | boxes = plot_phylo.get_boxes(ax, texts) 275 | bclean = dict() 276 | for b, vals in boxes.items(): 277 | bclean[b] = dict() 278 | for v in vals: 279 | bclean[b][v] = round(vals[v], 0) 280 | assert bclean == expected_result 281 | 282 | 283 | @pytest.mark.parametrize(test_plot_phylo_vars, 284 | test_plot_phylo_list, 285 | ids=test_plot_phylo_nams) 286 | @pytest.mark.parametrize("tree, ylim", [["examples/bad_tree.nw", 1]]) 287 | def test_bad_tree(xpos, 288 | ypos, 289 | width, 290 | show_axis, 291 | show_support, 292 | align_tips, 293 | rev_align_tips, 294 | branch_lengths, 295 | scale_bar, 296 | scale_bar_width, 297 | reverse, 298 | outgroup, 299 | col_dict, 300 | label_dict, 301 | font_size, 302 | line_col, 303 | line_width, 304 | bold, 305 | expected_figure, 306 | ID, tree, ylim): 307 | f = plt.figure(figsize=(10, 20)) 308 | a = f.add_subplot(111) 309 | a.set_xlim(-10, 20) 310 | a.set_ylim(-1, ylim) 311 | with pytest.raises(RuntimeError, 312 | match="Error in parsing Newick"): 313 | plot_phylo.plot_phylo(tree=tree, ax=a, 314 | xpos=xpos, 315 | ypos=ypos, 316 | width=width, 317 | height=ylim-1, 318 | show_axis=show_axis, 319 | show_support=show_support, 320 | align_tips=align_tips, 321 | rev_align_tips=rev_align_tips, 322 | branch_lengths=branch_lengths, 323 | scale_bar=scale_bar, 324 | scale_bar_width=scale_bar_width, 325 | reverse=reverse, 326 | outgroup=outgroup, 327 | col_dict=col_dict, 328 | label_dict=label_dict, 329 | font_size=font_size, 330 | line_col=line_col, 331 | line_width=line_width, 332 | bold=bold) 333 | -------------------------------------------------------------------------------- /tests/test_plot_phylo_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import plot_phylo 3 | import copy 4 | 5 | # Default parameters values 6 | defaults = plot_phylo.plot_phylo.__defaults__ 7 | # Number of parameters 8 | ac = plot_phylo.plot_phylo.__code__.co_argcount 9 | # Argument names, excluding variables defined within the function and 10 | # arguments with no default values 11 | varis = list(plot_phylo.plot_phylo.__code__.co_varnames[ 12 | ac-len(defaults):ac]) 13 | 14 | variD = dict(zip(varis, defaults)) 15 | 16 | varis.remove('height') 17 | variD.pop('height') 18 | 19 | defaults_draw_tree = plot_phylo.draw_tree.__defaults__ 20 | ac_draw_tree = plot_phylo.draw_tree.__code__.co_argcount 21 | varis_draw_tree = list(plot_phylo.draw_tree.__code__.co_varnames[ 22 | ac_draw_tree-len(defaults_draw_tree):ac_draw_tree]) 23 | varis_draw_tree.remove('height') 24 | 25 | varis_rev_align = copy.deepcopy(varis_draw_tree) 26 | varis_rev_align.remove('align_tips') 27 | varis_rev_align.remove('rev_align_tips') 28 | varis_rev_align.remove('ps') 29 | 30 | tests_plot_phylo = [{}, 31 | {'xpos': 1, 'ypos': 1}, 32 | {'show_axis': False}, 33 | {'show_support': False}, 34 | {'align_tips': True}, 35 | {'rev_align_tips': True}, 36 | {'branch_lengths': False}, 37 | {'scale_bar': False}, 38 | {'scale_bar_width': 6}, 39 | {'reverse': True}, 40 | {'outgroup': 'Homo sapiens'}, 41 | {'rev_align_tips': True, 'reverse': True}, 42 | {'col_dict': {'Homo sapiens': 'blue'}}, 43 | {'label_dict': {'Homo sapiens': 'human'}}, 44 | {'font_size': 20}, 45 | {'line_col': 'orange'}, 46 | {'line_width': 5}, 47 | {'bold': ['Homo sapiens']}] 48 | 49 | tests_draw_tree = [{}, 50 | {'xpos': 1, 'ypos': 1}, 51 | {'show_axis': False}, 52 | {'align_tips': True}, 53 | {'rev_align_tips': True}, 54 | {'branch_lengths': False}, 55 | {'scale_bar': False}, 56 | {'scale_bar_width': 6}, 57 | {'reverse': True}, 58 | {'rev_align_tips': True, 'reverse': True}, 59 | {'appearance': {'col_dict': {'Homo sapiens': 'blue'}, 60 | 'label_dict': {'Homo sapiens': 'human'}, 61 | 'font_size': 20, 62 | 'line_col': 'orange', 63 | 'line_width': 5, 64 | 'show_support': True, 65 | 'bold': ['Homo sapiens']}}, 66 | {'depth': [2, 2, 2]}] 67 | 68 | test_plot_phylo_list = [] 69 | test_plot_phylo_nams = [] 70 | for test in tests_plot_phylo: 71 | testnam = "_".join(test.keys()) 72 | if len(testnam) == 0: 73 | testnam = "basic" 74 | curr_dict = copy.deepcopy(variD) 75 | curr_dict.update(test) 76 | pass_vals = [curr_dict[v] for v in varis] 77 | pass_vals.append('tests/test_images/%s.png' % testnam) 78 | pass_vals.append(testnam) 79 | test_plot_phylo_list.append(pass_vals) 80 | test_plot_phylo_nams.append(testnam) 81 | test_plot_phylo_vars = ",".join(varis + ['expected_figure', 'ID']) 82 | 83 | test_draw_tree_list = [] 84 | test_draw_tree_nams = [] 85 | for test in tests_draw_tree: 86 | testnam = "draw_tree_%s" % "_".join(test.keys()) 87 | curr_dict = copy.deepcopy(variD) 88 | curr_dict['x'] = curr_dict['xpos'] 89 | curr_dict['x0'] = curr_dict['xpos'] 90 | curr_dict['y'] = curr_dict['ypos'] 91 | curr_dict['ps'] = [] 92 | curr_dict['appearance'] = dict() 93 | for var in ['col_dict', 'label_dict', 'font_size', 94 | 'line_col', 'line_width', 'show_support', 'bold']: 95 | curr_dict['appearance'][var] = curr_dict[var] 96 | curr_dict['depth'] = [5, 5, 5] 97 | curr_dict.update(test) 98 | pass_vals = [curr_dict[v] for v in varis_draw_tree] 99 | pass_vals.append('tests/test_objects/%s.pickle' % testnam) 100 | pass_vals.append(testnam) 101 | test_draw_tree_list.append(pass_vals) 102 | test_draw_tree_nams.append(testnam) 103 | test_draw_tree_vars = ",".join(varis_draw_tree + ['expected', 'ID']) 104 | 105 | 106 | test_rev_align_list = [] 107 | test_rev_align_nams = [] 108 | for test in tests_draw_tree: 109 | testnam = "rev_align_%s" % "_".join(test.keys()) 110 | if 'align_tips' not in testnam: 111 | curr_dict = copy.deepcopy(variD) 112 | curr_dict['x'] = curr_dict['xpos'] 113 | curr_dict['x0'] = curr_dict['xpos'] 114 | curr_dict['y'] = curr_dict['ypos'] 115 | curr_dict['appearance'] = dict() 116 | for var in ['col_dict', 'label_dict', 'font_size', 117 | 'line_col', 'line_width', 'show_support', 'bold']: 118 | curr_dict['appearance'][var] = curr_dict[var] 119 | curr_dict.update(test) 120 | curr_dict['depth'] = [5, 5, 5] 121 | curr_dict.pop('rev_align_tips') 122 | curr_dict.pop('align_tips') 123 | pass_vals = [curr_dict[v] for v in varis_rev_align] 124 | pass_vals.append('tests/test_objects/%s.pickle' % testnam) 125 | pass_vals.append(testnam) 126 | test_rev_align_list.append(pass_vals) 127 | test_rev_align_nams.append(testnam) 128 | test_rev_align_vars = ",".join(varis_rev_align + ['expected', 'ID']) 129 | --------------------------------------------------------------------------------