representation.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /**
  2. * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { arrayFind } from '../../../mol-data/util';
  7. import { PluginContext } from '../../../mol-plugin/context';
  8. import { StateBuilder, StateObjectRef, StateObjectSelector, StateTransform } from '../../../mol-state';
  9. import { Task } from '../../../mol-task';
  10. import { isProductionMode } from '../../../mol-util/debug';
  11. import { objectForEach } from '../../../mol-util/object';
  12. import { ParamDefinition as PD } from '../../../mol-util/param-definition';
  13. import { createStructureRepresentationParams, StructureRepresentationBuiltInProps, StructureRepresentationProps } from '../../helpers/structure-representation-params';
  14. import { PluginStateObject } from '../../objects';
  15. import { StructureRepresentation3D } from '../../transforms/representation';
  16. import { PresetStructureReprentations, StructureRepresentationPresetProvider } from './representation-preset';
  17. export type StructureRepresentationPresetProviderRef = keyof PresetStructureReprentations | StructureRepresentationPresetProvider | string
  18. export class StructureRepresentationBuilder {
  19. private _providers: StructureRepresentationPresetProvider[] = [];
  20. private providerMap: Map<string, StructureRepresentationPresetProvider> = new Map();
  21. private get dataState() { return this.plugin.state.data; }
  22. readonly defaultProvider = PresetStructureReprentations.auto;
  23. private resolveProvider(ref: StructureRepresentationPresetProviderRef) {
  24. return typeof ref === 'string'
  25. ? PresetStructureReprentations[ref as keyof PresetStructureReprentations] ?? arrayFind(this._providers, p => p.id === ref)
  26. : ref;
  27. }
  28. hasPreset(s: PluginStateObject.Molecule.Structure) {
  29. for (const p of this._providers) {
  30. if (!p.isApplicable || p.isApplicable(s, this.plugin)) return true;
  31. }
  32. return false;
  33. }
  34. get providers(): ReadonlyArray<StructureRepresentationPresetProvider> { return this._providers; }
  35. getPresets(s?: PluginStateObject.Molecule.Structure) {
  36. if (!s) return this.providers;
  37. const ret = [];
  38. for (const p of this._providers) {
  39. if (p.isApplicable && !p.isApplicable(s, this.plugin)) continue;
  40. ret.push(p);
  41. }
  42. return ret;
  43. }
  44. getPresetSelect(s?: PluginStateObject.Molecule.Structure): PD.Select<string> {
  45. const options: [string, string][] = [];
  46. for (const p of this._providers) {
  47. if (s && p.isApplicable && !p.isApplicable(s, this.plugin)) continue;
  48. options.push([p.id, p.display.name]);
  49. }
  50. return PD.Select('auto', options);
  51. }
  52. getPresetsWithOptions(s: PluginStateObject.Molecule.Structure) {
  53. const options: [string, string][] = [];
  54. const map: { [K in string]: PD.Any } = Object.create(null);
  55. for (const p of this._providers) {
  56. if (p.isApplicable && !p.isApplicable(s, this.plugin)) continue;
  57. options.push([p.id, p.display.name]);
  58. map[p.id] = p.params ? PD.Group(p.params(s, this.plugin)) : PD.EmptyGroup()
  59. }
  60. if (options.length === 0) return PD.MappedStatic('', { '': PD.EmptyGroup() });
  61. return PD.MappedStatic(options[0][0], map, { options });
  62. }
  63. registerPreset(provider: StructureRepresentationPresetProvider) {
  64. if (this.providerMap.has(provider.id)) {
  65. throw new Error(`Repr. provider with id '${provider.id}' already registered.`);
  66. }
  67. this._providers.push(provider);
  68. this.providerMap.set(provider.id, provider);
  69. }
  70. applyPreset<K extends keyof PresetStructureReprentations>(parent: StateObjectRef<PluginStateObject.Molecule.Structure>, preset: K, params?: StructureRepresentationPresetProvider.Params<PresetStructureReprentations[K]>): Promise<StructureRepresentationPresetProvider.State<PresetStructureReprentations[K]>> | undefined
  71. applyPreset<P = any, S = {}>(parent: StateObjectRef<PluginStateObject.Molecule.Structure>, provider: StructureRepresentationPresetProvider<P, S>, params?: P): Promise<S> | undefined
  72. applyPreset(parent: StateObjectRef<PluginStateObject.Molecule.Structure>, providerId: string, params?: any): Promise<any> | undefined
  73. applyPreset(parent: StateObjectRef, providerRef: string | StructureRepresentationPresetProvider, params?: any): Promise<any> | undefined {
  74. const provider = this.resolveProvider(providerRef);
  75. if (!provider) return;
  76. const state = this.plugin.state.data;
  77. const cell = StateObjectRef.resolveAndCheck(state, parent);
  78. if (!cell) {
  79. if (!isProductionMode) console.warn(`Applying structure repr. provider to bad cell.`);
  80. return;
  81. }
  82. const prms = params || (provider.params
  83. ? PD.getDefaultValues(provider.params(cell.obj, this.plugin) as PD.Params)
  84. : {})
  85. const task = Task.create(`${provider.display.name}`, () => provider.apply(cell, prms, this.plugin) as Promise<any>);
  86. return this.plugin.runTask(task);
  87. }
  88. async addRepresentation<P extends StructureRepresentationBuiltInProps>(structure: StateObjectRef<PluginStateObject.Molecule.Structure>, props: P, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>): Promise<StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>>
  89. async addRepresentation<P extends StructureRepresentationProps>(structure: StateObjectRef<PluginStateObject.Molecule.Structure>, props: P, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>): Promise<StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>>
  90. async addRepresentation(structure: StateObjectRef<PluginStateObject.Molecule.Structure>, props: any, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>) {
  91. const repr = this.dataState.build();
  92. const selector = this.buildRepresentation(repr, structure, props, options);
  93. if (!selector) return;
  94. await this.plugin.updateDataState(repr);
  95. return selector;
  96. }
  97. async buildRepresentation<P extends StructureRepresentationBuiltInProps>(builder: StateBuilder.Root, structure: StateObjectRef<PluginStateObject.Molecule.Structure> | undefined, props: P, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>): Promise<StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>>
  98. async buildRepresentation<P extends StructureRepresentationProps>(builder: StateBuilder.Root, structure: StateObjectRef<PluginStateObject.Molecule.Structure> | undefined, props: P, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>): Promise<StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>>
  99. async buildRepresentation(builder: StateBuilder.Root, structure: StateObjectRef<PluginStateObject.Molecule.Structure> | undefined, props: any, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>) {
  100. if (!structure) return;
  101. const data = StateObjectRef.resolveAndCheck(this.dataState, structure)?.obj?.data;
  102. if (!data) return;
  103. const params = createStructureRepresentationParams(this.plugin, data, props);
  104. return builder.to(structure)
  105. .apply(StructureRepresentation3D, params, { tags: options?.tag, state: options?.initialState }).selector;
  106. }
  107. constructor(public plugin: PluginContext) {
  108. objectForEach(PresetStructureReprentations, r => this.registerPreset(r));
  109. }
  110. }
  111. export namespace StructureRepresentationBuilder {
  112. export interface AddRepresentationOptions {
  113. initialState?: Partial<StateTransform.State>,
  114. tag?: string
  115. }
  116. }