UNPKG

molstar

Version:

A comprehensive macromolecular library.

226 lines 11.8 kB
/** * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { __assign, __awaiter, __generator } from "tslib"; import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { Structure, Unit, Bond } from '../../../mol-model/structure'; import { Features, FeaturesBuilder } from './features'; import { ValenceModelProvider } from '../valence-model'; import { interactionTypeLabel } from './common'; import { IntraContactsBuilder, InterContactsBuilder } from './contacts-builder'; import { IntMap } from '../../../mol-data/int'; import { addUnitContacts, addStructureContacts, ContactsParams } from './contacts'; import { HalogenDonorProvider, HalogenAcceptorProvider, HalogenBondsProvider } from './halogen-bonds'; import { HydrogenDonorProvider, WeakHydrogenDonorProvider, HydrogenAcceptorProvider, HydrogenBondsProvider, WeakHydrogenBondsProvider } from './hydrogen-bonds'; import { NegativChargeProvider, PositiveChargeProvider, AromaticRingProvider, IonicProvider, PiStackingProvider, CationPiProvider } from './charged'; import { HydrophobicAtomProvider, HydrophobicProvider } from './hydrophobic'; import { SetUtils } from '../../../mol-util/set'; import { MetalCoordinationProvider, MetalProvider, MetalBindingProvider } from './metal'; import { refineInteractions } from './refine'; import { DataLocation } from '../../../mol-model/location'; import { CentroidHelper } from '../../../mol-math/geometry/centroid-helper'; import { DataLoci } from '../../../mol-model/loci'; import { bondLabel } from '../../../mol-theme/label'; import { ObjectKeys } from '../../../mol-util/type-helpers'; export { Interactions }; var Interactions; (function (Interactions) { function Location(interactions, structure, unitA, indexA, unitB, indexB) { return DataLocation('interactions', { structure: structure, interactions: interactions }, { unitA: unitA, indexA: indexA, unitB: unitB, indexB: indexB }); } Interactions.Location = Location; function isLocation(x) { return !!x && x.kind === 'data-location' && x.tag === 'interactions'; } Interactions.isLocation = isLocation; function areLocationsEqual(locA, locB) { return (locA.data.structure === locB.data.structure && locA.data.interactions === locB.data.interactions && locA.element.indexA === locB.element.indexA && locA.element.indexB === locB.element.indexB && locA.element.unitA === locB.element.unitA && locA.element.unitB === locB.element.unitB); } Interactions.areLocationsEqual = areLocationsEqual; function _label(interactions, element) { var unitA = element.unitA, indexA = element.indexA, unitB = element.unitB, indexB = element.indexB; var contacts = interactions.contacts, unitsContacts = interactions.unitsContacts; if (unitA === unitB) { var contacts_1 = unitsContacts.get(unitA.id); var idx = contacts_1.getDirectedEdgeIndex(indexA, indexB); return interactionTypeLabel(contacts_1.edgeProps.type[idx]); } else { var idx = contacts.getEdgeIndex(indexA, unitA.id, indexB, unitB.id); return interactionTypeLabel(contacts.edges[idx].props.type); } } function locationLabel(location) { return _label(location.data.interactions, location.element); } Interactions.locationLabel = locationLabel; function Loci(structure, interactions, elements) { return DataLoci('interactions', { structure: structure, interactions: interactions }, elements, function (boundingSphere) { return getBoundingSphere(interactions, elements, boundingSphere); }, function () { return getLabel(structure, interactions, elements); }); } Interactions.Loci = Loci; function isLoci(x) { return !!x && x.kind === 'data-loci' && x.tag === 'interactions'; } Interactions.isLoci = isLoci; function getBoundingSphere(interactions, elements, boundingSphere) { var unitsFeatures = interactions.unitsFeatures; return CentroidHelper.fromPairProvider(elements.length, function (i, pA, pB) { var e = elements[i]; Features.setPosition(pA, e.unitA, e.indexA, unitsFeatures.get(e.unitA.id)); Features.setPosition(pB, e.unitB, e.indexB, unitsFeatures.get(e.unitB.id)); }, boundingSphere); } Interactions.getBoundingSphere = getBoundingSphere; function getLabel(structure, interactions, elements) { var element = elements[0]; if (element === undefined) return ''; var unitA = element.unitA, indexA = element.indexA, unitB = element.unitB, indexB = element.indexB; var unitsFeatures = interactions.unitsFeatures; var _a = unitsFeatures.get(unitA.id), mA = _a.members, oA = _a.offsets; var _b = unitsFeatures.get(unitB.id), mB = _b.members, oB = _b.offsets; var options = { granularity: 'element' }; if (oA[indexA + 1] - oA[indexA] > 1 || oB[indexB + 1] - oB[indexB] > 1) { options.granularity = 'residue'; } return [ _label(interactions, element), bondLabel(Bond.Location(structure, unitA, mA[oA[indexA]], structure, unitB, mB[oB[indexB]]), options) ].join('</br>'); } Interactions.getLabel = getLabel; })(Interactions || (Interactions = {})); var FeatureProviders = [ HydrogenDonorProvider, WeakHydrogenDonorProvider, HydrogenAcceptorProvider, NegativChargeProvider, PositiveChargeProvider, AromaticRingProvider, HalogenDonorProvider, HalogenAcceptorProvider, HydrophobicAtomProvider, MetalProvider, MetalBindingProvider, ]; var ContactProviders = { 'ionic': IonicProvider, 'pi-stacking': PiStackingProvider, 'cation-pi': CationPiProvider, 'halogen-bonds': HalogenBondsProvider, 'hydrogen-bonds': HydrogenBondsProvider, 'weak-hydrogen-bonds': WeakHydrogenBondsProvider, 'hydrophobic': HydrophobicProvider, 'metal-coordination': MetalCoordinationProvider, }; function getProvidersParams(defaultOn) { if (defaultOn === void 0) { defaultOn = []; } var params = Object.create(null); Object.keys(ContactProviders).forEach(function (k) { params[k] = PD.MappedStatic(defaultOn.includes(k) ? 'on' : 'off', { on: PD.Group(ContactProviders[k].params), off: PD.Group({}) }, { cycle: true }); }); return params; } export var ContactProviderParams = getProvidersParams([ // 'ionic', 'cation-pi', 'pi-stacking', 'hydrogen-bonds', 'halogen-bonds', // 'hydrophobic', 'metal-coordination', // 'weak-hydrogen-bonds', ]); export var InteractionsParams = { providers: PD.Group(ContactProviderParams, { isFlat: true }), contacts: PD.Group(ContactsParams, { label: 'Advanced Options' }), }; export function computeInteractions(ctx, structure, props) { return __awaiter(this, void 0, void 0, function () { var p, contactTesters, requiredFeatures, featureProviders, unitsFeatures, unitsContacts, i, il, group, features, intraUnitContacts, j, jl, u, contacts, interactions; return __generator(this, function (_a) { switch (_a.label) { case 0: p = __assign(__assign({}, PD.getDefaultValues(InteractionsParams)), props); return [4 /*yield*/, ValenceModelProvider.attach(ctx, structure)]; case 1: _a.sent(); contactTesters = []; ObjectKeys(ContactProviders).forEach(function (k) { var _a = p.providers[k], name = _a.name, params = _a.params; if (name === 'on') { contactTesters.push(ContactProviders[k].createTester(params)); } }); requiredFeatures = new Set(); contactTesters.forEach(function (l) { return SetUtils.add(requiredFeatures, l.requiredFeatures); }); featureProviders = FeatureProviders.filter(function (f) { return SetUtils.areIntersecting(requiredFeatures, f.types); }); unitsFeatures = IntMap.Mutable(); unitsContacts = IntMap.Mutable(); i = 0, il = structure.unitSymmetryGroups.length; _a.label = 2; case 2: if (!(i < il)) return [3 /*break*/, 6]; group = structure.unitSymmetryGroups[i]; if (!ctx.runtime.shouldUpdate) return [3 /*break*/, 4]; return [4 /*yield*/, ctx.runtime.update({ message: 'computing interactions', current: i, max: il })]; case 3: _a.sent(); _a.label = 4; case 4: features = findUnitFeatures(structure, group.units[0], featureProviders); intraUnitContacts = findIntraUnitContacts(structure, group.units[0], features, contactTesters, p.contacts); for (j = 0, jl = group.units.length; j < jl; ++j) { u = group.units[j]; unitsFeatures.set(u.id, features); unitsContacts.set(u.id, intraUnitContacts); } _a.label = 5; case 5: ++i; return [3 /*break*/, 2]; case 6: contacts = findInterUnitContacts(structure, unitsFeatures, contactTesters, p.contacts); interactions = { unitsFeatures: unitsFeatures, unitsContacts: unitsContacts, contacts: contacts }; refineInteractions(structure, interactions); return [2 /*return*/, interactions]; } }); }); } function findUnitFeatures(structure, unit, featureProviders) { var count = unit.elements.length; var featuresBuilder = FeaturesBuilder.create(count, count / 2); if (Unit.isAtomic(unit)) { for (var _i = 0, featureProviders_1 = featureProviders; _i < featureProviders_1.length; _i++) { var fp = featureProviders_1[_i]; fp.add(structure, unit, featuresBuilder); } } return featuresBuilder.getFeatures(count); } function findIntraUnitContacts(structure, unit, features, contactTesters, props) { var builder = IntraContactsBuilder.create(features, unit.elements.length); if (Unit.isAtomic(unit)) { addUnitContacts(structure, unit, features, builder, contactTesters, props); } return builder.getContacts(); } function findInterUnitContacts(structure, unitsFeatures, contactTesters, props) { var builder = InterContactsBuilder.create(); Structure.eachUnitPair(structure, function (unitA, unitB) { var featuresA = unitsFeatures.get(unitA.id); var featuresB = unitsFeatures.get(unitB.id); addStructureContacts(structure, unitA, featuresA, unitB, featuresB, builder, contactTesters, props); }, { maxRadius: Math.max.apply(Math, contactTesters.map(function (t) { return t.maxDistance; })), validUnit: function (unit) { return Unit.isAtomic(unit); }, validUnitPair: function (unitA, unitB) { return Structure.validUnitPair(structure, unitA, unitB); } }); return builder.getContacts(unitsFeatures); } //# sourceMappingURL=interactions.js.map