Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions src/api/mavedb/score-sets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@ type ScoreSetSearch = components['schemas']['ScoreSetsSearch']
type ScoreSetsSearchResponse = components['schemas']['ScoreSetsSearchResponse']
export type ScoreSetsSearchFilterOptionsResponse = components['schemas']['ScoreSetsSearchFilterOptionsResponse']

const HISTOGRAM_VARIANT_DATA_NAMESPACES = ['vep', 'scores', 'clingen']

function scoreSetVariantDataParams(
options: {includePostMappedHgvs?: boolean; namespaces?: string[]} = {}
): URLSearchParams {
const params = new URLSearchParams()
if (options.includePostMappedHgvs) params.append('include_post_mapped_hgvs', 'true')
for (const namespace of options.namespaces ?? []) params.append('namespaces', namespace)
return params
}

function scoreSetVariantDataUrl(urn: string, params: URLSearchParams = new URLSearchParams()): string {
const query = params.toString()
const baseUrl = `${config.apiBaseUrl}/score-sets/${encodeURIComponent(urn)}/variants/data`
return query ? `${baseUrl}?${query}` : baseUrl
}

export function histogramScoreSetVariantDataUrl(urn: string): string {
return scoreSetVariantDataUrl(
urn,
scoreSetVariantDataParams({includePostMappedHgvs: true, namespaces: HISTOGRAM_VARIANT_DATA_NAMESPACES})
)
}

// ---------------------------------------------------------------------------
// Search
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -91,9 +115,7 @@ export async function downloadScoreSetFile(urn: string, type: 'scores' | 'counts
}

export async function downloadScoreSetVariantData(urn: string, params: URLSearchParams): Promise<string> {
const response = await axios.get(
`${config.apiBaseUrl}/score-sets/${encodeURIComponent(urn)}/variants/data?${params.toString()}`
)
const response = await axios.get(scoreSetVariantDataUrl(urn, params))
return response.data
}

Expand Down
12 changes: 6 additions & 6 deletions src/api/mavedb/variants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import axios from 'axios'

import config from '@/config'
import {histogramScoreSetVariantDataUrl} from '@/api/mavedb/score-sets'
import {components} from '@/schema/openapi'

type ScoreSet = components['schemas']['ScoreSet']
Expand All @@ -18,10 +19,9 @@ export async function lookupVariantsByClingenId(
}

export async function lookupVariantsByVrsDigest(identifier: string): Promise<MappedVariant[]> {
const response = await axios.get(
`${config.apiBaseUrl}/mapped-variants/vrs/${encodeURIComponent(identifier)}`,
{params: {only_current: true}}
)
const response = await axios.get(`${config.apiBaseUrl}/mapped-variants/vrs/${encodeURIComponent(identifier)}`, {
params: {only_current: true}
})
return response.data
}

Expand All @@ -30,8 +30,8 @@ export async function getVariantDetail(urn: string): Promise<VariantEffectMeasur
return response.data
}

export async function getVariantScores(scoreSetUrn: string): Promise<string> {
const response = await axios.get(`${config.apiBaseUrl}/score-sets/${encodeURIComponent(scoreSetUrn)}/variants/data`)
export async function getHistogramVariantData(scoreSetUrn: string): Promise<string> {
const response = await axios.get(histogramScoreSetVariantDataUrl(scoreSetUrn))
return response.data
}

Expand Down
18 changes: 9 additions & 9 deletions src/components/screens/ScoreSetView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -502,9 +502,13 @@ import config from '@/config'
import {hasPathogenicityCalibrations, hasFunctionalCalibrations} from '@/lib/calibrations'
import {variantNotNullOrNA} from '@/lib/mave-hgvs'
import {getScoreSetShortName} from '@/lib/score-sets'
import {parseScoresOrCounts} from '@/lib/scores'
import {parseSimpleCodingVariants, translateSimpleCodingVariants, type Variant} from '@/lib/variants'
import {deleteScoreSet, publishScoreSet, getScoreSetClinicalControlOptions} from '@/api/mavedb'
import {parseScoreSetVariantData, type Variant} from '@/lib/variants'
import {
deleteScoreSet,
publishScoreSet,
getScoreSetClinicalControlOptions,
histogramScoreSetVariantDataUrl
} from '@/api/mavedb'
import {components} from '@/schema/openapi'
import MvLoader from '@/components/common/MvLoader.vue'
import MvEmptyState from '@/components/common/MvEmptyState.vue'
Expand Down Expand Up @@ -714,7 +718,7 @@ export default {
this.setItemId(newValue)
let scoresUrl = null
if (this.itemType?.restCollectionName && this.itemId) {
scoresUrl = `${config.apiBaseUrl}/${this.itemType.restCollectionName}/${this.itemId}/variants/data?include_post_mapped_hgvs=true&namespaces=vep&namespaces=scores&namespaces=clingen`
scoresUrl = histogramScoreSetVariantDataUrl(this.itemId)
}
this.setScoresDataUrl(scoresUrl)
this.ensureScoresDataLoaded()
Expand All @@ -723,11 +727,7 @@ export default {
immediate: true
},
scoresData(newValue: unknown) {
const parsed = newValue ? parseScoresOrCounts(newValue as string, true) : null
if (parsed) {
parseSimpleCodingVariants(parsed as Variant[])
translateSimpleCodingVariants(parsed as Variant[])
}
const parsed = newValue ? parseScoreSetVariantData(newValue as string) : null
this.variants = parsed ? (Object.freeze(parsed) as Variant[]) : null
this.applyUrlState()
},
Expand Down
3 changes: 2 additions & 1 deletion src/components/screens/VariantScreen.vue
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,12 @@
<ScoreSetHistogram
:key="lookup.selectedScoreSetUrn.value || ''"
ref="histogram"
:coordinates="'mapped'"
:external-selection="lookup.variantScoreRow.value"
:lock-selection="true"
:score-set="lookup.selectedScoreSet.value"
:selected-calibration="lookup.selectedCalibration.value || undefined"
:variants="lookup.scores.value as any"
:variants="lookup.scores.value"
@calibration-changed="lookup.selectedCalibration.value = $event"
@selection-changed="() => {}"
/>
Expand Down
14 changes: 7 additions & 7 deletions src/composables/use-variant-lookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {computed, ref, shallowRef, watch, type ComputedRef, type Ref} from 'vue'
import {
getVariantAnnotation,
getVariantDetail,
getVariantScores,
getHistogramVariantData,
lookupVariantsByClingenId
} from '@/api/mavedb/variants'
import {useCalibrationResolution, type UseCalibrationResolutionReturn} from '@/composables/use-calibration-resolution'
Expand All @@ -18,7 +18,7 @@ import {
} from '@/lib/calibrations'
import {triggerDownload} from '@/lib/downloads'
import {getExperimentKeyword} from '@/lib/experiments'
import {parseScoresOrCounts, type ScoresOrCountsRow} from '@/lib/scores'
import {parseScoreSetVariantData, type Variant} from '@/lib/variants'
import type {MeasurementType} from '@/lib/measurement-types'
import type {components} from '@/schema/openapi'

Expand Down Expand Up @@ -60,8 +60,8 @@ export interface UseVariantLookupReturn {
// Scores
selectedScoreSet: ComputedRef<ScoreSet | null>
selectedScoreSetUrn: ComputedRef<string | null>
scores: ComputedRef<readonly ScoresOrCountsRow[] | null>
variantScoreRow: ComputedRef<ScoresOrCountsRow | undefined>
scores: ComputedRef<Variant[] | null>
variantScoreRow: ComputedRef<Variant | undefined>
selectedVariantScore: ComputedRef<number | string | null>

// Calibration
Expand Down Expand Up @@ -116,7 +116,7 @@ export function useVariantLookup(
const showNucleotide = ref(true)
const showProtein = ref(true)
const variantDetailCache = ref<Record<string, VariantEffectMeasurementWithScoreSet>>({})
const scoresCache = shallowRef<Record<string, readonly ScoresOrCountsRow[]>>({})
const scoresCache = shallowRef<Record<string, Variant[]>>({})
const selectedCalibration = ref<string | null>(null)

// ── Filters ───────────────────────────────────────────────
Expand Down Expand Up @@ -212,10 +212,10 @@ export function useVariantLookup(
async function fetchScores(scoreSetUrn: string) {
if (scoresCache.value[scoreSetUrn]) return
try {
const data = await getVariantScores(scoreSetUrn)
const data = await getHistogramVariantData(scoreSetUrn)
scoresCache.value = {
...scoresCache.value,
[scoreSetUrn]: Object.freeze(parseScoresOrCounts(data, true))
[scoreSetUrn]: parseScoreSetVariantData(data)
}
} catch (error) {
console.error(`Error fetching scores for score set "${scoreSetUrn}"`, error)
Expand Down
42 changes: 31 additions & 11 deletions src/lib/variants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import {AMINO_ACIDS, AMINO_ACIDS_WITH_TER, singleLetterAminoAcidOrHgvsCode} from
import {DEFAULT_CLNREVSTAT_FIELD, DEFAULT_CLNSIG_FIELD} from '@/lib/clinical-controls'
import geneticCodes from '@/lib/genetic-codes'
import {parseSimpleNtVariant, parseSimpleProVariant} from '@/lib/mave-hgvs'
import {parseScoresOrCounts} from '@/lib/scores'
import type {SimpleDnaVariation, SimpleProteinVariation} from '@/lib/mave-hgvs'
import {components} from '@/schema/openapi'

type ScoreSet = components['schemas']['ScoreSet']

export type HgvsReferenceSequenceType = 'c' | 'p' // | 'n'

Expand All @@ -21,6 +19,16 @@ export interface ClinicalControlVariant {
[DEFAULT_CLNREVSTAT_FIELD]: string
}

type ParsedSimpleDnaVariation = SimpleDnaVariation & {
residueType?: 'nt'
origin?: 'mapped' | 'unmapped'
}

type ParsedSimpleProteinVariation = SimpleProteinVariation & {
residueType?: 'aa'
origin?: 'mapped' | 'unmapped'
}

export interface RawVariant {
accession: string
hgvs_nt?: string
Expand Down Expand Up @@ -51,19 +59,20 @@ export interface RawVariant {
}

export interface VariantPropertiesAddedByPreparingCodingVariants {
// Added by prepareSimpleCodingVariants.
parsedPostMappedHgvsC?: SimpleDnaVariation
parsedPostMappedHgvsP?: SimpleProteinVariation
// Added by parseSimpleCodingVariants.
parsedPostMappedHgvsC?: ParsedSimpleDnaVariation
parsedPostMappedHgvsP?: ParsedSimpleProteinVariation
}

export interface Variant extends RawVariant, VariantPropertiesAddedByPreparingCodingVariants {
// Added by translateSimpleCodingVariants
translated_hgvs_p?: string
}

export const HGVS_REFERENCE_SEQUENCE_TYPES: {
[type: HgvsReferenceSequenceType]: {parsedPostMappedHgvsField: keyof VariantPropertiesAddedByPreparingCodingVariants}
} = {
export const HGVS_REFERENCE_SEQUENCE_TYPES: Record<
HgvsReferenceSequenceType,
{parsedPostMappedHgvsField: keyof VariantPropertiesAddedByPreparingCodingVariants}
> = {
c: {
parsedPostMappedHgvsField: 'parsedPostMappedHgvsC'
},
Expand Down Expand Up @@ -106,6 +115,17 @@ export const VARIANT_EFFECT_TYPE_OPTIONS = [

export const DEFAULT_VARIANT_EFFECT_TYPES = ['Missense', 'Nonsense', 'Synonymous', 'Other']

export function parseScoreSetVariantData(csvData: string): Variant[] {
const variants = parseScoresOrCounts(csvData, true) as Variant[]
prepareScoreSetVariantData(variants)
return variants
}

function prepareScoreSetVariantData(variants: Variant[]) {
parseSimpleCodingVariants(variants)
translateSimpleCodingVariants(variants)
}

export const PARSED_POST_MAPPED_VARIANT_PROPERTIES: ParsedPostMappedVariantProperties = {
c: 'parsedPostMappedHgvsC',
g: 'parsedPostMappedHgvsC',
Expand All @@ -128,7 +148,7 @@ function getParsedPostMappedHgvs(variant: Variant, type: HgvsReferenceSequenceTy
*
* @param variants The variants to modify.
*/
export function parseSimpleCodingVariants(variants: Variant[]) {
function parseSimpleCodingVariants(variants: Variant[]) {
for (const v of variants) {
// Create the mavedb namespace if it doesn't exist.
if (!v.mavedb) v.mavedb = {}
Expand Down Expand Up @@ -302,7 +322,7 @@ export function inferReferenceSequenceFromVariants(variants: Variant[], referenc
*
* @param variants The array of variants to translate.
*/
export function translateSimpleCodingVariants(variants: Variant[]) {
function translateSimpleCodingVariants(variants: Variant[]) {
const {referenceSequence: codingSequence, referenceSequenceRange: codingSequenceRange} =
inferReferenceSequenceFromVariants(variants, 'c')
if (codingSequence.length > 0) {
Expand Down