representation.ts 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 { PresetStructureRepresentations, StructureRepresentationPresetProvider } from './representation-preset';
  17. import { arrayRemoveInPlace } from '../../../mol-util/array';
  18. import { PluginConfig } from '../../../mol-plugin/config';
  19. // TODO factor out code shared with TrajectoryHierarchyBuilder?
  20. export type StructureRepresentationPresetProviderRef = keyof PresetStructureRepresentations | StructureRepresentationPresetProvider | string
  21. export class StructureRepresentationBuilder {
  22. private _providers: StructureRepresentationPresetProvider[] = [];
  23. private providerMap: Map<string, StructureRepresentationPresetProvider> = new Map();
  24. private get dataState() { return this.plugin.state.data; }
  25. readonly defaultProvider = PresetStructureRepresentations.auto;
  26. private resolveProvider(ref: StructureRepresentationPresetProviderRef) {
  27. return typeof ref === 'string'
  28. ? PresetStructureRepresentations[ref as keyof PresetStructureRepresentations] ?? arrayFind(this._providers, p => p.id === ref)
  29. : ref;
  30. }
  31. hasPreset(s: PluginStateObject.Molecule.Structure) {
  32. for (const p of this._providers) {
  33. if (!p.isApplicable || p.isApplicable(s, this.plugin)) return true;
  34. }
  35. return false;
  36. }
  37. get providers(): ReadonlyArray<StructureRepresentationPresetProvider> { return this._providers; }
  38. getPresets(s?: PluginStateObject.Molecule.Structure) {
  39. if (!s) return this.providers;
  40. const ret = [];
  41. for (const p of this._providers) {
  42. if (p.isApplicable && !p.isApplicable(s, this.plugin)) continue;
  43. ret.push(p);
  44. }
  45. return ret;
  46. }
  47. getPresetSelect(s?: PluginStateObject.Molecule.Structure): PD.Select<string> {
  48. const options: [string, string, string | undefined][] = [];
  49. for (const p of this._providers) {
  50. if (s && p.isApplicable && !p.isApplicable(s, this.plugin)) continue;
  51. options.push([p.id, p.display.name, p.display.group]);
  52. }
  53. return PD.Select('auto', options);
  54. }
  55. getPresetsWithOptions(s: PluginStateObject.Molecule.Structure) {
  56. const options: [string, string][] = [];
  57. const map: { [K in string]: PD.Any } = Object.create(null);
  58. for (const p of this._providers) {
  59. if (p.isApplicable && !p.isApplicable(s, this.plugin)) continue;
  60. options.push([p.id, p.display.name]);
  61. map[p.id] = p.params ? PD.Group(p.params(s, this.plugin)) : PD.EmptyGroup();
  62. }
  63. if (options.length === 0) return PD.MappedStatic('', { '': PD.EmptyGroup() });
  64. return PD.MappedStatic(options[0][0], map, { options });
  65. }
  66. registerPreset(provider: StructureRepresentationPresetProvider) {
  67. if (this.providerMap.has(provider.id)) {
  68. throw new Error(`Representation provider with id '${provider.id}' already registered.`);
  69. }
  70. this._providers.push(provider);
  71. this.providerMap.set(provider.id, provider);
  72. }
  73. unregisterPreset(provider: StructureRepresentationPresetProvider) {
  74. this.providerMap.delete(provider.id);
  75. arrayRemoveInPlace(this._providers, provider);
  76. }
  77. applyPreset<K extends keyof PresetStructureRepresentations>(parent: StateObjectRef<PluginStateObject.Molecule.Structure>, preset: K, params?: StructureRepresentationPresetProvider.Params<PresetStructureRepresentations[K]>): Promise<StructureRepresentationPresetProvider.State<PresetStructureRepresentations[K]>> | undefined
  78. applyPreset<P = any, S = {}>(parent: StateObjectRef<PluginStateObject.Molecule.Structure>, provider: StructureRepresentationPresetProvider<P, S>, params?: P): Promise<S> | undefined
  79. applyPreset(parent: StateObjectRef<PluginStateObject.Molecule.Structure>, providerId: string, params?: any): Promise<any> | undefined
  80. applyPreset(parent: StateObjectRef, providerRef: string | StructureRepresentationPresetProvider, params?: any): Promise<any> | undefined {
  81. const provider = this.resolveProvider(providerRef);
  82. if (!provider) return;
  83. const state = this.plugin.state.data;
  84. const cell = StateObjectRef.resolveAndCheck(state, parent);
  85. if (!cell) {
  86. if (!isProductionMode) console.warn(`Applying structure repr. provider to bad cell.`);
  87. return;
  88. }
  89. const pd = provider.params?.(cell.obj, this.plugin) as PD.Params || {};
  90. let prms = params || (provider.params
  91. ? PD.getDefaultValues(pd)
  92. : {});
  93. const defaults = this.plugin.config.get(PluginConfig.Structure.DefaultRepresentationPresetParams);
  94. prms = PD.merge(pd, defaults, prms);
  95. const task = Task.create(`${provider.display.name}`, () => provider.apply(cell, prms, this.plugin) as Promise<any>);
  96. return this.plugin.runTask(task);
  97. }
  98. async addRepresentation<P extends StructureRepresentationBuiltInProps>(structure: StateObjectRef<PluginStateObject.Molecule.Structure>, props: P, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>): Promise<StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>>
  99. async addRepresentation<P extends StructureRepresentationProps>(structure: StateObjectRef<PluginStateObject.Molecule.Structure>, props: P, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>): Promise<StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>>
  100. async addRepresentation(structure: StateObjectRef<PluginStateObject.Molecule.Structure>, props: any, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>) {
  101. const repr = this.dataState.build();
  102. const selector = this.buildRepresentation(repr, structure, props, options);
  103. if (!selector) return;
  104. await repr.commit();
  105. return selector;
  106. }
  107. buildRepresentation<P extends StructureRepresentationBuiltInProps>(builder: StateBuilder.Root, structure: StateObjectRef<PluginStateObject.Molecule.Structure> | undefined, props: P, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>): StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>
  108. buildRepresentation<P extends StructureRepresentationProps>(builder: StateBuilder.Root, structure: StateObjectRef<PluginStateObject.Molecule.Structure> | undefined, props: P, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>): StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>
  109. buildRepresentation(builder: StateBuilder.Root, structure: StateObjectRef<PluginStateObject.Molecule.Structure> | undefined, props: any, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>) {
  110. if (!structure) return;
  111. const data = StateObjectRef.resolveAndCheck(this.dataState, structure)?.obj?.data;
  112. if (!data) return;
  113. const params = createStructureRepresentationParams(this.plugin, data, props);
  114. return options?.tag
  115. ? builder.to(structure).applyOrUpdateTagged(options.tag, StructureRepresentation3D, params, { state: options?.initialState }).selector
  116. : builder.to(structure).apply(StructureRepresentation3D, params, { state: options?.initialState }).selector;
  117. }
  118. constructor(public plugin: PluginContext) {
  119. objectForEach(PresetStructureRepresentations, r => this.registerPreset(r));
  120. }
  121. }
  122. export namespace StructureRepresentationBuilder {
  123. export interface AddRepresentationOptions {
  124. initialState?: Partial<StateTransform.State>,
  125. tag?: string
  126. }
  127. }