representation-preset.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /**
  2. * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  6. */
  7. import { PresetProvider } from '../preset-provider';
  8. import { PluginStateObject } from '../../objects';
  9. import { ParamDefinition as PD } from '../../../mol-util/param-definition';
  10. import { VisualQuality, VisualQualityOptions } from '../../../mol-geo/geometry/base';
  11. import { ColorTheme } from '../../../mol-theme/color';
  12. import { Structure } from '../../../mol-model/structure';
  13. import { PluginContext } from '../../../mol-plugin/context';
  14. import { StateObjectRef } from '../../../mol-state';
  15. import { StaticStructureComponentType } from '../../helpers/structure-component';
  16. import { StructureSelectionQueries as Q } from '../../helpers/structure-selection-query';
  17. export interface StructureRepresentationPresetProvider<P = any, S = {}> extends PresetProvider<PluginStateObject.Molecule.Structure, P, S> { }
  18. export namespace StructureRepresentationPresetProvider {
  19. export type Params<P extends StructureRepresentationPresetProvider> = P extends StructureRepresentationPresetProvider<infer T> ? T : never;
  20. export type State<P extends StructureRepresentationPresetProvider> = P extends StructureRepresentationPresetProvider<infer _, infer S> ? S : never;
  21. }
  22. export function StructureRepresentationPresetProvider<P, S>(repr: StructureRepresentationPresetProvider<P, S>) { return repr; }
  23. export const CommonStructureRepresentationPresetParams = {
  24. ignoreHydrogens: PD.Optional(PD.Boolean(false)),
  25. quality: PD.Optional(PD.Select<VisualQuality>('auto', VisualQualityOptions)),
  26. globalThemeName: PD.Optional(PD.Text<ColorTheme.BuiltIn>(''))
  27. }
  28. export type CommonStructureRepresentationParams = PD.ValuesFor<typeof CommonStructureRepresentationPresetParams>
  29. const auto = StructureRepresentationPresetProvider({
  30. id: 'preset-structure-representation-auto',
  31. display: { name: 'Automatic', group: 'Preset' },
  32. params: () => CommonStructureRepresentationPresetParams,
  33. apply(ref, params, plugin) {
  34. const structure = StateObjectRef.resolveAndCheck(plugin.state.data, ref)?.obj?.data;
  35. if (!structure) return { };
  36. const size = Structure.getSize(structure)
  37. switch (size) {
  38. case Structure.Size.Gigantic:
  39. case Structure.Size.Huge:
  40. return coarseSurface.apply(ref, params, plugin);
  41. case Structure.Size.Large:
  42. return polymerCartoon.apply(ref, params, plugin);
  43. case Structure.Size.Medium:
  44. return polymerAndLigand.apply(ref, params, plugin);
  45. case Structure.Size.Small:
  46. return atomicDetail.apply(ref, params, plugin);
  47. }
  48. }
  49. });
  50. function reprBuilder(plugin: PluginContext, params: CommonStructureRepresentationParams) {
  51. const update = plugin.state.data.build();
  52. const builder = plugin.builders.structure.representation;
  53. const typeParams = {
  54. quality: plugin.managers.structure.component.state.options.visualQuality,
  55. ignoreHydrogens: !plugin.managers.structure.component.state.options.showHydrogens,
  56. };
  57. if (params.quality && params.quality !== 'auto') typeParams.quality = params.quality;
  58. if (params.ignoreHydrogens !== void 0) typeParams.ignoreHydrogens = !!params.ignoreHydrogens;
  59. const color: ColorTheme.BuiltIn | undefined = params.globalThemeName ? params.globalThemeName : void 0;
  60. return { update, builder, color, typeParams };
  61. }
  62. const empty = StructureRepresentationPresetProvider({
  63. id: 'preset-structure-representation-empty',
  64. display: { name: 'Empty', group: 'Preset' },
  65. async apply(ref, params, plugin) {
  66. return { };
  67. }
  68. });
  69. const polymerAndLigand = StructureRepresentationPresetProvider({
  70. id: 'preset-structure-representation-polymer-and-ligand',
  71. display: { name: 'Polymer & Ligand', group: 'Preset' },
  72. params: () => CommonStructureRepresentationPresetParams,
  73. async apply(ref, params, plugin) {
  74. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  75. if (!structureCell) return {};
  76. const components = {
  77. polymer: await presetStaticComponent(plugin, structureCell, 'polymer'),
  78. ligand: await presetStaticComponent(plugin, structureCell, 'ligand'),
  79. nonStandard: await presetStaticComponent(plugin, structureCell, 'non-standard'),
  80. branched: await presetStaticComponent(plugin, structureCell, 'branched'),
  81. water: await presetStaticComponent(plugin, structureCell, 'water'),
  82. coarse: await presetStaticComponent(plugin, structureCell, 'coarse')
  83. };
  84. const { update, builder, typeParams, color } = reprBuilder(plugin, params);
  85. const representations = {
  86. polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams, color }),
  87. ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams, color }),
  88. nonStandard: builder.buildRepresentation(update, components.nonStandard, { type: 'ball-and-stick', typeParams, color: color || 'polymer-id' }),
  89. branched: components.branched && {
  90. ballAndStick: builder.buildRepresentation(update, components.branched, { type: 'ball-and-stick', typeParams: { ...typeParams, alpha: 0.15 }, color }),
  91. snfg3d: builder.buildRepresentation(update, components.branched, { type: 'carbohydrate', typeParams, color }),
  92. },
  93. water: builder.buildRepresentation(update, components.water, { type: 'ball-and-stick', typeParams: { ...typeParams, alpha: 0.51 }, color }),
  94. coarse: builder.buildRepresentation(update, components.coarse, { type: 'spacefill', typeParams, color: color || 'polymer-id' })
  95. };
  96. await plugin.updateDataState(update, { revertOnError: false });
  97. return { components, representations };
  98. }
  99. });
  100. const proteinAndNucleic = StructureRepresentationPresetProvider({
  101. id: 'preset-structure-representation-protein-and-nucleic',
  102. display: { name: 'Protein & Nucleic', group: 'Preset' },
  103. params: () => CommonStructureRepresentationPresetParams,
  104. async apply(ref, params, plugin) {
  105. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  106. if (!structureCell) return {};
  107. const components = {
  108. protein: await presetSelectionComponent(plugin, structureCell, 'protein'),
  109. nucleic: await presetSelectionComponent(plugin, structureCell, 'nucleic'),
  110. };
  111. const { update, builder, typeParams, color } = reprBuilder(plugin, params);
  112. const representations = {
  113. protein: builder.buildRepresentation(update, components.protein, { type: 'cartoon', typeParams, color }),
  114. nucleic: builder.buildRepresentation(update, components.nucleic, { type: 'gaussian-surface', typeParams, color })
  115. };
  116. await plugin.updateDataState(update, { revertOnError: true });
  117. return { components, representations };
  118. }
  119. });
  120. const coarseSurface = StructureRepresentationPresetProvider({
  121. id: 'preset-structure-representation-coarse-surface',
  122. display: { name: 'Coarse Surface', group: 'Preset' },
  123. params: () => CommonStructureRepresentationPresetParams,
  124. async apply(ref, params, plugin) {
  125. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  126. if (!structureCell) return {};
  127. const structure = structureCell.obj!.data;
  128. const size = Structure.getSize(structure)
  129. const gaussianProps = Object.create(null);
  130. const components = Object.create(null);
  131. if (size === Structure.Size.Gigantic) {
  132. Object.assign(gaussianProps, {
  133. radiusOffset: 1,
  134. smoothness: 0.5,
  135. visuals: ['structure-gaussian-surface-mesh']
  136. })
  137. components.trace = await presetSelectionComponent(plugin, structureCell, 'trace')
  138. } else if(size === Structure.Size.Huge) {
  139. Object.assign(gaussianProps, {
  140. smoothness: 0.5,
  141. })
  142. components.trace = await presetSelectionComponent(plugin, structureCell, 'polymer')
  143. } else {
  144. components.trace = await presetSelectionComponent(plugin, structureCell, 'polymer')
  145. }
  146. const { update, builder, typeParams, color } = reprBuilder(plugin, params);
  147. const representations = {
  148. trace: builder.buildRepresentation(update, components.trace, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color })
  149. };
  150. await plugin.updateDataState(update, { revertOnError: true });
  151. return { components, representations };
  152. }
  153. });
  154. const polymerCartoon = StructureRepresentationPresetProvider({
  155. id: 'preset-structure-representation-polymer-cartoon',
  156. display: { name: 'Polymer Cartoon', group: 'Preset' },
  157. params: () => CommonStructureRepresentationPresetParams,
  158. async apply(ref, params, plugin) {
  159. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  160. if (!structureCell) return {};
  161. const components = {
  162. polymer: await presetSelectionComponent(plugin, structureCell, 'polymer'),
  163. };
  164. const { update, builder, typeParams, color } = reprBuilder(plugin, params);
  165. const representations = {
  166. polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams, color })
  167. };
  168. await plugin.updateDataState(update, { revertOnError: true });
  169. return { components, representations };
  170. }
  171. });
  172. const atomicDetail = StructureRepresentationPresetProvider({
  173. id: 'preset-structure-representation-atomic-detail',
  174. display: { name: 'Atomic Detail', group: 'Preset' },
  175. params: () => CommonStructureRepresentationPresetParams,
  176. async apply(ref, params, plugin) {
  177. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  178. if (!structureCell) return {};
  179. const components = {
  180. all: await presetSelectionComponent(plugin, structureCell, 'all'),
  181. };
  182. const { update, builder, typeParams, color } = reprBuilder(plugin, params);
  183. const representations = {
  184. all: builder.buildRepresentation(update, components.all, { type: 'ball-and-stick', typeParams, color })
  185. };
  186. await plugin.updateDataState(update, { revertOnError: true });
  187. return { components, representations };
  188. }
  189. });
  190. export function presetStaticComponent(plugin: PluginContext, structure: StateObjectRef<PluginStateObject.Molecule.Structure>, type: StaticStructureComponentType) {
  191. return plugin.builders.structure.tryCreateComponentStatic(structure, type, `static-${type}`);
  192. }
  193. export function presetSelectionComponent(plugin: PluginContext, structure: StateObjectRef<PluginStateObject.Molecule.Structure>, query: keyof typeof Q) {
  194. return plugin.builders.structure.tryCreateComponentFromSelection(structure, Q[query], `selection-${query}`);
  195. }
  196. export const PresetStructureRepresentations = {
  197. empty,
  198. auto,
  199. 'atomic-detail': atomicDetail,
  200. 'polymer-cartoon': polymerCartoon,
  201. 'polymer-and-ligand': polymerAndLigand,
  202. 'protein-and-nucleic': proteinAndNucleic,
  203. 'coarse-surface': coarseSurface
  204. };
  205. export type PresetStructureRepresentations = typeof PresetStructureRepresentations;