@gmod/bam
Version:
Parser for BAM and BAM index (bai) files
82 lines • 2.76 kB
JavaScript
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