accessible-surface-area.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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 { PluginBehavior } from '../../../behavior';
  7. import { ParamDefinition as PD } from '../../../../../mol-util/param-definition';
  8. import { AccessibleSurfaceAreaProvider } 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. export const AccessibleSurfaceArea = PluginBehavior.create<{ autoAttach: boolean, showTooltip: boolean }>({
  15. name: 'computed-accessible-surface-area-prop',
  16. category: 'custom-props',
  17. display: { name: 'Accessible Surface Area' },
  18. ctor: class extends PluginBehavior.Handler<{ autoAttach: boolean, showTooltip: boolean }> {
  19. private provider = AccessibleSurfaceAreaProvider
  20. private label = (loci: Loci): string | undefined => {
  21. if (!this.params.showTooltip) return
  22. return accessibleSurfaceAreaLabel(loci)
  23. }
  24. update(p: { autoAttach: boolean, showTooltip: boolean }) {
  25. let updated = (
  26. this.params.autoAttach !== p.autoAttach ||
  27. this.params.showTooltip !== p.showTooltip
  28. )
  29. this.params.autoAttach = p.autoAttach;
  30. this.params.showTooltip = p.showTooltip;
  31. this.ctx.customStructureProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach);
  32. return updated;
  33. }
  34. register(): void {
  35. DefaultQueryRuntimeTable.addCustomProp(this.provider.descriptor);
  36. this.ctx.customStructureProperties.register(this.provider, this.params.autoAttach);
  37. this.ctx.structureRepresentation.themeCtx.colorThemeRegistry.add('accessible-surface-area', AccessibleSurfaceAreaColorThemeProvider)
  38. this.ctx.managers.lociLabels.addProvider(this.label);
  39. }
  40. unregister() {
  41. // TODO
  42. // DefaultQueryRuntimeTable.removeCustomProp(this.provider.descriptor);
  43. this.ctx.customStructureProperties.unregister(this.provider.descriptor.name);
  44. this.ctx.structureRepresentation.themeCtx.colorThemeRegistry.remove('accessible-surface-area')
  45. this.ctx.managers.lociLabels.removeProvider(this.label);
  46. }
  47. },
  48. params: () => ({
  49. autoAttach: PD.Boolean(false),
  50. showTooltip: PD.Boolean(true)
  51. })
  52. });
  53. function accessibleSurfaceAreaLabel(loci: Loci): string | undefined {
  54. if(loci.kind === 'element-loci') {
  55. if (loci.elements.length === 0) return;
  56. const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(loci.structure).value
  57. if (!accessibleSurfaceArea || loci.structure.customPropertyDescriptors.hasReference(AccessibleSurfaceAreaProvider.descriptor)) return;
  58. const { getSerialIndex } = loci.structure.root.serialMapping
  59. const { area, serialResidueIndex } = accessibleSurfaceArea
  60. const seen = new Set<number>()
  61. let cummulativeArea = 0
  62. for (const { indices, unit } of loci.elements) {
  63. const { elements } = unit
  64. OrderedSet.forEach(indices, idx => {
  65. const rSI = serialResidueIndex[getSerialIndex(unit, elements[idx])]
  66. if (rSI !== -1 && !seen.has(rSI)) {
  67. cummulativeArea += area[rSI]
  68. seen.add(rSI)
  69. }
  70. })
  71. }
  72. if (seen.size === 0) return
  73. const residueCount = `<small>(${seen.size} ${seen.size > 1 ? 'Residues sum' : 'Residue'})</small>`
  74. return `Accessible Surface Area ${residueCount}: ${cummulativeArea.toFixed(2)} \u212B<sup>2</sup>`;
  75. } else if(loci.kind === 'structure-loci') {
  76. const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(loci.structure).value
  77. if (!accessibleSurfaceArea || loci.structure.customPropertyDescriptors.hasReference(AccessibleSurfaceAreaProvider.descriptor)) return;
  78. return `Accessible Surface Area <small>(Whole Structure)</small>: ${arraySum(accessibleSurfaceArea.area).toFixed(2)} \u212B<sup>2</sup>`;
  79. }
  80. }