UNPKG

molstar

Version:

A comprehensive macromolecular library.

149 lines (148 loc) 9.65 kB
"use strict"; /** * Copyright (c) 2023 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Sebastian Bittrich <sebastian.bittrich@rcsb.org> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ChemicalComponentPreset = exports.ChemicalCompontentTrajectoryHierarchyPreset = void 0; const param_definition_1 = require("../../../mol-util/param-definition"); const mol_state_1 = require("../../../mol-state"); const transforms_1 = require("../../../mol-plugin-state/transforms"); const representation_preset_1 = require("../../../mol-plugin-state/builder/structure/representation-preset"); const mmcif_1 = require("../../../mol-model-formats/structure/mmcif"); const minimize_rmsd_1 = require("../../../mol-math/linear-algebra/3d/minimize-rmsd"); const set_1 = require("../../../mol-util/set"); const hierarchy_preset_1 = require("../../../mol-plugin-state/builder/structure/hierarchy-preset"); const string_1 = require("../../../mol-util/string"); const CCDParams = (a, plugin) => ({ representationPresetParams: param_definition_1.ParamDefinition.Optional(param_definition_1.ParamDefinition.Group(representation_preset_1.StructureRepresentationPresetProvider.CommonParams)), showOriginalCoordinates: param_definition_1.ParamDefinition.Optional(param_definition_1.ParamDefinition.Boolean(true, { description: `Show original coordinates for 'model' and 'ideal' structure and do not align them.` })), shownCoordinateType: param_definition_1.ParamDefinition.Select('ideal', param_definition_1.ParamDefinition.arrayToOptions(['ideal', 'model', 'both']), { description: `What coordinate sets are visible.` }), aromaticBonds: param_definition_1.ParamDefinition.Boolean(false, { description: 'Display aromatic bonds with dashes' }), ...hierarchy_preset_1.TrajectoryHierarchyPresetProvider.CommonParams(a, plugin) }); exports.ChemicalCompontentTrajectoryHierarchyPreset = (0, hierarchy_preset_1.TrajectoryHierarchyPresetProvider)({ id: 'preset-trajectory-ccd', display: { name: 'Chemical Component', group: 'Preset', description: 'Shows molecules from the Chemical Component Dictionary.' }, isApplicable: o => { return mmcif_1.CCDFormat.is(o.data.representative.sourceData); }, params: CCDParams, async apply(trajectory, params, plugin) { var _a, _b; const tr = (_b = (_a = mol_state_1.StateObjectRef.resolveAndCheck(plugin.state.data, trajectory)) === null || _a === void 0 ? void 0 : _a.obj) === null || _b === void 0 ? void 0 : _b.data; if (!tr) return {}; const builder = plugin.builders.structure; const idealModel = await builder.createModel(trajectory, { modelIndex: 0 }); const idealModelProperties = await builder.insertModelProperties(idealModel, params.modelProperties, { isCollapsed: true }); const idealStructure = await builder.createStructure(idealModelProperties || idealModel, { name: 'model', params: {} }); const idealStructureProperties = await builder.insertStructureProperties(idealStructure, params.structureProperties); const representationPreset = params.representationPreset || exports.ChemicalComponentPreset.id; const representationPresetParams = params.representationPresetParams || {}; if (representationPresetParams.ignoreHydrogens === undefined) representationPresetParams.ignoreHydrogens = true; // degenerate case where either model or ideal coordinates are missing if (tr.frameCount !== 2) { const coordinateType = mmcif_1.CCDFormat.CoordinateType.get(idealModel.obj.data); await builder.representation.applyPreset(idealStructureProperties, representationPreset, { ...representationPresetParams, coordinateType }); return { models: [idealModel], structures: [idealStructure] }; } const modelModel = await builder.createModel(trajectory, { modelIndex: 1 }); const modelModelProperties = await builder.insertModelProperties(modelModel, params.modelProperties, { isCollapsed: true }); const modelStructure = await builder.createStructure(modelModelProperties || modelModel, { name: 'model', params: {} }); const modelStructureProperties = await builder.insertStructureProperties(modelStructure, params.structureProperties); // align ideal and model coordinates if (!params.showOriginalCoordinates) { const [a, b] = getPositionTables(idealStructure.obj.data, modelStructure.obj.data); if (!a) { plugin.log.warn(`Cannot align chemical components whose atom sets are disjoint.`); } else { const { bTransform, rmsd } = minimize_rmsd_1.MinimizeRmsd.compute({ a, b }); await transform(plugin, modelStructure.cell, bTransform); plugin.log.info(`Superposed [model] and [ideal] with RMSD ${rmsd.toFixed(2)}.`); } } await builder.representation.applyPreset(idealStructureProperties, representationPreset, { ...representationPresetParams, aromaticBonds: params.aromaticBonds, coordinateType: 'ideal', isHidden: params.shownCoordinateType === 'model' }); await builder.representation.applyPreset(modelStructureProperties, representationPreset, { ...representationPresetParams, aromaticBonds: params.aromaticBonds, coordinateType: 'model', isHidden: params.shownCoordinateType === 'ideal' }); return { models: [idealModel, modelModel], structures: [idealStructure, modelStructure] }; } }); function getPositionTables(s1, s2) { const m1 = getAtomIdSerialMap(s1); const m2 = getAtomIdSerialMap(s2); const intersecting = set_1.SetUtils.intersection(new Set(m1.keys()), new Set(m2.keys())); const ret = [ minimize_rmsd_1.MinimizeRmsd.Positions.empty(intersecting.size), minimize_rmsd_1.MinimizeRmsd.Positions.empty(intersecting.size) ]; let o = 0; intersecting.forEach(k => { ret[0].x[o] = s1.model.atomicConformation.x[m1.get(k)]; ret[0].y[o] = s1.model.atomicConformation.y[m1.get(k)]; ret[0].z[o] = s1.model.atomicConformation.z[m1.get(k)]; ret[1].x[o] = s2.model.atomicConformation.x[m2.get(k)]; ret[1].y[o] = s2.model.atomicConformation.y[m2.get(k)]; ret[1].z[o] = s2.model.atomicConformation.z[m2.get(k)]; o++; }); return ret; } function getAtomIdSerialMap(structure) { const map = new Map(); const { label_atom_id } = structure.model.atomicHierarchy.atoms; for (let i = 0, il = label_atom_id.rowCount; i < il; ++i) { const id = label_atom_id.value(i); if (!map.has(id)) map.set(id, map.size); } return map; } function transform(plugin, s, matrix) { const b = plugin.state.data.build().to(s) .insert(transforms_1.StateTransforms.Model.TransformStructureConformation, { transform: { name: 'matrix', params: { data: matrix, transpose: false } } }); return plugin.runTask(plugin.state.data.updateTree(b)); } exports.ChemicalComponentPreset = (0, representation_preset_1.StructureRepresentationPresetProvider)({ id: 'preset-structure-representation-chemical-component', display: { name: 'Chemical Component', group: 'Miscellaneous', description: `Show 'Ideal' and 'Model' coordinates of chemical components.` }, isApplicable: o => { return mmcif_1.CCDFormat.is(o.data.model.sourceData); }, params: () => ({ ...representation_preset_1.StructureRepresentationPresetProvider.CommonParams, aromaticBonds: param_definition_1.ParamDefinition.Boolean(true), coordinateType: param_definition_1.ParamDefinition.Select('ideal', param_definition_1.ParamDefinition.arrayToOptions(['ideal', 'model'])), isHidden: param_definition_1.ParamDefinition.Boolean(false), }), async apply(ref, params, plugin) { var _a, _b, _c, _d, _e, _f; const structureCell = mol_state_1.StateObjectRef.resolveAndCheck(plugin.state.data, ref); if (!structureCell) return {}; const { aromaticBonds, coordinateType, isHidden } = params; const components = { [coordinateType]: await (0, representation_preset_1.presetStaticComponent)(plugin, structureCell, 'all', { label: (0, string_1.capitalize)(coordinateType), tags: [coordinateType] }) }; const structure = structureCell.obj.data; const { update, builder, typeParams } = representation_preset_1.StructureRepresentationPresetProvider.reprBuilder(plugin, params); const representations = { [coordinateType]: builder.buildRepresentation(update, components[coordinateType], { type: 'ball-and-stick', typeParams: { ...typeParams, aromaticBonds } }, { initialState: { isHidden } }), }; // sync UI state if (((_b = (_a = components[coordinateType]) === null || _a === void 0 ? void 0 : _a.cell) === null || _b === void 0 ? void 0 : _b.state) && isHidden) { mol_state_1.StateTransform.assignState(components[coordinateType].cell.state, { isHidden }); } await update.commit({ revertOnError: true }); await representation_preset_1.StructureRepresentationPresetProvider.updateFocusRepr(plugin, structure, (_d = (_c = params.theme) === null || _c === void 0 ? void 0 : _c.focus) === null || _d === void 0 ? void 0 : _d.name, (_f = (_e = params.theme) === null || _e === void 0 ? void 0 : _e.focus) === null || _f === void 0 ? void 0 : _f.params); return { components, representations }; } });