Skip to content

Python API

tree_annotated_plot.plot

plot

plot(tree: str | Path | dict | TreeNode, chart: ChartInput, *, chart_strain_field: str, tree_strain_field: str, branch_length: Literal['div', 'num_date'], tree_size: int = 100, tree_location: TreeLocation | None = None, spacing: int = 0, tree_line_width: float = 2.0, tree_node_size: float = 45, leader_line_width: float = 1.0, scale_bar: bool = False, branch_length_units: str | None = None, prune_tree_to_chart: bool = False, prune_chart_to_tree: bool = False, strict_version: bool = True, connect_leader_to_label: bool = False, strain_label_font_size: float = 10.0, strain_label_font_weight: Literal['normal', 'bold'] = 'normal', shift_tree_loc: int = 0, color_tree_by: str | None = None, tree_color_scale: dict[str, str] | None = None, tree_color_legend_format: dict[str, Any] | None = None, tree_color_legend_show: bool = True, scale_bar_font_size: float = 10.0) -> alt.HConcatChart | alt.VConcatChart

Return an Altair chart with a phylogenetic tree drawn alongside chart.

PlotConfig

The single source of truth for plot-parameter descriptions. The tree-annotated-plot CLI generates its options from this dataclass (see Command line), and the tree_annotated_plot.plot function accepts the same keyword arguments.

PlotConfig dataclass

Configuration for tree_annotated_plot.plot.

Each field's type annotation is Annotated[T, "<description>"]. The description is the canonical text that appears in the function's docstring, the click --help text, and the rendered Python API page.

chart_strain_field instance-attribute

chart_strain_field: Annotated[str, 'Required. The data-column name the chart\'s strain axis encodes (e.g. "strain" or "axis_label").']

tree_strain_field instance-attribute

tree_strain_field: Annotated[str, 'Required. Where on each tree tip to find the strain identifier. The literal string "name" selects the top-level Auspice node `name` field; any other value X selects node_attrs[X] (auto-unwrapping the Auspice {"value": ...} convention). Dotted paths are not accepted.']

branch_length instance-attribute

branch_length: Annotated[Literal['div', 'num_date'], 'Required. Which Auspice node attribute supplies branch lengths. "div" means divergence branch lengths; "num_date" means calendar dates.']

tree_size class-attribute instance-attribute

tree_size: Annotated[int, "Size in pixels of tree depth. For vertical layout (chart strain on `y`) this is the tree panel's *width*; for horizontal layout (chart strain on `x`) this is the tree panel's *height*."] = 100

tree_location class-attribute instance-attribute

tree_location: Annotated[TreeLocation | None, 'Which side of the chart to draw the tree on. Defaults to the side with the strain-axis labels ("left" for y-encoded strain, "bottom" for x-encoded). Other valid values: "right" (y-encoded), "top" (x-encoded).'] = None

spacing class-attribute instance-attribute

spacing: Annotated[int, 'Pixels of blank space between the tree panel and the chart panel. Default 0, which butts the two together. Distinct from `shift_tree_loc`, which moves the tree within its own panel by resizing the label strip; `spacing` sets the gap between the panels and applies whether or not `connect_leader_to_label` is on.'] = 0

tree_line_width class-attribute instance-attribute

tree_line_width: Annotated[float, "Stroke width (px) for the tree's branch lines. Default 2."] = 2.0

tree_node_size class-attribute instance-attribute

tree_node_size: Annotated[float, 'Area (px²) of the small filled circles drawn at each tip. Default 45. Setting tree_node_size=0 disables the tip-circle layer entirely.'] = 45

leader_line_width class-attribute instance-attribute

leader_line_width: Annotated[float, "Stroke width (px) for the dashed leader lines that connect each tip's branch endpoint to the strain row when the branch doesn't extend all the way to branch_max. Default 1.0. Setting leader_line_width=0 disables the leader-line layer entirely."] = 1.0

scale_bar class-attribute instance-attribute

scale_bar: Annotated[bool, 'Off by default. When on, adds a small bar in the tree panel showing the branch-length scale. Tip-row alignment with the chart is preserved.'] = False

branch_length_units class-attribute instance-attribute

branch_length_units: Annotated[str | None, 'Used only when scale_bar is on and branch_length="div": the unit string pasted after the bar\'s numeric length (e.g. "substitutions/site"). None renders unitless. For branch_length="num_date" the label is always in years/months and this argument is ignored.'] = None

prune_tree_to_chart class-attribute instance-attribute

prune_tree_to_chart: Annotated[bool, "When off (default), tree tips not present in the chart's strain set are a fatal error. When on, those tips (and any internal nodes whose subtrees become empty) are dropped before drawing, with single-child internals collapsed into their kept child."] = False

prune_chart_to_tree class-attribute instance-attribute

prune_chart_to_tree: Annotated[bool, "When off (default), chart strains not present in the tree are a fatal error. When on, chart rows whose `chart_strain_field` value isn't a tree tip are filtered out before drawing."] = False

strict_version class-attribute instance-attribute

strict_version: Annotated[bool, 'When on (default), known-stale specs raise: Vega-Lite 5 or earlier, and Auspice JSON whose `version` is not v2. When off, those become warnings and parsing proceeds.'] = True

connect_leader_to_label class-attribute instance-attribute

connect_leader_to_label: Annotated[bool, "Off (default): the chart's strain-axis labels are kept as the user wrote them and dashed leader lines stop at the tree panel's chart-facing edge. On: leaders extend all the way to the labels — which requires moving the labels off the chart's strain axis and into the tree panel, so the chart's strain-axis labels, ticks, axis line, and title are SUPPRESSED (any user-supplied `axis=...` is overridden) and replacement labels are rendered alongside the tree. Label widths are estimated; for crowded charts tune `strain_label_font_size` or `shift_tree_loc`."] = False

strain_label_font_size class-attribute instance-attribute

strain_label_font_size: Annotated[float, 'Font size (px) for the strain text labels rendered in the tree panel when `connect_leader_to_label` is on.'] = 10.0

strain_label_font_weight class-attribute instance-attribute

strain_label_font_weight: Annotated[Literal['normal', 'bold'], 'Font weight for the strain text labels rendered in the tree panel when `connect_leader_to_label` is on.'] = 'normal'

shift_tree_loc class-attribute instance-attribute

shift_tree_loc: Annotated[int, 'Pixels by which to shift the tree toward (positive) or away from (negative) the chart, by resizing the label strip inside the tree panel. Default 0. Has no effect when connect_leader_to_label is off; to set the gap between the tree and chart panels use `spacing`.'] = 0

color_tree_by class-attribute instance-attribute

color_tree_by: Annotated[str | None, 'Color the tree by an Auspice attribute. Pass a node_attrs key (e.g. "subclade"), or "genotype:<GENE>:<SITE>" / "genotype:<GENE>:<SITE1>,<SITE2>,..." (e.g. "genotype:HA1:158" or "genotype:HA1:158,189") to color by the inferred genotype state at a site or haplotype across sites. A categorical legend is drawn below the plot; missing values are gray. None (default) leaves the tree black.'] = None

tree_color_scale class-attribute instance-attribute

tree_color_scale: Annotated[dict[str, str] | None, 'Hardcoded color scale that overrides the default coloring. Keys are category labels, values are colors (any Vega-Lite-compatible string — e.g. hex codes). The legend order follows the order keys appear here. The keys must match the tree\'s categories one-to-one (extra or missing keys are an error). "unknown" is always gray and must not be specified. For genotype/haplotype colorings, the category strings include the site number (e.g. "K158" or "K158/E189"); a mismatch error lists the actual tree categories. CLI form: "value1=#hex1,value2=#hex2,...".'] = None

tree_color_legend_format class-attribute instance-attribute

tree_color_legend_format: Annotated[dict[str, Any] | None, 'Vega-Lite Legend properties to apply to the tree-coloring legend. Pass any subset of the keys at https://vega.github.io/vega-lite/docs/legend.html#properties as a Python dict (e.g. `{"orient": "left", "labelFontSize": 13, "titleFontSize": 13}`). Common keys: "orient" (default "bottom"), "direction", "columns", "padding", "offset", "labelFontSize", "titleFontSize". Smart default: when "orient" is "left" or "right" and you have not set "columns" or "direction", "columns" is forced to 1 so entries stack vertically. None (default) leaves Vega-Lite\'s defaults. Has no effect when `color_tree_by` is None. CLI form: a JSON object string (quote the whole argument), e.g. \'{"orient":"left","labelFontSize":13}\'.'] = None

tree_color_legend_show class-attribute instance-attribute

tree_color_legend_show: Annotated[bool, 'Whether to render the tree-coloring legend. On (default) shows it. Off hides the legend entirely while keeping the tree colored. Has no effect when `color_tree_by` is None.'] = True

scale_bar_font_size class-attribute instance-attribute

scale_bar_font_size: Annotated[float, "Font size (px) for the tree's scale bar label. Default 10. Has no effect when `scale_bar` is off."] = 10.0

__init__

__init__(*, chart_strain_field: Annotated[str, 'Required. The data-column name the chart\'s strain axis encodes (e.g. "strain" or "axis_label").'], tree_strain_field: Annotated[str, 'Required. Where on each tree tip to find the strain identifier. The literal string "name" selects the top-level Auspice node `name` field; any other value X selects node_attrs[X] (auto-unwrapping the Auspice {"value": ...} convention). Dotted paths are not accepted.'], branch_length: Annotated[Literal['div', 'num_date'], 'Required. Which Auspice node attribute supplies branch lengths. "div" means divergence branch lengths; "num_date" means calendar dates.'], tree_size: Annotated[int, "Size in pixels of tree depth. For vertical layout (chart strain on `y`) this is the tree panel's *width*; for horizontal layout (chart strain on `x`) this is the tree panel's *height*."] = 100, tree_location: Annotated[TreeLocation | None, 'Which side of the chart to draw the tree on. Defaults to the side with the strain-axis labels ("left" for y-encoded strain, "bottom" for x-encoded). Other valid values: "right" (y-encoded), "top" (x-encoded).'] = None, spacing: Annotated[int, 'Pixels of blank space between the tree panel and the chart panel. Default 0, which butts the two together. Distinct from `shift_tree_loc`, which moves the tree within its own panel by resizing the label strip; `spacing` sets the gap between the panels and applies whether or not `connect_leader_to_label` is on.'] = 0, tree_line_width: Annotated[float, "Stroke width (px) for the tree's branch lines. Default 2."] = 2.0, tree_node_size: Annotated[float, 'Area (px²) of the small filled circles drawn at each tip. Default 45. Setting tree_node_size=0 disables the tip-circle layer entirely.'] = 45, leader_line_width: Annotated[float, "Stroke width (px) for the dashed leader lines that connect each tip's branch endpoint to the strain row when the branch doesn't extend all the way to branch_max. Default 1.0. Setting leader_line_width=0 disables the leader-line layer entirely."] = 1.0, scale_bar: Annotated[bool, 'Off by default. When on, adds a small bar in the tree panel showing the branch-length scale. Tip-row alignment with the chart is preserved.'] = False, branch_length_units: Annotated[str | None, 'Used only when scale_bar is on and branch_length="div": the unit string pasted after the bar\'s numeric length (e.g. "substitutions/site"). None renders unitless. For branch_length="num_date" the label is always in years/months and this argument is ignored.'] = None, prune_tree_to_chart: Annotated[bool, "When off (default), tree tips not present in the chart's strain set are a fatal error. When on, those tips (and any internal nodes whose subtrees become empty) are dropped before drawing, with single-child internals collapsed into their kept child."] = False, prune_chart_to_tree: Annotated[bool, "When off (default), chart strains not present in the tree are a fatal error. When on, chart rows whose `chart_strain_field` value isn't a tree tip are filtered out before drawing."] = False, strict_version: Annotated[bool, 'When on (default), known-stale specs raise: Vega-Lite 5 or earlier, and Auspice JSON whose `version` is not v2. When off, those become warnings and parsing proceeds.'] = True, connect_leader_to_label: Annotated[bool, "Off (default): the chart's strain-axis labels are kept as the user wrote them and dashed leader lines stop at the tree panel's chart-facing edge. On: leaders extend all the way to the labels — which requires moving the labels off the chart's strain axis and into the tree panel, so the chart's strain-axis labels, ticks, axis line, and title are SUPPRESSED (any user-supplied `axis=...` is overridden) and replacement labels are rendered alongside the tree. Label widths are estimated; for crowded charts tune `strain_label_font_size` or `shift_tree_loc`."] = False, strain_label_font_size: Annotated[float, 'Font size (px) for the strain text labels rendered in the tree panel when `connect_leader_to_label` is on.'] = 10.0, strain_label_font_weight: Annotated[Literal['normal', 'bold'], 'Font weight for the strain text labels rendered in the tree panel when `connect_leader_to_label` is on.'] = 'normal', shift_tree_loc: Annotated[int, 'Pixels by which to shift the tree toward (positive) or away from (negative) the chart, by resizing the label strip inside the tree panel. Default 0. Has no effect when connect_leader_to_label is off; to set the gap between the tree and chart panels use `spacing`.'] = 0, color_tree_by: Annotated[str | None, 'Color the tree by an Auspice attribute. Pass a node_attrs key (e.g. "subclade"), or "genotype:<GENE>:<SITE>" / "genotype:<GENE>:<SITE1>,<SITE2>,..." (e.g. "genotype:HA1:158" or "genotype:HA1:158,189") to color by the inferred genotype state at a site or haplotype across sites. A categorical legend is drawn below the plot; missing values are gray. None (default) leaves the tree black.'] = None, tree_color_scale: Annotated[dict[str, str] | None, 'Hardcoded color scale that overrides the default coloring. Keys are category labels, values are colors (any Vega-Lite-compatible string — e.g. hex codes). The legend order follows the order keys appear here. The keys must match the tree\'s categories one-to-one (extra or missing keys are an error). "unknown" is always gray and must not be specified. For genotype/haplotype colorings, the category strings include the site number (e.g. "K158" or "K158/E189"); a mismatch error lists the actual tree categories. CLI form: "value1=#hex1,value2=#hex2,...".'] = None, tree_color_legend_format: Annotated[dict[str, Any] | None, 'Vega-Lite Legend properties to apply to the tree-coloring legend. Pass any subset of the keys at https://vega.github.io/vega-lite/docs/legend.html#properties as a Python dict (e.g. `{"orient": "left", "labelFontSize": 13, "titleFontSize": 13}`). Common keys: "orient" (default "bottom"), "direction", "columns", "padding", "offset", "labelFontSize", "titleFontSize". Smart default: when "orient" is "left" or "right" and you have not set "columns" or "direction", "columns" is forced to 1 so entries stack vertically. None (default) leaves Vega-Lite\'s defaults. Has no effect when `color_tree_by` is None. CLI form: a JSON object string (quote the whole argument), e.g. \'{"orient":"left","labelFontSize":13}\'.'] = None, tree_color_legend_show: Annotated[bool, 'Whether to render the tree-coloring legend. On (default) shows it. Off hides the legend entirely while keeping the tree colored. Has no effect when `color_tree_by` is None.'] = True, scale_bar_font_size: Annotated[float, "Font size (px) for the tree's scale bar label. Default 10. Has no effect when `scale_bar` is off."] = 10.0) -> None

Tree loading

load_auspice

load_auspice(source: str | Path | dict, *, tree_strain_field: str, branch_length: str = 'div', strict_version: bool = True) -> TreeNode

Load an Auspice JSON tree from a path or dict.

Parameters:

Name Type Description Default
source str | Path | dict

Path to an Auspice JSON file, or an already-parsed dict.

required
tree_strain_field str

Where on each tip to find the strain identifier. The literal string "name" selects the tip's top-level name field; any other value X selects node_attrs[X] (auto-unwrapping the Auspice {"value": ...} convention). Dotted paths are not accepted.

required
branch_length str

Which Auspice node attribute supplies branch lengths. "div" (default) reads node_attrs.div (a scalar absolute divergence from the root). "num_date" reads node_attrs.num_date.value (an absolute calendar position in years). In both cases the value is stored on each TreeNode.x and is used as-is by layout, segments, and pruning — they're branch-source-agnostic.

'div'
strict_version bool

When True (default), raise ValueError if the Auspice JSON's top-level version field does not start with "v2". With False the same case becomes a warnings.warn. A missing version field always warns and proceeds.

True

TreeNode dataclass

A node in a phylogenetic tree.

name carries the resolved strain identifier for tips (the value at tree_strain_field). For internal nodes, name is the Auspice top-level name field — internal-node identity isn't used for chart-strain matching.

x is divergence from the root (read from node_attrs.div). y is set by :func:layout and is the integer index of the node's tip (for tips) or the midpoint of its descendants' tip indices (for internal nodes).

node_attrs and branch_attrs carry the raw Auspice JSON dicts unchanged so downstream code (e.g. _color) can read them directly. node_attrs.div has already been consumed by _resolve_branch_length; node_attrs[X] is where things like subclade live; branch_attrs.mutations[<gene>] is where mutation strings like "N158K" live.

name instance-attribute

name: str

x instance-attribute

x: float

y class-attribute instance-attribute

y: float | None = None

children class-attribute instance-attribute

children: list['TreeNode'] = field(default_factory=list)

is_tip property

is_tip: bool