molstar
Version:
A comprehensive macromolecular library.
373 lines • 21.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SequenceView = void 0;
var tslib_1 = require("tslib");
var jsx_runtime_1 = require("react/jsx-runtime");
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
*/
var React = (0, tslib_1.__importStar)(require("react"));
var base_1 = require("./base");
var objects_1 = require("../mol-plugin-state/objects");
var sequence_1 = require("./sequence/sequence");
var structure_1 = require("../mol-model/structure");
var polymer_1 = require("./sequence/polymer");
var marker_action_1 = require("../mol-util/marker-action");
var parameters_1 = require("./controls/parameters");
var param_definition_1 = require("../mol-util/param-definition");
var hetero_1 = require("./sequence/hetero");
var mol_state_1 = require("../mol-state");
var chain_1 = require("./sequence/chain");
var element_1 = require("./sequence/element");
var label_1 = require("../mol-theme/label");
var icons_1 = require("./controls/icons");
var array_1 = require("../mol-util/array");
var MaxDisplaySequenceLength = 5000;
function opKey(l) {
var ids = structure_1.StructureProperties.unit.pdbx_struct_oper_list_ids(l);
var ncs = structure_1.StructureProperties.unit.struct_ncs_oper_id(l);
var hkl = structure_1.StructureProperties.unit.hkl(l);
var spgrOp = structure_1.StructureProperties.unit.spgrOp(l);
return ids.sort().join(',') + "|" + ncs + "|" + hkl + "|" + spgrOp;
}
function splitModelEntityId(modelEntityId) {
var _a = modelEntityId.split('|'), modelIdx = _a[0], entityId = _a[1];
return [parseInt(modelIdx), entityId];
}
function getSequenceWrapper(state, structureSelection) {
var structure = state.structure, modelEntityId = state.modelEntityId, chainGroupId = state.chainGroupId, operatorKey = state.operatorKey;
var l = structure_1.StructureElement.Location.create(structure);
var _a = splitModelEntityId(modelEntityId), modelIdx = _a[0], entityId = _a[1];
var units = [];
for (var _i = 0, _b = structure.units; _i < _b.length; _i++) {
var unit = _b[_i];
structure_1.StructureElement.Location.set(l, structure, unit, unit.elements[0]);
if (structure.getModelIndex(unit.model) !== modelIdx)
continue;
if (structure_1.StructureProperties.entity.id(l) !== entityId)
continue;
if (unit.chainGroupId !== chainGroupId)
continue;
if (opKey(l) !== operatorKey)
continue;
units.push(unit);
}
if (units.length > 0) {
var data = { structure: structure, units: units };
var unit = units[0];
var sw = void 0;
if (unit.polymerElements.length) {
var l_1 = structure_1.StructureElement.Location.create(structure, unit, unit.elements[0]);
var entitySeq = unit.model.sequence.byEntityKey[structure_1.StructureProperties.entity.key(l_1)];
// check if entity sequence is available
if (entitySeq && entitySeq.sequence.length <= MaxDisplaySequenceLength) {
sw = new polymer_1.PolymerSequenceWrapper(data);
}
else {
var polymerElementCount = units.reduce(function (a, v) { return a + v.polymerElements.length; }, 0);
if (structure_1.Unit.isAtomic(unit) || polymerElementCount > MaxDisplaySequenceLength) {
sw = new chain_1.ChainSequenceWrapper(data);
}
else {
sw = new element_1.ElementSequenceWrapper(data);
}
}
}
else if (structure_1.Unit.isAtomic(unit)) {
var residueCount = units.reduce(function (a, v) { return a + v.residueCount; }, 0);
if (residueCount > MaxDisplaySequenceLength) {
sw = new chain_1.ChainSequenceWrapper(data);
}
else {
sw = new hetero_1.HeteroSequenceWrapper(data);
}
}
else {
console.warn('should not happen, expecting coarse units to be polymeric');
sw = new chain_1.ChainSequenceWrapper(data);
}
sw.markResidue(structureSelection.getLoci(structure), marker_action_1.MarkerAction.Select);
return sw;
}
else {
return 'No sequence available';
}
}
function getModelEntityOptions(structure, polymersOnly) {
if (polymersOnly === void 0) { polymersOnly = false; }
var options = [];
var l = structure_1.StructureElement.Location.create(structure);
var seen = new Set();
for (var _i = 0, _a = structure.units; _i < _a.length; _i++) {
var unit = _a[_i];
structure_1.StructureElement.Location.set(l, structure, unit, unit.elements[0]);
var id = structure_1.StructureProperties.entity.id(l);
var modelIdx = structure.getModelIndex(unit.model);
var key = modelIdx + "|" + id;
if (seen.has(key))
continue;
if (polymersOnly && structure_1.StructureProperties.entity.type(l) !== 'polymer')
continue;
var description = structure_1.StructureProperties.entity.pdbx_description(l).join(', ');
if (structure.models.length) {
if (structure.representativeModel) { // indicates model trajectory
description += " (Model " + structure.models[modelIdx].modelNum + ")";
}
else if (description.startsWith('Polymer ')) { // indicates generic entity name
description += " (" + structure.models[modelIdx].entry + ")";
}
}
var label = id + ": " + description;
options.push([key, label]);
seen.add(key);
}
if (options.length === 0)
options.push(['', 'No entities']);
return options;
}
function getChainOptions(structure, modelEntityId) {
var options = [];
var l = structure_1.StructureElement.Location.create(structure);
var seen = new Set();
var _a = splitModelEntityId(modelEntityId), modelIdx = _a[0], entityId = _a[1];
for (var _i = 0, _b = structure.units; _i < _b.length; _i++) {
var unit = _b[_i];
structure_1.StructureElement.Location.set(l, structure, unit, unit.elements[0]);
if (structure.getModelIndex(unit.model) !== modelIdx)
continue;
if (structure_1.StructureProperties.entity.id(l) !== entityId)
continue;
var id = unit.chainGroupId;
if (seen.has(id))
continue;
// TODO handle special case
// - more than one chain in a unit
var label = (0, label_1.elementLabel)(l, { granularity: 'chain', hidePrefix: true, htmlStyling: false });
options.push([id, label]);
seen.add(id);
}
if (options.length === 0)
options.push([-1, 'No units']);
return options;
}
function getOperatorOptions(structure, modelEntityId, chainGroupId) {
var options = [];
var l = structure_1.StructureElement.Location.create(structure);
var seen = new Set();
var _a = splitModelEntityId(modelEntityId), modelIdx = _a[0], entityId = _a[1];
for (var _i = 0, _b = structure.units; _i < _b.length; _i++) {
var unit = _b[_i];
structure_1.StructureElement.Location.set(l, structure, unit, unit.elements[0]);
if (structure.getModelIndex(unit.model) !== modelIdx)
continue;
if (structure_1.StructureProperties.entity.id(l) !== entityId)
continue;
if (unit.chainGroupId !== chainGroupId)
continue;
var id = opKey(l);
if (seen.has(id))
continue;
var label = unit.conformation.operator.name;
options.push([id, label]);
seen.add(id);
}
if (options.length === 0)
options.push(['', 'No operators']);
return options;
}
function getStructureOptions(state) {
var _a;
var options = [];
var all = [];
var structures = state.select(mol_state_1.StateSelection.Generators.rootsOfType(objects_1.PluginStateObject.Molecule.Structure));
for (var _i = 0, structures_1 = structures; _i < structures_1.length; _i++) {
var s = structures_1[_i];
if (!((_a = s.obj) === null || _a === void 0 ? void 0 : _a.data))
continue;
all.push(s.obj.data);
options.push([s.transform.ref, s.obj.data.label]);
}
if (options.length === 0)
options.push(['', 'No structure']);
return { options: options, all: all };
}
var SequenceViewModeParam = param_definition_1.ParamDefinition.Select('single', [['single', 'Chain'], ['polymers', 'Polymers'], ['all', 'Everything']]);
var SequenceView = /** @class */ (function (_super) {
(0, tslib_1.__extends)(SequenceView, _super);
function SequenceView() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { structureOptions: { options: [], all: [] }, structure: structure_1.Structure.Empty, structureRef: '', modelEntityId: '', chainGroupId: -1, operatorKey: '', mode: 'single' };
_this.setParamProps = function (p) {
var state = (0, tslib_1.__assign)({}, _this.state);
switch (p.name) {
case 'mode':
state.mode = p.value;
if (_this.state.mode === state.mode)
return;
if (state.mode === 'all' || state.mode === 'polymers') {
break;
}
case 'structure':
if (p.name === 'structure')
state.structureRef = p.value;
state.structure = _this.getStructure(state.structureRef);
state.modelEntityId = getModelEntityOptions(state.structure)[0][0];
state.chainGroupId = getChainOptions(state.structure, state.modelEntityId)[0][0];
state.operatorKey = getOperatorOptions(state.structure, state.modelEntityId, state.chainGroupId)[0][0];
break;
case 'entity':
state.modelEntityId = p.value;
state.chainGroupId = getChainOptions(state.structure, state.modelEntityId)[0][0];
state.operatorKey = getOperatorOptions(state.structure, state.modelEntityId, state.chainGroupId)[0][0];
break;
case 'chain':
state.chainGroupId = p.value;
state.operatorKey = getOperatorOptions(state.structure, state.modelEntityId, state.chainGroupId)[0][0];
break;
case 'operator':
state.operatorKey = p.value;
break;
}
_this.setState(state);
};
return _this;
}
SequenceView.prototype.componentDidMount = function () {
var _this = this;
if (this.plugin.state.data.select(mol_state_1.StateSelection.Generators.rootsOfType(objects_1.PluginStateObject.Molecule.Structure)).length > 0)
this.setState(this.getInitialState());
this.subscribe(this.plugin.state.events.object.updated, function (_a) {
var ref = _a.ref, obj = _a.obj;
if (ref === _this.state.structureRef && obj && obj.type === objects_1.PluginStateObject.Molecule.Structure.type && obj.data !== _this.state.structure) {
_this.sync();
}
});
this.subscribe(this.plugin.state.events.object.created, function (_a) {
var obj = _a.obj;
if (obj && obj.type === objects_1.PluginStateObject.Molecule.Structure.type) {
_this.sync();
}
});
this.subscribe(this.plugin.state.events.object.removed, function (_a) {
var obj = _a.obj;
if (obj && obj.type === objects_1.PluginStateObject.Molecule.Structure.type && obj.data === _this.state.structure) {
_this.sync();
}
});
};
SequenceView.prototype.sync = function () {
var structureOptions = getStructureOptions(this.plugin.state.data);
if ((0, array_1.arrayEqual)(structureOptions.all, this.state.structureOptions.all))
return;
this.setState(this.getInitialState());
};
SequenceView.prototype.getStructure = function (ref) {
var state = this.plugin.state.data;
var cell = state.select(ref)[0];
if (!ref || !cell || !cell.obj)
return structure_1.Structure.Empty;
return cell.obj.data;
};
SequenceView.prototype.getSequenceWrapper = function (params) {
return {
wrapper: getSequenceWrapper(this.state, this.plugin.managers.structure.selection),
label: param_definition_1.ParamDefinition.optionLabel(params.chain, this.state.chainGroupId) + " | " + param_definition_1.ParamDefinition.optionLabel(params.entity, this.state.modelEntityId)
};
};
SequenceView.prototype.getSequenceWrappers = function (params) {
if (this.state.mode === 'single')
return [this.getSequenceWrapper(params)];
var structure = this.getStructure(this.state.structureRef);
var wrappers = [];
for (var _i = 0, _a = getModelEntityOptions(structure, this.state.mode === 'polymers'); _i < _a.length; _i++) {
var _b = _a[_i], modelEntityId = _b[0], eLabel = _b[1];
for (var _c = 0, _d = getChainOptions(structure, modelEntityId); _c < _d.length; _c++) {
var _e = _d[_c], chainGroupId = _e[0], cLabel = _e[1];
for (var _f = 0, _g = getOperatorOptions(structure, modelEntityId, chainGroupId); _f < _g.length; _f++) {
var operatorKey = _g[_f][0];
wrappers.push({
wrapper: getSequenceWrapper({
structure: structure,
modelEntityId: modelEntityId,
chainGroupId: chainGroupId,
operatorKey: operatorKey
}, this.plugin.managers.structure.selection),
label: cLabel + " | " + eLabel
});
}
}
}
return wrappers;
};
SequenceView.prototype.getInitialState = function () {
var _a;
var structureOptions = getStructureOptions(this.plugin.state.data);
var structureRef = structureOptions.options[0][0];
var structure = this.getStructure(structureRef);
var modelEntityId = getModelEntityOptions(structure)[0][0];
var chainGroupId = getChainOptions(structure, modelEntityId)[0][0];
var operatorKey = getOperatorOptions(structure, modelEntityId, chainGroupId)[0][0];
if (this.state.structure && this.state.structure === structure) {
modelEntityId = this.state.modelEntityId;
chainGroupId = this.state.chainGroupId;
operatorKey = this.state.operatorKey;
}
return { structureOptions: structureOptions, structure: structure, structureRef: structureRef, modelEntityId: modelEntityId, chainGroupId: chainGroupId, operatorKey: operatorKey, mode: (_a = this.props.defaultMode) !== null && _a !== void 0 ? _a : 'single' };
};
Object.defineProperty(SequenceView.prototype, "params", {
get: function () {
var _a = this.state, structureOptions = _a.structureOptions, structure = _a.structure, modelEntityId = _a.modelEntityId, chainGroupId = _a.chainGroupId;
var entityOptions = getModelEntityOptions(structure);
var chainOptions = getChainOptions(structure, modelEntityId);
var operatorOptions = getOperatorOptions(structure, modelEntityId, chainGroupId);
return {
structure: param_definition_1.ParamDefinition.Select(structureOptions.options[0][0], structureOptions.options, { shortLabel: true }),
entity: param_definition_1.ParamDefinition.Select(entityOptions[0][0], entityOptions, { shortLabel: true }),
chain: param_definition_1.ParamDefinition.Select(chainOptions[0][0], chainOptions, { shortLabel: true, twoColumns: true, label: 'Chain' }),
operator: param_definition_1.ParamDefinition.Select(operatorOptions[0][0], operatorOptions, { shortLabel: true, twoColumns: true }),
mode: SequenceViewModeParam
};
},
enumerable: false,
configurable: true
});
Object.defineProperty(SequenceView.prototype, "values", {
get: function () {
return {
structure: this.state.structureRef,
entity: this.state.modelEntityId,
chain: this.state.chainGroupId,
operator: this.state.operatorKey,
mode: this.state.mode
};
},
enumerable: false,
configurable: true
});
SequenceView.prototype.render = function () {
if (this.getStructure(this.state.structureRef) === structure_1.Structure.Empty) {
return (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-sequence' }, { children: (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-sequence-select' }, { children: [(0, jsx_runtime_1.jsx)(icons_1.Icon, { svg: icons_1.HelpOutlineSvg, style: { cursor: 'help', position: 'absolute', right: 0, top: 0 }, title: 'Shows a sequence of one or more chains. Use the controls to alter selection.' }, void 0), (0, jsx_runtime_1.jsx)("span", { children: "Sequence" }, void 0), (0, jsx_runtime_1.jsx)("span", (0, tslib_1.__assign)({ style: { fontWeight: 'normal' } }, { children: "No structure available" }), void 0)] }), void 0) }), void 0);
}
var params = this.params;
var values = this.values;
var sequenceWrappers = this.getSequenceWrappers(params);
return (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-sequence' }, { children: [(0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-sequence-select' }, { children: [(0, jsx_runtime_1.jsx)(icons_1.Icon, { svg: icons_1.HelpOutlineSvg, style: { cursor: 'help', position: 'absolute', right: 0, top: 0 }, title: 'This shows a single sequence. Use the controls to show a different sequence.' }, void 0), (0, jsx_runtime_1.jsx)("span", { children: "Sequence of" }, void 0), (0, jsx_runtime_1.jsx)(parameters_1.PureSelectControl, { title: "[Structure] " + param_definition_1.ParamDefinition.optionLabel(params.structure, values.structure), param: params.structure, name: 'structure', value: values.structure, onChange: this.setParamProps }, void 0), (0, jsx_runtime_1.jsx)(parameters_1.PureSelectControl, { title: "[Mode]", param: SequenceViewModeParam, name: 'mode', value: values.mode, onChange: this.setParamProps }, void 0), values.mode === 'single' && (0, jsx_runtime_1.jsx)(parameters_1.PureSelectControl, { title: "[Entity] " + param_definition_1.ParamDefinition.optionLabel(params.entity, values.entity), param: params.entity, name: 'entity', value: values.entity, onChange: this.setParamProps }, void 0), values.mode === 'single' && (0, jsx_runtime_1.jsx)(parameters_1.PureSelectControl, { title: "[Chain] " + param_definition_1.ParamDefinition.optionLabel(params.chain, values.chain), param: params.chain, name: 'chain', value: values.chain, onChange: this.setParamProps }, void 0), params.operator.options.length > 1 && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(parameters_1.PureSelectControl, { title: "[Instance] " + param_definition_1.ParamDefinition.optionLabel(params.operator, values.operator), param: params.operator, name: 'operator', value: values.operator, onChange: this.setParamProps }, void 0) }, void 0)] }), void 0), (0, jsx_runtime_1.jsx)(NonEmptySequenceWrapper, { children: sequenceWrappers.map(function (s, i) {
var elem = typeof s.wrapper === 'string'
? (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-sequence-wrapper' }, { children: s.wrapper }), i)
: (0, jsx_runtime_1.jsx)(sequence_1.Sequence, { sequenceWrapper: s.wrapper }, i);
if (values.mode === 'single')
return elem;
return (0, jsx_runtime_1.jsxs)(React.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-sequence-chain-label' }, { children: s.label }), void 0), elem] }, i);
}) }, void 0)] }), void 0);
};
return SequenceView;
}(base_1.PluginUIComponent));
exports.SequenceView = SequenceView;
function NonEmptySequenceWrapper(_a) {
var children = _a.children;
return (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-sequence-wrapper-non-empty' }, { children: children }), void 0);
}
//# sourceMappingURL=sequence.js.map