UNPKG

@gmod/bam

Version:

Parser for BAM and BAM index (bai) files

82 lines 2.76 kB
import QuickLRU from '@jbrowse/quick-lru'; import { optimizeChunks } from "./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. export function memoizeByRefId(getIndices, maxSize = 5) { const cache = new QuickLRU({ maxSize }); return (refId) => { if (cache.has(refId)) { return cache.get(refId); } const result = getIndices(refId); if (result) { cache.set(refId, result); } return result; }; } export default 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 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 = optimizeChunks(blockResults.flat()); let total = 0; for (const block of mergedBlocks) { total += block.fetchedSize(); } return total; } } //# sourceMappingURL=indexFile.js.map