Skip to content

Commit

Permalink
Handle VCF files with no info fields. Fixes #1868
Browse files Browse the repository at this point in the history
  • Loading branch information
jrobinso committed Aug 8, 2024
1 parent 3172d44 commit 25c83c2
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 31 deletions.
44 changes: 44 additions & 0 deletions dev/variant/noheader.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="IE=edge" http-equiv="X-UA-Compatible">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<meta content="" name="description">
<meta content="" name="author">
<link href=https://igv.org/web/img/favicon.ico rel="shortcut icon">
<title>indel</title>

</head>

<body>

<div id="igvDiv" style="padding-top: 50px;padding-bottom: 20px; height: auto"></div>

<script type="module">

import igv from "../../js/index.js";

const options =
{
genome: "hg19",
locus: "chr6:63,498,615-63,498,653",
tracks: [
{
"url": "../../test/data/vcf/noheader.vcf"
},

]
};

igv.createBrowser(document.getElementById('igvDiv'), options)
.then(function (browser) {

})


</script>

</body>

</html>
11 changes: 6 additions & 5 deletions js/variant/variant.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class Variant {
this.filter = tokens[6]
this.info = {}
const infoStr = tokens[7]
if (infoStr) {
if (infoStr && infoStr !== '.') {
for (let elem of infoStr.split(';')) {
var element = elem.split('=')
this.info[element[0]] = element[1]
Expand Down Expand Up @@ -205,9 +205,10 @@ class Variant {
}
}

if (this.info) {
const infoKeys = Object.keys(this.info)
if (this.info && infoKeys.length > 0) {
fields.push({html: '<hr style="border-top: dotted 1px;border-color: #c9c3ba" />'})
for (let key of Object.keys(this.info)) {
for (let key of infoKeys) {
fields.push({name: key, value: arrayToString(decodeURIComponent(this.info[key]))})
}
}
Expand Down Expand Up @@ -274,7 +275,7 @@ class SVComplement {
}

getAttributeValue(key) {
return this.mate.getAttributeValue(key)
return this.mate.getAttributeValue(key)
}

getInfo(tag) {
Expand All @@ -297,7 +298,7 @@ class SVComplement {
popupData.push({name: 'Pos', value: `${StringUtils.numberFormatter(this.pos)}`})
popupData.push({html: '<hr style="border-top: dotted 1px;border-color: #c9c3ba" />'})
popupData.push("SV")
popupData.push(... this.mate.popupData(genomicLocation, genomeId))
popupData.push(...this.mate.popupData(genomicLocation, genomeId))

return popupData
}
Expand Down
33 changes: 18 additions & 15 deletions js/variant/variantTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,23 +126,26 @@ class VariantTrack extends TrackBase {
this.header = await this.getHeader()

// Set colorBy, if not explicitly set default to allele frequency, if available, otherwise default to none (undefined)
const infoFields = new Set(Object.keys(this.header.INFO))
if (this.config.colorBy) {
this.colorBy = this.config.colorBy
} else if (!this.config.color && infoFields.has('AF')) {
this.colorBy = 'AF'
}
if(this.header.INFO) {
const infoFields = new Set(Object.keys(this.header.INFO))
if (this.config.colorBy) {
this.colorBy = this.config.colorBy
} else if (!this.config.color && infoFields.has('AF')) {
this.colorBy = 'AF'
}

// Configure menu items based on info available
if (infoFields.has('AF')) {
this._colorByItems.set('AF', 'Allele frequency')
}
if (infoFields.has('VT')) {
this._colorByItems.set('VT', 'Variant Type')
}
if (infoFields.has('SVTYPE')) {
this._colorByItems.set('SVTYPE', 'SV Type')
// Configure menu items based on info available
if (infoFields.has('AF')) {
this._colorByItems.set('AF', 'Allele frequency')
}
if (infoFields.has('VT')) {
this._colorByItems.set('VT', 'Variant Type')
}
if (infoFields.has('SVTYPE')) {
this._colorByItems.set('SVTYPE', 'SV Type')
}
}

if (this.config.colorBy && !this._colorByItems.has(this.config.colorBy)) {
this._colorByItems.set(this.config.colorBy, this.config.colorBy)
}
Expand Down
5 changes: 5 additions & 0 deletions test/data/vcf/noheader.vcf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
##fileformat=VCFv4.2
#CHROM POS ID REF ALT QUAL FILTER INFO
chr6 63498622 <a href='https://www.ncbi.nlm.nih.gov/snp/rs1779765' target='_blank'>rs1779765</a> T A . . .
chr6 63498633 <a href='https://www.ncbi.nlm.nih.gov/snp/rs1779766' target='_blank'>rs1779766</a> G A . . .
chr6 63498639 <a href='https://www.ncbi.nlm.nih.gov/snp/rs1779767' target='_blank'>rs1779767</a> G A . . .
35 changes: 24 additions & 11 deletions test/testVariant.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import {assert} from 'chai'
import getDataWrapper from "../js/feature/dataWrapper.js"
import {createGenome} from "./utils/MockGenome.js"
import pack from "../js/feature/featurePacker.js"

const genome = createGenome()
import Browser from "../js/browser.js"
import VariantTrack from "../js/variant/variantTrack.js"

const genome = createGenome()
const browser = {genome}

suite("testVariant", function () {

Expand Down Expand Up @@ -156,9 +157,6 @@ suite("testVariant", function () {
indexURL: "test/data/vcf/large_header.vcf.idx"
}


const browser = {genome}

const track = await Browser.prototype.createTrack.call(browser, config)
assert.equal(track.type, "variant")

Expand All @@ -171,15 +169,13 @@ suite("testVariant", function () {
})

test("tabix indexed - large header", async function () {

const config = {
url: "test/data/vcf/large_header.vcf",
indexURL: "test/data/vcf/large_header.vcf.idx"

}


const browser = {genome}

const track = await Browser.prototype.createTrack.call(browser, config)
assert.equal(track.type, "variant")

Expand Down Expand Up @@ -213,9 +209,6 @@ suite("testVariant", function () {
indexed: false
}


const browser = {genome}

const track = await Browser.prototype.createTrack.call(browser, config)
assert.equal(track.type, "variant")

Expand Down Expand Up @@ -258,6 +251,26 @@ suite("testVariant", function () {

})

test("Test no info fields", async function () {

const url = "test/data/vcf/noheader.vcf"

const config = {url}

const track = await Browser.prototype.createTrack.call(browser, config)

await track.postInit()

const variants = await track.getFeatures("chr6", 0, Number.MAX_SAFE_INTEGER)

assert.equal(variants.length, 3)

for (let v of variants) {
assert.equal(v.type, "SNP")
}

})


})

0 comments on commit 25c83c2

Please sign in to comment.