Repository navigation
How Are Clade and Subclade Colors Handled
One page that follows a clade call from Nextclade to the color you see in Auspice: how clades and subclades are assigned, how they are merged into the metadata, where their colors come from, and how the subclade colors are kept in step with nextstrain.org.
Colors are how most people read a tree. If our colors differ from the official Nextstrain builds, or change between runs, readers can draw the wrong conclusion. Knowing where each color comes from tells you which differences are expected and which need fixing.
Read it once. Come back to Problems and how to fix them when something looks wrong. The day-to-day instructions are also in Step 5 §7: Subclade colors; this page repeats them, adds the clade side, and lists its sources.
flowchart LR
HA["HA sequences<br/>data/{subtype}/ha/"] --> NC["nextclade<br/>results/{subtype}/ha/nextclade.tsv"]
NC -->|"left join on sample ID"| MD["metadata of every<br/>segment + genome build"]
MD --> TR["augur traits<br/>legacy-clade, subclade"]
GH["nextstrain/seasonal-flu<br/>(GitHub)"] -->|"sync_subclade_colors"| CT["config/{subtype}/colors.tsv"]
TR --> EX["augur export v2"]
CT --> EX
EX --> AU["Auspice"]
Clade and subclade calls come from the HA segment only (top); subclade colors
come from the official Nextstrain builds (bottom). Both meet at augur export.
All code links point to commit
c4b289a
so the line numbers stay correct; check the current files if they have
changed since.
-
Nextclade calls them from HA. Rule
nextcladeruns Nextclade on each build's sequences, writingresults/{subtype}/{segment}/nextclade.tsv. The HA datasets it uses are downloaded fresh at the start of every run by rulefetch_hana_datasets, and their version tags are recorded in the run's provenance file (Step 4). How Nextclade decides a clade is described in Nextclade: Clade assignment; the influenza names themselves are maintained by influenza-clade-nomenclature. Each column is described in Nextclade: Analysis results (tabular). -
The HA calls are merged into every segment's metadata. Rule
assign_cladesrunsscripts/assign_clades.py. It reads four columns from the HA Nextclade table (seqName,clade,subclade,legacy-clade) and left-joins them ontodata/{subtype}/{segment}/metadata.tsv, matching the metadata'ssample_IDto Nextclade'sseqName(the FASTA header). The result isresults/{subtype}/{segment}/metadata.tsv. So a PB2 tree is labelled with the specimen's HA subclade, and a specimen with no HA sequence in the HA build gets no clade on any segment. The log (.run/logs/assign_clades/) reports how many rows matched, and warns if none did or if the row count changed. -
QC comes from the segment's own Nextclade run. Rule
merge_quality_metricsadds that segment'scoverage,qc.overallScoreandqc.overallStatus(script), whichaugur_filteruses to drop low-quality sequences (filter query; Step 3). -
Genome builds join the same HA table differently. Rule
genome_cladesleft-joins all columns ofresults/{subtype}/ha/nextclade.tsvontodata/{subtype}/genome/metadata.tsvwithcsvtk, matchingsequence_ID(notsample_ID) toseqName. -
Internal branches are inferred.
augur traits(docs) reconstructslegacy-cladeandsubcladefor the tree's internal nodes from the tips: ruleannotate_traits(segments, with--confidence) andgenome_traits(genomes, without it).
Which column is which in Auspice. The
auspice config
(same in all three subtypes) shows Nextclade's legacy-clade under the
title clade (e.g. 3C.2a1b.2a.2a.3a.1, V1A.3a.2), and subclade as
subclade (e.g. J.2, K, C.5.6). Trees open colored by subclade
(display_defaults).
Nextclade's own clade column is merged in but not shown, because it now
repeats the subclade (Glossary).
| Shown in Auspice as | Column | Colors come from | Same as nextstrain.org? |
|---|---|---|---|
| subclade | subclade |
config/{subtype}/colors.tsv, synced from Nextstrain (section 3) |
Yes, after a sync |
| clade | legacy-clade |
Nobody: no colors are listed, so Auspice picks them | No |
Subclade. export and genome_export pass colors.tsv to
augur export v2 --colors
(segments,
genomes;
augur export docs;
file format).
augur export writes into each tree only the listed subclades that occur in
that tree, in file order, which is the legend order. The colored rows are
copied from the official Nextstrain
seasonal-flu builds
(config/<lineage>/ha/auspice_config.json:
H3N2,
H1N1pdm,
B/Vic),
so a subclade has the same color in our trees as on
nextstrain.org. All other subclades
are listed in shades of grey, light to dark in nomenclature order.
A subclade that is in the tree but not in colors.tsv is colored by Auspice
from the grey ramp #BDC3C6 → #868992 and added to the bottom of the legend
(Auspice colorScale.ts,
createNonContinuousScaleFromProvidedScaleMap). The first of those greys,
#BDC3C6, is also the color of the first grey row in colors.tsv.
Clade. No colors are listed for legacy-clade, so Auspice builds the
scale itself
(colorScale.ts,
getDiscreteValuesFromTree and createDiscreteScale): it orders the clades
by how many tree nodes carry them, most common first (ties alphabetical,
sortedDomain.js),
and assigns colors from a fixed palette chosen by the number of clades
(globals.js,
colors). So a clade's color can differ between segments, between runs, and
from nextstrain.org. This is expected. Fixed clade colors would need
legacy-clade rows in colors.tsv, but the sync keeps only subclade rows
(read_local) and would delete
them on its next run. So a clade palette needs a change to
scripts/sync_subclade_colors.py first (Tier 2).
Why it is needed. Nextstrain picks subclade colors by hand when a subclade is designated, and sometimes recolors the existing subclades at the same time (every H3N2 color changed when K was added in October 2025). Our HA Nextclade datasets are downloaded fresh every run, so a new subclade shows up in our builds right away. Its official color only appears after a sync.
How it works. The rule
sync_subclade_colors
(workflow/snakemake_rules/colors.smk) runs
scripts/sync_subclade_colors.py
once per run, before any tree is exported:
- It downloads each lineage's official subclade colors from GitHub
(
raw.githubusercontent.com) and looks up the seasonal-flu commit they came from (api.github.com). - It replaces the whole colored block of each
colors.tsvwith the official one, and moves subclades Nextstrain no longer colors into the grey block. - It records the seasonal-flu commit and the sync date in
config/subclade_colors_source.tsv. - It creates the marker
.run/subclade_colors.synced. Everyexportandgenome_exportjob waits for this marker (segments, genomes), so all 27 trees are exported with the colors just synced. Snakemake deletes the marker after the last export (temp()), so the next build syncs again.
What is printed goes to .run/logs/sync_subclade_colors/sync_subclade_colors.log.
Each subtype shows either up to date or one line per change (+ new color,
~ recolored, > moved to grey, - removed).
Good to know:
- No login is needed. The sync downloads public files anonymously. It does not use your Nextstrain or GitHub account, only an internet connection.
- It runs only when something is exported. If every tree is already up to date, Snakemake has nothing to export and skips the sync.
-
A failed sync never stops the build. If GitHub cannot be reached, the
rule logs a warning and the trees are exported with the colors already in
config/(theif !line). -
It changes tracked files. A sync that finds new colors rewrites
config/*/colors.tsvandconfig/subclade_colors_source.tsvin your working copy. Committing them is a Tier 2 change: reviewgit diff config/after the run, then commit.
colors.tsv holds data rows only (no header or # comment lines); the grey
block starts at the first #BDC3C6 row. Hand-picked colors in the colored
block are replaced on the next sync.
snakemake --cores 1 sync_subclade_colors # sync now, without building
snakemake --cores 8 --config sync_subclade_colors=false # build without syncing
python scripts/sync_subclade_colors.py --check --auspice-dir auspice # report only; changes nothing
git diff config/ # review, then commitRunning sync_subclade_colors by name leaves the marker in place, so the
next build re-exports every tree. That is expected and harmless. All config
options are listed in Step 2.
| What you see | Why | What to do |
|---|---|---|
WARNING: could not sync subclade colours in the sync log, often after URLError or Connection refused
|
No internet, a firewall or proxy blocks GitHub, or GitHub is down | Nothing breaks: the trees use the existing colors. When you are online, run snakemake --cores 1 sync_subclade_colors, then rerun the build so the trees are re-exported with any new colors |
The same warning after a Python traceback that is not a network error (KeyError, ERROR: no 'subclade' scale ...) |
Nextstrain changed the layout of its auspice_config.json, or the script has a bug |
Tell the maintainer, with the log. Until it is fixed, build with --config sync_subclade_colors=false to skip the failing step |
| The build pauses for a minute or two before the first export | The network is slow; each GitHub request waits up to 30 s before giving up (timeout=30) |
Wait, or skip the sync for that run with --config sync_subclade_colors=false
|
config/subclade_colors_source.tsv shows master and unknown instead of a commit and date |
GitHub's anonymous API limit (60 requests an hour per IP address) was reached, typically on a shared server | The colors themselves synced correctly. Run the sync again after an hour to fill in the commit |
One subtype's colors.tsv changed but subclade_colors_source.tsv did not |
The sync failed partway through (for example, the network dropped after H3N2) | Run snakemake --cores 1 sync_subclade_colors again once online; it completes the rest and updates the record |
Unexpected changes to config/*/colors.tsv in git status after a run |
The sync found new official colors. This is the sync working | Review git diff config/ and commit it. To undo it instead, git checkout config/ and rerun with --config sync_subclade_colors=false
|
| Every tree re-exports even though no data changed | The sync marker was left by a by-hand sync, or sync_subclade_colors was switched on or off since the last run (Snakemake reruns a rule whose inputs change) |
Expected; let it finish. It happens once |
| A subclade is grey at the bottom of the legend | It is not in colors.tsv, usually because Nextstrain has not colored it yet |
See below |
| A clade (not subclade) has a different color than last run, or than on nextstrain.org | Clade colors are picked by Auspice from how common each clade is in that tree (section 2) | Expected; see section 2 |
No rows matched an HA clade in .run/logs/assign_clades/
|
The metadata sample_ID does not match the HA FASTA header |
Check the source naming (Step 1) |
If a subclade has no color. The build still finishes. augur export
writes a warning to .run/logs/export/ (or .run/logs/genome_export/), and
Auspice shows that subclade in grey at the bottom of the legend, in the same
light grey as the oldest listed subclade. Check with
python scripts/sync_subclade_colors.py --check --auspice-dir auspice. If
nextstrain.org has not colored it yet either, it is grey there too: give it a
fixed grey with
python scripts/sync_subclade_colors.py --subtypes <subtype> --add-grey <subclade>,
or wait for Nextstrain to color it. The next build picks the color up
automatically.
Written on 2026-10-16 against commit c4b289a. To be transparent about what
each statement rests on:
Checked against the code or by running it
- Clade calling, merging and trait columns: read in
segments.smk,genomes.smk,assign_clades.py,merge_quality_metrics.pyand the threeauspice_config.jsonfiles at that commit. -
augur exportwrites only the listed subclades present in a tree, in file order, and no scale forlegacy-clade: checked inauspice/vic/ha.json(exported 2026-10-15), whose subclade scale holds the 4 listed subclades found in that tree and whose clade coloring has no scale. - Auspice's grey ramp for unlisted values and its frequency-ordered palette
for unscaled clades: read in the Auspice source on
master(2026-10-16), linked above. - The sync keeps only
subcladerows ofcolors.tsv: read in the script. - The sync rule: dry-run of the full pipeline;
sync_subclade_colorsrun on its own (all three subtypesup to date); and run with GitHub made unreachable through a dead proxy, which logged the warning, finished successfully and leftconfig/unchanged. -
--config sync_subclade_colors=falseremoves the rule from the dry-run. - All external links returned the expected page on 2026-10-16.
Taken from elsewhere, not re-checked here
- That every H3N2 color changed when K was added (October 2025): carried over from Step 5 §7.
- That
augur exportlogs a warning for a subclade missing fromcolors.tsv: carried over from Step 5 §7. - GitHub's 60-requests-an-hour limit: GitHub's documentation, linked above; not tested.
- The slow-network delay, the rate-limit fallback (
master/unknown) and the partial-sync mismatch: read from the script (fallback, record written last), not reproduced. - How
augur traitstreats a specimen with no clade call: not checked. - How Nextclade assigns clades: Nextclade's documentation, linked above; not checked here.
Related pages: Step 5 §7: Subclade colors · Snakemake & Scripts Reference · Step 2: Config options · Step 3: Filtering & QC · Glossary
Pekosz Lab Seasonal Influenza Nextstrain · Repository · Builds · Never post GISAID or unpublished JHH data on this wiki (why) · Found an error? Fix it in the same PR as your code (how).
Written with support from Opus 5.5.
Start here
The pipeline, in order
- Source Data Preparation
- Running the Pipeline
- Filtering & QC
- Reports & Outputs
- Reviewing & Publishing
🧪 Tutorials
🤖 Coding with Agents
📚 Reference