UNPKG

@gmod/bam

Version:

Parser for BAM and BAM index (bai) files

89 lines 3.09 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.memoizeByRefId = memoizeByRefId; const quick_lru_1 = __importDefault(require("@jbrowse/quick-lru")); const util_ts_1 = require("./util.js"); // SYNC: ~/src/gmod/tabix-js/src/util.ts memoizeByRefId // LRU-cache the result of getIndices(refId) so repeated lookups for the same // reference don't re-walk the index bytes. function memoizeByRefId(getIndices, maxSize = 5) { const cache = new quick_lru_1.default({ maxSize }); return (refId) => { if (cache.has(refId)) { return cache.get(refId); } const result = getIndices(refId); if (result) { cache.set(refId, result); } return result; }; } class IndexFile { filehandle; renameRefSeq; setupP; constructor({ filehandle, renameRefSeq = (n) => n, }) { this.filehandle = filehandle; this.renameRefSeq = renameRefSeq; } async blocksForRange(refId, min, max, opts = {}) { if (min < 0) { min = 0; } const indexData = await this.parse(opts); const ba = indexData.indices(refId); if (!ba) { return []; } const overlappingBins = this.reg2bins(min, max); if (overlappingBins.length === 0) { return []; } const chunks = []; const { binIndex } = ba; for (const [start, end] of overlappingBins) { for (let bin = start; bin <= end; bin++) { const binChunks = binIndex[bin]; if (binChunks) { for (let i = 0, l = binChunks.length; i < l; i++) { chunks.push(binChunks[i]); } } } } return (0, util_ts_1.optimizeChunks)(chunks, this.getLowestChunk(ba, min)); } parse(opts = {}) { if (!this.setupP) { this.setupP = this._parse(opts).catch((e) => { this.setupP = undefined; throw e; }); } return this.setupP; } async lineCount(refId, opts) { const indexData = await this.parse(opts); return indexData.indices(refId)?.stats?.lineCount ?? 0; } async hasRefSeq(seqId, opts) { const indexData = await this.parse(opts); return !!indexData.indices(seqId); } async estimatedBytesForRegions(regions, opts) { const blockResults = await Promise.all(regions.map(r => this.blocksForRange(r.refId, r.start, r.end, opts))); // Deduplicate and merge overlapping blocks across all regions const mergedBlocks = (0, util_ts_1.optimizeChunks)(blockResults.flat()); let total = 0; for (const block of mergedBlocks) { total += block.fetchedSize(); } return total; } } exports.default = IndexFile; //# sourceMappingURL=indexFile.js.map