molstar
Version:
A comprehensive macromolecular library.
193 lines • 9.65 kB
JavaScript
/**
* 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
;