UNPKG

molstar

Version:

A comprehensive macromolecular library.

182 lines 8.98 kB
"use strict"; /** * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.addStructureContacts = exports.addUnitContacts = exports.ContactsParams = void 0; var tslib_1 = require("tslib"); var int_1 = require("../../../mol-data/int"); var linear_algebra_1 = require("../../../mol-math/linear-algebra"); var structure_1 = require("../../../mol-model/structure"); var atomic_1 = require("../../../mol-model/structure/model/properties/atomic"); var lookup3d_1 = require("../../../mol-model/structure/structure/util/lookup3d"); var param_definition_1 = require("../../../mol-util/param-definition"); var util_1 = require("../chemistry/util"); var features_1 = require("./features"); exports.ContactsParams = { lineOfSightDistFactor: param_definition_1.ParamDefinition.Numeric(1.0, { min: 0, max: 3, step: 0.1 }), }; var MAX_LINE_OF_SIGHT_DISTANCE = 3; function validPair(structure, infoA, infoB) { var indexA = infoA.members[infoA.offsets[infoA.feature]]; var indexB = infoB.members[infoB.offsets[infoB.feature]]; if (indexA === indexB && infoA.unit === infoB.unit) return false; // no self interaction var altA = (0, util_1.altLoc)(infoA.unit, indexA); var altB = (0, util_1.altLoc)(infoB.unit, indexB); if (altA && altB && altA !== altB) return false; // incompatible alternate location id if (infoA.unit.residueIndex[infoA.unit.elements[indexA]] === infoB.unit.residueIndex[infoB.unit.elements[indexB]] && infoA.unit === infoB.unit) return false; // same residue // e.g. no hbond if donor and acceptor are bonded if ((0, util_1.connectedTo)(structure, infoA.unit, indexA, infoB.unit, indexB)) return false; return true; } // function invalidAltLoc(unitA, indexA, unitB, indexB) { var altA = (0, util_1.altLoc)(unitA, indexA); var altB = (0, util_1.altLoc)(unitB, indexB); return altA && altB && altA !== altB; } function isMember(element, info) { var feature = info.feature, offsets = info.offsets, members = info.members; for (var i = offsets[feature], il = offsets[feature + 1]; i < il; ++i) { if (members[i] === element) return true; } return false; } var tmpVec = (0, linear_algebra_1.Vec3)(); var tmpVecA = (0, linear_algebra_1.Vec3)(); var tmpVecB = (0, linear_algebra_1.Vec3)(); // need to use a separate context for structure.lookup3d.find because of nested queries var lineOfSightLookupCtx = (0, lookup3d_1.StructureLookup3DResultContext)(); function checkLineOfSight(structure, infoA, infoB, distFactor) { var featureA = infoA.feature; var featureB = infoB.feature; var indexA = infoA.members[infoA.offsets[featureA]]; var indexB = infoB.members[infoB.offsets[featureB]]; features_1.Features.position(tmpVecA, infoA); features_1.Features.position(tmpVecB, infoB); linear_algebra_1.Vec3.scale(tmpVec, linear_algebra_1.Vec3.add(tmpVec, tmpVecA, tmpVecB), 0.5); var distMax = distFactor * MAX_LINE_OF_SIGHT_DISTANCE; var _a = structure.lookup3d.find(tmpVec[0], tmpVec[1], tmpVec[2], distMax, lineOfSightLookupCtx), count = _a.count, indices = _a.indices, units = _a.units, squaredDistances = _a.squaredDistances; if (count === 0) return true; for (var r = 0; r < count; ++r) { var i = indices[r]; var unit = units[r]; if (!structure_1.Unit.isAtomic(unit)) continue; var element = (0, util_1.typeSymbol)(unit, i); // allow hydrogens if (element === "H" /* H */) continue; var vdw = (0, atomic_1.VdwRadius)(element); // check distance if (vdw * vdw * distFactor * distFactor <= squaredDistances[r]) continue; // allow different altlocs if (invalidAltLoc(unit, i, infoA.unit, indexA) || invalidAltLoc(unit, i, infoB.unit, indexB)) continue; // allow member atoms if ((infoA.unit === unit && isMember(i, infoA)) || (infoB.unit === unit && isMember(i, infoB))) continue; unit.conformation.position(unit.elements[i], tmpVec); // allow atoms at the center of functional groups if (linear_algebra_1.Vec3.squaredDistance(tmpVec, tmpVecA) < 1 || linear_algebra_1.Vec3.squaredDistance(tmpVec, tmpVecB) < 1) continue; return false; } return true; } /** * Add all intra-unit contacts, i.e. pairs of features */ function addUnitContacts(structure, unit, features, builder, testers, props) { for (var _i = 0, testers_1 = testers; _i < testers_1.length; _i++) { var tester = testers_1[_i]; _addUnitContacts(structure, unit, features, builder, tester, props); } } exports.addUnitContacts = addUnitContacts; function _addUnitContacts(structure, unit, features, builder, tester, props) { var x = features.x, y = features.y, z = features.z; var _a = features.subset(tester.requiredFeatures), lookup3d = _a.lookup3d, subsetIndices = _a.indices; var infoA = features_1.Features.Info(structure, unit, features); var infoB = (0, tslib_1.__assign)({}, infoA); var distFactor = props.lineOfSightDistFactor; for (var t = 0, tl = int_1.OrderedSet.size(subsetIndices); t < tl; ++t) { var i = int_1.OrderedSet.getAt(subsetIndices, t); var _b = lookup3d.find(x[i], y[i], z[i], tester.maxDistance), count = _b.count, indices = _b.indices, squaredDistances = _b.squaredDistances; if (count === 0) continue; infoA.feature = i; for (var r = 0; r < count; ++r) { var j = int_1.OrderedSet.getAt(subsetIndices, indices[r]); if (j <= i) continue; infoB.feature = j; if (!validPair(structure, infoA, infoB)) continue; var type = tester.getType(structure, infoA, infoB, squaredDistances[r]); if (type && checkLineOfSight(structure, infoA, infoB, distFactor)) { builder.add(i, j, type); } } } } var _imageTransform = (0, linear_algebra_1.Mat4)(); /** * Add all inter-unit contacts, i.e. pairs of features */ function addStructureContacts(structure, unitA, featuresA, unitB, featuresB, builder, testers, props) { var countA = featuresA.count, xA = featuresA.x, yA = featuresA.y, zA = featuresA.z; var lookup3d = featuresB.lookup3d; // the lookup queries need to happen in the "unitB space". // that means imageA = inverseOperB(operA(i)) var imageTransform = linear_algebra_1.Mat4.mul(_imageTransform, unitB.conformation.operator.inverse, unitA.conformation.operator.matrix); var isNotIdentity = !linear_algebra_1.Mat4.isIdentity(imageTransform); var imageA = (0, linear_algebra_1.Vec3)(); var maxDistance = Math.max.apply(Math, testers.map(function (t) { return t.maxDistance; })); var _a = lookup3d.boundary.sphere, center = _a.center, radius = _a.radius; var testDistanceSq = (radius + maxDistance) * (radius + maxDistance); var distFactor = props.lineOfSightDistFactor; var infoA = features_1.Features.Info(structure, unitA, featuresA); var infoB = features_1.Features.Info(structure, unitB, featuresB); builder.startUnitPair(unitA, unitB); for (var i = 0; i < countA; ++i) { linear_algebra_1.Vec3.set(imageA, xA[i], yA[i], zA[i]); if (isNotIdentity) linear_algebra_1.Vec3.transformMat4(imageA, imageA, imageTransform); if (linear_algebra_1.Vec3.squaredDistance(imageA, center) > testDistanceSq) continue; var _b = lookup3d.find(imageA[0], imageA[1], imageA[2], maxDistance), indices = _b.indices, count = _b.count, squaredDistances = _b.squaredDistances; if (count === 0) continue; infoA.feature = i; for (var r = 0; r < count; ++r) { var j = indices[r]; infoB.feature = j; if (!validPair(structure, infoA, infoB)) continue; var distanceSq = squaredDistances[r]; for (var _i = 0, testers_2 = testers; _i < testers_2.length; _i++) { var tester = testers_2[_i]; if (distanceSq < tester.maxDistance * tester.maxDistance) { var type = tester.getType(structure, infoA, infoB, distanceSq); if (type && checkLineOfSight(structure, infoA, infoB, distFactor)) { builder.add(i, j, type); break; } } } } } builder.finishUnitPair(); } exports.addStructureContacts = addStructureContacts; //# sourceMappingURL=contacts.js.map