accessible-surface-area.ts 4.0 KB

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