structure-selection-helper.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /**
  2. * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { MolScriptBuilder as MS } from '../../mol-script/language/builder';
  7. import { StateSelection } from '../../mol-state';
  8. import { PluginStateObject } from '../state/objects';
  9. import { QueryContext, StructureSelection, StructureQuery } from '../../mol-model/structure';
  10. import { compile } from '../../mol-script/runtime/query/compiler';
  11. import { Loci } from '../../mol-model/loci';
  12. import { PluginContext } from '../context';
  13. import Expression from '../../mol-script/language/expression';
  14. const all = MS.struct.generator.all()
  15. const polymer = MS.struct.modifier.union([
  16. MS.struct.generator.atomGroups({
  17. 'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'polymer'])
  18. })
  19. ])
  20. const trace = MS.struct.modifier.union([
  21. MS.struct.combinator.merge([
  22. MS.struct.modifier.union([
  23. MS.struct.generator.atomGroups({
  24. 'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'polymer']),
  25. 'chain-test': MS.core.set.has([
  26. MS.set('sphere', 'gaussian'), MS.ammp('objectPrimitive')
  27. ])
  28. })
  29. ]),
  30. MS.struct.modifier.union([
  31. MS.struct.generator.atomGroups({
  32. 'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'polymer']),
  33. 'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
  34. 'atom-test': MS.core.set.has([MS.set('CA', 'P'), MS.ammp('label_atom_id')])
  35. })
  36. ])
  37. ])
  38. ])
  39. const protein = MS.struct.modifier.union([
  40. MS.struct.generator.atomGroups({
  41. 'entity-test': MS.core.logic.and([
  42. MS.core.rel.eq([MS.ammp('entityType'), 'polymer']),
  43. MS.core.str.match([
  44. MS.re('(polypeptide|cyclic-pseudo-peptide)', 'i'),
  45. MS.ammp('entitySubtype')
  46. ])
  47. ])
  48. })
  49. ])
  50. const nucleic = MS.struct.modifier.union([
  51. MS.struct.generator.atomGroups({
  52. 'entity-test': MS.core.logic.and([
  53. MS.core.rel.eq([MS.ammp('entityType'), 'polymer']),
  54. MS.core.str.match([
  55. MS.re('(nucleotide|peptide nucleic acid)', 'i'),
  56. MS.ammp('entitySubtype')
  57. ])
  58. ])
  59. })
  60. ])
  61. const proteinAndNucleic = MS.struct.modifier.union([
  62. MS.struct.generator.atomGroups({
  63. 'entity-test': MS.core.logic.and([
  64. MS.core.rel.eq([MS.ammp('entityType'), 'polymer']),
  65. MS.core.str.match([
  66. MS.re('(polypeptide|cyclic-pseudo-peptide|nucleotide|peptide nucleic acid)', 'i'),
  67. MS.ammp('entitySubtype')
  68. ])
  69. ])
  70. })
  71. ])
  72. const water = MS.struct.modifier.union([
  73. MS.struct.generator.atomGroups({
  74. 'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'water'])
  75. })
  76. ])
  77. const branched = MS.struct.modifier.union([
  78. MS.struct.generator.atomGroups({
  79. 'entity-test': MS.core.logic.or([
  80. MS.core.rel.eq([MS.ammp('entityType'), 'branched']),
  81. MS.core.logic.and([
  82. MS.core.rel.eq([MS.ammp('entityType'), 'non-polymer']),
  83. MS.core.str.match([
  84. MS.re('oligosaccharide', 'i'),
  85. MS.ammp('entitySubtype')
  86. ])
  87. ])
  88. ])
  89. })
  90. ])
  91. const branchedPlusConnected = MS.struct.modifier.union([
  92. MS.struct.modifier.includeConnected({
  93. 0: branched, 'layer-count': 1, 'as-whole-residues': true
  94. })
  95. ])
  96. const branchedConnectedOnly = MS.struct.modifier.union([
  97. MS.struct.modifier.exceptBy({
  98. 0: branchedPlusConnected,
  99. by: branched
  100. })
  101. ])
  102. const ligand = MS.struct.modifier.union([
  103. MS.struct.generator.atomGroups({
  104. 'entity-test': MS.core.logic.and([
  105. MS.core.rel.neq([MS.ammp('entityType'), 'branched']),
  106. MS.core.rel.eq([MS.ammp('entityType'), 'non-polymer'])
  107. ]),
  108. 'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
  109. 'residue-test': MS.core.logic.not([
  110. MS.core.str.match([MS.re('saccharide', 'i'), MS.ammp('chemCompType')])
  111. ])
  112. })
  113. ])
  114. const ligandPlusConnected = MS.struct.modifier.union([
  115. MS.struct.modifier.includeConnected({
  116. 0: ligand, 'layer-count': 1, 'as-whole-residues': true
  117. })
  118. ])
  119. const modified = MS.struct.modifier.union([
  120. MS.struct.generator.atomGroups({
  121. 'residue-test': MS.ammp('isModified')
  122. })
  123. ])
  124. const coarse = MS.struct.modifier.union([
  125. MS.struct.generator.atomGroups({
  126. 'chain-test': MS.core.set.has([
  127. MS.set('sphere', 'gaussian'), MS.ammp('objectPrimitive')
  128. ])
  129. })
  130. ])
  131. export const StructureSelectionQueries = {
  132. all,
  133. polymer,
  134. trace,
  135. protein,
  136. nucleic,
  137. proteinAndNucleic,
  138. water,
  139. branched,
  140. branchedPlusConnected,
  141. branchedConnectedOnly,
  142. ligand,
  143. ligandPlusConnected,
  144. modified,
  145. coarse,
  146. }
  147. export const CompiledStructureSelectionQueries = (function () {
  148. const ret: { [K in keyof typeof StructureSelectionQueries]: StructureQuery } = Object.create(null);
  149. for (const k of Object.keys(StructureSelectionQueries)) {
  150. (ret as any)[k] = compile<StructureSelection>((StructureSelectionQueries as any)[k]);
  151. }
  152. return ret;
  153. })();
  154. //
  155. export type SelectionModifier = 'add' | 'remove' | 'only'
  156. export class StructureSelectionHelper {
  157. private get structures() {
  158. const state = this.plugin.state.dataState
  159. return state.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Structure))
  160. }
  161. private _set(modifier: SelectionModifier, loci: Loci) {
  162. switch (modifier) {
  163. case 'add':
  164. this.plugin.interactivity.lociSelects.select({ loci })
  165. break
  166. case 'remove':
  167. this.plugin.interactivity.lociSelects.deselect({ loci })
  168. break
  169. case 'only':
  170. this.plugin.interactivity.lociSelects.selectOnly({ loci })
  171. break
  172. }
  173. }
  174. set(modifier: SelectionModifier, query: Expression) {
  175. const compiled = compile<StructureSelection>(query)
  176. for (const so of this.structures) {
  177. const s = so.obj!.data
  178. const result = compiled(new QueryContext(s))
  179. const loci = StructureSelection.toLoci2(result)
  180. this._set(modifier, loci)
  181. }
  182. }
  183. constructor(private plugin: PluginContext) {
  184. }
  185. }