From 09fba43a1ce07f85e2a620dd2cfa046a7a83b132 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Sat, 28 Mar 2020 14:00:01 +0100
Subject: [PATCH] mol-plugin-state: representation presets "sync" instead of
recreate
---
src/apps/state-docs/pd-to-md.ts | 2 +-
src/mol-plugin-state/actions/structure.ts | 2 +-
.../builder/preset-provider.ts | 2 +-
src/mol-plugin-state/builder/structure.ts | 4 +-
.../structure/representation-preset.ts | 67 +++++++++++--------
.../builder/structure/representation.ts | 15 +++--
.../manager/structure/component.ts | 44 +++++++++++-
src/mol-plugin-ui/structure/components.tsx | 8 +--
.../custom-props/rcsb/assembly-symmetry.ts | 9 +--
.../custom-props/rcsb/validation-report.ts | 13 ++--
src/mol-util/param-definition.ts | 6 +-
11 files changed, 108 insertions(+), 64 deletions(-)
diff --git a/src/apps/state-docs/pd-to-md.ts b/src/apps/state-docs/pd-to-md.ts
index e26624b76..13e876ed7 100644
--- a/src/apps/state-docs/pd-to-md.ts
+++ b/src/apps/state-docs/pd-to-md.ts
@@ -39,7 +39,7 @@ function paramInfo(param: PD.Any, offset: number): string {
}
}
-function oToS(options: readonly (readonly [string, string] | readonly [string, string, string])[]) {
+function oToS(options: readonly (readonly [string, string] | readonly [string, string, string | undefined])[]) {
return options.map(o => `'${o[0]}'`).join(', ');
}
diff --git a/src/mol-plugin-state/actions/structure.ts b/src/mol-plugin-state/actions/structure.ts
index 80da538b4..84f21f932 100644
--- a/src/mol-plugin-state/actions/structure.ts
+++ b/src/mol-plugin-state/actions/structure.ts
@@ -129,7 +129,7 @@ export const DcdProvider: DataFormatProvider<any> = {
const DownloadModelRepresentationOptions = (plugin: PluginContext) => PD.Group({
type: RootStructureDefinition.getParams(void 0, 'auto').type,
representation: PD.Select(PresetStructureRepresentations.auto.id,
- plugin.builders.structure.representation.getPresets().map(p => [p.id, p.display.name] as any),
+ plugin.builders.structure.representation.getPresets().map(p => [p.id, p.display.name, p.display.group] as any),
{ description: 'Which representation preset to use.' }),
asTrajectory: PD.Optional(PD.Boolean(false, { description: 'Load all entries into a single trajectory.' }))
}, { isExpanded: false });
diff --git a/src/mol-plugin-state/builder/preset-provider.ts b/src/mol-plugin-state/builder/preset-provider.ts
index 5893d4186..23993590f 100644
--- a/src/mol-plugin-state/builder/preset-provider.ts
+++ b/src/mol-plugin-state/builder/preset-provider.ts
@@ -10,7 +10,7 @@ import { ParamDefinition as PD } from '../../mol-util/param-definition';
export interface PresetProvider<O extends StateObject = StateObject, P = any, S = {}> {
id: string,
- display: { name: string, group: string, description?: string },
+ display: { name: string, group?: string, description?: string },
isApplicable?(a: O, plugin: PluginContext): boolean,
params?(a: O | undefined, plugin: PluginContext): PD.For<P>,
apply(a: StateObjectRef<O>, params: P, plugin: PluginContext): Promise<S> | S
diff --git a/src/mol-plugin-state/builder/structure.ts b/src/mol-plugin-state/builder/structure.ts
index fc2161ff1..0e7301343 100644
--- a/src/mol-plugin-state/builder/structure.ts
+++ b/src/mol-plugin-state/builder/structure.ts
@@ -118,7 +118,7 @@ export class StructureBuilder {
}
/** returns undefined if the component is empty/null */
- async tryCreateComponent(structure: StateObjectRef<SO.Molecule.Structure>, params: StructureComponentParams, key: string, tags?: string[]): Promise<StateObjectRef<SO.Molecule.Structure> | undefined> {
+ async tryCreateComponent(structure: StateObjectRef<SO.Molecule.Structure>, params: StructureComponentParams, key: string, tags?: string[]): Promise<StateObjectSelector<SO.Molecule.Structure> | undefined> {
const state = this.dataState;
const root = state.build().to(structure);
@@ -157,7 +157,7 @@ export class StructureBuilder {
}, key, params?.tags);
}
- tryCreateComponentFromSelection(structure: StateObjectRef<SO.Molecule.Structure>, selection: StructureSelectionQuery, key: string, params?: { label?: string, tags?: string[] }): Promise<StateObjectRef<SO.Molecule.Structure> | undefined> {
+ tryCreateComponentFromSelection(structure: StateObjectRef<SO.Molecule.Structure>, selection: StructureSelectionQuery, key: string, params?: { label?: string, tags?: string[] }): Promise<StateObjectSelector<SO.Molecule.Structure> | undefined> {
return this.plugin.runTask(Task.create('Query Component', async taskCtx => {
let { label, tags } = params || { };
label = (label || '').trim();
diff --git a/src/mol-plugin-state/builder/structure/representation-preset.ts b/src/mol-plugin-state/builder/structure/representation-preset.ts
index 7de5d1256..413dd5485 100644
--- a/src/mol-plugin-state/builder/structure/representation-preset.ts
+++ b/src/mol-plugin-state/builder/structure/representation-preset.ts
@@ -12,15 +12,19 @@ import { VisualQuality, VisualQualityOptions } from '../../../mol-geo/geometry/b
import { ColorTheme } from '../../../mol-theme/color';
import { Structure } from '../../../mol-model/structure';
import { PluginContext } from '../../../mol-plugin/context';
-import { StateObjectRef } from '../../../mol-state';
+import { StateObjectRef, StateObjectSelector } from '../../../mol-state';
import { StaticStructureComponentType } from '../../helpers/structure-component';
import { StructureSelectionQueries as Q } from '../../helpers/structure-selection-query';
-export interface StructureRepresentationPresetProvider<P = any, S = {}> extends PresetProvider<PluginStateObject.Molecule.Structure, P, S> { }
-export function StructureRepresentationPresetProvider<P, S>(repr: StructureRepresentationPresetProvider<P, S>) { return repr; }
+export interface StructureRepresentationPresetProvider<P = any, S extends _Result = _Result> extends PresetProvider<PluginStateObject.Molecule.Structure, P, S> { }
+export function StructureRepresentationPresetProvider<P, S extends _Result>(repr: StructureRepresentationPresetProvider<P, S>) { return repr; }
export namespace StructureRepresentationPresetProvider {
export type Params<P extends StructureRepresentationPresetProvider> = P extends StructureRepresentationPresetProvider<infer T> ? T : never;
export type State<P extends StructureRepresentationPresetProvider> = P extends StructureRepresentationPresetProvider<infer _, infer S> ? S : never;
+ export type Result = {
+ components?: { [name: string]: StateObjectSelector | undefined },
+ representations?: { [name: string]: StateObjectSelector | undefined }
+ }
export const CommonParams = {
ignoreHydrogens: PD.Optional(PD.Boolean(false)),
@@ -44,13 +48,15 @@ export namespace StructureRepresentationPresetProvider {
}
}
+type _Result = StructureRepresentationPresetProvider.Result
+
const CommonParams = StructureRepresentationPresetProvider.CommonParams
type CommonParams = StructureRepresentationPresetProvider.CommonParams
const reprBuilder = StructureRepresentationPresetProvider.reprBuilder
const auto = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-auto',
- display: { name: 'Automatic', group: 'Preset' },
+ display: { name: 'Automatic' },
params: () => CommonParams,
apply(ref, params, plugin) {
const structure = StateObjectRef.resolveAndCheck(plugin.state.data, ref)?.obj?.data;
@@ -73,15 +79,17 @@ const auto = StructureRepresentationPresetProvider({
const empty = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-empty',
- display: { name: 'Empty', group: 'Preset' },
+ display: { name: 'Empty' },
async apply(ref, params, plugin) {
- return { };
+ return { };
}
});
+const BuiltInPresetGroupName = 'Basic'
+
const polymerAndLigand = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-polymer-and-ligand',
- display: { name: 'Polymer & Ligand', group: 'Preset' },
+ display: { name: 'Polymer & Ligand', group: BuiltInPresetGroupName },
params: () => CommonParams,
async apply(ref, params, plugin) {
const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
@@ -98,15 +106,13 @@ const polymerAndLigand = StructureRepresentationPresetProvider({
const { update, builder, typeParams, color } = reprBuilder(plugin, params);
const representations = {
- polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams, color }),
- ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams, color }),
- nonStandard: builder.buildRepresentation(update, components.nonStandard, { type: 'ball-and-stick', typeParams, color: color || 'polymer-id' }),
- branched: components.branched && {
- ballAndStick: builder.buildRepresentation(update, components.branched, { type: 'ball-and-stick', typeParams: { ...typeParams, alpha: 0.15 }, color }),
- snfg3d: builder.buildRepresentation(update, components.branched, { type: 'carbohydrate', typeParams, color }),
- },
- water: builder.buildRepresentation(update, components.water, { type: 'ball-and-stick', typeParams: { ...typeParams, alpha: 0.51 }, color }),
- coarse: builder.buildRepresentation(update, components.coarse, { type: 'spacefill', typeParams, color: color || 'polymer-id' })
+ polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams, color }, { tag: 'polymer' }),
+ ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams, color }, { tag: 'ligand' }),
+ nonStandard: builder.buildRepresentation(update, components.nonStandard, { type: 'ball-and-stick', typeParams, color: color || 'polymer-id' }, { tag: 'non-standard' }),
+ branchedBallAndStick: builder.buildRepresentation(update, components.branched, { type: 'ball-and-stick', typeParams: { ...typeParams, alpha: 0.15 }, color }, { tag: 'branched-ball-and-stick' }),
+ branchedSnfg3d: builder.buildRepresentation(update, components.branched, { type: 'carbohydrate', typeParams, color }, { tag: 'branched-snfg-3d' }),
+ water: builder.buildRepresentation(update, components.water, { type: 'ball-and-stick', typeParams: { ...typeParams, alpha: 0.51 }, color }, { tag: 'water' }),
+ coarse: builder.buildRepresentation(update, components.coarse, { type: 'spacefill', typeParams, color: color || 'polymer-id' }, { tag: 'coarse' })
};
await plugin.updateDataState(update, { revertOnError: false });
@@ -116,7 +122,7 @@ const polymerAndLigand = StructureRepresentationPresetProvider({
const proteinAndNucleic = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-protein-and-nucleic',
- display: { name: 'Protein & Nucleic', group: 'Preset' },
+ display: { name: 'Protein & Nucleic', group: BuiltInPresetGroupName },
params: () => CommonParams,
async apply(ref, params, plugin) {
const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
@@ -129,8 +135,8 @@ const proteinAndNucleic = StructureRepresentationPresetProvider({
const { update, builder, typeParams, color } = reprBuilder(plugin, params);
const representations = {
- protein: builder.buildRepresentation(update, components.protein, { type: 'cartoon', typeParams, color }),
- nucleic: builder.buildRepresentation(update, components.nucleic, { type: 'gaussian-surface', typeParams, color })
+ protein: builder.buildRepresentation(update, components.protein, { type: 'cartoon', typeParams, color }, { tag: 'protein' }),
+ nucleic: builder.buildRepresentation(update, components.nucleic, { type: 'gaussian-surface', typeParams, color }, { tag: 'nucleic' })
};
await plugin.updateDataState(update, { revertOnError: true });
@@ -140,7 +146,7 @@ const proteinAndNucleic = StructureRepresentationPresetProvider({
const coarseSurface = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-coarse-surface',
- display: { name: 'Coarse Surface', group: 'Preset' },
+ display: { name: 'Coarse Surface', group: BuiltInPresetGroupName },
params: () => CommonParams,
async apply(ref, params, plugin) {
const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
@@ -152,26 +158,29 @@ const coarseSurface = StructureRepresentationPresetProvider({
const gaussianProps = Object.create(null);
const components = Object.create(null);
+ let selectionType = 'polymer'
+
if (size === Structure.Size.Gigantic) {
Object.assign(gaussianProps, {
radiusOffset: 1,
smoothness: 0.5,
visuals: ['structure-gaussian-surface-mesh']
})
+ selectionType = 'trace'
components.trace = await presetSelectionComponent(plugin, structureCell, 'trace')
} else if(size === Structure.Size.Huge) {
Object.assign(gaussianProps, {
smoothness: 0.5,
})
- components.trace = await presetSelectionComponent(plugin, structureCell, 'polymer')
+ components.trace = await presetStaticComponent(plugin, structureCell, 'polymer')
} else {
- components.trace = await presetSelectionComponent(plugin, structureCell, 'polymer')
+ components.trace = await presetStaticComponent(plugin, structureCell, 'polymer')
}
const { update, builder, typeParams, color } = reprBuilder(plugin, params);
const representations = {
- trace: builder.buildRepresentation(update, components.trace, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color })
+ trace: builder.buildRepresentation(update, components.trace, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color }, { tag: selectionType })
};
await plugin.updateDataState(update, { revertOnError: true });
@@ -181,19 +190,19 @@ const coarseSurface = StructureRepresentationPresetProvider({
const polymerCartoon = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-polymer-cartoon',
- display: { name: 'Polymer Cartoon', group: 'Preset' },
+ display: { name: 'Polymer Cartoon', group: BuiltInPresetGroupName },
params: () => CommonParams,
async apply(ref, params, plugin) {
const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
if (!structureCell) return {};
const components = {
- polymer: await presetSelectionComponent(plugin, structureCell, 'polymer'),
+ polymer: await presetStaticComponent(plugin, structureCell, 'polymer'),
};
const { update, builder, typeParams, color } = reprBuilder(plugin, params);
const representations = {
- polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams, color })
+ polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams, color }, { tag: 'polymer' })
};
await plugin.updateDataState(update, { revertOnError: true });
@@ -203,19 +212,19 @@ const polymerCartoon = StructureRepresentationPresetProvider({
const atomicDetail = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-atomic-detail',
- display: { name: 'Atomic Detail', group: 'Preset' },
+ display: { name: 'Atomic Detail', group: BuiltInPresetGroupName },
params: () => CommonParams,
async apply(ref, params, plugin) {
const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
if (!structureCell) return {};
const components = {
- all: await presetSelectionComponent(plugin, structureCell, 'all'),
+ all: await presetStaticComponent(plugin, structureCell, 'all'),
};
const { update, builder, typeParams, color } = reprBuilder(plugin, params);
const representations = {
- all: builder.buildRepresentation(update, components.all, { type: 'ball-and-stick', typeParams, color })
+ all: builder.buildRepresentation(update, components.all, { type: 'ball-and-stick', typeParams, color }, { tag: 'all' })
};
await plugin.updateDataState(update, { revertOnError: true });
diff --git a/src/mol-plugin-state/builder/structure/representation.ts b/src/mol-plugin-state/builder/structure/representation.ts
index 1ab82c5f7..7bde496a8 100644
--- a/src/mol-plugin-state/builder/structure/representation.ts
+++ b/src/mol-plugin-state/builder/structure/representation.ts
@@ -54,10 +54,10 @@ export class StructureRepresentationBuilder {
}
getPresetSelect(s?: PluginStateObject.Molecule.Structure): PD.Select<string> {
- const options: [string, string][] = [];
+ const options: [string, string, string | undefined][] = [];
for (const p of this._providers) {
if (s && p.isApplicable && !p.isApplicable(s, this.plugin)) continue;
- options.push([p.id, p.display.name]);
+ options.push([p.id, p.display.name, p.display.group]);
}
return PD.Select('auto', options);
}
@@ -121,16 +121,17 @@ export class StructureRepresentationBuilder {
return selector;
}
- 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>>
- 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>>
- async buildRepresentation(builder: StateBuilder.Root, structure: StateObjectRef<PluginStateObject.Molecule.Structure> | undefined, props: any, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>) {
+ buildRepresentation<P extends StructureRepresentationBuiltInProps>(builder: StateBuilder.Root, structure: StateObjectRef<PluginStateObject.Molecule.Structure> | undefined, props: P, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>): StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>
+ buildRepresentation<P extends StructureRepresentationProps>(builder: StateBuilder.Root, structure: StateObjectRef<PluginStateObject.Molecule.Structure> | undefined, props: P, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>): StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>
+ buildRepresentation(builder: StateBuilder.Root, structure: StateObjectRef<PluginStateObject.Molecule.Structure> | undefined, props: any, options?: Partial<StructureRepresentationBuilder.AddRepresentationOptions>) {
if (!structure) return;
const data = StateObjectRef.resolveAndCheck(this.dataState, structure)?.obj?.data;
if (!data) return;
const params = createStructureRepresentationParams(this.plugin, data, props);
- return builder.to(structure)
- .apply(StructureRepresentation3D, params, { tags: options?.tag, state: options?.initialState }).selector;
+ return options?.tag
+ ? builder.to(structure).applyOrUpdateTagged(options.tag, StructureRepresentation3D, params, { state: options?.initialState }).selector
+ : builder.to(structure).apply(StructureRepresentation3D, params, { state: options?.initialState }).selector;
}
constructor(public plugin: PluginContext) {
diff --git a/src/mol-plugin-state/manager/structure/component.ts b/src/mol-plugin-state/manager/structure/component.ts
index a6580a8c4..d3dbb43ce 100644
--- a/src/mol-plugin-state/manager/structure/component.ts
+++ b/src/mol-plugin-state/manager/structure/component.ts
@@ -25,6 +25,7 @@ import { HierarchyRef, StructureComponentRef, StructureRef, StructureRepresentat
import { createStructureColorThemeParams, createStructureSizeThemeParams } from '../../helpers/structure-representation-params';
import { ColorTheme } from '../../../mol-theme/color';
import { SizeTheme } from '../../../mol-theme/size';
+import { objectForEach } from '../../../mol-util/object';
export { StructureComponentManager };
@@ -103,15 +104,52 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
}
}
- applyPreset<P = any, S = {}>(structures: ReadonlyArray<StructureRef>, provider: StructureRepresentationPresetProvider<P, S>, params?: P): Promise<any> {
+ applyPreset<P extends StructureRepresentationPresetProvider>(structures: ReadonlyArray<StructureRef>, provider: P, params?: StructureRepresentationPresetProvider.Params<P>): Promise<any> {
return this.plugin.dataTransaction(async () => {
- await this.clearComponents(structures);
for (const s of structures) {
- await this.plugin.builders.structure.representation.applyPreset(s.cell, provider, params);
+ const preset = await this.plugin.builders.structure.representation.applyPreset(s.cell, provider, params);
+ await this.syncPreset(s, preset);
}
}, { canUndo: 'Preset' });
}
+ private async syncPreset(root: StructureRef, preset?: StructureRepresentationPresetProvider.Result) {
+ if (!preset || !preset.components) return this.clearComponents([root]);
+
+ const keptRefs = new Set<string>();
+ objectForEach(preset.components, c => {
+ if (c) keptRefs.add(c.ref);
+ });
+
+ if (preset.representations) {
+ objectForEach(preset.representations, r => {
+ if (r) keptRefs.add(r.ref);
+ });
+ }
+
+ if (keptRefs.size === 0) return this.clearComponents([root]);
+
+ let changed = false;
+ const update = this.dataState.build();
+
+ const sync = (r: HierarchyRef) => {
+ if (!keptRefs.has(r.cell.transform.ref)) {
+ changed = true;
+ update.delete(r.cell);
+ }
+ };
+
+ for (const c of root.components) {
+ sync(c);
+ for (const r of c.representations) sync(r);
+ if (c.genericRepresentations) {
+ for (const r of c.genericRepresentations) sync(r);
+ }
+ }
+
+ if (changed) return this.plugin.updateDataState(update);
+ }
+
clear(structures: ReadonlyArray<StructureRef>) {
return this.clearComponents(structures);
}
diff --git a/src/mol-plugin-ui/structure/components.tsx b/src/mol-plugin-ui/structure/components.tsx
index 0e33bd70d..a9d3ca5e2 100644
--- a/src/mol-plugin-ui/structure/components.tsx
+++ b/src/mol-plugin-ui/structure/components.tsx
@@ -90,13 +90,9 @@ class ComponentEditorControls extends PurePluginUIComponent<{}, ComponentEditorC
}
get presetActions() {
- const actions = [];
const pivot = this.plugin.managers.structure.component.pivotStructure;
- const providers = this.plugin.builders.structure.representation.getPresets(pivot?.cell.obj)
- for (const p of providers) {
- actions.push(ActionMenu.Item(p.display.name, p));
- }
- return actions;
+ const providers = this.plugin.builders.structure.representation.getPresets(pivot?.cell.obj);
+ return ActionMenu.createItems(providers, { label: p => p.display.name, category: p => p.display.group });
}
applyPreset: ActionMenu.OnSelect = item => {
diff --git a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts
index 92e7a421a..69290fb60 100644
--- a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts
+++ b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts
@@ -146,16 +146,17 @@ const AssemblySymmetry3D = PluginStateTransform.BuiltIn({
const assemblySymmetryPreset = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-rcsb-assembly-symmetry',
- display: { name: 'Assembly Symmetry', group: 'Preset' },
+ display: { name: 'Assembly Symmetry', group: 'Annotation' },
params: () => StructureRepresentationPresetProvider.CommonParams,
async apply(ref, params, plugin) {
const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
- const model = structureCell?.obj?.data.model
+ const model = structureCell?.obj?.data.model;
if (!structureCell || !model) return {};
- await tryCreateAssemblySymmetry(plugin, structureCell)
+ const assemblySymmetry = await tryCreateAssemblySymmetry(plugin, structureCell);
+ const repr = await PresetStructureRepresentations.auto.apply(ref, { ...params, globalThemeName: Tag.Cluster as any }, plugin);
- return await PresetStructureRepresentations.auto.apply(ref, { ...params, globalThemeName: Tag.Cluster as any }, plugin)
+ return { components: repr.components, representations: { ...repr.components, assemblySymmetry } };
}
});
diff --git a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/validation-report.ts b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/validation-report.ts
index 880e3cee1..0f2b9ff68 100644
--- a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/validation-report.ts
+++ b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/validation-report.ts
@@ -290,7 +290,7 @@ const hasClash = StructureSelectionQuery('Residues with Clashes', MS.struct.modi
const validationReportPreset = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-rcsb-validation-report',
- display: { name: 'Validation Report', group: 'Preset' },
+ display: { name: 'Validation Report', group: 'Annotation' },
params: () => StructureRepresentationPresetProvider.CommonParams,
async apply(ref, params, plugin) {
const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
@@ -305,17 +305,16 @@ const validationReportPreset = StructureRepresentationPresetProvider({
const { components, representations } = await PresetStructureRepresentations.auto.apply(ref, { ...params, globalThemeName: colorTheme }, plugin)
- components.clashes = await plugin.builders.structure.tryCreateComponentFromExpression(structureCell, hasClash.expression, 'clashes', { label: 'Clashes' })
+ const clashes = await plugin.builders.structure.tryCreateComponentFromExpression(structureCell, hasClash.expression, 'clashes', { label: 'Clashes' })
const { update, builder, typeParams, color } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
+ let clashesBallAndStick, clashesSnfg3d;
if (representations) {
- (representations as any).clashes = components.clashes && {
- ballAndStick: builder.buildRepresentation(update, components.clashes, { type: 'ball-and-stick', typeParams, color: colorTheme }),
- snfg3d: builder.buildRepresentation<any>(update, components.clashes, { type: ClashesRepresentationProvider.name, typeParams, color }),
- }
+ clashesBallAndStick = builder.buildRepresentation(update, components.clashes, { type: 'ball-and-stick', typeParams, color: colorTheme }, { tag: 'clashes-ball-and-stick' });
+ clashesSnfg3d = builder.buildRepresentation<any>(update, components.clashes, { type: ClashesRepresentationProvider.name, typeParams, color }, { tag: 'clashes-snfg-3d' });
}
await plugin.updateDataState(update, { revertOnError: false });
- return { components, representations };
+ return { components: { ...components, clashes }, representations: { ...representations, clashesBallAndStick, clashesSnfg3d } };
}
});
\ No newline at end of file
diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts
index 0784933c1..67151e712 100644
--- a/src/mol-util/param-definition.ts
+++ b/src/mol-util/param-definition.ts
@@ -74,10 +74,10 @@ export namespace ParamDefinition {
export interface Select<T> extends Base<T> {
type: 'select'
/** array of (value, label) tuples */
- options: readonly (readonly [T, string] | readonly [T, string, string])[]
+ options: readonly (readonly [T, string] | readonly [T, string, string | undefined])[]
cycle?: boolean
}
- export function Select<T>(defaultValue: T, options: readonly (readonly [T, string] | readonly [T, string, string])[], info?: Info & { cycle?: boolean }): Select<T> {
+ export function Select<T>(defaultValue: T, options: readonly (readonly [T, string] | readonly [T, string, string | undefined])[], info?: Info & { cycle?: boolean }): Select<T> {
return setInfo<Select<T>>({ type: 'select', defaultValue: checkDefaultKey(defaultValue, options), options, cycle: info?.cycle }, info)
}
@@ -469,7 +469,7 @@ export namespace ParamDefinition {
return ret;
}
- function checkDefaultKey<T>(k: T, options: readonly (readonly [T, string] | readonly [T, string, string])[]) {
+ function checkDefaultKey<T>(k: T, options: readonly (readonly [T, string] | readonly [T, string, string | undefined])[]) {
for (const o of options) {
if (o[0] === k) return k;
}
--
GitLab