Skip to content

Commit

Permalink
feat: Finish integration of genome browser (#102) (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
gromdimon authored Oct 2, 2023
1 parent b2411a6 commit a2f8282
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 97 deletions.
60 changes: 24 additions & 36 deletions frontend/src/components/GenomeBrowser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
import igv from 'igv'
import { onMounted, ref, watch } from 'vue'
// import { genCaseTrack, publicTracks } from '@/components/GenomeBrowser.tracks'
import { publicTracks } from '@/lib/genomeBrowserTracks'
/** Alias for Genome Browser type. */
type GenomeBrowser = any
export interface Props {
// Case UUID
caseUuid: string
// Genome build, e.g., "hg19" or "b37"
genome: string
// Locus to go to, e.g., "chr1:1,900,000-2,000,000"
Expand All @@ -19,36 +17,37 @@ export interface Props {
// Define the props.
const props = defineProps<Props>()
// The <div> to show the browser in.
/** The <div> to show the browser in. */
const genomeBrowserDivRef = ref(null)
// Set on IGV browser creation.
/** Set on IGV browser creation. */
const igvBrowser = ref(null)
/**
* Translate genome build names from GRCh37/GRCh38 to hg19/hg38.
*
* @param value The genome build name.
* @returns The translated genome build name. (hg19/hg38)
*/
const translateGenome = (value: any) => {
if (value === 'GRCh37') {
return 'hg19'
} else if (value === 'GRCh38') {
return 'b38'
return 'hg38'
} else {
return value
}
}
// Conditionally add case tracks.
// const addCaseTracks = (browser: GenomeBrowser) => {
// if (props.caseUuid) {
// console.log(genCaseTrack(props.caseUuid))
// browser.loadTrack(genCaseTrack(props.caseUuid))
// }
// }
// Add all tracks.
// const addTracks = (browser: any) => {
// addCaseTracks(browser)
// for (const track of publicTracks) {
// browser.loadTrack(track)
// }
// }
/**
* Add public tracks.
*
* @param browser The IGV browser.
*/
const addTracks = (browser: any) => {
for (const track of publicTracks) {
browser.loadTrack(track)
}
}
// Watch changes to the genome (requires full reload).
watch(
Expand All @@ -59,20 +58,9 @@ watch(
.then((browser: GenomeBrowser) => {
browser.search(props.locus)
})
// .then((browser: GenomeBrowser) => {
// addTracks(browser)
// })
}
)
// Watch changes to the case (requires track reload).
watch(
() => props.caseUuid,
() => {
if (igvBrowser.value) {
;(igvBrowser.value! as GenomeBrowser).removeTrackByName('Case SVs')
// addCaseTracks(igvBrowser.value)
}
.then((browser: GenomeBrowser) => {
addTracks(browser)
})
}
)
Expand All @@ -95,7 +83,7 @@ onMounted(() => {
})
.then((browser: GenomeBrowser) => {
igvBrowser.value = browser
// addTracks(browser)
addTracks(browser)
if (props.locus) {
;(igvBrowser.value! as GenomeBrowser).search(props.locus)
}
Expand Down
16 changes: 14 additions & 2 deletions frontend/src/components/__tests__/GenomeBrowser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,29 @@ import { setupMountedComponents } from '@/lib/test-utils'
import GenomeBrowser from '../GenomeBrowser.vue'

describe.concurrent('GenomeBrowser', async () => {
it('renders the GenomeBrowser', async () => {
it('renders the GenomeBrowser with the hg19 genome', async () => {
const { wrapper } = setupMountedComponents(
{ component: GenomeBrowser, template: false },
{
props: {
caseUuid: 'your_case_uuid',
genome: 'hg19',
locus: 'chr17:41246243-41246243'
}
}
)
expect(wrapper.exists()).toBe(true)
})

it('renders the GenomeBrowser with the hg38 genome', async () => {
const { wrapper } = setupMountedComponents(
{ component: GenomeBrowser, template: false },
{
props: {
genome: 'hg38',
locus: 'chr17:41246243-41246243'
}
}
)
expect(wrapper.exists()).toBe(true)
})
})
45 changes: 45 additions & 0 deletions frontend/src/lib/__tests__/genomeBrowserTracks.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { describe, expect, it } from 'vitest'

import { publicTracks } from '../genomeBrowserTracks'

describe('publicTracks', () => {
it('should have at least one track', () => {
expect(publicTracks.length).toBeGreaterThan(0)
})

it('should have a name for each track', () => {
publicTracks.forEach((track) => {
expect(track.name).toBeDefined()
})
})

it('should have a sourceType for each track', () => {
publicTracks.forEach((track) => {
expect(track.sourceType).toBeDefined()
})
})

it('should have a format for each track', () => {
publicTracks.forEach((track) => {
expect(track.format).toBeDefined()
})
})

it('should have a visibilityWindow for each track', () => {
publicTracks.forEach((track) => {
expect(track.visibilityWindow).toBeDefined()
})
})

it('should have a url for each track', () => {
publicTracks.forEach((track) => {
expect(track.url).toBeDefined()
})
})

it('should have a color for each track', () => {
publicTracks.forEach((track) => {
expect(track.color).toBeDefined()
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,6 @@ const curatedMmsTrack = {
color: 'red'
}

// const clinvarTrack = {
// name: 'ClinVar SVs',
// sourceType: 'custom',
// visibilityWindow,
// height: 100,
// displayMode: 'SQUISHED',
// source: {
// url: `/svs/worker/clinvar/grch37/?min_pathogenicity=likely-pathogenic&chromosome=$CHR&begin=$START&end=$END`,
// method: 'GET',
// contentType: 'application/json',
// mappings: {
// chr: 'chromosome',
// start: 'begin',
// },
// queryable: true,
// },
// format: 'annotation',
// colorBy: 'pathogenicity',
// colorTable: {
// pathogenic: 'red',
// 'likely-pathogenic': 'orange',
// uncertain: 'blue',
// 'likely-benign': 'gray',
// benign: 'light gray',
// },
// }

const duplicationTrack = {
name: 'UCSC Segmental Duplications',
sourceType: 'annotation',
Expand Down Expand Up @@ -90,10 +63,6 @@ const fixTrack = {
}

const bgDbTracks = [
// {
// title: 'In-House SVs',
// token: 'inhouse',
// },
{
title: 'gnomad-SV',
token: 'gnomad'
Expand Down Expand Up @@ -122,38 +91,12 @@ const bgDbTracks = [
color: 'black'
}
})

export const publicTracks = [
duplicationTrack,
repeatsTrack,
altTrack,
fixTrack,
hescTadTrack,
curatedMmsTrack
// clinvarTrack,
].concat(bgDbTracks)

export const genCaseTrack = (caseUuid: string) => ({
order: -1,
height: '200',
name: 'Case SVs',
sourceType: 'custom',
visibilityWindow,
source: {
url: `/svs/ajax/fetch-variants/${caseUuid}/?chromosome=$CHR&start=$START&end=$END`,
// url: `https://varfish.bihealth.org/svs/ajax/fetch-variants/7a538a72-f8fb-4d71-a08b-6045f1e983dc/?chromosome=chr15&start=16989370.8&end=26828561.7`,
method: 'GET',
contentType: 'application/json',
mappings: {
chr: 'chromosome'
},
queryable: true
},
format: 'annotation',
colorBy: 'sv_type',
colorTable: {
DEL: 'red',
DUP: 'green',
INV: 'blue',
'*': 'black'
}
})
1 change: 0 additions & 1 deletion frontend/src/views/SvDetailView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ const genomeReleaseRef = ref(props.genomeRelease)
<h2>Genome Browser</h2>
<v-divider />
<GenomeBrowser
:case-uuid="'case-uuid'"
:genome="genomeRelease === 'grch37' ? 'hg19' : 'b38'"
:locus="svLocus(svInfoStore.currentSvRecord) as string"
/>
Expand Down

0 comments on commit a2f8282

Please sign in to comment.