diff --git a/frontend/src/api/__tests__/dotty.spec.ts b/frontend/src/api/__tests__/dotty.spec.ts index 10dcfde9..2fed9053 100644 --- a/frontend/src/api/__tests__/dotty.spec.ts +++ b/frontend/src/api/__tests__/dotty.spec.ts @@ -28,4 +28,20 @@ describe.concurrent('DottyClient', () => { expect(result).toEqual(mockData) }) + + it('should load transcripts successfully', async () => { + const mockData = { + transcripts: { + 'HGNC:1100': { + gene: 'info' + } + } + } + fetchMocker.mockResponseOnce(JSON.stringify(mockData), { status: 200 }) + + const client = new DottyClient() + const result = await client.fetchTranscripts('HGNC:1100', 'GRCh37') + + expect(result).toEqual(mockData) + }) }) diff --git a/frontend/src/api/dotty.ts b/frontend/src/api/dotty.ts index 3b7bf6ed..140fc29f 100644 --- a/frontend/src/api/dotty.ts +++ b/frontend/src/api/dotty.ts @@ -42,4 +42,19 @@ export class DottyClient { return null } } + + async fetchTranscripts( + hgnc_id: string, + assembly: 'GRCh37' | 'GRCh38' = 'GRCh38' + ): Promise { + const url = `${API_INTERNAL_BASE_PREFIX_DOTTY}/api/v1/find-transcripts?hgnc_id=${hgnc_id}&assembly=${assembly}` + const response = await fetch(url, { + method: 'GET' + }) + if (response.status == 200) { + return await response.json() + } else { + return null + } + } } diff --git a/frontend/src/components/VariantDetails/VariationLandscape.vue b/frontend/src/components/VariationLandscape.vue similarity index 82% rename from frontend/src/components/VariantDetails/VariationLandscape.vue rename to frontend/src/components/VariationLandscape.vue index eedd1ab9..00ac69aa 100644 --- a/frontend/src/components/VariantDetails/VariationLandscape.vue +++ b/frontend/src/components/VariationLandscape.vue @@ -6,16 +6,19 @@ import VegaPlot from '@/components/VegaPlot.vue' export interface Props { /** Gene information from annonars. */ clinvar: any + /** Transctipts information. */ + transcripts: any /** The genome release. */ genomeRelease: string - /** The gene symbol. */ - geneSymbol: string + /** The gene HGNC symbol. */ + hgnc: string } const props = withDefaults(defineProps(), { clinvar: null, + transcripts: null, genomeRelease: 'grch37', - geneSymbol: '' + hgnc: '' }) const clinvarSignificanceMapping: Record = { @@ -45,6 +48,54 @@ const convertClinvarSignificance = (input: number): number => { } } +const minMax = computed(() => { + if (!props.clinvar) { + return [] + } + let min = null + let max = null + for (const item of props.clinvar.variants ?? []) { + if (item.genome_release.toLowerCase() == props.genomeRelease) { + // Go through all item.variants and find the min and max pos. + for (const variant of item.variants) { + if (variant.pos < min || min == null) { + min = variant.pos + } + if (variant.pos > max || max == null) { + max = variant.pos + } + } + } + } + for (const exon of exons.value) { + if (exon.start < min || min == null) { + min = exon.start + } + if (exon.stop > max || max == null) { + max = exon.stop + } + } + return [min, max] +}) + +const exons = computed(() => { + if (!props.transcripts) { + return [] + } + const exons = [] + for (const transcript of props.transcripts.transcripts) { + for (const alignment of transcript.alignments) { + for (const exon of alignment.exons) { + exons.push({ + start: exon.ref_start, + stop: exon.ref_end + }) + } + } + } + return exons +}) + const vegaData = computed(() => { if (!props.clinvar) { return [] @@ -100,7 +151,7 @@ const vegaLayer = [ x: { field: 'pos', type: 'quantitative', - scale: { domain: [41190000, 41282000] }, + scale: { domain: minMax.value }, axis: { grid: false, zindex: 1000 }, title: null }, @@ -204,7 +255,7 @@ const vegaLayer = [ x: { field: 'pos', type: 'quantitative', - scale: { domain: [41190000, 41282000] }, + scale: { domain: minMax.value }, axis: { grid: false }, title: null }, @@ -246,13 +297,13 @@ const vegaLayer = [ }, { description: 'gene - line', - data: { values: [{ pos: 41196312 }, { pos: 41277381 }] }, + data: { values: [{ pos: minMax.value[0] }, { pos: minMax.value[1] }] }, mark: { type: 'line', stroke: 'black', size: 1, opacity: 0.5 }, encoding: { x: { field: 'pos', type: 'quantitative', - scale: { domain: [41190000, 41282000] }, + scale: { domain: minMax.value }, axis: { grid: false }, title: null }, @@ -262,10 +313,7 @@ const vegaLayer = [ { description: 'gene - exons', data: { - values: [ - { start: 41196312, stop: 41197819 }, - { start: 41199660, stop: 41199720 } - ] + values: exons.value }, mark: { type: 'rect', @@ -278,7 +326,7 @@ const vegaLayer = [ x: { field: 'start', type: 'quantitative', - scale: { domain: [41190000, 41282000] }, + scale: { domain: minMax.value }, axis: { grid: false }, title: null }, @@ -292,7 +340,7 @@ const vegaLayer = [