Skip to content

Commit d226689

Browse files
committed
Use indexes wherever possible ...
1 parent 2b418af commit d226689

File tree

10 files changed

+67
-52
lines changed

10 files changed

+67
-52
lines changed

js/bam/bamReader.js

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class BamReader {
2626
}
2727

2828
async readAlignments(chr, bpStart, bpEnd) {
29+
2930
const chrId = await this.#getChrIdx(chr)
3031
const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.config)
3132

@@ -54,27 +55,38 @@ class BamReader {
5455
}
5556

5657
async #getChrIdx(chr) {
57-
const chrToIndex = await this.getChrIndex()
58-
59-
if (!this.chrAliasTable.has(chr)) {
60-
const chromosome = this.genome.getChromosome(chr)
61-
if (chromosome) {
62-
const aliases = chromosome.altNames
63-
for (let a of aliases) {
64-
if (this.chrNames.has(a)) {
65-
this.chrAliasTable.set(chr, a)
66-
}
58+
59+
await this.getHeader()
60+
61+
if (this.chrAliasTable.has(chr)) {
62+
chr = this.chrAliasTable.get(chr)
63+
}
64+
65+
let chrIdx = this.header.chrToIndex[chr]
66+
67+
// Try alias
68+
if (chrIdx === undefined) {
69+
const aliasRecord = await this.genome.getAliasRecord(chr)
70+
let alias
71+
if (aliasRecord) {
72+
const aliases = Object.keys(aliasRecord)
73+
.filter(k => k !== "start" && k !== "end")
74+
.map(k => aliasRecord[k])
75+
.filter(a => this.header.chrToIndex[a])
76+
if (aliases.length > 0) {
77+
alias = aliases[0]
78+
chrIdx = this.header.chrToIndex[aliases[0]]
6779
}
6880
}
69-
if (!this.chrAliasTable.has(chr)) this.chrAliasTable.set(chr, chr)
81+
this.chrAliasTable.set(chr, alias) // alias may be undefined => no alias exists. Setting prevents repeated attempts
7082
}
71-
72-
const queryChr = this.chrAliasTable.get(chr) || chr
73-
74-
const chrId = chrToIndex[queryChr]
75-
return chrId
83+
return chrIdx
7684
}
7785

86+
/**
87+
*
88+
* @returns {Promise<{magicNumer: number, size: number, chrNames: Array, chrToIndex: ({}|*), chrAliasTable: ({}|*)}>}
89+
*/
7890
async getHeader() {
7991
if (!this.header) {
8092
const genome = this.genome
@@ -97,9 +109,8 @@ class BamReader {
97109
}
98110

99111
async getIndex() {
100-
const genome = this.genome
101112
if (!this.index) {
102-
this.index = await loadIndex(this.baiPath, this.config, genome)
113+
this.index = await loadIndex(this.baiPath, this.config, this.genome)
103114
}
104115
return this.index
105116
}

js/browser.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ class Browser {
8282
this.root = DOMUtils.div({class: 'igv-container'})
8383
parentDiv.appendChild(this.root)
8484

85-
86-
8785
// spinner
8886
this.spinner = DOMUtils.div({class: 'igv-loading-spinner-container'})
8987
this.root.appendChild(this.spinner)
@@ -553,7 +551,7 @@ class Browser {
553551
console.warn("No genome or reference object specified")
554552
return
555553
}
556-
const genomeConfig = genomeOrReference //await GenomeUtils.expandReference(this.alert, genomeOrReference)
554+
const genomeConfig = await GenomeUtils.expandReference(this.alert, genomeOrReference)
557555

558556

559557
await this.loadReference(genomeConfig, session.locus)

js/genome/chromAliasBB.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import BWReader from "../bigwig/bwReader.js"
1313

1414
class ChromAliasBB {
1515

16-
chrAliasTable = new Map()
16+
aliasRecordCache = new Map()
1717

1818
constructor(url, config, genome) {
1919
config = config || {}
@@ -28,7 +28,7 @@ class ChromAliasBB {
2828
* @returns {*}
2929
*/
3030
getChromosomeName(alias) {
31-
return this.chrAliasTable.has(alias) ? this.chrAliasTable.get(alias).chr : alias
31+
return this.aliasRecordCache.has(alias) ? this.aliasRecordCache.get(alias).chr : alias
3232
}
3333

3434
/**
@@ -39,27 +39,27 @@ class ChromAliasBB {
3939
*/
4040
getChromosomeAlias(chr, nameSet)
4141
{
42-
const aliasRecord = this.chrAliasTable.get(chr)
42+
const aliasRecord = this.aliasRecordCache.get(chr)
4343
return aliasRecord ? aliasRecord[nameSet] || chr : chr
4444
}
4545

4646
/**
47-
* Search for chromosome alias bed record.
47+
* Search for chromosome alias bed record. If found, catch results in the alias -> chr map
4848
* @param alias
4949
* @returns {Promise<any>}
5050
*/
5151
async search(alias) {
52-
if (!this.chrAliasTable.has(alias)) {
52+
if (!this.aliasRecordCache.has(alias)) {
5353
const aliasRecord = await this.reader.search(alias)
5454
if (aliasRecord) {
5555
for (let key of Object.keys(aliasRecord)) {
5656
if ("start" !== key && "end" !== key) {
57-
this.chrAliasTable.set(aliasRecord[key], aliasRecord)
57+
this.aliasRecordCache.set(aliasRecord[key], aliasRecord)
5858
}
5959
}
6060
}
6161
}
62-
return this.chrAliasTable.get(alias)
62+
return this.aliasRecordCache.get(alias)
6363
}
6464

6565
}

js/genome/chromAliasFile.js

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,53 +14,53 @@ import {igvxhr, StringUtils} from "../../node_modules/igv-utils/src/index.js"
1414

1515
class ChromAliasFile {
1616

17-
aliasToChrMap
17+
aliasRecordCache = new Map()
1818

1919
constructor(aliasURL, config, chromosomes) {
2020
this.aliasURL = aliasURL
2121
this.config = config
2222
this.chromosomes = chromosomes
2323
}
2424

25-
/**
26-
* Initialize the alias table for the canonical chromosome names
27-
*
28-
* @param chromosomes - collection of canonical chromosome names (i.e names as used in the fasta or twobit file)
29-
* @returns {Promise<void>}
30-
*/
31-
async init(chromosomes) {
32-
this.createAliasTable(chromosomes)
33-
}
34-
3525
/**
3626
* Return the canonical chromosome name for the alias. If none found return the alias
3727
*
3828
* @param alias
3929
* @returns {*}
4030
*/
4131
getChromosomeName(alias) {
42-
return this.aliasToChrMap.has(alias) ? this.aliasToChrMap.get(alias).chr : alias
32+
return this.aliasRecordCache.has(alias) ? this.aliasRecordCache.get(alias).chr : alias
4333
}
4434

4535

46-
4736
async loadAliases() {
48-
4937
const data = await igvxhr.loadString(this.aliasURL, buildOptions(this.config))
5038
const lines = StringUtils.splitLines(data)
5139
const firstLine = lines[0]
5240
if (firstLine.startsWith("#")) {
53-
this.headings = line.split("\t").map(h => h.trim())
41+
this.headings = firstLine.split("\t").map(h => h.trim())
5442
this.altNameSets = this.headings.slice(1)
5543
}
5644

57-
const aliases = []
5845
for (let line of lines) {
5946
if (!line.startsWith("#") && line.length > 0) {
60-
aliases.push(line.split("\t"))
47+
const tokens = line.split("\t")
48+
const aliasRecord = {chr: tokens[0]} // TODO -- in IGV alias file format we don't know this
49+
for (let i = 0; i < tokens.length; i++) {
50+
const key = this.headings ? this.headings[i] : i
51+
aliasRecord[key] = tokens[i]
52+
this.aliasRecordCache.set(tokens[i], aliasRecord)
53+
}
6154
}
6255
}
63-
this. aliases = aliases
56+
}
57+
58+
async search(alias) {
59+
if(this.aliasRecordCache.size === 0) {
60+
await this.loadAliases()
61+
}
62+
return this.aliasRecordCache.get(alias)
63+
6464
}
6565
}
6666

js/genome/twobit.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ class TwobitSequence {
3939
} else {
4040
const idx = await this._readIndex()
4141
this.index = {
42-
search: async (name) => {offset: idx.get(name)}
42+
search: async (name) => {
43+
return idx.has(name) ? {offset: idx.get(name)} : undefined
44+
}
4345
}
4446
}
4547
}

test/testGenome.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import "./utils/mockObjects.js"
22
import GenomeUtils from "../js/genome/genomeUtils.js"
33
import {assert} from 'chai'
4-
import {loadCytobandsBB} from "../js/genome/cytoband.js"
54
import CytobandFileBB from "../js/genome/cytobandFileBB.js"
65

76

test/testSearch.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ suite("testSearch", function () {
5151
// Chr name alias
5252
const s2 = "1:100-200"
5353
const locus2 = parseLocusString(browser, s2)
54-
assert.equal(locus2.chr, "chr1")
54+
assert.equal(locus2.chr, "1")
5555
assert.equal(locus2.start, 99)
5656
assert.equal(locus2.end, 200)
5757

@@ -123,8 +123,9 @@ suite("testSearch", function () {
123123

124124
const mockBrowser = {
125125
genome: {
126+
loadChromosome: async (chr) => chr,
126127
getChromosomeName: (chr) => chr,
127-
getChromosome: (chr) => undefined
128+
getChromosome: (chr) => {return {name: chr, bpLenght: 0}}
128129
},
129130
tracks: [{
130131
featureSource: featureSource,

test/testTwobit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ suite("testTwobit", function () {
4949
})
5050

5151
test("twobit metadata", async function () {
52-
const url = "test/data/genomes/GCF_000002655.1.2bit"
52+
const url = "test/data/twobit/GCF_000002655.1.2bit"
5353
const twobit = new TwobitSequence({twoBitURL: url})
5454
await twobit.init()
5555
const sequenceRecord = await twobit.getSequenceRecord("NC_007196.1")

test/testUCSC.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ suite("ucsc utilities", function () {
2727
assert.equal("Python bivittatus", genomeConfig.name)
2828
assert.ok(genomeConfig.twoBitBptURL)
2929
assert.ok(genomeConfig.twoBitURL)
30-
assert.ok(genomeConfig.aliasBbURL)
30+
assert.ok(genomeConfig.chromAliasBbURL)
3131
assert.ok(genomeConfig.cytobandBbURL)
3232
})
3333

test/utils/Genome.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ function createGenome() {
3939
chr.startsWith("chr") ? chr : "chr" + chr
4040
},
4141

42+
loadChromosome: async function (chr) {
43+
return this.getChromosomechr
44+
},
45+
4246
getChromosome: function (chr) {
4347

4448
const name = this.getChromosomeName(chr)

0 commit comments

Comments
 (0)