Skip to content

How Are Clade and Subclade Colors Handled

Elgin Akin edited this page Oct 16, 2026 · 1 revision

How are clade and subclade colors handled

What is this?

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.

Why does it matter?

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.

What do I do?

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"]
Loading

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.

1. How clades and subclades are called

  1. Nextclade calls them from HA. Rule nextclade runs Nextclade on each build's sequences, writing results/{subtype}/{segment}/nextclade.tsv. The HA datasets it uses are downloaded fresh at the start of every run by rule fetch_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).
  2. The HA calls are merged into every segment's metadata. Rule assign_clades runs scripts/assign_clades.py. It reads four columns from the HA Nextclade table (seqName, clade, subclade, legacy-clade) and left-joins them onto data/{subtype}/{segment}/metadata.tsv, matching the metadata's sample_ID to Nextclade's seqName (the FASTA header). The result is results/{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.
  3. QC comes from the segment's own Nextclade run. Rule merge_quality_metrics adds that segment's coverage, qc.overallScore and qc.overallStatus (script), which augur_filter uses to drop low-quality sequences (filter query; Step 3).
  4. Genome builds join the same HA table differently. Rule genome_clades left-joins all columns of results/{subtype}/ha/nextclade.tsv onto data/{subtype}/genome/metadata.tsv with csvtk, matching sequence_ID (not sample_ID) to seqName.
  5. Internal branches are inferred. augur traits (docs) reconstructs legacy-clade and subclade for the tree's internal nodes from the tips: rule annotate_traits (segments, with --confidence) and genome_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).

2. Where the colors come from

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).

3. The automatic subclade color sync

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:

  1. 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).
  2. It replaces the whole colored block of each colors.tsv with the official one, and moves subclades Nextstrain no longer colors into the grey block.
  3. It records the seasonal-flu commit and the sync date in config/subclade_colors_source.tsv.
  4. It creates the marker .run/subclade_colors.synced. Every export and genome_export job 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/ (the if ! line).
  • It changes tracked files. A sync that finds new colors rewrites config/*/colors.tsv and config/subclade_colors_source.tsv in your working copy. Committing them is a Tier 2 change: review git 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.

4. Sync or check by hand

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 commit

Running 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.

5. Problems and how to fix them

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.

How this page was checked

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.py and the three auspice_config.json files at that commit.
  • augur export writes only the listed subclades present in a tree, in file order, and no scale for legacy-clade: checked in auspice/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 subclade rows of colors.tsv: read in the script.
  • The sync rule: dry-run of the full pipeline; sync_subclade_colors run on its own (all three subtypes up to date); and run with GitHub made unreachable through a dead proxy, which logged the warning, finished successfully and left config/ unchanged.
  • --config sync_subclade_colors=false removes 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 export logs a warning for a subclade missing from colors.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 traits treats 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

Clone this wiki locally