diff --git a/dev/tnt/chm13v2.0.html b/dev/tnt/chm13v2.0.html
deleted file mode 100644
index 445b4aea3..000000000
--- a/dev/tnt/chm13v2.0.html
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-
-
- All demo
-
-
-
-
-
-
-
-
-
-
diff --git a/dev/twobit/twobit_aliasBB.html b/dev/twobit/twobit_aliasBB.html
deleted file mode 100644
index ca25a799a..000000000
--- a/dev/twobit/twobit_aliasBB.html
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
- twobit
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dev/twobit/twobit_basic.html b/dev/twobit/twobit_basic.html
deleted file mode 100644
index 909d16e65..000000000
--- a/dev/twobit/twobit_basic.html
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
- twobit
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dev/twobit/twobit_chromSizes.html b/dev/twobit/twobit_chromSizes.html
deleted file mode 100644
index 6962b8e4c..000000000
--- a/dev/twobit/twobit_chromSizes.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
- twobit
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dev/twobit/twobit_t2t.html b/dev/twobit/twobit_t2t.html
deleted file mode 100644
index 078bd9bd3..000000000
--- a/dev/twobit/twobit_t2t.html
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
- twobit
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dev/ucsc/hub.html b/dev/ucsc/hub.html
index 0531e15fe..4465cc909 100644
--- a/dev/ucsc/hub.html
+++ b/dev/ucsc/hub.html
@@ -38,21 +38,29 @@
includeTracks: true
}
- const hub = await Hub.loadHub("https://hgdownload.soe.ucsc.edu/hubs/GCA/018/471/515/GCA_018471515.1/hub.txt", hubOptions)
+ const hub = await Hub.loadHub("https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/hub.txt", hubOptions)
const ref = hub.getGenomeConfig()
const igvConfig = {
- locus: hub.getDefaultPosition(),
- showChromosomeWidget: false,
reference: ref
}
+ // for(let tc of hub.getTrackConfigurations()) {
+ // for(let t of tc.tracks) {
+ // if(t.url.endsWith("undefined")) console.log(`${tc.label} ${t.name} ${t.url}`)
+ // }
+ // }
+
const browser = await igv.createBrowser(document.getElementById('igvDiv'), igvConfig)
const selector = document.getElementById("select")
selector.addEventListener("change", () => document.getElementById("hub-input").value = selector.value)
+
+ document.getElementById("hub-input").value = "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/hub.txt"
+
document.getElementById("load-genome").addEventListener("click", () =>
browser.loadGenome({url: document.getElementById("hub-input").value}))
+
document.getElementById("load-session").addEventListener("click", () =>
browser.loadSession({url: document.getElementById("hub-input").value}))
diff --git a/dev/twobit/twobit.html b/dev/ucsc/twobit.html
similarity index 100%
rename from dev/twobit/twobit.html
rename to dev/ucsc/twobit.html
diff --git a/dev/ucsc/twobit_t2t.html b/dev/ucsc/twobit_t2t.html
new file mode 100644
index 000000000..f58e4f583
--- /dev/null
+++ b/dev/ucsc/twobit_t2t.html
@@ -0,0 +1,61 @@
+
+
+
+ twobit
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/twobit/twobithg38.html b/dev/ucsc/twobithg38.html
similarity index 86%
rename from dev/twobit/twobithg38.html
rename to dev/ucsc/twobithg38.html
index 85ddca1f3..b8f034ddc 100644
--- a/dev/twobit/twobithg38.html
+++ b/dev/ucsc/twobithg38.html
@@ -22,10 +22,9 @@
"fastaURL": "http://s3.amazonaws.com/igv.broadinstitute.org/genomes/seq/hg38/hg38.fa",
"indexURL": "http://s3.amazonaws.com/igv.broadinstitute.org/genomes/seq/hg38/hg38.fa.fai",
"cytobandURL": "http://hgdownload.cse.ucsc.edu/goldenPath/hg38/database/cytoBandIdeo.txt.gz",
- "aliasURL": "https://s3.amazonaws.com/igv.broadinstitute.org/annotations/hg38/hg38_alias.tab",
- "format": "2bit",
+ "aliasURL": "https://hgdownload.cse.ucsc.edu/goldenPath/hg38/database/chromAlias.txt.gz",
+ "chromSizes": "https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.chrom.sizes",
"twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.2bit",
- "aliasBbURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.chromAlias.bb",
"tracks": [
{
"name": "Refseq Genes",
diff --git a/js/bigwig/trix.js b/js/bigwig/trix.js
index 8129bf4ef..1ad726211 100644
--- a/js/bigwig/trix.js
+++ b/js/bigwig/trix.js
@@ -51,7 +51,6 @@ export default class Trix {
const match = word.startsWith(searchWord)
if (match) {
matches.push(line)
- console.log("match " + line)
}
// we are done scanning if we are lexicographically greater than the search string
if (word.slice(0, searchWord.length) > searchWord) {
diff --git a/js/browser.js b/js/browser.js
index 640273008..df6497f78 100755
--- a/js/browser.js
+++ b/js/browser.js
@@ -448,16 +448,11 @@ class Browser {
/**
* Initialize a session from an object, json, or by loading from a file.
*
- * TODO Really should be split into at least 2 functions, load from file and load from object/json
- *
* @param options
* @returns {*}
*/
async loadSession(options) {
- // UCSC hub hack
- const chromosomeSelectWidget = this.chromosomeSelectWidget
-
this.sampleInfo.initialize()
// TODO: deprecated
@@ -487,7 +482,6 @@ class Browser {
}
if (filename.endsWith(".xml")) {
-
const knownGenomes = GenomeUtils.KNOWN_GENOMES
const string = await igvxhr.loadString(urlOrFile)
return new XMLSession(string, knownGenomes)
@@ -495,15 +489,8 @@ class Browser {
} else if (filename.endsWith("hub.txt")) {
const hub = await Hub.loadHub(urlOrFile, options)
-
- if(chromosomeSelectWidget) {
- chromosomeSelectWidget.hide()
- }
- const genomeConfig = hub.getGenomeConfig(options.includeTracks)
- const initialLocus = hub.getDefaultPosition()
+ const genomeConfig = hub.getGenomeConfig()
const config = {
- showChromosomeWidget: false,
- locus: initialLocus,
reference: genomeConfig
}
return setDefaults(config)
@@ -516,7 +503,6 @@ class Browser {
}
}
-
/**
* Note: public API function
* @param session
@@ -668,20 +654,23 @@ class Browser {
}
- createCenterLineList(columnContainer) {
+ cleanHouseForSession() {
- const centerLines = columnContainer.querySelectorAll('.igv-center-line')
- for (let i = 0; i < centerLines.length; i++) {
- centerLines[i].remove()
+ for (let trackView of this.trackViews) {
+ // empty axis column, viewport columns, sampleName column, scroll column, drag column, gear column
+ trackView.removeDOMFromColumnContainer()
}
- const centerLineList = []
- const viewportColumns = columnContainer.querySelectorAll('.igv-column')
- for (let i = 0; i < viewportColumns.length; i++) {
- centerLineList.push(new ViewportCenterLine(this, this.referenceFrameList[i], viewportColumns[i]))
+ // discard all columns
+ const elements = this.columnContainer.querySelectorAll('.igv-axis-column, .igv-column-shim, .igv-column, .igv-sample-info-column, .igv-sample-name-column, .igv-scrollbar-column, .igv-track-drag-column, .igv-gear-menu-column')
+ elements.forEach(column => column.remove())
+
+ this.trackViews = []
+
+ if (this.circularView) {
+ this.circularView.clearChords()
}
- return centerLineList
}
/**
@@ -701,20 +690,16 @@ class Browser {
this.updateNavbarDOMWithGenome(genome)
- // TODO -- I don't understand the genomeChange test. We always want to trigger a fresh start on loading a session or genome
- //if (genomeChange) {
- this.removeAllTracks()
- //}
+ this.removeAllTracks()
+
+ let locus = initialLocus || genome.initialLocus
+ if (Array.isArray(locus)) {
+ locus = locus.join(' ')
+ }
- let locus = getInitialLocus(initialLocus, genome)
const locusFound = await this.search(locus, true)
if (!locusFound) {
- console.log("Initial locus not found: " + locus)
- locus = genome.getHomeChromosomeName()
- const locusFound = await this.search(locus, true)
- if (!locusFound) {
- throw new Error("Cannot set initial locus")
- }
+ throw new Error(`Cannot set initial locus ${locus}`)
}
if (genomeChange && this.circularView) {
@@ -726,31 +711,23 @@ class Browser {
}
}
- cleanHouseForSession() {
-
- for (let trackView of this.trackViews) {
- // empty axis column, viewport columns, sampleName column, scroll column, drag column, gear column
- trackView.removeDOMFromColumnContainer()
- }
-
- // discard all columns
- const elements = this.columnContainer.querySelectorAll('.igv-axis-column, .igv-column-shim, .igv-column, .igv-sample-info-column, .igv-sample-name-column, .igv-scrollbar-column, .igv-track-drag-column, .igv-gear-menu-column')
- elements.forEach(column => column.remove())
-
- this.trackViews = []
-
- if (this.circularView) {
- this.circularView.clearChords()
- }
-
- }
updateNavbarDOMWithGenome(genome) {
- let genomeLabel = (genome.id && genome.id.length < 20 ? genome.id : `${genome.id.substring(0,8)}...${genome.id.substring(genome.id.length-8)}`)
+ let genomeLabel = (genome.id && genome.id.length < 20 ? genome.id : `${genome.id.substring(0, 8)}...${genome.id.substring(genome.id.length - 8)}`)
this.$current_genome.text(genomeLabel)
this.$current_genome.attr('title', genome.description)
- if(this.config.showChromosomeWidget !== false) {
+
+ // chromosome select widget -- Show this IFF its not explicitly hidden AND the genome has pre-loaded chromosomes
+ const showChromosomeWidget =
+ this.config.showChromosomeWidget !== false &&
+ genome.getChromosomes().size > 1 &&
+ (genome.wgChromosomeNames || genome.getChromosomes().size < 1000)
+
+ if (showChromosomeWidget) {
this.chromosomeSelectWidget.update(genome)
+ this.chromosomeSelectWidget.show()
+ } else {
+ this.chromosomeSelectWidget.hide()
}
}
@@ -771,7 +748,7 @@ class Browser {
genomeConfig = idOrConfig //await GenomeUtils.expandReference(this.alert, idOrConfig)
}
- await this.loadReference(genomeConfig, undefined)
+ await this.loadReference(genomeConfig)
const tracks = genomeConfig.tracks || []
@@ -794,20 +771,9 @@ class Browser {
* @returns {Promise}
*/
async loadTrackHub(options) {
-
const hub = await Hub.loadHub(options.url, options)
- const genomeConfig = hub.getGenomeConfig()
- const initialLocus = hub.getDefaultPosition()
- if (initialLocus) {
- const session = {
- locus: initialLocus,
- reference: genomeConfig
- }
- return this.loadSessionObject(session)
-
- } else {
- return this.loadGenome(genomeConfig)
- }
+ const genomeConfig = setDefaults(hub.getGenomeConfig())
+ return this.loadGenome(genomeConfig)
}
/**
@@ -1424,22 +1390,22 @@ class Browser {
}
// An autoscaleGroup of only one (1) trackView has the lone trackView removed from group autoscale mode
- const singleTonKeys = Object.keys(groupAutoscaleTrackViews).filter(key => 1 === groupAutoscaleTrackViews[ key ].length)
+ const singleTonKeys = Object.keys(groupAutoscaleTrackViews).filter(key => 1 === groupAutoscaleTrackViews[key].length)
if (singleTonKeys.length > 0) {
// Look for any single trackView groupAutoscale groups and move the single trackView to otherTrackViews list
for (const key of singleTonKeys) {
- for (const trackView of groupAutoscaleTrackViews[ key ]) {
+ for (const trackView of groupAutoscaleTrackViews[key]) {
trackView.track.autoscaleGroup = undefined
}
- otherTrackViews.push(...groupAutoscaleTrackViews[ key ])
- delete groupAutoscaleTrackViews[ key ]
+ otherTrackViews.push(...groupAutoscaleTrackViews[key])
+ delete groupAutoscaleTrackViews[key]
}
}
// Calculate group autoscale dataRange
if (Object.entries(groupAutoscaleTrackViews).length > 0) {
- for (const [ group, trackViews] of Object.entries(groupAutoscaleTrackViews)) {
+ for (const [group, trackViews] of Object.entries(groupAutoscaleTrackViews)) {
const featureArray = await Promise.all(trackViews.map(trackView => trackView.getInViewFeatures()))
const dataRange = doAutoscale(featureArray.flat())
for (const trackView of trackViews) {
@@ -1473,13 +1439,12 @@ class Browser {
referenceFrame.end = referenceFrame.start + referenceFrame.bpPerPixel * width
}
- this.chromosomeSelectWidget.select.value = referenceFrameList.length === 1 ? this.referenceFrameList[0].chr : ''
-
-
+ if (this.chromosomeSelectWidget) {
+ this.chromosomeSelectWidget.select.value = referenceFrameList.length === 1 ? this.referenceFrameList[0].chr : ''
+ }
const loc = this.referenceFrameList.map(rf => rf.getLocusString()).join(' ')
-
this.$searchInput.val(loc)
this.fireEvent('locuschange', [this.referenceFrameList])
@@ -1571,6 +1536,22 @@ class Browser {
await this.updateViews(true)
}
+ createCenterLineList(columnContainer) {
+
+ const centerLines = columnContainer.querySelectorAll('.igv-center-line')
+ for (let i = 0; i < centerLines.length; i++) {
+ centerLines[i].remove()
+ }
+
+ const centerLineList = []
+ const viewportColumns = columnContainer.querySelectorAll('.igv-column')
+ for (let i = 0; i < viewportColumns.length; i++) {
+ centerLineList.push(new ViewportCenterLine(this, this.referenceFrameList[i], viewportColumns[i]))
+ }
+
+ return centerLineList
+ }
+
async removeMultiLocusPanel(referenceFrame) {
// find the $column corresponding to this referenceFrame and remove it
@@ -2269,14 +2250,6 @@ function mouseUpOrLeave(e) {
}
-function getInitialLocus(locus, genome) {
- if (locus) {
- return Array.isArray(locus) ? locus.join(' ') : locus
- } else {
- return genome.getHomeChromosomeName()
- }
-}
-
function logo() {
return $(
diff --git a/js/genome/genome.js b/js/genome/genome.js
index 4e2324a1d..c6a226f37 100644
--- a/js/genome/genome.js
+++ b/js/genome/genome.js
@@ -47,11 +47,10 @@ class Genome {
}
// For backward compatibility
- if(this.chromosomes.size > 0) {
+ if (this.chromosomes.size > 0) {
this.chromosomeNames = Array.from(this.chromosomes.keys())
}
-
if (config.chromAliasBbURL) {
this.chromAlias = new ChromAliasBB(config.chromAliasBbURL, Object.assign({}, config), this)
} else if (config.aliasURL) {
@@ -60,7 +59,7 @@ class Genome {
if (config.cytobandBbURL) {
this.cytobandSource = new CytobandFileBB(config.cytobandBbURL, Object.assign({}, config), this)
- } else if(config.cytobandURL) {
+ } else if (config.cytobandURL) {
this.cytobandSource = new CytobandFile(config.cytobandURL, Object.assign({}, config))
}
@@ -86,7 +85,6 @@ class Genome {
}
-
get description() {
return this.config.description || `${this.id}\n${this.name}`
}
@@ -109,8 +107,8 @@ class Genome {
return Object.assign({}, this.config, {tracks: undefined})
}
- getInitialLocus() {
-
+ get initialLocus() {
+ return this.config.locus ? this.config.locus : this.getHomeChromosomeName()
}
getHomeChromosomeName() {
@@ -143,23 +141,20 @@ class Genome {
async loadChromosome(chr) {
+ let chromAliasRecord
+ if (this.chromAlias) {
+ chromAliasRecord = await this.chromAlias.search(chr)
+ chr = chromAliasRecord.chr
+ }
+
if (!this.chromosomes.has(chr)) {
- const sequenceRecord = await this.sequence.getSequenceRecord(chr)
+ let chromosome
+ const sequenceRecord = await this.sequence.getSequenceRecord(chr)
if (sequenceRecord) {
- const chromosome = new Chromosome(chr, 0, sequenceRecord.bpLength)
- this.chromosomes.set(chr, chromosome)
- } else {
- // Try alias
- if (this.chromAlias) {
- const chromAliasRecord = await this.chromAlias.search(chr)
- if (chromAliasRecord) {
- const chromosome = new Chromosome(chromAliasRecord.chr, 0, sequenceRecord.bpLength)
- this.chromosomes.set(chr, chromosome)
- }
- }
-
- this.chromosomes.set(chr, undefined) // Prevents future attempts
+ chromosome = new Chromosome(chr, 0, sequenceRecord.bpLength)
}
+
+ this.chromosomes.set(chr, chromosome) // <= chromosome might be undefined, setting it prevents future attempts
}
return this.chromosomes.get(chr)
diff --git a/js/ucsc/ucscHub.js b/js/ucsc/ucscHub.js
index e1a41440a..37bedde8d 100644
--- a/js/ucsc/ucscHub.js
+++ b/js/ucsc/ucscHub.js
@@ -9,23 +9,35 @@ import {igvxhr} from "../../node_modules/igv-utils/src/index.js"
class Hub {
- static supportedTypes = new Set(["bigBed", "bigWig", "bigGenePred"])
+ static supportedTypes = new Set(["bigBed", "bigWig", "bigGenePred", "vcfTabix"])
static filterTracks = new Set(["cytoBandIdeo", "assembly", "gap", "gapOverlap", "allGaps",
"cpgIslandExtUnmasked", "windowMasker"])
static async loadHub(url, options) {
+ const idx = url.lastIndexOf("/")
+ const baseURL = url.substring(0, idx + 1)
const stanzas = await loadStanzas(url, options)
let groups
if ("genome" === stanzas[1].type) {
const genome = stanzas[1]
if (genome.hasProperty("groups")) {
- const idx = url.lastIndexOf("/")
- const baseURL = url.substring(0, idx + 1)
const groupsTxtURL = baseURL + genome.getProperty("groups")
groups = await loadStanzas(groupsTxtURL)
}
}
+
+ // load includes. Nested includes are not supported
+ for (let s of stanzas.slice()) {
+ if ("include" === s.type) {
+ const includeStanzas = await loadStanzas(baseURL + s.getProperty("include"))
+ for (s of includeStanzas) {
+ s.setProperty("visibility", "hide")
+ stanzas.push(s)
+ }
+ }
+ }
+
return new Hub(url, stanzas, groups)
}
@@ -59,8 +71,6 @@ class Hub {
for (let i = 2; i < stanzas.length; i++) {
if ("track" === stanzas[i].type) {
this.trackStanzas.push(stanzas[i])
- } else {
- console.warn(`Unexpected stanza type: ${stanzas[i].type}`)
}
}
@@ -84,38 +94,26 @@ class Hub {
// Organize track configs by group
const trackConfigMap = new Map()
for (let c of this.#getTracksConfigs()) {
- const name = c.group || "other"
- if (trackConfigMap.has(name)) {
- trackConfigMap.get(name).push(c)
+ const groupName = c.group || "other"
+ if (trackConfigMap.has(groupName)) {
+ trackConfigMap.get(groupName).push(c)
} else {
- trackConfigMap.set(name, [c])
+ trackConfigMap.set(groupName, [c])
}
}
// Build group structure
- const t = []
- if (this.groupStanzas) {
- for (let g of this.groupStanzas) {
- const groupName = g.getProperty("name")
- if(trackConfigMap.has(groupName)) {
- t.push(
- {
- label: g.getProperty("label"),
- tracks: trackConfigMap.get(g.getProperty("name"))
- }
- )
- }
+ const groupStanazMap = this.groupStanzas ?
+ new Map(this.groupStanzas.map(groupStanza => [groupStanza.getProperty("name"), groupStanza])) :
+ new Map()
+
+ return Array.from(trackConfigMap.keys()).map(groupName => {
+ return {
+ label: groupStanazMap.has(groupName) ? groupStanazMap.get(groupName).getProperty("label") : groupName,
+ tracks: trackConfigMap.get(groupName)
}
- }
-
- if(trackConfigMap.has("other")) {
- t.push({
- label: "other",
- tracks: trackConfigMap.get("other")
- })
- }
+ })
- return t
}
/* Example genome stanza
@@ -136,7 +134,7 @@ transBlat dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
*/
- getGenomeConfig(includeTracks = "all") {
+ getGenomeConfig(includeTrackGroups = "all") {
// TODO -- add blat? htmlPath?
const config = {
id: this.genomeStanza.getProperty("genome"),
@@ -146,6 +144,10 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
wholeGenomeView: false
}
+ if (this.genomeStanza.hasProperty("defaultPos")) {
+ config.locus = this.genomeStanza.getProperty("defaultPos")
+ }
+
config.description = config.id
if (this.genomeStanza.hasProperty("blat")) {
@@ -165,6 +167,7 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
// if (this.genomeStanza.hasProperty("chromSizes")) {
// config.chromSizes = this.baseURL + this.genomeStanza.getProperty("chromSizes")
// }
+
if (this.genomeStanza.hasProperty("description")) {
config.description += `\n${this.genomeStanza.getProperty("description")}`
}
@@ -189,14 +192,17 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
type bigBed 4 +
bigDataUrl bbi/GCA_004027145.1_DauMad_v1_BIUU.cytoBand.bb
*/
- const cytoStanza = this.trackStanzas.filter(t => "cytoBandIdeo" === t.name && t.getProperty("bigDataUrl"))
+ const cytoStanza = this.trackStanzas.filter(t => "cytoBandIdeo" === t.name && t.hasProperty("bigDataUrl"))
if (cytoStanza.length > 0) {
config.cytobandBbURL = this.baseURL + cytoStanza[0].getProperty("bigDataUrl")
}
- // Tracks. To prevent loading tracks set `includeTracks`to false
- if (includeTracks) {
- config.tracks = this.#getTracksConfigs(Hub.filterTracks)
+ // Tracks. To prevent loading tracks set `includeTrackGroups`to false or "none"
+ if (includeTrackGroups && "none" !== includeTrackGroups) {
+ const filter = (t) => !Hub.filterTracks.has(t.name) &&
+ "hide" !== t.getProperty("visibility") &&
+ ("all" === includeTrackGroups || t.getProperty("group") === includeTrackGroups)
+ config.tracks = this.#getTracksConfigs(filter)
}
return config
@@ -207,10 +213,7 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
*/
#getTracksConfigs(filter) {
return this.trackStanzas.filter(t => {
- return t.getProperty("visibility") !== "hide" &&
- Hub.supportedTypes.has(t.format) &&
- (!filter || !Hub.filterTracks.has(t.name) &&
- t.hasProperty("bigDataUrl"))
+ return Hub.supportedTypes.has(t.format) && t.hasProperty("bigDataUrl") && (!filter || filter(t))
})
.map(t => this.#getTrackConfig(t))
}
@@ -246,6 +249,10 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
"displayMode": t.displayMode,
}
+ if ("vcfTabix" === format) {
+ config.indexURL = config.url + ".tbi"
+ }
+
if (t.hasProperty("longLabel") && t.hasProperty("html")) {
if (config.description) config.description += "
"
config.description =