diff --git a/dev/annotation/annotation.html b/dev/annotation/annotation.html index b98c2fce6..edf78c37d 100644 --- a/dev/annotation/annotation.html +++ b/dev/annotation/annotation.html @@ -37,6 +37,14 @@

Annotation tracks

"supportsWholeGenome": true, "name": "Bed - No Index" }, + { + "type": "annotation", + "format": "bigBed", + "url": "../../genes.bb", + "indexed": false, + "supportsWholeGenome": true, + "name": "Bed - No Index" + }, { "type": "annotation", "format": "bed", diff --git a/dev/twobit/twobit.html b/dev/twobit/twobit.html index f87f2a2fa..b7568e751 100644 --- a/dev/twobit/twobit.html +++ b/dev/twobit/twobit.html @@ -18,7 +18,7 @@ reference: { id: "GCF_016699485.2", format: "2bit", - twobitURL: "https://hgdownload.gi.ucsc.edu/hubs//GCA/011/100/615/GCA_011100615.1/GCA_011100615.1.2bit", + twoBitURL: "https://hgdownload.gi.ucsc.edu/hubs//GCA/011/100/615/GCA_011100615.1/GCA_011100615.1.2bit", aliasBbURL: "https://hgdownload.gi.ucsc.edu/hubs//GCA/011/100/615/GCA_011100615.1/GCA_011100615.1.chromAlias.bb", nameSet: "ucsc", wholeGenomeView: false diff --git a/dev/twobit/twobit_aliasBB.html b/dev/twobit/twobit_aliasBB.html new file mode 100644 index 000000000..ca25a799a --- /dev/null +++ b/dev/twobit/twobit_aliasBB.html @@ -0,0 +1,52 @@ + + + + twobit + + + + +
+ + + + + + diff --git a/dev/twobit/twobit_basic.html b/dev/twobit/twobit_basic.html new file mode 100644 index 000000000..909d16e65 --- /dev/null +++ b/dev/twobit/twobit_basic.html @@ -0,0 +1,50 @@ + + + + twobit + + + + +
+ + + + + + diff --git a/dev/twobit/twobit_chromSizes.html b/dev/twobit/twobit_chromSizes.html index 7e5280fc3..6962b8e4c 100644 --- a/dev/twobit/twobit_chromSizes.html +++ b/dev/twobit/twobit_chromSizes.html @@ -18,7 +18,7 @@ reference: { id: "GCF_016699485.2", format: "2bit", - twobitURL: "https://hgdownload.gi.ucsc.edu/hubs//GCA/011/100/615/GCA_011100615.1/GCA_011100615.1.2bit", + twoBitURL: "https://hgdownload.gi.ucsc.edu/hubs//GCA/011/100/615/GCA_011100615.1/GCA_011100615.1.2bit", chromeSizes: "https://hgdownload.gi.ucsc.edu/hubs//GCA/011/100/615/GCA_011100615.1/GCA_011100615.1.chrom.sizes.txt", wholeGenomeView: false } diff --git a/dev/twobit/twobit_t2t.html b/dev/twobit/twobit_t2t.html index a999a4acb..078bd9bd3 100644 --- a/dev/twobit/twobit_t2t.html +++ b/dev/twobit/twobit_t2t.html @@ -14,60 +14,69 @@ const config = { - locus: "myc", + //locus: "myc", + locus:"CP068269.2:35,726,976-35,734,192", + showChromosomeWidget: false, reference: { - "id": "chm13v2.0", - "name": "Human (T2T CHM13-v2.0)", - "fastaURL": "https://s3.amazonaws.com/igv.org.genomes/chm13v2.0/chm13v2.0.fa", - "indexURL": "https://s3.amazonaws.com/igv.org.genomes/chm13v2.0/chm13v2.0.fa.fai", - "cytobandURL": "https://s3.amazonaws.com/igv.org.genomes/chm13v2.0/CHM13_v2.0.cytoBandMapped.bed", - "aliasURL": "https://s3.amazonaws.com/igv.org.genomes/chm13v2.0/GCA_009914755.4.chromAlias.txt", - twobitURL: "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/GCA_009914755.4.2bit", + wholeGenomeView: false, + id: "chm13v2.0", + name: "Human (T2T CHM13-v2.0)", + twoBitURL: "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/GCA_009914755.4.2bit", cytobandBbURL: "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/bbi/GCA_009914755.4_T2T-CHM13v2.0.cytoBandMapped/cytoBandMapped.bb", - aliasBbURL: "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/GCA_009914755.4.chromAlias.bb", + chromAliasBbURL: "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/GCA_009914755.4.chromAlias.bb", nameSet: "ucsc", - "tracks": [ + tracks: [ + // { + // "id": "catLiftOffGenesV1", + // "name": "CAT/Liftoff Genes", + // "format": "bigbed", + // "description": " CAT + Liftoff Gene Annotations", + // "url": "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/bbi/GCA_009914755.4_T2T-CHM13v2.0.catLiftOffGenesV1/catLiftOffGenesV1.bb", + // "displayMode": "EXPANDED", + // "height": 200, + // "visibilityWindow": -1, + // "supportsWholeGenome": false + // }, + // + // // Include a hg38 bigwig track -- test chromosome aliasing + // { + // "url": "https://www.encodeproject.org/files/ENCFF754TJH/@@download/ENCFF754TJH.bigWig", + // "name": "Encode bigwig", + // }, + + // plain wig track + { + url: "../../test/data/hubs/ENCFF754TJH.wig", + name: "Encode wig" + }, + + // plain bed track { - "id": "catLiftOffGenesV1", - "name": "CAT/Liftoff Genes", - "format": "bigbed", - "description": " CAT + Liftoff Gene Annotations", - "url": "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/bbi/GCA_009914755.4_T2T-CHM13v2.0.catLiftOffGenesV1/catLiftOffGenesV1.bb", - "displayMode": "EXPANDED", - "height": 200, - "visibilityWindow": -1, - "supportsWholeGenome": false, - "order": 1000000 + url: "../../test/data/hubs/catLiftOff.bed", + name: "plain bed" }, + + // indexed bed track { - "id": "augustus", - "name": "Augustus", - "format": "bigbed", - "description": " Augustus Gene Predictions", - "url": "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/bbi/GCA_009914755.4_T2T-CHM13v2.0.augustus.bb", - "displayMode": "EXPANDED", - "color": "180,0,0", - "height": 200, - "visibilityWindow": -1, - "supportsWholeGenome": false, - "order": 1000001 + url: "../../test/data/hubs/catLiftOff.bed.gz", + indexUrl: "../../test/data/hubs/catLiftOff.bed.gz.tbi", + name: "indexed bed" }, + + //bam { - "name": "Genes", - "format": "bed", - "url": "https://s3.amazonaws.com/igv.org.genomes/chm13v2.0/chm13v2.0_geneLocations.short.bed.gz", - "hidden" : true, - "searchable": true + type: "alignment", + url: "https://1000genomes.s3.amazonaws.com/phase3/data/NA19625/exome_alignment/NA19625.mapped.ILLUMINA.bwa.ASW.exome.20120522.bam", + indexURL: "https://1000genomes.s3.amazonaws.com/phase3/data/NA19625/exome_alignment/NA19625.mapped.ILLUMINA.bwa.ASW.exome.20120522.bam.bai", + name: "NA12878n" } ] } } - igv.createBrowser(document.getElementById('igvDiv'), config) - .then(browser => { + const browser = await igv.createBrowser(document.getElementById('igvDiv'), config) - }) diff --git a/dev/twobit/twobithg38.html b/dev/twobit/twobithg38.html index 5baaccb90..85ddca1f3 100644 --- a/dev/twobit/twobithg38.html +++ b/dev/twobit/twobithg38.html @@ -24,7 +24,7 @@ "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", - "twobitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.2bit", + "twoBitURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.2bit", "aliasBbURL": "https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.chromAlias.bb", "tracks": [ { diff --git a/dev/ucsc/hub.html b/dev/ucsc/hub.html index 2f9dd8a65..5cc243574 100644 --- a/dev/ucsc/hub.html +++ b/dev/ucsc/hub.html @@ -35,7 +35,7 @@ const hubOptions = { - url: "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/hub.txt", + url: "https://hgdownload.soe.ucsc.edu/hubs/GCA/018/471/515/GCA_018471515.1/hub.txt", includeTracks: "all" } @@ -45,6 +45,7 @@ const igvConfig = { locus: hub.getDefaultPosition(), + showChromosomeWidget: false, reference: ref } diff --git a/dev/ucsc/slowHub.html b/dev/ucsc/slowHub.html index 5857a5530..a74d865d8 100644 --- a/dev/ucsc/slowHub.html +++ b/dev/ucsc/slowHub.html @@ -22,21 +22,16 @@ const hub = await Hub.loadHub(hubOptions) - const ref = hub.getGenomeConfig() const igvConfig = { + showChromosomeWidget: false, locus: hub.getDefaultPosition(), - reference: ref + reference: hub.getGenomeConfig() } - const browser = await igv.createBrowser(document.getElementById('igvDiv'), igvConfig) + //igvConfig.reference.chromAliasBbURL = undefined // TODO <- chromAliasBB is slowish - const selector = document.getElementById("select") - selector.addEventListener("change", () => document.getElementById("hub-input").value = selector.value) - 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})) + const browser = await igv.createBrowser(document.getElementById('igvDiv'), igvConfig) diff --git a/dev/wig/bigWigs.html b/dev/wig/bigWigs.html index 6a372da20..18f8c05b2 100644 --- a/dev/wig/bigWigs.html +++ b/dev/wig/bigWigs.html @@ -29,17 +29,17 @@ "Bar": 999.999 } }, - { - "url": "https://www.encodeproject.org/files/ENCFF754TJH/@@download/ENCFF754TJH.bigWig", - "graphType": "points", - "pointSize": 3, - "name": "Encode bigwig points" - }, - { - "url": "https://www.encodeproject.org/files/ENCFF754TJH/@@download/ENCFF754TJH.bigWig", - "graphType": "line", - "name": "Encode bigwig line" - }, + // { + // "url": "https://www.encodeproject.org/files/ENCFF754TJH/@@download/ENCFF754TJH.bigWig", + // "graphType": "points", + // "pointSize": 3, + // "name": "Encode bigwig points" + // }, + // { + // "url": "https://www.encodeproject.org/files/ENCFF754TJH/@@download/ENCFF754TJH.bigWig", + // "graphType": "line", + // "name": "Encode bigwig line" + // }, { "url": "https://s3-us-west-2.amazonaws.com/ilmn.igv-test/test2.bigWig", color: 'rgb(0,0,255)', diff --git a/js/bam/bamReader.js b/js/bam/bamReader.js index 071e1682b..a7be50b96 100644 --- a/js/bam/bamReader.js +++ b/js/bam/bamReader.js @@ -1,29 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2016-2017 The Regents of the University of California - * Author: Jim Robinson - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - import {loadIndex} from "./indexFactory.js" import AlignmentContainer from "./alignmentContainer.js" import BamUtils from "./bamUtils.js" @@ -39,6 +13,8 @@ import BGZBlockLoader from "./bgzBlockLoader.js" */ class BamReader { + chrAliasTable = new Map() + constructor(config, genome) { this.config = config this.genome = genome @@ -51,9 +27,7 @@ class BamReader { async readAlignments(chr, bpStart, bpEnd) { - const chrToIndex = await this.getChrIndex() - const queryChr = this.chrAliasTable.hasOwnProperty(chr) ? this.chrAliasTable[chr] : chr - const chrId = chrToIndex[queryChr] + const chrId = await this.#getChrIdx(chr) const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.config) if (chrId === undefined) { @@ -70,7 +44,7 @@ class BamReader { for (let c of chunks) { const ba = await this._blockLoader.getData(c.minv, c.maxv) - const done = BamUtils.decodeBamRecords(ba, c.minv.offset, alignmentContainer, this.indexToChr, chrId, bpStart, bpEnd, this.filter) + const done = BamUtils.decodeBamRecords(ba, c.minv.offset, alignmentContainer, this.header.chrNames, chrId, bpStart, bpEnd, this.filter) if (done) { break } @@ -80,6 +54,42 @@ class BamReader { } } + async #getChrIdx(chr) { + + await this.getHeader() + + if (this.chrAliasTable.has(chr)) { + chr = this.chrAliasTable.get(chr) + if (chr === undefined) { + return undefined + } + } + + let chrIdx = this.header.chrToIndex[chr] + + // Try alias + if (chrIdx === undefined) { + const aliasRecord = await this.genome.getAliasRecord(chr) + let alias + if (aliasRecord) { + const aliases = Object.keys(aliasRecord) + .filter(k => k !== "start" && k !== "end") + .map(k => aliasRecord[k]) + .filter(a => this.header.chrToIndex[a]) + if (aliases.length > 0) { + alias = aliases[0] + chrIdx = this.header.chrToIndex[aliases[0]] + } + } + this.chrAliasTable.set(chr, alias) // alias may be undefined => no alias exists. Setting prevents repeated attempts + } + return chrIdx + } + + /** + * + * @returns {Promise<{magicNumer: number, size: number, chrNames: Array, chrToIndex: ({}|*), chrAliasTable: ({}|*)}>} + */ async getHeader() { if (!this.header) { const genome = this.genome @@ -102,9 +112,8 @@ class BamReader { } async getIndex() { - const genome = this.genome if (!this.index) { - this.index = await loadIndex(this.baiPath, this.config, genome) + this.index = await loadIndex(this.baiPath, this.config, this.genome) } return this.index } @@ -116,7 +125,7 @@ class BamReader { const header = await this.getHeader() this.chrToIndex = header.chrToIndex this.indexToChr = header.chrNames - this.chrAliasTable = header.chrAliasTable + this.chrNames = new Set(header.chrNames) return this.chrToIndex } diff --git a/js/bam/bamReaderNonIndexed.js b/js/bam/bamReaderNonIndexed.js index f210659e9..1819af123 100644 --- a/js/bam/bamReaderNonIndexed.js +++ b/js/bam/bamReaderNonIndexed.js @@ -37,6 +37,8 @@ import {buildOptions, isDataURL} from "../util/igvUtils.js" */ class BamReaderNonIndexed { + chrAliasTable = new Map() + constructor(config, genome) { this.config = config this.genome = genome @@ -45,52 +47,75 @@ class BamReaderNonIndexed { BamUtils.setReaderDefaults(this, config) } - // Return an alignment container + /** + * + * @param chr + * @param bpStart + * @param bpEnd + * @returns {Promise} + */ async readAlignments(chr, bpStart, bpEnd) { - if (this.alignmentCache) { - const header = this.header - const queryChr = header.chrAliasTable.hasOwnProperty(chr) ? header.chrAliasTable[chr] : chr - const qAlignments = this.alignmentCache.queryFeatures(queryChr, bpStart, bpEnd) - const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.config) - for (let a of qAlignments) { - alignmentContainer.push(a) - } - alignmentContainer.finish() - return alignmentContainer - - } else { + if (!this.alignmentCache) { + // For a non-indexed BAM file all alignments are read at once and cached. + let unc if (this.isDataUri) { const data = decodeDataURI(this.bamPath) - const unc = BGZip.unbgzf(data.buffer) - this.parseAlignments(unc) - return this.fetchAlignments(chr, bpStart, bpEnd) + unc = BGZip.unbgzf(data.buffer) } else { const arrayBuffer = await igvxhr.loadArrayBuffer(this.bamPath, buildOptions(this.config)) - const unc = BGZip.unbgzf(arrayBuffer) - this.parseAlignments(unc) - return this.fetchAlignments(chr, bpStart, bpEnd) + unc = BGZip.unbgzf(arrayBuffer) } + this.alignmentCache = this.#parseAlignments(unc) } + const queryChr = await this.#getQueryChr(chr) + const qAlignments = this.alignmentCache.queryFeatures(queryChr, bpStart, bpEnd) + const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.config) + for (let a of qAlignments) { + alignmentContainer.push(a) + } + alignmentContainer.finish() + return alignmentContainer } - parseAlignments(data) { + #parseAlignments(data) { const alignments = [] this.header = BamUtils.decodeBamHeader(data) - BamUtils. decodeBamRecords(data, this.header.size, alignments, this.header.chrNames) - this.alignmentCache = new FeatureCache(alignments, this.genome) + BamUtils.decodeBamRecords(data, this.header.size, alignments, this.header.chrNames) + return new FeatureCache(alignments, this.genome) } - fetchAlignments(chr, bpStart, bpEnd) { - const queryChr = this.header.chrAliasTable.hasOwnProperty(chr) ? this.header.chrAliasTable[chr] : chr - const features = this.alignmentCache.queryFeatures(queryChr, bpStart, bpEnd) - const alignmentContainer = new AlignmentContainer(chr, bpStart, bpEnd, this.config) - for (let feature of features) { - alignmentContainer.push(feature) + async #getQueryChr(chr) { + + const ownNames = new Set(this.header.chrNames) + if (ownNames.has(chr)) { + return chr } - alignmentContainer.finish() - return alignmentContainer + + if (this.chrAliasTable.has(chr)) { + return this.chrAliasTable.get(chr) + } + + // Try alias + + if (this.genome) { + const aliasRecord = await this.genome.getAliasRecord(chr) + let alias + if (aliasRecord) { + const aliases = Object.keys(aliasRecord) + .filter(k => k !== "start" && k !== "end") + .map(k => aliasRecord[k]) + .filter(a => ownNames.has(a)) + if (aliases.length > 0) { + alias = aliases[0] + } + } + this.chrAliasTable.set(chr, alias) // alias may be undefined => no alias exists. Setting prevents repeated attempts + return alias + } + + return chr } } diff --git a/js/bam/bamUtils.js b/js/bam/bamUtils.js index b847a55cd..5f1faacd4 100644 --- a/js/bam/bamUtils.js +++ b/js/bam/bamUtils.js @@ -51,23 +51,11 @@ const MAXIMUM_SAMPLING_DEPTH = 10000 const BamUtils = { - readHeader: function (url, options, genome) { - - return igvxhr.loadArrayBuffer(url, options) - - .then(function (compressedBuffer) { - - var header, unc, uncba - - unc = BGZip.unbgzf(compressedBuffer) - uncba = unc - - header = BamUtils.decodeBamHeader(uncba, genome) - - return header - - }) + readHeader: async function (url, options, genome) { + const compressedBuffer = await igvxhr.loadArrayBuffer(url, options) + const uncba = BGZip.unbgzf(compressedBuffer) + return BamUtils.decodeBamHeader(uncba, genome) }, /** @@ -97,7 +85,6 @@ const BamUtils = { chrToIndex = {} chrNames = [] - chrAliasTable = {} for (i = 0; i < nRef; ++i) { var lName = readInt(ba, p) @@ -111,11 +98,6 @@ const BamUtils = { chrToIndex[name] = i chrNames[i] = name - if (genome) { - alias = genome.getChromosomeName(name) - chrAliasTable[alias] = name - } - p = p + 8 + lName } @@ -123,8 +105,7 @@ const BamUtils = { magicNumber: magic, size: p, chrNames: chrNames, - chrToIndex: chrToIndex, - chrAliasTable: chrAliasTable + chrToIndex: chrToIndex } }, diff --git a/js/bigwig/bpTree.js b/js/bigwig/bpTree.js index 50f3dcf04..0d996568d 100644 --- a/js/bigwig/bpTree.js +++ b/js/bigwig/bpTree.js @@ -10,6 +10,8 @@ import BinaryParser from "../binary.js" */ export default class BPTree { + nodeCache = new Map() + static async loadBpTree(path, startOffset) { const bpTree = new BPTree(path, startOffset) return bpTree.init() @@ -37,52 +39,89 @@ export default class BPTree { const {keySize, valSize} = this.header - if (valSize !== 16) { - throw Error(`Unexpected valSize: ${valSize}`) + if (!(valSize === 16 || valSize === 8)) { + throw Error(`Unexpected valSize ${valSize}`) } const readTreeNode = async (offset) => { - let binaryParser = await this.#getParserFor(offset, 4) - const type = binaryParser.getByte() - const reserved = binaryParser.getByte() - const count = binaryParser.getUShort() + if (this.nodeCache.has(offset)) { + return this.nodeCache.get(offset) + } else { + + let binaryParser = await this.#getParserFor(offset, 4) + const type = binaryParser.getByte() + const reserved = binaryParser.getByte() + const count = binaryParser.getUShort() + const items = [] + + if (type === 1) { + // Leaf node + const size = count * (keySize + valSize) + binaryParser = await this.#getParserFor(offset + 4, size) + for (let i = 0; i < count; i++) { + const key = binaryParser.getFixedLengthString(keySize) + const offset = binaryParser.getLong() + + let value + if (valSize === 16) { + const length = binaryParser.getInt() + binaryParser.getInt() + value = {offset, length} + } else { + value = {offset} + } + items.push({key, value}) + } + } else { + // Non leaf node + const size = count * (keySize + 8) + binaryParser = await this.#getParserFor(offset + 4, size) + + for (let i = 0; i < count; i++) { + const key = binaryParser.getFixedLengthString(keySize) + const offset = binaryParser.getLong() + items.push({key, offset}) + } + } + + const node = {type, count, items} + this.nodeCache.set(offset, node) + return node + } + } + + const walkTreeNode = async (offset) => { + + const node = await readTreeNode(offset) - if (type === 1) { + if (node.type === 1) { // Leaf node - const size = count * (keySize + valSize) - binaryParser = await this.#getParserFor(offset + 4, size) - for (let i = 0; i < count; i++) { - const key = binaryParser.getFixedLengthString(keySize) - const offset = binaryParser.getLong() - const length = binaryParser.getInt() - const reserved = binaryParser.getInt() - const value = {offset, length} - if (term === key) return value + for (let item of node.items) { + if (term === item.key) { + return item.value + } } } else { // Non leaf node - const size = count * (keySize + 8) - binaryParser = await this.#getParserFor(offset + 4, size) // Read and discard the first key. - const firstKey = binaryParser.getFixedLengthString(keySize) - let childOffset = binaryParser.getLong() + let childOffset = node.items[0].offset - for (let i = 1; i < count; i++) { - const key = binaryParser.getFixedLengthString(keySize) + for (let i = 1; i < node.items.length; i++) { + const key = node.items[i].key if (term.localeCompare(key) < 0) { break } - childOffset = binaryParser.getLong() + childOffset = node.items[i].offset } - return readTreeNode(childOffset) + return walkTreeNode(childOffset) } } // Kick things off - return readTreeNode(this.header.nodeOffset) + return walkTreeNode(this.header.nodeOffset) } async #getParserFor(start, size) { diff --git a/js/bigwig/bwReader.js b/js/bigwig/bwReader.js index 594471e50..baa3b01b0 100644 --- a/js/bigwig/bwReader.js +++ b/js/bigwig/bwReader.js @@ -45,11 +45,13 @@ const BUFFER_SIZE = 512000 // buffer class BWReader { + chrAliasTable = new Map() + rpTreeCache = new Map() + constructor(config, genome) { this.path = config.url this.format = config.format || "bigwig" this.genome = genome - this.rpTreeCache = {} this.config = config this.bufferSize = BUFFER_SIZE this.loader = isDataURL(this.path) ? @@ -74,9 +76,14 @@ class BWReader { async readFeatures(chr1, bpStart, chr2, bpEnd, bpPerPixel, windowFunction = "mean") { + if (!bpStart) bpStart = 0 + if (!bpEnd) bpEnd = Number.MAX_SAFE_INTEGER + await this.loadHeader() - const chrIdx1 = this.chromTree.nameToId[chr1] - const chrIdx2 = this.chromTree.nameToId[chr2] + + let chrIdx1 = await this.#getIdForChr(chr1) + let chrIdx2 = await this.#getIdForChr(chr2) + if (chrIdx1 === undefined || chrIdx2 === undefined) { return [] } @@ -153,6 +160,42 @@ class BWReader { } } + /** + * Return the ID for the given chromosome name. If there is no direct match, search for a chromosome alias. + * + * @param chr + * @returns {Promise<*>} + */ + async #getIdForChr(chr) { + + if (this.chrAliasTable.has(chr)) { + chr = this.chrAliasTable.get(chr) + if (chr === undefined) { + return undefined + } + } + + let chrIdx = this.chromTree.nameToId.get(chr) + + // Try alias + if (chrIdx === undefined) { + const aliasRecord = await this.genome.getAliasRecord(chr) + let alias + if (aliasRecord) { + const aliases = Object.keys(aliasRecord) + .filter(k => k !== "start" && k !== "end") + .map(k => aliasRecord[k]) + .filter(a => this.chromTree.nameToId.has(a)) + if (aliases.length > 0) { + alias = aliases[0] + chrIdx = this.chromTree.nameToId.get(aliases[0]) + } + } + this.chrAliasTable.set(chr, alias) // alias may be undefined => no alias exists. Setting prevents repeated attempts + } + return chrIdx + } + /** * Potentially searchable if a bigbed source. Bigwig files are not searchable. @@ -205,28 +248,23 @@ class BWReader { async _searchForRegions(term) { const searchTrees = await this.#getSearchTrees() if (searchTrees) { - // First try search term as entered. For now take the first one, we don't support multiple results + + // Use a trix index if we have one to map entered term to indexed value in bb file + if (this._trix) { + const termLower = term.toLowerCase() + const trixResults = await this._trix.search(termLower) + if (trixResults && trixResults.has(termLower)) { // <= exact matches only for now + term = trixResults.get(termLower)[0] + } + } + + // For now take the first match, we don't support multiple results for (let bpTree of searchTrees) { const result = await bpTree.search(term) if (result) { return result } } - - // If no term use a trix index if we have one to map entered term to indexed value in bb file - if (this._trix) { - term = term.toLowerCase() - const trixResults = await this._trix.search(term) - if (trixResults && trixResults.has(term)) { // <= exact matches only for now - const term2 = trixResults.get(term)[0] - for (let bpTree of searchTrees) { - const result = await bpTree.search(term2) - if (result) { - return result - } - } - } - } } } @@ -346,6 +384,7 @@ class BWReader { if (header.chromTreeOffset > 0) { binaryParser.position = header.chromTreeOffset - startOffset this.chromTree = await ChromTree.parseTree(binaryParser, startOffset, this.genome) + this.chrNames = new Set(this.chromTree.idToName) } else { // TODO -- this is an error, not expected throw "BigWig chromosome tree offset <= 0" @@ -382,7 +421,7 @@ class BWReader { const extensionSize = binaryParser.getUShort() const extraIndexCount = binaryParser.getUShort() const extraIndexListOffset = binaryParser.getLong() - if(extraIndexCount === 0) return + if (extraIndexCount === 0) return let sz = extraIndexCount * (2 + 2 + 8 + 4 + 10 * (2 + 2)) data = await this.loader.loadArrayBuffer(this.path, buildOptions(this.config, { @@ -409,6 +448,10 @@ class BWReader { for (let j = 0; j < fc; j++) { const fieldId = binaryParser.getUShort() + + //const field = this.autoSql.fields[fieldId] + //console.log(field) + reserved.push(binaryParser.getUShort()) } } @@ -418,13 +461,13 @@ class BWReader { async loadRPTree(offset) { - let rpTree = this.rpTreeCache[offset] + let rpTree = this.rpTreeCache.get(offset) if (rpTree) { return rpTree } else { rpTree = new RPTree(offset, this.config, this.littleEndian, this.loader) await rpTree.load() - this.rpTreeCache[offset] = rpTree + this.rpTreeCache.set(offset, rpTree) return rpTree } } @@ -447,10 +490,11 @@ class BWReader { if (this.type === "bigwig") { this.visibilityWindow = -1 } else { - // bigbed - let genomeSize = this.genome ? this.genome.getGenomeLength() : 3088286401 + this.visibilityWindow = -1 + // bigbed -- todo, we can't know genome length. + //let genomeSize = this.genome ? this.genome.getGenomeLength() : 3088286401 // Estimate window size to return ~ 1,000 features, assuming even distribution across the genome - this.visibilityWindow = header.dataCount < 1000 ? -1 : 1000 * (genomeSize / header.dataCount) + //this.visibilityWindow = header.dataCount < 1000 ? -1 : 1000 * (genomeSize / header.dataCount) } } diff --git a/js/bigwig/chromTree.js b/js/bigwig/chromTree.js index 79a1e33b8..2bf7f05a4 100644 --- a/js/bigwig/chromTree.js +++ b/js/bigwig/chromTree.js @@ -27,7 +27,7 @@ export default class ChromTree { const reserved = binaryParser.getLong() const header = {magic, blockSize, keySize, valSize, itemCount, reserved} - const nameToId = {} + const nameToId = new Map() const idToName = [] const readTreeNode = (offset) => { @@ -45,7 +45,7 @@ export default class ChromTree { value = binaryParser.getInt() const chromSize = binaryParser.getInt() if (genome) key = genome.getChromosomeName(key) // Translate to canonical chr name - nameToId[key] = value + nameToId.set(key, value) idToName[value] = key } else { diff --git a/js/bigwig/trix.js b/js/bigwig/trix.js index 1360bd656..8129bf4ef 100644 --- a/js/bigwig/trix.js +++ b/js/bigwig/trix.js @@ -8,6 +8,7 @@ import {igvxhr} from "../../node_modules/igv-utils/src/index.js" + // this is the number of hex characters to use for the address in ixixx, see // https://github.com/GMOD/ixixx-js/blob/master/src/index.ts#L182 const ADDRESS_SIZE = 10 @@ -16,7 +17,7 @@ export default class Trix { ixFile // URL to the ix file ixxFile // URL to the ixx file - ixBuffer // Buffer for the ix file contents -- we read it once, they aren't very large + bufferCache = new Map() constructor(ixxFile, ixFile) { this.ixFile = ixFile @@ -50,6 +51,7 @@ 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) { @@ -65,6 +67,7 @@ export default class Trix { const [term, ...parts] = m.split(' ') results.set(term, parts.map(p => p.split(',')[0])) } + console.log(results) return results } } @@ -94,10 +97,6 @@ export default class Trix { async _getBuffer(searchWord, opts) { - if (!this.ixBuffer) { - this.ixBuffer = await igvxhr.loadString(this.ixFile) - } - let start = 0 let end = 65536 const indexes = await this.getIndex(opts) @@ -116,6 +115,13 @@ export default class Trix { return undefined } - return this.ixBuffer.slice(start, start + len) + if(this.bufferCache.has(start)) { + return this.bufferCache.get(start) + } else { + const buffer = igvxhr.loadString(this.ixFile, {range: {start, size: len}}) + this.bufferCache.set(start, buffer) + return buffer + } + } } diff --git a/js/browser.js b/js/browser.js index 60fa217eb..637794097 100755 --- a/js/browser.js +++ b/js/browser.js @@ -54,6 +54,8 @@ import {translateSession} from "./hic/shoeboxUtils.js" import Hub from "./ucsc/ucscHub.js" import MultiTrackSelectButton from "./ui/multiTrackSelectButton.js" import MenuUtils from "./ui/menuUtils.js" +import Genome from "./genome/genome.js" +import {setDefaults} from "./igv-create.js" // css - $igv-scrollbar-outer-width: 14px; const igv_scrollbar_outer_width = 14 @@ -81,8 +83,6 @@ class Browser { this.root = DOMUtils.div({class: 'igv-container'}) parentDiv.appendChild(this.root) - - // spinner this.spinner = DOMUtils.div({class: 'igv-loading-spinner-container'}) this.root.appendChild(this.spinner) @@ -234,10 +234,7 @@ class Browser { // chromosome select widget this.chromosomeSelectWidget = new ChromosomeSelectWidget(this, $genomicLocation.get(0)) - if (undefined === config.showChromosomeWidget) { - config.showChromosomeWidget = true // Default to true - } - if (true === config.showChromosomeWidget) { + if (config.showChromosomeWidget !== false) { this.chromosomeSelectWidget.show() } else { this.chromosomeSelectWidget.hide() @@ -458,6 +455,9 @@ class Browser { */ async loadSession(options) { + // UCSC hub hack + const chromosomeSelectWidget = this.chromosomeSelectWidget + this.sampleInfo.initialize() // TODO: deprecated @@ -494,12 +494,17 @@ class Browser { } else if (filename.endsWith("hub.txt")) { const hub = await Hub.loadHub(options) + if(chromosomeSelectWidget) { + chromosomeSelectWidget.hide() + } const genomeConfig = hub.getGenomeConfig(options.includeTracks) const initialLocus = hub.getDefaultPosition() - return { + const config = { + showChromosomeWidget: false, locus: initialLocus, reference: genomeConfig } + return setDefaults(config) } else if (filename.endsWith(".json")) { return igvxhr.loadJson(urlOrFile) } else { @@ -519,6 +524,7 @@ class Browser { // prepare to load a new session, discarding DOM and state this.cleanHouseForSession() + this.config = session // Check for juicebox session if (session.browsers) { @@ -557,7 +563,9 @@ class Browser { console.warn("No genome or reference object specified") return } - const genomeConfig = await GenomeUtils.expandReference(this.alert, genomeOrReference) + const genomeConfig = StringUtils.isString(genomeOrReference) ? + await GenomeUtils.expandReference(this.alert, genomeOrReference) : + genomeOrReference await this.loadReference(genomeConfig, session.locus) @@ -683,7 +691,7 @@ class Browser { */ async loadReference(genomeConfig, initialLocus) { - const genome = await GenomeUtils.loadGenome(genomeConfig) + const genome = await Genome.loadGenome(genomeConfig) const genomeChange = undefined === this.genome || (this.genome.id !== genome.id) @@ -739,7 +747,9 @@ class Browser { 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) - this.chromosomeSelectWidget.update(genome) + if(this.config.showChromosomeWidget !== false) { + this.chromosomeSelectWidget.update(genome) + } } /** @@ -756,7 +766,7 @@ class Browser { const hub = await Hub.loadHub(idOrConfig) genomeConfig = hub.getGenomeConfig("genes") } else { - genomeConfig = await GenomeUtils.expandReference(this.alert, idOrConfig) + genomeConfig = idOrConfig //await GenomeUtils.expandReference(this.alert, idOrConfig) } await this.loadReference(genomeConfig, undefined) @@ -1454,8 +1464,11 @@ class Browser { this.chromosomeSelectWidget.select.value = referenceFrameList.length === 1 ? this.referenceFrameList[0].chr : '' + + const loc = this.referenceFrameList.map(rf => rf.getLocusString()).join(' ') - //const loc = this.referenceFrameList.length === 1 ? this.referenceFrameList[0].getLocusString() : ''; + + this.$searchInput.val(loc) this.fireEvent('locuschange', [this.referenceFrameList]) @@ -2282,16 +2295,5 @@ function toggleTrackLabels(trackViews, isVisible) { } } -async function searchWebService(browser, locus, searchConfig) { - - let path = searchConfig.url.replace("$FEATURE$", locus.toUpperCase()) - if (path.indexOf("$GENOME$") > -1) { - path = path.replace("$GENOME$", (browser.genome.id ? browser.genome.id : "hg19")) - } - const result = await igvxhr.loadString(path) - return {result: result, locusSearchString: locus} -} - -export {searchWebService} export default Browser diff --git a/js/cram/cramReader.js b/js/cram/cramReader.js index 5abddeee1..9e9e7ad86 100644 --- a/js/cram/cramReader.js +++ b/js/cram/cramReader.js @@ -1,28 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 The Regents of the University of California - * Author: Jim Robinson - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ import gmodCRAM from "../vendor/cram-bundle.js" import AlignmentContainer from "../bam/alignmentContainer.js" @@ -46,6 +21,7 @@ const CRAM_MATE_MAPPED_FLAG = 0x2 */ class CramReader { + chrAliasTable = new Map() constructor(config, genome, browser) { this.config = config @@ -69,35 +45,26 @@ class CramReader { BamUtils.setReaderDefaults(this, config) - function seqFetch(seqID, start, end) { - + async function seqFetch(seqID, start, end) { const sequence = this.genome.sequence const genome = this.genome - - return this.getHeader() - .then(function (header) { - const chr = genome.getChromosomeName(header.chrNames[seqID]) - return sequence.getSequence(chr, start - 1, end) - }) + const header = await this.getHeader() + const chr = genome.getChromosomeName(header.indexToChr[seqID]) + return sequence.getSequence(chr, start - 1, end) } } /** - * Parse the sequence dictionary from the SAM header and build chr name tables. This function - * is public so it can be unit tested. - * - * @returns {PromiseLike} + * Parse the sequence dictionary from the SAM header and build chr name tables. */ async getHeader() { if (!this.header) { - const genome = this.genome const samHeader = await this.cramFile.getSamHeader() const chrToIndex = {} - const chrNames = [] - const chrAliasTable = {} + const indexToChr = [] const readGroups = [] for (let line of samHeader) { @@ -105,12 +72,8 @@ class CramReader { for (let d of line.data) { if (d.tag === "SN") { const seq = d.value - chrToIndex[seq] = chrNames.length - chrNames.push(seq) - if (genome) { - const alias = genome.getChromosomeName(seq) - chrAliasTable[alias] = seq - } + chrToIndex[seq] = indexToChr.length + indexToChr.push(seq) break } } @@ -120,10 +83,11 @@ class CramReader { } this.header = { - chrNames: chrNames, + indexToChr: indexToChr, chrToIndex: chrToIndex, - chrAliasTable: chrAliasTable, + chrNames: new Set(header.chrToIndex), readGroups: readGroups + } } @@ -132,7 +96,18 @@ class CramReader { async readAlignments(chr, bpStart, bpEnd) { - const browser = this.browser + if (!this.chrAliasTable.has(chr)) { + const chromosome = this.genome.getChromosome(chr) + if (chromosome) { + const aliases = chromosome.altNames + for (let a of aliases) { + if (this.chrNames.has(a)) { + this.chrAliasTable.set(chr, a) + } + } + } + } + const header = await this.getHeader() const queryChr = header.chrAliasTable.hasOwnProperty(chr) ? header.chrAliasTable[chr] : chr const chrIdx = header.chrToIndex[queryChr] diff --git a/js/genome/bpt.js b/js/genome/bpt.js new file mode 100644 index 000000000..e793f62f8 --- /dev/null +++ b/js/genome/bpt.js @@ -0,0 +1,195 @@ +/* bptFile - B+ Trees. These are a method of indexing data similar to binary trees, but + * with many children rather than just two at each node. They work well when stored on disk, + * since typically only two or three disk accesses are needed to locate any particular + * piece of data. This implementation is *just* for disk based storage. For memory + * use the rbTree instead. Currently the implementation is just useful for data warehouse + * type applications. That is it implements a function to create a b+ tree from bulk data + * (bptFileCreate) and a function to lookup a value given a key (bptFileFind) but not functions + * to add or delete individual items. + * + * The layout of the file on disk is: + * header + * root node + * (other nodes) + * In general when the tree is first built the higher level nodes are stored before the + * lower level nodes. It is possible if a b+ tree is dynamically updated for this to + * no longer be strictly true, but actually currently the b+ tree code here doesn't implement + * dynamic updates - it just creates a b+ tree from a sorted list. + * + * Each node can be one of two types - index or leaf. The index nodes contain pointers + * to child nodes. The leaf nodes contain the actual data. + * + * The layout of the file header is: + * 4 bytes - The value bptSig (0x78CA8C91) + * 4 bytes - Number of children per block (not byte size of block) + * 4 bytes - Number of significant bytes in key + * 4 bytes - Number of bytes in value + * 8 bytes - Number of items in index + * 4 bytes - Always 0 for now + * 4 bytes - Always 0 for now + * The magic number may be byte-swapped, in which case all numbers in the file + * need to be byte-swapped. + * + * The nodes start with a header: + * 1 byte - 1 for leaf nodes, 0 for index nodes. + * 1 byte - Always 0 for now. + * 2 bytes - The number of children/items in node + * This is followed by count items. For the index nodes the items are + * key size bytes - always written most significant byte first + * 8 bytes - Offset of child node in index file. + * For leaf nodes the items are + * key size bytes - always written most significant byte first + * val sized bytes - the value associated with the key. + * Note in general the leaf nodes may not be the same size as the index nodes, though in + * the important case where the values are file offsets they will be. + */ + + +// static void twoBitSeekTo(struct twoBitFile *tbf, char *name) +// /* Seek to start of named record. Abort if can't find it. */ +// { +// if (tbf->bpt) +// { +// bits32 offset; +// if (!bptFileFind(tbf->bpt, name, strlen(name), &offset, sizeof(offset))) +// errAbort("%s is not in %s", name, tbf->bpt->fileName); +// fseek(tbf->f, offset, SEEK_SET); +// } +// else +// { +// struct twoBitIndex *index = hashFindVal(tbf->hash, name); +// if (index == NULL) +// errAbort("%s is not in %s", name, tbf->fileName); +// fseek(tbf->f, index->offset, SEEK_SET); +// } +// } + +// struct twoBitFile *twoBitOpenExternalBptIndex(char *twoBitName, char *bptName) +// /* Open file, read in header, but not regular index. Instead use +// * bpt index. Beware if you use this the indexList field will be NULL +// * as will the hash. */ +// { +// struct twoBitFile *tbf = twoBitOpenReadHeader(twoBitName); +// tbf->bpt = bptFileOpen(bptName); +// if (tbf->seqCount != tbf->bpt->itemCount) +// errAbort("%s and %s don't have same number of sequences!", twoBitName, bptName); +// return tbf; +// } + + +// static boolean rFind(struct bptFile *bpt, bits64 blockStart, void *key, void *val) +// /* Find value corresponding to key. If found copy value to memory pointed to by val and return +// * true. Otherwise return false. */ +// { +// /* Seek to start of block. */ +// udcSeek(bpt->udc, blockStart); +// +// /* Read block header. */ +// UBYTE isLeaf; +// UBYTE reserved; +// bits16 i, childCount; +// udcMustReadOne(bpt->udc, isLeaf); +// udcMustReadOne(bpt->udc, reserved); +// boolean isSwapped = bpt->isSwapped; +// childCount = udcReadBits16(bpt->udc, isSwapped); +// +// UBYTE keyBuf[bpt->keySize]; /* Place to put a key, buffered on stack. */ +// +// if (isLeaf) +// { +// for (i=0; iudc, keyBuf, bpt->keySize); +// udcMustRead(bpt->udc, val, bpt->valSize); +// if (memcmp(key, keyBuf, bpt->keySize) == 0) +// return TRUE; +// } +// return FALSE; +// } +// else +// { +// /* Read and discard first key. */ +// udcMustRead(bpt->udc, keyBuf, bpt->keySize); +// +// /* Scan info for first file offset. */ +// bits64 fileOffset = udcReadBits64(bpt->udc, isSwapped); +// +// /* Loop through remainder. */ +// for (i=1; iudc, keyBuf, bpt->keySize); +// if (memcmp(key, keyBuf, bpt->keySize) < 0) +// break; +// fileOffset = udcReadBits64(bpt->udc, isSwapped); +// } +// return rFind(bpt, fileOffset, key, val); +// } +// } + +// boolean bptFileFind(struct bptFile *bpt, void *key, int keySize, void *val, int valSize) +// /* Find value associated with key. Return TRUE if it's found. +// * Parameters: +// * bpt - file handle returned by bptFileOpen +// * key - pointer to key string, which needs to be bpt->keySize long +// * val - pointer to where to put retrieved value +// */ +// { +// /* Check key size vs. file key size, and act appropriately. If need be copy key to a local +// * buffer and zero-extend it. */ +// if (keySize > bpt->keySize) +// return FALSE; +// char keyBuf[keySize]; +// if (keySize != bpt->keySize) +// { +// memcpy(keyBuf, key, keySize); +// memset(keyBuf+keySize, 0, bpt->keySize - keySize); +// key = keyBuf; +// } +// +// /* Make sure the valSize matches what's in file. */ +// if (valSize != bpt->valSize) +// errAbort("Value size mismatch between bptFileFind (valSize=%d) and %s (valSize=%d)", +// valSize, bpt->fileName, bpt->valSize); +// +// /* Call recursive finder. */ +// return rFind(bpt, bpt->rootOffset, key, val); +// } + + +// struct bptFile *bptFileAttach(char *fileName, struct udcFile *udc) +// /* Open up index file on previously open file, with header at current file position. */ +// { +// /* Open file and allocate structure to hold info from header etc. */ +// struct bptFile *bpt = needMem(sizeof(*bpt)); +// bpt->fileName = fileName; +// bpt->udc = udc; +// +// /* Read magic number at head of file and use it to see if we are proper file type, and +// * see if we are byte-swapped. */ +// bits32 magic; +// boolean isSwapped = FALSE; +// udcMustReadOne(udc, magic); +// if (magic != bptSig) +// { +// magic = byteSwap32(magic); +// isSwapped = bpt->isSwapped = TRUE; +// if (magic != bptSig) +// errAbort("%s is not a bpt b-plus tree index file", fileName); +// } +// +// /* Read rest of defined bits of header, byte swapping as needed. */ +// bpt->blockSize = udcReadBits32(udc, isSwapped); +// bpt->keySize = udcReadBits32(udc, isSwapped); +// bpt->valSize = udcReadBits32(udc, isSwapped); +// bpt->itemCount = udcReadBits64(udc, isSwapped); +// +// /* Skip over reserved bits of header. */ +// bits32 reserved32; +// udcMustReadOne(udc, reserved32); +// udcMustReadOne(udc, reserved32); +// +// /* Save position of root block of b+ tree. */ +// bpt->rootOffset = udcTell(udc); +// +// return bpt; +// } \ No newline at end of file diff --git a/js/genome/cachedSequence.js b/js/genome/cachedSequence.js index b39eb5b1d..b022bad29 100644 --- a/js/genome/cachedSequence.js +++ b/js/genome/cachedSequence.js @@ -10,6 +10,16 @@ class CachedSequence { this.sequenceReader = sequenceReader } + get hasChromosomes() { + return this.sequenceReader.hasChromosomes + } + get chromosomes() { + return this.sequenceReader.chromosomes + } + async getSequenceRecord(chr) { + return this.sequenceReader.getSequenceRecord(chr) + } + async getSequence(chr, start, end) { const hasCachedSquence = this.interval && this.interval.contains(chr, start, end) @@ -40,14 +50,13 @@ class CachedSequence { return this.sequenceReader.init() } - get chromosomes() { - return this.sequenceReader.chromosomes - } - get chromosomeNames() { return this.sequenceReader.chromosomeNames } + getFirstChromosomeName() { + return typeof this.sequenceReader.getFirstChromosomeName === 'function' ? this.sequenceReader.getFirstChromosomeName() : undefined + } } export default CachedSequence diff --git a/js/genome/chromAliasBB.js b/js/genome/chromAliasBB.js new file mode 100644 index 000000000..d3ff4cce6 --- /dev/null +++ b/js/genome/chromAliasBB.js @@ -0,0 +1,67 @@ +/** + * Represenets a UCSC bigbed alias file + * + * + * @param aliasURL + * @param config + * @returns {Promise<*[]>} + */ +import {isNumber, buildOptions} from "../util/igvUtils.js" +import {igvxhr, StringUtils} from "../../node_modules/igv-utils/src/index.js" +import BWSource from "../bigwig/bwSource.js" +import BWReader from "../bigwig/bwReader.js" + +class ChromAliasBB { + + aliasRecordCache = new Map() + + constructor(url, config, genome) { + config = config || {} + config.url = url + this.reader = new BWReader(config, genome) + } + + /** + * Return the canonical chromosome name for the alias. If none found return the alias + * + * @param alias + * @returns {*} + */ + getChromosomeName(alias) { + return this.aliasRecordCache.has(alias) ? this.aliasRecordCache.get(alias).chr : alias + } + + /** + * Return an alternate chromosome name (alias). If not exists, return chr + * @param chr + * @param nameSet -- The name set, e.g. "ucsc" + * @returns {*|undefined} + */ + getChromosomeAlias(chr, nameSet) + { + const aliasRecord = this.aliasRecordCache.get(chr) + return aliasRecord ? aliasRecord[nameSet] || chr : chr + } + + /** + * Search for chromosome alias bed record. If found, catch results in the alias -> chr map + * @param alias + * @returns {Promise} + */ + async search(alias) { + if (!this.aliasRecordCache.has(alias)) { + const aliasRecord = await this.reader.search(alias) + if (aliasRecord) { + for (let key of Object.keys(aliasRecord)) { + if ("start" !== key && "end" !== key) { + this.aliasRecordCache.set(aliasRecord[key], aliasRecord) + } + } + } + } + return this.aliasRecordCache.get(alias) + } + +} + +export default ChromAliasBB diff --git a/js/genome/chromAliasFile.js b/js/genome/chromAliasFile.js new file mode 100644 index 000000000..fdb7ef49b --- /dev/null +++ b/js/genome/chromAliasFile.js @@ -0,0 +1,77 @@ +/** + * Represenets a UCSC tab-delimited Alias file + * + * example - header line is optional but reccomended, required to support altName setting for genome + * # refseq assembly genbank ncbi ucsc + * NC_048407.1 chr01 CM023106.1 1 chr1 + * + * @param aliasURL + * @param config + * @returns {Promise<*[]>} + */ +import {isNumber, buildOptions} from "../util/igvUtils.js" +import {igvxhr, StringUtils} from "../../node_modules/igv-utils/src/index.js" + +class ChromAliasFile { + + aliasRecordCache = new Map() + + constructor(aliasURL, config, genome) { + this.aliasURL = aliasURL + this.config = config + this.genome = genome + } + + /** + * Return the canonical chromosome name for the alias. If none found return the alias + * + * @param alias + * @returns {*} + */ + getChromosomeName(alias) { + return this.aliasRecordCache.has(alias) ? this.aliasRecordCache.get(alias).chr : alias + } + + + async loadAliases() { + + const data = await igvxhr.loadString(this.aliasURL, buildOptions(this.config)) + const lines = StringUtils.splitLines(data) + const firstLine = lines[0] + if (firstLine.startsWith("#")) { + this.headings = firstLine.split("\t").map(h => h.trim()) + this.altNameSets = this.headings.slice(1) + } + + const chromosomeNameSet = this.genome.chromosomes ? + new Set(this.genome.chromosomes.keys()) : new Set() + + for (let line of lines) { + if (!line.startsWith("#") && line.length > 0) { + const tokens = line.split("\t") + + let chr = tokens.find(t => chromosomeNameSet.has(t)) + if(!chr) { + chr = tokens[0] + } + + const aliasRecord = {chr} + for (let i = 0; i < tokens.length; i++) { + const key = this.headings ? this.headings[i] : i + aliasRecord[key] = tokens[i] + this.aliasRecordCache.set(tokens[i], aliasRecord) + } + } + } + } + + async search(alias) { + if(this.aliasRecordCache.size === 0) { + await this.loadAliases() + } + return this.aliasRecordCache.get(alias) + + } +} + +export default ChromAliasFile diff --git a/js/genome/chromSizes.js b/js/genome/chromSizes.js index 320a9bf1d..e95b4df4d 100644 --- a/js/genome/chromSizes.js +++ b/js/genome/chromSizes.js @@ -1,29 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014 Broad Institute - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// Indexed fasta files import {BGZip, igvxhr, StringUtils} from "../../node_modules/igv-utils/src/index.js" import Chromosome from "./chromosome.js" import {isDataURL} from "../util/igvUtils.js" @@ -48,6 +22,14 @@ class ChromSizes { return this.loadAll() } + get hasChromosomes() { + return true + } + + getSequenceRecord(chr) { + return this.chromosomes.get(chr) + } + get chromosomeNames() { if(!this.#chromosomeNames) { this.#chromosomeNames = Array.from(this.chromosomes.keys()) diff --git a/js/genome/cytoband.js b/js/genome/cytoband.js index 0ab9cd1b1..9eb008022 100644 --- a/js/genome/cytoband.js +++ b/js/genome/cytoband.js @@ -22,18 +22,18 @@ class Cytoband { } } -async function loadCytobands(cytobandUrl, config) { +async function loadCytobands(cytobandURL, config) { let data - if (isDataURL(cytobandUrl)) { - const plain = BGZip.decodeDataURI(cytobandUrl) + if (isDataURL(cytobandURL)) { + const plain = BGZip.decodeDataURI(cytobandURL) data = "" const len = plain.length for (let i = 0; i < len; i++) { data += String.fromCharCode(plain[i]) } } else { - data = await igvxhr.loadString(cytobandUrl, buildOptions(config)) + data = await igvxhr.loadString(cytobandURL, buildOptions(config)) } const cytobands = {} @@ -118,4 +118,4 @@ async function loadCytobandsBB(url, config) { return {chromosomes, cytobands} } -export {Cytoband, loadCytobands, loadCytobandsBB} +export {Cytoband} diff --git a/js/genome/cytobandFile.js b/js/genome/cytobandFile.js new file mode 100644 index 000000000..8bec39c34 --- /dev/null +++ b/js/genome/cytobandFile.js @@ -0,0 +1,77 @@ +import {buildOptions, isDataURL} from "../util/igvUtils.js" +import {BGZip, igvxhr, StringUtils} from "../../node_modules/igv-utils/src/index.js" +import {Cytoband} from "./cytoband.js" + +class CytobandFile { + + cytobands = new Map() + + constructor(url, config) { + this.url = url; + this.config = config; + } + + async getCytobands(chr) { + if(this.cytobands.size === 0) { + await this.#loadCytobands() + } + return this.cytobands.get(chr) + } + + + /** + * Load a UCSC bigbed cytoband file. Features are in bed+4 format. + * { + * "chr": "chr1", + * "start": 0, + * "end": 1735965, + * "name": "p36.33", + * "gieStain": "gneg" + * } + * @returns {Promise<*[]>} + */ + async #loadCytobands() { + + let data + if (isDataURL(this.url)) { + const plain = BGZip.decodeDataURI(this.url) + data = "" + const len = plain.length + for (let i = 0; i < len; i++) { + data += String.fromCharCode(plain[i]) + } + } else { + data = await igvxhr.loadString(this.url, buildOptions(this.config)) + } + + let lastChr + let bands = [] + const lines = StringUtils.splitLines(data) + for (let line of lines) { + + const tokens = line.split("\t") + const chrName = tokens[0] //genome.getChromosomeName(tokens[0]) // Note allowance for alias name, not sure why this is needed here + if (!lastChr) lastChr = chrName + + if (chrName !== lastChr) { + this.cytobands.set(lastChr, bands) + bands = [] + lastChr = chrName + } + + if (tokens.length === 5) { + //10 0 3000000 p15.3 gneg + var start = parseInt(tokens[1]) + var end = parseInt(tokens[2]) + var name = tokens[3] + var stain = tokens[4] + bands.push(new Cytoband(start, end, name, stain)) + } + } + + } + +} + +export default CytobandFile + diff --git a/js/genome/cytobandFileBB.js b/js/genome/cytobandFileBB.js new file mode 100644 index 000000000..6de6c5de1 --- /dev/null +++ b/js/genome/cytobandFileBB.js @@ -0,0 +1,32 @@ +import {Cytoband} from "./cytoband.js" +import BWSource from "../bigwig/bwSource.js" + +class CytobandFileBB { + + cytobandMap = new Map() + + constructor(url, config, genome) { + config = config || {} + config.url = url + this.source = new BWSource(config, genome) + } + + async getCytobands(chr) { + + if (this.cytobandMap.has(chr)) { + return this.cytobandMap.get(chr) + } else { + let cytobands = await this.#readCytobands(chr) + if (!cytobands) cytobands = [] // Prevent loading again + this.cytobandMap.set(chr, cytobands) + return cytobands + } + } + + async #readCytobands(chr) { + const features = await this.source.getFeatures({chr}) + return features.map(f => new Cytoband(f.start, f.end, f.name, f.gieStain)) + } +} + +export default CytobandFileBB \ No newline at end of file diff --git a/js/genome/fasta.js b/js/genome/fasta.js index 429bf9eae..4e4aa6b42 100644 --- a/js/genome/fasta.js +++ b/js/genome/fasta.js @@ -10,7 +10,7 @@ async function loadFasta(reference) { let fasta if ("chromsizes" === reference.format) { fasta = new ChromSizes(reference.fastaURL) - } else if ("2bit" === reference.format || reference.twobitURL) { + } else if ("2bit" === reference.format || reference.twoBitURL) { fasta = new CachedSequence(new Twobit(reference)) } else if (isDataURL(reference.fastaURL) || reference.indexed === false) { fasta = new NonIndexedFasta(reference) diff --git a/js/genome/genome.js b/js/genome/genome.js index b706897ce..4e2324a1d 100644 --- a/js/genome/genome.js +++ b/js/genome/genome.js @@ -1,6 +1,12 @@ import {StringUtils} from "../../node_modules/igv-utils/src/index.js" -import {isNumber} from "../util/igvUtils.js" import Chromosome from "./chromosome.js" +import {loadFasta} from "./fasta.js" +import ChromAliasBB from "./chromAliasBB.js" +import ChromAliasFile from "./chromAliasFile.js" +import CytobandFileBB from "./cytobandFileBB.js" +import CytobandFile from "./cytobandFile.js" + +import {loadChromSizes} from "./chromSizes.js" /** * The Genome class represents an assembly and consists of the following elements @@ -12,67 +18,73 @@ import Chromosome from "./chromosome.js" class Genome { - constructor(config, sequence, aliases, chromosomes, cytobands) { + static async loadGenome(options) { + + const genome = new Genome(options) + await genome.init() + return genome + } + constructor(config) { this.config = config this.id = config.id || generateGenomeID(config) this.name = config.name - this.sequence = sequence this.nameSet = config.nameSet - this.chromosomes = chromosomes - this.chromosomeNames = Array.from(this.chromosomes.keys()) + } - const firstChromosome = chromosomes.values().next().value - if(firstChromosome.altNames) { - this.altNameSets = Array.from(firstChromosome.altNames.keys()) - } + async init() { - // Set chromosome order for WG view and chromosome pulldown. If chromosome order is not specified sort - if (config.chromosomeOrder) { - if (Array.isArray(config.chromosomeOrder)) { - this.wgChromosomeNames = config.chromosomeOrder - } else { - this.wgChromosomeNames = config.chromosomeOrder.split(',').map(nm => nm.trim()) - } + const config = this.config + + this.sequence = await loadFasta(config) + + if (config.chromSizes) { + // a chromSizes file is neccessary for 2bit sequences for whole-genome view or chromosome pulldown + this.chromosomes = await loadChromSizes(config.chromSizes) } else { - this.wgChromosomeNames = trimSmallChromosomes(chromosomes) + this.chromosomes = this.sequence.chromosomes || new Map() // This might be undefined, depending on sequence type } - // Build the alias table and correct cytoband sequence names - if(aliases) { - this.chrAliasTable = createAliasTable(this.chromosomes, aliases) - } else { - this.chrAliasTable = {} + // For backward compatibility + if(this.chromosomes.size > 0) { + this.chromosomeNames = Array.from(this.chromosomes.keys()) } - if (cytobands) { - this.cytobands = {} - for (let c of Object.keys(cytobands)) { - const chrName = this.getChromosomeName(c) - this.cytobands[chrName] = cytobands[c] + + if (config.chromAliasBbURL) { + this.chromAlias = new ChromAliasBB(config.chromAliasBbURL, Object.assign({}, config), this) + } else if (config.aliasURL) { + this.chromAlias = new ChromAliasFile(config.aliasURL, Object.assign({}, config), this) + } + + if (config.cytobandBbURL) { + this.cytobandSource = new CytobandFileBB(config.cytobandBbURL, Object.assign({}, config), this) + } else if(config.cytobandURL) { + this.cytobandSource = new CytobandFile(config.cytobandURL, Object.assign({}, config)) + } + + if (false !== config.wholeGenomeView && this.chromosomes.size > 0) { + // Set chromosome order for WG view and chromosome pulldown. If chromosome order is not specified sort + if (config.chromosomeOrder) { + if (Array.isArray(config.chromosomeOrder)) { + this.wgChromosomeNames = config.chromosomeOrder + } else { + this.wgChromosomeNames = config.chromosomeOrder.split(',').map(nm => nm.trim()) + } + } else { + this.wgChromosomeNames = trimSmallChromosomes(this.chromosomes) } } // Optionally create the psuedo chromosome "all" to support whole genome view - this.wholeGenomeView = config.wholeGenomeView !== false && this.wgChromosomeNames && this.chromosomeNames.length > 1 + this.wholeGenomeView = config.wholeGenomeView !== false && this.wgChromosomeNames && this.chromosomes.size > 1 if (this.wholeGenomeView) { const l = this.wgChromosomeNames.reduce((accumulator, currentValue) => accumulator += this.chromosomes.get(currentValue).bpLength, 0) this.chromosomes.set("all", new Chromosome("all", 0, l)) - //this.chromosomeNames.unshift("all") } } - updateChromosomes(chromosomes) { - for(let key of chromosomes.keys()) { - this.chromosomes.set(key, chromosomes.get(key)) - } - } - - updateAliases(aliases) { - this.chrAliasTable = createAliasTable(this.chromosomes, aliases); - } - get description() { @@ -105,47 +117,65 @@ class Genome { if (this.showWholeGenomeView() && this.chromosomes.has("all")) { return "all" } else { - return this.chromosomeNames[0] + return this.sequence.getFirstChromosomeName() } } - getChromosomeName(str) { - const chr = str ? this.chrAliasTable[str.toLowerCase()] : str - return chr ? chr : str + getChromosomeName(chr) { + return this.chromAlias ? this.chromAlias.getChromosomeName(chr) : chr } getChromosomeDisplayName(str) { - const canonicalName = this.getChromosomeName(str) - if (this.nameSet) { - return this.chromosomes.has(canonicalName) ? this.chromosomes.get(canonicalName).getAltName("ucsc") : canonicalName + if (this.nameSet && this.chromAlias) { + return this.chromAlias.getChromosomeAlias(str, this.nameSet) || str } else { - return canonicalName + return str } } getChromosome(chr) { - chr = this.getChromosomeName(chr) + if (this.chromAlias) { + chr = this.chromAlias.getChromosomeName(chr) + } return this.chromosomes.get(chr) } - getCytobands(chr) { - const chrName = this.getChromosomeName(chr) - return this.cytobands ? this.cytobands[chrName] : null - } - - getLongestChromosome() { + async loadChromosome(chr) { - var longestChr, - chromosomes = this.chromosomes - for (let key in chromosomes) { - if (chromosomes.hasOwnProperty(key)) { - var chr = chromosomes[key] - if (longestChr === undefined || chr.bpLength > longestChr.bpLength) { - longestChr = chr + if (!this.chromosomes.has(chr)) { + 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 } - return longestChr + } + + return this.chromosomes.get(chr) + } + + async getAliasRecord(chr) { + if (this.chromAlias) { + return this.chromAlias.search(chr) + } + } + + + getCytobands(chr) { + if (this.cytobandSource) { + const chrName = this.getChromosomeName(chr) + return this.cytobandSource.getCytobands(chrName) } } @@ -253,55 +283,6 @@ class Genome { } } -function createAliasTable(chromosomes, aliases) { - - /** - * Return the official chromosome name for the (possibly) alias. Deals with - * 1 <-> chr1, chrM <-> MT, IV <-> chr4, etc. - * @param str - */ - const chrAliasTable = {} - - // The standard mappings - chrAliasTable["all"] = "all" - chromosomes.forEach(function (c) { - const name = c.name - if (name.startsWith("chr")) { - chrAliasTable[name.substring(3)] = name - } else if (isNumber(name)) { - chrAliasTable["chr" + name] = name - } - if (name === "chrM") chrAliasTable["mt"] = "chrM" - if (name === "MT") chrAliasTable["chrm"] = "MT" - chrAliasTable[name.toLowerCase()] = name - }) - - // Custom mappings - if (aliases) { - for (let array of aliases) { - - // Find the official chr name - let defName - for (let i = 0; i < array.length; i++) { - if (chromosomes.get(array[i])) { - defName = array[i] - break - } - } - - if (defName) { - for (let alias of array) { - if (alias !== defName) { - chrAliasTable[alias.toLowerCase()] = defName - chrAliasTable[alias] = defName // Should not be needed - } - } - } - } - } - return chrAliasTable -} - /** * Trim small sequences (chromosomes) and return the list of trimmed chromosome names. * The results are used to construct the whole genome view and optionally chromosome pulldown @@ -322,7 +303,7 @@ function trimSmallChromosomes(chromosomes) { if (c.bpLength < runningAverage / 100) { continue } - runningAverage = ((i-1) * runningAverage + c.bpLength) / i + runningAverage = ((i - 1) * runningAverage + c.bpLength) / i wgChromosomeNames.push(c.name) } i++ diff --git a/js/genome/genomeUtils.js b/js/genome/genomeUtils.js index c426dd529..12d35042a 100644 --- a/js/genome/genomeUtils.js +++ b/js/genome/genomeUtils.js @@ -1,65 +1,10 @@ -import Genome from "./genome.js" -import {loadFasta} from "./fasta.js" -import {loadCytobands, loadCytobandsBB} from "./cytoband.js" -import {loadChromSizes} from "./chromSizes.js" -import {buildOptions} from "../util/igvUtils.js" import {igvxhr, StringUtils} from "../../node_modules/igv-utils/src/index.js" -import BWReader from "../bigwig/bwReader.js" -import Chromosome from "./chromosome.js" const DEFAULT_GENOMES_URL = "https://igv.org/genomes/genomes.json" const BACKUP_GENOMES_URL = "https://s3.amazonaws.com/igv.org.genomes/genomes.json" const GenomeUtils = { - loadGenome: async function (options) { - - const sequence = await loadFasta(options) - - let aliases - let chromosomes - let cytobands - - - if (options.chromSizes) { // Order is important, try this first - chromosomes = await loadChromSizes(options.chromSizes) - } else { - chromosomes = sequence.chromosomes - } - - - if (options.cytobandURL) { - cytobands = await loadCytobands(options.cytobandURL, options) - } - - if (options.aliasURL) { - aliases = await loadAliases(options.aliasURL, options) - } - - - const genome = new Genome(options, sequence, aliases, chromosomes, cytobands) - - if (options.cytobandBbURL) { - - loadCytobandsBB(options.cytobandBbURL, options).then((cc) => { - if (!chromosomes) { - genome.updateChromosomes(cc.chromosomes) - } - genome.cytobands = cc.cytobands - }) - } - if (options.aliasBbURL) { - loadAliasesBB(options.aliasBbURL, options) - .then(abb => { - genome.updateChromosomes(abb.chromosomes) - genome.updateAliases(abb.aliases) - }) - } - - - return genome - }, - initializeGenomes: async function (config) { if (!GenomeUtils.KNOWN_GENOMES) { @@ -146,62 +91,6 @@ const GenomeUtils = { } } -/** - * Load a tab-delimited alias file - * @param aliasURL - * @param config - * @returns {Promise<*[]>} - */ -async function loadAliases(aliasURL, config) { - - const data = await igvxhr.loadString(aliasURL, buildOptions(config)) - const lines = StringUtils.splitLines(data) - const aliases = [] - for (let line of lines) { - if (!line.startsWith("#") && line.length > 0) aliases.push(line.split("\t")) - } - return aliases -} -/** - * Load a UCSC bigbed alias file. Features are in bed+3 format. - * { - * "chr": "CM021939.1", - * "start": 0, - * "end": 223606306, - * "genbank": "CM021939.1", - * "assembly": "1", - * "ensembl": "1", - * "ncbi": "1", - * "ucsc": "chr1" - * } - * @param url - * @param config - * @returns {Promise<*[]>} - */ -async function loadAliasesBB(url, config) { - - const bbReader = new BWReader({url: url, format: "bigbed", wholeFile: true}) - const features = await bbReader.readWGFeatures() - if (features.length === 0) return - - const keys = Object.keys(features[0]).filter(k => !(k === "start" || k === "end")) - - - const aliases = [] - const chromosomes = new Map() // chromosome metadata object - let order = 0 - for (let f of features) { - aliases.push(keys.filter(k => f[k]).map(k => f[k])) - - const altNames = new Map() - for (let k of keys.filter(k => k != "chr")) { - altNames.set(k, f[k]) - } - chromosomes.set(f["chr"], new Chromosome(f["chr"], order++, f["end"], altNames)) - } - - return {chromosomes, aliases} -} export default GenomeUtils diff --git a/js/genome/indexedFasta.js b/js/genome/indexedFasta.js index 087409d2c..e762fbcca 100644 --- a/js/genome/indexedFasta.js +++ b/js/genome/indexedFasta.js @@ -56,6 +56,13 @@ class FastaSequence { this.config = config } + get hasChromosomes() { + return true + } + + getSequenceRecord(chr) { + return this.chromosomes.get(chr) + } async init() { return this.getIndex() @@ -65,6 +72,11 @@ class FastaSequence { if(!this.#chromosomeNames) { this.#chromosomeNames = Array.from(this.chromosomes.keys()) } + return this.#chromosomeNames + } + + getFirstChromosomeName() { + return this.chromosomeNames[0] } async getIndex() { diff --git a/js/genome/nonIndexedFasta.js b/js/genome/nonIndexedFasta.js index c33170720..a3045be33 100644 --- a/js/genome/nonIndexedFasta.js +++ b/js/genome/nonIndexedFasta.js @@ -1,29 +1,4 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014 Broad Institute - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// Indexed fasta files + import {BGZip, igvxhr, StringUtils} from "../../node_modules/igv-utils/src/index.js" import Chromosome from "./chromosome.js" import {buildOptions, isDataURL} from "../util/igvUtils.js" @@ -59,10 +34,19 @@ class NonIndexedFasta { return this.loadAll() } + getSequenceRecord(chr) { + return this.chromosomes.get(chr) + } + get chromosomeNames() { if(!this.#chromosomeNames) { this.#chromosomeNames = Array.from(this.chromosomes.keys()) } + return this.#chromosomeNames + } + + getFirstChromosomeName() { + return this.chromosomeNames[0] } async getSequence(chr, start, end) { diff --git a/js/genome/twobit.js b/js/genome/twobit.js index a189a0330..516265a26 100644 --- a/js/genome/twobit.js +++ b/js/genome/twobit.js @@ -6,6 +6,7 @@ import {igvxhr} from "../../node_modules/igv-utils/src/index.js" import BinaryParser from "../binary.js" +import BPTree from "../bigwig/bpTree.js" const twoBit = ['T', 'C', 'A', 'G'] const byteTo4Bases = [] @@ -22,28 +23,40 @@ const maskedByteTo4Bases = byteTo4Bases.map(bases => bases.toLowerCase()) class TwobitSequence { littleEndian - index = new Map() metaIndex = new Map() + bpt constructor(config) { - this.url = config.twobitURL || config.fastaURL - } + this.url = config.twoBitURL || config.fastaURL + if(config.twoBitBptURL) { + this.bptURL = config.twoBitBptURL + } + } async init() { - await this._readIndex() + if(this.bptURL) { + this.index = await BPTree.loadBpTree(this.bptURL, 0) + } else { + const idx = await this._readIndex() + this.index = { + search: async (name) => { + return idx.has(name) ? {offset: idx.get(name)} : undefined + } + } + } } - get chromosomeNames() { - return Array.from(this.index.keys()) + get hasChromosomes() { + return false } async readSequence(seqName, regionStart, regionEnd) { - if (this.index.size === 0) { + if (!this.index) { await this.init() } - const record = await this._getSequenceMetaData(seqName) + const record = await this.getSequenceRecord(seqName) if (!record) { return null } @@ -108,6 +121,9 @@ class TwobitSequence { } async _readIndex() { + + const index = new Map() + const loadRange = {start: 0, size: 64} let arrayBuffer = await igvxhr.loadArrayBuffer(this.url, {range: loadRange}) let dataView = new DataView(arrayBuffer) @@ -156,29 +172,14 @@ class TwobitSequence { const name = binaryBuffer.getString(len) const offset = binaryBuffer.getUInt() ptr += len + 4 - this.index.set(name, offset) + index.set(name, offset) estNameLength = Math.floor(estNameLength * (i / (i + 1)) + name.length / (i + 1)) } + return index } - /** - * NOTE: this can be very slow for large # of sequences as each requires a seek. Its provided in case a 2bit - * file is used without a corresponding chromSizes, chromAliases, or cytobad file. In other words last resort * - * @returns {Promise<*>} - */ - async getChromosomes() { - if (!this.chromosomes) { - await this.init() - const seqNames = Array.from(this.index.keys()) - this.chromosomes = [] - for (let name of seqNames) { - const metadata = await this._getSequenceMetaData(name) - this.chromosomes.push({name, bpLength: metadata.dnaSize}) - } - } - return this.chromosomes - } + /** * Fetch the sequence metadata for the given seq name * @@ -186,7 +187,7 @@ class TwobitSequence { * @param seqName * @returns {Promise} */ - async _getSequenceMetaData(seqName) { + async getSequenceRecord(seqName) { if (!this.metaIndex.has(seqName)) { @@ -194,10 +195,11 @@ class TwobitSequence { throw Error("TwobitSequence object must be initialized before accessing sequence") } - let offset = this.index.get(seqName) - if (!offset) { + let result = await this.index.search(seqName) + if (!result) { return } + let offset = result.offset // Read size of dna data & # of "N" blocks let size = 8 @@ -253,7 +255,8 @@ class TwobitSequence { dnaSize, nBlocks, maskBlocks, - packedPos + packedPos, + bpLength: dnaSize } this.metaIndex.set(seqName, meta) diff --git a/js/ideogramTrack.js b/js/ideogramTrack.js index 045b31c77..91a04dd4f 100644 --- a/js/ideogramTrack.js +++ b/js/ideogramTrack.js @@ -48,7 +48,7 @@ class IdeogramTrack { return this.height } - draw({context, referenceFrame, pixelWidth, pixelHeight}) { + async draw({context, referenceFrame, pixelWidth, pixelHeight}) { const chr = referenceFrame.chr const chromosome = referenceFrame.genome.getChromosome(chr) @@ -59,7 +59,7 @@ class IdeogramTrack { const stainColors = [] - drawIdeogram({ + await drawIdeogram({ ctx: context, chr, referenceFrame, @@ -117,7 +117,7 @@ class IdeogramTrack { } } -function drawIdeogram({ctx, chr, referenceFrame, genome, width, height, stainColors}) { +async function drawIdeogram({ctx, chr, referenceFrame, genome, width, height, stainColors}) { const shim = 1 const shim2 = 0.5 * shim @@ -129,7 +129,7 @@ function drawIdeogram({ctx, chr, referenceFrame, genome, width, height, stainCol IGVGraphics.fillRect(ctx, 0, 0, width, height, {fillStyle: IGVColor.greyScale(255)}) - const cytobands = genome.getCytobands(chr) + const cytobands = await genome.getCytobands(chr) if (cytobands) { const center = (ideogramTop + height / 2) diff --git a/js/ideogramViewport.js b/js/ideogramViewport.js index 55825e42e..67829624a 100644 --- a/js/ideogramViewport.js +++ b/js/ideogramViewport.js @@ -105,7 +105,7 @@ class IdeogramViewport extends TrackViewport { this.draw({referenceFrame: this.referenceFrame}) } - draw({referenceFrame}) { + async draw({referenceFrame}) { IGVGraphics.configureHighDPICanvas(this.ideogram_ctx, this.$viewport.width(), this.$viewport.height()) diff --git a/js/igv-create.js b/js/igv-create.js index 2ec4d058b..8fc77a907 100644 --- a/js/igv-create.js +++ b/js/igv-create.js @@ -199,6 +199,8 @@ function setDefaults(config) { config.tracks = [] } + return config + } @@ -282,4 +284,4 @@ async function createTrack(config, browser) { return await Browser.prototype.createTrack.call(browser, config) } -export {createTrack, createBrowser, removeBrowser, removeAllBrowsers, getAllBrowsers, visibilityChange} +export {createTrack, createBrowser, removeBrowser, removeAllBrowsers, getAllBrowsers, visibilityChange, setDefaults} diff --git a/js/referenceFrame.js b/js/referenceFrame.js index f20eee76f..7e3976d62 100755 --- a/js/referenceFrame.js +++ b/js/referenceFrame.js @@ -34,8 +34,8 @@ class ReferenceFrame { constructor(genome, chr, start, end, bpPerPixel) { this.genome = genome - this.chr = chr + this.chr = chr // this.genome.getChromosomeName(chr) this.start = start // TODO WARNING THIS IS NOT UPDATED !!! @@ -45,6 +45,10 @@ class ReferenceFrame { this.id = DOMUtils.guid() } + get locusSearchString() { + return `${this.chr}:${this.start+1}-${this.end}` + } + /** * Extend this frame to accomodate the given locus. Used th CircularView methods to merge 2 frames. * @param locus @@ -125,9 +129,9 @@ class ReferenceFrame { const centerBP = undefined === centerBPOrUndefined ? (this.start + this.toBP(viewportWidth / 2.0)) : centerBPOrUndefined // save initial start and bpp - const {start, bpPerPixel} = this.start - - const {bpLength} = this.getChromosome() + const initialStart = this.start + const initialBpPerPixel = this.bpPerPixel + const bpLength = this.getChromosome().bpLength const bppThreshold = scaleFactor < 1.0 ? browser.minimumBases() / viewportWidth : bpLength / viewportWidth // update bpp @@ -144,7 +148,7 @@ class ReferenceFrame { this.end = this.start + widthBP - const viewChanged = start !== this.start || bpPerPixel !== this.bpPerPixel + const viewChanged = initialStart !== this.start || initialBpPerPixel !== this.bpPerPixel if (viewChanged) { await browser.updateViews(true) } @@ -229,7 +233,6 @@ function createReferenceFrameList(loci, genome, browserFlanking, minimumBases, v locus.end, (locus.end - locus.start) / viewportWidth) - referenceFrame.locusSearchString = locus.locusSearchString // GTEX hack if (locus.gene || locus.snp) { @@ -249,7 +252,6 @@ function adjustReferenceFrame(scaleFactor, referenceFrame, viewportWidth, alignm referenceFrame.start = alignmentCC - (referenceFrame.bpPerPixel * (viewportWidth / 2)) referenceFrame.end = referenceFrame.start + (referenceFrame.bpPerPixel * viewportWidth) - referenceFrame.locusSearchString = referenceFrame.getLocusString() } function createReferenceFrameWithAlignment(genome, chromosomeName, bpp, viewportWidth, alignmentStart, alignmentLength) { diff --git a/js/search.js b/js/search.js index 41f9c42ad..17aa068b7 100644 --- a/js/search.js +++ b/js/search.js @@ -33,59 +33,88 @@ async function search(browser, string) { return } - if (string && string.trim().toLowerCase() === "all" || string === "*") { - string = "all" - } - const loci = string.split(' ') let searchConfig = browser.searchConfig || DEFAULT_SEARCH_CONFIG let list = [] - const searchLocus = async (locus) => { - let locusObject = parseLocusString(browser, locus) + const searchForLocus = async (locus) => { + + if (locus.trim().toLowerCase() === "all" || locus === "*") { + if (browser.genome.wholeGenomeView) { + const wgChr = browser.genome.getChromosome("all") + return {chr: "all", start: 0, end: wgChr.bpLength} + } else { + return undefined + } + } + + let locusObject + let chromosome + if(locus.includes(":")) { + locusObject = parseLocusString(locus, browser.isSoftclipped()) + chromosome = await browser.genome.loadChromosome(locusObject.chr) + } + + if (!chromosome) { + locusObject = undefined - if (!locusObject) { + // Not a locus string, search track annotations const searchableTracks = browser.tracks.filter(t => t.searchable) - for(let track of searchableTracks) { + for (let track of searchableTracks) { const feature = await track.search(locus) - if(feature) { + if (feature) { locusObject = { chr: feature.chr, start: feature.start, end: feature.end, - gene: feature.name, - locusSearchString: string + gene: feature.name } - break; // We don't support multiple feature hits yets + break + } + } + + // If still not found try webservice, if enabled + if (!locusObject && (browser.config && false !== browser.config.search)) { + try { + locusObject = await searchWebService(browser, locus, searchConfig) + } catch (error) { + console.error(error) + throw Error("Search service currently unavailable.") } } + + // Finally assume string is a chromosome name. + chromosome = await browser.genome.loadChromosome(locus) + if(chromosome) { + locusObject = {chr: chromosome.name} + } } - if (!locusObject && (browser.config && false !== browser.config.search)) { - try { - locusObject = await searchWebService(browser, locus, searchConfig) - } catch (error) { - console.error(error) - throw Error("Search service currently unavailable.") + // Force load chromosome here (a side effect, but neccessary to do this in an async function so it's available) + if (locusObject) { + chromosome = chromosome || await browser.genome.loadChromosome(locusObject.chr) + locusObject.chr = chromosome.name // Replace possible alias with canonical name + if (locusObject.start === undefined && locusObject.end === undefined) { + locusObject.start = 0 + locusObject.end = chromosome.bpLength } } + return locusObject } for (let locus of loci) { - const locusObject = await searchLocus(locus) + const locusObject = await searchForLocus(locus) if (locusObject) { - locusObject.locusSearchString = locus list.push(locusObject) } } // If nothing is found, consider possibility that loci name itself has spaces if (list.length === 0) { - const locusObject = await searchLocus(string.replaceAll(' ', '+')) + const locusObject = await searchForLocus(string.replaceAll(' ', '+')) if (locusObject) { - locusObject.locusSearchString = string list.push(locusObject) } } @@ -93,14 +122,21 @@ async function search(browser, string) { return 0 === list.length ? undefined : list } -function parseLocusString(browser, locus) { +/** + * Parse a locus string of the form :- + * + * @param locus + * @param isSoftclipped + * @returns {{start: number, end: number, chr: *}|undefined|{start: number, chr: *}} + */ +function parseLocusString(locus, isSoftclipped = false) { // Check for tab delimited locus string const tabTokens = locus.split('\t') - if (tabTokens.length >= 3) { + if (tabTokens.length > 2) { // Possibly a tab-delimited locus try { - const chr = browser.genome.getChromosomeName(tabTokens[0]) + const chr = tabTokens[0]// browser.genome.getChromosomeName(tabTokens[0]) const start = parseInt(tabTokens[1].replace(/,/g, ''), 10) - 1 const end = parseInt(tabTokens[2].replace(/,/g, ''), 10) if (!isNaN(start) && !isNaN(end)) { @@ -109,77 +145,61 @@ function parseLocusString(browser, locus) { } catch (e) { // Not a tab delimited locus, apparently, but not really an error as that was a guess } - } const a = locus.split(':') - const chr = a[0] - if ('all' === chr && browser.genome.getChromosome(chr)) { - return {chr, start: 0, end: browser.genome.getChromosome(chr).bpLength} - - } else if (undefined === browser.genome.getChromosome(chr)) { - return undefined + const locusObject = {chr: a[0]} + if (a.length > 1) { + + let b = a[1].split('-') + if (b.length > 2) { + // Allow for negative coordinates, which is possible if showing alignment soft clips + if (a[1].startsWith('-')) { + const i = a[1].indexOf('-', 1) + if (i > 0) { + const t1 = a[1].substring(0, i) + const t2 = a[1].substring(i + 1) + b = [t1, t2] + } + } else { + return undefined + } + } - } else { - const queryChr = browser.genome.getChromosomeName(chr) - const extent = { - chr: queryChr, - start: 0, - end: browser.genome.getChromosome(chr).bpLength + let numeric + numeric = b[0].replace(/,/g, '') + if (isNaN(numeric)) { + return undefined } - if (a.length > 1) { - - let b = a[1].split('-') - if (b.length > 2) { - // Allow for negative coordinates, which is possible if showing alignment soft clips - if (a[1].startsWith('-')) { - const i = a[1].indexOf('-', 1) - if (i > 0) { - const t1 = a[1].substring(0, i) - const t2 = a[1].substring(i + 1) - b = [t1, t2] - } - } else { - return undefined - } + locusObject.start = parseInt(numeric, 10) - 1 + locusObject.end = locusObject.start + 1 - } + if (1 === b.length) { + // Don't clamp coordinates if single coordinate is supplied. + locusObject.start -= 20 + locusObject.end += 20 + } - let numeric - numeric = b[0].replace(/,/g, '') + if (2 === b.length) { + numeric = b[1].replace(/,/g, '') if (isNaN(numeric)) { return undefined + } else { + locusObject.end = parseInt(numeric, 10) } - extent.start = parseInt(numeric, 10) - 1 - extent.end = extent.start + 1 - - if (1 === b.length) { - // Don't clamp coordinates if single coordinate is supplied. - extent.start -= 20 - extent.end += 20 - } - - if (2 === b.length) { - numeric = b[1].replace(/,/g, '') - if (isNaN(numeric)) { - return undefined - } else { - extent.end = parseInt(numeric, 10) - } - - // Allow negative coordinates only if browser is softclipped, i.e. there is at least alignment track with softclipping on - if (extent.start < 0 && !browser.isSoftclipped()) { - const delta = -extent.start - extent.start += delta - extent.end += delta - } + // Allow negative coordinates only if browser is softclipped, i.e. there is at least alignment track with softclipping on + if (locusObject.start < 0 && !isSoftclipped) { + const delta = -extent.start + locusObject.start += delta + locusObject.end += delta } } - - return extent } + + return locusObject + } async function searchWebService(browser, locus, searchConfig) { @@ -192,9 +212,6 @@ async function searchWebService(browser, locus, searchConfig) { const result = await igvxhr.loadString(path, options) const locusObject = processSearchResult(browser, result, searchConfig) - if (locusObject) { - locusObject.locusSearchString = locus - } return locusObject } @@ -238,13 +255,7 @@ function processSearchResult(browser, result, searchConfig) { console.error("Search service results must include chromosome and start fields: " + result) } - const chrResult = result[chromosomeField] - const chromosome = browser.genome.getChromosome(chrResult) - if (!chromosome) { - return undefined - } - const chr = chromosome.name - + const chr = result[chromosomeField] let start = result[startField] - coords let end = result[endField] if (undefined === end) { diff --git a/js/trackViewport.js b/js/trackViewport.js index 1724c9159..2e66835b1 100644 --- a/js/trackViewport.js +++ b/js/trackViewport.js @@ -178,7 +178,8 @@ class TrackViewport extends Viewport { const chr = referenceFrame.chr // Expand the requested range so we can pan a bit without reloading. But not beyond chromosome bounds - const chrLength = this.browser.genome.getChromosome(chr).bpLength + const chromosome = this.browser.genome.getChromosome(chr) + const chrLength = chromosome ? chromosome.bpLength : Number.MAX_SAFE_INTEGER const pixelWidth = this.$viewport.width()// * 3; const bpWidth = pixelWidth * referenceFrame.bpPerPixel const bpStart = Math.floor(Math.max(0, referenceFrame.start - bpWidth)) diff --git a/js/ucsc/ucscHub.js b/js/ucsc/ucscHub.js index 7cbf6def6..5bef81623 100644 --- a/js/ucsc/ucscHub.js +++ b/js/ucsc/ucscHub.js @@ -1,4 +1,3 @@ - /* https://genomewiki.ucsc.edu/index.php/Assembly_Hubs https://genome.ucsc.edu/goldenpath/help/hgTrackHubHelp.html @@ -6,7 +5,7 @@ https://genome.ucsc.edu/goldenpath/help/trackDb/trackDbHub.html */ -import { igvxhr} from "../../node_modules/igv-utils/src/index.js" +import {igvxhr} from "../../node_modules/igv-utils/src/index.js" class Hub { @@ -32,7 +31,8 @@ class Hub { } static supportedTypes = new Set(["bigBed", "bigWig", "bigGenePred"]) - static filterTracks = new Set(["cytoBandIdeo"]) + static filterTracks = new Set(["cytoBandIdeo", "assembly", "gap", "gapOverlap", "allGaps", + "cpgIslandExtUnmasked", "windowMasker"]) constructor(url, stanzas, groups) { @@ -83,13 +83,14 @@ class Hub { getDefaultPosition() { return this.genomeStanza.getProperty("defaultPos") } + /* Example genome stanza genome GCF_000186305.1 taxId 176946 groups groups.txt description Burmese python twoBitPath GCF_000186305.1.2bit -twoBitBptUrl GCF_000186305.1.2bit.bpt +twoBitBptURL GCF_000186305.1.2bit.bpt chromSizes GCF_000186305.1.chrom.sizes.txt chromAliasBb GCF_000186305.1.chromAlias.bb organism Python_molurus_bivittatus-5.0.2 Sep. 2013 @@ -106,17 +107,29 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1 const config = { id: this.genomeStanza.getProperty("genome"), name: this.genomeStanza.getProperty("scientificName") || this.genomeStanza.getProperty("organism") || this.genomeStanza.getProperty("description"), - twobitURL: this.baseURL + this.genomeStanza.getProperty("twoBitPath"), - aliasBbURL: this.baseURL + this.genomeStanza.getProperty("chromAliasBb"), + twoBitURL: this.baseURL + this.genomeStanza.getProperty("twoBitPath"), nameSet: "ucsc", - blat: this.genomeStanza.getProperty("blat") + wholeGenomeView: false } config.description = config.id - if (this.genomeStanza.hasProperty("chromSizes")) { - config.chromSizes = this.baseURL + this.genomeStanza.getProperty("chromSizes") + if (this.genomeStanza.hasProperty("blat")) { + config.blat = this.baseURL + this.genomeStanza.getProperty("blat") + } + if (this.genomeStanza.hasProperty("chromAliasBb")) { + config.chromAliasBbURL = this.baseURL + this.genomeStanza.getProperty("chromAliasBb") } + if (this.genomeStanza.hasProperty("twoBitBptURL")) { + config.twoBitBptURL = this.baseURL + this.genomeStanza.getProperty("twoBitBptURL") + } + if (this.genomeStanza.hasProperty("twoBitBptUrl")) { + config.twoBitBptURL = this.baseURL + this.genomeStanza.getProperty("twoBitBptUrl") + } + // chromSizes can take a very long time to load, and is not useful with the default WGV = off + // 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")}` } @@ -132,6 +145,15 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1 } // Search for cytoband + /* + track cytoBandIdeo + shortLabel Chromosome Band (Ideogram) + longLabel Ideogram for Orientation + group map + visibility dense + 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")) if (cytoStanza.length > 0) { config.cytobandBbURL = this.baseURL + cytoStanza[0].getProperty("bigDataUrl") @@ -184,6 +206,7 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1 const format = t.format const config = { + "id": t.getProperty("track"), "name": t.getProperty("shortLabel"), "format": format, "url": this.baseURL + t.getProperty("bigDataUrl"), @@ -234,11 +257,11 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1 if (t.hasProperty("url")) { config.infoURL = t.getProperty("url") } - if(t.hasProperty("searchIndex")) { - config.searchIndex = t.getProperty("searchIndex") + if (t.hasProperty("searchIndex")) { + config.searchIndex = t.getProperty("searchIndex") } - if(t.hasProperty("searchTrix")) { - config.searchTrix = this.baseURL + t.getProperty("searchTrix") + if (t.hasProperty("searchTrix")) { + config.searchTrix = this.baseURL + t.getProperty("searchTrix") } if (t.hasProperty("group")) { @@ -345,8 +368,8 @@ async function loadStanzas(options) { // Break - start a new node startNewNode = true } else { - const key = line.substring(indent, i) + if (key.startsWith("#")) continue const value = line.substring(i + 1) if (startNewNode) { // Start a new node -- indent is currently ignored as igv.js does not support sub-tracks, diff --git a/js/ui/chromosomeSelectWidget.js b/js/ui/chromosomeSelectWidget.js index 751034ef4..d62573535 100644 --- a/js/ui/chromosomeSelectWidget.js +++ b/js/ui/chromosomeSelectWidget.js @@ -65,11 +65,7 @@ class ChromosomeSelectWidget { // Add the "all" selector if whole genome view is supported if (genome.showWholeGenomeView()) { - const name = 'all' - const option = document.createElement('option') - option.setAttribute('value', name) - option.innerText = genome.getChromosomeDisplayName(name) - this.select.appendChild(option) + list.unshift("all") } if (list.length < 1000) { diff --git a/test/data/genomes/GCF_000002655.1.chromAlias.bb b/test/data/genomes/GCF_000002655.1.chromAlias.bb new file mode 100644 index 000000000..9c21ef476 Binary files /dev/null and b/test/data/genomes/GCF_000002655.1.chromAlias.bb differ diff --git a/test/data/genomes/GCF_000002655.1.chromAlias.txt b/test/data/genomes/GCF_000002655.1.chromAlias.txt new file mode 100644 index 000000000..f04d5686a --- /dev/null +++ b/test/data/genomes/GCF_000002655.1.chromAlias.txt @@ -0,0 +1,9 @@ +# refseq assembly genbank ncbi ucsc +NC_007194.1 1 CM000169.1 1 chr1 +NC_007195.1 2 CM000170.1 2 chr2 +NC_007196.1 3 CM000171.1 3 chr3 +NC_007197.1 4 CM000172.1 4 chr4 +NC_007198.1 5 CM000173.1 5 chr5 +NC_007199.1 6 CM000174.1 6 chr6 +NC_007200.1 7 CM000175.1 7 chr7 +NC_007201.1 8 CM000176.1 8 chr8 diff --git a/test/data/genomes/hub.txt b/test/data/genomes/hub.txt new file mode 100644 index 000000000..676408fbe --- /dev/null +++ b/test/data/genomes/hub.txt @@ -0,0 +1,309 @@ +hub GCF_000002655.1 genome assembly +shortLabel ascomycetes A.fumigatus Af293 +longLabel ascomycetes A.fumigatus Af293/Aspergillus fumigatus Af293/GCF_000002655.1_ASM265v1 genome assembly +useOneFile on +email hclawson@ucsc.edu +descriptionUrl html/GCF_000002655.1_ASM265v1.description.html + +genome GCF_000002655.1 +taxId 330879 +groups groups.txt +description ascomycetes A.fumigatus Af293 +twoBitPath GCF_000002655.1.2bit +twoBitBptURL GCF_000002655.1.2bit.bpt +chromSizes GCF_000002655.1.chrom.sizes.txt +chromAliasBb GCF_000002655.1.chromAlias.bb +chromAuthority ucsc +organism ASM265v1 Jun. 2005 +defaultPos NC_007194.1:1639659-1649659 +scientificName Aspergillus fumigatus Af293 +htmlPath html/GCF_000002655.1_ASM265v1.description.html +blat dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/002/655/GCF_000002655.1 +transBlat dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/002/655/GCF_000002655.1 +isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/002/655/GCF_000002655.1 + +track assembly +longLabel Assembly +shortLabel Assembly +visibility pack +colorByStrand 150,100,30 230,170,40 +color 150,100,30 +altColor 230,170,40 +bigDataUrl bbi/GCF_000002655.1_ASM265v1.assembly.bb +type bigBed 6 +html html/GCF_000002655.1_ASM265v1.assembly +searchIndex name +searchTrix ixIxx/GCF_000002655.1_ASM265v1.assembly.ix +url https://www.ncbi.nlm.nih.gov/nuccore/$$ +urlLabel NCBI Nucleotide database: +group map + +track gap +longLabel AGP gap +shortLabel Gap (AGP defined) +visibility dense +color 0,0,0 +bigDataUrl bbi/GCF_000002655.1_ASM265v1.gap.bb +type bigBed 4 +group map +html html/GCF_000002655.1_ASM265v1.gap + +track cytoBandIdeo +shortLabel Chromosome Band (Ideogram) +longLabel Ideogram for Orientation +group map +visibility dense +type bigBed 4 + +bigDataUrl bbi/GCF_000002655.1_ASM265v1.cytoBand.bb + +track gc5Base +shortLabel GC Percent +longLabel GC Percent in 5-Base Windows +group map +visibility full +autoScale Off +maxHeightPixels 128:36:16 +graphTypeDefault Bar +gridDefault OFF +windowingFunction Mean +color 0,0,0 +altColor 128,128,128 +viewLimits 30:70 +type bigWig 0 100 +bigDataUrl bbi/GCF_000002655.1_ASM265v1.gc5Base.bw +html html/GCF_000002655.1_ASM265v1.gc5Base + +track tanDups +shortLabel Tandem Dups +longLabel Paired identical sequences +compositeTrack on +visibility hide +type bigBed 12 +group map +html html/GCF_000002655.1_ASM265v1.tanDups + + track tandemDups + parent tanDups on + shortLabel Tandem Dups + longLabel Paired exactly identical sequence survey over entire genome assembly + bigDataUrl bbi/GCF_000002655.1_ASM265v1.tandemDups.bb + type bigBed 12 + +track repeatMasker +compositeTrack on +shortLabel RepeatMasker +longLabel Repeating Elements by RepeatMasker +group varRep +visibility dense +type bigBed 6 + +colorByStrand 50,50,150 150,50,50 +maxWindowToDraw 10000000 +spectrum on +html html/GCF_000002655.1_ASM265v1.repeatMasker + + track repeatMaskerLINE + parent repeatMasker + shortLabel LINE + longLabel LINE Repeating Elements by RepeatMasker + type bigBed 6 + + priority 2 + bigDataUrl bbi/GCF_000002655.1_ASM265v1.rmsk.LINE.bb + + track repeatMaskerLTR + parent repeatMasker + shortLabel LTR + longLabel LTR Repeating Elements by RepeatMasker + type bigBed 6 + + priority 3 + bigDataUrl bbi/GCF_000002655.1_ASM265v1.rmsk.LTR.bb + + track repeatMaskerDNA + parent repeatMasker + shortLabel DNA + longLabel DNA Repeating Elements by RepeatMasker + type bigBed 6 + + priority 4 + bigDataUrl bbi/GCF_000002655.1_ASM265v1.rmsk.DNA.bb + + track repeatMaskerSimple + parent repeatMasker + shortLabel Simple + longLabel Simple Repeating Elements by RepeatMasker + type bigBed 6 + + priority 5 + bigDataUrl bbi/GCF_000002655.1_ASM265v1.rmsk.Simple.bb + + track repeatMaskerLowComplexity + parent repeatMasker + shortLabel Low Complexity + longLabel Low Complexity Repeating Elements by RepeatMasker + type bigBed 6 + + priority 6 + bigDataUrl bbi/GCF_000002655.1_ASM265v1.rmsk.Low_complexity.bb + + track repeatMaskerRNA + parent repeatMasker + shortLabel RNA + longLabel RNA Repeating Elements by RepeatMasker + type bigBed 6 + + priority 8 + bigDataUrl bbi/GCF_000002655.1_ASM265v1.rmsk.RNA.bb + +track simpleRepeat +shortLabel Simple Repeats +longLabel Simple Tandem Repeats by TRF +group varRep +visibility dense +type bigBed 4 + +bigDataUrl bbi/GCF_000002655.1_ASM265v1.simpleRepeat.bb +html html/GCF_000002655.1_ASM265v1.simpleRepeat + +track refSeqComposite +compositeTrack on +shortLabel NCBI RefSeq +longLabel RefSeq gene predictions from NCBI +group genes +visibility pack +type bigBed +dragAndDrop subTracks +allButtonPair on +dataVersion INSDC submitter (2020-03-07) +html html/GCF_000002655.1_ASM265v1.refSeqComposite +priority 2 + + track ncbiRefSeq + parent refSeqComposite on + color 12,12,120 + altColor 120,12,12 + shortLabel RefSeq All + type bigGenePred + labelFields name,geneName,geneName2 + defaultLabelFields geneName2 + searchIndex name + searchTrix ixIxx/GCF_000002655.1_ASM265v1.ncbiRefSeq.ix + bigDataUrl bbi/GCF_000002655.1_ASM265v1.ncbiRefSeq.bb + longLabel NCBI RefSeq genes, curated and predicted sets (NM_*, XM_*, NR_*, XR_*, NP_* or YP_*) + idXref ncbiRefSeqLink mrnaAcc name + baseColorUseCds given + baseColorDefault genomicCodons + priority 1 + + track ncbiRefSeqPredicted + color 12,12,120 + parent refSeqComposite on + shortLabel RefSeq Predicted + longLabel NCBI RefSeq genes, predicted subset (XM_* or XR_*) + type bigGenePred + labelFields name,geneName,geneName2 + defaultLabelFields geneName2 + searchIndex name + searchTrix ixIxx/GCF_000002655.1_ASM265v1.ncbiRefSeqPredicted.ix + idXref ncbiRefSeqLink mrnaAcc name + bigDataUrl bbi/GCF_000002655.1_ASM265v1.ncbiRefSeqPredicted.bb + baseColorUseCds given + baseColorDefault genomicCodons + priority 3 + + track ncbiRefSeqOther + color 32,32,32 + parent refSeqComposite on + shortLabel RefSeq Other + longLabel NCBI RefSeq other annotations (not NM_*, NR_*, XM_*, XR_*, NP_* or YP_*) + priority 4 + searchIndex name + searchTrix ixIxx/GCF_000002655.1_ASM265v1.ncbiRefSeqOther.ix + bigDataUrl bbi/GCF_000002655.1_ASM265v1.ncbiRefSeqOther.bb + type bigBed 12 + + labelFields name + skipEmptyFields on + urls GeneID="https://www.ncbi.nlm.nih.gov/gene/$$" MIM="https://www.ncbi.nlm.nih.gov/omim/$$" HGNC="http://www.genenames.org/cgi-bin/gene_symbol_report?hgnc_id=$$" FlyBase="http://flybase.org/reports/$$" WormBase="http://www.wormbase.org/db/gene/gene?name=$$" RGD="https://rgd.mcw.edu/rgdweb/search/search.html?term=$$" SGD="https://www.yeastgenome.org/locus/$$" miRBase="http://www.mirbase.org/cgi-bin/mirna_entry.pl?acc=$$" ZFIN="https://zfin.org/$$" MGI="http://www.informatics.jax.org/marker/$$" + + track ncbiRefSeqPsl + priority 5 + parent refSeqComposite off + shortLabel RefSeq Alignments + longLabel RefSeq Alignments of RNAs + type bigPsl + searchIndex name + bigDataUrl bbi/GCF_000002655.1_ASM265v1.bigPsl.bb + indelDoubleInsert on + indelQueryInsert on + showDiffBasesAllScales . + showDiffBasesMaxZoom 10000.0 + showCdsMaxZoom 10000.0 + showCdsAllScales . + baseColorDefault diffCodons + pslSequence no + baseColorUseSequence lfExtra + baseColorUseCds table given + color 0,0,0 + +track cpgIslands +compositeTrack on +shortLabel CpG Islands +longLabel CpG Islands (Islands < 300 Bases are Light Green) +group regulation +visibility pack +type bigBed 4 + +html html/GCF_000002655.1_ASM265v1.cpgIslands + + track cpgIslandExt + parent cpgIslands off + shortLabel CpG Islands + longLabel CpG Islands (Islands < 300 Bases are Light Green) + type bigBed 4 + + priority 1 + bigDataUrl bbi/GCF_000002655.1_ASM265v1.cpgIslandExt.bb + + track cpgIslandExtUnmasked + parent cpgIslands on + shortLabel Unmasked CpG + longLabel CpG Islands on All Sequence (Islands < 300 Bases are Light Green) + type bigBed 4 + + priority 2 + bigDataUrl bbi/GCF_000002655.1_ASM265v1.cpgIslandExtUnmasked.bb + +track windowMasker +shortLabel WM + SDust +longLabel Genomic Intervals Masked by WindowMasker + SDust +group varRep +visibility dense +type bigBed 3 +bigDataUrl bbi/GCF_000002655.1_ASM265v1.windowMasker.bb +html html/GCF_000002655.1_ASM265v1.windowMasker + +track allGaps +shortLabel All Gaps +longLabel All gaps of unknown nucleotides (N's), including AGP annotated gaps +group map +visibility dense +type bigBed 3 +bigDataUrl bbi/GCF_000002655.1_ASM265v1.allGaps.bb +html html/GCF_000002655.1_ASM265v1.allGaps + +track augustus +shortLabel Augustus +longLabel Augustus Gene Predictions +group genes +visibility dense +color 180,0,0 +type bigGenePred +bigDataUrl bbi/GCF_000002655.1_ASM265v1.augustus.bb +html html/GCF_000002655.1_ASM265v1.augustus + +track xenoRefGene +shortLabel RefSeq mRNAs +longLabel RefSeq mRNAs mapped to this assembly +group rna +visibility pack +color 180,0,0 +type bigGenePred +bigDataUrl bbi/GCF_000002655.1_ASM265v1.xenoRefGene.bb +url https://www.ncbi.nlm.nih.gov/nuccore/$$ +urlLabel NCBI Nucleotide database: +labelFields name,geneName,geneName2 +defaultLabelFields geneName +searchIndex name +searchTrix ixIxx/GCF_000002655.1_ASM265v1.xenoRefGene.ix +html html/GCF_000002655.1_ASM265v1.xenoRefGene + diff --git a/test/data/hubs/ENCFF754TJH.wig b/test/data/hubs/ENCFF754TJH.wig new file mode 100644 index 000000000..970736df9 --- /dev/null +++ b/test/data/hubs/ENCFF754TJH.wig @@ -0,0 +1,2621 @@ +#bedGraph section chr9:35696794-35728096 +chr9 35726969 35726977 8.62197 +chr9 35726977 35726986 7.45196 +chr9 35726986 35726989 7.51607 +chr9 35726989 35726992 6.45094 +chr9 35726992 35727002 7.51607 +chr9 35727002 35727006 8.62197 +chr9 35727006 35727015 9.76519 +chr9 35727015 35727021 8.62197 +chr9 35727021 35727025 9.76519 +chr9 35727025 35727065 10.9428 +chr9 35727065 35727069 12.1523 +chr9 35727069 35727070 13.3915 +chr9 35727070 35727081 12.1523 +chr9 35727081 35727084 13.3915 +chr9 35727084 35727087 14.6585 +chr9 35727087 35727090 13.3915 +chr9 35727090 35727094 12.1523 +chr9 35727094 35727103 10.9428 +chr9 35727103 35727104 12.1523 +chr9 35727104 35727107 13.3915 +chr9 35727107 35727109 12.1523 +chr9 35727109 35727121 10.9428 +chr9 35727121 35727124 12.1523 +chr9 35727124 35727127 13.3915 +chr9 35727127 35727129 14.6585 +chr9 35727129 35727131 15.9518 +chr9 35727131 35727132 14.9609 +chr9 35727132 35727135 13.729 +chr9 35727135 35727140 14.9609 +chr9 35727140 35727142 16.2176 +chr9 35727142 35727143 14.9609 +chr9 35727143 35727146 16.2176 +chr9 35727146 35727147 14.9609 +chr9 35727147 35727150 16.2176 +chr9 35727150 35727151 17.4975 +chr9 35727151 35727161 18.7997 +chr9 35727161 35727162 17.4975 +chr9 35727162 35727163 18.7997 +chr9 35727163 35727165 20.1229 +chr9 35727165 35727167 18.7997 +chr9 35727167 35727173 20.1229 +chr9 35727173 35727175 13.1908 +chr9 35727175 35727178 14.214 +chr9 35727178 35727187 15.2572 +chr9 35727187 35727190 16.3196 +chr9 35727190 35727193 17.4004 +chr9 35727193 35727199 18.4987 +chr9 35727199 35727205 19.614 +chr9 35727205 35727212 18.4987 +chr9 35727212 35727214 19.614 +chr9 35727214 35727215 18.4987 +chr9 35727215 35727221 19.614 +chr9 35727221 35727222 18.4987 +chr9 35727222 35727224 20.7455 +chr9 35727224 35727229 19.614 +chr9 35727229 35727231 20.7455 +chr9 35727231 35727236 19.614 +chr9 35727236 35727239 20.7455 +chr9 35727239 35727240 21.8928 +chr9 35727240 35727243 23.0552 +chr9 35727243 35727244 21.8928 +chr9 35727244 35727246 20.7455 +chr9 35727246 35727250 23.0552 +chr9 35727250 35727261 24.2323 +chr9 35727261 35727262 23.0552 +chr9 35727262 35727264 24.2323 +chr9 35727264 35727266 23.0552 +chr9 35727266 35727267 24.2323 +chr9 35727267 35727271 23.0552 +chr9 35727271 35727274 31.3667 +chr9 35727274 35727275 32.8443 +chr9 35727275 35727280 31.3667 +chr9 35727280 35727283 29.9038 +chr9 35727283 35727287 28.456 +chr9 35727287 35727289 27.0241 +chr9 35727289 35727290 28.456 +chr9 35727290 35727295 27.0241 +chr9 35727295 35727299 28.456 +chr9 35727299 35727302 29.9038 +chr9 35727302 35727303 28.456 +chr9 35727303 35727307 27.0241 +chr9 35727307 35727311 25.6084 +chr9 35727311 35727313 28.456 +chr9 35727313 35727315 30.6236 +chr9 35727315 35727316 29.1087 +chr9 35727316 35727328 27.6103 +chr9 35727328 35727330 26.1288 +chr9 35727330 35727333 24.6649 +chr9 35727333 35727338 23.2195 +chr9 35727338 35727339 21.7934 +chr9 35727339 35727346 20.3874 +chr9 35727346 35727349 21.7934 +chr9 35727349 35727350 20.3874 +chr9 35727350 35727352 21.7934 +chr9 35727352 35727354 20.3874 +chr9 35727354 35727355 21.7934 +chr9 35727355 35727357 20.3874 +chr9 35727357 35727362 21.7934 +chr9 35727362 35727365 20.3874 +chr9 35727365 35727371 18.7997 +chr9 35727371 35727374 20.1229 +chr9 35727374 35727376 21.4662 +chr9 35727376 35727380 20.1229 +chr9 35727380 35727384 18.7997 +chr9 35727384 35727386 20.1229 +chr9 35727386 35727390 18.7997 +chr9 35727390 35727393 17.4975 +chr9 35727393 35727394 18.7997 +chr9 35727394 35727398 20.1229 +chr9 35727398 35727399 22.8288 +chr9 35727399 35727402 24.2098 +chr9 35727402 35727403 22.8288 +chr9 35727403 35727404 24.2098 +chr9 35727404 35727407 25.6084 +chr9 35727407 35727412 27.0241 +chr9 35727412 35727413 28.456 +chr9 35727413 35727415 27.0241 +chr9 35727415 35727416 19.614 +chr9 35727416 35727425 20.7455 +chr9 35727425 35727431 23.0552 +chr9 35727431 35727439 21.8928 +chr9 35727439 35727442 20.7455 +chr9 35727442 35727443 21.8928 +chr9 35727443 35727450 23.0552 +chr9 35727450 35727452 24.2323 +chr9 35727452 35727453 26.6286 +chr9 35727453 35727457 27.8468 +chr9 35727457 35727458 29.0781 +chr9 35727458 35727469 27.8468 +chr9 35727469 35727476 29.0781 +chr9 35727476 35727479 30.3218 +chr9 35727479 35727485 31.5778 +chr9 35727485 35727486 32.8456 +chr9 35727486 35727491 31.5778 +chr9 35727491 35727501 32.8456 +chr9 35727501 35727503 31.5778 +chr9 35727503 35727505 32.8456 +chr9 35727505 35727511 43.5622 +chr9 35727511 35727514 41.9937 +chr9 35727514 35727518 40.437 +chr9 35727518 35727519 41.9937 +chr9 35727519 35727531 43.5622 +chr9 35727531 35727533 45.1423 +chr9 35727533 35727536 43.5622 +chr9 35727536 35727537 46.7337 +chr9 35727537 35727538 45.1423 +chr9 35727538 35727541 43.5622 +chr9 35727541 35727543 45.1423 +chr9 35727543 35727546 43.5622 +chr9 35727546 35727547 41.9937 +chr9 35727547 35727548 40.437 +chr9 35727548 35727553 41.9937 +chr9 35727553 35727555 43.5622 +chr9 35727555 35727564 46.2963 +chr9 35727564 35727565 47.9521 +chr9 35727565 35727576 46.2963 +chr9 35727576 35727578 47.9521 +chr9 35727578 35727579 49.6192 +chr9 35727579 35727580 51.2972 +chr9 35727580 35727582 52.9859 +chr9 35727582 35727583 51.2972 +chr9 35727583 35727585 47.9521 +chr9 35727585 35727588 49.6192 +chr9 35727588 35727589 51.2972 +chr9 35727589 35727591 52.9859 +chr9 35727591 35727592 51.2972 +chr9 35727592 35727593 47.9521 +chr9 35727593 35727595 46.2963 +chr9 35727595 35727596 47.9521 +chr9 35727596 35727599 46.2963 +chr9 35727599 35727601 47.9521 +chr9 35727601 35727603 46.7337 +chr9 35727603 35727607 48.336 +chr9 35727607 35727612 49.9491 +chr9 35727612 35727617 51.5726 +chr9 35727617 35727620 54.85 +chr9 35727620 35727621 56.5035 +chr9 35727621 35727624 58.1665 +chr9 35727624 35727627 59.8388 +chr9 35727627 35727628 61.5202 +chr9 35727628 35727632 63.2106 +chr9 35727632 35727633 64.9098 +chr9 35727633 35727635 63.2106 +chr9 35727635 35727637 64.9098 +chr9 35727637 35727638 63.2106 +chr9 35727638 35727639 64.9098 +chr9 35727639 35727640 66.6175 +chr9 35727640 35727643 68.3337 +chr9 35727643 35727645 66.6175 +chr9 35727645 35727646 68.3337 +chr9 35727646 35727648 70.0582 +chr9 35727648 35727654 71.7907 +chr9 35727654 35727657 73.5313 +chr9 35727657 35727658 75.2796 +chr9 35727658 35727661 73.5313 +chr9 35727661 35727662 75.2796 +chr9 35727662 35727664 77.0356 +chr9 35727664 35727668 75.2796 +chr9 35727668 35727669 77.0356 +chr9 35727669 35727671 78.7992 +chr9 35727671 35727672 77.0356 +chr9 35727672 35727674 80.5702 +chr9 35727674 35727675 78.7992 +chr9 35727675 35727676 80.5702 +chr9 35727676 35727687 77.0356 +chr9 35727687 35727693 78.7992 +chr9 35727693 35727695 77.0356 +chr9 35727695 35727697 75.2796 +chr9 35727697 35727704 77.0356 +chr9 35727704 35727708 75.2796 +chr9 35727708 35727714 77.0356 +chr9 35727714 35727716 80.5702 +chr9 35727716 35727718 78.7992 +chr9 35727718 35727726 77.0356 +chr9 35727726 35727730 78.7992 +chr9 35727730 35727731 82.3485 +chr9 35727731 35727732 80.5702 +chr9 35727732 35727736 82.3485 +chr9 35727736 35727738 84.134 +chr9 35727738 35727739 85.9265 +chr9 35727739 35727740 84.134 +chr9 35727740 35727741 85.9265 +chr9 35727741 35727754 89.6805 +chr9 35727754 35727755 91.5414 +chr9 35727755 35727756 93.4091 +chr9 35727756 35727757 91.5414 +chr9 35727757 35727759 89.6805 +chr9 35727759 35727760 87.8265 +chr9 35727760 35727762 84.1399 +chr9 35727762 35727763 85.9796 +chr9 35727763 35727765 87.8265 +chr9 35727765 35727766 85.9796 +chr9 35727766 35727769 87.8265 +chr9 35727769 35727770 87.4079 +chr9 35727770 35727771 89.2549 +chr9 35727771 35727772 87.4079 +chr9 35727772 35727775 85.5679 +chr9 35727775 35727777 87.4079 +chr9 35727777 35727778 89.2549 +chr9 35727778 35727780 87.4079 +chr9 35727780 35727781 85.5679 +chr9 35727781 35727787 89.2549 +chr9 35727787 35727788 87.4079 +chr9 35727788 35727789 85.5679 +chr9 35727789 35727792 87.4079 +chr9 35727792 35727801 85.5679 +chr9 35727801 35727802 83.7352 +chr9 35727802 35727803 81.9097 +chr9 35727803 35727806 85.5679 +chr9 35727806 35727808 89.2549 +chr9 35727808 35727810 87.4079 +chr9 35727810 35727812 89.2549 +chr9 35727812 35727813 87.4079 +chr9 35727813 35727816 89.2549 +chr9 35727816 35727817 88.8361 +chr9 35727817 35727818 90.6832 +chr9 35727818 35727822 88.8361 +chr9 35727822 35727823 92.5372 +chr9 35727823 35727824 94.3978 +chr9 35727824 35727825 96.2651 +chr9 35727825 35727827 98.1389 +chr9 35727827 35727831 96.2651 +chr9 35727831 35727832 98.1389 +chr9 35727832 35727834 96.2651 +chr9 35727834 35727836 98.1389 +chr9 35727836 35727837 100.019 +chr9 35727837 35727839 101.906 +chr9 35727839 35727843 103.799 +chr9 35727843 35727844 105.698 +chr9 35727844 35727846 107.603 +chr9 35727846 35727847 109.514 +chr9 35727847 35727854 111.431 +chr9 35727854 35727855 107.603 +chr9 35727855 35727858 105.698 +chr9 35727858 35727860 107.603 +chr9 35727860 35727862 106.178 +chr9 35727862 35727863 108.09 +chr9 35727863 35727865 111.932 +chr9 35727865 35727866 110.008 +chr9 35727866 35727867 108.09 +chr9 35727867 35727868 110.008 +chr9 35727868 35727869 108.09 +chr9 35727869 35727870 106.178 +chr9 35727870 35727874 104.272 +chr9 35727874 35727875 106.178 +chr9 35727875 35727884 104.272 +chr9 35727884 35727887 100.508 +chr9 35727887 35727891 98.6628 +chr9 35727891 35727892 96.8238 +chr9 35727892 35727895 94.9912 +chr9 35727895 35727898 93.165 +chr9 35727898 35727899 94.9912 +chr9 35727899 35727901 96.8238 +chr9 35727901 35727902 94.9912 +chr9 35727902 35727906 93.165 +chr9 35727906 35727907 94.9912 +chr9 35727907 35727909 93.165 +chr9 35727909 35727910 91.3453 +chr9 35727910 35727915 89.5323 +chr9 35727915 35727916 85.9265 +chr9 35727916 35727918 87.726 +chr9 35727918 35727919 91.3453 +chr9 35727919 35727920 89.5323 +chr9 35727920 35727921 91.3453 +chr9 35727921 35727924 87.726 +chr9 35727924 35727926 85.9265 +chr9 35727926 35727929 87.726 +chr9 35727929 35727932 85.9265 +chr9 35727932 35727938 87.726 +chr9 35727938 35727939 89.5323 +chr9 35727939 35727940 87.726 +chr9 35727940 35727942 89.5323 +chr9 35727942 35727943 91.3453 +chr9 35727943 35727946 89.5323 +chr9 35727946 35727947 87.726 +chr9 35727947 35727948 89.5323 +chr9 35727948 35727949 93.165 +chr9 35727949 35727950 89.5323 +chr9 35727950 35727954 85.9265 +chr9 35727954 35727955 84.134 +chr9 35727955 35727957 85.9265 +chr9 35727957 35727959 84.134 +chr9 35727959 35727961 85.9265 +chr9 35727961 35727962 84.134 +chr9 35727962 35727963 82.3485 +chr9 35727963 35727964 80.5702 +chr9 35727964 35727965 78.7992 +chr9 35727965 35727967 77.0356 +chr9 35727967 35727968 78.7992 +chr9 35727968 35727971 77.0356 +chr9 35727971 35727972 78.7992 +chr9 35727972 35727973 80.5702 +chr9 35727973 35727974 82.3485 +chr9 35727974 35727976 80.5702 +chr9 35727976 35727977 78.7992 +chr9 35727977 35727980 77.0356 +chr9 35727980 35727982 73.5313 +chr9 35727982 35727983 75.2796 +chr9 35727983 35727985 73.5313 +chr9 35727985 35727987 71.7907 +chr9 35727987 35727991 70.0582 +chr9 35727991 35727992 68.3337 +chr9 35727992 35727996 70.0582 +chr9 35727996 35728003 71.7907 +chr9 35728003 35728005 70.0582 +chr9 35728005 35728007 71.7907 +chr9 35728007 35728010 70.0582 +chr9 35728010 35728012 68.3337 +chr9 35728012 35728014 70.0582 +chr9 35728014 35728015 68.3337 +chr9 35728015 35728016 70.0582 +chr9 35728016 35728017 71.7907 +chr9 35728017 35728020 70.0582 +chr9 35728020 35728023 68.3337 +chr9 35728023 35728024 66.6175 +chr9 35728024 35728027 71.4733 +chr9 35728027 35728032 73.2592 +chr9 35728032 35728033 76.8551 +chr9 35728033 35728034 80.4824 +chr9 35728034 35728035 78.6649 +chr9 35728035 35728038 80.4824 +chr9 35728038 35728040 78.6649 +chr9 35728040 35728041 80.4824 +chr9 35728041 35728042 82.3074 +chr9 35728042 35728045 84.1399 +chr9 35728045 35728046 82.3074 +chr9 35728046 35728049 80.4824 +chr9 35728049 35728053 84.1399 +chr9 35728053 35728054 85.9796 +chr9 35728054 35728072 89.6805 +chr9 35728072 35728073 91.5414 +chr9 35728073 35728074 93.4091 +chr9 35728074 35728075 95.2836 +chr9 35728075 35728078 97.1647 +chr9 35728078 35728080 96.7113 +chr9 35728080 35728081 98.592 +chr9 35728081 35728082 100.479 +chr9 35728082 35728083 98.592 +chr9 35728083 35728086 96.7113 +chr9 35728086 35728087 94.8372 +chr9 35728087 35728088 91.1088 +chr9 35728088 35728090 89.2549 +chr9 35728090 35728091 91.1088 +chr9 35728091 35728092 92.9696 +chr9 35728092 35728094 91.1088 +chr9 35728094 35728095 92.9696 +chr9 35728095 35728096 91.1088 +#bedGraph section chr9:35728096-35730652 +chr9 35728096 35728097 92.9696 +chr9 35728097 35728102 96.7113 +chr9 35728102 35728108 94.8372 +chr9 35728108 35728109 96.7113 +chr9 35728109 35728110 94.8372 +chr9 35728110 35728111 96.7113 +chr9 35728111 35728112 92.9696 +chr9 35728112 35728113 91.1088 +chr9 35728113 35728114 89.2549 +chr9 35728114 35728115 91.1088 +chr9 35728115 35728116 92.9696 +chr9 35728116 35728117 94.8372 +chr9 35728117 35728119 96.7113 +chr9 35728119 35728120 98.592 +chr9 35728120 35728125 102.373 +chr9 35728125 35728135 104.272 +chr9 35728135 35728137 106.178 +chr9 35728137 35728138 108.09 +chr9 35728138 35728139 106.178 +chr9 35728139 35728140 108.09 +chr9 35728140 35728144 111.932 +chr9 35728144 35728145 113.861 +chr9 35728145 35728147 111.932 +chr9 35728147 35728150 113.861 +chr9 35728150 35728151 115.797 +chr9 35728151 35728152 117.738 +chr9 35728152 35728153 115.797 +chr9 35728153 35728154 117.738 +chr9 35728154 35728156 119.685 +chr9 35728156 35728159 112.363 +chr9 35728159 35728162 114.259 +chr9 35728162 35728163 112.363 +chr9 35728163 35728164 114.259 +chr9 35728164 35728165 112.363 +chr9 35728165 35728168 114.259 +chr9 35728168 35728169 112.363 +chr9 35728169 35728170 114.259 +chr9 35728170 35728171 112.363 +chr9 35728171 35728172 115.797 +chr9 35728172 35728173 113.861 +chr9 35728173 35728178 111.932 +chr9 35728178 35728180 111.431 +chr9 35728180 35728181 109.514 +chr9 35728181 35728182 107.603 +chr9 35728182 35728184 105.698 +chr9 35728184 35728188 103.799 +chr9 35728188 35728189 105.698 +chr9 35728189 35728194 103.799 +chr9 35728194 35728196 101.906 +chr9 35728196 35728198 100.019 +chr9 35728198 35728212 96.2651 +chr9 35728212 35728214 92.5372 +chr9 35728214 35728215 88.8361 +chr9 35728215 35728218 88.4273 +chr9 35728218 35728219 86.5939 +chr9 35728219 35728220 84.7675 +chr9 35728220 35728221 81.1363 +chr9 35728221 35728222 79.3317 +chr9 35728222 35728223 82.9482 +chr9 35728223 35728228 84.7675 +chr9 35728228 35728229 86.5939 +chr9 35728229 35728230 84.7675 +chr9 35728230 35728231 82.9482 +chr9 35728231 35728232 81.1363 +chr9 35728232 35728235 82.9482 +chr9 35728235 35728236 84.7675 +chr9 35728236 35728237 82.9482 +chr9 35728237 35728239 79.3317 +chr9 35728239 35728241 77.5348 +chr9 35728241 35728250 79.3317 +chr9 35728250 35728253 77.5348 +chr9 35728253 35728254 79.3317 +chr9 35728254 35728255 77.5348 +chr9 35728255 35728256 75.7455 +chr9 35728256 35728257 73.964 +chr9 35728257 35728259 72.1905 +chr9 35728259 35728260 68.668 +chr9 35728260 35728263 65.1792 +chr9 35728263 35728265 63.6317 +chr9 35728265 35728266 61.9326 +chr9 35728266 35728267 60.2424 +chr9 35728267 35728271 58.5613 +chr9 35728271 35728273 60.2424 +chr9 35728273 35728274 58.5613 +chr9 35728274 35728276 56.8895 +chr9 35728276 35728277 55.2273 +chr9 35728277 35728279 53.5749 +chr9 35728279 35728280 51.9324 +chr9 35728280 35728282 50.3001 +chr9 35728282 35728284 48.6783 +chr9 35728284 35728287 45.467 +chr9 35728287 35728291 43.8782 +chr9 35728291 35728293 42.3009 +chr9 35728293 35728298 39.1822 +chr9 35728298 35728300 40.7354 +chr9 35728300 35728301 42.3009 +chr9 35728301 35728303 40.7354 +chr9 35728303 35728305 39.1822 +chr9 35728305 35728315 37.6416 +chr9 35728315 35728316 36.1139 +chr9 35728316 35728317 37.6416 +chr9 35728317 35728319 36.1139 +chr9 35728319 35728320 34.5996 +chr9 35728320 35728322 36.1139 +chr9 35728322 35728324 37.3607 +chr9 35728324 35728325 38.8926 +chr9 35728325 35728326 40.437 +chr9 35728326 35728328 38.8926 +chr9 35728328 35728330 37.3607 +chr9 35728330 35728332 35.8418 +chr9 35728332 35728340 37.3607 +chr9 35728340 35728345 27.8468 +chr9 35728345 35728346 26.6286 +chr9 35728346 35728348 25.4236 +chr9 35728348 35728349 26.6286 +chr9 35728349 35728357 27.8468 +chr9 35728357 35728362 29.0781 +chr9 35728362 35728363 27.8468 +chr9 35728363 35728364 26.6286 +chr9 35728364 35728372 27.8468 +chr9 35728372 35728373 26.6286 +chr9 35728373 35728375 27.8468 +chr9 35728375 35728382 25.4236 +chr9 35728382 35728387 24.2323 +chr9 35728387 35728392 23.0552 +chr9 35728392 35728393 24.2323 +chr9 35728393 35728396 23.0552 +chr9 35728396 35728398 24.2323 +chr9 35728398 35728399 26.6286 +chr9 35728399 35728401 27.8468 +chr9 35728401 35728402 29.0781 +chr9 35728402 35728405 30.3218 +chr9 35728405 35728406 31.5778 +chr9 35728406 35728409 32.8456 +chr9 35728409 35728411 34.125 +chr9 35728411 35728413 32.8456 +chr9 35728413 35728416 34.125 +chr9 35728416 35728420 35.4156 +chr9 35728420 35728423 34.125 +chr9 35728423 35728424 32.8456 +chr9 35728424 35728425 34.125 +chr9 35728425 35728427 36.7172 +chr9 35728427 35728431 38.0294 +chr9 35728431 35728432 39.3521 +chr9 35728432 35728433 40.6851 +chr9 35728433 35728438 42.0279 +chr9 35728438 35728439 40.6851 +chr9 35728439 35728440 39.3521 +chr9 35728440 35728441 40.6851 +chr9 35728441 35728442 42.0279 +chr9 35728442 35728447 43.3806 +chr9 35728447 35728448 46.1142 +chr9 35728448 35728453 48.8843 +chr9 35728453 35728454 50.2826 +chr9 35728454 35728457 51.6894 +chr9 35728457 35728458 53.1047 +chr9 35728458 35728461 54.5283 +chr9 35728461 35728462 55.96 +chr9 35728462 35728465 70.0582 +chr9 35728465 35728466 68.3337 +chr9 35728466 35728473 70.0582 +chr9 35728473 35728475 68.3337 +chr9 35728475 35728478 66.6175 +chr9 35728478 35728479 68.3337 +chr9 35728479 35728480 54.5283 +chr9 35728480 35728483 70.0582 +chr9 35728483 35728486 71.7907 +chr9 35728486 35728487 73.5313 +chr9 35728487 35728489 75.2796 +chr9 35728489 35728492 73.5313 +chr9 35728492 35728494 71.7907 +chr9 35728494 35728498 73.5313 +chr9 35728498 35728499 75.2796 +chr9 35728499 35728507 77.0356 +chr9 35728507 35728510 78.7992 +chr9 35728510 35728513 80.5702 +chr9 35728513 35728516 78.7992 +chr9 35728516 35728522 80.5702 +chr9 35728522 35728524 82.3485 +chr9 35728524 35728526 84.134 +chr9 35728526 35728536 85.9265 +chr9 35728536 35728538 87.726 +chr9 35728538 35728543 85.9265 +chr9 35728543 35728547 84.134 +chr9 35728547 35728548 85.9265 +chr9 35728548 35728550 84.134 +chr9 35728550 35728551 85.9265 +chr9 35728551 35728560 67.6883 +chr9 35728560 35728561 69.1869 +chr9 35728561 35728562 70.6922 +chr9 35728562 35728564 72.2043 +chr9 35728564 35728565 70.6922 +chr9 35728565 35728566 67.6883 +chr9 35728566 35728567 69.1869 +chr9 35728567 35728571 67.6883 +chr9 35728571 35728572 66.1967 +chr9 35728572 35728574 64.7122 +chr9 35728574 35728575 63.2349 +chr9 35728575 35728577 61.7648 +chr9 35728577 35728580 64.7122 +chr9 35728580 35728586 61.7648 +chr9 35728586 35728587 50.6919 +chr9 35728587 35728588 49.4127 +chr9 35728588 35728589 46.8775 +chr9 35728589 35728592 48.1412 +chr9 35728592 35728594 46.8775 +chr9 35728594 35728597 48.1412 +chr9 35728597 35728600 46.8775 +chr9 35728600 35728604 45.6218 +chr9 35728604 35728605 44.3741 +chr9 35728605 35728606 45.6218 +chr9 35728606 35728607 44.3741 +chr9 35728607 35728611 45.6218 +chr9 35728611 35728612 46.8775 +chr9 35728612 35728615 45.6218 +chr9 35728615 35728616 46.8775 +chr9 35728616 35728617 48.1412 +chr9 35728617 35728619 46.8775 +chr9 35728619 35728621 54.5283 +chr9 35728621 35728623 55.96 +chr9 35728623 35728624 54.5283 +chr9 35728624 35728625 55.96 +chr9 35728625 35728628 57.3996 +chr9 35728628 35728629 55.96 +chr9 35728629 35728630 57.3996 +chr9 35728630 35728631 58.847 +chr9 35728631 35728635 60.3021 +chr9 35728635 35728636 61.7648 +chr9 35728636 35728639 60.3021 +chr9 35728639 35728640 58.847 +chr9 35728640 35728642 60.3021 +chr9 35728642 35728644 58.847 +chr9 35728644 35728648 60.3021 +chr9 35728648 35728649 58.847 +chr9 35728649 35728650 60.3021 +chr9 35728650 35728653 58.847 +chr9 35728653 35728654 60.3021 +chr9 35728654 35728657 58.847 +chr9 35728657 35728662 60.3021 +chr9 35728662 35728664 61.7648 +chr9 35728664 35728671 60.3021 +chr9 35728671 35728672 61.7648 +chr9 35728672 35728675 60.3021 +chr9 35728675 35728676 61.7648 +chr9 35728676 35728677 60.3021 +chr9 35728677 35728678 61.7648 +chr9 35728678 35728679 63.2349 +chr9 35728679 35728680 64.7122 +chr9 35728680 35728681 63.2349 +chr9 35728681 35728682 64.7122 +chr9 35728682 35728686 63.2349 +chr9 35728686 35728689 61.7648 +chr9 35728689 35728691 60.3021 +chr9 35728691 35728693 75.2796 +chr9 35728693 35728694 58.847 +chr9 35728694 35728695 60.3021 +chr9 35728695 35728696 58.847 +chr9 35728696 35728697 60.3021 +chr9 35728697 35728702 61.7648 +chr9 35728702 35728706 63.2349 +chr9 35728706 35728707 61.7648 +chr9 35728707 35728709 63.2349 +chr9 35728709 35728710 64.7122 +chr9 35728710 35728711 66.1967 +chr9 35728711 35728713 67.6883 +chr9 35728713 35728716 66.1967 +chr9 35728716 35728717 67.6883 +chr9 35728717 35728719 66.1967 +chr9 35728719 35728726 67.6883 +chr9 35728726 35728729 82.9255 +chr9 35728729 35728731 81.1822 +chr9 35728731 35728733 79.4459 +chr9 35728733 35728734 77.7168 +chr9 35728734 35728736 75.9951 +chr9 35728736 35728739 74.2807 +chr9 35728739 35728743 75.9951 +chr9 35728743 35728744 77.7168 +chr9 35728744 35728746 81.1822 +chr9 35728746 35728758 82.9255 +chr9 35728758 35728759 81.1822 +chr9 35728759 35728765 82.9255 +chr9 35728765 35728766 81.1822 +chr9 35728766 35728767 79.4459 +chr9 35728767 35728768 77.7168 +chr9 35728768 35728769 81.1822 +chr9 35728769 35728770 79.4459 +chr9 35728770 35728771 77.7168 +chr9 35728771 35728772 75.9951 +chr9 35728772 35728774 74.2807 +chr9 35728774 35728776 72.5739 +chr9 35728776 35728783 74.2807 +chr9 35728783 35728785 75.9951 +chr9 35728785 35728788 74.2807 +chr9 35728788 35728790 75.9951 +chr9 35728790 35728791 77.7168 +chr9 35728791 35728792 81.1822 +chr9 35728792 35728793 82.9255 +chr9 35728793 35728794 81.1822 +chr9 35728794 35728801 82.9255 +chr9 35728801 35728802 81.1822 +chr9 35728802 35728805 76.4363 +chr9 35728805 35728812 78.1214 +chr9 35728812 35728815 79.8135 +chr9 35728815 35728819 78.1214 +chr9 35728819 35728821 74.7583 +chr9 35728821 35728832 71.4245 +chr9 35728832 35728833 69.7688 +chr9 35728833 35728834 71.4245 +chr9 35728834 35728836 69.7688 +chr9 35728836 35728837 66.4806 +chr9 35728837 35728842 64.8484 +chr9 35728842 35728850 61.6085 +chr9 35728850 35728854 60.001 +chr9 35728854 35728857 61.6085 +chr9 35728857 35728858 60.001 +chr9 35728858 35728859 61.6085 +chr9 35728859 35728861 60.001 +chr9 35728861 35728863 61.6085 +chr9 35728863 35728866 63.2243 +chr9 35728866 35728873 64.8484 +chr9 35728873 35728879 66.4806 +chr9 35728879 35728880 64.8484 +chr9 35728880 35728884 66.4806 +chr9 35728884 35728885 64.8484 +chr9 35728885 35728886 63.2243 +chr9 35728886 35728888 60.001 +chr9 35728888 35728892 58.4022 +chr9 35728892 35728894 60.8494 +chr9 35728894 35728896 59.2082 +chr9 35728896 35728898 57.5759 +chr9 35728898 35728899 59.2082 +chr9 35728899 35728901 55.9528 +chr9 35728901 35728904 54.3391 +chr9 35728904 35728908 52.7348 +chr9 35728908 35728910 49.5558 +chr9 35728910 35728914 51.9324 +chr9 35728914 35728915 53.5749 +chr9 35728915 35728916 51.9324 +chr9 35728916 35728917 50.3001 +chr9 35728917 35728919 49.9491 +chr9 35728919 35728921 48.336 +chr9 35728921 35728922 46.7337 +chr9 35728922 35728923 48.336 +chr9 35728923 35728924 46.7337 +chr9 35728924 35728926 45.1423 +chr9 35728926 35728929 43.5622 +chr9 35728929 35728931 41.9937 +chr9 35728931 35728932 38.8926 +chr9 35728932 35728934 37.3607 +chr9 35728934 35728936 35.8418 +chr9 35728936 35728937 34.3362 +chr9 35728937 35728939 32.8443 +chr9 35728939 35728942 34.3362 +chr9 35728942 35728945 32.8443 +chr9 35728945 35728949 31.3667 +chr9 35728949 35728950 29.9038 +chr9 35728950 35728951 31.3667 +chr9 35728951 35728952 29.9038 +chr9 35728952 35728953 28.456 +chr9 35728953 35728957 27.0241 +chr9 35728957 35728958 25.6084 +chr9 35728958 35728960 24.2098 +chr9 35728960 35728967 25.6084 +chr9 35728967 35728971 24.2098 +chr9 35728971 35728973 25.6084 +chr9 35728973 35728979 24.2098 +chr9 35728979 35728980 22.8288 +chr9 35728980 35728987 21.4662 +chr9 35728987 35728991 20.1229 +chr9 35728991 35728994 18.7997 +chr9 35728994 35728996 17.4975 +chr9 35728996 35728998 16.2176 +chr9 35728998 35729001 14.9609 +chr9 35729001 35729002 12.5232 +chr9 35729002 35729003 13.729 +chr9 35729003 35729009 12.5232 +chr9 35729009 35729011 11.3451 +chr9 35729011 35729014 10.1968 +chr9 35729014 35729015 9.08031 +chr9 35729015 35729018 10.1968 +chr9 35729018 35729020 9.08031 +chr9 35729020 35729021 7.99814 +chr9 35729021 35729022 6.9532 +chr9 35729022 35729023 7.99814 +chr9 35729023 35729038 6.9532 +chr9 35729038 35729045 5.94894 +chr9 35729045 35729057 6.9532 +chr9 35729057 35729062 7.45196 +chr9 35729062 35729079 6.39373 +chr9 35729079 35729084 5.38041 +chr9 35729084 35729090 6.39373 +chr9 35729090 35729095 5.38041 +chr9 35729095 35729125 6.39373 +chr9 35729125 35729128 8.55095 +chr9 35729128 35729130 7.99814 +chr9 35729130 35729132 9.08031 +chr9 35729132 35729141 10.1968 +chr9 35729141 35729145 11.3451 +chr9 35729145 35729147 12.5232 +chr9 35729147 35729149 13.729 +chr9 35729149 35729170 14.9609 +chr9 35729170 35729171 16.2176 +chr9 35729171 35729175 17.4975 +chr9 35729175 35729177 18.7997 +chr9 35729177 35729179 20.1229 +chr9 35729179 35729182 21.4662 +chr9 35729182 35729183 22.8288 +chr9 35729183 35729184 24.2098 +chr9 35729184 35729188 25.6084 +chr9 35729188 35729192 27.0241 +chr9 35729192 35729194 28.456 +chr9 35729194 35729199 27.0241 +chr9 35729199 35729201 28.456 +chr9 35729201 35729202 29.9038 +chr9 35729202 35729204 31.3667 +chr9 35729204 35729205 32.8443 +chr9 35729205 35729209 34.3362 +chr9 35729209 35729211 35.8418 +chr9 35729211 35729213 37.3607 +chr9 35729213 35729214 40.437 +chr9 35729214 35729216 41.9937 +chr9 35729216 35729219 43.5622 +chr9 35729219 35729226 45.1423 +chr9 35729226 35729228 48.336 +chr9 35729228 35729232 49.9491 +chr9 35729232 35729236 38.0294 +chr9 35729236 35729238 39.3521 +chr9 35729238 35729243 40.6851 +chr9 35729243 35729245 42.0279 +chr9 35729245 35729247 43.3806 +chr9 35729247 35729248 44.7427 +chr9 35729248 35729250 46.1142 +chr9 35729250 35729253 47.4948 +chr9 35729253 35729256 48.8843 +chr9 35729256 35729257 50.2826 +chr9 35729257 35729258 51.6894 +chr9 35729258 35729260 54.5283 +chr9 35729260 35729261 55.96 +chr9 35729261 35729263 57.3996 +chr9 35729263 35729265 58.847 +chr9 35729265 35729268 55.96 +chr9 35729268 35729270 73.5313 +chr9 35729270 35729272 71.7907 +chr9 35729272 35729273 70.0582 +chr9 35729273 35729274 71.7907 +chr9 35729274 35729275 73.5313 +chr9 35729275 35729278 75.2796 +chr9 35729278 35729281 77.0356 +chr9 35729281 35729282 75.2796 +chr9 35729282 35729287 73.5313 +chr9 35729287 35729289 71.7907 +chr9 35729289 35729290 70.0582 +chr9 35729290 35729293 71.7907 +chr9 35729293 35729294 70.0582 +chr9 35729294 35729296 71.7907 +chr9 35729296 35729300 70.0582 +chr9 35729300 35729302 73.5313 +chr9 35729302 35729303 75.2796 +chr9 35729303 35729307 77.0356 +chr9 35729307 35729308 78.7992 +chr9 35729308 35729309 80.5702 +chr9 35729309 35729311 82.3485 +chr9 35729311 35729316 80.5702 +chr9 35729316 35729317 82.3485 +chr9 35729317 35729321 84.134 +chr9 35729321 35729323 85.9265 +chr9 35729323 35729324 84.134 +chr9 35729324 35729326 82.3485 +chr9 35729326 35729334 85.9265 +chr9 35729334 35729336 87.726 +chr9 35729336 35729341 89.5323 +chr9 35729341 35729343 91.3453 +chr9 35729343 35729348 93.165 +chr9 35729348 35729349 96.8238 +chr9 35729349 35729350 94.9912 +chr9 35729350 35729353 96.8238 +chr9 35729353 35729356 93.165 +chr9 35729356 35729357 91.3453 +chr9 35729357 35729358 93.165 +chr9 35729358 35729359 91.3453 +chr9 35729359 35729364 89.5323 +chr9 35729364 35729366 87.726 +chr9 35729366 35729372 85.9265 +chr9 35729372 35729373 90.6832 +chr9 35729373 35729378 88.8361 +chr9 35729378 35729379 86.9959 +chr9 35729379 35729380 88.8361 +chr9 35729380 35729381 90.6832 +chr9 35729381 35729383 92.5372 +chr9 35729383 35729384 90.6832 +chr9 35729384 35729387 88.8361 +chr9 35729387 35729390 85.1628 +chr9 35729390 35729391 83.3369 +chr9 35729391 35729393 81.5183 +chr9 35729393 35729394 83.3369 +chr9 35729394 35729398 81.5183 +chr9 35729398 35729400 79.7071 +chr9 35729400 35729404 80.0916 +chr9 35729404 35729406 81.9097 +chr9 35729406 35729408 83.7352 +chr9 35729408 35729409 85.5679 +chr9 35729409 35729411 87.4079 +chr9 35729411 35729413 89.2549 +chr9 35729413 35729414 87.4079 +chr9 35729414 35729415 85.5679 +chr9 35729415 35729416 83.7352 +chr9 35729416 35729418 85.5679 +chr9 35729418 35729419 81.9097 +chr9 35729419 35729421 83.7352 +chr9 35729421 35729424 85.5679 +chr9 35729424 35729425 89.2549 +chr9 35729425 35729428 87.4079 +chr9 35729428 35729430 89.2549 +chr9 35729430 35729431 87.4079 +chr9 35729431 35729440 89.2549 +chr9 35729440 35729442 87.4079 +chr9 35729442 35729443 85.5679 +chr9 35729443 35729445 83.7352 +chr9 35729445 35729446 81.9097 +chr9 35729446 35729448 80.0916 +chr9 35729448 35729449 78.2811 +chr9 35729449 35729450 76.4783 +chr9 35729450 35729451 74.6833 +chr9 35729451 35729456 76.4783 +chr9 35729456 35729457 74.6833 +chr9 35729457 35729458 72.8962 +chr9 35729458 35729459 71.1173 +chr9 35729459 35729462 69.3466 +chr9 35729462 35729464 67.5844 +chr9 35729464 35729465 69.3466 +chr9 35729465 35729466 67.5844 +chr9 35729466 35729468 65.8308 +chr9 35729468 35729469 64.0859 +chr9 35729469 35729472 65.8308 +chr9 35729472 35729473 64.0859 +chr9 35729473 35729474 65.8308 +chr9 35729474 35729476 64.0859 +chr9 35729476 35729481 62.35 +chr9 35729481 35729483 58.9057 +chr9 35729483 35729484 57.1978 +chr9 35729484 35729486 53.8115 +chr9 35729486 35729487 55.4996 +chr9 35729487 35729488 57.1978 +chr9 35729488 35729490 55.4996 +chr9 35729490 35729491 53.8115 +chr9 35729491 35729495 52.1335 +chr9 35729495 35729497 53.8115 +chr9 35729497 35729500 52.1335 +chr9 35729500 35729502 53.8115 +chr9 35729502 35729503 55.4996 +chr9 35729503 35729504 57.1978 +chr9 35729504 35729508 58.9057 +chr9 35729508 35729509 60.6232 +chr9 35729509 35729510 64.0859 +chr9 35729510 35729511 62.35 +chr9 35729511 35729515 64.0859 +chr9 35729515 35729516 62.35 +chr9 35729516 35729517 60.6232 +chr9 35729517 35729519 62.35 +chr9 35729519 35729521 60.6232 +chr9 35729521 35729522 58.9057 +chr9 35729522 35729523 60.6232 +chr9 35729523 35729524 62.35 +chr9 35729524 35729525 64.0859 +chr9 35729525 35729528 65.8308 +chr9 35729528 35729530 64.0859 +chr9 35729530 35729533 66.1659 +chr9 35729533 35729535 64.4141 +chr9 35729535 35729536 66.1659 +chr9 35729536 35729537 64.4141 +chr9 35729537 35729540 62.6712 +chr9 35729540 35729541 60.9374 +chr9 35729541 35729543 59.213 +chr9 35729543 35729544 57.4981 +chr9 35729544 35729546 55.793 +chr9 35729546 35729548 56.0913 +chr9 35729548 35729554 52.697 +chr9 35729554 35729557 54.389 +chr9 35729557 35729558 56.0913 +chr9 35729558 35729559 57.8035 +chr9 35729559 35729561 56.0913 +chr9 35729561 35729562 54.389 +chr9 35729562 35729564 56.0913 +chr9 35729564 35729565 52.697 +chr9 35729565 35729566 54.389 +chr9 35729566 35729571 52.697 +chr9 35729571 35729572 51.0155 +chr9 35729572 35729575 52.697 +chr9 35729575 35729584 50.3001 +chr9 35729584 35729587 51.9324 +chr9 35729587 35729589 53.5749 +chr9 35729589 35729590 55.2273 +chr9 35729590 35729592 56.8895 +chr9 35729592 35729593 58.5613 +chr9 35729593 35729601 60.2424 +chr9 35729601 35729602 58.5613 +chr9 35729602 35729604 60.2424 +chr9 35729604 35729605 58.5613 +chr9 35729605 35729606 56.8895 +chr9 35729606 35729607 58.5613 +chr9 35729607 35729609 60.2424 +chr9 35729609 35729611 58.5613 +chr9 35729611 35729612 60.2424 +chr9 35729612 35729618 61.9326 +chr9 35729618 35729619 63.6317 +chr9 35729619 35729622 61.9326 +chr9 35729622 35729623 60.2424 +chr9 35729623 35729625 61.9326 +chr9 35729625 35729627 60.2424 +chr9 35729627 35729628 58.5613 +chr9 35729628 35729629 56.8895 +chr9 35729629 35729632 58.5613 +chr9 35729632 35729633 56.8895 +chr9 35729633 35729634 58.5613 +chr9 35729634 35729635 60.2424 +chr9 35729635 35729636 58.5613 +chr9 35729636 35729638 60.2424 +chr9 35729638 35729640 63.6317 +chr9 35729640 35729642 61.9326 +chr9 35729642 35729643 57.5759 +chr9 35729643 35729645 55.9528 +chr9 35729645 35729646 59.2082 +chr9 35729646 35729651 57.5759 +chr9 35729651 35729652 59.2082 +chr9 35729652 35729657 57.5759 +chr9 35729657 35729662 59.2082 +chr9 35729662 35729665 57.5759 +chr9 35729665 35729667 59.2082 +chr9 35729667 35729669 60.8494 +chr9 35729669 35729671 48.8843 +chr9 35729671 35729672 47.4948 +chr9 35729672 35729677 48.8843 +chr9 35729677 35729678 50.2826 +chr9 35729678 35729682 48.8843 +chr9 35729682 35729685 50.2826 +chr9 35729685 35729687 51.6894 +chr9 35729687 35729689 53.1047 +chr9 35729689 35729690 54.5283 +chr9 35729690 35729692 53.1047 +chr9 35729692 35729693 51.6894 +chr9 35729693 35729694 54.5283 +chr9 35729694 35729695 53.1047 +chr9 35729695 35729696 54.5283 +chr9 35729696 35729700 53.1047 +chr9 35729700 35729703 54.5283 +chr9 35729703 35729709 55.96 +chr9 35729709 35729710 57.3996 +chr9 35729710 35729712 60.3021 +chr9 35729712 35729713 58.847 +chr9 35729713 35729718 60.3021 +chr9 35729718 35729722 61.7648 +chr9 35729722 35729723 64.7122 +chr9 35729723 35729727 66.1967 +chr9 35729727 35729730 64.7122 +chr9 35729730 35729732 63.2349 +chr9 35729732 35729735 60.3021 +chr9 35729735 35729737 58.847 +chr9 35729737 35729739 60.3021 +chr9 35729739 35729742 61.7648 +chr9 35729742 35729745 60.3021 +chr9 35729745 35729746 61.7648 +chr9 35729746 35729755 60.3021 +chr9 35729755 35729762 61.7648 +chr9 35729762 35729764 63.2349 +chr9 35729764 35729767 64.7122 +chr9 35729767 35729768 66.1967 +chr9 35729768 35729774 67.6883 +chr9 35729774 35729775 66.1967 +chr9 35729775 35729776 67.6883 +chr9 35729776 35729777 66.1967 +chr9 35729777 35729778 67.6883 +chr9 35729778 35729782 64.7122 +chr9 35729782 35729784 66.1967 +chr9 35729784 35729785 64.7122 +chr9 35729785 35729788 63.2349 +chr9 35729788 35729789 64.7122 +chr9 35729789 35729791 61.7648 +chr9 35729791 35729793 60.3021 +chr9 35729793 35729795 63.2349 +chr9 35729795 35729797 64.7122 +chr9 35729797 35729799 63.2349 +chr9 35729799 35729800 61.7648 +chr9 35729800 35729801 60.3021 +chr9 35729801 35729802 61.7648 +chr9 35729802 35729803 80.5702 +chr9 35729803 35729805 78.7992 +chr9 35729805 35729807 77.0356 +chr9 35729807 35729809 72.5739 +chr9 35729809 35729812 70.8747 +chr9 35729812 35729815 69.1834 +chr9 35729815 35729817 67.5001 +chr9 35729817 35729818 65.8249 +chr9 35729818 35729822 67.5001 +chr9 35729822 35729825 65.8249 +chr9 35729825 35729826 64.1579 +chr9 35729826 35729827 62.4993 +chr9 35729827 35729830 60.8494 +chr9 35729830 35729833 62.4993 +chr9 35729833 35729834 60.8494 +chr9 35729834 35729837 64.1579 +chr9 35729837 35729840 62.4993 +chr9 35729840 35729843 60.8494 +chr9 35729843 35729845 57.5759 +chr9 35729845 35729849 55.9528 +chr9 35729849 35729850 54.3391 +chr9 35729850 35729852 52.7348 +chr9 35729852 35729853 54.3391 +chr9 35729853 35729854 51.1403 +chr9 35729854 35729856 49.5558 +chr9 35729856 35729857 47.9815 +chr9 35729857 35729858 49.5558 +chr9 35729858 35729862 47.9815 +chr9 35729862 35729864 44.8645 +chr9 35729864 35729865 43.3223 +chr9 35729865 35729868 44.8645 +chr9 35729868 35729871 46.4176 +chr9 35729871 35729872 44.8645 +chr9 35729872 35729874 46.4176 +chr9 35729874 35729877 47.9815 +chr9 35729877 35729883 46.4176 +chr9 35729883 35729890 47.9815 +chr9 35729890 35729891 49.5558 +chr9 35729891 35729894 47.9815 +chr9 35729894 35729895 46.4176 +chr9 35729895 35729898 44.8645 +chr9 35729898 35729901 43.3223 +chr9 35729901 35729902 44.8645 +chr9 35729902 35729903 43.3223 +chr9 35729903 35729906 41.7914 +chr9 35729906 35729907 40.272 +chr9 35729907 35729909 38.7646 +chr9 35729909 35729912 35.7866 +chr9 35729912 35729914 37.2693 +chr9 35729914 35729915 38.7646 +chr9 35729915 35729922 37.2693 +chr9 35729922 35729927 35.7866 +chr9 35729927 35729928 34.3169 +chr9 35729928 35729931 32.8605 +chr9 35729931 35729933 31.4178 +chr9 35729933 35729938 29.9893 +chr9 35729938 35729939 31.4178 +chr9 35729939 35729940 32.8605 +chr9 35729940 35729941 34.3169 +chr9 35729941 35729942 32.8605 +chr9 35729942 35729944 31.4178 +chr9 35729944 35729946 29.9893 +chr9 35729946 35729948 31.4178 +chr9 35729948 35729949 32.8605 +chr9 35729949 35729955 34.3169 +chr9 35729955 35729958 35.7866 +chr9 35729958 35729959 34.3169 +chr9 35729959 35729961 35.7866 +chr9 35729961 35729963 27.8468 +chr9 35729963 35729968 30.3218 +chr9 35729968 35729970 31.5778 +chr9 35729970 35729972 30.3218 +chr9 35729972 35729973 31.5778 +chr9 35729973 35729974 30.3218 +chr9 35729974 35729982 27.8468 +chr9 35729982 35729985 29.0781 +chr9 35729985 35729986 30.3218 +chr9 35729986 35729992 31.5778 +chr9 35729992 35729993 30.3218 +chr9 35729993 35729994 31.5778 +chr9 35729994 35729997 32.8456 +chr9 35729997 35729998 31.5778 +chr9 35729998 35730005 32.8456 +chr9 35730005 35730007 26.7526 +chr9 35730007 35730008 27.8562 +chr9 35730008 35730012 26.7526 +chr9 35730012 35730016 31.5778 +chr9 35730016 35730018 32.8456 +chr9 35730018 35730019 31.5778 +chr9 35730019 35730023 30.3218 +chr9 35730023 35730025 29.0781 +chr9 35730025 35730026 30.3218 +chr9 35730026 35730029 29.0781 +chr9 35730029 35730030 30.3218 +chr9 35730030 35730031 29.0781 +chr9 35730031 35730032 30.3218 +chr9 35730032 35730034 31.5778 +chr9 35730034 35730039 32.8456 +chr9 35730039 35730040 34.125 +chr9 35730040 35730041 35.4156 +chr9 35730041 35730043 34.125 +chr9 35730043 35730044 35.4156 +chr9 35730044 35730046 36.7172 +chr9 35730046 35730049 38.0294 +chr9 35730049 35730051 39.3521 +chr9 35730051 35730052 40.6851 +chr9 35730052 35730053 39.3521 +chr9 35730053 35730056 40.6851 +chr9 35730056 35730058 42.0279 +chr9 35730058 35730072 43.3806 +chr9 35730072 35730078 35.8811 +chr9 35730078 35730083 34.7044 +chr9 35730083 35730088 35.8811 +chr9 35730088 35730089 34.7044 +chr9 35730089 35730090 33.5373 +chr9 35730090 35730091 34.7044 +chr9 35730091 35730093 35.8811 +chr9 35730093 35730094 38.263 +chr9 35730094 35730095 39.4677 +chr9 35730095 35730096 38.263 +chr9 35730096 35730100 39.4677 +chr9 35730100 35730101 40.6814 +chr9 35730101 35730103 48.8843 +chr9 35730103 35730105 47.4948 +chr9 35730105 35730107 48.8843 +chr9 35730107 35730108 50.2826 +chr9 35730108 35730114 48.8843 +chr9 35730114 35730118 50.2826 +chr9 35730118 35730119 48.8843 +chr9 35730119 35730120 50.2826 +chr9 35730120 35730122 51.6894 +chr9 35730122 35730130 50.2826 +chr9 35730130 35730131 51.6894 +chr9 35730131 35730133 53.1047 +chr9 35730133 35730134 51.6894 +chr9 35730134 35730138 50.2826 +chr9 35730138 35730143 48.8843 +chr9 35730143 35730145 47.4948 +chr9 35730145 35730147 57.5759 +chr9 35730147 35730149 55.9528 +chr9 35730149 35730153 57.5759 +chr9 35730153 35730154 59.2082 +chr9 35730154 35730156 57.5759 +chr9 35730156 35730158 55.9528 +chr9 35730158 35730160 57.5759 +chr9 35730160 35730163 59.2082 +chr9 35730163 35730165 60.8494 +chr9 35730165 35730167 59.2082 +chr9 35730167 35730169 60.8494 +chr9 35730169 35730171 59.2082 +chr9 35730171 35730173 57.5759 +chr9 35730173 35730174 55.9528 +chr9 35730174 35730175 54.3391 +chr9 35730175 35730176 55.9528 +chr9 35730176 35730177 57.5759 +chr9 35730177 35730179 55.9528 +chr9 35730179 35730183 57.5759 +chr9 35730183 35730186 55.9528 +chr9 35730186 35730189 54.3391 +chr9 35730189 35730190 52.0964 +chr9 35730190 35730192 53.6591 +chr9 35730192 35730193 55.231 +chr9 35730193 35730196 53.6591 +chr9 35730196 35730203 52.0964 +chr9 35730203 35730206 53.6591 +chr9 35730206 35730207 55.231 +chr9 35730207 35730209 56.8122 +chr9 35730209 35730211 58.4022 +chr9 35730211 35730212 60.001 +chr9 35730212 35730213 61.6085 +chr9 35730213 35730216 63.2243 +chr9 35730216 35730220 64.8484 +chr9 35730220 35730221 63.2243 +chr9 35730221 35730224 64.8484 +chr9 35730224 35730225 66.4806 +chr9 35730225 35730231 68.1208 +chr9 35730231 35730232 66.4806 +chr9 35730232 35730233 69.1834 +chr9 35730233 35730237 67.5001 +chr9 35730237 35730238 55.96 +chr9 35730238 35730239 57.3996 +chr9 35730239 35730240 55.96 +chr9 35730240 35730241 54.5283 +chr9 35730241 35730242 55.96 +chr9 35730242 35730245 54.5283 +chr9 35730245 35730246 53.1047 +chr9 35730246 35730247 51.6894 +chr9 35730247 35730250 50.2826 +chr9 35730250 35730251 51.6894 +chr9 35730251 35730253 53.1047 +chr9 35730253 35730254 51.6894 +chr9 35730254 35730255 50.2826 +chr9 35730255 35730257 51.6894 +chr9 35730257 35730260 50.2826 +chr9 35730260 35730266 48.8843 +chr9 35730266 35730269 47.4948 +chr9 35730269 35730270 48.8843 +chr9 35730270 35730271 47.4948 +chr9 35730271 35730273 46.1142 +chr9 35730273 35730275 47.4948 +chr9 35730275 35730280 48.8843 +chr9 35730280 35730281 50.2826 +chr9 35730281 35730286 51.6894 +chr9 35730286 35730291 54.5283 +chr9 35730291 35730292 55.96 +chr9 35730292 35730293 57.3996 +chr9 35730293 35730294 55.96 +chr9 35730294 35730300 57.3996 +chr9 35730300 35730303 55.96 +chr9 35730303 35730306 54.5283 +chr9 35730306 35730307 55.96 +chr9 35730307 35730310 54.5283 +chr9 35730310 35730311 55.96 +chr9 35730311 35730312 57.3996 +chr9 35730312 35730313 55.96 +chr9 35730313 35730315 57.3996 +chr9 35730315 35730319 55.96 +chr9 35730319 35730320 54.5283 +chr9 35730320 35730322 53.1047 +chr9 35730322 35730324 54.5283 +chr9 35730324 35730325 53.1047 +chr9 35730325 35730327 54.5283 +chr9 35730327 35730328 53.1047 +chr9 35730328 35730329 51.6894 +chr9 35730329 35730330 50.2826 +chr9 35730330 35730332 48.8843 +chr9 35730332 35730335 47.4948 +chr9 35730335 35730339 48.8843 +chr9 35730339 35730340 47.4948 +chr9 35730340 35730343 48.8843 +chr9 35730343 35730344 47.4948 +chr9 35730344 35730346 48.8843 +chr9 35730346 35730347 47.4948 +chr9 35730347 35730349 48.8843 +chr9 35730349 35730352 47.4948 +chr9 35730352 35730353 46.1142 +chr9 35730353 35730354 44.7427 +chr9 35730354 35730355 47.4948 +chr9 35730355 35730356 46.1142 +chr9 35730356 35730361 43.3806 +chr9 35730361 35730364 42.0279 +chr9 35730364 35730365 40.6851 +chr9 35730365 35730370 39.3521 +chr9 35730370 35730375 38.0294 +chr9 35730375 35730376 36.7172 +chr9 35730376 35730386 44.8645 +chr9 35730386 35730388 46.4176 +chr9 35730388 35730392 47.9815 +chr9 35730392 35730395 46.4176 +chr9 35730395 35730399 44.8645 +chr9 35730399 35730402 43.3223 +chr9 35730402 35730404 44.8645 +chr9 35730404 35730408 46.4176 +chr9 35730408 35730415 47.9815 +chr9 35730415 35730416 46.4176 +chr9 35730416 35730417 44.8645 +chr9 35730417 35730418 46.4176 +chr9 35730418 35730420 47.9815 +chr9 35730420 35730421 46.4176 +chr9 35730421 35730424 44.8645 +chr9 35730424 35730426 46.4176 +chr9 35730426 35730427 43.3223 +chr9 35730427 35730429 44.8645 +chr9 35730429 35730432 43.3223 +chr9 35730432 35730438 41.7914 +chr9 35730438 35730442 40.272 +chr9 35730442 35730446 42.3009 +chr9 35730446 35730448 40.7354 +chr9 35730448 35730450 39.1822 +chr9 35730450 35730452 37.6416 +chr9 35730452 35730453 39.1822 +chr9 35730453 35730458 37.6416 +chr9 35730458 35730466 39.1822 +chr9 35730466 35730467 40.7354 +chr9 35730467 35730468 42.3009 +chr9 35730468 35730475 43.8782 +chr9 35730475 35730478 42.3009 +chr9 35730478 35730480 40.7354 +chr9 35730480 35730481 39.1822 +chr9 35730481 35730482 40.7354 +chr9 35730482 35730484 42.3009 +chr9 35730484 35730487 40.7354 +chr9 35730487 35730490 37.6416 +chr9 35730490 35730491 36.1139 +chr9 35730491 35730492 34.5996 +chr9 35730492 35730493 36.1139 +chr9 35730493 35730494 37.6416 +chr9 35730494 35730495 34.5996 +chr9 35730495 35730498 36.1139 +chr9 35730498 35730501 37.6416 +chr9 35730501 35730502 39.1822 +chr9 35730502 35730511 37.6416 +chr9 35730511 35730512 39.1822 +chr9 35730512 35730513 40.7354 +chr9 35730513 35730517 39.1822 +chr9 35730517 35730519 37.6416 +chr9 35730519 35730521 39.1822 +chr9 35730521 35730525 37.6416 +chr9 35730525 35730526 39.1822 +chr9 35730526 35730530 37.6416 +chr9 35730530 35730531 36.1139 +chr9 35730531 35730539 38.1976 +chr9 35730539 35730542 39.7922 +chr9 35730542 35730544 38.1976 +chr9 35730544 35730549 36.6163 +chr9 35730549 35730551 35.0488 +chr9 35730551 35730558 33.4956 +chr9 35730558 35730560 31.957 +chr9 35730560 35730571 33.4956 +chr9 35730571 35730572 31.957 +chr9 35730572 35730575 33.4956 +chr9 35730575 35730582 33.9098 +chr9 35730582 35730584 35.4777 +chr9 35730584 35730590 33.9098 +chr9 35730590 35730591 35.4777 +chr9 35730591 35730595 33.9098 +chr9 35730595 35730596 35.4777 +chr9 35730596 35730598 36.6163 +chr9 35730598 35730599 35.0488 +chr9 35730599 35730601 36.6163 +chr9 35730601 35730602 38.1976 +chr9 35730602 35730604 36.6163 +chr9 35730604 35730605 38.1976 +chr9 35730605 35730611 36.6163 +chr9 35730611 35730613 38.1976 +chr9 35730613 35730616 39.7922 +chr9 35730616 35730619 38.1976 +chr9 35730619 35730622 35.8418 +chr9 35730622 35730627 34.3362 +chr9 35730627 35730629 35.8418 +chr9 35730629 35730633 37.3607 +chr9 35730633 35730635 35.8418 +chr9 35730635 35730641 37.3607 +chr9 35730641 35730644 35.8418 +chr9 35730644 35730645 34.3362 +chr9 35730645 35730647 35.8418 +chr9 35730647 35730648 37.3607 +chr9 35730648 35730650 35.8418 +chr9 35730650 35730651 37.3607 +chr9 35730651 35730652 35.8418 +#bedGraph section chr9:35730652-35733148 +chr9 35730652 35730655 34.3362 +chr9 35730655 35730658 35.8418 +chr9 35730658 35730659 34.3362 +chr9 35730659 35730660 32.8443 +chr9 35730660 35730663 34.3362 +chr9 35730663 35730665 35.8418 +chr9 35730665 35730666 34.3362 +chr9 35730666 35730671 35.8418 +chr9 35730671 35730672 34.3362 +chr9 35730672 35730673 35.8418 +chr9 35730673 35730679 37.3607 +chr9 35730679 35730680 35.8418 +chr9 35730680 35730685 37.3607 +chr9 35730685 35730687 38.8926 +chr9 35730687 35730693 40.437 +chr9 35730693 35730694 41.9937 +chr9 35730694 35730695 43.5622 +chr9 35730695 35730699 45.1423 +chr9 35730699 35730701 46.7337 +chr9 35730701 35730702 48.336 +chr9 35730702 35730707 46.7337 +chr9 35730707 35730709 45.1423 +chr9 35730709 35730712 46.7337 +chr9 35730712 35730713 45.1423 +chr9 35730713 35730714 43.5622 +chr9 35730714 35730715 45.1423 +chr9 35730715 35730719 46.7337 +chr9 35730719 35730721 48.336 +chr9 35730721 35730722 49.9491 +chr9 35730722 35730724 48.336 +chr9 35730724 35730731 49.9491 +chr9 35730731 35730732 51.5726 +chr9 35730732 35730735 53.2063 +chr9 35730735 35730736 51.5726 +chr9 35730736 35730741 49.9491 +chr9 35730741 35730742 48.336 +chr9 35730742 35730747 49.9491 +chr9 35730747 35730748 48.336 +chr9 35730748 35730751 45.1423 +chr9 35730751 35730759 43.5622 +chr9 35730759 35730768 45.7804 +chr9 35730768 35730769 47.4219 +chr9 35730769 35730771 45.7804 +chr9 35730771 35730772 47.4219 +chr9 35730772 35730774 45.7804 +chr9 35730774 35730775 49.0747 +chr9 35730775 35730780 45.7804 +chr9 35730780 35730785 43.5622 +chr9 35730785 35730790 41.9937 +chr9 35730790 35730792 40.437 +chr9 35730792 35730796 41.9937 +chr9 35730796 35730797 43.5622 +chr9 35730797 35730798 45.1423 +chr9 35730798 35730799 46.7337 +chr9 35730799 35730800 48.336 +chr9 35730800 35730801 46.7337 +chr9 35730801 35730802 48.336 +chr9 35730802 35730805 49.9491 +chr9 35730805 35730810 51.5726 +chr9 35730810 35730812 53.2063 +chr9 35730812 35730813 51.5726 +chr9 35730813 35730815 49.9491 +chr9 35730815 35730819 51.5726 +chr9 35730819 35730821 53.2063 +chr9 35730821 35730822 54.85 +chr9 35730822 35730826 53.2063 +chr9 35730826 35730828 54.85 +chr9 35730828 35730830 53.2063 +chr9 35730830 35730831 54.85 +chr9 35730831 35730835 56.5035 +chr9 35730835 35730838 53.2063 +chr9 35730838 35730840 54.85 +chr9 35730840 35730841 53.2063 +chr9 35730841 35730843 51.5726 +chr9 35730843 35730846 54.85 +chr9 35730846 35730847 56.5035 +chr9 35730847 35730849 58.1665 +chr9 35730849 35730852 56.5035 +chr9 35730852 35730854 58.1665 +chr9 35730854 35730856 56.5035 +chr9 35730856 35730857 58.1665 +chr9 35730857 35730858 59.8388 +chr9 35730858 35730859 61.5202 +chr9 35730859 35730861 59.8388 +chr9 35730861 35730863 58.1665 +chr9 35730863 35730864 59.8388 +chr9 35730864 35730868 56.5035 +chr9 35730868 35730869 58.1665 +chr9 35730869 35730870 59.8388 +chr9 35730870 35730871 58.1665 +chr9 35730871 35730873 56.5035 +chr9 35730873 35730879 58.1665 +chr9 35730879 35730881 59.8388 +chr9 35730881 35730883 61.5202 +chr9 35730883 35730885 59.8388 +chr9 35730885 35730887 61.5202 +chr9 35730887 35730890 63.2106 +chr9 35730890 35730893 64.9098 +chr9 35730893 35730895 66.6175 +chr9 35730895 35730900 64.9098 +chr9 35730900 35730901 66.6175 +chr9 35730901 35730902 68.3337 +chr9 35730902 35730903 70.0582 +chr9 35730903 35730905 68.3337 +chr9 35730905 35730907 70.0582 +chr9 35730907 35730911 71.7907 +chr9 35730911 35730920 70.0582 +chr9 35730920 35730924 73.2592 +chr9 35730924 35730928 75.0532 +chr9 35730928 35730929 76.8551 +chr9 35730929 35730931 78.6649 +chr9 35730931 35730932 80.4824 +chr9 35730932 35730934 78.6649 +chr9 35730934 35730935 80.4824 +chr9 35730935 35730937 78.6649 +chr9 35730937 35730938 76.8551 +chr9 35730938 35730939 75.0532 +chr9 35730939 35730942 73.2592 +chr9 35730942 35730944 69.6957 +chr9 35730944 35730945 71.4733 +chr9 35730945 35730946 73.2592 +chr9 35730946 35730947 71.4733 +chr9 35730947 35730953 73.2592 +chr9 35730953 35730954 75.0532 +chr9 35730954 35730955 76.8551 +chr9 35730955 35730956 75.0532 +chr9 35730956 35730959 78.6649 +chr9 35730959 35730960 76.8551 +chr9 35730960 35730961 75.0532 +chr9 35730961 35730962 73.2592 +chr9 35730962 35730963 75.0532 +chr9 35730963 35730964 76.8551 +chr9 35730964 35730966 78.6649 +chr9 35730966 35730967 76.8551 +chr9 35730967 35730968 75.0532 +chr9 35730968 35730969 78.6649 +chr9 35730969 35730970 80.4824 +chr9 35730970 35730971 78.6649 +chr9 35730971 35730975 80.4824 +chr9 35730975 35730976 82.3074 +chr9 35730976 35730977 84.1399 +chr9 35730977 35730983 85.9796 +chr9 35730983 35730986 84.1399 +chr9 35730986 35730987 82.3074 +chr9 35730987 35730991 80.4824 +chr9 35730991 35730992 84.1399 +chr9 35730992 35730995 82.3074 +chr9 35730995 35730996 84.1399 +chr9 35730996 35730997 82.3074 +chr9 35730997 35731008 80.4824 +chr9 35731008 35731009 78.6649 +chr9 35731009 35731012 76.8551 +chr9 35731012 35731013 75.0532 +chr9 35731013 35731019 73.2592 +chr9 35731019 35731021 71.4733 +chr9 35731021 35731022 69.6957 +chr9 35731022 35731023 67.9265 +chr9 35731023 35731026 67.5844 +chr9 35731026 35731029 63.2106 +chr9 35731029 35731032 61.5202 +chr9 35731032 35731033 63.2106 +chr9 35731033 35731035 61.5202 +chr9 35731035 35731041 63.2106 +chr9 35731041 35731042 61.5202 +chr9 35731042 35731045 59.8388 +chr9 35731045 35731047 56.5035 +chr9 35731047 35731048 54.85 +chr9 35731048 35731049 53.2063 +chr9 35731049 35731054 54.85 +chr9 35731054 35731055 53.2063 +chr9 35731055 35731060 51.5726 +chr9 35731060 35731063 53.2063 +chr9 35731063 35731064 54.85 +chr9 35731064 35731067 53.2063 +chr9 35731067 35731069 51.5726 +chr9 35731069 35731070 49.9491 +chr9 35731070 35731071 51.5726 +chr9 35731071 35731072 49.9491 +chr9 35731072 35731074 51.5726 +chr9 35731074 35731075 49.9491 +chr9 35731075 35731077 51.5726 +chr9 35731077 35731080 49.9491 +chr9 35731080 35731082 51.5726 +chr9 35731082 35731083 53.2063 +chr9 35731083 35731084 51.5726 +chr9 35731084 35731087 49.9491 +chr9 35731087 35731090 46.7337 +chr9 35731090 35731093 45.1423 +chr9 35731093 35731096 43.5622 +chr9 35731096 35731101 41.9937 +chr9 35731101 35731103 43.5622 +chr9 35731103 35731104 41.9937 +chr9 35731104 35731108 40.437 +chr9 35731108 35731112 37.3607 +chr9 35731112 35731114 35.8418 +chr9 35731114 35731115 34.3362 +chr9 35731115 35731116 32.8443 +chr9 35731116 35731118 31.3667 +chr9 35731118 35731121 29.9038 +chr9 35731121 35731131 31.3667 +chr9 35731131 35731135 29.9038 +chr9 35731135 35731136 28.456 +chr9 35731136 35731140 27.0241 +chr9 35731140 35731141 28.456 +chr9 35731141 35731154 31.3667 +chr9 35731154 35731159 32.8443 +chr9 35731159 35731160 34.3362 +chr9 35731160 35731161 35.8418 +chr9 35731161 35731166 37.3607 +chr9 35731166 35731176 38.8892 +chr9 35731176 35731178 37.3227 +chr9 35731178 35731181 38.8892 +chr9 35731181 35731183 40.4687 +chr9 35731183 35731186 42.0607 +chr9 35731186 35731187 43.665 +chr9 35731187 35731192 45.0396 +chr9 35731192 35731198 46.6606 +chr9 35731198 35731199 48.2929 +chr9 35731199 35731200 49.9362 +chr9 35731200 35731202 48.2929 +chr9 35731202 35731203 49.9362 +chr9 35731203 35731208 48.2929 +chr9 35731208 35731209 46.6606 +chr9 35731209 35731210 48.2929 +chr9 35731210 35731212 46.6606 +chr9 35731212 35731214 45.0396 +chr9 35731214 35731216 46.6606 +chr9 35731216 35731218 45.0396 +chr9 35731218 35731222 46.6606 +chr9 35731222 35731229 45.0396 +chr9 35731229 35731230 46.6606 +chr9 35731230 35731232 48.2929 +chr9 35731232 35731236 49.9362 +chr9 35731236 35731239 48.2929 +chr9 35731239 35731244 51.5902 +chr9 35731244 35731248 53.2546 +chr9 35731248 35731249 53.2063 +chr9 35731249 35731250 54.85 +chr9 35731250 35731251 56.5035 +chr9 35731251 35731253 54.85 +chr9 35731253 35731256 53.2063 +chr9 35731256 35731259 54.85 +chr9 35731259 35731267 56.5035 +chr9 35731267 35731269 54.85 +chr9 35731269 35731275 56.5035 +chr9 35731275 35731276 58.1665 +chr9 35731276 35731277 61.5202 +chr9 35731277 35731280 63.2106 +chr9 35731280 35731281 61.5202 +chr9 35731281 35731282 59.8388 +chr9 35731282 35731283 58.1665 +chr9 35731283 35731284 59.8388 +chr9 35731284 35731286 61.5202 +chr9 35731286 35731287 63.2106 +chr9 35731287 35731288 64.9098 +chr9 35731288 35731289 63.2106 +chr9 35731289 35731294 64.9098 +chr9 35731294 35731300 63.2106 +chr9 35731300 35731301 61.5202 +chr9 35731301 35731302 59.8388 +chr9 35731302 35731305 58.1665 +chr9 35731305 35731308 56.5035 +chr9 35731308 35731310 58.1665 +chr9 35731310 35731315 59.8388 +chr9 35731315 35731316 58.1665 +chr9 35731316 35731318 59.8388 +chr9 35731318 35731319 58.1665 +chr9 35731319 35731320 59.8388 +chr9 35731320 35731327 58.1665 +chr9 35731327 35731332 56.5035 +chr9 35731332 35731334 54.85 +chr9 35731334 35731336 56.5035 +chr9 35731336 35731337 58.1665 +chr9 35731337 35731338 59.8388 +chr9 35731338 35731340 58.1665 +chr9 35731340 35731341 61.5202 +chr9 35731341 35731343 59.8388 +chr9 35731343 35731344 61.5202 +chr9 35731344 35731348 63.2106 +chr9 35731348 35731351 64.9098 +chr9 35731351 35731352 66.6175 +chr9 35731352 35731353 68.3337 +chr9 35731353 35731354 70.0582 +chr9 35731354 35731355 68.3337 +chr9 35731355 35731358 66.6175 +chr9 35731358 35731359 64.9098 +chr9 35731359 35731360 68.3337 +chr9 35731360 35731364 66.6175 +chr9 35731364 35731366 68.3337 +chr9 35731366 35731370 70.0582 +chr9 35731370 35731372 68.3337 +chr9 35731372 35731373 66.6175 +chr9 35731373 35731374 68.3337 +chr9 35731374 35731379 70.0582 +chr9 35731379 35731385 66.6175 +chr9 35731385 35731386 64.9098 +chr9 35731386 35731387 66.6175 +chr9 35731387 35731388 68.3337 +chr9 35731388 35731389 68.3352 +chr9 35731389 35731391 64.8597 +chr9 35731391 35731392 66.5931 +chr9 35731392 35731393 70.0857 +chr9 35731393 35731396 71.8444 +chr9 35731396 35731397 70.0857 +chr9 35731397 35731399 71.8444 +chr9 35731399 35731401 68.3352 +chr9 35731401 35731402 66.5931 +chr9 35731402 35731403 68.3352 +chr9 35731403 35731404 70.0857 +chr9 35731404 35731405 71.8444 +chr9 35731405 35731407 73.6113 +chr9 35731407 35731408 75.3861 +chr9 35731408 35731409 77.1688 +chr9 35731409 35731410 75.3861 +chr9 35731410 35731411 77.1688 +chr9 35731411 35731415 75.7455 +chr9 35731415 35731416 73.964 +chr9 35731416 35731420 72.1905 +chr9 35731420 35731423 73.964 +chr9 35731423 35731425 72.1905 +chr9 35731425 35731426 73.964 +chr9 35731426 35731427 72.1905 +chr9 35731427 35731429 70.4251 +chr9 35731429 35731431 68.668 +chr9 35731431 35731432 70.4251 +chr9 35731432 35731435 72.1905 +chr9 35731435 35731437 70.4251 +chr9 35731437 35731440 72.1905 +chr9 35731440 35731442 73.964 +chr9 35731442 35731443 75.7455 +chr9 35731443 35731445 77.5348 +chr9 35731445 35731450 79.3317 +chr9 35731450 35731454 77.5348 +chr9 35731454 35731460 79.3317 +chr9 35731460 35731461 81.1363 +chr9 35731461 35731462 82.9482 +chr9 35731462 35731463 84.7675 +chr9 35731463 35731464 82.9482 +chr9 35731464 35731465 84.7675 +chr9 35731465 35731466 86.5939 +chr9 35731466 35731467 84.6603 +chr9 35731467 35731470 86.4616 +chr9 35731470 35731472 88.2698 +chr9 35731472 35731474 90.0849 +chr9 35731474 35731475 88.2698 +chr9 35731475 35731476 90.0849 +chr9 35731476 35731477 88.2698 +chr9 35731477 35731478 84.6757 +chr9 35731478 35731480 86.4328 +chr9 35731480 35731481 82.9255 +chr9 35731481 35731486 86.4328 +chr9 35731486 35731490 89.9671 +chr9 35731490 35731492 91.7441 +chr9 35731492 35731493 89.9671 +chr9 35731493 35731494 91.7441 +chr9 35731494 35731495 93.5275 +chr9 35731495 35731496 95.3172 +chr9 35731496 35731499 97.1132 +chr9 35731499 35731500 95.3172 +chr9 35731500 35731505 97.1132 +chr9 35731505 35731507 98.9153 +chr9 35731507 35731508 100.724 +chr9 35731508 35731510 97.1132 +chr9 35731510 35731511 98.9153 +chr9 35731511 35731512 102.538 +chr9 35731512 35731513 104.358 +chr9 35731513 35731514 102.538 +chr9 35731514 35731519 100.724 +chr9 35731519 35731520 102.538 +chr9 35731520 35731521 104.358 +chr9 35731521 35731522 102.538 +chr9 35731522 35731524 100.724 +chr9 35731524 35731525 98.9153 +chr9 35731525 35731529 100.724 +chr9 35731529 35731531 102.538 +chr9 35731531 35731532 100.724 +chr9 35731532 35731544 97.1132 +chr9 35731544 35731545 93.5275 +chr9 35731545 35731546 91.7441 +chr9 35731546 35731548 89.9671 +chr9 35731548 35731549 88.1966 +chr9 35731549 35731552 73.723 +chr9 35731552 35731554 75.2483 +chr9 35731554 35731559 73.723 +chr9 35731559 35731560 75.2483 +chr9 35731560 35731569 73.723 +chr9 35731569 35731571 75.2483 +chr9 35731571 35731572 73.723 +chr9 35731572 35731575 75.2483 +chr9 35731575 35731577 76.7799 +chr9 35731577 35731580 75.2483 +chr9 35731580 35731581 73.723 +chr9 35731581 35731583 76.7799 +chr9 35731583 35731586 75.2483 +chr9 35731586 35731589 76.7799 +chr9 35731589 35731590 78.3179 +chr9 35731590 35731591 79.8622 +chr9 35731591 35731595 78.3179 +chr9 35731595 35731596 76.7799 +chr9 35731596 35731598 78.3179 +chr9 35731598 35731600 76.7799 +chr9 35731600 35731601 73.723 +chr9 35731601 35731603 72.2043 +chr9 35731603 35731605 73.723 +chr9 35731605 35731606 72.2043 +chr9 35731606 35731612 70.6922 +chr9 35731612 35731613 69.1869 +chr9 35731613 35731614 70.6922 +chr9 35731614 35731620 69.1869 +chr9 35731620 35731621 70.6922 +chr9 35731621 35731622 69.1869 +chr9 35731622 35731626 67.6883 +chr9 35731626 35731627 66.1967 +chr9 35731627 35731628 64.7122 +chr9 35731628 35731629 63.2349 +chr9 35731629 35731630 78.7992 +chr9 35731630 35731631 80.5702 +chr9 35731631 35731633 82.3485 +chr9 35731633 35731635 78.7992 +chr9 35731635 35731636 80.5702 +chr9 35731636 35731639 78.7992 +chr9 35731639 35731640 80.5702 +chr9 35731640 35731643 78.7992 +chr9 35731643 35731644 82.3485 +chr9 35731644 35731645 80.5702 +chr9 35731645 35731649 77.0356 +chr9 35731649 35731650 78.7992 +chr9 35731650 35731659 77.0356 +chr9 35731659 35731661 78.7992 +chr9 35731661 35731662 80.5702 +chr9 35731662 35731665 82.3485 +chr9 35731665 35731666 64.7122 +chr9 35731666 35731667 66.1967 +chr9 35731667 35731668 64.7122 +chr9 35731668 35731669 66.1967 +chr9 35731669 35731672 64.7122 +chr9 35731672 35731678 67.6883 +chr9 35731678 35731681 69.1869 +chr9 35731681 35731682 70.6922 +chr9 35731682 35731684 72.2043 +chr9 35731684 35731685 73.723 +chr9 35731685 35731686 62.5291 +chr9 35731686 35731687 63.8784 +chr9 35731687 35731689 65.234 +chr9 35731689 35731690 73.723 +chr9 35731690 35731693 76.7799 +chr9 35731693 35731697 78.3179 +chr9 35731697 35731698 79.8622 +chr9 35731698 35731700 76.7799 +chr9 35731700 35731703 78.3179 +chr9 35731703 35731704 79.8622 +chr9 35731704 35731705 82.969 +chr9 35731705 35731706 81.4126 +chr9 35731706 35731708 84.5315 +chr9 35731708 35731717 86.0998 +chr9 35731717 35731718 87.674 +chr9 35731718 35731719 89.254 +chr9 35731719 35731720 87.674 +chr9 35731720 35731721 89.254 +chr9 35731721 35731724 87.674 +chr9 35731724 35731725 89.254 +chr9 35731725 35731726 87.674 +chr9 35731726 35731729 86.0998 +chr9 35731729 35731730 87.674 +chr9 35731730 35731731 86.0998 +chr9 35731731 35731733 89.254 +chr9 35731733 35731736 90.8396 +chr9 35731736 35731737 89.254 +chr9 35731737 35731738 90.8396 +chr9 35731738 35731741 92.4308 +chr9 35731741 35731744 94.0275 +chr9 35731744 35731745 95.6297 +chr9 35731745 35731746 97.2373 +chr9 35731746 35731749 98.8502 +chr9 35731749 35731752 97.2373 +chr9 35731752 35731753 98.8502 +chr9 35731753 35731756 97.2373 +chr9 35731756 35731759 98.8502 +chr9 35731759 35731761 100.468 +chr9 35731761 35731762 98.8502 +chr9 35731762 35731763 100.468 +chr9 35731763 35731765 102.092 +chr9 35731765 35731766 103.72 +chr9 35731766 35731768 105.354 +chr9 35731768 35731770 108.636 +chr9 35731770 35731771 105.354 +chr9 35731771 35731772 103.72 +chr9 35731772 35731776 105.354 +chr9 35731776 35731779 106.992 +chr9 35731779 35731780 105.354 +chr9 35731780 35731781 108.636 +chr9 35731781 35731782 110.284 +chr9 35731782 35731785 111.938 +chr9 35731785 35731788 113.596 +chr9 35731788 35731789 115.259 +chr9 35731789 35731794 113.596 +chr9 35731794 35731795 111.938 +chr9 35731795 35731796 113.596 +chr9 35731796 35731797 115.259 +chr9 35731797 35731798 116.926 +chr9 35731798 35731799 118.598 +chr9 35731799 35731800 115.259 +chr9 35731800 35731802 113.596 +chr9 35731802 35731804 115.259 +chr9 35731804 35731805 118.598 +chr9 35731805 35731809 146.468 +chr9 35731809 35731811 150.428 +chr9 35731811 35731812 152.415 +chr9 35731812 35731814 150.428 +chr9 35731814 35731816 152.415 +chr9 35731816 35731818 154.406 +chr9 35731818 35731819 152.415 +chr9 35731819 35731824 154.406 +chr9 35731824 35731825 156.402 +chr9 35731825 35731826 159.766 +chr9 35731826 35731828 157.736 +chr9 35731828 35731829 161.153 +chr9 35731829 35731830 163.185 +chr9 35731830 35731834 161.153 +chr9 35731834 35731835 165.221 +chr9 35731835 35731836 167.262 +chr9 35731836 35731837 171.356 +chr9 35731837 35731839 169.307 +chr9 35731839 35731840 167.262 +chr9 35731840 35731843 165.221 +chr9 35731843 35731844 163.185 +chr9 35731844 35731846 159.125 +chr9 35731846 35731847 157.101 +chr9 35731847 35731849 159.125 +chr9 35731849 35731851 161.153 +chr9 35731851 35731854 165.221 +chr9 35731854 35731855 167.262 +chr9 35731855 35731856 169.307 +chr9 35731856 35731858 173.409 +chr9 35731858 35731859 171.356 +chr9 35731859 35731860 173.409 +chr9 35731860 35731863 171.356 +chr9 35731863 35731865 173.409 +chr9 35731865 35731867 175.466 +chr9 35731867 35731869 177.527 +chr9 35731869 35731870 175.466 +chr9 35731870 35731871 177.527 +chr9 35731871 35731872 175.466 +chr9 35731872 35731874 179.593 +chr9 35731874 35731881 181.662 +chr9 35731881 35731884 179.593 +chr9 35731884 35731885 177.527 +chr9 35731885 35731886 175.466 +chr9 35731886 35731891 173.409 +chr9 35731891 35731892 175.466 +chr9 35731892 35731893 173.409 +chr9 35731893 35731894 175.466 +chr9 35731894 35731895 177.527 +chr9 35731895 35731896 175.466 +chr9 35731896 35731900 170.492 +chr9 35731900 35731901 168.466 +chr9 35731901 35731905 170.492 +chr9 35731905 35731906 168.466 +chr9 35731906 35731907 166.445 +chr9 35731907 35731909 133.849 +chr9 35731909 35731910 135.565 +chr9 35731910 35731912 137.286 +chr9 35731912 35731913 135.565 +chr9 35731913 35731914 137.286 +chr9 35731914 35731919 133.849 +chr9 35731919 35731920 135.565 +chr9 35731920 35731922 132.137 +chr9 35731922 35731923 130.43 +chr9 35731923 35731924 132.137 +chr9 35731924 35731925 130.43 +chr9 35731925 35731926 128.726 +chr9 35731926 35731927 127.027 +chr9 35731927 35731933 125.333 +chr9 35731933 35731934 127.027 +chr9 35731934 35731936 128.726 +chr9 35731936 35731938 130.43 +chr9 35731938 35731939 128.726 +chr9 35731939 35731940 130.43 +chr9 35731940 35731942 132.137 +chr9 35731942 35731943 130.43 +chr9 35731943 35731944 128.726 +chr9 35731944 35731946 125.333 +chr9 35731946 35731949 123.642 +chr9 35731949 35731951 121.957 +chr9 35731951 35731952 120.275 +chr9 35731952 35731954 118.598 +chr9 35731954 35731956 116.926 +chr9 35731956 35731959 115.259 +chr9 35731959 35731960 113.596 +chr9 35731960 35731961 111.938 +chr9 35731961 35731963 110.284 +chr9 35731963 35731964 106.992 +chr9 35731964 35731965 105.354 +chr9 35731965 35731967 103.72 +chr9 35731967 35731968 102.092 +chr9 35731968 35731970 98.8502 +chr9 35731970 35731971 97.2373 +chr9 35731971 35731972 95.6297 +chr9 35731972 35731973 94.0275 +chr9 35731973 35731974 92.4308 +chr9 35731974 35731975 90.8396 +chr9 35731975 35731976 87.674 +chr9 35731976 35731981 86.0998 +chr9 35731981 35731985 84.5315 +chr9 35731985 35731986 86.0998 +chr9 35731986 35731987 84.5315 +chr9 35731987 35731988 81.4126 +chr9 35731988 35731989 79.8622 +chr9 35731989 35731990 78.3179 +chr9 35731990 35731991 76.7799 +chr9 35731991 35731993 73.723 +chr9 35731993 35731994 72.2043 +chr9 35731994 35731995 69.1869 +chr9 35731995 35731996 67.6883 +chr9 35731996 35731997 66.1967 +chr9 35731997 35732001 63.2349 +chr9 35732001 35732002 61.7648 +chr9 35732002 35732003 60.3021 +chr9 35732003 35732004 58.847 +chr9 35732004 35732005 57.3996 +chr9 35732005 35732006 55.96 +chr9 35732006 35732007 57.3996 +chr9 35732007 35732008 55.96 +chr9 35732008 35732010 54.5283 +chr9 35732010 35732011 53.1047 +chr9 35732011 35732012 51.6894 +chr9 35732012 35732014 48.8843 +chr9 35732014 35732016 46.1142 +chr9 35732016 35732018 44.7427 +chr9 35732018 35732022 43.3806 +chr9 35732022 35732023 42.0279 +chr9 35732023 35732024 40.6851 +chr9 35732024 35732025 39.3521 +chr9 35732025 35732026 40.6851 +chr9 35732026 35732029 39.3521 +chr9 35732029 35732034 38.0294 +chr9 35732034 35732036 36.7172 +chr9 35732036 35732037 48.336 +chr9 35732037 35732038 46.7337 +chr9 35732038 35732039 45.1423 +chr9 35732039 35732042 43.5622 +chr9 35732042 35732043 41.9937 +chr9 35732043 35732045 40.437 +chr9 35732045 35732046 38.8926 +chr9 35732046 35732047 37.3607 +chr9 35732047 35732048 37.6416 +chr9 35732048 35732049 36.1139 +chr9 35732049 35732050 34.5996 +chr9 35732050 35732053 33.099 +chr9 35732053 35732055 31.6126 +chr9 35732055 35732056 30.1409 +chr9 35732056 35732058 28.6844 +chr9 35732058 35732059 27.2437 +chr9 35732059 35732063 25.9699 +chr9 35732063 35732069 23.1603 +chr9 35732069 35732071 21.7827 +chr9 35732071 35732073 20.4244 +chr9 35732073 35732074 19.0862 +chr9 35732074 35732075 17.7691 +chr9 35732075 35732076 16.4741 +chr9 35732076 35732077 15.2025 +chr9 35732077 35732079 13.9556 +chr9 35732079 35732080 12.7348 +chr9 35732080 35732087 10.3785 +chr9 35732087 35732088 9.24709 +chr9 35732088 35732089 8.15 +chr9 35732089 35732090 7.09016 +chr9 35732090 35732093 6.07102 +chr9 35732093 35732095 8.15 +chr9 35732095 35732097 7.09016 +chr9 35732097 35732108 6.07102 +chr9 35732108 35732119 7.09016 +chr9 35732119 35732142 9.24709 +chr9 35732142 35732146 10.3785 +chr9 35732146 35732149 9.24709 +chr9 35732149 35732153 9.17755 +chr9 35732153 35732164 10.3028 +chr9 35732164 35732165 11.4598 +chr9 35732165 35732172 10.3028 +chr9 35732172 35732178 9.17755 +chr9 35732178 35732181 8.08668 +chr9 35732181 35732210 7.03305 +chr9 35732210 35732225 8.08668 +chr9 35732225 35732233 6.05104 +chr9 35732233 35732235 5.14595 +chr9 35732235 35732255 5.55229 +chr9 35732255 35732259 6.02011 +chr9 35732259 35732265 4.13368 +chr9 35732265 35732269 3.27149 +chr9 35732269 35732279 2.97456 +chr9 35732279 35732293 2.23271 +chr9 35732293 35732298 1.56475 +chr9 35732298 35732304 0.98447 +chr9 35732304 35732316 0.51106 +chr9 35732316 35732325 0.44498 +chr9 35732325 35732346 0.87362 +chr9 35732346 35732350 1.40663 +chr9 35732350 35732373 0.87362 +chr9 35732373 35732401 0.44498 +chr9 35732401 35732404 0.87362 +chr9 35732404 35732424 1.40663 +chr9 35732424 35732441 2.02601 +chr9 35732441 35732465 2.71852 +chr9 35732465 35732466 2.02601 +chr9 35732466 35732474 2.23271 +chr9 35732474 35732477 2.97456 +chr9 35732477 35732479 3.22618 +chr9 35732479 35732483 4.07979 +chr9 35732483 35732486 4.98946 +chr9 35732486 35732487 4.07979 +chr9 35732487 35732496 4.98946 +chr9 35732496 35732531 5.94894 +chr9 35732531 35732536 6.02011 +chr9 35732536 35732539 8.08668 +chr9 35732539 35732540 9.17755 +chr9 35732540 35732553 10.3028 +chr9 35732553 35732554 11.4598 +chr9 35732554 35732555 12.5232 +chr9 35732555 35732557 13.729 +chr9 35732557 35732561 14.9609 +chr9 35732561 35732564 16.2176 +chr9 35732564 35732569 14.9609 +chr9 35732569 35732570 16.2176 +chr9 35732570 35732575 17.4975 +chr9 35732575 35732577 20.1229 +chr9 35732577 35732578 21.4662 +chr9 35732578 35732579 20.4329 +chr9 35732579 35732580 16.3196 +chr9 35732580 35732581 17.4004 +chr9 35732581 35732588 18.4987 +chr9 35732588 35732590 19.614 +chr9 35732590 35732593 20.7455 +chr9 35732593 35732595 23.0552 +chr9 35732595 35732596 25.4236 +chr9 35732596 35732599 27.8468 +chr9 35732599 35732600 29.0781 +chr9 35732600 35732602 30.3218 +chr9 35732602 35732606 31.5778 +chr9 35732606 35732608 32.8456 +chr9 35732608 35732609 34.125 +chr9 35732609 35732610 35.4156 +chr9 35732610 35732612 38.0294 +chr9 35732612 35732613 40.6851 +chr9 35732613 35732619 42.0279 +chr9 35732619 35732620 40.6851 +chr9 35732620 35732621 42.0279 +chr9 35732621 35732625 43.3806 +chr9 35732625 35732628 44.7427 +chr9 35732628 35732629 47.4948 +chr9 35732629 35732631 48.8843 +chr9 35732631 35732632 50.2826 +chr9 35732632 35732633 51.6894 +chr9 35732633 35732636 53.1047 +chr9 35732636 35732637 51.6894 +chr9 35732637 35732638 53.1047 +chr9 35732638 35732639 54.5283 +chr9 35732639 35732640 57.3996 +chr9 35732640 35732641 58.847 +chr9 35732641 35732644 60.3021 +chr9 35732644 35732646 61.7648 +chr9 35732646 35732647 63.2349 +chr9 35732647 35732648 64.7122 +chr9 35732648 35732652 67.6883 +chr9 35732652 35732654 69.1869 +chr9 35732654 35732655 70.6922 +chr9 35732655 35732656 53.4922 +chr9 35732656 35732659 54.7101 +chr9 35732659 35732661 55.9345 +chr9 35732661 35732662 58.4025 +chr9 35732662 35732664 59.6459 +chr9 35732664 35732665 62.1511 +chr9 35732665 35732667 63.4127 +chr9 35732667 35732668 64.6802 +chr9 35732668 35732669 65.9535 +chr9 35732669 35732670 67.2326 +chr9 35732670 35732671 68.5173 +chr9 35732671 35732676 69.8076 +chr9 35732676 35732677 67.2326 +chr9 35732677 35732678 68.5173 +chr9 35732678 35732679 69.8076 +chr9 35732679 35732680 68.5173 +chr9 35732680 35732682 67.2326 +chr9 35732682 35732683 68.5173 +chr9 35732683 35732684 67.2326 +chr9 35732684 35732685 68.5173 +chr9 35732685 35732690 69.8076 +chr9 35732690 35732692 71.1034 +chr9 35732692 35732694 73.7114 +chr9 35732694 35732697 83.4034 +chr9 35732697 35732699 81.9718 +chr9 35732699 35732701 72.4048 +chr9 35732701 35732702 71.1034 +chr9 35732702 35732705 73.7114 +chr9 35732705 35732706 75.0235 +chr9 35732706 35732707 76.3408 +chr9 35732707 35732710 77.6632 +chr9 35732710 35732711 76.3408 +chr9 35732711 35732712 77.6632 +chr9 35732712 35732713 78.9908 +chr9 35732713 35732715 77.6632 +chr9 35732715 35732719 75.0235 +chr9 35732719 35732721 84.8403 +chr9 35732721 35732723 81.9718 +chr9 35732723 35732731 84.8403 +chr9 35732731 35732732 86.2824 +chr9 35732732 35732733 87.7298 +chr9 35732733 35732736 86.2824 +chr9 35732736 35732738 84.8403 +chr9 35732738 35732740 87.7298 +chr9 35732740 35732741 89.1823 +chr9 35732741 35732743 90.6398 +chr9 35732743 35732745 92.1024 +chr9 35732745 35732746 93.5699 +chr9 35732746 35732747 81.6612 +chr9 35732747 35732750 83.0038 +chr9 35732750 35732751 81.6612 +chr9 35732751 35732755 83.0038 +chr9 35732755 35732756 84.3514 +chr9 35732756 35732759 85.7038 +chr9 35732759 35732761 87.061 +chr9 35732761 35732765 88.4229 +chr9 35732765 35732767 87.061 +chr9 35732767 35732768 88.4229 +chr9 35732768 35732769 87.061 +chr9 35732769 35732771 88.4229 +chr9 35732771 35732778 89.7895 +chr9 35732778 35732779 87.061 +chr9 35732779 35732783 85.7038 +chr9 35732783 35732784 87.061 +chr9 35732784 35732789 85.7038 +chr9 35732789 35732792 87.061 +chr9 35732792 35732793 85.7038 +chr9 35732793 35732795 88.4229 +chr9 35732795 35732796 115.259 +chr9 35732796 35732797 113.596 +chr9 35732797 35732800 115.259 +chr9 35732800 35732801 116.926 +chr9 35732801 35732802 113.596 +chr9 35732802 35732806 111.938 +chr9 35732806 35732807 113.596 +chr9 35732807 35732810 111.938 +chr9 35732810 35732811 110.284 +chr9 35732811 35732812 111.938 +chr9 35732812 35732815 113.596 +chr9 35732815 35732817 116.926 +chr9 35732817 35732819 118.598 +chr9 35732819 35732820 120.275 +chr9 35732820 35732821 121.957 +chr9 35732821 35732822 123.642 +chr9 35732822 35732823 121.957 +chr9 35732823 35732824 123.642 +chr9 35732824 35732826 121.957 +chr9 35732826 35732827 120.275 +chr9 35732827 35732829 121.957 +chr9 35732829 35732831 123.642 +chr9 35732831 35732832 125.333 +chr9 35732832 35732833 121.957 +chr9 35732833 35732835 120.275 +chr9 35732835 35732839 121.957 +chr9 35732839 35732840 132.656 +chr9 35732840 35732843 134.455 +chr9 35732843 35732848 136.259 +chr9 35732848 35732851 138.067 +chr9 35732851 35732854 136.259 +chr9 35732854 35732855 138.067 +chr9 35732855 35732858 141.696 +chr9 35732858 35732860 143.518 +chr9 35732860 35732861 145.343 +chr9 35732861 35732862 149.006 +chr9 35732862 35732864 150.844 +chr9 35732864 35732865 152.686 +chr9 35732865 35732866 154.532 +chr9 35732866 35732867 152.686 +chr9 35732867 35732868 156.382 +chr9 35732868 35732869 154.532 +chr9 35732869 35732870 156.382 +chr9 35732870 35732872 158.236 +chr9 35732872 35732873 156.382 +chr9 35732873 35732874 154.532 +chr9 35732874 35732875 152.686 +chr9 35732875 35732878 150.844 +chr9 35732878 35732879 149.006 +chr9 35732879 35732880 147.173 +chr9 35732880 35732882 145.343 +chr9 35732882 35732890 143.518 +chr9 35732890 35732891 141.696 +chr9 35732891 35732892 139.88 +chr9 35732892 35732894 136.259 +chr9 35732894 35732895 134.455 +chr9 35732895 35732896 132.656 +chr9 35732896 35732897 130.861 +chr9 35732897 35732899 132.656 +chr9 35732899 35732900 134.455 +chr9 35732900 35732901 132.656 +chr9 35732901 35732902 130.861 +chr9 35732902 35732905 132.656 +chr9 35732905 35732906 134.455 +chr9 35732906 35732907 136.259 +chr9 35732907 35732908 134.455 +chr9 35732908 35732909 132.656 +chr9 35732909 35732910 130.861 +chr9 35732910 35732912 129.071 +chr9 35732912 35732914 127.285 +chr9 35732914 35732916 129.071 +chr9 35732916 35732918 132.656 +chr9 35732918 35732919 134.455 +chr9 35732919 35732920 136.259 +chr9 35732920 35732921 134.455 +chr9 35732921 35732922 132.656 +chr9 35732922 35732923 136.259 +chr9 35732923 35732925 134.455 +chr9 35732925 35732926 136.259 +chr9 35732926 35732929 134.455 +chr9 35732929 35732931 130.861 +chr9 35732931 35732932 129.071 +chr9 35732932 35732933 130.861 +chr9 35732933 35732935 129.071 +chr9 35732935 35732936 127.285 +chr9 35732936 35732937 129.071 +chr9 35732937 35732940 127.285 +chr9 35732940 35732944 125.504 +chr9 35732944 35732945 123.728 +chr9 35732945 35732948 121.956 +chr9 35732948 35732949 120.189 +chr9 35732949 35732951 118.427 +chr9 35732951 35732953 114.918 +chr9 35732953 35732954 118.427 +chr9 35732954 35732955 121.956 +chr9 35732955 35732956 118.427 +chr9 35732956 35732957 120.189 +chr9 35732957 35732958 116.67 +chr9 35732958 35732961 114.918 +chr9 35732961 35732963 114.846 +chr9 35732963 35732964 113.068 +chr9 35732964 35732965 114.846 +chr9 35732965 35732967 116.63 +chr9 35732967 35732969 114.846 +chr9 35732969 35732970 113.068 +chr9 35732970 35732974 111.295 +chr9 35732974 35732975 113.068 +chr9 35732975 35732976 111.295 +chr9 35732976 35732977 113.068 +chr9 35732977 35732979 116.63 +chr9 35732979 35732980 118.418 +chr9 35732980 35732982 116.63 +chr9 35732982 35732984 113.068 +chr9 35732984 35732988 111.295 +chr9 35732988 35732989 109.527 +chr9 35732989 35732990 107.765 +chr9 35732990 35732991 109.527 +chr9 35732991 35732995 111.295 +chr9 35732995 35732997 107.765 +chr9 35732997 35732998 106.008 +chr9 35732998 35733001 104.256 +chr9 35733001 35733002 100.77 +chr9 35733002 35733003 99.0349 +chr9 35733003 35733004 97.3058 +chr9 35733004 35733005 95.5826 +chr9 35733005 35733006 93.8653 +chr9 35733006 35733007 95.5826 +chr9 35733007 35733009 93.8653 +chr9 35733009 35733011 92.154 +chr9 35733011 35733014 90.4487 +chr9 35733014 35733016 92.154 +chr9 35733016 35733030 90.4487 +chr9 35733030 35733031 92.154 +chr9 35733031 35733033 90.4487 +chr9 35733033 35733035 92.154 +chr9 35733035 35733036 95.5826 +chr9 35733036 35733037 93.8653 +chr9 35733037 35733039 92.154 +chr9 35733039 35733044 90.4487 +chr9 35733044 35733045 92.154 +chr9 35733045 35733048 90.4487 +chr9 35733048 35733050 92.154 +chr9 35733050 35733052 93.8653 +chr9 35733052 35733056 95.5826 +chr9 35733056 35733057 92.154 +chr9 35733057 35733062 90.4487 +chr9 35733062 35733063 87.0568 +chr9 35733063 35733064 88.7496 +chr9 35733064 35733065 90.4487 +chr9 35733065 35733066 88.7496 +chr9 35733066 35733068 90.4487 +chr9 35733068 35733070 88.7496 +chr9 35733070 35733076 90.4487 +chr9 35733076 35733078 88.7496 +chr9 35733078 35733079 87.0568 +chr9 35733079 35733082 85.3703 +chr9 35733082 35733083 87.0568 +chr9 35733083 35733084 85.3703 +chr9 35733084 35733087 83.6902 +chr9 35733087 35733088 85.3703 +chr9 35733088 35733092 87.0568 +chr9 35733092 35733093 83.6902 +chr9 35733093 35733094 82.0166 +chr9 35733094 35733096 78.6895 +chr9 35733096 35733097 77.0361 +chr9 35733097 35733099 78.6895 +chr9 35733099 35733105 77.0361 +chr9 35733105 35733107 73.7504 +chr9 35733107 35733108 75.3897 +chr9 35733108 35733113 67.6883 +chr9 35733113 35733114 66.1967 +chr9 35733114 35733116 63.2349 +chr9 35733116 35733117 61.7648 +chr9 35733117 35733118 60.3021 +chr9 35733118 35733119 58.847 +chr9 35733119 35733120 57.3996 +chr9 35733120 35733121 58.847 +chr9 35733121 35733125 60.3021 +chr9 35733125 35733126 58.847 +chr9 35733126 35733127 57.3996 +chr9 35733127 35733128 58.847 +chr9 35733128 35733130 57.3996 +chr9 35733130 35733133 55.96 +chr9 35733133 35733137 54.5283 +chr9 35733137 35733138 55.96 +chr9 35733138 35733139 57.3996 +chr9 35733139 35733140 55.96 +chr9 35733140 35733142 54.5283 +chr9 35733142 35733145 55.96 +chr9 35733145 35733147 46.8775 +chr9 35733147 35733148 45.6218 +#bedGraph section chr9:35733148-35747728 +chr9 35733148 35733150 55.96 +chr9 35733150 35733155 54.5283 +chr9 35733155 35733156 55.96 +chr9 35733156 35733158 54.5283 +chr9 35733158 35733159 55.96 +chr9 35733159 35733166 54.5283 +chr9 35733166 35733167 53.1047 +chr9 35733167 35733168 51.6894 +chr9 35733168 35733170 50.2826 +chr9 35733170 35733171 51.6894 +chr9 35733171 35733172 53.1047 +chr9 35733172 35733175 54.5283 +chr9 35733175 35733179 51.6894 +chr9 35733179 35733181 53.1047 +chr9 35733181 35733182 51.6894 +chr9 35733182 35733183 50.2826 +chr9 35733183 35733188 48.8843 +chr9 35733188 35733189 47.4948 +chr9 35733189 35733190 46.1142 +chr9 35733190 35733191 44.7427 +chr9 35733191 35733194 43.3806 +chr9 35733194 35733195 42.0279 +chr9 35733195 35733196 40.6851 +chr9 35733196 35733200 42.0279 +chr9 35733200 35733202 40.6851 +chr9 35733202 35733203 42.0279 +chr9 35733203 35733204 40.6851 +chr9 35733204 35733205 39.3521 +chr9 35733205 35733212 38.0294 +chr9 35733212 35733213 36.7172 +chr9 35733213 35733216 35.4156 +chr9 35733216 35733219 36.7172 +chr9 35733219 35733225 38.0294 +chr9 35733225 35733227 39.3521 +chr9 35733227 35733237 38.0294 +chr9 35733237 35733238 36.7172 +chr9 35733238 35733245 38.0294 +chr9 35733245 35733247 39.3521 +chr9 35733247 35733248 38.0294 +chr9 35733248 35733251 47.9815 +chr9 35733251 35733254 49.5558 +chr9 35733254 35733258 51.1403 +chr9 35733258 35733261 40.6851 +chr9 35733261 35733262 38.0294 +chr9 35733262 35733268 40.6851 +chr9 35733268 35733269 42.0279 +chr9 35733269 35733271 43.3806 +chr9 35733271 35733273 42.0279 +chr9 35733273 35733276 43.3806 +chr9 35733276 35733277 44.7427 +chr9 35733277 35733278 43.3806 +chr9 35733278 35733279 42.0279 +chr9 35733279 35733281 40.6851 +chr9 35733281 35733282 42.0279 +chr9 35733282 35733283 40.6851 +chr9 35733283 35733285 39.3521 +chr9 35733285 35733295 49.5694 +chr9 35733295 35733298 47.9658 +chr9 35733298 35733300 46.373 +chr9 35733300 35733303 44.7911 +chr9 35733303 35733304 43.2204 +chr9 35733304 35733305 44.7911 +chr9 35733305 35733307 43.2204 +chr9 35733307 35733310 44.7911 +chr9 35733310 35733311 43.2204 +chr9 35733311 35733312 44.7911 +chr9 35733312 35733324 43.2204 +chr9 35733324 35733325 41.6614 +chr9 35733325 35733326 40.1142 +chr9 35733326 35733330 38.5792 +chr9 35733330 35733334 40.1142 +chr9 35733334 35733337 41.6614 +chr9 35733337 35733342 43.2204 +chr9 35733342 35733344 41.6614 +chr9 35733344 35733346 43.2204 +chr9 35733346 35733348 41.6614 +chr9 35733348 35733350 43.2204 +chr9 35733350 35733352 41.6614 +chr9 35733352 35733354 43.2204 +chr9 35733354 35733355 44.7911 +chr9 35733355 35733356 47.9658 +chr9 35733356 35733359 46.373 +chr9 35733359 35733360 44.7911 +chr9 35733360 35733362 46.373 +chr9 35733362 35733364 44.7911 +chr9 35733364 35733366 43.2204 +chr9 35733366 35733368 41.6614 +chr9 35733368 35733385 43.2204 +chr9 35733385 35733387 41.6614 +chr9 35733387 35733389 43.2204 +chr9 35733389 35733390 41.6614 +chr9 35733390 35733391 40.1142 +chr9 35733391 35733392 38.5792 +chr9 35733392 35733394 38.7774 +chr9 35733394 35733400 37.249 +chr9 35733400 35733402 35.7335 +chr9 35733402 35733406 32.7431 +chr9 35733406 35733407 34.2314 +chr9 35733407 35733408 32.7431 +chr9 35733408 35733410 31.2689 +chr9 35733410 35733414 31.4395 +chr9 35733414 35733415 29.974 +chr9 35733415 35733421 31.4395 +chr9 35733421 35733422 29.974 +chr9 35733422 35733426 31.4395 +chr9 35733426 35733431 29.974 +chr9 35733431 35733433 28.5236 +chr9 35733433 35733434 27.0891 +chr9 35733434 35733436 26.9367 +chr9 35733436 35733444 28.3652 +chr9 35733444 35733447 26.9367 +chr9 35733447 35733450 25.5246 +chr9 35733450 35733451 24.1294 +chr9 35733451 35733456 21.3928 +chr9 35733456 35733472 20.053 +chr9 35733472 35733474 18.7332 +chr9 35733474 35733476 17.4346 +chr9 35733476 35733478 16.1581 +chr9 35733478 35733488 14.9049 +chr9 35733488 35733492 13.6765 +chr9 35733492 35733493 12.4741 +chr9 35733493 35733494 11.2996 +chr9 35733494 35733495 10.1547 +chr9 35733495 35733500 9.04166 +chr9 35733500 35733502 7.96295 +chr9 35733502 35733508 9.04166 +chr9 35733508 35733513 7.96295 +chr9 35733513 35733519 9.04166 +chr9 35733519 35733522 7.96295 +chr9 35733522 35733527 6.92148 +chr9 35733527 35733542 5.92066 +chr9 35733542 35733546 6.92148 +chr9 35733546 35733549 5.92066 +chr9 35733549 35733555 5.94894 +chr9 35733555 35733556 4.98946 +chr9 35733556 35733571 4.07979 +chr9 35733571 35733576 2.34351 +chr9 35733576 35733581 1.78082 +chr9 35733581 35733585 2.34351 +chr9 35733585 35733617 3.6244 +chr9 35733617 35733642 2.95987 +chr9 35733642 35733646 2.34351 +chr9 35733646 35733653 2.95987 +chr9 35733653 35733658 2.34351 +chr9 35733658 35733660 1.78082 +chr9 35733660 35733682 2.34351 +chr9 35733682 35733684 1.78082 +chr9 35733684 35733687 3.2082 +chr9 35733687 35733692 4.05839 +chr9 35733692 35733701 4.96463 +chr9 35733701 35733702 5.92066 +chr9 35733702 35733707 4.96463 +chr9 35733707 35733721 5.92066 +chr9 35733721 35733724 4.96463 +chr9 35733724 35733725 5.92066 +chr9 35733725 35733734 4.96463 +chr9 35733734 35733739 5.92066 +chr9 35733739 35733741 6.92148 +chr9 35733741 35733745 5.92066 +chr9 35733745 35733762 5.87208 +chr9 35733762 35733763 6.86696 +chr9 35733763 35733786 6.92148 +chr9 35733786 35733788 5.92066 +chr9 35733788 35733827 6.92148 +chr9 35733827 35733830 5.92066 +chr9 35733830 35733832 6.92148 +chr9 35733832 35733834 5.92066 +chr9 35733834 35733841 6.92148 +chr9 35733841 35733865 5.92066 +chr9 35733865 35733869 4.96463 +chr9 35733869 35733874 5.92066 +chr9 35733874 35733875 4.96463 +chr9 35733875 35733879 4.05839 +chr9 35733879 35733902 3.2082 +chr9 35733902 35733940 2.42202 +chr9 35733940 35733957 1.71033 +chr9 35733957 35733970 1.69102 +chr9 35733970 35733974 1.07366 +chr9 35733974 35733987 0.56487 +chr9 35733987 35733993 0.57318 +chr9 35733993 35734140 0.19719 +chr9 35734140 35734198 0.19372 diff --git a/test/data/hubs/catLiftOff.bed b/test/data/hubs/catLiftOff.bed new file mode 100644 index 000000000..794a43de7 --- /dev/null +++ b/test/data/hubs/catLiftOff.bed @@ -0,0 +1,5 @@ +chr9 35717602 35752875 TLN1-201 0 - 35718445 35746352 76,85,212 57 969,129,183,63,126,125,106,108,186,117,126,184,167,147,120,102,150,171,102,133,182,141,162,144,123,90,94,140,198,120,209,103,129,135,114,117,129,167,295,168,99,209,109,114,181,77,102,156,105,61,128,143,153,130,98,163,121 0,1096,1375,1669,1860,2084,2408,3026,3243,6616,6831,7047,7388,7725,8606,8805,9017,9251,9505,9823,10127,10403,10786,11396,13616,13852,14044,14310,14650,15060,15890,16251,17008,17294,17629,17815,18114,19445,20201,20674,21867,22129,22574,22795,23094,23488,23867,24703,25174,25916,27007,27247,27627,27885,28279,28620,35152 TLN1 cmpl cmpl 0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,2,0,0,0,0,2,0,1,1,0,1,0,-1 CHM13_T0216333 protein_coding CHM13_G0055742 protein_coding ENSG00000137076.21 ENST00000314888.10 ENST00000314888.10-0 N/A nan nan N/A N/A nan 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 1,2,2,2,2,1,1,1,1,2,2,2,2,1,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,1 ortholog transMap True True True False +chr9 35717993 35753211 CHM13_T0216334 0 - 35753211 35753211 76,85,212 53 578,129,183,63,126,125,106,108,186,117,126,184,167,147,120,102,150,171,102,133,182,141,162,144,123,90,94,140,198,120,209,103,129,135,114,117,129,167,295,168,99,167,57,156,105,61,128,143,153,130,98,163,457 0,705,984,1278,1469,1693,2017,2635,2852,6225,6440,6656,6997,7334,8215,8414,8626,8860,9114,9432,9736,10012,10395,11005,13225,13461,13653,13919,14259,14669,15499,15860,16617,16903,17238,17424,17723,19054,19810,20283,21476,21738,23521,24312,24783,25525,26616,26856,27236,27494,27888,28229,34761 MSTRG.5603 none none -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 CHM13_T0216334 protein_coding CHM13_G0055742 protein_coding ENSG00000137076.21 N/A exRef-MSTRG.5603.2 N/A N/A N/A N/A N/A N/A 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,0 1,2,2,2,2,1,1,1,1,2,2,2,2,1,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,2,2,2,2,2,1 putative_novel_isoform exRef N/A N/A N/A False +chr9 35724217 35728532 TLN1-203 0 - 35728532 35728532 85,212,76 6 118,126,184,167,114,105 0,216,432,773,1110,4210 TLN1 none none -1,-1,-1,-1,-1,-1 CHM13_T0216336 processed_transcript CHM13_G0055742 protein_coding ENSG00000137076.21 ENST00000464379.5 ENST00000464379.5-0 N/A nan nan N/A N/A nan 1,1,1,1,1,1 2,2,2,2,1 ortholog transMap True True True False +chr9 35728013 35728625 TLN1-208 0 - 35728625 35728625 85,212,76 2 133,237 0,375 TLN1 none none -1,-1 CHM13_T0216340 processed_transcript CHM13_G0055742 protein_coding ENSG00000137076.21 ENST00000495712.1 ENST00000495712.1-0 N/A nan nan N/A N/A nan 1,1 2 ortholog transMap True True True False +chr9 35731333 35731399 MIR6852-201 0 - 35731399 35731399 85,212,76 1 66 0 MIR6852 none none -1 CHM13_T0216341 miRNA CHM13_G0055743 miRNA ENSG00000284195.1 ENST00000621699.1 ENST00000621699.1-0 N/A nan nan N/A N/A nan 1 nan ortholog transMap True True True False diff --git a/test/data/hubs/catLiftOff.bed.gz b/test/data/hubs/catLiftOff.bed.gz new file mode 100644 index 000000000..86441cd59 Binary files /dev/null and b/test/data/hubs/catLiftOff.bed.gz differ diff --git a/test/data/hubs/catLiftOff.bed.gz.tbi b/test/data/hubs/catLiftOff.bed.gz.tbi new file mode 100644 index 000000000..f6737da70 Binary files /dev/null and b/test/data/hubs/catLiftOff.bed.gz.tbi differ diff --git a/test/data/hubs/groups.txt b/test/data/hubs/groups.txt new file mode 100644 index 000000000..aff9f47f7 --- /dev/null +++ b/test/data/hubs/groups.txt @@ -0,0 +1,39 @@ +name user +label Custom Tracks +priority 1 +defaultIsClosed 1 + +name map +label Mapping and Sequencing +priority 2 +defaultIsClosed 0 + +name genes +label Genes and Gene Predictions +priority 3 +defaultIsClosed 0 + +name rna +label mRNA and EST +priority 4 +defaultIsClosed 0 + +name regulation +label Expression and Regulation +priority 5 +defaultIsClosed 0 + +name compGeno +label Comparative Genomics +priority 6 +defaultIsClosed 0 + +name varRep +label Variation and Repeats +priority 7 +defaultIsClosed 0 + +name x +label Experimental Tracks +priority 10 +defaultIsClosed 1 diff --git a/test/data/hubs/hub.txt b/test/data/hubs/hub.txt new file mode 100644 index 000000000..7944f7e6c --- /dev/null +++ b/test/data/hubs/hub.txt @@ -0,0 +1,281 @@ +hub GCF_000186305.1 genome assembly +shortLabel Burmese python +longLabel Burmese python/Python bivittatus/GCF_000186305.1_Python_molurus_bivittatus-5.0.2 genome assembly +useOneFile on +email hclawson@ucsc.edu +descriptionUrl html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.description.html + +genome GCF_000186305.1 +taxId 176946 +groups groups.txt +description Burmese python +twoBitPath GCF_000186305.1.2bit +twoBitBptURL GCF_000186305.1.2bit.bpt +chromSizes GCF_000186305.1.chrom.sizes.txt +chromAliasBb GCF_000186305.1.chromAlias.bb +organism Python_molurus_bivittatus-5.0.2 Sep. 2013 +defaultPos NW_006532014.1:484194-494194 +scientificName Python bivittatus +htmlPath html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.description.html +blat dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1 +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 + +track assembly +longLabel Assembly +shortLabel Assembly +visibility pack +colorByStrand 150,100,30 230,170,40 +color 150,100,30 +altColor 230,170,40 +bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.assembly.bb +type bigBed 6 +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.assembly +searchIndex name +searchTrix ixIxx/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.assembly.ix +url https://www.ncbi.nlm.nih.gov/nuccore/$$ +urlLabel NCBI Nucleotide database: +group map + +track gap +longLabel AGP gap +shortLabel Gap (AGP defined) +visibility dense +color 0,0,0 +bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.gap.bb +type bigBed 4 +group map +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.gap + +track cytoBandIdeo +shortLabel Chromosome Band (Ideogram) +longLabel Ideogram for Orientation +group map +visibility dense +type bigBed 4 + +bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.cytoBand.bb + +track gc5Base +shortLabel GC Percent +longLabel GC Percent in 5-Base Windows +group map +visibility full +autoScale Off +maxHeightPixels 128:36:16 +graphTypeDefault Bar +gridDefault OFF +windowingFunction Mean +color 0,0,0 +altColor 128,128,128 +viewLimits 30:70 +type bigWig 0 100 +bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.gc5Base.bw +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.gc5Base + +track tanDups +shortLabel Tandem Dups +longLabel Paired identical sequences +compositeTrack on +visibility hide +type bigBed 12 +group map +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.tanDups + + track gapOverlap + parent tanDups on + shortLabel Gap Overlaps + longLabel Paired exactly identical sequence on each side of a gap + bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.gapOverlap.bb + type bigBed 12 + + track tandemDups + parent tanDups on + shortLabel Tandem Dups + longLabel Paired exactly identical sequence survey over entire genome assembly + bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.tandemDups.bb + type bigBed 12 + +track repeatMasker +shortLabel RepeatMasker +longLabel RepeatMasker Repetitive Elements +type bigRmsk 9 + +visibility pack +group varRep +bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.rmsk.bb +maxWindowToDraw 5000000 +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.repeatMasker + +track simpleRepeat +shortLabel Simple Repeats +longLabel Simple Tandem Repeats by TRF +group varRep +visibility dense +type bigBed 4 + +bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.simpleRepeat.bb +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.simpleRepeat + +track refSeqComposite +compositeTrack on +shortLabel NCBI RefSeq +longLabel RefSeq gene predictions from NCBI +group genes +visibility pack +type bigBed +dragAndDrop subTracks +allButtonPair on +dataVersion NCBI Python bivittatus Annotation Release 102 (2022-11-07) +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.refSeqComposite +priority 2 + + track ncbiRefSeq + parent refSeqComposite on + color 12,12,120 + altColor 120,12,12 + shortLabel RefSeq All + type bigGenePred + labelFields name,geneName,geneName2 + defaultLabelFields geneName2 + searchIndex name + searchTrix ixIxx/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.ncbiRefSeq.ix + bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.ncbiRefSeq.bb + longLabel NCBI RefSeq genes, curated and predicted sets (NM_*, XM_*, NR_*, XR_*, NP_* or YP_*) + idXref ncbiRefSeqLink mrnaAcc name + baseColorUseCds given + baseColorDefault genomicCodons + priority 1 + + track ncbiRefSeqCurated + color 12,12,120 + parent refSeqComposite on + shortLabel RefSeq Curated + longLabel NCBI RefSeq genes, curated subset (NM_*, NR_*, NP_* or YP_*) + type bigGenePred + labelFields name,geneName,geneName2 + defaultLabelFields geneName2 + searchIndex name + searchTrix ixIxx/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.ncbiRefSeqCurated.ix + idXref ncbiRefSeqLink mrnaAcc name + bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.ncbiRefSeqCurated.bb + baseColorUseCds given + baseColorDefault genomicCodons + priority 2 + + track ncbiRefSeqPredicted + color 12,12,120 + parent refSeqComposite on + shortLabel RefSeq Predicted + longLabel NCBI RefSeq genes, predicted subset (XM_* or XR_*) + type bigGenePred + labelFields name,geneName,geneName2 + defaultLabelFields geneName2 + searchIndex name + searchTrix ixIxx/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.ncbiRefSeqPredicted.ix + idXref ncbiRefSeqLink mrnaAcc name + bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.ncbiRefSeqPredicted.bb + baseColorUseCds given + baseColorDefault genomicCodons + priority 3 + + track ncbiRefSeqOther + color 32,32,32 + parent refSeqComposite on + shortLabel RefSeq Other + longLabel NCBI RefSeq other annotations (not NM_*, NR_*, XM_*, XR_*, NP_* or YP_*) + priority 4 + searchIndex name + searchTrix ixIxx/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.ncbiRefSeqOther.ix + bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.ncbiRefSeqOther.bb + type bigBed 12 + + labelFields name + skipEmptyFields on + urls GeneID="https://www.ncbi.nlm.nih.gov/gene/$$" MIM="https://www.ncbi.nlm.nih.gov/omim/$$" HGNC="http://www.genenames.org/cgi-bin/gene_symbol_report?hgnc_id=$$" FlyBase="http://flybase.org/reports/$$" WormBase="http://www.wormbase.org/db/gene/gene?name=$$" RGD="https://rgd.mcw.edu/rgdweb/search/search.html?term=$$" SGD="https://www.yeastgenome.org/locus/$$" miRBase="http://www.mirbase.org/cgi-bin/mirna_entry.pl?acc=$$" ZFIN="https://zfin.org/$$" MGI="http://www.informatics.jax.org/marker/$$" + + track ncbiRefSeqPsl + priority 5 + parent refSeqComposite off + shortLabel RefSeq Alignments + longLabel RefSeq Alignments of RNAs + type bigPsl + searchIndex name + bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.bigPsl.bb + indelDoubleInsert on + indelQueryInsert on + showDiffBasesAllScales . + showDiffBasesMaxZoom 10000.0 + showCdsMaxZoom 10000.0 + showCdsAllScales . + baseColorDefault diffCodons + pslSequence no + baseColorUseSequence lfExtra + baseColorUseCds table given + color 0,0,0 + +track cpgIslands +compositeTrack on +shortLabel CpG Islands +longLabel CpG Islands (Islands < 300 Bases are Light Green) +group regulation +visibility pack +type bigBed 4 + +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.cpgIslands + + track cpgIslandExt + parent cpgIslands off + shortLabel CpG Islands + longLabel CpG Islands (Islands < 300 Bases are Light Green) + type bigBed 4 + + priority 1 + bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.cpgIslandExt.bb + + track cpgIslandExtUnmasked + parent cpgIslands on + shortLabel Unmasked CpG + longLabel CpG Islands on All Sequence (Islands < 300 Bases are Light Green) + type bigBed 4 + + priority 2 + bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.cpgIslandExtUnmasked.bb + +track windowMasker +shortLabel WM + SDust +longLabel Genomic Intervals Masked by WindowMasker + SDust +group varRep +visibility dense +type bigBed 3 +bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.windowMasker.bb +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.windowMasker + +track allGaps +shortLabel All Gaps +longLabel All gaps of unknown nucleotides (N's), including AGP annotated gaps +group map +visibility dense +type bigBed 3 +bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.allGaps.bb +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.allGaps + +track augustus +shortLabel Augustus +longLabel Augustus Gene Predictions +group genes +visibility dense +color 180,0,0 +type bigGenePred +bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.augustus.bb +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.augustus + +track xenoRefGene +shortLabel RefSeq mRNAs +longLabel RefSeq mRNAs mapped to this assembly +group rna +visibility pack +color 180,0,0 +type bigGenePred +bigDataUrl bbi/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.xenoRefGene.bb +url https://www.ncbi.nlm.nih.gov/nuccore/$$ +urlLabel NCBI Nucleotide database: +labelFields name,geneName,geneName2 +defaultLabelFields geneName +searchIndex name +searchTrix ixIxx/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.xenoRefGene.ix +html html/GCF_000186305.1_Python_molurus_bivittatus-5.0.2.xenoRefGene + diff --git a/test/data/twobit/GCA_004363605.1.2bit.bpt b/test/data/twobit/GCA_004363605.1.2bit.bpt new file mode 100644 index 000000000..ec06fad36 Binary files /dev/null and b/test/data/twobit/GCA_004363605.1.2bit.bpt differ diff --git a/test/data/twobit/GCF_000002655.1.2bit b/test/data/twobit/GCF_000002655.1.2bit new file mode 100644 index 000000000..a522a4cd6 Binary files /dev/null and b/test/data/twobit/GCF_000002655.1.2bit differ diff --git a/test/data/twobit/GCF_000002655.1.2bit.bpt b/test/data/twobit/GCF_000002655.1.2bit.bpt new file mode 100644 index 000000000..efffb7e74 Binary files /dev/null and b/test/data/twobit/GCF_000002655.1.2bit.bpt differ diff --git a/test/testHtsgetReader.js b/test/old/testHtsgetReader.js similarity index 94% rename from test/testHtsgetReader.js rename to test/old/testHtsgetReader.js index 48ae94422..428fdd70e 100644 --- a/test/testHtsgetReader.js +++ b/test/old/testHtsgetReader.js @@ -1,8 +1,8 @@ -import "./utils/mockObjects.js" +import "../utils/mockObjects.js" import {assert} from 'chai' -import HtsgetBamReader from "../js/htsget/htsgetBamReader.js" -import HtsgetVariantReader from "../js/htsget/htsgetVariantReader.js" -import Browser from "../js/browser.js" +import HtsgetBamReader from "../../js/htsget/htsgetBamReader.js" +import HtsgetVariantReader from "../../js/htsget/htsgetVariantReader.js" +import Browser from "../../js/browser.js" // Mock genome with "1,2,3..." name convention diff --git a/test/testAlignmentUtils.js b/test/testAlignmentUtils.js index aef5a04df..0015d7405 100755 --- a/test/testAlignmentUtils.js +++ b/test/testAlignmentUtils.js @@ -8,46 +8,53 @@ suite("testAlignmentUtils", function () { test("Alignment packing", async function () { this.timeout(10000) - const chr = 'chr22' - const start = 24375132 - const end = 24385311 - const bamReader = new BamReaderNonIndexed({ - type: 'bam', - url: 'test/data/bam/gstt1_sample.bam', - indexed: false - }) + await _testPacking('chr22') + await _testPacking('22') // Test aliasing - const alignmentContainer = await bamReader.readAlignments(chr, start, end) - const rows = packAlignmentRows(alignmentContainer.alignments, start, end, false) + async function _testPacking(chr) { + const start = 24375132 + const end = 24385311 - let count = 0 - for (let r of rows) count += r.alignments.length + const bamReader = new BamReaderNonIndexed({ + type: 'bam', + url: 'test/data/bam/gstt1_sample.bam', + indexed: false + }) - // All alignments are packed - assert.equal(alignmentContainer.alignments.length, count) + const alignmentContainer = await bamReader.readAlignments(chr, start, end) - // No duplicates - const seen = new Set() - for (let r of rows) { - for (let a of r.alignments) { - if (seen.has(a)) { - assert.fail(a, undefined, 'Alignment seen twice') + const rows = packAlignmentRows(alignmentContainer.alignments, start, end, false) + + let count = 0 + for (let r of rows) count += r.alignments.length + + // All alignments are packed + assert.equal(alignmentContainer.alignments.length, count) + + // No duplicates + const seen = new Set() + for (let r of rows) { + for (let a of r.alignments) { + if (seen.has(a)) { + assert.fail(a, undefined, 'Alignment seen twice') + } + seen.add(a) } - seen.add(a) } - } - // No alignment overlaps - for (let r of rows) { - let lastEnd = -1 - for (let a of r.alignments) { - assert.isAtLeast(a.start, lastEnd, 'Alignment start is < last end') - lastEnd = a.end + // No alignment overlaps + for (let r of rows) { + let lastEnd = -1 + for (let a of r.alignments) { + assert.isAtLeast(a.start, lastEnd, 'Alignment start is < last end') + lastEnd = a.end + } } } + }) diff --git a/test/testBAM.js b/test/testBAM.js index f0e440e0c..4895e4f07 100755 --- a/test/testBAM.js +++ b/test/testBAM.js @@ -2,6 +2,10 @@ import "./utils/mockObjects.js" import BamReader from "../js/bam/bamReader.js" import {assert} from 'chai' import BamReaderNonIndexed from "../js/bam/bamReaderNonIndexed.js" +import {createGenome} from "./utils/Genome.js" + + +const genome = createGenome() suite("testBAM", function () { @@ -12,10 +16,11 @@ suite("testBAM", function () { const end = 155160000 const bamReader = new BamReader({ - type: 'bam', - url: 'test/data/bam/na12889.bam', - indexURL: 'test/data/bam/na12889.bam.csi' - }) + type: 'bam', + url: 'test/data/bam/na12889.bam', + indexURL: 'test/data/bam/na12889.bam.csi' + }, + genome) const alignmentContainer = await bamReader.readAlignments(chr, start, end) validate(assert, alignmentContainer) @@ -23,17 +28,20 @@ suite("testBAM", function () { test("BAM alignments - non indexed", async function () { - const chr = 'chr1' const start = 155140000 const end = 155160000 const bamReader = new BamReaderNonIndexed({ - type: 'bam', - url: 'test/data/bam/na12889.bam', - indexed: false - }) + type: 'bam', + url: 'test/data/bam/na12889.bam', + indexed: false + }, + genome) - const alignmentContainer = await bamReader.readAlignments(chr, start, end) + let alignmentContainer = await bamReader.readAlignments("chr1", start, end) + validate(assert, alignmentContainer) + + alignmentContainer = await bamReader.readAlignments("1", start, end) validate(assert, alignmentContainer) }) diff --git a/test/testBED.js b/test/testBED.js index fdbcb0020..500307b28 100644 --- a/test/testBED.js +++ b/test/testBED.js @@ -5,7 +5,7 @@ import {assert} from 'chai' import {createGenome} from "./utils/Genome.js" const genome = createGenome() -import GenomeUtils from "../js/genome/genomeUtils.js" +import Genome from "../js/genome/genome.js" suite("testBed", function () { @@ -325,7 +325,7 @@ suite("testBed", function () { this.timeout(20000) // Need an actual genome object for this test, not a mock object - const genome = await GenomeUtils.loadGenome({ + const genome = await Genome.loadGenome({ id: "hg38", name: "Human (GRCh38/hg38)", fastaURL: "https://s3.dualstack.us-east-1.amazonaws.com/igv.broadinstitute.org/genomes/seq/hg38/hg38.fa", diff --git a/test/testChromAlias.js b/test/testChromAlias.js new file mode 100644 index 000000000..d14bde29b --- /dev/null +++ b/test/testChromAlias.js @@ -0,0 +1,58 @@ +import "./utils/mockObjects.js" +import ChromAliasFile from "../js/genome/chromAliasFile.js" +import BWReader from "../js/bigwig/bwReader.js" +import {assert} from "chai" + + +suite("chromAlias", function () { + + const genome = { + chromosomes: new Map([ + ["NC_007194.1", {name: "NC_007194.1", bpLength: 1}], + ]) + } + + /** + * Test a UCSC style chrom alias flat file + * + * # refseq assembly genbank ncbi ucsc + * NC_007194.1 1 CM000169.1 1 chr1 + * NC_007195.1 2 CM000170.1 2 chr2 + * NC_007196.1 3 CM000171.1 3 chr3 + * NC_007197.1 4 CM000172.1 4 chr4 + * NC_007198.1 5 CM000173.1 5 chr5 + * NC_007199.1 6 CM000174.1 6 chr6 + * NC_007200.1 7 CM000175.1 7 chr7 + * NC_007201.1 8 CM000176.1 8 chr8 + */ + test("test chromAlias.txt", async function () { + + const url = "test/data/genomes/GCF_000002655.1.chromAlias.txt" + + const chromAlias = new ChromAliasFile(url, {}, genome) + const chromAliasRecord = await chromAlias.search("1") + assert.equal(chromAliasRecord.chr, "NC_007194.1") + assert.equal(chromAliasRecord.genbank, "CM000169.1") + assert.equal(chromAliasRecord.ncbi, "1") + assert.equal(chromAliasRecord.ucsc, "chr1") + }) + + test("test chromalias bb extra index search", async function () { + this.timeout(200000) + const config = { + url: "test/data/genomes/GCF_000002655.1.chromAlias.bb", + format: "bigbed" + } + + const bbReader = new BWReader(config) + + // There are 5 extra indexes, 1 for each alias + const ncbiName = "3" + const f1 = await bbReader.search(ncbiName) + assert.equal(ncbiName, f1.ncbi) + + const ucscName = "chr2" + const f2 = await bbReader.search(ucscName) + assert.equal(ucscName, f2.ucsc) + }) +}) diff --git a/test/testCytobands.js b/test/testCytobands.js new file mode 100644 index 000000000..ecbe2fe6e --- /dev/null +++ b/test/testCytobands.js @@ -0,0 +1,42 @@ +import "./utils/mockObjects.js" +import {assert} from 'chai' +import CytobandFileBB from "../js/genome/cytobandFileBB.js" + + +suite("test cytobands", function () { + + + /** + * test parsing a cytoband BB file + * Example feature + * { + * "chr": "chr1", + * "start": 0, + * "end": 1735965, + * "name": "p36.33", + * "gieStain": "gneg" + * } + */ + test("test cytoband bigbed", async function () { + + const url = "test/data/bb/cytoBandMapped.bb" + const src = new CytobandFileBB(url) + + const cytobands = await src.getCytobands("chr1") + const last = cytobands[cytobands.length-1]; + assert.equal(248387328, last.end) + + }) + + test("test cytoband bigbed remote", async function () { + + const url = "https://hgdownload.soe.ucsc.edu/hubs/GCA/009/914/755/GCA_009914755.4/bbi/GCA_009914755.4_T2T-CHM13v2.0.cytoBandMapped/cytoBandMapped.bb" + const src = new CytobandFileBB(url) + + const cytobands = await src.getCytobands("chr1") // "CP068269.2 + const last = cytobands[cytobands.length-1]; + assert.equal(248387328, last.end) + + }) + //CP068269.2 +}) diff --git a/test/testGenome.js b/test/testGenome.js index 74affb027..70b1970fd 100644 --- a/test/testGenome.js +++ b/test/testGenome.js @@ -1,7 +1,8 @@ import "./utils/mockObjects.js" -import GenomeUtils from "../js/genome/genomeUtils.js" +import Genome from "../js/genome/genome.js" import {assert} from 'chai' -import {loadCytobandsBB} from "../js/genome/cytoband.js" +import CytobandFileBB from "../js/genome/cytobandFileBB.js" + suite("testGenome", function () { @@ -13,36 +14,32 @@ suite("testGenome", function () { id: "hg19", fastaURL: "https://s3.amazonaws.com/igv.broadinstitute.org/genomes/seq/1kg_v37/human_g1k_v37_decoy.fasta", cytobandURL: "https://s3.amazonaws.com/igv.broadinstitute.org/genomes/seq/b37/b37_cytoband.txt", - wholeGenomeView: false + wholeGenomeView: true } - const genome = await GenomeUtils.loadGenome(reference) + const genome = await Genome.loadGenome(reference) assert.ok(genome) assert.equal(86, genome.chromosomeNames.length) assert.equal(genome.getCumulativeOffset("2"), 249250621) }) - /** - * test parsing a cytoband BB file from the T2T hub - * Example feature - * { - * "chr": "chr1", - * "start": 0, - * "end": 1735965, - * "name": "p36.33", - * "gieStain": "gneg" - * } - */ - test("test cytoband bigbed", async function () { - - const url = "test/data/bb/cytoBandMapped.bb" - const {cytobands, chromosomes} = await loadCytobandsBB(url, {}) - - assert.equal(23, Object.keys(cytobands).length) - assert.equal(23, chromosomes.size) - const chr1 = chromosomes.get("chr1") - assert.equal(248387328, chr1.bpLength) + test("2bit genome with chromSizes", async function() { + + this.timeout(400000) + + const reference = { + id: "GCF_016699485.2", + format: "2bit", + twoBitURL: "https://hgdownload.gi.ucsc.edu/hubs//GCA/011/100/615/GCA_011100615.1/GCA_011100615.1.2bit", + chromSizes: "https://hgdownload.gi.ucsc.edu/hubs//GCA/011/100/615/GCA_011100615.1/GCA_011100615.1.chrom.sizes.txt" + } + + const genome = await Genome.loadGenome(reference) + assert.ok(genome.chromosomes.size > 0) + assert.ok(genome.chromosomeNames.length > 0) }) + + }) diff --git a/test/testGenomeUtils.js b/test/testGenomeUtils.js index 2e0e5e939..9e3e1884f 100644 --- a/test/testGenomeUtils.js +++ b/test/testGenomeUtils.js @@ -118,22 +118,4 @@ suite("testGenomeUtils", function () { }) - test("2bit genome", async function() { - - this.timeout(400000) - - const reference = { - id: "GCF_016699485.2", - format: "2bit", - twobitURL: "https://hgdownload.gi.ucsc.edu/hubs//GCA/011/100/615/GCA_011100615.1/GCA_011100615.1.2bit", - chromSizes: "https://hgdownload.gi.ucsc.edu/hubs//GCA/011/100/615/GCA_011100615.1/GCA_011100615.1.chrom.sizes.txt" - } - - - const genome = await GenomeUtils.loadGenome(reference) - - assert.ok(genome) - - }) - }) \ No newline at end of file diff --git a/test/testSearch.js b/test/testSearch.js index 53289dda5..227ca728f 100644 --- a/test/testSearch.js +++ b/test/testSearch.js @@ -39,32 +39,25 @@ suite("testSearch", function () { snpField: "snp" }, + isSoftclipped: () => false + } test("locus strings", function () { const s1 = "chr1:100-200" - const locus1 = parseLocusString(browser, s1) + const locus1 = parseLocusString(s1) assert.equal(locus1.chr, "chr1") assert.equal(locus1.start, 99) assert.equal(locus1.end, 200) - // Chr name alias - const s2 = "1:100-200" - const locus2 = parseLocusString(browser, s2) - assert.equal(locus2.chr, "chr1") - assert.equal(locus2.start, 99) - assert.equal(locus2.end, 200) // Single base const s3 = "1:100" - const locus3 = parseLocusString(browser, s3) - assert.equal(locus3.chr, "chr1") + const locus3 = parseLocusString(s3) + assert.equal(locus3.chr, "1") assert.equal(locus3.start, 79) assert.equal(locus3.end, 120) - const s4 = "egfr" - const locus4 = parseLocusString(browser, s4) - assert.equal(locus4, undefined) }) test("webservice", async function () { @@ -77,7 +70,6 @@ suite("testSearch", function () { assert.equal(locus.chr, "chr8") assert.equal(locus.start, 127735432) assert.equal(locus.end, 127742951) - assert.equal(locus.locusSearchString, gene) }) test("search (main function)", async function () { @@ -94,19 +86,16 @@ suite("testSearch", function () { assert.equal(locus1.chr, "chr1") assert.equal(locus1.start, 99) assert.equal(locus1.end, 200) - assert.equal(locus1.locusSearchString, s1) const locus2 = results[1] assert.equal(locus2.chr, "chr8") assert.equal(locus2.start, 127735432) assert.equal(locus2.end, 127742951) - assert.equal(locus2.locusSearchString, s2) const locus3 = results[2] assert.equal(locus3.chr, "chr1") assert.equal(locus3.start, 155185822) assert.equal(locus3.end, 155192915) - assert.equal(locus3.locusSearchString, s3) }) test("search name with spaces from bed file", async function () { @@ -123,8 +112,9 @@ suite("testSearch", function () { const mockBrowser = { genome: { + loadChromosome: async (chr) => chr, getChromosomeName: (chr) => chr, - getChromosome: (chr) => undefined + getChromosome: (chr) => {return {name: chr, bpLenght: 0}} }, tracks: [{ featureSource: featureSource, diff --git a/test/testSeg.js b/test/testSeg.js index 3f930130e..f4f3f88d1 100644 --- a/test/testSeg.js +++ b/test/testSeg.js @@ -1,6 +1,6 @@ import "./utils/mockObjects.js" import FeatureSource from "../js/feature/featureSource.js" -import GenomeUtils from "../js/genome/genomeUtils.js" +import Genome from "../js/genome/genome.js" import {assert} from 'chai' import {createGenome} from "./utils/Genome.js" @@ -41,7 +41,7 @@ suite("testSeg", function () { cytobandURL: "https://s3.amazonaws.com/igv.broadinstitute.org/genomes/seq/b37/b37_cytoband.txt" } - const genome = await GenomeUtils.loadGenome(reference) + const genome = await Genome.loadGenome(reference) const url = "https://www.dropbox.com/s/h1rotg4xgn1bq8a/segmented_data_080520.seg.gz?dl=0" const featureSource = FeatureSource({ format: 'seg', diff --git a/test/testTwobit.js b/test/testTwobit.js index 7840f9b5d..8d4848856 100644 --- a/test/testTwobit.js +++ b/test/testTwobit.js @@ -1,6 +1,7 @@ import "./utils/mockObjects.js" import {assert} from 'chai' import TwobitSequence from "../js/genome/twobit.js" +import BPTree from "../js/bigwig/bpTree.js" suite("testTwobit", function () { @@ -15,7 +16,7 @@ suite("testTwobit", function () { const start = 5 const end = 100 const seqString = await twobit.readSequence("chr1", start, end) - // assert.equal(seqString.length, end - start) + // assert.equal(seqString.length, end - start) assert.equal(seqString, expectedSequence.substring(start, end)) }) @@ -47,18 +48,23 @@ suite("testTwobit", function () { assert.equal(expectedSeq, seq) }) + test("twobit metadata", async function () { + const url = "test/data/twobit/GCF_000002655.1.2bit" + const twobit = new TwobitSequence({twoBitURL: url}) + await twobit.init() + const sequenceRecord = await twobit.getSequenceRecord("NC_007196.1") + assert.deepEqual(sequenceRecord.dnaSize, 4079167) + }) test("twobit blocks", async function () { this.timeout(200000) const url = "https://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.2bit" - const twobit = new TwobitSequence({fastaURL: url}) + const twobit = new TwobitSequence({twoBitURL: url}) await twobit.init() - await twobit._getSequenceMetaData("chr1") - - const meta = twobit.metaIndex.get("chr1") + const meta = await twobit.getSequenceRecord("chr1") assert.equal(248956422, meta.dnaSize) let lastBlockEnd = -1 @@ -76,5 +82,34 @@ suite("testTwobit", function () { } }) + test("twobit .bpt index", async function () { + + const url = "test/data/twobit/GCA_004363605.1.2bit.bpt" + const bpTree = await BPTree.loadBpTree(url, 0) + assert.ok(bpTree) + + const result = await bpTree.search("RJWJ011179649.1") + assert.ok(result) + + + }) + + test("twobit w bpt", async function () { + + const expectedSequence = "GCAGGTATCCAAAGCCAGAGGCCTGGTGCTACACGACTGG" + + const url = "test/data/twobit/GCF_000002655.1.2bit" + const bptUrl = "test/data/twobit/GCF_000002655.1.2bit.bpt" + const twobit = new TwobitSequence({twoBitURL: url, twoBitBptURL: bptUrl}) + const chr = "NC_007194.1" + const start = 1644639 + const end = 1644679 + const seqString = await twobit.readSequence(chr, start, end) + assert.equal(seqString, expectedSequence) + + + + }) + }) \ No newline at end of file diff --git a/test/testUCSC.js b/test/testUCSC.js index 545ad591c..e29e76be5 100644 --- a/test/testUCSC.js +++ b/test/testUCSC.js @@ -14,22 +14,21 @@ suite("ucsc utilities", function () { this.timeout(200000) - const hub = await Hub.loadHub({url: "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/186/305/GCF_000186305.1/hub.txt"}) + const hub = await Hub.loadHub({url: "test/data/hubs/hub.txt"}) assert.ok(hub.hub) assert.ok(hub.genomeStanza) assert.equal(22, hub.trackStanzas.length) const genomeConfig = hub.getGenomeConfig() - //const genome = await GenomeUtils.loadGenome(genomeConfig) + //const genome = await Genome.loadGenome(genomeConfig) assert.ok(genomeConfig) assert.equal("GCF_000186305.1", genomeConfig.id) assert.equal("Python bivittatus", genomeConfig.name) - assert.ok(genomeConfig.twobitURL) - assert.ok(genomeConfig.aliasBbURL) + assert.ok(genomeConfig.twoBitBptURL) + assert.ok(genomeConfig.twoBitURL) + assert.ok(genomeConfig.chromAliasBbURL) assert.ok(genomeConfig.cytobandBbURL) - - }) test("trix", async function () { @@ -68,5 +67,9 @@ suite("ucsc utilities", function () { assert.equal(f2.name2.toLowerCase(), name2.toLowerCase()) }) + + + + }) diff --git a/test/utils/Genome.js b/test/utils/Genome.js index e53d33bbe..4996f5927 100644 --- a/test/utils/Genome.js +++ b/test/utils/Genome.js @@ -39,6 +39,10 @@ function createGenome() { chr.startsWith("chr") ? chr : "chr" + chr }, + loadChromosome: async function (chr) { + return this.getChromosome(chr) + }, + getChromosome: function (chr) { const name = this.getChromosomeName(chr) @@ -46,43 +50,21 @@ function createGenome() { return bpLength ? {name, bpLength} : undefined }, - wgChromosomeNames: Object.keys(sizes), + getAliasRecord : async function(chr) { + const chromosome = this.getChromosome(chr) - featureDB: new Map(), + return { + chr: chromosome.name, + start: 0, + end: chromosome.bpLength, + ncbi: chromosome.name.substring(3) + } - addFeaturesToDB: function (featureList, config) { + }, - const insertFeature = (name, feature) => { - const current = this.featureDB.get(name) - if (current) { - feature = (feature.end - feature.start) > (current.end - current.start) ? feature : current - } - this.featureDB.set(name, feature) - } + wgChromosomeNames: Object.keys(sizes), - for (let feature of featureList) { - if (feature.name) { - insertFeature(feature.name.toUpperCase(), feature) - } - if (feature.gene && feature.gene.name) { - insertFeature(feature.gene.name.toUpperCase(), feature) - } - - if (config.searchableFields) { - for (let f of config.searchableFields) { - const value = feature.getAttributeValue(f) - if (value) { - if (value.indexOf(" ") > 0) { - insertFeature(value.replaceAll(" ", "+").toUpperCase(), feature) - } else { - insertFeature(value.toUpperCase(), feature) - } - } - } - } - } - } } }