UNPKG

molstar

Version:

A comprehensive macromolecular library.

578 lines 30.1 kB
"use strict"; /** * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Sebastian Bittrich <sebastian.bittrich@rcsb.org> * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.MaxAsa = exports.isHydrophobic = exports.isInMembranePlane = exports.calculate = exports.computeANVIL = exports.ANVILParams = void 0; var tslib_1 = require("tslib"); var structure_1 = require("../../mol-model/structure"); var mol_task_1 = require("../../mol-task"); var centroid_helper_1 = require("../../mol-math/geometry/centroid-helper"); var accessible_surface_area_1 = require("../../mol-model-props/computed/accessible-surface-area"); var linear_algebra_1 = require("../../mol-math/linear-algebra"); var util_1 = require("../../mol-model/structure/util"); var shrake_rupley_1 = require("../../mol-model-props/computed/accessible-surface-area/shrake-rupley"); var param_definition_1 = require("../../mol-util/param-definition"); var LARGE_CA_THRESHOLD = 5000; var DEFAULT_UPDATE_INTERVAL = 10; var LARGE_CA_UPDATE_INTERVAL = 1; ; exports.ANVILParams = { numberOfSpherePoints: param_definition_1.ParamDefinition.Numeric(175, { min: 35, max: 700, step: 1 }, { description: 'Number of spheres/directions to test for membrane placement. Original value is 350.' }), stepSize: param_definition_1.ParamDefinition.Numeric(1, { min: 0.25, max: 4, step: 0.25 }, { description: 'Thickness of membrane slices that will be tested' }), minThickness: param_definition_1.ParamDefinition.Numeric(20, { min: 10, max: 30, step: 1 }, { description: 'Minimum membrane thickness used during refinement' }), maxThickness: param_definition_1.ParamDefinition.Numeric(40, { min: 30, max: 50, step: 1 }, { description: 'Maximum membrane thickness used during refinement' }), asaCutoff: param_definition_1.ParamDefinition.Numeric(40, { min: 10, max: 100, step: 1 }, { description: 'Relative ASA cutoff above which residues will be considered' }), adjust: param_definition_1.ParamDefinition.Numeric(14, { min: 0, max: 30, step: 1 }, { description: 'Minimum length of membrane-spanning regions (original values: 14 for alpha-helices and 5 for beta sheets). Set to 0 to not optimize membrane thickness.' }), tmdetDefinition: param_definition_1.ParamDefinition.Boolean(false, { description: "Use TMDET's classification of membrane-favoring amino acids. TMDET's classification shows better performance on porins and other beta-barrel structures." }) }; /** ANVIL-specific (not general) definition of membrane-favoring amino acids */ var ANVIL_DEFINITION = new Set(['ALA', 'CYS', 'GLY', 'HIS', 'ILE', 'LEU', 'MET', 'PHE', 'SER', 'TRP', 'VAL']); /** TMDET-specific (not general) definition of membrane-favoring amino acids */ var TMDET_DEFINITION = new Set(['LEU', 'ILE', 'VAL', 'PHE', 'MET', 'GLY', 'TRP', 'TYR']); /** * Implements: * Membrane positioning for high- and low-resolution protein structures through a binary classification approach * Guillaume Postic, Yassine Ghouzam, Vincent Guiraud, and Jean-Christophe Gelly * Protein Engineering, Design & Selection, 2015, 1–5 * doi: 10.1093/protein/gzv063 * * ANVIL is derived from TMDET, the corresponding classification of hydrophobic amino acids is provided as optional parameter: * Gabor E. Tusnady, Zsuzsanna Dosztanyi and Istvan Simon * Transmembrane proteins in the Protein Data Bank: identification and classification * Bioinformatics, 2004, 2964-2972 * doi: 10.1093/bioinformatics/bth340 */ function computeANVIL(structure, props) { var _this = this; return mol_task_1.Task.create('Compute Membrane Orientation', function (runtime) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () { return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, calculate(runtime, structure, props)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }); } exports.computeANVIL = computeANVIL; // avoiding namespace lookup improved performance in Chrome (Aug 2020) var v3add = linear_algebra_1.Vec3.add; var v3clone = linear_algebra_1.Vec3.clone; var v3create = linear_algebra_1.Vec3.create; var v3distance = linear_algebra_1.Vec3.distance; var v3dot = linear_algebra_1.Vec3.dot; var v3magnitude = linear_algebra_1.Vec3.magnitude; var v3normalize = linear_algebra_1.Vec3.normalize; var v3scale = linear_algebra_1.Vec3.scale; var v3scaleAndAdd = linear_algebra_1.Vec3.scaleAndAdd; var v3set = linear_algebra_1.Vec3.set; var v3squaredDistance = linear_algebra_1.Vec3.squaredDistance; var v3sub = linear_algebra_1.Vec3.sub; var v3zero = linear_algebra_1.Vec3.zero; var centroidHelper = new centroid_helper_1.CentroidHelper(); function initialize(structure, props, accessibleSurfaceArea) { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { function isPartOfEntity(l) { return !structure_1.Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.residues.label_seq_id.valueKind(l.unit.residueIndex[l.element]) === 0; } var l, _a, label_atom_id, label_comp_id, x, y, z, asaCutoff, offsets, exposed, hydrophobic, definition, vec, i, il, unit, elements, j, jl, eI, centroid, k, kl, extent; return (0, tslib_1.__generator)(this, function (_b) { l = structure_1.StructureElement.Location.create(structure); _a = structure_1.StructureProperties.atom, label_atom_id = _a.label_atom_id, label_comp_id = _a.label_comp_id, x = _a.x, y = _a.y, z = _a.z; asaCutoff = props.asaCutoff / 100; centroidHelper.reset(); offsets = new Array(); exposed = new Array(); hydrophobic = new Array(); definition = props.tmdetDefinition ? TMDET_DEFINITION : ANVIL_DEFINITION; vec = v3zero(); for (i = 0, il = structure.units.length; i < il; ++i) { unit = structure.units[i]; elements = unit.elements; l.unit = unit; for (j = 0, jl = elements.length; j < jl; ++j) { eI = elements[j]; l.element = eI; // consider only amino acids in chains if ((0, util_1.getElementMoleculeType)(unit, eI) !== 5 /* Protein */ || !isPartOfEntity(l)) { continue; } // only CA is considered for downstream operations if (label_atom_id(l) !== 'CA' && label_atom_id(l) !== 'BB') { continue; } // original ANVIL only considers canonical amino acids if (!exports.MaxAsa[label_comp_id(l)]) { continue; } // while iterating use first pass to compute centroid v3set(vec, x(l), y(l), z(l)); centroidHelper.includeStep(vec); // keep track of offsets and exposed state to reuse offsets.push(structure.serialMapping.getSerialIndex(l.unit, l.element)); if (shrake_rupley_1.AccessibleSurfaceArea.getValue(l, accessibleSurfaceArea) / exports.MaxAsa[label_comp_id(l)] > asaCutoff) { exposed.push(structure.serialMapping.getSerialIndex(l.unit, l.element)); hydrophobic.push(isHydrophobic(definition, label_comp_id(l))); } } } // calculate centroid and extent centroidHelper.finishedIncludeStep(); centroid = v3clone(centroidHelper.center); for (k = 0, kl = offsets.length; k < kl; k++) { setLocation(l, structure, offsets[k]); v3set(vec, x(l), y(l), z(l)); centroidHelper.radiusStep(vec); } extent = 1.2 * Math.sqrt(centroidHelper.radiusSq); return [2 /*return*/, (0, tslib_1.__assign)((0, tslib_1.__assign)({}, props), { structure: structure, offsets: offsets, exposed: exposed, hydrophobic: hydrophobic, centroid: centroid, extent: extent, large: offsets.length > LARGE_CA_THRESHOLD })]; }); }); } function calculate(runtime, structure, params) { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { var asaProps, accessibleSurfaceArea, ctx, initialHphobHphil, initialMembrane, refinedMembrane, membrane, normalVector, center, extent; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: asaProps = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, param_definition_1.ParamDefinition.getDefaultValues(accessible_surface_area_1.AccessibleSurfaceAreaParams)), { probeSize: 4.0, traceOnly: true, numberOfSpherePoints: 184 }); return [4 /*yield*/, shrake_rupley_1.AccessibleSurfaceArea.compute(structure, asaProps).runInContext(runtime)]; case 1: accessibleSurfaceArea = _a.sent(); return [4 /*yield*/, initialize(structure, params, accessibleSurfaceArea)]; case 2: ctx = _a.sent(); initialHphobHphil = HphobHphil.initial(ctx); return [4 /*yield*/, findMembrane(runtime, 'Placing initial membrane...', ctx, generateSpherePoints(ctx, ctx.numberOfSpherePoints), initialHphobHphil)]; case 3: initialMembrane = (_a.sent()); return [4 /*yield*/, findMembrane(runtime, 'Refining membrane placement...', ctx, findProximateAxes(ctx, initialMembrane), initialHphobHphil)]; case 4: refinedMembrane = (_a.sent()); membrane = initialMembrane.qmax > refinedMembrane.qmax ? initialMembrane : refinedMembrane; if (!(ctx.adjust && !ctx.large)) return [3 /*break*/, 6]; return [4 /*yield*/, adjustThickness(runtime, 'Adjusting membrane thickness...', ctx, membrane, initialHphobHphil)]; case 5: membrane = _a.sent(); _a.label = 6; case 6: normalVector = v3zero(); center = v3zero(); v3sub(normalVector, membrane.planePoint1, membrane.planePoint2); v3normalize(normalVector, normalVector); v3add(center, membrane.planePoint1, membrane.planePoint2); v3scale(center, center, 0.5); extent = adjustExtent(ctx, membrane, center); return [2 /*return*/, { planePoint1: membrane.planePoint1, planePoint2: membrane.planePoint2, normalVector: normalVector, centroid: center, radius: extent }]; } }); }); } exports.calculate = calculate; var MembraneCandidate; (function (MembraneCandidate) { function initial(c1, c2, stats) { return { planePoint1: c1, planePoint2: c2, stats: stats }; } MembraneCandidate.initial = initial; function scored(spherePoint, planePoint1, planePoint2, stats, qmax, centroid) { var normalVector = v3zero(); v3sub(normalVector, centroid, spherePoint); return { planePoint1: planePoint1, planePoint2: planePoint2, stats: stats, normalVector: normalVector, spherePoint: spherePoint, qmax: qmax }; } MembraneCandidate.scored = scored; })(MembraneCandidate || (MembraneCandidate = {})); function findMembrane(runtime, message, ctx, spherePoints, initialStats) { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { var centroid, stepSize, minThickness, maxThickness, large, membrane, qmax, diam, n, nl, spherePoint, diamNorm, sliceStats, qvartemp, i, il, c1, c2, stats, jmax, width, widthl, i, il, hphob, hphil, j, ij, stats, qvaltest; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: centroid = ctx.centroid, stepSize = ctx.stepSize, minThickness = ctx.minThickness, maxThickness = ctx.maxThickness, large = ctx.large; qmax = 0; diam = v3zero(); n = 0, nl = spherePoints.length; _a.label = 1; case 1: if (!(n < nl)) return [3 /*break*/, 5]; if (!(runtime.shouldUpdate && message && (n + 1) % (large ? LARGE_CA_UPDATE_INTERVAL : DEFAULT_UPDATE_INTERVAL) === 0)) return [3 /*break*/, 3]; return [4 /*yield*/, runtime.update({ message: message, current: (n + 1), max: nl })]; case 2: _a.sent(); _a.label = 3; case 3: spherePoint = spherePoints[n]; v3sub(diam, centroid, spherePoint); v3scale(diam, diam, 2); diamNorm = v3magnitude(diam); sliceStats = HphobHphil.sliced(ctx, stepSize, spherePoint, diam, diamNorm); qvartemp = []; for (i = 0, il = diamNorm - stepSize; i < il; i += stepSize) { c1 = v3zero(); c2 = v3zero(); v3scaleAndAdd(c1, spherePoint, diam, i / diamNorm); v3scaleAndAdd(c2, spherePoint, diam, (i + stepSize) / diamNorm); stats = sliceStats[Math.round(i / stepSize)]; qvartemp.push(MembraneCandidate.initial(c1, c2, stats)); } jmax = Math.floor((minThickness / stepSize) - 1); for (width = 0, widthl = maxThickness; width <= widthl;) { for (i = 0, il = qvartemp.length - 1 - jmax; i < il; i++) { hphob = 0; hphil = 0; for (j = 0; j < jmax; j++) { ij = qvartemp[i + j]; if (j === 0 || j === jmax - 1) { hphob += Math.floor(0.5 * ij.stats.hphob); hphil += 0.5 * ij.stats.hphil; } else { hphob += ij.stats.hphob; hphil += ij.stats.hphil; } } if (hphob !== 0) { stats = { hphob: hphob, hphil: hphil }; qvaltest = qValue(stats, initialStats); if (qvaltest >= qmax) { qmax = qvaltest; membrane = MembraneCandidate.scored(spherePoint, qvartemp[i].planePoint1, qvartemp[i + jmax].planePoint2, stats, qmax, centroid); } } } jmax++; width = (jmax + 1) * stepSize; } _a.label = 4; case 4: n++; return [3 /*break*/, 1]; case 5: return [2 /*return*/, membrane]; } }); }); } /** Adjust membrane thickness by maximizing the number of membrane segments. */ function adjustThickness(runtime, message, ctx, membrane, initialHphobHphil) { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { var minThickness, large, step, maxThickness, maxNos, optimalThickness, n, nl, p, temp, nos; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: minThickness = ctx.minThickness, large = ctx.large; step = 0.3; maxThickness = v3distance(membrane.planePoint1, membrane.planePoint2); maxNos = membraneSegments(ctx, membrane).length; optimalThickness = membrane; n = 0; nl = Math.ceil((maxThickness - minThickness) / step); _a.label = 1; case 1: if (!(maxThickness > minThickness)) return [3 /*break*/, 5]; n++; if (!(runtime.shouldUpdate && message && n % (large ? LARGE_CA_UPDATE_INTERVAL : DEFAULT_UPDATE_INTERVAL) === 0)) return [3 /*break*/, 3]; return [4 /*yield*/, runtime.update({ message: message, current: n, max: nl })]; case 2: _a.sent(); _a.label = 3; case 3: p = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, ctx), { maxThickness: maxThickness, stepSize: step }); return [4 /*yield*/, findMembrane(runtime, void 0, p, [membrane.spherePoint], initialHphobHphil)]; case 4: temp = _a.sent(); if (temp) { nos = membraneSegments(ctx, temp).length; if (nos > maxNos) { maxNos = nos; optimalThickness = temp; } } maxThickness -= step; return [3 /*break*/, 1]; case 5: return [2 /*return*/, optimalThickness]; } }); }); } /** Report auth_seq_ids for all transmembrane segments. Will reject segments that are shorter than the adjust parameter specifies. Missing residues are considered in-membrane. */ function membraneSegments(ctx, membrane) { var offsets = ctx.offsets, structure = ctx.structure, adjust = ctx.adjust; var normalVector = membrane.normalVector, planePoint1 = membrane.planePoint1, planePoint2 = membrane.planePoint2; var units = structure.units; var _a = structure.serialMapping, elementIndices = _a.elementIndices, unitIndices = _a.unitIndices; var testPoint = v3zero(); var auth_seq_id = structure_1.StructureProperties.residue.auth_seq_id; var d1 = -v3dot(normalVector, planePoint1); var d2 = -v3dot(normalVector, planePoint2); var dMin = Math.min(d1, d2); var dMax = Math.max(d1, d2); var inMembrane = Object.create(null); var outMembrane = Object.create(null); var segments = []; var authAsymId; var lastAuthAsymId = null; var authSeqId; var lastAuthSeqId = units[0].model.atomicHierarchy.residues.auth_seq_id.value(units[0].chainIndex[0]) - 1; var startOffset = 0; var endOffset = 0; // collect all residues in membrane layer for (var k = 0, kl = offsets.length; k < kl; k++) { var unit = units[unitIndices[offsets[k]]]; if (!structure_1.Unit.isAtomic(unit)) notAtomic(); var elementIndex = elementIndices[offsets[k]]; authAsymId = unit.model.atomicHierarchy.chains.auth_asym_id.value(unit.chainIndex[elementIndex]); if (authAsymId !== lastAuthAsymId) { if (!inMembrane[authAsymId]) inMembrane[authAsymId] = new Set(); if (!outMembrane[authAsymId]) outMembrane[authAsymId] = new Set(); lastAuthAsymId = authAsymId; } authSeqId = unit.model.atomicHierarchy.residues.auth_seq_id.value(unit.residueIndex[elementIndex]); v3set(testPoint, unit.conformation.x(elementIndex), unit.conformation.y(elementIndex), unit.conformation.z(elementIndex)); if (_isInMembranePlane(testPoint, normalVector, dMin, dMax)) { inMembrane[authAsymId].add(authSeqId); } else { outMembrane[authAsymId].add(authSeqId); } } for (var k = 0, kl = offsets.length; k < kl; k++) { var unit = units[unitIndices[offsets[k]]]; if (!structure_1.Unit.isAtomic(unit)) notAtomic(); var elementIndex = elementIndices[offsets[k]]; authAsymId = unit.model.atomicHierarchy.chains.auth_asym_id.value(unit.chainIndex[elementIndex]); authSeqId = unit.model.atomicHierarchy.residues.auth_seq_id.value(unit.residueIndex[elementIndex]); if (inMembrane[authAsymId].has(authSeqId)) { // chain change if (authAsymId !== lastAuthAsymId) { segments.push({ start: startOffset, end: endOffset }); lastAuthAsymId = authAsymId; startOffset = k; endOffset = k; } // sequence gaps if (authSeqId !== lastAuthSeqId + 1) { if (outMembrane[authAsymId].has(lastAuthSeqId + 1)) { segments.push({ start: startOffset, end: endOffset }); startOffset = k; } lastAuthSeqId = authSeqId; endOffset = k; } else { lastAuthSeqId++; endOffset++; } } } segments.push({ start: startOffset, end: endOffset }); var l = structure_1.StructureElement.Location.create(structure); var startAuth; var endAuth; var refinedSegments = []; for (var k = 0, kl = segments.length; k < kl; k++) { var _b = segments[k], start = _b.start, end = _b.end; if (start === 0 || end === offsets.length - 1) continue; // evaluate residues 1 pos outside of membrane setLocation(l, structure, offsets[start - 1]); v3set(testPoint, l.unit.conformation.x(l.element), l.unit.conformation.y(l.element), l.unit.conformation.z(l.element)); var d3 = -v3dot(normalVector, testPoint); setLocation(l, structure, offsets[end + 1]); v3set(testPoint, l.unit.conformation.x(l.element), l.unit.conformation.y(l.element), l.unit.conformation.z(l.element)); var d4 = -v3dot(normalVector, testPoint); if (Math.min(d3, d4) < dMin && Math.max(d3, d4) > dMax) { // reject this refinement setLocation(l, structure, offsets[start]); startAuth = auth_seq_id(l); setLocation(l, structure, offsets[end]); endAuth = auth_seq_id(l); if (Math.abs(startAuth - endAuth) + 1 < adjust) { return []; } refinedSegments.push(segments[k]); } } return refinedSegments; } function notAtomic() { throw new Error('Property only available for atomic models.'); } /** Filter for membrane residues and calculate the final extent of the membrane layer */ function adjustExtent(ctx, membrane, centroid) { var offsets = ctx.offsets, structure = ctx.structure; var normalVector = membrane.normalVector, planePoint1 = membrane.planePoint1, planePoint2 = membrane.planePoint2; var l = structure_1.StructureElement.Location.create(structure); var testPoint = v3zero(); var _a = structure_1.StructureProperties.atom, x = _a.x, y = _a.y, z = _a.z; var d1 = -v3dot(normalVector, planePoint1); var d2 = -v3dot(normalVector, planePoint2); var dMin = Math.min(d1, d2); var dMax = Math.max(d1, d2); var extent = 0; for (var k = 0, kl = offsets.length; k < kl; k++) { setLocation(l, structure, offsets[k]); v3set(testPoint, x(l), y(l), z(l)); if (_isInMembranePlane(testPoint, normalVector, dMin, dMax)) { var dsq = v3squaredDistance(testPoint, centroid); if (dsq > extent) extent = dsq; } } return Math.sqrt(extent); } function qValue(currentStats, initialStats) { if (initialStats.hphob < 1) { initialStats.hphob = 0.1; } if (initialStats.hphil < 1) { initialStats.hphil += 1; } var part_tot = currentStats.hphob + currentStats.hphil; return (currentStats.hphob * (initialStats.hphil - currentStats.hphil) - currentStats.hphil * (initialStats.hphob - currentStats.hphob)) / Math.sqrt(part_tot * initialStats.hphob * initialStats.hphil * (initialStats.hphob + initialStats.hphil - part_tot)); } function isInMembranePlane(testPoint, normalVector, planePoint1, planePoint2) { var d1 = -v3dot(normalVector, planePoint1); var d2 = -v3dot(normalVector, planePoint2); return _isInMembranePlane(testPoint, normalVector, Math.min(d1, d2), Math.max(d1, d2)); } exports.isInMembranePlane = isInMembranePlane; function _isInMembranePlane(testPoint, normalVector, min, max) { var d = -v3dot(normalVector, testPoint); return d > min && d < max; } /** Generates a defined number of points on a sphere with radius = extent around the specified centroid */ function generateSpherePoints(ctx, numberOfSpherePoints) { var centroid = ctx.centroid, extent = ctx.extent; var points = []; var oldPhi = 0, h, theta, phi; for (var k = 1, kl = numberOfSpherePoints + 1; k < kl; k++) { h = -1 + 2 * (k - 1) / (2 * numberOfSpherePoints - 1); theta = Math.acos(h); phi = (k === 1 || k === numberOfSpherePoints) ? 0 : (oldPhi + 3.6 / Math.sqrt(2 * numberOfSpherePoints * (1 - h * h))) % (2 * Math.PI); var point = v3create(extent * Math.sin(phi) * Math.sin(theta) + centroid[0], extent * Math.cos(theta) + centroid[1], extent * Math.cos(phi) * Math.sin(theta) + centroid[2]); points[k - 1] = point; oldPhi = phi; } return points; } /** Generates sphere points close to that of the initial membrane */ function findProximateAxes(ctx, membrane) { var numberOfSpherePoints = ctx.numberOfSpherePoints, extent = ctx.extent; var points = generateSpherePoints(ctx, 30000); var j = 4; var sphere_pts2 = []; var s = 2 * extent / numberOfSpherePoints; while (sphere_pts2.length < numberOfSpherePoints) { var dsq = (s + j) * (s + j); sphere_pts2 = []; for (var i = 0, il = points.length; i < il; i++) { if (v3squaredDistance(points[i], membrane.spherePoint) < dsq) { sphere_pts2.push(points[i]); } } j += 0.2; } return sphere_pts2; } var HphobHphil; (function (HphobHphil) { function initial(ctx) { var exposed = ctx.exposed, hydrophobic = ctx.hydrophobic; var hphob = 0; var hphil = 0; for (var k = 0, kl = exposed.length; k < kl; k++) { if (hydrophobic[k]) { hphob++; } else { hphil++; } } return { hphob: hphob, hphil: hphil }; } HphobHphil.initial = initial; var testPoint = v3zero(); function sliced(ctx, stepSize, spherePoint, diam, diamNorm) { var exposed = ctx.exposed, hydrophobic = ctx.hydrophobic, structure = ctx.structure; var units = structure.units, serialMapping = structure.serialMapping; var unitIndices = serialMapping.unitIndices, elementIndices = serialMapping.elementIndices; var sliceStats = []; for (var i = 0, il = diamNorm - stepSize; i < il; i += stepSize) { sliceStats[sliceStats.length] = { hphob: 0, hphil: 0 }; } for (var i = 0, il = exposed.length; i < il; i++) { var unit = units[unitIndices[exposed[i]]]; var elementIndex = elementIndices[exposed[i]]; v3set(testPoint, unit.conformation.x(elementIndex), unit.conformation.y(elementIndex), unit.conformation.z(elementIndex)); v3sub(testPoint, testPoint, spherePoint); if (hydrophobic[i]) { sliceStats[Math.floor(v3dot(testPoint, diam) / diamNorm / stepSize)].hphob++; } else { sliceStats[Math.floor(v3dot(testPoint, diam) / diamNorm / stepSize)].hphil++; } } return sliceStats; } HphobHphil.sliced = sliced; })(HphobHphil || (HphobHphil = {})); /** Returns true if the definition considers this as membrane-favoring amino acid */ function isHydrophobic(definition, label_comp_id) { return definition.has(label_comp_id); } exports.isHydrophobic = isHydrophobic; /** Accessible surface area used for normalization. ANVIL uses 'Total-Side REL' values from NACCESS, from: Hubbard, S. J., & Thornton, J. M. (1993). naccess. Computer Program, Department of Biochemistry and Molecular Biology, University College London, 2(1). */ exports.MaxAsa = { 'ALA': 69.41, 'ARG': 201.25, 'ASN': 106.24, 'ASP': 102.69, 'CYS': 96.75, 'GLU': 134.74, 'GLN': 140.99, 'GLY': 32.33, 'HIS': 147.08, 'ILE': 137.96, 'LEU': 141.12, 'LYS': 163.30, 'MET': 156.64, 'PHE': 164.11, 'PRO': 119.90, 'SER': 78.11, 'THR': 101.70, 'TRP': 211.26, 'TYR': 177.38, 'VAL': 114.28 }; function setLocation(l, structure, serialIndex) { l.structure = structure; l.unit = structure.units[structure.serialMapping.unitIndices[serialIndex]]; l.element = structure.serialMapping.elementIndices[serialIndex]; return l; } //# sourceMappingURL=algorithm.js.map