UNPKG

molstar

Version:

A comprehensive macromolecular library.

193 lines 9.65 kB
"use strict"; /** * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.parse = exports.parseFile = exports.getCcp4DataOffset = exports.getCcp4ValueType = exports.readCcp4Slices = exports.readCcp4Header = void 0; var tslib_1 = require("tslib"); var mol_task_1 = require("../../../mol-task"); var result_1 = require("../result"); var file_handle_1 = require("../../common/file-handle"); var simple_buffer_1 = require("../../../mol-io/common/simple-buffer"); var typed_array_1 = require("../../../mol-io/common/typed-array"); function readCcp4Header(file) { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { var headerSize, buffer, MAP, MACHST, littleEndian, modeLE, readInt, readFloat, header; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: headerSize = 1024; return [4 /*yield*/, file.readBuffer(0, headerSize)]; case 1: buffer = (_a.sent()).buffer; MAP = String.fromCharCode(buffer.readUInt8(52 * 4), buffer.readUInt8(52 * 4 + 1), buffer.readUInt8(52 * 4 + 2), buffer.readUInt8(52 * 4 + 3)); if (MAP !== 'MAP ') { throw new Error('ccp4 format error, missing "MAP " string'); } MACHST = [buffer.readUInt8(53 * 4), buffer.readUInt8(53 * 4 + 1)]; littleEndian = false; if (MACHST[0] === 68 && MACHST[1] === 65) { littleEndian = true; } else if (MACHST[0] === 17 && MACHST[1] === 17) { littleEndian = false; } else { modeLE = buffer.readInt32LE(3 * 4); if (modeLE <= 16) littleEndian = true; } readInt = littleEndian ? function (o) { return buffer.readInt32LE(o * 4); } : function (o) { return buffer.readInt32BE(o * 4); }; readFloat = littleEndian ? function (o) { return buffer.readFloatLE(o * 4); } : function (o) { return buffer.readFloatBE(o * 4); }; header = { NC: readInt(0), NR: readInt(1), NS: readInt(2), MODE: readInt(3), NCSTART: readInt(4), NRSTART: readInt(5), NSSTART: readInt(6), NX: readInt(7), NY: readInt(8), NZ: readInt(9), xLength: readFloat(10), yLength: readFloat(11), zLength: readFloat(12), alpha: readFloat(13), beta: readFloat(14), gamma: readFloat(15), MAPC: readInt(16), MAPR: readInt(17), MAPS: readInt(18), AMIN: readFloat(19), AMAX: readFloat(20), AMEAN: readFloat(21), ISPG: readInt(22), NSYMBT: readInt(23), LSKFLG: readInt(24), SKWMAT: [], SKWTRN: [], userFlag1: readInt(39), userFlag2: readInt(40), // bytes 50-52 origin in X,Y,Z used for transforms originX: readFloat(49), originY: readFloat(50), originZ: readFloat(51), MAP: MAP, MACHST: MACHST, ARMS: readFloat(54), // TODO bytes 56 NLABL // TODO bytes 57-256 LABEL }; return [2 /*return*/, { header: header, littleEndian: littleEndian }]; } }); }); } exports.readCcp4Header = readCcp4Header; function readCcp4Slices(header, buffer, file, byteOffset, length, littleEndian) { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { var valueByteOffset, int8, b1, b0, j, jl; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: if (!isMapmode2to0(header)) return [3 /*break*/, 2]; valueByteOffset = 3 * length; // read int8 data to last quarter of the read buffer return [4 /*yield*/, file.readBuffer(byteOffset, buffer.readBuffer, length, valueByteOffset)]; case 1: // read int8 data to last quarter of the read buffer _a.sent(); int8 = new Int8Array(buffer.valuesBuffer.buffer, valueByteOffset); b1 = (header.AMAX - header.AMIN) / 255.0; b0 = 0.5 * (header.AMIN + header.AMAX + b1); for (j = 0, jl = length; j < jl; ++j) { buffer.values[j] = b1 * int8[j] + b0; } return [3 /*break*/, 4]; case 2: return [4 /*yield*/, (0, typed_array_1.readTypedArray)(buffer, file, byteOffset, length, 0, littleEndian)]; case 3: _a.sent(); _a.label = 4; case 4: return [2 /*return*/]; } }); }); } exports.readCcp4Slices = readCcp4Slices; function getCcp4DataType(mode) { switch (mode) { case 0: return typed_array_1.TypedArrayValueType.Int8; case 1: return typed_array_1.TypedArrayValueType.Int16; case 2: return typed_array_1.TypedArrayValueType.Float32; case 3: throw new Error('mode 3 unsupported, complex 16-bit integers'); case 4: throw new Error('mode 4 unsupported, complex 32-bit reals'); case 6: typed_array_1.TypedArrayValueType.Uint16; case 16: throw new Error('mode 16 unsupported, unsigned char * 3 (for rgb data, non-standard)'); } throw new Error("unknown mode '" + mode + "'"); } /** check if the file was converted by mapmode2to0, see https://github.com/uglymol/uglymol */ function isMapmode2to0(header) { return header.userFlag1 === -128 && header.userFlag2 === 127; } function getCcp4ValueType(header) { return isMapmode2to0(header) ? typed_array_1.TypedArrayValueType.Float32 : getCcp4DataType(header.MODE); } exports.getCcp4ValueType = getCcp4ValueType; function getCcp4DataOffset(header) { return 256 * 4 + header.NSYMBT; } exports.getCcp4DataOffset = getCcp4DataOffset; function parseInternal(file, size, ctx) { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { var _a, header, littleEndian, offset, dataType, valueType, count, elementByteSize, byteCount, buffer, result; return (0, tslib_1.__generator)(this, function (_b) { switch (_b.label) { case 0: return [4 /*yield*/, ctx.update({ message: 'Parsing CCP4/MRC/MAP file...' })]; case 1: _b.sent(); return [4 /*yield*/, readCcp4Header(file)]; case 2: _a = _b.sent(), header = _a.header, littleEndian = _a.littleEndian; offset = getCcp4DataOffset(header); dataType = getCcp4DataType(header.MODE); valueType = getCcp4ValueType(header); count = header.NC * header.NR * header.NS; elementByteSize = (0, typed_array_1.getElementByteSize)(dataType); byteCount = count * elementByteSize; buffer = (0, typed_array_1.createTypedArrayBufferContext)(count, valueType); readCcp4Slices(header, buffer, file, offset, byteCount, littleEndian); result = { header: header, values: buffer.values, name: file.name }; return [2 /*return*/, result]; } }); }); } function parseFile(file, size) { var _this = this; return mol_task_1.Task.create('Parse CCP4/MRC/MAP', function (ctx) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () { var _a, _b, e_1; return (0, tslib_1.__generator)(this, function (_c) { switch (_c.label) { case 0: _c.trys.push([0, 2, , 3]); _b = (_a = result_1.ReaderResult).success; return [4 /*yield*/, parseInternal(file, size, ctx)]; case 1: return [2 /*return*/, _b.apply(_a, [_c.sent()])]; case 2: e_1 = _c.sent(); return [2 /*return*/, result_1.ReaderResult.error(e_1)]; case 3: return [2 /*return*/]; } }); }); }); } exports.parseFile = parseFile; function parse(buffer, name) { return parseFile(file_handle_1.FileHandle.fromBuffer(simple_buffer_1.SimpleBuffer.fromUint8Array(buffer), name), buffer.length); } exports.parse = parse; //# sourceMappingURL=parser.js.map