pax_global_header 0000666 0000000 0000000 00000000064 15211731751 0014515 g ustar 00root root 0000000 0000000 52 comment=b8a3d6a6963a802c1b32207b76fa7528993d24e1
iqtree-piqtree-b8a3d6a/ 0000775 0000000 0000000 00000000000 15211731751 0015147 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/.devcontainer/ 0000775 0000000 0000000 00000000000 15211731751 0017706 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/.devcontainer/DockerFile 0000664 0000000 0000000 00000003260 15211731751 0021641 0 ustar 00root root 0000000 0000000 FROM continuumio/miniconda3
# Install dependencies
RUN apt-get update && apt-get install -y \
build-essential \
btop \
cmake \
gdb \
gh \
git \
zsh \
sudo \
wget \
libeigen3-dev \
libboost-all-dev \
binutils \
&& rm -rf /var/lib/apt/lists/*
# Set up a non-root user with sudo
RUN useradd -ms /bin/zsh user && echo "user ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/user
USER user
WORKDIR /home/user/repos
# Install Oh My Zsh
RUN sh -c "$(wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -)" "" --unattended
# Install zsh autosuggestions
RUN git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
# Install zsh syntax highlighting
RUN git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
# Configure zsh
RUN sed -i 's/plugins=(git)/plugins=(git zsh-autosuggestions zsh-syntax-highlighting)/' ~/.zshrc
# Create a new conda environment with Python 3.14 and fix the bug with VS-code terminal showing 2 conda env prompts
RUN . /opt/conda/etc/profile.d/conda.sh && \
conda config --set auto_activate_base False && \
/opt/conda/bin/conda create -n piq-dev python=3.14 -y && \
conda activate piq-dev
# Initialize conda for zsh shell
RUN echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.zshrc
# Install pybind11 in the conda environment
RUN . /opt/conda/etc/profile.d/conda.sh && \
conda activate piq-dev && \
pip install pybind11
# Set up zsh as the default shell
SHELL ["/bin/zsh", "-c"]
# Set zsh as the default shell for the container
CMD [ "zsh" ] iqtree-piqtree-b8a3d6a/.devcontainer/devcontainer.json 0000664 0000000 0000000 00000002735 15211731751 0023271 0 ustar 00root root 0000000 0000000 {
"name": "piqtree devcontainer",
"image": "ghcr.io/iqtree/piqtree:latest",
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.shell.linux": "/bin/zsh",
"terminal.integrated.profiles.linux": {
"zsh": {
"path": "zsh"
}
},
"python.defaultInterpreterPath": "/home/user/.conda/envs/piq-dev/bin/python",
"C_Cpp.default.includePath": [
"${workspaceFolder}/**",
"/home/user/.conda/envs/piq-dev/lib/python3.14/site-packages/pybind11/include/",
"/home/user/.conda/envs/piq-dev/include/python3.14/"
]
},
"extensions": [
"ms-python.python",
"ms-toolsai.jupyter",
"ms-vscode.cpptools",
"ms-vscode.cpptools-extension-pack",
"ms-vscode.makefile-tools",
"charliermarsh.ruff",
"njpwerner.autodocstring",
"github.vscode-github-actions",
"tamasfe.even-better-toml",
"DavidAnson.vscode-markdownlint",
"be5invis.toml",
"mhutchie.git-graph"
]
}
},
"remoteUser": "user",
"postCreateCommand": "sudo chown -R user:user /home/user/.ssh && git config --global --add safe.directory ${containerWorkspaceFolder}"
} iqtree-piqtree-b8a3d6a/.github/ 0000775 0000000 0000000 00000000000 15211731751 0016507 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/.github/actions/ 0000775 0000000 0000000 00000000000 15211731751 0020147 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/.github/actions/build-iqtree/ 0000775 0000000 0000000 00000000000 15211731751 0022535 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/.github/actions/build-iqtree/action.yml 0000664 0000000 0000000 00000005450 15211731751 0024541 0 ustar 00root root 0000000 0000000 name: Fetch or Build IQ-TREE Static Library
description: "Checks if the IQ-TREE static library exists, if not then building it."
inputs:
os:
description: "Runner OS Name."
required: true
outputs:
iqtree-sha:
description: "SHA for commit of IQ-TREE static library."
value: ${{ steps.iqtree-sha.outputs.iqtree-sha }}
runs:
using: composite
steps:
- id: iqtree-sha
name: Get IQ-TREE SHA
shell: bash
run: |
cd iqtree3
IQ_TREE_SHA=$(git rev-parse HEAD)
echo "iqtree-sha=${IQ_TREE_SHA}" >> "$GITHUB_OUTPUT"
- name: Cache IQ-TREE (Windows)
if: runner.os == 'Windows'
uses: actions/cache@v5
id: cache-windows
with:
key: libiqtree-${{ inputs.os }}-${{ steps.iqtree-sha.outputs.iqtree-sha }}
path: |
src/piqtree/_libiqtree/iqtree.lib
src/piqtree/_libiqtree/iqtree.dll
lookup-only: true
- name: Cache IQ-TREE (Linux/macOS)
if: runner.os != 'Windows'
uses: actions/cache@v5
id: cache-unix
with:
key: libiqtree-${{ inputs.os }}-${{ steps.iqtree-sha.outputs.iqtree-sha }}
path: |
src/piqtree/_libiqtree/libiqtree.a
lookup-only: true
- name: Combine Cache Hits
id: cache
shell: bash
run: |
if [[ "${{ steps.cache-windows.outputs.cache-hit }}" == 'true' || "${{ steps.cache-unix.outputs.cache-hit }}" == 'true' ]]; then
echo "cache-hit=true" >> "$GITHUB_OUTPUT"
else
echo "cache-hit=false" >> "$GITHUB_OUTPUT"
fi
- name: Install Boost
if: runner.os == 'Windows' && steps.cache.outputs.cache-hit != 'true'
uses: MarkusJx/install-boost@v2.6.0
id: install-boost
with:
boost_version: 1.84.0
platform_version: 2022
toolset: mingw
- name: Set Boost Environment Variables
if: runner.os == 'Windows' && steps.cache.outputs.cache-hit != 'true'
shell: bash
run: |
echo "Boost_INCLUDE_DIR=${{ steps.install-boost.outputs.BOOST_ROOT }}/include" >> "$GITHUB_ENV"
echo "Boost_LIBRARY_DIRS=${{ steps.install-boost.outputs.BOOST_ROOT }}/lib" >> "$GITHUB_ENV"
- name: Setup MSVC Developer Command Prompt
if: runner.os == 'Windows' && steps.cache.outputs.cache-hit != 'true'
uses: ilammy/msvc-dev-cmd@v1
- name: Build IQ-TREE
shell: bash
if: steps.cache.outputs.cache-hit != 'true'
run: |
if [[ "${{ runner.os }}" == "Linux" ]]; then
sudo ./build_tools/before_all_linux.sh
elif [[ "${{ runner.os }}" == "macOS" ]]; then
./build_tools/before_all_mac.sh
elif [[ "${{ runner.os }}" == "Windows" ]]; then
./build_tools/before_all_windows.sh
else
echo "Unrecognized OS: '${{ inputs.os }}'."
exit 1
fi iqtree-piqtree-b8a3d6a/.github/actions/setup-piqtree/ 0000775 0000000 0000000 00000000000 15211731751 0022756 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/.github/actions/setup-piqtree/action.yml 0000664 0000000 0000000 00000001702 15211731751 0024756 0 ustar 00root root 0000000 0000000 name: Setup piqtree
description: "Setup Python and Fetch Static Library."
inputs:
python-version:
description: "Python version."
required: true
cache-key:
description: "Key for static library cache."
required: true
runs:
using: composite
steps:
- uses: actions/setup-python@v6
with:
python-version: ${{ inputs.python-version }}
- name: Cache IQ-TREE (Windows)
if: runner.os == 'Windows'
uses: actions/cache/restore@v5
id: cache-windows
with:
key: ${{ inputs.cache-key }}
path: |
src/piqtree/_libiqtree/iqtree.lib
src/piqtree/_libiqtree/iqtree.dll
fail-on-cache-miss: true
- name: Cache IQ-TREE (Linux/macOS)
if: runner.os != 'Windows'
uses: actions/cache/restore@v5
id: cache-unix
with:
key: ${{ inputs.cache-key }}
path: |
src/piqtree/_libiqtree/libiqtree.a
fail-on-cache-miss: true
iqtree-piqtree-b8a3d6a/.github/dependabot.yml 0000664 0000000 0000000 00000002133 15211731751 0021336 0 ustar 00root root 0000000 0000000 # To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "pip" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/.github/actions/build-iqtree/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/.github/actions/setup-piqtree/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
- package-ecosystem: "gitsubmodule"
directory: "/"
schedule:
interval: "daily"
iqtree-piqtree-b8a3d6a/.github/workflows/ 0000775 0000000 0000000 00000000000 15211731751 0020544 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/.github/workflows/add_source_to_release.yml 0000664 0000000 0000000 00000001661 15211731751 0025605 0 ustar 00root root 0000000 0000000 name: Attach Full Source to Release
on:
release:
types: [published]
permissions:
contents: write
jobs:
upload-source:
runs-on: ubuntu-latest
env:
VERSION: ${{ github.ref_name }}
TARBALL: piqtree-${{ github.ref_name }}.tar.gz
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Make Tarball
run: |
tar czf "../$TARBALL" \
--transform "s,^\.,piqtree-${VERSION}," \
--exclude-vcs .
mv "../$TARBALL" "$TARBALL"
- name: Compute SHA256 Checksum
run: sha256sum "$TARBALL" > "$TARBALL.sha256"
- name: Upload Full Source and SHA256 to GitHub Release
uses: softprops/action-gh-release@v3.0.0
with:
files: |
${{ env.TARBALL }}
${{ env.TARBALL }}.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} iqtree-piqtree-b8a3d6a/.github/workflows/build_container.yml 0000664 0000000 0000000 00000001263 15211731751 0024432 0 ustar 00root root 0000000 0000000 name: Build and Push Docker Image to ghcr
on:
workflow_dispatch:
push:
branches:
- main
paths:
- .devcontainer/DockerFile
permissions:
contents: read
packages: write
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v6
- name: Login to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u iqtree --password-stdin
- name: Build and Push Base Docker Image
run: |
docker build -f .devcontainer/DockerFile . \
-t ghcr.io/iqtree/piqtree:latest
docker push ghcr.io/iqtree/piqtree:latest
iqtree-piqtree-b8a3d6a/.github/workflows/build_docs.yml 0000664 0000000 0000000 00000002667 15211731751 0023411 0 ustar 00root root 0000000 0000000 name: Build Docs
concurrency:
group: docs-build-${{ github.ref }}
cancel-in-progress: true
on:
workflow_dispatch:
push:
branches:
- main
paths:
- 'docs/**'
- '.readthedocs.yaml'
- 'mkdocs.yml'
- 'rtd_get_docs.py'
permissions:
contents: read
jobs:
build-iqtree:
name: Fetch or Build IQ-TREE Static Library
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- id: build
uses: ./.github/actions/build-iqtree
with:
os: ubuntu-latest
outputs:
iqtree-sha: ${{steps.build.outputs.iqtree-sha}}
build-docs:
runs-on: ubuntu-latest
needs: build-iqtree
steps:
- name: Checkout Repository
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- uses: ./.github/actions/setup-piqtree
with:
python-version: "3.14"
cache-key: libiqtree-ubuntu-latest-${{ needs.build-iqtree.outputs.iqtree-sha }}
- name: Install Docs Dependencies
run: |
pip install .[doc]
- name: Build Documentation
run: |
mkdocs build
working-directory: ${{ github.workspace }}
- name: Upload Documentation Artifact
uses: actions/upload-artifact@v7
with:
name: piqtree-docs-html
path: site
iqtree-piqtree-b8a3d6a/.github/workflows/build_wheels.yml 0000664 0000000 0000000 00000005261 15211731751 0023741 0 ustar 00root root 0000000 0000000 name: Build Wheels
on: [workflow_dispatch]
permissions:
contents: read
jobs:
build:
name: Build Wheels for ${{matrix.platform_id}} on ${{matrix.os}}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# manylinux x86_64
- os: ubuntu-latest
platform_id: manylinux_x86_64
# MacOS arm64
- os: macos-15
platform_id: macosx_arm64
# Windows x86_64
- os: windows-latest
platform_id: win_amd64
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Set up QEMU for Linux ARM builds
if: ${{runner.os == 'Linux' && endsWith(matrix.platform_id, '_aarch64')}}
uses: docker/setup-qemu-action@v4
with:
platforms: arm64
- name: Set macOS Deployment Target
if: runner.os == 'macOS'
run: |
echo "MACOSX_DEPLOYMENT_TARGET=15.0" >> $GITHUB_ENV
- name: Install Boost
if: runner.os == 'Windows'
uses: MarkusJx/install-boost@v2.6.0
id: install-boost
with:
boost_version: 1.84.0
platform_version: 2022
toolset: mingw
- name: Setup MSVC Developer Command Prompt
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
- name: Build Wheels
uses: pypa/cibuildwheel@v4.0.0
env: # Can specify per os - e.g. CIBW_BEFORE_ALL_LINUX, CIBW_BEFORE_ALL_MACOS, CIBW_BEFORE_ALL_WINDOWS
CIBW_BEFORE_ALL_LINUX: ./build_tools/before_all_linux.sh
CIBW_BEFORE_ALL_MACOS: ./build_tools/before_all_mac.sh
CIBW_BEFORE_ALL_WINDOWS: bash ./build_tools/before_all_windows.sh
CIBW_ENVIRONMENT_WINDOWS: Boost_INCLUDE_DIR='${{ steps.install-boost.outputs.BOOST_ROOT }}/include' Boost_LIBRARY_DIRS='${{ steps.install-boost.outputs.BOOST_ROOT }}/lib'
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: >-
delvewheel repair --add-path src/piqtree/_libiqtree -w {dest_dir} {wheel}
CIBW_ARCHS_LINUX: ${{endsWith(matrix.platform_id, '_x86_64') && 'x86_64' || 'aarch64'}}
CIBW_ARCHS_MACOS: ${{endsWith(matrix.platform_id, 'universal2') && 'universal2' || 'auto'}}
CIBW_ARCHS_WINDOWS: ${{endsWith(matrix.platform_id, '_amd64') && 'AMD64' || 'ARM64'}}
CIBW_BUILD: "*${{matrix.platform_id}}"
CIBW_SKIP: "cp314t-*"
CIBW_TEST_REQUIRES: pytest pytest-mock
CIBW_TEST_COMMAND: pytest {package}/tests
- name: Upload Wheels
uses: actions/upload-artifact@v7
with:
name: cibw-wheels-${{ matrix.platform_id }}
path: ./wheelhouse/*.whl
iqtree-piqtree-b8a3d6a/.github/workflows/ci.yml 0000664 0000000 0000000 00000010571 15211731751 0021666 0 ustar 00root root 0000000 0000000 name: CI
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
workflow_dispatch:
schedule:
- cron: "35 4 */6 * *" # Every 6 days.
pull_request:
push:
branches-ignore:
- 'dependabot/**'
permissions:
contents: read
jobs:
build-iqtree:
name: Fetch or Build IQ-TREE Static Library on ${{matrix.os}}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-15, windows-latest] # Intel linux, ARM Mac, Windows
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- id: build
uses: ./.github/actions/build-iqtree
with:
os: ${{ matrix.os }}
outputs:
iqtree-sha: ${{steps.build.outputs.iqtree-sha}}
tests:
name: Run Tests with Python ${{matrix.python-version}} on ${{matrix.os}}
needs: build-iqtree
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-15, windows-latest] # Intel linux, ARM Mac, Windows
python-version: ["3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- uses: ./.github/actions/setup-piqtree
with:
python-version: ${{ matrix.python-version }}
cache-key: libiqtree-${{ matrix.os }}-${{ needs.build-iqtree.outputs.iqtree-sha }}
- name: Install llvm (macOS)
if: runner.os == 'macOS'
run: |
brew install llvm
- name: Install llvm (Windows)
if: runner.os == 'Windows'
run: |
choco install -y llvm --version=14.0.6 --allow-downgrade
- name: Run Nox Testing
run: |
pip install nox
nox -s test-${{ matrix.python-version }} -- --cov --cov-report=lcov:${{matrix.os}}-${{matrix.python-version}}.lcov --cov-report=term --cov-append --durations=20
- name: Coveralls Parallel
uses: coverallsapp/github-action@v2
with:
parallel: true
github-token: ${{secrets.github_token}}
flag-name: run-${{matrix.python-version}}-${{matrix.os}}
file: "${{matrix.os}}-${{matrix.python-version}}.lcov"
upload-coverage:
name: Finish Coveralls
needs: tests
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.github_token }}
parallel-finished: true
type_check:
name: Type Check
needs: build-iqtree
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.14"]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: ./.github/actions/setup-piqtree
with:
python-version: ${{ matrix.python-version }}
cache-key: libiqtree-${{ matrix.os }}-${{ needs.build-iqtree.outputs.iqtree-sha }}
- name: "Run Type Checking for ${{ matrix.python-version }}"
run: |
pip install nox
nox -s type_check-${{ matrix.python-version }}
lint:
name: Linting
needs: build-iqtree
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.14"]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: ./.github/actions/setup-piqtree
with:
python-version: ${{ matrix.python-version }}
cache-key: libiqtree-${{ matrix.os }}-${{ needs.build-iqtree.outputs.iqtree-sha }}
- name: "Run Linting for ${{ matrix.python-version }}"
run: |
pip install nox
nox -s ruff-${{ matrix.python-version }}
test-docs:
name: Test Code Blocks in Docs
needs: build-iqtree
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.14"]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- uses: ./.github/actions/setup-piqtree
with:
python-version: ${{ matrix.python-version }}
cache-key: libiqtree-${{ matrix.os }}-${{ needs.build-iqtree.outputs.iqtree-sha }}
- name: Test Code Blocks in Docs
run: |
pip install nox
nox -s test_docs-${{ matrix.python-version }}
iqtree-piqtree-b8a3d6a/.github/workflows/release.yml 0000664 0000000 0000000 00000011425 15211731751 0022712 0 ustar 00root root 0000000 0000000 name: Release
on: [workflow_dispatch]
permissions:
contents: read
jobs:
build-wheels:
name: Build Wheels for ${{matrix.platform_id}} on ${{matrix.os}}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# manylinux x86_64
- os: ubuntu-latest
platform_id: manylinux_x86_64
# MacOS arm64
- os: macos-15
platform_id: macosx_arm64
# Windows x86_64
- os: windows-latest
platform_id: win_amd64
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Set up QEMU for Linux ARM builds
if: ${{runner.os == 'Linux' && endsWith(matrix.platform_id, '_aarch64')}}
uses: docker/setup-qemu-action@v4
with:
platforms: arm64
- name: Set macOS Deployment Target
if: runner.os == 'macOS'
run: |
echo "MACOSX_DEPLOYMENT_TARGET=15.0" >> $GITHUB_ENV
- name: Install Boost
if: runner.os == 'Windows'
uses: MarkusJx/install-boost@v2.6.0
id: install-boost
with:
boost_version: 1.84.0
platform_version: 2022
toolset: mingw
- name: Setup MSVC Developer Command Prompt
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
- name: Build Wheels
uses: pypa/cibuildwheel@v4.0.0
env: # Can specify per os - e.g. CIBW_BEFORE_ALL_LINUX, CIBW_BEFORE_ALL_MACOS, CIBW_BEFORE_ALL_WINDOWS
CIBW_BEFORE_ALL_LINUX: ./build_tools/before_all_linux.sh
CIBW_BEFORE_ALL_MACOS: ./build_tools/before_all_mac.sh
CIBW_BEFORE_ALL_WINDOWS: bash ./build_tools/before_all_windows.sh
CIBW_ENVIRONMENT_WINDOWS: Boost_INCLUDE_DIR='${{ steps.install-boost.outputs.BOOST_ROOT }}/include' Boost_LIBRARY_DIRS='${{ steps.install-boost.outputs.BOOST_ROOT }}/lib'
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: >-
delvewheel repair --add-path src/piqtree/_libiqtree -w {dest_dir} {wheel}
CIBW_ARCHS_LINUX: ${{endsWith(matrix.platform_id, '_x86_64') && 'x86_64' || 'aarch64'}}
CIBW_ARCHS_MACOS: ${{endsWith(matrix.platform_id, 'universal2') && 'universal2' || 'auto'}}
CIBW_ARCHS_WINDOWS: ${{endsWith(matrix.platform_id, '_amd64') && 'AMD64' || 'ARM64'}}
CIBW_BUILD: "*${{matrix.platform_id}}"
CIBW_SKIP: "cp314t-*"
CIBW_TEST_REQUIRES: pytest pytest-mock
CIBW_TEST_COMMAND: pytest {package}/tests
- name: Upload Wheels
uses: actions/upload-artifact@v7
with:
name: cibw-wheels-${{ matrix.platform_id }}
path: ./wheelhouse/*.whl
build-iqtree:
name: Fetch or Build IQ-TREE Static Library
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- id: build
uses: ./.github/actions/build-iqtree
with:
os: ubuntu-latest
outputs:
iqtree-sha: ${{steps.build.outputs.iqtree-sha}}
build-docs:
runs-on: ubuntu-latest
needs: build-iqtree
steps:
- name: Checkout Repository
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- uses: ./.github/actions/setup-piqtree
with:
python-version: "3.14"
cache-key: libiqtree-ubuntu-latest-${{ needs.build-iqtree.outputs.iqtree-sha }}
- name: Install Docs Dependencies
run: |
pip install .[doc]
- name: Build Documentation
run: |
mkdocs build
working-directory: ${{ github.workspace }}
- name: Upload Documentation Artifact
uses: actions/upload-artifact@v7
with:
name: piqtree-docs-html
path: site
release-test:
name: Release to Test PyPI
needs: [build-wheels, build-docs]
environment: release
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Download Artifacts
uses: actions/download-artifact@v8
with:
pattern: cibw-*
path: dist
merge-multiple: true
- name: Publish Package Distributions to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
release:
name: Release to PyPI
needs: release-test
environment: release
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Download Artifacts
uses: actions/download-artifact@v8
with:
pattern: cibw-*
path: dist
merge-multiple: true
- name: Publish Package Distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1 iqtree-piqtree-b8a3d6a/.gitignore 0000664 0000000 0000000 00000006636 15211731751 0017152 0 ustar 00root root 0000000 0000000 # vscode
.vscode
# iqtree
*.bionj
*.ckp.gz
*.iqtree
*.log
*.mldist
*.treefile
# piqtree specific ignores
src/piqtree/_libiqtree/**/*.a
src/piqtree/_libiqtree/**/*.dll
src/piqtree/_libiqtree/**/*.lib
src/*.dll
# docs
/data/
/my_alignment.fasta
/my_protein.fasta
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
lcov.info
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
#Ignore vscode AI rules
.github/instructions/codacy.instructions.md
iqtree-piqtree-b8a3d6a/.gitmodules 0000664 0000000 0000000 00000000144 15211731751 0017323 0 ustar 00root root 0000000 0000000 [submodule "iqtree3"]
path = iqtree3
url = https://github.com/iqtree/iqtree3.git
branch = master
iqtree-piqtree-b8a3d6a/.readthedocs.yaml 0000664 0000000 0000000 00000001175 15211731751 0020402 0 ustar 00root root 0000000 0000000 # .readthedocs.yaml
# Read the Docs configuration file for MkDocs projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.14"
commands:
# Install the required dependencies
- pip install requests
# Run the script to download and extract the pre-built docs
- python rtd_get_docs.py
- echo "Documentation downloaded and extracted"
# Disable the default build processes since we're using pre-built docs
sphinx:
configuration: null
python:
install: []
iqtree-piqtree-b8a3d6a/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000012226 15211731751 0017751 0 ustar 00root root 0000000 0000000 # Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement by emailing
Gavin Huttley.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
iqtree-piqtree-b8a3d6a/LICENSE 0000664 0000000 0000000 00000043176 15211731751 0016167 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
iqtree-piqtree-b8a3d6a/README.md 0000664 0000000 0000000 00000006670 15211731751 0016437 0 ustar 00root root 0000000 0000000 # piqtree
[](https://pypi.org/project/piqtree/)
[](https://pypi.org/project/piqtree/)
[](https://github.com/iqtree/piqtree/blob/main/LICENSE)
[](https://github.com/iqtree/piqtree/actions/workflows/ci.yml)
[](https://coveralls.io/github/iqtree/piqtree?branch=main)
[](https://piqtree.readthedocs.io/en/latest/?badge=latest)
[](https://github.com/astral-sh/ruff)
`piqtree` (pronounced 'pie-cue-tree') is a library which allows you to use IQ-TREE directly from Python! The interface with Python is through [cogent3](https://cogent3.org) objects.
For usage, please refer to the [documentation](https://piqtree.readthedocs.io/) or the examples below.
If you encounter any problems or have any feature requests feel free to raise an [issue](https://github.com/iqtree/piqtree/issues)!
## Contributing
If you would like to help out by contributing to the piqtree project, please check out our [contributor guide](https://piqtree.readthedocs.io/en/latest/developers/)!
## Examples
### Phylogenetic Reconstruction
```python
from piqtree import build_tree
from cogent3 import load_aligned_seqs # Included with piqtree!
# Load Sequences
aln = load_aligned_seqs("tests/data/example.fasta", moltype="dna")
aln = aln.take_seqs(["Human", "Chimpanzee", "Rhesus", "Mouse"])
# Reconstruct a phylogenetic tree with IQ-TREE!
tree = build_tree(aln, "JC", rand_seed=1) # Optionally specify a random seed.
print("Tree topology:", tree) # A cogent3 tree object
print("Log-likelihood:", tree.params["lnL"])
# In a Jupyter notebook, try tree.get_figure() to see a dendrogram
```
> **Note**
> See the [cogent3 docs](https://cogent3.org) for examples on what you can do with cogent3 trees.
### Fit Branch Lengths to Tree Topology
```python
from piqtree import fit_tree
from cogent3 import load_aligned_seqs, make_tree
# Load Sequences
aln = load_aligned_seqs("tests/data/example.fasta", moltype="dna")
aln = aln.take_seqs(["Human", "Chimpanzee", "Rhesus", "Mouse"])
# Construct tree topology
tree = make_tree("(Human, Chimpanzee, (Rhesus, Mouse));")
# Fit branch lengths with IQ-TREE!
tree = fit_tree(aln, tree, "JC")
print("Tree with branch lengths:", tree)
print("Log-likelihood:", tree.params["lnL"])
```
## More
For more examples ranging from using ModelFinder and AliSim, to making rapid neighbour-joining trees, or randomly generated trees be sure to check out the [documentation](https://piqtree.readthedocs.io/)!
## Citation
Please cite
```bibtex
@article{10.1093/molbev/msag061,
author = {McArthur, Robert Neil and Wong, Thomas King-Fung and Lang, Yapeng and Morris, Richard Andrew and Caley, Katherine and Mallawaarachchi, Vijini and Minh, Bui Quang and Huttley, Gavin},
title = {piqtree: A Python Package for Seamless Phylogenetic Inference with IQ-TREE},
journal = {Molecular Biology and Evolution},
year = {2026},
pages = {msag061},
doi = {10.1093/molbev/msag061},
url = {https://doi.org/10.1093/molbev/msag061},
}
``` iqtree-piqtree-b8a3d6a/build_tools/ 0000775 0000000 0000000 00000000000 15211731751 0017466 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/build_tools/before_all_linux.sh 0000775 0000000 0000000 00000000566 15211731751 0023345 0 ustar 00root root 0000000 0000000 if command -v apt-get &> /dev/null; then
apt-get update -y && apt-get install -y libeigen3-dev libboost-all-dev
elif command -v yum &> /dev/null; then
yum update -y && yum install -y eigen3-devel boost-devel
elif command -v apk &> /dev/null; then
apk update && apk add eigen-dev boost-dev
else
echo "Unsupported package manager";
exit 1;
fi
bash build_tools/build_iqtree.sh iqtree-piqtree-b8a3d6a/build_tools/before_all_mac.sh 0000775 0000000 0000000 00000001015 15211731751 0022734 0 ustar 00root root 0000000 0000000 # Check if running in GitHub Actions
if [ "$GITHUB_ACTIONS" = "true" ]; then
brew update
fi
brew install llvm eigen@3 boost libomp make
export LDFLAGS="-L$(brew --prefix libomp)/lib"
export CPPFLAGS="-I$(brew --prefix libomp)/include -I$(brew --prefix eigen@3)/include"
export CXXFLAGS="-I$(brew --prefix libomp)/include"
export CMAKE_PREFIX_PATH="$(brew --prefix eigen@3):${CMAKE_PREFIX_PATH:-}"
export PKG_CONFIG_PATH="$(brew --prefix eigen@3)/share/pkgconfig:${PKG_CONFIG_PATH:-}"
bash build_tools/build_iqtree.sh
iqtree-piqtree-b8a3d6a/build_tools/before_all_windows.sh 0000664 0000000 0000000 00000001020 15211731751 0023657 0 ustar 00root root 0000000 0000000 # Install dependencies using choco
export Boost_INCLUDE_DIR=$(echo $Boost_INCLUDE_DIR | sed 's|\\|/|g')
export Boost_LIBRARY_DIRS=$(echo $Boost_LIBRARY_DIRS | sed 's|\\|/|g')
echo "Boost_INCLUDE_DIR: $Boost_INCLUDE_DIR"
echo "Boost_LIBRARY_DIRS: $Boost_LIBRARY_DIRS"
choco install -y llvm --version=14.0.6 --allow-downgrade
choco install -y eigen
LLVM_BIN=$(cygpath -u "${PROGRAMFILES}\\LLVM\\bin")
export PATH="$LLVM_BIN:$PATH"
export CC=clang.exe
export CXX=clang++.exe
# Build IQ-TREE
bash build_tools/build_iqtree.sh
iqtree-piqtree-b8a3d6a/build_tools/build_iqtree.sh 0000775 0000000 0000000 00000002546 15211731751 0022504 0 ustar 00root root 0000000 0000000 cd iqtree3
rm -rf build
mkdir build && cd build
if [[ "$OSTYPE" == "darwin"* ]]; then
echo "Building for macOS."
echo $LDFLAGS
echo $CPPFLAGS
echo $CXXFLAGS
cmake -DBUILD_LIB=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ..
gmake -j
elif [[ "$OSTYPE" == "msys"* || "$OSTYPE" == "cygwin"* ]]; then
echo "Building for Windows."
if [[ -n "$BOOST_ROOT" ]]; then
export Boost_INCLUDE_DIR="${BOOST_ROOT}"
export Boost_LIBRARY_DIRS="${BOOST_ROOT}"
fi
cmake -G "MinGW Makefiles" \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_FLAGS=--target=x86_64-pc-windows-gnu \
-DCMAKE_CXX_FLAGS=--target=x86_64-pc-windows-gnu \
-DCMAKE_MAKE_PROGRAM=make \
-DBoost_INCLUDE_DIR=$Boost_INCLUDE_DIR \
-DBoost_LIBRARY_DIRS=$Boost_LIBRARY_DIRS \
-DIQTREE_FLAGS="cpp14" \
-DBUILD_LIB=ON \
..
make -j
else
echo "Building for linux."
cmake -DBUILD_LIB=ON -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ..
make -j
fi
cd ../..
if [[ "$OSTYPE" == "darwin"* || "$OSTYPE" == "linux"* ]]; then
mv iqtree3/build/libiqtree.a src/piqtree/_libiqtree/
elif [[ "$OSTYPE" == "msys"* || "$OSTYPE" == "cygwin"* ]]; then
mv iqtree3/build/iqtree.lib src/piqtree/_libiqtree/
mv iqtree3/build/iqtree.dll src/piqtree/_libiqtree/
fi
iqtree-piqtree-b8a3d6a/changelog.d/ 0000775 0000000 0000000 00000000000 15211731751 0017320 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/changelog.d/README.md 0000664 0000000 0000000 00000005214 15211731751 0020601 0 ustar 00root root 0000000 0000000 # Adding changelog entries
This directory is used to store changelog fragments for the next release
of the project. Each file should contain a small changelog fragment
that will be added to the full changelog when the release is made.
The file is created using
```
scriv create --edit
```
to create a change entry
This will create a file with the correct name and format and commented out sample categories, and load it into your `git` editor (the one specified by ```git config --global core.editor``` )
Uncomment the category of change you are making and add a short description of the
change as a markdown bullet point. For example:
Contributors
* khiron
ENH
* Added a new feature that allows users to do Y
DEP
* Removed deprecated feature Z
BUG
* Fixed a bug that caused the project to crash when a user did X by doing Y instead
DOC
* Documented feature Z
Check the file in with your changes.
---
# Building a changelog
To build the changelog for the next release, run
```
scriv collect
```
This will create a file called `CHANGELOG.md` in the root of the project. This file will contain the full changelog for the project, including all the fragments that have been added to the changelog.d directory and remove those fragments. Note this requires that the `__init__.py` file's `__version__` variable is updated from the last time you ran collect, otherwise you will get a warning
```
Entry 'Changes since release 0.0.1' already uses version '0.0.1'.
```
... and the fragments will not be collected. When the `__version__` variable in the project is updated the next time you run collect, the fragments will be collected and the changelog will be updated.
You can override this to create a new collection of all available fragments that are not aligned with a `__version__` with
```
scriv collect --version "description of a milestone not yet used"
```
---
# Releasing a new version
To release a version of the project, run
```
scriv release
```
This will create a new tag in the `git` repository, and create a new release on GitHub. The release will contain the full changelog for the project, and the tag will be annotated with the full changelog as well. Note you will need to have a GitHub classic personal access token set up in your environment (GITHUB_TOKEN) for this to work.
If you are using VS code and powershell you can add the following to your `settings.json` file to set the environment variable for the terminal. If you are using a different terminal you will need to set the environment variable in the appropriate way for your terminal.
```json
"terminal.integrated.env.windows": {
"GITHUB_TOKEN": "ghp_...",
}
```
---
iqtree-piqtree-b8a3d6a/changelog.d/templates/ 0000775 0000000 0000000 00000000000 15211731751 0021316 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/changelog.d/templates/new.md.j2 0000664 0000000 0000000 00000000354 15211731751 0022745 0 ustar 00root root 0000000 0000000
{% for cat in config.categories -%}
{% endfor -%}
iqtree-piqtree-b8a3d6a/changelog.d/templates/new.rst.j2 0000664 0000000 0000000 00000000560 15211731751 0023154 0 ustar 00root root 0000000 0000000 .. A new scriv changelog fragment.
{% if config.categories -%}
..
.. Uncomment the header that is right (remove the leading dots).
..
{% for cat in config.categories -%}
.. {{ cat }}
.. {{ config.rst_header_chars[1] * (cat|length) }}
..
.. - A bullet item for the {{ cat }} category.
..
{% endfor -%}
{% else %}
- A bullet item for this fragment. EDIT ME!
{% endif -%} iqtree-piqtree-b8a3d6a/changelog.d/templates/title.md.j2 0000664 0000000 0000000 00000000040 15211731751 0023265 0 ustar 00root root 0000000 0000000 Changes in release "{{version}}" iqtree-piqtree-b8a3d6a/changelog.md 0000664 0000000 0000000 00000017113 15211731751 0017423 0 ustar 00root root 0000000 0000000
# Changes in release "0.8.0"
## Contributors
- @rmcar17 - Python `simulate_alignment` implementation, documentation, project maintanence and Python processing of additional cli options.
- @thomaskf - IQ-TREE library interface maintanence and enhancements (including processing additional cli options!).
- @trongnhanuit & @The-CodeBreakeR - AliSim implementation.
- @YapengLang - processing UNREST model parameters and storing additional values on returned tree objects.
## ENH
- AliSim can now be used through `simulate_alignment`.
- Additional command line options can now be sent to `build_tree`, `fit_tree` and `model_finder` with the `other_options` parameter.
- UNREST model parameters are now populated on generated trees.
- More specific type information is now used across a suite of functions.
- The used model name is now stored on trees generated by `build_tree`.
## API
- A seed of 0 is now deterministic across all IQ-TREE functions. `None` must be used (the default) for non-determinism.
## DOC
- Various enhancements to grammar/spelling.
- Add sections for `simulate_alignment`.
# Changes in release "0.7.0"
## Contributors
- @rmcar17, fixed a jupyter bug on windows and unwanted behaviour when taxon names contained underscores.
- @thomaskf and @rmcar17 implemented the ability to fix certain branch lengths when using `fit_tree`.
## ENH
- Add an option to fix branch lengths when using `fit_tree` called `bl_fixed`.
## BUG
- `piqtree` now works in jupyter notebooks on windows platforms, like it already does for the others.
- Fix unexpected behaviour when taxon names contain underscores when using `fit_tree`.
# Changes in release "0.6.1"
## Contributors
- @GavinHuttley docs
- @rmcar17 dependencies
## BUG
- Pin build dependencies for reproducible builds and use new delvewheel `get_all_needed` API.
## DOC
- Update examples to the latest Cogent3 API.
# Changes in release "0.6.0"
## Contributors
- @rmcar17 and @thomaskf enabled windows support for piqtree!
- @rmcar17 ensured `nj_tree` raises an appropriate error on NaN input.
- @rmcar17 reworked `random_trees` and the related app to become `random_tree`, returning a single tree.
- @rmcar17 and @thomaskf integrated IQ-TREE 3 into piqtree.
- @rmcar17 added support for Lie Markov Model prefixes.
- @rmcar17 added the STRSYM and UNREST models.
- @rmcar17 added source tracking for the inputs of apps.
- @rmcar17 and @thomaskf integrated consensus tree contruction into `piqtree`.
- @rmcar17 added support for the parameterisation of currently supported models, base frequencies, and rate heterogeneity.
## ENH
- Added windows support!
- Add `random_tree` and `piqtree_random_tree`. The function and app have the same parameters as the `random_trees` and `piqtree_random_trees` versions, except the `num_trees` argument has been removed.
- `piqtree` now uses IQ-TREE 3 for its internal library.
- Add support for Lie Markov Model prefixes.
- Add the STRSYM and UNREST models.
- `piqtree` apps now track the sources of their inputs.
- Add a method for building consensus trees with specifiable support parameters.
- Add a consensus tree app.
- Substitution models, base frequencies, and models for rateheterogeneity can now be parameterised.
## BUG
- An error is now raised when calling `nj_tree` with NaN distances instead of failing silently.
## API
- Split Lie Markov Models out of the standard dna enum.
- Remove unused `rand_seed` from `fit_tree`.
- All apps have been renamed to take the form `piq_`.
- `random_trees` and `piqtree_random_trees` have been removed in favour of `random_tree` and `piq_random_tree`. Looping can be used if multiple trees are needed.
# Changes in release "0.5.0"
## Contributors
- @GavinHuttley added `nj_tree` as a hook for `cogent3.Alignment.quick_tree`.
- @YapengLang handled negative branch lengths from the rapidNJ tree.
- @rmcar17, @thomaskf general maintanence on the piqtree/IQ-TREE sides including work on windows behind the scenes.
## ENH
- Add support for Python 3.13, remove support for 3.10
- IQ-TREE's rapidNJ implementation can be used as a hook for `quick_tree` on `cogent3` alignment objects. Try `Alignment.quick_tree(use_hook="piqtree")`.
- `nj_tree` now by default does not allow negative branch lengths. Set `allow_negative=True` if this behaviour is desired.
- Allow `str` to be used for `model` in `build_tree` and `fit_tree`. The value is automatically coerced into the `Model` class.
## API
- Simplify API for `piqtree_phylo` and `piqtree_fit` apps. Both now take a single parameter for the model, matching the parameter for `model` in `build_tree` and `fit_tree`.
# Changes in release "0.4.0"
## Contributors
- @rmcar17 integrated new functions from IQ-TREE in Python, added multithreading support, and wrote the API refererence and quickstart.
- @thomaskf exposed all new functions from IQ-TREE to be available from Python, and worked on multithreading support.
- @GavinHuttley worked on setting up and writing the documentation and associated devtools, ModelFinder, and integration with `cogent3` apps.
- @YapengLang worked on bootstrapping support and extracting model parameters
- @KatherineCaley worked on processing the ModelFinder results.
## ENH
- piqtree2 renamed piqtree to support future major releases of IQ-TREE.
- piqtree now supports multithreading!
- New function `nj_tree` constructs a rapid neighbour-joining tree from a pairwise distance matrix.
- New function `model_finder` finds the best model for a given alignment.
- New function `jc_distances` constructs a pairwise JC distance matrix from an alignment.
- New function `make_model` allows converting an IQ-TREE string representation of a model to a `Model` class.
- API for `random_trees` has changed - new order (`num_trees`, `num_taxa`, `tree_mode`, then `rand_seed`).
- API for `robinson_foulds` has changed - now accepts a Sequence of trees.
- Model parameters are now extracted from IQ-TREE where for now possible.
- `build_tree` now supports ultrafast bootstrapping.
- `Model` creation is now more robust.
- Use `piqtree.__iqtree_version__` to see what version of piqtree is being used.
- See what can now be done in our [new documentation](https://piqtree.readthedocs.io)!
## DOC
- [Documentation](https://piqtree.readthedocs.io) is now on readthedocs!
# Changes in release "0.3.1"
## ENH
- Add support for Lie Markov Models.
- Base frequencies default to None (specified by model).
## BUG
- `piqtree2` apps are now pickleable (they can now be run with `parallel=True` in the cogent3 app infrastructure)
# Changes in release "0.3.0"
## Contributors
- @rmcar17 Added new classes to enhance model specification when calling `build_tree` and `fit_tree`.
- @thomaskf fixed a bug in IQ-TREE resulting in segmentation faults on some invalid arguments.
## ENH
- `build_tree` and `fit_tree` now allow specifying base frequencies, invariable sites and rate heterogeneity options.
## BUG
- Fixed a segmentation fault on repetitive calls to IQ-TREE with particular arguments.
# Changes in release "0.2.0"
## Contributors
- Richard Morris
- Robert McArthur
## ENH
- `build_tree` and `fit_tree` now use enums for the substitution model.
## BUG
- Fixed an issue where calling `build_tree` or `fit_tree` twice, then another function with invalid input resulted in a segmentation fault.
## DOC
- Implement scriv as a tool to manage collection of changes, and automated collation into the changelog
iqtree-piqtree-b8a3d6a/docs/ 0000775 0000000 0000000 00000000000 15211731751 0016077 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/api/ 0000775 0000000 0000000 00000000000 15211731751 0016650 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/api/alignment/ 0000775 0000000 0000000 00000000000 15211731751 0020626 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/api/alignment/simulate_alignment.md 0000664 0000000 0000000 00000000234 15211731751 0025030 0 ustar 00root root 0000000 0000000 # simulate_alignment
::: piqtree.simulate_alignment
## Usage
For usage, see ["Simulate alignments with AliSim"](../../quickstart/simulate_alignment.md).
iqtree-piqtree-b8a3d6a/docs/api/genetic_distance/ 0000775 0000000 0000000 00000000000 15211731751 0022140 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/api/genetic_distance/jc_distances.md 0000664 0000000 0000000 00000000236 15211731751 0025114 0 ustar 00root root 0000000 0000000 # jc_distances
::: piqtree.jc_distances
## Usage
For usage, see ["Calculate pairwise Jukes-Cantor distances"](../../quickstart/calculate_jc_distances.md).
iqtree-piqtree-b8a3d6a/docs/api/index.md 0000664 0000000 0000000 00000003206 15211731751 0020302 0 ustar 00root root 0000000 0000000 # API Reference Index
## Trees
| Name | Summary |
|------|---------|
| [build_tree](tree/build_tree.md) | Construct a maximum-likelihood phylogenetic tree. |
| [fit_tree](tree/fit_tree.md) | Fit branch lengths to a phylogenetic tree. |
| [nj_tree](tree/nj_tree.md) | Construct rapid neighbour-joining tree from pairwise distance matrix. |
| [consensus_tree](tree/consensus_tree.md) | Construct a consensus tree from a collection of trees. |
| [random_tree](tree/random_tree.md) | Create a randomly generated phylogenetic tree. |
## Alignments
| Name | Summary |
|------|---------|
| [simulate_alignment](alignment/simulate_alignment.md) | Simulate an alignment with AliSim. |
## Substitution Models
| Name | Summary |
|------|---------|
| [model_finder](model/model_finder.md) | Determine the best-fit model for your data. |
| [ModelFinderResult](model/ModelFinderResult.md) | Collection of data returned by IQ-TREE's ModelFinder. |
| [Model](model/Model.md) | Class for substitution models. |
| [make_model](model/make_model.md) | Function to construct Model classes from IQ-TREE strings. |
| [SubstitutionModel](model/SubstitutionModel.md) | Enums for substitution models. |
| [FreqType](model/FreqType.md) | Enum for base frequencies and class for custom base frequencies. |
| [RateModel](model/RateModel.md) | Classes for rate heterogeneity. |
## Genetic Distances
| Name | Summary |
|------|---------|
| [jc_distances](genetic_distance/jc_distances.md) | Pairwise Jukes-Cantor genetic distances. |
## Tree Distances
| Name | Summary |
|------|---------|
| [robinson_foulds](tree_distance/robinson_foulds.md) | Pairwise Robinson-Foulds distances. |
iqtree-piqtree-b8a3d6a/docs/api/model/ 0000775 0000000 0000000 00000000000 15211731751 0017750 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/api/model/FreqType.md 0000664 0000000 0000000 00000000403 15211731751 0022026 0 ustar 00root root 0000000 0000000 # FreqType
::: piqtree.model.FreqType
options:
show_if_no_docstring: true
::: piqtree.model.CustomBaseFreq
## Usage
For usage, see ["Use different kinds of substitution models"](../../quickstart/using_substitution_models.md#base-frequencies).
iqtree-piqtree-b8a3d6a/docs/api/model/Model.md 0000664 0000000 0000000 00000000224 15211731751 0021330 0 ustar 00root root 0000000 0000000 # Model
::: piqtree.Model
## Usage
For usage, see ["Use different kinds of substitution models"](../../quickstart/using_substitution_models.md).
iqtree-piqtree-b8a3d6a/docs/api/model/ModelFinderResult.md 0000664 0000000 0000000 00000000246 15211731751 0023663 0 ustar 00root root 0000000 0000000 # ModelFinderResult
::: piqtree.ModelFinderResult
## Usage
For usage, see ["Find the model of best fit with ModelFinder"](../../quickstart/using_model_finder.md).
iqtree-piqtree-b8a3d6a/docs/api/model/RateModel.md 0000664 0000000 0000000 00000000337 15211731751 0022151 0 ustar 00root root 0000000 0000000 # RateModel
::: piqtree.model.DiscreteGammaModel
::: piqtree.model.FreeRateModel
## Usage
For usage, see ["Use different kinds of substitution models"](../../quickstart/using_substitution_models.md#rate-heterogeneity).
iqtree-piqtree-b8a3d6a/docs/api/model/SubstitutionModel.md 0000664 0000000 0000000 00000001246 15211731751 0023772 0 ustar 00root root 0000000 0000000 # SubstitutionModel
Enums for available DNA (including Lie Markov Models) and amino acid models. Strings may be used instead of the enums.
::: piqtree.model.StandardDnaModel
options:
show_if_no_docstring: true
::: piqtree.model.StandardDnaModelInstance
options:
show_if_no_docstring: true
::: piqtree.model.LieModel
options:
show_if_no_docstring: true
::: piqtree.model.LieModelInstance
options:
show_if_no_docstring: true
::: piqtree.model.AaModel
options:
show_if_no_docstring: true
## Usage
For usage, see ["Use different kinds of substitution models"](../../quickstart/using_substitution_models.md#usage).
iqtree-piqtree-b8a3d6a/docs/api/model/make_model.md 0000664 0000000 0000000 00000000236 15211731751 0022370 0 ustar 00root root 0000000 0000000 # make_model
::: piqtree.make_model
## Usage
For usage, see ["Use different kinds of substitution models"](../../quickstart/using_substitution_models.md).
iqtree-piqtree-b8a3d6a/docs/api/model/model_finder.md 0000664 0000000 0000000 00000000234 15211731751 0022720 0 ustar 00root root 0000000 0000000 # model_finder
::: piqtree.model_finder
## Usage
For usage, see ["Find the model of best fit with ModelFinder"](../../quickstart/using_model_finder.md).
iqtree-piqtree-b8a3d6a/docs/api/tree/ 0000775 0000000 0000000 00000000000 15211731751 0017607 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/api/tree/build_tree.md 0000664 0000000 0000000 00000000234 15211731751 0022246 0 ustar 00root root 0000000 0000000 # build_tree
::: piqtree.build_tree
## Usage
For usage, see ["Construct a maximum likelihood phylogenetic tree"](../../quickstart/construct_ml_tree.md).
iqtree-piqtree-b8a3d6a/docs/api/tree/consensus_tree.md 0000664 0000000 0000000 00000000260 15211731751 0023166 0 ustar 00root root 0000000 0000000 # consensus_tree
::: piqtree.consensus_tree
## Usage
For usage, see ["Construct a consensus tree from a collection of trees"](../../quickstart/construct_consensus_tree.md).
iqtree-piqtree-b8a3d6a/docs/api/tree/fit_tree.md 0000664 0000000 0000000 00000000237 15211731751 0021734 0 ustar 00root root 0000000 0000000 # fit_tree
::: piqtree.fit_tree
## Usage
For usage, see ["Fit branch lengths to a tree topology from an alignment"](../../quickstart/fit_tree_topology.md).
iqtree-piqtree-b8a3d6a/docs/api/tree/nj_tree.md 0000664 0000000 0000000 00000000245 15211731751 0021560 0 ustar 00root root 0000000 0000000 # nj_tree
::: piqtree.nj_tree
## Usage
For usage, see ["Construct a rapid neighbour-joining tree from a distance matrix"](../../quickstart/construct_nj_tree.md).
iqtree-piqtree-b8a3d6a/docs/api/tree/random_tree.md 0000664 0000000 0000000 00000000341 15211731751 0022426 0 ustar 00root root 0000000 0000000 # random_tree
::: piqtree.random_tree
::: piqtree.TreeGenMode
options:
show_if_no_docstring: true
## Usage
For usage, see ["Make a randomly generated phylogenetic tree"](../../quickstart/make_random_tree.md).
iqtree-piqtree-b8a3d6a/docs/api/tree_distance/ 0000775 0000000 0000000 00000000000 15211731751 0021461 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/api/tree_distance/robinson_foulds.md 0000664 0000000 0000000 00000000265 15211731751 0025213 0 ustar 00root root 0000000 0000000 # robinson_foulds
::: piqtree.robinson_foulds
## Usage
For usage, see ["Calculate pairwise Robinson-Foulds distances between trees"](../../quickstart/calculate_rf_distances.md).
iqtree-piqtree-b8a3d6a/docs/apps/ 0000775 0000000 0000000 00000000000 15211731751 0017042 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/apps/app_pipeline.py 0000664 0000000 0000000 00000004067 15211731751 0022070 0 ustar 00root root 0000000 0000000 # %% [markdown]
# ## Building workflows using `piqtree` apps
# > **WARNING**
# > This page is under construction!
#
# We can combine `piqtree` apps with other cogent3 apps to develop a pipeline. There are multiple concepts involved here, particularly data stores, composed apps, parallel execution, log files etc... See the `cogent3` [app documentation](https://cogent3.org/doc/app/index.html) for more details.
#
# To develop a pipeline efficiently we only need a subset of the sequences in an alignment. We will use the [diverse-seq](https://pypi.org/project/diverse-seq/) plugin for that purpose. This allows selecting a specified subset of sequences that capture the diversity in an alignment.
#
# But first, we need the data.
# %%
from piqtree import download_dataset
alns_path = download_dataset("mammal-orths.zip", dest_dir="data", inflate_zip=False)
# %% [markdown]
# We open this directory as a `cogent3` data store.
# %%
from cogent3 import open_data_store
dstore = open_data_store(alns_path, suffix="fa")
dstore.describe
# %% [markdown]
# We need to create some apps to: load data, a divergent sequence selector app, drop alignment columns containing non-canonical nucleotides (so gaps and N's), select alignments with a minimym number of aligned columns, a "data store" to write results to and a writer. These will then be combined into a single composed app which will be applied to all the alignments in the data store.
# %%
import pathlib
from collections import Counter
from cogent3 import get_app
outpath = pathlib.Path("data/delme.sqlitedb")
outpath.unlink(missing_ok=True)
loader = get_app("load_aligned", format_name="fasta", moltype="dna")
divergent = get_app("dvs_nmost", n=10, k=6)
just_nucs = get_app("omit_degenerates") # has to go after the divergent selector
min_length = get_app("min_length", length=600)
best_model = get_app("piq_model_finder")
app = loader + divergent + just_nucs + min_length + best_model
model_counts = Counter(
str(result.best_aic)
for result in app.as_completed(dstore, show_progress=True, parallel=True)
if result
)
model_counts
iqtree-piqtree-b8a3d6a/docs/apps/available_help.py 0000664 0000000 0000000 00000000657 15211731751 0022354 0 ustar 00root root 0000000 0000000 # %% [markdown]
# To see the apps that `piqtree` makes available, use the `cogent3` function `available_apps()` as follows.
# %%
from cogent3 import available_apps
available_apps("piqtree")
# %% [markdown]
# For a particular app, use the `cogent3` function `app_help()` to find out what the options are.
# %%
from cogent3 import app_help
app_help("piq_build_tree")
# %%
from cogent3 import app_help
app_help("piq_fit_tree")
iqtree-piqtree-b8a3d6a/docs/apps/fit_tree.py 0000664 0000000 0000000 00000002574 15211731751 0021225 0 ustar 00root root 0000000 0000000 # %% [markdown]
# We evaluate a support for a specific phylogeny using `piq_fit_tree`.
# For this simple case, we will assess the support for a specific phylogeny using the GTR model on one alignment.
# %%
import cogent3
from piqtree import download_dataset
aln_path = download_dataset("example.phy.gz", dest_dir="data")
aln = cogent3.load_aligned_seqs(aln_path, moltype="dna", format_name="phylip")
aln
# %% [markdown]
# We use a tree corresponding to the data in the `example.phy` file.
# %%
tree_path = download_dataset("example.tree.gz", dest_dir="data")
tree = cogent3.load_tree(tree_path)
tree.get_figure().show()
# %% [markdown]
# We now take a look at the help for the `piq_fit_tree` app.
# %%
from cogent3 import app_help
app_help("piq_fit_tree")
# %% [markdown]
# We fit a GTR model and estimate the nucleotide frequencies by maximum likelihood.
# %%
from cogent3 import get_app
fit_gtr = get_app("piq_fit_tree", tree, model="GTR+FO")
fit_gtr
# %% [markdown]
# ## Fit the model
# %%
fit = fit_gtr(aln)
# %% [markdown]
# The `fit` object is a `cogent3` tree (`PhyloNode`) and the maximum likelihood estimated parameters are stored in the `params` attribute.
#
# > **Note**
# > "lnL" is short for log likelihood and is the log likelihood of the model.
# > "mprobs" is short for motif probabilities and are the estimated equilibrium frequencies of the nucleotides.
# %%
fit.params
iqtree-piqtree-b8a3d6a/docs/apps/index.md 0000664 0000000 0000000 00000000520 15211731751 0020470 0 ustar 00root root 0000000 0000000 # Using the `piqtree` apps
- [Available apps](available_help.py)
- [Selecting models for phylogenetic analysis](model_finder.py)
- [Estimate a phylogenetic tree](phylo.py)
- [Fit a model to one tree](fit_tree.py)
- [Pairwise JC distances](pairwise_dist.py)
- [NJ tree](nj.py)
- [Parallel processing across alignments](app_pipeline.py)
iqtree-piqtree-b8a3d6a/docs/apps/model_finder.py 0000664 0000000 0000000 00000002304 15211731751 0022042 0 ustar 00root root 0000000 0000000 # %% [markdown]
# We use the `piq_model_finder` app to rank models. This is the python binding to the IQ-TREE ModelFinder tool.
# %%
from cogent3 import app_help, get_app, load_aligned_seqs
from piqtree import download_dataset
aln_path = download_dataset("example.phy.gz", dest_dir="data")
aln = load_aligned_seqs(aln_path, moltype="dna", format_name="phylip")
# %% [markdown]
# Get help and then apply `piq_model_finder`.
# %%
app_help("piq_model_finder")
# %%
mfinder = get_app("piq_model_finder")
ranked = mfinder(aln)
ranked
# %% [markdown]
# ## Accessing the best model
# The different measures used to select the best model, AIC, AICc, and BIC, are available as attributes of the result object. We'll select AICc as the measure for choosing the best model.
# %%
selected = ranked.best_aicc
# %% [markdown]
# You can inspect the statistics for one of these using the `model_stats` attribute.
# %%
ranked.model_stats[selected]
# %% [markdown]
# ## Using the best model
# You can apply the selected model to a phylogenetic analysis.
# > **Note**
# > The process is the same for both the `piq_build_tree` and the `piq_fit_tree` apps.
# %%
fit = get_app("piq_build_tree", selected)
fitted = fit(aln)
fitted
iqtree-piqtree-b8a3d6a/docs/apps/nj.py 0000664 0000000 0000000 00000002766 15211731751 0020036 0 ustar 00root root 0000000 0000000 # %% [markdown]
# The Neighbour-Joining method uses genetic distances to build a phylogenetic tree. `piqtree` provides only `piq_jc_distances` for this. `cogent3` includes many more methods. The results of either can be used to build a tree. For divergent sequences we will use Lake's paralinear measure as it accomodates divergent sequence compositions.
# %%
import cogent3
from piqtree import download_dataset
aln_path = download_dataset("example.phy.gz", dest_dir="data")
aln = cogent3.load_aligned_seqs(aln_path, moltype="dna", format_name="phylip")
# %% [markdown]
# ## Getting a paralinear distance matrix
# This can be obtained directly from the alignment object itself.
# %%
dists = aln.distance_matrix(calc="paralinear")
dists
# %% [markdown]
# Get help on the `piq_nj_tree` app.
# %%
cogent3.app_help("piq_nj_tree")
# %% [markdown]
# Make an app and apply it to the distance matrix.
# %%
nj = cogent3.get_app("piq_nj_tree")
tree = nj(dists)
# %% [markdown]
# > **Warning**
# > Branch lengths can be negative in the piqtree NJ tree. This manifests as branches going backwards!
# %%
tree.get_figure().show()
# %% [markdown]
# > **Note**
# > To write the tree to a file, use the `write()` method.
# %% [markdown]
# ## Combining the piqtree dist and nj apps
# We can combine the `piq_jc_distances` and `piq_nj_tree` apps to build a tree from an alignment in one step.
# %%
jc = cogent3.get_app("piq_jc_distances")
nj = cogent3.get_app("piq_nj_tree")
app = jc + nj
tree = app(aln)
tree.get_figure().show()
iqtree-piqtree-b8a3d6a/docs/apps/pairwise_dist.py 0000664 0000000 0000000 00000001056 15211731751 0022264 0 ustar 00root root 0000000 0000000 # %% [markdown]
# We estimate pairwise distances via the Jukes-Cantor model with the `piq_jc_distances` app.
# %%
import cogent3
from piqtree import download_dataset
aln_path = download_dataset("example.phy.gz", dest_dir="data")
aln = cogent3.load_aligned_seqs(aln_path, moltype="dna", format_name="phylip")
# %% [markdown]
# We get help on the `piqtree_jc_dist` app.
# %%
cogent3.app_help("piq_jc_distances")
# %% [markdown]
# Make an app and apply it to the alignment.
# %%
jc_dists = cogent3.get_app("piq_jc_distances")
dists = jc_dists(aln)
dists
iqtree-piqtree-b8a3d6a/docs/apps/phylo.py 0000664 0000000 0000000 00000002214 15211731751 0020546 0 ustar 00root root 0000000 0000000 # %% [markdown]
# We use the `piq_build_tree` app to build phylogenies.
# For this simple case, we will build a single phylogeny using the GTR model on one alignment.
# We have a utility script for this documentation that provides the local path to that data. We will then load that data and, as it contains quite a few sequences, we will use a subset of it. We use methods on the `cogent3` object to do that.
# %%
import cogent3
from piqtree import download_dataset
aln_path = download_dataset("example.phy.gz", dest_dir="data")
aln = cogent3.load_aligned_seqs(aln_path, moltype="dna", format_name="phylip")
aln
# %% [markdown]
# We now take a look at the help for the `piq_build_tree` app.
# %%
from cogent3 import app_help
app_help("piq_build_tree")
# %% [markdown]
# We build an app for estimating phylogenies with a GTR model
# %%
from cogent3 import get_app
phylo_gtr = get_app("piq_build_tree", model="GTR", bootstrap_reps=1000)
phylo_gtr
# %% [markdown]
# ## Run the phylogeny estimation and display branches with support < 90%.
# %%
tree = phylo_gtr(aln)
dnd = tree.get_figure(show_support=True, threshold=90)
dnd.show(width=600, height=600)
iqtree-piqtree-b8a3d6a/docs/citation.md 0000664 0000000 0000000 00000002300 15211731751 0020226 0 ustar 00root root 0000000 0000000 # Citation
Please cite piqtree as follows:
McArthur RN, Wong TK-F, Lang Y, Morris RA, Caley K, Mallawaarachchi V, Minh BQ, Huttley G, 2026. "piqtree: A Python Package for Seamless Phylogenetic Inference with IQ-TREE", Molecular Biology and Evolution, msag061, [10.1093/molbev/msag061](https://doi.org/10.1093/molbev/msag061).
```bibtex
@article{piqtree,
author = {McArthur, Robert Neil and Wong, Thomas King-Fung and Lang, Yapeng and Morris, Richard Andrew and Caley, Katherine and Mallawaarachchi, Vijini and Minh, Bui Quang and Huttley, Gavin},
title = {piqtree: A Python Package for Seamless Phylogenetic Inference with IQ-TREE},
journal = {Molecular Biology and Evolution},
year = {2026},
pages = {msag061},
doi = {10.1093/molbev/msag061},
url = {https://doi.org/10.1093/molbev/msag061},
}
```
Please cite cogent3 as follows:
Huttley, G. (2021). cogent3: comparative genomics toolkit (2020.12.21). [10.5281/zenodo.4542532](https://doi.org/10.5281/zenodo.4542532)
```bibtex
@misc{cogent3,
title = {cogent3: comparative genomics toolkit (2020.12.21)},
author = {Huttley, Gavin A},
year = {2021},
doi = {10.5281/zenodo.4542532},
}
```
iqtree-piqtree-b8a3d6a/docs/developers/ 0000775 0000000 0000000 00000000000 15211731751 0020247 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/developers/contributing.md 0000664 0000000 0000000 00000001711 15211731751 0023300 0 ustar 00root root 0000000 0000000 # Contributing to `piqtree`
We welcome all contributors who would like to work on the `piqtree` project.
## Overview
Contributions can be made through a GitHub pull request to the main repository.
We recommend working off a new branch when contributing new features.
After submitting a pull request, it will be reviewed by a member of the core dev team.
It's rare for a contribution to be accepted without some edits.
This is a constructive process and we hope you will find our remarks useful.
Thanks for participating!
## Code formatting
We use `ruff` to format the project's code. The formatter can be run in the terminal in the project's base directory:
```bash
ruff format
```
## Docstrings
All public-facing functions must be documented and we strongly encourage docstrings for internal functions,
particularly those with wide usage. We follow the [NumPy docstring style guide](https://numpydoc.readthedocs.io/en/latest/format.html)
for all docstrings.
iqtree-piqtree-b8a3d6a/docs/developers/environment_setup.md 0000664 0000000 0000000 00000003751 15211731751 0024363 0 ustar 00root root 0000000 0000000 # Setting up your environment for development
## Initial setup
Fork and clone the [`piqtree` repository](https://github.com/iqtree/piqtree).
## Working with the `iqtree3` submodule
We use a git submodule to keep track of the version of IQ-TREE that is being used.
To initialise the submodule, or to get the latest version after an update, the
following can be run:
```bash
git submodule update --init --recursive
```
## Building the IQ-TREE library
There are several build scripts used by the CI to install dependencies and build the
IQ-TREE library.
If you are working through the dev container, all dependencies should already be installed.
The IQ-TREE library can be built with `./build_tools/build_iqtree.sh`.
If you are working on a Mac, running `./build_tools/before_all_mac.sh` will install the
required dependencies through homebrew, then build the IQ-TREE library. If you need to
build the library again, running `./build_tools/build_iqtree.sh` will skip the dependency
installation step.
If you are working on linux, check the top of the `.devcontainer/DockerFile` for the list of
dependencies. Once installed, the IQ-TREE library can be built with `./build_tools/build_iqtree.sh`.
## Installing `piqtree` for standard development
After completing the above steps, in your preferred Python virtual environment run the following
in the repository's directory:
```bash
pip install -e ".[dev]"
```
This will install `piqtree` in editable mode, alongside testing, linting and other dependencies.
## Installing `piqtree` for documentation development
To contribute to the documentation, we recommend running the following after the above
steps in a separate virtual environment:
```bash
pip install -e ".[doc]"
```
This will install `piqtree` in editable mode, along with dependencies for building the documentation.
## Running the tests
To verify that installation has worked, run the following in the base directory of this repository using your chosen development environment.
```bash
pytest
```
iqtree-piqtree-b8a3d6a/docs/developers/index.md 0000664 0000000 0000000 00000001173 15211731751 0021702 0 ustar 00root root 0000000 0000000 # Contributor Guide
This guide is intended for those who wish to contribute to the `piqtree` project.
- See ["Setting up your environment for development"](./environment_setup.md) for setting up `piqtree`.
- See ["Working with the IQ-TREE submodule"](./iqtree_submodule.md) for keeping the IQ-TREE library up to date.
- See ["Contributing"](./contributing.md) for how to contribute to `piqtree`.
- See ["Testing, linting, and type checking"](./testing.md) for checking your code.
- See ["Troubleshooting"](./troubleshooting.md) for common problems.
- See ["Release checklist"](./release.md) for releasing a new version of `piqtree`.
iqtree-piqtree-b8a3d6a/docs/developers/iqtree_submodule.md 0000664 0000000 0000000 00000001142 15211731751 0024137 0 ustar 00root root 0000000 0000000 # Working with the IQ-TREE submodule
We use a submodule to keep track of the version of IQ-TREE being used.
Every so often, there is an update to the submodule.
This most frequently happens when new features are being added from IQ-TREE, or
upon a new release.
When the submodule updates, to ensure the latest version of the IQ-TREE library is being used
the submodule must be updated locally and the library rebuilt. This can be done by running the
following two commands in the base directory of the `piqtree` repository:
```bash
git submodule update --init --recursive
./build_tools/build_iqtree.sh
```
iqtree-piqtree-b8a3d6a/docs/developers/release.md 0000664 0000000 0000000 00000001475 15211731751 0022220 0 ustar 00root root 0000000 0000000 # Release checklist
These instructions are for `piqtree` release managers.
The release is largely automated by the CI, but there are several things to confirm and do in this process.
The release process is automated through the "Release" GitHub Action.
The documentation is fetched by readthedocs from the "Build Docs" GitHub Action.
- The `piqtree` version has been correctly bumped.
- The testing, linting and type checking all pass on all supported platforms.
- The code has been thoroughly tested (check what's been missed in the coverage report).
- The documentation builds and appears correct.
- The latest version of the documentation has been updated on readthedocs (and appears correct).
- The "Release" GitHub Action has correctly uploaded to Test PyPI.
- The "Release" GitHub action has correctly uploaded to PyPI.
iqtree-piqtree-b8a3d6a/docs/developers/testing.md 0000664 0000000 0000000 00000001056 15211731751 0022250 0 ustar 00root root 0000000 0000000 # Testing, linting, and type checking
We use `pytest` for testing, `ruff` for linting and `mypy` for type checking. Pull requests require all three of these things to pass.
## Testing
To run the tests, run the following in the base directory of the `piqtree` repository:
```bash
pytest
```
## Linting
To run the linting, run the following in the base directory of the `piqtree` repository:
```bash
ruff check
```
## Type checking
To run type checking, run the following in the base directory of the `piqtree` repository:
```bash
mypy src tests
```
iqtree-piqtree-b8a3d6a/docs/developers/troubleshooting.md 0000664 0000000 0000000 00000002550 15211731751 0024022 0 ustar 00root root 0000000 0000000 # Troubleshooting
This is a guide for common problems that may occur when working on `piqtree` development. If you have an issue that isn't listed here,
please feel more than welcome to [raise an issue](https://github.com/iqtree/piqtree/issues) and we'll look into it.
## `piqtree` doesn't install
There could be several reasons `piqtree` doesn't install correctly.
### Check your operating system is supported
At this stage, we currently only support x86-64 linux, x86-64 Windows, and ARM macOS.
### Check the IQ-TREE library is up-to-date
Try running the following to build the latest version of the IQ-TREE library.
```bash
git submodule update --init --recursive
./build_tools/build_iqtree.sh
```
If the above doesn't work, please retry the guide on ["Setting up your environment for development"](./environment_setup.md).
## The IQ-TREE library doesn't build
There could be several reasons `piqtree` doesn't build.
### Check your operating system is supported
At this stage, we currently only support x86-64 linux, x86-64 Windows, and ARM macOS.
### Check dependencies have been installed
- If on Windows, try running `./before_all_windows.sh` which will also install dependencies.
- If on macOS, try running `./before_all_mac.sh` which will also install dependencies.
- If on linux, try installing the dependencies listed at the top of `.devcontainer/DockerFile`
iqtree-piqtree-b8a3d6a/docs/index.md 0000664 0000000 0000000 00000004715 15211731751 0017537 0 ustar 00root root 0000000 0000000 ## Overview
`piqtree` (pronounced 'pie-cue-tree') is a Python package that exposes selected [IQ-TREE](http://www.iqtree.org) capabilities within Python, using the [cogent3](https://cogent3.org) library as the interface.
`piqtree` is implemented with the goals of:
- making the individual high-performance components of IQ-TREE available within Python, enabling the community to take advantage of these routines.
- facilitating exploratory analyses by leveraging cogent3's capabilities to provide a rich user experience in interactive Jupyter notebooks, e.g. trivial parallelisation across collections of alignments.
- code using piqtree apps should be easy to understand.
In addition to the functions provided, `piqtree` provides mini-applications in the form of [cogent3 apps](https://cogent3.org/doc/app/index.html). These can interplay with other such apps, e.g. the [cogent3-ete3](https://pypi.org/project/cogent3-ete3/) tree conversion plugin, the [diverse-seqs](https://pypi.org/project/diverse-seq/) sequence subsampling plugin.
> **Note**
> `piqtree` does not implement all of the capabilities of IQ-TREE!
## Installation
You get the vanilla version of `piqtree` by running the following command.
```bash
pip install piqtree
```
To get Jupyter and visualisation support (with plotly) use the `[extra]` option.
```bash
pip install "piqtree[extra]"
```
## Sharing your cool solutions 😎
If you've done something you would like to share which either used `piqtree` or helped you to it (e.g. some data sampling steps with `cogent3`), please share your code on [our community contribution site](https://github.com/cogent3/c3codeshare). Contributing is as easy as clicking a button and pasting your code! Who knows, it may lead to collaborations 🙂.
If you want to see how others are using `piqtree`, take a look at the site. (At the time of writing, this is very new, so there's not many contributions.)
## Getting help
If you have a question about using `piqtree`, you can post a question [in the piqtree forums](https://github.com/iqtree/piqtree/discussions). Likewise, if you have any questions about using `cogent3`, post a question [in the cogent3 forums](https://github.com/cogent3/cogent3/discussions).
## Reporting problems
To report problems or potential bugs 🐛, please raise an issue on the [piqtree GitHub issues page](https://github.com/iqtree/piqtree/issues).
## Citing piqtree
Please cite our [preprint](https://www.biorxiv.org/content/10.1101/2025.07.13.664626v3).
iqtree-piqtree-b8a3d6a/docs/llms.txt 0000664 0000000 0000000 00000005301 15211731751 0017606 0 ustar 00root root 0000000 0000000 # piqtree
> piqtree (pronounced 'pie-cue-tree') is a Python library that exposes IQ-TREE phylogenetic inference capabilities within Python, using cogent3 as the interface.
## Overview
piqtree makes individual high-performance components of IQ-TREE available within Python, enabling phylogenetic analyses directly from Python code. It integrates with cogent3 for rich interactive experiences in Jupyter notebooks.
## Installation
```bash
pip install piqtree
pip install "piqtree[extra]" # With Jupyter and plotly support
```
## Documentation
- Main docs: https://piqtree.readthedocs.io/
- GitHub: https://github.com/iqtree/piqtree
- cogent3 docs: https://cogent3.org
## Core Functions
### Tree Construction
- `build_tree(alignment, model)` - Construct maximum-likelihood phylogenetic tree
- `fit_tree(alignment, tree, model)` - Fit branch lengths to existing tree topology
- `nj_tree(distances)` - Construct rapid neighbour-joining tree from distance matrix
- `consensus_tree(trees)` - Construct consensus tree from collection of trees
- `random_tree(names)` - Create randomly generated phylogenetic tree
### Alignment Simulation
- `simulate_alignment(tree, model, length)` - Simulate alignment with AliSim
### Model Selection
- `model_finder(alignment)` - Determine best-fit substitution model
- `make_model(model_string)` - Construct Model from IQ-TREE model string
- `Model` - Class for substitution models
- `SubstitutionModel` - Enum for available substitution models (JC, K2P, HKY, GTR, etc.)
- `FreqType` - Enum for base frequency options
- `RateModel` - Classes for rate heterogeneity (+G, +I, +R)
### Distance Calculations
- `jc_distances(alignment)` - Pairwise Jukes-Cantor genetic distances
- `robinson_foulds(tree1, tree2)` - Pairwise Robinson-Foulds tree distances
## Quick Example
```python
from piqtree import build_tree
from cogent3 import load_aligned_seqs
aln = load_aligned_seqs("seqs.fasta", moltype="dna")
tree = build_tree(aln, "JC", rand_seed=1)
print(tree) # cogent3 tree object
print(tree.params["lnL"]) # log-likelihood
```
## cogent3 Apps
piqtree provides cogent3-compatible apps for use in pipelines:
- `piqtree_phylo` - ML tree reconstruction
- `piqtree_fit` - Fit branch lengths
- `piqtree_nj` - Neighbour-joining trees
- `piqtree_model_finder` - Model selection
- `piqtree_pairwise_dist` - Pairwise distances
## Key Concepts
- All sequence data uses cogent3 `Alignment` objects
- All trees are cogent3 `PhyloNode` objects with branch lengths and likelihood info
- Substitution models follow IQ-TREE naming conventions
- Results include log-likelihood in `tree.params["lnL"]`
## Support
- Issues: https://github.com/iqtree/piqtree/issues
- Discussions: https://github.com/iqtree/piqtree/discussions
iqtree-piqtree-b8a3d6a/docs/quickstart/ 0000775 0000000 0000000 00000000000 15211731751 0020271 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/quickstart/available_frequency_options.py 0000664 0000000 0000000 00000000302 15211731751 0026412 0 ustar 00root root 0000000 0000000 # %% [markdown]
# ## State frequency types
# These specify how the frequencies of nucleotides or amino acids are obtained.
# %%
from piqtree import available_freq_type
available_freq_type()
iqtree-piqtree-b8a3d6a/docs/quickstart/available_rate_heterogeneity_options.py 0000664 0000000 0000000 00000000172 15211731751 0030304 0 ustar 00root root 0000000 0000000 # %% [markdown]
# ## Site-heterogeneity model types
# %%
from piqtree import available_rate_type
available_rate_type()
iqtree-piqtree-b8a3d6a/docs/quickstart/available_submodels.py 0000664 0000000 0000000 00000000364 15211731751 0024643 0 ustar 00root root 0000000 0000000 # %% [markdown]
# ## Substitution model types
# Assign the value in the "Abbreviation" column as a string to the `submod_type` parameter, e.g.
# ```python
# submod_type="GTR"
# ```
# %%
from piqtree import available_models
available_models()
iqtree-piqtree-b8a3d6a/docs/quickstart/calculate_jc_distances.md 0000664 0000000 0000000 00000002276 15211731751 0025270 0 ustar 00root root 0000000 0000000 # Calculate pairwise Jukes-Cantor distances
A pairwise Jukes-Cantor distance matrix can be constructed from a cogent3 alignment object using [`jc_distances`](../api/genetic_distance/jc_distances.md).
The resulting distance matrix can be indexed by integer index, or by name.
## Usage
### Basic Usage
Construct a `cogent3` alignment object, then calculate the pairwise JC distance matrix.
```python
from cogent3 import load_aligned_seqs
from piqtree import jc_distances
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
distance_matrix = jc_distances(aln)
distance_1 = distance_matrix[0, 1]
distance_2 = distance_matrix["Human", "Chimpanzee"]
```
### Multithreading
The number of threads to be used may be specified. By default, or if 0 is specified, all available threads are used.
```python
from cogent3 import load_aligned_seqs
from piqtree import jc_distances
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
# Use only 4 threads
distance_matrix = jc_distances(aln, num_threads=4)
```
## See also
- For using the JC distance matrix to construct a rapid neighbour-joining tree, see ["Construct a rapid neighbour-joining tree from a distance matrix"](construct_nj_tree.md).
iqtree-piqtree-b8a3d6a/docs/quickstart/calculate_rf_distances.md 0000664 0000000 0000000 00000001624 15211731751 0025277 0 ustar 00root root 0000000 0000000 # Calculate pairwise Robinson-Foulds distances between trees
A pairwise Robinson-Foulds distance matrix can be constructed from a sequence of cogent3 tree objects using [`robinson_foulds`](../api/tree_distance/robinson_foulds.md).
## Usage
### Basic Usage
Construct a collection of cogent3 tree objects, then use [`robinson_foulds`](../api/tree_distance/robinson_foulds.md) to find the pairwise distances.
```python
from cogent3 import make_tree
from piqtree import robinson_foulds
tree1 = make_tree("(a,b,(c,(d,e)));")
tree2 = make_tree("(e,b,(c,(d,a)));")
tree3 = make_tree("(a,b,(d,(c,e)));")
rf_distances = robinson_foulds([tree1, tree2, tree3])
```
## See also
- For constructing a maximum likelihood tree, see ["Construct a maximum likelihood phylogenetic tree"](construct_ml_tree.md).
- For making a random phylogenetic tree, see ["Make a randomly generated phylogenetic tree"](make_random_tree.md).
iqtree-piqtree-b8a3d6a/docs/quickstart/construct_consensus_tree.md 0000664 0000000 0000000 00000005671 15211731751 0025767 0 ustar 00root root 0000000 0000000 # Construct a consensus tree from a collection of trees
A consensus tree can be constructed from a collection of `cogent3` tree objects with
[`consensus_tree`](../api/tree/consensus_tree.md). The method defaults to the majority-rule consensus
tree - though different minimum levels of support can be used to achieve the strict consensus tree,
and extended majority-rule consensus tree. By default, the support values of the input trees are
carried over onto the consensus tree (see [Bootstrap values](#bootstrap-values) below).
## Usage
### Majority-rule consensus tree
From a collection of trees, the majority-rule consensus tree can be constructed.
```python
from cogent3 import make_tree
from piqtree import consensus_tree
tree1 = make_tree("(a,(b,(c,(d,e))));")
tree2 = make_tree("(a,((b,c),(d,e)));")
tree3 = make_tree("(a,((b,d),(c,e)));")
tree = consensus_tree([tree1, tree2, tree3]) # (a,(b,c,(d,e)));
```
### Strict consensus tree
The `min_support` parameter can be set to 1.0 to construct a strict consensus tree (only the clades that appear in all of the trees).
The parameter represents the proportion of trees a clade must appear in to be in the resulting tree.
```python
from cogent3 import make_tree
from piqtree import consensus_tree
tree1 = make_tree("(a,(b,(c,(d,e))));")
tree2 = make_tree("(a,((b,c),(d,e)));")
tree3 = make_tree("(a,((b,d),(c,e)));")
tree = consensus_tree([tree1, tree2, tree3], min_support=1.0) # (a,(b,c,d,e));
```
### Extended majority-rule consensus tree
When the `min_support` parameter is equal to 0, the extended majority-rule consensus tree is computed.
```python
from cogent3 import make_tree
from piqtree import consensus_tree
tree1 = make_tree("(a,(b,(c,(d,e))));")
tree2 = make_tree("(a,((b,c),(d,e)));")
tree3 = make_tree("(a,((b,c),(d,e)));")
tree4 = make_tree("(a,(c,(b,(d,e))));")
tree5 = make_tree("(c,(b,(a,(d,e))));")
tree = consensus_tree([tree1, tree2, tree3, tree4, tree5], min_support=0) # (a,((b,c),(d,e)));
```
### Bootstrap values
When the input trees carry their own branch support - for example, the ultrafast bootstrap support
produced by [`build_tree`](construct_ml_tree.md) - `consensus_tree` carries these values over onto
the matching clades of the consensus tree, averaged across the input trees that contain each clade.
The way the values are combined is set by `support_aggregate` (`"mean"` by default, or `"max"` /
`"min"`), and each node's value can be accessed from `#!py3 node.support`.
```python
from cogent3 import make_tree
from piqtree import consensus_tree
# the numbers on the internal nodes are each tree's own bootstrap support
tree1 = make_tree("(a,((b,c)96,(d,e)90));")
tree2 = make_tree("(a,((b,c)88,(d,e)70));")
tree = consensus_tree([tree1, tree2]) # support_aggregate="mean" by default
# (b,c) -> mean(96, 88) -> 92.0
# (d,e) -> mean(90, 70) -> 80.0
```
## See also
- For making a random phylogenetic tree, see ["Make a randomly generated phylogenetic tree"](make_random_tree.md).
iqtree-piqtree-b8a3d6a/docs/quickstart/construct_ml_tree.md 0000664 0000000 0000000 00000005257 15211731751 0024357 0 ustar 00root root 0000000 0000000 # Construct a maximum likelihood phylogenetic tree
A maximum-likelihood phylogenetic tree can be constructed from
cogent3 alignment objects using [`build_tree`](../api/tree/build_tree.md).
## Usage
### Basic Usage
Construct a `cogent3` alignment object, then construct a maximum-likelihood tree.
```python
from cogent3 import load_aligned_seqs
from piqtree import build_tree
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
tree = build_tree(aln, "GTR")
log_likelihood = tree.params["lnL"]
```
### Ultrafast Bootstrap
To perform ultrafast bootstrapping, the number of replicates can be specified. The number of replicates must be at least 1000.
The support for each node in the tree object can be accessed from `#!py3 node.support`.
```python
from cogent3 import load_aligned_seqs
from piqtree import build_tree
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
tree = build_tree(aln, "K81+FO", bootstrap_replicates=2000)
```
### Reproducible Results
For reproducible results, a random seed may be specified.
> **Caution:** 0 is a specific random seed. None is equivalent to no random seed being specified.
```python
from cogent3 import load_aligned_seqs
from piqtree import build_tree
aln = load_aligned_seqs("my_protein.fasta", moltype="protein")
tree = build_tree(aln, "Dayhoff", rand_seed=3)
```
### Multithreading
To speed up computation, the number of threads to be used may be specified.
By default, the computation is done on a single thread. If 0 is specified,
then IQ-TREE attempts to determine the optimal number of threads.
> **Caution:** If 0 is specified with small datasets, the time to determine the
> optimal number of threads may exceed the time to find the maximum likelihood
> tree.
```python
from cogent3 import load_aligned_seqs
from piqtree import build_tree
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
model = "HKY+I+G6"
tree = build_tree(aln, model, num_threads=4)
```
### Additional options
Additional options in the format that would be passed to the IQ-TREE CLI can be set.
Options in `other_options` already allowed through `build_tree` will be ignored.
```python
from cogent3 import load_aligned_seqs
from piqtree import build_tree
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
tree = build_tree(aln, "GTR", other_options="--epsilon 0.1 -n 0")
```
## See also
- For how to specify a `Model`, see ["Use different kinds of substitution models"](using_substitution_models.md).
- For selecting the best `Model`, see ["Find the model of best fit with ModelFinder"](using_model_finder.md).
- For fitting branch lengths to a tree topology, see ["Fit branch lengths to a tree topology from an alignment"](fit_tree_topology.md).
iqtree-piqtree-b8a3d6a/docs/quickstart/construct_nj_tree.md 0000664 0000000 0000000 00000002357 15211731751 0024354 0 ustar 00root root 0000000 0000000 # Construct a rapid neighbour-joining tree from a distance matrix
A rapid neighbour-joining tree can be constructed from a pairwise `DistanceMatrix` object with [`nj_tree`](../api/tree/nj_tree.md).
## Usage
### Basic Usage
Make a pairwise distance matrix, then construct the rapid neighbour-joining tree.
```python
from cogent3 import load_aligned_seqs
from piqtree import jc_distances, nj_tree
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
distance_matrix = jc_distances(aln)
tree = nj_tree(distance_matrix)
```
### Other Distance Matrices
`cogent3` supports the calculation of **paralinear**, **JC69**, **TN93**, **hamming** and **pdist** distance matrices from alignment objects.
```python
from cogent3 import load_aligned_seqs
from piqtree import nj_tree
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
distance_matrix = aln.distance_matrix(calc="TN93") # calc is not case sensitive
tree = nj_tree(distance_matrix)
```
## See also
- For constructing the JC distance matrix with `piqtree`, see ["Construct a rapid neighbour-joining tree from a distance matrix"](calculate_jc_distances.md).
- For constructing a maximum likelihood tree, see ["Construct a maximum likelihood phylogenetic tree"](construct_ml_tree.md).
iqtree-piqtree-b8a3d6a/docs/quickstart/fit_tree_topology.md 0000664 0000000 0000000 00000005204 15211731751 0024351 0 ustar 00root root 0000000 0000000 # Fit branch lengths to a tree topology from an alignment
Branch lengths can be fitted to a tree from a cogent3 alignment object
using [`fit_tree`](../api/tree/fit_tree.md).
## Usage
### Basic Usage
Construct `cogent3` alignment and tree objects, then fit branch lengths to a new tree.
```python
from cogent3 import load_aligned_seqs, make_tree
from piqtree import fit_tree
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
tree = make_tree("((Human, Chimpanzee), Rhesus, Mouse);")
fitted_tree = fit_tree(aln, tree, model="F81")
log_likelihood = fitted_tree.params["lnL"]
```
### Multithreading
To speed up computation, the number of threads to be used may be specified.
By default, the computation is done on a single thread. If 0 is specified,
then IQ-TREE attempts to determine the optimal number of threads.
> **Caution:** If 0 is specified with small datasets, the time to determine the
> optimal number of threads may exceed the time to find the maximum likelihood
> tree.
```python
from cogent3 import load_aligned_seqs, make_tree
from piqtree import fit_tree
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
tree = make_tree("((Human, Chimpanzee), Rhesus, Mouse);")
model = "HKY+I+R3"
fitted_tree = fit_tree(aln, tree, model, num_threads=4)
```
### Fixed branch lengths
The likelihood for a tree with specified branch lengths may be calculated
by using the `bl_fixed` argument. When set to True, specified branch lengths
are not optimised and the likelihood for the tree is calculated. Any unspecified
branch lengths will still be optimised.
```python
from cogent3 import load_aligned_seqs, make_tree
from piqtree import fit_tree
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
tree = make_tree("((Human:0.1, Chimpanzee:0.15):0.2, Rhesus:0.3, Mouse:0.5);")
tree_with_likelihood = fit_tree(aln, tree, model="GTR", bl_fixed=True)
log_likelihood = tree_with_likelihood.params["lnL"]
```
### Additional options
Additional options in the format that would be passed to the IQ-TREE CLI can be set.
Options in `other_options` already allowed through `fit_tree` will be ignored.
```python
from cogent3 import load_aligned_seqs, make_tree
from piqtree import fit_tree
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
tree = make_tree("((Human, Chimpanzee), Rhesus, Mouse);")
fitted_tree = fit_tree(aln, tree, model="GTR", other_options="-blmin 0.001 -blmax 1.5")
```
## See also
- For how to specify a `Model`, see ["Use different kinds of substitution models"](using_substitution_models.md).
- For constructing a maximum likelihood tree, see ["Construct a maximum likelihood phylogenetic tree"](construct_ml_tree.md).
iqtree-piqtree-b8a3d6a/docs/quickstart/index.md 0000664 0000000 0000000 00000002317 15211731751 0021725 0 ustar 00root root 0000000 0000000 # Quickstart
Want to jump right in to using `piqtree`? This is the place to be! Here, you can find examples to:
- [Construct a maximum likelihood phylogenetic tree.](construct_ml_tree.md)
- [Fit branch lengths to a tree topology from an alignment.](fit_tree_topology.md)
- [Simulate alignments with AliSim.](simulate_alignment.md)
- [Use different kinds of substitution models.](using_substitution_models.md)
- [Find the model of best fit with ModelFinder.](using_model_finder.md)
- [Calculate pairwise Jukes-Cantor distances.](calculate_jc_distances.md)
- [Construct a rapid neighbour-joining tree from a distance matrix.](construct_nj_tree.md)
- [Construct a consensus tree from a collection of trees.](construct_consensus_tree.md)
- [Make a randomly generated phylogenetic tree.](make_random_tree.md)
- [Calculate pairwise Robinson-Foulds distances between trees.](calculate_rf_distances.md)
- [Display substitution models.](available_submodels.py)
- [Display frequency options.](available_frequency_options.py)
- [Display rate-heterogeneity options.](available_rate_heterogeneity_options.py)
- [Using the `piqtree` `cogent3` apps.](../apps/index.md)
Be sure to check out the [API Reference](../api/index.md) for full usage!
iqtree-piqtree-b8a3d6a/docs/quickstart/make_random_tree.md 0000664 0000000 0000000 00000002662 15211731751 0024115 0 ustar 00root root 0000000 0000000 # Make a randomly generated phylogenetic tree
A randomly generated phylogenetic tree can be made using [`random_tree`](../api/tree/random_tree.md#piqtree.random_tree).
Multiple tree generation modes are supported with the [`TreeGenMode`](../api/tree/random_tree.md#piqtree.TreeGenMode) including
balanced, birth-death, caterpillar, star, uniform, and Yule-Harding tree.
## Usage
### Basic Usage
Specify the number of taxa, and under what method the tree is to be generated.
See the documentation for [`TreeGenMode`](../api/tree/random_tree.md#piqtree.TreeGenMode) for all available generation options.
> **Note:** if star trees are generated the tree appears bifurcating, but branch lengths are set to zero where appropriate.
```python
from piqtree import TreeGenMode, random_tree
num_taxa = 100
tree = random_tree(num_taxa, TreeGenMode.YULE_HARDING)
```
### Reproducible Results
For reproducible results, a random seed may be specified.
> **Caution:** 0 is a specific random seed. None is equivalent to no random seed being specified.
```python
from piqtree import TreeGenMode, random_tree
num_taxa = 100
tree = random_tree(num_taxa, TreeGenMode.CATERPILLAR, rand_seed=1)
```
## See also
- For constructing a maximum likelihood tree, see ["Construct a maximum likelihood phylogenetic tree"](construct_ml_tree.md).
- For constructing a consensus tree, see ["Construct a consensus tree from a collection of trees"](construct_consensus_tree.md). iqtree-piqtree-b8a3d6a/docs/quickstart/simulate_alignment.md 0000664 0000000 0000000 00000003024 15211731751 0024473 0 ustar 00root root 0000000 0000000 # Simulate alignments with AliSim
An alignment can be simulated over a cogent3 tree object using [`simulate_alignment`](../api/alignment/simulate_alignment.md).
## Usage
### Basic Usage
Construct a `cogent3` tree object, then simulate an alignment over it.
```python
from cogent3 import make_tree
from piqtree import simulate_alignment
tree = make_tree("(A:0.3544,(B:0.1905,C:0.1328):0.0998,D:0.0898);")
aln = simulate_alignment(tree, "JC")
```
### Reproducible Results
For reproducible results, a random seed may be specified.
> **Caution:** 0 is a specific random seed. None is equivalent to no random seed being specified.
```python
from cogent3 import make_tree
from piqtree import simulate_alignment
tree = make_tree("(A:0.3544,(B:0.1905,C:0.1328):0.0998,D:0.0898);")
aln = simulate_alignment(tree, "Dayhoff", rand_seed=42)
```
### Multithreading
To speed up computation, the number of threads to be used may be specified.
By default, the computation is done on a single thread. If 0 is specified,
then IQ-TREE automatically determines the optimal number of threads.
```python
from cogent3 import make_tree
from piqtree import simulate_alignment
tree = make_tree("(A:0.3544,(B:0.1905,C:0.1328):0.0998,D:0.0898);")
aln = simulate_alignment(tree, "JC", length=10000, num_threads=0)
```
## See also
- For how to specify a `Model`, see ["Use different kinds of substitution models"](using_substitution_models.md).
- For constructing a maximum likelihood tree, see ["Construct a maximum likelihood phylogenetic tree"](construct_ml_tree.md). iqtree-piqtree-b8a3d6a/docs/quickstart/using_model_finder.md 0000664 0000000 0000000 00000006307 15211731751 0024455 0 ustar 00root root 0000000 0000000 # Find the model of best fit with ModelFinder
IQ-TREE's ModelFinder can be used to automatically find the model of best fit for an alignment using [`model_finder`](../api/model/model_finder.md).
The best scoring model under either **the *Akaike information criterion* (AIC), *corrected Akaike information criterion* (AICc), or the *Bayesian information criterion* (BIC) can be selected.
## Usage
### Basic Usage
Construct a `cogent3` alignment object, then construct a maximum-likelihood tree.
```python
from cogent3 import load_aligned_seqs
from piqtree import model_finder
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
result = model_finder(aln)
best_aic_model = result.best_aic
best_aicc_model = result.best_aicc
best_bic_model = result.best_bic
```
### Specifying the Search Space
We expose the `mset`, `mfreq` and `mrate` parameters from IQ-TREE's ModelFinder to specify the substitution model search space, base frequency search space, and rate heterogeneity search space respectively. They can be specified as a set of strings in either `model_set`, `freq_set` or `rate_set` respectively.
```python
from cogent3 import load_aligned_seqs
from piqtree import model_finder
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
result = model_finder(aln, model_set={"HKY", "TIM"})
best_aic_model = result.best_aic
best_aicc_model = result.best_aicc
best_bic_model = result.best_bic
```
### Reproducible Results
For reproducible results, a random seed may be specified.
> **Caution:** 0 is a specific random seed. None is equivalent to no random seed being specified.
```python
from cogent3 import load_aligned_seqs
from piqtree import model_finder
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
result = model_finder(aln, rand_seed=5)
best_aic_model = result.best_aic
best_aicc_model = result.best_aicc
best_bic_model = result.best_bic
```
### Multithreading
To speed up computation, the number of threads to be used may be specified.
By default, the computation is done on a single thread. If 0 is specified,
then IQ-TREE attempts to determine the optimal number of threads.
> **Caution:** If 0 is specified with small datasets, the time to determine the
> optimal number of threads may exceed the time to find the maximum likelihood
> tree.
```python
from cogent3 import load_aligned_seqs
from piqtree import model_finder
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
result = model_finder(aln, num_threads=4)
best_aic_model = result.best_aic
best_aicc_model = result.best_aicc
best_bic_model = result.best_bic
```
### Additional options
Additional options in the format that would be passed to the IQ-TREE CLI can be set.
Options in `other_options` already allowed through `model_finder` will be ignored.
```python
from cogent3 import load_aligned_seqs
from piqtree import model_finder
aln = load_aligned_seqs("my_alignment.fasta", moltype="dna")
result = model_finder(aln, model_set={"HKY", "TIM"}, other_options="-mtree")
```
## See also
- For constructing a maximum likelihood tree, see ["Construct a maximum likelihood phylogenetic tree"](construct_ml_tree.md).
- For how to specify a `Model`, see ["Use different kinds of substitution models"](using_substitution_models.md).
iqtree-piqtree-b8a3d6a/docs/quickstart/using_substitution_models.md 0000664 0000000 0000000 00000016367 15211731751 0026154 0 ustar 00root root 0000000 0000000 # Use different kinds of substitution models
piqtree currently supports all named IQ-TREE DNA models including Lie Markov models, empirical amino-acid exchange rate matrices,
as well as specification for base frequencies and rate heterogeneity across sites.
We use the [`Model`](../api/model/Model.md) class to represent the substitution model which can be constructed from strings, or
using enums. Most functions can already compute this directly from the passed model string, so usage of [`make_model`](../api/model/make_model.md) may be preferable. Substitution models can be combined with specification for base frequencies, and rate heterogeneity across sites models.
## Usage
### Standard DNA Models
DNA models may be specified using the [`StandardDnaModel`](../api/model/SubstitutionModel.md#piqtree.model.StandardDnaModel) enum, or by using
the IQ-TREE string representation. A full list of supported DNA models is available [here](../api/model/SubstitutionModel.md#piqtree.model.StandardDnaModel).
```python
from piqtree import Model
from piqtree.model import StandardDnaModel
hky_model_1 = Model("HKY")
hky_model_2 = Model(StandardDnaModel.HKY)
```
#### Parameterisation of Standard DNA Models
IQ-TREE allows DNA models to be parameterised by specifying relative substitution rates. See the [IQ-TREE documentation](https://iqtree.github.io/doc/Substitution-Models) for the precise definition of the parameters for the chosen model.
```python
from piqtree import Model
from piqtree.model import StandardDnaModel
model = Model("GTR{1.0,2.0,1.5,3.7,2.8}")
model = Model(StandardDnaModel.GTR([1.0, 2.0, 1.5, 3.7, 2.8]))
```
### Lie Markov Models
Lie Markov models may be specified using the [`LieModel`](../api/model/SubstitutionModel.md#piqtree.model.LieModel) enum, or by using
the IQ-TREE string representation. A full list of supported DNA models is available [here](../api/model/SubstitutionModel.md#piqtree.model.LieModel). The pairing prefix may also be specified - RY for purine-pyrimidine pairing (default); WS for weak-strong pairing; and MK aMino-Keto pairing.
```python
from piqtree import Model
from piqtree.model import LieModel
lie_ws_6_6_model_1 = Model("WS6.6")
lie_ws_6_6_model_2 = Model(LieModel.LIE_6_6("WS"))
lie_12_12_model_1 = Model("12.12")
lie_12_12_model_2 = Model(LieModel.LIE_12_12)
```
#### Parameterisation of Lie Markov Models
IQ-TREE supports the parameterisation of Lie Markov models. The first number (before the period) corresponds to the number of basis matrices used by the model. The first basis matrix is unparameterised, and the parameters refer to the weights (bounded between -0.98 and 0.98 exclusive) of the remaining basis matrices of the model.
```python
from piqtree import Model
from piqtree.model import LieModel
model = Model("MK3.3b{0.3,-0.5}")
model = Model(LieModel.LIE_3_3b("MK", [0.3, -0.5]))
```
### Amino-acid Models
Amino-acid models may be specified using the [`AaModel`](../api/model/SubstitutionModel.md#piqtree.model.AaModel) enum, or by using
the IQ-TREE string representation. A full list of supported amino-acid models is available [here](../api/model/SubstitutionModel.md#piqtree.model.AaModel).
```python
from piqtree import Model
from piqtree.model import AaModel
dayhoff_model_1 = Model("Dayhoff")
dayhoff_model_2 = Model(AaModel.Dayhoff)
nq_yeast_model_1 = Model("NQ.yeast")
nq_yeast_model_2 = Model(AaModel.NQ_yeast)
```
### Base Frequencies
Three types of base frequencies can be specified using the [`FreqType`](../api/model/FreqType.md) enum, or alternatively the [`CustomBaseFreq`](../api/model/FreqType.md) class can be used to fix base frequencies. Otherwise, the IQ-TREE string representation can be used.
If base frequencies are not specified, the chosen model's default settings are used.
- [`F`](../api/model/FreqType.md#piqtree.model.FreqType.F): Empirical base frequencies. String representation also used to fix base frequencies.
- [`FQ`](../api/model/FreqType.md#piqtree.model.FreqType.FQ): Equal base frequencies.
- [`FO`](../api/model/FreqType.md#piqtree.model.FreqType.FO): Optimised base frequencies by maximum-likelihood.
```python
from piqtree import Model
from piqtree.model import CustomBaseFreq, FreqType
# Default for the GTR model
empirical_freqs_1 = Model("GTR", freq_type="F")
empirical_freqs_2 = Model("GTR", freq_type=FreqType.F)
equal_freqs_1 = Model("GTR", freq_type="FQ")
equal_freqs_2 = Model("GTR", freq_type=FreqType.FQ)
opt_freqs_1 = Model("GTR", freq_type="FO")
opt_freqs_2 = Model("GTR", freq_type=FreqType.FO)
custom_freqs_1 = Model("GTR", freq_type="F{0.1,0.2,0.3,0.4}")
custom_freqs_2 = Model("GTR", freq_type=CustomBaseFreq([0.1, 0.2, 0.3, 0.4]))
```
### Rate Heterogeneity
#### Invariable Sites
A boolean flag can be specified when constructing the [`Model`](../api/model/Model.md) class to allow for a proportion of invariable sites. To fix the proportion of invariable sites, a float representing the proportion can be used instead.
```python
from piqtree import Model
without_invar_sites = Model("TIM", invariable_sites=False) # Default
with_invar_sites = Model("TIM", invariable_sites=True)
prop_invar = Model("TIM", invariable_sites=0.1)
```
#### Discrete Gamma Model
We support the [`DiscreteGammaModel`](../api/model/RateModel.md#piqtree.model.DiscreteGammaModel) allowing for a variable number of rate categories (by default 4). The Gamma shape parameter (alpha) can also be set.
```python
from piqtree import Model
from piqtree.model import DiscreteGammaModel
# 4 rate categories, no invariable sites
k81_discrete_gamma_4 = Model("K81", rate_model=DiscreteGammaModel())
# 8 rate categories, with invariable sites
k81_invar_discrete_gamma_8 = Model("K81", rate_model=DiscreteGammaModel(8), invariable_sites=True)
# 4 rate categories, alpha=0.2
k81_alpha = Model("K81", rate_model=DiscreteGammaModel(alpha=0.2))
```
#### FreeRate Model
We support the [`FreeRateModel`](../api/model/RateModel.md#piqtree.model.FreeRateModel) allowing for a variable number of rate categories (by default 4). The FreeRate weights for each of the rate categories and the corresponding rates may also be fixed.
```python
from piqtree import Model
from piqtree.model import FreeRateModel
# 4 rate categories, no invariable sites
sym_free_rate_4 = Model("SYM", rate_model=FreeRateModel())
# 8 rate categories, with invariable sites
sym_invar_free_rate_8 = Model("SYM", rate_model=FreeRateModel(8), invariable_sites=True)
# 2 rate categories with specified weights and rates
sym_free_rate_parameterised = Model("SYM", rate_model=FreeRateModel(2, weights=[0.2, 0.8], rates=[2.5, 0.625]))
```
### Making Model Classes from IQ-TREE Strings
For the supported model types, the Model class can be created by using [`make_model`](../api/model/make_model.md) on the IQ-TREE string representation of the model.
```python
from piqtree import make_model
model = make_model("GTR+FQ+I+R3")
```
## See also
- Use a [`Model`](../api/model/Model.md) to construct a maximum likelihood tree: ["Construct a maximum likelihood phylogenetic tree"](construct_ml_tree.md).
- Use a [`Model`](../api/model/Model.md) to fit branch lengths to a tree topology: ["Fit branch lengths to a tree topology from an alignment"](fit_tree_topology.md).
- Use a [`Model`](../api/model/Model.md) to simulate an alignment with AliSim: ["Simulate alignments with AliSim"](simulate_alignment.md).
iqtree-piqtree-b8a3d6a/docs/scripts/ 0000775 0000000 0000000 00000000000 15211731751 0017566 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/docs/scripts/prepare_doc_test_data.py 0000664 0000000 0000000 00000001365 15211731751 0024460 0 ustar 00root root 0000000 0000000 from pathlib import Path
from cogent3 import load_aligned_seqs
PROJECT_ROOT = Path(__file__)
while PROJECT_ROOT.name != "docs":
PROJECT_ROOT = PROJECT_ROOT.parent
PROJECT_ROOT = PROJECT_ROOT.parent
def prepare_my_alignment() -> None:
aln = load_aligned_seqs(PROJECT_ROOT / "tests/data/example.fasta", moltype="dna")
aln = aln.take_seqs(["Human", "Chimpanzee", "Rhesus", "Mouse"])
aln.write("my_alignment.fasta")
def prepare_protein_alignment() -> None:
aln = load_aligned_seqs(
PROJECT_ROOT / "tests/data/protein.fasta",
moltype="protein",
)
aln = aln.take_seqs(sorted(aln.names)[:4])
aln.write("my_protein.fasta")
if __name__ == "__main__":
prepare_my_alignment()
prepare_protein_alignment()
iqtree-piqtree-b8a3d6a/iqtree3/ 0000775 0000000 0000000 00000000000 15211731751 0016523 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/mkdocs.yml 0000664 0000000 0000000 00000006174 15211731751 0017162 0 ustar 00root root 0000000 0000000 site_name: piqtree
site_url: "https://github.com/iqtree/piqtree"
site_author: "Gavin Huttley"
repo_url: "https://github.com/iqtree/piqtree"
repo_name: 'GitHub'
exclude_docs: |
scripts/*
theme:
name: material
features:
- navigation.indexes
highlightjs: true
hljs_languages:
- yaml
- python
- text
markdown_extensions:
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.superfences
plugins:
- search
- mkdocstrings:
handlers:
python:
paths: [src]
options:
show_root_heading: true
docstring_style: numpy
docstring_section_style: spacy
docstring_options:
ignore_init_summary: true
merge_init_into_class: true
- mkdocs-jupyter:
allow_errors: false
include_requirejs: true
execute: true
remove_tag_config:
remove_input_tags:
- hide_code
nav:
- Introduction: index.md
- Quickstart:
- quickstart/index.md
- quickstart/construct_ml_tree.md
- quickstart/fit_tree_topology.md
- quickstart/simulate_alignment.md
- quickstart/using_substitution_models.md
- quickstart/using_model_finder.md
- quickstart/calculate_jc_distances.md
- quickstart/construct_nj_tree.md
- quickstart/construct_consensus_tree.md
- quickstart/make_random_tree.md
- quickstart/calculate_rf_distances.md
- Available substitution models: quickstart/available_submodels.py
- Available state frequency options: quickstart/available_frequency_options.py
- Available rate-heterogeneity options: quickstart/available_rate_heterogeneity_options.py
- Apps:
- apps/index.md
- The available piqtree apps: apps/available_help.py
- Selecting models for phylogenetic analysis: apps/model_finder.py
- Estimate a phylogenetic tree: apps/phylo.py
- Fit a model to one tree: apps/fit_tree.py
- Pairwise JC distances: apps/pairwise_dist.py
- NJ tree: apps/nj.py
- Parallel processing across alignments: apps/app_pipeline.py
- API reference:
- api/index.md
- Trees:
- api/tree/build_tree.md
- api/tree/fit_tree.md
- api/tree/nj_tree.md
- api/tree/consensus_tree.md
- api/tree/random_tree.md
- Alignments:
- api/alignment/simulate_alignment.md
- Substitution models:
- api/model/model_finder.md
- api/model/ModelFinderResult.md
- api/model/Model.md
- api/model/make_model.md
- api/model/SubstitutionModel.md
- api/model/FreqType.md
- api/model/RateModel.md
- Genetic distances:
- api/genetic_distance/jc_distances.md
- Tree distances:
- api/tree_distance/robinson_foulds.md
- Contributing:
- developers/index.md
- developers/environment_setup.md
- developers/iqtree_submodule.md
- developers/contributing.md
- developers/testing.md
- developers/troubleshooting.md
- developers/release.md
- Citation: citation.md
iqtree-piqtree-b8a3d6a/noxfile.py 0000664 0000000 0000000 00000003414 15211731751 0017167 0 ustar 00root root 0000000 0000000 import os
import tempfile
from pathlib import Path
import nox
_py_versions = range(12, 15)
_python_sessions = [f"3.{v}" for v in _py_versions]
@nox.session(python=_python_sessions)
def test(session: nox.Session) -> None:
posargs = list(session.posargs)
env = os.environ.copy()
install_spec = "-e.[test]"
session.install(install_spec)
session.run("pytest", *posargs, env=env)
@nox.session(python=_python_sessions)
def type_check(session: nox.Session) -> None:
posargs = list(session.posargs)
env = os.environ.copy()
install_spec = ".[typing]"
session.install(install_spec)
session.run("mypy", "src", "tests", *posargs, env=env)
@nox.session(python=_python_sessions)
def ruff(session: nox.Session) -> None:
posargs = list(session.posargs)
env = os.environ.copy()
install_spec = ".[lint]"
session.install(install_spec)
session.run("ruff", "check", *posargs, env=env)
@nox.session(python=_python_sessions)
def test_docs(session: nox.Session) -> None:
doc_md_files = [path.resolve() for path in Path("docs").rglob("*.md")]
doc_py_files = [path.resolve() for path in Path("docs").rglob("*.py")]
doctest_setup_path = Path("docs/scripts/prepare_doc_test_data.py").resolve()
posargs: list[str | Path] = list(session.posargs)
posargs.extend(["--markdown-docs", *doc_md_files])
env = os.environ.copy()
install_spec = ".[test]"
session.install(install_spec)
with tempfile.TemporaryDirectory() as tmpdir:
session.chdir(tmpdir)
session.run("python", doctest_setup_path, env=env)
session.run("pytest", *posargs, env=env)
session.install("cogent3[extra]", "diverse-seq")
for py_file in doc_py_files:
session.run("python", py_file, env=env, silent=True)
iqtree-piqtree-b8a3d6a/pyproject.toml 0000664 0000000 0000000 00000014170 15211731751 0020066 0 ustar 00root root 0000000 0000000 [build-system]
requires = ["setuptools>=61.0", "pybind11==3.0.4", "delvewheel==1.13.0"]
build-backend = "setuptools.build_meta"
[project]
name = "piqtree"
dependencies = [
"citeable>=2026.3.11b0",
"cogent3>=2026.4.20a0",
"pyyaml",
"requests",
]
requires-python = ">=3.12"
authors = [
{ name = "Gavin Huttley" },
{ name = "Robert McArthur" },
{ name = "Bui Quang Minh " },
{ name = "Richard Morris" },
{ name = "Thomas Wong" },
]
description = "Python bindings for IQTree"
readme = "README.md"
dynamic = ["version"]
license = "GPL-2.0-only"
license-files = ["LICENSE"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering :: Bio-Informatics",
"Topic :: Software Development :: Libraries :: Python Modules",
"Natural Language :: English",
"Operating System :: Microsoft :: Windows",
"Operating System :: MacOS",
"Operating System :: POSIX :: Linux",
"Programming Language :: C++",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Typing :: Typed",
]
[project.urls]
Repository = "https://github.com/cogent3/piqtree"
Documentation = "https://piqtree.readthedocs.io"
[project.optional-dependencies]
dev = [
"cibuildwheel==4.0.0",
"pybind11==3.0.4",
"delvewheel==1.13.0",
"scriv",
"piqtree[test]",
"piqtree[lint]",
"piqtree[typing]",
]
test = ["pytest", "pytest-cov", "pytest-markdown-docs", "pytest-mock", "nox"]
lint = ["ruff==0.15.16"]
typing = ["mypy==2.1.0", "piqtree[stubs]", "piqtree[test]"]
stubs = ["types-PyYAML", "types-requests"]
extra = ["cogent3[extra]"]
doc = [
"mkdocs",
"mkdocstrings[python]",
"mkdocs-jupyter",
"pymdown-extensions",
"jupytext",
"piqtree[test]",
"cogent3[extra]",
"diverse-seq>=2025.7.10",
"jupyter",
"ipywidgets",
]
[project.entry-points."cogent3.app"]
piq_build_tree = "piqtree._app:piq_build_tree"
piq_fit_tree = "piqtree._app:piq_fit_tree"
piq_random_tree = "piqtree._app:piq_random_tree"
piq_jc_distances = "piqtree._app:piq_jc_distances"
piq_nj_tree = "piqtree._app:piq_nj_tree"
piq_model_finder = "piqtree._app:piq_model_finder"
piq_consensus_tree = "piqtree._app:piq_consensus_tree"
piq_simulate_alignment = "piqtree._app:piq_simulate_alignment"
[project.entry-points."cogent3.hook"]
quick_tree = "piqtree._app:piq_nj_tree"
[tool.setuptools.dynamic]
version = { attr = "piqtree.__version__" }
[tool.ruff]
exclude = [
"iqtree3",
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
]
# Same as Black.
line-length = 88
indent-width = 4
target-version = "py312"
[tool.ruff.lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
# McCabe complexity (`C901`) by default.
select = ["ALL"]
ignore = [
"EXE002", # don't require shebang
"E501", # allow long lines where appropriate
"PLC0415", # allow imports inside functions
"PLR0913", # allow many arguments
"PLR2004", # allow magic value comparisons
"D", # doc linting rules
]
# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []
# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = [
"S101", # asserts allowed in tests...
"INP001", # __init__.py files are not required...
"N802", # allow non snake_case function names for fixtures
"N803", # allow use of fixture constants
"SLF001", # private member access is useful for testing
"FBT001", # allow bool pos args for parameterisation
"D", # don't require docstring linting
]
"docs/**/*.py" = ["B018", "E402", "ERA001", "INP001", "D"]
"src/piqtree/_app/__init__.py" = [
"N801", # apps follow function naming convention
]
"src/piqtree/__init__.py" = [
"E402", # handle DLLs before imports
"PTH118", # os operations for DLL path
"PTH120", # os operations for DLL path
]
"src/piqtree/model/_substitution_model.py" = [
"N815", # use IQ-TREE naming scheme
]
"setup.py" = [
"S603", # allow subprocess invalidated input for brew install
"S607", # allow subprocess with partial path
"D", # Don't expect docstrings for setup.py
]
"noxfile.py" = [
"D", # Don't expect docstrings for noxfile
]
"rtd_get_docs.py" = [
"D", # Don't expect docstrings for rtd file.
]
[tool.ruff.format]
# Like Black, use double quotes for strings.
quote-style = "double"
# Like Black, indent with spaces, rather than tabs.
indent-style = "space"
# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false
# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"
# Enable auto-formatting of code examples in docstrings. Markdown,
# reStructuredText code/literal blocks and doctests are all supported.
#
# This is currently disabled by default, but it is planned for this
# to be opt-out in the future.
docstring-code-format = false
# Set the line length limit used when formatting code snippets in
# docstrings.
#
# This only has an effect when the `docstring-code-format` setting is
# enabled.
docstring-code-line-length = "dynamic"
[tool.scriv]
format = "md"
categories = [
"Contributors",
"ENH",
"BUG",
"API",
"DOC",
"Deprecations",
"Discontinued",
]
output_file = "changelog.md"
version = "literal: src/piqtree/__init__.py: __version__"
skip_fragments = "README.*"
new_fragment_template = "file: changelog.d/templates/new.md.j2"
entry_title_template = "file: changelog.d/templates/title.md.j2"
[[tool.mypy.overrides]]
module = ['cogent3.*', "_piqtree"]
ignore_missing_imports = true
iqtree-piqtree-b8a3d6a/rtd_get_docs.py 0000664 0000000 0000000 00000006470 15211731751 0020170 0 ustar 00root root 0000000 0000000 # this file
# is directly used by .readthedocs.yaml
# it extracts the built docs from the github artefact
# created by the build_docs.yml github action
import os
import pathlib
import time
import zipfile
import requests
MAX_WAIT_TIME = 600 # Typically takes 5.5 minutes
POLL_INTERVAL = 20
def get_rtd_version_name() -> str:
return os.environ.get("READTHEDOCS_VERSION_NAME", "").lower()
def get_github_token() -> str:
token = os.environ.get("GITHUB_TOKEN")
if token is None:
token = os.environ.get("GITHUB_TOKEN_PRIVATE")
if not token:
msg = "GitHub token not found."
raise OSError(msg)
return token
def get_latest_run(workflow_filename: str, headers: dict) -> dict:
url = f"https://api.github.com/repos/iqtree/piqtree/actions/workflows/{workflow_filename}/runs"
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
runs = response.json()["workflow_runs"]
if not runs:
msg = f"No workflow runs found for: '{workflow_filename}'"
raise ValueError(msg)
return runs[0]
def wait_for_run_completion(run: dict, headers: dict) -> dict:
run_id = run["id"]
run_url = f"https://api.github.com/repos/iqtree/piqtree/actions/runs/{run_id}"
waited = 0
while waited < MAX_WAIT_TIME:
response = requests.get(run_url, headers=headers, timeout=10)
response.raise_for_status()
run_status = response.json()
status = run_status["status"]
conclusion = run_status["conclusion"]
if status == "completed":
if conclusion != "success":
msg = f"Latest workflow run failed with conclusion: '{conclusion}'"
raise RuntimeError(msg)
return run_status
time.sleep(POLL_INTERVAL)
waited += POLL_INTERVAL
msg = "Timed out waiting for workflow run to complete."
raise TimeoutError(msg)
def download_and_extract_artifact(run: dict, headers: dict) -> None:
artifact_name = "piqtree-docs-html"
artifacts_url = run["artifacts_url"]
response = requests.get(artifacts_url, headers=headers, timeout=10)
response.raise_for_status()
artifacts = response.json()["artifacts"]
artifact = next((a for a in artifacts if a["name"] == artifact_name), None)
if artifact is None:
msg = f"Artifact '{artifact_name}' not found in the run."
raise ValueError(msg)
download_url = artifact["archive_download_url"]
response = requests.get(download_url, headers=headers, timeout=10)
response.raise_for_status()
out = pathlib.Path(f"{artifact_name}.zip")
out.write_bytes(response.content)
with zipfile.ZipFile(out, "r") as zip_ref:
zip_ref.extractall("_readthedocs/html/")
def download_and_extract_docs() -> None:
version = get_rtd_version_name()
if version not in ("latest", "stable"):
msg = f"Unexpected version '{version}' for readthedocs."
raise ValueError(msg)
workflow_filename = "release.yml" if version == "stable" else "build_docs.yml"
headers = {"Authorization": f"token {get_github_token()}"}
latest_run = get_latest_run(workflow_filename, headers)
completed_run = wait_for_run_completion(latest_run, headers)
download_and_extract_artifact(completed_run, headers)
if __name__ == "__main__":
download_and_extract_docs()
iqtree-piqtree-b8a3d6a/setup.py 0000664 0000000 0000000 00000005251 15211731751 0016664 0 ustar 00root root 0000000 0000000 """setup for piqtree."""
import platform
import subprocess
from pathlib import Path
from pybind11.setup_helpers import Pybind11Extension, build_ext
from setuptools import setup
LIBRARY_DIR = "src/piqtree/_libiqtree/"
IQTREE_LIB_NAME = "iqtree"
def get_brew_prefix(package: str) -> Path:
"""Get the prefix path for a specific Homebrew package."""
return Path(
subprocess.check_output(["brew", "--prefix", package]).strip().decode("utf-8"),
)
extra_libs = []
extra_compile_args = []
include_dirs = []
library_dirs = []
def include_dlls() -> None:
import shutil
from delvewheel._dll_utils import get_all_needed
needed_dll_paths, _, _, _ = get_all_needed(
LIBRARY_DIR + f"{IQTREE_LIB_NAME}.dll",
set(),
None,
"raise",
False, # noqa: FBT003
False, # noqa: FBT003
)
for dll_path in needed_dll_paths:
shutil.copy(dll_path, LIBRARY_DIR)
def setup_windows() -> None:
include_dlls()
def setup_macos() -> None:
brew_prefix_llvm = get_brew_prefix("llvm")
brew_prefix_libomp = get_brew_prefix("libomp")
# Define OpenMP flags and libraries for macOS
extra_compile_args.extend(["-Xpreprocessor", "-fopenmp"])
extra_libs.extend(["z", "omp"])
# Use the paths from Homebrew for libomp
include_dirs.extend([str(brew_prefix_libomp / "include")])
library_dirs.extend(
[
str(brew_prefix_libomp / "lib"),
str(brew_prefix_llvm / "lib"),
],
)
def setup_linux() -> None:
extra_compile_args.extend(["-fopenmp"])
extra_libs.extend(["z", "gomp"])
match system := platform.system():
case "Windows":
setup_windows()
case "Darwin":
setup_macos()
case "Linux":
setup_linux()
case _:
msg = f"Unsupported platform: {system}"
raise ValueError(msg)
ext_modules = [
Pybind11Extension(
"_piqtree",
["src/piqtree/_libiqtree/_piqtree.cpp"],
library_dirs=[
*library_dirs,
LIBRARY_DIR,
],
libraries=[IQTREE_LIB_NAME, *extra_libs],
extra_compile_args=extra_compile_args,
include_dirs=include_dirs,
),
]
class StripBuildExt(build_ext):
def run(self) -> None:
super().run()
system = platform.system()
flag = "-x" if system == "Darwin" else "--strip-unneeded"
for ext in self.extensions:
ext_path = self.get_ext_fullpath(ext.name)
subprocess.run(["strip", flag, ext_path], check=True)
setup(
name="piqtree",
ext_modules=ext_modules,
cmdclass={"build_ext": StripBuildExt},
zip_safe=False,
package_data={"piqtree": ["_libiqtree/*.dll"]},
)
iqtree-piqtree-b8a3d6a/src/ 0000775 0000000 0000000 00000000000 15211731751 0015736 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/src/piqtree/ 0000775 0000000 0000000 00000000000 15211731751 0017407 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/src/piqtree/__init__.py 0000664 0000000 0000000 00000002315 15211731751 0021521 0 ustar 00root root 0000000 0000000 """piqtree - access the power of IQ-TREE within Python."""
def _add_dll_path() -> None:
import os
if "add_dll_directory" in dir(os):
dll_folder = os.path.join(os.path.dirname(__file__), "_libiqtree")
os.add_dll_directory(dll_folder) # type: ignore[attr-defined]
_add_dll_path()
del _add_dll_path
from _piqtree import __iqtree_version__
from piqtree._data import dataset_names, download_dataset
from piqtree.iqtree import (
ModelFinderResult,
TreeGenMode,
build_tree,
consensus_tree,
fit_tree,
jc_distances,
model_finder,
nj_tree,
random_tree,
robinson_foulds,
simulate_alignment,
)
from piqtree.model import (
Model,
available_freq_type,
available_models,
available_rate_type,
make_model,
)
__version__ = "0.8.3"
__all__ = [
"Model",
"ModelFinderResult",
"TreeGenMode",
"__iqtree_version__",
"available_freq_type",
"available_models",
"available_rate_type",
"build_tree",
"consensus_tree",
"dataset_names",
"download_dataset",
"fit_tree",
"jc_distances",
"make_model",
"model_finder",
"nj_tree",
"random_tree",
"robinson_foulds",
"simulate_alignment",
]
iqtree-piqtree-b8a3d6a/src/piqtree/_app/ 0000775 0000000 0000000 00000000000 15211731751 0020326 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/src/piqtree/_app/__init__.py 0000664 0000000 0000000 00000011666 15211731751 0022451 0 ustar 00root root 0000000 0000000 """cogent3 apps for piqtree."""
from collections.abc import Iterable
from cogent3.core.alignment import Alignment
from cogent3.core.tree import PhyloNode
from cogent3.evolve.fast_distance import DistanceMatrix
from scinexus import composable
from scinexus.misc import extend_docstring_from
from piqtree import (
TreeGenMode,
build_tree,
consensus_tree,
fit_tree,
jc_distances,
model_finder,
nj_tree,
random_tree,
simulate_alignment,
)
from piqtree._cite import cite_piqtree
from piqtree.distribution import IndelDistribution
from piqtree.iqtree import ModelFinderResult
from piqtree.model import Model
@composable.define_app(cite=cite_piqtree)
class piq_build_tree:
@extend_docstring_from(build_tree)
def __init__(
self,
model: Model | str,
*,
rand_seed: int | None = None,
bootstrap_reps: int | None = None,
num_threads: int | None = None,
other_options: str = "",
) -> None:
self._model = model
self._rand_seed = rand_seed
self._bootstrap_reps = bootstrap_reps
self._num_threads = num_threads
self._other_options = other_options
def main(
self,
aln: Alignment,
) -> PhyloNode:
tree = build_tree(
aln,
self._model,
self._rand_seed,
bootstrap_replicates=self._bootstrap_reps,
num_threads=self._num_threads,
other_options=self._other_options,
)
tree.source = getattr(aln, "source", None)
return tree
@composable.define_app(cite=cite_piqtree)
class piq_fit_tree:
@extend_docstring_from(fit_tree)
def __init__(
self,
tree: PhyloNode,
model: Model | str,
*,
num_threads: int | None = None,
other_options: str = "",
bl_fixed: bool = False,
) -> None:
self._tree = tree
self._model = model
self._num_threads = num_threads
self._bl_fixed = bl_fixed
self._other_options = other_options
def main(
self,
aln: Alignment,
) -> PhyloNode:
tree = fit_tree(
aln,
self._tree,
self._model,
self._num_threads,
other_options=self._other_options,
bl_fixed=self._bl_fixed,
)
tree.source = getattr(aln, "source", None)
return tree
@composable.define_app(cite=cite_piqtree)
@extend_docstring_from(random_tree)
def piq_random_tree(
num_taxa: int,
tree_mode: TreeGenMode,
rand_seed: int | None = None,
) -> PhyloNode:
return random_tree(num_taxa, tree_mode, rand_seed)
@composable.define_app(cite=cite_piqtree)
class piq_jc_distances:
@extend_docstring_from(jc_distances)
def __init__(
self,
num_threads: int | None = None,
) -> None:
self._num_threads = num_threads
def main(
self,
aln: Alignment,
) -> DistanceMatrix:
dists = jc_distances(
aln,
num_threads=self._num_threads,
)
dists.source = getattr(aln, "source", None)
return dists
@composable.define_app(cite=cite_piqtree)
@extend_docstring_from(nj_tree)
def piq_nj_tree(
dists: DistanceMatrix,
*,
allow_negative: bool = False,
) -> PhyloNode:
tree = nj_tree(dists, allow_negative=allow_negative)
tree.params |= {"provenance": "piqtree"}
tree.source = getattr(dists, "source", None)
return tree
@composable.define_app(cite=cite_piqtree)
@extend_docstring_from(model_finder)
def piq_model_finder(
aln: Alignment,
) -> ModelFinderResult:
return model_finder(aln)
@composable.define_app(cite=cite_piqtree)
@extend_docstring_from(consensus_tree)
def piq_consensus_tree(
trees: Iterable[PhyloNode],
*,
min_support: float = 0.5,
) -> PhyloNode:
return consensus_tree(trees, min_support=min_support)
@composable.define_app(cite=cite_piqtree)
@extend_docstring_from(simulate_alignment)
def piq_simulate_alignment(
tree: PhyloNode,
model: Model | str,
length: int = 1000,
rand_seed: int | None = None,
insertion_rate: float = 0.0,
deletion_rate: float = 0.0,
insertion_size_distribution: IndelDistribution | str = "POW{1.7/100}",
deletion_size_distribution: IndelDistribution | str = "POW{1.7/100}",
root_seq: str | None = None,
num_threads: int | None = None,
) -> Alignment:
return simulate_alignment(
tree,
model,
length=length,
rand_seed=rand_seed,
insertion_rate=insertion_rate,
deletion_rate=deletion_rate,
insertion_size_distribution=insertion_size_distribution,
deletion_size_distribution=deletion_size_distribution,
root_seq=root_seq,
num_threads=num_threads,
)
_ALL_APP_NAMES = [
"piq_build_tree",
"piq_fit_tree",
"piq_random_tree",
"piq_jc_distances",
"piq_nj_tree",
"piq_model_finder",
"piq_consensus_tree",
"piq_simulate_alignment",
]
iqtree-piqtree-b8a3d6a/src/piqtree/_cite.py 0000664 0000000 0000000 00000001123 15211731751 0021041 0 ustar 00root root 0000000 0000000 from citeable import Article
cite_piqtree = Article(
key="piqtree",
author=[
"McArthur, Robert Neil",
"Wong, Thomas King-Fung",
"Lang, Yapeng",
"Morris, Richard Andrew",
"Caley, Katherine",
"Mallawaarachchi, Vijini",
"Minh, Bui Quang",
"Huttley, Gavin",
],
title="{piqtree}: A Python Package for Seamless Phylogenetic Inference with {IQ-TREE}",
year=2026,
journal="Molecular Biology and Evolution",
pages="msag061",
doi="10.1093/molbev/msag061",
url="https://doi.org/10.1093/molbev/msag061",
)
iqtree-piqtree-b8a3d6a/src/piqtree/_data.py 0000664 0000000 0000000 00000004435 15211731751 0021037 0 ustar 00root root 0000000 0000000 import pathlib
import zipfile
import requests
_data_files = {
"mammal-orths.zip": "https://github.com/user-attachments/files/17806562/mammal-orths.zip",
"brca1.fasta.gz": "https://github.com/user-attachments/files/17806563/brca1.fasta.gz",
"example.phy.gz": "https://github.com/user-attachments/files/17806561/example.phy.gz",
"example.tree.gz": "https://github.com/user-attachments/files/17821150/example.tree.gz",
}
def _inflate_zip(zip_path: pathlib.Path, output_dir: pathlib.Path) -> pathlib.Path:
"""Decompress the contents of a zip file to a named directory."""
with zipfile.ZipFile(zip_path, "r") as zip_ref:
zip_ref.extractall(output_dir)
return output_dir
def _get_url(name: str) -> str:
"""URL for a data file."""
if name not in _data_files:
msg = f"Unknown data file: {name}"
raise ValueError(msg)
return _data_files[name]
def dataset_names() -> list[str]:
"""Return the names of available datasets."""
return list(_data_files.keys())
def download_dataset(
name: str,
dest_dir: str | pathlib.Path,
dest_name: str | None = None,
*,
inflate_zip: bool = True,
) -> pathlib.Path:
"""Download data files used in docs, requires an internet connection.
Parameters
----------
name : str
Data set name, see `dataset_names()`.
dest_dir : str | pathlib.Path
Where to write a local copy.
dest_name : str | None, optional
Name of the file to write, if None (default) uses name.
inflate_zip : bool, optional
Whether to unzip archives, by default True.
Returns
-------
pathlib.Path
Path to the downloaded file
Notes
-----
Only downloads if dest_dir / dest_name does not exist.
"""
dest_dir = pathlib.Path(dest_dir)
url = _get_url(name)
dest_name = dest_name or name
outpath = dest_dir / dest_name
outpath.parent.mkdir(parents=True, exist_ok=True)
if outpath.exists():
return outpath
response = requests.get(url, stream=True, timeout=20)
block_size = 4096
with outpath.open("wb") as out:
for data in response.iter_content(block_size):
out.write(data)
if inflate_zip and outpath.suffix == ".zip":
outpath = _inflate_zip(outpath, dest_dir)
return outpath
iqtree-piqtree-b8a3d6a/src/piqtree/_libiqtree/ 0000775 0000000 0000000 00000000000 15211731751 0021526 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/src/piqtree/_libiqtree/README.txt 0000664 0000000 0000000 00000000103 15211731751 0023216 0 ustar 00root root 0000000 0000000 Place the IQ-TREE static library, `libiqtree.a`, in this directory. iqtree-piqtree-b8a3d6a/src/piqtree/_libiqtree/_piqtree.cpp 0000664 0000000 0000000 00000012577 15211731751 0024056 0 ustar 00root root 0000000 0000000 #include "_piqtree.h"
#include
#include
#include
#include
#include
#include
#include "_piqtree.h"
namespace py = pybind11;
void checkError(char* errorStr) {
if (errorStr && std::strlen(errorStr) > 0) {
string msg(errorStr);
iqtree_free(errorStr);
throw std::runtime_error(msg);
}
if (errorStr)
iqtree_free(errorStr);
}
namespace PYBIND11_NAMESPACE {
namespace detail {
template <>
struct type_caster {
public:
PYBIND11_TYPE_CASTER(StringArray, const_name("StringArray"));
// Conversion from Python to C++
bool load(handle src, bool) {
/* Extract PyObject from handle */
PyObject* source = src.ptr();
if (!py::isinstance(source)) {
return false;
}
auto seq = reinterpret_borrow(src);
value.length = seq.size();
tmpStrings.reserve(value.length);
tmpCStrs.reserve(value.length);
for (size_t i = 0; i < seq.size(); ++i) {
auto item = seq[i];
if (!py::isinstance(item)) {
return false;
}
tmpStrings.push_back(item.cast());
tmpCStrs.push_back(tmpStrings[i].c_str());
}
value.strings = tmpCStrs.data();
return true;
}
// Conversion from C++ to Python
static handle cast(StringArray src, return_value_policy, handle) {
throw std::runtime_error("Unsupported operation");
}
private:
vector tmpStrings;
vector tmpCStrs;
};
template <>
struct type_caster {
public:
PYBIND11_TYPE_CASTER(DoubleArray, _("DoubleArray"));
// Conversion from Python to C++
bool load(handle src, bool) {
if (!py::isinstance>(src)) {
return false; // Only accept numpy arrays of float64
}
auto arr = py::cast>(src);
if (arr.ndim() != 1) {
return false; // Only accept 1D arrays
}
value.length = arr.size();
tmpDoubles.assign(arr.data(), arr.data() + value.length);
value.doubles = tmpDoubles.data();
return true;
}
// Conversion from C++ to Python
static handle cast(DoubleArray src, return_value_policy, handle) {
throw std::runtime_error("Unsupported operation");
}
private:
vector tmpDoubles;
};
template <>
struct type_caster {
public:
PYBIND11_TYPE_CASTER(IntegerResult, _("IntegerResult"));
// Conversion from Python to C++
bool load(handle /* src */, bool /* convert */) {
throw std::runtime_error("Unsupported operation");
}
// Conversion from C++ to Python
static handle cast(const IntegerResult& src, return_value_policy, handle) {
checkError(src.errorStr);
return py::int_(src.value).release();
}
};
template <>
struct type_caster {
public:
// Indicate that this caster only supports conversion from C++ to Python
PYBIND11_TYPE_CASTER(StringResult, _("StringResult"));
// Reject Python to C++ conversion
bool load(handle src, bool) {
throw std::runtime_error("Unsupported operation");
}
// Conversion from C++ to Python
static handle cast(const StringResult& src, return_value_policy, handle) {
checkError(src.errorStr);
PyObject* py_str = PyUnicode_FromString(src.value);
if (!py_str)
throw error_already_set();
iqtree_free(src.value);
return handle(py_str);
}
};
template <>
struct type_caster {
public:
PYBIND11_TYPE_CASTER(DoubleArrayResult, _("DoubleArrayResult"));
// Conversion from Python to C++
bool load(handle src, bool) {
throw std::runtime_error("Unsupported operation");
}
// Conversion from C++ to Python
static handle cast(DoubleArrayResult src, return_value_policy, handle) {
checkError(src.errorStr);
auto result = py::array_t(src.length);
std::memcpy(result.mutable_data(), src.value, src.length * sizeof(double));
iqtree_free(src.value);
return result.release();
}
};
} // namespace detail
} // namespace PYBIND11_NAMESPACE
int mine() {
return 42;
}
PYBIND11_MODULE(_piqtree, m) {
m.doc() = "_piqtree - Linking IQ-TREE to Python!";
m.attr("__iqtree_version__") = version();
m.def("iq_robinson_fould", &robinson_fould,
"Calculates the robinson fould distance between two trees");
m.def("iq_random_tree", &random_tree,
"Generates a set of random phylogenetic trees. tree_gen_mode "
"allows:\"YULE_HARDING\", \"UNIFORM\", \"CATERPILLAR\", \"BALANCED\", "
"\"BIRTH_DEATH\", \"STAR_TREE\".");
m.def("iq_build_tree", &build_tree,
"Perform phylogenetic analysis on the input alignment (in string "
"format). With estimation of the best topology.");
m.def("iq_fit_tree", &fit_tree,
"Perform phylogenetic analysis on the input alignment (in string "
"format). With restriction to the input toplogy.");
m.def("iq_model_finder", &modelfinder,
"Find optimal model for an alignment.");
m.def("iq_jc_distances", &build_distmatrix,
"Construct pairwise distance matrix for alignment.");
m.def("iq_nj_tree", &build_njtree,
"Build neighbour-joining tree from distance matrix.");
m.def("iq_consensus_tree", &consensus_tree,
"Compute a consensus tree from a sequence of trees.");
m.def("iq_simulate_alignment", &simulate_alignment,
"Simulate an alignment with AliSim.");
m.def("mine", &mine, "The meaning of life, the universe (and everything)!");
}
iqtree-piqtree-b8a3d6a/src/piqtree/_libiqtree/_piqtree.h 0000664 0000000 0000000 00000013570 15211731751 0023515 0 ustar 00root root 0000000 0000000 #ifndef _PIQTREE_H
#define _PIQTREE_H
#include
#include
using namespace std;
#ifdef _MSC_VER
#pragma pack(push, 1)
#else
#pragma pack(1)
#endif
typedef struct {
const char** strings;
size_t length;
} StringArray;
typedef struct {
double* doubles;
size_t length;
} DoubleArray;
typedef struct {
int value;
char* errorStr;
} IntegerResult;
typedef struct {
char* value;
char* errorStr;
} StringResult;
typedef struct {
double* value;
size_t length;
char* errorStr;
} DoubleArrayResult;
#ifdef _MSC_VER
#pragma pack(pop)
#else
#pragma pack()
#endif
/*
* Calculates the robinson fould distance between two trees
*/
extern "C" IntegerResult robinson_fould(const char* ctree1, const char* ctree2);
/*
* Generates a set of random phylogenetic trees
* tree_gen_mode allows:"YULE_HARDING", "UNIFORM", "CATERPILLAR", "BALANCED",
* "BIRTH_DEATH", "STAR_TREE" output: a newick tree (in string format)
*/
extern "C" StringResult random_tree(int num_taxa,
const char* tree_gen_mode,
int num_trees,
int rand_seed = 0);
/*
* Perform phylogenetic analysis on the input alignment
* With estimation of the best topology
* num_thres -- number of cpu threads to be used, default: 1; 0 - auto detection
* of the optimal number of cpu threads output: results in YAML format with the
* tree and the details of parameters
*/
extern "C" StringResult build_tree(StringArray& names,
StringArray& seqs,
const char* model,
int rand_seed = 0,
int bootstrap_rep = 0,
int num_thres = 1,
const char* other_options = NULL);
/*
* Perform phylogenetic analysis on the input alignment
* With restriction to the input toplogy
* blfix -- whether to fix the branch length as those on the given tree,
* default: false num_thres -- number of cpu threads to be used, default: 1; 0 -
* auto detection of the optimal number of cpu threads output: results in YAML
* format with the details of parameters
*/
extern "C" StringResult fit_tree(StringArray& names,
StringArray& seqs,
const char* model,
const char* intree,
bool blfix = false,
int rand_seed = 0,
int num_thres = 1,
const char* other_options = NULL);
/*
* Perform phylogenetic analysis with ModelFinder
* on the input alignment (in string format)
* model_set -- a set of models to consider
* freq_set -- a set of frequency types
* rate_set -- a set of RHAS models
* rand_seed -- random seed, if 0, then will generate a new random seed
* num_thres -- number of cpu threads to be used, default: 1; 0 - auto detection
* of the optimal number of cpu threads output: modelfinder results in YAML
* format
*/
extern "C" StringResult modelfinder(StringArray& names,
StringArray& seqs,
int rand_seed = 0,
const char* model_set = "",
const char* freq_set = "",
const char* rate_set = "",
int num_thres = 1,
const char* other_options = NULL);
/*
* Build pairwise JC distance matrix
* output: set of distances
* (n * i + j)-th element of the list represents the distance between i-th and
* j-th sequence, where n is the number of sequences num_thres -- number of cpu
* threads to be used, default: 1; 0 - use all available cpu threads on the
* machine
*/
extern "C" DoubleArrayResult build_distmatrix(StringArray& names,
StringArray& seqs,
int num_thres = 1);
/*
* Using Rapid-NJ to build tree from a distance matrix
* output: a newick tree (in string format)
*/
extern "C" StringResult build_njtree(StringArray& names,
DoubleArray& distances);
/*
* Compute a consensus tree
* trees -- a set of input trees
* minsup -- a threshold to build the majority consensus (default: 0.5)
* output -- the resulting consensus tree
*/
extern "C" StringResult consensus_tree(StringArray& trees, double minsup = 0.5);
/*
* Execute AliSim Simulation
* output: results in YAML format that contains the simulated alignment and the
* content of the log file tree -- the NEWICK tree string subst_model -- the
* substitution model name seed -- the random seed partition_info -- partition
* information partition_type -- partition type is either ‘equal’, ‘proportion’,
* or ‘unlinked’ seq_length -- the length of sequences insertion_rate -- the
* insertion rate deletion_rate -- the deletion rate root_seq -- the root
* sequence num_threads -- the number of threads insertion_size_distribution --
* the insertion size distribution deletion_size_distribution -- the deletion
* size distribution population_size -- the population size
*/
extern "C" StringResult simulate_alignment(
const char* tree,
const char* subst_model,
int seed,
const char* partition_info = "",
const char* partition_type = "",
int seq_length = 1000,
double insertion_rate = 0,
double deletion_rate = 0,
const char* root_seq = "",
int num_threads = 1,
const char* insertion_size_distribution = "",
const char* deletion_size_distribution = "",
int population_size = -1);
/*
* version number
*/
extern "C" StringResult version();
/*
* Free memory allocated by IQ-TREE
*/
extern "C" void iqtree_free(void* p);
#endif /* _PIQTREE_H */
iqtree-piqtree-b8a3d6a/src/piqtree/distribution/ 0000775 0000000 0000000 00000000000 15211731751 0022126 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/src/piqtree/distribution/__init__.py 0000664 0000000 0000000 00000000425 15211731751 0024240 0 ustar 00root root 0000000 0000000 from .indel_distribution import (
IndelDistribution,
IndelGeometric,
IndelLavalette,
IndelNegativeBinomial,
IndelZipfian,
)
__all__ = [
"IndelDistribution",
"IndelGeometric",
"IndelLavalette",
"IndelNegativeBinomial",
"IndelZipfian",
]
iqtree-piqtree-b8a3d6a/src/piqtree/distribution/indel_distribution.py 0000664 0000000 0000000 00000002204 15211731751 0026370 0 ustar 00root root 0000000 0000000 from abc import ABC, abstractmethod
class IndelDistribution(ABC):
@abstractmethod
def iqtree_str(self) -> str:
pass # pragma: no cover
def __str__(self) -> str:
return self.iqtree_str()
class IndelZipfian(IndelDistribution):
def __init__(self, exponent: float, max_size: int) -> None:
self.exponent = exponent
self.max_size = max_size
def iqtree_str(self) -> str:
return f"POW{{{self.exponent}/{self.max_size}}}"
class IndelGeometric(IndelDistribution):
def __init__(self, mean: float) -> None:
self.mean = mean
def iqtree_str(self) -> str:
return f"GEO{{{self.mean}}}"
class IndelNegativeBinomial(IndelDistribution):
def __init__(self, mean: float, variance: float) -> None:
self.mean = mean
self.variance = variance
def iqtree_str(self) -> str:
return f"NB{{{self.mean}/{self.variance}}}"
class IndelLavalette(IndelDistribution):
def __init__(self, a: float, max_size: int) -> None:
self.a = a
self.max_size = max_size
def iqtree_str(self) -> str:
return f"LAV{{{self.a}/{self.max_size}}}"
iqtree-piqtree-b8a3d6a/src/piqtree/exceptions.py 0000664 0000000 0000000 00000000317 15211731751 0022143 0 ustar 00root root 0000000 0000000 """Contains piqtree exceptions."""
class IqTreeError(Exception):
"""An error thrown by IQ-TREE."""
class ParseIqTreeError(Exception):
"""There was an error when parsing a result from IQ-TREE."""
iqtree-piqtree-b8a3d6a/src/piqtree/iqtree/ 0000775 0000000 0000000 00000000000 15211731751 0020700 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/src/piqtree/iqtree/__init__.py 0000664 0000000 0000000 00000001172 15211731751 0023012 0 ustar 00root root 0000000 0000000 """Functions for calling IQ-TREE as a library."""
from ._alignment import simulate_alignment
from ._jc_distance import jc_distances
from ._model_finder import ModelFinderResult, ModelResultValue, model_finder
from ._random_tree import TreeGenMode, random_tree
from ._robinson_foulds import robinson_foulds
from ._tree import build_tree, consensus_tree, fit_tree, nj_tree
__all__ = [
"ModelFinderResult",
"ModelResultValue",
"TreeGenMode",
"build_tree",
"consensus_tree",
"fit_tree",
"jc_distances",
"model_finder",
"nj_tree",
"random_tree",
"robinson_foulds",
"simulate_alignment",
]
iqtree-piqtree-b8a3d6a/src/piqtree/iqtree/_alignment.py 0000664 0000000 0000000 00000010657 15211731751 0023400 0 ustar 00root root 0000000 0000000 from typing import cast
import yaml
from _piqtree import iq_simulate_alignment
from cogent3 import make_aligned_seqs
from cogent3.core.alignment import Alignment
from cogent3.core.tree import PhyloNode
from piqtree.distribution import IndelDistribution
from piqtree.exceptions import ParseIqTreeError
from piqtree.iqtree._decorator import iqtree_func
from piqtree.model import LieModel, Model, make_model
from piqtree.util import get_newick, make_rand_seed
iq_simulate_alignment = iqtree_func(iq_simulate_alignment, hide_files=True)
UNSUPPORTED_MODELS = {
LieModel.LIE_1_1,
LieModel.LIE_3_3a,
LieModel.LIE_4_4a,
LieModel.LIE_6_7a,
LieModel.LIE_9_20a,
LieModel.LIE_9_20b,
LieModel.LIE_12_12,
}
def simulate_alignment(
tree: PhyloNode,
model: Model | str,
length: int = 1000,
rand_seed: int | None = None,
insertion_rate: float = 0.0,
deletion_rate: float = 0.0,
insertion_size_distribution: IndelDistribution | str = "POW{1.7/100}",
deletion_size_distribution: IndelDistribution | str = "POW{1.7/100}",
root_seq: str | None = None,
num_threads: int | None = None,
) -> Alignment:
"""Uses AliSim to simulate an Alignment through IQ-TREE.
Parameters
----------
tree: list[cogent3.PhyloNode]
A tree to simulate an alignment over.
model: str
The substitution model's specification.
length: int
The length of the alignment (by default 1000).
Alignment may be longer when indel model is used due to insertion events.
rand_seed : int | None, optional
The random seed - None means no seed is used, by default None.
insertion_rate: float | None, optional
The insertion rate relative to substitution rate (by default 0.0).
deletion_rate: float | None, optional
The deletion rate relative to substitution rate (by default 0.0).
insertion_size_distribution: str | None, optional
The insertion size distribution (by default the Zipfian
distribution with a=1.7 and maximum size 100).
deletion_size_distribution: str | None, optional
The deletion size distribution (by default the Zipfian
distribution with a=1.7 and maximum size 100).
root_seq: str | None, optional
The root sequence (by default None).
num_threads: int | None, optional
Number of threads for IQ-TREE to use, by default None (single-threaded).
Returns
-------
c3_types.AlignedSeqsType
The simulated alignment.
"""
if rand_seed is None:
rand_seed = make_rand_seed()
if root_seq is None:
root_seq = ""
if num_threads is None:
num_threads = 1
if isinstance(model, str):
model = make_model(model)
if model.submod_type.base_model in UNSUPPORTED_MODELS:
msg = f"Lie Model {cast('LieModel', model.submod_type.base_model).value} is unsupported."
raise ValueError(msg)
newick_tree = get_newick(tree)
yaml_result = yaml.safe_load(
iq_simulate_alignment(
newick_tree,
str(model),
rand_seed,
"",
"",
length,
insertion_rate,
deletion_rate,
root_seq,
num_threads,
str(insertion_size_distribution),
str(deletion_size_distribution),
-1,
),
)
seqs = _parse_yaml_alignment(yaml_result["alignment"])
return make_aligned_seqs(seqs, moltype=model.submod_type.get_moltype())
def _parse_yaml_alignment(yaml_alignment: str) -> dict[str, str]:
seqs: dict[str, str] = {}
name = None
seq_buffer = None
for part in yaml_alignment.split("\n"):
if part.startswith(">"):
if seq_buffer is not None:
if name is None:
msg = "Got sequence data without name." # pragma: no cover
raise ParseIqTreeError(msg) # pragma: no cover
seqs[name] = seq_buffer
name = part.strip()[1:]
seq_buffer = ""
elif seq_buffer is not None:
seq_buffer += part.strip()
else:
msg = f"Unexpected parsed value '{part}'" # pragma: no cover
raise ParseIqTreeError(msg) # pragma: no cover
if seq_buffer is not None:
if name is None:
msg = "Got sequence data without name." # pragma: no cover
raise ParseIqTreeError(msg) # pragma: no cover
seqs[name] = seq_buffer
return seqs
iqtree-piqtree-b8a3d6a/src/piqtree/iqtree/_decorator.py 0000664 0000000 0000000 00000006005 15211731751 0023374 0 ustar 00root root 0000000 0000000 """Decorators for IQ-TREE functions."""
import io
import os
import pathlib
import sys
import tempfile
from collections.abc import Callable
from functools import wraps
from piqtree.exceptions import IqTreeError
def _fd_or_fallback(stream: object, fallback_fd: int) -> int:
"""Return the file descriptor for the stream, or a fallback file descriptor.
Parameters
----------
stream : stdout or stderr stream
The io stream.
fallback_fd : int
Fallback file descriptor.
Returns
-------
int
The file descriptor for the stream, or the fallback on error.
"""
try:
return stream.fileno() # type: ignore[attr-defined]
except io.UnsupportedOperation: # pragma: no cover
return fallback_fd # pragma: no cover
def iqtree_func[**Param, RetType](
func: Callable[Param, RetType],
*,
hide_files: bool = False,
) -> Callable[Param, RetType]:
"""IQ-TREE function wrapper.
Hides stdout and stderr, as well as any output files.
Parameters
----------
func : Callable[Param, RetType]
The IQ-TREE library function.
hide_files : bool, optional
Whether hiding output files is necessary, by default False.
Returns
-------
Callable[Param, RetType]
The wrapped IQ-TREE function.
Raises
------
IqTreeError
An error from the IQ-TREE library.
"""
@wraps(func)
def wrapper_iqtree_func(*args: Param.args, **kwargs: Param.kwargs) -> RetType:
# Flush stdout and stderr
sys.stdout.flush()
sys.stderr.flush()
# Fetch file descriptors
out_fd = _fd_or_fallback(sys.stdout, 1)
err_fd = _fd_or_fallback(sys.stderr, 2)
# Save original stdout and stderr file descriptors
saved_stdout_fd = os.dup(out_fd)
saved_stderr_fd = os.dup(err_fd)
# Open /dev/null (or NUL on Windows) as destination for stdout and stderr
devnull_fd = os.open(os.devnull, os.O_WRONLY)
if hide_files:
original_dir = pathlib.Path.cwd()
tempdir = tempfile.TemporaryDirectory(prefix=f"piqtree_{func.__name__}")
os.chdir(tempdir.name)
try:
# Replace stdout and stderr with /dev/null
os.dup2(devnull_fd, out_fd)
os.dup2(devnull_fd, err_fd)
# Call the wrapped function
return func(*args, **kwargs)
except RuntimeError as e:
raise IqTreeError(e) from None
finally:
# Flush stdout and stderr
sys.stdout.flush()
sys.stderr.flush()
# Restore stdout and stderr
os.dup2(saved_stdout_fd, out_fd)
os.dup2(saved_stderr_fd, err_fd)
# Close the devnull file descriptor, and duplicated file descriptors
os.close(devnull_fd)
os.close(saved_stdout_fd)
os.close(saved_stderr_fd)
if hide_files:
os.chdir(original_dir)
tempdir.cleanup()
return wrapper_iqtree_func
iqtree-piqtree-b8a3d6a/src/piqtree/iqtree/_jc_distance.py 0000664 0000000 0000000 00000003271 15211731751 0023662 0 ustar 00root root 0000000 0000000 from collections.abc import Sequence
import numpy as np
from _piqtree import iq_jc_distances
from cogent3.core.alignment import Alignment
from cogent3.evolve.fast_distance import DistanceMatrix
from piqtree.iqtree._decorator import iqtree_func
iq_jc_distances = iqtree_func(iq_jc_distances, hide_files=True)
def _dists_to_distmatrix(
distances: np.ndarray,
names: Sequence[str],
) -> DistanceMatrix:
"""Convert numpy representation of distance matrix into cogent3 pairwise distance matrix.
Parameters
----------
distances : np.ndarray
Pairwise distances.
names : Sequence[str]
Corresponding sequence names.
Returns
-------
DistanceMatrix
Pairwise distance matrix.
"""
dist_dict = {}
for i in range(1, len(distances)):
for j in range(i):
dist_dict[(names[i], names[j])] = distances[i, j]
return DistanceMatrix(dist_dict)
def jc_distances(
aln: Alignment,
num_threads: int | None = None,
) -> DistanceMatrix:
"""Compute pairwise JC distances for a given alignment.
Parameters
----------
aln : Alignment
The alignment to compute pairwise JC distances for.
num_threads: int | None, optional
Number of threads for IQ-TREE to use,
by default None (uses all available threads).
Returns
-------
DistanceMatrix
Pairwise JC distance matrix.
"""
if num_threads is None:
num_threads = 0
names = aln.names
seqs = [str(seq) for seq in aln.iter_seqs(names)]
distances = np.array(iq_jc_distances(names, seqs, num_threads)).reshape(
(len(names), len(names)),
)
return _dists_to_distmatrix(distances, names)
iqtree-piqtree-b8a3d6a/src/piqtree/iqtree/_model_finder.py 0000664 0000000 0000000 00000014334 15211731751 0024045 0 ustar 00root root 0000000 0000000 """Python wrapper for model finder in the IQ-TREE library."""
import dataclasses
from collections.abc import Iterable
from typing import Any, cast
import yaml
from _piqtree import iq_model_finder
from cogent3.core.alignment import Alignment
from scinexus.misc import get_object_provenance
from piqtree.iqtree._decorator import iqtree_func
from piqtree.model import Model, make_model
from piqtree.util import process_rand_seed_nonzero, validate_other_options
iq_model_finder = iqtree_func(iq_model_finder, hide_files=True)
@dataclasses.dataclass(slots=True, frozen=True)
class ModelResultValue:
"""Model statistics from IQ-TREE model_finder.
Parameters
----------
lnL : float
Log likelihood of the model.
nfp : int
Number of free parameters in the model.
tree_length : float
Length of the tree (sum of branch lengths).
"""
lnL: float # noqa: N815
nfp: int
tree_length: float
@classmethod
def from_string(cls, val: str) -> "ModelResultValue":
"""Parse the string produced by IQ-TREE model_finder for a given model."""
try:
lnL, nfp, tree_length = val.split()[:3] # noqa: N806
return cls(lnL=float(lnL), nfp=int(nfp), tree_length=float(tree_length))
except ValueError as e:
msg = f"Error parsing string '{val}'"
raise ValueError(msg) from e
@dataclasses.dataclass(slots=True)
class ModelFinderResult:
"""Data returned by ModelFinder.
Attributes
----------
source : str
Source of the alignment.
raw_data : dict[str, Any]
Raw data returned by ModelFinder.
best_aic : Model
The best AIC model.
best_aicc : Model
The best AICc model.
best_bic : Model
The best BIC model.
model_stats : dict[Model | str, ModelResultValue]
Semi-processed representation of raw_data.
"""
source: str
raw_data: dataclasses.InitVar[dict[str, Any]]
best_aic: Model = dataclasses.field(init=False)
best_aicc: Model = dataclasses.field(init=False)
best_bic: Model = dataclasses.field(init=False)
model_stats: dict[Model | str, ModelResultValue] = dataclasses.field(
init=False,
repr=False,
default_factory=dict,
)
def __post_init__(self, raw_data: dict[str, Any]) -> None:
self.model_stats = {
key: ModelResultValue.from_string(val)
for key, val in raw_data.items()
if not key.startswith(("best_", "initTree")) and isinstance(val, str)
}
self.best_aic = make_model(raw_data["best_model_AIC"])
self.best_aicc = make_model(raw_data["best_model_AICc"])
self.best_bic = make_model(raw_data["best_model_BIC"])
self.model_stats[self.best_aic] = ModelResultValue.from_string(
raw_data[str(self.best_aic)],
)
self.model_stats[self.best_aicc] = ModelResultValue.from_string(
raw_data[str(self.best_aicc)],
)
self.model_stats[self.best_bic] = ModelResultValue.from_string(
raw_data[str(self.best_bic)],
)
def to_rich_dict(self) -> dict[str, Any]:
import piqtree
result: dict[str, Any] = {
"version": piqtree.__version__,
"type": get_object_provenance(self),
}
raw_data = {
str(model_): f"{stats.lnL} {stats.nfp} {stats.tree_length}"
for model_, stats in self.model_stats.items()
}
for attr in ("best_model_AIC", "best_model_AICc", "best_model_BIC"):
raw_data[attr] = str(getattr(self, attr.replace("_model", "").lower()))
result["init_kwargs"] = {"raw_data": raw_data, "source": self.source}
return result
@classmethod
def from_rich_dict(cls, data: dict[str, Any]) -> "ModelFinderResult":
return cls(**data["init_kwargs"])
INVALID_MODEL_FINDER_PARAMS = [
"-s", # aln file
"-m", # model selection
"-mset", # model set
"-mfreq", # freq set
"-mrate", # rate set
"-seed", # seed
"-nt", # threads
"-ntmax", # threads
]
def model_finder(
aln: Alignment,
model_set: Iterable[str] | None = None,
freq_set: Iterable[str] | None = None,
rate_set: Iterable[str] | None = None,
rand_seed: int | None = None,
num_threads: int | None = None,
other_options: str = "",
) -> ModelFinderResult:
"""Find the models of best fit for an alignment using ModelFinder.
Parameters
----------
aln : Alignment
The alignment to find the model of best fit for.
model_set : Iterable[str] | None, optional
Search space for models.
Equivalent to IQ-TREE's mset parameter, by default None
freq_set : Iterable[str] | None, optional
Search space for frequency types.
Equivalent to IQ-TREE's mfreq parameter, by default None
rate_set : Iterable[str] | None, optional
Search space for rate heterogeneity types.
Equivalent to IQ-TREE's mrate parameter, by default None
rand_seed : int | None, optional
The random seed - None means no seed is used, by default None.
num_threads: int | None, optional
Number of threads for IQ-TREE to use, by default None (single-threaded).
If 0 is specified, IQ-TREE attempts to find the optimal number of threads.
other_options: str, optional
Additional command line options for IQ-TREE.
Returns
-------
ModelFinderResult
Collection of data returned from IQ-TREE's ModelFinder.
"""
validate_other_options(other_options, INVALID_MODEL_FINDER_PARAMS)
source = cast("str", aln.info.source)
rand_seed = process_rand_seed_nonzero(rand_seed)
if num_threads is None:
num_threads = 1
if model_set is None:
model_set = set()
if freq_set is None:
freq_set = set()
if rate_set is None:
rate_set = set()
names = aln.names
seqs = [str(seq) for seq in aln.iter_seqs(names)]
raw = yaml.safe_load(
iq_model_finder(
names,
seqs,
rand_seed,
",".join(model_set),
",".join(freq_set),
",".join(rate_set),
num_threads,
other_options,
),
)
return ModelFinderResult(raw_data=raw, source=source)
iqtree-piqtree-b8a3d6a/src/piqtree/iqtree/_parse_tree_parameters.py 0000664 0000000 0000000 00000014756 15211731751 0026002 0 ustar 00root root 0000000 0000000 from typing import Any
from cogent3.core.tree import PhyloNode
from piqtree.exceptions import ParseIqTreeError
from piqtree.model import Model, StandardDnaModel
# the order defined in IQ-TREE
# assume UNREST model has 12 rates, GTR and simpler models always have 6 rates present
RATE_PARS = "A/C", "A/G", "A/T", "C/G", "C/T", "G/T"
RATE_PARS_UNREST = (
"A/C",
"A/G",
"A/T",
"C/A",
"C/G",
"C/T",
"G/A",
"G/C",
"G/T",
"T/A",
"T/C",
"T/G",
)
MOTIF_PARS = "A", "C", "G", "T"
def _insert_edge_pars(tree: PhyloNode, **kwargs: dict) -> None:
# inserts the edge parameters into each edge to match the structure of
# PhyloNode
for node in tree.get_edge_vector():
# skip the rate parameters when node is the root
if node.is_root():
kwargs = {k: v for k, v in kwargs.items() if k == "mprobs"}
del node.params["edge_pars"]
node.params.update(kwargs)
def _edge_pars_for_cogent3(tree: PhyloNode, model: Model) -> None:
base_model = model.submod_type.base_model
rate_pars = tree.params["edge_pars"]["rates"]
motif_pars = {"mprobs": tree.params["edge_pars"]["mprobs"]}
# renames parameters to conform to cogent3's naming conventions
if base_model in {StandardDnaModel.JC, StandardDnaModel.F81}:
# skip rate_pars since rate parameters are constant in JC and F81
_insert_edge_pars(
tree,
**motif_pars,
)
return
if base_model in {StandardDnaModel.K80, StandardDnaModel.HKY}:
rate_pars = {"kappa": rate_pars["A/G"]}
elif base_model is StandardDnaModel.TN:
rate_pars = {"kappa_r": rate_pars["A/G"], "kappa_y": rate_pars["C/T"]}
elif base_model is StandardDnaModel.GTR:
del rate_pars["G/T"]
# applies global rate parameters to each edge
_insert_edge_pars(
tree,
**rate_pars,
**motif_pars,
)
def _parse_nonlie_model(tree: PhyloNode, tree_yaml: dict) -> None:
# parse motif and rate parameters in the tree_yaml for non-Lie DnaModel
model_fits = tree_yaml.get("ModelDNA", {})
state_freq_str = model_fits.get("state_freq", "")
rate_str = model_fits.get("rates", "")
# parse motif parameters, assign each to a name, and raise an error if not found
if state_freq_str:
# converts the strings of motif parameters into dictionary
state_freq_list = [
float(value) for value in state_freq_str.replace(" ", "").split(",")
]
tree.params["edge_pars"] = {
"mprobs": dict(zip(MOTIF_PARS, state_freq_list, strict=True)),
}
else:
msg = "IQ-TREE output is malformed, motif parameters not found."
raise ParseIqTreeError(msg)
# parse rate parameters, assign each to a name, and raise an error if not found
if rate_str:
rate_list = [float(value) for value in rate_str.replace(" ", "").split(",")]
tree.params["edge_pars"]["rates"] = dict(
zip(RATE_PARS, rate_list, strict=True),
)
else:
msg = "IQ-TREE output is malformed, rate parameters not found."
raise ParseIqTreeError(msg)
def _parse_lie_model(
tree: PhyloNode,
tree_yaml: dict,
lie_model_name: str,
) -> None:
# parse motif and rate parameters in the tree_yaml for Lie DnaModel
model_fits = tree_yaml.get(lie_model_name, {})
# parse motif parameters, assign each to a name, and raise an error if not found
state_freq_str = model_fits.get("state_freq", "")
if state_freq_str:
state_freq_list = [
float(value) for value in state_freq_str.replace(" ", "").split(",")
]
tree.params[lie_model_name] = {
"mprobs": dict(zip(MOTIF_PARS, state_freq_list, strict=True)),
}
else:
msg = "IQ-TREE output is malformed, motif parameters not found."
raise ParseIqTreeError(msg)
# parse rate parameters, skipping LIE_1_1 (aka JC69) since its rate parameter is constant thus absent
if "model_parameters" in model_fits:
model_parameters = model_fits["model_parameters"]
# convert model parameters to a list of floats if they are a string
if isinstance(model_parameters, str):
tree.params[lie_model_name]["model_parameters"] = [
float(value) for value in model_parameters.replace(" ", "").split(",")
]
else:
# directly use the float
tree.params[lie_model_name]["model_parameters"] = model_parameters
def _parse_unrest_model(tree: PhyloNode, tree_yaml: dict) -> None:
model_fits = tree_yaml.get("ModelUnrest", {})
state_freq_str = model_fits.get("state_freq", "")
rate_str = model_fits.get("rates", "")
# parse state frequencies
if state_freq_str:
state_freq_list = [
float(value) for value in state_freq_str.replace(" ", "").split(",")
]
tree.params["edge_pars"] = {
"mprobs": dict(zip(MOTIF_PARS, state_freq_list, strict=True)),
}
else:
msg = "IQ-TREE output is malformed, motif parameters not found." # pragma: no cover
raise ParseIqTreeError(msg) # pragma: no cover
# parse rates
if rate_str:
rate_list = [float(value) for value in rate_str.replace(" ", "").split(",")]
tree.params["edge_pars"]["rates"] = dict(
zip(RATE_PARS_UNREST, rate_list, strict=True),
)
else:
msg = "IQ-TREE output is malformed, rate parameters not found." # pragma: no cover
raise ParseIqTreeError(msg) # pragma: no cover
def parse_model_parameters(
tree: PhyloNode,
tree_yaml: dict[str, Any],
model: Model,
) -> None:
"""Parse model parameters from the returned yaml format.
Parameters
----------
tree : PhyloNode
The tree to attach model parameters to.
tree_yaml : dict[str, Any]
The yaml result returned from IQ-TREE.
model : Model
The model used.
"""
# parse non-Lie DnaModel parameters
if "ModelDNA" in tree_yaml:
_parse_nonlie_model(tree, tree_yaml)
elif "ModelUnrest" in tree_yaml:
_parse_unrest_model(tree, tree_yaml)
# parse Lie DnaModel parameters, handling various Lie model names
elif key := next(
(key for key in tree_yaml if key.startswith("ModelLieMarkov")),
None,
):
_parse_lie_model(tree, tree_yaml, key)
# for non-Lie models, populate parameters to each branch and
# rename them to mimic PhyloNode
if "edge_pars" in tree.params:
_edge_pars_for_cogent3(tree, model)
iqtree-piqtree-b8a3d6a/src/piqtree/iqtree/_random_tree.py 0000664 0000000 0000000 00000002412 15211731751 0023707 0 ustar 00root root 0000000 0000000 """Python wrappers to random tree generation in the IQ-TREE library."""
from enum import Enum, auto
from _piqtree import iq_random_tree
from cogent3 import make_tree
from cogent3.core.tree import PhyloNode
from piqtree.iqtree._decorator import iqtree_func
from piqtree.util import process_rand_seed_nonzero
iq_random_tree = iqtree_func(iq_random_tree)
class TreeGenMode(Enum):
"""Setting under which to generate a random tree."""
YULE_HARDING = auto()
UNIFORM = auto()
CATERPILLAR = auto()
BALANCED = auto()
BIRTH_DEATH = auto()
STAR_TREE = auto()
def random_tree(
num_taxa: int,
tree_mode: TreeGenMode,
rand_seed: int | None = None,
) -> PhyloNode:
"""Generate a random phylogenetic tree.
Generates a random tree through IQ-TREE.
Parameters
----------
num_taxa : int
The number of taxa per tree.
tree_mode : TreeGenMode
How the tree is generated.
rand_seed : int | None, optional
The random seed - None means no seed is used, by default None.
Returns
-------
PhyloNode
A random phylogenetic tree.
"""
rand_seed = process_rand_seed_nonzero(rand_seed)
newick = iq_random_tree(num_taxa, tree_mode.name, 1, rand_seed).strip()
return make_tree(newick)
iqtree-piqtree-b8a3d6a/src/piqtree/iqtree/_robinson_foulds.py 0000664 0000000 0000000 00000002205 15211731751 0024615 0 ustar 00root root 0000000 0000000 """Python wrappers to RF distances in the IQ-TREE library."""
from collections.abc import Sequence
import numpy as np
from _piqtree import iq_robinson_fould
from cogent3.core.tree import PhyloNode
from piqtree.iqtree._decorator import iqtree_func
from piqtree.util import get_newick
iq_robinson_fould = iqtree_func(iq_robinson_fould)
def robinson_foulds(trees: Sequence[PhyloNode]) -> np.ndarray:
"""Pairwise Robinson-Foulds distance between a sequence of trees.
For the given collection of trees, returns a numpy array containing
the pairwise distances between the trees.
Parameters
----------
trees : Sequence[PhyloNode]
The sequence of trees to calculate the pairwise Robinson-Foulds
distances of.
Returns
-------
np.ndarray
Pairwise Robinson-Foulds distances.
"""
pairwise_distances = np.zeros((len(trees), len(trees)))
for i in range(1, len(trees)):
for j in range(i):
rf = iq_robinson_fould(get_newick(trees[i]), get_newick(trees[j]))
pairwise_distances[i, j] = rf
pairwise_distances[j, i] = rf
return pairwise_distances
iqtree-piqtree-b8a3d6a/src/piqtree/iqtree/_tree.py 0000664 0000000 0000000 00000027220 15211731751 0022353 0 ustar 00root root 0000000 0000000 """Python wrappers to tree searching functions in the IQ-TREE library."""
import statistics
from collections.abc import Callable, Iterable, Sequence
from typing import Any, cast
import numpy as np
import yaml
from _piqtree import iq_build_tree, iq_consensus_tree, iq_fit_tree, iq_nj_tree
from cogent3 import make_tree
from cogent3.core.alignment import Alignment
from cogent3.core.tree import PhyloNode
from cogent3.evolve.fast_distance import DistanceMatrix
from piqtree.exceptions import ParseIqTreeError
from piqtree.iqtree._decorator import iqtree_func
from piqtree.iqtree._parse_tree_parameters import parse_model_parameters
from piqtree.model import Model, make_model
from piqtree.util import get_newick, process_rand_seed_nonzero, validate_other_options
iq_build_tree = iqtree_func(iq_build_tree, hide_files=True)
iq_fit_tree = iqtree_func(iq_fit_tree, hide_files=True)
iq_nj_tree = iqtree_func(iq_nj_tree, hide_files=True)
iq_consensus_tree = iqtree_func(iq_consensus_tree, hide_files=True)
def _rename_iq_tree(tree: PhyloNode, names: Sequence[str]) -> None:
for tip in tree.tips():
tip.name = names[int(tip.name)]
def _tree_equal(node1: PhyloNode, node2: PhyloNode) -> bool:
children_group1 = node1.children
children_group2 = node2.children
if len(children_group1) != len(children_group2):
return False
# recursively check if two PhyloNodes have the same name and branch length, and do the same for their children.
for child1, child2 in zip(children_group1, children_group2, strict=True):
if not _tree_equal(child1, child2):
return False
# handle empty/different internal node names
if children_group1 == []:
return node1.name == node2.name and node1.length == node2.length
return node1.length == node2.length
def _process_tree_yaml(
tree_yaml: dict[str, Any],
names: Sequence[str],
model: Model,
) -> PhyloNode:
newick = tree_yaml["PhyloTree"]["newick"]
tree = make_tree(newick)
candidates = tree_yaml["CandidateSet"]
likelihood = None
for candidate in candidates.values():
candidate_likelihood, candidate_newick = candidate.split(" ")
candidate_tree = make_tree(candidate_newick)
if _tree_equal(candidate_tree, tree):
likelihood = float(candidate_likelihood)
break
if likelihood is None:
msg = "IQ-TREE output is malformed, likelihood not found."
raise ParseIqTreeError(msg)
tree.params["lnL"] = likelihood
parse_model_parameters(tree, tree_yaml, model)
# parse rate model, handling various rate model names
if key := next((key for key in tree_yaml if key.startswith("Rate")), None):
tree.params[key] = tree_yaml[key]
_rename_iq_tree(tree, names)
tree.name_unnamed_nodes()
tree.params["model"] = str(model)
return tree
# Bad options
INVALID_BUILD_TREE_PARAMS = [
"-s", # aln file
"-m", # model selection
"-seed", # seed
"-bb", # bootstrap replicates
"-nt", # threads
"-ntmax", # threads
]
def build_tree(
aln: Alignment,
model: Model | str,
rand_seed: int | None = None,
bootstrap_replicates: int | None = None,
num_threads: int | None = None,
other_options: str = "",
) -> PhyloNode:
"""Reconstruct a phylogenetic tree.
Given a sequence alignment, uses IQ-TREE to reconstruct a phylogenetic tree.
Parameters
----------
aln : Alignment
The sequence alignment.
model : Model | str
The substitution model with base frequencies and rate heterogeneity.
rand_seed : int | None, optional
The random seed - None means no seed is used, by default None.
bootstrap_replicates : int | None, optional
The number of bootstrap replicates to perform, by default None.
If 0 is provided, then no bootstrapping is performed.
At least 1000 is required to perform bootstrapping.
num_threads: int | None, optional
Number of threads for IQ-TREE to use, by default None (single-threaded).
If 0 is specified, IQ-TREE attempts to find the optimal number of threads.
other_options: str, optional
Additional command line options for IQ-TREE.
Returns
-------
PhyloNode
The IQ-TREE maximum likelihood tree from the given alignment.
"""
validate_other_options(other_options, INVALID_BUILD_TREE_PARAMS)
if isinstance(model, str):
model = make_model(model)
rand_seed = process_rand_seed_nonzero(rand_seed)
if bootstrap_replicates is None:
bootstrap_replicates = 0
if num_threads is None:
num_threads = 1
names = aln.names
seqs = [str(seq) for seq in aln.iter_seqs(names)]
yaml_result = yaml.safe_load(
iq_build_tree(
names,
seqs,
str(model),
rand_seed,
bootstrap_replicates,
num_threads,
other_options,
),
)
return _process_tree_yaml(yaml_result, names, model)
INVALID_FIT_TREE_PARAMS = [
"-s", # aln file
"-t", # tree specification
"-te", # tree specification
"-m", # model selection
"-nt", # threads
"-ntmax", # threads
"-blfix", # whether to fix current branch lengths
]
def fit_tree(
aln: Alignment,
tree: PhyloNode,
model: Model | str,
num_threads: int | None = None,
other_options: str = "",
*,
bl_fixed: bool = False,
) -> PhyloNode:
"""Fit branch lengths and likelihood for a tree.
Given a sequence alignment and a fixed topology,
uses IQ-TREE to fit branch lengths to the tree.
Parameters
----------
aln : Alignment
The sequence alignment.
tree : PhyloNode
The topology to fit branch lengths to.
model : Model | str
The substitution model with base frequencies and rate heterogeneity.
num_threads: int | None, optional
Number of threads for IQ-TREE to use, by default None (single-threaded).
If 0 is specified, IQ-TREE attempts to find the optimal number of threads.
bl_fixed: bool, optional
If True, evaluates likelihood using the provided branch lengths on the tree.
Branch lengths will be treated as constant in this case, with any unspecified
branch lengths still being optimised. Otherwise if False, branch lengths are
fitted to the tree whether provided or not. By default False.
other_options: str, optional
Additional command line options for IQ-TREE.
Returns
-------
PhyloNode
A phylogenetic tree with the same given topology fitted with branch lengths.
"""
validate_other_options(other_options, INVALID_FIT_TREE_PARAMS)
if isinstance(model, str):
model = make_model(model)
if num_threads is None:
num_threads = 1
names = aln.names
seqs = [str(seq) for seq in aln.iter_seqs(names)]
newick = get_newick(tree)
yaml_result = yaml.safe_load(
iq_fit_tree(
names,
seqs,
str(model),
newick,
bl_fixed,
0,
num_threads,
other_options,
),
)
return _process_tree_yaml(yaml_result, names, model)
def nj_tree(
pairwise_distances: DistanceMatrix,
*,
allow_negative: bool = False,
) -> PhyloNode:
"""Construct a neighbour joining tree from a pairwise distance matrix.
Parameters
----------
pairwise_distances : DistanceMatrix
Pairwise distances to construct neighbour joining tree from.
allow_negative : bool, optional
Whether to allow negative branch lengths in the output.
Coerces to 0 if not allowed, by default False.
Returns
-------
PhyloNode
The neighbour joining tree.
See Also
--------
jc_distances : construction of pairwise JC distance matrix from alignment.
"""
if np.isnan(pairwise_distances.array).any():
msg = "The pairwise distance matrix cannot contain NaN values."
raise ValueError(msg)
newick_tree = iq_nj_tree(
pairwise_distances.keys(),
np.array(pairwise_distances).flatten(),
)
tree = make_tree(newick_tree)
if not allow_negative:
for node in tree.preorder(include_self=False):
node.length = max(cast("float", node.length), 0)
return tree
def _all_same_taxa_set(trees: Iterable[PhyloNode]) -> bool:
tree_it = iter(trees)
try:
taxa_set = set(next(tree_it).get_tip_names())
except StopIteration:
return True
return all(taxa_set == set(tree.get_tip_names()) for tree in tree_it)
_SUPPORT_AGGREGATES: dict[str, Callable[[Iterable[float]], float]] = {
"mean": statistics.mean,
"max": max,
"min": min,
}
def _transfer_support(
consensus: PhyloNode,
trees: Iterable[PhyloNode],
aggregate: Callable[[Iterable[float]], float],
) -> None:
"""Set each consensus clade's support from the input trees' support for the same split."""
taxa = frozenset(consensus.get_tip_names())
reference = min(taxa)
def split_key(node: PhyloNode) -> frozenset[str]:
side = frozenset(node.get_tip_names())
return taxa - side if reference in side else side
lookup: dict[frozenset[str], list[float]] = {}
for tree in trees:
for node in tree.postorder():
if node.is_tip() or node.is_root():
continue
support = getattr(node, "support", None)
if support is None:
continue
lookup.setdefault(split_key(node), []).append(support)
for node in consensus.postorder():
if node.is_tip() or node.is_root():
continue
values = lookup.get(split_key(node))
if values:
node.support = aggregate(values)
def consensus_tree(
trees: Iterable[PhyloNode],
*,
min_support: float = 0.5,
support_aggregate: str | None = "mean",
) -> PhyloNode:
"""Build a consensus tree, defaults to majority-rule consensus tree.
The min_support parameter represents the proportion of trees a clade
must appear in to be in the resulting consensus tree.
If min_support is 1.0, computes the strict consensus tree.
If min_support is 0.0, computes the extended majority-rule consensus tree.
By default the input trees' own support values are transferred onto
matching consensus clades.
Parameters
----------
trees : Iterable[PhyloNode]
The trees to form a consensus tree from.
min_support : float, optional
The minimum support for a clade to appear
in the consensus tree, by default 0.5.
support_aggregate : str | None, optional
How to combine the input trees' support for a shared clade.
One of "mean" (default), "max", "min". If None, the consensus'
own clade-frequency support is kept and the input support ignored.
Returns
-------
PhyloNode
The constructed consensus tree.
"""
if not 0 <= min_support <= 1:
msg = f"Only min support values in the range 0 <= value <= 1 are supported, got {min_support}"
raise ValueError(msg)
if support_aggregate is not None and support_aggregate not in _SUPPORT_AGGREGATES:
allowed = ", ".join(sorted(_SUPPORT_AGGREGATES))
msg = f"support_aggregate must be one of {allowed} or None, got {support_aggregate!r}"
raise ValueError(msg)
trees = list(trees)
if not _all_same_taxa_set(trees):
msg = "Trees must be on same taxa set."
raise ValueError(msg)
newick_trees = [get_newick(tree) for tree in trees]
consensus = make_tree(iq_consensus_tree(newick_trees, min_support))
if support_aggregate is not None:
_transfer_support(consensus, trees, _SUPPORT_AGGREGATES[support_aggregate])
return consensus
iqtree-piqtree-b8a3d6a/src/piqtree/model/ 0000775 0000000 0000000 00000000000 15211731751 0020507 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/src/piqtree/model/__init__.py 0000664 0000000 0000000 00000001721 15211731751 0022621 0 ustar 00root root 0000000 0000000 """Models available in IQ-TREE."""
from ._freq_type import CustomBaseFreq, FreqType, get_freq_type
from ._model import Model, make_model
from ._options import available_freq_type, available_models, available_rate_type
from ._rate_type import (
DiscreteGammaModel,
FreeRateModel,
RateModel,
RateType,
get_rate_type,
)
from ._substitution_model import (
AaModel,
LieModel,
LieModelInstance,
StandardDnaModel,
StandardDnaModelInstance,
SubstitutionModel,
get_substitution_model,
)
__all__ = [
"AaModel",
"CustomBaseFreq",
"DiscreteGammaModel",
"FreeRateModel",
"FreqType",
"LieModel",
"LieModelInstance",
"Model",
"RateModel",
"RateType",
"StandardDnaModel",
"StandardDnaModelInstance",
"SubstitutionModel",
"available_freq_type",
"available_models",
"available_rate_type",
"get_freq_type",
"get_rate_type",
"get_substitution_model",
"make_model",
]
iqtree-piqtree-b8a3d6a/src/piqtree/model/_freq_type.py 0000664 0000000 0000000 00000007552 15211731751 0023227 0 ustar 00root root 0000000 0000000 import contextlib
import functools
from collections.abc import Sequence
from enum import Enum, unique
@unique
class FreqType(Enum):
"""Types of base frequencies."""
F = "F"
FO = "FO"
FQ = "FQ"
@staticmethod
@functools.cache
def _descriptions() -> dict["FreqType", str]:
return {
FreqType.F: "Empirical state frequency observed from the data.",
FreqType.FO: "State frequency optimized by maximum-likelihood from the data. Note that this is with letter-O and not digit-0.",
FreqType.FQ: "Equal state frequency.",
}
@property
def description(self) -> str:
"""The description of the FreqType.
Returns
-------
str
The description of the FreqType.
"""
return self._descriptions()[self]
def iqtree_str(self) -> str:
return self.value
class CustomBaseFreq:
def __init__(self, frequencies: Sequence[float]) -> None:
"""Create a custom base frequency specification.
For DNA models the order of the frequencies is:
A C G T
For AA models the order of the frequencies is:
| A | R | N | D | C | Q | E | G | H | I | L | K | M | F | P | S | T | W | Y | V |
|-----|-----|-----|-----|-----|----|----|----|----|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| Ala | Arg | Asn | Asp | Cys | Gln| Glu| Gly| His| Ile| Leu | Lys | Met | Phe | Pro | Ser | Thr | Trp | Tyr | Val |
IQ-TREE normalises the frequencies if they do not sum to one.
Parameters
----------
frequencies : Sequence[float]
The fixed base frequencies.
"""
self.frequencies = frequencies
if len(self.frequencies) not in (4, 20):
msg = f"Expected either 4 frequencies for DNA model or 20 for AA model but got {len(self.frequencies)}"
raise ValueError(msg)
@property
def description(self) -> str:
return "Fixed base frequencies."
def iqtree_str(self) -> str:
return f"F{{{','.join(map(str, self.frequencies))}}}"
@classmethod
def from_str(cls, base_freq_str: str) -> "CustomBaseFreq":
if len(base_freq_str) == 0:
msg = "An empty string does not specify base frequencies."
raise ValueError(msg)
if base_freq_str[0] != "F":
msg = f"A CustomBaseFreq must start with F but got {base_freq_str!r}."
raise ValueError(msg)
if base_freq_str[1] != "{" or base_freq_str[-1] != "}":
msg = f"A CustomBaseFreq must be parameterised with {{}} but got {base_freq_str!r}."
raise ValueError(msg)
try:
frequencies = tuple(
float(val.strip()) for val in base_freq_str[2:-1].split(",")
)
except ValueError:
msg = f"Unable to parse parameters for CustomBaseFreq: {base_freq_str!r}."
raise ValueError(msg) from None
return cls(frequencies)
def get_freq_type(
base_freq_str: str | FreqType | CustomBaseFreq,
) -> FreqType | CustomBaseFreq:
"""Return the FreqType enum for a given name.
Parameters
----------
base_freq_str : str | FreqType | CustomBaseFreq
The string form of the frequency type.
Returns
-------
FreqType | CustomBaseFreq
The resolved FreqType Enum or CustomBaseFreq.
Raises
------
ValueError
If the FreqType name cannot be resolved.
"""
if isinstance(base_freq_str, (FreqType, CustomBaseFreq)):
return base_freq_str
shortened = base_freq_str.lstrip("+")
with contextlib.suppress(KeyError):
return FreqType[shortened]
if shortened.startswith("F{"):
return CustomBaseFreq.from_str(shortened)
msg = f"Unknown state frequency type: {base_freq_str!r}."
raise ValueError(msg)
iqtree-piqtree-b8a3d6a/src/piqtree/model/_model.py 0000664 0000000 0000000 00000012757 15211731751 0022334 0 ustar 00root root 0000000 0000000 from piqtree.model._freq_type import CustomBaseFreq, FreqType, get_freq_type
from piqtree.model._rate_type import RateModel, get_rate_type
from piqtree.model._substitution_model import SubstitutionModel, get_substitution_model
class Model:
"""Specification for substitution models.
Stores the substitution model with base frequency settings.
"""
def __init__(
self,
submod_type: str | SubstitutionModel,
freq_type: str | FreqType | CustomBaseFreq | None = None,
rate_model: str | RateModel | None = None,
*,
invariable_sites: bool | float = False,
) -> None:
"""Construct Model class.
Parameters
----------
submod_type : str | SubstitutionModel
The substitution model to use.
freq_type : str | FreqType | CustomBaseFreq | None, optional
State frequency specification, by default None (defaults
to empirical base frequencies if not specified by model).
rate_model : str | RateModel | None, optional
Rate heterogeneity across sites model, by default None
(no Gamma and no FreeRate).
invariable_sites : bool | float, optional
Invariable sites, by default False.
If a float in the range [0,1), specifies the proportion of invariable sites.
"""
self.submod_type = get_substitution_model(submod_type)
self.freq_type = get_freq_type(freq_type) if freq_type else None
self.rate_type = (
get_rate_type(rate_model, invariable_sites=invariable_sites)
if rate_model is not None or invariable_sites
else None
)
def __hash__(self) -> int:
return hash(str(self))
def __repr__(self) -> str:
attrs = [
f"submod_type={self.submod_type.iqtree_str()}",
f"freq_type={getattr(self.freq_type, 'name', None)}",
f"rate_type={getattr(self.rate_type, 'name', None)}",
]
return f"Model({', '.join(attrs)})"
def __str__(self) -> str:
"""Convert the model into the IQ-TREE representation.
Returns
-------
str
The IQ-TREE representation of the model.
"""
iqtree_extra_args = (
x for x in (self.freq_type, self.rate_type) if x is not None
)
return "+".join(x.iqtree_str() for x in [self.submod_type, *iqtree_extra_args])
@property
def rate_model(self) -> RateModel | None:
"""The RateModel used, if one is chosen.
Returns
-------
RateModel | None
The RateModel used by the Model.
"""
return self.rate_type.rate_model if self.rate_type else None
@property
def invariable_sites(self) -> bool:
"""Whether invariable sites are used.
Returns
-------
bool
True if invariable sites are used by the model, False otherwise.
"""
return self.rate_type.invariable_sites if self.rate_type else False
@property
def proportion_invariable_sites(self) -> float | None:
"""The proportion of invariable sites if specified.
Returns
-------
float | None
The proportion of invariable sites if specified, None otherwise.
"""
return self.rate_type.proportion_invariable if self.rate_type else None
def make_model(iqtree_str: str) -> Model:
"""Convert an IQ-TREE model specification into a Model class.
Parameters
----------
iqtree_str : str
The IQ-TREE model string.
Returns
-------
Model
The equivalent Model class.
"""
if "+" not in iqtree_str:
return Model(iqtree_str)
sub_mod_str, components = iqtree_str.split("+", maxsplit=1)
freq_type = None
invariable_sites: float | bool | None = None
rate_model = None
for component in components.split("+"):
if component.startswith("F"):
if freq_type is not None:
msg = f"Model {iqtree_str!r} contains multiple base frequency specifications."
raise ValueError(msg)
freq_type = component
elif component.startswith("I"):
if invariable_sites is not None:
msg = f"Model {iqtree_str!r} contains multiple specifications for invariable sites."
raise ValueError(msg)
invariable_sites = _parse_invariable_sites(component)
elif component.startswith(("G", "R")):
if rate_model is not None:
msg = f"Model {iqtree_str!r} contains multiple rate heterogeneity specifications."
raise ValueError(msg)
rate_model = component
else:
msg = f"Model {iqtree_str!r} contains unexpected component."
raise ValueError(msg)
if invariable_sites is None:
invariable_sites = False
return Model(sub_mod_str, freq_type, rate_model, invariable_sites=invariable_sites)
def _parse_invariable_sites(component: str) -> bool | float:
# Assumes that component starts with "I"
remainder = component[1:]
if len(remainder) == 0:
return True
if remainder[0] != "{" or remainder[-1] != "}":
msg = f"Invalid specification for proportion of invariable sites, got '{component}'."
raise ValueError(msg)
number_part = remainder[1:-1]
try:
return float(number_part)
except ValueError:
msg = f"Failed to read proportion of invariable sites, got '{component}'"
raise ValueError(msg) from None
iqtree-piqtree-b8a3d6a/src/piqtree/model/_options.py 0000664 0000000 0000000 00000006126 15211731751 0022720 0 ustar 00root root 0000000 0000000 """Convenience functions for showing user facing options and their descriptions."""
import functools
from typing import Literal
from cogent3.core.table import Table, make_table
from piqtree.model._freq_type import FreqType
from piqtree.model._rate_type import ALL_BASE_RATE_TYPES, get_description
from piqtree.model._substitution_model import (
ALL_MODELS_CLASSES,
AaModel,
LieModel,
StandardDnaModel,
SubstitutionModel,
)
@functools.cache
def _make_models(
model_classes: type[SubstitutionModel] | tuple[type[SubstitutionModel], ...],
) -> dict[str, list[str]]:
data: dict[str, list[str]] = {
"Model Type": [],
"Abbreviation": [],
"Description": [],
}
if model_classes == SubstitutionModel:
model_classes = ALL_MODELS_CLASSES
if isinstance(model_classes, type) and issubclass(model_classes, SubstitutionModel):
model_classes = (model_classes,)
for model_class in model_classes:
for model in model_class.iter_available_models():
data["Model Type"].append(model.model_type())
data["Abbreviation"].append(model.iqtree_str())
data["Description"].append(model.description)
return data
def available_models(
model_type: Literal["dna", "protein"] | None = None,
*,
show_all: bool = True,
) -> Table:
"""Return a table showing available substitution models.
Parameters
----------
model_type : Literal["dna", "protein"] | None, optional
The models to fetch, by default None (all models).
show_all : bool, optional
If True, the representation of the table shows all records, by default True.
Returns
-------
Table
Table with all available models.
"""
template = "Available {}substitution models"
if model_type == "dna":
table = make_table(
data=_make_models((StandardDnaModel, LieModel)),
title=template.format("nucleotide "),
)
elif model_type == "protein":
table = make_table(
data=_make_models(AaModel),
title=template.format("protein "),
)
else:
table = make_table(
data=_make_models(SubstitutionModel),
title=template.format(""),
)
if show_all:
table.set_repr_policy(head=table.shape[0])
return table
def available_freq_type() -> Table:
"""Return a table showing available freq type options."""
data: dict[str, list[str]] = {"Freq Type": [], "Description": []}
for freq_type in FreqType:
data["Freq Type"].append(freq_type.value)
data["Description"].append(freq_type.description)
return make_table(data=data, title="Available frequency types")
def available_rate_type() -> Table:
"""Return a table showing available rate type options."""
data: dict[str, list[str]] = {"Rate Type": [], "Description": []}
for rate_type in ALL_BASE_RATE_TYPES:
data["Rate Type"].append(rate_type.iqtree_str())
data["Description"].append(get_description(rate_type))
return make_table(data=data, title="Available rate heterogeneity types")
iqtree-piqtree-b8a3d6a/src/piqtree/model/_rate_type.py 0000664 0000000 0000000 00000027561 15211731751 0023227 0 ustar 00root root 0000000 0000000 import itertools
from abc import ABC, abstractmethod
from collections.abc import Sequence
class RateModel(ABC):
"""Base class for rate models."""
@abstractmethod
def iqtree_str(self) -> str:
"""Convert to an iqtree settings string.
Returns
-------
str
String parsable by IQ-TREE for the rate heterogeneity model.
"""
class RateType:
def __init__(
self,
*,
invariable_sites: bool | float = False,
rate_model: RateModel | None = None,
) -> None:
"""Rate heterogeneity across sites model.
Parameters
----------
invariable_sites : bool | float, optional
Invariable sites, by default False.
If a float in the range [0,1), specifies the proportion of invariable sites.
rate_model : RateModel | None, optional
Discrete Gamma Model or FreeRate Model, by default None.
"""
if not isinstance(invariable_sites, bool):
if not (0 <= invariable_sites < 1):
msg = "The proportion of invariant sites must be in the range [0,1)"
raise ValueError(msg)
self.invariable_sites = True
self.proportion_invariable: float | None = invariable_sites
else:
self.invariable_sites = invariable_sites
self.proportion_invariable = None
self.rate_model = rate_model
def iqtree_str(self) -> str:
"""Convert to an iqtree settings string.
Returns
-------
str
String parsable by IQ-TREE for the rate heterogeneity model.
"""
rate_type_str = "I" if self.invariable_sites else ""
if self.proportion_invariable is not None:
rate_type_str += f"{{{self.proportion_invariable}}}"
if self.rate_model is None:
return rate_type_str
# Invariant sites and model need to be joined by a '+'
if self.invariable_sites:
rate_type_str += "+"
return rate_type_str + self.rate_model.iqtree_str()
@property
def name(self) -> str:
return self.iqtree_str()
class DiscreteGammaModel(RateModel):
def __init__(
self,
rate_categories: int | None = None,
alpha: float | None = None,
) -> None:
"""Discrete Gamma Model.
Parameters
----------
rate_categories : int | None, optional
The number of rate categories, by default None (uses 4).
alpha : float | None, optional
The Gamma shape parameter - fixed if not None, by default None
References
----------
.. [1] Yang, Ziheng. "Maximum likelihood phylogenetic estimation from
DNA sequences with variable rates over sites: approximate methods."
Journal of Molecular evolution 39 (1994): 306-314.
"""
self.rate_categories = rate_categories
self.alpha = alpha
def iqtree_str(self) -> str:
out_str = "G"
if self.rate_categories is not None:
out_str += str(self.rate_categories)
if self.alpha is not None:
out_str += f"{{{self.alpha}}}"
return out_str
@classmethod
def from_str(cls, rate_model_str: str) -> "DiscreteGammaModel":
if len(rate_model_str) == 0:
msg = "An empty string is not a DiscreteGammaModel."
raise ValueError(msg)
if rate_model_str[0] != "G":
msg = f"A DiscreteGammaModel must start with G but got {rate_model_str!r}."
raise ValueError(msg)
if len(rate_model_str) == 1:
return cls()
rate_categories = _parse_rate_categories(rate_model_str)
parameter_start = rate_model_str.find("{")
# If there is no parameterisation
if parameter_start == -1:
return cls(rate_categories=rate_categories)
if not rate_model_str.endswith("}"):
msg = f"Missing end bracket for parameterisation {rate_model_str!r}"
raise ValueError(msg)
try:
alpha = float(rate_model_str[parameter_start + 1 : -1])
except ValueError:
msg = f"Parameterisation of Discrete Gamma Model is not a number {rate_model_str!r}"
raise ValueError(msg) from None
return cls(rate_categories=rate_categories, alpha=alpha)
class FreeRateModel(RateModel):
default_rate_categories = 4
def __init__(
self,
rate_categories: int | None = None,
weights: Sequence[float] | None = None,
rates: Sequence[float] | None = None,
) -> None:
"""FreeRate Model.
Parameters
----------
rate_categories : int | None, optional
The number of rate categories, by default None (uses 4).
weights : Sequence[float] | None, optional
The weights for each rate category, by default None
rates : Sequence[float] | None, optional
The rates for each rate category, by default None
References
----------
.. [1] Yang, Ziheng. "A space-time process model for the evolution of
DNA sequences." Genetics 139.2 (1995): 993-1005.
.. [2] Soubrier, Julien, et al. "The influence of rate heterogeneity
among sites on the time dependence of molecular rates." Molecular
biology and evolution 29.11 (2012): 3345-3358.
"""
self.rate_categories = rate_categories
if (weights is None) ^ (rates is None):
msg = "Must specify both rates and weights or neither."
raise ValueError(msg)
check_rate_categories = (
rate_categories
if rate_categories is not None
else FreeRateModel.default_rate_categories
)
if weights is None or rates is None:
self.weights = None
self.rates = None
else:
if (
len(weights) != check_rate_categories
or len(rates) != check_rate_categories
):
msg = f"Expected {check_rate_categories} rates and weights but got {len(weights)} and {len(rates)} respectively."
raise ValueError(msg)
self.weights = list(weights)
self.rates = list(rates)
def iqtree_str(self) -> str:
base = "R" if self.rate_categories is None else f"R{self.rate_categories}"
if self.weights is None or self.rates is None:
return base
weights_and_rates = itertools.chain.from_iterable(
zip(self.weights, self.rates, strict=True),
)
return f"{base}{{{','.join(str(val) for val in weights_and_rates)}}}"
@classmethod
def from_str(cls, rate_model_str: str) -> "FreeRateModel":
if len(rate_model_str) == 0:
msg = "An empty string is not a FreeRateModel."
raise ValueError(msg)
if rate_model_str[0] != "R":
msg = f"A FreeRateModel must start with R but got {rate_model_str!r}."
raise ValueError(msg)
if len(rate_model_str) == 1:
return cls()
rate_categories = _parse_rate_categories(rate_model_str)
parameter_start = rate_model_str.find("{")
# If there is no parameterisation
if parameter_start == -1:
return cls(rate_categories=rate_categories)
if not rate_model_str.endswith("}"):
msg = f"Missing end bracket for parameterisation {rate_model_str!r}"
raise ValueError(msg)
try:
weights_and_rates = [
float(part.strip())
for part in rate_model_str[parameter_start + 1 : -1].split(",")
]
except ValueError:
msg = f"Unable to parse parameters for FreeRateModel: {rate_model_str!r}."
raise ValueError(msg) from None
expected_params = 2 * (
cls.default_rate_categories if rate_categories is None else rate_categories
)
if len(weights_and_rates) != expected_params:
msg = f"Expected {expected_params} parameters but got {len(weights_and_rates)}."
raise ValueError(msg)
weights = weights_and_rates[::2]
rates = weights_and_rates[1::2]
return cls(rate_categories=rate_categories, weights=weights, rates=rates)
ALL_BASE_RATE_TYPES = [
RateType(),
RateType(invariable_sites=True),
RateType(rate_model=DiscreteGammaModel()),
RateType(invariable_sites=True, rate_model=DiscreteGammaModel()),
RateType(rate_model=FreeRateModel()),
RateType(invariable_sites=True, rate_model=FreeRateModel()),
]
_BASE_RATE_TYPE_DESCRIPTIONS = {
RateType().iqtree_str(): "no invariable sites, no rate heterogeneity model.",
RateType(
invariable_sites=True,
).iqtree_str(): "allowing for a proportion of invariable sites.",
RateType(
rate_model=DiscreteGammaModel(),
).iqtree_str(): "discrete Gamma model (Yang, 1994) with default 4 rate categories. The number of categories can be changed with e.g. +G8.",
RateType(
invariable_sites=True,
rate_model=DiscreteGammaModel(),
).iqtree_str(): "invariable site plus discrete Gamma model (Gu et al., 1995).",
RateType(
rate_model=FreeRateModel(),
).iqtree_str(): "FreeRate model (Yang, 1995; Soubrier et al., 2012) that generalizes the +G model by relaxing the assumption of Gamma-distributed rates. The number of categories can be specified with e.g. +R6 (default 4 categories if not specified). The FreeRate model typically fits data better than the +G model and is recommended for analysis of large data sets.",
RateType(
invariable_sites=True,
rate_model=FreeRateModel(),
).iqtree_str(): "invariable site plus FreeRate model.",
}
def get_description(rate_type: RateType) -> str:
rate_type_str = "".join(c for c in rate_type.iqtree_str() if not c.isdigit())
return _BASE_RATE_TYPE_DESCRIPTIONS[rate_type_str]
def get_rate_type(
rate_model: str | RateModel | None = None,
*,
invariable_sites: bool | float = False,
) -> RateType:
"""Make a RateType from a chosen rate model and invariable sites.
Parameters
----------
rate_model : str | RateModel | None, optional
The chosen rate model, by default None.
invariable_sites : bool | float, optional
Invariable sites, by default False.
If a float in the range [0,1), specifies the proportion of invariable sites.
Returns
-------
RateType
RateType generated from the rate model with invariable sites.
"""
if isinstance(rate_model, RateModel):
return RateType(rate_model=rate_model, invariable_sites=invariable_sites)
if rate_model is None:
return RateType(invariable_sites=invariable_sites)
if not isinstance(rate_model, str):
msg = f"Unexpected type for rate_model: {type(rate_model)}"
raise TypeError(msg)
stripped_rate_model = rate_model.lstrip("+")
rate_model_char = stripped_rate_model[0]
if rate_model_char == "G":
rate_model = DiscreteGammaModel.from_str(stripped_rate_model)
elif rate_model_char == "R":
rate_model = FreeRateModel.from_str(stripped_rate_model)
else:
msg = f"Unexpected value for rate_model {rate_model!r}"
raise ValueError(msg)
return RateType(
rate_model=rate_model,
invariable_sites=invariable_sites,
)
def _parse_rate_categories(rate_model_str: str) -> int | None:
# Assume that the rate model str starts with a G or an R
parameters_start = rate_model_str.find("{")
# There is no {} style parameterisation
if parameters_start == -1:
categories_str = rate_model_str[1:]
else:
categories_str = rate_model_str[1:parameters_start]
if len(categories_str) == 0:
return None
try:
return int(categories_str)
except ValueError:
msg = f"Invalid specification for rate categories {rate_model_str!r}"
raise ValueError(msg) from None
iqtree-piqtree-b8a3d6a/src/piqtree/model/_substitution_model.py 0000664 0000000 0000000 00000054547 15211731751 0025173 0 ustar 00root root 0000000 0000000 import contextlib
import functools
from collections.abc import Sequence
from dataclasses import dataclass
from enum import Enum, unique
from typing import ClassVar, Literal, cast
class SubstitutionModel:
"""Base class for substitution models."""
@staticmethod
def model_type() -> str:
"""Get the type of the model.
Returns
-------
str
The type of the model.
"""
raise NotImplementedError
def iqtree_str(self) -> str:
"""Get the IQ-TREE representation of the model.
Returns
-------
str
The IQ-TREE representation of the model.
"""
raise NotImplementedError
def get_moltype(self) -> Literal["dna", "protein"]:
"""The model's moltype string for cogent3
Returns
-------
str
The model's moltype string.
"""
raise NotImplementedError
@property
def base_model(self) -> "SubstitutionModel":
"""Get the base model enum used by the model.
Returns
-------
SubstitutionModel
The enum of the model.
"""
raise NotImplementedError
@staticmethod
def iter_available_models() -> Sequence["SubstitutionModel"]:
"""Get the available models for the model type.
Returns
-------
Sequence[SubstitutionModel]
The available models.
"""
raise NotImplementedError
@staticmethod
def num_available_models() -> int:
"""Get the number of available models for the model type.
Returns
-------
int
The number of available models.
"""
raise NotImplementedError
@property
def description(self) -> str:
"""The model's description.
Returns
-------
str
The model's description.
"""
raise NotImplementedError
@dataclass(frozen=True)
class StandardDnaModelInstance(SubstitutionModel):
dna_model: "StandardDnaModel"
model_params: Sequence[float] | None = None
@staticmethod
def model_type() -> str:
return "nucleotide"
def iqtree_str(self) -> str:
params = (
f"{{{','.join(map(str, self.model_params))}}}" if self.model_params else ""
)
return f"{self.dna_model.value}{params}"
def get_moltype(self) -> Literal["dna", "protein"]:
return "dna"
@property
def base_model(self) -> "StandardDnaModel":
return self.dna_model
@staticmethod
def iter_available_models() -> Sequence["StandardDnaModel"]:
return StandardDnaModel.iter_available_models()
@staticmethod
def num_available_models() -> int:
return StandardDnaModel.num_available_models()
@property
def description(self) -> str:
return StandardDnaModel._descriptions()[self.dna_model] # noqa: SLF001
@unique
class StandardDnaModel(SubstitutionModel, Enum):
"""Standard DNA substitution models."""
JC = "JC"
JC69 = "JC69"
F81 = "F81"
K80 = "K80"
K2P = "K2P"
HKY = "HKY"
HKY85 = "HKY85"
TN = "TN"
TN93 = "TN93"
TNe = "TNe"
K81 = "K81"
K3P = "K3P"
K81u = "K81u"
TPM2 = "TPM2"
TPM2u = "TPM2u"
TPM3 = "TPM3"
TPM3u = "TPM3u"
TIM = "TIM"
TIMe = "TIMe"
TIM2 = "TIM2"
TIM2e = "TIM2e"
TIM3 = "TIM3"
TIM3e = "TIM3e"
TVM = "TVM"
TVMe = "TVMe"
SYM = "SYM"
GTR = "GTR"
STRSYM = "STRSYM"
UNREST = "UNREST"
def __call__(
self,
model_params: Sequence[float] | None = None,
) -> StandardDnaModelInstance:
"""Parameterise the model.
If parameters are not supplied, the model is not parameterised.
Parameters
----------
model_params : Sequence[float] | None, optional
The relative substitution rates, by default None
Returns
-------
StandardDnaModelInstance
The parameterised model.
"""
return StandardDnaModelInstance(self, model_params)
@staticmethod
def model_type() -> str:
return "nucleotide"
def iqtree_str(self) -> str:
return self.value
def get_moltype(self) -> Literal["dna", "protein"]:
return "dna"
@property
def base_model(self) -> "StandardDnaModel":
return self
@staticmethod
def iter_available_models() -> Sequence["StandardDnaModel"]:
return list(StandardDnaModel)
@staticmethod
def num_available_models() -> int:
return len(StandardDnaModel)
@property
def description(self) -> str:
return self._descriptions()[self]
@staticmethod
@functools.cache
def _descriptions() -> dict[SubstitutionModel, str]:
return {
StandardDnaModel.JC: "Equal substitution rates and equal base frequencies (Jukes and Cantor, 1969).",
StandardDnaModel.JC69: "Equal substitution rates and equal base frequencies (Jukes and Cantor, 1969).",
StandardDnaModel.F81: "Equal rates but unequal base freq. (Felsenstein, 1981).",
StandardDnaModel.K80: "Unequal transition/transversion rates and equal base freq. (Kimura, 1980).",
StandardDnaModel.K2P: "Unequal transition/transversion rates and equal base freq. (Kimura, 1980).",
StandardDnaModel.HKY: "Unequal transition/transversion rates and unequal base freq. (Hasegawa, Kishino and Yano, 1985).",
StandardDnaModel.HKY85: "Unequal transition/transversion rates and unequal base freq. (Hasegawa, Kishino and Yano, 1985).",
StandardDnaModel.TN: "Like HKY but unequal purine/pyrimidine rates (Tamura and Nei, 1993).",
StandardDnaModel.TN93: "Like HKY but unequal purine/pyrimidine rates (Tamura and Nei, 1993).",
StandardDnaModel.TNe: "Like TN but equal base freq.",
StandardDnaModel.K81: "Three substitution types model and equal base freq. (Kimura, 1981).",
StandardDnaModel.K3P: "Three substitution types model and equal base freq. (Kimura, 1981).",
StandardDnaModel.K81u: "Like K81 but unequal base freq.",
StandardDnaModel.TPM2: "AC=AT, AG=CT, CG=GT and equal base freq.",
StandardDnaModel.TPM2u: "Like TPM2 but unequal base freq.",
StandardDnaModel.TPM3: "AC=CG, AG=CT, AT=GT and equal base freq.",
StandardDnaModel.TPM3u: "Like TPM3 but unequal base freq.",
StandardDnaModel.TIM: "Transition model, AC=GT, AT=CG and unequal base freq.",
StandardDnaModel.TIMe: "Like TIM but equal base freq.",
StandardDnaModel.TIM2: "AC=AT, CG=GT and unequal base freq.",
StandardDnaModel.TIM2e: "Like TIM2 but equal base freq.",
StandardDnaModel.TIM3: "AC=CG, AT=GT and unequal base freq.",
StandardDnaModel.TIM3e: "Like TIM3 but equal base freq.",
StandardDnaModel.TVM: "Transversion model, AG=CT and unequal base freq.",
StandardDnaModel.TVMe: "Like TVM but equal base freq.",
StandardDnaModel.SYM: "Symmetric model with unequal rates but equal base freq. (Zharkikh, 1994).",
StandardDnaModel.GTR: "General time reversible model with unequal rates and unequal base freq. (Tavare, 1986).",
StandardDnaModel.STRSYM: "Strand-symmetric model (Bielawski and Gold, 2002).",
StandardDnaModel.UNREST: "Unrestricted model.",
}
lie_model_pairing = Literal["RY", "WS", "MK"]
@dataclass(frozen=True)
class LieModelInstance(SubstitutionModel):
lie_model: "LieModel"
pairing: lie_model_pairing | None = None
model_params: Sequence[float] | None = None
valid_pairings: ClassVar[
tuple[lie_model_pairing, lie_model_pairing, lie_model_pairing]
] = "RY", "WS", "MK"
pairing_descriptions: ClassVar[dict[lie_model_pairing, str]] = {
"RY": "purine-pyrimidine pairing (default).",
"WS": "weak-strong pairing.",
"MK": "aMino-Keto pairing",
}
def __post_init__(self) -> None:
if (
self.pairing is not None
and self.pairing not in LieModelInstance.valid_pairings
):
msg = f"Invalid Lie Model pairing prefix: '{self.pairing}'"
raise ValueError(msg)
@staticmethod
def model_type() -> str:
return "nucleotide"
def iqtree_str(self) -> str:
prefix = self.pairing or ""
params = (
f"{{{','.join(map(str, self.model_params))}}}" if self.model_params else ""
)
return f"{prefix}{self.lie_model.value}{params}"
def get_moltype(self) -> Literal["dna", "protein"]:
return "dna"
@property
def base_model(self) -> "LieModel":
return self.lie_model
@staticmethod
def iter_available_models() -> Sequence["LieModelInstance"]:
return [
LieModelInstance(lie_model, prefix)
for prefix in (None, *LieModelInstance.valid_pairings)
for lie_model in LieModel
]
@staticmethod
def num_available_models() -> int:
return (len(LieModelInstance.valid_pairings) + 1) * len(LieModel)
@property
def description(self) -> str:
base_desc = LieModel._descriptions()[self.lie_model] # noqa: SLF001
if self.pairing is None:
return base_desc
return f"{base_desc} Pairing: {LieModelInstance.pairing_descriptions[self.pairing]}"
class LieModel(SubstitutionModel, Enum):
LIE_1_1 = "1.1"
LIE_2_2b = "2.2b"
LIE_3_3a = "3.3a"
LIE_3_3b = "3.3b"
LIE_3_3c = "3.3c"
LIE_3_4 = "3.4"
LIE_4_4a = "4.4a"
LIE_4_4b = "4.4b"
LIE_4_5a = "4.5a"
LIE_4_5b = "4.5b"
LIE_5_6a = "5.6a"
LIE_5_6b = "5.6b"
LIE_5_7a = "5.7a"
LIE_5_7b = "5.7b"
LIE_5_7c = "5.7c"
LIE_5_11a = "5.11a"
LIE_5_11b = "5.11b"
LIE_5_11c = "5.11c"
LIE_5_16 = "5.16"
LIE_6_6 = "6.6"
LIE_6_7a = "6.7a"
LIE_6_7b = "6.7b"
LIE_6_8a = "6.8a"
LIE_6_8b = "6.8b"
LIE_6_17a = "6.17a"
LIE_6_17b = "6.17b"
LIE_8_8 = "8.8"
LIE_8_10a = "8.10a"
LIE_8_10b = "8.10b"
LIE_8_16 = "8.16"
LIE_8_17 = "8.17"
LIE_8_18 = "8.18"
LIE_9_20a = "9.20a"
LIE_9_20b = "9.20b"
LIE_10_12 = "10.12"
LIE_10_34 = "10.34"
LIE_12_12 = "12.12"
def __call__(
self,
pairing: lie_model_pairing | None = None,
model_params: Sequence[float] | None = None,
) -> LieModelInstance:
"""Parameterise the model.
If parameters are not supplied, the model is not parameterised.
Parameters
----------
pairing : Literal["RY", "WS", "MK"] | None, optional
The pairing type.
RY: purine-pyrimidine pairing
WS: weak-strong pairing
MK: aMino-Keto pairing
by default None (unparameterised uses RY).
model_params : Sequence[float] | None, optional
The weights of the basis matrices, the weights should be
bounded between -0.98 and 0.98 exclusive, by default None.
Returns
-------
LieModelInstance
The parameterised Lie Markov Model.
"""
return LieModelInstance(self, pairing, model_params)
@staticmethod
def model_type() -> str:
return "nucleotide"
def iqtree_str(self) -> str:
return self.value
def get_moltype(self) -> Literal["dna", "protein"]:
return "dna"
@property
def base_model(self) -> "LieModel":
return self
@staticmethod
def iter_available_models() -> Sequence[LieModelInstance]:
return LieModelInstance.iter_available_models()
@staticmethod
def num_available_models() -> int:
return LieModelInstance.num_available_models()
@property
def description(self) -> str:
return LieModel._descriptions()[self]
@staticmethod
@functools.cache
def _descriptions() -> dict[SubstitutionModel, str]:
return {
LieModel.LIE_1_1: "Reversible model. Equal base frequencies. equiv. to JC",
LieModel.LIE_2_2b: "Reversible model. Equal base frequencies. equiv. to K2P",
LieModel.LIE_3_3a: "Reversible model. Equal base frequencies. equiv. to K3P",
LieModel.LIE_3_3b: "Non-reversible model. Equal base frequencies.",
LieModel.LIE_3_3c: "Reversible model. Equal base frequencies. equiv. to TNe",
LieModel.LIE_3_4: "Reversible model. f(A)=f(G) and f(C)=f(T).",
LieModel.LIE_4_4a: "Reversible model. Unconstrained base frequencies. equiv. to F81",
LieModel.LIE_4_4b: "Reversible model. f(A)=f(G) and f(C)=f(T).",
LieModel.LIE_4_5a: "Non-reversible model. f(A)=f(G) and f(C)=f(T).",
LieModel.LIE_4_5b: "Non-reversible model. f(A)=f(G) and f(C)=f(T).",
LieModel.LIE_5_6a: "Non-reversible model. Equal base frequencies.",
LieModel.LIE_5_6b: "Non-reversible model. Unconstrained base frequencies.",
LieModel.LIE_5_7a: "Non-reversible model. f(A)+f(G)=0.5=f(C)+f(T).",
LieModel.LIE_5_7b: "Non-reversible model. Equal base frequencies.",
LieModel.LIE_5_7c: "Non-reversible model. Equal base frequencies.",
LieModel.LIE_5_11a: "Non-reversible model. f(A)+f(G)=0.5=f(C)+f(T).",
LieModel.LIE_5_11b: "Non-reversible model. Equal base frequencies.",
LieModel.LIE_5_11c: "Non-reversible model. Equal base frequencies.",
LieModel.LIE_5_16: "Non-reversible model. f(A)=f(G) and f(C)=f(T).",
LieModel.LIE_6_6: "Non-reversible model. f(A)=f(G) and f(C)=f(T). equiv. to STRSYM for strand-symmetric model (Bielawski and Gold, 2002)",
LieModel.LIE_6_7a: "Non-reversible model. Unconstrained base frequencies. F81+K3P",
LieModel.LIE_6_7b: "Non-reversible model. Unconstrained base frequencies.",
LieModel.LIE_6_8a: "Non-reversible model. Unconstrained base frequencies.",
LieModel.LIE_6_8b: "Non-reversible model. f(A)=f(G) and f(C)=f(T).",
LieModel.LIE_6_17a: "Non-reversible model. f(A)=f(G) and f(C)=f(T).",
LieModel.LIE_6_17b: "Non-reversible model. f(A)=f(G) and f(C)=f(T).",
LieModel.LIE_8_8: "Non-reversible model. Unconstrained base frequencies.",
LieModel.LIE_8_10a: "Non-reversible model. Unconstrained base frequencies.",
LieModel.LIE_8_10b: "Non-reversible model. f(A)=f(G) and f(C)=f(T).",
LieModel.LIE_8_16: "Non-reversible model. Unconstrained base frequencies.",
LieModel.LIE_8_17: "Non-reversible model. Unconstrained base frequencies.",
LieModel.LIE_8_18: "Non-reversible model. Unconstrained base frequencies.",
LieModel.LIE_9_20a: "Non-reversible model. f(A)+f(G)=0.5=f(C)+f(T).",
LieModel.LIE_9_20b: "Non-reversible model. Equal base frequencies. Doubly stochastic",
LieModel.LIE_10_12: "Non-reversible model. Unconstrained base frequencies.",
LieModel.LIE_10_34: "Non-reversible model. Unconstrained base frequencies.",
LieModel.LIE_12_12: "Non-reversible model. Unconstrained base frequencies. equiv. to UNREST (unrestricted model)",
}
@unique
class AaModel(SubstitutionModel, Enum):
"""Protein substitution models."""
Blosum62 = "Blosum62"
cpREV = "cpREV"
Dayhoff = "Dayhoff"
DCMut = "DCMut"
EAL = "EAL"
ELM = "ELM"
FLAVI = "FLAVI"
FLU = "FLU"
GTR20 = "GTR20"
HIVb = "HIVb"
HIVw = "HIVw"
JTT = "JTT"
JTTDCMut = "JTTDCMut"
LG = "LG"
mtART = "mtART"
mtMAM = "mtMAM"
mtREV = "mtREV"
mtZOA = "mtZOA"
mtMet = "mtMet"
mtVer = "mtVer"
mtInv = "mtInv"
NQ_bird = "NQ.bird"
NQ_insect = "NQ.insect"
NQ_mammal = "NQ.mammal"
NQ_pfam = "NQ.pfam"
NQ_plant = "NQ.plant"
NQ_yeast = "NQ.yeast"
Poisson = "Poisson"
PMB = "PMB"
Q_bird = "Q.bird"
Q_insect = "Q.insect"
Q_mammal = "Q.mammal"
Q_pfam = "Q.pfam"
Q_plant = "Q.plant"
Q_yeast = "Q.yeast"
rtREV = "rtREV"
VT = "VT"
WAG = "WAG"
@staticmethod
def model_type() -> str:
return "protein"
def iqtree_str(self) -> str:
return self.value
def get_moltype(self) -> Literal["dna", "protein"]:
return "protein"
@property
def base_model(self) -> "AaModel":
return self
@staticmethod
def iter_available_models() -> Sequence["AaModel"]:
return list(AaModel)
@staticmethod
def num_available_models() -> int:
return len(AaModel)
@property
def description(self) -> str:
return self._descriptions()[self]
@staticmethod
@functools.cache
def _descriptions() -> dict[SubstitutionModel, str]:
return {
AaModel.Blosum62: "BLOcks SUbstitution Matrix (Henikoff and Henikoff, 1992). Note that BLOSUM62 is not recommended for phylogenetic analysis as it was designed mainly for sequence alignments.",
AaModel.cpREV: "chloroplast matrix (Adachi et al., 2000).",
AaModel.Dayhoff: "General matrix (Dayhoff et al., 1978).",
AaModel.DCMut: "Revised Dayhoff matrix (Kosiol and Goldman, 2005).",
AaModel.EAL: "General matrix. To be used with profile mixture models (for eg. EAL+C60) for reconstructing relationships between eukaryotes and Archaea (Banos et al., 2024).",
AaModel.ELM: "General matrix. To be used with profile mixture models (for eg. ELM+C60) for phylogenetic analysis of proteins encoded by nuclear genomes of eukaryotes (Banos et al., 2024).",
AaModel.FLAVI: "Flavivirus (Le and Vinh, 2020).",
AaModel.FLU: "Influenza virus (Dang et al., 2010).",
AaModel.GTR20: "General time reversible models with 190 rate parameters.",
AaModel.HIVb: "HIV between-patient matrix HIV-Bm (Nickle et al., 2007).",
AaModel.HIVw: "HIV within-patient matrix HIV-Wm (Nickle et al., 2007).",
AaModel.JTT: "General matrix (Jones et al., 1992).",
AaModel.JTTDCMut: "Revised JTT matrix (Kosiol and Goldman, 2005).",
AaModel.LG: "General matrix (Le and Gascuel, 2008).",
AaModel.mtART: "Mitochondrial Arthropoda (Abascal et al., 2007).",
AaModel.mtMAM: "Mitochondrial Mammalia (Yang et al., 1998).",
AaModel.mtREV: "Mitochondrial Vertebrate (Adachi and Hasegawa, 1996).",
AaModel.mtZOA: "Mitochondrial Metazoa (Animals) (Rota-Stabelli et al., 2009).",
AaModel.mtMet: "Mitochondrial Metazoa (Vinh et al., 2017).",
AaModel.mtVer: "Mitochondrial Vertebrate (Vinh et al., 2017).",
AaModel.mtInv: "Mitochondrial Invertebrate (Vinh et al., 2017).",
AaModel.NQ_bird: "Non-reversible Q matrix (Dang et al., 2022) estimated for birds (Jarvis et al., 2015).",
AaModel.NQ_insect: "Non-reversible Q matrix (Dang et al., 2022) estimated for insects (Misof et al., 2014).",
AaModel.NQ_mammal: "Non-reversible Q matrix (Dang et al., 2022) estimated for mammals (Wu et al., 2018).",
AaModel.NQ_pfam: "General non-reversible Q matrix (Dang et al., 2022) estimated from Pfam version 31 database (El-Gebali et al., 2018).",
AaModel.NQ_plant: "Non-reversible Q matrix (Dang et al., 2022) estimated for plants (Ran et al., 2018).",
AaModel.NQ_yeast: "Non-reversible Q matrix (Dang et al., 2022) estimated for yeasts (Shen et al., 2018).",
AaModel.Poisson: "Equal amino-acid exchange rates and frequencies.",
AaModel.PMB: "Probability Matrix from Blocks, revised BLOSUM matrix (Veerassamy et al., 2004).",
AaModel.Q_bird: "Q matrix (Minh et al., 2021) estimated for birds (Jarvis et al., 2015).",
AaModel.Q_insect: "Q matrix (Minh et al., 2021) estimated for insects (Misof et al., 2014).",
AaModel.Q_mammal: "Q matrix (Minh et al., 2021) estimated for mammals (Wu et al., 2018).",
AaModel.Q_pfam: "General Q matrix (Minh et al., 2021) estimated from Pfam version 31 database (El-Gebali et al., 2018).",
AaModel.Q_plant: "Q matrix (Minh et al., 2021) estimated for plants (Ran et al., 2018).",
AaModel.Q_yeast: "Q matrix (Minh et al., 2021) estimated for yeasts (Shen et al., 2018).",
AaModel.rtREV: "Retrovirus (Dimmic et al., 2002).",
AaModel.VT: "General 'Variable Time' matrix (Mueller and Vingron, 2000).",
AaModel.WAG: "General matrix (Whelan and Goldman, 2001).",
}
ALL_MODELS_CLASSES: tuple[type[SubstitutionModel], ...] = (
StandardDnaModel,
LieModelInstance,
AaModel,
)
def get_substitution_model(name: str | SubstitutionModel) -> SubstitutionModel:
"""Return the substitution model enum for a given name.
Parameters
----------
name : str | SubstitutionModel
The name of the chosen substitution model.
Returns
-------
SubstitutionModel
The corresponding substitution model enum.
"""
if isinstance(name, SubstitutionModel):
return name
norm_name = _normalise_prefix(name)
if len(norm_name) == 0:
msg = f"Unknown substitution model: {name!r}"
raise ValueError(msg)
# No parameterisation of AaModels
with contextlib.suppress(KeyError):
return AaModel[norm_name]
model_params = _get_model_parameters(norm_name)
if model_params is not None:
norm_name = norm_name[: norm_name.find("{")]
with contextlib.suppress(KeyError):
return StandardDnaModel[norm_name](model_params)
# Lie models
prefix = _get_lie_prefix(norm_name)
if prefix is not None:
norm_name = norm_name[2:]
with contextlib.suppress(KeyError):
return LieModel["LIE_" + norm_name](prefix, model_params)
msg = f"Unknown substitution model: {name!r}"
raise ValueError(msg)
def _normalise_prefix(name: str) -> str:
parts = name.split("{")
parts[0] = parts[0].replace(".", "_")
return "{".join(parts)
def _get_lie_prefix(name: str) -> lie_model_pairing | None:
potential_prefix = name[:2]
if potential_prefix in LieModelInstance.valid_pairings:
return cast("lie_model_pairing", potential_prefix)
return None
def _get_model_parameters(name: str) -> tuple[float, ...] | None:
params_start = name.find("{")
if params_start == -1: # No params
return None
# The model is parameterised here
if name[-1] != "}":
msg = f"Missing closing bracket for parameterisation of {name!r}"
raise ValueError(msg)
return tuple(
float(param.strip()) for param in name[params_start + 1 : -1].split(",")
)
iqtree-piqtree-b8a3d6a/src/piqtree/py.typed 0000664 0000000 0000000 00000000000 15211731751 0021074 0 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/src/piqtree/util/ 0000775 0000000 0000000 00000000000 15211731751 0020364 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/src/piqtree/util/__init__.py 0000664 0000000 0000000 00000004017 15211731751 0022477 0 ustar 00root root 0000000 0000000 import secrets
from collections.abc import Iterable
from cogent3.core.tree import PhyloNode
def validate_other_options(other_options: str, banned_options: Iterable[str]) -> None:
option_parts = set(other_options.split())
for banned_option in banned_options:
if banned_option in option_parts:
msg = f"Option {banned_option!r} will be overridden by parameter of function. Use the parameter directly instead."
raise ValueError(msg)
def get_newick(tree: PhyloNode) -> str:
return tree.get_newick(with_distances=True, escape_name=False)
def make_rand_seed() -> int:
"""Make a 32-bit random seed.
Returns
-------
int
A 32-bit random seed.
"""
seed = secrets.randbits(32)
return seed if seed < (1 << 31) else seed - (1 << 32)
def make_nonzero_rand_seed() -> int:
"""Make a non-zero 32-bit random seed.
Returns
-------
int
A non-zero 32-bit random seed.
"""
while (seed := make_rand_seed()) == 0:
pass # pragma: no cover
return seed
def process_rand_seed_nonzero(seed: int | None) -> int:
"""Process a random seed before sending to IQ-TREE.
Some functions treat 0 as non-deterministic. For
consistency between methods, 0 is treated as always
deterministic and replaced with a pre-determined
number.
If the seed is None, a random seed is generated.
If the seed is 0, it is replaced with a pre-determined
number (1074213633).
If the seed is anything else, returns that number.
Parameters
----------
seed : int | None
The random seed to process.
Returns
-------
int
The original seed if no processing is required.
Otherwise if the original seed was None, a random non-zero seed
is returned. If the original seed was zero, a pre-determined
number is returned.
"""
if seed == 0:
seed = 1074213633 # Randomly chosen once with make_rand_seed
if seed is None:
seed = make_nonzero_rand_seed()
return seed
iqtree-piqtree-b8a3d6a/tests/ 0000775 0000000 0000000 00000000000 15211731751 0016311 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/tests/conftest.py 0000664 0000000 0000000 00000004215 15211731751 0020512 0 ustar 00root root 0000000 0000000 import pathlib
import pytest
from cogent3 import PhyloNode, load_aligned_seqs, make_tree
from cogent3.core.alignment import Alignment
@pytest.fixture(scope="session")
def DATA_DIR() -> pathlib.Path:
return pathlib.Path(__file__).parent / "data"
@pytest.fixture
def three_otu(DATA_DIR: pathlib.Path) -> Alignment:
aln = load_aligned_seqs(DATA_DIR / "example.fasta", moltype="dna")
aln = aln.take_seqs(["Human", "Rhesus", "Mouse"])
return aln.omit_gap_pos(allowed_gap_frac=0)
@pytest.fixture
def four_otu(DATA_DIR: pathlib.Path) -> Alignment:
aln = load_aligned_seqs(
DATA_DIR / "example.fasta",
moltype="dna",
)
aln = aln.take_seqs(["Human", "Chimpanzee", "HumpbackW", "SpermWhale"])
aln = aln.omit_gap_pos(allowed_gap_frac=0)
return aln[::15]
@pytest.fixture
def five_otu(DATA_DIR: pathlib.Path) -> Alignment:
aln = load_aligned_seqs(
DATA_DIR / "example.fasta",
moltype="dna",
)
aln = aln.take_seqs(["Human", "Chimpanzee", "Rhesus", "Manatee", "Dugong"])
return aln.omit_gap_pos(allowed_gap_frac=0)
@pytest.fixture
def all_otu(DATA_DIR: pathlib.Path) -> Alignment:
aln = load_aligned_seqs(
DATA_DIR / "example.fasta",
moltype="dna",
)
return aln.omit_gap_pos(allowed_gap_frac=0)
@pytest.fixture
def protein_four_otu(DATA_DIR: pathlib.Path) -> Alignment:
aln = load_aligned_seqs(DATA_DIR / "protein.fasta", moltype="protein")
aln = aln.take_seqs(sorted(aln.names)[:4])
aln = aln.omit_gap_pos(allowed_gap_frac=0)
return aln[::15]
@pytest.fixture
def five_trees() -> list[PhyloNode]:
tree1 = make_tree("(a,(b,(c,(d,(e,f)))))")
tree2 = make_tree("(a,(b,(c,(d,(e,f)))))")
tree3 = make_tree("((a,b),(c,(d,(e,f))))")
tree4 = make_tree("(((a,b),c),(d,(e,f)))")
tree5 = make_tree("((((a,b),c),d),(e,f))")
return [tree1, tree2, tree3, tree4, tree5]
@pytest.fixture
def four_taxon_unrooted_tree() -> PhyloNode: # Unrooted
return make_tree("((a:0.1,b:0.2):0.05,c:0.3,d:0.1);")
@pytest.fixture
def five_taxon_rooted_tree() -> PhyloNode: # Rooted
return make_tree("(((a:0.1,b:0.2):0.05,(c:0.3,d:0.1):0.2):0.05,e:0.4);")
iqtree-piqtree-b8a3d6a/tests/data/ 0000775 0000000 0000000 00000000000 15211731751 0017222 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/tests/data/example.fasta 0000664 0000000 0000000 00000510250 15211731751 0021700 0 ustar 00root root 0000000 0000000 >FlyingFox
TGTGGCACAAATGCTCATGCCAGCTCTTTACAGCATGAGAAC---AGTTTATTATACACTAAAGACAGAATGAATGTAGA
AAAGACTGACTTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACAGAACAGATGGGTTGAAACTAAGGAAA
CATGTAACGAT---ATGCAGACTTCCAGCACAGAGAAAAAGGTAGTTCTGAATGCTGATCCCCTGAATGGGAGAATAGAA
CTGAATAAGCAGAAACCTCCATGCTCTGACAGTCCTAGAGAT---TCTCAAGAT---ATTTCTTGGATAACACGGAATAG
TAGCATACAGAAAGTTAATGAGTGGTTTTCCAGACGTGATGAAATATTAACTTCTGATGTCTCACCTGATGGGAGGTCTG
AATCAAATGTG---------------GTAGAAGTTCCAAAT------GAAGTAGATGGATACTCTGGTGCTTCAGAGAAA
ATAGCTTTAAAGGCCAATGATCCTCATGGTGCTTTAATGTGC------GAAAGAGTTCACTCCAAACTGGTAGAAAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACATATCGGAGGAAAGCAAGCCTCCCTAACTTGAGCCACATAACTGAAAATC
TAATTACAGGAGCATCTGCTATAGAACCTCAGATAACACAA---------------------------------------
---------------------GAGTATCCCCTCACAAATAAACTAAAGCGTAAAAGGAGAACTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAATAGATTTGGCAGTTGTTCAGAAAACTCCGGAAAACATAATTGAGGAAACTGACCAAATAG
AGCAGAAT---------GGTCATGTGATGAATAGTACTAATAATGGTCATGAGAATGAAACAAAAGGTGATTAT---GTT
CAGAAGAAGAAAAATACAAACCCAACAGAA------TCATTGGAAAAAGAATCTACTTTCAAAACTAAAGCTGAACCTAT
ATGCAGCAGCATAAGCAATATGGAACTAGAATTAAATATCCACAGTTCAAAAGCAGTTAAGAAGAATAGGCTGAGGAGGA
AGTCCTCTACCAGGCATATTCATGCACTTGAACTAGTAGTCAATAGAAATCCAAGCCCACCTAATCATACTGAACTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---CTGAAGGAAAAA---AATTCTGACCAAATGCCAGTCAGACACAGCAAAAA
ACTTCAATTCATAGAAGATAAAGAATCTTCAACTGGAGCCAAGAAGAATAACAAGCCAAATGAGACAATCAATAAAAGAC
TTGCCAGTGATGCTTTTCCAGAATTAAATATAACAAACATACCTGGTTTTTTTACTAATGGTTCAAGTTCTAATAAACTT
CAAGAGTTTGTCAATCCTAGCCTTCAAAGAGAAGAAATAAAAGAGAAC---CTAGGAACAATTCAAGTGTCTAATAGTAC
CAAGGACCCCAAAATTTTGATCTTCGGTGAAGGAAGA---GGTTCACAA---ACTGATCGATCTACAGAGAGTACCAGTA
TTTTATTGGTGCCTGAAACGGATTATGGCACTCAAGATAGTATCTCATTACTGGAACCTGACATCCCAGAG---AGGGTA
AAG---ACAGCACCAAACCATCAT------------GCAGCAATTAAAAACCCCAGAGAACTTATTCATGGTTGT---TC
TGAAGATACTAGAAATGATGCAGAGGGCTTTAAAGATCCATTGAGACGTGAAGTTAAC---TACANNNNNNNNNNN----
-----NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNTTCAAACCCAGGAAATCTAGAAAAGGAATGTGCAACAGGCTATGCCCACTCCAAGTCCTTGAGGAAACAAAGTCCAAA
AGTCACTCTTGAATGTGACCGAAAAGAA---AATCAGGGAAAGAAAGAGTCTAACGTCAAGCATGTGCAGGCAGTTTATA
CAACTGTAGGCTTTCCTGTGGTTTGTGAGAAAGAAAAAAAGCCAGGAGATTATGCTAAATATGGCATAAAAGAAGTCTCT
AGGCTTTGTCAGTCATTTCAGTTCAGA---GAAAATGAAACTGAACTCACTATTGCAAATAAACTTGGAATTTCACAAAA
CCCATATCATATGCCATCCATTCCTCCCATCAAGTCATCTGTTAAAACTACATGTAAGAAAAAT---CTGTCAGAGGAAA
AGTTTGAAGAACATTCAATATCCCCTGAAAGAACAATAGGAAATGAGACCATCATTCAAAGTACAGTGGGCACAATTAGC
CAAAATAACATTAGAGAAAGCACTTTTAAAGAAGGCAGCTCAAGCAGTATTTATGAAGCAGGTTCCAGTACTAACGAACT
AGGCTCTAGTGTCAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCAAGCAGAACTAAGTA
GAAACAGAGGACCACAATTAAATGCTGTGCTTCAATTGGGTCTCATGCAGCCTGAAGTCTATAAGCAAAGCCTT---CCT
CTAAGTAATTGTAAACATCCTGAAATAAAAAGGCAAGGAGAAAATGAAGGAGTAGTTCAGGCTGTTAATGCAGATGTCTC
TCTACGTCAGATTTCAGATAACTTAGAGCAA---CCTATGGGAAACAGTAATGCTTCTCAGGTTTGTTCTGAGACACCGG
ATGACCTGTTAAATGATGACAAAATAAAAGAGAATATCGGCTTTGATGAAAGTGGCATTAAGGAAAGATCTGCTGTTTTT
AGCAAAAGTGTCCAGAAAGGAGAATTCAAAAGGAGCCCTAGTCCCTTAGCCCAT---ACAAGTTTGTCTCAAGGTCGCCG
AAGAGGGGCTAGGAAATTAGAGTCCTCAGAAGAGGA-------------
>DogFaced
TGTGGCACAAATACTCATGCCAACTCATTACAGCATGAGAACAGCAGTTTATTATACACTAAAGACAGAATGAATGTAGA
AAAGACTGACTTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAGCAGAACAGATGGGTTGAAACTAAGGAAA
CATGTAATGAT---AGGCAGACTTCCAGCANAGAGAAAAAGGTAGTTCTGAATGCTGATCCCCTGAATGGAAGAATAAAA
CTGAATAAGCAGAAACCTCCATGCTCTGACAGTCCTAGAGAT---TCCAAAGAT---ATTCCTTGGATAACACGGAATAG
TAGCATACAGAAAGTTAATGAGTGGTTTTCCAGACGTGATGAAACATTAACTTCTGATGTCTTACTTGATGAGAGGTCTG
AATCAAATGTG---------------GTAGAAGTTCCAAAT------GAAGTAGATGGATACTCTGGTGCTTCAGAGGAA
ATAGCCTTAAAGGCCAGTGATCCTCATGGTGCTTTAATATGT------GAAAGAGTTCACTCCAAATTGATAGAAAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACATATCGGAGGAAAGCAAGCCTCCCTAACTTAAGCCACATAACTGAAAATC
TAATTACAAGAGCATCTGCTACAGAACCTCAGATAACACAA---------------------------------------
---------------------GAGTGCCCCCTCACAAATAAACTAAAACGTAAAAGAAGAACTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAATAGATTTGACAACTGTTCAAAAAACTTCTGAAAATATAATTGAGGGAACTGACCAAATAG
AGCAGAAT---------GGTCATGTGATGAATAGTTCTAATGATGGTCATGAGAATGAAACAAAAGGTGATTAT---GTT
CAGAAGAAGAAAAATACAAACCCAACAGAA------TCATTGGAAAAAGAATCTGCTTTCAGAACTAAAGTTGAGTCTGT
ACCCAACAACATAAGCAATGTGGAACTAGAATTAAATATTCACGGTTCAAAAGCACTCAAGAAGAATAGNCTGAGGAGGA
AGTCCTNTACCAGGCATATTCATGCACTTGAACTAGTAGTCAATAGAAATTCAAGCCCACCTAATCATACTGAACTACAA
ATTGATAGTTGTTCCAGCAGTGAAGAA---CTGAAGGAAAAA---AATTCTGACCGAATGCCAGACAGACACAGCAAAAA
ACTTCAGTTCGTAGAAGATAAAGAATCTGCAACTGGAGCCAAGAAGAATAACATGCCAAATGAGGCAATAAATAAAAGAC
TTTCCAGTGAAGCTTTTCCCGAATTAAATATAACAAACGTACCTGGTTTTTTTACTAATGGTTCAAGTTCTAATAAACGT
CAAGAGTTTGTCAATCCTAGCCTTCAAGGAGAAGAAATAAAAGAGAAT---CTACGAACAATTCAAGTGTCTAATAGCAC
CAAAGACCCCAAAATTCTAATCTTTGGTGAAGGAAGA---GGTTCACAA---ACTGATCGATCTACAGAGAGTACCAGTA
TTTTATTGGGACCTGAAACGGATTATGGCACTCAAGATAGTATCTCATTACTGGAATCTGACATCCCAGGG---AGGGCA
AAG---ACAGCACCAAACCAACATGCAGATCTGTGTGCAGCAATTGAAAACCCCAGAGAACTTATTCATGATTGT---TT
TAAAGAAACTAGAAATGACACAGAGAGCTTTAAAGATCCATTGAGACATGAAGTTAAC---TCCACNNNNNNNNNN----
-----NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNTTCAGACCCAGGAAATCTAGAAAAGGAATGTGCAACAGGCTATGCCCACTCCAGGTCCTTGATAAAACAAAGTCCAAA
AGTCACTCTTGAATGTGACCGAAAAGGA---AATCAGGGAAAGAAAGAGTCTAACATNGAGCATGTGCAGGCAGTTTATA
CAACTATAGGCTTTCCTGGGGTTTCTGAGAAAGACAAAAAGCCAGGAGATTATGCCAGATATGGCATAAAAGAAGTCTCT
AGGCTTTGTCAGTCATTTCAGTCTAGA---AGAAATGAAACTGAGCTCACTATTGCAAATAAACTTGGACTTTCACAAAA
CCCATATCATATGCCATCCATTTCTCCCATCAAGTCATCTGTTAAAACTATATGTAAGAAAAAT---CTGTCAGAGGAAA
AGTTTGAAGAACATTCAATATTCCCTGAAAGAGCAATAGGAAATGAGACCATCATTCAAAGTACAGTGGGCACAATTAGC
CAAAATAACATTAGAGAAAGCACTTTTAAAGAAGGCAGCTCAAGCGGTATTTATGAAGCAGGTTCCAGTACCAATGAACT
AGGCTCTAGTGTCAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCAAGCAGAACTAAGTA
GAAACAGAGGACCAAAATTAAATGCTGTGCTTCAGTTGGGTCTCATGCAGCCTGAAGTCTATGAGCAAAGCCTT---CCT
CTAAGTAATTGTAAACATTCTGAAATAAAAAGGCAAGGAGAAAATGAAGGAGTGGTTCAGGCTGTTAATGCAGATGTCTC
TCCANGTCAAATTTCAGATAACTTAGAGCAA---CCTATGGGAAACAGTAATATTTCTCAGGTTTGTTCTGAGACACCGG
ATGACCTGTTAAATGATGACAAAATAAAGGACAATATCAGCTTTGATGAAAGTGGCATTCAGGAAAGATCTGCTGTTTTT
AGCAAAAATGTCCAGAAAGGAGAATTCAGAAGGAGCCCTAGTCCCTTAGCCCAT---GCAAGTTTGTCTCAAGGTCGCCC
AAGAAGGGC----------------------------------------
>FreeTaile
TGTGGCACAGATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTACTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAGCAGCCTGGCTTAGCAAAGAGCCAGCAGAGCAGATGGGCTGAAAGTAAAGAAA
CATGTAATGAT---AGGCAGACTCTCAGCACAGAGAAAAGGGTAGTTCTGAATGCTGATCCTCTGAATAGG---------
------AGAAAAGAACCTCCAGGCTCTAACTATCCTAGAGAT---TCCCAAGAT---GTTCCTTGGATAACACGGAGTAG
TAGCATACAGAAAGTTAATGAGTGGTTCTCCAGACGTGATGAAATACTAACTACTGGTGGCTCACATAACGGTAGATTTG
AATCAAATGTTGAAGTAGCTGGTGCAGTAGAAGTTCCAAAT------GAAGTAGATGGATATTCTGGTTCTCCAGAGAAA
ATAGCCTTAATGGCCTGTGATCCTCCTGATGCTTTAATATGT------GAAAGAGTCTCCTCTAAACCACTAGAAAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGAAAGGCAAGCTTCCCTAACTTGAGCCACATAAGTGAAAATC
TAATTATAGGAGCATCTGCTATAGAACCCCAGGTAACAAAA---------------------------------------
---------------------GAATGTCCCCTCACAAATAAACTAAAGCGTAAAAGAAGA---ACATCAAGCCTTCATCC
TGAGGATTTTATCAAGAAAGTAGATTTGGCAGTTGTTCAAAAGACTCTTGAAAAGGTAATTGAGGGAACTGACCAAATAG
AACAGAAT---------GGTCATGTGATGAGTATTACTAGTAATTGTCATGAGAATAAAACAAAAGGTGATTAT---GTT
CAGAAAGAGAAAAATTCTAACCCAACAGAA------TCATTGGAAAAAGAATCTGCTTTCACAACTAAAGCTGAACCTAT
AAGCAGCAGCATAAGCAATATGGAACTAGAGTTAAATATCCACAGTTCAAAAGCACCTAAGAAGAATAGGCTGAAGAGGA
AGTCCTCTACCAGGCACATTTATGCACTTGAACTAGTAGTCAATAGAAATCCAAGCCCACCTAATCACACTGAACTACAA
ATTGATAGCTGTTCTAGCAGTGAAGAG---GTGAAGGAAAAA---AATTCTGACCAAATACCAGTCAGACACAGCAAAAA
GCTTCAACTCATGGAAGGTAAAGAACCTGCAACTGGAGCCAAGAAGAGTAACAAATCAAATGAACAAATAAATAAAAAAC
TTGCCAGTGATGTTTTTCCAGAACTAAACTTAACAAACATACCTGGTTTTTTAAGTAATGATTCAAGTTCTAATAAACTT
AAAGAGTTTGTCAATCCTAACCTTCAAAGAGAAGAAATAACAGAGAAC---CTAGGAACAGTTCACATGTCTAATAGTAC
CAAAGACCTCAAAGATCTGATATTAAGTGGAGGAAGA---AGTTTGCAA---ACTGATAGATCTATGGAGAGTACCAATA
TTTTATTGGTACCTGAAACTGATTATGGCACGCAGGATAGTATCTCATTACTGGAACCTGACACCCCAGGG---AAGGCA
AAA---AAAGCTCCAAATCAATATGCGGGTCTGTGTGCAGAAATTAAAAACCNCAAGGAACTTATCCATGGTTGT---TC
TAACGATAATAGAAATGACAGAGAGGACATTAAGGATCTATTGAGACCTGAAGTTAAC---CACANNNNNNNNNNNNNNN
NNNNNNNGGAAGAGAGTGAACTTGATACACAGTATTTACAGAATACATTCAAGGTTTCAAAACGTCAGTCGTTTGCTCTG
TTTTCAAATCCA---------GAAAAGGAATATGCAACAGTCTATGGCCACTCCAGGTCCTTAAGGAAACAAAGTCCAAA
AGTCACTCTTGAATGTGGACAAAAAGAAGAAAATCAGGGAGAGAAAGAATCTGAAATCAAGTATGTACGGGGAGTTCACA
CAACTGCAGGCTTTCCTGTGGTTTGTGAGAAAGACGAAAAGCCAGAAGAATATGCCAAATGTAGCATAAAAGGAACCTCT
AGCCTTTGTCAGCCACCTCAGTTCAGA---GGCAACGAAACTGAACTCACTATTGCAAATAAACCCGGAATTTCACGAAA
CCCATATCATATACCATGCATTTCTCCCATCAGGTCCTTTGTTAAAACTATAAATAAGAAAAAC---CTGTCAGAGGAAA
AGTTTGAGGAACATTCAGTGTCACCTGAAAGAGCAATGAGAAATGAGAAT---ATTCTAAGTACAGTGAGCCCAATTAGC
CTAAATAAC---AGAGAAAGCACTTTTAAAGAAGGCAGCTCAAGC---------------------AGTACTAATGAAGT
AGGCTCTAGTACCAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCAAGCAGAACTAGGTA
GAAACAGAGGATCAAAAATAAATGCTATGCTCAGATCAGGTCTCATGCAACCTGAAGTCTATAAGCCAAGCCTT---TCT
GTAAGTAATTGTGAACATCCTGAAATAAAAAGGCAAGGAGAAAATGAAGGAGTAGTTCAGGCTGTTAATGCAGATTTCTC
TCCATGTCAAATTTCAGATAACTTAGAACAA---TCTATGGGAAGTACTCCTGCTTCTCAGGTTTGTTCTGAGACACCAG
ATGACCTGTTAAATGATGACAAAATAAAGGAGAATAGCAGCTTTGCTGGAAGTGGCATTAAGGAAAGATCTGCTATTTTT
AGCAAAAGTGTCAAGAAAGAAAAATTCAGAAGGAGCCCTAGCCCCTTTGCCCAT---ACACATTTGACTCATACTCGCCA
AAGAGGGGCCAGGAAATTAGAGTCCTCAG--------------------
>LittleBro
TGTGGCACAGATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTACTACTCACCAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAGCAGCCTGGCTTAGCAAGGAGCCAGCAGAGCAGATGGGCTGAAAGTAAAGAAA
CATGTAATGAT---AGGCAGACTCCCAGCACAGAGAAAAGGGTAATTCTGGATGCTGATCCTCTGAATGGG---------
------GAAAAAGAACTTCCACGCTCTGACCATCCCAGAGAT---TCCCAAGAT---GTGCCTTGGATAACACGGAGCAG
TAGCATACAGAAAGTTAATGAGTGGTTTTCCAGGCGTGATGAAATACTAACTTCTGATGGCTCACATAATGGCAAGTCTG
AGTCAAATGCTGAAGTAGCTGGTGCAGTGGAAGTTGCAAAT------GAAGTAGATGGGTATTCTGGTTCTCCAGGGAAA
ATAACCTTAATGGCCCATGATCCTCATGGTGCTTTAACCTGTGAAAGTGAAAGAGTTCACTCCAAACCAGTAGAAAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCAAACTTGAGCCACATAACTAAAAATC
TAATTGTAGGAGCATCTGCTATAGAACCTCAGATAGCACAA---------------------------------------
---------------------GAGTGTCCCCTCACAAATAAACTAAAGCGTAAAAGGAGAAGTACATCNGGCCTTCATCC
TGAGGATTTTATTAAGAAAGTAGATTTGGCAGTTGTTCAAAAGACTCCTGAAGAGATAATTAAGGGAACTGACCGAATAG
AACAGAAT---------GGTCATGAGATGAATATTACTAATAATGATCATGAGAATGAAACAAAAGGTGATTGT---GTT
CAGAAAGAGAAAAATGCTAACCTAACAGAA------TCACTGGAAAAAGAATCTGCGTTCACAAGTAAAGCTGAACCTAT
AAGCAGCAGCATAAGCAATATGGAACTAGAATTAAATGTCCACAGTTCAAAAGCACCTAAGAAGAATAGGCTGAAGAGGA
AGTCCTCTACCAGGCCTATTCATGCACTTGAACTAGTAGTCAATAGAAATCCGAGCCCATCTAACCATACTGAACTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---GTGAAGGAAAAA---AATTCTGACCAAATACCAGTCAGACACAGCAAGAA
GCTTCAACTCATGGAAGGTAAAGAACCTGCAGCTGGAGCCAAGAAGAGTAATAAGTCAGATGAACAAATAAATAAAAAAC
TTGCCAGTGATGCTTTTCTAGAACAAAACTTAACAAACATGCCTGGTGTTTTTACTAATGGTTTAAGCTCTAATAAGCTT
AACGAGTTTGTCGATCCTAACCTACAAAGAGAAGAAACAGAAGAGAAC---CTAGGAGCAGTTCAAATGTCTAATAGTAC
CAAAGACCTCGAAGATCTGACATTAAGTGGAGGAAGA---AGTGTGCAA---ATTGATAGATCTAAAGAGAGTACCAATA
TTGTATTGGTACCTGAAACTGATTATGGCACACAGGATAGTGTCTCATTACTGGAACCTGACATCCCAGGG---AAGGCA
AAA---ACAGCTCCAAATCAATGTGGGGATCTGTGTGCAGCAGTTAAAAATCCTAAAGAACTTATTCGTGGTTGT---TC
TAAAGATATTAGAAATGACAGAGAGGGCTTTAAGGATCTATTGAGATGTGAAGTTAAC---CACACGCAGGAGACAAGCA
TAGAAGTGGAAGAGAGTGAACTTGATACACAGGAATTACAGAATACATTCAAGGTGTCAAAGCGCCAGTCATTTGCTCTG
TTTTCAAATCCA---------GAAAAGGAATGTGCAACAGCCTATGCTCACTCCCAGTCTTTAAGGAAACAAAGTCCAAA
AGTCACTCTTGAATGTGGACAAAAAGAAGAAAATCAGGGAAAGAAAGAATCTAAAATCAAGCATGTACAGGCAGTTCACA
CAGCTGTAGGCTTTCCTGTGGTTTGTGAGAAAGACAGAAAGCCAGGAGAGTATGCCAAATACAGCATAAAAGGAACCTCT
ATGCATTGCCNGTCCTCTCAGTTCAGA---GGCAACAAAACTGAACTCACTATTACAGATAAATATGGACTTTCCCCAAA
CCCATATCATATACCATCCATTTCTCCCATCAAGTCATTTGTTAAAACTGTAAGTAAGAAAAAC---CTGTCAAAGGAAA
AGTTTGAGGAACATTTAGTGTCACCTGAAAGAGCAATGGGAAATGAGAAC---ATTCAAAGTACAGTGAGCCCAATTAGC
CTAAGTAACATTAGAGAAAGCGCTTTTAAAGAAAGCAGCTCAAGC---------------------AGTACTAATGAAGG
GGGCTCTAGTATCAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCATGCAGAACTAGATA
TAAACAAAGGATCAAAATTAACTGCTATGCTCAGATTAGGTCTCATGCAACCCGAAGTCTATAAGCCAAGCCTT---CCT
GTAAGTAATTGTAAACATCCTGAAGTAAAAAGGCAAGGAGACAACGAAGGACTAGTTCAGGCTGTTAATGCAGACTTCCC
TCCATGTCAAATTTCAGATAACCTAGAACAA---CCTATGGGAAGTAGTCCTGTTTCTCAGGTTTGTTCTGCGACACCGG
ATGACTTGTTAACTGATGATGAAATAAAGGAGAATAGCGGCTTTGATGAAAGTGGCATTAANGAAAGATCTGCTGTTTTT
AGCAAAGATGTTCAGAAAGAAGAATTCAGAGGGAGCCCTAGCCCCTTAGCCCAT---ACATATTTGACTCGGAGTTGCCA
AAGAAGGGCCAGGAAATTAGAGTCCTCAGAAGAGGA-------------
>TombBat
TGTGGCACAAGTACTCATGCCAGCTCAGTACAGCATGAGAACAGCAGTTTACTACTCACTAAAGACAGAATGAACGTAGA
AAAGCTTGACTTCTGTAATAAAAGCAAGCAGCCTGGCTTAGCAAGGAGCCAGCAGAGCAGATGGGCTGAAAGTAAAGAAA
CATGTAATGAT---AGGCAGACTCCCAGCACAGAGAAAAGGGTAGTTGTGAATGCTGATACCCTGGATGGG---------
------AGAAAAGAACCTCCATACTCTGACTGTCCTAATGAT---TCCCAAGAT---GTCCCTTGGATAACAGGGAATAG
TAGCATACAGAAAGTTAGTGAGTGGTTTTCCAGGCGTGATGAAATATTAACTTCTGATGGATCACATGATGGGAGATCTG
AATCAAATATGGAAGTAGCTGGTGCAGTAGAAGTTCCATAT------GAAGTAGATGGATATTCTGATTCTCCAGAGAAA
ATAGGCTTAATGGCCAGTGATCCTCTTGGTGCTTTACTATGTGAAAGTGAAAGAATCCACTCCAAACCAGTAGAAAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCTAACTTGAGCCATATAACTGAAAATC
TAATTATAGGAGCACCTACTATACAATCTCAGATAACACAA---------------------------------------
---------------------AATTGTCCCCTCACAGATAAACTAAAGCATAAAAGAAGAACTACATCAGGCCTTCGTCC
TGAGGATTTTATCAAGAAGGTAGATTTGGCAGCTGTTCAGAAGACTCCTGAAAAGATAATTGAGGGAACTGATCAAACAG
AACAGAAT---------GGTTCTGTGATGAATATTACTGATAATGGTCATGAGGATGAAACAAAATGTGATTAT---GGT
CAGAAAGAGAAAAATGCTAACCCAGCAGAA------TCATTGGAAAAAGAATCTGCTTTCAGAACTAAAGCTGAACCTAT
AAGCAGCAGCATAAGCAACATGGAACTAGAGTTAAATATCAACAGTTCAAAAGCACCTAAGAAGAATAGACTGAGGAGGA
AGTCCTCTACCAGGCATATTTATGCACTTGAACTGGTAGTCAATAGAAATCCAAGCCCACCTAATCATATTGAACTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---GTGAAGAAAAGA---AATTCTGACCAAATACCAGTCAGGCACAGCAAAGA
GCCTCAACTCGTGGAAGGTGAAGAACCTACGACTAGAGCCAAGAAG---AATAAGTCAAATGAACAAATAAATAAAAGAC
TTGCCAGTGATACTTTTCCAGAACTAAATTTAAAAAACATACCTGGTTTTTTTACTAATGGTTCAAGTTCTAATAAACTT
CAAGAGTTTGTTGATCCTAACCTTCGAAGAGAAGAAGTGGAAGAGAAC---CTAGGAACAATTCAAGTGTCTGATAGTAC
CAAAGACCTCAAAGATCTGATATTAAGTGGAGGAAGA---AGTTTGCAA---ACTGATAGATCTATGGAGAGTACCAATA
TTTTATTGGTACCTGAAACTGATTATGACACTCAGTATAGTATCTCATTACTGGAACCTGACACCCCAGGG---AAGGCA
AAA---ACAGCACCAAGTCAACATGCGAGTCTGTGTGCAGCAATTGAAAACCCCAAGGAGTTTAACCATGGTTGT---TC
TAAAGATACTAGAAGTGACACAGAGGGTGTTAAGGATCTACTGAGATGTGAAATTAAC---CNCACNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNGAATACATTCNNGNTTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCAAATTCAGAAAATCCAGAAAAGGAATGTGCAACAGTCTATGCCCACTCCAAGTCCTTAAGGAAACACAGTCCAAA
AGTCACTCTTGGATGTGGTCAAAAAGAAGAAAATCAGGAAGAGAAAGAATCTAAAATCAAGCATGTACAGGCTGTTCACA
CAGCTGCAGGCCTTCCTGCCATTTGTGAGAAAGACAAGAAGCCAGGAGAATATGACAGATACAATATAAAAGGAATCTCT
AGGCTTTGTCAGTTATCTCAGTTCAGA---GGCAATGAAACTGAACTCACTATTGAAAATAAACACAGAATTTTACAAAA
CCCATATCATATATCACCCATCTCTCCCATCAGGTCATCTGTTAAAACGATAAGTAAGAAAAAC---CTGTCAGAGGAAA
AGTTTGAGAAACAGTCAGTGTCACCTGAAAAAGCAATGGGAAATGAGAACATCATTCAAAGTACAGTGAGCACAATTAGC
CAAAATAATGTTAGAGAAAGAGCTGTTAAAGAAGGCAGCTCAAGC---------------------AGTACTAACGAAGT
AGGCTCTAGTATCGATGAAGCAGGTTCCAGT---------------------GGTAAAAACATTGGAGCAGAACTAGATA
GAAACAGAGGATCAAAATTAAGTGCTGTTCTCAGATTAGGTCTCATGCAACCCGAAGTCTATAAGCCAAGCCTT---CCT
ATAAGTAATTGTAAACACTCTGAAATAGAAAGGCAAGGAGAAAATGAAGTAGTAGTTCAGGCTGTTAATGCA--------
----TGTCAAATTTCAGATAACTTAGAACAG---CCTATGGGAAGTAGTCCTGTTTCTCAGGCTTGTTCTGAGACACCAG
ATGACCTATTAGATGATGACAAAATAAAGGAGAATAGCAGCTTTGCTGAAAGTGGCATTAAGGAAAGATCTGCTATTTTT
AGCAAAAGTGCCCAGGAA---GAACTCAGCAGGAGCCCTAGCCCCTTAACCCAT---ACACATTTGGCTCAGGGTCAGCA
GAGAAGGGCCGGGAAATTAGAGCC-------------------------
>RoundEare
---------------------NGCTCATTANAGCNTGAGAACAGCAGTTTACTGCTCACTGAGGACCAGATGAGTGTGGG
AAAGGCTGAATTCCGTCATGAAAGCAAGCAGCCCGGCTTAGCGAGGAGCCAGCAGAGCAGATGGGCTGAAAGTAAAGAAA
CATGTGACGAT---AGGCAGGCTCCCAGCGCAGAGGAAAGGGCAGTTCTGAATGCTGATCCCCAGAATGGG---------
------AGGGAAGAATCTCCATCCTCTGACCACCCTAGAGAT---TCCCAAGAT---GTTCCTTGGATAACACGGAATAG
CAGCATACAGAAAGTTAATGAGTGGTTTTCCAGACGTGATGAAACACGGACTTCCAACGGCTCCCACGGTGGGAGGCCTG
AGTCAGACACGGAAGGAGCCGACACGGTAGAAGCTCCGGAC------GAAGTGCGTGGATGCCCTGGCTCTCCAGAGAAC
ACAGCCTCGCCGGCCGGCGAGCCTCATGGCGCTTTAATGTGCGGAAGTGAAAGCGTCCACTCCAAACCAGTGGAGAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCTAACTTGAGCCACGTAACTGACAGGC
TAACTACGGGACTGTCCGCTCCAGACCCTCAGATAACACGA---------------------------------------
---------------------GAGCGTCCCTTCACCAACAAACTAAAGCGTAAAAGGAGAACTACACCGGGCCTTCACCC
AGAGGATTTTATCAAGACAGTGGATTTGACCGTTGTCCAGAAGACTCCTGAGAAGACCATTGAGGGAACTGACCAAACAG
AACAGAAC---------GGTCGTGTGATGGATATTGCTAACAGTGGTCACGGGAATGAAGCAAAAGGTGATTAT---GTT
CAGAATGAGAAGAGTTCTGACCCAACAGAA------TCACTGGGAGAAGAACCCGCTTTCAGAACTAAAGCTGGACCTAT
AAGCAGCAGCATAAGCACCGTGGGACTAGAATTGAATGTCCACGGTTCAAAAGCGCCCAGGAAGACTAAGCGGAGGGAGA
AGACTGCTGCCGAGCATACTTATGCACCTGGACTCGGGGTCAGCAAGAGCCCGAGCCCCCCTGCTCACGCCGGACTGCGG
ACGGACGGTTGTTCTGGCGGCGAGGAG---GCAAAGATCGGG---AATTCTGGGCAGAGGCCAGCCAGGCGGAGCAGCAA
GCTTCCGCTCGAGGAGGGTCAGGAGCCTGCAGCTGGGGCCAGCAAGGGTGACCGGTCAGATGCACCGATGAATAAGAGAC
TTGCCAATGATGCTTTTCCGGAACTAAATTTAACAAGCGTATCTGCCGTTTTTACTAATGGTTCAGGTTCTACTAAACTT
AAAGAGTGTGTCGATTCTAACCCTCAAGGAGAAGACACAGAAGAGAAC---CGAGGAACAGTTCAAGTGTCTAGTAGCAC
CAAAGACCTCAAAGATCTGATATTCAGTGGGGGAAGA---AGTTTGCAA---ACTGACAGATCTGTGGAGAGTCCCAATA
TTGNATTGGTACCTGAAACTGACTGTGACACTCAGGATAGCGTCTCCCTGCTGGCACCTGACACCCCAGGG---AAGGCA
GAA---ACAGCACCAGGCCAACGTGTGGGTGGGTGCGCAGCTGCTGGAAGCCCGAAGGAACTTATCCGTGATTGT---TC
GAAG------------GACACAGAGGGCGTTAAGGATCTCCCGAGATGTGAAGTTCAG---GAGACNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNTGCTCTG
TGTTCAAATCCAGGNAATCCAGGAAAGGAATGTGCAACCATGTATTCCCACTCCAGGTCCACAAGGAAACGAAGTCCAAA
AGTTACTCTTGAATGTGGACGAAAAGAA---CATCAGGGAGAGAAGGAATTTAATATGGAGCGTGCGCAGCCACCTTACA
CAACAGCAGGCTTTCCTAAGGGTTGTGAGAAAGACAAAACGCCAGGAGAGTGTGCCACATATACTATGAAAGGAATCTCT
AAGCCTTGTCAGTCATCTTCGTTCAGA---GGCAATGAAACTAAACTCACTATTGAAAATAAATATGGGATTTCACAAAA
CCCCTATCACATACCACCCATTTCTCCCGTCAGGTCATCTGTTAAAACTACAAGTAAGAAGAAC---CTGTCAGAGGAGA
AGTGTGAGGAACATTCAGTGTCACCTGCCAGAGCCGTGGGACGTGAGAACATCATTCAGAGTACAGCGGGCACTCCTAGC
CAGAACAAAACCAGGGAAAGTGCCGCCAGAGAAGGCAGCTCGAGC---------------------GGCACTAACGAAGT
AGGCTCCAGT------------------------------------------GGTGAAAACGGTCAAGCAGAGCCAGGCA
CAAACAGAGCATCAAAATTAAGCGCTCTTCTCAGATCAGGGCTCATGCAACCTGAAGTCTGTAAGCCGAGTCTT---CCT
CTGAGTAATTGTGAAGATCCTGAAATAAAAAGGCAA---GAAGATGGGGGAGTAGTGCAGGCTGTTAATGCAGATTTCTC
TCCGTGTCAAATTTTAGATAACCTAGAACAA---CCTCTGGGAAGCAGTCCCGCTTCTCGGGTTTGTTCCGAGACCCCAG
ACGACCTGTTAAATGATGACAAGGTAAAGGAGGATAACAGCTTTGCTGAAGGCGGCATGAAGGACAGATCTGCTGTTTTT
AGCAAAAGCGTCCTGAAA---GAATTCAGAAGGAGCCCCAGTCCCTTAGCCCAC---ACANTCTTGGCTCGGGGTCACCC
CAGAAGGGCCAGGAAACTCGAGTCCTCAGAAGAGGA-------------
>FalseVamp
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAATTTATTACTGACTGAAGACATAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGTGTTAGCAAGGAGCCAGCAGAGCAGATGGGCTAACAGTAAAGAAA
TATGTAATGAT---AGGCAGACTCCCAACACAGAGAAAAGGGTAGTTCTGAATGCTGATCCCTTGAATGAGAGAAAAGAA
CTGAATAATCAGAAACCTCTATGCTCTGACAGTCCTAGAGAT---TCCCAAGAC---GTTCCTTGGATAACACGTAATAG
TAGCATACAGAAAGTTAATGAGTGGTTTTCCAGACGTGATGAAATACTAACTTCTCATGGTTCACATGATGGGACAGGTG
GATCAAATACAGAAGAAGCTGGTGCAGCAGAAATTCTAAAT------GAAGTAGATGGATATTCTGGTTCTTCAGAGAAA
ATAGCTTTAATGGCCAGTGATCCTCCTGGTGCTTCAATTTGTGAAAGTGAAAGAGTCTACTCCAAACCAGTAGAAAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTACAGGAGGAAGGCAAGCCTCCCTAACTTGGGCCACAGAGCTGAAAATC
TAATTATAGGAGCATCTGCTGTAGAACCTCAGATAATACAA---------------------------------------
---------------------GAGTGTCTCCTCATAAATAAACTAAAGCGTAAAAGGAGAACTACATCAGCCCTCCATCC
TGAGGATTTTATCAAGAAAGTAGATGTGGCAGTTGTTGAAAAGATTCCTGGAGATAGAATCAAGGGAACTGACCAAATAG
AGCAGCAT---------GGTCATGTGATGAATATTACTAATTATGGTCATGAGAATGAAACA------------------
------------AATGCTCACTCAACAGAA------TCACTGGACAAAGAATCTGCTTTTAGAACTAAAGCTGAACCTAT
AAGCAGCAGTATAAGTAATATGGAACTAGAATTAAATATCCACAGTTTAAAAGCACCTAAGAAGAATAGGCTGAGGAGGA
AGTCCTCTACAAGGCATATTCATGCACTTGAACTA---GTCAGTAGAAATCCAAGCCCACCTAATCATACTGAACTACAG
ATTGATAGTTGTTCTAGCAATGAAGAG---GTGGAGAAGAAA---AACTCTGACCAAATGCCAGCCAGACACAACAAAAA
TCTTCAACTTATAGAAGATAAAGAACCTGCAACTAGAGCTAAGAAGAGTAACAAGCCAGATGAACAAATAAATAAGAGAC
TTACCAGTGATGCTTTTTCAGAACTAAATTTAACAAACACACCTGGTTTTGTTACCAACAGTTCAAATTCTGATAAACTT
AAAGAGTTTGTCAATCCTAGCCTTCAAAGAGAAGAAATAGAAGAGCAT---CTGGGAACGATTAAAGTGTCTAATAGTAC
CAAAGACCCCAAAGATCTGATACTAAGTGGAGGAAGA---GGTTTGCAA---ACCGATCGTTCTATGGAGAGTACCAGTA
TTTCATTGGTACCTGATACTGATTATGGCACTCAGGCTAGTATGTCATTACTGGAACCTGACACCCCAGGG---AAGGTA
AAA---ACAGCACCAAATCGACGTGCAGGTGTGTGTGCTGCAATTGAAAACCCCAAGGAAATTATCCATGGTTGT---TC
TAAAGATACTAGAAATGACACAGGGGACTTTAAGGATCCACTAAGAGGTGAAGTTAAC---CACACNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NTTTCAAATCCAGGAAATCCAGAAAAGGAATGTGCAACAGTCTGTGCCCACTCCAGTTCCTTAAGGAACGAAAGTCCAAA
GGTCACTCTTGAATGTGGACAAAAAGAAGAAAATCACGGAAAGAAAGAGTCCAAAATCAAGCATGTGCAGGCAGTTCCAA
CAACTGCAGGCTTTCCTGTGGTTTGTGAGAAAGAAAAAAATCCAGGAGATTATGCCAAATATACCAAAAAAGGAGTCTCT
AGGCTTCGTCAGTCATCTCAGATCAGA---GGCAACAAAACCGAACTCACTGTTACAAATAAACATGGAATTTCTCAAAA
CCCATATCATATACCACCCATTTCTTCCATCAGGTCATCTGTTAAAACTATATGTAAGGAAAAC---CTGTCAGAGGAAA
ACCTTGAGGCATATTTGGTGTCACCTGAAAGAGCAATGGGAAATGAGAGCATTGTTCAAAGTACAGTGAGCACAGTTAGC
CAAAGTAACATTAGAGAAAGCACTTTTAAAGAGGGCAGCTCCAGCAATATTTATGAAGCAGATTCCAGTGCTAATGAAGT
AGGCTCTAGTATCAGTGAGGTAAGTTCCAGT---------------------GGTGAGAACATTCAAACAGAACTGGGTA
GAAACCAAGGACCAAAATTAAATGCTGTGCTCAGATTAGGTCTCATGCAACCTCAAGTCTATGTGCAAAGCCTT---CCT
GTAAGCAATTGTGAACATTCTGAAATAAAAAGGCAAGGAGAAAATGAAGGAGTAGTTGAGGCTGTTAATGCAGAATTCTC
TCCATGTCAAACTTCAGATAACCTGGAACAA---CCTATGGGAAGTAGTCATGCTTCTCAAATTTGTTCTGAGACACCGG
ATGACCTGTTAAACGATTATGAAATAAAGGAAAATGTTAGCTTT---------------AAGGAAAGATCTGCTGTTTTT
AGCAAAAGTGTCCAAAAAGAAGAATTGAGTAGAAGCCCTAGCCCCTTAATCCAT---ACATGTTTAGCTCAGGGTCACCG
AAGA---------------------------------------------
>LeafNose
TGTGGCACAAATACTCATGCCAGCTCTTTACATTATGAGCACAGCAGTTTATTACTCACTGAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAGCAGCCTGGCTTAGCAAGGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCCAGCACAGAGGAAAATGTAGTTCTGAATACTGATCCCCTGAATGGGAGAAAAGAA
CTGAATAAGCAGAAACCTCCATGCTCTGACAGTCCTAGGGAT---TCCCAAGTT---GTTGCATGGATAACACAGAATAG
TAGCATACAGAAAGTTAATGAGTGGTTTTCCAGACGTGATGAAATATTAACTTCTCATAGCTCATGTTATGGGAGAGCTG
AATCAAATACAGAAGTATCTGGTGCAGTAGAAGTTCCACTT------GAAGTAGATGGATTTTCTGGCTCTACAGAGAAA
ATAACCTTAATGACCAGTGATCCTCATGATGCTGTAATATGTGAAAGTGGAAGAGTCCACTCCAAACCATTGGAAAGTAC
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCTAACTTCAGCCACACAACTGAAAACA
TAATTATAGGAGCATCTGCTGTAGAACCTCAGATAACACAA---------------------------------------
---------------------GAGTGTCCCCTCACAAACAAACTAAGGCGTAAGAGGCGAACTACGTCAGGCCTTCATCC
TGAGGATTTCATCAAGAAAGTAGATTTGACAGTTGTTCAAAAGACTCCTGAAAAGATAATTGAGAGAACTCACCAAACAG
AACAGAAT---------GGTCATGTGATGAACATTACTGATAATGGTCATGGGAATGAAACAAAAGGTGATTAT---GTT
CAGAAAGAGGATAATGCTAACCCAACAGAA------TCATTGGAAAAAGAATCTGCTTTCAGAACTACAGCTGAACCTAT
AAGCAGCAGTATAAGCCATATGGAACTAGAATTAAATATCCATAGTTCAAAAGCACCTAAGAAAAATAGGCTGAGGAGGA
AGTCCTCTACCAGGCCTATTCATGCACTTGAACTAGTAGTCAGTGGAAATCCACGCCCACCTAGTCAGACTGAGCTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---GTGAAGAAAAAA---ATTTCTGACCAAGTGCCAGTCACACACAGCAAAAC
GCTTGAACTCATAGAAGATCAAGAACCTGCAAATGGAGTCAAGAAGAGGAACAAGCCAAATGAACAAATAAATAAGAGAC
TTACCAGTAATGCTTTTCCAGAACTAAATTTAACAAACATACCTGGTATATTG---AACCGTTCAAGTTCAAATAAACTT
CAAGAGTTTGTCAATCCTAGCCTTCAAAGAGAAGAAATAGAAGAGAGC---CTAGGAACAATTCAAGTGTCTAATAGTAC
CAAAGGCCTCAAAGATTTGATATCAAATGGGGGAAGA---GGCTTGCAA---ACTGGTCAATCTATGGAAAGTACCAGTA
TTTTATTGGTACCTGATACTGATTATGGCAGTCAGGATAGTATGTCATTACTCGAACCTGACACCCCAGGG---AAGGCA
AAG---ACTGCACCAAATCAACATGTGGGTGTATGTACAGCAGTTGAAAACCCCGAGGAACTTATCCATGGTGGT---TC
TAATGATACTAGAAATGACACAGAGAGCTTTAAGGATTCATTGAGACATGAAGTTAAC---CACGGTCAGGAGACAAGCA
TAGAAATGGAAGAGAGTGAACTTGATACACAGTATTTACAGGAAACATTCAAGGTTTCAAAGCGTCAATCATTTGCTCTG
TTTTCAAATCCAAGAAATCAAAGAAAGGAATGTGCAACAATCCAGTCCAGGTCC------TTAAGGAAACAAAGTGCAAA
AGTCACTCTTGAATGTGGACAAAAAGAAGAAAATCAGGGAAAGAAAGATTCTAAAATCAAGCTTGTACAGGCAGTTCATA
CAACTGCAGGCTATCCTGTGGTTTGTGAGAAAGATGAAAATCCAGGAGATTATGCCAAATACAGCACAAAAGGAGTCTCT
AGGCTTTGTCAATCATCTCTGTTCAGA---AGCAACGAAACTGAACTCACTATTGCAAATAAACATGGAATTTCTCAAAA
CCCACATAATATACCACATATTTCTCCCATCAGGTCATCTGTTAAAACTGTATGTAAGAAAAAC---CTGTCAGAGGAAA
ACTTGGAGGAATATCCAGTGTCACCTGAAAGAGCAATGGGAAATGAGAGCATCATTCAAAGTACAGTGAGCACAATTAGC
CAAAATAACATTAGAGAAAGCACTTTTAAAGAAAGCAGCTCAAGCAATNTTTATGAAGCAGATTCCAGTACTAATGAAGT
AGGCTCTAGTATCAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCAAGCAGAACTCGGCA
GAAACAGAGGACCGAAATTAAATGCTGTGCTCGGATTAGGTCTCGTGCAACCTGAAGTCTATAGGCAAAGCCTT---CCT
GTAAGTAATTGTCAACATCCAGAAATAAAAAGGCAGGGAGAAAATGAAGGAATAGTTCAGGCTGTTAGTGCAGACTTCTC
TCCATGTCAAATTTCAGATAACCTAGAACAA---CCTACGGGAAGTAGTCATGCTTCTCAGGTTTGTCCTGAGACACCGG
ATGACCTGTTAAATGATAACGAAATAAAGGAAAATGACAGCTTTGCTGAAAGTGACATTAAGGAAAGATCTGCTGTTTTT
AGCAAAAGTGTCCAGAAAGGAGAATTCAGAAGGAGCCCTAGCCCCGTAGCTCAC---ACACGTTTGGCTCAGGGTCACCA
AAGACGGGCCAGGAAATTAGAGTCCTCAGAAGAGGA-------------
>Horse
TGTGGCACAAATACTCATGCCAGCTCATTGCAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAAGAGCCAACAGAGCAGACGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGGCCCCCAACTCAGAGGAAAAGCTAGTTCTGAATGCTGATCCGCTGTATGGGAGAGAAGAA
CTGAATAAGCAGAAACCTCCACGCTCTGACAGTCCTAGAGAC---TCCCAAGAT---GTTCCTTGGATAACACTGAATAG
TAGCATACAGAAAGTTAATGAGTGGTTTTCCAGAAGTGAGGAAATGTTAACTTCTGATGACTCATGTGACGGAGGGCCTG
AATCAAATACAGAAGTAGCTGGTGCAGTAGAAGTTCCAAAT------GAAGTACGTGGATATTCTGGTTCTTCAGAGAAA
ATAGACTTAATGGCCGGTGATCCTTCTAGTGCTTTAATATGTGAAAGTGAAAGAGTCCGCTCCAAACCAGTAGAGAATAA
T---ATTGAAGATAGAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCTTCCCTAACTTGAGCCACATAACTGAAGATC
TAATTATAGGGGCATCTGCTATAGAACCTCAGATTACACAA---------------------------------------
---------------------GAGCGTCCACTCACAAATAGAGTGAAGCATAAAAGGAGAACGTCATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGTAGATTTGGCAGTTGTCCAAAAGACTCCTGAAAAGATAATTGAGGGAACTGACCAAATAG
AGCAGAAC---------AGTCATGTGATGAATATTACTCCTAATGGTCATGGGAATGAAACAAAAGGCGATTAT---GTT
CAGAATGAGAAAAACGCTTACCTAACAGAA------TCATTGGAGACAGAATCTGCTTTCAGAACTAAAGCTGAACCTAT
AAGCAGCAGCATAGGCAATCTGGAACTGGAATTAAATATCCACAGTTCAAAAGCACCTAAGAAGAATAGGCTGAGGAGGA
AGTCTTGTACCAAGCAGATTCATGCACTTGAACTAGTAGTCAGTAAAAATCCAAGCCCACCTAATCATACTGAACTACAA
ATCGATAGTTGTTCTAGTAGTGAAGAG---ATGAAGAAAAAA---AATTCTGACCAAATGCCGGTCAGACACAGCAAAAA
GCTTCAACTCATGGAAGATAAAGAACCTGCCACTGGAGCCAAAAAGAGTAACAAGCCAAATGAACAAATAAATAAAAGAC
TTGCCAGTGATGCTTTTCCAGAGCTAAAATTAACAAACATACCTGGTTTTTTTACTAACTGTTCAAGTTCTAATAAACTT
CATGAGTTTGTCAATCCTAGCCTTCAAAGAGAAGAAATAGAACAGAAC---CTAGGAGCAAATCGACTGTCTAATAGTGC
CAAAGACCCCAAAGATCTGATATTAAGTGGAGGAAAA---TGTTTGCAA---GCTGAAAGATCTGTAGAGAGTTCCGGTA
TTTCATTGGTACCTGATACTGATTATGGGACTCAGGATAGTATCTCACTGCTGGAAGCTGACACCCTAGGG---AAGGCA
AAA---ACAGCACCAAATCAATGTGCAAATCTATGCGCAGCAATTGAAAACCCCAAGGAACTTACCCATGATTGT---TC
TAAGGATACTAGAAATGATACACAGGGCGTTAAGGATCCATTGAGACGTGAAGTTAAC---CACACTCAGGAGACAAGCA
TAGAAATGGAAGAGAGTGAATTTGATACGCAGTATCTACAGAATATGTTCAAGGTTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCAAATCCAGGAAGTCCAGAAAAGAAGTGTGCAACAGTCAGTGCCCACTCCAGGTCCTTAAGGAAACAAAGTCCAAA
AGTCACTCTTAAATGTGGACAAAAAGAAGGAAAGGAGGGAAAGAAAGAGTCTAAAATCAAGAATGTGCAGTCAGTTCACA
CAACTGTGGGCTTTCCTGTGATTTGTCAGAAAGATAAGAAGCCAGGTGACTATGTCAAATGTAGCACAAAAGAAGCCTCT
AGGCTTTGTCAGTCATCTCAGTTCAGA---GGCAACGAAACNGAACTTATTACTGCAAATAAACATGGAATTTCACAAAA
CCCATATTATATACCATCACTTTCTCCCATCAGGTCATCTGTTAAAACTGTATGTCAGAAAAAC---CTGCCAGAGGGAA
AGCTTGAGGAACAGTCACTGTCACCTGAAAGAGCAATGGGAAATGAGAGCATTGTTCAAAGTACAGTGAGCACAATTAGC
CAAAATAACATTAGAGAAAGCACATTGAAAGAAGTCAGCTCAAGC---------------------AGTATTAATGAAGT
AGGCTCTAGTATTAATGAAGTAGGTTCCAGT---------------------GGTGAACACATTCAAGCAGAACTAGGCA
GAAACAGAGGACCTAAATTAAATGCTATTCTCAGATTAGGTCTTATGCAACCTGAAGTCTATAAGCAAAGTCTT---CCT
ATAAGTAATTGTAAACATCTGGAAATAAAAAGGCAAGGAGAAAAGGAA---GTAGTTCAGGCTGTTAACGCAGACTTTTC
TCCGTGTCTAATTTCAGATAACCTAGAACAA---CCTATGGGAAGTAGTTGTGCTTCTCAGGTTTGTTCTGAGACACCTG
ATGACCTGTTAAATGATGACGAAATAAAGGAAAATATCAGCTTTGCTGAAAGTGGCGTTAAGGAAAGATCTGCCGTTTTT
AGCAAAAGCGTCCAGAAAGGAAAGTTCAGAAGGAGTCCTAGCCCTATAGGCCGT---ACGTGTTTGGCTCAGGGTCACCA
AAGACGGGCCAGGAAATTAGAGTCCTCAGAAGAGAACACGTCTAGTGAG
>Rhino
TGTGGCACGAATACTCATGCCAGCTCATTGCAGCATGAGAACAGCAGTGTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGTGAACAGCCTGGTTTAGCCAAGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCCAACTCAGAGAAAAAGCTAGTTCTGAACGCTGATCCYCTGTATGGGAGAAAAGAA
CTGAATAAGCAGAAACCTCCATGTTCTGACAGTCCTAGAGAT---TCCCAAGAT---ATTCCTTGGATAACACGGAATAG
TAGCATACAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAAATATTAACTTCTGATGACTCACATGATGGGGGGCCTG
AATCAAATACTGAAGTAGCTGGTGCAGTAGAAGTTCAAAAT------GAAGTAGATGGATATTCTGGTTCTTCAGAGAAA
ATAGGCTTAATGGCCAGTGATCCTCCTGGTGCTTTAATATGTGAAAGTGAAAGAGTCCACTCCAAACCAGTAGAGAATAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCTTAACTTGAGCCACATAACTGAAGATC
TAATTATAGGAGCATCTGCTATAGAATCTCAGATTACACAG---------------------------------------
---------------------GAGCGTCCCCTCACAAATAAACTGAAGCATAAAAGGAGAACTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGTAGATTTGGCAGTTGTCCAAAAGACTCCTGAAAAGATAATTGAGGGAACTGACCAAATAG
AGCAGAAC---------GGTCGTGTGATGAGTATTGCTAATAATGGTCATGAGAATGAAACAAAAGGTGATTAT---GTT
CAGAAAGAGAAAAATGCTAACCCAACAGAA------TCATTGGAGAAAGAATCTGCTTTCAGAACGAAAGCTGAACCTAT
AAGCAGCAGCATAAGCAATCTGGAACTGGAATTAAATATCCACAGTTCAAAAGCACCTAAGAAGAATAGGCTGAGGAGGA
AATCCTCTACCAGGCATATTCATGCACTTGAACTAGTAGTCAGTAGAAATCTAAGCCCACCTAATCATACTGAACTACAG
GTTGATAGTTGTTCTAGCAGTGAGGAG---ATGAAGAAGAAA---AGTCCCAGCCAGGTGCCAGTCAGACATAGCAGAAA
GCTTCAACTCACMGAAGATAAAGAACCCGCAGCTGGAGCCAAGAAAAGTAACAAGCCAAATGAACAGATAAATAAAAGAC
TCGCCAGTGATGCTTTTCCAGAACTAAAATTAACAAACGTACCTGGTTTTTTTGCTAACTGTTCAAGTTCTAATAAACTT
CAAGAGTTTGTCAATCCTAGCCTTCAAAGAGAAGACATAGAACGGAAC---CTAGGAGCAATTCAAGTGTCTAATAGTAC
CAAAGACCCCGAAGATCTGATATTAAGTGGAGGAAGA---GGTTTGCAR---GCTGAAAGATCTGTAGAGAGCACCAGTA
TTTCATTGGTACCTGATACTGATTATGGCACTCAGGGTAGTATCTCATTACTGGAAGCTGACACCCTAGGG---AAGGCA
AAA---ACAGCACCAGATCAACGTGCAAGTCTATGTGCAGCAATTGAAAACCCCAAGGAACTTATCCATGATTGT---TC
TAAAGATACTAGAAATGACACAGAGGGCCTTAAGGATCCATTGAGATGTGAAGTTAAC---CACACTCAGGAGACAAGCA
TAGAAATGGAAGAGAGTGAACTTGATACACAGTATCTACAGAATACGTTCAAGGTTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCAAATTCAGGAAATCCAGAAAAGGATTGTGCAGCAGTCTCTGCCCACACCAGGTCTTTAAGGAAACCAAGTCCGAA
AGTCACTCTTGAATGTGGACAAAAAGAAGAAAATCAGGGAAAGAAAGAGTCTAAAGTCAAGCATGTGCAGTCAGTTCATA
CAACTGTGGACTTTCCTGTGGTTTGTCAGAAAGATAAGAAACCAGGTGATCATGTCAAATATAGCATAAAAGAACTCTCT
AGGCTTTGTCAGTCATCTCAGTTCAGA---GGCAATGAAACTGAACTCATTACTGCAAATAAACGTGAACTTTCACAAAA
CCTGTGTTATATACCATCACTTTCTCCCATCAGGTCATCTGTTAAAACTATATGTAAGAAAAAT---GTGTCAGAGGAAA
AGCTTGAGGAACATTCAGTGTCCCCTGAAAGAGCACTGGGAAACAAGAGCGTCATTCAAAGTACAGTGAGCACAATTAGC
CAAAATAACATTAGAGAAAGCACTTTTAAAGAAGTCGGCTCAAGCAGTATTAATGAAGTAGATTCCAGTACTAATGAAGT
AGGCTCTAGTATTAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTGAAGCAGAGCTAGGCA
GAAACAGAGGACCTAAATTAAATGCTATTCTCAGATTAGGTCTTATGCAACCTGAAGTCTATAAGCAAAGTCTT---CCA
ATAAGTAATTGTAAACATCCGGAAATAAAAAGGCGAGGAGAAAATGAAGGAGTAGTTCAGCCTGTTAATGCAGATTTCTC
TCCGTGTCCAATTTCAGATAACCTAGAACAA---CCTGTGGGAATTAGTTGTGCTTCTCAGGTTTGTTCTGAGACACCTG
ATGACCTATTAAATGACAACGAAATAAAGGAAAATATCAGCTTTACTGAAAGTGGCATTAAGGAAAGATCTGCTATTTTT
AGCAAAAGCGTCCAGAAAGGAGAATTCAGAAGGAGCCCTAGCCCTTTAGCCCGT---ACATGTTTGGCT---------CA
AAGAGGGGCCAGGAAATTAGAGTCCTCAGAAGAGAACATGTCTAGTGAG
>Pangolin
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATAAATGTAGA
AAAGACTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCTGCAAAGCAGATGGGCTGAATGTAAAGAAA
CATGTAACGAT---AGGCAGGCTCTCAGCACAGGGAAAAAGGTAGTTCTGAATGCTGATCCCCTGTGTGGGAGAAAAGAA
CTGAATAAGCAGAAACCTTCATGCTCTGACAGTCCTAGAGTT---TCTCAAGAC---GTTCCTTGGATAACACTAAATAG
TAGCATACRGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAAATGTTAACTTCTGATGATCCATGTGATGGGAGGTCTG
AATCAAATACTGAAGTAGCTGGTGCAGTAGAAGTTCCAAAT------GAAGTAGATGAAAATTGTGGTTCTTCAGAGAAA
AAAGACTTAATGGCCAGTGATCCTCATGATGCTTTAATACGTGAAAGTAAAAGAGGCCACTCCAAACCAGTAGAGAGTAA
T---ACTGAAGATAAAATATTTGGGAAAACCTATCGGAAGAAGGCAAGTCTCTCTCACTTGAGCCACGTAACTGAAAATC
TAATTATTGGAGCATTTGCAGTAGAACCTCAGATAACACAA---------------------------------------
---------------------GAGCGTCCCCTCAGAAATAGAGTAAAGCGTAAAAGGAGAACTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGTAGATTTGGAAGTTGTTCAAAAGACTCCTGAAAAGATAATTGAGGGAACCGACCAAATAG
AGCAGAAT---------GCTCTTCTGATGAATAGAACAAATAACGGTCATAAGAATGAAACAAAAGGTGATTAT---GTT
CAGAAAGAGAAAAATGCTAACCCAACAGAA------TCATTGAAAAAAGAACCTGCTTTCAGAACTAGAGCTGAACCTAT
AACCAGCAATATAAGCAATATGGAGCTAGAATTAAATATCCATAGTTCAAAAGTACTTAAGAAGAATAGGCTGAGGAGGA
AGTCTTCTACCAGGCACATTCATGCACTTGAACTAGTAGTCAATAGAAATCCAAGCCCCCCTAAACATACTGAACTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAGTTGATGAAA---------------AACCAAATACCAGTCAAACATNCCAAAAA
GCTTCAACTCAAGGAAGATAGAGAACCTGCATCTAGAGCCAAGAAGAGTAACAAGCCAAATGAACAAATAAATAAAAGAT
TTACCAGTGACACTTTTCCAGAACTAAATTTAACAAACATACCTGGTTTTTTTAGTAAATGTTCAAGTTCTAATAAACTT
CAAGAGTTTGTTGACCCTAGCCTTCAAAGAGAAGAAATAGAAAATAAT---CTAGAAACAATTCTA------------AC
CAAAGACCCCAAAGATGTGATATTACATAGAGGA------GGTTTGCAA---ACTGAAAGATGTGTAGAGAGTAACAGTA
TTTCATTGGTACCTGATACTGATTACGGCACTCAGGATAGTATCTCATTACTGGAAGCTGACACACTAGGG---AAGACA
AAA---ACAGCACCAAATCAATGTGCAAGTCTGTGTGCAGCAATTGAAAACCCCAAGGAACTTACCCATTGTTGT---GC
TAAAGATATTAGAAATGACACAGAGAGCTTTAAGGATCTATTGAGACATGAAGATAAC---CACACTCAGGAGACAAGCA
TAGGAACGGAAGAGAATAAACTTGATAAGCAGTACTTACAGAATACTTTCAGGGTTTCAAAGCATCAGTCATTTGCTCAG
TTTTCAAATATGGGAAATCCAGAAAAAGAATGTGCAGCAGTCAGTGCCCACTCTGGGTCCTTAAGGAAACAAAGTCCAAA
AGTCACTCTTGCATATGGACAAAAAGAAGAAAATGAGGGAAAGAAAGAGTCTGAAATCAAGCATGTTCAAACAATTCATA
CAACTGCAGGCCCTCTTGTGGTTAGTCAGAAAGATGAGAAGCCAGGTGATTATGTAAAATTTGGCATAAAAGGAGTCTCT
ACGCATTGTCAGTCATCTCAGTTCAGA---GGCAATAAAACTGAACTTATTTTTGCAAATAAACCTGGAATTTCACAATA
CCCATATCATATATCATCAATTTCTCCCATCAGGTCATCTGTTAAAATAATATGTAAGGAAAAC---CTGTCAGAGGAAA
AGTCTGTGGAACATTCGATGTCATTGGAAAAAGCAGTGGGAAACAAGAGCATCATTCAAAGTACTGTGAGCACAATTAGC
CAAAATAACATTAAAGGAAACAATTTTAAAGATGGCAGCTCCAGCAGCATTAATGAAATAGGTTCCAGTACTAATGAAGT
AGGCTCTAGTATTAATGAAGTAGGTTCCAGT---------------------GGTGAAAAAATTCAAGCAGAACTAGGTA
GAAACAGAGGACCTAAATTAAGTGCTGTGCTCAGATTAGGTCTTATGCAACCTGAGGCCTATAAGCAAAATCTT---CTT
ATAGGTAATCGTAAACACCCTGAAATTAAAAGACAAGGAGAAAAAGAAGGAGTAGTTCAGGTTGTTAATGCTGATTTCTC
TCCATGTCTAATTTCAGATAACCTAGAACAA---CCTATGGGAAGTAGTCATGCTTCTCAGGTTTGTTCTGAGACACCTG
AGGACATATTAAATGGTGATGAAATAAAGGAAAATATCGGCTTTGCTGAAAGTGGTATTAAGGAAAGATCTGCTGTTTCT
AGCAAAAGTGTCCAGAAAGGAGAATTCAGAAAGAGCCCAAGCCCTGTAGTCCAT---ATGAGTTTGTCTCAGAGTCACCA
AAGAAGAGCTGGGATAATAGAGTCTTCAGAAGAGAACATGTTTAGTGAG
>Cat
TGTGCCACAAATACTCGTGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGGCAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATGAAAGCAAACAGCCTGGCGTAGCAAGGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCCAGCACAGAGAAAAAGGTAGTTCTGAATGCTGATCCCCTGTGTAGGAGAAAA---
CTGAGTAAGCAGAAATCTCCATGCTCTGACAGTCCTAGAGAT---TCCCAAGAT---GTACCTTGGATAACACTGAATAG
TAGCATACAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAAATGTTAACTTCTGATGACTCACATGATGAGGGATCTG
AATCGAATCCTGGAGTAGCTGGTGCA---GAAGTTCCAAAT------GTAGTGGATGGATATTCTGGTTCTTCTGAGAAA
ATAGACTTAATGGCCAGTGATCCTCATGATGCTTTGATATGTGAAAGTGAAAGAGTTCACACCAAACCAGTAGAGAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTTCCTAACTTGAGCCACACAAGTGAAGATC
TCATTATAGGAGCATGTGCTATAGAACCTCAGATAACGCAA---------------------------------------
---------------------GCCTATCCCCTCACAAATAAAACAAAGCGTAAAAGGAGATCTACCGCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGTAGATTTGGCCATTGTTCAAAAGACTCCTGAAAAGCTAATTGAGGGAACCGATCGAATAG
GGCAAAAT---------GGCCATGTGATGAATAGAACAAATAATGGTCCTGAGAATGGGACAAAAGGTGATTAT---GTT
CAGAAAGAGAAAAATGCTAAGCCAACAGAA------TCATTGGAAAAAGAATCTGCTTTTAGAACCAAAGCTGAACCAAT
AAGCAGCAATATAAGTAATATGGAATCAGAATTAAATAGCCACAGTTCAAGGGCACCTAAGGAGAACAGGCTGAGGAGGA
AGTCCTCTACCAGGCACATGCGTGCGCTGGAATTAGTAGTCAATAGAAATCCAAGCCCACCTGATCATACCGAACTACAG
ATTGATAGTTGTTCTAGCAGTGAAGAGATGGTGAAAAGAAAA---AGTTCGGAACAAATGCTAGTCAGACACAGCAAAAC
ACTTCAACTCGTGGAAAATAAAGAACCTGCACCTGGAGCCAAGAAGCGTAACAAGCCAAGTAAACAAATAAATAAAAGAC
TTGCCAGTAACACTTTTCCAGAGCTAAATTTAACAAACATACCTGGGGTTTTTACTAACTGTTCAAGTTCTAATACACTT
CAAGAGTTTGTCAACCCTGGCATTCAAAGAGAAGAACTAGAAGAGAGC---CGAGGAACGATTCACGTGTCTGATAGGAC
CAGAGATCCCAAAGCGCTGGTATCGAGTGGAGGAAGA---AGTTTGCAA---ACTGAAAGATCTGTAGAGAGTACCAGTA
TTTCATTGGTACCTGATGCCGATTATGGCACTCAGGATAGTATCTCATTACTGGAAGCTGACACCCTAGGG---AAGGCA
AAA---ACAGCACCAAATCAACGTGTGAGTCTGTGTGCAGCAATTGAAAACCCCAAGGAAGCTATCCGTGGTTGT---TC
CAAAGATACTAGAAATGGCACAGAGAGTTTTACAGATCCTCTGAGACGTGAAGATANC---CATACTCAGGAGACAAGTA
TAGAAATGGAAGAGAATGAACTTGATACGCAGTGGTTATACAATACGTTCAAGGGTTCAAAACGTCAGTCATTTGCTCTG
TTTTCAAATCCAGGAAACCCAGAAAAGGAATGTGCTACAGCCTGGGCCCGTTCCACGTCCTTAAGGAAACAAAGTCCAAA
AGTCGCTCTTGAATATGAACAAAAAGAAGAAAATCAGGGAAAGAATCAGTCTGAAATCAAGCATGTGCAGGCAGTCCGTG
CAACTGCAGGCTTTTCTGCAGTCAGTCAGAAAGTGGAGAAGCCAGGTGATTATGCCAAATGTAGCATAAAAGGAGTCCCT
GGGCTCTGTCAGTCATCTCAGTTCAGA---GGCAATGAAACTGAACTCTTTATTGCAAATAACCATGACATTTCAAAAAA
CCCTTATCATATACCACCACTTTCTCCCATCAGATCATCTGTTAATGCTGTATGTAAGAAAAAC---CTGTCAGAGGAAA
AGTTTGAGCAGCGTTCAATGTCACCTGAAAGAGCAGTGGGAAATGAGAGCGTCATTCAAAGTACAGTGAACACAATTAGC
CAAAATAACATTAGAGAAAACACTTTTAAAGAAGTTAGCTCAAGCAGTGTTAATGAAGTAGGTTCCAGTGCTAATGAAGT
AGGCTCTAGCATTAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCAAACAGAACTGGGTA
GAAACCGAGGACCTAAGTTAAGTGCTATGCTCAGGTTAGGTCTTATGCAACCTGAAGTCTATGAGCAAAGTCTT---CCT
ATAAGTAATTGTAAATGTCCAGAAATGAAAAGGCAAGGAGAAAATGAAGGAGTAGTTCAGTCTGTTAATGCAGATTTTTC
TCCATGTCTAATTTCCGATAATGTAGAACAA---CCTATGGAAAGTAGCCGTGCTTCTCAGGTTTGTTCTGAGACACCCA
ATGACCTATTAAATGGTGATGAAATAAAGGGAAAAATCAGCTTTGCTGAAAGT---GCTAAGGAAAGATCTGCTGTTTTT
GGCAAGAGTGTCCAGAAAGGAGAATTCAGAAGGAGCCCTAGCCCTTTAGACCAT---ACACATCTGGCTCAGGGTCACCA
AACAGAGACCAGGAAGTTAGAGTCCTCAGAAGAGAACGTGTCTAGTGAG
>Dog
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAACACAGAATGAATGTAGA
AAAGGCTGAAATCTGTAATAACAGCAAACAGCCTGGCTTAGCAAGGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGATTCCCAGCACAGAGAAAAAGGTAGTTGTGAATGCTGATCTCCTGTGTGGGAGAAAAGAA
CTGAATAAACAGAAACCTCCACACTCTGATAGTCCTAGAGAT---TCCCAAGAT---GTTCCTTGGATAACACTGAATAG
TAGCATACGGAAAGTTAATGAGTGGTTTTCCAGAAGTGACGAAATATTAACTTCTGATGATTCACATGACAGAGGATCTG
AATTGAATACTGAAGTAGGTGGTGCAGTAGAAGTTCCAAAT------GAAGTGGGTGAATATTCTGGTTCTTCTGAGAAA
ATAGACTTAATGGCCAGTGATCCTCAGGATGCTTTCATATGTGAAAGTGAAAGAGTCCACACCAAGCCAGTAGGAGGTAA
T---ATCGAAGATAAAATATTTGGAAAAACCTATCGGAGGAAGGCAAGCCTCCCTAAGGTGAGCCACACAACTGAAGTTC
TAACTATAGGAGCGTGTGCTATAGAACCTCAGACAATGCAA---------------------------------------
---------------------ACCCATCCCTTCATGAATAAAGCAGAGCATAAAAGGAGAACTACATCTAGCCTTCATCC
TGAGGATTTTATCAAGAAAGTAGAGTTAGGCATTGTTCCAAAGACTCCTGAAAAGCTAATTGAGGGAATCAACCAAATCA
AGCGAGAT---------GGTCATGTGATAAATATTACAAATAATGGTCCTGAGAATGAAACAGAAGGTGATTAT---GTT
CAGAAAGAGAAAAATGCTAACCCAACAGAA------TCATTGGAAAAAGAATCTGCTTTTAGAACCAAAACTGAACCAAT
GAGCAGCAGGATAAGCAATATGGAACTGGAATTAAATAGCTCCAGTTCAAAAGCACCTAAGAAGAACAGGCTGAGGAGGA
AGTCCTCTGCCAGGCACACTTGTGCCCTTGAATTCGTAGTCAATAGAAATCTAAACCCACCTGATCATAGTGAACTACAG
ATTGAAAGTTGTTCTAGCAGTGAAGAG---ATGAAGAAACAG---CATCTGGACCAAGTACCAGTCAGACACAACAAAAC
ACTTCAGCTCATGCAAGATAAAGAACCTGCAGGTAGAGCTAAGAAAAGTAGTAAGCCAGGAGAACAAATAAATAAGAGAC
TCGCCAGCCATGCTTTTCCAGAGCTAACTTTAACAAATGTATCTGGTTTTTTTGCTAACTATTCAAGTTCTAGTAAGCCT
CAAGAGTGCATCAACCCTGGCCTTCGAAGAGAAGAAATAGAAGAGAGC---CGAAGAATGACTCAAGTGTCTGATAGTAC
CAGAGATCCCAAAGAGCTGGTATTGAGTGGAGGAAGA---GGTTTGCAA---ACTGAGAGATCTGTAGAGAGTACCAGTA
TTTCATTGGTACTTGATACTGATTATGGTACACAGGACAGTATCTCATTACTGGAAGCTGACACCCTGAGG---AAGGCA
AAA---ACAGTATCAAATCAACAGGCGAATCTGTGTGCAACAATTGAGAACCCCAAGGAACCTATCCATGGTTGT---TC
TAAGGACACTAGAAATGACACAGAGGGTTTTGTAGTTCCATTGACGTGCAAAGATAAC---CACACTCAAGAGACAAGCA
TAGAAATGGAAGAGAGTGAACTTGACACGCAGTGCTTACGCAATATGTTCAAGGTTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCATATCCAAGAGATCCGGAAGAGGACTGTGTAACAGTCTGTCCCCGCTCTGGGGCCTTTGGAAAACAAGGTCCAAA
AGTCACTCTAGAATGTGGACAGAAAGAAGAAAGTCAGGGAAAGAAAGAGTCTGAAATCAGACATGTGCAGGCAGTTCATA
CAAATGCAGGCTTTTCTGCAGTTAGTCAGAAAGCTAAGAAGCCAGGCGATTTTGCCAAATGTAGCATAAAGGGAGTCTCT
CGGCTTTGTCTGTCATCTCAGTTCAAA---GGCAAGGAAACTGAACTCCTTATTGCAAATTACCATGGAATTTCCCAAAA
CCCTTATCATATACCACCACTTTCTCCCATCAGATCATGTGTTAAAACTCTATGTCAGGAAAAC---CTGTCAGAGGAAA
AGTTTGAGCAACATTCAATGTCACCCGAAAGAGCAGTGGGAAATGAGAGAGTCATTCAAAGTACAGTGAGCACAATTAGC
CAAAATAACATTAGAGAATGTGCTTCTAAAGAAGTCGGCTCAAGCAGTGTTAATGAAGTAGTTTCCAGTACTAATGAAGT
AGGCTCTAGTGTTAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCAAGCAGAACTAGGTA
GAAACCGAGGACCTAAATTAAATGCTATGCTCAGATTAGGTCTTATGCAACCTGAAGTCTGTAAGCAAAGCCTT---TCT
TTAAGTAATTGTAAACATCCAGAAATGAAATGGCAAGGACAAAGTGAAGGAGCAGTTCTGTCTGTTAGTGCAGATTTCTC
TCCATGTCTGATTTCAGATAACCCAGAACAA---CCTATGGGAAGTAGTCGGTCTTCTCAGGTTTGTTCTGAGACACCTG
ATGACCTATTAAATGGTGACAAAATAAAGGGAAAAGTCAGCTTTGCTGAAAGTGACATTAAGGAAAAATCTGCTGTGTTT
AGCAAAAGTGTCCAGAGTGGAGAGTTCAGCAGAAGCCCTAGCCCTTCAGACCAT---ACACGTTTGGCCCAGGGTTACCA
GAGAGGGACCAAGAAATTAGAGTCCTCAGAAGAGAACATGTCTAGTGAG
>Llama
TGTGGCACAGATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAGGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGTCTTAGCAAGGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGACA
CATGTAATGAT---AGGCAGACTCCCAGCACAGAGAAAAAGGTGGCTCTGAATGCCGATCGCTTATATGGGAGCGAAGAA
CTGAATAAGCAGAAACCTGCATGCTCTGACAGTCCTAGAGAT---TCCCAAGAT---GTTCCTTGGATAACACTGAATAG
TAGCATACAGAAAGTGAATGAGTGGTTTTCCAGAAGCGACGAAATGTTACCTTCTGATGACTCACATGAAGTGGGGCCTG
AATCAAATACTGAAGTAGCTGGTGCAGTGGAAGTTCCAAAT------GAAGTAGATGGCTATTCAGGCTCTTCAGAGAAA
ATAGACTTAATGGCCAGTGATCCTCATGGTGCTTTAAAATGTGAAAATGAAAAAGTCCACGCCAAACCAGTAGGGAGTAA
C---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCTAACTTGACCCACAGAGCTGAAGATC
TAATTCTAGGAGCATCTGTTCTAGAGCCTCAGATAACACAA---------------------------------------
---------------------GAGCGCCCCTTCACAAATAAACTAAAGCGTAAAAGGAGAACTCTACCAGGTCTTCATCC
TGAGGATTTTATCAAGAAAGTCGATTTGGCCGTTGTTCAAAAGTCTCCTGAAAAGATAATTGAGCGAACAGACCAAACAG
AGCAGAAT---------GGTCATGGGATGAATATTACTAGTAATGGTCATGAGAATGAAACAAACGACGATTAT---GTT
CAGAAAGAGAAAAATGCTAACCCAACAGAA------TCATTGGAAAAAGAATCTGCTTTCAAAACTAAGGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTGAATACCCATAGTTCAAAAGCACCTAAG---AATAGGCCGAGGAGGA
AGTCCTCTACCAGGCAGATTCATGCACTTGAACTAATAGTCAGTAGAAACCCAAGCCCACCTAATCACACTGAACTACAG
ATTGAGAGTTGTTCCAGCAGTGAAGAG---ATGAAGGAAAAA---CATTCTGACCAAATGCCAGTCAGGCACCGCAAAAA
GCTTCAGCTCACGGGAGATAAAGAACCTACGACTGGAACCAAGAAGAGTAACAAGCCACATCAACAAATAAATAAAAGAC
TTGTCGGTAACACTTTTCCAGAACTAAATTTAACAAACACACCTGGTTTTTTTACTAAGTGTTCAAGTTCTAATAAACTT
CAAGAGTTTGCCAATCCTAGCCTTCAAAGAGAA---------GAGAAC---CCAGGAGCAATTCAAGTATCGAACAGTAC
CAAAGACCCCAAAGTTCTGATATTAAGTGGAGGGAGA---GGTTTACAA---ATTGAAAGATCTGTAGAGAATACCAGTA
TTTCCTTGGTACCTGAAACTGATTATGACACTCAGGACAGTGTCTCATTACTGGAAGCTGACACCCTAGGG---AAGGCA
AAA---ACAGCACCAAATCAATGTGTGAGTCTCTGTGCAGCAACTGAAAACCCCAAGGAACTTATCCATAGTTGT---TC
TAAAGATACTAGAAATGGCACAGCAGGCTTTAAGGATCCATTGGGATGTGATGTTAAT---CACACTCAGGAGGCAAGCA
TGGAAGTGGAAGAGAGTGAACTTGATACTCAGTATTTGCAGAATACGTTCAAGGTTTCAAAGCGTCAGACATTTGCTCTG
TTTTCAAATCCAGGAGATTCAGAAAAGGAATGTGCAACGATCTATGCCCACTCTGGGCCCTTAAGGGAACAAAGTCCAAA
AATCACTCTTGAATGTGGACAAAAAGAAGAAAATCAGAGAAAGAGCAAGTCTGAAATCAAGCATATGCAGGCAGTTCATA
CAACTTTGAACTTTCCTGTGGTTGGTCAAAAAGATAAG---CCGAGTGATTATGCCAAATATAGCCCAAAAGGAATATCT
AGGCTTTGTTGGCCATCACAGCTCAGA---GGCAATGAATCTGAGTTCATTATTGCAAATAAACATGGGATTTTACAAAA
CCCATATCTTATAACATCACTTTCTCCTAACAGGTCATCTGTTAAAACTATGTGTAAGAAAAAC---CCGTCCGAGGAAA
AGCTTGAGAAATGTGTCATATCACCTAAAAGAGTGATGGGAAACGAGAGCACCATTCAAAGTATAGTGAGTGCAATGAGC
CAAAATAACATTAGAGAAAGCACTTTTAAAGAAGTCAGCTCAAGCAGTGTCAATGAAGTAGGTTCCAGTACTAATGAAGT
AGGTTCTAGTATTAATGAAGTAGGTTCCAGT---------------------GGCGAAAACATTCAAGCAGAACTAGGTA
GAAACATGGGACCTAAATTAAATGCTATGCTCAGATTAGGTCTTTTGCAACCTGAAGTCTGTAAGCAAAGTCTT---CCT
GTAAGTAATTGTAAACAACCTGAAATAAAAAGGCAAGGAGAAAATGAAGGCATCTTTCAGGCTGTTAATACCGACTTCTC
TCCATGTCTAATTTCAGATAACCTAGAACAA---CCTATGGGAAGCAGTCATGCTTCTCAGGTTTGTTCTGAGACACCTG
ATGACCTGTTATATGATGACGAAATAAAGGAAAATACCAGCTTTGCTGAAAGTGACATTAAGGAAAGATCTGCTGTTTTT
AGCAAAAGTGTCCAAAAA---GAATTCAGAAGGAGCCCTAGCCCTTTAGTGCAT---ACGCATTTGGCTCAGGGTCACCA
AAGAGGGGCTAGGAAATTAGAGTCCTCAGAAGAGAATGTGTCTAGTGAG
>Pig
TGTGGCACAGATACTCATGCCAGCTCGTTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTTTGTAATAAAAGCAAGCAGCCTGTCTTAGCAAAGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGGCA
CATGTAATGAT---AGGCAGACTCCTAACACAGAGAAAAAGGTAGTTCTGAATACTGATCTCCTGTATGGGAGAAACGAA
CTGAATAAGCAGAAACCTGCGTGCTCTGACAGTCCTAGAGAT---TCCCAAGAT---GTTCCTTGGATAACATTGAATAG
TAGCATACAGAAAGTTAATGAGTGGTTTTCTAGAAGCGATGAAATGTTAACTTCTGACGACTCACAGGACAGGAGGTCTG
AATCAAATACTGGGGTAGCTGGTGCAGCAGAGGTTCCAAAT------GAAGCAGATGGACATTTGGGTTCTTCAGAGAAA
ATAGACTTAATGGCCAGTGACCCTCATGGTGCTTTAATACGTGAACGTGAAAGAGGGCACTCCAAACCAGCAGAGAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCTAACTTGAGCCACGTAATTGAAGATC
TAATTTTAGGAGCATCTGCTGTAGAGCCTCAAATAACACAA---------------------------------------
---------------------GAGCGCCCCCTCACAAATAAACTAAAGCGGAAAAGGAGAGGTACATCAGGCCTTGATCC
CGAGGATTTTATCAAGAGAGCCGATTCGGCAGTTGTTCCAAAAACTCCTGAAAAGACAATTGAGGGAACTGATGAGACAG
AGCAGAAT---------GGTCAGGGGATGAATATTACCAGTAAAGGTCATGAGAATGAAACAAAAAGTGGTAAT---GTT
CAGAAAGAGAAAAATGTTAACCCAACTGCA------TCGTTGGGAAAAGAACCTGCTTTCAGAGCTAGGGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTGAATATCCATGGTTCGAAAGCACCAAAG---AACAGGCTGAGGAGGA
AGTCCTCTACCAGGCAGATCCATGCACTTGAACTAGTAGTCAATAGAAACCCAAGCCCACCTAGTCATACTGAGTTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---ATGAAGAAGAGA---AATTCCGACCAAGTGCCAGTCAGGCACAGCAAAAA
GCTTCACCTCAGGGGAGATAAAGAACCTACAACTGGAGCCAAGAAGAATAATAGGCCACATGAACAAGTAAATAAAAGAC
CTATCAGTGATGCTTTTCCAGAACTAAATTTAACAAATGTACCTGTTTCTATTACTAACTGTTCAAATTCTAATAAGCTT
CAAGAATCTGTCAGTCCTAACCTTCAAAGAGAA---------GAGAAC---CTAGGGACAATTCAAGTGTCGAATAGTAA
CAAAGACCCCAAAGATGTGATGTTAAGTGGAGGAAAA---GGTTTTCAA---ATTGAAAGATCTGTAGAGAATACCAGTA
TTTCCCTGGTACCTGATACTGATTATGGCACTCAGGACAGTATCTCATTACTGGAAACTGACACCCTAGGA---AAGGCA
AAA---ACAACACCCAATCAACATGTGAGGCTGTGTGCAGCAACTGAAAACCCCAAAGAACTTAGCCTTGGTTGT---TC
TAAAGGTGTTAGAAACGACACAGGGGACTTTAAGGATCCCCTGGCTCATGATGTTAAC---CACACTCAGGAAGCAAGCA
TAGAAGTGGAAGAGAATGAACTTGATACACAGTATTTGCAGAGTATGTTCAAGGTTTCAAAGCGTCAGACATTTGCTCTG
TTTTCAAATCCAGCAAATCCAGAAAAGGAATGTACAACCGTCCATGCCCACTCCAAGTCCTTAAGAGAACAAAGTCCAAA
AGTCACTCATGAAGGTGGACAAAAAGATGAAAATCAGGGAAAGAGTGAGTCTAAAGTCAAGCATGGGCAGTCAGTTCATA
CAACTGTGGACTTTCTAGTGGTTGGTCAAAAGGATAAGAAGCCGAGTGATTTTGCCAAATGTGGTGCAAAAGGAGTAACT
GGGCTTTATCAGACATCACAGTTCAGA---GGCCACAAAACTGAGTTCATTAATGCAAATAAACCTGGGATTTCACAAAA
CCCATATGTCATACCATCCCTTTCTCCCATCAGGTCGTCTGTTAAAACTATATGTAAGAAAAAC---CTGTCAGAGGAAA
AGTTTGAGGAACCTAAAATGTCACCCGAAAGAACAATGGGAAACGAGAGCATCATTCCAAATACAGAGAGCACAGTTAGC
CAAAATAACATTCAAGAGAGAACTTTTAAAGAAGGCAGCTCAGGCAGTCCTAATGAAGTCGGGTCCAGTACCAACGAAGT
AGGCTCTAGTATTAATGAAGTAGGTTCCAGC---------------------GGTGAAAACGTTCGAGCAGAACCAGGTA
GAAACAGAGGACCTAAATTAAGTGCAATGCTCAGATTAGGTCTCATGCAACCCGAAGTTTATAAGCAAAGTCTT---CCT
GTAAGTAATTGTAACCACACAGAAATAAAAAGGCAAGGAGAAAATGAAGGCATATTTCAGGCTGTTAATGCAGATTTCTC
CCCATATCTAATTTCAGATAACCCCGAACAA---CCTATGGGAAGTAGTCATGCTTCTCAGATTTGTTCTGAGACACCTG
ATGACCTGTTAAATGATGACAAAATAAAGGAAAATCTCAACTTTGCTGAAAGTGACGTTAAGGAAAGATCTGCTGTTTTT
AGCAAAAGTGCCCAAGAAGGGGAATTTAAAAGGAGCCCTAGCCCTTTAGCCCAC---AGACGTTTGGCTCAGGGTCACCA
AAGATGGGCTAGGAAATTAGAGTCTTCAGAAGAGAGTGGGTCTAGTGAG
>Cow
TGTGGCACAGATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTGCTCACTGAAAACAGACTGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGTCTTAGTAAAGAGCCAGCAGAGCAGATGGGCTGAAAGTAAGGGCA
CATGTAAGGAT---AGGCAGATTCCCAGCACTGAGAAAAAGATAGTTCTGAATACTGATCCCCTGTACAGAAGAAAAGAA
CTGCGTAAGCAGAAACCTGCATGCCCTGACAGTCCTGGAGAT---TCCCAAGAT---GTTCCTTGGGTAACCCTGAATAA
TAGCATACAGAAAGTTAATGACTGGTTTTCCAGAAGTGATGAAATATTAACTTCTGATGACTCGTGCGATGGGGGGTYTG
AATCAAATAATGAAGTAGCTGGTGCAGTGGAAATTCCAAAT------AAAGTAGATGGATATTCAGGTTCTTCAGAGAAA
ATCAACTTAATGGCCAGTGATCCTCATGGTACTTTAATACAC------GAAAGAGTCCACTCCAAACCCGTAGAGAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGTCAAGTCTCCCTAACTTCAGCCACATAGCTGAAGATC
TAATTCTAGGCGCATTTACTGTAGAACCTCAGATAACACAA---------------------------------------
---------------------GAGCAGCCCCTCACAAATAAACTAAAATGTAAAAGGAGAGGTACATCAGGCCTTCAGCC
TGAGGATTTTATCAAGAAAGTCGATTTGACAATTGTTCCAAAGACTCCTGAAAAGATGACGGAGGGAACTGACCAAACAG
AGCAGAAA---------TGTCATGGGATGAATATTACTAGTGATGGTCATGAGAATAAAACAAAACGTGATTAT---GTT
CAGAAAGAGCAAAACGCTAACCCAGCAGAA------TCATTGGAAAAAGAATCTGTTTTCAGAACTGAGGCTGAACCTAT
AAGCATCAGTATAAGCAATATGGAACTAGAATTGAATATCCACCGTTCAAAAGCACCTAAG---AATAGGCTGAAGAGAA
AGTCCTCTACCAGGAAAATTCCTGAACTTGAACTAGTAGTCAGTAGAAACCCAAGTCTACCTAATCATACTGAGCTACCA
ATTGATAGCAGTTCTAGCAATGAAGAG---ATGAAGAAAAAA---CATTCTAGCCAAATGCCAGTCAGGCAGAGCCAAAA
GCTTCAACTCATTGGAGATAAAGAACTTACTGCTGGAGCC---AAGAATAACAAAACATATGAACAAATAAATAAAAGAC
TTGCTAGTGATGCTTTTCCAGAACTAAAGTTAACAAACACACCTGGTTATTTTACTAACTGTTCTAGT------AAACCT
GAAGAGTTTGTTCATCCTAGCCTTCAAAGAGAG---------GAGAAC---CTAGGAACAATTCAAGTGTCGAATAGTAC
CAAAGACCCCAAAGATCTGATATTAAGAGAAGGAAAA---GCTTTGCAA---ATTGAAAGATCTGTAGAGAGTACCAATA
TTTCCTTGGTTCCTGATACTGATTATAGCACTCAGGATAGTATCTCATTACTAGAAGCTAAAACCCCAGAA---AAGGCA
AAG---ACTGCACCAAATCCATGTGTGAGTCTGTGTACAGCAACCAAAAACCTCAAGGAACTTATCCATAGGGAT---TT
TAAAGATACCAAAAACAACACAGAGGGCTTTCAGGATCTACTGGGACATGACATTAACTACGTCATTCAGGAGACAAGCA
GAGAAATGGAAGACAGTGAACTTGATACACAGTATTTGCAGAATACATTCAAGGCTTCAAAGCGTCAGACATTTGCTCTG
TTTTCCAATCCAGGAAATCCACAAAAGGAATGTGCCACAGTCTTTGCCCACTCGGGGTCCTTAAGGGATCAAAGTCCAAG
AGACCCCCTCAAATGCAGACAAAAAGAAGACAGTCAGGGAAAGAGTGAGTCTAAAAGCCAGCACGTGCAGGCCATTTGTA
CAACAGTGCACTTTCCTGTGGCTGATCAGCAAGATAGGACGCCAGGTGACGATGCCAAATGTAGCGCAAAAGAAGTAACT
AGGGTTTGTCAGTCATCACAGTTGAGA---GGCCACAAAACTGAACTTGTTTTTGCAAATAAACAAGGGGTTTCAGAAAA
ACCAAATCTTATACCATCACTTTCTCCCATCAAGTCATCTGTTAAAACCATATGTAAGAAAAGC---CCATCAGAG---A
AGTTTGAGGAACCTGTAACGTCACCTGAAAAAACATTGGGGAGTGAGAGCATCATTCAAAGTGCAGTGAGCACAATCAGC
CAAAATAACATTCAAGAAAGCACTTTTAAAGAAGTCAGCTCAAACAGTGTAAATGAAGTAGGTTCCAGTACTAATGAAGT
AGGCTCTAGTGTTAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCAAGCAGAACCAGGTA
GAAACAGAGAACCTAAATTAAGAGCTTTACTCGGATTAGGTCTTACGCAACCTGAAGTCTATAAGCAAAGTCTT---CCT
GTAAGTAACTGTCACCATCCTGAAATAAAAAGGCAAGGAGAAAATGAGGACATGCCTCAGGCTGTTAAGGCAGATTTCTC
CCCATGTCTAATTTCAGATAACCTCGAACAA---CCTACGGGAAGCCGTCATGCTTCTCAGGTTTGTTCTGAGACACCTG
ACAACTTGTTAAATGATGATGAAATAAAAGAAAATAGCCACTTTGCTGAAAGTGACATTAAGGAAAGATCTGCTGTTTTT
AGTGAAAGTGTCCAAAAAGGAGAATTCAGAGGGAGCCCTGGCCCTTTCACCCAT---ACACATTTGGCTCAGGGTCACCA
AAGAGGGGCTGGCAAACTAGAG---TCAGAAGAGACTGTGTCTAGTGAG
>Hippo
TGTGGCACAGATACTCGTGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGCAGA
AAAGGCTGAATTCTGTAATAAAAGCNAACAGCCTCTCTTAGCAAAGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGACA
CATGTAATGAT---AGACAGACTCCCAGCACAGAGAAAAAGGTAGTTCTGAACGCTGATCCCCTATACGGGAGAAAAGAA
CTGAATAAGCAGAAACGTGCATGCTCTGACGGCCCTAGCGAT---TCCCAAGAT---GTTCCTTGGATAACACTGAATAG
TAGCATACAGAAAGTTAATGAATGGTTTTCCAGGAGTGGCGAGATGTTAACTTCTGACGACTTATGTGTTAAGGGGTGTG
AATCAAATACTGAAGTAGCTGGTGCAGCGGAAGTTCCAAAT------GAAATTGATGGGTGTTTGGGTTCTTCAGAGAAA
ATAGATTTAATGGCCCGTGACCCTCGTGGTGCCTTAATACGTGAAAGTGAAAGAGTCCACGCCAAACCAGTAGAGAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCTAACTTGAGCCACATAGCTGAAGATC
TAATTAAAGGAGCATCTGCTGTAGGACCTCAGATAACACAA---------------------------------------
---------------------GAGCGCCCCCTCACAAATAAACTAAAGCGTAAAAGGAGGCGGACATCGGGCCTTCATCC
TGAGGATTTTATCAAGAAAGTCGATGCGGCAGTTGTTCCAAAGACTCCTGAAAAGATAATTGAGGGAACTGATCAAACAG
AGCAGAAT------------------------------------GGTCATGAGAATGAAATGAAAGGTGATTAT---GTT
CAGAAAGAAAAAAATGCTAACCCAACAGAA------TCTTTGGAAAAAGAATCTGCTTTCAGAACTAAGGCTGAACCTAT
AAGCATCAGTATAAGCAATATGGAACTAGAATTGAATATCCACAGTTCAAAAGCACCTAAG---AGTACGCTGAGAAGGA
AGTCCTCTACCAGGCAGATTCATGCACTTGAACTAGTAGTCAGTAGAAACCCGAGCCCACCTAATCGTACTGAACTACAA
ATCGATAGTTGTTCTAGCAGTGAAGAG---ATGAAGAAAAAA---CATTCCTGCCAAATGCCAGTCAGGCACAGCAAAAA
GCTTCAATTCATGGGATATAAAGAACCCGCAACTGGAGTCAGGAAGAGTAATAAACCACACGAACAAATAAATAAAACAC
TTGCCAGTGGTGCTTTTCCAGAACTAAATGTAACAAACATACCTGGTTTTTTTACTAACTGTTCTAGTTCTAGTAAACTT
CAAGAGGTTGTTAATCCTGGCCTTCCAAGAGAG---------GAGAAC---CTAGGAACAATTCAAGTGTCAAATAGTAC
CAAAGACCCCAAAAATCTGATATTAAGTAGAGGAAAA---GGTTTGCAA---ATTGAAAGATCTATAGAGAGCACCAGTA
TTTCCTTGGTACCTGATACTGATTATGGCACTCAGGACAGTATCTCATTACTGGAAGCTGACACCCTAGGG---AAGGCA
AAG---ACAGCAACAAATCAACGTGTGGGTCTGTGTGCAGCAACTGAAAACCCCAAGGAACTTATCCATGGTTAT---TC
CAAAGATACTAGAAACGACATGGACGGCGTCCAGCATCCATTGGGACAGGATGTTAAC---CACACTCAGGATGCAAGCA
TAGAAGTGGAAGACAGTGAACTTGATACACAGTATTTGCAGAATACATTCAGGGTTTCAAAGCGTCAGACATTTGCCCTG
TTTTCAAATCCAGGAAATCCAGGAAAGGAACGTGCAACAGTCTGTGCTCATTCCGGGTCCTTAAGGGAACAAAGTCCAAG
AGTCCCTCTTGAATGCGGACAAAAAGAAGAAAATCAGGGCAAGAGTGAATCTAAA---------ATGCAGGCAATTTATA
CAACTGTGGACTTTGCTGTGGCTGGTCAAAATGATAGGAAGCCGAGTGATTACACCAAATGTAGCACTAAAGGAGTAACT
AGGCTTTGTCCCTCATCACAGTTTGGA---AGCAACAAAACTGAGCACATTATTGCAAATAAATATGGAATTTCACAAAA
CCCATATGTTATACCATCACTTTCTCCCATCAGGTCATCTGTTAAAACTATACGGAAGAAAAAC---CTGTCAGAGGAAA
AGTTTGAGGAACCTGTAGTGTCAGCTGAAAGAGCAATGGCAAATGAGAGCATCCTTCAAAGTACAGTGAACACAATTAGC
CAAAATAACATTCGAGAAAACACTTTTAAAGAAGTCAGTTCAAGCAGTATTAATGAAGTAGTTTCCAGTACTAATGAAGT
AGGCTCTAGTATCAGTGAAGTAGGTTCTAGT---------------------GGTGGAAACATTCAAGCAGAACTAGACA
GAAAGAGAGGACCTAAACTAAGTGCTTTGCTTAGATTAGGTCTTATGCAACCTGAAGTATATAAGCAAAGTCTT---CCT
GTAAGTAATTGTCAACATCCTGAAATAAAAAGGCAAGGAGAAAATGAAGGCATACTTCAGGCTGTTAATGCAGATTTCTC
CCCGTGTCTAATTTCAGATAACCTAGAACAA---CCTATGGGAAGCAGTCATGCTTCTCAGGTTTGTTCTGAAACACCTG
ATGATTTGTTAAATGATGACGGAATAAAGGAAAATAGCAACTTTGCTGAAAGTGACATTAAGGAAAGATCTGCTGTTTTT
AGCAAAAATGTCCAAAAAGGAGAATTCAGAAGGAGCCCTGGCCCTTTAGCCCAT---ACACGTTTGGCTCAGGGTCACCA
AAGAAGGGCTGGGAAATTGGAGTCCTCAGAAGA----------------
>SpermWhale
TGTGGCACAGATACTCATGCCAGCTCATTACAGCATGAAAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGTCTTAGCAAAGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGACA
CATGTAATGAT---AGGCAGACTCCCAGTACAGAGAAAAAGGTAGTTCTGAATGCTGATCCCCTATATGGGAGAAAAGAA
CTGAATAAGCAGAAATCTGCATGCTCTGACAGTCCTAGAGAT---TCCCAAGAG---TTTCCTTGGATAGCAGTGAATAG
TAGCATACAGAAAGTTAATGAATGGTTTTCCAGAAGTGATGAAATGTTAACTTCTAACGACTTACGTGATGGGGGATTTG
AATCAAACCCTGAAGTAGCTCGTGCAGTGGAAGTTCCACAG------GAAGTTGATGGATATTTGGGTTCTTCAGAGAAA
ATAGACTTAATGGCCAGTGATCCTCATGGTGCTTTAATACGTGAAAGTGAAAGAGTCCACTCCAAACCAGTAGAGAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCTAACTTGAGCCACGTAGCTGAAAATC
TAATTATAGGAGCATCTACTGTAGGACCTCAGATTACACAA---------------------------------------
---------------------GAGCGCCCCCTCACAAATAAACTAAAGCGTAAAAGGAGAAGTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGTCGATTTGGCAGTTATTCCAAAGACTCCTGAAAAAATAATTGAGGGAACTGACCAAACAG
AGCAGAAT---------GGTCATGGGGTGAATATTACTAGTAATGGTCATGAGACTGAAATGAAAGGTGATTGT---GTT
CAGAAAGAGAAAAATGCTAACCTAACAGAA------TCATTGGAAAAAGAATCTGCTTTCAGAACTAAGGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTGAATATCCATAGTTCAAAAGCACCTAAA---AATAGGCTGGGGNGGA
TGTCCTCTTCCAGGAAGATTCATGCACTTGAACTAGTAGTCAGTAGAAACCCAAGCCCACCTAATCATACTGAACTACAA
ATTGATAGTTGTTCTAGCACTGAAGAG---ATGAAGAAAAAA---CATTCCAGCCAAATGCCAGTCAGGTGCGGCAAAAA
GCTTCAATTCATTGGAGATAAAGAACCTACAACTGGAGCCAAGAAGAGTAACAAGCCACATGAACAAATAAATAAAAGAC
TTGACAGTGACACTTATCCAGAACTAAATTTAACAAACATACCTGTTTTTTTTACTCACTGTTCTAGTTCTAATAAACTT
CAAGAGTTTGTTAATCCTAGCCTTCAAAGAGAG---------GAGAAC---CTAGGAACAATTCAAGTGTCGAATAGTAC
TGAAGACCCCAAAGATCTGACATTAAGTGGAGGAAAA---GGTTTGCAA---ATTGAAAGATCTGTAGAGAGTTCCAGTA
TTTCCTTGGTACCTGATACTGATTATGGCACTCAGGATAGTATCTCATTACTGGAAGCTGACACCCTAGGG---AAGGCA
AAG---ACAGCACCAAATCAACATGTGAGTCTGTGTGCAGCAATTGAAAGCCCCAAGGAACTTATCCACGGTTGT---TC
TAAAGATATTAGAAACGACACAGAGGACTTTAAGGATCCACTGGGACATCACGTTAAC---CACATTCAGGAGGCGAGCA
CAGNNNNNNNNNNNNNNNNACTTGATACTCAGTTTTTGCAGAATATGTTCAAGGTTTCAAAGCGTCAGACGTTTGCTCTG
TTTTCAAATCCAGAAAATCCAGAAAAGGAATGTGCAACAGTCTGTGCCCACTCTGGGTCCTTAAGAGAACAAAGTCCAAG
AGTCCCTCTTGAATGCAGACAAAAAGAAGAAAATCAGGGAAAGAGTGAGTCTAAAATCAAGCATGTGTGGGCAATTAATA
CAACTGTGGACTTCCCTGTTGCTGGTCAAAAAGATAAG---CCGAGCGATCATGCCAAACGTAGCCCCAAAAGAGTAACT
AGGCTTTGTCAGTCATCACAGTTCAGA---AGCAACAAAACTGAGCTCATTATTGCAAATAAACATGGGATTTCACAAAA
CCCATATCTTATACCATCACTTTCTCCCATCAGGTCATCTGTTAAAACTATATGTAAGAAAAAC---CTGTCAGAGGAAA
AGTTTGCGGAACCTGTAATGTCACCTGAAAGAGCAATGGAAAACGAGAGCATCATTCAAAGTACAGTGAGCACAATCAGC
CAAAATAACATTCGAGAAAGCACTTTTAAAGAAGTCAGCTCAAGCAGTACTAATGAAGTAGGTTCCAGTACCAATGAAGT
AGGCTCTAGTATTAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCAAGCAAAACTAGATA
GAAACAGAGGACCTAAATTAAGTGCTTTGCTCAGATTAGGTCTCATGCAACCCGAAGTCTATAAGCAAAGTCTT---CCT
GTAAGTAACTGTCAACTTCCTGAAATAAAAAGGCAAGGAGAAAATGAAGGCACACTTCAGGCTGTTAATGCAGATTTCTC
CCCATGTCTAGTTTCAGATAACCTAGAACAA---CCTATGGGAAGAAGCCATGCTTCTCAGGTTTGCTCTGAGACATCTG
ATGAGTTGTTAAATGATGACAAAATAAAGGAAAATAGCAACTTTGCTGAAAGTGACATTAAGGAAAGATCT---GTTTTT
AGCAAAAGTGTCCAAAAAGGAGAATTCAGAAAGAGCACTGGCCCTTTAGCCCATCATACATGTTTGGCTCAGGGTCACGA
AAGAGGGGCT---------GAGTCCTCAGAAGAGAAAGTGTCTAGTGAG
>HumpbackW
TGTGGCACAGATACTCATGCCAGCTCATTACAACATGAAAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGTCTCAGCAAAGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGACA
CATGTAATGAT---AGGCAGACTCCCAGTACAGAGAAAAAGGTAGTTCTGAATGCTGATCCCCTGTATGGGAGAAAAGAA
CTGAATAAGCAGAAACCTGCATGCTCTGACAGTCCTAGAGAT---TCCCAAGAG---TTTCCTTGGATAACAGTGAATAG
TCGCATACAGAAAGTTAATGAATGGTTTTCCAGAAGTGATGAAATGTTAACTTCTAACGACTCACGTGATGGGGGATTTG
AATCAAACACTGAAGTAGCTTGTGCAGTGGAAGTTCCAAAG------GAAGTTGATGGATATTTGGGTTCTTCAGAGAAA
ATAGACTTAATGGCCAGTGATCCTCATGGTGCTTTAATACGTGAAAGTGAAAGAGTCCACTCCAAACCAGTAGAGAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCTAACTTGAGCCACATAGCTGAACATC
TAATTATAGGAGCATCTACTGTAGAACCTCAGATAACACAA---------------------------------------
---------------------GAGCGCCCCCTCACAAATAAACTAAAGCGTAAAAGGAGAAGTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGTCGATTTGGCAGTTATTGCAAAGACTCCTGAAAAAATAACTGAGGGAACTGACCAAACAG
AGCAGAAT---------GGTCATGGGATGCATGTTACTAGTAATGGTCCTGAGACTGAAATGAAAGATGATTAT---GTT
CAGAAAGAGAAAAATGCTAACCTAACAGAG------TCATTGGAAAAACAATCTGCTTTCAGAACTAAGCCTGAACCTAT
AAGCAGCAGTATAGGCAATATGGAACTAGAATTGAATATCCATAGTTCAAAAGCACCTAAA---AATAGGCTGAGGAGGA
AGTCCTCTACCAGGAAGATTCATGCACTTGAACTAGTAGTCAGTAGAAACCCAAGCCCACCTAATCATACTGAACTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---ATGAAGAAAAAA---CATTCCAGCCAAATGCCAGTCAGGCACGGCAAAAA
GCTTCAATTCATGGGAGATAAAGCACCTACAACTGGAGCCAAGAAGAGTAACAAGCCACACGAACAAATAAATAAAAGAC
TTACCAGTGACGCTTATCCAGAACTAAATTTAACAAACATACCTGGTTTTTTTACTCACTGTTCTAGTTCTAATAAACTT
CAAGAGTTTGTTAATCCTAGCCTTCAAAGAGAG---------GAGAAC---CTAGGAAAAATTCAAGTGTCGAATAGTAC
CAAAGACCCCAAAGATCTGACATTAAGTGGAGGAAAA---GGTTTGCAA---ATTGAAAGATCTGTAGAGAGTACCGGTA
TTTCCTTGGTACCTGATACTGATTATGGCACTCAGGATAGTATCTCATTACTGGAAGCTGACACCCTAGGG---AAGGCA
AAG---ACAGCACCAAATCAACATGTGAGTCTGTGTGCAGCAATTGAAAGCCCCAAGGAACTTATCCATGGTTGT---TC
TAAAGATATTAGAAACGACACAGAGGACTTTCAGGATCCACTGGGACATCACGTTAAC---CACATTCAGGAGGCGAGCG
CAGAAATGGAAGAGAATGAACTTGATACACAGTATTTGCAGAATATGTTCAGGGTTTCAAAGCGTCAGACGTTTGTTCTG
TTTTCAAATCCA---------GAAAAGGAATGTGCAACAGTCTGTGCCCGCTCTGGGTCCTTAAGAGAACAAAGTCCAAG
AGTCCCTCTTGAATGCAGACAAAAAGAAGAAAATCAGGGAAAGAGTGAGTCTAAAATCAAGCATGTGCGGGCAATTAATA
CAACTGTGGACTTCCCTGTTGCTGGTCAAAAAGATAAGAAGCCGAGCGATCATGCCAAACGTAGCCCAAAAAGAGTAACT
AGGCTTTGTCAGTCATCACAGTTCAGA---AGCAACAAAACTGAGCTCATTATTGCAAATAAACATGGGATTTCACAAAA
CCCATATCTTATACCATCACTTTCTCCCATCAGGTCATCTGTTAAAACTATATGTAAGAAAAAC---CTGTCAGAGGAAA
AGTTTGAGGAACCTGTAAGGTCACCTGAAAGAGCAATGGAAAACGAGAGCATCATTCAAAGTACAGTGAGCACAATTAGC
CAAAATAACATTCGAGAAAGCACTTTTAAAGAAGTCAGCTCAAGCAGTATTAATGAAGTAGGTTCCAGTACTAATGAAGT
AGGCTCTAGTATTAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCAAGCAAAACTAGRTA
GAAACAGAGGACCTAAATTAAGTGCTTTGCTCAGATTAGGTCTTATGCAACCCGAAGTCTATAAGCAAAGTCTT---CCT
ATAAGTAACTGTCAACTTCCTGAAATAAAAAGGCAAGGAGAAAGTGAAGGCACACTTCAGGCTGTTAATGCAGATTTCTC
CCCAAGTCTAATTTCAGATAACCTAGAACAA---CCTATGGGAAGAAGCCATGCTTCTCAGGTTTGTTCTGAGACATCTG
ACGAGTTTTTAAATGATGACAAAATAAGGGAAAATAGCAACTTTGCTGAAAGTGACATTAAGGAAAGATCT---GTTTTT
AGCAAAAGTGTCCAAAAAGGAGAATTCAGAAGGAGCCCTGGCCCTTTAGCCCATCATACATGTTTGGCTCAGGGTCACGA
AAGAGGGGCT---------GAGTCCTCAGAAGAGAATGTGTCTAGTGAG
>Mole
TGTGGCATAAATACTCATGCCAGCTTATTACAGCATGAAAACAGCAGTTTATTACTCACTGAAAACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGACTTAGCAAAGAGCCAGCAGAACAGATGGGCTGAAAGTAAAGAAA
CATGTAATGAT---AGGCAGACTTCCAGCCCAGAGAAAAGGGTAGACCCGAATGCTGATCCCATGTATGGGAGAAAAGAA
CTGAATAAGCAGAAACCTCCATGCTCTGACAGCCCCAGAAAT---TCCCAAGGT---GTTGCCTGGATAACACTGAACAG
TAGCATTCGAAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAAATATTAACTTCTGATGAATCTCGTGATGGGGAGTCCC
CATCAAATATTGAAATGACTGGTGAAGTAGAAGTTCCAAAC------ACAGTAGATGGATTTTCTGGTTCTTCAGAGAAA
ATAGACTTAATGGCCAGCGATCCTCCC---GCTTTAATGTGTAAAAGTGAAAGAGTCCGCACCAAACCAGTAGAAAGTAA
T---ATTGAAGATAAGATATTTGGGAAAACCTATCGGAGGAAGACAAGCCTCCCAAACTTGAGCCACGTGGCTGAATATT
TAATTACAGGGACATCTGTCACAGAACCTCAGATAGTTCAA---------------------------------------
---------------------GAGCGTCCCTTCACAAATAGATTAAAACGTAAAAGGAGAACTCTACCAGGCCTTTGTCC
TGAGGATTTTATCAAGAAAGTAGATTTGGAAGTTGTTCAGAACACCCCTGAAAAGATAAGTGCGGGAACTGATCAAATGG
ATCAGAGT---------GGTCAAGTGATGGATGTTGCTTATAATGGTCATGGGAATGAAACAAAACGTGATTAT---GTT
CAGAAAGAGAAAAGTGCTAACCCAGCCGAA------TCTTTAGAAAAAGAATCTACCTTCAGAATTAAAGCTAAGCCCAT
AAGTAGCAGTATAAGCAATATGGAACTAGAATTAAATATCCACTCTTCAAAAGCACCTAAGAAGAACAGGCTGAGGAGGA
AGTCTTCTACCAAGCATATTCATGCACTTGAACTGGTGGTCAAAAGAAATCCAAGCCCACCTAATCATACAGAACTACAA
ATTGATAGCTGTTCTAGCAGTGAAGAG---ATGAAGGAAAGA---AATTCCAACCAAATGCCAGTAAGACACAGCAAAAG
GCTTCAACTCATGGAAGATAAAGACCCCGCAACTGAAGCCGTCAAGAGTAACAAGCCAAAAGAACAAATT---AAAAGAT
TTGCCAGTGATACTTTGCCAGAACTAAATTCAACACATGTACCTGGCTTTCTTAGCAACTATTCAAGTTCTAATAACCTT
GAAGAGTTTTCCAATCCTAGCCTTCAAAGAGAAGAACTAGAAGAGAAC---CTAGGAACAAATCAAGTGTCAAATAATAC
CAAAGACCCCAAAGATCCGATACTTAGTGGACAAAGA---GATTTGCAA---GCTGAAAGATCTGGCGAGAGTACCAATA
TTTCATTGGTACCTGAGACTGATTTTGGCAGTCAGGATAGTGTCTCATTACTGGAAATTGACATCCTAGGC---AAGGCA
AAA---AAAGTGCCGAATCAGTGTGCAAGTCTGTGTACAAAAATTGAAAACTCTAAGGAACTTATTCATAGTTGT---TC
TAAAGATACTAGAAATGACACACAGGGCTGTAAGGATCCACTGAAATACGAAGTTAAC---CACACTCAGGAGATAAGGA
TAGAGATGGAAGAGAATGAACTTGATACACAGTATTTACAGTCTACGTTCAAAGCTTCAAAGCGTCAATCATTTGCTCTG
TCTTCACATCCGGGAAATTCAGAAAAGAAATATCCCCCAGTCTCTGCCCCTTCCAGGTCCTTGAAGAGACAAACTCCAAA
AATCACTCTGGAATGTGAACTGAAAGAAGAAAATCAAGGGAAGAAAGAGTCTAAAACCGAGCATGTACAGGCAGTACATA
GAATTGCAGACTTAACTCTGGCTTGTCAGAACGATAAG---CCACATGATTCTGCCAAATGTAGCATAAAAGGAGTCTCT
AGGCTTTGTCAGTCATCTCAGTTCAGA---GGCAACGAAACAGAAGTCATTGTTGCAAATAAACGTTTAATCTTACAAAA
CCCATATCTTATTCCACCACTTTCTTCAATTCAGTCATCTGTTAAAAGTGCTTGTAAGAAAAAC---CTGGCGGAGGAAA
AGCTTGAGGAACACTCATGGTCACCCGAAAGAGAAACAGGAAACGGGAGCATCATTGAAAGTACAGTGAGCAGGGTTAGC
CAAAATAACAATAGAGAAAATGCTTTTAAGGAAGTCAGCTCAAGTAGTATTAACGAAGTAGGTTCCAGTACTAACGAAGC
TGACTCTAGTATTAATGAAGTAGGTTCCAGT---------------------GGTGAAAATATTCAAGCTGAACTAGATG
GAAGCAGAGGACCTAAATTAAATGCTATGCTCAGATTGGGTCTTATGCAACCTGAAGTCTATAAGCAAAGTCTT---CCT
AAAAGTACTTGTAAACATCCTGAAGTTAAAAGGCAAGGAGAAAATGAAGGCATAGTTCAGGCTGTTCATACAGATTTCTT
TCCATGTCTGATTTCAGATAACCAAGAACAA---CCTATGGGAAGTAGTCATGCTTCTCAGGTTTGTTCTGAGACGCCTG
AGGACCTGTTAAATGACGAAATAAAGGATAATAACATCAGCTTTGCTGACAGTGGCATTAAGGAAAGATCTGCTGTTTTT
AGCAAAAGTTTCCAGAAAGGAGAATTC---AGGAGCCCTAGCCTTTTAGACCAT---ACATGTTTGGCTCAGGACCACGA
AAGTGGG------AAATTGGAGTCCCCAGAAGAGACTATGTCTAGTGAG
>Hedgehog
---------------------------------CGTGAGAACAGCAGTTTATTACTCACTAAAGGCAAAATGAATGTAGA
AAAGGCTGAATTCTGTAGTAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACAGAGCAGATGGGCTGAAAATATGGAAA
CATGTAATGAT---AGGCAGACTCCTAGCCCAGACAAAGAAGTAGATCTGAATGCTGATTCCTTATATGAGAGAAAAGAA
CTAAACGAGCAGATCTCTTCATACTCCAGCAGTCCTAAAGAT---TCCAAAGAC---ATTTCTTGGGTAGCACTGAAT--
-AGCATACAGAAAGTGAATGAATGGCTTTCCAGAAGTGATGAACTGTTAACTTCTGATGACTCATATGATAAGGGATCTA
AATCAAAAACTGAAGTAACTGTAACAACAGAAGTTCCAAAT------GCAATAGATAGRTTTTTTGGTTCTTCAGAGAAA
ATAAACTTAACAGCCAGTGATCCTCATGTTGCTTTAATACGTGAAGGTGAAGGAGTCCACTTCAAACCAGTAAAGAATAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATGGGAGGAAGGCAAGCCTTCTTAATTTGAGCCACGTAACTGAAGATG
TAATTATAAGG------------GAACCTCAGGTAGCCAAA---------------------------------------
---------------------GAGCCTCTCCTTGCAACTAAATTAAAACGTAAAAGGAGAACTGATGTAGGTCTTTGTCC
TGAGGATTTTATCAAGAAAGTAGATGTGGCAATTGTTCAGAAGACTCCTGAAAAGATAATCAAGAGACCTGGCCAACTGG
ATCAAAGT---------GACCAAGTAATGAATATTGCTACTAATGGTCATGAAACTGAAACAAAGAGTGATTAT---GTT
CAGAAGGAGAAAAATGCTAACCCAGCAGAA------TCACCAGACAAAGAATCTGCTTTTAGAAATAAACCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTAAATGTCCACAGTTCAAAAGCACCTAAGAAGAATAAACTCAGGAGAA
AGTCATCTGCCAGGCATATTCATGCACTTGAAGTAGTAGTCAATAAAAACTCAAGCCCACCTAGCCATACAGAACTACAA
ATTGATAGCTGTTCTAGCAATGAAGAG---ATGAGGGGGGTG---AAAGCTGATCAAATGCCAGTCAGGCACAGCAAACA
ACTTCCACTCATTGAAGACAAAGAACCTGCAACTAGAGCCTTTAGTAGTAGCAAGTCAAATGAACAAATAAGTAAACAGT
TTGTTGGTGAGACTTTTTCAGACCTAAATTTAACAAACATCCCTGGTTTTCTTACCAGCTGTTCAAGTTCCAATAAACAT
CAGGAATGTATTAATCCTAACCTACAAAGAGAGGTATTAGGAGAAAGC---CGTGGGACTATTCAAGTGTGTAATAATAC
CAAAAACCCTAAAGATCTGATAGTAAGTGGAAAGAGA---GGTTTACAA---ATTGAAAGATCTGTAGAGAGTCCT----
--------GTAGAGAACACTGACTATGGCAGTCAGGATAGTATCTCATTACTGGAAACTGATACTCTAGGG---AAGGCA
AAA---AAGACACCAAATCAATGTGTAAGTCTGTGTGTAGCAACTGAAACCCCCAAAGAACTTAGCCATAGTTGT---TC
TAAAGATACTAGAAATGACACTGAAGGCTTTAGGGATTCACTCAGATGTGAAGTTGAT---CACACGCAGGAGACAAGCA
CAGAACTGGAGGAGAGTGAACTTGATACACAGTATTTACAGAATACCTTCAAGGTTTCAAAACGTCGGTCATTTGCTCTG
TTTTCAAGTCCAGAGAATTCAGAAAAGGCATGTACAAGAGGCTCTGTCCATTCTAAGTCTTTAAGGAAACAAAGTCCAAA
AGTTATTCTGGACTGTGAACAAAAAGAAGAAAATCAAGGAGAGAAAGCATCTGAAATCAAGTATTTGCCATCAGAACATA
CAACTACAGGCTTTCCTGTGGTGTGTTATAAAGATACA---TCAGGTGATTATGCCAAATGTAGCGTAAAAGGAGTCTCC
AGGCATTGTCAGCCATCTCGGTTCAGA---GGCAGTGAACCTGAACTCATTGTTGCAAATAAAAATTTAATTTTACAAAA
CCTATATCATATACCAACACTTCCTACCATCATGTCATCTACTAAGAGTATATGCAAGAAAAAC---CTGTCTGAGGAAA
AT------------TCACTGTCGCCTGAAAGAGCAGTGACAAACAAAAGCATCATCCAAAGTACAGTGAACACCATTAGC
CAGACTAATGCCAGTGAAAATGCTCTTAAAGATGTCAGTTCAAGCAGTGTTAATGATATGGGTTCCAGTACTAATGAAGT
AGGTTCCAGT------------------------------------------AGTGAAAACATTCAAGCTAAACTATGTA
GAAACAGAGGACCCAGATTAAATGCTACTCTTAGAGCAAGTCTTATGCAACCTGAAGTCTTTGAGCAGTGTCTT---CTG
ATGAGTAACTGTAAACATTCTGAAATGAAAAGACAAGGAGAAAATGAAGGTGTTATTCAGACTGTTAATATAGAATCCGA
TTCATGCCCAAGACCAGATAACTTAGAACAA---CCGGTGGAAACTAGTCAT---------GTTTGTTCTGAAACACCTG
ACGATCTGTTAAATGACGATGAAATGAAGGAAAATACAAGCTTTACTGAAAGTGGCATTAAGGAACAATCTGCTGTTTTT
GGCAAAAGTACCCAGAAAGGT---TTCAGAAGGAGCCCTAGCCCTTTAGGCCAC---ACATGTTTGAGACAGGATCAGCA
AAGAGGGGCACAAAAATCAGAGCCCTCTGAAGATTTCATGTCTAGTGAG
>TreeShrew
TGTGGCATAAATACTTATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAGGACAGAATGAATGTAGA
AAAGGCTGAATTGTGTAATAAAAGCCAACAACCTGACTTAGCAAGGAGCCAGCAGAGCAGATGGACTGAAAATAAGGAAA
CATGTAATGAT---AGGCAGATTCCCAGCACAGAAAAAAAGGTAGATCTAAATGCTGATCCCCTGTGTGGGAAGAAAAAA
CAAGCTAAGCAGAAACYGCTATGTTCTAACAGTCCTAGAGAT---GACCAAGAT---TCTCCTTGGATAACTCTAAATAG
TAGCATTCAGAAAGTTAATGAATGGTTTTCCAGAAGTGATGAAATGTTAACTTCTAACGACTCACATGATGGTGAGTCTG
AA------------ATAGCTGGTGCATTYGAAGYTCCAAAT------AAAGTAGATGAATATTCTGGTTCTTCAGAAAAA
ATAGACTTAATGGCCAACAATCTTCATGATGCTTTAATAAGTAAAAGTGAAGGAATCTACTCCAAACCAGTAGAGGGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAAGCAAGTCTTCCTAACTTGAGCCGTGTAACTGATGATC
TAATTAGAGGGGCATTTGTTACAGAGCCTGAGATAACTCGA---------------------------------------
---------------------GAGCGTCCCTTCACAAATAAATTAAAGCGGAAAAGGAGAACTATATCAGGCCTTCATCC
TGAAGATTTTATCAAGAAAACAGATTTGGCAGTTGTTCAAAAGACTCCTGAAAAGATAAATCAGAGAACTGACCAAATAG
AGCATAAT---------GGTCAGGTGATGAGTATTGCTAATAGTGGTCATGAGAATGAAACAAAAGGTGATTAT---ATT
TCGAAAGAGAAAAATGCTAACCCAATGGAA------TCATTAGAAAAAGAATCTGCTCTCAGAACTAAAGCTGAGCCCAT
AAGCAGCAGTGTAAGCAATATGGAACTAGAAATAAATAACCACAGTTCAGAAGCACCTAAGAAGAATAGGCTGAGGAGAA
AGTTTTCTGCTAGGCATATTCGCACACTTGAACTAGTAGACAATAAAAGTCCAAGCCCACCTAATCGTACTGAACTACAA
ATTGACAGTTATTCTAGCGGTGAAGAG---AGAAAGAAAAAG---GGT---GAGCAAATGCCAGTTGGACACAGCAGAAA
GTTTCAACTTGAGGAAGAGAAAGAACCTACAACTGGAGCCAAGAAAAATAACCAGCCAAATACAGAAATAAGTGAAAGAC
ATGCCAGTGGTGTTATCCCAGATCTGAAGTTAACAAACATACCTGGTTTTTTCACAAACTCTTCGAGTTCTAATAAACTT
CCAGAATTTGTCCATCGTAGCCTTCAAAGAGAAAAA---GAAGAGAAC---CGAGAAACAATTCAAATATCCAGTAGTAC
C---------AAAGATCTGGTATTAAGGGGAGAAAGG---GGTTTGCAA---GATGTAAGGTCTGCAGAGAGTACCAGTA
TTTCTTTGGTACCTGATACTGATGATAACACCCAGGATAGCATCTCATTACTAGATGCTAACCCCCTAGCTAGGAAGGCA
AAA---ACAGCACCAAATCAATGTGTAAATCAGAGTGCAACAACTGAAAACCCCAAGGAACTTATACACAGTTGT---TC
TAAAACTACTAGGAAT------GAAGGCTTCAAGGATCCATTGAAAAGTGAAGTTAAT---CATATTCAGGAGATGAGTG
TAGAAATGGAGGAGAGTGAACTTGATACTCAGTATTTACAGAATACATTCAGGAGTTCAAAGCGTCAGTCATTTGCTCTG
TCTTCAAATCCAGGAAATCCAGAAAAGGAACATGTCTGTGTT--------------------------------------
-------------------------------AAAGAAAGTCTGAAAGAGTCTAACATCCAACATATACAGGCAGTTAGTA
CC---------------ATGGTTTTTCAGAAAGATAAG---CTAGGTGATTTTGCTACATCTGGCATTAAAGAAGTCCCT
AGACTTTGTCCATCATCTCAGTTCAGA---GGCAATGAAACTGATCTCATTACTGCAAATAAACCTGAAGTTTCACAAAA
CCCGTATCATATGCCATTACTTTATCCTGTCAAGTCACCTATTATAACTAAAAGTAAGAAAAGC---CTGTCAGAGGAAG
GGTTTGAGGAACAGGCAATGTCACTTGAAAGAGCAATGGAAAATGAGAACATCATTCAAAGTACAGTGAGCACAATTAGC
CAAGATAACATTAGAGAAGGTGCTTTTAAAGAAGCCAGCTCAAGCAGTATTAATGAAATAGGTCCTAGTACTAATGAAGG
AAGCTCTAGTATTAATGAGGTAGGTTCCAGT---------------------GGTGAAAACATTCAAGCAGAACTAGGTA
AAAAGAGAGGATCCAAATTAAATGCTGTGCTTAGATTAGGTCTTATGCAACCCGAAGTCTATAAGCAAAGTCTT---CCT
TTAAGTAATCATAATGATCCTGAAATGAAAAGACAAGAAAAAAATGAAGGAGGAGTTCAGGCTATTAAA---GATTTACC
TCCATGTCTAATTTCAGATAATCAAGAGCAT------ATGGGAAGTAGCCATGCTTCTCAGATTTGTTCTGAGACACCTG
ATGATCTGTTAGATGATGATGAAGGAAAAGAAAAT---AGCTTTGCTGAGGTTGATGTTAAGGAAAGATCTGCTGTTTTT
GGCAAAACTGTCCAGAGAAGAGAGTTAAGAAGGAGCTCTAGCCCTTTAACTCGT---GCATGTTTGACTGAGGGTCAGCA
AACAGGAGCCCAGAAATTAGATTCATCAGAAGAGAACCTATCTAGTGAG
>FlyingLem
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACGCACTAAAGACAGAATAAATGTTGA
AAAGACTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAGGAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACGCCCAGCACAGAGAAAAAGATAGATCTAAATGCTGATTCCCAGCATGGGAGAAAAGAA
CGGAATATGCAGAAACCTCCATACCCTGAGAGTCCTAGAGAT---ACCCAAGAT---GTTCCTTGGATAACACTAAACAG
CAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAAATTTTAGCTTCTGATGACTCACGTGACAGGGTGTCTG
AATCAAATGCCAAAGTAGCTGGTGCATTAGAAGTTCCAAAT------GATGTAGATGGATATTCTGATTCTTCAGAGAAA
GTTGATTTAATGGCCAGTGATCCTCATGATGCTTTAATATGTAAAAGTGAAAGAATCCACTCCAGACCAGTAGAGAGTAA
T---ATCAAAGATAAAATATTTGGGAAAACCTATCAGAGGAAGACAAGCCTCCCTAACTTGAGCCACGTAAATGAAGATC
TAATTATAGGAGCATTTGTTACAGAACCACAGATAACACAA---------------------------------------
---------------------GAGCGTCCCCTCACAAATAAGGTAAAGCCTAAAAGGAGAACTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGCAGACTTGGCAGTTGTTCAAAAAACTCCTGAAAAGATAAATCAGGGAATTGACCAAATGG
AGCAGAAT---------GATCGAGTGATGAATATTATTAATAGTGGTCATGAGAATGAAACAAAGGATGATTAT---GTT
CAGAAAGAGAAAAATGCTAACCCAACAGAA------TCATTGGAAAAAGAATCTGCTTTCAGAACTAAAGCAGAACCTAT
AAGCAGCAGTATAAGCAATATGGAAATAGAATTAAATATCCACAATTCAAAACCATCTAAGAAGAATAGGCTGAGGAAGA
TGTCCTCTACTAGGCATATTCATGCACTTGAACTAGTAGTCAATAGAAATCCAAGCCCACCTAATTATACTGAACTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAA---ATAGAGAAAAAA---AATTCCAGCCAAATGCCAGTCAGGCACAGCAGAAA
GCTTCAACTCATGGAAAATAAAGAACCTGCAACTGGAGCCAAGAAGAGTAACAAGCCAAATGAACAAATAAGTAGAAGAC
ATTCCAGTAATGCTTTCCCAGAACTGCGGTTAACAAATGTACCTGTTTTTTTTGCTAACTGTTCAAGTTCTAATAAACTT
CAAGAATTTATCGATCCTAGCCTTCAAAGAGAAGAAATAGAAGAGAAC---CTAGAAACAATTCATGTGTCTAATAGTGC
CAAAGACCCCAAAGATTTGGTGTTAAGTGGGGAGAAG---GGTTTGCAA---ACTGAAAGATCTGTAGAGAGTACCAGTA
TTTCATTAGTACCTGATACTGATTATGGCACTCAAGACAGTATCTCAATATTAGAAGCTAACATCCTAGGG---AAGGCA
AAA---ACAGCACCAAGTCAACATGCAAATCAGTGTGCAGCAATTGAAAACCCCAAAGAACTTATCCATGGTTGT---CC
TAAAGGTACTAGAAATGACACAGAGGATTTTAAGGATCCATTGAGATGTGGAGTTGAC---CACATTCAGAAGACAAGCA
TAGAAATGCAAGAGAGTGAACTTGATACTCAGTATTTACAAAATATATTCAAGGTTTCAAAACGTCAGTCATTTGCTCTC
TTTTCAAATCCAGGAAATCCAGAAAAGGAGTGTGCAACAGTCTATGCCCACTCCAGGTTGTTAAGGAAACAAAGTCCAAA
AGTCACTCCTGAATGTGAACAAAAAGAAGAAAATGAGGGAAATAAAGAGTCTAAAATCAAGCACATACAGGCAGTTAATA
CCACTGTGGGCTTTTCTGTCCTTTGTCAGAATGTTAAGAAGCCAGGTGATTATGCCAAATTTAGCATTAAAGGAGTCTCT
AGGCATTGTTCATCATCTCAGTTCAGA---GGCAATGAAACTGAACTCATTACTGCAAATAAACATGGAATTTTACAAAA
CTCATGTCATATGTCATCACTTTCCCCCATCAGGTCATCTGTTAAAATTAAATGTAAGAAGAAC---CTGTCAGAGGAAA
GGTTTGAGGAACATTCAGTGTCACCTGAAAGAGCAATGGCAAACAAGAGAATCATTCAAAGTACAGTGAACACAATTAGC
CAAAATAACATTAGAGACAGTGCTTCTAAAGAAGCCAGCTCAAGCAGTATTAATGAAGTAGGTTCCAGTACTAATGAAGT
AGGCTCCAGTATTAATGAAGTAGGTCCCAGT---------------------GGTGAAAACATTCAAGCAGAACTAGGTA
GAAACAGAGGACCTAAATTAAGTGCTATGCTTAGATTAGGCCTCATGCAACCTGAAGTTTACAAGCAAAATCTT---CCT
TTAGGTAATTGTAAACATCCTGAAATA---AGGCAAGAAGAAAATGAAGGAATAGTTCAGGCTGTTAATACAAATCTGTC
TCTGTGCCTAATTTCACATAACCTCGAACAA---CCTATGGAAAGTAGTCATGCTTCCCAGGTTTGTTCTGAGACACCTG
ATGACCTGTTAGATGGTGATGAGATAAAGGAAAACACCAGCTTTGCTGAAAGTGACAGTAAGGAAAGATCTGCTGTTTTT
AGCAAAAGTGTCCAGAGAGGAGAGTTAAGCAGGAGCCCTAGCCCTTTTGCCCAA---ACATGTTTGGCTCAGGGTCACCA
AAGAGGAGCCAGGAAATTAGAGTCTTCTGAAGAGAACGTATCTAGTGAG
>Galago
TGTGGCAAAAATACTCATGCCAGCTCATTACAGCATGAGAGCAGCAGTTTATTACTCACTAAAGACAAAATGAATGTAGA
AAAGGCTGAATTTTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACAGAGCAGATCGGCTCAAAGTAAGGAAA
CATGCAATGAT---AGGCACACTTGCAGCCCTGAGCAAAAGGTAGATCTGAATACTGCTCCCCCATATGGGAGAAAAGAA
CAGAATAAGGAGAAACTTCTATGCTCCAAGAATCCTAGAGAT---AGCCAAGAT---GTTCCTTGGATAACACTAAATAG
CAGCATTCAGAAAGTTAATGAATGGTTTTCTAGAAGTGATGAAATGTTAACTTCTGATGACTCACATGATGAGGGTTCTG
AATCACATGCTGAAGTAGCTGGAGCCTTAGAAGTTCCAAGT------GAAGTAGATGGATATTCCAGTTCCTCAGAGAAA
ATAGACTTACTGGCCAGTGATCCTCATTATCCTATAATATGTAAAAGTGAAAGAGTTCACTCCAAACCAATAAAGAGTAA
A---GTTGAAGATAAAATATTTGGGAAAACTTATCGGAGGAAGGCAAGCCTCCCTAACTTAAGCCATGTAACTGAAAATC
TAATTATAAGAGCAGCTGCTACTGAGCCACAGATAACACAA---------------------------------------
---------------------GAGTGTTCCCTCACAAATAAATTAAAACGTAAAAGGAGAACTACATCAGGTCTTTGTCC
TGAGGATTTTATCAAGAAGGCAGATTTGGCAGTTGTTCAAAAGACACCTGAAAAGAGAATTCAGGGAACTAACCAAGTGG
ATCAGAAT---------AGTCACGTGGTAAATATTACTAATAGTGGTTATGAGAATGAAACAAAAGGTGATTAT---GTT
CAGAATGAAAAAAATGCTAACTCAACAGAA------TCATTGGAAAAAGAATCTTCTCTCGGAACTAAAGCTGAACCTAT
AAGCAGCAGTATAAGTAATATGAAATTAGAATTAAATATTCACAATTCAAAAGCAAGTAAAAAGAAAAGGCTGAGGAAGA
AGTCTTCTAGCAGGCATATTCGTGCACTTGAACTAGTAGTCAATAAAAATCCAAGCCCTCCTAATCATACCAACCTACAA
ATTGACAGTTGTTCTAGCAGTGAAGAA---ATAAAGGATAAA---AGTTCTGACCAAATACCAGTCAGGCATAGCAGAAA
GCCTGGACTCATGGAAGATAGAGAACCTGCAACTGGAGCCAAGAAAAGTAACAAGCCAAATGAGCAAATAAGTAAAAGAC
ATGTCAGTGATACTTTCCCAGAAGTGGCATTAACAAATATATCTAGTTTTTTTACTAACTGTTCAGGTTCTAATAGACTT
AAAGAATTTGTCAATCCTAGCCTTCAAAGAAAAAAAACAGAAGAGAACTTAGAAGAAACAATTCAAGTGTCTAATAGTAC
CAAAGGTCCGGTGTTAAGTGGAGAAAGGGTTTTGCAA---ATTGAAAGT---GAAGAAAGATCTATAAAAAGCACCAGTA
TTTCATTGGTACCTGATACTGATTATGGTACTCAGGACAGTAACTCGTTACTGAAAGTTAAAGTCTTACGG---AAGGTG
AAA---ACAGCACCAAATAAACATGCAAGTCAGGGTACAGCCACTGAAAACCCCAAGGAACTAATCCATGGTTGC---TC
TAAAGATACTGGAAATGACACAGAGGGCTATAAGGATCCATTGAGACATGAAATTAAC---CACATTCAGAAGATAAGCA
TGGAAATGGAAGACAGTGAACTTGATACTCAGTATTTACAGAATACATTCAAGTTTTCAAAGCGTCAGTCGTTTGCTCTG
TTTTCAAACCTAGGA---------AAGGAATGTGCAACAGTCTGTGCCCAGTCTCTCTCTGCGTCCTTAAGAAAAGGTTC
AAAAGTCATTCTTGAATGTGAACAAATAGAAAATCCAGGAATGAAAGAGCCTAAAATCAAGCATATACAGGGAAATAATA
TCAATACAGGCTTCTCTGTAGTTTGTCAGAAAGATAAGAAAACAGATGATTATGCCAAATACAGCATCAAAGAAGCATCT
AGGTTTTGTTTGTCAAATCAGTTTCGA---GACAATGAAACTGAATCCATTACTGTAAATAAACTTGGAATTTTACAAAA
CCTCTATCATATACCACCACTTTCTCCTATCAGGCTATTTGATAAAACTAAATGTAATACAAAC---CTGTTAGAGGAAA
GGTTTGAAGAACATTCAGTGTTACCTGAAAAAGCAGTAGGAAACGAGAACACCGTTCCAAGTACAATGAATACAATTAAC
CAAAATAAC---AGAGAAAGTGCTTATAAAGAAGCCAGTTCAAGCAGTATCAATGAAGTAAGCTCGAGTACTAATGAAGT
GGGCTCCAGTGTTAACGAAGTAGGCCCCAGT---------------------AGTGAAAACATTCAAGCAGAACTAGATA
AAAACAGAGGACCTAAGTTGAATGCTGTGCTTAGATTAGGTCTTATGCAACCTGAAGTCTATAAACAAAATCTT---CCT
ATAAGTAATTGTGAACATCCTAAAATAAAAGGGCAAGAAGAAAATGGA---GTAGTTCAACCTGTTAATCCAGATTTTTC
TTCATGTCTAATTTCAGATAACCTAGAACAA---CCTACGAGAAGTAGTCATGCTTCTCAGCTTTGTTCTGAGACACCTG
ATGACTTATTAGTTGATGATGAACTAAAGGAAAATACCAGTTTTGCTGAAAATAACATTAAGGAAAGATCTGCTGTTTTT
AGCAAAAATGTCATGAGAAGAGAGATTAGCAGGAGCCCTAGCCCTTTAGCCCAT---ATACATTTGACTCAGGCTCACCA
AAGAGAGGTTAGGAAATTAGAGTCCTCAGAAGAGAACATGTCTAGTGAA
>HowlerMon
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTGTTACTCACTAAAGACACACTGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACATAACAGATGGGCTGAAAGTGAGGAAA
CATGTAATGAT---AGGCAGACTCCCAGCACAGAGAAAAAGGTAGATGTGGATGCTGATCCCCTGCATGGGAGAAAAGAA
TGGAATAAGCAGAAACCTCCGTGCTCTGAGAATCCTAGAGATGATACTGAAGAT---GTTGCTTGGATAATGCTAAATAG
CAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAACTGTTAACTTCTGATGACTCACATGATGGGGGGTCTG
AATCAAATGCCAAAGTAGCTGAAGCATTGGAAGTTCTAAAT------GAGGTAGATGGATATTCTAGTTCTTCAGAGAAA
ATAGACTTACTGGCCAGTGATCCTCATGATCATTTGATATGTAAAAGTGAAAGAGTTCACTGCAAATCAGTAGAGAGTAG
T---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCTAACTTGAGCCACGTAACTGAAAATC
TAATTATAGGAGCATTTGTTACTGAGCCACAGATAATACAA---------------------------------------
---------------------GAGCATCCTCTCACAAATAAATTAAAGCGTAAAAGGAGAGTTACATCAGGACTTCATCC
TGAGGATTTTATCAAGAAAGCAGATTTGGCAGTT---CAAAAGACTCCTGAAAAGATAAATCAGGGAACTAACCAAACAG
AGCGGAAT---------GATCAAGTGATGAATATTACTAACAGTGGTCATGAGAATAAAACAAAAGGTGATTCT---ATT
CAGAATGAGAACAATCCTAACCCAGTAGAA------TCACTGGAAAAAGAATCA---TTCAAAAGTAAAGCTGAACCTAT
AAGCAGTAGTATAAGCAATATGGAATTAGAATTGAATGTCCACAATTCCAAAGCATCTAAAAAGAATAGGCTGAGAAGGA
AGTCTTCTACCAGGCATATTCATGAGCTTGAACTAGTAGTCAGTAGAAATCTAAGCCCACCTAATTATACTGAAGTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---ATAAAGAAAAAA---AATTACAACCAAATGCCAGTCAGGCACAGCAGAAA
GCTACAACTCATGGAAGATAAAGAACGTGCAGCTAGAGCCAAAAAGAGTAGCAAGCCAAATGAACAAACAAGTAAAAGAC
ATGCCAGTGATACTTTCCCAGAACTGAGGTTAACAAACATACCTGGTTCTTTTACTAACTGTTCAAATACTAATGAATTT
AAAGAATTTGTCAATCCTAGCCTTCCAAGAGAACAAACAGAAGAGAAA---CTAGAAACAGTTAAACTGTCTAATAATGC
CAAAGACCCCAAAGATCTCATGTTAAGTGGAGAAAGT---GTTTTGCAA---ATTGAAAGATCTGTAGAGAGTAGCAGTA
TTTTGTTGATACCTGGTACTGATTATGGCACTCAGGAAAGTATCTCATTACTGGAAGTTAGCACTCTGGGG---AAGGCA
AAA---ACAGAACCAAATAAATGTGTGAGTCAGTGTGCAGCATTTGAAAACCCCAAGGAACTAATTCATGGTTGT---TC
TAAAGATACTAGAAATGGCACAGAAGGCTTGAAGTATCCATTGGGACCTGAAGTTAAC---TACAGTCAGGAAACAAGCA
TAGATATGAGAGAAAGTGAACTTGATACTCAATATTTGCAGAATACATTCAAGGTTTCAAAGCGCCAGTCATTTGCTCTG
TTTTCAAATCCAGGAAATCCAGAAAAGGAATGTGCAACATTCTCTGCCTGCTCTAGGTCCTTAAAGAAACAAAGTCCAAA
GGTCACTCCTGAATGTGAACAAAAGGAAGAAAATCAAGGAGAGAAAGAGTCTAATATCGAGCTTGTAGAGACAGTTAATA
CCACTGCAGGCTTTCCTATGGTTTGTCAGAAAGATAAG---CCAGTTGATTATGCCAGATGT---ATCGAAGGAGGCTCT
AGGCTTTGTCTATCATCTCAGTTCAGA---GGCAACGAAACTGGACTCATTATTCCAAATAAACATGGACTTTTACAGAA
CCCATATCATATGTCACCGCTTATTCCCACCAGGTCATTTGTTAAAACTAAATGTAAGAAAAAC---CTGCTAGAAGAAA
ACTCTGAGGAACATTCAATGTCACCTGAAAGAGCAATGGGAAACAAGAACATCATTCCAAGTACAGTGAGCACAATTAGC
CATAATAAC---AGAGAAAATGCTTTTAAAGAAACCAGCTCAAGCAGTATTTATGAAGTAGGTTCCAGTACTAATGAAGC
AGGTTCTAGTACTAATGAAGTAGGCTCCAGTATTAATGAAGTAGGTTCCAGTGATGAAAACATTCAAGCAGAGCTAGGTA
GAAACAGAAGGCCAAAATTGAATGCTATGCTTAGATTAGGGCTTCTGCAACCTGAGATTTGTAAGCAAAGTCTT---CCT
ATAAGTGATTGTAAACATCCTGAAATTAAAAAGCAAGAACATGAAGAA---GTAGTTCAGACTGTTAATACAGACGTCTC
TCTATGTCTGATTTCATATAACCTAGAACAG---CATATGGGAAGCAGTCATACATCTCAGGTTTGTTCTGAGACACCTG
ACAACCTGTTAGATGATGGTGAAATAAAGGAAGATACTAGTTTTGCTGAATATGGCATTAAGGAGACTTCTACTGTTTTT
AGCAAAAGTGTCCAGAGAGGAGAGCTCAGCAGGAGCCCTAGCCCTTTCACCCAT---ACACATTTGGCTCAGGTTTACCA
AAGAGGGGCCAAGAAATTAGAGTCCTCGGAAGAGAATTTATCTAGTGAG
>Rhesus
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAAC---AGTTTGTTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTGGCAAGGAGCCAACATAACAGATGGACTGGAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCCAGCACAGAGAAAAAGGTAGATCTGAATGCTAATGCCCTGTATGAGAGAAAAGAA
TGGAATAAGCAAAAACTGCCATGCTCTGAGAATCCTAGAGAC---ACTGAAGAT---GTTCCTTGGATAACACTAAATAG
CAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAACTGTTAAGTTCTGATGACTCACATGATGGGGGGTCTG
AATCAAATGCCAAAGTAGCTGATGTATTGGACGTTCTAAAT------GAGGTAGATGAATATTCTGGTTCTTCAGAGAAA
ATAGACTTACTGGCCAGTGATCCTCATGAGCCTTTAATATGTAAAAGTGAAAGAGTTCACTCCAGTTCAGTAGAGAGTAA
T---ATTAAAGACAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAACCTTCCCAATTTAAGCCATGTAACTGAAAATC
TAATTATAGGAGCACTTGTTACTGAGTCACAGATAATGCAA---------------------------------------
---------------------GAGCGTCCCCTCACAAATAAATTAAAGCGTAAAAGGAGAACTACATCAGGTCTTCATCC
TGAGGATTTTATAAAGAAAGCAGATTTGGCAGTT---CAAAAGACTCCTGAAATAATAAATCAGGGAACTAACCAAATGG
AGCAGAAT---------GGTCAAGTGATGAATATTACTAATAGTGCTCATGAGAATAAAACAAAAGGTGATTCT---ATT
CAGAATGAGAAAAATCCTAACCCAATAGAA------TCACTGGAAGAAGAATCTGCTTTCAAAACTAAAGCTGAACCTAT
AAGCAGCAGTATAAACAATATGGAACTAGAATTAAATATCCACAATTCAAAAGCACCTAAAAAAAATAGGCTGAGGAGGA
AGTCTTCTACCAGGCATATTCATGCGCTTGAACTAGTAGTCAGTAGAAATCTAAGCCCACCTAACTGTACTGAACTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---ATAAAGAAAAAA---AATTACAACCAAATGCCAGTCAGGCACAGCAGAAA
CCTACAACTCATGGAAGATAAAGAATCTGCAACTGGAGCCAAGAAGAGTAACAAGCCAAATGAACAGACAAGTAAAAGAC
ATGCCAGTGATACTTTCCCAGAACTGAAGTTAACAAAGGTACCTGGTTCTTTTACTAACTGTTCAAATACTAGTGAA---
AAAGAATTTGTCAATCCTAGCCTTTCAAGAGAAGAAAAAGAAGAGAAA---CTAGAAACAGTTAAAGTGTCTAATAATGC
CAAAGACCCCAAAGATCTCATCTTAAGTGGAGAAAGG---GTTTTACAA---ACTGAAAGATCTGTAGAGAGTAGCAGTA
TTTCATTGGTACCTGGTACCGATTATGGCACTCAGGAAAGTATCTCATTACTGGAAGTTAGCACTCTAGGG---AAGGCA
AAA---ACAGAACGAAATAAATGTATGAGTCAGTGTGCAGCATTTGAAAACCCCAAGGAACTAATTCATGGTTGT---TC
TGAAGATACTAGAAATGACACAGAAGGCTTTAAGTATCCATTGGGAAGTGAAGTTAAC---CACAGTCAGGAAACAAGCA
TAGAAATAGAAGAAAGTGAACTTGATACTCAGTATTTGCAGAATACATTCAAGGTTTCAAAGCGCCAGTCCTTTGCTCTG
TTTTCAAATCCAGGAAATCCAGAAGAGGAATGTGCAACATTCTCTGCCCACTCTAGGTCCTTAAAGAAACAAAGTCCAAA
AGTTACTTCTGAATGTGAACAAAAGGAAGAAAATCAAGGAAAGAAACAGTCTAATATCAAGCCTGTACAGACAGTTAATA
TCACTGCAGGCTTTTCTGTGGTTTGTCAGAAAGATAAG---CCAGTTGATAATGCCAAATGTAGTATCAAAGGAGGCTCT
AGGTTTTGTCTATCATCTCAGTTCAGA---GGCAACGAAACTGGACTCATTACTCCAAATAAACATGGACTGTTACAAAA
CCCATACCATATACCACCACTTTTTCCTGTCAAGTCATTTGTTAAAACTAAATGTAACAAAAAC---CTGCTAGAGGAAA
ACTCTGAGGAACATTCAGTGTCACCTGAAAGAGCAGTGGGAAACAAGAACATCATTCCAAGTACAGTGAGCACAATTAGC
CATAATAACATTAGAGAAAATGCTTTTAAAGAAGCCAGCTCGAGCAATATTAATGAAGTAGGTTCCAGTACTAATGAAGT
GGGCTCCAGTATTAATGAAGTAGGTTCCAGT---------------------GATGAAAACATTCAAGCAGAACTAGGTA
GAAACAGAGGGCCAAAATTGAATGCTGTGCTTAGATTAGGGCTTTTGCAACCTGAGGTCTGTAAACAAAGTCTT---CCT
ATAAGTAATTGTAAGCATCCTGAAATAAAAAAGCAAGAACATGAAGAA---TTAGTTCAGACTGTTAATACAGACTTCTC
TCCATGTCTGATTTCAGATAACCTAGAACAG---CCTATGGGAAGTAGTCATGCGTCTGAGGTTTGTTCTGAGACTCCTG
ATGATCTGTTAGATGATGGTGAAATAAAGGAAGATACTAGTTTTGCTGAAAATGACATTAAGGAGAGTTCTGCTGTTTTT
AGCAAAAGCATCCAGAGAGGAGAGCTCAGCAGGAGCCCTAGCCCTTTCACCCAT---ACACATTTAGCTCAGGGTTACCG
AAAAGAGGCCAAGAAATTAGAGTCCTCAGAAGAGAACTTATCTAGTGAG
>Orangutan
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACATAACAGATGGGCTGGAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCCAGCACAGAAAAAAAGGTAGACCTGAATGCTGATCCCCTGTGTGAGAGAAAAGAA
TGGAATAAGCAGAAACTGCCATGCTCAGAGAATCCTAGAGAT---ACTGAAGAT---GTTCCTTGGATAACACTAAATAG
CAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGACGAACTGTTAGGTTCTGATGACTCACATGATGGGAGGTCTG
AATCAAATGCCAAAGTAGCGGATGTATTGGACGTTCTAAAT------GAGGTAGATGAATATTCTGGTTCTTCAGAGAAA
ATAGACTTACTGGCCAGTGATCCTCATGAGGCTTTAATTTGTAAAAGTGAAAGAGTTCACTCCAAATCAGTAGAGAGTAA
T---ATTGAAGACAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCCAACTTAAGCCATGTAACTGAAAATC
TAATTATAGGAGCATTTGTTACTGAGCCACAGATAATACAA---------------------------------------
---------------------GAGCGTCCCCTCACAAATAAATTAAAGCGTAAAAGGAGAGCTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGCAGATTTGGCAGTT---CAAAAGACTCCTGAAATGATAAATCAGGGAACTAACCAAATGG
AGCAGAAT---------GGTCAAGTGATGAATATTACTAATAGTGGTCATGAGAATAAAACAAAAGGTGATTCT---ATT
CAGAATGAGAAAAATCCTAACCCAATAGAA------TCACTCGAAAAAGAATCTGCTTTCAAAACAAAAGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTCGAATTAAATATCCATAATTCAAAAGCACCTAAAAAGAATAGGCTGAGGAGGA
AGTCTTCTACCAGGCATATTCATGCGCTTGAACTAGTAGTCAGTAGAAATCTAAGCCCACCTAATTGTACTGAATTGCAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---ATAAAGAAAAAA---AAATACAACCAAATGCCAGTCAGGCACAGCAGAAA
CCTACAACTCATGGAAGATAAAGAACCTGCAACTGGAGCCAAGAAGAGTAACAAGCCAAATGAACAGACAAGTAAAAGAC
ATGACAGCGATACTTTCCCAGAGCTGAAGTTAACAAATGCACCTGGTTCTTTTACTAACTGTTCAAATACCAGTGAGCTT
AAAGAATTTGTCAATCCTAGCCTTCCAAGAGAAGAAAAAGAAGAGAAA---CTAGGAACAGTTAAAGTGTCTAATAATGC
CAAAGACCCCAAAGATCTCATGTTAAGTGGAGGAAGG---GTTTTGCAA---ACTGAAAGATCTGTAGAGAGTAGCAGTA
TTTCATTGGTACCTGGTACTGATTATGGCACTCAGGAAAGTATCTCGTTACTGGAAGTTAGCACTCTAGGG---AAGGCA
AAA---ACAGAACCAAATAAATGTGTGAGTCAGTGTGCAGCATTTGAAAACCCCAAGGAACTAATTCATGGTTGT---TT
CAAAGATACTAGAAATGACACAGAAGGGTTTAAGTATCCATTGGGACATGAAGTTAAC---CACAGTCAGGAAACAAGCA
TAGAAATGGAAGAAAGTGAACTTGATACTCAGTATTTGCAGAATACATTCAAGGTTTCAAAGCGCCAGTCATTTGCTCTG
TTTTCAAATCCAGGAAATCCAGAAGAGGAATGTGCAACATTCTCTGCCCACTCTAGGTCCTTAAAGAAACAAAGTCCAAA
AGTCACTTTTGAATGTGAACAAAAGGAAGAAAATCAAGGAAAGAATGAGTCTAATATCAAGCCTGTACAGACAGCTAATA
TCACTGCAGGCTTTCCTGTGGTTTGTCAGAAAGATAAG---CCAGTTGATTATGCCAAATGTAGTATCAAAGGAGGCTCT
AGGTTTTGTCTATCATCTCAGTTCAGA---GGCAACGAAACTGGACTCATTACTCCAAATAAACATGGACTTTCACAAAA
CCCATATCATATACCACCACTTTTTCCCATCAAGTCATTTGTTAAAACTAAATGTAAGAAAAAC---CTGCTAGAGGAAA
ACTCTGAGGAACATTCAATGTCACCTGAAAGAGAAATGGGAAACGAGAAC---ATTCCAAGTACAGTGAGCATAATTAGC
CGTAATAACATTAGAGAAAATGTTTTTAAAGAAGCCAGCTCAAGCAATATTAATGAAGTAGGTTCCAGTACTAATGAAGT
GGGCTCCAGTATTAATGAAGTAGGTTCCAGT---------------------GATGAAAACATTCAAGCAGAACTAGGTA
GAAGCAGAGGGCCAAAATTGAATGCTATGCTTAGATTAGGGGTTTTGCAACCTGAGGTCTATAAACAAAGTTTT---CCT
GGAAGTAATGGTAAGCATCCTGAAATAAAAAAGCAAGAATATGAAGAA---GTACTTCAGACTGTTAATACAGACTTCTC
TCCATGTCTGATTTCAGATAACCTAGAACAG---CCTATGAGAAGTAGTCATGCATCTCAGGTTTGTTCTGAGACACCTA
ATGACCTGTTAGATGATGGTGAAATAAAGGAAGATACTAGTTTTGCTGAAAATGACATTAAGGAAAGTTCTGCTGTTTTT
AGCAAAAGCGTCCAGAGAGGAGAGCTTAGCAGGAGTCCTAGCCCTTTCACCCAT---ACACATTTGGCTCAGGGTTACCG
AAGAGGGGCCAAGAAATTAGAGTCCTCAGAAGAGAACTTATCTAGTGAG
>Gorilla
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAACAAACAGCCTGGCTTAGCAAGGAGCCAACATAACAGATGGGCTGGAAGTAAGGAAA
CATGTAATGAT---AGGCGGACTCCCAGCACAGAAAAAAAGGTAGATCTGAATGCTGATCCCCTGTGTGAGAGAAACGAA
TGGAATAAGCAGAAACTGCCATGCTCAGAGAATCCTAGAGAT---ACTGAAGAT---GTTCCTTGGATAACACTAAATAG
CAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAACTGTTAGGTTCTGATGACTCACATGATGGGGGGTCTG
AATCAAATGCCAAAGTAGCTGATGTATTGGACGTTCTAAAT------GAGGTAGATGAATATTCTGGTTCTTCAGAGAAA
ATAGACTTACTGGCCAGTGATCCTCATGAGGCTTTAATATGTAAAAGTGAAAGAGTTCACTCCAAATCAGTAGAGAGTAA
T---ATTGAAGACAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCCAGCTTAAGCCATGTAACTGAAAATC
TAATTATAGGAGCATTTGTTACTGAGCCACAGATAATACAA---------------------------------------
---------------------GAGCGTCCCCTCACAAATAAATTAAAGCGTAAAAGGAGAGCTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGCAGATTTGGCAGTT---CAAAAGACTCCTGAAATGATAAATCAGGGAACTAACCAAATGG
AGCAGAAT---------GGTCAAGTGATGAATATTACTAATAGTGGTCATGAGAATAAAACAAAAGGTGATTCT---ATT
CAGAATGAGAAAAATCCTAACCCAATAGAA------TCACTAGAAAAAGAATCTGCTTTCAAAACGAAAGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTCGAATTAAATATCCACAATTCAAAAGCGCCTAAAAAGAATAGGCTGAGGAGGA
AGTCTTCTACCAGGCATATTCATGCGCTTGAACTAGTAGTCAGTAGAAATCTAAGCCCACCTAATTGTACTGAATTGCAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---ATAAAGAAAAAA---AAGTACAACCAAATGCCAGTCAGGCACAGCAGAAA
CCTACAGCTCATGGAAGATAAAGAACCTGCAACTGGAGCCAAGAAGAGTAACAAGCCAAATGAACAGACAAGTAAAAGAC
ATGACAGCGATACTTTCCCAGAGCTGAAGTTAACAAATGCACCTGGTTCTTTTACTAACTGTTCAAATACCAGTGAACTT
AAAGAATTTGTCAATCCTAGCCTTCCAAGAGAAGAAAAAGAAGAGAAA---CTAGAAACAGTTAAAGTGTCTAATAATGC
CGAAGACCCCAAAGATCTCATGTTAAGTGGAGAAAGG---GTTTTGCAA---ACTGAAAGATCTGTAGAGAGTAGCAGTA
TTTCATTGGTACCTGGTACTGATTATGGCACTCAGGAAAGTATCTCGTTACTGGAAGTTAGCACTCTAGGG---AAGGCA
AAA---ACAGAACCAAATAAATGTGTGAGTCAGTGTGCAGCATTTGAAAACCCCAAGGGACTAATTCATGGTTGT---TC
CAAAGATACTAGAAATGACACAGAAGGCTTTAAGTATCCATTGGGACATGAAGTTAAC---CACAGTCGGGAAACAAGCA
TAGAAATGGAAGAAAGTGAACTTGATGCTCAGTATTTGCAGAATACATTCAAGGTTTCAAAGCGCCAGTCATTTGCTCTG
TTTTCAAATCCAGGAAATCCAGAAGAGGAATGTGCAACATTCTCTGCCCACTCTAGGTCCTTAAAGAAACAAAGTCCAAA
AGTCACTTTTGAATGTGAACAAAAGGAAGAAAATCAAGGAAAGAATGAGTCTAATATCAAGCCTGTACAGACAGTTAATA
TCACTGCAGGCTTTCCTGTGGTTTGTCAGAAAGATAAG---CCAGTTGATTATGCCAAATGTAGTATCAAAGGAGGCTCT
AGGTTTTGTCTATCATCTCAGTTCAGA---GGCAACGAAACTGGACTCATTACTCCAAATAAACATGGACTTTTACAAAA
CCCATATCATATACCACCACTTTTTCCCATCAAGTCATTTGTTAAAACTAAATGTAAGAAAAAC---CTGCTAGAGGAAA
ACTTTGAGGAACATTCAATGTCACCTGAAAGAGAAATGGGAAATGAGAAC---ATTCCAAGTACAGTGAGCACAATTAGC
CGTAATAACATTAGAGAAAATGTTTTTAAAGAAGCCAGCTCAAGCAATATTAATGAAGTAGGTTCCAGTACTAATGAAGT
GGGCTCCAGTATTAATGAAGTAGGTTCCAGT---------------------GATGAAAACATTCAAGCAGAACTAGGTA
GAAACAGAGGGCCAAAATTGAATGCTATGCTTAGATTAGGGGTTTTGCAACCTGAGGTCTATAAACAAAGTCTT---CCT
GGAAGTAATTGTAAGCATCCTGAAATAAAAAAGCAAGAATATGAAGAA---GTAGTTCAGACTGTTAATACAGATTTCTC
TCCATGTCTGATTTCAGATAACTTAGAACAG---CCTATGGGAAGTAGTCATGCATCTCAGGTTTGTTCTGAGACACCTG
ATGACCTGTTAGATGATGGTGAAATAAAGGAAGATACTAGTTTTGCTAAAAATGACATTAAGGAAAGTTCTGCTGTTTTT
AGCAAAAGCGTCCAGAGAGGAGAGCTTAGCAGGAGTCCTAGCCCTTTCACCCAT---ACACATTTGGCTCAGGGTTACCG
AAGAGGGGCCAAGAAATTAGAGTCCTCAGAAGAGAACTTATCTAGTGAG
>Human
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACATAACAGATGGGCTGGAAGTAAGGAAA
CATGTAATGAT---AGGCGGACTCCCAGCACAGAAAAAAAGGTAGATCTGAATGCTGATCCCCTGTGTGAGAGAAAAGAA
TGGAATAAGCAGAAACTGCCATGCTCAGAGAATCCTAGAGAT---ACTGAAGAT---GTTCCTTGGATAACACTAAATAG
CAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAACTGTTAGGTTCTGATGACTCACATGATGGGGAGTCTG
AATCAAATGCCAAAGTAGCTGATGTATTGGACGTTCTAAAT------GAGGTAGATGAATATTCTGGTTCTTCAGAGAAA
ATAGACTTACTGGCCAGTGATCCTCATGAGGCTTTAATATGTAAAAGTGAAAGAGTTCACTCCAAATCAGTAGAGAGTAA
T---ATTGAAGACAAAATATTTGGGAAAACCTATCGGAAGAAGGCAAGCCTCCCCAACTTAAGCCATGTAACTGAAAATC
TAATTATAGGAGCATTTGTTACTGAGCCACAGATAATACAA---------------------------------------
---------------------GAGCGTCCCCTCACAAATAAATTAAAGCGTAAAAGGAGACCTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGCAGATTTGGCAGTT---CAAAAGACTCCTGAAATGATAAATCAGGGAACTAACCAAACGG
AGCAGAAT---------GGTCAAGTGATGAATATTACTAATAGTGGTCATGAGAATAAAACAAAAGGTGATTCT---ATT
CAGAATGAGAAAAATCCTAACCCAATAGAA------TCACTCGAAAAAGAATCTGCTTTCAAAACGAAAGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTCGAATTAAATATCCACAATTCAAAAGCACCTAAAAAGAATAGGCTGAGGAGGA
AGTCTTCTACCAGGCATATTCATGCGCTTGAACTAGTAGTCAGTAGAAATCTAAGCCCACCTAATTGTACTGAATTGCAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---ATAAAGAAAAAA---AAGTACAACCAAATGCCAGTCAGGCACAGCAGAAA
CCTACAACTCATGGAAGGTAAAGAACCTGCAACTGGAGCCAAGAAGAGTAACAAGCCAAATGAACAGACAAGTAAAAGAC
ATGACAGCGATACTTTCCCAGAGCTGAAGTTAACAAATGCACCTGGTTCTTTTACTAAGTGTTCAAATACCAGTGAACTT
AAAGAATTTGTCAATCCTAGCCTTCCAAGAGAAGAAAAAGAAGAGAAA---CTAGAAACAGTTAAAGTGTCTAATAATGC
TGAAGACCCCAAAGATCTCATGTTAAGTGGAGAAAGG---GTTTTGCAA---ACTGAAAGATCTGTAGAGAGTAGCAGTA
TTTCATTGGTACCTGGTACTGATTATGGCACTCAGGAAAGTATCTCGTTACTGGAAGTTAGCACTCTAGGG---AAGGCA
AAA---ACAGAACCAAATAAATGTGTGAGTCAGTGTGCAGCATTTGAAAACCCCAAGGGACTAATTCATGGTTGT---TC
CAAAGATAATAGAAATGACACAGAAGGCTTTAAGTATCCATTGGGACATGAAGTTAAC---CACAGTCGGGAAACAAGCA
TAGAAATGGAAGAAAGTGAACTTGATGCTCAGTATTTGCAGAATACATTCAAGGTTTCAAAGCGCCAGTCATTTGCTCCG
TTTTCAAATCCAGGAAATGCAGAAGAGGAATGTGCAACATTCTCTGCCCACTCTGGGTCCTTAAAGAAACAAAGTCCAAA
AGTCACTTTTGAATGTGAACAAAAGGAAGAAAATCAAGGAAAGAATGAGTCTAATATCAAGCCTGTACAGACAGTTAATA
TCACTGCAGGCTTTCCTGTGGTTGGTCAGAAAGATAAG---CCAGTTGATAATGCCAAATGTAGTATCAAAGGAGGCTCT
AGGTTTTGTCTATCATCTCAGTTCAGA---GGCAACGAAACTGGACTCATTACTCCAAATAAACATGGACTTTTACAAAA
CCCATATCGTATACCACCACTTTTTCCCATCAAGTCATTTGTTAAAACTAAATGTAAGAAAAAT---CTGCTAGAGGAAA
ACTTTGAGGAACATTCAATGTCACCTGAAAGAGAAATGGGAAATGAGAAC---ATTCCAAGTACAGTGAGCACAATTAGC
CGTAATAACATTAGAGAAAATGTTTTTAAAGAAGCCAGCTCAAGCAATATTAATGAAGTAGGTTCCAGTACTAATGAAGT
GGGCTCCAGTATTAATGAAATAGGTTCCAGT---------------------GATGAAAACATTCAAGCAGAACTAGGTA
GAAACAGAGGGCCAAAATTGAATGCTATGCTTAGATTAGGGGTTTTGCAACCTGAGGTCTATAAACAAAGTCTT---CCT
GGAAGTAATTGTAAGCATCCTGAAATAAAAAAGCAAGAATATGAAGAA---GTAGTTCAGACTGTTAATACAGATTTCTC
TCCATATCTGATTTCAGATAACTTAGAACAG---CCTATGGGAAGTAGTCATGCATCTCAGGTTTGTTCTGAGACACCTG
ATGACCTGTTAGATGATGGTGAAATAAAGGAAGATACTAGTTTTGCTGAAAATGACATTAAGGAAAGTTCTGCTGTTTTT
AGCAAAAGCGTCCAGAAAGGAGAGCTTAGCAGGAGTCCTAGCCCTTTCACCCAT---ACACATTTGGCTCAGGGTTACCG
AAGAGGGGCCAAGAAATTAGAGTCCTCAGAAGAGAACTTATCTAGTGAG
>Chimpanzee
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACATAACAGATGGGCTGGAAGTAAGGAAA
CATGTAATGAT---AGGCGGACTCCCAGCACAGAAAAAAAGGTAGATCTGAATGCTGATCCCCTGTGTGAGAGAAAAGAA
TGGAATAAGCAGAAACTGCCATGCTCAGAGAATCCTAGAGAT---ACTGAAGAT---GTTCCTTGGATAACACTAAATAG
CAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAACTGTTAGGTTCTGATGACTCACATGATGGGGGGTCTG
AATCAAATGCCAAAGTAGCTGATGTATTGGACGTTCTAAAT------GAGGTAGATGAATATTCTGGTTCTTCAGAGAAA
ATAGACTTACTGGCCAGCGATCCTCATGAGGCTTTAATATGTAAAAGTGAAAGAGTTCACTCCAAATCAGTAGAGAGTAA
T---ACTGAAGACAAAATATTTGGGAAAACCTATCGGAGGAAGGCAAGCCTCCCCAACTTAAGCCATGTAACTGAAAATC
TAATTATAGGAGCATTTGTTACTGAGCCACAGATAATACAA---------------------------------------
---------------------GAGCGTCCCCTCACAAATAAATTAAAGCGTAAAAGGAGAGCTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGCAGATTTGGCAGTT---CAAAAGACTCCTGAAATGATAAATCAGGGAACTAACCAAATGG
AGCAGAAT---------GGTCAAGTGATGAATATTACTAATAGTGGTCATGAGAATAAAACAAAAGGTGATTCT---ATT
CAGAATGAGAAAAATCCTAACCCAATAGAA------TCACTCGAAAAAGAATCTGCTTTCAAAACGAAAGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTCGAATTAAATATCCACAATTCAAAAGCACCTAAAAAGAATAGGCTGAGGAGGA
AGTCTTCTACCAGGCATATTCATGCGCTTGAACTAGTAGTCAGTAGAAATCTAAGCCCACCTAATTGTACTGAATTGCAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---ATAAAGAAAAAA---AAGTACAACCAAATGCCAGTCAGGCACAGCAGAAA
CCTACAACTCATGGAAGATAAAGAACCTGCAACTGGAGTCAAGAAGAGTAACAAGCCAAATGAACAGACAAGTAAAAGAC
ATGACAGCGATACTTTCCCAGAGCTGAAGTTAACAAATGCACCTGGTTCTTTTACTAACTGTTCAAATACCAGTGAACTT
AAAGAATTTGTCAATCCTAGCCTTCCAAGAGAAGAAGAAGAAGAGAAA---CTAGAAACAGTTAAAGTGTCTAATAATGC
CGAAGACCCCAAAGATCTCATGTTAAGTGGAGAAAGG---GTTTTGCAA---ACTGAAAGATCTGTAGAGAGTAGCAGTA
TTTCATTGGTACCTGGTACTGATTATGGCACTCAGGAAAGTATCTCGTTACTGGAAGTTAGCACTCTAGGG---AAGGCA
AAA---ACAGAACCAAATAAATGTGTGAGTCAGTGTGCAGCATTTGAAAACCCCAAGGGACTAATTCATGGTTGT---TC
CAAAGATACTAGAAATGACACAGAAGGCTTTAAGTATCCATTGGGACATGAAGTTAAC---CACAGTCGGGAAACAAGCA
TAGAAATGGAAGAAAGTGAACTTGATGCTCAGTATTTGCAGAATACATTCAAGGTTTCAAAGCGCCAGTCATTTGCTCTG
TTTTCAAATCCAGGAAATCCAGAAGAGGAATGTGCAACATTCTCTGCCCACTGTAGGTCCTTAAAGAAACAAAGTCCAAA
AGTCACTTTTGAACGTGAACAAAAGGAACAAAATCAAGGAAAGAATGAGTCTAATATCAAGCCTGTACAGACAGTTAATA
TCACTGCAGGCTTTCCTGTGGTTTGTCAGAAAGATAAG---CCAGTTGATTATGCCAAATGTAGTATCAAAGGAGGCTCT
AGGTTTTGTCTATCATCTCAGTTCAGA---GGCAACGAAACTGGACTCATTACTCCAAATAAACATGGACTTTTACAAAA
CCCATATCATATACCACCACTTTTTCCCATCAAGTCATTTGTTAAAACTAAATGTAAGAAAAAC---CTGCTAGAGGAAA
ACTTTGAGGAACATTCAATGTCACCTGAAAGAGAAATGGGAAATGAGAAC---ATTCCAAGTACAGTGAGCACAATTAGC
CGTAATAACATTAGAGAAAATGTTTTTAAAGAAGCCAGCTCAAGCAATATTAATGAAGTAGGTTCCAGTACTAATGAAGT
GGGCTCCAGTATTAATGAAGTAGGTTCCAGT---------------------GATGAAAACATTCAAGCAGAACTAGGTA
GAAACAGAGGGCCAAAATTGAATGCTATGCTTAGATTAGGGGTTTTGCAACCTGAGGTCTATAAACAAAGTCTT---CCT
GAAAGTAATTGTAAGCATCCTGAAATAAAAAAGCAAGAATATGAAGAA---GTAGTTCAGACTGTTAATACAGATTTCTC
TCCATGTCTGATTTCAGATAACTTAGAACAG---CCTATGGGAAGTAGTCATGCATCTCAGGTTTGTTCTGAGACACCTG
ATGACCTGTTAGATGATGGTGAAATAAAGGAAGATACTAGTTTTGCTGAAAATGACATTAAGGAAAGTTCTGCTGTTTTT
AGCAAAAGCGTCCAGAGAGGAGAGCTTAGCAGGAGTCCTAGCCCTTTCACCCAT---ACACATTTGGCTCAGGGTTACCG
AAGAGGGGCCAAGAAATTAGAGTCCTCAGAAGAGAACTTATCTAGTGAG
>Jackrabbit
--------------------------------------------------------------------------------
-AAGGCTGAATTCTGTAATAAGAGCAAACAGCCTGGCTTAGCAAGAAGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCCAGCACAGAGAAAAAGGTAGTTCTGAATGTTGACTGCCTGTATGGGAGAAAACAA
CAGGATAAGCAGAAACCTCCATGCCCTGAGACCTCTGGAGAT---AACCAAGAT---GTTTCTTGGATAACAGTAAATAG
CAGCATTCGGAAAGTTAACGAGTGGTTCTCCAGAAGTAATGAAATGTTAACTCCTGATGACTCACTTGACCGGCGGTCTG
AATCAAATGCCAAAGTGGCTGGTGCATTAGAAGTCCCAAAG------GAGGTAGATGGATATTCTGGTTCTACAGAGAAA
ATAGACTTACTGGCCAGTGATTCCCATAATGCTTTAATATGTGAAAGCAAAAGAGTCCATTCCAAACCAGTAGAGAATAA
T---ATCAAAGATAAAATATTTGGGAAAACCTACCACAGGAAGACAAGCCTCCCTAACTTGAGCCACATAACTGAAGATC
TAACTATAGGAGCATTTGCTGCGGAACCACTGGTA---------------------------------------------
---------------------CCATGTCCCCCCGCAAATAAATTAAAGCGTAAAAGAAGAACTTCTTCAGGCCTTCAACC
TGAAGATTTTATCAAGAAGGTAGATTTGGCAGTTGTTCCAAAAACCACTGCACAGATAAATCAGGGAACTGATCAAACGG
TGGACAGT---------GATCAGGTGATGAATATTACTAATTGTGGTAATGAGAATGAAACAGAAGGTGACTAT---ATT
CAGAAAGAGACAAATGCTAACCCAACAGAA------TCCCTAGAAAAAGACTCTTCCTTCAGAACTAAAGTTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTAAATGTCCATAATTCAAAAAAACCCAAGAAGAATAGGCTGAGGAGGA
AGTCCTCTACCAGGCGTGTTCATGCACTTGAACTAGTAGTCAATAAGAAACCGAGCCCACCTAATCATGCTGAACTACAA
ATTGACAGTTGTACTAGCAGTGAAGAA---ATG------------AATTTTGACCAAATACCAGTCAGTCACAGCAGACA
GGCTCAAGTCATAGAAGATACAGAACCTCCAACTGGAGCTAGGAAG---AACAAGCCAAGTGAACAAATAAGTAAAAGAC
ATGCCAGTGATGTTTTCCCAGAAGTCAAATTAACAAACATACCTGGTGTTTTTACAAACTGTTCAAGTTCTAATAAACTT
CAAGAATCTGTCGATCCTAGCCTTCAAAGAAGGGAAATAGAAGAGAAC---CTAGACACAGTTCAAGTGCCTAACAGTGC
CATAGACCCCAAAGATCTCCTGTTATGTGGAGAAAGG---GGCTTGCAA---ACTGAAAGGTCTGCGGAGAGTACCAGTA
TTTCACTGGTACCTGATACTGAATATGGTACCCAGGACAGCATCTCATTACTGGGCGCTAACACCCTTGGG---AAGGCA
AAA---ACAGCAGCAAATGGACATGTGAGTGAGAGCACAACAATTGGAAATCCCAAGGAACTTAGCCATGATTGT---TT
GAAAGATACTGGAAATGACCCAGACAACTGTAAGGATCCACTGAGAAGTGAAGTTGAC---------CAAGAGACAAGCG
TAGAAATGGAAGAGAGTGAGTTTGATACTCAGTATTTACAGAATACATTCATGGGTTCAAAGCGTCGTTCATTTGCTCTG
TGTTCAAAACCAGGAGATCCAGAAAAGGAATGTGCAGCAGTCTGTACCCGCTCCAACTCCTCAAGGAAACAAAGTCCAGA
AGTCACTCTTGAACGTGAACAAAAAGAA---AGTCAGAGAAAGGAAGAGTGGAAAATCAGTCATGTCCAGGCAGCTGATA
GCACTGTGGGCTTTCCTGTGGTGTGTCAGAAAGAAAAG---GCAGGTGATTGTGCCAAATGGAGCACTAAAGAGATCTCT
AGGCTTTGTCTGTCATCTCAGTCCAAA---GGCAGTGAAACTGAGCTCATTGCTGTAAGTAAACATGGGATGTCACAAAA
CCCATATCATATACCACCAATTTCTCCCATCAAGACATCTGTTAAAGCCACACGCCAGGTACAC---CTGTCAGGGGAAA
GGTCTGAGGAGCATTCCGTGTCATCTGAAAGAGCAGTGGGAAGCGAGAGCATCATTCAAAGCACAGTGAGCACAATTAGC
CAAGAGTACATTAGAGAAAGTGCTTTGAAAGGATTCAGCTCAAGCAGTATTAATGAAGGGGGCTCTAGTGCTAACGAAGT
ATGCTCCAGTGTGAATGAAGTAGGATCCAGT---------------------GGTGAAAACATGCAAGCACAACCAGGCA
GAAGCAGAGCACCTGAGTTAAATGCTGTGCTGAGAATAGGTCTTCTGCAGCCTGAAGTCTCTGAGCAAAGCCTT---CCT
ATAAGTAATTCTGAACTTCCCAAACTACAAAGGCAAGGAGAAAACGAAGGAGTAGTTCAGGCTGTGAATAGAGATTTCTC
TTCGTATCTGGTTCCTGATAGCCAAGAGCAG---TCTATGGGAGGAAGGCATGCTTCTCAGATTTGTTCTGAGACACCTG
ATGACCTGTTAGATATTTATGAAATAAAGGAAAATACCAGCTTTGCTGAGAGCGGCATTAAGGAAAGATCTGCTGTGTTT
AGTAAAAGTGTTCAGAGGGGAGAGTGCAGTAGAACCCCTAGCCCTTCAGGCCAT---GCATGTTTGGCTCAGAGTCA---
-------------------------------------------------
>FlyingSqu
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAGCAGAGCAGATGGGCTAAAAGTAAGGAAA
CCTGTAATGAT---AGGCAAATTCCCAGCTCAGAGAAAAAGGTAGATTTGAATGCTGATCCCCAATATGAGAAAAAAGAA
CCAAGTAAGCAGAAACATCCATGCTCTGAGAATTCCAGAGAT---ACCCAAGAT---GTTCCTTGGATAACACTAAATAG
CAGCATTCGGAAAGTTAACGAGTGGTTTTCCAGAAGTGACGAAATGTTAACTTCTGATGACTCAGATGATGGGGGTTCTG
AATCAAATGCTGAAATAGCTGGTATATTAGAAATTCCAAAT------GAAGTAGATGGATTTTCTGGTTCTTCGGAGAAA
ATAGACTTGTTGGCCACTGATCCGCATAATGCTTTAATTTCTAAATGTAAAAGAGTCTGCTCCAAAGCAGTCAAGAGTAA
T---ATTGAAGATAAAATATTTGGGAAAACCTATCAGAGGAAGGCAAGCCTCCCTAACTTGAGCCATATAACTGAAAATC
TAATTATAGGAGCATTTGCCAGAGAACCACAAATAACACAAGAGCTTGCCAGAGAACCACAAATAACACAACAGCTTGCC
AGAGAACCACAAATAACACAAGAGCGTCCCCTCACAAATAAATTAAGACGTAAAAGGAGAACTACATCATGCCTTCATCC
TGAGGACTTTATCAAGAAAACAGATTTGGCAATTGTTCAAAAGACTCCTGAAAAGATAAATCAGGGAACTGACCAAATGG
AACACAAT---------GATCAAGTAATGAATATTACTAATAGTGGTCAAGAGAATGAAACAAAAGTTGATTAT---GTT
CAGAAAGAGAAAAATGCTAACCCAGTTGAA------TCATTGGAAAAAGAGTCTGCTTTCAGAACTAAAGCTGAACCTAT
AAGCAGTAGTATAAGCAACATGGAACTAGAATTAAATATCCACAATTCAAAAGCACCTAAGAAAAATAGGCTGAGGAGGA
AGTCTTCTACTAGGTACATTCATGTGCTTGAACCAGTAGTTAATAGAAATACAAGTCCACCTCATCACACTGAATTGCAA
ATTGATAGTTGTACTAGTAGTGAAGAA---ATAAAGACAAGA---AATTCCAACCAAATGTCAGTCAGGCATGGCAAAAA
GCTTCAGTTCATGGAAGATGCAGAACCTGCAACTGATGTCAGAAAAAGTAACAAGCCAAATGAACAAGTAAATAAGAGAC
ATACCAATGATGCTTTCCCAGGACTGAAGTTAACAGGCATATCTGGTATTTTTACTAACTGCTCAAGTTCTAGTAAAGTT
GAAGAATTTATCAATCCTAACCTTCAGAAAGAAGGAACAGAAGAGAAC---ATAGAAATAATTCAAGTGTCTGATAATAC
CCAAGACCCCAAAGATACGGTGTTAAGTGGAGAAAGG---GTTTTGCAA---ACTGAGAGATCTGTAGAGAGTACCAGTA
TTTCATTGGTACCTGATACTGATTATGGCACTCAGGACAGTATCTCATTACTGGAAGCTAACACCTTTGGA---AAAGCA
AGA---ACAGCATCAAATCAACATGTTACTCAGTATGTGGCAATTGAAAATCCCAAAGAATTTGTCCATGGTCAT---TC
TAAAGATACTAAAAATGACCCAGAGGGTTTCAAGGATTCATTGAGATGTGAAGTTAAC---CACATTCAAGAGACAAATG
TAGAAATGGAAGAAAGTGAACTTGATACTCAGTCTTTAGAGAATACATTCCAAGTTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCAAATCCAGGAAATCTAGAAAAGGAATGTGCAGCCAACTATACCTCTTCCAAGTCCTTACGGAAACAAAGCCCAGA
CATGACTCTTGAATGTGAGCAAGAAGAAGAAAATTGGGGAAAGAAAGAGTCTAAAATTAGGCATGTACAGGCAATTAATG
CTACT------------ATGGTTTGTCAGAAAAGTAAG---CCAGATGATGATGCCCAATGTAGTGTTACAGAAGTCTCT
AGAATTTTTCCATCATTTCAGTTCAGA---GACAATCTAACTAAACTCATAACTGCAGATAAACATGGAATTTCACAAAA
CCCATATCATATGCCATCCATTTCTCCCAGCAGGTCATCTGTTAACACTAAATGTAGGAGAAAC---CTATCAGAAGAAA
AGTTTGAGAAAGATTCAAGGTCACCTAAAGAAGCGGTGGGATATAAGAGAATCATTCAAAGTACAGTGAGCACAATTAGC
CAAAATAACATTAGACAAAGTGCCTTTAAAGAAGCGAACTCAGGCAGTATTAATGAAGTAGGCTCTAGTACTAATGAAGT
AGGCTCCAGTATTAATGAAGTAGGTTCCAGT---------------------GGTGAAAACATTCAAGCAGAACTAGGTA
GAAACAGAGGACCCAAATTAAATGCTGTGCTTAGATTAGGTCTTATGCAACCTGAAGCCTGTAAACAAAATCTT------
CTAAGTAATTGTAAATACCCTGAAATAAAAAGACAAGGAGAAGATGAA---GTAGTTCAAGTTGTTAATGCAGATTTCTC
TCCATGTCTAATTTCAGATGACTTAGAACAA---CCTATGGGAAATAGTCATGTCACTCAGGTTTGTTCTGAGACTCCTG
ATGACCTGTTAGATGATGATGAAATACAGGAAAATACCAGCTTTGCTGAAGGTGGTATTAAGGAAAGATCTGCTGTTTTT
AGTAAGAGTGTCCAAAGAGGAGAGTTTAGCAGGAGCCCGAGTCCTTTATCCCAT---ACGTCTTTGGCTCGGAGTCATCA
AAAAGGGGCCAGGAAATTAGAGTCCTCAGAAGAGAGCATCTGTAGTGAG
>OldWorld
--------------------------------------------------------------------------------
----------------------------------------------AGCCAACAGAGCAGGTGGGCTGAGAGCAAGGAGA
GGTGCCATGAC---AGGCAGGCTCCTGGCACAGAGCAGAAGGTAGAGCTGACTGCTGAGCCCCTCCACGAGAGAAAAAGA
CGGAAAAAGCAGAACCCTCCGAGCTCCGAGGCTCATGGAGGG---ACCCAGGAT---GTTCCTTGGATCACACTAAATAG
CAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGACAAAGCAGTGACTTCTGACAGCACCTGTGACAGGGAGTCCA
AGTCAGATGCTGAAGAAGCTGGTGTGGCAGAAGATCCAAAA------GGCCTAGAT---------GGCTCTTCAGAGAAA
GTAGGCTTGCTGACCAGCAGTCCTCAAAAAGCTATAATCTGTGCCAGGGAGAGGGTCTGCTCCAAAGCACTGAAGAGTGA
C---ATGGAAGATAAAGTATTTGGGAAAACCTATCAGAGGAGGGTGAGCCTCCGCAGCTCAAGCCACGGAGCTGAAAGTC
TGACCGTGGGAGCGTTTGTTAGAGAGCCGCAGCTGACACTG---------------------------------------
---------------------GAGCGCTCCTTCACAAATAAAATAAAGCGCAAGAGGAGAACCACATCGTGCCTTCATCC
TGAGGACTTTGTCAAGAAAGCAGATTTGACAGTGGCTCAAAAGACTCCTGAAAAGGTAAATCAGGGAACGAAGCAAATGG
AGGAGAGT---------AGTCAAGTGACAAATACTACTAATAACAGTCATGAGAATGAGACAAAAATGGGCAAT---GTT
CAG------AGAAACCCTAACCCAGTACTA------TCAGTGGAAAAAGAGTCTGCTTCTGGTACTAACGCAGAGCCCTC
GAGCAGCAGCATAAACAACAGGGAACTAGAATTAAACACCCCTCTTGCAAAAGAACCTAAGGAAGACAGGCTGAGGGGGA
CGTCCTCAAGCAGACACAGACCT------------------------AATCCACACCTGCTGGATCACACAGAGCTGCAA
AGTGGCAATTCTATCAGCAGTGAAGAA---ATAAAGGAAAAA---AGCTCCCCCCAAATGCCCATCAGGCACAGCAGGAC
GCTGCACCTCACAGGGGCTGTGGAAGCTTCTATTGGAGCCAGGGAGAGTAAGAAGCCAGCTGGACAAGTAAGGGAGAGAC
ATGCCGGGGACTCTTTCCTAGAACCAAGATTAGCAAGACTACCTGCT---TTTACTAACAGTTCAAGCCCTGATAACCTT
AAAGAATTTGTCAACCTTAGTGCACAGACAGAAGAGATGGAAGAGAAC---CCAGAAACAGTACAAGTGTCCGAAAGTAC
CAGAGACTCCAAAGGTCCTGTGTTAAGTGGGGAAAAG---GGAGTGCAA---ACCGAGAGGTCTATGGAGAGCACTAGCA
TTTCACTAGTCCCTGACACTGACTGTGGCACTCAGGACAGTGTCTCCTTACTGGAAGCCGACAGCCTCAGG---AAGGCA
CGG---AGAGCATCGCATCAGTGTATGGCTCAATATGTGGCGGTTGCGAAGCCCAAGGAACTTCTGCCTGCTTGT---TC
TGAAGACACTGGAAACGGCACAGACAGCTTAAATGATCCATTGAGATGTGGAGGGAGC---CACATCCAGGAGGCAAATA
TAGAAATGGAAGATAGTGAACTCGACACTCAGTATTTACAGAATACATTCCAGGCTTCAAAGCGTCAGTCATTTGCTCTC
TTTTCAAATCCAGGAAACTCAAAAAAGGAATCAACAACAGTCTGTGCCCACTCTGAGTCCTTTAAGAAACAAAATCCAGA
AGTCATTCCTGAATGTGAACAAACAGAAGAAAATTGGGGCAAGAAAGTGCCTAAAATTAGTTGTGTGCAAGAGAGCGCC-
--------------CCTCTGGTTTCTCAGAGGGATCAG---CCAGGCACCAGCATCATATGTAGCGGCACAGGAGTCTCG
AGGCTCTGTCTCTCGTCTTGGTTCACA---GGCAGCAAAACTGAACTCGTCACAGCTGACAAACATGGAATTTCACAAAA
TCCATATCACATGCCATCAATTTCTCCCATCAGGCCATTTGTTAAAACTCCATGTAAGAAAACC----------------
-----------CGTTCCTCATCACCTGGAGAAGCCACAGGTAACCAGATCATCCTTCAGAGCACC---------------
------------AGCCATCGCGCTTGCAGAGAAGCCAGCTTGGGCAGTGGGAACGAAGGGGGCTCCAGT-----------
----------------------------------------------------GGGGAGCACATTCAAGCAGAACCCAGTA
GACACCAAGAGCCTGAACTA------------AGATTAGGTCTGACGCAGCCCGAAGTCTACCAGCAAAGTCTT---CCT
GTAGGTGACTGTAGACATCCCGAAATACAAACACGAGGAGAAAATGGAGTGGTAGCTCAGGCTGTCCATGCAGATTTCTC
TCCGTGTCTAATTTTAGATAACGTGGAACAG---CCTATGGGAAATAATCCTGCTTCTCAGATCTGTTCTGAGACGCCCG
ATGACCTGTTAGATGATGAGAACAAAAAGGAAGATGCCAGCTTTGCCGAAGGTGGCATTAAGGAAACTTCTGCCATTTTT
AGCAAGAGTGTCCAGACAAGACGATTCAGCAGGAGCCCCAGCCCTGTAACCAAT---ACCACTTTGGCTCAGGGTCACCG
AAGAAGGGCGAGAAAACTCGAGTCTTCTGAGGAGAGCATGTCAAGTGAG
>Mouse
TGTGGCACAGATGCTCATGCCAGCTCATTACAGCCTGAGACCAGCAGTTTATTGCTCATTGAAGACAGAATGAATGCAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCATAGCAGTGAGCCAGCAGAGCAGATGGGCTGCAAGTAAAGGAA
CATGTAACGAC---AGGCAGGTTCCCAGCACTGGGGAAAAGGTAGGTCCAAACGCTGACTCCCTTAGTGATAGAGAGAAG
TGGACTCACCCGCAAAGTCTGTGCCCTGAGAATTCTGGAGCT---ACCACCGAT---GTTCCTTGGATAACACTAAATAG
CAGCGTTCAGAAAGTTAATGAGTGGTTTTCCAGAACTGGTGAAATGTTAACTTCTGACAGCGCATCTGCCAGGAGGCACG
AGTCAAATGCTGAAGCAGCTGTTGTGTTGGAAGTTTCAAAC------GAAGTGGATGGGGGTTTTAGTTCTTCAAGGAAA
ACAGACTTAGTAACCCCCGACCCCCATCATACTTTAATGTGTAAAAGTGGAAGAGACTTCTCCAAACCAGTAGAGGATAA
T---ATCAGTGATAAAATATTTGGGAAATCCTATCAGAGAAAGGGAAGCCGCCCTCACCTGAACCATGTGACTGAA----
--ATTATAGGCACATTTATTACAGAACCACAGATAACACAA---------------------------------------
---------------------GAGCAGCCCTTCACAAATAAATTAAAACGTAAGAGA------AGTACATCCCTTCAACC
TGAGGACTTCATCAAGAAAGCAGATTCAGCAGGTGTTCAAAGGACTCCTGACAACATAAATCAGGGAACTGACCTAATGG
AGCCAAAT---------GAGCAAGCAGTGAGTACTACCAGTAACTGTCAGGAGAACAAAATAGCAGGTAGTAAT---CTC
CAGAAAGAGAAAAGCGCTCATCCAACTGAA------TCATTGAGAAAGGAACCTGCTTCCACAGCAGGAGCCAAATCTAT
AAGCAACAGTGTAAGTGATTTGGAGGTAGAATTAAACGTCCACAGTTCAAAAGCACCTAAGAAAAATAGGCTGAGGAGGA
AGTCTTCTATCAGGTGTGCTCTTCCACTTGAACCA---ATCAGTAGAAATCCAAGCCCACCTACTTGTGCTGAGCTTCAA
ATCGATAGTTGTGGTAGCAGTGAAGAA---ACAAAGAAAAAC---CATTCCAACCAACAGCCAGCCGGGCACCTTAGAGA
GCCTCAACTCATCGAAGACACTGAACCTGCAGCGGATGCCAAGAAG---AACGAGCCAAATGAACACATAAGGAAGAGAC
GTGCCAGCGATGCTTTCCCAGAAGAGAAATTAATGAACAAAGCTGGTTTATTAACTAGCTGTTCAAGTCCTAGAAAATCT
CAAGGGCCTGTCAATCCCAGCCCTCAGAGAACAGGAACA---GAGCAA---CTTGAAACACGCCAAATGTCTGACAGTGC
CAAAGAACTCGGGGATCGGGTCCTAGGAGGAGAGCCC---AGTGGCAAAACCACTGACCGATCTGAGGAGAGCACCAGCG
TATCCTTGGTACCTGACACTGACTACGACACTCAGAACAGTGTCTCAGTCCTGGACGCTCACACTGTCAGA---TATGCA
AGA---ACAGGATCCGCTCAGTGTATGACTCAGTTTGTAGCAAGCGAAAACCCCAAGGAACTCGTCCATGGC------TC
TAACAATGCTGGGAGTGGCACAGAGGGTCTCAAGCCCCCCTTGAGACACGCGCTTAAC---CTCAGTCAGGAGAAA---G
TAGAAATGGAAGACAGTGAACTTGATACTCAGTATTTGCAGAATACATTTCAAGTTTCAAAGCGTCAGTCATTTGCTTTA
TTTTCAAAACCTAGAAGTCCCCAAAAGGACTGTGCT------------CACTCTGTGCCCTCAAAGGAACTGAGTCCAAA
GGTGACAGCTAAAGGTAAACAAAAAGAA---CGTCAGGGACAGGAAGAATTTGAAATCAGTCACGTACAAGCAGTTGCGG
CCACAGTGGGCTTACCTGTGCCCTGTCAAGAAGGTAAG---CTAGCTGCTGATACAATGTGT------GATAGAGGTTGT
AGGCTTTGTCCATCATCTCATTACAGA---AGCGGGGAGAATGGACTCAGCGCCACAGGTAAATCAGGAATTTCACAAAA
CTCACATTTTAAACAATCAGTTTCTCCCATCAGGTCATCTATAAAAACTGACAATAGGAAACCT---CTGACAGAGGGAC
GATTTGAGAGACATACATCATCAACTGAGATGGCGGTGGGAAATGAGAACATTCTTCAGAGTACAGTGCACACAGTTAGC
CTGAATAAC---AGAGGAAATGCTTGTCAAGAAGCCGGCTCGGGCAGTATTCATGAAGTATGTTCCACT-----------
----------------------------------------------------GGTGACTCCTTCCCAGGACAACTAGGTA
GAAACAGAGGGCCTAAGGTGAACACTGTGCCTCCATTAGATAGTATGCAGCCTGGTGTCTGTCAGCAAAGTGTT---CCT
GTAAGTGAT---AAGTATCTTGAAATAAAAAAGCAGGAG---------------GGTGAGGCTGTCTGTGCAGACTTCTC
TCCATGTCTATTCTCAGACCATCTTGAGCAA---TCTATG---AGTGGTAAGGTTTTTCAGGTTTGCTCTGAGACACCTG
ATGACCTGCTGGATGATGTTGAAATACAGGGACATACTAGCTTTGGTGAAGGTGACATAATGGAGAGATCTGCTGTCTTT
AACGGAAGCATCCTGAGAAGGGAGTCCAGTAGGAGCCCTAGTCCTGTAACCCAT---GCATCGAAGTCTCAGAGTCTCCA
CAGAGCGTCTAGGAAATTAGAATCGTCAGAAGAGAGCGACTCCACTGAG
>Rat
TGTGGCACAGATGCTCGTGCCAGCTCATTACAGCGTGGGACCCGCAGTTTATTGTTCACTGAGGACAGACTGGATGCAGA
AAAGGCTGAATTCTGTGATAGAAGCAAACAGTCTGGCGCAGCAGTGAGCCAGCAGAGCAGATGGGCTGACAGTAAAGAAA
CATGTAATGGC---AGGCCGGTTCCCCGCACTGAGGGAAAGGCAGATCCAAATGTGGATTCCCTCTGTGGTAGAAAGCAG
TGGAATCATCCGAAAAGCCTGTGCCCTGAGAATTCTGGAGCT---ACCACTGAC---GTTCCTTGGATAACACTGAATAG
CAGCATTCAGAAAGTGAATGAGTGGTTTTCCAGAACTGGTGAAATGTTAACTTCTGACAATGCATCTGACAGGAGGCCTG
CGTCAAATGCAGAAGCTGCTGTTGTGTTAGAAGTTTCAAAT------GAAGTGGATGGATGTTTCAGTTCTTCAAAGAAA
ATAGACTTAGTTGCCCCTGATCCCGATAATGCTGTAATGTGTACAAGTGGAAGAGACTTCTCCAAGCCAGTAGAGAATAT
T---ATCAACGATAAAATATTTGGGAAAACCTATCAGAGAAAGGGAAGCCGCCCTCACTTGAACCATGTGACTGAA----
--ATTATAGGCACATTTACTACAGAACCACAGATTATACAA---------------------------------------
---------------------GAGCAGCCCTTCACAAATAAATTAAAACGCAAAAGA------AGTACATGCCTTCATCC
TGAGGACTTTATCAAGAAAGCAGATTTAACAGTTGTTCAAAGGATTTCTGAAAATTTAAATCAGGGAACTGACCAAATGG
AGCCAAAT---------GACCAAGCAATGAGTATTACCAGTAACGGTCAGGAGAACAGAGCAACAGGTAATGAT---CTT
CAGAGAGGGAGAAATGCTCATCCAATAGAA------TCATTGAGAAAGGAACCTGCTTTCACAGCTAAAGCCAAATCTAT
AAGCAACAGTATAAGTGATTTGGAGGTAGAATTAAATGTTCACAGTTCAAAAGCACCTAAGAAAAATAGGCTGAGGAGGA
AGTCT---ACCAGGTGTGTTCTTCCACTCGAACCA---ATCAGTAGAAATCCGAGCCCACCTACTTGTGCTGAACTTCAG
ATCGAGAGTTGTGGTAGCAGTGAAGAA---ACAAAGAAAAAC---AATTCCAACCAAACCCCAGCCGGGCACATTAGAGA
GCCTCAACTCATCGAAGACACAGAACCCGCAGCTGATGCCAAGAAG---AACGAGCCAAATGAACACATAAGGAAGAGAA
GTGCCAGTGATGCGTTCCCAGAAGAGAAATTAATGAACAAAGCTGGTTTATTAACTAGCTGTTCAAGTCCTAGAAAGCCT
CAAGGACCTGTCAATCCTAGCCCTGAGAGAAAAGGAATA---GAGCAA---CTTGAAATGTGCCAGATGCCTGATAATAA
CAAAGAACTCGGGGATTTGGTCCTGGGAGGAGAGCCC---AGTGGGAAACCTACTGAACCATCTGAGGAGAGCACCAGTG
TGTCCTTGGTACCCGACACAGACTACGACACCCAGAACAGTGTCTCAATACTGGAAGCGAACACTGTCAGA---TATGCA
AGA---ACAGGATCAGTTCAGTGTATGACTCAGTTTGTCGCAAGTGAAAACCCCAAGGAACTTGTCCATGGT------TC
TAACAATGCTGGAAGTGGCTCGGAGTGCTTCAAGCACCCATTGAGACATGAACTTAAC---CACAATCAAGAGACA---A
TAGAAATGGAAGACAGTGAACTTGATACTCAGTATTTGCAGAATACATTTCAAGTTTCAAAGCGTCAGTCATTTGCTTTA
TTTTCAAAACTTAGAAGTCCCCAAAAGGACTGTACTCTGGTAGGTGCCCGCTCTGTGCCCTCAAGGGAACCAAGTCCAAA
GGTGACTTCTAGAGGTGAACAAAAAGAA---CGTCAGGGACAAGAAGAGTCTGAAATCAGTCATGTACAGGCAGTCACAG
TCACAGTAGGCTTACCTGTGCCCTGTCAGGAAGGTAAG---CCAGGTGCTGTTACAATGTGT------GCTGATGTTTCT
AGGCTTTGTCCGTCATCTCATTATAGA---AGCTGTGAGAATGGACTCAACACCACAGATAAATCTGGAATTTCACAAAA
CTCACATTTTAGACAATCAGTTTCTCCCCTCAGGTCATCTATAAAAACTGACAATAGAAAAACT---CTGACAGAGGGNC
GATTTGAGAAACAT---------ACTGAAAGGGGRATGGGAAATGAGACTGCTGTTCAAAGTACAATACACACAATTAGT
CTAAATAAC---AGAGGAGATGCTTGTCTAGAAGCCAGCTCAGGCAGTGTTATTGAAGTACATTCCACT-----------
----------------------------------------------------GGTGAAAACGTCCAGGGGCAACTAGATA
GAAACAGAGGGCCTAAGGTAAACACCGTGTCTCTATTAGATAGTACACAGCCTGGTGTCTCTAAGCAGAGTGCT---CCT
GTAAGTGAT---AAGTATCTTGAAATA---AAGCAGGAG---------------AGTAAGGCTGTCAGTGCAGACTTCTC
TCCATGTCTGTTCTCAGATCATCTTGAAAAA---CCTATGAGAAGTGATAAGACTTTTCAGGTTTGCTCTGAGACACCTG
ATGACCTGTTGGATGATGTTGAAATACAGGAAAATGCTAGCTTCGGTGAAGGTGGCATAACGGAAAAGTCTGCTATTTTT
AATGGAAGTGTCCTGAGAAGAGAGTCCAGTAGGAGCCCTAGCCCTGTAACCCAT---GCATCGAAGTCGCGGAGTCTCCA
CAGAGGGTCTAGGAAATTAGAATTCTCAGAAGAGAGCGACTCCACTGAG
>NineBande
TGTGGCACAAATACTCATGCCAACTTATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGCGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCCAGCATAGAGAAAAAGGTAGATGTGGATGCTGATCCCCTGTATGGGCGAAAAGAA
CTGAATAAGCAGAAACCTCCATGCTCTGAGAGTCATAGAGAT---ACCCAAGAT---ATTCCTTGGATAATGCTGAATAG
TAGCATTCAGAAAGTTAACGAGTGGTTTTCCAGAGGTGATGACATATTAACTTCTGATGACTCACACGATAGGGGGTCTG
AATTAAATGCAGAAGTAGCTGGTGCATTGAAAGTTTCAAAA------GAAGTAGATGAATATTCTAGTTTTTCAGAGAAG
ATAGACTTAATGGCCATTAATCCTCATGATACTTTACAATTTGCAAGTGAAAGAGTCCAATTGAAACCAGCAGAGAGTAA
C---ATCAAAGATAAAATATTTGGGAAAACCTATCATAGGAAGGCAAGCCTCCCTAACTTGAGCCACATAACCCGAAACC
TTTTTATAGGAGCTATTGCTGCAGAGCCCAAGATAACACAA---------------------------------------
---------------------GAGCATTCCCTCCAAAATAAAATAAAGCGTAAAAGGAGAACTGCATCAGGCCTTCGTCC
TGAGGATTTATCCAAGAAAGTAGATTTGACAGTTGTTCAAAAAACCCCTGAAAAGATAAATCAGGGAACTGACCAAATGG
AGCAGAAT---------GATCCAGTGATGAATATTGCTAATAGTGGTCATGAGAATGAAACAAAAGGTGATTGT---GTT
CAGAAAGAGAAAAATGCTAATCCGACAGAA------TCATTGGGAAAAGAATCTGCTTTCAGAACTAAAGGCGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTAAATATTTTAAATTCAAAAGCATCTAAGAAGAATAGGCCGAAGAGGA
TGTCCTCTACCAGGCATATTCATGCACTTGAACTAGTCGGCAGTAGAAATCCAAGCCCACCTAATCATACTGAACTACAA
ATTGATAGTTGTTCTAGCATTGAAGAG---ATAGAGAAAATA---AATTCTAACCAAAAGCCAATCAGACACAACAGAAT
GCTTCAACTCACGAAAGAAAAAGAAACCACAACTGGAGCCAAAAAGAACAATAAGCCAAATGAACAAATAAGTGAAAGAC
ATGCCAGTGATGCTTTCCTAGAACTTAAA------AATGTAACTGATTTTCTTCCTAAATGTTCAAGTTCTGATAAACTT
CAAAAATTT---AATTCTAGCCTGCAAGGAGAAGTAGCA---GAGAAC---CTAGAAACAATTCAAGTGTCTGATAGTAC
CAGGGACCCTGAAGATCTGGTGGTAAGTGGAGAAAAG---TGTTTGCAA---ACTGAAAGATCTGCAGAGAGTACCGGTA
TTTCAGTGGTACCTGATACTGATTATGGCACTCAAGACAGTATCTCATTACTGGAAGCTGACACCCTGGGG---AAGGCA
AAA---ACAGCACTAAATCAACATGTGAGTCAGTATGTAGCAATTAGAAATGCCACTGAACTTTCCCATGGTTGT---TC
TAAAGACACTAGAAATGACACTGAAGATTTTAAGGATTCATTGAGACATGAAGTTAAC---CACACTCAGGGGACAAATG
TTGAAATAGAAGAGAGTGAACTTGATACTCAGTATTTGCAGAATACATTCAAGATTTCAAAGCGCCAGTCATTTGCTCTG
TTTTCGAATCCA---------GAAAATGAATGTGCAACAGTCTGTGCCCACTCCAGGTTCTTAGGGAAACAAAGTCCAAA
AGTCACCTTTGAATGTAGACATAAAGAAGAAAATCAGGGGAAGAAAGAGTCTAAAATCAAACATGTGCAGGTAATTCACA
CAACTGCAGGCTTTCCTATAGTTTGTCAGAAAGATAAG---CCAGGTGATTATGCCAAAGGTAGCATTCAAGGAGTCTCT
AGGCTTTGTCAGTCCTCTCAGGCCAGA---GGCAATGAATCTGAACTCATTAATTCAAATGAACATGAAATTTCACAAAA
CCCAGATCAAATGCCATCACTTTCTCACATGAAGTCATCTGTTAAAACTAAATGTAAGGAAAAC---CTGTCAGAGGAAA
AGTTTGAGGAACTTACAGTGTCACTTGAAAGAACAATGGTAAATGAGAACATCATTCAAAGTACAGTAAGCACAATTAGC
CACAGTAACATTAGAGAAAACACTTTTAAAGAAGCCAGCTCAAGCAGTATTAATGAAGTAGGGTCCAGT-----------
----------------------------------------------------GATGAGAACATTCAAGCAGAAGTAGGTA
GAAACAGAGCACCTAAATTAAATGCTATGCTCAGATTAGGTCTTATGCAACCTGAAGTCTATAAGCAAAGTCTT---CCT
ATAACCAATTGTAAATATCCTGAAATAAAAAGTCAAGGAGAAAATGAAGAAGCAATTCGGGCTGTTGATATAGACTTCTC
TCCATGTCTAATTTCAGATAACCTACAACTA---CCTATGGGAAATAGTTGTGCTTCCCAGATTTGTTCTGAGACACCTG
ATGACTTGTTAGATGATGATGAAATAAAGGAAAATAACTGCTTTGCTGAAAGTGACATTAAGGAAAGATCTGCTATTTTT
AGCAAAACTGTCCAGAAAAGAGAGTTCAGAAGGAGCCCTAGCCCTTTAGTCCAT---ACAAGTTTTGCTCAGGGTCACCA
AAGAAAGCCCAGGAAATTAGACTCCTCAGAAGAGGACGTATCTAGTGAG
>HairyArma
TGTGGCACAAATACTCATGCCAACTTATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAGTGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGCGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCCAACACAGAGAAAAAGGTAGATGTGGCTGCTGATTCCCTGTATGGGCGAAAAGAA
CTGAATAAGCAGAAACTTCCATGCTCTGAGAGTCCTAGAGAT---ACCCAAGAT---ATTCCTTGGATAACGCTGAATAG
TAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGACCTATTAACTTCTGATGACTCACACGATGGGGGGTCTG
AATCAAAAGCAGAAGTAGCTGGTGCATTAAAAGTTCCAAAT------GAAGTAAATGGATATTCTAGTTCTTCAGAGAAG
ATAGACTTATTGGCCAGTGATCCTCATAATGCTTTAATATTTGCAAGTGAAAGAGTCCAATCCAAACCAGCAGAGAGTAA
C---ATCAAAGATAAAATATTTGGGAAAACCTATCACAGGAAGGCAAGCTTTCCTAACTTGAGCCACATAACTGAGGATC
TTTTTATAGGAGCTATTGCTACAGAACCCAAGATAATACAA---------------------------------------
---------------------GAGCATTCCCTCACAAATAAAATAAAGCGTAAAAGGAGAACTACGTCATGCCTTCATCC
TGAGGATTTTATCAAGAAAGTAGATTTGACAGTTGTTCAAAAGACGCCTGAAAAGATAAATCAGGGAACTGACCAAATGG
AGCAGAAT---------GATCAAGTGATGAATAGTGCTAATAGTGGTCATGAAAATGAAACAAAAGGTGATTAT---GTT
CAGAAAGAGGAAAATGCTAACCCAATAGAA------TCATTGGAAAAAGAATCTGCTTTCAGAACTAAAGGTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTAAATATCTATAATTCAAAAGCATCTAAGAAGAATAGGCTGAGGAGGA
TGTCCTCTACCAGGCATATTCATGCACTTGAACTAGTAGGCAATAGAAATCCAAGCCCACCTAAACATACTGAACTACAA
ATTGATAGTTGTTCTAGCACTGAAGAG---ATAGAGAAAATA---AATTCTAACCAAAAACCAATCAGACACAACAGAAT
GCTTCAACTCATGAAAGAAAAAGAAAACACAACTGGAGCTAAAAAGAATAACAAGCCAAATGAACAAATAAGTGAAAGAC
ATGCCAGTGATGTTTTCCCAGAACTAAAATTAACAAATGTAACCGATTTTCTTCCTAAATGTTCAAATCCTGATAAACTT
CAAGAATTTGTTAATTCTAGCCTGCAAGGGGAAGTAGCA---GAGAAC---CTAGAAACAATTCAAGTGTCTGATACTAC
CAGGAATCCTGAAGATCTGGTGTTAAGTGAAGGAAAG---AGTTTGCAA---ACTCAAAGGTCTGCAGAGAGTACCAGTA
TTTCAGTGGTACCTGATACTGATTATGGCACTCAAGACAGTGTCTCATTACTGGAAGCTGACACCCTGGGG---AAGGCA
AAA---ACAGCACTAAATCAACCTATGAGTCAGTATGCAGCAATTAAAAATGCCACTGAACTCTCCCATGGTTGT---GC
TAAAGACACTAGAAATGACACTGAGGATTTTAAGGATCCGTTGAGACATGAAGTTACC---CACACTCAGGAGACTAGTG
TAGAAATGGAAGAGAGTGAACTTGATACTCAGTATTTACAGAATACATTCAAGATTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCGAATCCA---------GAAAATGAATGCGCAACAGTGTGTGCCCACTCCAGGTTCTTAGGCAAACAAAGTCCAAA
AGTCATTTTTGAATGTAGGCAAAAAGAAGAAAATCAGGGGAAGAAAGAGTCTAAAATCAAACATGTGCAGGCAGTTCATA
CAACTGCAGGCTTTCCTGTAGTTTGTCAGAAAGATAAG---CCAGGTGATTATGCCAAATGTAGCATTCAAGAAGTCTCT
AGGCTTTGTCAGTCCTCTCAGTTCAGA---GGCAATGAATCTGAACTCATTACTGCAAATGAACATGAAATTTCACAAAA
CCCAGATCAAATGCCATCACTTTCTCACATCAGGTCATCTGTTAAAACTAAATGTAAGGAAAAC---CTGTCAGAGGAAA
AGTTTGAGGAACTTACAATATCACTTGAAAGAACAGTGGGAAATGAGAACATCGTTCAAAGTACAGTAAGCACAATTAGC
CACAATAACATTAGAGAAAACGCTTTTAAAGAAGCCAGCTCAAGCAGTATTAATGAAGTAGGTTCTAGT-----------
----------------------------------------------------GGTGAAAACATTCAAGCAGAACTAGGTA
GAAACAGAGCACCTAAATTAAATGCTATGCTCAGATTAGGTCTTATGCAACCTGAAGTCTATAAGCAAAGTCTT---CCT
ATAACTAGTTGTAAACATCCTGAAATAAAAAGGCAAGGAGAAAATGAAGAAGCAATTCAGGCTGTTGATACTGATTTCTC
TCCACATCTAATTTCAGATAACCTAGAACTA---CCTATGGGAAATAGTCATGTTTCTCAGATTTGTTCTGAGACGCCTG
ATGATTTGTTAGATGATGATGAAATAAAGGAAAATAACAGCTTTGCTGAARATGGCATTAAGGAAAGATCTGCTGTTTTT
AGCAAAAGTGTCCAGAAAAGAGAGTTCAGAAGGAGTCCTAGCCCTTTAGGCCAT---ACAAGTTTGGCTCAGGGTCACCA
AAGAAGGGCCAGGAAATTAGACTCCTCAGAAGAGGACGTATCTAGTGAG
>Anteater
TGTGGCACAAATATTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAAAGAATGTAGA
AAAGGCTGAATTCTGTGATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAGCAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCACACTACCAGCACAGAGAAAAAAGTAGATGTGGATGCTGATCCCCTGCATCGGAGAAAAGAA
CTGAAGAAGTGGAAATCTCCATACTCTGAGAATCCTAGAGGT---ACCCAAGAT---ATTCCTTGGATAACACTGAATAG
TAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGACATATTGACTTCTAATGACTCATGCAATGAGGGGTCTG
AATTAAATGCAGAAGTAGCTGATGCATCAAAAGTTCCAAAT------GACGTAGATAGATATTCTGGTTCTTCAGAGAAA
ATAGACTTAATAGCCAGTGACCCTCATAATGCTTTAATATGTGCAAGTGAAAAAGTCCAGTCCAAACCAACAGAGAGTAA
T---ATCAAAGATAAAATATTTGGGAAAACCTATCACAGGAAGGCAAGCCTCCCTAACTTGAGCCGTATAGCTAAAGATC
TTTTTATAGGAGCTGTTGCTGCAGAACCTAAGATAACACAA---------------------------------------
---------------------GAGCTCCCCCTGACAAATGAAATGAAGCTTAAAAGGAGGACTACATCAGGACTTCATCC
TGAGGATTTTATCAAGAAAGTAGATTTGACAGTTGTTCAAAAGAAGCCTAAAATGATAAATCAGGGAACTAACCAAATAG
AGCAGAAT---------TGTCAACTGATGAATATTGCCAATAGTGGTAATGAAAATGAAACAAAAGGTGATTTT---GTT
CAGAAGGAGAAAAGTGCTAACCCAACAGAA------TCATCAGAAAAAGAATCTGCTTTCAGAACTAAAGGTGAACCTAT
AAGTAGTAGTATAAGCAATATGAAACTAGAATTAAATACCTGCAATTCAAAAGCATCTAAGAAGAATAGGCTGAGGAGAA
TGTCCTCTACCAGGCATATGCATGCACTTGAACTAGTAGCCAATAGAAAGCCAAGCCAGCCTAATCACACTGAACTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAA---ATAAAGAAAAAA---AAATCTGACCAAAAGCCAATAAGACACAGCAGAAC
AGTTCAATTCATGAAAGATAAAGAAACTGCAATTGGAGCCAAGAAGAGTAACAAGCGAAATGAACAAATAAATAAAAGAC
ATGCCAGTGATGCTTTCCCAGAACTAAATTTAACAAACGTAACTGGTTTTCCTACTAAATGTTCAAATTCTGATAAACTT
CAAGAATTTGTCAATTCTAGCCTGCAAGGAGAAGCAGCA---GAGAAC---CTAGAAACAATACAAGTGTCTGATACTAC
CATGGACCCTGAAGGTCTGGTATTAAGTGAAGGAAAG---AATTTGCAA---ACTGAAAGATCTGTAGAGAGCACCAGTA
TTTCATTGGTGCCTGACACTGATTATGGCACTCAAGATAGTATCTCATTACTAGAAGCTGCTACCCTAGGG---AAAGCA
AAA---GCAGCACCAAATCAACATGTGAGTCTGTGTGCAGCAGTTGGAAATGCCACTGAACTTGTCCATGGTTGT---TC
TAAAGATACTAGAAATGACACTGAAGATTTTAAGGATTCATTGAGACATGAAGTTAAC---CACACACAAGGGACAGTCA
TAGAAAAGGAAGAGAGTGAACTTGATACTCAGTATTTNNNNNNNNNNTACAAGATTTCAAAGCGTCAGTCATTTGCTCTG
TATTCAAATTCT---------GAAAAGGAATGTGTAACAATCTGTGCCCACTCCAGGTCCGTACGGAAACAAAGTCCAAA
AGTAACTTTTGACTATAGACAAAAAGAAGAAAATCAAGGAAAGAAAGAGTCTAAGATCAAACATGTGCAGGCAGTTCATA
CAACCGCAGGCTTCTCTGTAGTTTGTCAGAAAGATAAGAAGCCCCATGATTATGCCAAGTGTAGCATTCAGGGAGTCTCT
AAGCTTTGTGAGTCATCTCAGTTCAGA---GGCAATGAATCTGAACTCATTACTGCAAACGAACATGGAATTTCCCCAAA
TCCAGATCAAATGCCATCACTTTCTCCCAACAGGTCATCTGTTAAAACTAAATATAAGAAAAAC---TTGTCAGAAGAAA
GGTTTGAGGAACATACAGTGTCACTTGATAGAGCAGTGGGAAATGAGAGCATCATTCAAAGTACAGTAAGCACAATTAGC
CAAAATAACATTAGAGAAAGCACTTTTAAAGAAGCCAGCTCAAGCAGTATTAATGAAGTAGGTTCCAGTATTAATGAAGT
GGGTTCCAGTATTAATGAAGTGGGTTCCAGT---------------------GGTGAGAACGTTCAAGCAGAGCTAGGTA
GAAACAGA---CCTAAGCTAAATGCTATGCTCAGATTAGGTCTTATGCAACCTGAAGTCTATGAGCAAAATCTT---CCT
ATAACTAATTTTAAACTTTCTGAAATTAAAAAACAAGGAGAAAATGAAGAAGTAGTTCAGGCTGTTAATACAGATTTCTC
CCCATGTCTAATTTCAGATAACCTAGAACTG---CCTATGGGAAGTAGTCGTGTTTCTCAGATTTGTTCTGAGACACCTG
ATGACCTGTTAGATGATGATGAAATAAAGGAAAATAACAGCTTTGCTGAAAGTGGCGTTAAGGAAAGATCTGCTGTTTTT
AGCAAAAGTGTCCAGAGAAGAGAATTCAGAAGGAGCCCTAGCCCTTTAGCCCAA---ACAAGTGTGGCTCAGGGTCACCA
AAGAGGGGCCAGGAAATTAGCCTCCTCAGAAGNGGACNAGTCTAGNGAG
>Sloth
TGTGGCACATATACTCATGCCAGCTCATTACAGCGTGAGAACAGCAGTTTATTACTCACTAAAAACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAGCAGCCTGGCTTAGCAAGGAGCCAACAGAACAGATGGGCTGAAAGTAAGGAAA
CACGTAATGAT---AGGCAGACTCCCAGCACAGAGAAAAAGGTAGATGTGGATGCTGATCCCCTGTATGGGCGAAAAGAA
CTGAATAAGCAGAAACCTCCATGCTCTGAGAGTCCTCAAAAT---ACCCAAGAT---ATTCCTTGGATAACACTGAATAG
TAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGACATACTAACTTCTGATGACTCACACAATGGGGGGTCTG
AATCAAATGCAGAAGTAGTTGGTGCATTGAAAGTTCCAAAT------GAAGTAGATGGATATTCTGGTTCTTCAGAGAAG
ATAGACTTAATAGCCAGTGATCCTCACAATGCTTTAATATTTGCAGGTGAAAGAGTCCAGTCCAAACCAACAGAGACTAA
C---ATTGAAGATAAAATATTTGGGAAAACCTATCACAGGAAGGCAAGCCTCCCTAACTTGAGCCACATAGCTGAAAATC
TTTTTATAGGAGCCATTGCTACAAAACCTAAGATAACACAA---------------------------------------
---------------------GAGCACCCCCTGACAAAGAAAATAAAGCATAAAAGTAGGACTACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGTCGATTTGACAGTTGTTCAAAAGATGCCTGAAAAGATAAATCAGGGAACTGACCAAATGG
AGCAGAAG------AATAGTCAAGTGATAAATATTGCTAATAGTGGTCATGAGAATGAAACAAAAGATGATTAT---GTT
CAGAAAGAGAAAAATGCTAACCCAACAGAA------TCATTGGAAAAAGAATCTGCTTTCAGAACTGAAGGTGAACCCAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTAAATATCTTCAATTCAAAAGTATCTAAGAAGAATAGGCTGAAGAGGA
TGTCCTCTACCAGGCATATTCATGCACTTGAACTAGTAGCCAATAGAAATCCAAGCCAACCTAATCATAATGAACTACAA
ATTGATAGTTGTTCTAGCAGTGAAGAG---ATAAAGAAAGAA---AATTCTGTCCAAAAGCCAATAAGGCACAGCAGAAT
GCTTCAACTCCTGAAAGGTAAAGAAACTCCAACCGTAACCAAGAAGAGTAACAAGCGAAATGAACAAATAAGTAAAAGGC
ATTCCAGTGATGCTTTCCCAGAACTAAATTTAACAAATGTAACTGGTTTTCTTACTAAATGTTCAAGTTCTGATAAACTT
CAAGAATTTGTCAATTCTAGCCTGCAAGGAGAAGTAGCA---GAGAAC---CTAGAAACAATTCAAGTGTCTGATAGTAC
CAGAGACCCCGGAGCTCTGGTGTTAAGTGGAGGAAAG---GGTTTGCAA---ACTGAAAGATCTCTAGAGAGTACCAGTA
TTACAATGATACCTGAAACTGATTATGACACTCAAGACAGTATCTCCTTACTGGAAGCTGACACCCTAGGG---AAAGCA
AAA---GCAGCACCAAATCAACATGTGAGTCAGTATGCAGCAATTGGAAATGCCACTAAACTTTTCCATGGTTGT---TC
TAAAGATACTAGAAGTGACACTGAGAATTTTAAGGATCCATTGAGACATGAAGTTAAC---CACACACAGGAGACATTTG
TAGAAATGGAAGAGAGTGAACTTGATACTCAGTATTTACAGAATACATTCAAGATTTCAAAGCGTCAATCATTTGCTCTG
TTTTCAAATCCA---------GAAAAGGAATGCGCAACAGTCTCTGCCCACTCCAGGCCCTTAGGAAAACAAAGTCCAAA
AGTCACTTTTGACTGTAGACAAAAAGAA---GATCAGGAGAAGAAGGAGTCTAAAATCAAACACGTGCAGGCAGTTCATA
CAACTGCAGACTTTCCTGTAGTTTGTCAGAAAGATAAG---CCAGGTGATTATGCTAAATGTAGCATTCAAGGAGTCTCT
AAGCTTTGTCAGTTATTTCAGTTCAGA---GGCAATGAATCTGAACCCATTACTGCAGATGAACATGAAATTTCACAAAA
TCCAGATCAGATGCCATCACTTTCTCCCATGAAGTCATCTGTTAAAAGTAAATTTAAGGAAAAC---CTGTCAGAGGAAA
GATTTGAGGAACATACAGTATCACTTGAAAGAGCAGTGGGAAAGGAGCACATCATTCAAAGGACAGTGAGTCCAATTAGC
CAAAATAACATTAGAGAAAGCGCTTTTAAAGAAGCCAGCTCAAGCAGTATCAATGAAGTAGGTTCCAGTGTTAATGAAGT
AGGTTCCAGTGTTAATGAAGTAGGTTCCAGT---------------------GGTGAGAACACTCAAGCAGAGCTAGGTA
GAAACAGAGGATCTAAATTAAGTGCTATGCTCAGATTAAGTCTTATGCAACCTGAAGTCTATAAGCAAAGTCTT---CCT
ATAACTAATTGTAAGCATCCTGAAATTAAAAAGCAAGGAGAAAATGAAGAAGTAGTTCAGGCTGTTAAAACA--------
----TGTCTAATTTCAGATAACCTAGAACTA---CCTATGGGAAGTAGTCATGCTTCTCAGATTTGTTCTGAGACACCTG
ATGATCTGTTAGATGATGGTGAAATAAAGGAAAATAACAGCTTTGCTGAAAGTGGCATTAAGGAAAGATCTGCTGTTTTT
ACCAAAAGTGTCCAGAAAAGAGAGTTCAGAAGGAGCCCGAGCCCGTTAGCCCAA---ACAAGGGTCACC---------AA
AAGACGGGCCAGGAAATTAGACTCCTCAGAAGAGGATGTGTCTAGTGAG
>Dugong
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAATAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTCATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAGCAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCTAGCACAGAGAAAAAGGTAGATATGAATGCTAATCCATTGTATGAGAGAAAAGAA
GTGAATAAGCAGAAACCTCCATGCTCCGAGAGTGTTAGAGAT---ACACAGGAT---ATTCCTTGGCTAACACTGAATAG
TAGCATTCAGAAAGTTAATGAGTGGTTTTTCAGAAGTGATGGCCTG---------GATGACTTGCATGATAAGGGGTCTG
AGTCAAATGCAGAAGTAGCTGGTGCTTTAGAAGTTCCAGAA------GAAGTACATGGATATTCTAGTTCTTCAGAGAAA
ATAGACTTAATGGCTAGTGATCCTCATAGTGCTTTAATATGTGAAAGTGAAAGAGTCCTCTTCAAACCAGCAGAAAGTAA
C---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAATTCTCCCTCATTTGAGCCATGTAACTGAAGATC
TAATTATAGGAGCTGTTGCTACAGAACCTCAGATAGCACAA---------------------------------------
---------------------GAACGTCCTCTTACAAATAAATTAAAGCGTAAAAGGAGA---ACATCAGGCCTTCATCC
TGAGGATTTCATCAAGAAAGTAGATTTGGCAGTTGTTCAAAAGACTCCTGAAAAGATAAATCAAGAAACTGACCAAGTGG
AGCAGAAT---------GGTCAAGTGATGAATATTGCTAATGGTGGTCATGGAAATGAAACAAAAGATGATTAT---GTT
CAGAAAGAGAAGAATGCTAACCCAACAGAA------TCACTGACAAAGGAATCTGCTTTCAGAACTAAAGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTAAATATGCATAATTCAAAAGCACCGAAGAAGAACAGGCTGAGGAGGA
AGTCCTCTACCAGGCATATTCATGCACTTGAACTAGTAGTCAATAGAAATCCAAGTCCACCTACTCATACTGAACTACAA
ATTGATAGTTGGTCTAGCAGTGAAGAG---ATAAAGAAA------AGTTCTGAGCAAAAGCCAGTCAGACACAACAGAAA
CCTTCAACTCATGAAAAACCAAGAAACCACAACTGGAGCCAAGAAAAGTAACAAGCCAAAGGAACAAATAAGTAAAAGAC
ATGCCAGTGACGCTTACCCAGAACTAAATTTAACAAGCACAACTGGCTTAATTACTAACTGTTCAAGTTCTCATAATTAT
CAAGAATTT---AATCCTAGCCTTCAGGGAGAAGAAATAGAAGAAAAT---CTGGGAACAATTCAAGTGTCTAATAGAAC
CAGAGACCCCGAGGATCTAGTGTTAAATGGAGGAAGA---GGTTTGCAA---ACTGAAATATCTGTTGAGAGTACCAGTA
TCTCAGTGATACCTGATACTGACTATGGCAGTCAGAACAGCATCTCATTACTGGAAGCTGACACCCTCAGG---AAGGCA
AAA---ACAGCACCAAATCAATGTGCAAGTCAGTGTGCAGCAATTGAAAACCCCAATGAACTTATCCATGGTTGT---CC
TAAAGATACTAGAAATGACACAGAGGATTTTAAGGATCTGTTGAGATGTGAAGTTAAC---CACATTCAGGAGACGTGCG
TAGAAATGGAAGACAGNGAACTTGATACTCAGTATTTGCAGAGTACATTCAAGGTTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCAAATCCA---------GAAAAGGAATGTGCAACAATTTGTGCCCACTCCAAGTCCTTAAGGAAACAAAGTCCAAA
AGTCACTCCTGAGTATGGAGAAGAAGAAGAAAATCAAGGGAACAAAGAGTCTAAAATCAAGCATGAGCAGGCAGTTCATA
CGACTGCGGGCTATCCTGAGGATTGTCAGAAAGAGAAGAAGCCAAGTGATTATACCAAAAGTAGCATCAAAGGAGTCTCT
AGGCTTTGTCAGTCATCTCAGTTCAGA---GGCAGTGAATCCCAACACATTACTGCAGGTGAACATGGAATTTCACAAAA
TCCAGATCAAATGCCATTGCTTTCTCCCATCAGGGCATCTGTTAAAAGT------AAGAAAAAC---TTGTCAGAAGAAA
GGTTTGAGGAACATACAATATCACTTGAAAGAGCAGTAGGAAATGAGAGCATCGTTCAAAGTACAGTGAGCACAGTTAGC
CAAAATGACATTAAGGAAAGTGCTTCTAAAGAAGCCAGCTCAAGCAGTATTAATGAAGTAGGTTCTAGT-----------
----------------------------------------------------GGCGAAAACATTCGAGCAGAGCTAGGTA
GGAACAGAGGACCTAAATTAAATGCTGTGCTCAGATTAGGTCTTATGCAACCTGAAGTCTATAAACAAAGTCTT---CCT
GTAAGTAACTGTAAACGTCCTGAAATAAAAAGGCAAGGAGAAAATGAAGGAGTAGTTCAGGATGTTAATATGGATTTCTC
TCCATGTCTAATTTCAGATAACCTAGAACAA---CCTATGGGAAGTAGTCGTGCTTCTCAGATTTGTTCTGAGACTCCTG
ATGACCTGTTAGATGATGATGAAATAAAGGAAAATATCAGCTTTGCTGAAAGTGGCATTAAGGAAAGATCTGCTGTTTTT
AGTAAA---GACCAGAGAAGAGAGTTCAGAAGGAACCCAAGCCCTTTATCCCAT---TCAGGTTTGGCTCAGGGTCACCT
AAGAGGGGCCAGGGAATTAGAGTCCTCAGACGAGAACATATCTAGTGAG
>Manatee
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAATAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTCATAAAAGCAAACAGCCTGGCTTAACAAGGAGCCAGCAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCTAGCACAGAGAAAAAGGTAGATATGAATGCTAATCCATTGTATGAGAGAAAAGAA
GTGAATAAGCAGAAACCTCCATGCTCCGAGAGTGTTAGAGAT---ACACAAGAT---ATTCCTTGGCTGACACTGAATAG
TAGCATTCAGAAAGTTAATGAGTGGTTTTTCAGAAGTGATGGCCTG---------GATGACTTGCATGATAAGGGGTCTG
AATCAAATGCAGAAGTAGCTGGTGCATTAGAAGTTCCAGAA------GAAGTACATGGATATTCTAGTTCTTCAGAGAAA
ATAGACTTAATGGCCAGTGATCCTCATAGTGCTTTAATATGTGAAAGTGAAAGAGTCCTCTCCAAACCAGCAGAAAGTAA
C---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAATTCTCCCTCATTTGAGCCATGTAACTGAAGATC
TAATTATAGGAGCTGTTGCTACAGAACCTCAGATAGCACAA---------------------------------------
---------------------GAACGTCCCCTTACAAATAAATTAAAGCGTAAAAGGAGA---ACATCAGGCCTTCATCC
TGAGGATTTCATCAAGAAAGTAGATTTGGCAGTTGTTCAAAAGACTCCTGAAAAGATAAATCAGGAAACTGACCAAGTGG
AGCAGAAT---------GGTCAAGTGATGAATATTGCTAATGGTGGTCATGAAAATGAAACAAAAGATGATTAT---GTT
CAGAAGGAGAAGAATGCTAACCCAACAGAA------TCACTGACAAAGGAATCTGCTTTCAGAACTAAAGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTAAATATGCATAATTCAAAAGCACTGAAGAAGAATCGGCTGAGGAGGA
AGTCCTCTACCAGGCATATTCATGCACTTGAACTAGTAGTCAATAGAAATCCAAGTCCACCTACTCATACTGAACTACAA
ATTGATAGTTGGTCTAGCAGTGACGAG---ATAAAGAAA------AGTTCTGAGCAAAAGCCAGTCAGACACAACAGAAA
CCTTCAACTCATGAAAAACCAAGAAACCACAACTGGAGCCAAGAAAAGTAACAAGCCAAAGGAACAAATAAGTAAAAGAC
ATGCCAGTGACACTTACCCAGAACTAAATTTAACAAGCACAACTGGCTTAATTACTAACTGTTCAAGTTCTCATAATTAT
CAAAAATTTGTTAATCCTAGCCTTCAGGGAGAAGAAATAGAAGAAAAT---CTGGGAGCAACTCAAGTGTCTAATAGAAC
CAGAGACCCCGAGGATCTAGTGTTAAATGGAGGAAGA---GGTTTGCAA---ACTGAAATATCTGTTGAGAGTACCAGTA
TCTCAGTGATACCTGATACTGATTATGGCAGTCAGAACAGCATCTCATTACTGGAAGCTGACACCCTCAGG---AAGGCA
AAA---ACAGCACCAAATCACTGTGCAAGTCAGTGTGCAGCAATTGAAAACCCCAATGAACTTATCCATGGTTGT---CC
TAAAGATACTAGAAATGACACAGAGGATTTTAAGGATCTGTTGAGATGTGAAGTTAAC---CACGTTCAGGAGACATGCA
TAGAAATGGAAGACAGTGAACTTGATACTCAGTATTTGCAGAGTACATTCAAGGTTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCAAATCCA---------GAAAAGGAATGTGCAACAATTTGTGCCCACTCCAAGTCCTTAAGGAAACAAAGTCCAAA
AGTCACTCCTGAGTATGGAGAAAAAGAAGAAAATCAAGGGAACAAAGAGTCTAAAATCAAGCATGAGCAGGCAGTTCATA
CAACTGCTGGCTATCCTGAGGATTGTCAGAAAGAGAAGAAGCCAAGTGATTATACCAAATGTAGCACTAAAGGAGTCTCT
AGGCTTTGTCAGTCATCTCAGTTCAGA---GGCAGTGAATCCGAACACATT---ACAGGTGAACATGGAATTTCACAAAA
TCCAGATCAAATGCCATTGCTTTCTCCCATCAGGGCATCTGTTAAAAGT------AAGAAAAAC---TTGTCAGAAGAAA
GGTTTGAGGAACATACAATATCACTTGAAAGAGCAGTAGGAAATGAGAGCATCGTTCAAAGTACAGTGAGCACAGTTAGC
CAAAATAACATTAAGGAAAGTGCTTCTAAAGAAGCCAGCTCAAGCAGTATTAATGAAGTAGGTTCCAGTGTTAATGAAGT
AGGTTCTAGT------------------------------------------GGCGAAAACATTGAAGCAGAGCTAGGTA
GGAACAGAGGACCTAAATTAAATGCTGTGCTCAGATTAGGTCTTATGCAACCTGAAGTGTATAAACAAAGTCTT---CCT
GTAAGTAACTGTAAACATCCTGAAATAAAAAGGCAAGGAGAAAATGAAGGAGTCGTTGAGGATGTTAATATGGATTTCTC
TCCATGTCTAATTTCAGATAACCTAGAACAA---CCTATGGGAAGTAGTCGTGCTTCTCAGATTTGTTCTGAGACTCCTG
ATGACCTGTTAGATGATGATGAAATAAAGGAAAATATCAGCTTTGCTGAAAGTGGCATTAAGGAAAGATCTGCTGTTTTT
AGTAAA---GACCAGAGAAGAGAGTTCAGAAGGAACCCAAGCCCTTTATCCCGT---TCAGGTTTGGCTCAGGGTCACCT
AAGAGGGGCCAGGGAATTAGAGTCCTCAGAAGAGAACATATCTAGTGAG
>AfricanEl
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATAAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAACAAAAGCAAACAGCCTGGCTTAGCAAGAAGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCTAGCACAGAGAAAAAGGTAGATGTGAATGCTGATCCCTTGTATGAGAGAAAAGAA
GTGAATAAGCAGAAACCTCCACGCTCTGAGAATCTTAGAGAC---ACCCAAGAT---ATTCCTTGGATAACACTGAATAG
TAGCATTCAGAAAGTTAATGAGTGGTTTTTCAGAAGTGACGGCCTG---------GATGTCTTAAATGATGAGGGGCCTG
AATCCAGTGCAGAAGTAGCTGGTGCATTAGAAGTTCCAAAT------GAAGTACAT------TCTAATTCTTCAGAGAAA
ATAGACCTAATGGCCAGTGATCTGCATGGTGCTTTAATATGTGAAAGTGAAAGAGTCCCCTCCAAACCAGCAGAAAGTAA
C---ATCGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAGGTATGTCTCATTTGAGCCACATAACTGAAGATC
TGATTATGGGAGCTATTGCTTCAGAACCTCAGATAGCACGA---------------------------------------
---------------------GAACATCCTTTTACAAATAAATTAAAGCGTAAAAGGAGA---ACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGTAGATTTGGCAGTTGTTCAAAAGATCCCTGAAAAGATAAATCAGGAAACTGACCATGTGG
AGCAGAAC---------GGTCAAGTGATGAATATTGCTAATGGTGGTCGTGAGAATGAAACAAAAGGTGATTAT---GTT
CAGAAAGAGAAGAATGCTATCCCAACAGAA------TCATTGGCAAAAGAATCTGCTTTCAGAACTAAAGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAACTAGAATTAAATATGCATAATTCAAAAGCACCAAAGAAGAATAGGCTGAGGAGGA
AGTCGTCAACCAGACATATTCATGCACTTGAACTAGTAGTCAATAGAAATCCAAGTCCACCTACTCATACTGAACTACAA
ATTGACAGTTGGTCTAGCAGTGAAGAG---ACAAAGAAAAAA---AGTTCTGAGCAAAAGCCAATCAGACACAACAGAAA
CCTTCAACTCATGAAAAATCAAGAAACCGCAACTGGAGCCAAGAAGAGTAACAAGCCAAAGGAACAAATAAGTAAAAGAC
ATGGCGCTGACTCTTACCCAGAACTACATTTAACAACCACAGCTGGCTTTATTACTAAGTGTTCAAGTTCTGATAATCTT
CAAGAATTTGTCAATCCTAGCCTTCAAGGAGAGAAAACAGAAGAAAAC---CTGGAAACAATTCAAGTGTCTAATATTAC
CAAAGAGCCCAAGGATCTAGTGTTAAATGGAGGAAGA---GATTTGCAA---ACCAAAAAATCTATTGAGAGTACCAATA
TCTCAGTGATACCTGATACTGTTTATGGCACTCAGGACAGCGTCTCATTGCTGGGAGCTGACACCCCAGGG---AAGGCA
AAA---ACAGCACCAAATCGATGTGCAAGTCAGTGTACAGCAATTGAAAACCCAAGTGAACTTACCAACAGTTGT---CC
TAAAGATACTAGAAATGACACAGAGGGTTTTAAGGATCTATTGAGATGTGAAGCTAGC---CACATTCAGGAGACATGCA
TAGAAATAGAAGAGAGTGAACTTGATACTCAGTATTTGCAGAGTACATTCAAGGTTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCAAATCCA---------GAAAAGAAATGTGCAACAATTTGTGCCCACTCCAAGTCCTTAAGGAAGCAAAGCCCAAA
AGTCACTCTTGTGTGTGGAGAAAAAGAAGAAAATCAAGGGAACAGAGAGCCTAAAATCAAGCATGAGCAGGCAGTTCATA
TGCCTACAGGCTATCCTGAGGCTTGTCAGAAAGAGAAG---CCAAGTGACTATACCAAATATAGCATTAAAGGAGTCTCT
GGGCTTTGTCAGTCATCTCAGTTCAGA---GGCAGTGAATCTGAACTCATTACTGCAGATGGACATGGAATCTCACAAAA
CCCAGATCAAATACCATCACTTTCTCCCACCAGGTCATCTGTTAAAACTAAATGTAAGACAAAC---CTGTTGGAAGAAA
GGTTTGAGGAACATACAATATCACTTGAAAGAGCAATGAGAAATGAGAACGTCATTCAAAGTACAGTGAGCACAGTTAGC
CAAAATAACATTAGGGAAAGTGCTTCTAAAGAAGCCAGCTCAAGCAGTATTAATGAAGTATGTTCCAGTATTAATGAAGT
AGGTTCTAGT------------------------------------------GGTGAAAACATTCAAGCAGAAATAAGTA
GGAAGAGAGGACCTAAATTAAATGCTGTGCTCAGATTAGGTCTTATGCAACCTGAAGTTTATAAACAAAGTCTT---CCT
ATAAGTGACTGTAAACATCCTGGAATAAAAACGCAAGGAGAAAATGAAGGAGTAGTTCAGGCTGTTAATACAGATTTCTC
CCCATGTCTAATTTCAGATAACCTAGAACAA---CCTGTGGGAACTAGTCGTGCTTCTCAGGTTTGTTCTGAGACTCCCG
ACGACCTGTTAGATGATGATGAAATAAAGGAAAATATCAGCTTTGCTGAAAACGGCATTAAGGAAAGATCT---GTTTTT
ATTAAAGATGACCAGAGAAGAGAGTTCAGAAGGAACCCAAGCCCTTTATCCCAT---TCAGGTTTGGCTCAGGGTTGCCT
AAGAGGGGCCAGGGAATTGGAGCCCTCACAAGAGAACATATCTAG----
>AsianElep
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATAAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAACAAAAGCAAACAGCCTGGCTTAGCAAGAAGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCTAGCACAGAGAAAAAGGTAGATGTGAATGCTAATCCCTTGTATGAGAGAAAAGAA
GTGAATAAGCAGAAACCTCCACGCTCTGAGAATCTTAGAGAC---ACCCAAGAT---ATTCCTTGGATAACACTGAATAG
TAGCATTCAGAAAGTTAATGAGTGGTTTTTCAGAAGTGACGGCCTG---------GATGTCTTAAATGATGAGGGGCCTG
AATCCAGTGCAGAAGTAGCTGGTGCATTAGAAGTTCCAAAT------GAAGTACAT------TCTAATTCTTCAGAGAAA
ATAGACCTAATGGCCAGTGATCTGCGTGGTGCTTTAATATGTGAAAGTGAAAGAGTCCCCTCCAAACCAGCAGAAAGTAA
C---ATCGAAGATAAAATATTTGGGAAAACCTATCGGAGGAAGGCAGGTATCTCTCATTTGAGCCACATAACTGAAGATC
TGATTATGGGAGCTATTGCTTCAGAACCTCAGATAGCACGA---------------------------------------
---------------------GAACATCCTTTTACAAATAAATTAAAGCGTAAAAGGAGA---ACATCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGTAGATTTGGCAGTTGTTCAAAAGATCCCTGAAAAGATAAATCAGGAAACTGACCATGTGG
AGCAGAAC---------GGTCAAGTGATGAATATTGCTAATGGTGGTCGTGAGAATGAAACAAAAGGTGATTAT---GTT
CAGAAAGAGAAGAATGCTATCCCAACAGAA------TCATTGGCAAAAGAATCTGCTTTCAGAACTAAAGCTGAACCTAT
AAGCAGCAGTATAAGCAATATGGAGGTAGAATTAAATATGCATAATTCAAAAGCCCCAAAGAAGAATAGGCTGAGGAGGA
AGTCGTCAACCAGGCATATTCATGCACTTGAACTAGTAGTCAATAGAAATCTAAGTCCACCTACTCATACTGAACTACAA
ATTGACAGTTGGTCTAGCAGTGAAGAG---ACAAAGAAAAAA---AGTTCTGAGCAAAAGCCAATCAGACACAACAGAAA
CCTTCAACTCATGAAAAATCAAGAAACCGCAACTGGAGCCAAGAAGAGTAACAAGCCAAAGGAACAAATAAGTAAAAGAC
ATGGCGCTGACTCTTACCCAGAACTACATTTAACAACCACAGCTGGCTTTATTACTAAGTGTTCAAGTTCTGATAATCTT
CAAGAATTTGTCAATCCTAGCCTTCAAGGAGAGAAAACAGAAGAAAAC---CTGGAAACAATTCAAGTGTCTAATATTAC
CAAAGAGCCCAAGGATCTAGTGTTAAATGGAGGAAGA---GATTTGCAA---ACCAAAAAATCTATTGAGAGTACCAATA
TCTCAGTGATACCTGATACTGTTTATGGCACTCAGGACAGCGTCTCATTGCTGGGAGCTGACACCCCAGGG---AAGGCA
AAA---ACAGCACCAAATCAATGTGCAAGTCAGTGTACAGCAATTGAAAACCCAAGTGAACTTACCAACAGTTGT---CC
TAAAGATACTAGAAATGACACAGAGGGTTTTAAGGATCTATTGAGATGTGAAGCTAGC---CACATTCAGGAGACATGCA
TAGAAATAGAAGAGAGTGAACTTGATACTCAGTATTTACAGAGTACATTCAAGGTTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCAAATCCA---------GAAAAGAAATGTGCAACAATTTGTGCCCACTCCAAGTCCTTAAGGAAGCAAAGCCCAAA
AGTCACTCTTGTGTGTGGAGAAAAAGAAGAAAATCAAGGGAACAGAGAGCCTAAAATCAAGCATGAGCAGGCAGTTCATA
TGCCTGCAGGCTATCCTGAGGCTTGTCAGAAAGAGAAG---CCAAGTGACTATACCAAATATAGCATTAAAGGAGTCTCT
GGGCTTTGTCAGTCATCTCAGTTCAGA---GGCAGTGAATCTGAACTCATTACTGCAGATGGACATGGAATCTCACAAAA
CCCAGATCAAATACCATCACTTTCTCCCACCAGGTCATCTGTTAAAACTAAATGTAAGACAAAC---CTGTTGGAAGAAA
GGTTTGAGGAACATACAATATCACTTGAAAGAGCAATGAGAAATGAGAACGTCATTCAAAGTACAGTGAGCACAGTTAGC
CAAAATAACATTAGGGAAAGTGCTTCTAAAGAAGCCAGCTCAAGCAGTATTAATGAAGTATGTTCCAGTATTAATGAAGT
AGGTTCTAGT------------------------------------------GGTGAAAACATTCAAGCAGAAATAAGTA
GGAAGAGAGGACCTAAATTAAATGCTGTGCTCAGATTAGGTCTTATGCAACCTGAAGTTTATAAACAAAGTCTT---CCT
ATAAGTGACTGTAAACATCCTGGAATAAAAACGCAAGGAGAAAATGAAGGAGTAGTTCAGGCTGTTAATACAGATTTCTC
CCCATGTCTAATTTCAGATAACCTAGAACAA---CCTGTGGGAACTAGTCGTGCTTCTCAGGTTTGTTCTGAGACTCCCG
ACGACCTGTTAGATGATGATGAAATAAAGGAAAATATCAGCTTTGCTGAAAACAGCATTAAGGAAAGATCT---GTTTTT
ATTAAAGATGACCAGAGAAGAGAGTTCAGAAGGAACCCAAGCCCTTTATCCCAT---TCAGGTTTGGCTCAGGGTTGCCT
AAGAGGGGCCAGGGAATTGGAGCCCTCACAAGAGAACA-----------
>RockHyrax
TGTGGCACAGATACTTGTGCCAGCTCGTTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGGATGTAGA
AAAGGCTGAATTCTGTAGTAAGAGCAAACAGCCTGGCTTAGCAAGGAGCCAACAGAGCAGATGGGCTGAGAGTACGGAAA
CATGTAATGGT---AGGCAGATTCTTAGAACAGAGAAAAAGGTAGAAACGAATGCTGATCCTTTGTATGGGAAAAAAGAA
GGGAATAAGCAGAAACCTCCATGCTCTGAGAGTCGCACAGAT---ACGCAAGAT---ATTCCTTGGGTAACACTGAATAA
CAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGACAACCTA---------AGTGATTCACCTAGTGAGGGGTCTG
AATTAAATGGAAAAGTGGCTGGTCCAGTAAAACTTCCAGGT------GAAGTACATAGATATTCTAGTTTTCCAGAGAAC
ATAGATTTAATGGCCAGTGGTCCTCCTGGT------------------GAAAGAATCCCCTGCAAACCACCAAAAAGTAA
C---ATCAAAGATAAAATATTTGGGAAAACCTATCAGAGGAAGGGAAGTCTCCCTCACCTGAGCCACATAACCGAAGATC
TAGTTAAAGGCGCCATTGCTACACAACCACAGATAGCACGA---------------------------------------
---------------------GAACATCCTCTTACAAATAAGTTACAGCATAAAAGGAGA---ACATCAGGCCTTCATCC
TGAGGATTTTATCAAAAAAGCAGATTTGACAGTTGTTCAGAAGGCATCTGAGAAGATAAATCAGGAAACTGACAAAGTGG
AGCAGAGT---------GGTCAAGTGATAAATATTGGTAATGGTGGTCATGAGAATGAAACAAAAGATGATTAT---GTT
CTGAAAGAGAAGAATGGTAACCCAGCAGAA------TCACTGAAAAAAGAATCTGTGTTCAAAACTAAAGCTGAACCTAT
AAGCAACAGTATAAGCAATATGGAACTAGAATTAAATACACATAATTCAAAATCACTGAAGAAGAACAGGCTGAGGAAGA
AGTCCTCCTCCAGACATGTTCATGCCCTTGAACTGGTAGTCAATAGAAATCCAAGTTCACCACCTCATACTGGGCTACAA
ATTGATAGCTGGTCTGGCAGTGAAGAA---ATGAAGAAAACA---AGTTCTGAGCAAAAGCCAGTCAGACACAACATAAA
CCTCCAACTCATGAAAAACCAAGAAACCACAACTGGAGCCAAGAAGAGTAACAAGCCAAAGGAACAAATAAATAAAAGAC
ACACTAGTAATCCTTACCCAGAACTAAATTTAACAAGCACAGCTGGCTTTATTACTGTATGTTCAAGTTCTGATAATCTT
CAAGAACCTGTCAACCCCAGCCTTCAAGGAGAGGAAATAGAAGAAAAC---TTGGCAACAGTCCAAATGTCTAATACTGC
CAAAGAACCTGAGGATCTAGAGTTAAATGGAGGGAGA---GTTTTGCAA---ACCAAAAGATCTGTTGAAAGTACTAGTA
CCTCAGTGATACCTGATGCTGACTGTGGTGCTCAGGACAGCATCTCGTTACTGGAAGCTGACACTCTAGGG---AAGGCA
AAA---ACAGCACCAAATCAAGGGGCAGGTCAATGTTCGGCAATCGAAAACCCCAACGAACTTATTCATGGTAGT---CC
TAAAGACACTAGAAATGATATAGAGGGTTTTAAGGATCCACTGAGATGCAAAGTTAAC---CCTATTCAGGAGATATGTG
TAGAAATGGATGAAAATGAACTTGATACTCAGTATATACAGAGTACATTCAAGGTTTCAAAGCGTCATTCTTTTGCTCTG
TTTTCAAATCCG---------GAAAAGGAGTGTGCGACAAGTTATACCCACTCCAAGTCGTTAAGGAAAGAAAATCCCAA
AGTCACTCTTCAGCGTGGAGAAGAAGAAGAAAATCAAGGGAACAAAGAATCTAAAATCAAGCAT---------GTTCATA
CAACTGCAAGCTGTCCTGAGGTTTGTCAGGAAGACACAAAGCCTAGTGATCGTACTAACTGTAGTGTTAAAGGACTCCCT
AGGCTTTGTCACTCATCTCAATTCAAA---GGTAGTGAGTCTGAACTCATTACTGAAGGTGAACATGGAATTGCACAAAA
CCCGGATCAGATGCCATCATCTTCTCCCATCAGATCATCTGTTAACTCTAAGTGTAACAAAAAC---CTGTCAGAAGAGC
GATTTAAGGAACATAAAATATTACTTGAAAGAACAACAGGAAATGAAACCATTGTCCAAAGTACAGTGAGCACAGGTAGC
CAAGATAACATTAGGGGAAGTGCTTCGAAAGAAACCAGCTCAAGCAGTATTAATGAAGTAGGTTCTAGT-----------
----------------------------------------------------AGCGAAAACATTCAAGCAGAAATAAGTA
GGAACAGAGAACCTAGATTAAATGCTGTGCTCAGGTTAGGTGTTATGCAACCTGAAGTGTATAAACAAAGTCTT---TCT
ATAAGTAACTGTAAACAGCCAGAAATAAAAAAGCGAGGAGAAAATGAAGGAGTAGTTCAGGCTGTTAGTACAGATTTCTC
TGCATGTCCCATTTCAGAAAACCTAGAACAA---CCTGTGAGAAGTAGTCACACTTCTCAGGTTTGTTCTCAGACTCCTG
ATAACCTGTTAGATGATGATGAAATAAAGGGAAAGACTGACTTTGCTGGAAGTAGCATTAAGGACAGACCT---GTCTTT
AGTAAAGATGACCAGGGAAGAGAGTTCAGAAGGAACCCAAGCCCTTTATCCCAT---TCAGGTTTGGCTCAGGGCCACCT
GATAGGGGCCAGGGAATTAGAGGCCTCACAAGAGAACACATCTAGCGG-
>TreeHyrax
------NCAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGGATGTAGA
AAAGGCTGAATTCTGTAGTAAGAGCAAACAGCCTGGCTTAGCAAGGAGCCAACAGAGCAGATGGGCTGAGAGTACGGAAA
CATGTAATGAT---AGGCAGATTCTTAGAACAGAGAAAAAGGTAGATACAAATGCTGATCCTTTGTATGGTAAAAAAGAA
GGGAATAAGCAGAAACCTCCATGCTCTGAGAGTCGCACAGAT---ACGCAAGAT---ATTCCTTGGGTAACACTGAATAA
CAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGACAACCTA---------AGTGATTCACCTAGTGAGGGGTCTG
AATTAAATGGAAAAGTGGCTGGTCCAGTAAAGCTTCCAGGT------GAAGTACATAGATATTCTAGTTTTCCAGAGAAC
ATAGATTTAATGGCCAGTGGTCCTCCTGGTGATTTAATATGTGAAAGTGAAAGAATCCCCTGCAAACCACCAAAAAGTAA
C---ATCAAAGATAAAATATTTGGGAAAACCTATCAGAGGAAGGGAAGTCTCCCTCACCTGAGCCACATAACTGAAGATC
TAGTTAAAGGCGCCATTACTACACAACCACAGATAGCACGA---------------------------------------
---------------------GAACATCCTCTTACAAATAAGTTACAGCATAAAAGGAGA---ACATCAGGCCTTCATCC
TGAGGATTTTATCAAAAAAGCAGATTTGACAGTTGTTCAGAAGGCATCTGAGAAGATAAATCAGGAAACTGACAAAGTGG
AGCAGAGT---------GGTCAAGTGATAAATATTGCTAATGGTGGTCATGAGAAGGAAACAAAAGATGATTAT---GTT
CTGAAAGAGAAGAATGGTAACCCAGCAGAA------TCACTGAAAAAAGAATCTGTGTTCAAAACTAAAGCTGAACCTAT
AAGCAACAGTATAAGCAATATGGAACTAGAATTAAATACACATAATTCAAAATCACTGAAGAAGAACAGACTGAGGAAGA
AGTCCTCCTCCAGACATGTTCATGCCCTTGAACTGGTAGTCAATAGAAATCCAAGTTCACCACCTCATACTGGGCTACAA
ATTGATAGTTGGTCTGGCAGTGAAGAA---ATGAAGAAAACA---AGTTCTGAGCAAAAGCCAGTCAGACACAACATAAA
CCTCCAACTCATGAAAAACCAAGAAACCACAACTGGAGCCAAGAAGAGTAACAAGCCAAAGGAACAAATAAATAAAAGAC
ACACTAGTAATCCTTACCCAGAACTAAATTTAACAAGCACAGCTGGCTTTATTACTGCGTGTTCAAGTTCTGATAATCTT
CAAGAACCTGTCAACCCCAGCCTTCAAGGAGAGGAAATAGAAAAAAAC---TTGGCAACAGTCCAAATGTCTAATACTGC
CAAAGAACCTGAGGATCTAGAGTTAAATGGAGGGGGA---GTTTTGCAA---ACCAAAAGATCTGTTGAAAGTACCAGTA
CCTCAGTGATACCTGATGCTGACTGTGGTGCTCAGGACAGTATCTCGTTACTGGAAGCTGACACTCTAGGG---AAGGCA
AAA---ACAGCACCAAATCAAGGGGCAGGTCAATGTTCAGCAATCGAAAACCCCAACGAACTTATTCATGGTAGT---CC
TAAAGACACTAGAAATGATATAGAGGGTTTTAAGGATCCACTGAGATGCGAAGTTAAC---CCTATTCAGGAGATATGTG
TAGAAATGGATGAAAATGAACTTGATACTCAGTATATACAGAGTACATTCAAGGTTTCAAAGCGTCATTCTTTTGCTCTG
TTTTCAAATCCA---------GAAAAGGAGTGTGTGAAAAGTTATACCCACTCCAAGTCGTTAAGGAAAGAAAATCCCAA
AGTCACTCTTCAGCGTGGAGAAGAAGAAGAAAATCAAGGGAACAAAGAATCTAAAATCAAGCAT---------GTTCATA
CAACTGCAAGCTGTCCTAAGGTTTGTCAGGAAGACGCAAAGCCTAGTGATCGTACCAACTGTAGTGTTAAAGGACTCCCT
AGGCTTTGTCACTCATCTCAATTCAAA---GGTAGTGAGTCTGAACTCATTACTGAAGGTGAACATGGAATTGCACAAAA
CCCAGATCAGATGCCATCATCTTCTCCCATCAGATCATCTGTTAACTCTAAGTGTAACAAAAAC---CTGTCAGAAGAGC
GATTTAAGGAACATAAAATATTATTTGAAAGAACAACAGGAAATGAAACCATTGTCCAAAGTACAGTGAGCACAGGTAGC
CAAGATAACATTAGGGGAAGTGCTTCGAAAGAAACCAGCTCAAGCAGTATTAATGAAGTAGGTTCTAGT-----------
----------------------------------------------------AGCGAAAACATTCAAGCAGAAATAAGTA
GGAACAGAGAACCTAGATTAAATGCTGTGCTCAGGTTAGGTGTTATGCAACCTGAAGTGTATAAGCAAAGTCTT---TCT
ATAAGTAACTGTAAACAGCCAGAAATAAAAAAGCAAGGAGAAAATGAAGGAGTAGTTCAGGCTGTTAGTACGGATTTCTC
TGCATGTCCCATTTCAGAAAACCTAGAACAA---CCTGTGAGAAGTAGTCACACTTCTCAGGTTTGTTCTCAGACTCCTG
ATAACCTGTTAGATGATGATGAAATAAAGGGAAAGACTGACTTTGCTGGAAGTAGCATTAAGGACAGACCT---GTCTTT
AGTAAAGATGACCAGGGAAGAGAGTTCAGAAGGAACCCAAGCCCTTTGTCCCAT---TCAGGTTTGGCTCAGGGCCACCT
GATAGGGGCCAGGGAATTAGAGNCCTCACAAGAGAACACATCTAGCAA-
>Aardvark
TGTGGCACAAATACTCATGCCAGCTCGTTACAGCATGAGAACAGCAGTTTATCACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGTGAGGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCTTAGCACAGGGGAAAAGGTAGATATGAAGGCTGATCCCTTGTATGGGAGAAAAGAA
GTGAATAAGCAGAAACCTCCATGCTCTGAGAATCCTAGAGAT---ACTGAAGAT---ATTCCTTGGATAACACTGAATAG
TAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGGCCTG---------GATGGCTCACATGATGAAGGGTCTG
AATCAAATGCAGAAATAGGTGGTGCATTAGAAGTTTCAAAT------GAAGTACATAGTTACTCTGGTTCTTCAGAGAAA
ATAGACTTAATGGCCAGTGAACCTCATGTTGCTTTAATATGTGAAAGTGAAAGAGTCCTCTCCAAACCAGCAGAAAGTAA
C---ATCGAAGATAAGATATTTGGGAAAACCTATCGGAGGAAGTCGAGTCTCCCTAACATAAGCCATATAACTGAAGATC
TAATTTTAGGAGCTATTGCTACAGAACCTCAGGTTGCACGA---------------------------------------
---------------------GAATGTCCTCTTGGAAATAAATTAAAGCGTAAAAGGAGA---ACATCAGGCCTTCATCC
TGAGGATTTTATTAAGAAAGTAGATTTGGCAGTT---CAAAAGACTCCTGAAAAGATAAATCAGGAAAATGACCAAATGG
AACAAAAT---------GGTCAGGAGGAGAATATTGCTGATGGCTGTCATGAGAATGCAACAAAAGGTGAATAC---ATG
CAGAAAAAGAAGAGTGCAAATCCAACAGAA------TCATTGGCAACAGAATCTGTTTTCAGAACTAAAGCTGAACCTAT
AAGCAGCAGTATAAGCAATTTGGAACTAGAATTAAATACACACAATTCAAAGGCATCCAAGAAGAATAAGCTGAGGAGGA
AATCCTCTACCAGGCATATTCATGCACTTGAACTAGTAGTCAATAGGAATCCAAGTCCCCCTAGTCATACTGAGTTACAG
ATTGATAGCTGGCCTAGCAGTGAAGAG---TTAAAGAAAAAA---AGTTCTGAGCACAAGCCAATCAGACAGAATACAAA
CCTGCAACTCATGAAAGATCAAGAGGCCACAACTGGGGCCAAGAAGAGTAACAAGCCAAATGAACAAATAAGTACAGGAC
ACGCCTCTGACATTTTCCCAAAATTGAATTTAACAAACATAACTGGTTTTATTACTAATTGTTCAAGTTCTGATAATCTT
CAAGAATTTGTCAATCCTAGCCTTCAAGAAGAGGAAATAAAAGAGAAC---CTGGGAACAATTCAAGTGTCTGATAGTAC
CAGAGATCCTACGGATGAGGTGTTAAAC---AGAAGA---GGTTTGCAA---ACTGAAAGATCTGTGGAGAATACCAGTA
TTTCAGTGAAACCTGATACTGATTATAGCACTCAGGACAGCATCTTATTACTGAAAGCTAACTCCCTAAGG---AAGGCA
AAA---ACAGCACCA------------AGTCAGTGTGCAGCAATTGAAAATCCTAACAAACTTAGCCATGGTTTT---CC
TAAAGATACCAGAAATGACATAGAGGGTTTTAAGGATCTATTTAGAGGTGAAGATAAC---CACGTTCAGGAGACATACA
TAGAAATGGAAGAGAGTGAACTTGATACTCAGTATTTACAGAATACATTCAAGGTTTCAAAGCGTCAGTCATTTGCTCTG
TTTTCAAATCCA---------GAAAAGGAATTTGCAACAGTCCATGCCCACTCCAGGTCCTTGAGGAAACAAAGTCCAAA
CATCACTCTTGAGTGTGGAGAAAAAGAAGAAAATCAGGGGAACGAGGAATCTAAAATCAAGTGCGTACAGCTAGTTCTTT
CAACTACAGGCTATGCTGGAGCTTGTCAGAAAGAGAAG---CCAAGTGATTATGCCAAATGTAGCATTAAAGGAGTCTCT
AGACTTTGTCAGTCATCTCAATTCAGA---GGCAATGAATCTGAAATCATTACTGCAAATGAACATGGAGTCTCACAAAA
CCTGGATCAGACACCATCACTTTCTCCCACTAGGTCATCTGTTAAAGCTAAATGTAAGACAAAT---CTGTCCAAAGAAA
GATTTGAGCAACAGAAAATATCACATGAAAGAGTAATGGGAAATGAGAGCACCATTCAGAGTACAGTGGGCACAGTTAGC
CAAAGTAACATTAGGGAAAGTGCTTTTAAAGAAGCTAGCTCAAGCAGTATTAATGAGGTAGGTTCCAGTGTTAATGAAAT
AGGTTCTAGT------------------------------------------GGTGAAAACATTCAAGCAGAACTAGGTA
AGAACAGAGGACCTAAATTGAATGCTGTGCTCAAATTATGTCTTATGCAACCTGAAGAGTATAAACAAAGTCCT---CCT
ATAAGTAATTGTAAACATCCTTCAATAAAAACCCAAGGACAAAATGAAGGAGTAGTTCAGGCTGTTAATACAGGTTTTTC
TTCATGTCTGATTTCAGATAACCTAGGACAA---CCTATGGGAAGCAGTCATGCTTCTCAGATTTGTTCTGAGACACCTG
ATGACCTGTTAGATGATGACAAAATAAAGGAAAATACCAGCTTTGCTGTAAGTGGCATTAAGGAAAGATCTGCTGTTTTT
AGTAAAGATGACCAGGAAAGAGAGTTCAGAAGGAGCCTGAGCCGTTTCTCCCAT---TCAAGTTTGGCTCAGGTTCACGT
AAGAGGTGCCAGGGAATTAGAGTCCTCAGAAGAGAACATATCTAGTGAG
>GoldenMol
TGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTGTAATAAAAACAAACAGTCTGGCTTAGCGAGGAGCCAGCAGAGCAGATGGGCTGGAAGTAAGGCAG
CGTGCAATGAC---AAGCAGACTCCTAGCACACAGACAGAGCTATATAGGAGTGCTGGTCCCATGCACAGGAGAAAAGAA
GTAAATAAGCTGAAATCTCCATGGTCTGAGAGTCCTGGAGCT---ACCCAAGAG---ATTCCTTGGATAACACTGAATAG
TAGCATTCGGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGGCCTG---------GATGAGTCACATGATGAGGGGTCTG
AATCAAATGCAGAGGTTGCTTGTAAATTCGAATTTCCCAAG------GAAGTACAAGGATATTCTAGTTCTTCAGAGAAA
ATGGACTTAATGGCCAATGATCCTCATGATGCTTTAATATGTGAAAATGAGAGAATCCTCTCCAAACCAGCTGTAAGTAA
C---ATTGAAGATAAAATTTTTGGGAAAACCTATCGGAGGAAGACAAGTCTCCCTAACTTGAGCCATGTAACTAAAGACC
TAATGATAGGAGCTGTTGCTACAGAAGCTCAGATGGCACAA---------------------------------------
---------------------GAACGTCCTCTTACAAATAAATTAAAGCGCAAAAGGAGA---ACCTCAGGCCTTCATCC
TGAGGATTTTATCAAGAAAGCAGGCATGAAAGTTGTTCAAAAGACTCCTGAAAAGATAAATCAAGAAACTAACCAAATGG
AGCAGAAT---------GATCAAGTGAGGAATATTGTTGATGGTGGTCATGAAAATGATACAAAAAGTGATTAT---GTT
CAGAAAGAGAAGAGTGCTAACCCAGCCAAA------TCATTGGCAAAAGAGTCCGCTTTCACAACTAAAGCGGAACCTAT
AAGCAGTAGTATAAGCAATATGGAACTAGAATTAAATATGTACAATTCTAAAGCACTGAGGAAGAATAGGTTGAGGAGGA
AGTCCTCTTCCAGGCATATTCACACACTTGACTTGGTAGTCAATAGAAATCCAAGTCCACCTCCTTACACTGAACTACAG
ATTGATAGTTGGCCTAGCAGTGAAGAA---ATAAACGAAACA---AGTTCTGAACAAAAGCCAACCAGACACAGCAGAAA
CCTTCACCTCATGAAAGAACAGGAAACTGCAACTGGAACCAAGAACAGTAACAAGCCAAATGAACAAATAAGTAAAAGAC
ATGCCACTTACACTTTTTCAGAACTAAACATAACAAATAGAACTGACTTTATTACTAACTGCCCACGTTCTGATAATCTT
CAAGAACTTGTCAATCCTAGCCTTCAAGGAGAGGAAAGGGAAGAGAAA---TCGGAAACAATGCAAGTATATGATAACAC
CAAAGAACCTGAGGATCAGGTGTTAAGTGGAAGAAGG---GATTTGCAA---ATGGAAAGATCTGTTGAGAGTACCAGTG
TTTCAGTGATACCCGATACTGATCATGGCACTCAGAACCACACCTCATTACCGGAAGCTGGCACCCTCGGG---AAGGCA
GAA---ACAGCACCAAATCAATGTACAAGTCAGTGTAAAGCAATTGAAAATCCCAACCAACTTATCCATGGTTGT---CC
T---------AGAAATGACACAGAGGGCTTTAAGGATCTATTGAAACATGAAGTTAAA---CACAATCAGGAGACATGCA
TAGAAATGGAAGAGGGTGAGCTTGATATTCAGTATTTACAGAATACATTCAAGGTTTCAAAGCGTCGGTCATTTGCTCTG
TTTTCAAATCCA---------GAAAAGGAATGTGCAACAGTCAGTGCCCACTCTAGGTCCTTCAGGAAACAAAGTCCAAA
AGCCACTCTTGAATGTGGCGAAAAAGAAGAAAATCAGGGGCACAAAGAGTCTAAAGTCAAGCATGTACAGGCAGTTCATA
CAAGTGTGGGCTATCCTGGACTCTGTCAGAAAGAGAAG---CCAAGTGATTATACCAAAGGTAGCATTCAGGGGGCCTCT
AGGCTTCATCAGTCATCTCAGTTCAGT---GGCAATGAATCTGAACAAATTACTGCAAATGAAAATGGAATTTCACAAAG
CCCAGATCAAACAGCATTGCTTTCT------------------------AAATGTAAGAAAAAC---TTGTCTGAAGAAA
GATTTGAAGAACGTGCAGTATCACTCGAAAAAGCAGTGGGAAATGAGAGCATCATTCAAAGTACAGTGAGCACAGTTAGC
CACAATAACATTAGGGAAAGGGCTTTTAAGGAAACCAGCTCAAGTAGTACTAATGAAGTAGGTTCCAGTATTAATGAAGT
AGGTTCTAGT------------------------------------------AACGAAAACATCCAAGCAGAGGTAGGTA
GGAACAGAGGACCTAAGTTAAATGCTATGCTCACATTAGGTTTTATGCAACCTGAAGTCTATAAACAAAATCTT---ACT
CTAAGTAATTGTAAACATCCTGAAATAACAAAGCAGGGAGACAATGAAGAAAGAGTTCAAGCTGCTGACCCAGGTTTCTC
TCCGTGTCTAATTTCAGATAACCTAGAACCA---CCTATGGGAAGTAATCATGCTTCTCAGATTTGTTCTGAGACACCTG
ATGACCTGTTAGATGATGATGAAATCAAAGAAAATATCAGCTTTGCTGAAAGTGGCATTAACGAAAGATCTGCAGTTTTT
AGTAAAGATGACCATAGAAGACAATTCAGAAGGAACCTAAGCCCTTTATCCCAT---TTAGGTTTGACTCAGGGTCACTT
AAGAGGTACCAGAGAATTAGAGTCTTCAGAAGAGAACCTGTCTAGTGAG
>Madagascar
TGTGGAACAAATACGCTTGCCAACTCATTACAGCGTGAGAACTACAGTTTATTACTCACTAAAGACAGACTGAATGTAGA
AAAGGCTGGATTCTGTAATGAAAGCAAACAGCCCGGCTTAGCAAGGAGCCAACATAACAGATGGGCTGAAAGTAAGGAGA
CATGTAATGAC---AAGCCGACTCCTAGCACAGAGAAAAAGGTAGATAAGAATGCTGACCCCGTGCATGGGAGAAAAGGA
GTGCCTAAGCAGAAACCTCCGTGCCATGGAAGTCCTAGAAAG---AGCCACGAT---GTGCCTTGGAAAACACGGAAGAG
TAGCATTTGGAAAGTCAATGAGTGGTTTTCCAAAAGCGATGGCCTG---------GGTGACTCGCATGATGAGCGGCCTG
AATCAGATGCAGACGTCGCTGGGGCCTTCGAAGTTCCAGAT------GAAGCACGCGAATCTTCTAGTTCACCAGAGAAA
ACAGACTTGATGGTCAGTGATCCTCATGTTCCTTTACTGCCTAAAAGTGAAATAGTCCTTTCCAAACCAGTAGAAAGTAA
C---ATCGAAGACAAAATATTTGGGAAAACGTATCGGAGGAAGTCAAGTCTCCTTAACTCGAGCCATGTAACCGAAGATC
TAATGGTAGGAGCTGCTGCTGCTGTAGCACCTCCGATAGCG---------------------------------------
------------------CAAGAGCACCTTCTTACCAGTAAATTAAAACGC---AGAAGA---TCATCCGTCCTCCACCC
TGAGGACTTTATCAAGAAAGCAGATTTGGCAGTTGTTGAAAAG------------ATCAACCAGGGAACTGACCAAACAC
GGCCGAAG---------GGTCAAGTGGAGCATACTCCCGATGGTGGTCACGGGCATGGAACAAAAGGCGGGAAT---TGT
GTTCAGAAGGAGAGTGCTGACCTGGCAGAA------TCATCGGCCAAAGAATCTGCCTTTCGAACTGTAGCTGAGCCTTT
GAGCAGTAGGAAAAGCGGTATGGAACTGGAACCGACTGTGTTCAATGCAAAAGCACAN---AAGAACAGGCTGAGGAGGA
AGCCCTCTGCCAGGCACATCCACCCCCTGGAACTA---GTCAACAGACAGCCAAGCCCGACGAGGCACACAGAACTGCAA
ATCAGTAGCTGGCCTAGCAGTGAAGAG---CTAAAGAAAGAA---GAATCTGAGCCAAAGCCAGTCAGACGGAGCCGGAA
CTTACAGCTCACGAAAGACCAAGAAATGGCCATCGGAGCCAAGAAGAATGACAAACCAAATGAAGAAAGGGGCAAAAAAC
ACGCCCCTGACACTTTCCCAGAACGAAATTTAACAGACACAACTGACCTAATTACTACCTGTTCGTTTTCTGGTAATCTT
CAAGCATCTGTCTGTCCTAGCCTTCCAGGGGCAAACCTGAAAGAGAAA---CTGGGAACAGTGCAGGTGTCTAATGGTAC
CAGAGACCCCAAAGGTGAGGTGTTGGGTAGAGCAAGG---GGCCTGCAA---ACCGCAAGATCTGTTGAGAGTACCAGTG
TTTCACTGATACCTGATGCTGATGATGGCCCTCAGGGTACCATCTCAATCATGGAAGCAGGCAACCGAGGG---GAGGCA
CAA---ACAGCACCAGGTGAATGTGCAAGGCAGTGTGCAGCAACTGAAAACCCCAACAGGAGTGTCCAGGGTCTT---TC
CAAAGACACTAGAAATAACAGGGAGGGCTCTGAGGATCTCTTGACACACGACGTTAAC---CACCTTCAAGAGACATGCA
CAGAAATGGAAGAGAGTGAACTTGATATTCAATCCTTACAGAATACATTCAAAGTCTCAAAGCGTCAGTCATTTGCTCTG
TCTTCAAATCCA---------GAAAAGGAGTGTGCCTCGCTCGGTGCCCGCCCT---------------------CCAAA
CATTGCTCTTGAGTGTGGGGAA---GAAGGGACTGAGGAGAACAAAGAGTCTGCAGTTCGACCTGTGCAGGCAGTTCCTG
CAACTGTGGGCGGTGCTGGAGGTAGTCCAACAGAGCAACAGCCACGTGATTATACCAAAAGTCACCTTCAAGGAGTGTCC
AGGCTTGGTCAGGCAGCTCCATTCAGA---GGCAGTGAATCTGACCCCAGTACCTCAGTTGAACATGGGATTGTGCAGAC
CTCGGAGCNTGCCCCACCACTCGCTCCCATCAGGTCATCTGTTAACAGTGAACGTAAG------------------GAAA
GACTGGAGGATCATGCAGAATCACTTGAAAGAGCCTCAGAAAACGAGAGTATCATTCCAAGTACAGTGAGCACAATTAGC
CAAAATACCCCGAGAGAAAATGCTTTCAAAGGAACCAGCTCAAGCAGTCTTAATGAAGTAGGTTCTAGC-----------
----------------------------------------------------AGCGAAAACATTCAAGCAGAGCTAGCTA
GGAACAGAGAACCTAAATTGGATGCTGTGCTCAGGTTGGGTCTTGTGCAACCTGAAGTCTGTAAGGAAAGTCTT---CCT
ATGAGGAAATGTAAGCATTCTGAAGTAAAAAGGCAAAAAGGCAATGGAGGACTAGTTCCAGCTGTTCATCCAGATTTCTC
TCGCTATCTAATGTCACATAACCCAGAGCAG---CCTATGGAGGACAAT---GATCCTCAGATTTGTTCTGAGACACCTG
AAGACCTGTTAGATGACAGTGAAATAAATAAAAACAGCCACTTGGTTCAAAGTGACATTAGGGAAAGATCTGCTGTTTTT
AGCAAAGATAACCAGAGAAGAGATTTCAGAAGGAGCCCTGGGCCTACATCCCAT---TTAGGTTTGTCTTGGGGTCACCC
NAGAGGTGCTGAAGAGTTAGAGTCCTTAG--------------------
>Tenrec
TGTGGCACACGTACGCTTGCCAGCTCGGCACAGCGCGAGGACTGCAGCTTATTACTCACCGAAGACAGACTGGATGGAGA
AAAGGCTGGATTCTGCAAGGAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAGCATAGCAGATGGGCTGAAAGTAGGGGAA
CGGGTAATGAC---AAGCCGACTCGTAACACAGAGGAAGAGGTAGTTGTGAGCGCTGACTCCGCGCATGGGAGGAAAGGA
GTGTCTAAGCAGAAACCTCCGCGCCAGAAAAGGCCCAGAAAG---AGCCATGAT---GTGCCTTGGAAAACACGGAAGAG
CAGCATTTCGAAGGTTAACGAGTGGTTTTCCAAAAGCCACGGCCTG---------GGTGACTCTCGCGATGGGCGGCCTG
AGTCAGGCGCAGACGTAGCTGTAGCCTTCGAAGTTCCAGAC------GAAGCATGTGAATCTTATAGTTCTCCAGAGAAA
ACAGACCTGATGGCCAGGGACCCTCCTATTCCCTTACTGCATAAAAGCGCAAGAGTCTTTTCCAAACCAGTAGAAAGTAA
C---ATCGAAGACAAAATATTTGGGAAAACGTATCGGAGGAAGTCAAGCCTCCTTAACTCGAGCCATGTAACTGAAGATC
TGGTGCTAGGAGCTGCGGCTGCCGTAGCGCCTCCGGTAGCA---------------------------------------
------------------CAAGAGCAGCTTCTTACCAGTAAATTAAAGCGCAAGAGGAGA---TCCTTCGTCCTGCACCC
TGAGGACTTCATCAAGAAAGCAGATTTGGCTGTCGTTCAAAAGACTCCTGAAACGATCCATCAGGGACCTGACCCAATGC
AGCCGAAG---------GGGCCAGTGCAGAAGATTCCCGATGGTGGTCCCGGGCGAGGGACAAAAGGCGGGGATCGTGTT
CCGAAGGAGAAGAGTGCTAACCTGGCAGAA------ACATCGGCCAAAGAATCTGCCTTTCGAACTGTAGCTGAACCTTT
GAGCAGCCGGAAAAGCAGTATGGAACTGGAGTTGCCTGTGTTCAGTTCAAGAGCGCAG---AAGAACAGGCTGAGGAGGA
AGCCCTCTGCCAGGCACATCCATCCGCTGGAACTA---GTCAACAGACAACCAAGCCCGACTACGCACACGGAGCTGCAA
ATCAGCAGTTGGCCTAGCAGTGAGGAG---CTAAAGAAAGAA---GAATCCGAGCCAAAGCCAATCAGACGGAGCCGGCA
CTTAAAGCGGGAAAGA---------------------GCCAAGAAGAATGACAAGCCAAACGGAGAAAGGGGCAAAAAAC
ACGCCCCTGACACATTCCCAGACCGAAAGTCAACAAGCACAACGGACTTAATTGCTAACTGTTCCGTTTCTGGCAGTCTT
CATGGAGCTGTCTGTCCTGGCCTTCCAGGGGCAAAGCAAACAGAGAAA---CGGGGAGCAGTGCAGGTGTCTAATAGCGC
CAGAGACCCCAAAGATGAGGTGTTGGGTAGAGCAAGG---GGCCTGCAA---ACTGCAAGATCTGTTGAGAGCACCAGTT
TTTCACTGATACCTGCTGCTGCTGACGGCACCCCGGGTGGCGTCTCAATAATGGAAGCAGGCAGCCGAGGA---CAGGCA
CAA---ACAGCACCAGATCCATGTGCAAGGCAGTGTACAGCAACGGACAACCCCAGCGAAAGTGCCCACGGTCTT---TC
CAGAGATACTAGAAACAGCACGGAGGGCTTTGCGGATCTATTGACACATGGCGTTCCC---CACATCCAAGAGACATGCA
CAGAAATGGAAGAGAGTGAACTTGATATTCAGTCTCTACAGAATATGTTCAAAGTCTCCAAGCGTCAGTCATTTGCTCTC
TCTTCAAATCCA---------GAAAAGGAGTGTGCCACACTCTGTGCCCATCCTAGCGCCTTCAGGAAACAGAATCCAAA
CGATGCTCTTGAGGGTGGAGAA---GAAGGGACTCGGGAGAACAAAGAGTCTACAATTAAGCCTGTGCGGGCAGTTCATA
CCACCGTGGGC------------------ACGGAGAAGCAGCCAAGTGATTACACCAACAGTAGCTTTCAAGGAGTTTCT
AGGCGTGGTCAGGCATCTCAATTCAGA---GCCAGTGAATCTGACCCCGGTACCTCAGTCGAACACGGAAGTTTGCAAAC
CACAGAGCATACCCCACCACTCTCTCCCATCAGATCCTCCCTTAAAAGTAAATGTAAGGAAAAG---CTGTCAGAAGAAA
GATTGGAGGATCAGGCAGAATCCCTTGAAAGAGCCTCGGGGAATGAGAGCATCATTCAAAGTACAGTGAGCACAATTAGC
CAAAATACGCTTAGAGAAAATGCTTTTAAAGGAACCAGCTCAAGCAGTCTTAATGAAGTAGGTTCTAGC-----------
----------------------------------------------------AGCGAAAACATTCAGGCAGAACTAGCTA
GGAACAGAGAACCTAAATTGGATGCTGTGCTCAGACTAGGACTTGTGCAGCCTGAAGGCTGTAAGGAGGAAAGTCTTCCC
CTAAGGAAATGCAAGCATCCTGAAGTAAGAAGGCAAAAAGGCAATGGAGGACTAGTTCCAGCTGTCAATCCGGATCTCTC
CCGCTATCTAATGTCACGTAACCCGGAGCAA---CCGATGGAGAGCAAC---GGTTCTCAGATTTGCTCGGAGACACCTG
AAGACCTGTTAGATGACAGTGAAATAAAAAATAACAGCTACTTTGTTCAAAGTGACGTTAAGGAAAGGTCTGCAGTTTTT
GGCAAAGATAACCAGAGAAGAGATTTCAGAAGGAGCCCTGGGCCTACATCCCAT---TTAGGTTTGACTTGGGGTCACCC
AAGGGGTGCGGAAGAATTAGAGTCCTTAGAAGAAAGCGAAGCCAGTGAG
>LesserEle
TGTGGCACAGATCCTCATGCCAGCTCATTACAGCATGAGAGCAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGA
AAAGGCTGAATTCTATAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACAGAGCAGATGGGCTGAAAGTAAGGAAA
CATGTAATGAT---AGGCAGACTCCTAGCACAGAAAAAAAGGTAGCTGTGAGTGCTGATCTTTATTATGGGATAAAAGAA
GTGAATAAGCAGAAATCTCCGCACTCTGAGAGTCCAAACAAT---AACCAGAAT---ACTCCTTGGATGACATTGAACAG
TAGCATTCGGAAAGTTAATGACTGGTTTTCCAGAAGCGGTGGCCTG---------GATGGCTGCCATGAT---AGATCTG
AATCGAATGTAGTAATAGCTGGTGAAGTGGAAGTTCCAAAT------GAAGTACACGGATATTCTATTTATTCAGAGAAA
TTAGACTTAATGCCCAACAATCCTCATGATACTTCACTGTATGAAAGTGAAAGAACCCTCTCCAAACCAGCTGAAAACAA
C---ATTGAAGATAAAATATTTGGGAAAACCTATCGGAAGAAGGCAAGTCTCTCTAACTTGAGCCATGTGACTCAAGATC
TCATTACAGGAGCTGTTGCTACAGAATGTCAAACAGCACAA---------------------------------------
---------------------GAACGCCCTCTTACAAATAAATTAAAGCGTAAAAGAAGA---ACATCAGGCCTTCAGCC
TGAGGATTTTATCAAGAAGGTAGATTTGACAGTTGTTCAAAAGATTCCTGAAAAGACAAATCAGGAAACTGAACAAATGG
TGCAGAAT------GGTCAAGTGAAGAATAAGATTGCTAGTGGTGGTCATGAGAGTGATACAAAAGGTGATTAT---GTT
CAGGAAGAGAAGAATACTAACCCAACAGAG------TCACTGGTAAGAGAATCTGATTTCAGAAATAAAGCTGAACCTAT
AAGCAGCAGTATAAGCAAAATGGAGCTAGATTTAAATACACACAGTTCGGTAGCACCAAAGGAGAACAGGCTGAGGAGGA
TGTCCTCAACCGGGCATGTTCACGCACTTGAACTAGTAGTCAATATAAGTCCAAGGTCACCTATCCATACTGAAGTACAG
ATTGATGGTTGGTCTAGCAGTGAAGAG---AAAACGAAAAAA---CATTCCGAGCATAAGCCAGTCAGACCTAGCAGAAA
CGTTTCAGTTACAACAAATCAAGAAACTGAAACTGGGTCCAAGAAGAATAACAAGCCAAATGAACAAATGAGTAAAAGAC
ATGCCACTGACACTTCCCCAGGGCAC---------AACATAACTGGCTTCATTACTGACTGTTCAAATACCAGCAGTCTT
CAAGAATGTTTTAATCCTAGACTTCAGGGAGAGGCAGTAGAAGACAAC---TTTGGACCAGTTCAAGTGTCTAATAGTAT
CAAAGATCCCAAGGATCAAGTATTAAATAGAGGAAGG---AGTTTGCAGCACACTGGAAAATGTGTTGAGAGTACCAGTA
TTTCAGTGTTATCTGATACTGATTATGGCACTCAGAATAGCATCTCATTACTGGAGGCTGGCACCCTAGGG---AAGGCA
GAA---ACAGCACCAGATCAATGTGCAAGTCACTGTGCAGCAATGGAAAACTCCAAGAAACATGTTCATGACTTT---CC
TAAAGATACTGGAAATGATACAAAGGGTTTAAAGGACTCATTGAAATGTGATGCTAGC---CACAGTAAGGATACGTACA
TGGAAATGGAAGATAGTGAACTTGATACTCAGTATTTACAGCATACATTCAAGGTTTCAAAGCGTCAGTCATTTTCTCTG
TTTCCAAATCCA---------GAAAGGGACTATACA--------------------------------------------
----------------------------------------------------------AAGCTAGTGCAGCTAGTTCATA
CCACTGCGAGCTATCCTGGAGCCTGTGAGGAAAAGAAA---CCAAATGATTTTACCAAATGTAGCATTAAAGGAGTCACT
AGACTCTCTCATTCATCTCCATTGAGA---GGCAATGAATCTGAACTCATTACCGCAAATGAACATGAAATGTCACATAG
CCCAGATCAGACACCGTCACTTTCTCCCACCAAGGTTCCTGTTAAAATGACATGGAAGAAAAACCACCTGTCAGAAGAAA
ACTTTGAGGAACATACAATA------------ACAATGGGAAATGAGAGCATCGTTTATAGTCCAGTGAGCACAGTTAGC
CAAAGTAATGTTAAGGGA------TATGCTCAGGCCAGTTCAAGCAGTATTAACGAAGTAGGTTCCAGTACTAATGAAGG
AGGTTCCAGTATTAATGAAGTAGGTTCTAGT---------------------GGTGAAAACATCCAAGCAGAGCTCGATA
GGAACAGAGGACCTGCATTAAATGCTGTACTCAGATTAGGTCTTGTGCAACCTGAAGTCTATGAACAAAGTCTT---CCT
GCAGGAAATTGTAAACATCCTGAAATGACAAGGCCAGGAGACAGTGAAGGAGAAAAAAAGACTGTTAATCCAGATTTCTC
TCCATGTCTACTCTCAGATAATTTAGAACAA---CCTAGGGGAAGTTGTCATGCTTCTCAGATTTGTTCTGAGACACCAG
ATGACCTGTTTGGTGATGATGAAATAAAGGAAAATAGCAGCTTTGGTGAAATCAGCTTTAAAGAGAGATCTGCTGTTTTT
AGTAAAGATGAGCAGGCCAGAGAGTTCAATAGGAACTCAAGCCGTTCATCTCGT---TCAGATTTGGCTCCCAGTCATCT
AAGACGCGATAGGGAATTAGAGTCCTCAGAAGAGAATGTATGTA-----
>GiantElep
TGTGCCACAAGTATTCATGCCAGCTCATTACTGCATGAGAACAGCAGGTTATTGCTCAGTAAAGACAGAATGGATGTAGA
AAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACAGAGCAGATGGACTGAAAATAAGGAAA
CATGTAATCAT---AGGCAGACTCCTAGTATAGAGAAAAAATTAGATATGAATGCTGATCCCTCTTATGGGCGAAAAGAA
GTGAATAAGCAGAAATATGAATGCTCTGAAAGCCCTCAAGAT---ACCCAAGAT---ATTCCTTGGATGACACTGAATAG
TAGCGTTCAGAAAGTTAATGCATGGTTTTCCAGAAGTGATGGCCTC---------GATGATGCCCCTGATGTAGGGTCTG
AATCAAATACAGCAATAACTGGTGCACTGGAAGTTTCAAAG------GAAGTACATGGATATTCTAGTTCTTCAGAGAAA
GTACACACAATGACTGGTGATCCTCAGGGTGCTTCAGTATGTGAAAGTGAAAGAGTCTTCTCTAAACCAGCAGAAAATAA
C---GTTGAAGATAAAATATTTGGGAAAACCTATCGGAGAAAGTCAAGTCTCCCTAACTTGAACCATATAACGCAAGATC
TCATTGTAGGAGCTGTTGCTACAGGACCTCAGACAGCACAA---------------------------------------
---------------------GAACACCCTCTTATAAATAAACTAAAGCGTAAAAGGAGA---ATATCTGGCCTTCGTCC
TGAAGATTTTATCAAGAAGGTAGATTTGACT---AGTCAGAAGACTCCTGAAAAGAGAAATCAGACCATTTACCAAGTGG
AC------------------------AGTAGTATTGCTGGCGGTGGTCATGAGCATGAAACGAAAGGTGACTGT---GTT
CAGAAAGAGAAGAATGTTAGCCCAGCAGAA------TCATTGACAAAAGCTTCTGCTTTCAGAACTAAGGATGAACCTAT
AAGCAGCAGTGTGAGCAGTATGGAACTAGAATTAAATATGTACAGTTCGATAGCACCAAAGAAGAACAGGCTGAGAAGGA
AGTCCTCTACTAAGCGTATTTGTGCACTTGAACTAGTAGTCGATAGAAATCCAACTTCACCTACCCATGCTGAGCTAGAG
ATTGATAGTTGGCCTAGCAGTGAAGAG---AGAAGGGAAAAA---TGTTCAGAGTTTAACTCCGTCAGACACAGCAGAAC
CTTTCAGCTTATGAAAGGTCAAGAAACTGAAATTGGAGACCAAAAGAATAATGACAAGCAAAATGAACAAATAAGTAAAA
AACATGCCACTGACACTTCTCCAAAACGA------AACATAACTGGCTTTATCACAAACTGTTCAAATACTGATAATCTT
CAAGAATTTGTTAATCCTAGATTTGAAGGAGAGGAAATAGCC---------GTGGGACCAATTCAAGTGTTGAATAGTAC
CAAGGACCCTGGAACTCAAGTGTTAAGTAAGGAAAGG---GGTTTGCAC---ACTGGGAATTATGTTGAGAGTACCAGTA
TTTCAGTAATACCTGATACTGATGATGGTATTCAAAATAGCACCTCATTACTGGAAGCTGGCACATTAGAA---AAGGCA
GAAGAAACAGCATTGACTCAATGTGCAAGTCACTGTGCAACAATTTTAAACCCCAACACACATGTTCATGGCTTT---CC
TAAAGATCCTGCAAATGACACAGAGGGTGTTAAGGATCTGTTGAAATGTAATCCTAAC---CACCTTCAGGATACGTGCA
TAGAAATGGAAGATAGTGAACTAGATACTCAGTATTTACAGAATACATTCAAAGTTTCAAAACGTCAGTCATTTACCCTG
TTTCCAAATCCA---------GAAAAAGAATGTACAACAGTCTGTGCCCACTCCAGGCTCTCAAAGAAACAAAATCCAAG
TGTCACTCTTGAGTGTAGAGAAAAAAAAGAAAATCAGGGGAATGAAGAGTCTAAAATGAAACATGTGCAGGTCGTTCATA
CATCTGTGCACTATCCGGGAGTTTGTGAAGAAGAGAAGATACCAGATGATCACACCAAAGTTAGCATTAAAGGGATCTCT
AGGCTTTGTCAGTCATCTCCTTTCAGG---AGCAATGAATCTGAACGCATTACTGAAAATGAATGTAAAATGTCACATAG
CCCAAACCAGACACCATCATTTTCTCCCACCAAGCCATCAGTTAGAACCAAATATAAGCAATTCTACTTGTCAGAAGAAG
AGTTGGAGGAACATGCACTATCACCTGAAAGAGCAATGGAAAATGAGAGTTTCATTCACAGTACAGTGAACGCAGTTAGC
CAAAATAACCTTAGGGGAAGTGTCTTTAAAGAAGGCAGCTCAAGCAGTATTAATGAAGCAGGATCCAGTACTAATGAAGT
AAGTTCCAGTATTAATGAAGTATGTTCTAGT---------------------GATGAAAACATCCAAGCCGAACTAGATA
GGAACAGAAGACCTGAATTAAATGCTGTACTCAGGTTAGGTCTTATGCAACCTGAAGTGTATCAACCAAGTCTT---CCA
ACAAATAACTGTGAATATCTTGAAATTAGTGGGCCAGGAAAAAATGAAGGCATAATTCAGGCTGTTAATCCAGATTTTAC
TCCGTGTCTGATTTCAGATAACTTAGAACAACAGCCTATGGGAAGTAATCATGCTTCTCAGATTTGTTCTGAAACACCTG
ATGACCTGTTAAATGATGAGAAAAGAAATGAGAATATCAGCTTTGCTCAAATCAGCATTAAGGAACGATCCACTGTTTTT
AGTAAA---GACCAGGCAAGAGAATTCAGAGGAAACCCAAACCCTTTATCCCAT---TCAGATTTGACTCAGAGTCATCT
AAGAAGTGGTAGGGAATTAGAGTCATCAGAAGANAA-------------
>Caenolest
---------------------NGCTCATTACTGCCTGAGATCACCAGTTTATTGCCCAACACAGACAGAATGAATGTAGA
AAAGGCTGAACTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGCAACCAGCAGAGCAATCTGGATGAAAGTAAGGAAA
TATGTAGTGCTAGCAAGACCCCAGGTGCAGAGGAA---CAGCCTGAGCTGAATGCCAATCATCTGTGTGAGAGGAAAGAA
CTAGAGGAG---AAGCTGCAGTGCCCTGAGAGCCCCAGAGGTGATTCTGGGGACTGCCTGTCTGGAACCAAAGTGAAAAA
CAGTATTCAGAAAGTTAATGAGTGGTTATTCAGAAGTAATGACGTTTTAGCCCCAGATTACTCAAGTGTTAGGAGCCATG
AACAGAATGCAGAGGCAACCAATGCTTTAGAATATGGGCATGTAGAG---ACAGATGGAAATTCTAGCATTTCTGAAAAG
ACTGATATGGTGGCTGACAGTACTGATGGTTCCTGGCTACATGCACCTGAAAAAAACTGCCCCAGACCGGCAGAGAGCAA
CAATATTGAAGATAAAATATTTGGAAAAACCTATCGAAGAAAGTCGGTTCACCCTGTTTTGAATTACGTAACTGAAAACT
TGATTGTTGAAACCATTGCTCCTGATTCTGTGATCCCTCCA---------------------------------------
---------------------GAGCCTCTCAAAAAAACCAAATTAAAGCGTAAAAGAAAGACCATATGTRACCTGCAGCC
TGAGGATTTCATCAAAAAGACAAACATTCCAGTTATTCCCAAAACCCCTGAAAAGAAAAATCACCCTGTTGACCAGATCC
TTGAAAAAGAACAAAATGGCCAGGTGATGAGCACAGCTGATGGTCAGTCCAAGCAGAAAGCACCCGGTTGTCAT---GTG
GGGGAACTGAAAGAGGCTCAGGCATCAGAACCATCCTCTGTAGAGAAAGGATCCACTTTCAAAACTGGATCCGAGCCTGC
AGCTGGTAGCACAAACCAGAGGGAACTTGAATTAAATGGTAGAGATGCAAAAATGACAAAAAAAGACAGACCAAGGAAGA
GGCCTTCAGTTAGGACTGTCTGTGCTCTGGAGCTCGTGACTGATAGACACCCAGGCTCTTCTAATGAGACAGAACTACAG
ATCGATAGCTATCCCAGCAGTGAAGAG---ATAAGGAAAGGAAATAATTCTGAGCAAAAGCAAGTCAGACGCAGCAGAAG
ACTTCAGATGCTGTCAGAA---GAAATTGCAGCAGGAGCCAAGAAGGCCCATAAGCCAGATGAAGAAGTGGAAGAGAATT
GTGTCAATGAAGTTTCCCCAGAACTAAAAATAGGAAAAGTATCTGCCTGTTCTACTGACAGTCTAGCTACTGATAGTGAT
CTGGTATTAGCTAGCTGCAGTTTCACAGAA---GGAGATGAAAAGAGC---CTGGAAGCCTTCCAG---------CCCAG
CAGAGACCAAGAC---AGCCTGGCAGTAAGCAGAGGAGAGAAGTTGCAA---GGGAAAAGAACCAAAGGAAACATGGAGG
TTTTGGAGGTTGCCAGTACTGATTGGGACACTCAGGACAGCACCTCATTGTTTCCAACCGATGTTCCCCCA---AATCCA
ACA---GCAGACTCTGGCCCACACAGAAATCAACATGAGGTCATAGAAACCCCCAAGGAACTCTTTGATGATTGCTCATC
CAAAAACACCGGAAGTGGTAAAGAAGATTTG---------ACAAGACAAGAAGTCAAA---AATACCTCAGAGACAACCA
CAGAGATAGAGGACAGTGAACTTGATACCCAATATTTACAGAATACCTTCAAACGTTCAAAACGCCAATCATTTGCTCTG
TGTCCCAGTCCAAGG------CAGACAAGTATGAAACTCCGGTCCATCCCTAGAGCTCTAAGTCATCAGAGCCCAGATAA
AGCCACGAATCATGGGGGGCAGGAAAAAAAAAAGCAGGGAAGCAGAGAATCAGACAAGGCTGTGCAGCCAGAACTTGCAG
TCATGAGTTCAGCTGCGGTTTGTCAGACAAAGGAGAAAAAGCCAGGTGATTATGCCAAATGTAGCACA------GTCTCT
AGGCTTTGTCACATAGCTCCATTACATGATGACAATGACTGTGACCACAGTGCTGAAAACAACAAGGGAATTTCACAAGT
TCCTGATCAAAAGCAATCTGTCTCTCCAGCAAAGTCATCAGCTGGTAGATCTATATACACAAAAAGCCTCCTGGAGGAAA
GACTTGATGAACAGACCACATGTCCCGAAACAGTGATGGGAAATGAAAGCTTAGTCCACAGTAGCTTAAGCCTGGTTAGC
CAAAGTAACAGCGGAGAATATATTTCTAAAGCAACTGACTCAAACAGATTTGTTGGTGTAGACTCTAGC-----------
----------------------------------------------------GGAGAAGGTAGTCAGGAAGAAAAAGGTG
AAAACAAATTAAATCAGTCCCAAGTCTGTCAACAAAGCTT----------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-------------------------------------------------
>Phascogale
---------------------NGCTCATTACTGCCTGAAACCTCCAGTTTATTGCCCAACACAGACAGAATGTCT---GA
AAAAGCTGAGCTCAGTAATAAAAGCAAACAGTCTGGCTTAGCAAGGAACCAACAGAGCAGACTGGATGAAAGTAAGGGAA
TATGTAGTACTGGGAAGACCCCCAGTGTAGGAGAG---CAGCCTGAGTTGAATGCCCATCATCTGTGTGAGAAGCAAGAA
CTAAAGGAG---AAGCCACAAGGTCCTGAAGGCCCCAGAGGAAATCCTCAGAATTGCCTATCTGGAACCAAACTGAAAAG
CAGTATTCAGAAAGTTAATGAGTGGTTATCCAGGAGTAATGACATTTTAGCCTCCGATTGCTCCCTTGACAAGAATCATA
AGCAGAATGCAGAGATAGCTAGTGCCTTAGAAGATGGGCATCCAGATAACTCTGATGGAAATTCTAGCATTTCTGAGAAG
ACTGACGTTGTGGCTGACACTGCCGATGGAGCCTGGCTACATGTGCCTAAAAGAACTTACACCAGGCCAGCAGAAAACAA
CAATATTAAAGATAAAATATTTGGAAAAACCTATCGGAGAAAGTCGGGTCACCCTAATTTGAATCACATAACTGAAAATT
TGATTGTTGAGACAGTTGTTCCTGATTCTTTGGTTCCTCCA---------------------------------------
---------------------GAACCTCTGAAAAATACCAAGTTAAAGCGTAAAAGAAAGACTATATGTGACTTGCAGCC
TGAGGATTTCATTAAGAAGACG---GTTCCAGTTACTCACAAAACCCCTGAAAAGAAACATCACGCTGCTGACCAAACCC
TTGAAAGAGAACAAAATGACCAAGTGATGAACATGGATAATGGTCATCCTGAACAGAAAGCACTAAATGGTCAT---GTA
GGGGAAATTAAAGAAGCTCAGACATCGGAACTGTTCTCTGCAGAGAAAGAATCCACTTTCAGAACTGGAACAGAGCCTGC
AGCTAGC------------------------TTAAATGGTGAAGAAACCAACATAACAAAAAAAGACAAGCTGAGGAAGC
AGCCTTCATTCAAGATTGTCTGTGCTCTTGAGCTTGGAGTTGATGGAAGCCCAAGCTCTTCTAATGAGACTGAACTACAG
ATCGATAGCTATCCCAGCAGTGAAGAG---ATAAGGAGAAAAAATAATTCTGAACAGAAGCAACTTAGACGCAGCAGAAG
ACTTCAGCAGGTGTCAGAA---GAGATTGCAATTGGAGCCAAGAAAGCCCATAAGCCAGATGATCAAGCAGAAGAAAGTT
GTATCACTGAAGTTGTCTCAGAACTAAAATTAGGAAATCTACCTGCCTGTGCTCCTGACAATGTCAGTACTGATAAGGAT
CAAGTATTAGCTAGTTGCAGTTTCACA------GGAGATGAAAGGAGT---CTGGAAGTAATCCCT---------AGCAG
CCAAGACCAAGAT------TTGGCATTGAGTGGAAAGGAAGGGTTGCAA---GGTGAAATATCTCAAGGAAGCCTGGGGA
CTGTGGAGGTTCCTGATACTGCTTGGGACACTCAGGACAGTACCTCGTTGTTTCCAGCTGATACTCCTCAA---AATTCA
AAA---CCAGGTCCCAGTCCTCACAGAAATCACTGTGAAATAATGGAAACCCCCAAGGAACTCTTAGAAAGTAGTTCATC
CAAAAACACTGAAAGTAGTGTAGAAGATTTAAGGAGCCTGATGAAACAAGAAGTTAAA---AATGCCTCCAAGACAATCA
CAGAAATGGAGGATAGTGAACTTGACACCCAGTATTTACAGAATACTTTCAAGCGTTCAAAGCGCCAGTCATTTGCACTG
TGTTCTAGCCCAAGG------CAAGAATATGTGAAAACCTGTGCTGTCCCTGGGGCTATAAGTCAGCAAAGT--------
----ACAGTTCGTAGGTACCAGGAAAAAGAAAAGCAAGAAAACAGAGAATCAAACAAGCCTGTGCAGCCAAAGCCTGCTG
TTGTG---------------------ATAGAGAAGGGGAAGCCAGGTGATCATGCCAAATGGAGCACCAGAGAAGTCTCC
AGGCTTTGTCACATAGCTTCATTAAATAGTGGCAATGACTGTGAACCCATTGCTGAAATCAACCAGGGAATTTCACAAGT
TCCTGATCAAAACCAATCAGTTTCTCCAGCAAGGTCATCTGATAGTAAAACCATATATGCAAAAAACTTCCTGGAGGAAA
GGCTTGATGAGCAAACCACGTGCCCTGAAACAACTATGGGAAATGAAAGCTTAGCCCAAAGCAGCATTAGTTTAGTTAGT
CAAAGTAATAGCAGAGAATATGTTTCTAACCCAATTGACTTAATT------ATCAGCGTAGGCTCCAGT-----------
----------------------------------------------------GGAGAAGGCACTCAGGCAGAAAAAAGTG
AAAACAAAGAATCTGAATTAAATACACCACCCAAATTAAAGCTTATGCAACCCCAAGTCTCTCAACAGACCTTT---CCT
CAGAATAATTGCAAA-----------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-------------------------------------------------
>Wombat
---------------NNTGCCAGTTCATTACTTCCTAAAACCAGCAGTTTATTGCCCAACACAGACAGAATGAATGTAGA
AAAGGCTGAACTCTGCCATAAAAACAAACAGCCTGCCTTAGGAAGGAACCAAGAGAGCAGTCTCGATGAAAGTAAGGAAA
TATGTAGCCCTGGGAAGACCCCAGGTGCCTGTGAG---CGGCATGAGCTGAATGACCATCATCTGTGTGAGAGGCAAGGC
CTAGAGGAG---AAGCCGCAGCACCCTGAGAGCCCTAGAGGTAATCCTCAGAACTGCCTGTCTGGAACCAAACTGAAAAG
CAGCATTCAGAAAGTTAATGAGTGGTTATCCAGAAGTAGTGACATTTTAGCCTCTGATAACTCCAACGGTAGGAGCCATG
AGCAGAGCGCAGAGGTGCCTAGTGCCTTAGAAGATGGGCATCCAGATACCGCAGAGGGAAATTCTAGCGTTTCTGAGAAG
ACTGACCCAGTGGCTGACAGCACTGATGATGCCTGGCTACATGTGCCTAAAAGAAGCTGTCTCAGGCCTGCAGAAAAC--
-AATATTGAAGATAAAATATTTGGAAAAACCTATCGGAGAAAGTCAGGTCACCCTAATTTGAATTATGTAACTGAAAACT
TGTTTGCTGAAGCTGTGGCTCCTGATTCCTTGATCCCTCTA---------------------------------------
---------------------GAGGCTCCCAAAAACACCAGGTTAAAGCGTAAAGGAAGGAGCATAGCTGACCTGCAGCC
TGAGGATTTCATCAGGAAGACGGACGTTCCAGTTATTCACAAAACCCCTGAAAAGAAAAATCACTCTGTTGACCAAATTC
TCAAAAGAGAACAAAGTGACCAAGTGATGAACACGGCTAACAGTCTTCCTGAGCAGAAAGCCCTAGGTGGTCAT---GTA
GGGGAAGTGAAAGATGTTCAGGTATTAGAGCTGTTCTCTGCGGAGAAAGAATCCACTTTCAGAACTGGAACAGAGCCTGT
AGCTGGCAGCACAAACCATGGGGAGCTTGAATTAAATAGTAGAAATGCCAAAATGACAAGAAAAGACAGGCTGAGGAAGA
AGCCTTCAGCCAGGATCGTCCGTGCTCTTGAGCTCGTAGTTGATAGAAACCCAAGCTCTTCTAATGAGAGTGAACTGCAG
ATCGATAGCTATCCCAGCAGTGAAGAG---ATAAGGAAAGGAACTAATTCTGAACAGAAGCAAATCAGACGCAGCAGAAG
GCTTCGGCTGCTATCAGAA---GAAATTGTGGTTGGAGCCAAGAAGGCCCATAAGCCAGATGACCAAGCAGAAGAAAGTT
GTATCAGTGAAGTTTTCCCAGAACTAAAAATAGGAAACGTGCCTGCCTGTGCTACTGACAGTCTAACTACTGATAGGGAT
CAAGTGTTAGCTAGCTGCAGTTTCACAGAAGAAAGAGATGAAAGGAGC---CTGGAAGCAATCCCA---------AGCAG
CAAAGACCAAGAT------CTGCCCTTGAATGGAGGGGAGGGGTTGCAA---GGTGAAAGAGCCCCAGGAAGCCTGGAGG
CTTTGGAGGTTCCTGATACTGATTGGGACACTCAGGACAGTACCTCATTGTTTCCAGCTGATACTCCCCAA---AATTCA
AAA---GCAGGACCCAGTCCTCACAGAAGCCACAGTGAAATAATGGAAACCCCCAAGGAACTCTTAGATGGTTGTTCATC
CAAAAACACTGAAAGTGACGAAGAAGATTTGAGGAGCCTGATGAGACAGGAAGTTAAA---AATGCCTCCAAGACAACCA
CAGAAATGGAGGATAGTGAACTCGACACCCAGTATTTACAAAATACCTTCAAACGTTCAAAGCGCCAGTCATTTGCTCTG
CGTTCTAGCCCAAGG------CAGGAATGTAGGAAACCCTCTGCTGTCCCTGGGACTGTAAATCAGCAGAGTCCAGATAA
CACCACAGATTGTGGGGGCCAGGAAAAAGAAAAGCAGGGAAACAGAGAATCAAACAAGCCTGTGTGGCCAAAGTCTGCAG
TCATGAGCTTAGCTGCGGCTTGTCAGACAGAGGAGAGGAAGCCAGGTGTTTATGCCAAATGTAGCACCACAGAAGTGTCC
AGGCTTTGTCACATAGCTCCATTACATGGTGTCATTGACTGTGAACACATTGCTGGAAACAACCAGGGAATTTCGCAAGT
TCCTGATCAAAAACCATCAGTTTCTCCAGCAAGGTCATCTGCTAGTAAAACTATAAATACAAAAAACCTCCTGGAGGAAA
GGCTTGATGAACAGACCACATGTCCTGAAACAGCTATGGGAAATGAAAGCTTAGCCCAAAGCAGCTTAAGTCCAGTAAGC
CAAAGTAATAGCAGAGAATATATTTCTAAAGCAACTGACTTAAATAGATTTATCAGCATAGGCTCTAGT-----------
----------------------------------------------------GGAGAAGGCAGTCAGGCACAAAAAGGTG
AAAACAAAGAATCTGAATTAAATACACAACCCAAATTAAAGCTTGTGCAACCCCAAATCTGTCAACAAAGCTTT---CCT
CAGGATAATTGCAAAGAGTCTAAAAGAAAAGGGAAGGGAGGAAATGGAAAATTAGCTCAGGCCATCAGTACAGATTCATC
TCCATGTTTAGAACAA------------------ACTAAAGAGAGTACACATTCTTCTCAGGTTTGTTCTGAGACACCTG
ATGACCT-------------------------------------------------------------------------
--------------------------------------------------------------------------------
-------------------------------------------------
>Bandicoot
---------------------NACTCATTAATGCTTGAAACCAGCAGTTTATTGTCCAACATAGACAGAATGACTACAAA
AAAGGCTGAACTCTGTAATAAAAGTAAAGATCCTGGCTTAGCAAGGAACCAACAGGACTGTTTGGGTGAAAGTAAAGAAA
TAAGTAGCACTGTGAAGACCCCAGCTGCAGGGGAG---CAGCATAAGCTGAATGCCCACCATCTGTGTGAGAAGCAAGAA
CTAGAGGTA---AAGTCACAGCACCCTGAGAGCCCCAAAGGTAGTCCTCGGAGGTGCCGGTCTGGAACCAAACTGAAAAG
CAGTATTCAGAAAGTCAGTGAGTGGTTGTCTAGAAGTAATGACATTTTAAACTCTGATTATTCCCATGAGAGAAGCCAGG
AGCAGAATGCAGAGATTGCTATTGCCTTAGAAGATGGGCATCTGAATACTGCTGATGGAAATTCTAGCATTTCTGAGAAG
ACTGNCCTGGTGGCTGNCACCACTGAT---------------GTGCTGGAAACTAGCTTNTCCAGGCCAGCTAAAAGC--
-AATATTGAAGATAAAATATTTGGGAAGACCTATCGGAGAAAGTCANGTCACTCTAATTTGAATTATCTAACTGAAAACC
TCCTTGTTGAAACTATTGCTCCTGATTCTTTGATCCCTCCA---------------------------------------
---------------------GAATCTCTCAAGAACATCAAGTTAAAGCGAAAAAGAAAAACTATATCTGACCTGCAGCC
TGAAGATTTCATCAGGAAGACAGATGTTCCAGTTAGTCACAAAACCCCTGAAAAGAAAAATCCTGCTGTTGACCAGATTC
TTGAAAGAGAACAAAATGACCAAGTGATGAACACAGCTAATGGTCATCTTAAACAGAAAGCACTGGGTGATCAT---GTC
AAGGAAGTGAAAGATGCTCAGGCAGCAGAACTGTTCTCTACAGAGAAAGAATCAACATTCAGGACTAGAACAGAGCCTAA
AGCTGGCAGCATAGTCCACGGGGAGCTCGAATTAAATGGGAGAGGTGCCAAAATGACAAAAAAGGACAGGTTGAGGAAAA
AGCCTTCAGCCAGGATTGTCCGTGCTCTTGAGCTTGTGGCTGATAAAAACTCAGGCTCTTCTAATGAGGCTGAATTACAG
ATCGATAGTTATCCCAGCAGTGATGAG---ATAAGGAAAGGAAATAATTCTGAACAGAAGCAAATCAGACGCAGCAGAAG
ACTTCAGCTACTGTCAGAA---GAAATTGCAGTTGGAACCAAGAAGGCCCATGAGCCATATGACCAAGCAGAAGAAAGAT
GTGTCAAGAAGGTTTTCCCAGAATTGGAAATGGGAACTGTGTCTGCTGGTGCTACTGACAGCCTATCTACTGATAGGGAT
GAAGTGTTAGCTAGTTGCAGTTTCACAGAT---GGAGAGGAAAGGAAC---CTGGAAGTAATCCCA---------AGCAG
CAAAGACCAAGACCAAGATCTGGCATTAAGTGAAAGGGAAAGGTTGCAA---GAAAAAAGAACCCAAGGAAACCTGGAGC
TTCTGGAGGTTCCAGATACTTATTGGGAAACTCAAGACAGTACTTCACTGTTTCCAGCTGAAACTCCCCAG---AATTCA
AAA---GCAGGACCCAGTCCTCACAGAAGTAACTGTGAAATAATGGAATCCTCCAAAGAACTCTTCGATGCTTATTCATC
CAAAAACACTGACAGTGGCACTGAAGGTTTG---------ATAAGACAGGAAATTAAA---TATGGCTCTGAGACATCTT
CAGTAATGGAGGATAGTGAACTTGACACCCAGTATTTGCAGAATACCTTCAAACGTTCTAAGCGCCAAACATTTGCTCTG
TGTTCCAACCCAAAG------CAGGAACAGATAAAACCCTGCTCTGTTCCTAGGGCTGTCAGCCACCAGAGTTCAGATAA
TGCCTCAGACTGTGGGGGCCAAGAAAAAGAAAAGCAAGGAAACAGAGAATCAAATAAACCTGGCCAACTAGCATCTGCAG
TCAGGAGCTCAGCTGCCACTTGTCAGACA---GAGAGGAAGCCAGGTGATCCTGACAAATGTAGCGCCACAGGAGTTTCC
AGACTTTGTCACATAGCTCCATTACAAGAAGGCAATGACTGTGAATACATTGCTGGAAAAAAACAGGGAATTTCACAAGT
TCCTAATCAAAAACAATCAGTTTCTCCGACAAGGTCATCAGTTAGTAAA---ATATATACAAAAAACCTCTTGAAAGATA
GACTT---GAACAGACCACATGCCCTGAAACAGTTATGGGAAATGAAAGCTTAGGCCAAAGCAGCTTAAGTCCAGTTAGC
CAAAATAACAGCAGAGAATATATTTCTAAAGCAACTGACTTAAATAGATTTATTAGCAGGGACTCTAGT-----------
----------------------------------------------------GGAGAAGACAGTCGGGCAGAAAAAGGTA
AAATCAAAGAATCTGAATTAAATACACCAACCAAATTCAAACTTGTGCAACCACAAGTATGTCAACTAAGCTTT---TCT
CAGGATAATTGCAAAGAGCCAAAAAGAAAAGGGAAAGGAGGAAATGGAATATTAGCTCTGGCCACCAGTACAGATTCATC
TCCATGTTTAAAAGAA------------------ACTAAAGAGAGTACACATTCTTCTCAGG------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-------------------------------------------------
iqtree-piqtree-b8a3d6a/tests/data/protein.fasta 0000664 0000000 0000000 00000003111 15211731751 0021716 0 ustar 00root root 0000000 0000000 >Seq1
LYLIFGAWAGMVGTALSLLIRAELGQPGTLLGDDQIYNVIVTAHAFVMIFFMVMPIMIGGFGNWLVPLMI
GAPDMAFPRMNNMSFWLLPPSFLLLLASSTVEAGAGTGWTVYPPLAGNLAHAGASVDLAIFSLHLAGVSS
ILGAINFITTAINMKPPTLSQYQTPLFVWSVLITAVLLLLSLPVLAAGITMLLTDRNLNTTFFDPAGGGD
PVLYQHLFWF
>Seq2
VGTALXLLIRAELXQPGALLGDDQIYNVVVTAHAFVMIFFMVMPIMIGGFGNWLVPLMIGAPDMAFPRMN
NMSFWLLPPSFLLLMASSTVEAGAGTGWTVYPPLAGNLAHAGASVDLAIFSLHLAGISSILGAINFITTA
INMKPPALSQYQTPLFVWSVLITAVLLLLSLPVLAAGITMLLTDRNLNTTFFDPAGGGDPVLYQHLFWFF
GHPEVYILIL
>Seq3
LYLIFGAWAGMVGTALSLLIRAELGQPGALLGDDQVYNVVVTAHAFVMIFFMVMPIMIGGFGNWLVPLMI
GAPDMAFPRMNNMSFWLLPPSFLLLLASSTVEAGVGTGWTVYPPLAGNLAHAGASVDLAIFSLHLAGISS
ILGAINFITTAINMKPPALSQYQTPLFVWSVLITAVLLLLSLPVLAAGITMLLTDRNLNTTFFDPAGGGD
PVLYQHLFWF
>Seq4
WAGMVGTALSLLIRAELGQPGALLGDDQIYNVVXTAHAFVMIFFMVMPIMIGGFGNWLVPLMIGAPDMAF
PRMNNMSFWLLPPSFLLLMASSTVEAGVGTGWTVYPPLAGNLAHAGASVDLAIFSLHLAGISSILGAINF
ITTAINMKPPALSQYQTPLFVWSVLITAVLLLLSLPVLAAGITMLLTDRNLNTTFFDPAGGGDPVLYQHL
FWFFGHPEVY
>Seq5
LYLIFGAWAGMVGTALSLLIRAELGQPGALLGDDQVYNVVVTAHAFVMIFFMVMPIMIGGFGNWLVPLMI
GAPDMAFPRMNNMSFWLLPPSFLLLLASSTVEAGVGTGWTVYPPLAGNLAHAGASVDLAIFSLHLAGISS
ILGAINFITTAINMKPPALSQYQTPLFVWSVLITAVLLLLSLPVLAAGITMLLTDRNLNTTFFDPAGGGD
PVLYQHLFWF
>Seq6
WAGMVGTALSLLIRAELGQPGALLGDDQIYNVVVTAHAFVMIFFMVMPIMIGGFGNWLVPLMIGAPDMAF
PRMNNMSFWLLPPSFLLLMASSTVEAGVGTGWTVYPPLAGNLAHAGASVDLAIFSLHLAGISSILGAINF
ITTAINMKPPALSQYQTPLFVWSVLITAVLLLLSLPVLAAGITMLLTDRNLNTTFFDPAGGGDPVLYQHL
FWFFGHPEVY
>Seq7
VGTALSLLIRAELGQPGTLLGDDQIYNVIVTAHAFVMIFFMVMPVMIGGFGNWLVPLMIGAPDMAFPRMN
NMSFWLLPPSFLLLLASSTVEAGAGTGWTVYPPLAGNLAHAGASVDLAIFSLHLAGVSSILGAINFITTA
INMKPPALSQYQTPLFVWSVLITAVLLLLSLPVLAAGITMLLTDRNLNTTFFDPAGGGDPVLYQHLFWFF
GHPEVYILIL iqtree-piqtree-b8a3d6a/tests/test_app/ 0000775 0000000 0000000 00000000000 15211731751 0020130 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/tests/test_app/test_app.py 0000664 0000000 0000000 00000011746 15211731751 0022332 0 ustar 00root root 0000000 0000000 import pytest
from cogent3 import PhyloNode, get_app, make_tree
from cogent3.core.alignment import Alignment
import piqtree
from piqtree import ModelFinderResult, jc_distances, make_model
def test_piq_build_tree(four_otu: Alignment) -> None:
expected = make_tree("(Human,Chimpanzee,(SpermWhale,HumpbackW));")
app = get_app("piq_build_tree", model="JC")
got = app(four_otu)
assert expected.same_topology(got)
assert got.source == four_otu.source
def test_piq_build_tree_support(four_otu: Alignment) -> None:
app = get_app("piq_build_tree", model=make_model("JC"), bootstrap_reps=1000)
got = app(four_otu)
supports = [
node.support
for node in got.postorder()
if not node.is_tip() and node.name != "root"
]
assert all(supports)
def test_piq_fit_tree(three_otu: Alignment) -> None:
tree = make_tree(tip_names=three_otu.names)
app = get_app("model", "JC69", tree=tree)
expected = app(three_otu)
piphylo = get_app("piq_fit_tree", tree=tree, model="JC")
got = piphylo(three_otu)
assert got.params["lnL"] == pytest.approx(expected.lnL)
assert got.source == three_otu.source
@pytest.mark.parametrize("num_taxa", [10, 50, 100])
@pytest.mark.parametrize("tree_mode", list(piqtree.TreeGenMode))
def test_piq_random_tree(num_taxa: int, tree_mode: piqtree.TreeGenMode) -> None:
app = get_app("piq_random_tree", tree_mode=tree_mode, rand_seed=1)
tree = app(num_taxa)
assert len(tree.tips()) == num_taxa
def test_piq_jc_distances(five_otu: Alignment) -> None:
app = get_app("piq_jc_distances")
dists = app(five_otu)
assert (
0 < dists["Human", "Chimpanzee"] < dists["Human", "Dugong"]
) # chimpanzee closer than rhesus
assert (
0 < dists["Human", "Rhesus"] < dists["Human", "Manatee"]
) # rhesus closer than manatee
assert (
0 < dists["Human", "Rhesus"] < dists["Human", "Dugong"]
) # rhesus closer than dugong
assert (
0 < dists["Chimpanzee", "Rhesus"] < dists["Chimpanzee", "Manatee"]
) # rhesus closer than manatee
assert (
0 < dists["Chimpanzee", "Rhesus"] < dists["Chimpanzee", "Dugong"]
) # rhesus closer than dugong
assert (
0 < dists["Manatee", "Dugong"] < dists["Manatee", "Rhesus"]
) # dugong closer than rhesus
assert dists.source == five_otu.source
def test_piq_nj_tree(five_otu: Alignment) -> None:
dists = jc_distances(five_otu)
expected = make_tree("(((Human, Chimpanzee), Rhesus), Manatee, Dugong);")
app = get_app("piq_nj_tree")
actual = app(dists)
assert expected.same_topology(actual)
def test_piq_model_finder(five_otu: Alignment) -> None:
app = get_app("piq_model_finder")
got = app(five_otu)
assert isinstance(got, ModelFinderResult)
def test_piq_model_finder_result_roundtrip(five_otu: Alignment) -> None:
app = get_app("piq_model_finder")
got = app(five_otu)
rd = got.to_rich_dict()
inflated = ModelFinderResult.from_rich_dict(rd)
assert isinstance(inflated, ModelFinderResult)
assert str(got.best_aicc) == str(inflated.best_aicc)
def tree_equal(tree1: PhyloNode, tree2: PhyloNode) -> bool:
return str(tree1.sorted()) == str(tree2.sorted())
def test_piq_consesus_tree(five_trees: list[PhyloNode]) -> None:
app_majority = get_app("piq_consensus_tree")
app_strict = get_app("piq_consensus_tree", min_support=1)
app_0_3 = get_app("piq_consensus_tree", min_support=0.3)
expected_majority = make_tree("((a,b),(((e,f),d),c))")
got_majority = app_majority(five_trees)
assert tree_equal(got_majority, expected_majority)
expected_strict = make_tree("(a,b,c,d,(e,f));")
got_strict = app_strict(five_trees)
assert tree_equal(got_strict, expected_strict)
expected_0_3 = make_tree("((a,b),(((e,f),d),c))")
got_0_3 = app_0_3(five_trees)
assert tree_equal(got_0_3, expected_0_3)
def test_piq_simulate_alignment(five_taxon_rooted_tree: PhyloNode) -> None:
app = get_app("piq_simulate_alignment", model="JC")
aln = app(five_taxon_rooted_tree)
assert isinstance(aln, Alignment)
assert sorted(aln.names) == sorted(five_taxon_rooted_tree.get_tip_names())
assert len(aln) == 1000
@pytest.mark.parametrize(
("app_name", "kwargs"),
[
("piq_build_tree", {"model": "JC"}),
(
"piq_fit_tree",
{"tree": make_tree(tip_names=["a", "b", "c"]), "model": "JC"},
),
("piq_random_tree", {"tree_mode": piqtree.TreeGenMode.UNIFORM}),
("piq_jc_distances", {}),
("piq_nj_tree", {}),
("piq_model_finder", {}),
("piq_consensus_tree", {}),
("piq_simulate_alignment", {"model": "JC"}),
],
)
def test_app_citation_bib(app_name: str, kwargs: dict) -> None:
app = get_app(app_name, **kwargs)
bib = app.bib
assert "@article{piqtree," in bib
assert "McArthur" in bib
def test_quick_tree_hook(four_otu: Alignment) -> None:
tree = four_otu.quick_tree(use_hook="piqtree")
assert tree.params["provenance"] == "piqtree"
iqtree-piqtree-b8a3d6a/tests/test_app/test_pickle.py 0000664 0000000 0000000 00000000703 15211731751 0023010 0 ustar 00root root 0000000 0000000 """Apps must be pickleable to be able to be run with parallel=True"""
import pickle
from cogent3 import get_app, make_tree
from piqtree._app import _ALL_APP_NAMES
def test_pickle() -> None:
app_args = {
"piq_build_tree": ("JC",),
"piq_fit_tree": (make_tree("(a,b,(c,d));"), "JC"),
}
for app_name in _ALL_APP_NAMES:
app = get_app(app_name, *app_args.get(app_name, ()))
assert len(pickle.dumps(app)) > 0
iqtree-piqtree-b8a3d6a/tests/test_data.py 0000664 0000000 0000000 00000001643 15211731751 0020637 0 ustar 00root root 0000000 0000000 import pathlib
from pytest_mock import MockerFixture
import piqtree
def test_dataset_names() -> None:
names = piqtree.dataset_names()
assert len(names) > 0
def test_download_dataset(tmp_path: pathlib.Path, mocker: MockerFixture) -> None:
# Mock the requests response
fake_content = b"fake dataset data"
mock_response = mocker.Mock()
mock_response.iter_content.return_value = [fake_content]
mocker.patch("piqtree._data.requests.get", return_value=mock_response)
dataset_name = "example.tree.gz"
dest_path = piqtree.download_dataset(dataset_name, dest_dir=tmp_path)
assert dest_path.exists()
assert dest_path.read_bytes() == fake_content
# Check correct arguments
expected_url = piqtree._data._get_url(dataset_name)
piqtree._data.requests.get.assert_called_once_with( # type: ignore[attr-defined]
expected_url,
stream=True,
timeout=20,
)
iqtree-piqtree-b8a3d6a/tests/test_iqtree/ 0000775 0000000 0000000 00000000000 15211731751 0020641 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_build_tree.py 0000664 0000000 0000000 00000012414 15211731751 0024372 0 ustar 00root root 0000000 0000000 import re
import pytest
from cogent3 import make_tree
from cogent3.core.alignment import Alignment
import piqtree
from piqtree import make_model
from piqtree.exceptions import IqTreeError
from piqtree.model import (
CustomBaseFreq,
DiscreteGammaModel,
FreeRateModel,
FreqType,
LieModel,
LieModelInstance,
Model,
RateModel,
StandardDnaModel,
SubstitutionModel,
)
def check_build_tree_model(
aln: Alignment,
model: Model,
*,
coerce_str: bool = False,
) -> None:
expected = make_tree("(Human,Chimpanzee,(SpermWhale,HumpbackW));")
got = piqtree.build_tree(aln, str(model) if coerce_str else model)
# Check topology
assert expected.same_topology(got.unrooted())
# Check if branch lengths exist
assert all(v.length is not None for v in got.get_edge_vector(include_root=False))
assert got.params["model"] == str(model)
def check_build_tree(
aln: Alignment,
dna_model: SubstitutionModel,
freq_type: FreqType | CustomBaseFreq | None = None,
rate_model: RateModel | None = None,
*,
invariable_sites: bool = False,
coerce_str: bool = False,
) -> None:
model = Model(
dna_model,
freq_type=freq_type or None,
invariable_sites=invariable_sites,
rate_model=rate_model,
)
check_build_tree_model(aln, model, coerce_str=coerce_str)
@pytest.mark.parametrize("dna_model", StandardDnaModel.iter_available_models())
@pytest.mark.parametrize("freq_type", list(FreqType))
def test_non_lie_build_tree(
four_otu: Alignment,
dna_model: StandardDnaModel,
freq_type: FreqType,
) -> None:
check_build_tree(four_otu, dna_model, freq_type)
@pytest.mark.parametrize("lie_model", LieModel.iter_available_models())
def test_lie_build_tree(four_otu: Alignment, lie_model: LieModelInstance) -> None:
check_build_tree(four_otu, lie_model)
@pytest.mark.parametrize("lie_model", LieModel.iter_available_models()[:3])
def test_str_build_tree(four_otu: Alignment, lie_model: LieModelInstance) -> None:
check_build_tree(four_otu, lie_model, coerce_str=True)
@pytest.mark.parametrize("dna_model", StandardDnaModel.iter_available_models()[:3])
@pytest.mark.parametrize("invariable_sites", [False, True])
@pytest.mark.parametrize(
"rate_model",
[
None,
DiscreteGammaModel(),
FreeRateModel(),
DiscreteGammaModel(6),
FreeRateModel(6),
],
)
def test_rate_model_build_tree(
four_otu: Alignment,
dna_model: StandardDnaModel,
invariable_sites: bool,
rate_model: RateModel,
) -> None:
check_build_tree(
four_otu,
dna_model,
rate_model=rate_model,
invariable_sites=invariable_sites,
)
def test_build_tree_inadequate_bootstrapping(four_otu: Alignment) -> None:
with pytest.raises(IqTreeError, match=re.escape("#replicates must be >= 1000")):
piqtree.build_tree(
four_otu,
Model(StandardDnaModel.GTR),
bootstrap_replicates=10,
)
def test_build_tree_bootstrapping(four_otu: Alignment) -> None:
tree = piqtree.build_tree(
four_otu,
Model(StandardDnaModel.GTR),
bootstrap_replicates=1000,
)
supported_node = max(tree.children, key=lambda x: len(x.children))
assert supported_node.support is not None
@pytest.mark.parametrize(
"model_str",
[
"GTR{4.39,5.30,4.39,1.0,12.1}+F{0.1,0.2,0.3,0.4}+I{0.2}+G3{0.7}",
"GTR{4.39,5.30,4.39,1.0,12.1,3.2}+R3{0.1,0.8,0.2,0.5,0.7,0.6}",
"WS3.3b{0.5,-0.2}+F{0.6,0.1,0.2,0.1}+I{0.1}",
],
)
def test_build_tree_paramaterisation(four_otu: Alignment, model_str: str) -> None:
model = make_model(model_str)
check_build_tree_model(four_otu, model)
def test_invalid_protein_base_freq(four_otu: Alignment) -> None:
base_freqs = ["0.05"] * 20
model = f"K81+F{{{','.join(base_freqs)}}}"
with pytest.raises(IqTreeError):
_ = piqtree.build_tree(four_otu, model)
def test_too_many_dna_params(four_otu: Alignment) -> None:
with pytest.raises(IqTreeError):
_ = piqtree.build_tree(four_otu, "GTR{4.39,5.30,4.39,1.0,12.1,3.2,1.5}")
def test_too_few_dna_params(four_otu: Alignment) -> None:
with pytest.raises(IqTreeError):
_ = piqtree.build_tree(four_otu, "GTR{4.39,5.30,4.39,1.0}")
def test_build_tree_other_options(four_otu: Alignment) -> None:
_ = piqtree.build_tree(four_otu, "GTR", other_options="--epsilon 0.1 -n 0")
with pytest.raises(IqTreeError):
# Invalid extra options
_ = piqtree.build_tree(four_otu, "GTR", other_options="--epslon 0.1 -n 0")
def test_build_tree_overridden_option(four_otu: Alignment) -> None:
with pytest.raises(
ValueError,
match=re.escape(
"Option '-seed' will be overridden by parameter of function. Use the parameter directly instead.",
),
):
_ = piqtree.build_tree(
four_otu,
"GTR",
other_options="--epsilon 0.1 -seed 123 -n 0",
)
with pytest.raises(
ValueError,
match=re.escape(
"Option '-bb' will be overridden by parameter of function. Use the parameter directly instead.",
),
):
_ = piqtree.build_tree(
four_otu,
"GTR",
other_options="--epsilon 0.1 -n 0 -bb 2000",
)
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_consensus_tree.py 0000664 0000000 0000000 00000013162 15211731751 0025314 0 ustar 00root root 0000000 0000000 import re
from collections.abc import Iterable
import pytest
from cogent3 import PhyloNode, make_tree
from piqtree import consensus_tree
from piqtree.exceptions import IqTreeError
def tree_equal(tree1: PhyloNode, tree2: PhyloNode) -> bool:
return str(tree1.sorted()) == str(tree2.sorted())
def test_majority_consensus_tree(five_trees: list[PhyloNode]) -> None:
expected = make_tree("((a,b),(((e,f),d),c))")
got_default = consensus_tree(five_trees)
assert tree_equal(got_default, expected)
got = consensus_tree(five_trees, min_support=0.5)
assert tree_equal(got, expected)
def test_higher_support(five_trees: list[PhyloNode]) -> None:
expected_0_7 = make_tree("(a,b,c,(d,(e,f)));")
got_0_7 = consensus_tree(five_trees, min_support=0.7)
assert tree_equal(got_0_7, expected_0_7)
expected_0_9 = make_tree("(a,b,c,d,(e,f));")
got_0_9 = consensus_tree(five_trees, min_support=0.9)
assert tree_equal(got_0_9, expected_0_9)
def test_strict_consensus_tree(five_trees: list[PhyloNode]) -> None:
expected = make_tree("(a,b,c,d,(e,f));")
got = consensus_tree(five_trees, min_support=1)
assert tree_equal(got, expected)
def test_extended_majority_rule() -> None:
tree1 = make_tree("(a,(b,(c,(d,e))))")
tree2 = make_tree("(a,((b,c),(d,e)))")
tree3 = make_tree("(a,((b,c),(d,e)))")
tree4 = make_tree("(a,(c,(b,(d,e))))")
tree5 = make_tree("(c,(b,(a,(d,e))))")
got = consensus_tree([tree1, tree2, tree3, tree4, tree5], min_support=0)
expected = make_tree("(a,((b,c),(d,e)))")
assert tree_equal(got, expected)
def test_lower_support(five_trees: list[PhyloNode]) -> None:
expected = make_tree("((a,b),(((e,f),d),c))")
for support in 0.1, 0.3:
got = consensus_tree(five_trees, min_support=support)
assert tree_equal(got, expected)
def test_single_tree(five_trees: list[PhyloNode]) -> None:
single_tree = five_trees[0]
got = consensus_tree([single_tree])
assert tree_equal(got, single_tree)
def test_even_majority_rule() -> None:
tree1 = make_tree("(a,(b,(c,d)))")
tree2 = make_tree("(a,(b,(c,d)))")
tree3 = make_tree("(b,(a,(c,d)))")
tree4 = make_tree("(c,(a,(b,d)))")
expected = make_tree("(a,b,(c,d))") # Not including (b, (c,d)) as that's only in 2
got = consensus_tree([tree1, tree2, tree3, tree4])
assert tree_equal(got, expected)
@pytest.mark.parametrize("min_support", [-1, -0.1, 1.00001, 2.5])
def test_bad_min_support(five_trees: list[PhyloNode], min_support: float) -> None:
with pytest.raises(
ValueError,
match=re.escape(
f"Only min support values in the range 0 <= value <= 1 are supported, got {min_support}",
),
):
consensus_tree(five_trees, min_support=min_support)
@pytest.mark.parametrize(
"trees",
[
[make_tree("(a,(b,(c,d)))"), make_tree("(a,(b,(c,(d,e))))")],
[make_tree("(a,(b,(c,(d,e))))"), make_tree("(a,(b,(c,d)))")],
(make_tree("(a,(b,(c,e)))"), make_tree("(a,(b,(c,d)))")),
(make_tree("(a,(b,(c,d)))"), make_tree("(a,(b,(c,a)))")),
],
)
def test_bad_trees(trees: Iterable[PhyloNode]) -> None:
with pytest.raises(ValueError, match=re.escape("Trees must be on same taxa set.")):
consensus_tree(trees)
def test_no_trees() -> None:
with pytest.raises(IqTreeError):
consensus_tree([])
def _internal_supports(tree: PhyloNode) -> dict[frozenset, float]:
return {
frozenset(node.get_tip_names()): node.support
for node in tree.postorder()
if not node.is_tip() and not node.is_root()
}
@pytest.mark.parametrize(
("aggregate", "expected_ab", "expected_de"),
[
("mean", 93.0, 79.0),
("max", 95.0, 88.0),
("min", 91.0, 70.0),
],
)
def test_support_aggregate(
aggregate: str,
expected_ab: float,
expected_de: float,
) -> None:
# inputs are rooted differently to the consensus, so matching is by bipartition
tree1 = make_tree("(((a:1,b:1)95:1,c:1)88:1,d:1,e:1);")
tree2 = make_tree("(((a:1,b:1)91:1,c:1)70:1,d:1,e:1);")
got = consensus_tree([tree1, tree2], support_aggregate=aggregate)
supports = _internal_supports(got)
assert supports[frozenset({"c", "d", "e"})] == expected_ab # {a,b}|{c,d,e}
assert supports[frozenset({"d", "e"})] == expected_de # {a,b,c}|{d,e}
def test_support_aggregate_default_is_mean() -> None:
tree1 = make_tree("(((a:1,b:1)95:1,c:1)88:1,d:1,e:1);")
tree2 = make_tree("(((a:1,b:1)91:1,c:1)70:1,d:1,e:1);")
supports = _internal_supports(consensus_tree([tree1, tree2]))
assert supports[frozenset({"c", "d", "e"})] == 93.0
assert supports[frozenset({"d", "e"})] == 79.0
def test_support_aggregate_none_keeps_clade_frequency() -> None:
tree1 = make_tree("(((a:1,b:1)95:1,c:1)88:1,d:1,e:1);")
tree2 = make_tree("(((a:1,b:1)91:1,c:1)70:1,d:1,e:1);")
got = consensus_tree([tree1, tree2], support_aggregate=None)
assert set(_internal_supports(got).values()) == {100.0}
def test_support_aggregate_clade_absent_from_inputs() -> None:
# inputs have no support, so consensus keeps its clade-frequency value
tree1 = make_tree("(((a,b),c),d,e);")
tree2 = make_tree("(((a,b),c),d,e);")
got = consensus_tree([tree1, tree2], support_aggregate="mean")
assert set(_internal_supports(got).values()) == {100.0}
@pytest.mark.parametrize("aggregate", ["median", "average", "MEAN", ""])
def test_bad_support_aggregate(
five_trees: list[PhyloNode],
aggregate: str,
) -> None:
with pytest.raises(
ValueError,
match=re.escape("support_aggregate must be one of"),
):
consensus_tree(five_trees, support_aggregate=aggregate)
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_distance.py 0000664 0000000 0000000 00000001556 15211731751 0024053 0 ustar 00root root 0000000 0000000 from cogent3.core.alignment import Alignment
from piqtree import jc_distances
def test_jc_distance(five_otu: Alignment) -> None:
dists = jc_distances(five_otu)
assert (
0 < dists["Human", "Chimpanzee"] < dists["Human", "Dugong"]
) # chimpanzee closer than rhesus
assert (
0 < dists["Human", "Rhesus"] < dists["Human", "Manatee"]
) # rhesus closer than manatee
assert (
0 < dists["Human", "Rhesus"] < dists["Human", "Dugong"]
) # rhesus closer than dugong
assert (
0 < dists["Chimpanzee", "Rhesus"] < dists["Chimpanzee", "Manatee"]
) # rhesus closer than manatee
assert (
0 < dists["Chimpanzee", "Rhesus"] < dists["Chimpanzee", "Dugong"]
) # rhesus closer than dugong
assert (
0 < dists["Manatee", "Dugong"] < dists["Manatee", "Rhesus"]
) # dugong closer than rhesus
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_fit_tree.py 0000664 0000000 0000000 00000017173 15211731751 0024064 0 ustar 00root root 0000000 0000000 import re
from typing import cast
import numpy as np
import pytest
from cogent3 import get_app, make_tree
from cogent3.app.result import model_result
from cogent3.core.alignment import Alignment
from cogent3.core.tree import PhyloNode
import piqtree
from piqtree.exceptions import IqTreeError
from piqtree.model import Model, StandardDnaModel
def check_model_name(got: PhyloNode, expected: str) -> None:
got_model = cast("str", got.params.get("model"))
assert got_model == expected
def check_likelihood(got: PhyloNode, expected: model_result) -> None:
assert got.params["lnL"] == pytest.approx(expected.lnL)
def check_motif_probs(got: PhyloNode, expected: PhyloNode) -> None:
expected_mprobs = expected.params["mprobs"]
got_mprobs = got.params["mprobs"]
expected_keys = set(expected_mprobs.keys())
got_keys = set(got_mprobs.keys())
# Check that the base characters are the same
assert expected_keys == got_keys
# Check that the probs are the same
expected_values = [expected_mprobs[key] for key in expected_keys]
got_values = [got_mprobs[key] for key in expected_keys]
assert all(
got == pytest.approx(exp)
for got, exp in zip(got_values, expected_values, strict=True)
)
def check_rate_parameters(got: PhyloNode, expected: PhyloNode) -> None:
# Collect all rate parameters in got and expected
exclude = {"length", "ENS", "paralinear", "mprobs"}
expected_keys = {
k for k in expected.get_edge_vector()[0].params if k not in exclude
}
got_keys = {k for k in got.get_edge_vector()[0].params if k not in exclude}
# Check that the keys of rate are the same
assert expected_keys == got_keys
# Check that the values of rate are the same
expected_values = [expected[0].params[key] for key in expected_keys]
got_values = [got[0].params[key] for key in expected_keys]
assert all(
got == pytest.approx(exp, rel=1e-2)
for got, exp in zip(got_values, expected_values, strict=True)
)
def check_branch_lengths(got: PhyloNode, expected: PhyloNode) -> None:
got_dists = got.tip_to_tip_distances()
expected_dists = expected.tip_to_tip_distances()
# make sure the distance matrices have the same name order
# so we can just compare entire numpy arrays
expected_dists = expected_dists.take_dists(got_dists.names)
# Check that the keys of branch lengths are the same
assert set(got_dists.names) == set(expected_dists.names)
# Check that the branch lengths are the same
np.testing.assert_allclose(got_dists.array, expected_dists.array, atol=1e-4)
@pytest.mark.parametrize(
("iq_model", "c3_model"),
[
(StandardDnaModel.JC, "JC69"),
(StandardDnaModel.K80, "K80"),
(StandardDnaModel.GTR, "GTR"),
(StandardDnaModel.TN, "TN93"),
(StandardDnaModel.HKY, "HKY85"),
(StandardDnaModel.F81, "F81"),
],
)
def test_fit_tree(
three_otu: Alignment,
iq_model: StandardDnaModel,
c3_model: str,
) -> None:
tree_topology = make_tree(tip_names=three_otu.names)
app = get_app("model", c3_model, tree=tree_topology)
expected = app(three_otu)
model = Model(iq_model)
got = piqtree.fit_tree(three_otu, tree_topology, model)
check_likelihood(got, expected)
check_motif_probs(got, expected.tree)
check_rate_parameters(got, expected.tree)
check_branch_lengths(got, expected.tree)
check_model_name(got, str(model))
@pytest.mark.parametrize(
("iq_model", "c3_model"),
[
(StandardDnaModel.JC, "JC69"),
(StandardDnaModel.K80, "K80"),
(StandardDnaModel.GTR, "GTR"),
(StandardDnaModel.TN, "TN93"),
(StandardDnaModel.HKY, "HKY85"),
(StandardDnaModel.F81, "F81"),
],
)
def test_fit_tree_str_model(
three_otu: Alignment,
iq_model: StandardDnaModel,
c3_model: str,
) -> None:
tree_topology = make_tree(tip_names=three_otu.names)
app = get_app("model", c3_model, tree=tree_topology)
expected = app(three_otu)
model = str(Model(iq_model))
got = piqtree.fit_tree(three_otu, tree_topology, model)
check_likelihood(got, expected)
check_motif_probs(got, expected.tree)
check_rate_parameters(got, expected.tree)
check_branch_lengths(got, expected.tree)
def test_fit_tree_fixed_branch_length(
three_otu: Alignment,
) -> None:
tree_topology: PhyloNode = make_tree(tip_names=three_otu.names)
lengths = (0.1, 0.2, 0.3)
for i, node in enumerate(tree_topology.postorder(include_self=False)):
node.length = lengths[i]
with_fixed = piqtree.fit_tree(
three_otu,
tree_topology,
"GTR",
bl_fixed=True,
)
without_fixed = piqtree.fit_tree(
three_otu,
tree_topology,
"GTR",
bl_fixed=False,
)
assert "lnL" in with_fixed.params
assert "lnL" in without_fixed.params
assert with_fixed.params["lnL"] != pytest.approx(without_fixed.params["lnL"])
for fixed_node, not_fixed_node, original_node in zip(
with_fixed.postorder(include_self=False),
without_fixed.postorder(include_self=False),
tree_topology.postorder(include_self=False),
strict=True,
):
assert fixed_node.name == not_fixed_node.name
assert not_fixed_node.name == original_node.name
assert fixed_node.length == original_node.length
assert not_fixed_node.length != original_node.length
@pytest.mark.parametrize(
"model_str",
[
"GTR{4.39,5.30,4.39,1.0,12.1}+F{0.1,0.2,0.3,0.4}+I{0.2}+G3{0.7}",
"GTR{4.39,5.30,4.39,1.0,12.1,3.2}+R3{0.1,0.8,0.2,0.5,0.7,0.6}",
"WS3.3b{0.5,-0.2}+F{0.6,0.1,0.2,0.1}+I{0.1}",
],
)
def test_fit_tree_paramaterisation(three_otu: Alignment, model_str: str) -> None:
tree_topology = make_tree(tip_names=three_otu.names)
tree = piqtree.fit_tree(three_otu, tree_topology, model_str)
assert isinstance(tree.params["lnL"], float)
for node in tree.preorder(include_self=False):
assert cast("float", node.length) > 0
def test_special_characters(three_otu: Alignment) -> None:
def _renamer(before: str) -> str:
if before == three_otu.names[0]:
return r"_F''<.'_l_?|\y}_F_o_!@#$%^&*x_''"
return before
three_otu = three_otu.renamed_seqs(_renamer)
to_fit = make_tree(r"(_F''<.'_l_?|\y}_F_o_!@#$%^&*x_'', (Rhesus, Mouse))")
tree = piqtree.fit_tree(three_otu, to_fit, "GTR")
assert isinstance(tree.params["lnL"], float)
for node in tree.preorder(include_self=False):
assert cast("float", node.length) > 0
assert set(three_otu.names) == set(tree.get_tip_names())
def test_fit_tree_other_options(four_otu: Alignment) -> None:
tree = make_tree(tip_names=four_otu.names)
fitted_tree = piqtree.fit_tree(
four_otu,
tree,
"GTR",
other_options="-blmin 0.1 -blmax 0.5",
)
for node in fitted_tree.postorder(include_self=False):
assert node.length is not None
assert 0.1 <= node.length <= 0.5
with pytest.raises(IqTreeError):
# Invalid extra options
fitted_tree = piqtree.fit_tree(
four_otu,
tree,
"GTR",
other_options="-blminn 0.1 -blmaax 0.5",
)
def test_fit_tree_overridden_option(four_otu: Alignment) -> None:
tree = make_tree(tip_names=four_otu.names)
with pytest.raises(
ValueError,
match=re.escape(
"Option '-blfix' will be overridden by parameter of function. Use the parameter directly instead.",
),
):
# Invalid extra options
_ = piqtree.fit_tree(
four_otu,
tree,
"JC",
other_options="-blfix",
)
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_model_finder.py 0000664 0000000 0000000 00000006230 15211731751 0024702 0 ustar 00root root 0000000 0000000 import multiprocessing
import re
import pytest
from cogent3.core.alignment import Alignment
from piqtree.exceptions import IqTreeError
from piqtree.iqtree import ModelFinderResult, ModelResultValue, model_finder
def test_model_result_value_from_string() -> None:
val = "123.45 10 0.678"
result = ModelResultValue.from_string(val)
assert result.lnL == 123.45
assert result.nfp == 10
assert result.tree_length == 0.678
@pytest.mark.parametrize(
"bad_val",
[
"123.45.00 10 0.678", # invalid float
"123.45 10", # too few values
],
)
def test_model_result_value_from_bad_string(bad_val: str) -> None:
with pytest.raises(ValueError, match="Error parsing string"):
_ = ModelResultValue.from_string(bad_val)
@pytest.mark.parametrize("model", ["GTR+F", "GTR+F+G"])
def test_model_finder_result(model: str) -> None:
raw_data = {
model: "123.45 10 0.678",
"best_model_AIC": model,
"best_model_AICc": model,
"best_model_BIC": model,
"best_tree_AIC": "((a,b),(c,d));", # ignored
"initTree": "((a,b),(c,d));", # ignored
"partition_type": 0, # ignored
}
result = ModelFinderResult("test", raw_data)
assert isinstance(result.model_stats[model], ModelResultValue)
assert result.model_stats[model].lnL == 123.45
assert result.model_stats[model].nfp == 10
assert result.model_stats[model].tree_length == 0.678
def test_model_finder(five_otu: Alignment) -> None:
result1 = model_finder(five_otu, rand_seed=1)
result2 = model_finder(
five_otu,
num_threads=multiprocessing.cpu_count(),
rand_seed=1,
)
assert str(result1.best_aic) == str(result2.best_aic)
assert str(result1.best_aicc) == str(result2.best_aicc)
assert str(result1.best_bic) == str(result2.best_bic)
def test_model_finder_restricted_submod(five_otu: Alignment) -> None:
result = model_finder(five_otu, rand_seed=1, model_set={"HKY", "TIM"})
assert str(result.best_aic).startswith(("HKY", "TIM"))
assert str(result.best_aicc).startswith(("HKY", "TIM"))
assert str(result.best_bic).startswith(("HKY", "TIM"))
def test_model_finder_other_options(five_otu: Alignment) -> None:
result = model_finder(
five_otu,
rand_seed=1,
model_set={"HKY", "TIM"},
other_options="-mtree",
)
assert str(result.best_aic).startswith(("HKY", "TIM"))
assert str(result.best_aicc).startswith(("HKY", "TIM"))
assert str(result.best_bic).startswith(("HKY", "TIM"))
with pytest.raises(IqTreeError):
# Invalid extra options
_ = model_finder(
five_otu,
rand_seed=1,
model_set={"HKY", "TIM"},
other_options="-mtre",
)
def test_model_finder_overridden_option(five_otu: Alignment) -> None:
with pytest.raises(
ValueError,
match=re.escape(
"Option '-mset' will be overridden by parameter of function. Use the parameter directly instead.",
),
):
_ = model_finder(
five_otu,
rand_seed=1,
model_set={"HKY", "TIM"},
other_options="-mset JC,HKY,TIM",
)
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_nj_tree.py 0000664 0000000 0000000 00000002461 15211731751 0023703 0 ustar 00root root 0000000 0000000 import re
from typing import cast
import numpy as np
import pytest
from cogent3 import make_tree
from cogent3.core.alignment import Alignment
from piqtree import jc_distances, nj_tree
def test_nj_tree(five_otu: Alignment) -> None:
expected = make_tree("(((Human, Chimpanzee), Rhesus), Manatee, Dugong);")
dists = jc_distances(five_otu)
actual = nj_tree(dists)
assert expected.same_topology(actual)
def test_nj_tree_allow_negative(all_otu: Alignment) -> None:
# a distance matrix can produce trees with negative branch lengths
dists = jc_distances(all_otu)
# check that all branch lengths are non-negative, by default
tree1 = nj_tree(dists)
assert all(
cast("float", node.length) >= 0 for node in tree1.preorder(include_self=False)
)
# check that some branch lengths are negative when allow_negative=True
tree2 = nj_tree(dists, allow_negative=True)
assert any(
cast("float", node.length) < 0 for node in tree2.preorder(include_self=False)
)
def test_nj_tree_nan(four_otu: Alignment) -> None:
dists = jc_distances(four_otu)
dists[1, 0] = dists[0, 1] = np.nan
with pytest.raises(
ValueError,
match=re.escape("The pairwise distance matrix cannot contain NaN values."),
):
nj_tree(dists, allow_negative=True)
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_protein_build_tree.py 0000664 0000000 0000000 00000003207 15211731751 0026132 0 ustar 00root root 0000000 0000000 import pytest
from cogent3.core.alignment import Alignment
import piqtree
from piqtree import make_model
from piqtree.exceptions import IqTreeError
from piqtree.model import (
AaModel,
Model,
SubstitutionModel,
)
def check_build_tree_model(
aln: Alignment,
model: Model,
*,
coerce_str: bool = False,
) -> None:
got = piqtree.build_tree(aln, str(model) if coerce_str else model, rand_seed=1)
# Check if all branch lengths exist
assert all(v.length is not None for v in got.get_edge_vector(include_root=False))
def check_build_tree(
aln: Alignment,
aa_model: SubstitutionModel,
*,
coerce_str: bool = False,
) -> None:
model = Model(aa_model)
check_build_tree_model(aln, model, coerce_str=coerce_str)
@pytest.mark.parametrize("aa_model", AaModel.iter_available_models())
def test_protein_build_tree(protein_four_otu: Alignment, aa_model: AaModel) -> None:
check_build_tree(protein_four_otu, aa_model, coerce_str=True)
@pytest.mark.parametrize("aa_model", AaModel.iter_available_models())
def test_str_protein_build_tree(protein_four_otu: Alignment, aa_model: AaModel) -> None:
check_build_tree(protein_four_otu, aa_model, coerce_str=False)
def test_parameterised_model(protein_four_otu: Alignment) -> None:
base_freq_values = ["0.05"] * 20
model = make_model(f"rtREV+F{{{','.join(base_freq_values)}}}+I{{0.2}}+G3{{1.2}}")
check_build_tree_model(protein_four_otu, model)
def test_invalid_protein_base_freq(protein_four_otu: Alignment) -> None:
model = "FLAVI+F{0.2,0.3,0.4,0.1}"
with pytest.raises(IqTreeError):
_ = piqtree.build_tree(protein_four_otu, model)
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_random_tree.py 0000664 0000000 0000000 00000002631 15211731751 0024553 0 ustar 00root root 0000000 0000000 import pytest
from piqtree import TreeGenMode, random_tree
from piqtree.exceptions import IqTreeError
@pytest.mark.parametrize("num_taxa", [10, 50, 100])
@pytest.mark.parametrize("tree_mode", list(TreeGenMode))
def test_random_tree(num_taxa: int, tree_mode: TreeGenMode) -> None:
tree = random_tree(num_taxa, tree_mode, rand_seed=1)
assert len(tree.tips()) == num_taxa
@pytest.mark.parametrize("rand_seed", [0, 1234])
def test_random_tree_determinism(rand_seed: int) -> None:
tree_1 = random_tree(10, TreeGenMode.YULE_HARDING, rand_seed=rand_seed)
tree_2 = random_tree(10, TreeGenMode.YULE_HARDING, rand_seed=rand_seed)
for node_a, node_b in zip(tree_1.postorder(), tree_2.postorder(), strict=True):
assert node_a.name == node_b.name
assert node_a.length == node_b.length
assert len(node_a.children) == len(node_b.children)
@pytest.mark.parametrize("num_taxa", [10, 50, 100])
@pytest.mark.parametrize("tree_mode", list(TreeGenMode))
def test_random_tree_no_seed(num_taxa: int, tree_mode: TreeGenMode) -> None:
tree = random_tree(num_taxa, tree_mode)
assert len(tree.tips()) == num_taxa
@pytest.mark.parametrize("num_taxa", [-1, 0, 1, 2])
@pytest.mark.parametrize("tree_mode", list(TreeGenMode))
def test_invalid_taxa(
num_taxa: int,
tree_mode: TreeGenMode,
) -> None:
with pytest.raises(IqTreeError):
_ = random_tree(num_taxa, tree_mode, rand_seed=1)
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_robinson_foulds.py 0000664 0000000 0000000 00000000550 15211731751 0025457 0 ustar 00root root 0000000 0000000 import numpy as np
from cogent3 import make_tree
from numpy.testing import assert_array_equal
import piqtree
def test_robinson_foulds() -> None:
tree1 = make_tree("(A,B,(C,D));")
tree2 = make_tree("(A,C,(B,D));")
pairwise_distances = piqtree.robinson_foulds([tree1, tree2])
assert_array_equal(pairwise_distances, np.array([[0, 2], [2, 0]]))
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_segmentation_fault.py 0000664 0000000 0000000 00000004304 15211731751 0026143 0 ustar 00root root 0000000 0000000 """Test combinations of calls which under previous versions resulted in a segmentation fault."""
import pytest
from cogent3 import make_aligned_seqs, make_tree
from cogent3.core.alignment import Alignment
from piqtree import TreeGenMode, build_tree, fit_tree, random_tree
from piqtree.exceptions import IqTreeError
from piqtree.model import DiscreteGammaModel, FreeRateModel, Model, StandardDnaModel
@pytest.fixture
def tiny_alignment() -> Alignment:
return make_aligned_seqs(
{"a": "GGG", "b": "GGC", "c": "AAC", "d": "AAA"},
moltype="dna",
)
def test_two_build_random_tree(tiny_alignment: Alignment) -> None:
"""
Calling build tree twice followed by random tree with a bad input
used to result in a Segmentation Fault in a previous version.
"""
build_tree(tiny_alignment, Model(StandardDnaModel.JC), 1)
build_tree(tiny_alignment, Model(StandardDnaModel.JC), 2)
with pytest.raises(IqTreeError):
random_tree(2, TreeGenMode.BALANCED, 1)
def test_two_fit_random_tree(tiny_alignment: Alignment) -> None:
"""
Calling fit tree twice followed by random tree with a bad input
used to result in a Segmentation Fault in a previous version.
"""
tree = make_tree("(a,b,(c,d));")
fit_tree(tiny_alignment, tree, Model(StandardDnaModel.JC))
fit_tree(tiny_alignment, tree, Model(StandardDnaModel.JC))
with pytest.raises(IqTreeError):
random_tree(2, TreeGenMode.BALANCED, 1)
@pytest.mark.parametrize("rate_model_class", [DiscreteGammaModel, FreeRateModel])
@pytest.mark.parametrize("categories", [0, -4])
def test_two_invalid_models(
tiny_alignment: Alignment,
rate_model_class: type[DiscreteGammaModel] | type[FreeRateModel],
categories: int,
) -> None:
"""
Calling build_tree multiple times with an invalid
model has resulted in a Segmentation Fault.
"""
with pytest.raises(IqTreeError):
_ = build_tree(
tiny_alignment,
Model(StandardDnaModel.JC, rate_model=rate_model_class(categories)),
)
with pytest.raises(IqTreeError):
_ = build_tree(
tiny_alignment,
Model(StandardDnaModel.JC, rate_model=rate_model_class(categories)),
)
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_simulate_alignment.py 0000664 0000000 0000000 00000012767 15211731751 0026150 0 ustar 00root root 0000000 0000000 import re
from typing import cast
import pytest
from cogent3 import make_tree
from cogent3.core.alignment import Alignment
from cogent3.core.tree import PhyloNode
from piqtree import Model, simulate_alignment
from piqtree.distribution import (
IndelDistribution,
IndelGeometric,
IndelLavalette,
IndelNegativeBinomial,
IndelZipfian,
)
from piqtree.iqtree._alignment import UNSUPPORTED_MODELS
from piqtree.model import (
AaModel,
LieModel,
StandardDnaModel,
SubstitutionModel,
)
def check_simulate_alignment(
tree: PhyloNode,
model: Model | str,
length: int | None = None,
insertion_rate: float = 0.0,
deletion_rate: float = 0.0,
insertion_size_distribution: IndelDistribution | str = "POW{1.7/100}",
deletion_size_distribution: IndelDistribution | str = "POW{1.7/100}",
seed: int | None = None,
) -> Alignment:
if length is None:
aln = simulate_alignment(
tree,
model,
rand_seed=seed,
insertion_rate=insertion_rate,
deletion_rate=deletion_rate,
insertion_size_distribution=insertion_size_distribution,
deletion_size_distribution=deletion_size_distribution,
)
else:
aln = simulate_alignment(
tree,
model,
length,
rand_seed=seed,
insertion_rate=insertion_rate,
deletion_rate=deletion_rate,
insertion_size_distribution=insertion_size_distribution,
deletion_size_distribution=deletion_size_distribution,
)
if length is None:
length = 1000
if insertion_rate > 0:
assert len(aln) >= length
else:
assert len(aln) == length
assert aln.num_seqs == len(tree.tips())
assert sorted(aln.names) == sorted(tree.get_tip_names())
return aln
@pytest.mark.parametrize(
"model",
[
*StandardDnaModel.iter_available_models(),
*LieModel.iter_available_models(),
*AaModel.iter_available_models(),
],
)
def test_rooted_tree(
five_taxon_rooted_tree: PhyloNode,
model: SubstitutionModel,
) -> None:
if model.base_model in UNSUPPORTED_MODELS:
with pytest.raises(
ValueError,
match=re.escape(
f"Lie Model {cast('LieModel', model.base_model).value} is unsupported.",
),
):
check_simulate_alignment(five_taxon_rooted_tree, Model(model))
else:
check_simulate_alignment(five_taxon_rooted_tree, Model(model))
@pytest.mark.parametrize(
"model",
[
*StandardDnaModel.iter_available_models(),
*LieModel.iter_available_models(),
*AaModel.iter_available_models(),
],
)
def test_unrooted_tree(
four_taxon_unrooted_tree: PhyloNode,
model: SubstitutionModel,
) -> None:
if model.base_model in UNSUPPORTED_MODELS:
with pytest.raises(
ValueError,
match=re.escape(
f"Lie Model {cast('LieModel', model.base_model).value} is unsupported.",
),
):
check_simulate_alignment(four_taxon_unrooted_tree, Model(model))
else:
check_simulate_alignment(four_taxon_unrooted_tree, Model(model))
@pytest.mark.parametrize("length", [None, 500, 1500])
def test_lengths(
four_taxon_unrooted_tree: PhyloNode,
length: int | None,
) -> None:
check_simulate_alignment(
four_taxon_unrooted_tree,
Model(StandardDnaModel.GTR),
length=length,
)
@pytest.mark.parametrize("insertion_rate", [0.0, 0.03, 0.2])
@pytest.mark.parametrize("deletion_rate", [0.0, 0.04, 0.18])
def test_indel_rates(
four_taxon_unrooted_tree: PhyloNode,
insertion_rate: float,
deletion_rate: float,
) -> None:
check_simulate_alignment(
four_taxon_unrooted_tree,
Model(StandardDnaModel.GTR),
insertion_rate=insertion_rate,
deletion_rate=deletion_rate,
)
@pytest.mark.parametrize(
"indel_size_distributions",
[
(IndelGeometric(5), IndelGeometric(4)),
(IndelNegativeBinomial(5, 20), IndelZipfian(1.5, 10)),
(IndelLavalette(1.5, 10), IndelLavalette(1.5, 10)),
],
)
def test_indel_sizes(
four_taxon_unrooted_tree: PhyloNode,
indel_size_distributions: tuple[IndelDistribution | str, IndelDistribution | str],
) -> None:
insertion_size_distribution = indel_size_distributions[0]
deletion_size_distribution = indel_size_distributions[1]
aln = check_simulate_alignment(
four_taxon_unrooted_tree,
"GTR{1.0,2.0,1.5,3.7,2.8}+F{0.1,0.2,0.3,0.4}",
insertion_rate=0.1,
deletion_rate=0.05,
insertion_size_distribution=insertion_size_distribution,
deletion_size_distribution=deletion_size_distribution,
seed=1,
)
aln_indel_str = check_simulate_alignment(
four_taxon_unrooted_tree,
"GTR{1.0,2.0,1.5,3.7,2.8}+F{0.1,0.2,0.3,0.4}",
insertion_rate=0.1,
deletion_rate=0.05,
insertion_size_distribution=str(insertion_size_distribution),
deletion_size_distribution=str(deletion_size_distribution),
seed=1,
)
assert aln.names == aln_indel_str.names
for name in aln.names:
assert aln.get_seq(name) == aln_indel_str.get_seq(name)
def test_root_seq() -> None:
tree = make_tree("((a:0.8,(b:1.2,c:0)):0.0,d:0.5,e:0.0)")
root_seq = "GGGGCCCCAAAATTTT" * 10
aln = simulate_alignment(tree, "JC", len(root_seq), root_seq=root_seq)
assert str(aln.get_seq("c")) == root_seq
assert str(aln.get_seq("e")) == root_seq
iqtree-piqtree-b8a3d6a/tests/test_iqtree/test_tree_yaml.py 0000664 0000000 0000000 00000025254 15211731751 0024243 0 ustar 00root root 0000000 0000000 import re
from typing import Any
import pytest
from cogent3 import make_tree
from piqtree import make_model
from piqtree.exceptions import ParseIqTreeError
from piqtree.iqtree._tree import _process_tree_yaml, _tree_equal
@pytest.fixture
def newick_not_in_candidates() -> list[dict[str, Any]]:
return [
{ # Newick string not in candidate set (different branch length)
"CandidateSet": {
0: "-6519.33018689 (0:0.0058955371,1:0.0026486308,(2:0.0230933557,3:0.3069062230):0.01387802789);",
1: "-6540.1924365 (0:0.0059276645,(1:0.0026255655,2:0.0369876991):2.43436209e-06,3:0.3205542282);",
2: "-6540.32542968 (0:0.0059468612,(1:0.0021841363,3:0.3203544844):2.076530752e-06,2:0.0369270512);",
},
"ModelDNA": {
"rates": "1, 3.815110072, 1, 1, 3.815110072, 1",
"state_freq": "0.3640205807, 0.1862366777, 0.217291437, 0.2324513047",
},
"PhyloTree": {
"newick": "(0:0.0068955371,1:0.0026486308,(2:0.0230933557,3:0.3069062230):0.01387802789);",
},
"StopRule": {
"curIteration": 101,
"start_real_time": 1731027583,
"time_vec": None,
},
"boot_consense_logl": 0,
"contree_rfdist": -1,
"finished": True,
"finishedCandidateSet": True,
"finishedModelFinal": True,
"finishedModelInit": True,
"initTree": "(0:0.0063001853,1:0.0022115739,(2:0.0203850510,3:0.3497395366):0.01883712169);",
"iqtree": {
"seed": 598834595,
"start_time": 1731027582,
"version": "2.3.6.lib",
},
},
{ # Newick string not in candidate set (different names)
"CandidateSet": {
0: "-6519.33018689 (0:0.0058955371,2:0.0026486308,(1:0.0230933557,3:0.3069062230):0.01387802789);",
1: "-6540.1924365 (0:0.0059276645,(1:0.0026255655,2:0.0369876991):2.43436209e-06,3:0.3205542282);",
2: "-6540.32542968 (0:0.0059468612,(1:0.0021841363,3:0.3203544844):2.076530752e-06,2:0.0369270512);",
},
"ModelDNA": {
"rates": "1, 3.815110072, 1, 1, 3.815110072, 1",
"state_freq": "0.3640205807, 0.1862366777, 0.217291437, 0.2324513047",
},
"PhyloTree": {
"newick": "(0:0.0058955371,1:0.0026486308,(2:0.0230933557,3:0.3069062230):0.01387802789);",
},
"StopRule": {
"curIteration": 101,
"start_real_time": 1731027583,
"time_vec": None,
},
"boot_consense_logl": 0,
"contree_rfdist": -1,
"finished": True,
"finishedCandidateSet": True,
"finishedModelFinal": True,
"finishedModelInit": True,
"initTree": "(0:0.0063001853,1:0.0022115739,(2:0.0203850510,3:0.3497395366):0.01883712169);",
"iqtree": {
"seed": 598834595,
"start_time": 1731027582,
"version": "2.3.6.lib",
},
},
]
@pytest.fixture
def non_lie_dna_with_rate_model() -> dict[str, Any]:
return {
"CandidateSet": {
0: "-6736.94578464 (0:0.0063211201,1:0.0029675780,(2:0.0228519739,3:0.3072009029):0.01373649616);",
1: "-6757.78815651 (0:0.0063607954,(1:0.0030079874,2:0.0365597715):2.296825575e-06,3:0.3208135518);",
2: "-6758.07765021 (0:0.0063826033,(1:0.0021953253,3:0.3207201830):0.0001145372551,2:0.0365362763);",
},
"ModelDNA": {
"rates": "1, 3.82025079, 1, 1, 3.82025079, 1",
"state_freq": "0.3628523161, 0.1852938562, 0.2173913044, 0.2344625233",
},
"PhyloTree": {
"newick": "(0:0.0063211201,1:0.0029675780,(2:0.0228519739,3:0.3072009029):0.01373649616);",
},
"RateGammaInvar": {"gamma_shape": 1.698497993, "p_invar": 1.002841144e-06},
"StopRule": {
"curIteration": 101,
"start_real_time": 1724397157,
"time_vec": None,
},
"boot_consense_logl": 0,
"contree_rfdist": -1,
"finished": True,
"finishedCandidateSet": True,
"finishedModelFinal": True,
"finishedModelInit": True,
"initTree": "(0:0.0063680036,1:0.0026681490,(2:0.0183861083,3:0.3034074996):0.01838610827);",
"iqtree": {"seed": 95633264, "start_time": 1724397157, "version": "2.3.6.lib"},
}
@pytest.fixture
def lie_dna_model() -> dict[str, Any]:
return {
"CandidateSet": {
0: "-6606.82337571 ((0:0.0058632731,(2:0.0225450645,3:0.3055011501):0.01414755595):2.340509431e-06,1:0.0026433577):0;",
1: "-6606.82337581 (0:0.0058609304,(1:0.0026456850,(2:0.0225450645,3:0.3055011501):0.01414755618):2.340509431e-06):0;",
2: "-6606.82337581 ((0:0.0058632731,1:0.0026456850):2.340509431e-06,(2:0.0225450645,3:0.3055011501):0.01414520892):0;",
3: "-6606.82337594 (((0:0.0058630055,1:0.0026461740):0.01414791335,2:0.0225451031):0.1178978025,3:0.1876035160):0;",
4: "-6628.65519886 (0:0.0000023102,((1:0.0027556399,3:0.3193110364):2.07651076e-06,2:0.0366286909):0.005770021808):1e-06;",
5: "-6628.70596445 (0:0.0000022647,((1:0.0027641463,2:0.0366284785):2.43434433e-06,3:0.3193357780):0.005401508376):1e-06;",
},
"ModelLieMarkovRY2.2b": {
"model_parameters": 0.4841804549,
"state_freq": "0.25, 0.25, 0.25, 0.25",
},
"PhyloTree": {
"newick": "((0:0.0058632731,(2:0.0225450645,3:0.3055011501):0.01414755595):2.340509431e-06,1:0.0026433577):0;",
},
"StopRule": {
"curIteration": 101,
"start_real_time": 1729226726,
"time_vec": None,
},
"boot_consense_logl": 0,
"contree_rfdist": -1,
"finished": True,
"finishedCandidateSet": True,
"finishedModelFinal": True,
"finishedModelInit": True,
"initTree": "(0:0.0063001853,1:0.0022115739,(2:0.0203850510,3:0.3497395366):0.01883712169);",
"iqtree": {"seed": 1, "start_time": 1729226725, "version": "2.3.6.lib"},
}
@pytest.fixture
def unrest_model() -> dict[str, Any]:
return {
"CandidateSet": {
0: "-6736.94578464 (0:0.0063211201,1:0.0029675780,(2:0.0228519739,3:0.3072009029):0.01373649616);",
1: "-6757.78815651 (0:0.0063607954,(1:0.0030079874,2:0.0365597715):2.296825575e-06,3:0.3208135518);",
2: "-6758.07765021 (0:0.0063826033,(1:0.0021953253,3:0.3207201830):0.0001145372551,2:0.0365362763);",
},
"ModelUnrest": {
"rates": "0.9543854572, 2.942336813, 0.5526681694, 0.7599462192, 0.897052927, 3.38882313, 4.630689862, 0.7223043133, 0.4970030179, 0.8401385788, 2.854877074, 1",
"state_freq": "0.3234606464, 0.2202693695, 0.2343932981, 0.221876686",
},
"PhyloTree": {
"newick": "(0:0.0063211201,1:0.0029675780,(2:0.0228519739,3:0.3072009029):0.01373649616);",
},
}
def test_newick_not_in_candidates(
newick_not_in_candidates: list[dict[str, Any]],
) -> None:
for yaml in newick_not_in_candidates:
with pytest.raises(
ParseIqTreeError,
match=re.escape("IQ-TREE output is malformed, likelihood not found."),
):
_ = _process_tree_yaml(yaml, ["a", "b", "c", "d"], make_model("JC"))
def test_non_lie_dna_with_rate_model(
non_lie_dna_with_rate_model: dict[str, Any],
) -> None:
# test parsing yaml file containing fits from non-Lie DnaModel and rate heterogeneity model
edge_params = {
"rates": {
"A/C": 1.0,
"A/G": 3.82025079,
"A/T": 1.0,
"C/G": 1.0,
"C/T": 3.82025079,
},
"mprobs": {
"A": 0.3628523161,
"C": 0.1852938562,
"G": 0.2173913044,
"T": 0.2344625233,
},
}
rate_params = {"gamma_shape": 1.698497993, "p_invar": 1.002841144e-06}
tree = _process_tree_yaml(
non_lie_dna_with_rate_model,
["a", "b", "c", "d"],
make_model("GTR+I+G"),
)
for rate, value in edge_params["rates"].items():
assert tree[0].params[rate] == value
assert tree.params["RateGammaInvar"] == rate_params
def test_non_lie_dna_model_motif_absent(
non_lie_dna_with_rate_model: dict[str, Any],
) -> None:
non_lie_dna_with_rate_model["ModelDNA"].pop("state_freq")
with pytest.raises(
ParseIqTreeError,
match=re.escape("IQ-TREE output is malformed, motif parameters not found."),
):
_ = _process_tree_yaml(
non_lie_dna_with_rate_model,
["a", "b", "c", "d"],
make_model("GTR+I+G"),
)
def test_non_lie_dna_model_rate_absent(
non_lie_dna_with_rate_model: dict[str, Any],
) -> None:
non_lie_dna_with_rate_model["ModelDNA"].pop("rates")
with pytest.raises(
ParseIqTreeError,
match=re.escape("IQ-TREE output is malformed, rate parameters not found."),
):
_ = _process_tree_yaml(
non_lie_dna_with_rate_model,
["a", "b", "c", "d"],
make_model("GTR+I+G"),
)
def test_lie_dna_model(
lie_dna_model: dict[str, Any],
) -> None:
# test parsing yaml file containing fits from Lie DnaModel
model_parameters = {
"model_parameters": 0.4841804549,
"mprobs": {"A": 0.25, "C": 0.25, "G": 0.25, "T": 0.25},
}
tree = _process_tree_yaml(lie_dna_model, ["a", "b", "c", "d"], make_model("RY2.2b"))
assert tree.params["ModelLieMarkovRY2.2b"] == model_parameters
def test_lie_dna_model_motif_absent(
lie_dna_model: dict[str, Any],
) -> None:
lie_dna_model["ModelLieMarkovRY2.2b"].pop("state_freq")
with pytest.raises(
ParseIqTreeError,
match=re.escape("IQ-TREE output is malformed, motif parameters not found."),
):
_ = _process_tree_yaml(
lie_dna_model,
["a", "b", "c", "d"],
make_model("RY2.2b"),
)
def test_unrest_model(
unrest_model: dict[str, Any],
) -> None:
tree = _process_tree_yaml(unrest_model, ["a", "b", "c", "d"], make_model("UNREST"))
assert "A/C" in tree[0].params
assert tree.params["mprobs"]
@pytest.mark.parametrize(
("candidate", "expected"),
[
("((a:1.0,b:0.9),c:0.8);", True),
("((a:0.9,b:0.9),c:0.8);", False),
("((a:1.0,c:0.8),b:0.9);", False),
],
)
def test_tree_equal(candidate: str, expected: bool) -> None:
tree = make_tree("((a:1.0,b:0.9),c:0.8);")
candidate_tree = make_tree(candidate)
assert _tree_equal(tree, candidate_tree) == expected
iqtree-piqtree-b8a3d6a/tests/test_model/ 0000775 0000000 0000000 00000000000 15211731751 0020450 5 ustar 00root root 0000000 0000000 iqtree-piqtree-b8a3d6a/tests/test_model/test_freq_type.py 0000664 0000000 0000000 00000006215 15211731751 0024063 0 ustar 00root root 0000000 0000000 import re
from collections.abc import Sequence
import pytest
from piqtree.model import CustomBaseFreq, FreqType, get_freq_type
def test_number_of_descriptions() -> None:
assert len(FreqType) == len(FreqType._descriptions())
def test_descriptions_exist() -> None:
for freq_type in FreqType:
# Raises an error if description not present
_ = freq_type.description
_ = get_freq_type("F{0.1,0.2,0.3,0.4}").description
@pytest.mark.parametrize(
("freq_type", "iqtree_str"),
[
(FreqType.F, "F"),
(FreqType.FO, "FO"),
(FreqType.FQ, "FQ"),
("F", "F"),
("FO", "FO"),
("FQ", "FQ"),
("+F", "F"),
("+FO", "FO"),
("+FQ", "FQ"),
],
)
def test_get_freq_type(freq_type: FreqType | str, iqtree_str: str) -> None:
out = get_freq_type(freq_type)
assert isinstance(out, FreqType)
assert out.iqtree_str() == iqtree_str
@pytest.mark.parametrize(
("freq_type", "iqtree_str"),
[
("+F{0.1,0.2,0.3,0.4}", "F{0.1,0.2,0.3,0.4}"),
(
f"+F{{{','.join(map(str, [0.05] * 20))}}}",
f"F{{{','.join(map(str, [0.05] * 20))}}}",
),
],
)
def test_get_custom_freq_type(freq_type: str, iqtree_str: str) -> None:
out = get_freq_type(freq_type)
assert isinstance(out, CustomBaseFreq)
assert out.iqtree_str() == iqtree_str
@pytest.mark.parametrize(
"freq_type",
["F0", "+F0", "+G", "+R9"],
)
def test_invalid_freq_type_name(freq_type: str) -> None:
with pytest.raises(
ValueError,
match=re.escape(f"Unknown state frequency type: {freq_type!r}"),
):
_ = get_freq_type(freq_type)
@pytest.mark.parametrize(
"freqs",
[[0.1, 0.2, 0.7], [0.2] * 5, [0.04] * 25],
)
def test_invalid_freq_type_params(freqs: Sequence[float]) -> None:
with pytest.raises(
ValueError,
match=re.escape(
f"Expected either 4 frequencies for DNA model or 20 for AA model but got {len(freqs)}",
),
):
_ = get_freq_type(f"F{{{','.join(map(str, freqs))}}}")
def test_custom_empty_str() -> None:
with pytest.raises(
ValueError,
match=re.escape("An empty string does not specify base frequencies."),
):
_ = CustomBaseFreq.from_str("")
def test_custom_bad_start() -> None:
base_freq_str = "G{0.1,0.2,0.3,0.4}"
with pytest.raises(
ValueError,
match=re.escape(
f"A CustomBaseFreq must start with F but got {base_freq_str!r}.",
),
):
_ = CustomBaseFreq.from_str(base_freq_str)
def test_custom_missing_bracket() -> None:
base_freq_str = "F{0.1,0.2,0.3,0.4"
with pytest.raises(
ValueError,
match=re.escape(
f"A CustomBaseFreq must be parameterised with {{}} but got {base_freq_str!r}.",
),
):
_ = CustomBaseFreq.from_str(base_freq_str)
def test_custom_bad_parameter() -> None:
base_freq_str = "F{0.1,0.2,0.3,cat}"
with pytest.raises(
ValueError,
match=re.escape(
f"Unable to parse parameters for CustomBaseFreq: {base_freq_str!r}.",
),
):
_ = CustomBaseFreq.from_str(base_freq_str)
iqtree-piqtree-b8a3d6a/tests/test_model/test_model.py 0000664 0000000 0000000 00000016341 15211731751 0023166 0 ustar 00root root 0000000 0000000 import re
import pytest
from piqtree.model import (
AaModel,
CustomBaseFreq,
DiscreteGammaModel,
FreeRateModel,
FreqType,
LieModel,
Model,
RateModel,
StandardDnaModel,
SubstitutionModel,
make_model,
)
def check_make_model(
sub_mod: SubstitutionModel,
freq_type: FreqType | CustomBaseFreq | None = None,
rate_model: RateModel | None = None,
*,
invariable_sites: bool | float = False,
) -> None:
model = Model(sub_mod, freq_type, rate_model, invariable_sites=invariable_sites)
expected = str(model)
# Check the expected string is approximately generated correctly
# float and True should be True, False should be False
assert (invariable_sites is not False) == model.invariable_sites
if not isinstance(invariable_sites, bool):
assert re.search(r"\+I\{\d+(\.\d+)?\}", expected)
assert model.proportion_invariable_sites == invariable_sites
assert model.invariable_sites
else:
assert model.proportion_invariable_sites is None
assert model.invariable_sites == invariable_sites
assert ("+I" in expected) == invariable_sites
if isinstance(rate_model, DiscreteGammaModel):
assert isinstance(model.rate_model, DiscreteGammaModel)
assert "+G" in expected
if rate_model.alpha is not None:
assert re.search(r"\+G\d*\{\d+(\.\d+)?\}", expected)
else:
assert not isinstance(model.rate_model, DiscreteGammaModel)
assert "+G" not in expected
if isinstance(rate_model, FreeRateModel):
assert isinstance(model.rate_model, FreeRateModel)
assert "+R" in expected
if rate_model.rates is not None:
assert re.search(r"\+R\d*\{\d+(\.\d+)?(,\d+(\.\d+)?)*\}", expected)
else:
assert not isinstance(model.rate_model, FreeRateModel)
assert "+R" not in expected
if freq_type is not None:
assert "+F" in expected
if isinstance(freq_type, CustomBaseFreq):
assert re.search(r"\+F\{\d+(\.\d+)?(,\d+(\.\d+)?)*\}", expected)
else:
assert "+F" not in expected
# Check make_model
got = str(make_model(expected))
assert got == expected
@pytest.mark.parametrize(
"sub_mod",
[
*StandardDnaModel.iter_available_models(),
StandardDnaModel.GTR([4.39, 5.30, 4.39, 1.0, 12.1]),
StandardDnaModel.TIM2([4.39, 5.30, 12.1]),
*LieModel.iter_available_models(),
*AaModel.iter_available_models(),
],
)
def test_make_model_sub_mod(sub_mod: SubstitutionModel) -> None:
check_make_model(sub_mod)
@pytest.mark.parametrize(
"sub_mod",
[
StandardDnaModel.iter_available_models()[0],
LieModel.iter_available_models()[0],
AaModel.iter_available_models()[0],
],
)
@pytest.mark.parametrize(
"freq_type",
[*list(FreqType), CustomBaseFreq([0.1, 0.2, 0.3, 0.4])],
)
def test_make_model_freq_type(
sub_mod: SubstitutionModel,
freq_type: FreqType | CustomBaseFreq,
) -> None:
check_make_model(sub_mod, freq_type=freq_type)
@pytest.mark.parametrize(
"sub_mod",
[
StandardDnaModel.iter_available_models()[-1],
LieModel.iter_available_models()[-1],
AaModel.iter_available_models()[-1],
],
)
@pytest.mark.parametrize("invariable_sites", [0.2, True])
def test_make_model_invar_sites(
sub_mod: SubstitutionModel,
invariable_sites: bool | float,
) -> None:
check_make_model(sub_mod, invariable_sites=invariable_sites)
@pytest.mark.parametrize(
"sub_mod",
[
StandardDnaModel.iter_available_models()[1],
LieModel.iter_available_models()[1],
AaModel.iter_available_models()[1],
],
)
@pytest.mark.parametrize(
"rate_model",
[
DiscreteGammaModel(),
DiscreteGammaModel(6),
DiscreteGammaModel(2, 0.3),
FreeRateModel(),
FreeRateModel(6),
FreeRateModel(2, [0.4, 0.6], [0.9, 0.1]),
],
)
def test_make_model_rate_model(
sub_mod: SubstitutionModel,
rate_model: RateModel,
) -> None:
check_make_model(sub_mod, rate_model=rate_model)
@pytest.mark.parametrize(
"sub_mod",
[
*StandardDnaModel.iter_available_models()[:3],
StandardDnaModel.GTR([1.0, 2.0, 1.5, 3.7, 2.8]),
*LieModel.iter_available_models()[:3],
*AaModel.iter_available_models()[:3],
],
)
@pytest.mark.parametrize(
"freq_type",
[None, FreqType.FQ, CustomBaseFreq([0.1, 0.2, 0.3, 0.4])],
)
@pytest.mark.parametrize("invariable_sites", [False, 0.2, True])
@pytest.mark.parametrize(
"rate_model",
[
None,
DiscreteGammaModel(6),
DiscreteGammaModel(2, 0.3),
FreeRateModel(),
FreeRateModel(2, [0.4, 0.6], [0.9, 0.1]),
],
)
def test_make_model(
sub_mod: SubstitutionModel,
freq_type: FreqType | CustomBaseFreq | None,
invariable_sites: bool | float,
rate_model: RateModel | None,
) -> None:
check_make_model(sub_mod, freq_type, rate_model, invariable_sites=invariable_sites)
def test_model_repr() -> None:
model = make_model("GTR")
assert repr(model) == "Model(submod_type=GTR, freq_type=None, rate_type=None)"
model = make_model("MK6.6+FO+R3")
assert repr(model) == "Model(submod_type=MK6.6, freq_type=FO, rate_type=R3)"
model = make_model("12.12+G")
assert repr(model) == "Model(submod_type=12.12, freq_type=None, rate_type=G)"
model = make_model("NQ.mammal+FQ")
assert repr(model) == "Model(submod_type=NQ.mammal, freq_type=FQ, rate_type=None)"
def test_bad_sub_model() -> None:
with pytest.raises(
ValueError,
match=re.escape("Unknown substitution model: 'GYR'"),
):
make_model("GYR")
def test_multiple_freq_type() -> None:
with pytest.raises(
ValueError,
match=re.escape(
"Model 'GTR+FO+FO' contains multiple base frequency specifications.",
),
):
make_model("GTR+FO+FO")
def test_multiple_invariable_sites() -> None:
with pytest.raises(
ValueError,
match=re.escape(
"Model 'GTR+I+I' contains multiple specifications for invariable sites.",
),
):
make_model("GTR+I+I")
def test_multiple_rate_het() -> None:
with pytest.raises(
ValueError,
match=re.escape(
"Model 'GTR+G+R' contains multiple rate heterogeneity specifications.",
),
):
make_model("GTR+G+R")
def test_unexpected_component() -> None:
with pytest.raises(
ValueError,
match=re.escape(
"Model 'GTR+Z' contains unexpected component.",
),
):
make_model("GTR+Z")
def test_missing_invar_brackets() -> None:
with pytest.raises(
ValueError,
match=re.escape(
"Invalid specification for proportion of invariable sites, got 'I{0.5'.",
),
):
_ = make_model("GTR+I{0.5")
with pytest.raises(
ValueError,
match=re.escape(
"Invalid specification for proportion of invariable sites, got 'I0.3}'.",
),
):
_ = make_model("GTR+I0.3}")
def test_invar_invalid_proportion() -> None:
with pytest.raises(
ValueError,
match=re.escape("Failed to read proportion of invariable sites, got 'I{cat}'"),
):
_ = make_model("HKY+I{cat}")
iqtree-piqtree-b8a3d6a/tests/test_model/test_options.py 0000664 0000000 0000000 00000004041 15211731751 0023553 0 ustar 00root root 0000000 0000000 # testing the display of functions
from typing import Literal
import pytest
from piqtree import available_freq_type, available_models, available_rate_type
from piqtree.model import (
AaModel,
FreqType,
LieModel,
StandardDnaModel,
SubstitutionModel,
)
from piqtree.model._rate_type import ALL_BASE_RATE_TYPES
@pytest.mark.parametrize(
("model_classes", "model_type"),
[(None, None), ([StandardDnaModel, LieModel], "dna"), ([AaModel], "protein")],
)
def test_num_available_models(
model_classes: list[type[SubstitutionModel]] | None,
model_type: Literal["dna", "protein"] | None,
) -> None:
table = available_models(model_type)
if model_classes is None:
model_classes = [StandardDnaModel, LieModel, AaModel]
total_models = sum(
model_class.num_available_models() for model_class in model_classes
)
assert total_models > 0
assert table.shape[0] == total_models
assert table._repr_policy["head"] == table.shape[0]
def test_num_available_models_not_show_all() -> None:
table = available_models(show_all=False)
assert table._repr_policy["head"] != table.shape[0]
@pytest.mark.parametrize(
("model_fetch", "model_type"),
[(None, None), ("dna", "nucleotide"), ("protein", "protein")],
)
def test_available_models_types(
model_fetch: Literal["dna", "protein"] | None,
model_type: str | None,
) -> None:
table = available_models(model_fetch)
if model_type is None:
for check_model_type in table[:, 0]:
assert check_model_type[0] in ["nucleotide", "protein"]
else:
for check_model_type in table[:, 0]:
assert check_model_type[0] == model_type
def test_num_freq_type() -> None:
table = available_freq_type()
total_freq_types = len(FreqType)
assert total_freq_types > 0
assert table.shape[0] == total_freq_types
def test_num_rate_type() -> None:
table = available_rate_type()
total_rate_types = len(ALL_BASE_RATE_TYPES)
assert total_rate_types > 0
assert table.shape[0] == total_rate_types
iqtree-piqtree-b8a3d6a/tests/test_model/test_rate_type.py 0000664 0000000 0000000 00000016551 15211731751 0024065 0 ustar 00root root 0000000 0000000 import re
import pytest
from piqtree.model import (
DiscreteGammaModel,
FreeRateModel,
RateModel,
RateType,
get_rate_type,
)
def test_rate_model_uninstantiable() -> None:
with pytest.raises(TypeError):
_ = RateModel() # type: ignore[abstract]
@pytest.mark.parametrize(
("invariable_sites", "rate_model", "iqtree_str"),
[
(False, None, ""),
(True, None, "I"),
(0.1, None, "I{0.1}"),
(False, DiscreteGammaModel(), "G"),
(True, DiscreteGammaModel(), "I+G"),
(False, FreeRateModel(), "R"),
(True, FreeRateModel(), "I+R"),
(False, DiscreteGammaModel(8), "G8"),
(True, DiscreteGammaModel(8), "I+G8"),
(False, FreeRateModel(8), "R8"),
(True, FreeRateModel(8), "I+R8"),
(False, DiscreteGammaModel(2, 0.5), "G2{0.5}"),
(0.3, DiscreteGammaModel(3, 0.7), "I{0.3}+G3{0.7}"),
(False, FreeRateModel(2, [0.3, 0.7], [0.1, 0.9]), "R2{0.3,0.1,0.7,0.9}"),
(
0.2,
FreeRateModel(3, [0.2, 0.3, 0.5], [2.0, 0.1, 1.3]),
"I{0.2}+R3{0.2,2.0,0.3,0.1,0.5,1.3}",
),
(False, "G", "G"),
(True, "+G", "I+G"),
(False, "+R", "R"),
(True, "R", "I+R"),
(False, "G8", "G8"),
(True, "+G8", "I+G8"),
(False, "+R8", "R8"),
(True, "R8", "I+R8"),
(False, "+G42", "G42"),
(True, "G42", "I+G42"),
(0.3, "+G2{0.5}", "I{0.3}+G2{0.5}"),
(0.2, "R3{0.2,2.0,0.3,0.1,0.5,1.3}", "I{0.2}+R3{0.2,2.0,0.3,0.1,0.5,1.3}"),
(False, "R42", "R42"),
(True, "+R42", "I+R42"),
],
)
def test_get_rate_type(
invariable_sites: bool | float,
rate_model: RateModel | None,
iqtree_str: str,
) -> None:
model = get_rate_type(invariable_sites=invariable_sites, rate_model=rate_model)
assert model.iqtree_str() == iqtree_str
if rate_model is None:
model = get_rate_type(invariable_sites=invariable_sites)
assert model.iqtree_str() == iqtree_str
if not invariable_sites:
model = get_rate_type(rate_model=rate_model)
assert model.iqtree_str() == iqtree_str
@pytest.mark.parametrize("invariable_sites", [True, False])
@pytest.mark.parametrize(
"bad_rate_model",
["M", "T46"],
)
def test_invalid_rate_model_name(
invariable_sites: bool,
bad_rate_model: str,
) -> None:
with pytest.raises(
ValueError,
match=re.escape(f"Unexpected value for rate_model {bad_rate_model!r}"),
):
_ = get_rate_type(invariable_sites=invariable_sites, rate_model=bad_rate_model)
def test_bad_rate_categories() -> None:
bad_rate_model = "R2D2"
expected_error = re.escape(
f"Invalid specification for rate categories {bad_rate_model!r}",
)
with pytest.raises(
ValueError,
match=expected_error,
):
_ = get_rate_type(invariable_sites=True, rate_model=bad_rate_model)
@pytest.mark.parametrize("invariable_sites", [True, False])
@pytest.mark.parametrize(
"bad_rate_model",
[4, 3.15, ["R3", "G"]],
)
def test_invalid_rate_model_type(
invariable_sites: bool,
bad_rate_model: float | list,
) -> None:
with pytest.raises(
TypeError,
match=re.escape(f"Unexpected type for rate_model: {type(bad_rate_model)}"),
):
_ = get_rate_type(
invariable_sites=invariable_sites,
rate_model=bad_rate_model, # type: ignore[arg-type]
)
def test_discrete_empty_str() -> None:
with pytest.raises(
ValueError,
match=re.escape("An empty string is not a DiscreteGammaModel."),
):
_ = DiscreteGammaModel.from_str("")
def test_bad_invariable_sites() -> None:
for invar_p in (1, 1.5, -0.3):
with pytest.raises(
ValueError,
match=re.escape(
"The proportion of invariant sites must be in the range [0,1)",
),
):
_ = RateType(invariable_sites=invar_p)
def test_discrete_bad_start() -> None:
rate_model_str = "R"
with pytest.raises(
ValueError,
match=re.escape(
f"A DiscreteGammaModel must start with G but got {rate_model_str!r}.",
),
):
_ = DiscreteGammaModel.from_str(rate_model_str)
def test_discrete_missing_bracket() -> None:
rate_model_str = "G{0.5"
with pytest.raises(
ValueError,
match=re.escape(f"Missing end bracket for parameterisation {rate_model_str!r}"),
):
_ = DiscreteGammaModel.from_str(rate_model_str)
def test_discrete_bad_parameter() -> None:
rate_model_str = "G{cat}"
with pytest.raises(
ValueError,
match=re.escape(
f"Parameterisation of Discrete Gamma Model is not a number {rate_model_str!r}",
),
):
_ = DiscreteGammaModel.from_str(rate_model_str)
def test_free_empty_str() -> None:
with pytest.raises(
ValueError,
match=re.escape("An empty string is not a FreeRateModel."),
):
_ = FreeRateModel.from_str("")
def test_free_bad_start() -> None:
rate_model_str = "G"
with pytest.raises(
ValueError,
match=re.escape(
f"A FreeRateModel must start with R but got {rate_model_str!r}.",
),
):
_ = FreeRateModel.from_str(rate_model_str)
def test_free_missing_bracket() -> None:
rate_model_str = "R2{0.5,1,0.5,1"
with pytest.raises(
ValueError,
match=re.escape(f"Missing end bracket for parameterisation {rate_model_str!r}"),
):
_ = FreeRateModel.from_str(rate_model_str)
def test_free_bad_parameter() -> None:
rate_model_str = "R2{0.5,cat,0.5,1}"
with pytest.raises(
ValueError,
match=re.escape(
f"Unable to parse parameters for FreeRateModel: {rate_model_str!r}.",
),
):
_ = FreeRateModel.from_str(rate_model_str)
def test_free_bad_number_of_parameters() -> None:
rate_model_str = "R2{0.5,1,0.5,1,0.5,1}"
with pytest.raises(
ValueError,
match=re.escape("Expected 4 parameters but got 6."),
):
_ = FreeRateModel.from_str(rate_model_str)
rate_model_str = "R2{0.5,1,0.5}"
with pytest.raises(
ValueError,
match=re.escape("Expected 4 parameters but got 3."),
):
_ = FreeRateModel.from_str(rate_model_str)
def test_free_missing_rates() -> None:
with pytest.raises(
ValueError,
match=re.escape("Must specify both rates and weights or neither."),
):
_ = FreeRateModel(2, weights=[0.3, 0.7])
def test_free_missing_weights() -> None:
with pytest.raises(
ValueError,
match=re.escape("Must specify both rates and weights or neither."),
):
_ = FreeRateModel(3, rates=[0.3, 0.4, 0.3])
def test_free_wrong_number_of_weights() -> None:
weights = [0.2, 0.5, 0.3]
rates = [0.6, 0.4]
with pytest.raises(
ValueError,
match=re.escape(
f"Expected 2 rates and weights but got {len(weights)} and {len(rates)} respectively.",
),
):
_ = FreeRateModel(2, weights=weights, rates=rates)
def test_free_wrong_number_of_rates() -> None:
weights = [0.2, 0.5, 0.3]
rates = [0.6, 0.4]
with pytest.raises(
ValueError,
match=re.escape(
f"Expected 3 rates and weights but got {len(weights)} and {len(rates)} respectively.",
),
):
_ = FreeRateModel(3, weights=weights, rates=rates)
iqtree-piqtree-b8a3d6a/tests/test_model/test_substitution_model.py 0000664 0000000 0000000 00000012076 15211731751 0026023 0 ustar 00root root 0000000 0000000 import re
from collections.abc import Sequence
import pytest
from piqtree.model import (
AaModel,
LieModel,
Model,
StandardDnaModel,
StandardDnaModelInstance,
SubstitutionModel,
get_substitution_model,
)
@pytest.mark.parametrize("model_class", [StandardDnaModel, AaModel])
def test_number_of_descriptions(
model_class: type[StandardDnaModel] | type[AaModel],
) -> None:
assert len(model_class) == len(model_class._descriptions())
@pytest.mark.parametrize("model_class", [StandardDnaModel, AaModel])
def test_descriptions_exist(
model_class: type[StandardDnaModel] | type[AaModel],
) -> None:
for model in model_class:
# Raises an error if description not present
_ = model.description
@pytest.mark.parametrize(
("model_class", "model_type"),
[(StandardDnaModel, "nucleotide"), (AaModel, "protein")],
)
def test_model_type(
model_class: type[StandardDnaModel] | type[AaModel],
model_type: str,
) -> None:
assert model_class.model_type() == model_type
for model in model_class:
assert model.model_type() == model_type
@pytest.mark.parametrize(
("submod_type", "iqtree_str"),
[
(StandardDnaModel.F81, "F81"),
(LieModel.LIE_10_34, "10.34"),
(LieModel.LIE_4_4a("WS"), "WS4.4a"),
(LieModel.LIE_5_11c("RY"), "RY5.11c"),
(AaModel.NQ_insect, "NQ.insect"),
("NQ.yeast", "NQ.yeast"),
("GTR", "GTR"),
("2.2b", "2.2b"),
],
)
def test_get_substitution_model(
submod_type: SubstitutionModel | str,
iqtree_str: str,
) -> None:
out = get_substitution_model(submod_type)
assert isinstance(out, SubstitutionModel)
assert out.iqtree_str() == iqtree_str
@pytest.mark.parametrize(
("model_str", "params"),
[("GTR", (1.0, 2.0, 1.5, 3.7, 2.8)), ("TIM2", (4.39, 5.30, 12.1))],
)
def test_model_params(model_str: str, params: Sequence[float]) -> None:
iqtree_str = model_str + f"{{{','.join(map(str, params))}}}"
model = get_substitution_model(iqtree_str)
assert model.iqtree_str() == iqtree_str
assert isinstance(model, StandardDnaModelInstance)
assert model.model_params is not None
for model_param, param in zip(model.model_params, params, strict=True):
assert model_param == param
def test_missing_bracket() -> None:
model = "GTR{4.39,5.30,4.39,1.0,12.1"
with pytest.raises(
ValueError,
match=re.escape(f"Missing closing bracket for parameterisation of {model!r}"),
):
_ = get_substitution_model(model)
@pytest.mark.parametrize(
"submod_type",
["FQ", "F", "+GTR", "AA", "G8", ""],
)
def test_invalid_substitution_model(submod_type: str) -> None:
with pytest.raises(
ValueError,
match=re.escape(f"Unknown substitution model: {submod_type!r}"),
):
_ = get_substitution_model(submod_type)
def test_bad_lie_model() -> None:
with pytest.raises(
ValueError,
match=re.escape("Invalid Lie Model pairing prefix: 'RS'"),
):
_ = LieModel.LIE_10_34("RS") # type: ignore[arg-type]
def test_lie_model_enum() -> None:
# Test that using just the enum instead of LieModelInstance still works
lie_model = LieModel.LIE_3_3a
assert str(Model(lie_model)) == "3.3a"
assert lie_model.model_type() == "nucleotide"
assert LieModel.model_type() == "nucleotide"
assert (
lie_model.description
== "Reversible model. Equal base frequencies. equiv. to K3P"
)
@pytest.mark.parametrize(
("model", "base"),
[
(AaModel.WAG, AaModel.WAG),
(LieModel.LIE_2_2b("RY"), LieModel.LIE_2_2b),
(LieModel.LIE_10_12, LieModel.LIE_10_12),
(StandardDnaModel.HKY([0.2]), StandardDnaModel.HKY),
(StandardDnaModel.K3P, StandardDnaModel.K3P),
],
)
def test_base_model(model: SubstitutionModel, base: SubstitutionModel) -> None:
assert model.base_model == base
def test_extended_descriptions() -> None:
for model in StandardDnaModel:
assert model.description == model().description
def test_extended_num_available() -> None:
assert (
StandardDnaModel.num_available_models()
== StandardDnaModelInstance.num_available_models()
)
def test_extended_iter_available() -> None:
for m1, m2 in zip(
StandardDnaModel.iter_available_models(),
StandardDnaModelInstance.iter_available_models(),
strict=True,
):
assert m1 == m2
def test_extended_model_type() -> None:
assert StandardDnaModelInstance.model_type() == "nucleotide"
def test_base_does_not_work() -> None:
with pytest.raises(NotImplementedError):
_ = SubstitutionModel.model_type()
with pytest.raises(NotImplementedError):
_ = SubstitutionModel().iqtree_str()
with pytest.raises(NotImplementedError):
_ = SubstitutionModel().base_model
with pytest.raises(NotImplementedError):
_ = SubstitutionModel.iter_available_models()
with pytest.raises(NotImplementedError):
_ = SubstitutionModel.num_available_models()
with pytest.raises(NotImplementedError):
_ = SubstitutionModel().description