genomic-reader
Version:
A Typescript library for reading BigWig, BigBed, 2bit, and Bam files. Capable of streaming. For use in the browser or on Node.js.
165 lines • 7.14 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadHeaderData = exports.FileType = void 0;
const BinaryParser_1 = require("../util/BinaryParser");
const TwoBitHeaderReader_1 = require("./TwoBitHeaderReader");
const TWOBIT_MAGIC_LTH = 0x1A412743;
const TWOBIT_MAGIC_HTL = 0x4327411A;
const BIGWIG_MAGIC_LTH = 0x888FFC26;
const BIGWIG_MAGIC_HTL = 0x26FC8F88;
const BIGBED_MAGIC_LTH = 0x8789F2EB;
const BIGBED_MAGIC_HTL = 0xEBF28987;
const CHROM_TREE_MAGIC = 0x78CA8C91;
const BBFILE_HEADER_SIZE = 64;
var FileType;
(function (FileType) {
FileType["BigWig"] = "BigWig";
FileType["BigBed"] = "BigBed";
FileType["TwoBit"] = "TwoBit";
})(FileType = exports.FileType || (exports.FileType = {}));
function loadHeaderData(dataLoader) {
return __awaiter(this, void 0, void 0, function* () {
const headerData = yield dataLoader.load(0, BBFILE_HEADER_SIZE);
let fileType = undefined;
let littleEndian = true;
let binaryParser = new BinaryParser_1.BinaryParser(headerData, littleEndian);
let magic = binaryParser.getUInt();
if (BIGWIG_MAGIC_LTH === magic) {
fileType = FileType.BigWig;
}
else if (BIGBED_MAGIC_LTH === magic) {
fileType = FileType.BigBed;
}
else if (TWOBIT_MAGIC_LTH === magic) {
return TwoBitHeaderReader_1.loadTwoBitHeaderData(dataLoader, littleEndian);
}
else {
littleEndian = false;
binaryParser = new BinaryParser_1.BinaryParser(headerData, littleEndian);
magic = binaryParser.getUInt();
if (BIGWIG_MAGIC_HTL === magic) {
fileType = FileType.BigWig;
}
else if (BIGBED_MAGIC_HTL === magic) {
fileType = FileType.BigBed;
}
else if (TWOBIT_MAGIC_HTL === magic) {
return TwoBitHeaderReader_1.loadTwoBitHeaderData(dataLoader, littleEndian);
}
}
if (undefined === fileType) {
throw new Error("Unable to determine file type.");
}
const commonHeader = {
bwVersion: binaryParser.getUShort(),
nZoomLevels: binaryParser.getUShort(),
chromTreeOffset: binaryParser.getLong(),
fullDataOffset: binaryParser.getLong(),
fullIndexOffset: binaryParser.getLong(),
fieldCount: binaryParser.getUShort(),
definedFieldCount: binaryParser.getUShort(),
autoSqlOffset: binaryParser.getLong(),
totalSummaryOffset: binaryParser.getLong(),
uncompressBuffSize: binaryParser.getInt(),
reserved: binaryParser.getLong()
};
const xdata = yield dataLoader.load(BBFILE_HEADER_SIZE, commonHeader.fullDataOffset - BBFILE_HEADER_SIZE + 5);
const zoomLevelHeaders = [];
binaryParser = new BinaryParser_1.BinaryParser(xdata);
for (let i = 1; i <= commonHeader.nZoomLevels; i++) {
const zoomNumber = commonHeader.nZoomLevels - i;
const zoomLevelHeader = {
index: zoomNumber,
reductionLevel: binaryParser.getInt(),
reserved: binaryParser.getInt(),
dataOffset: binaryParser.getLong(),
indexOffset: binaryParser.getLong()
};
zoomLevelHeaders[zoomNumber] = zoomLevelHeader;
}
let autosql = undefined;
if (commonHeader.autoSqlOffset > 0) {
binaryParser.position = commonHeader.autoSqlOffset - BBFILE_HEADER_SIZE;
autosql = binaryParser.getString();
}
let totalSummary = undefined;
if (commonHeader.totalSummaryOffset > 0) {
binaryParser.position = commonHeader.totalSummaryOffset - BBFILE_HEADER_SIZE;
totalSummary = {
basesCovered: binaryParser.getLong(),
minVal: binaryParser.getDouble(),
maxVal: binaryParser.getDouble(),
sumData: binaryParser.getDouble(),
sumSquares: binaryParser.getDouble()
};
}
let chromTree = undefined;
if (commonHeader.chromTreeOffset > 0) {
binaryParser.position = commonHeader.chromTreeOffset - BBFILE_HEADER_SIZE;
const magic = binaryParser.getUInt();
if (CHROM_TREE_MAGIC !== magic) {
throw new Error("Chomosome ID B+ Tree not found.");
}
chromTree = {
magic: magic,
blockSize: binaryParser.getInt(),
keySize: binaryParser.getInt(),
valSize: binaryParser.getInt(),
itemCount: binaryParser.getLong(),
reserved: binaryParser.getLong(),
chromToId: {},
chromSize: {},
idToChrom: []
};
buildChromTree(chromTree, binaryParser);
}
return {
fileType: fileType,
littleEndian: littleEndian,
common: commonHeader,
zoomLevelHeaders: zoomLevelHeaders,
autosql: autosql,
totalSummary: totalSummary,
chromTree: chromTree
};
});
}
exports.loadHeaderData = loadHeaderData;
function buildChromTree(chromTree, binaryParser, offset) {
if (undefined !== offset) {
binaryParser.position = offset;
}
const type = binaryParser.getByte();
binaryParser.position++;
const count = binaryParser.getUShort();
if (1 === type) {
for (let i = 0; i < count; i++) {
const key = binaryParser.getFixedLengthTrimmedString(chromTree.keySize);
const chromId = binaryParser.getInt();
const chromSize = binaryParser.getInt();
chromTree.chromToId[key] = chromId;
chromTree.idToChrom[chromId] = key;
chromTree.chromSize[key] = chromSize;
}
}
else {
for (let i = 0; i < count; i++) {
const key = binaryParser.getFixedLengthTrimmedString(chromTree.keySize);
const childOffset = binaryParser.getLong();
const bufferOffset = childOffset - BBFILE_HEADER_SIZE;
const currOffset = binaryParser.position;
buildChromTree(chromTree, binaryParser, bufferOffset);
binaryParser.position = currOffset;
}
}
}
//# sourceMappingURL=BigWigHeaderReader.js.map