molstar
Version:
A comprehensive macromolecular library.
377 lines • 19.4 kB
JavaScript
"use strict";
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.abortingObserver = exports.resolveJob = void 0;
var tslib_1 = require("tslib");
var path = (0, tslib_1.__importStar)(require("path"));
var cif_1 = require("../../../mol-io/writer/cif");
var structure_1 = require("../../../mol-model/structure");
var mmcif_1 = require("../../../mol-model/structure/export/mmcif");
var console_logger_1 = require("../../../mol-util/console-logger");
var now_1 = require("../../../mol-util/now");
var performance_monitor_1 = require("../../../mol-util/performance-monitor");
var config_1 = require("../config");
var property_provider_1 = require("../property-provider");
var version_1 = require("../version");
var structure_wrapper_1 = require("./structure-wrapper");
var CifField = cif_1.CifWriter.Field;
var string_1 = require("../../../mol-util/string");
var chem_comp_1 = require("../../../mol-model-formats/structure/property/bonds/chem_comp");
var sdf_1 = require("../../../mol-io/writer/sdf");
var mol_1 = require("../../../mol-io/writer/mol");
var mol2_1 = require("../../../mol-io/writer/mol2");
var encoder_1 = require("../../../mol-io/writer/mol/encoder");
var encoder_2 = require("../../../mol-io/writer/mol2/encoder");
var chem_comp_2 = require("../../../mol-model-formats/structure/property/atoms/chem_comp");
var linear_algebra_1 = require("../../../mol-math/linear-algebra");
var global_transform_1 = require("../../../mol-model/structure/model/properties/global-transform");
var perf = new performance_monitor_1.PerformanceMonitor();
var _propertyProvider;
function propertyProvider() {
if (_propertyProvider)
return _propertyProvider;
_propertyProvider = (0, property_provider_1.createModelPropertiesProviderFromConfig)() || (function () { return []; });
return _propertyProvider;
}
function resolveJob(job) {
return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
return (0, tslib_1.__generator)(this, function (_a) {
if (job.responseFormat.tarball) {
return [2 /*return*/, resolveMultiFile(job)];
}
else {
return [2 /*return*/, resolveSingleFile(job)];
}
return [2 /*return*/];
});
});
}
exports.resolveJob = resolveJob;
var SharedParams = {
encoderName: "ModelServer " + version_1.VERSION
};
var SharedLigandWritingParams = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, SharedParams), { hydrogens: true });
function createEncoder(job) {
switch (job.responseFormat.encoding) {
case 'bcif':
return cif_1.CifWriter.createEncoder((0, tslib_1.__assign)((0, tslib_1.__assign)({}, SharedParams), { binary: true, binaryAutoClassifyEncoding: true }));
case 'sdf':
ensureCompatibleQueryType(job);
return sdf_1.SdfWriter.createEncoder((0, tslib_1.__assign)({}, SharedLigandWritingParams));
case 'mol':
ensureCompatibleQueryType(job);
return mol_1.MolWriter.createEncoder((0, tslib_1.__assign)({}, SharedLigandWritingParams));
case 'mol2':
ensureCompatibleQueryType(job);
return mol2_1.Mol2Writer.createEncoder((0, tslib_1.__assign)({}, SharedLigandWritingParams));
default:
return cif_1.CifWriter.createEncoder((0, tslib_1.__assign)((0, tslib_1.__assign)({}, SharedParams), { binary: false, binaryAutoClassifyEncoding: true }));
}
}
function ensureCompatibleQueryType(job) {
job.entries.forEach(function (e) {
if (e.queryDefinition.niceName !== 'Ligand') {
throw Error("sdf, mol and mol2 encoding are only available for queries of type 'Ligand'");
}
});
}
function resolveSingleFile(job) {
return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
var encoder, headerMap, _i, _a, entry, hasDataBlock, structure, header, i, e_1;
return (0, tslib_1.__generator)(this, function (_b) {
switch (_b.label) {
case 0:
console_logger_1.ConsoleLogger.logId(job.id, 'Query', "Starting (format: " + job.responseFormat.encoding + ").");
encoder = createEncoder(job);
headerMap = new Map();
_i = 0, _a = job.entries;
_b.label = 1;
case 1:
if (!(_i < _a.length)) return [3 /*break*/, 7];
entry = _a[_i];
hasDataBlock = false;
_b.label = 2;
case 2:
_b.trys.push([2, 5, , 6]);
return [4 /*yield*/, (0, structure_wrapper_1.createStructureWrapperFromJobEntry)(entry, propertyProvider())];
case 3:
structure = _b.sent();
header = structure.cifFrame.header.toUpperCase();
if (headerMap.has(header)) {
i = headerMap.get(header) + 1;
headerMap.set(header, i);
header += ' ' + i;
}
else {
headerMap.set(header, 0);
}
encoder.startDataBlock(header);
hasDataBlock = true;
return [4 /*yield*/, resolveJobEntry(entry, structure, encoder)];
case 4:
_b.sent();
return [3 /*break*/, 6];
case 5:
e_1 = _b.sent();
if (job.entries.length === 1) {
throw e_1;
}
else {
if (!hasDataBlock) {
createErrorDataBlock(entry, encoder);
}
doError(entry, encoder, e_1);
console_logger_1.ConsoleLogger.errorId(entry.job.id, '' + e_1);
}
return [3 /*break*/, 6];
case 6:
_i++;
return [3 /*break*/, 1];
case 7:
console_logger_1.ConsoleLogger.logId(job.id, 'Query', 'Encoding.');
encoder.encode();
encoder.writeTo(job.writer);
return [2 /*return*/];
}
});
});
}
function getFilename(i, entry, header, encoding) {
return i + "_" + header.toLowerCase() + "_" + (0, string_1.splitCamelCase)(entry.queryDefinition.name.replace(/\s/g, '_'), '-').toLowerCase() + "." + encoding;
}
function resolveMultiFile(job) {
return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
var i, _i, _a, entry, encoder, hasDataBlock, header, structure, e_2;
return (0, tslib_1.__generator)(this, function (_b) {
switch (_b.label) {
case 0:
console_logger_1.ConsoleLogger.logId(job.id, 'Query', 'Starting.');
i = 0;
_i = 0, _a = job.entries;
_b.label = 1;
case 1:
if (!(_i < _a.length)) return [3 /*break*/, 8];
entry = _a[_i];
encoder = createEncoder(job);
hasDataBlock = false;
header = '';
_b.label = 2;
case 2:
_b.trys.push([2, 5, , 6]);
return [4 /*yield*/, (0, structure_wrapper_1.createStructureWrapperFromJobEntry)(entry, propertyProvider())];
case 3:
structure = _b.sent();
header = structure.cifFrame.header;
encoder.startDataBlock(structure.cifFrame.header);
hasDataBlock = true;
return [4 /*yield*/, resolveJobEntry(entry, structure, encoder)];
case 4:
_b.sent();
return [3 /*break*/, 6];
case 5:
e_2 = _b.sent();
if (!hasDataBlock) {
header = createErrorDataBlock(entry, encoder);
}
console_logger_1.ConsoleLogger.errorId(entry.job.id, '' + e_2);
doError(entry, encoder, e_2);
return [3 /*break*/, 6];
case 6:
console_logger_1.ConsoleLogger.logId(job.id, 'Query', "Encoding " + entry.key + "/" + entry.queryDefinition.name);
encoder.encode();
job.writer.beginEntry(getFilename(++i, entry, header, job.responseFormat.encoding), encoder.getSize());
encoder.writeTo(job.writer);
job.writer.endEntry();
console_logger_1.ConsoleLogger.logId(job.id, 'Query', "Written " + entry.key + "/" + entry.queryDefinition.name);
_b.label = 7;
case 7:
_i++;
return [3 /*break*/, 1];
case 8: return [2 /*return*/];
}
});
});
}
function createErrorDataBlock(job, encoder) {
var header;
if (job.sourceId === '_local_')
header = path.basename(job.entryId).replace(/[^a-z0-9\-]/gi, '').toUpperCase();
else
header = job.entryId.replace(/[^a-z0-9\-]/gi, '').toUpperCase();
encoder.startDataBlock(header);
return header;
}
function resolveJobEntry(entry, structure, encoder) {
return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
var sourceStructures, structures, _i, sourceStructures_1, s, _a, _b, modelNums_1, queries, result, i, s, stats, e_3;
return (0, tslib_1.__generator)(this, function (_c) {
switch (_c.label) {
case 0:
console_logger_1.ConsoleLogger.logId(entry.job.id, 'Query', "Start " + entry.key + "/" + entry.queryDefinition.name + ".");
_c.label = 1;
case 1:
_c.trys.push([1, 7, 8, 9]);
perf.start('query');
return [4 /*yield*/, (0, structure_wrapper_1.resolveStructures)(structure, entry.modelNums)];
case 2:
sourceStructures = _c.sent();
if (!sourceStructures.length)
throw new Error('Model not available');
structures = sourceStructures;
if (!entry.queryDefinition.structureTransform) return [3 /*break*/, 6];
structures = [];
_i = 0, sourceStructures_1 = sourceStructures;
_c.label = 3;
case 3:
if (!(_i < sourceStructures_1.length)) return [3 /*break*/, 6];
s = sourceStructures_1[_i];
_b = (_a = structures).push;
return [4 /*yield*/, entry.queryDefinition.structureTransform(entry.normalizedParams, s)];
case 4:
_b.apply(_a, [_c.sent()]);
_c.label = 5;
case 5:
_i++;
return [3 /*break*/, 3];
case 6:
modelNums_1 = entry.modelNums || structure.models.map(function (m) { return m.modelNum; });
queries = structures.map(function (s) { return entry.queryDefinition.query(entry.normalizedParams, s, modelNums_1); });
result = [];
for (i = 0; i < structures.length; i++) {
s = structure_1.StructureSelection.unionStructure(structure_1.StructureQuery.run(queries[i], structures[i], { timeoutMs: config_1.ModelServerConfig.queryTimeoutMs }));
if (s.elementCount > 0) {
if (!entry.transform || linear_algebra_1.Mat4.isIdentity(entry.transform)) {
result.push(s);
}
else {
result.push(structure_1.Structure.transform(s, entry.transform));
}
}
}
perf.end('query');
console_logger_1.ConsoleLogger.logId(entry.job.id, 'Query', "Queried " + entry.key + "/" + entry.queryDefinition.name + ".");
perf.start('encode');
encoder.binaryEncodingProvider = getEncodingProvider(structure);
// TODO: this actually needs to "reversible" in case of error.
encoder.writeCategory(_model_server_result, entry);
encoder.writeCategory(_model_server_params, entry);
if (entry.queryDefinition.niceName === 'Ligand') {
if (encoder instanceof encoder_1.MolEncoder) {
encoder.setComponentAtomData(chem_comp_2.ComponentAtom.Provider.get(structure.models[0]));
}
if (encoder instanceof encoder_1.MolEncoder || encoder instanceof encoder_2.Mol2Encoder) {
encoder.setComponentBondData(chem_comp_1.ComponentBond.Provider.get(structure.models[0]));
}
}
// TODO propagate data for cif/bcif as well?
if (!entry.copyAllCategories && entry.queryDefinition.filter)
encoder.setFilter(entry.queryDefinition.filter);
if (result.length > 0)
(0, mmcif_1.encode_mmCIF_categories)(encoder, result, { copyAllCategories: entry.copyAllCategories });
else
console_logger_1.ConsoleLogger.logId(entry.job.id, 'Warning', "Empty result for Query " + entry.key + "/" + entry.queryDefinition.name);
if (entry.transform && !linear_algebra_1.Mat4.isIdentity(entry.transform))
global_transform_1.GlobalModelTransformInfo.writeMmCif(encoder, entry.transform);
if (!entry.copyAllCategories && entry.queryDefinition.filter)
encoder.setFilter();
perf.end('encode');
stats = {
structure: structure,
queryTimeMs: perf.time('query'),
encodeTimeMs: perf.time('encode'),
resultSize: result.reduce(function (n, s) { return n + s.elementCount; }, 0)
};
encoder.writeCategory(_model_server_stats, stats);
console_logger_1.ConsoleLogger.logId(entry.job.id, 'Query', "Written " + entry.key + "/" + entry.queryDefinition.name + ".");
return [2 /*return*/, encoder];
case 7:
e_3 = _c.sent();
console_logger_1.ConsoleLogger.errorId(entry.job.id, e_3);
doError(entry, encoder, e_3);
return [3 /*break*/, 9];
case 8:
encoder.binaryEncodingProvider = void 0;
return [7 /*endfinally*/];
case 9: return [2 /*return*/];
}
});
});
}
function getEncodingProvider(structure) {
if (!structure.isBinary)
return void 0;
return cif_1.CifWriter.createEncodingProviderFromCifFrame(structure.cifFrame);
}
function doError(entry, encoder, e) {
encoder.writeCategory(_model_server_result, entry);
encoder.writeCategory(_model_server_params, entry);
encoder.writeCategory(_model_server_error, '' + e);
}
var maxTime = config_1.ModelServerConfig.queryTimeoutMs;
function abortingObserver(p) {
if ((0, now_1.now)() - p.root.progress.startedTime > maxTime) {
p.requestAbort("Exceeded maximum allowed time for a query (" + maxTime + "ms)");
}
}
exports.abortingObserver = abortingObserver;
function string(name, str, isSpecified) {
if (isSpecified) {
return CifField.str(name, function (i, d) { return str(d, i); }, { valueKind: function (i, d) { return isSpecified(d) ? 0 /* Present */ : 1 /* NotPresent */; } });
}
return CifField.str(name, function (i, d) { return str(d, i); });
}
function int32(name, value) {
return CifField.int(name, function (i, d) { return value(d); });
}
var _model_server_result_fields = [
string('job_id', function (ctx) { return '' + ctx.job.id; }),
string('datetime_utc', function (ctx) { return ctx.job.datetime_utc; }),
string('server_version', function (ctx) { return version_1.VERSION; }),
string('query_name', function (ctx) { return ctx.queryDefinition.name; }),
string('source_id', function (ctx) { return ctx.sourceId; }),
string('entry_id', function (ctx) { return ctx.entryId; }),
];
var _model_server_params_fields = [
string('name', function (ctx, i) { return ctx[i][0]; }),
string('value', function (ctx, i) { return ctx[i][1]; })
];
var _model_server_error_fields = [
string('message', function (ctx, i) { return ctx; })
];
var _model_server_stats_fields = [
int32('io_time_ms', function (ctx) { return ctx.structure.info.readTime | 0; }),
int32('parse_time_ms', function (ctx) { return ctx.structure.info.parseTime | 0; }),
// int32<Stats>('attach_props_time_ms', ctx => ctx.structure.info.attachPropsTime | 0),
int32('create_model_time_ms', function (ctx) { return ctx.structure.info.createModelTime | 0; }),
int32('query_time_ms', function (ctx) { return ctx.queryTimeMs | 0; }),
int32('encode_time_ms', function (ctx) { return ctx.encodeTimeMs | 0; }),
int32('element_count', function (ctx) { return ctx.resultSize | 0; }),
];
var _model_server_result = {
name: 'model_server_result',
instance: function (job) { return cif_1.CifWriter.categoryInstance(_model_server_result_fields, { data: job, rowCount: 1 }); }
};
var _model_server_error = {
name: 'model_server_error',
instance: function (message) { return cif_1.CifWriter.categoryInstance(_model_server_error_fields, { data: message, rowCount: 1 }); }
};
var _model_server_params = {
name: 'model_server_params',
instance: function (job) {
var params = [];
for (var _i = 0, _a = Object.keys(job.normalizedParams); _i < _a.length; _i++) {
var k = _a[_i];
params.push([k, JSON.stringify(job.normalizedParams[k])]);
}
return cif_1.CifWriter.categoryInstance(_model_server_params_fields, { data: params, rowCount: params.length });
}
};
var _model_server_stats = {
name: 'model_server_stats',
instance: function (stats) { return cif_1.CifWriter.categoryInstance(_model_server_stats_fields, { data: stats, rowCount: 1 }); }
};
//# sourceMappingURL=query.js.map