molstar
Version:
A comprehensive macromolecular library.
226 lines • 11.8 kB
JavaScript
/**
* 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