tree-annotated-plot 0.1.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tree_annotated_plot-0.2.1/CHANGELOG.md +65 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/CLAUDE.md +5 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/PKG-INFO +5 -1
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/README.md +4 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/docs/examples.md +166 -2
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/pyproject.toml +1 -1
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/scripts/generate_docs_assets.py +103 -3
- tree_annotated_plot-0.2.1/src/tree_annotated_plot/_color.py +526 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/src/tree_annotated_plot/_config.py +99 -6
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/src/tree_annotated_plot/_plot.py +451 -79
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/src/tree_annotated_plot/_tree.py +83 -10
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/src/tree_annotated_plot/cli.py +131 -0
- tree_annotated_plot-0.2.1/tests/test_appearance_tuning.py +797 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_cli.py +4 -0
- tree_annotated_plot-0.2.1/tests/test_color_tree.py +800 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_introspection.py +68 -1
- tree_annotated_plot-0.2.1/tests/test_label_connection.py +559 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_plot.py +67 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_style.py +7 -2
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_tree_location.py +5 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/.github/workflows/docs.yml +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/.github/workflows/release.yml +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/.github/workflows/tests.yml +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/.gitignore +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/LICENSE +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/docs/cli.md +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/docs/index.md +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/docs/python-api.md +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/examples/fetch_auspice_data.py +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/examples/flu-seqneut-2025to2026_titer_charts.py +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/examples/synthetic_example.py +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/mkdocs.yml +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/scripts/build_docs.sh +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/scripts/check.sh +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/src/tree_annotated_plot/__init__.py +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_branch_length.py +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_chart_loader.py +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_examples_run.py +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_plot_config.py +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_real_data.py +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_reconciliation.py +0 -0
- {tree_annotated_plot-0.1.0 → tree_annotated_plot-0.2.1}/tests/test_scale_bar.py +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.1] - 2026-05-06
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Apply tree-tip ordering to chart axes that use untyped Altair
|
|
13
|
+
shorthand (`alt.Y("strain")` without a `:N` / `:O` type suffix).
|
|
14
|
+
Previously the sort override was silently skipped, so the chart
|
|
15
|
+
rendered in data order instead of tree order.
|
|
16
|
+
- An internal consistency check now raises if the spec-level walk
|
|
17
|
+
and the live-object walk over the user's chart ever disagree on
|
|
18
|
+
the number of strain-axis encodings, so silent skips like the
|
|
19
|
+
one above can't recur in another shape.
|
|
20
|
+
|
|
21
|
+
## [0.2.0] - 2026-05-06
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- `connect_leader_to_label` (default `False`): extends each strain's
|
|
26
|
+
dashed leader line all the way to its text label. When on, the
|
|
27
|
+
chart's strain-axis labels are suppressed and replacement labels
|
|
28
|
+
are rendered alongside the tree on its chart-facing edge.
|
|
29
|
+
- `strain_label_font_size` (default `10`), `strain_label_font_weight`
|
|
30
|
+
(default `"normal"`), and `shift_tree_loc` (default `0`) for tuning
|
|
31
|
+
the size, weight, and placement of the connected labels.
|
|
32
|
+
- `color_tree_by` (default `None`): color the tree's branches and tip
|
|
33
|
+
circles by an Auspice node attribute (e.g. `"subclade"`) or by the
|
|
34
|
+
inferred genotype state at one or more sites
|
|
35
|
+
(e.g. `"genotype:HA1:158"` or `"genotype:HA1:158,189"`). Colors,
|
|
36
|
+
category ordering, and the bottom-of-plot legend match the
|
|
37
|
+
Nextstrain view of the same tree.
|
|
38
|
+
- `tree_color_scale` (default `None`): override the default coloring
|
|
39
|
+
with an explicit `{category: color}` mapping. Keys must match the
|
|
40
|
+
tree's categories one-to-one and the legend order follows the
|
|
41
|
+
user's key order. CLI form: `"value1=#hex1,value2=#hex2,..."`.
|
|
42
|
+
- `tree_color_legend_format` (default `None`): pass any subset of
|
|
43
|
+
Vega-Lite's
|
|
44
|
+
[Legend properties](https://vega.github.io/vega-lite/docs/legend.html#properties)
|
|
45
|
+
as a dict to style the tree's color legend (`orient`, `direction`,
|
|
46
|
+
`columns`, `padding`, `labelFontSize`, `titleFontSize`, …). When
|
|
47
|
+
`orient` is `"left"` or `"right"` and the user has not set
|
|
48
|
+
`columns` or `direction`, `columns=1` is forced so entries stack
|
|
49
|
+
vertically. CLI form: a JSON object string.
|
|
50
|
+
- `tree_color_legend_show` (default `True`): set to `False` to hide
|
|
51
|
+
the tree's color legend entirely while still coloring the tree.
|
|
52
|
+
- `scale_bar_font_size` (default `10`): font size for the tree's
|
|
53
|
+
scale bar label.
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- Default `tree_line_width` bumped from `1.5` to `2`, default
|
|
58
|
+
`tree_node_size` from `28` to `45`. Tree branch lines and tip
|
|
59
|
+
circles are now drawn at full opacity. The thicker / fuller
|
|
60
|
+
defaults read better when the tree is colored (the prior values
|
|
61
|
+
were tuned for unicolor black trees).
|
|
62
|
+
|
|
63
|
+
## [0.1.0] - 2026-05-04
|
|
64
|
+
|
|
65
|
+
Initial release.
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
- **Keep CLAUDE.md, README.md, and the docs site updated** when changing the
|
|
4
4
|
code. `CLAUDE.md` describes programming conventions; `README.md` describes
|
|
5
5
|
basic use; `docs/` is the user-facing reference. Don't let them drift.
|
|
6
|
+
- **Record user-facing changes in `CHANGELOG.md`** under the `## [Unreleased]`
|
|
7
|
+
section as you make them — new parameters, behavior changes, removed
|
|
8
|
+
features, bug fixes — in [Keep a Changelog](https://keepachangelog.com/)
|
|
9
|
+
format. At release time, `## [Unreleased]` is renamed to
|
|
10
|
+
`## [X.Y.Z] - YYYY-MM-DD` and a fresh `## [Unreleased]` is created.
|
|
6
11
|
- **Single source of truth — `pyproject.toml`**: canonical for dependencies,
|
|
7
12
|
supported Python version, build config, tool settings. Don't restate any of
|
|
8
13
|
these in prose; refer to `pyproject.toml`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tree-annotated-plot
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Annotate the axis of an Altair / Vega-Lite plot with a phylogenetic tree.
|
|
5
5
|
Project-URL: Documentation, https://jbloomlab.github.io/tree-annotated-plot/
|
|
6
6
|
Project-URL: Homepage, https://github.com/jbloomlab/tree-annotated-plot
|
|
@@ -80,6 +80,10 @@ pip install git+https://github.com/jbloomlab/tree-annotated-plot.git
|
|
|
80
80
|
|
|
81
81
|
For a development checkout, see [Installation (development)](#installation-development) below.
|
|
82
82
|
|
|
83
|
+
## Changelog
|
|
84
|
+
|
|
85
|
+
See [CHANGELOG.md](CHANGELOG.md) for the version history.
|
|
86
|
+
|
|
83
87
|
## Notes for developing the package
|
|
84
88
|
|
|
85
89
|
### Installation (development)
|
|
@@ -29,6 +29,10 @@ pip install git+https://github.com/jbloomlab/tree-annotated-plot.git
|
|
|
29
29
|
|
|
30
30
|
For a development checkout, see [Installation (development)](#installation-development) below.
|
|
31
31
|
|
|
32
|
+
## Changelog
|
|
33
|
+
|
|
34
|
+
See [CHANGELOG.md](CHANGELOG.md) for the version history.
|
|
35
|
+
|
|
32
36
|
## Notes for developing the package
|
|
33
37
|
|
|
34
38
|
### Installation (development)
|
|
@@ -97,8 +97,170 @@ With the tree panel added by `tree-annotated-plot`:
|
|
|
97
97
|
The strain axis is on `y`, so `tree_annotated_plot.plot` auto-picks
|
|
98
98
|
the **vertical layout** (`tree_location` defaults to `"left"` on a
|
|
99
99
|
y-encoded strain): result is an `HConcatChart` with the tree on the
|
|
100
|
-
left
|
|
101
|
-
|
|
100
|
+
left and a centered scale bar at the bottom of the tree panel. The
|
|
101
|
+
chart's natural strain-axis labels are kept exactly as the
|
|
102
|
+
chart-builder wrote them (fonts, ticks, axis title, and all), and the
|
|
103
|
+
tree's dashed leader lines stop at the tree panel's chart-facing
|
|
104
|
+
edge.
|
|
105
|
+
|
|
106
|
+
The H3N2 example above is rendered with `color_tree_by="subclade"`,
|
|
107
|
+
which colors the tree's branches and tip circles by the
|
|
108
|
+
`node_attrs.subclade` value at each node and adds a categorical legend
|
|
109
|
+
below the plot. See "Color the tree" below for the full set of options.
|
|
110
|
+
|
|
111
|
+
### Optional: connect leaders all the way to the labels
|
|
112
|
+
|
|
113
|
+
If you'd prefer the dashed leaders to run flush into the strain
|
|
114
|
+
labels themselves (with no break between tip and label), set
|
|
115
|
+
`connect_leader_to_label=True`. This involves moving the labels off
|
|
116
|
+
the chart's natural axis and into the tree panel, with a few
|
|
117
|
+
trade-offs to be aware of:
|
|
118
|
+
|
|
119
|
+
- The chart's strain-axis is replaced: any labels, ticks, title,
|
|
120
|
+
or custom `axis=...` you set on that encoding are dropped, and
|
|
121
|
+
replacement labels are rendered alongside the tree.
|
|
122
|
+
- Label widths are estimated, not measured exactly, so layout may
|
|
123
|
+
need tuning. The two main knobs are `strain_label_font_size`
|
|
124
|
+
(default 10) and `shift_tree_loc` (a manual pixel offset that
|
|
125
|
+
moves the tree closer to the labels).
|
|
126
|
+
|
|
127
|
+
The example below turns on label connection, shrinks the labels to
|
|
128
|
+
9 pt, and uses `shift_tree_loc=60` to bring the tree flush against
|
|
129
|
+
them:
|
|
130
|
+
|
|
131
|
+

|
|
132
|
+
|
|
133
|
+
[Open the interactive chart in a new tab →](charts/h3n2_combined_label_connect.html){target="_blank"}
|
|
134
|
+
|
|
135
|
+
CLI flags: `--connect-leader-to-label --strain-label-font-size 9
|
|
136
|
+
--shift-tree-loc 60`. In Python:
|
|
137
|
+
`connect_leader_to_label=True, strain_label_font_size=9, shift_tree_loc=60`.
|
|
138
|
+
|
|
139
|
+
### Color the tree
|
|
140
|
+
|
|
141
|
+
Pass `color_tree_by` to color the tree's branches and tip circles by
|
|
142
|
+
any property the Auspice JSON exposes — broadly, anything that
|
|
143
|
+
appears in the "Color By" dropdown on the Nextstrain view of the same
|
|
144
|
+
tree. Two forms are supported:
|
|
145
|
+
|
|
146
|
+
- A named attribute, e.g. `color_tree_by="subclade"` (used in the
|
|
147
|
+
example above). Common alternatives include `"clade_membership"`,
|
|
148
|
+
`"region"`, `"country"` — whichever the tree provides.
|
|
149
|
+
- A genotype at one or more sites in a gene. For a single site,
|
|
150
|
+
`color_tree_by="genotype:HA1:158"` colors each tip by the amino
|
|
151
|
+
acid at HA1 site 158. A comma-separated list gives a haplotype:
|
|
152
|
+
`"genotype:HA1:158,189"`. Sites that don't vary in the tree are
|
|
153
|
+
dropped from the haplotype label.
|
|
154
|
+
|
|
155
|
+
Colors match what you'd see on the Nextstrain view of the same tree —
|
|
156
|
+
either from the JSON's palette information when the build provides it,
|
|
157
|
+
or from the same default palette Auspice uses when it doesn't.
|
|
158
|
+
Categories are ordered by descending frequency in both cases. Missing
|
|
159
|
+
values render in gray, and the legend is drawn at the bottom of the
|
|
160
|
+
combined plot.
|
|
161
|
+
|
|
162
|
+
The example below colors the same H3N2 chart by genotype at HA1
|
|
163
|
+
site 158, which has two mutations in the tree (`N158K`, `N158D`) and
|
|
164
|
+
so renders three states (N, K, D):
|
|
165
|
+
|
|
166
|
+

|
|
167
|
+
|
|
168
|
+
[Open the interactive chart in a new tab →](charts/h3n2_combined_genotype_158.html){target="_blank"}
|
|
169
|
+
|
|
170
|
+
CLI flag: `--color-tree-by genotype:HA1:158`. In Python:
|
|
171
|
+
`color_tree_by="genotype:HA1:158"`.
|
|
172
|
+
|
|
173
|
+
### Customizing the colors and legend
|
|
174
|
+
|
|
175
|
+
Four optional knobs let you override the defaults:
|
|
176
|
+
|
|
177
|
+
- `tree_color_scale` — supply your own `{category: color}` mapping
|
|
178
|
+
instead of the Auspice palette. Keys must match the tree's
|
|
179
|
+
categories one-to-one (extras or misses are an error). The legend
|
|
180
|
+
order follows the order of keys you pass. `"unknown"` is always
|
|
181
|
+
gray and must not be specified.
|
|
182
|
+
- `tree_color_legend_format` — pass any subset of Vega-Lite's
|
|
183
|
+
[Legend properties](https://vega.github.io/vega-lite/docs/legend.html#properties)
|
|
184
|
+
as a dict to style the legend (`orient`, `direction`, `columns`,
|
|
185
|
+
`padding`, `offset`, `labelFontSize`, `titleFontSize`, …). Smart
|
|
186
|
+
default: when `orient` is `"left"` or `"right"` and you have not
|
|
187
|
+
set `columns` or `direction`, entries stack vertically
|
|
188
|
+
(`columns=1` is forced).
|
|
189
|
+
- `tree_color_legend_show` — set to `False` to hide the legend
|
|
190
|
+
entirely while keeping the tree colored.
|
|
191
|
+
- `scale_bar_font_size` — font size for the scale bar's label.
|
|
192
|
+
|
|
193
|
+
The exact category strings depend on the form of `color_tree_by`:
|
|
194
|
+
|
|
195
|
+
| `color_tree_by` | Example category strings |
|
|
196
|
+
|---|---|
|
|
197
|
+
| node attribute (e.g. `"subclade"`) | `"K"`, `"J.2"`, `"J.2.4"` |
|
|
198
|
+
| `"genotype:HA1:158"` (single site) | `"K158"`, `"R158"`, `"E158"` |
|
|
199
|
+
| `"genotype:HA1:158,189"` (both sites vary) | `"K158/E189"`, `"R158/E189"` |
|
|
200
|
+
| `"genotype:HA1:158,189"` (189 invariant) | `"K158"`, `"R158"` (invariant site dropped) |
|
|
201
|
+
|
|
202
|
+
If you pass keys that don't match, the error message lists the
|
|
203
|
+
tree's actual categories so you can copy them.
|
|
204
|
+
|
|
205
|
+
The H3N2 example below puts all four knobs to work: an explicit
|
|
206
|
+
6-color palette (a colorblind-safe Okabe–Ito-inspired set) ordered
|
|
207
|
+
K → J.2.4 → J.2.3 → J.2.2 → J.2 → G.1.3.1, the legend moved to the
|
|
208
|
+
**left** of the combined plot at 14-pt, and a matching 14-pt
|
|
209
|
+
scale-bar label.
|
|
210
|
+
|
|
211
|
+

|
|
212
|
+
|
|
213
|
+
[Open the interactive chart in a new tab →](charts/h3n2_combined_custom_colors.html){target="_blank"}
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
out = tree_annotated_plot.plot(
|
|
217
|
+
"examples/data/flu-seqneut-2025to2026_H3N2.json",
|
|
218
|
+
chart,
|
|
219
|
+
chart_strain_field="axis_label",
|
|
220
|
+
tree_strain_field="derived_haplotype",
|
|
221
|
+
branch_length="div",
|
|
222
|
+
tree_size=140,
|
|
223
|
+
scale_bar=True,
|
|
224
|
+
branch_length_units="substitutions",
|
|
225
|
+
color_tree_by="subclade",
|
|
226
|
+
tree_color_scale={
|
|
227
|
+
"K": "#0072B2",
|
|
228
|
+
"J.2.4": "#009E73",
|
|
229
|
+
"J.2.3": "#D55E00",
|
|
230
|
+
"J.2.2": "#CC79A7",
|
|
231
|
+
"J.2": "#56B4E9",
|
|
232
|
+
"G.1.3.1": "#E69F00",
|
|
233
|
+
},
|
|
234
|
+
tree_color_legend_format={
|
|
235
|
+
"orient": "left",
|
|
236
|
+
"labelFontSize": 14,
|
|
237
|
+
"titleFontSize": 14,
|
|
238
|
+
},
|
|
239
|
+
scale_bar_font_size=14,
|
|
240
|
+
)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`--tree-color-scale` on the CLI is a comma-separated list of
|
|
244
|
+
`key=color` pairs and `--tree-color-legend-format` is a JSON object
|
|
245
|
+
string (quote the whole argument in both cases so the shell doesn't
|
|
246
|
+
interpret `#`, braces, or quotes):
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
tree-annotated-plot \
|
|
250
|
+
--tree examples/data/flu-seqneut-2025to2026_H3N2.json \
|
|
251
|
+
--chart examples/data/flu-seqneut-2025to2026_H3N2_titers.json \
|
|
252
|
+
--chart-strain-field axis_label \
|
|
253
|
+
--tree-strain-field derived_haplotype \
|
|
254
|
+
--branch-length div \
|
|
255
|
+
--tree-size 140 \
|
|
256
|
+
--scale-bar \
|
|
257
|
+
--branch-length-units substitutions \
|
|
258
|
+
--color-tree-by subclade \
|
|
259
|
+
--tree-color-scale "K=#0072B2,J.2.4=#009E73,J.2.3=#D55E00,J.2.2=#CC79A7,J.2=#56B4E9,G.1.3.1=#E69F00" \
|
|
260
|
+
--tree-color-legend-format '{"orient":"left","labelFontSize":14,"titleFontSize":14}' \
|
|
261
|
+
--scale-bar-font-size 14 \
|
|
262
|
+
--output examples/data/h3n2_combined_custom_colors.html
|
|
263
|
+
```
|
|
102
264
|
|
|
103
265
|
### Reproduce — command line
|
|
104
266
|
|
|
@@ -114,6 +276,7 @@ tree-annotated-plot \
|
|
|
114
276
|
--tree-size 140 \
|
|
115
277
|
--scale-bar \
|
|
116
278
|
--branch-length-units substitutions \
|
|
279
|
+
--color-tree-by subclade \
|
|
117
280
|
--output examples/data/h3n2_combined.json
|
|
118
281
|
```
|
|
119
282
|
|
|
@@ -131,6 +294,7 @@ out = tree_annotated_plot.plot(
|
|
|
131
294
|
tree_size=140,
|
|
132
295
|
scale_bar=True,
|
|
133
296
|
branch_length_units="substitutions",
|
|
297
|
+
color_tree_by="subclade",
|
|
134
298
|
)
|
|
135
299
|
```
|
|
136
300
|
|
|
@@ -110,9 +110,7 @@ def _render_kikawa() -> None:
|
|
|
110
110
|
# Render the bare chart (no tree) so the docs page can show what
|
|
111
111
|
# the chart looks like before tree-annotated-plot wraps it.
|
|
112
112
|
_save_pair(chart, f"{basename}_chart_only")
|
|
113
|
-
|
|
114
|
-
DATA_DIR / f"flu-seqneut-2025to2026_{subtype}.json",
|
|
115
|
-
chart,
|
|
113
|
+
plot_kwargs = dict(
|
|
116
114
|
chart_strain_field="axis_label",
|
|
117
115
|
tree_strain_field="derived_haplotype",
|
|
118
116
|
branch_length="div",
|
|
@@ -120,8 +118,110 @@ def _render_kikawa() -> None:
|
|
|
120
118
|
scale_bar=True,
|
|
121
119
|
branch_length_units="substitutions",
|
|
122
120
|
)
|
|
121
|
+
if subtype == "H3N2":
|
|
122
|
+
# Color H3N2 by subclade so the docs SVG matches what users see
|
|
123
|
+
# on Nextstrain. The Auspice JSON's meta.colorings.subclade has
|
|
124
|
+
# no `scale` defined, so colors come from the default palette.
|
|
125
|
+
plot_kwargs["color_tree_by"] = "subclade"
|
|
126
|
+
out = tree_annotated_plot.plot(
|
|
127
|
+
DATA_DIR / f"flu-seqneut-2025to2026_{subtype}.json",
|
|
128
|
+
chart,
|
|
129
|
+
**plot_kwargs,
|
|
130
|
+
)
|
|
123
131
|
_save_pair(out, f"{basename}_combined")
|
|
124
132
|
|
|
133
|
+
# H3N2 again, with `connect_leader_to_label=True` and a 9-point label
|
|
134
|
+
# font: opt-in label connection where leaders run flush into the
|
|
135
|
+
# labels rendered alongside the tree (the default keeps the chart's
|
|
136
|
+
# natural strain-axis labels untouched).
|
|
137
|
+
h3n2_chart = builder.make_chart(
|
|
138
|
+
subtype="H3N2",
|
|
139
|
+
chart_type="iqr",
|
|
140
|
+
titers=titers,
|
|
141
|
+
viruses=viruses,
|
|
142
|
+
metadata=metadata,
|
|
143
|
+
all_cohorts=all_cohorts,
|
|
144
|
+
)
|
|
145
|
+
out = tree_annotated_plot.plot(
|
|
146
|
+
DATA_DIR / "flu-seqneut-2025to2026_H3N2.json",
|
|
147
|
+
h3n2_chart,
|
|
148
|
+
chart_strain_field="axis_label",
|
|
149
|
+
tree_strain_field="derived_haplotype",
|
|
150
|
+
branch_length="div",
|
|
151
|
+
tree_size=140,
|
|
152
|
+
scale_bar=True,
|
|
153
|
+
branch_length_units="substitutions",
|
|
154
|
+
connect_leader_to_label=True,
|
|
155
|
+
strain_label_font_size=9,
|
|
156
|
+
shift_tree_loc=60,
|
|
157
|
+
color_tree_by="subclade",
|
|
158
|
+
)
|
|
159
|
+
_save_pair(out, "h3n2_combined_label_connect")
|
|
160
|
+
|
|
161
|
+
# H3N2 once more, colored by genotype at HA1 site 158: same chart and
|
|
162
|
+
# default layout as `h3n2_combined`, with `color_tree_by` switched to
|
|
163
|
+
# the genotype form. Site 158 has two mutations (N158K, N158D) in the
|
|
164
|
+
# tree, so this renders three states (N, K, D).
|
|
165
|
+
h3n2_chart_genotype = builder.make_chart(
|
|
166
|
+
subtype="H3N2",
|
|
167
|
+
chart_type="iqr",
|
|
168
|
+
titers=titers,
|
|
169
|
+
viruses=viruses,
|
|
170
|
+
metadata=metadata,
|
|
171
|
+
all_cohorts=all_cohorts,
|
|
172
|
+
)
|
|
173
|
+
out = tree_annotated_plot.plot(
|
|
174
|
+
DATA_DIR / "flu-seqneut-2025to2026_H3N2.json",
|
|
175
|
+
h3n2_chart_genotype,
|
|
176
|
+
chart_strain_field="axis_label",
|
|
177
|
+
tree_strain_field="derived_haplotype",
|
|
178
|
+
branch_length="div",
|
|
179
|
+
tree_size=140,
|
|
180
|
+
scale_bar=True,
|
|
181
|
+
branch_length_units="substitutions",
|
|
182
|
+
color_tree_by="genotype:HA1:158",
|
|
183
|
+
)
|
|
184
|
+
_save_pair(out, "h3n2_combined_genotype_158")
|
|
185
|
+
|
|
186
|
+
# H3N2 once more, demonstrating all four appearance-tuning knobs:
|
|
187
|
+
# an explicit `tree_color_scale` (Okabe-Ito-inspired colorblind-safe
|
|
188
|
+
# palette, ordered K, J.2.4, J.2.3, J.2.2, J.2, G.1.3.1), a 14-pt
|
|
189
|
+
# legend on the left, and a 14-pt scale-bar label.
|
|
190
|
+
h3n2_chart_custom = builder.make_chart(
|
|
191
|
+
subtype="H3N2",
|
|
192
|
+
chart_type="iqr",
|
|
193
|
+
titers=titers,
|
|
194
|
+
viruses=viruses,
|
|
195
|
+
metadata=metadata,
|
|
196
|
+
all_cohorts=all_cohorts,
|
|
197
|
+
)
|
|
198
|
+
out = tree_annotated_plot.plot(
|
|
199
|
+
DATA_DIR / "flu-seqneut-2025to2026_H3N2.json",
|
|
200
|
+
h3n2_chart_custom,
|
|
201
|
+
chart_strain_field="axis_label",
|
|
202
|
+
tree_strain_field="derived_haplotype",
|
|
203
|
+
branch_length="div",
|
|
204
|
+
tree_size=140,
|
|
205
|
+
scale_bar=True,
|
|
206
|
+
branch_length_units="substitutions",
|
|
207
|
+
color_tree_by="subclade",
|
|
208
|
+
tree_color_scale={
|
|
209
|
+
"K": "#0072B2",
|
|
210
|
+
"J.2.4": "#009E73",
|
|
211
|
+
"J.2.3": "#D55E00",
|
|
212
|
+
"J.2.2": "#CC79A7",
|
|
213
|
+
"J.2": "#56B4E9",
|
|
214
|
+
"G.1.3.1": "#E69F00",
|
|
215
|
+
},
|
|
216
|
+
tree_color_legend_format={
|
|
217
|
+
"orient": "left",
|
|
218
|
+
"labelFontSize": 14,
|
|
219
|
+
"titleFontSize": 14,
|
|
220
|
+
},
|
|
221
|
+
scale_bar_font_size=14,
|
|
222
|
+
)
|
|
223
|
+
_save_pair(out, "h3n2_combined_custom_colors")
|
|
224
|
+
|
|
125
225
|
|
|
126
226
|
def main() -> None:
|
|
127
227
|
"""Render every example to SVG + interactive HTML under `docs/`."""
|