├── .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 | 
2 | [](https://plot-phylo.readthedocs.io/en/latest/?badge=latest)
3 | [](https://www.repostatus.org/#active)
4 | 
5 | [](https://doi.org/10.5281/zenodo.13871592)
6 | [](https://github.com/pyOpenSci/software-review/issues/issue-number)
7 |
8 | # plot_phylo
9 |
10 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------