diff --git a/dev/ucsc/genome.html b/dev/ucsc/genome.html
index 9441cf697..edaff11a3 100644
--- a/dev/ucsc/genome.html
+++ b/dev/ucsc/genome.html
@@ -12,8 +12,9 @@
import igv from "../../js/index.js"
+ //https://hgdownload.soe.ucsc.edu/hubs/GCF/000/002/035/GCF_000002035.6/hub.txt
const igvConfig = {
- genome: "GCA_000002305.1"
+ genome: "GCF_000002035.6"
}
diff --git a/js/bigwig/bwReader.js b/js/bigwig/bwReader.js
index a7b4ea6b8..00e653a42 100644
--- a/js/bigwig/bwReader.js
+++ b/js/bigwig/bwReader.js
@@ -54,7 +54,8 @@ class BWReader {
this.config = config
this.bufferSize = BUFFER_SIZE
this.loader = isDataURL(this.path) ?
- new DataBuffer(this.path) : igvxhr
+ new DataBuffer(BGZip.decodeDataURI(this.path).buffer) :
+ igvxhr
const trixURL = config.trixURL || config.searchTrix
if (trixURL) {
@@ -63,6 +64,15 @@ class BWReader {
}
+ /**
+ * Preload all the data for this bb file
+ * @returns {Promise}
+ */
+ async preload() {
+ const data = await igvxhr.loadArrayBuffer(this.path)
+ this.loader = new DataBuffer(data)
+ }
+
async readWGFeatures(bpPerPixel, windowFunction) {
await this.loadHeader()
const chrIdx1 = 0
@@ -732,8 +742,8 @@ function decodeZoomData(data, chrIdx1, bpStart, chrIdx2, bpEnd, featureArray, ch
class DataBuffer {
- constructor(dataURI) {
- this.data = BGZip.decodeDataURI(dataURI).buffer
+ constructor(data) {
+ this.data = data
}
/**
@@ -762,49 +772,5 @@ class DataBuffer {
}
}
-class WholeFileBuffer {
-
- data
-
- constructor(path) {
- this.path = path
- }
-
- async loadFile() {
- this.data = await igvxhr.loadArrayBuffer(this.path)
- }
-
- /**
- * igvxhr interface
- * @param ignore
- * @param options
- * @returns {any}
- */
- async loadArrayBuffer(ignore, options) {
- if (!this.data) {
- await this.loadFile()
- }
- const range = options.range
- return range ? this.data.slice(range.start, range.start + range.size) : this.data
- }
-
- /**
- * BufferedReader interface
- *
- * @param requestedRange - byte rangeas {start, size}
- * @param fulfill - function to receive result
- * @param asUint8 - optional flag to return result as an UInt8Array
- */
- async dataViewForRange(requestedRange, asUint8) {
- if (!this.data) {
- await this.loadFile()
- }
- const len = Math.min(this.data.byteLength - requestedRange.start, requestedRange.size)
- return asUint8 ?
- new Uint8Array(this.data, requestedRange.start, len) :
- new DataView(this.data, requestedRange.start, len)
- }
-
-}
export default BWReader
diff --git a/js/genome/chromAliasBB.js b/js/genome/chromAliasBB.js
index 8d38a3e46..2b1d16b64 100644
--- a/js/genome/chromAliasBB.js
+++ b/js/genome/chromAliasBB.js
@@ -19,6 +19,13 @@ class ChromAliasBB {
this.reader = new BWReader(config, genome)
}
+ async preload(chrNames) {
+ await this.reader.preload();
+ for(let nm of chrNames) {
+ await this.search(nm)
+ }
+ }
+
/**
* Return the cached canonical chromosome name for the alias. If none found return the alias.
*
diff --git a/js/genome/chromAliasDefaults.js b/js/genome/chromAliasDefaults.js
index 4fd66e0a5..4f3a57494 100644
--- a/js/genome/chromAliasDefaults.js
+++ b/js/genome/chromAliasDefaults.js
@@ -14,6 +14,9 @@ class ChromAliasDefaults {
this.update(id, chromosomeNames)
}
+ async preload() {
+ // no-op
+ }
/**
* Return the canonical chromosome name for the alias. If none found return the alias
diff --git a/js/genome/chromAliasFile.js b/js/genome/chromAliasFile.js
index 4a80ada14..16ffadb8d 100644
--- a/js/genome/chromAliasFile.js
+++ b/js/genome/chromAliasFile.js
@@ -22,6 +22,10 @@ class ChromAliasFile {
this.genome = genome
}
+ async preload() {
+ return this.loadAliases();
+ }
+
/**
* Return the canonical chromosome name for the alias. If none found return the alias
*
diff --git a/js/genome/genome.js b/js/genome/genome.js
index 376570903..fa72c94ab 100644
--- a/js/genome/genome.js
+++ b/js/genome/genome.js
@@ -57,28 +57,28 @@ class Genome {
if (config.chromAliasBbURL) {
this.chromAlias = new ChromAliasBB(config.chromAliasBbURL, Object.assign({}, config), this)
- if(!this.chromosomeNames) {
+ if (!this.chromosomeNames) {
this.chromosomeNames = await this.chromAlias.getChromosomeNames()
}
} else if (config.aliasURL) {
this.chromAlias = new ChromAliasFile(config.aliasURL, Object.assign({}, config), this)
} else if (this.chromosomeNames) {
- this.chromAlias = new ChromAliasDefaults(this.id, this.chromosomeNames);
+ this.chromAlias = new ChromAliasDefaults(this.id, this.chromosomeNames)
}
if (config.cytobandBbURL) {
this.cytobandSource = new CytobandFileBB(config.cytobandBbURL, Object.assign({}, config), this)
- if(!this.chromosomeNames) {
+ if (!this.chromosomeNames) {
this.chromosomeNames = await this.cytobandSource.getChromosomeNames()
}
} else if (config.cytobandURL) {
this.cytobandSource = new CytobandFile(config.cytobandURL, Object.assign({}, config))
- if(!this.chromosomeNames) {
+ if (!this.chromosomeNames) {
this.chromosomeNames = await this.cytobandSource.getChromosomeNames()
}
- if(this.chromosomes.size === 0) {
+ if (this.chromosomes.size === 0) {
const c = await this.cytobandSource.getChromosomes()
- for(let chromosome of c) {
+ for (let chromosome of c) {
this.chromosomes.set(c.name, c)
}
}
@@ -96,6 +96,7 @@ class Genome {
} else {
this.#wgChromosomeNames = trimSmallChromosomes(this.chromosomes)
}
+ await this.chromAlias.preload(this.#wgChromosomeNames)
}
// Optionally create the psuedo chromosome "all" to support whole genome view
@@ -162,15 +163,15 @@ class Genome {
async loadChromosome(chr) {
if (this.chromAlias) {
- const chromAliasRecord = await this.chromAlias.search(chr)
- if(chromAliasRecord) {
+ const chromAliasRecord = await this.chromAlias.search(chr)
+ if (chromAliasRecord) {
chr = chromAliasRecord.chr
}
}
if (!this.chromosomes.has(chr)) {
let chromosome
- const sequenceRecord = await this.sequence.getSequenceRecord(chr)
+ const sequenceRecord = await this.sequence.getSequenceRecord(chr)
if (sequenceRecord) {
chromosome = new Chromosome(chr, 0, sequenceRecord.bpLength)
}
@@ -180,6 +181,7 @@ class Genome {
return this.chromosomes.get(chr)
}
+
async getAliasRecord(chr) {
if (this.chromAlias) {
return this.chromAlias.search(chr)
@@ -199,7 +201,7 @@ class Genome {
}
get wgChromosomeNames() {
- return this.#wgChromosomeNames ? this.#wgChromosomeNames.slice() : undefined
+ return this.#wgChromosomeNames ? this.#wgChromosomeNames.slice() : undefined
}
get showChromosomeWidget() {
@@ -303,7 +305,7 @@ class Genome {
* @param end
*/
getSequenceInterval(chr, start, end) {
- if(typeof this.sequence.getSequenceInterval === 'function') {
+ if (typeof this.sequence.getSequenceInterval === 'function') {
return this.sequence.getSequenceInterval(chr, start, end)
} else {
return undefined
diff --git a/js/ucsc/ucscHub.js b/js/ucsc/ucscHub.js
index c2f72a7ef..b88bd6ead 100644
--- a/js/ucsc/ucscHub.js
+++ b/js/ucsc/ucscHub.js
@@ -24,6 +24,16 @@ class Hub {
const groupsTxtURL = baseURL + genome.getProperty("groups")
groups = await loadStanzas(groupsTxtURL)
}
+
+ // If the genome has a chromSizes file, and it is not too large, set the chromSizesURL property. This will
+ // enable whole genome view and the chromosome pulldown
+ if (genome.hasProperty("chromSizes")) {
+ const chromSizesURL = baseURL + genome.getProperty("chromSizes")
+ const l = await getContentLength(chromSizesURL)
+ if (l !== null && Number.parseInt(l) < 1000000) {
+ genome.setProperty("chromSizesURL", chromSizesURL)
+ }
+ }
}
// TODO -- categorize extra "user" supplied and other tracks in some distinctive way before including them
@@ -126,8 +136,13 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
name: name,
twoBitURL: this.baseURL + this.genomeStanza.getProperty("twoBitPath"),
nameSet: "ucsc",
- wholeGenomeView: false,
- showChromosomeWidget: false
+ }
+
+ if (this.genomeStanza.hasProperty("chromSizesURL")) {
+ config.chromSizesURL = this.genomeStanza.getProperty("chromSizesURL")
+ } else {
+ config.wholeGenomeView = false
+ config.showChromosomeWidget = false
}
if (this.genomeStanza.hasProperty("defaultPos")) {
@@ -419,6 +434,26 @@ class Stanza {
}
}
+
+/**
+ * Return the content length of the resource. If the content length cannot be determined return null;
+ * @param url
+ * @returns {Promise}
+ */
+async function getContentLength(url) {
+ try {
+ const response = await fetch(url, {method: 'HEAD'})
+ const headers = response.headers
+ if (headers.has("content-length")) {
+ return headers.get("content-length")
+ } else {
+ return null
+ }
+ } catch (e) {
+ return null
+ }
+}
+
/**
* Parse a UCSC file
* @param url
diff --git a/js/ui/chromosomeSelectWidget.js b/js/ui/chromosomeSelectWidget.js
index f3f900734..f8d98bb39 100644
--- a/js/ui/chromosomeSelectWidget.js
+++ b/js/ui/chromosomeSelectWidget.js
@@ -47,7 +47,7 @@ class ChromosomeSelectWidget {
})
this.showAllChromosomes = browser.config.showAllChromosomes !== false // i.e. default to true
-
+ this.genome = browser.genome
}
show() {
@@ -58,10 +58,16 @@ class ChromosomeSelectWidget {
this.container.style.display = 'none'
}
+ setValue(chrName) {
+ this.select.value = this.genome.getChromosomeDisplayName(chrName)
+ }
+
update(genome) {
+ this.genome = genome
+
// Start with explicit chromosome name list
- const list = genome.wgChromosomeNames || []
+ const list = genome.wgChromosomeNames.map(nm => genome.getChromosomeDisplayName(nm)) || []
if (this.showAllChromosomes && genome.chromosomeNames.length > 1) {
const exclude = new Set(list)
@@ -72,6 +78,7 @@ class ChromosomeSelectWidget {
break
}
if (!exclude.has(nm)) {
+ nm = genome.getChromosomeDisplayName(nm)
list.push(nm)
}
}