molstar
Version:
A comprehensive macromolecular library.
147 lines (146 loc) • 6.14 kB
JavaScript
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*
* based in part on NGL (https://github.com/arose/ngl)
*/
import { ParamDefinition as PD } from '../../../mol-util/param-definition';
import { Features } from './features';
import { typeSymbol, compId, atomId } from '../chemistry/util';
import { Elements, isTransitionMetal, isHalogen } from '../../../mol-model/structure/model/properties/atomic/types';
import { FeatureType, FeatureGroup, InteractionType } from './common';
import { AminoAcidNames, BaseNames, ProteinBackboneAtoms, NucleicBackboneAtoms } from '../../../mol-model/structure/model/types';
export const MetalCoordinationParams = {
distanceMax: PD.Numeric(3.0, { min: 1, max: 5, step: 0.1 }),
};
const IonicTypeMetals = [
Elements.LI, Elements.NA, Elements.K, Elements.RB, Elements.CS,
Elements.MG, Elements.CA, Elements.SR, Elements.BA, Elements.AL,
Elements.GA, Elements.IN, Elements.TL, Elements.SC, Elements.SN,
Elements.PB, Elements.BI, Elements.SB, Elements.HG
];
function addMetal(structure, unit, builder) {
const { elements } = unit;
const { x, y, z } = unit.model.atomicConformation;
for (let i = 0, il = elements.length; i < il; ++i) {
const element = typeSymbol(unit, i);
let type = FeatureType.None;
if (IonicTypeMetals.includes(element)) {
type = FeatureType.IonicTypeMetal;
}
else if (isTransitionMetal(element) || element === Elements.ZN || element === Elements.CD) {
type = FeatureType.TransitionMetal;
}
if (type) {
builder.add(type, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i);
}
}
}
function isProteinSidechain(atomname) {
return !ProteinBackboneAtoms.has(atomname);
}
function isProteinBackbone(atomname) {
return ProteinBackboneAtoms.has(atomname);
}
function isNucleicBackbone(atomname) {
return NucleicBackboneAtoms.has(atomname);
}
/**
* Metal binding partners (dative bond or ionic-type interaction)
*/
function addMetalBinding(structure, unit, builder) {
const { elements } = unit;
const { x, y, z } = unit.model.atomicConformation;
for (let i = 0, il = elements.length; i < il; ++i) {
const element = typeSymbol(unit, i);
const resname = compId(unit, i);
const atomname = atomId(unit, i);
let dative = false;
let ionic = false;
const isStandardAminoacid = AminoAcidNames.has(resname);
const isStandardBase = BaseNames.has(resname);
if (!isStandardAminoacid && !isStandardBase) {
if (isHalogen(element) || element === Elements.O || element === Elements.S) {
dative = true;
ionic = true;
}
else if (element === Elements.N) {
dative = true;
}
}
else if (isStandardAminoacid) {
// main chain oxygen atom or oxygen, nitrogen and sulfur from specific amino acids
if (element === Elements.O) {
if (['ASP', 'GLU', 'SER', 'THR', 'TYR', 'ASN', 'GLN'].includes(resname) && isProteinSidechain(atomname)) {
dative = true;
ionic = true;
}
else if (isProteinBackbone(atomname)) {
dative = true;
ionic = true;
}
}
else if (element === Elements.S && (resname === 'CYS' || resname === 'MET')) {
dative = true;
ionic = true;
}
else if (element === Elements.N) {
if (resname === 'HIS' && isProteinSidechain(atomname)) {
dative = true;
}
}
}
else if (isStandardBase) {
// http://pubs.acs.org/doi/pdf/10.1021/acs.accounts.6b00253
// http://onlinelibrary.wiley.com/doi/10.1002/anie.200900399/full
if (element === Elements.O && isNucleicBackbone(atomname)) {
dative = true;
ionic = true;
}
else if (['N3', 'N4', 'N7'].includes(atomname)) {
dative = true;
}
else if (['O2', 'O4', 'O6'].includes(atomname)) {
dative = true;
ionic = true;
}
}
if (dative) {
builder.add(FeatureType.DativeBondPartner, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i);
}
if (ionic) {
builder.add(FeatureType.IonicTypePartner, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i);
}
}
}
function isMetalCoordination(ti, tj) {
if (ti === FeatureType.TransitionMetal) {
return (tj === FeatureType.DativeBondPartner ||
tj === FeatureType.TransitionMetal);
}
else if (ti === FeatureType.IonicTypeMetal) {
return (tj === FeatureType.IonicTypePartner);
}
}
function testMetalCoordination(structure, infoA, infoB, distanceSq) {
const typeA = infoA.types[infoA.feature];
const typeB = infoB.types[infoB.feature];
if (!isMetalCoordination(typeA, typeB) && !isMetalCoordination(typeB, typeA))
return;
return InteractionType.MetalCoordination;
}
//
export const MetalProvider = Features.Provider([FeatureType.IonicTypeMetal, FeatureType.TransitionMetal], addMetal);
export const MetalBindingProvider = Features.Provider([FeatureType.IonicTypePartner, FeatureType.DativeBondPartner], addMetalBinding);
export const MetalCoordinationProvider = {
name: 'metal-coordination',
params: MetalCoordinationParams,
createTester: (props) => {
return {
maxDistance: props.distanceMax,
requiredFeatures: new Set([FeatureType.IonicTypeMetal, FeatureType.TransitionMetal, FeatureType.IonicTypePartner, FeatureType.DativeBondPartner]),
getType: (structure, infoA, infoB, distanceSq) => testMetalCoordination(structure, infoA, infoB, distanceSq)
};
}
};