accessible-surface-area.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { PluginBehavior } from '../../../behavior';
  7. import { ParamDefinition as PD } from '../../../../../mol-util/param-definition';
  8. import { AccessibleSurfaceAreaProvider, AccessibleSurfaceAreaSymbols } from '../../../../../mol-model-props/computed/accessible-surface-area';
  9. import { Loci } from '../../../../../mol-model/loci';
  10. import { AccessibleSurfaceAreaColorThemeProvider } from '../../../../../mol-model-props/computed/themes/accessible-surface-area';
  11. import { OrderedSet } from '../../../../../mol-data/int';
  12. import { arraySum } from '../../../../../mol-util/array';
  13. import { DefaultQueryRuntimeTable } from '../../../../../mol-script/runtime/query/compiler';
  14. import { StructureSelectionQuery, StructureSelectionCategory } from '../../../../../mol-plugin-state/helpers/structure-selection-query';
  15. import { MolScriptBuilder as MS } from '../../../../../mol-script/language/builder';
  16. export const AccessibleSurfaceArea = PluginBehavior.create<{ autoAttach: boolean, showTooltip: boolean }>({
  17. name: 'computed-accessible-surface-area-prop',
  18. category: 'custom-props',
  19. display: { name: 'Accessible Surface Area' },
  20. ctor: class extends PluginBehavior.Handler<{ autoAttach: boolean, showTooltip: boolean }> {
  21. private provider = AccessibleSurfaceAreaProvider
  22. private label = (loci: Loci): string | undefined => {
  23. if (!this.params.showTooltip) return
  24. return accessibleSurfaceAreaLabel(loci)
  25. }
  26. update(p: { autoAttach: boolean, showTooltip: boolean }) {
  27. let updated = (
  28. this.params.autoAttach !== p.autoAttach ||
  29. this.params.showTooltip !== p.showTooltip
  30. )
  31. this.params.autoAttach = p.autoAttach;
  32. this.params.showTooltip = p.showTooltip;
  33. this.ctx.customStructureProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach);
  34. return updated;
  35. }
  36. register(): void {
  37. DefaultQueryRuntimeTable.addCustomProp(this.provider.descriptor);
  38. this.ctx.customStructureProperties.register(this.provider, this.params.autoAttach);
  39. this.ctx.representation.structure.themes.colorThemeRegistry.add(AccessibleSurfaceAreaColorThemeProvider)
  40. this.ctx.managers.lociLabels.addProvider(this.label);
  41. this.ctx.query.structure.registry.add(isBuried)
  42. this.ctx.query.structure.registry.add(isAccessible)
  43. }
  44. unregister() {
  45. // TODO
  46. // DefaultQueryRuntimeTable.removeCustomProp(this.provider.descriptor);
  47. this.ctx.customStructureProperties.unregister(this.provider.descriptor.name);
  48. this.ctx.representation.structure.themes.colorThemeRegistry.remove(AccessibleSurfaceAreaColorThemeProvider)
  49. this.ctx.managers.lociLabels.removeProvider(this.label);
  50. this.ctx.query.structure.registry.remove(isBuried)
  51. this.ctx.query.structure.registry.remove(isAccessible)
  52. }
  53. },
  54. params: () => ({
  55. autoAttach: PD.Boolean(false),
  56. showTooltip: PD.Boolean(true)
  57. })
  58. });
  59. //
  60. function accessibleSurfaceAreaLabel(loci: Loci): string | undefined {
  61. if(loci.kind === 'element-loci') {
  62. if (loci.elements.length === 0) return;
  63. const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(loci.structure).value
  64. if (!accessibleSurfaceArea || loci.structure.customPropertyDescriptors.hasReference(AccessibleSurfaceAreaProvider.descriptor)) return;
  65. const { getSerialIndex } = loci.structure.root.serialMapping
  66. const { area, serialResidueIndex } = accessibleSurfaceArea
  67. const seen = new Set<number>()
  68. let cummulativeArea = 0
  69. for (const { indices, unit } of loci.elements) {
  70. const { elements } = unit
  71. OrderedSet.forEach(indices, idx => {
  72. const rSI = serialResidueIndex[getSerialIndex(unit, elements[idx])]
  73. if (rSI !== -1 && !seen.has(rSI)) {
  74. cummulativeArea += area[rSI]
  75. seen.add(rSI)
  76. }
  77. })
  78. }
  79. if (seen.size === 0) return
  80. const residueCount = `<small>(${seen.size} ${seen.size > 1 ? 'Residues sum' : 'Residue'})</small>`
  81. return `Accessible Surface Area ${residueCount}: ${cummulativeArea.toFixed(2)} \u212B<sup>2</sup>`;
  82. } else if(loci.kind === 'structure-loci') {
  83. const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(loci.structure).value
  84. if (!accessibleSurfaceArea || loci.structure.customPropertyDescriptors.hasReference(AccessibleSurfaceAreaProvider.descriptor)) return;
  85. return `Accessible Surface Area <small>(Whole Structure)</small>: ${arraySum(accessibleSurfaceArea.area).toFixed(2)} \u212B<sup>2</sup>`;
  86. }
  87. }
  88. //
  89. const isBuried = StructureSelectionQuery('Buried Protein Residues', MS.struct.modifier.union([
  90. MS.struct.modifier.wholeResidues([
  91. MS.struct.modifier.union([
  92. MS.struct.generator.atomGroups({
  93. 'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
  94. 'residue-test': AccessibleSurfaceAreaSymbols.isBuried.symbol(),
  95. })
  96. ])
  97. ])
  98. ]), {
  99. description: 'Select buried protein residues.',
  100. category: StructureSelectionCategory.Residue,
  101. ensureCustomProperties: (ctx, structure) => {
  102. return AccessibleSurfaceAreaProvider.attach(ctx, structure)
  103. }
  104. })
  105. const isAccessible = StructureSelectionQuery('Accessible Protein Residues', MS.struct.modifier.union([
  106. MS.struct.modifier.wholeResidues([
  107. MS.struct.modifier.union([
  108. MS.struct.generator.atomGroups({
  109. 'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
  110. 'residue-test': AccessibleSurfaceAreaSymbols.isAccessible.symbol(),
  111. })
  112. ])
  113. ])
  114. ]), {
  115. description: 'Select accessible protein residues.',
  116. category: StructureSelectionCategory.Residue,
  117. ensureCustomProperties: (ctx, structure) => {
  118. return AccessibleSurfaceAreaProvider.attach(ctx, structure)
  119. }
  120. })