Nextstrain pathogens
Genes, diversity, and a per-sample genotype matrix for SARS-CoV-2, Zika, Ebola, measles, and RSV-A.
Five viral genomes — SARS-CoV-2, Zika, Ebola, measles, RSV-A — each one config
object bundled with the app. The Pathogen dropdown swaps which config the
view is built from; nothing else changes. Gene annotations are inline
(FromConfigAdapter), while the reference (IndexedFastaAdapter) and the
Shannon-entropy diversity track (BigWigAdapter) are flatfiles on
jbrowse.org/demos.
Sample genotypes is a multi-sample variant matrix. The generator walks each
phylogeny’s nucleotide mutations root→tip to reconstruct every tip’s genotype at
every variable site, then writes a bgzipped VCF plus a samplesTsv of tip
metadata, which LinearMultiSampleVariantMatrixDisplay draws as samples × sites
colored by region. Zika and measles also carry a CramAdapter Published
genomes track — every genome NCBI publishes, aligned with minimap2.
scripts/gen-nextstrain-demos.mjs builds all of it from the live Nextstrain
datasets. Because each config is a plain JS object, your own code can import,
generate or template it the same way. See
react-msaview for
the matching reconstructed tree and alignment.
View source — 69 lines
import { useState } from 'react'
import {
JBrowseLinearGenomeView,
useCreateViewState,
} from '@jbrowse/react-linear-genome-view2'
import covid from './nextstrain_covid.json'
import ebola from './nextstrain_ebola.json'
import measles from './nextstrain_measles.json'
import rsvA from './nextstrain_rsv_a.json'
import zika from './nextstrain_zika.json'
// each config is generated by scripts/gen-nextstrain-demos.mjs from the live
// Nextstrain dataset: inline gene annotations, a hosted reference + diversity
// track, and a per-sample genotype matrix reconstructed from the phylogeny. The
// pathogen dropdown just swaps which committed config the view is built from.
const pathogens = [
{ slug: 'covid', label: 'SARS-CoV-2', config: covid },
{ slug: 'zika', label: 'Zika', config: zika },
{ slug: 'ebola', label: 'Ebola', config: ebola },
{ slug: 'measles', label: 'Measles', config: measles },
{ slug: 'rsv-a', label: 'RSV-A', config: rsvA },
]
function PathogenView({
config,
}: {
config: (typeof pathogens)[number]['config']
}) {
const { assembly, tracks, defaultSession, location } = config
const state = useCreateViewState({
assembly,
tracks,
defaultSession,
location,
})
// The `key` below unmounts this component on every pathogen change, so this
// page builds and discards engines rather than keeping one for the lifetime
// of the page. Nothing to do about it here: useCreateViewState destroys the
// engine on unmount, so the RPC worker threads and the autoruns go with it.
return <JBrowseLinearGenomeView viewState={state} />
}
export default function NextstrainPathogens() {
const [slug, setSlug] = useState('covid')
const pathogen = pathogens.find(p => p.slug === slug)!
return (
<div>
<label>
Pathogen{' '}
<select
value={slug}
onChange={event => {
setSlug(event.target.value)
}}
>
{pathogens.map(p => (
<option key={p.slug} value={p.slug}>
{p.label}
</option>
))}
</select>
</label>
{/* key forces a fresh view engine when the pathogen changes */}
<PathogenView key={slug} config={pathogen.config} />
</div>
)
}