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