structure-measurement.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /**
  2. * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { StructureElement } from '../../mol-model/structure';
  7. import { PluginContext } from '../context';
  8. import { StateSelection, StateTransform } from '../../mol-state';
  9. import { StateTransforms } from '../state/transforms';
  10. import { PluginCommands } from '../command';
  11. import { arraySetAdd } from '../../mol-util/array';
  12. export { StructureMeasurementManager }
  13. const MeasurementGroupTag = 'measurement-group';
  14. class StructureMeasurementManager {
  15. private getGroup() {
  16. const state = this.context.state.dataState;
  17. const groupRef = StateSelection.findTagInSubtree(state.tree, StateTransform.RootRef, MeasurementGroupTag);
  18. const builder = this.context.state.dataState.build();
  19. if (groupRef) return builder.to(groupRef);
  20. return builder.toRoot().group(StateTransforms.Misc.CreateGroup, { label: `Measurements` }, { tags: MeasurementGroupTag });
  21. }
  22. async addDistance(a: StructureElement.Loci, b: StructureElement.Loci) {
  23. const cellA = this.context.helpers.substructureParent.get(a.structure);
  24. const cellB = this.context.helpers.substructureParent.get(b.structure);
  25. if (!cellA || !cellB) return;
  26. const dependsOn = [cellA.transform.ref];
  27. arraySetAdd(dependsOn, cellB.transform.ref);
  28. const update = this.getGroup();
  29. update
  30. .apply(StateTransforms.Model.MultiStructureSelectionFromExpression, {
  31. selections: [
  32. { key: 'a', groupId: 'a', ref: cellA.transform.ref, expression: StructureElement.Loci.toExpression(a) },
  33. { key: 'b', groupId: 'b', ref: cellB.transform.ref, expression: StructureElement.Loci.toExpression(b) }
  34. ],
  35. isTransitive: true,
  36. label: 'Distance'
  37. }, { dependsOn })
  38. .apply(StateTransforms.Representation.StructureSelectionsDistance3D)
  39. const state = this.context.state.dataState;
  40. await PluginCommands.State.Update.dispatch(this.context, { state, tree: update, options: { doNotLogTiming: true } });
  41. }
  42. async addAngle(a: StructureElement.Loci, b: StructureElement.Loci, c: StructureElement.Loci) {
  43. const cellA = this.context.helpers.substructureParent.get(a.structure);
  44. const cellB = this.context.helpers.substructureParent.get(b.structure);
  45. const cellC = this.context.helpers.substructureParent.get(c.structure);
  46. if (!cellA || !cellB || !cellC) return;
  47. const dependsOn = [cellA.transform.ref];
  48. arraySetAdd(dependsOn, cellB.transform.ref);
  49. arraySetAdd(dependsOn, cellC.transform.ref);
  50. const update = this.getGroup();
  51. update
  52. .apply(StateTransforms.Model.MultiStructureSelectionFromExpression, {
  53. selections: [
  54. { key: 'a', ref: cellA.transform.ref, expression: StructureElement.Loci.toExpression(a) },
  55. { key: 'b', ref: cellB.transform.ref, expression: StructureElement.Loci.toExpression(b) },
  56. { key: 'c', ref: cellC.transform.ref, expression: StructureElement.Loci.toExpression(c) }
  57. ],
  58. isTransitive: true,
  59. label: 'Angle'
  60. }, { dependsOn })
  61. .apply(StateTransforms.Representation.StructureSelectionsAngle3D)
  62. const state = this.context.state.dataState;
  63. await PluginCommands.State.Update.dispatch(this.context, { state, tree: update, options: { doNotLogTiming: true } });
  64. }
  65. async addDihedral(a: StructureElement.Loci, b: StructureElement.Loci, c: StructureElement.Loci, d: StructureElement.Loci) {
  66. const cellA = this.context.helpers.substructureParent.get(a.structure);
  67. const cellB = this.context.helpers.substructureParent.get(b.structure);
  68. const cellC = this.context.helpers.substructureParent.get(c.structure);
  69. const cellD = this.context.helpers.substructureParent.get(d.structure);
  70. if (!cellA || !cellB || !cellC || !cellD) return;
  71. const dependsOn = [cellA.transform.ref];
  72. arraySetAdd(dependsOn, cellB.transform.ref);
  73. arraySetAdd(dependsOn, cellC.transform.ref);
  74. arraySetAdd(dependsOn, cellD.transform.ref);
  75. const update = this.getGroup();
  76. update
  77. .apply(StateTransforms.Model.MultiStructureSelectionFromExpression, {
  78. selections: [
  79. { key: 'a', ref: cellA.transform.ref, expression: StructureElement.Loci.toExpression(a) },
  80. { key: 'b', ref: cellB.transform.ref, expression: StructureElement.Loci.toExpression(b) },
  81. { key: 'c', ref: cellC.transform.ref, expression: StructureElement.Loci.toExpression(c) },
  82. { key: 'd', ref: cellD.transform.ref, expression: StructureElement.Loci.toExpression(d) }
  83. ],
  84. isTransitive: true,
  85. label: 'Dihedral'
  86. }, { dependsOn })
  87. .apply(StateTransforms.Representation.StructureSelectionsDihedral3D)
  88. const state = this.context.state.dataState;
  89. await PluginCommands.State.Update.dispatch(this.context, { state, tree: update, options: { doNotLogTiming: true } });
  90. }
  91. async addLabel(a: StructureElement.Loci) {
  92. const cellA = this.context.helpers.substructureParent.get(a.structure);
  93. if (!cellA) return;
  94. const dependsOn = [cellA.transform.ref];
  95. const update = this.getGroup();
  96. update
  97. .apply(StateTransforms.Model.MultiStructureSelectionFromExpression, {
  98. selections: [
  99. { key: 'a', ref: cellA.transform.ref, expression: StructureElement.Loci.toExpression(a) },
  100. ],
  101. isTransitive: true,
  102. label: 'Label'
  103. }, { dependsOn })
  104. .apply(StateTransforms.Representation.StructureSelectionsLabel3D)
  105. const state = this.context.state.dataState;
  106. await PluginCommands.State.Update.dispatch(this.context, { state, tree: update, options: { doNotLogTiming: true } });
  107. }
  108. async addOrientation(a: StructureElement.Loci) {
  109. const cellA = this.context.helpers.substructureParent.get(a.structure);
  110. if (!cellA) return;
  111. const dependsOn = [cellA.transform.ref];
  112. const update = this.getGroup();
  113. update
  114. .apply(StateTransforms.Model.MultiStructureSelectionFromExpression, {
  115. selections: [
  116. { key: 'a', ref: cellA.transform.ref, expression: StructureElement.Loci.toExpression(a) },
  117. ],
  118. isTransitive: true,
  119. label: 'Orientation'
  120. }, { dependsOn })
  121. .apply(StateTransforms.Representation.StructureSelectionsOrientation3D)
  122. const state = this.context.state.dataState;
  123. await PluginCommands.State.Update.dispatch(this.context, { state, tree: update, options: { doNotLogTiming: true } });
  124. }
  125. constructor(private context: PluginContext) {
  126. }
  127. }