radii.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /**
  2. * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
  5. */
  6. import { ShrakeRupleyContext, VdWLookup } from './common';
  7. import { getElementIdx, isHydrogen } from '../../../../mol-model/structure/structure/unit/links/common';
  8. import { isPolymer, isNucleic, MoleculeType, ElementSymbol } from '../../../../mol-model/structure/model/types';
  9. import { VdwRadius } from '../../../../mol-model/structure/model/properties/atomic';
  10. export async function assignRadiusForHeavyAtoms(ctx: ShrakeRupleyContext) {
  11. const { updateChunk, atomRadius } = ctx;
  12. for (let i = 0; i < atomRadius.length; i += updateChunk) {
  13. computeRange(ctx, i, Math.min(i + updateChunk, atomRadius.length));
  14. }
  15. }
  16. function computeRange(ctx: ShrakeRupleyContext, begin: number, end: number) {
  17. const { structure } = ctx;
  18. const { model } = structure;
  19. const { atoms: atomInfo, derived, residues, residueAtomSegments } = model.atomicHierarchy;
  20. const { label_comp_id } = residues;
  21. const { moleculeType } = derived.residue;
  22. const { type_symbol, label_atom_id } = atomInfo;
  23. for (let aI = begin; aI < end; ++aI) {
  24. const rI = residueAtomSegments.index[aI];
  25. const element = type_symbol.value(aI);
  26. const elementIdx = getElementIdx(element);
  27. // skip hydrogen atoms
  28. if (isHydrogen(elementIdx)) {
  29. ctx.atomRadius[aI] = VdWLookup[0];
  30. continue;
  31. }
  32. const residueType = moleculeType[rI];
  33. // skip non-polymer groups
  34. if (!ctx.nonPolymer) {
  35. if (!isPolymer(residueType)) {
  36. ctx.atomRadius[aI] = VdWLookup[0];
  37. continue;
  38. }
  39. }
  40. const atomId = label_atom_id.value(aI);
  41. let compId = label_comp_id.value(rI);
  42. // handle modified residues
  43. const parentId = model.properties.modifiedResidues.parentId.get(compId);
  44. if (parentId !== void 0) compId = parentId;
  45. if (isNucleic(residueType)) {
  46. ctx.atomRadius[aI] = determineRadiusNucl(atomId, element, compId);
  47. } else if (residueType === MoleculeType.Protein) {
  48. ctx.atomRadius[aI] = determineRadiusAmino(atomId, element, compId);
  49. } else {
  50. ctx.atomRadius[aI] = handleNonStandardCase(element);
  51. }
  52. }
  53. }
  54. /**
  55. * Gets the van der Waals radius of the given atom following the values defined by Chothia (1976)
  56. * J.Mol.Biol.105,1-14. NOTE: the vdw values defined by the paper assume no Hydrogens and thus "inflates" slightly
  57. * the heavy atoms to account for Hydrogens.
  58. */
  59. function determineRadiusAmino(atomId: string, element: ElementSymbol, compId: string): number {
  60. switch (element) {
  61. case 'O':
  62. return 5;
  63. case 'S':
  64. return 6;
  65. case 'N':
  66. return atomId === 'NZ' ? 4 : 3;
  67. case 'C':
  68. switch (atomId) {
  69. case 'C': case 'CE1': case'CE2': case 'CE3': case 'CH2': case 'CZ': case 'CZ2': case 'CZ3':
  70. return 1;
  71. case 'CA': case 'CB': case 'CE': case 'CG1': case 'CG2':
  72. return 2;
  73. default:
  74. switch (compId) {
  75. case 'PHE': case 'TRP': case 'TYR': case 'HIS': case 'ASP': case 'ASN':
  76. return 1;
  77. case 'PRO': case 'LYS': case 'ARG': case 'MET': case 'ILE': case 'LEU':
  78. return 2;
  79. case 'GLU': case 'GLN':
  80. return atomId === 'CD' ? 1 : 2;
  81. }
  82. }
  83. }
  84. return handleNonStandardCase(element);
  85. }
  86. function determineRadiusNucl(atomId: string, element: ElementSymbol, compId: string): number {
  87. switch (element) {
  88. case 'C':
  89. return 7;
  90. case 'N':
  91. return 8;
  92. case 'P':
  93. return 9;
  94. case 'O':
  95. return 5;
  96. }
  97. return handleNonStandardCase(element);
  98. }
  99. function handleNonStandardCase(element: ElementSymbol): number {
  100. const radius = VdwRadius(element);
  101. let index = VdWLookup.indexOf(radius);
  102. if (index === -1) {
  103. // add novel value to lookup array
  104. index = VdWLookup.length;
  105. VdWLookup[index] = radius;
  106. }
  107. return index;
  108. }