representation-preset.ts 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /**
  2. * Copyright (c) 2019-2022 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, StateObjectSelector } from '../../../mol-state';
  15. import { StaticStructureComponentType } from '../../helpers/structure-component';
  16. import { StructureSelectionQueries as Q } from '../../helpers/structure-selection-query';
  17. import { PluginConfig } from '../../../mol-plugin/config';
  18. import { StructureFocusRepresentation } from '../../../mol-plugin/behavior/dynamic/selection/structure-focus-representation';
  19. import { createStructureColorThemeParams } from '../../helpers/structure-representation-params';
  20. import { ChainIdColorThemeProvider } from '../../../mol-theme/color/chain-id';
  21. import { OperatorNameColorThemeProvider } from '../../../mol-theme/color/operator-name';
  22. import { IndexPairBonds } from '../../../mol-model-formats/structure/property/bonds/index-pair';
  23. import { StructConn } from '../../../mol-model-formats/structure/property/bonds/struct_conn';
  24. import { StructureRepresentationRegistry } from '../../../mol-repr/structure/registry';
  25. import { assertUnreachable } from '../../../mol-util/type-helpers';
  26. export interface StructureRepresentationPresetProvider<P = any, S extends _Result = _Result> extends PresetProvider<PluginStateObject.Molecule.Structure, P, S> { }
  27. export function StructureRepresentationPresetProvider<P, S extends _Result>(repr: StructureRepresentationPresetProvider<P, S>) { return repr; }
  28. export namespace StructureRepresentationPresetProvider {
  29. export type Params<P extends StructureRepresentationPresetProvider> = P extends StructureRepresentationPresetProvider<infer T> ? T : never;
  30. export type State<P extends StructureRepresentationPresetProvider> = P extends StructureRepresentationPresetProvider<infer _, infer S> ? S : never;
  31. export type Result = {
  32. components?: { [name: string]: StateObjectSelector | undefined },
  33. representations?: { [name: string]: StateObjectSelector | undefined }
  34. }
  35. export const CommonParams = {
  36. ignoreHydrogens: PD.Optional(PD.Boolean(false)),
  37. ignoreLight: PD.Optional(PD.Boolean(false)),
  38. quality: PD.Optional(PD.Select<VisualQuality>('auto', VisualQualityOptions)),
  39. theme: PD.Optional(PD.Group({
  40. globalName: PD.Optional(PD.Text<ColorTheme.BuiltIn>('')),
  41. globalColorParams: PD.Optional(PD.Value<any>({}, { isHidden: true })),
  42. carbonColor: PD.Optional(PD.Select('chain-id', PD.arrayToOptions(['chain-id', 'operator-name', 'element-symbol'] as const))),
  43. symmetryColor: PD.Optional(PD.Text<ColorTheme.BuiltIn>('')),
  44. symmetryColorParams: PD.Optional(PD.Value<any>({}, { isHidden: true })),
  45. focus: PD.Optional(PD.Group({
  46. name: PD.Optional(PD.Text<ColorTheme.BuiltIn>('')),
  47. params: PD.Optional(PD.Value<ColorTheme.BuiltInParams<ColorTheme.BuiltIn>>({} as any))
  48. }))
  49. }))
  50. };
  51. export type CommonParams = PD.ValuesFor<typeof CommonParams>
  52. function getCarbonColorParams(name: 'chain-id' | 'operator-name' | 'element-symbol') {
  53. return name === 'chain-id'
  54. ? { name, params: ChainIdColorThemeProvider.defaultValues }
  55. : name === 'operator-name'
  56. ? { name, params: OperatorNameColorThemeProvider.defaultValues }
  57. : { name, params: {} };
  58. }
  59. function isSymmetry(structure: Structure) {
  60. return structure.units.some(u => !u.conformation.operator.assembly && u.conformation.operator.spgrOp >= 0);
  61. }
  62. export function reprBuilder(plugin: PluginContext, params: CommonParams, structure?: Structure) {
  63. const update = plugin.state.data.build();
  64. const builder = plugin.builders.structure.representation;
  65. const typeParams = {
  66. quality: plugin.managers.structure.component.state.options.visualQuality,
  67. ignoreHydrogens: !plugin.managers.structure.component.state.options.showHydrogens,
  68. ignoreLight: plugin.managers.structure.component.state.options.ignoreLight,
  69. };
  70. if (params.quality && params.quality !== 'auto') typeParams.quality = params.quality;
  71. if (params.ignoreHydrogens !== void 0) typeParams.ignoreHydrogens = !!params.ignoreHydrogens;
  72. if (params.ignoreLight !== void 0) typeParams.ignoreLight = !!params.ignoreLight;
  73. const color: ColorTheme.BuiltIn | undefined = params.theme?.globalName ? params.theme?.globalName : void 0;
  74. const ballAndStickColor: ColorTheme.BuiltInParams<'element-symbol'> = params.theme?.carbonColor !== undefined
  75. ? { carbonColor: getCarbonColorParams(params.theme?.carbonColor), ...params.theme?.globalColorParams }
  76. : { ...params.theme?.globalColorParams };
  77. const symmetryColor: ColorTheme.BuiltIn | undefined = structure && params.theme?.symmetryColor
  78. ? isSymmetry(structure) ? params.theme?.symmetryColor : color
  79. : color;
  80. const symmetryColorParams = params.theme?.symmetryColorParams ? { ...params.theme?.globalColorParams, ...params.theme?.symmetryColorParams } : { ...params.theme?.globalColorParams };
  81. const globalColorParams = params.theme?.globalColorParams ? { ...params.theme?.globalColorParams } : undefined;
  82. return { update, builder, color, symmetryColor, symmetryColorParams, globalColorParams, typeParams, ballAndStickColor };
  83. }
  84. export function updateFocusRepr<T extends ColorTheme.BuiltIn>(plugin: PluginContext, structure: Structure, themeName: T | undefined, themeParams: ColorTheme.BuiltInParams<T> | undefined) {
  85. return plugin.state.updateBehavior(StructureFocusRepresentation, p => {
  86. const c = createStructureColorThemeParams(plugin, structure, 'ball-and-stick', themeName || 'element-symbol', themeParams);
  87. p.surroundingsParams.colorTheme = c;
  88. p.targetParams.colorTheme = c;
  89. });
  90. }
  91. }
  92. type _Result = StructureRepresentationPresetProvider.Result
  93. const CommonParams = StructureRepresentationPresetProvider.CommonParams;
  94. type CommonParams = StructureRepresentationPresetProvider.CommonParams
  95. const reprBuilder = StructureRepresentationPresetProvider.reprBuilder;
  96. const updateFocusRepr = StructureRepresentationPresetProvider.updateFocusRepr;
  97. const auto = StructureRepresentationPresetProvider({
  98. id: 'preset-structure-representation-auto',
  99. display: {
  100. name: 'Automatic',
  101. description: 'Show representations based on the size of the structure. Smaller structures are shown with more detail than larger ones, ranging from atomistic display to coarse surfaces.'
  102. },
  103. params: () => CommonParams,
  104. apply(ref, params, plugin) {
  105. const structure = StateObjectRef.resolveAndCheck(plugin.state.data, ref)?.obj?.data;
  106. if (!structure) return { };
  107. const thresholds = plugin.config.get(PluginConfig.Structure.SizeThresholds) || Structure.DefaultSizeThresholds;
  108. const size = Structure.getSize(structure, thresholds);
  109. const gapFraction = structure.polymerResidueCount / structure.polymerGapCount;
  110. switch (size) {
  111. case Structure.Size.Gigantic:
  112. case Structure.Size.Huge:
  113. return coarseSurface.apply(ref, params, plugin);
  114. case Structure.Size.Large:
  115. return polymerCartoon.apply(ref, params, plugin);
  116. case Structure.Size.Medium:
  117. if (gapFraction > 3) {
  118. return polymerAndLigand.apply(ref, params, plugin);
  119. } // else fall through
  120. case Structure.Size.Small:
  121. // `showCarbohydrateSymbol: true` is nice, e.g., for PDB 1aga
  122. return atomicDetail.apply(ref, { ...params, showCarbohydrateSymbol: true }, plugin);
  123. default:
  124. assertUnreachable(size);
  125. }
  126. }
  127. });
  128. const empty = StructureRepresentationPresetProvider({
  129. id: 'preset-structure-representation-empty',
  130. display: { name: 'Empty', description: 'Removes all existing representations.' },
  131. async apply(ref, params, plugin) {
  132. return { };
  133. }
  134. });
  135. const BuiltInPresetGroupName = 'Basic';
  136. const polymerAndLigand = StructureRepresentationPresetProvider({
  137. id: 'preset-structure-representation-polymer-and-ligand',
  138. display: {
  139. name: 'Polymer & Ligand', group: BuiltInPresetGroupName,
  140. description: 'Shows polymers as Cartoon, ligands as Ball & Stick, carbohydrates as 3D-SNFG and water molecules semi-transparent.'
  141. },
  142. params: () => CommonParams,
  143. async apply(ref, params, plugin) {
  144. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  145. if (!structureCell) return {};
  146. const components = {
  147. polymer: await presetStaticComponent(plugin, structureCell, 'polymer'),
  148. ligand: await presetStaticComponent(plugin, structureCell, 'ligand'),
  149. nonStandard: await presetStaticComponent(plugin, structureCell, 'non-standard'),
  150. branched: await presetStaticComponent(plugin, structureCell, 'branched', { label: 'Carbohydrate' }),
  151. water: await presetStaticComponent(plugin, structureCell, 'water'),
  152. ion: await presetStaticComponent(plugin, structureCell, 'ion'),
  153. lipid: await presetStaticComponent(plugin, structureCell, 'lipid'),
  154. coarse: await presetStaticComponent(plugin, structureCell, 'coarse')
  155. };
  156. const structure = structureCell.obj!.data;
  157. const cartoonProps = {
  158. sizeFactor: structure.isCoarseGrained ? 0.8 : 0.2,
  159. };
  160. // TODO make configurable
  161. const waterType = (components.water?.obj?.data?.elementCount || 0) > 50_000 ? 'line' : 'ball-and-stick';
  162. const lipidType = (components.lipid?.obj?.data?.elementCount || 0) > 20_000 ? 'line' : 'ball-and-stick';
  163. const { update, builder, typeParams, color, symmetryColor, symmetryColorParams, globalColorParams, ballAndStickColor } = reprBuilder(plugin, params, structure);
  164. const representations = {
  165. polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams: { ...typeParams, ...cartoonProps }, color: symmetryColor, colorParams: symmetryColorParams }, { tag: 'polymer' }),
  166. ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams, color, colorParams: ballAndStickColor }, { tag: 'ligand' }),
  167. nonStandard: builder.buildRepresentation(update, components.nonStandard, { type: 'ball-and-stick', typeParams, color, colorParams: ballAndStickColor }, { tag: 'non-standard' }),
  168. branchedBallAndStick: builder.buildRepresentation(update, components.branched, { type: 'ball-and-stick', typeParams: { ...typeParams, alpha: 0.3 }, color, colorParams: ballAndStickColor }, { tag: 'branched-ball-and-stick' }),
  169. branchedSnfg3d: builder.buildRepresentation(update, components.branched, { type: 'carbohydrate', typeParams, color, colorParams: globalColorParams }, { tag: 'branched-snfg-3d' }),
  170. water: builder.buildRepresentation(update, components.water, { type: waterType, typeParams: { ...typeParams, alpha: 0.6, visuals: waterType === 'line' ? ['intra-bond', 'element-point'] : undefined }, color, colorParams: { carbonColor: { name: 'element-symbol', params: {} }, ...globalColorParams } }, { tag: 'water' }),
  171. ion: builder.buildRepresentation(update, components.ion, { type: 'ball-and-stick', typeParams, color, colorParams: { carbonColor: { name: 'element-symbol', params: {} }, ...globalColorParams } }, { tag: 'ion' }),
  172. lipid: builder.buildRepresentation(update, components.lipid, { type: lipidType, typeParams: { ...typeParams, alpha: 0.6, visuals: lipidType === 'line' ? ['intra-bond'] : undefined }, color, colorParams: { carbonColor: { name: 'element-symbol', params: {} }, ...globalColorParams } }, { tag: 'lipid' }),
  173. coarse: builder.buildRepresentation(update, components.coarse, { type: 'spacefill', typeParams, color: color || 'chain-id', colorParams: globalColorParams }, { tag: 'coarse' })
  174. };
  175. await update.commit({ revertOnError: false });
  176. await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
  177. return { components, representations };
  178. }
  179. });
  180. const proteinAndNucleic = StructureRepresentationPresetProvider({
  181. id: 'preset-structure-representation-protein-and-nucleic',
  182. display: {
  183. name: 'Protein & Nucleic', group: BuiltInPresetGroupName,
  184. description: 'Shows proteins as Cartoon and RNA/DNA as Gaussian Surface.'
  185. },
  186. params: () => CommonParams,
  187. async apply(ref, params, plugin) {
  188. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  189. if (!structureCell) return {};
  190. const components = {
  191. protein: await presetSelectionComponent(plugin, structureCell, 'protein'),
  192. nucleic: await presetSelectionComponent(plugin, structureCell, 'nucleic'),
  193. };
  194. const structure = structureCell.obj!.data;
  195. const cartoonProps = {
  196. sizeFactor: structure.isCoarseGrained ? 0.8 : 0.2,
  197. };
  198. const gaussianProps = {
  199. radiusOffset: structure.isCoarseGrained ? 2 : 0,
  200. smoothness: structure.isCoarseGrained ? 1.0 : 1.5,
  201. };
  202. const { update, builder, typeParams, symmetryColor, symmetryColorParams } = reprBuilder(plugin, params, structure);
  203. const representations = {
  204. protein: builder.buildRepresentation(update, components.protein, { type: 'cartoon', typeParams: { ...typeParams, ...cartoonProps }, color: symmetryColor, colorParams: symmetryColorParams }, { tag: 'protein' }),
  205. nucleic: builder.buildRepresentation(update, components.nucleic, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color: symmetryColor, colorParams: symmetryColorParams }, { tag: 'nucleic' })
  206. };
  207. await update.commit({ revertOnError: true });
  208. await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
  209. return { components, representations };
  210. }
  211. });
  212. const coarseSurface = StructureRepresentationPresetProvider({
  213. id: 'preset-structure-representation-coarse-surface',
  214. display: {
  215. name: 'Coarse Surface', group: BuiltInPresetGroupName,
  216. description: 'Shows polymers and lipids as coarse Gaussian Surface.'
  217. },
  218. params: () => CommonParams,
  219. async apply(ref, params, plugin) {
  220. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  221. if (!structureCell) return {};
  222. const components = {
  223. polymer: await presetStaticComponent(plugin, structureCell, 'polymer'),
  224. lipid: await presetStaticComponent(plugin, structureCell, 'lipid'),
  225. };
  226. const structure = structureCell.obj!.data;
  227. const size = Structure.getSize(structure);
  228. const gaussianProps = Object.create(null);
  229. if (size === Structure.Size.Gigantic) {
  230. Object.assign(gaussianProps, {
  231. traceOnly: !structure.isCoarseGrained,
  232. radiusOffset: 2,
  233. smoothness: 1,
  234. visuals: ['structure-gaussian-surface-mesh']
  235. });
  236. } else if (size === Structure.Size.Huge) {
  237. Object.assign(gaussianProps, {
  238. radiusOffset: structure.isCoarseGrained ? 2 : 0,
  239. smoothness: 1,
  240. });
  241. } else if (structure.isCoarseGrained) {
  242. Object.assign(gaussianProps, {
  243. radiusOffset: 2,
  244. smoothness: 1,
  245. });
  246. }
  247. const { update, builder, typeParams, symmetryColor, symmetryColorParams } = reprBuilder(plugin, params, structure);
  248. const representations = {
  249. polymer: builder.buildRepresentation(update, components.polymer, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color: symmetryColor, colorParams: symmetryColorParams }, { tag: 'polymer' }),
  250. lipid: builder.buildRepresentation(update, components.lipid, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color: symmetryColor, colorParams: symmetryColorParams }, { tag: 'lipid' })
  251. };
  252. await update.commit({ revertOnError: true });
  253. await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
  254. return { components, representations };
  255. }
  256. });
  257. const polymerCartoon = StructureRepresentationPresetProvider({
  258. id: 'preset-structure-representation-polymer-cartoon',
  259. display: {
  260. name: 'Polymer Cartoon', group: BuiltInPresetGroupName,
  261. description: 'Shows polymers as Cartoon.'
  262. },
  263. params: () => CommonParams,
  264. async apply(ref, params, plugin) {
  265. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  266. if (!structureCell) return {};
  267. const components = {
  268. polymer: await presetStaticComponent(plugin, structureCell, 'polymer'),
  269. };
  270. const structure = structureCell.obj!.data;
  271. const cartoonProps = {
  272. sizeFactor: structure.isCoarseGrained ? 0.8 : 0.2
  273. };
  274. const { update, builder, typeParams, symmetryColor, symmetryColorParams } = reprBuilder(plugin, params, structure);
  275. const representations = {
  276. polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams: { ...typeParams, ...cartoonProps }, color: symmetryColor, colorParams: symmetryColorParams }, { tag: 'polymer' })
  277. };
  278. await update.commit({ revertOnError: true });
  279. await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
  280. return { components, representations };
  281. }
  282. });
  283. const atomicDetail = StructureRepresentationPresetProvider({
  284. id: 'preset-structure-representation-atomic-detail',
  285. display: {
  286. name: 'Atomic Detail', group: BuiltInPresetGroupName,
  287. description: 'Shows everything in atomic detail with Ball & Stick.'
  288. },
  289. params: () => ({
  290. ...CommonParams,
  291. showCarbohydrateSymbol: PD.Boolean(false)
  292. }),
  293. async apply(ref, params, plugin) {
  294. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  295. if (!structureCell) return {};
  296. const components = {
  297. all: await presetStaticComponent(plugin, structureCell, 'all'),
  298. branched: undefined
  299. };
  300. const structure = structureCell.obj!.data;
  301. const highElementCount = structure.elementCount > 100_000; // TODO make configurable
  302. const lowResidueElementRatio = structure.atomicResidueCount &&
  303. structure.elementCount > 1000 &&
  304. structure.atomicResidueCount / structure.elementCount < 3;
  305. const m = structure.models[0];
  306. const bondsGiven = !!IndexPairBonds.Provider.get(m) || StructConn.isExhaustive(m);
  307. let atomicType: StructureRepresentationRegistry.BuiltIn = 'ball-and-stick';
  308. if (structure.isCoarseGrained) {
  309. // TODO make configurable?
  310. atomicType = structure.elementCount > 1_000_000 ? 'point' : 'spacefill';
  311. } else if (lowResidueElementRatio && !bondsGiven) {
  312. atomicType = 'spacefill';
  313. } else if (highElementCount) {
  314. atomicType = 'line';
  315. }
  316. const showCarbohydrateSymbol = params.showCarbohydrateSymbol && !highElementCount && !lowResidueElementRatio;
  317. if (showCarbohydrateSymbol) {
  318. Object.assign(components, {
  319. branched: await presetStaticComponent(plugin, structureCell, 'branched', { label: 'Carbohydrate' }),
  320. });
  321. }
  322. const { update, builder, typeParams, color, ballAndStickColor, globalColorParams } = reprBuilder(plugin, params, structure);
  323. const colorParams = lowResidueElementRatio && !bondsGiven
  324. ? { carbonColor: { name: 'element-symbol', params: {} }, ...globalColorParams }
  325. : ballAndStickColor;
  326. const representations = {
  327. all: builder.buildRepresentation(update, components.all, { type: atomicType, typeParams, color, colorParams }, { tag: 'all' }),
  328. };
  329. if (showCarbohydrateSymbol) {
  330. Object.assign(representations, {
  331. snfg3d: builder.buildRepresentation(update, components.branched, { type: 'carbohydrate', typeParams: { ...typeParams, alpha: 0.4, visuals: ['carbohydrate-symbol'] }, color, colorParams: globalColorParams }, { tag: 'snfg-3d' }),
  332. });
  333. }
  334. await update.commit({ revertOnError: true });
  335. await updateFocusRepr(plugin, structure, params.theme?.focus?.name ?? color, params.theme?.focus?.params ?? colorParams);
  336. return { components, representations };
  337. }
  338. });
  339. const illustrative = StructureRepresentationPresetProvider({
  340. id: 'preset-structure-representation-illustrative',
  341. display: {
  342. name: 'Illustrative', group: 'Miscellaneous',
  343. description: '...'
  344. },
  345. params: () => ({
  346. ...CommonParams,
  347. showCarbohydrateSymbol: PD.Boolean(false)
  348. }),
  349. async apply(ref, params, plugin) {
  350. const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
  351. if (!structureCell) return {};
  352. const components = {
  353. all: await presetStaticComponent(plugin, structureCell, 'all'),
  354. branched: undefined
  355. };
  356. const structure = structureCell.obj!.data;
  357. const { update, builder, typeParams, color } = reprBuilder(plugin, params, structure);
  358. const representations = {
  359. all: builder.buildRepresentation(update, components.all, { type: 'spacefill', typeParams: { ...typeParams, ignoreLight: true }, color: 'illustrative' }, { tag: 'all' }),
  360. };
  361. await update.commit({ revertOnError: true });
  362. await updateFocusRepr(plugin, structure, params.theme?.focus?.name ?? color, params.theme?.focus?.params);
  363. return { components, representations };
  364. }
  365. });
  366. export function presetStaticComponent(plugin: PluginContext, structure: StateObjectRef<PluginStateObject.Molecule.Structure>, type: StaticStructureComponentType, params?: { label?: string, tags?: string[] }) {
  367. return plugin.builders.structure.tryCreateComponentStatic(structure, type, params);
  368. }
  369. export function presetSelectionComponent(plugin: PluginContext, structure: StateObjectRef<PluginStateObject.Molecule.Structure>, query: keyof typeof Q, params?: { label?: string, tags?: string[] }) {
  370. return plugin.builders.structure.tryCreateComponentFromSelection(structure, Q[query], `selection-${query}`, params);
  371. }
  372. export const PresetStructureRepresentations = {
  373. empty,
  374. auto,
  375. 'atomic-detail': atomicDetail,
  376. 'polymer-cartoon': polymerCartoon,
  377. 'polymer-and-ligand': polymerAndLigand,
  378. 'protein-and-nucleic': proteinAndNucleic,
  379. 'coarse-surface': coarseSurface,
  380. illustrative,
  381. };
  382. export type PresetStructureRepresentations = typeof PresetStructureRepresentations;