diff --git a/docs/content/finding-data/external-integrations.md b/docs/content/finding-data/external-integrations.md index e6005c88..4c914681 100644 --- a/docs/content/finding-data/external-integrations.md +++ b/docs/content/finding-data/external-integrations.md @@ -35,6 +35,8 @@ MaveDB displays ClinVar significance classifications and **star** status alongsi Mapped variants in MaveDB are cross-referenced with the [gnomAD database](https://gnomad.broadinstitute.org/) to retrieve population allele frequency data. This integration provides context about the prevalence of variants in diverse human populations, which is an important factor in clinical variant interpretation alongside functional evidence. +A variant's frequency is displayed on its [variant page](../mavemd/variant-page.md), and is available in bulk through the `gnomad` namespace of the variant data download. Each frequency is matched by ClinGen allele ID, so it is a direct assertion about that variant rather than an aggregate over related variants. Variants absent from gnomAD show no frequency. + ## Ensembl VEP MaveDB uses the [Ensembl Variant Effect Predictor (VEP)](https://www.ensembl.org/info/docs/tools/vep/index.html) to annotate mapped variants with predicted functional consequences, including effects on protein coding sequences, splicing, and regulatory regions. These VEP annotations are displayed alongside variant effect scores on score set pages, providing additional context for interpreting the functional impact of each variant. diff --git a/docs/content/mavemd/variant-page.md b/docs/content/mavemd/variant-page.md index 2a1b20ce..5d52f1f1 100644 --- a/docs/content/mavemd/variant-page.md +++ b/docs/content/mavemd/variant-page.md @@ -36,6 +36,17 @@ Each dataset on the variant page includes an [assay fact](../reference/assay-fac For the full list of assay fact properties and their definitions, see the [assay facts reference](../reference/assay-facts.md). +## Annotations + +Beneath the assay details, an annotations card gathers evidence about the variant itself, independent of any one assay. **Classification** reports the selected measurement's functional score, ACMG code, and OddsPath ratio. + +**Population frequency** reports the variant's frequency in [gnomAD](../finding-data/external-integrations.md#gnomad), where it is present: + +- **AF** -- The allele frequency, followed by the allele count and allele number it was computed from. +- **FAF95** -- The filtering allele frequency at 95% confidence, a conservative sampling-adjusted estimate, with the genetic ancestry group that attains it. A variant whose FAF95 exceeds a disease's maximum credible allele frequency is too common to be pathogenic (ACMG BA1/BS1). + +The gnomAD release the frequencies were drawn from is shown alongside them, with a link to the variant's gnomAD page. Variants absent from gnomAD are reported as having no record rather than as having zero frequency. + ## Interactive histogram The variant page includes the same interactive score histogram shown on score set pages, but with the selected variant's position highlighted within the distribution. This visualization helps you see where the variant falls relative to all other measured variants in the assay. diff --git a/src/api/mavedb/score-sets.ts b/src/api/mavedb/score-sets.ts index 24ef5517..77cfe891 100644 --- a/src/api/mavedb/score-sets.ts +++ b/src/api/mavedb/score-sets.ts @@ -7,7 +7,14 @@ type ScoreSetSearch = components['schemas']['ScoreSetsSearch'] type ScoreSetsSearchResponse = components['schemas']['ScoreSetsSearchResponse'] export type ScoreSetsSearchFilterOptionsResponse = components['schemas']['ScoreSetsSearchFilterOptionsResponse'] -const HISTOGRAM_VARIANT_DATA_NAMESPACES = ['vep', 'scores', 'clingen', 'mavedb'] +// Both screens read a score set's whole variant table from the same endpoint, but they render different +// things from it, so each names the namespaces it actually consumes. Keeping these separate matters at +// scale: a saturation-mutagenesis score set is 100k+ rows, and an unused namespace is 100k+ wasted cells. +const SCORE_SET_CHART_NAMESPACES = ['vep', 'scores', 'clingen', 'mavedb'] + +// The variant page additionally reads the selected measurement's gnomAD frequency out of its row; this +// request is the only source of it. See `gnomadFromVariantRow`. +const VARIANT_PAGE_NAMESPACES = [...SCORE_SET_CHART_NAMESPACES, 'gnomad'] function scoreSetVariantDataParams(options: {namespaces?: string[]} = {}): URLSearchParams { const params = new URLSearchParams() @@ -21,8 +28,14 @@ function scoreSetVariantDataUrl(urn: string, params: URLSearchParams = new URLSe return query ? `${baseUrl}?${query}` : baseUrl } -export function histogramScoreSetVariantDataUrl(urn: string): string { - return scoreSetVariantDataUrl(urn, scoreSetVariantDataParams({namespaces: HISTOGRAM_VARIANT_DATA_NAMESPACES})) +/** Variant data for a score set page's histogram and heatmap. */ +export function scoreSetChartVariantDataUrl(urn: string): string { + return scoreSetVariantDataUrl(urn, scoreSetVariantDataParams({namespaces: SCORE_SET_CHART_NAMESPACES})) +} + +/** Variant data for the variant page: the score distribution chart plus the selected row's annotations. */ +export function variantPageVariantDataUrl(urn: string): string { + return scoreSetVariantDataUrl(urn, scoreSetVariantDataParams({namespaces: VARIANT_PAGE_NAMESPACES})) } // --------------------------------------------------------------------------- diff --git a/src/api/mavedb/variants.ts b/src/api/mavedb/variants.ts index 24f5a31c..185d131c 100644 --- a/src/api/mavedb/variants.ts +++ b/src/api/mavedb/variants.ts @@ -1,7 +1,7 @@ import axios from 'axios' import config from '@/config' -import {histogramScoreSetVariantDataUrl} from '@/api/mavedb/score-sets' +import {variantPageVariantDataUrl} from '@/api/mavedb/score-sets' import {components} from '@/schema/openapi' type ScoreSet = components['schemas']['ScoreSet'] @@ -31,8 +31,9 @@ export async function getVariantDetail(urn: string): Promise { - const response = await axios.get(histogramScoreSetVariantDataUrl(scoreSetUrn)) +/** The containing score set's variant table, as read by the variant page. */ +export async function getVariantPageScoreSetData(scoreSetUrn: string): Promise { + const response = await axios.get(variantPageVariantDataUrl(scoreSetUrn)) return response.data } diff --git a/src/components/screens/ScoreSetView.vue b/src/components/screens/ScoreSetView.vue index 9cd13e8a..0ff431d4 100644 --- a/src/components/screens/ScoreSetView.vue +++ b/src/components/screens/ScoreSetView.vue @@ -508,7 +508,7 @@ import { deleteScoreSet, publishScoreSet, getScoreSetClinicalControlOptions, - histogramScoreSetVariantDataUrl + scoreSetChartVariantDataUrl } from '@/api/mavedb' import {components} from '@/schema/openapi' import MvLoader from '@/components/common/MvLoader.vue' @@ -719,7 +719,7 @@ export default { this.setItemId(newValue) let scoresUrl = null if (this.itemType?.restCollectionName && this.itemId) { - scoresUrl = histogramScoreSetVariantDataUrl(this.itemId) + scoresUrl = scoreSetChartVariantDataUrl(this.itemId) } this.setScoresDataUrl(scoresUrl) this.ensureScoresDataLoaded() diff --git a/src/components/screens/VariantScreen.vue b/src/components/screens/VariantScreen.vue index 8cae1126..7abdfb21 100644 --- a/src/components/screens/VariantScreen.vue +++ b/src/components/screens/VariantScreen.vue @@ -9,7 +9,8 @@ :model="tableDownloadMenu" severity="secondary" size="small" - @click="primaryTableDownload.command()"> + @click="primaryTableDownload.command()" + >