UNPKG

molstar

Version:

A comprehensive macromolecular library.

165 lines 6.29 kB
/** * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { __awaiter, __generator } from "tslib"; import { ReaderResult as Result } from '../result'; import { Task } from '../../../mol-task'; import { uint8ToString } from '../../common/binary'; export function _parseDcd(data) { // http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/dcdplugin.html // The DCD format is structured as follows // (FORTRAN UNFORMATTED, with Fortran data type descriptions): // HDR NSET ISTRT NSAVC 5-ZEROS NATOM-NFREAT DELTA 9-ZEROS // `CORD' #files step 1 step zeroes (zero) timestep (zeroes) // interval // C*4 INT INT INT 5INT INT DOUBLE 9INT // ========================================================================== // NTITLE TITLE // INT (=2) C*MAXTITL // (=32) // ========================================================================== // NATOM // #atoms // INT // ========================================================================== // X(I), I=1,NATOM (DOUBLE) // Y(I), I=1,NATOM // Z(I), I=1,NATOM // ========================================================================== var dv = new DataView(data.buffer); var header = Object.create(null); var frames = []; var nextPos = 0; // header block var intView = new Int32Array(data.buffer, 0, 23); var ef = intView[0] !== dv.getInt32(0); // endianess flag // swap byte order when big endian (84 indicates little endian) if (intView[0] !== 84) { var n = data.byteLength; for (var i = 0; i < n; i += 4) { dv.setFloat32(i, dv.getFloat32(i), true); } } if (intView[0] !== 84) { throw new Error('dcd bad format, header block start'); } // format indicator, should read 'CORD' var formatString = String.fromCharCode(dv.getUint8(4), dv.getUint8(5), dv.getUint8(6), dv.getUint8(7)); if (formatString !== 'CORD') { throw new Error('dcd bad format, format string'); } var isCharmm = false; var extraBlock = false; var fourDims = false; // version field in charmm, unused in X-PLOR if (intView[22] !== 0) { isCharmm = true; if (intView[12] !== 0) extraBlock = true; if (intView[13] === 1) fourDims = true; } header.NSET = intView[2]; header.ISTART = intView[3]; header.NSAVC = intView[4]; header.NAMNF = intView[10]; if (isCharmm) { header.DELTA = dv.getFloat32(44, ef); } else { header.DELTA = dv.getFloat64(44, ef); } if (intView[22] !== 84) { throw new Error('dcd bad format, header block end'); } nextPos = nextPos + 21 * 4 + 8; // title block var titleEnd = dv.getInt32(nextPos, ef); var titleStart = nextPos + 1; if ((titleEnd - 4) % 80 !== 0) { throw new Error('dcd bad format, title block start'); } header.TITLE = uint8ToString(data.subarray(titleStart, titleEnd)); if (dv.getInt32(titleStart + titleEnd + 4 - 1, ef) !== titleEnd) { throw new Error('dcd bad format, title block end'); } nextPos = nextPos + titleEnd + 8; // natom block if (dv.getInt32(nextPos, ef) !== 4) { throw new Error('dcd bad format, natom block start'); } header.NATOM = dv.getInt32(nextPos + 4, ef); if (dv.getInt32(nextPos + 8, ef) !== 4) { throw new Error('dcd bad format, natom block end'); } nextPos = nextPos + 4 + 8; // fixed atoms block if (header.NAMNF > 0) { // TODO read coordinates and indices of fixed atoms throw new Error('dcd format with fixed atoms unsupported, aborting'); } // frames var natom = header.NATOM; var natom4 = natom * 4; for (var i = 0, n = header.NSET; i < n; ++i) { var frame = Object.create(null); frame.elementCount = natom; if (extraBlock) { nextPos += 4; // block start frame.cell = [ dv.getFloat64(nextPos, ef), dv.getFloat64(nextPos + 1, ef), dv.getFloat64(nextPos + 2 * 8, ef), dv.getFloat64(nextPos + 3 * 8, ef), dv.getFloat64(nextPos + 4 * 8, ef), dv.getFloat64(nextPos + 5 * 8, ef) ]; nextPos += 48; nextPos += 4; // block end } // xyz coordinates for (var j = 0; j < 3; ++j) { if (dv.getInt32(nextPos, ef) !== natom4) { throw new Error("dcd bad format, coord block start: " + i + ", " + j); } nextPos += 4; // block start var c = new Float32Array(data.buffer, nextPos, natom); if (j === 0) frame.x = c; else if (j === 1) frame.y = c; else frame.z = c; nextPos += natom4; if (dv.getInt32(nextPos, ef) !== natom4) { throw new Error("dcd bad format, coord block end: " + i + ", " + j); } nextPos += 4; // block end } if (fourDims) { var bytes = dv.getInt32(nextPos, ef); nextPos += 4 + bytes + 4; // block start + skip + block end } frames.push(frame); } return { header: header, frames: frames }; } export function parseDcd(data) { var _this = this; return Task.create('Parse DCD', function (ctx) { return __awaiter(_this, void 0, void 0, function () { var dcdFile; return __generator(this, function (_a) { try { dcdFile = _parseDcd(data); return [2 /*return*/, Result.success(dcdFile)]; } catch (e) { return [2 /*return*/, Result.error(e)]; } return [2 /*return*/]; }); }); }); } //# sourceMappingURL=parser.js.map