Skip to content

Step 5 Reviewing and Publishing Builds

Elgin Akin edited this page Oct 16, 2026 · 5 revisions

Step 5: Reviewing & Publishing Builds

What is this?

Looking at every tree yourself, then uploading it to Nextstrain by hand.

Why does it matter?

A tree on nextstrain.org is read by people who trust it. Problems a computer cannot judge (a strange clade, a sample in the wrong place, a field that should not be visible) are caught here.

What do I do?

Open each build locally, work through the checklist, upload to the private group, check online, and only then (with approval) publish.

Important

Uploads are always manual: never part of a Snakemake rule, a scheduled job, or an AI agent's work, public or private.

flowchart TD
    A["Run finished: SUCCESS"] --> B["Open builds locally<br/>auspice view / auspice.us"]
    B --> C{"Review checklist<br/>all OK?"}
    C -->|no| D["Investigate:<br/>Step 3, maintainer"] --> A
    C -->|yes| E["Upload to PRIVATE group<br/>PekoszLab"]
    E --> F["Check online"]
    F --> G{"Public release wanted?"}
    G -->|no| H["Done: record the upload"]
    G -->|yes| I{"PI approval +<br/>GISAID acknowledgement<br/>in description.md?"}
    I -->|no| H
    I -->|yes| J["Upload to PUBLIC group<br/>PekoszLab-Public"] --> H
Loading

Every build goes private first. Public release needs a person's approval and the GISAID acknowledgement.

1. Open the builds locally

Auspice is the tree viewer behind nextstrain.org. Each build is a JSON file it reads.

auspice view --datasetDir auspice/h1n1     # then open http://localhost:4000
auspice view --datasetDir auspice/h3n2
auspice view --datasetDir auspice/vic

Or drag a build's JSON and its _tip-frequencies.json into https://auspice.us (files stay in your browser).

Note

Use auspice view from the pekosz-nextstrain conda environment, not nextstrain view from the Docker runtime. Under Docker, the viewer runs inside a container and the browser often cannot reach its localhost address, especially on WSL. With conda there is no container: on WSL, open http://localhost:4000 in your normal Windows browser. If the page still won't load, use https://auspice.us, which needs no local server. (Why conda and not Docker?)

2. Review checklist

  • The run finished SUCCESS (.run/reports/index.md) with no unexpected failed jobs or warnings (Step 4).
  • Tip counts are plausible compared with the previous snapshot; big drops are explained by filter_log.tsv (Step 3).
  • The newest sequencing run appears (color by sequencing_run).
  • Vaccine strains appear where expected.
  • Clades and subclades look right (no build entirely "unassigned"; Nextclade dataset updated as expected).
  • Subclade colors match the official Nextstrain builds: nothing is grey at the bottom of the subclade legend unless it is uncolored on nextstrain.org too (Subclade colors).
  • No long branches or tips far off the root-to-tip line (Clock view). Candidates for config/exclude.tsv are a Tier 2 decision for the maintainer.
  • Dates look right (no future dates, nothing in the 1900s).
  • Colorings and filters show only approved fields: clade, subclade, sequencing run, QC. No patient-level fields (age, sex, location). Builds open colored by subclade; "clade" shows the legacy clade (legacy-clade, see Glossary).
  • The surveillance report agrees with the trees.

3. Upload to the private group

Group Visibility Use
nextstrain.org/groups/PekoszLab Private (group members) Every new build goes here first
nextstrain.org/groups/PekoszLab-Public Public Only after review and PI approval

All builds with scripts/nextstrain_upload.py (8 segments + genome per subtype, each with its tip frequencies, to PekoszLab/seasonal/{subtype}/{build}):

python scripts/nextstrain_upload.py --dry-run           # check files, show the plan; uploads nothing
python scripts/nextstrain_upload.py                     # private group, all subtypes
python scripts/nextstrain_upload.py --subtypes h3n2     # private group, one subtype

The script stops if any build file is missing, runs nextstrain login (use your own account; never share credentials), shows what goes where, and uploads only after you type yes. It uploads to the private group unless you add --public (section 5).

One build (name it, and add any sidecar files such as tip frequencies):

nextstrain remote upload nextstrain.org/groups/PekoszLab/h3n2/ha \
    auspice/h3n2/ha.json auspice/h3n2/ha_tip-frequencies.json

Generic form: nextstrain remote upload nextstrain.org/groups/PekoszLab/${YOUR_BUILD_NAME} auspice/${YOUR_BUILD_NAME}.json

4. Check online

nextstrain remote list nextstrain.org/groups/PekoszLab

Open each page and repeat a quick look at the checklist.

5. Public release (only with approval)

  1. Dr. Pekosz approves the public release.

  2. config/description.md (shown on every Nextstrain page) acknowledges GISAID and the originating and submitting laboratories of the vaccine-strain sequences. GISAID requires this. The trees contain vaccine-strain names, dates and mutations derived from GISAID data, but no raw sequences. No EPI_SET ID is cited at present; if one is generated for the vaccine strains, add it to that paragraph and rerun the pipeline.

  3. Upload to PekoszLab-Public:

    python scripts/nextstrain_upload.py --public --dry-run   # check first
    python scripts/nextstrain_upload.py --public

    Builds go to PekoszLab-Public/seasonal-flu/{subtype}/{build} (the existing public URLs). The script refuses if any build's description lacks the GISAID acknowledgement (it looks for "via the GISAID Initiative"; builds exported before October 2026 lack it, so rerun the pipeline first), and you confirm by typing the group name PekoszLab-Public.

Tanglegrams (two trees side by side) work with the URL pattern https://nextstrain.org/groups/{group}/{subtype}/{segment}:groups/{group}/{subtype}/{segment}, e.g. https://nextstrain.org/groups/PekoszLab-Public/seasonal-flu/vic/ha:groups/PekoszLab-Public/seasonal-flu/vic/na.

6. Record the upload

Write down the date, run ID, git commit, destination and your name (lab notebook or upload log). Nothing records this automatically.

Never upload data/, results/, FASTA or metadata files. Only auspice/*.json.

7. Subclade colors

Where they come from. Every build colors subclades from config/{subtype}/colors.tsv, which the export and genome_export rules pass to augur export v2 --colors. The colored rows are copied from the official Nextstrain seasonal-flu builds (config/<lineage>/ha/auspice_config.json), 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. Row order is the legend order.

Why they need upkeep. Nextstrain picks these 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 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 the automatic sync works

The pipeline syncs the colors itself. 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, so all 27 trees are exported with the colors just synced. Snakemake deletes the marker after the last export, 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/.
  • 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.

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.

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

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.

Troubleshooting / FAQ

  • localhost:4000 won't load. Make sure auspice view is still running in a terminal with pekosz-nextstrain active (not nextstrain view inside Docker). Otherwise, drag the JSONs into https://auspice.us.
  • nextstrain asks me to log in every time. scripts/nextstrain_upload.py calls nextstrain login itself; that is expected.
  • "lack the GISAID acknowledgement". The builds were exported before the acknowledgement was added to config/description.md. Rerun the pipeline, then upload.
  • Upload refused / permission denied. Ask the maintainer to add you to the group with upload rights.
  • A tree looks wrong after upload. Upload the corrected JSON to the same name; it replaces the old one. Tell anyone who already saw it.
  • A subclade is grey at the bottom of the legend. It is missing from config/{subtype}/colors.tsv; see Subclade colors.
  • git status shows changes to config/*/colors.tsv after a run. The automatic color sync found new official colors. Review and commit them; see Problems and how to fix them.
  • I'm not sure something may go public. Then it does not, until Dr. Pekosz says so (Data Protection).

Next step → Best Practices

Clone this wiki locally