generators.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /**
  2. * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { StructureQuery } from '../query'
  7. import { StructureSelection } from '../selection'
  8. import { Unit, StructureProperties as P } from '../../structure'
  9. import { Segmentation } from 'mol-data/int'
  10. import { LinearGroupingBuilder } from '../utils/builders';
  11. import { QueryPredicate, QueryFn, QueryContextView } from '../context';
  12. export const all: StructureQuery = ctx => StructureSelection.Singletons(ctx.inputStructure, ctx.inputStructure);
  13. export interface AtomsQueryParams {
  14. entityTest: QueryPredicate,
  15. chainTest: QueryPredicate,
  16. residueTest: QueryPredicate,
  17. atomTest: QueryPredicate,
  18. groupBy: QueryFn
  19. }
  20. export function residues(params?: Partial<AtomsQueryParams>) { return atoms({ ...params, groupBy: ctx => P.residue.key(ctx.element) }); }
  21. export function chains(params?: Partial<AtomsQueryParams>) { return atoms({ ...params, groupBy: ctx => P.chain.key(ctx.element) }); }
  22. function _true(ctx: QueryContextView) { return true; }
  23. function _zero(ctx: QueryContextView) { return 0; }
  24. export function atoms(params?: Partial<AtomsQueryParams>): StructureQuery {
  25. if (!params || (!params.atomTest && !params.residueTest && !params.chainTest && !params.entityTest && !params.groupBy)) return all;
  26. if (!!params.atomTest && !params.residueTest && !params.chainTest && !params.entityTest && !params.groupBy) return atomGroupsLinear(params.atomTest);
  27. const normalized: AtomsQueryParams = {
  28. entityTest: params.entityTest || _true,
  29. chainTest: params.chainTest || _true,
  30. residueTest: params.residueTest || _true,
  31. atomTest: params.atomTest || _true,
  32. groupBy: params.groupBy || _zero,
  33. };
  34. if (!params.groupBy) return atomGroupsSegmented(normalized)
  35. return atomGroupsGrouped(normalized);
  36. }
  37. function atomGroupsLinear(atomTest: QueryPredicate): StructureQuery {
  38. return ctx => {
  39. const { inputStructure } = ctx;
  40. const { units } = inputStructure;
  41. const l = ctx.pushCurrentElement();
  42. const builder = inputStructure.subsetBuilder(true);
  43. for (const unit of units) {
  44. l.unit = unit;
  45. const elements = unit.elements;
  46. builder.beginUnit(unit.id);
  47. for (let j = 0, _j = elements.length; j < _j; j++) {
  48. l.element = elements[j];
  49. if (atomTest(ctx)) builder.addElement(l.element);
  50. }
  51. builder.commitUnit();
  52. ctx.throwIfTimedOut();
  53. }
  54. ctx.popCurrentElement();
  55. return StructureSelection.Singletons(inputStructure, builder.getStructure());
  56. };
  57. }
  58. function atomGroupsSegmented({ entityTest, chainTest, residueTest, atomTest }: AtomsQueryParams): StructureQuery {
  59. return ctx => {
  60. const { inputStructure } = ctx;
  61. const { units } = inputStructure;
  62. const l = ctx.pushCurrentElement();
  63. const builder = inputStructure.subsetBuilder(true);
  64. for (const unit of units) {
  65. if (unit.kind !== Unit.Kind.Atomic) continue;
  66. l.unit = unit;
  67. const elements = unit.elements;
  68. builder.beginUnit(unit.id);
  69. const chainsIt = Segmentation.transientSegments(unit.model.atomicHierarchy.chainAtomSegments, elements);
  70. const residuesIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, elements);
  71. while (chainsIt.hasNext) {
  72. const chainSegment = chainsIt.move();
  73. l.element = elements[chainSegment.start];
  74. // test entity and chain
  75. if (!entityTest(ctx) || !chainTest(ctx)) continue;
  76. residuesIt.setSegment(chainSegment);
  77. while (residuesIt.hasNext) {
  78. const residueSegment = residuesIt.move();
  79. l.element = elements[residueSegment.start];
  80. // test residue
  81. if (!residueTest(ctx)) continue;
  82. for (let j = residueSegment.start, _j = residueSegment.end; j < _j; j++) {
  83. l.element = elements[j];
  84. if (atomTest(ctx)) {
  85. builder.addElement(l.element);
  86. }
  87. }
  88. }
  89. }
  90. builder.commitUnit();
  91. ctx.throwIfTimedOut();
  92. }
  93. ctx.popCurrentElement();
  94. return StructureSelection.Singletons(inputStructure, builder.getStructure());
  95. };
  96. }
  97. function atomGroupsGrouped({ entityTest, chainTest, residueTest, atomTest, groupBy }: AtomsQueryParams): StructureQuery {
  98. return ctx => {
  99. const { inputStructure } = ctx;
  100. const { units } = inputStructure;
  101. const l = ctx.pushCurrentElement();
  102. const builder = new LinearGroupingBuilder(inputStructure);
  103. for (const unit of units) {
  104. if (unit.kind !== Unit.Kind.Atomic) continue;
  105. l.unit = unit;
  106. const elements = unit.elements;
  107. const chainsIt = Segmentation.transientSegments(unit.model.atomicHierarchy.chainAtomSegments, elements);
  108. const residuesIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, elements);
  109. while (chainsIt.hasNext) {
  110. const chainSegment = chainsIt.move();
  111. l.element = elements[chainSegment.start];
  112. // test entity and chain
  113. if (!entityTest(ctx) || !chainTest(ctx)) continue;
  114. residuesIt.setSegment(chainSegment);
  115. while (residuesIt.hasNext) {
  116. const residueSegment = residuesIt.move();
  117. l.element = elements[residueSegment.start];
  118. // test residue
  119. if (!residueTest(ctx)) continue;
  120. for (let j = residueSegment.start, _j = residueSegment.end; j < _j; j++) {
  121. l.element = elements[j];
  122. if (atomTest(ctx)) builder.add(groupBy(ctx), unit.id, l.element);
  123. }
  124. }
  125. }
  126. ctx.throwIfTimedOut();
  127. }
  128. ctx.popCurrentElement();
  129. return builder.getSelection();
  130. };
  131. }