Browse Source

crystal-contacts preset, color theme tweaks

Alexander Rose 4 years ago
parent
commit
1a29159dfd

+ 6 - 6
src/apps/docking-viewer/viewport.tsx

@@ -94,7 +94,7 @@ export const StructurePreset = StructureRepresentationPresetProvider({
 
         const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
         const representations = {
-            ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, sizeFactor: 0.35 }, color: 'element-symbol', colorParams: { carbonByChainId: { name: 'off', params: {} } } }, { tag: 'ligand' }),
+            ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, sizeFactor: 0.35 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
             polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams: { ...typeParams }, color: 'chain-id', colorParams: { palette: (plugin.customState as any).colorPalette } }, { tag: 'polymer' }),
         };
 
@@ -121,7 +121,7 @@ export const IllustrativePreset = StructureRepresentationPresetProvider({
 
         const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
         const representations = {
-            ligand: builder.buildRepresentation(update, components.ligand, { type: 'spacefill', typeParams: { ...typeParams }, color: 'element-symbol', colorParams: { carbonByChainId: { name: 'off', params: {} } } }, { tag: 'ligand' }),
+            ligand: builder.buildRepresentation(update, components.ligand, { type: 'spacefill', typeParams: { ...typeParams }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
             polymer: builder.buildRepresentation(update, components.polymer, { type: 'spacefill', typeParams: { ...typeParams }, color: 'illustrative', colorParams: { palette: (plugin.customState as any).colorPalette } }, { tag: 'polymer' }),
         };
 
@@ -149,7 +149,7 @@ const SurfacePreset = StructureRepresentationPresetProvider({
 
         const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
         const representations = {
-            ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, sizeFactor: 0.26 }, color: 'element-symbol', colorParams: { carbonByChainId: { name: 'off', params: {} } } }, { tag: 'ligand' }),
+            ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, sizeFactor: 0.26 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
             polymer: builder.buildRepresentation(update, components.polymer, { type: 'molecular-surface', typeParams: { ...typeParams, quality: 'custom', resolution: 0.5, doubleSided: true }, color: 'partial-charge' }, { tag: 'polymer' }),
         };
 
@@ -177,7 +177,7 @@ const PocketPreset = StructureRepresentationPresetProvider({
 
         const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
         const representations = {
-            ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, sizeFactor: 0.26 }, color: 'element-symbol', colorParams: { carbonByChainId: { name: 'off', params: {} } } }, { tag: 'ligand' }),
+            ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, sizeFactor: 0.26 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
             surroundings: builder.buildRepresentation(update, components.surroundings, { type: 'molecular-surface', typeParams: { ...typeParams, includeParent: true, quality: 'custom', resolution: 0.2, doubleSided: true }, color: 'partial-charge' }, { tag: 'surroundings' }),
         };
 
@@ -206,8 +206,8 @@ const InteractionsPreset = StructureRepresentationPresetProvider({
 
         const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
         const representations = {
-            ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, sizeFactor: 0.3 }, color: 'element-symbol', colorParams: { carbonByChainId: { name: 'off', params: {} } } }, { tag: 'ligand' }),
-            ballAndStick: builder.buildRepresentation(update, components.surroundings, { type: 'ball-and-stick', typeParams: { ...typeParams, sizeFactor: 0.1, sizeAspectRatio: 1 }, color: 'element-symbol', colorParams: { carbonByChainId: { name: 'off', params: {} } } }, { tag: 'ball-and-stick' }),
+            ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, sizeFactor: 0.3 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
+            ballAndStick: builder.buildRepresentation(update, components.surroundings, { type: 'ball-and-stick', typeParams: { ...typeParams, sizeFactor: 0.1, sizeAspectRatio: 1 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ball-and-stick' }),
             interactions: builder.buildRepresentation(update, components.interactions, { type: InteractionsRepresentationProvider, typeParams: { ...typeParams }, color: InteractionTypeColorThemeProvider }, { tag: 'interactions' }),
             label: builder.buildRepresentation(update, components.surroundings, { type: 'label', typeParams: { ...typeParams, background: false, borderWidth: 0.1 }, color: 'uniform', colorParams: { value: Color(0x000000) } }, { tag: 'label' }),
         };

+ 45 - 2
src/mol-plugin-state/builder/structure/hierarchy-preset.ts

@@ -16,6 +16,7 @@ import { PluginContext } from '../../../mol-plugin/context';
 import { Vec3 } from '../../../mol-math/linear-algebra';
 import { Model } from '../../../mol-model/structure';
 import { getStructureQuality } from '../../../mol-repr/util';
+import { OperatorNameColorThemeProvider } from '../../../mol-theme/color/operator-name';
 
 export interface TrajectoryHierarchyPresetProvider<P = any, S = {}> extends PresetProvider<PluginStateObject.Molecule.Trajectory, P, S> { }
 export function TrajectoryHierarchyPresetProvider<P, S>(preset: TrajectoryHierarchyPresetProvider<P, S>) { return preset; }
@@ -100,7 +101,7 @@ const allModels = TrajectoryHierarchyPresetProvider({
             structures.push(structure);
 
             const quality = structure.obj ? getStructureQuality(structure.obj.data, { elementCountFactor: tr.length }) : 'medium';
-            await builder.representation.applyPreset(structureProperties, params.representationPreset || 'auto', { globalThemeName: 'model-index', quality });
+            await builder.representation.applyPreset(structureProperties, params.representationPreset || 'auto', { theme: { globalName: 'model-index' }, quality });
         }
 
         return { models, structures };
@@ -125,7 +126,7 @@ async function applyCrystalSymmetry(props: { ijkMin: Vec3, ijkMax: Vec3, theme?:
     const structureProperties = await builder.insertStructureProperties(structure, params.structureProperties);
 
     const unitcell = await builder.tryCreateUnitcell(modelProperties, undefined, { isHidden: false });
-    const representation =  await plugin.builders.structure.representation.applyPreset(structureProperties, params.representationPreset || 'auto', { globalThemeName: props.theme });
+    const representation =  await plugin.builders.structure.representation.applyPreset(structureProperties, params.representationPreset || 'auto', { theme: { globalName: props.theme } });
 
     return {
         model,
@@ -167,10 +168,52 @@ const supercell = TrajectoryHierarchyPresetProvider({
     }
 });
 
+const CrystalContactsParams = (a: PluginStateObject.Molecule.Trajectory | undefined, plugin: PluginContext) => ({
+    model: PD.Optional(PD.Group(StateTransformer.getParamDefinition(StateTransforms.Model.ModelFromTrajectory, a, plugin))),
+    ...CommonParams(a, plugin)
+});
+
+const crystalContacts = TrajectoryHierarchyPresetProvider({
+    id: 'preset-trajectory-crystal-contacts',
+    display: {
+        name: 'Crystal Contacts', group: 'Preset',
+        description: 'Showsasymetric unit and chains from neighbours within 5 \u212B, i.e., symmetry mates.'
+    },
+    isApplicable: o => {
+        return Model.hasCrystalSymmetry(o.data[0]);
+    },
+    params: CrystalContactsParams,
+    async apply(trajectory, params, plugin) {
+        const builder = plugin.builders.structure;
+
+        const model = await builder.createModel(trajectory, params.model);
+        const modelProperties = await builder.insertModelProperties(model, params.modelProperties);
+
+        const structure = await builder.createStructure(modelProperties || model, {
+            name: 'symmetry-mates',
+            params: { radius: 5 }
+        });
+        const structureProperties = await builder.insertStructureProperties(structure, params.structureProperties);
+
+        const unitcell = await builder.tryCreateUnitcell(modelProperties, undefined, { isHidden: true });
+        const representation =  await plugin.builders.structure.representation.applyPreset(structureProperties, params.representationPreset || 'auto', { theme: { globalName: 'operator-name', carbonColor: 'operator-name', focus: { name: 'element-symbol', params: { carbonColor: { name: 'operator-name', params: OperatorNameColorThemeProvider.defaultValues } } } } });
+
+        return {
+            model,
+            modelProperties,
+            unitcell,
+            structure,
+            structureProperties,
+            representation
+        };
+    }
+});
+
 export const PresetTrajectoryHierarchy = {
     'default': defaultPreset,
     'all-models': allModels,
     unitcell,
     supercell,
+    crystalContacts,
 };
 export type PresetTrajectoryHierarchy = typeof PresetTrajectoryHierarchy;

+ 15 - 8
src/mol-plugin-state/builder/structure/representation-preset.ts

@@ -19,6 +19,7 @@ import { PluginConfig } from '../../../mol-plugin/config';
 import { StructureFocusRepresentation } from '../../../mol-plugin/behavior/dynamic/selection/structure-focus-representation';
 import { createStructureColorThemeParams } from '../../helpers/structure-representation-params';
 import { ChainIdColorThemeProvider } from '../../../mol-theme/color/chain-id';
+import { OperatorNameColorThemeProvider } from '../../../mol-theme/color/operator-name';
 
 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; }
@@ -35,7 +36,7 @@ export namespace StructureRepresentationPresetProvider {
         quality: PD.Optional(PD.Select<VisualQuality>('auto', VisualQualityOptions)),
         theme: PD.Optional(PD.Group({
             globalName: PD.Optional(PD.Text<ColorTheme.BuiltIn>('')),
-            carbonByChainId: PD.Optional(PD.Boolean(true)),
+            carbonColor: PD.Optional(PD.Select('chain-id', PD.arrayToOptions(['chain-id', 'operator-name', 'element-symbol'] as const))),
             focus: PD.Optional(PD.Group({
                 name: PD.Optional(PD.Text<ColorTheme.BuiltIn>('')),
                 params: PD.Optional(PD.Value<ColorTheme.BuiltInParams<ColorTheme.BuiltIn>>({} as any))
@@ -44,6 +45,14 @@ export namespace StructureRepresentationPresetProvider {
     };
     export type CommonParams = PD.ValuesFor<typeof CommonParams>
 
+    function getCarbonColorParams(name: 'chain-id' | 'operator-name' | 'element-symbol') {
+        return name === 'chain-id'
+            ? { name, params: ChainIdColorThemeProvider.defaultValues }
+            : name === 'operator-name'
+                ? { name, params: OperatorNameColorThemeProvider.defaultValues }
+                : { name, params: {} };
+    }
+
     export function reprBuilder(plugin: PluginContext, params: CommonParams) {
         const update = plugin.state.data.build();
         const builder = plugin.builders.structure.representation;
@@ -54,11 +63,9 @@ export namespace StructureRepresentationPresetProvider {
         if (params.quality && params.quality !== 'auto') typeParams.quality = params.quality;
         if (params.ignoreHydrogens !== void 0) typeParams.ignoreHydrogens = !!params.ignoreHydrogens;
         const color: ColorTheme.BuiltIn | undefined = params.theme?.globalName ? params.theme?.globalName : void 0;
-        const ballAndStickColor: ColorTheme.BuiltInParams<'element-symbol'> = typeof params.theme?.carbonByChainId !== 'undefined'
-            ? { carbonByChainId: params.theme.carbonByChainId
-                ? { name: 'on', params: ChainIdColorThemeProvider.defaultValues }
-                : { name: 'off', params: {} }
-            } : { };
+        const ballAndStickColor: ColorTheme.BuiltInParams<'element-symbol'> = params.theme?.carbonColor !== undefined
+            ? { carbonColor: getCarbonColorParams(params.theme?.carbonColor) }
+            : { };
 
         return { update, builder, color, typeParams, ballAndStickColor };
     }
@@ -158,8 +165,8 @@ const polymerAndLigand = StructureRepresentationPresetProvider({
             branchedBallAndStick: builder.buildRepresentation(update, components.branched, { type: 'ball-and-stick', typeParams: { ...typeParams, alpha: 0.3 }, color, colorParams: ballAndStickColor }, { 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: waterType, typeParams: { ...typeParams, alpha: 0.6 }, color }, { tag: 'water' }),
-            ion: builder.buildRepresentation(update, components.ion, { type: 'ball-and-stick', typeParams, color, colorParams: { carbonByChainId: { name: 'off', params: {} } } }, { tag: 'ion' }),
-            lipid: builder.buildRepresentation(update, components.lipid, { type: lipidType, typeParams: { ...typeParams, alpha: 0.6 }, color, colorParams: { carbonByChainId: { name: 'off', params: {} } } }, { tag: 'lipid' }),
+            ion: builder.buildRepresentation(update, components.ion, { type: 'ball-and-stick', typeParams, color, colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ion' }),
+            lipid: builder.buildRepresentation(update, components.lipid, { type: lipidType, typeParams: { ...typeParams, alpha: 0.6 }, color, colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'lipid' }),
             coarse: builder.buildRepresentation(update, components.coarse, { type: 'spacefill', typeParams, color: color || 'chain-id' }, { tag: 'coarse' })
         };
 

+ 16 - 10
src/mol-theme/color/element-symbol.ts

@@ -14,6 +14,7 @@ import { ThemeDataContext } from '../theme';
 import { TableLegend } from '../../mol-util/legend';
 import { getAdjustedColorMap } from '../../mol-util/color/color';
 import { ChainIdColorTheme, ChainIdColorThemeParams } from './chain-id';
+import { OperatorNameColorThemeParams, OperatorNameColorTheme } from './operator-name';
 
 // from Jmol http://jmol.sourceforge.net/jscolors/ (or 0xFFFFFF)
 export const ElementSymbolColors = ColorMap({
@@ -24,11 +25,14 @@ export type ElementSymbolColors = typeof ElementSymbolColors
 const DefaultElementSymbolColor = Color(0xFFFFFF);
 const Description = 'Assigns a color to every atom according to its chemical element.';
 
+// TODO generalise `carbonColor` param to all themes?
+
 export const ElementSymbolColorThemeParams = {
-    carbonByChainId: PD.MappedStatic('on', {
-        on: PD.Group({ ...ChainIdColorThemeParams }),
-        off: PD.Group({})
-    }, { cycle: true, description: 'Use chain-id coloring for carbon atoms.' }),
+    carbonColor: PD.MappedStatic('chain-id', {
+        'chain-id': PD.Group({ ...ChainIdColorThemeParams }),
+        'operator-name': PD.Group({ ...OperatorNameColorThemeParams }),
+        'element-symbol': PD.Group({})
+    }, { description: 'Use chain-id coloring for carbon atoms.' }),
     saturation: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }),
     lightness: PD.Numeric(0.2, { min: -6, max: 6, step: 0.1 })
 };
@@ -45,13 +49,15 @@ export function elementSymbolColor(colorMap: ElementSymbolColors, element: Eleme
 export function ElementSymbolColorTheme(ctx: ThemeDataContext, props: PD.Values<ElementSymbolColorThemeParams>): ColorTheme<ElementSymbolColorThemeParams> {
     const colorMap = getAdjustedColorMap(ElementSymbolColors, props.saturation, props.lightness);
 
-    const chainIdColor = props.carbonByChainId.name === 'on'
-        ? ChainIdColorTheme(ctx, props.carbonByChainId.params).color
-        : undefined;
+    const carbonColor = props.carbonColor.name === 'chain-id'
+        ? ChainIdColorTheme(ctx, props.carbonColor.params).color
+        : props.carbonColor.name === 'operator-name'
+            ? OperatorNameColorTheme(ctx, props.carbonColor.params).color
+            : undefined;
 
     function elementColor(element: ElementSymbol, location: Location) {
-        return (chainIdColor && element === 'C')
-            ? chainIdColor(location, false)
+        return (carbonColor && element === 'C')
+            ? carbonColor(location, false)
             : elementSymbolColor(colorMap, element);
     }
 
@@ -73,7 +79,7 @@ export function ElementSymbolColorTheme(ctx: ThemeDataContext, props: PD.Values<
 
     return {
         factory: ElementSymbolColorTheme,
-        granularity: 'group',
+        granularity: 'groupInstance',
         color,
         props,
         description: Description,

+ 1 - 11
src/mol-theme/color/operator-name.ts

@@ -12,9 +12,8 @@ import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { ThemeDataContext } from '../theme';
 import { getPaletteParams, getPalette } from '../../mol-util/color/palette';
 import { ScaleLegend, TableLegend } from '../../mol-util/legend';
-import { ColorLists, getColorListFromName } from '../../mol-util/color/lists';
 
-const DefaultList = 'dark-2';
+const DefaultList = 'many-distinct';
 const DefaultColor = Color(0xCCCCCC);
 const Description = `Assigns a color based on the operator name of a transformed chain.`;
 
@@ -24,15 +23,6 @@ export const OperatorNameColorThemeParams = {
 export type OperatorNameColorThemeParams = typeof OperatorNameColorThemeParams
 export function getOperatorNameColorThemeParams(ctx: ThemeDataContext) {
     const params = PD.clone(OperatorNameColorThemeParams);
-    if (ctx.structure) {
-        if (getOperatorNameSerialMap(ctx.structure.root).size > ColorLists[DefaultList].list.length) {
-            params.palette.defaultValue.name = 'colors';
-            params.palette.defaultValue.params = {
-                ...params.palette.defaultValue.params,
-                list: { kind: 'interpolate', colors: getColorListFromName(DefaultList).list }
-            };
-        }
-    }
     return params;
 }