UNPKG

molstar

Version:

A comprehensive macromolecular library.

377 lines 17.9 kB
"use strict"; /** * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * Adapted from NGL. * * @author David Sehnal <david.sehnal@gmail.com> * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.parseXtc = void 0; var tslib_1 = require("tslib"); var mol_task_1 = require("../../../mol-task"); var result_1 = require("../result"); var MagicInts = new Uint32Array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 10, 12, 16, 20, 25, 32, 40, 50, 64, 80, 101, 128, 161, 203, 256, 322, 406, 512, 645, 812, 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501, 8192, 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536, 82570, 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561, 832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042, 8388607, 10568983, 13316085, 16777216 ]); var FirstIdx = 9; // const LastIdx = MagicInts.length var Decoder; (function (Decoder) { function sizeOfInt(size) { var num = 1; var numOfBits = 0; while (size >= num && numOfBits < 32) { numOfBits++; num <<= 1; } return numOfBits; } Decoder.sizeOfInt = sizeOfInt; var _tmpBytes = new Uint8Array(32); function sizeOfInts(numOfInts, sizes) { var numOfBytes = 1; var numOfBits = 0; _tmpBytes[0] = 1; for (var i = 0; i < numOfInts; i++) { var bytecnt = void 0; var tmp = 0; for (bytecnt = 0; bytecnt < numOfBytes; bytecnt++) { tmp += _tmpBytes[bytecnt] * sizes[i]; _tmpBytes[bytecnt] = tmp & 0xff; tmp >>= 8; } while (tmp !== 0) { _tmpBytes[bytecnt++] = tmp & 0xff; tmp >>= 8; } numOfBytes = bytecnt; } var num = 1; numOfBytes--; while (_tmpBytes[numOfBytes] >= num) { numOfBits++; num *= 2; } return numOfBits + numOfBytes * 8; } Decoder.sizeOfInts = sizeOfInts; var _buffer = new ArrayBuffer(8 * 3); Decoder.buf = new Int32Array(_buffer); var uint32view = new Uint32Array(_buffer); function decodeBits(cbuf, offset, numOfBits1) { var numOfBits = numOfBits1; var mask = (1 << numOfBits) - 1; var lastBB0 = uint32view[1]; var lastBB1 = uint32view[2]; var cnt = Decoder.buf[0]; var num = 0; while (numOfBits >= 8) { lastBB1 = (lastBB1 << 8) | cbuf[offset + cnt++]; num |= (lastBB1 >> lastBB0) << (numOfBits - 8); numOfBits -= 8; } if (numOfBits > 0) { if (lastBB0 < numOfBits) { lastBB0 += 8; lastBB1 = (lastBB1 << 8) | cbuf[offset + cnt++]; } lastBB0 -= numOfBits; num |= (lastBB1 >> lastBB0) & ((1 << numOfBits) - 1); } num &= mask; Decoder.buf[0] = cnt; Decoder.buf[1] = lastBB0; Decoder.buf[2] = lastBB1; return num; } Decoder.decodeBits = decodeBits; function decodeByte(cbuf, offset) { // special version of decodeBits with numOfBits = 8 // const mask = 0xff; // (1 << 8) - 1; // let lastBB0 = uint32view[1]; var lastBB1 = uint32view[2]; var cnt = Decoder.buf[0]; lastBB1 = (lastBB1 << 8) | cbuf[offset + cnt]; Decoder.buf[0] = cnt + 1; // buf[1] = lastBB0; Decoder.buf[2] = lastBB1; return (lastBB1 >> uint32view[1]) & 0xff; } var intBytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // new Int32Array(32); function decodeInts(cbuf, offset, numOfBits1, sizes, nums) { var numOfBits = numOfBits1; var numOfBytes = 0; intBytes[0] = 0; intBytes[1] = 0; intBytes[2] = 0; intBytes[3] = 0; while (numOfBits > 8) { // this is inversed??? why??? because of the endiannness??? intBytes[numOfBytes++] = decodeByte(cbuf, offset); numOfBits -= 8; } if (numOfBits > 0) { intBytes[numOfBytes++] = decodeBits(cbuf, offset, numOfBits); } for (var i = 2; i > 0; i--) { var num = 0; var s = sizes[i]; for (var j = numOfBytes - 1; j >= 0; j--) { num = (num << 8) | intBytes[j]; var t = (num / s) | 0; intBytes[j] = t; num = num - t * s; } nums[i] = num; } nums[0] = intBytes[0] | (intBytes[1] << 8) | (intBytes[2] << 16) | (intBytes[3] << 24); } Decoder.decodeInts = decodeInts; })(Decoder || (Decoder = {})); function undefinedError() { throw new Error('(xdrfile error) Undefined error.'); } function parseInternal(ctx, data) { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { var dv, f, coordinates, boxes, times, minMaxInt, sizeint, bitsizeint, sizesmall, thiscoord, prevcoord, offset, buf, frameCoords, natoms, box, i, i, lfp, lsize, precision, bitsize, smallidx, tmpIdx, smaller, smallnum, adz, invPrecision, run_1, i, flag, isSmaller, k, tmpSwap, c; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: dv = new DataView(data.buffer, data.byteOffset); f = { frames: [], boxes: [], times: [], timeOffset: 0, deltaTime: 0 }; coordinates = f.frames; boxes = f.boxes; times = f.times; minMaxInt = [0, 0, 0, 0, 0, 0]; sizeint = [0, 0, 0]; bitsizeint = [0, 0, 0]; sizesmall = [0, 0, 0]; thiscoord = [0.1, 0.1, 0.1]; prevcoord = [0.1, 0.1, 0.1]; offset = 0; buf = Decoder.buf; _a.label = 1; case 1: if (!true) return [3 /*break*/, 4]; frameCoords = void 0; natoms = dv.getInt32(offset + 4); // const step = dv.getInt32(offset + 8) offset += 12; times.push(dv.getFloat32(offset)); offset += 4; box = new Float32Array(9); for (i = 0; i < 9; ++i) { box[i] = dv.getFloat32(offset) * 10; offset += 4; } boxes.push(box); if (natoms <= 9) { // no compression frameCoords = { count: natoms / 3, x: new Float32Array(natoms / 3), y: new Float32Array(natoms / 3), z: new Float32Array(natoms / 3) }; for (i = 0; i < natoms / 3; ++i) { frameCoords.x[i] = dv.getFloat32(offset); frameCoords.y[i] = dv.getFloat32(offset); frameCoords.z[i] = dv.getFloat32(offset); offset += 4; } } else { buf[0] = buf[1] = buf[2] = 0; sizeint[0] = sizeint[1] = sizeint[2] = 0; sizesmall[0] = sizesmall[1] = sizesmall[2] = 0; bitsizeint[0] = bitsizeint[1] = bitsizeint[2] = 0; thiscoord[0] = thiscoord[1] = thiscoord[2] = 0; prevcoord[0] = prevcoord[1] = prevcoord[2] = 0; frameCoords = { count: natoms, x: new Float32Array(natoms), y: new Float32Array(natoms), z: new Float32Array(natoms) }; lfp = 0; lsize = dv.getInt32(offset); offset += 4; precision = dv.getFloat32(offset); offset += 4; minMaxInt[0] = dv.getInt32(offset); minMaxInt[1] = dv.getInt32(offset + 4); minMaxInt[2] = dv.getInt32(offset + 8); minMaxInt[3] = dv.getInt32(offset + 12); minMaxInt[4] = dv.getInt32(offset + 16); minMaxInt[5] = dv.getInt32(offset + 20); sizeint[0] = minMaxInt[3] - minMaxInt[0] + 1; sizeint[1] = minMaxInt[4] - minMaxInt[1] + 1; sizeint[2] = minMaxInt[5] - minMaxInt[2] + 1; offset += 24; bitsize = void 0; if ((sizeint[0] | sizeint[1] | sizeint[2]) > 0xffffff) { bitsizeint[0] = Decoder.sizeOfInt(sizeint[0]); bitsizeint[1] = Decoder.sizeOfInt(sizeint[1]); bitsizeint[2] = Decoder.sizeOfInt(sizeint[2]); bitsize = 0; // flag the use of large sizes } else { bitsize = Decoder.sizeOfInts(3, sizeint); } smallidx = dv.getInt32(offset); offset += 4; tmpIdx = smallidx - 1; tmpIdx = (FirstIdx > tmpIdx) ? FirstIdx : tmpIdx; smaller = (MagicInts[tmpIdx] / 2) | 0; smallnum = (MagicInts[smallidx] / 2) | 0; sizesmall[0] = sizesmall[1] = sizesmall[2] = MagicInts[smallidx]; adz = Math.ceil(dv.getInt32(offset) / 4) * 4; offset += 4; invPrecision = 1.0 / precision; run_1 = 0; i = 0; // const buf8 = new Uint8Array(data.buffer, data.byteOffset + offset, 32 * 4); // 229... thiscoord[0] = thiscoord[1] = thiscoord[2] = 0; while (i < lsize) { if (bitsize === 0) { thiscoord[0] = Decoder.decodeBits(data, offset, bitsizeint[0]); thiscoord[1] = Decoder.decodeBits(data, offset, bitsizeint[1]); thiscoord[2] = Decoder.decodeBits(data, offset, bitsizeint[2]); } else { Decoder.decodeInts(data, offset, bitsize, sizeint, thiscoord); } i++; thiscoord[0] += minMaxInt[0]; thiscoord[1] += minMaxInt[1]; thiscoord[2] += minMaxInt[2]; prevcoord[0] = thiscoord[0]; prevcoord[1] = thiscoord[1]; prevcoord[2] = thiscoord[2]; flag = Decoder.decodeBits(data, offset, 1); isSmaller = 0; if (flag === 1) { run_1 = Decoder.decodeBits(data, offset, 5); isSmaller = run_1 % 3; run_1 -= isSmaller; isSmaller--; } // if ((lfp-ptrstart)+run > size3){ // fprintf(stderr, "(xdrfile error) Buffer overrun during decompression.\n"); // return 0; // } if (run_1 > 0) { thiscoord[0] = thiscoord[1] = thiscoord[2] = 0; for (k = 0; k < run_1; k += 3) { Decoder.decodeInts(data, offset, smallidx, sizesmall, thiscoord); i++; thiscoord[0] += prevcoord[0] - smallnum; thiscoord[1] += prevcoord[1] - smallnum; thiscoord[2] += prevcoord[2] - smallnum; if (k === 0) { tmpSwap = thiscoord[0]; thiscoord[0] = prevcoord[0]; prevcoord[0] = tmpSwap; tmpSwap = thiscoord[1]; thiscoord[1] = prevcoord[1]; prevcoord[1] = tmpSwap; tmpSwap = thiscoord[2]; thiscoord[2] = prevcoord[2]; prevcoord[2] = tmpSwap; frameCoords.x[lfp] = prevcoord[0] * invPrecision; frameCoords.y[lfp] = prevcoord[1] * invPrecision; frameCoords.z[lfp] = prevcoord[2] * invPrecision; lfp++; } else { prevcoord[0] = thiscoord[0]; prevcoord[1] = thiscoord[1]; prevcoord[2] = thiscoord[2]; } frameCoords.x[lfp] = thiscoord[0] * invPrecision; frameCoords.y[lfp] = thiscoord[1] * invPrecision; frameCoords.z[lfp] = thiscoord[2] * invPrecision; lfp++; } } else { frameCoords.x[lfp] = thiscoord[0] * invPrecision; frameCoords.y[lfp] = thiscoord[1] * invPrecision; frameCoords.z[lfp] = thiscoord[2] * invPrecision; lfp++; } smallidx += isSmaller; if (isSmaller < 0) { smallnum = smaller; if (smallidx > FirstIdx) { smaller = (MagicInts[smallidx - 1] / 2) | 0; } else { smaller = 0; } } else if (isSmaller > 0) { smaller = smallnum; smallnum = (MagicInts[smallidx] / 2) | 0; } sizesmall[0] = sizesmall[1] = sizesmall[2] = MagicInts[smallidx]; if (sizesmall[0] === 0 || sizesmall[1] === 0 || sizesmall[2] === 0) { undefinedError(); } } offset += adz; } for (c = 0; c < natoms; c++) { frameCoords.x[c] *= 10; frameCoords.y[c] *= 10; frameCoords.z[c] *= 10; } coordinates.push(frameCoords); if (!ctx.shouldUpdate) return [3 /*break*/, 3]; return [4 /*yield*/, ctx.update({ current: offset, max: data.length })]; case 2: _a.sent(); _a.label = 3; case 3: if (offset >= data.length) return [3 /*break*/, 4]; return [3 /*break*/, 1]; case 4: if (times.length >= 1) { f.timeOffset = times[0]; } if (times.length >= 2) { f.deltaTime = times[1] - times[0]; } return [2 /*return*/, f]; } }); }); } function parseXtc(data) { var _this = this; return mol_task_1.Task.create('Parse XTC', function (ctx) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () { var file, e_1; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); ctx.update({ canAbort: true, message: 'Parsing trajectory...' }); return [4 /*yield*/, parseInternal(ctx, data)]; case 1: file = _a.sent(); return [2 /*return*/, result_1.ReaderResult.success(file)]; case 2: e_1 = _a.sent(); return [2 /*return*/, result_1.ReaderResult.error('' + e_1)]; case 3: return [2 /*return*/]; } }); }); }); } exports.parseXtc = parseXtc; //# sourceMappingURL=parser.js.map