Browse Source

symmetryColor representation preset option

David Sehnal 4 years ago
parent
commit
13f28fbe33

+ 10 - 6
src/apps/viewer/index.ts

@@ -35,6 +35,7 @@ import { PluginStateObject } from '../../mol-plugin-state/objects';
 import { StateTransforms } from '../../mol-plugin-state/transforms';
 import { createVolumeRepresentationParams } from '../../mol-plugin-state/helpers/volume-representation-params';
 import { Mp4Export } from '../../extensions/mp4-export';
+import { StructureRepresentationPresetProvider } from '../../mol-plugin-state/builder/structure/representation-preset';
 
 require('mol-plugin-ui/skin/light.scss');
 
@@ -147,7 +148,7 @@ export class Viewer {
         return PluginCommands.State.Snapshots.OpenUrl(this.plugin, { url, type });
     }
 
-    loadStructureFromUrl(url: string, format: BuiltInTrajectoryFormat = 'mmcif', isBinary = false) {
+    loadStructureFromUrl(url: string, format: BuiltInTrajectoryFormat = 'mmcif', isBinary = false, options?: LoadStructureOptions) {
         const params = DownloadStructure.createDefaultParams(this.plugin.state.data.root.obj!, this.plugin);
         return this.plugin.runTask(this.plugin.state.data.applyAction(DownloadStructure, {
             source: {
@@ -156,7 +157,7 @@ export class Viewer {
                     url: Asset.Url(url),
                     format: format as any,
                     isBinary,
-                    options: params.source.params.options,
+                    options: { ...params.source.params.options, representationParams: options?.representationParams as any },
                 }
             }
         }));
@@ -177,7 +178,7 @@ export class Viewer {
         await this.plugin.builders.structure.hierarchy.applyPreset(trajectory, 'default');
     }
 
-    loadPdb(pdb: string) {
+    loadPdb(pdb: string, options?: LoadStructureOptions) {
         const params = DownloadStructure.createDefaultParams(this.plugin.state.data.root.obj!, this.plugin);
         const provider = this.plugin.config.get(PluginConfig.Download.DefaultPdbProvider)!;
         return this.plugin.runTask(this.plugin.state.data.applyAction(DownloadStructure, {
@@ -191,7 +192,7 @@ export class Viewer {
                             params: PdbDownloadProvider[provider].defaultValue as any
                         }
                     },
-                    options: params.source.params.options,
+                    options: { ...params.source.params.options, representationParams: options?.representationParams as any },
                 }
             }
         }));
@@ -262,10 +263,13 @@ export class Viewer {
     }
 }
 
+export interface LoadStructureOptions {
+    representationParams?: StructureRepresentationPresetProvider.CommonParams
+}
+
 export interface VolumeIsovalueInfo {
     type: 'absolute' | 'relative',
     value: number,
     color: Color,
     alpha?: number
-}
-
+}

+ 6 - 3
src/mol-plugin-state/actions/structure.ts

@@ -9,7 +9,7 @@ import { PluginContext } from '../../mol-plugin/context';
 import { StateAction, StateSelection, StateTransformer } from '../../mol-state';
 import { Task } from '../../mol-task';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
-import { PresetStructureRepresentations } from '../builder/structure/representation-preset';
+import { PresetStructureRepresentations, StructureRepresentationPresetProvider } from '../builder/structure/representation-preset';
 import { BuiltInTrajectoryFormat, BuiltInTrajectoryFormats } from '../formats/trajectory';
 import { RootStructureDefinition } from '../helpers/root-structure';
 import { PluginStateObject } from '../objects';
@@ -24,6 +24,7 @@ const DownloadModelRepresentationOptions = (plugin: PluginContext) => PD.Group({
     representation: PD.Select(PresetStructureRepresentations.auto.id,
         plugin.builders.structure.representation.getPresets().map(p => [p.id, p.display.name, p.display.group] as any),
         { description: 'Which representation preset to use.' }),
+    representationParams: PD.Group(StructureRepresentationPresetProvider.CommonParams, { isHidden: true }),
     asTrajectory: PD.Optional(PD.Boolean(false, { description: 'Load all entries into a single trajectory.' }))
 }, { isExpanded: false });
 
@@ -144,7 +145,8 @@ const DownloadStructure = StateAction.build({
             await plugin.builders.structure.hierarchy.applyPreset(trajectory, 'default', {
                 structure,
                 showUnitcell,
-                representationPreset
+                representationPreset,
+                representationPresetParams: params.source.params.options.representationParams
             });
         } else {
             for (const download of downloadParams) {
@@ -154,7 +156,8 @@ const DownloadStructure = StateAction.build({
                 await plugin.builders.structure.hierarchy.applyPreset(trajectory, 'default', {
                     structure,
                     showUnitcell,
-                    representationPreset
+                    representationPreset,
+                    representationPresetParams: params.source.params.options.representationParams
                 });
             }
         }

+ 4 - 3
src/mol-plugin-state/builder/structure/hierarchy-preset.ts

@@ -11,7 +11,7 @@ import { ParamDefinition as PD } from '../../../mol-util/param-definition';
 import { StateObjectRef, StateTransformer } from '../../../mol-state';
 import { StateTransforms } from '../../transforms';
 import { RootStructureDefinition } from '../../helpers/root-structure';
-import { PresetStructureRepresentations } from './representation-preset';
+import { PresetStructureRepresentations, StructureRepresentationPresetProvider } from './representation-preset';
 import { PluginContext } from '../../../mol-plugin/context';
 import { Vec3 } from '../../../mol-math/linear-algebra';
 import { Model } from '../../../mol-model/structure';
@@ -27,7 +27,7 @@ export namespace TrajectoryHierarchyPresetProvider {
     export const CommonParams = (a: PluginStateObject.Molecule.Trajectory | undefined, plugin: PluginContext) => ({
         modelProperties: PD.Optional(PD.Group(StateTransformer.getParamDefinition(StateTransforms.Model.CustomModelProperties, void 0, plugin))),
         structureProperties: PD.Optional(PD.Group(StateTransformer.getParamDefinition(StateTransforms.Model.CustomStructureProperties, void 0, plugin))),
-        representationPreset: PD.Optional(PD.Text<keyof PresetStructureRepresentations>('auto' as const)),
+        representationPreset: PD.Optional(PD.Text<keyof PresetStructureRepresentations>('auto' as const))
     });
 }
 
@@ -37,6 +37,7 @@ const DefaultParams = (a: PluginStateObject.Molecule.Trajectory | undefined, plu
     model: PD.Optional(PD.Group(StateTransformer.getParamDefinition(StateTransforms.Model.ModelFromTrajectory, a, plugin))),
     showUnitcell: PD.Optional(PD.Boolean(false)),
     structure: PD.Optional(RootStructureDefinition.getParams(void 0, 'assembly').type),
+    representationPresetParams: PD.Optional(PD.Group(StructureRepresentationPresetProvider.CommonParams)),
     ...CommonParams(a, plugin)
 });
 
@@ -60,7 +61,7 @@ const defaultPreset = TrajectoryHierarchyPresetProvider({
         const structureProperties = await builder.insertStructureProperties(structure, params.structureProperties);
 
         const unitcell = params.showUnitcell === void 0 || !!params.showUnitcell ? await builder.tryCreateUnitcell(modelProperties, undefined, { isHidden: true }) : void 0;
-        const representation = await plugin.builders.structure.representation.applyPreset(structureProperties, params.representationPreset || 'auto');
+        const representation = await plugin.builders.structure.representation.applyPreset(structureProperties, params.representationPreset || 'auto', params.representationPresetParams);
 
         return {
             model,

+ 23 - 12
src/mol-plugin-state/builder/structure/representation-preset.ts

@@ -37,6 +37,7 @@ export namespace StructureRepresentationPresetProvider {
         theme: PD.Optional(PD.Group({
             globalName: PD.Optional(PD.Text<ColorTheme.BuiltIn>('')),
             carbonColor: PD.Optional(PD.Select('chain-id', PD.arrayToOptions(['chain-id', 'operator-name', 'element-symbol'] as const))),
+            symmetryColor: PD.Optional(PD.Text<ColorTheme.BuiltIn>('')),
             focus: PD.Optional(PD.Group({
                 name: PD.Optional(PD.Text<ColorTheme.BuiltIn>('')),
                 params: PD.Optional(PD.Value<ColorTheme.BuiltInParams<ColorTheme.BuiltIn>>({} as any))
@@ -53,7 +54,11 @@ export namespace StructureRepresentationPresetProvider {
                 : { name, params: {} };
     }
 
-    export function reprBuilder(plugin: PluginContext, params: CommonParams) {
+    function isSymmetry(structure: Structure) {
+        return structure.units.some(u => !u.conformation.operator.assembly && u.conformation.operator.spgrOp >= 0);
+    }
+
+    export function reprBuilder(plugin: PluginContext, params: CommonParams, structure?: Structure) {
         const update = plugin.state.data.build();
         const builder = plugin.builders.structure.representation;
         const typeParams = {
@@ -66,8 +71,11 @@ export namespace StructureRepresentationPresetProvider {
         const ballAndStickColor: ColorTheme.BuiltInParams<'element-symbol'> = params.theme?.carbonColor !== undefined
             ? { carbonColor: getCarbonColorParams(params.theme?.carbonColor) }
             : { };
+        const symmetryColor: ColorTheme.BuiltIn | undefined = structure && params.theme?.symmetryColor
+            ? isSymmetry(structure) ? params.theme?.symmetryColor : color
+            : color;
 
-        return { update, builder, color, typeParams, ballAndStickColor };
+        return { update, builder, color, symmetryColor, typeParams, ballAndStickColor };
     }
 
     export function updateFocusRepr<T extends ColorTheme.BuiltIn>(plugin: PluginContext, structure: Structure, themeName: T | undefined, themeParams: ColorTheme.BuiltInParams<T> | undefined) {
@@ -156,10 +164,10 @@ const polymerAndLigand = StructureRepresentationPresetProvider({
         const waterType = (components.water?.obj?.data?.elementCount || 0) > 50_000 ? 'line' : 'ball-and-stick';
         const lipidType = (components.lipid?.obj?.data?.elementCount || 0) > 20_000 ? 'line' : 'ball-and-stick';
 
-        const { update, builder, typeParams, color, ballAndStickColor } = reprBuilder(plugin, params);
+        const { update, builder, typeParams, color, symmetryColor, ballAndStickColor } = reprBuilder(plugin, params, structure);
 
         const representations = {
-            polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams: { ...typeParams, ...cartoonProps }, color }, { tag: 'polymer' }),
+            polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams: { ...typeParams, ...cartoonProps }, color: symmetryColor }, { tag: 'polymer' }),
             ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams, color, colorParams: ballAndStickColor }, { tag: 'ligand' }),
             nonStandard: builder.buildRepresentation(update, components.nonStandard, { type: 'ball-and-stick', typeParams, color, colorParams: ballAndStickColor }, { tag: 'non-standard' }),
             branchedBallAndStick: builder.buildRepresentation(update, components.branched, { type: 'ball-and-stick', typeParams: { ...typeParams, alpha: 0.3 }, color, colorParams: ballAndStickColor }, { tag: 'branched-ball-and-stick' }),
@@ -202,10 +210,11 @@ const proteinAndNucleic = StructureRepresentationPresetProvider({
             smoothness: structure.isCoarseGrained ? 0.5 : 1.5,
         };
 
-        const { update, builder, typeParams, color } = reprBuilder(plugin, params);
+        const { update, builder, typeParams, symmetryColor } = reprBuilder(plugin, params, structure);
+
         const representations = {
-            protein: builder.buildRepresentation(update, components.protein, { type: 'cartoon', typeParams: { ...typeParams, ...cartoonProps }, color }, { tag: 'protein' }),
-            nucleic: builder.buildRepresentation(update, components.nucleic, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color }, { tag: 'nucleic' })
+            protein: builder.buildRepresentation(update, components.protein, { type: 'cartoon', typeParams: { ...typeParams, ...cartoonProps }, color: symmetryColor }, { tag: 'protein' }),
+            nucleic: builder.buildRepresentation(update, components.nucleic, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color: symmetryColor }, { tag: 'nucleic' })
         };
 
         await update.commit({ revertOnError: true });
@@ -252,9 +261,10 @@ const coarseSurface = StructureRepresentationPresetProvider({
             });
         }
 
-        const { update, builder, typeParams, color } = reprBuilder(plugin, params);
+        const { update, builder, typeParams, symmetryColor } = reprBuilder(plugin, params, structure);
+
         const representations = {
-            polymer: builder.buildRepresentation(update, components.polymer, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color }, { tag: 'polymer' })
+            polymer: builder.buildRepresentation(update, components.polymer, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color: symmetryColor }, { tag: 'polymer' })
         };
 
         await update.commit({ revertOnError: true });
@@ -284,9 +294,10 @@ const polymerCartoon = StructureRepresentationPresetProvider({
             sizeFactor: structure.isCoarseGrained ? 0.8 : 0.2
         };
 
-        const { update, builder, typeParams, color } = reprBuilder(plugin, params);
+        const { update, builder, typeParams, symmetryColor } = reprBuilder(plugin, params, structure);
+
         const representations = {
-            polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams: { ...typeParams, ...cartoonProps }, color }, { tag: 'polymer' })
+            polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams: { ...typeParams, ...cartoonProps }, color: symmetryColor }, { tag: 'polymer' })
         };
 
         await update.commit({ revertOnError: true });
@@ -331,7 +342,7 @@ const atomicDetail = StructureRepresentationPresetProvider({
             });
         }
 
-        const { update, builder, typeParams, color, ballAndStickColor } = reprBuilder(plugin, params);
+        const { update, builder, typeParams, color, ballAndStickColor } = reprBuilder(plugin, params, structure);
         const colorParams = lowResidueElementRatio
             ? { carbonColor: { name: 'element-symbol', params: {} } }
             : ballAndStickColor;