A Python Environment for (phylogenetic) Tree Exploration
—
Comprehensive tree visualization system with customizable styles, faces, and layouts for creating publication-quality phylogenetic tree figures. ETE3's visual framework provides extensive control over tree appearance and annotations.
Main classes for tree visualization and styling.
class TreeStyle:
"""
Global tree visualization style controlling overall appearance.
"""
def __init__(self):
"""Initialize tree style with default settings."""
# Global tree appearance properties
show_leaf_name: bool = True # Display leaf node names
show_branch_length: bool = False # Display branch lengths
show_branch_support: bool = False # Display support values
scale: float = None # Tree scale factor
branch_vertical_margin: float = 0 # Vertical space between branches
margin_left: float = 0 # Left margin
margin_right: float = 0 # Right margin
margin_top: float = 0 # Top margin
margin_bottom: float = 0 # Bottom margin
# Tree layout and orientation
mode: str = "r" # Drawing mode: "r" (rectangular), "c" (circular)
orientation: int = 0 # Orientation: 0, 90, 180, 270 degrees
arc_start: float = 0 # Start angle for circular trees (degrees)
arc_span: float = 360 # Angular span for circular trees (degrees)
rotation: float = 0 # Tree rotation angle
# Advanced layout options
optimal_scale_level: str = "mid" # Scale optimization level
force_topology: bool = False # Force topology-only layout
draw_guiding_lines: bool = False # Draw alignment guides
guiding_lines_type: int = 0 # Guide line style
guiding_lines_color: str = "gray" # Guide line color
complete_branch_lines_when_necessary: bool = True # Complete branch lines
class NodeStyle:
"""
Individual node visualization style.
"""
def __init__(self):
"""Initialize node style with default settings."""
# Node appearance
shape: str = "circle" # Node shape: "circle", "square", "sphere"
size: float = 3 # Node size in points
fgcolor: str = "black" # Foreground color
bgcolor: str = "transparent" # Background color
color: str = "black" # Alias for fgcolor
# Branch line styling
hz_line_color: str = "black" # Horizontal line color
vt_line_color: str = "black" # Vertical line color
hz_line_width: float = 1 # Horizontal line width
vt_line_width: float = 1 # Vertical line width
hz_line_type: int = 0 # Horizontal line type (0=solid, 1=dashed, 2=dotted)
vt_line_type: int = 0 # Vertical line type
# Node visibility and effects
draw_descendants: bool = True # Draw descendant branches
penwidth: float = 1 # Pen width for drawingDisplay trees with customizable styles and export options.
def show(self, tree_style=None, name=None):
"""
Display tree in interactive viewer.
Parameters:
- tree_style (TreeStyle): Global tree styling options
- name (str): Window name for display
"""
def render(self, file_name, w=None, h=None, units="px", tree_style=None, dpi=90):
"""
Render tree to image file.
Parameters:
- file_name (str): Output file path (supports PNG, PDF, SVG)
- w (int): Image width
- h (int): Image height
- units (str): Size units ("px", "mm", "in")
- tree_style (TreeStyle): Styling options
- dpi (int): Resolution for raster formats
Returns:
str: Path to rendered image file
"""
def get_ascii(self, show_internal=True, compact=False, attributes=None):
"""
Generate ASCII art representation of tree.
Parameters:
- show_internal (bool): Show internal node names
- compact (bool): Compact layout
- attributes (list): Node attributes to display
Returns:
str: ASCII tree representation
"""Flexible annotation system using "faces" to add information to tree nodes.
class Face:
"""Base class for all tree annotations."""
def __init__(self):
"""Initialize face with default properties."""
margin_left: float = 0
margin_right: float = 0
margin_top: float = 0
margin_bottom: float = 0
opacity: float = 1.0
rotation: float = 0
class TextFace(Face):
"""Text annotation face."""
def __init__(self, text, ftype="Verdana", fsize=10, fgcolor="black",
penwidth=0, fstyle="normal"):
"""
Create text face.
Parameters:
- text (str): Text content
- ftype (str): Font family
- fsize (int): Font size
- fgcolor (str): Text color
- penwidth (int): Text outline width
- fstyle (str): Font style ("normal", "bold", "italic")
"""
class AttrFace(TextFace):
"""Display node attribute as text."""
def __init__(self, attr, ftype="Verdana", fsize=10, fgcolor="black",
text_prefix="", text_suffix="", **kwargs):
"""
Create attribute display face.
Parameters:
- attr (str): Node attribute name to display
- text_prefix (str): Prefix text
- text_suffix (str): Suffix text
- Additional TextFace parameters
"""
class ImgFace(Face):
"""Image annotation face."""
def __init__(self, img_file, width=None, height=None, is_url=False):
"""
Create image face.
Parameters:
- img_file (str): Image file path or URL
- width (int): Image width in pixels
- height (int): Image height in pixels
- is_url (bool): Whether img_file is URL
"""
class CircleFace(Face):
"""Circle shape annotation."""
def __init__(self, radius, color, style="circle"):
"""
Create circle face.
Parameters:
- radius (float): Circle radius
- color (str): Fill color
- style (str): Shape style
"""
class RectFace(Face):
"""Rectangle shape annotation."""
def __init__(self, width, height, fgcolor="black", bgcolor="white",
label=None, label_size=10):
"""
Create rectangle face.
Parameters:
- width (float): Rectangle width
- height (float): Rectangle height
- fgcolor (str): Border color
- bgcolor (str): Fill color
- label (str): Optional text label
- label_size (int): Label font size
"""Specialized faces for complex data visualization.
class ProfileFace(Face):
"""Profile plot for numerical data."""
def __init__(self, max_v, min_v, center_v, width=200, height=40,
style="plot", colorscheme=None):
"""
Create profile plot face.
Parameters:
- max_v (float): Maximum value
- min_v (float): Minimum value
- center_v (float): Center value
- width (int): Plot width
- height (int): Plot height
- style (str): Plot style ("plot", "heatmap", "cbars")
- colorscheme (dict): Color mapping
"""
class SequenceFace(Face):
"""Sequence alignment visualization."""
def __init__(self, seq, seqtype="aa", fsize=10, codon=None):
"""
Create sequence face.
Parameters:
- seq (str): Sequence string
- seqtype (str): Sequence type ("aa", "nt")
- fsize (int): Font size
- codon (str): Codon table for translation
"""
class TreeFace(Face):
"""Embedded tree visualization."""
def __init__(self, tree, tree_style=None):
"""
Create embedded tree face.
Parameters:
- tree (Tree): Tree to embed
- tree_style (TreeStyle): Style for embedded tree
"""
class BarChartFace(Face):
"""Bar chart annotation."""
def __init__(self, values, width=200, height=100, colors=None,
labels=None, min_value=None, max_value=None):
"""
Create bar chart face.
Parameters:
- values (list): Data values
- width (int): Chart width
- height (int): Chart height
- colors (list): Bar colors
- labels (list): Value labels
- min_value (float): Minimum scale value
- max_value (float): Maximum scale value
"""
class PieChartFace(Face):
"""Pie chart annotation."""
def __init__(self, percents, width=100, height=100, colors=None, labels=None):
"""
Create pie chart face.
Parameters:
- percents (list): Percentage values (must sum to 100)
- width (int): Chart width
- height (int): Chart height
- colors (list): Slice colors
- labels (list): Slice labels
"""Control where faces are displayed relative to tree nodes.
def add_face(self, face, column, position="branch-right"):
"""
Add face to node at specified position.
Parameters:
- face (Face): Face object to add
- column (int): Column position (0, 1, 2, ...)
- position (str): Face position relative to node
"branch-top": Above the branch
"branch-bottom": Below the branch
"branch-right": Right of the branch (default)
"float": Floating position
"aligned": Aligned with other faces
"""
# Pre-defined face positions
FACE_POSITIONS = ["branch-top", "branch-bottom", "branch-right", "float", "aligned"]Color definitions and style utilities for visualization.
# SVG color constants (from svg_colors module)
SVG_COLORS = {
"aliceblue": "#F0F8FF",
"antiquewhite": "#FAEBD7",
"aqua": "#00FFFF",
# ... (extensive color dictionary)
"yellow": "#FFFF00",
"yellowgreen": "#9ACD32"
}
def random_color(h=None, s=None, v=None):
"""
Generate random color in HSV space.
Parameters:
- h (float): Hue (0-1, None for random)
- s (float): Saturation (0-1, None for random)
- v (float): Value/brightness (0-1, None for random)
Returns:
str: Hex color string
"""Pre-defined layout functions for common visualization patterns.
def apply_layout_function(tree, layout_fn, *args, **kwargs):
"""
Apply layout function to tree.
Parameters:
- tree (Tree): Target tree
- layout_fn (function): Layout function to apply
- args, kwargs: Arguments for layout function
"""
# Common layout functions in layouts module
def basic_layout(node):
"""Basic node styling with names and branch lengths."""
def phylogeny_layout(node):
"""Phylogenetic tree layout with species information."""
def evol_layout(node):
"""Evolutionary analysis layout with model information."""from ete3 import Tree, TreeStyle, NodeStyle
# Create and display tree
tree = Tree("(A:1,(B:1,(E:1,D:1):0.5):0.5);")
# Show with default style
tree.show()
# Custom tree style
ts = TreeStyle()
ts.show_leaf_name = True
ts.show_branch_length = True
ts.show_branch_support = False
ts.scale = 120
tree.show(tree_style=ts)from ete3 import Tree, NodeStyle
tree = Tree("(A:1,(B:1,(E:1,D:1):0.5):0.5);")
# Style specific nodes
for node in tree.traverse():
if node.is_leaf():
# Style leaf nodes
nstyle = NodeStyle()
nstyle.shape = "circle"
nstyle.size = 10
nstyle.fgcolor = "red"
node.set_style(nstyle)
else:
# Style internal nodes
nstyle = NodeStyle()
nstyle.shape = "square"
nstyle.size = 5
nstyle.fgcolor = "blue"
node.set_style(nstyle)
tree.show()from ete3 import Tree, TextFace, AttrFace, CircleFace
tree = Tree("(A:1,(B:1,(E:1,D:1):0.5):0.5);")
# Add text annotations
for node in tree.traverse():
if node.is_leaf():
# Add custom text
text_face = TextFace(f"Leaf: {node.name}", fsize=12, fgcolor="green")
node.add_face(text_face, column=0, position="branch-right")
# Add attribute display
dist_face = AttrFace("dist", fsize=10, fgcolor="blue", text_prefix="d=")
node.add_face(dist_face, column=1, position="branch-right")
# Add shape annotation
circle_face = CircleFace(radius=5, color="red")
node.add_face(circle_face, column=2, position="branch-right")
tree.show()from ete3 import Tree, TreeStyle, ProfileFace, BarChartFace
import random
tree = Tree("(A:1,(B:1,(E:1,D:1):0.5):0.5);")
# Add profile data to nodes
for node in tree.traverse():
# Generate random profile data
profile_data = [random.random() for _ in range(50)]
profile_face = ProfileFace(
max_v=max(profile_data),
min_v=min(profile_data),
center_v=sum(profile_data)/len(profile_data),
width=200,
height=40
)
node.add_face(profile_face, column=0, position="aligned")
# Add bar chart for leaves
if node.is_leaf():
values = [random.randint(1, 100) for _ in range(3)]
bar_face = BarChartFace(
values=values,
width=100,
height=50,
colors=["red", "green", "blue"],
labels=["A", "B", "C"]
)
node.add_face(bar_face, column=1, position="aligned")
# Custom tree style for alignment
ts = TreeStyle()
ts.show_leaf_name = False
ts.draw_guiding_lines = True
ts.guiding_lines_color = "gray"
tree.show(tree_style=ts)from ete3 import Tree, TreeStyle
tree = Tree("(A:1,(B:1,(E:1,D:1):0.5):0.5);")
# Setup visualization
ts = TreeStyle()
ts.show_leaf_name = True
ts.show_branch_length = True
# Export to different formats
tree.render("tree.png", tree_style=ts, dpi=300)
tree.render("tree.pdf", tree_style=ts, w=200, h=150, units="mm")
tree.render("tree.svg", tree_style=ts)
# ASCII output
ascii_tree = tree.get_ascii(show_internal=True, compact=False)
print(ascii_tree)from ete3 import Tree, TreeStyle
tree = Tree("(A:1,(B:1,(E:1,D:1):0.5):0.5);")
# Circular tree
ts_circular = TreeStyle()
ts_circular.mode = "c" # Circular mode
ts_circular.arc_start = 0
ts_circular.arc_span = 270
tree.show(tree_style=ts_circular)
# Rotated rectangular tree
ts_rotated = TreeStyle()
ts_rotated.rotation = 90
ts_rotated.orientation = 1
tree.show(tree_style=ts_rotated)Install with Tessl CLI
npx tessl i tessl/pypi-ete3