util.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /**
  2. * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Michal Malý <michal.maly@ibt.cas.cz>
  5. * @author Jiří Černý <jiri.cerny@ibt.cas.cz>
  6. */
  7. import { ConfalPyramidsProvider } from './property';
  8. import { ConfalPyramidsTypes as CPT } from './types';
  9. import { Segmentation } from '../../../mol-data/int';
  10. import { ChainIndex, ElementIndex, ResidueIndex, Structure, StructureElement, StructureProperties, Unit } from '../../../mol-model/structure';
  11. type Residue = Segmentation.Segment<ResidueIndex>;
  12. export type Pyramid = {
  13. O3: ElementIndex,
  14. P: ElementIndex,
  15. OP1: ElementIndex,
  16. OP2: ElementIndex,
  17. O5: ElementIndex,
  18. confalScore: number,
  19. stepIdx: number,
  20. };
  21. const EmptyStepIndices = new Array<number>();
  22. function copyResidue(r?: Residue) {
  23. return r ? { index: r.index, start: r.start, end: r.end } : void 0;
  24. }
  25. function getAtomIndex(loc: StructureElement.Location, residue: Residue, names: string[], altId: string): ElementIndex {
  26. for (let eI = residue.start; eI < residue.end; eI++) {
  27. loc.element = loc.unit.elements[eI];
  28. const elName = StructureProperties.atom.label_atom_id(loc);
  29. const elAltId = StructureProperties.atom.label_alt_id(loc);
  30. if (names.includes(elName) && (elAltId === altId || elAltId.length === 0))
  31. return loc.element;
  32. }
  33. return -1 as ElementIndex;
  34. }
  35. function getPyramid(loc: StructureElement.Location, one: Residue, two: Residue, altIdOne: string, altIdTwo: string, confalScore: number, stepIdx: number): Pyramid {
  36. const O3 = getAtomIndex(loc, one, ['O3\'', 'O3*'], altIdOne);
  37. const P = getAtomIndex(loc, two, ['P'], altIdTwo);
  38. const OP1 = getAtomIndex(loc, two, ['OP1'], altIdTwo);
  39. const OP2 = getAtomIndex(loc, two, ['OP2'], altIdTwo);
  40. const O5 = getAtomIndex(loc, two, ['O5\'', 'O5*'], altIdTwo);
  41. return { O3, P, OP1, OP2, O5, confalScore, stepIdx };
  42. }
  43. export class ConfalPyramidsIterator {
  44. private chainIt: Segmentation.SegmentIterator<ChainIndex>;
  45. private residueIt: Segmentation.SegmentIterator<ResidueIndex>;
  46. private residueOne?: Residue;
  47. private residueTwo: Residue;
  48. private data?: CPT.Steps;
  49. private loc: StructureElement.Location;
  50. private getStepIndices(r: Residue) {
  51. this.loc.element = this.loc.unit.elements[r.start];
  52. const modelIdx = StructureProperties.unit.model_num(this.loc) - 1;
  53. const chainId = StructureProperties.chain.auth_asym_id(this.loc);
  54. const seqId = StructureProperties.residue.auth_seq_id(this.loc);
  55. const chains = this.data!.mapping[modelIdx];
  56. if (!chains) return EmptyStepIndices;
  57. const residues = chains.get(chainId);
  58. if (!residues) return EmptyStepIndices;
  59. return residues.get(seqId) ?? EmptyStepIndices;
  60. }
  61. private moveStep() {
  62. this.residueOne = copyResidue(this.residueTwo);
  63. this.residueTwo = copyResidue(this.residueIt.move())!;
  64. return this.toPyramids(this.residueOne!, this.residueTwo);
  65. }
  66. private toPyramids(one: Residue, two: Residue) {
  67. const indices = this.getStepIndices(one);
  68. const points = [];
  69. for (const idx of indices) {
  70. const step = this.data!.steps[idx];
  71. points.push(getPyramid(this.loc, one, two, step.label_alt_id_1, step.label_alt_id_2, step.confal_score, idx));
  72. }
  73. return points;
  74. }
  75. constructor(structure: Structure, unit: Unit) {
  76. this.chainIt = Segmentation.transientSegments(unit.model.atomicHierarchy.chainAtomSegments, unit.elements);
  77. this.residueIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, unit.elements);
  78. const prop = ConfalPyramidsProvider.get(unit.model).value;
  79. this.data = prop?.data;
  80. if (this.chainIt.hasNext) {
  81. this.residueIt.setSegment(this.chainIt.move());
  82. if (this.residueIt.hasNext)
  83. this.residueTwo = this.residueIt.move();
  84. }
  85. this.loc = StructureElement.Location.create(structure, unit, -1 as ElementIndex);
  86. }
  87. get hasNext() {
  88. if (!this.data)
  89. return false;
  90. return this.residueIt.hasNext
  91. ? true
  92. : this.chainIt.hasNext;
  93. }
  94. move() {
  95. if (this.residueIt.hasNext) {
  96. return this.moveStep();
  97. } else {
  98. this.residueIt.setSegment(this.chainIt.move());
  99. return this.moveStep();
  100. }
  101. }
  102. }