secondary-structure.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { mmCIF_Database as mmCIF, mmCIF_Database } from 'mol-io/reader/cif/schema/mmcif'
  7. import { SecondaryStructureType } from '../../types';
  8. import { AtomicHierarchy } from '../../properties/atomic';
  9. import { SecondaryStructure } from '../../properties/seconday-structure';
  10. import { Column } from 'mol-data/db';
  11. export function getSecondaryStructureMmCif(data: mmCIF_Database, hierarchy: AtomicHierarchy): SecondaryStructure {
  12. const map: SecondaryStructureMap = new Map();
  13. addHelices(data.struct_conf, map);
  14. // must add Helices 1st because of 'key' value assignment.
  15. addSheets(data.struct_sheet_range, map, data.struct_conf._rowCount);
  16. const secStruct: SecondaryStructureData = {
  17. type: new Int32Array(hierarchy.residues._rowCount) as any,
  18. key: new Int32Array(hierarchy.residues._rowCount) as any
  19. };
  20. if (map.size > 0) assignSecondaryStructureRanges(hierarchy, map, secStruct);
  21. return secStruct;
  22. }
  23. type SecondaryStructureEntry = {
  24. startSeqNumber: number,
  25. startInsCode: string | null,
  26. endSeqNumber: number,
  27. endInsCode: string | null,
  28. type: SecondaryStructureType,
  29. key: number
  30. }
  31. type SecondaryStructureMap = Map<string, Map<number, SecondaryStructureEntry>>
  32. type SecondaryStructureData = { type: SecondaryStructureType[], key: number[] }
  33. function addHelices(cat: mmCIF['struct_conf'], map: SecondaryStructureMap) {
  34. if (!cat._rowCount) return;
  35. const { beg_label_asym_id, beg_label_seq_id, pdbx_beg_PDB_ins_code } = cat;
  36. const { end_label_seq_id, pdbx_end_PDB_ins_code } = cat;
  37. const { pdbx_PDB_helix_class, conf_type_id } = cat;
  38. for (let i = 0, _i = cat._rowCount; i < _i; i++) {
  39. const type = pdbx_PDB_helix_class.valueKind(i) === Column.ValueKind.Present
  40. ? SecondaryStructureType.SecondaryStructurePdb[pdbx_PDB_helix_class.value(i)]
  41. : conf_type_id.valueKind(i) === Column.ValueKind.Present
  42. ? SecondaryStructureType.SecondaryStructureMmcif[conf_type_id.value(i)]
  43. : SecondaryStructureType.Flag.NA
  44. const entry: SecondaryStructureEntry = {
  45. startSeqNumber: beg_label_seq_id.value(i),
  46. startInsCode: pdbx_beg_PDB_ins_code.value(i),
  47. endSeqNumber: end_label_seq_id.value(i),
  48. endInsCode: pdbx_end_PDB_ins_code.value(i),
  49. type: SecondaryStructureType.create(type),
  50. key: i + 1
  51. };
  52. const asymId = beg_label_asym_id.value(i)!;
  53. if (map.has(asymId)) {
  54. map.get(asymId)!.set(entry.startSeqNumber, entry);
  55. } else {
  56. map.set(asymId, new Map([[entry.startSeqNumber, entry]]));
  57. }
  58. }
  59. }
  60. function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap, sheetCount: number) {
  61. if (!cat._rowCount) return;
  62. const { beg_label_asym_id, beg_label_seq_id, pdbx_beg_PDB_ins_code } = cat;
  63. const { end_label_seq_id, pdbx_end_PDB_ins_code } = cat;
  64. const { sheet_id } = cat;
  65. const sheet_id_key = new Map<string, number>();
  66. let currentKey = sheetCount + 1;
  67. for (let i = 0, _i = cat._rowCount; i < _i; i++) {
  68. const id = sheet_id.value(i);
  69. let key: number;
  70. if (sheet_id_key.has(id)) key = sheet_id_key.get(id)!;
  71. else {
  72. key = currentKey++;
  73. sheet_id_key.set(id, key);
  74. }
  75. const entry: SecondaryStructureEntry = {
  76. startSeqNumber: beg_label_seq_id.value(i),
  77. startInsCode: pdbx_beg_PDB_ins_code.value(i),
  78. endSeqNumber: end_label_seq_id.value(i),
  79. endInsCode: pdbx_end_PDB_ins_code.value(i),
  80. type: SecondaryStructureType.create(SecondaryStructureType.Flag.Beta | SecondaryStructureType.Flag.BetaSheet),
  81. key
  82. };
  83. const asymId = beg_label_asym_id.value(i)!;
  84. if (map.has(asymId)) {
  85. map.get(asymId)!.set(entry.startSeqNumber, entry);
  86. } else {
  87. map.set(asymId, new Map([[entry.startSeqNumber, entry]]));
  88. }
  89. }
  90. return;
  91. }
  92. function assignSecondaryStructureEntry(hierarchy: AtomicHierarchy, entry: SecondaryStructureEntry, resStart: number, resEnd: number, data: SecondaryStructureData) {
  93. const { label_seq_id, pdbx_PDB_ins_code } = hierarchy.residues;
  94. const { endSeqNumber, endInsCode, type, key } = entry;
  95. let rI = resStart;
  96. while (rI < resEnd) {
  97. const seqNumber = label_seq_id.value(rI);
  98. data.type[rI] = type;
  99. data.key[rI] = key;
  100. if ((seqNumber > endSeqNumber) ||
  101. (seqNumber === endSeqNumber && pdbx_PDB_ins_code.value(rI) === endInsCode)) {
  102. break;
  103. }
  104. rI++;
  105. }
  106. }
  107. function assignSecondaryStructureRanges(hierarchy: AtomicHierarchy, map: SecondaryStructureMap, data: SecondaryStructureData) {
  108. const { segments: chainSegments, count: chainCount } = hierarchy.chainSegments;
  109. const { label_asym_id } = hierarchy.chains;
  110. const { label_seq_id, pdbx_PDB_ins_code } = hierarchy.residues;
  111. for (let cI = 0; cI < chainCount; cI++) {
  112. const resStart = chainSegments[cI], resEnd = chainSegments[cI + 1];
  113. const asymId = label_asym_id.value(cI);
  114. if (map.has(asymId)) {
  115. const entries = map.get(asymId)!;
  116. for (let rI = resStart; rI < resEnd; rI++) {
  117. const seqNumber = label_seq_id.value(rI);
  118. if (entries.has(seqNumber)) {
  119. const entry = entries.get(seqNumber)!;
  120. const insCode = pdbx_PDB_ins_code.value(rI);
  121. if (entry.startInsCode !== insCode) continue;
  122. assignSecondaryStructureEntry(hierarchy, entry, rI, resEnd, data);
  123. }
  124. }
  125. }
  126. }
  127. }