sequence.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  6. */
  7. import { Column } from '../../../../mol-data/db';
  8. import { AtomicHierarchy } from './atomic/hierarchy';
  9. import { Entities } from './common';
  10. import { Sequence } from '../../../sequence';
  11. import { ChainIndex } from '../indexing';
  12. import { CoarseHierarchy } from './coarse';
  13. import { CoarseElements } from './coarse/hierarchy';
  14. interface StructureSequence {
  15. readonly sequences: ReadonlyArray<StructureSequence.Entity>,
  16. readonly byEntityKey: { [key: number]: StructureSequence.Entity }
  17. }
  18. namespace StructureSequence {
  19. export interface Entity {
  20. readonly entityId: string,
  21. readonly sequence: Sequence
  22. }
  23. const Empty: StructureSequence = { byEntityKey: {}, sequences: [] };
  24. function merge(...entitySeqs: StructureSequence[]): StructureSequence {
  25. const sequences: StructureSequence.Entity[] = [];
  26. const byEntityKey: { [key: number]: StructureSequence.Entity } = {};
  27. for (let i = 0, il = entitySeqs.length; i < il; ++i) {
  28. sequences.push(...entitySeqs[i].sequences);
  29. Object.assign(byEntityKey, entitySeqs[i].byEntityKey);
  30. }
  31. return { sequences, byEntityKey };
  32. }
  33. export function fromHierarchy(entities: Entities, atomicHierarchy: AtomicHierarchy, coarseHierarchy: CoarseHierarchy): StructureSequence {
  34. const atomic = fromAtomicHierarchy(entities, atomicHierarchy);
  35. const coarse = coarseHierarchy.isDefined ? fromCoarseHierarchy(entities, coarseHierarchy) : Empty;
  36. return merge(atomic, coarse);
  37. }
  38. export function fromAtomicHierarchy(entities: Entities, hierarchy: AtomicHierarchy): StructureSequence {
  39. const { label_comp_id } = hierarchy.atoms;
  40. const { label_seq_id } = hierarchy.residues;
  41. const { chainAtomSegments, residueAtomSegments } = hierarchy;
  42. const { count, offsets } = chainAtomSegments;
  43. const byEntityKey: StructureSequence['byEntityKey'] = { };
  44. const sequences: StructureSequence.Entity[] = [];
  45. // check if chain segments are empty
  46. if (count === 1 && offsets[0] === 0 && offsets[1] === 0) {
  47. return { byEntityKey, sequences };
  48. }
  49. for (let cI = 0 as ChainIndex, _cI = hierarchy.chains._rowCount; cI < _cI; cI++) {
  50. const entityKey = hierarchy.index.getEntityFromChain(cI);
  51. // Only for polymers, trying to mirror _entity_poly_seq
  52. if (byEntityKey[entityKey] !== void 0 || entities.data.type.value(entityKey) !== 'polymer') continue;
  53. const start = cI;
  54. cI++;
  55. while (cI < _cI && entityKey === hierarchy.index.getEntityFromChain(cI) && entities.data.type.value(entityKey) !== 'polymer') {
  56. cI++;
  57. }
  58. cI--;
  59. const rStart = residueAtomSegments.index[offsets[start]];
  60. const rEnd = residueAtomSegments.index[offsets[cI + 1] - 1] + 1;
  61. const seqId = Column.window(label_seq_id, rStart, rEnd);
  62. const _compId: string[] = [];
  63. for (let rI = rStart; rI < rEnd; ++rI) {
  64. _compId.push(label_comp_id.value(residueAtomSegments.offsets[rI]));
  65. }
  66. const compId = Column.ofStringArray(_compId);
  67. byEntityKey[entityKey] = {
  68. entityId: entities.data.id.value(entityKey),
  69. sequence: Sequence.ofResidueNames(compId, seqId)
  70. };
  71. sequences.push(byEntityKey[entityKey]);
  72. }
  73. return { byEntityKey, sequences };
  74. }
  75. export function fromCoarseHierarchy(entities: Entities, hierarchy: CoarseHierarchy): StructureSequence {
  76. const spheres = fromCoarseElements(entities, hierarchy.spheres);
  77. const gaussians = fromCoarseElements(entities, hierarchy.gaussians);
  78. return merge(spheres, gaussians);
  79. }
  80. export function fromCoarseElements(entities: Entities, elements: CoarseElements): StructureSequence {
  81. const { chainElementSegments, seq_id_begin, seq_id_end } = elements;
  82. const { count, offsets } = chainElementSegments;
  83. const byEntityKey: StructureSequence['byEntityKey'] = { };
  84. const sequences: StructureSequence.Entity[] = [];
  85. // check if chain segments are empty
  86. if (count === 1 && offsets[0] === 0 && offsets[1] === 0) {
  87. return { byEntityKey, sequences };
  88. }
  89. for (let cI = 0 as ChainIndex, _cI = count; cI < _cI; cI++) {
  90. const eK = elements.getEntityFromChain(cI);
  91. if (byEntityKey[eK] !== void 0) continue;
  92. const start = cI;
  93. cI++;
  94. while (cI < _cI && eK === elements.getEntityFromChain(cI)) {
  95. cI++;
  96. }
  97. cI--;
  98. const eStart = offsets[start];
  99. const eEnd = offsets[cI + 1] - 1;
  100. const seqIdBegin = Column.window(seq_id_begin, eStart, eEnd);
  101. const seqIdEnd = Column.window(seq_id_end, eStart, eEnd);
  102. byEntityKey[eK] = {
  103. entityId: entities.data.id.value(eK),
  104. sequence: Sequence.ofSequenceRanges(seqIdBegin, seqIdEnd)
  105. };
  106. sequences.push(byEntityKey[eK]);
  107. }
  108. return { byEntityKey, sequences };
  109. }
  110. }
  111. export { StructureSequence };