UNPKG

pdbe-molstar

Version:
100 lines (99 loc) 7.19 kB
"use strict"; /** Helper functions to allow superposition of complexes */ Object.defineProperty(exports, "__esModule", { value: true }); exports.Coloring = void 0; exports.loadComplexSuperposition = loadComplexSuperposition; const tslib_1 = require("tslib"); const commands_1 = require("molstar/lib/mol-plugin/commands"); const sleep_1 = require("molstar/lib/mol-util/sleep"); const __1 = require("../.."); const helpers_1 = require("../../helpers"); const superposition_1 = require("../../superposition"); const Coloring = tslib_1.__importStar(require("./coloring")); const superpose_by_biggest_chain_1 = require("./superpose-by-biggest-chain"); const superpose_by_sequence_alignment_1 = require("./superpose-by-sequence-alignment"); exports.Coloring = tslib_1.__importStar(require("./coloring")); /** Load a structure, superpose onto the main structure based on Uniprot residue numbers (or seq alignment if numbers not available), * and optionally apply coloring to show common/additional components. * * **Superposition method:** * Complexes are superposed based on the largest common component (measured the by number of residues) with a UniProt mapping (taken from atom_site mmCIF category). * In case there are no common components with Uniprot mapping, the largest common component with an Rfam mapping is used (taken from `baseMappings` and `otherMappings` parameters). * Residue-residue correspondence is determined by UniProt residue numbers (for UniProt mappings) or by sequence alignment (for Rfam mappings). * * **Coloring - subcomplexes:** * Common components are colored by entity; additional components are gray. Components in the subcomplex are slightly darkened. * * **Coloring - supercomplexes:** * Common components are gray; mapped additional components are colored by entity; unmapped additional components are magenta. Components in the supercomplex are slightly darkened. */ function loadComplexSuperposition(viewer, params) { return tslib_1.__awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g; const { pdbId, assemblyId, animationDuration = 250, coloring, baseComponents, otherComponents, baseMappings, otherMappings, coreColor, unmappedColor, componentColors } = params; const baseStructId = __1.PDBeMolstarPlugin.MAIN_STRUCTURE_ID; const otherStructId = (_a = params.id) !== null && _a !== void 0 ? _a : `${pdbId}_${assemblyId}`; // Apply coloring to base structure if (coloring) { if (!baseComponents) throw new Error('`baseComponents` is required when `coloring` is not `undefined`'); if (!otherComponents) throw new Error('`otherComponents` is required when `coloring` is not `undefined`'); } if (coloring === 'subcomplex') { yield Coloring.colorSubcomplex(viewer, { baseStructId, baseComponents: baseComponents, otherComponents: otherComponents, baseMappings, otherMappings, coreColor, componentColors }); } if (coloring === 'supercomplex') { yield Coloring.colorSupercomplex(viewer, { baseStructId, baseComponents: baseComponents, otherComponents: otherComponents, baseMappings, otherMappings, coreColor, unmappedColor, componentColors }); } // Load other structure const otherStructUrl = (0, helpers_1.getStructureUrl)(viewer.initParams, { pdbId, queryType: 'full' }); yield viewer.load({ url: otherStructUrl, isBinary: viewer.initParams.encoding === 'bcif', assemblyId, id: otherStructId }, false); yield viewer.visual.structureVisibility(otherStructId, false); // hide structure until superposition complete, to avoid flickering const baseStruct = (_c = (_b = viewer.getStructure(baseStructId)) === null || _b === void 0 ? void 0 : _b.cell.obj) === null || _c === void 0 ? void 0 : _c.data; if (!baseStruct) throw new Error('Static structure not loaded'); const otherStruct = (_e = (_d = viewer.getStructure(otherStructId)) === null || _d === void 0 ? void 0 : _d.cell.obj) === null || _e === void 0 ? void 0 : _e.data; if (!otherStruct) throw new Error('Mobile structure not loaded'); // Superpose other structure on base structure let superposition = (0, superpose_by_biggest_chain_1.superposeByBiggestCommonChain)(baseStruct, otherStruct, baseComponents, otherComponents); if (!superposition) { console.log(`UniProt-based superposition method failed, trying sequence alignment superposition (RNAs)`); superposition = (0, superpose_by_sequence_alignment_1.superposeBySequenceAlignment)(baseStruct, otherStruct, baseMappings !== null && baseMappings !== void 0 ? baseMappings : {}, otherMappings !== null && otherMappings !== void 0 ? otherMappings : {}); } if (superposition) { yield (0, superposition_1.transform)(viewer.plugin, viewer.getStructure(otherStructId).cell, superposition.bTransform); } else { console.log(`Sequence alignment superposition method failed, leaving unsuperposed`); } // Apply coloring to other structure if (coloring === 'subcomplex') { yield Coloring.colorSubcomplex(viewer, { otherStructId, baseComponents: baseComponents, otherComponents: otherComponents, baseMappings, otherMappings, coreColor, componentColors }); } if (coloring === 'supercomplex') { yield Coloring.colorSupercomplex(viewer, { otherStructId, baseComponents: baseComponents, otherComponents: otherComponents, baseMappings, otherMappings, coreColor, unmappedColor, componentColors }); } // Adjust camera const staticStructRef = viewer.getStructure(baseStructId); const mobileStructRef = viewer.getStructure(otherStructId); // it is important to run this after superposition, to get correct coordinates for camera adjustment // Wanted to use PluginCommands.Camera.Focus with viewer.plugin.canvas3d?.boundingSphere, but seems to not work properly, so using the following workaround: yield commands_1.PluginCommands.Camera.FocusObject(viewer.plugin, { targets: [ { targetRef: staticStructRef === null || staticStructRef === void 0 ? void 0 : staticStructRef.cell.transform.ref, extraRadius: 0.3 }, { targetRef: (_g = ((_f = mobileStructRef === null || mobileStructRef === void 0 ? void 0 : mobileStructRef.transform) !== null && _f !== void 0 ? _f : mobileStructRef)) === null || _g === void 0 ? void 0 : _g.cell.transform.ref, extraRadius: 0.3 }, // 0.3 is amount by which bounding sphere algorithm usually underestimates actual visible bounding sphere ], durationMs: animationDuration, }); yield (0, sleep_1.sleep)(animationDuration); // wait until camera adjustment completed // Reveal new structure yield viewer.visual.structureVisibility(otherStructId, true); return { id: otherStructId, superposition, delete: () => viewer.deleteStructure(otherStructId), }; }); }