Parcourir la source

Merge branch 'master' of https://github.com/molstar/molstar into anim-rock

Alexander Rose il y a 3 ans
Parent
commit
bc13b98111

+ 4 - 0
CHANGELOG.md

@@ -15,6 +15,10 @@ Note that since we don't clearly distinguish between a public and private interf
     - Add ``animate`` to ``TrackballControlsParams``, remove ``spin`` and ``spinSpeed``
     - Add ``animate`` to ``SimpleSettingsParams``, remove ``spin``
 - Add "camera rock" state animation
+- Add support for custom colors to "molecule-type" theme
+- [Breaking] Add style parameter to "illustrative" color theme
+    - Defaults to "entity-id" style instad of "chain-id"
+- Add "illustrative" representation preset
 
 ## [v3.0.0-dev.9] - 2022-01-09
 

Fichier diff supprimé car celui-ci est trop grand
+ 294 - 264
package-lock.json


+ 31 - 31
package.json

@@ -91,41 +91,41 @@
   ],
   "license": "MIT",
   "devDependencies": {
-    "@graphql-codegen/add": "^3.1.0",
-    "@graphql-codegen/cli": "^2.3.0",
-    "@graphql-codegen/time": "^3.1.0",
-    "@graphql-codegen/typescript": "^2.4.1",
-    "@graphql-codegen/typescript-graphql-files-modules": "^2.1.0",
-    "@graphql-codegen/typescript-graphql-request": "^4.3.1",
-    "@graphql-codegen/typescript-operations": "^2.2.1",
+    "@graphql-codegen/add": "^3.1.1",
+    "@graphql-codegen/cli": "^2.3.1",
+    "@graphql-codegen/time": "^3.1.1",
+    "@graphql-codegen/typescript": "^2.4.2",
+    "@graphql-codegen/typescript-graphql-files-modules": "^2.1.1",
+    "@graphql-codegen/typescript-graphql-request": "^4.3.3",
+    "@graphql-codegen/typescript-operations": "^2.2.2",
     "@types/cors": "^2.8.12",
     "@types/gl": "^4.1.0",
-    "@types/jest": "^27.0.3",
-    "@typescript-eslint/eslint-plugin": "^5.5.0",
-    "@typescript-eslint/parser": "^5.5.0",
+    "@types/jest": "^27.4.0",
+    "@typescript-eslint/eslint-plugin": "^5.9.1",
+    "@typescript-eslint/parser": "^5.9.1",
     "benchmark": "^2.1.4",
-    "concurrently": "^6.4.0",
-    "cpx2": "^4.0.0",
+    "concurrently": "^7.0.0",
+    "cpx2": "^4.1.2",
     "crypto-browserify": "^3.12.0",
     "css-loader": "^6.5.1",
-    "eslint": "^8.3.0",
+    "eslint": "^8.7.0",
     "extra-watch-webpack-plugin": "^1.0.3",
     "file-loader": "^6.2.0",
     "fs-extra": "^10.0.0",
-    "graphql": "^15.7.2",
-    "http-server": "^14.0.0",
-    "jest": "^27.3.1",
-    "mini-css-extract-plugin": "^2.4.5",
+    "graphql": "^16.2.0",
+    "http-server": "^14.1.0",
+    "jest": "^27.4.7",
+    "mini-css-extract-plugin": "~2.4.7",
     "path-browserify": "^1.0.1",
     "raw-loader": "^4.0.2",
-    "sass": "^1.43.5",
-    "sass-loader": "^12.3.0",
-    "simple-git": "^2.47.0",
+    "sass": "^1.48.0",
+    "sass-loader": "^12.4.0",
+    "simple-git": "^2.48.0",
     "stream-browserify": "^3.0.0",
     "style-loader": "^3.3.1",
-    "ts-jest": "^27.0.7",
-    "typescript": "^4.5.2",
-    "webpack": "^5.64.4",
+    "ts-jest": "^27.1.3",
+    "typescript": "^4.5.4",
+    "webpack": "^5.66.0",
     "webpack-cli": "^4.9.1"
   },
   "dependencies": {
@@ -133,22 +133,22 @@
     "@types/benchmark": "^2.1.1",
     "@types/compression": "1.7.2",
     "@types/express": "^4.17.13",
-    "@types/node": "^16.11.10",
+    "@types/node": "^16.11.19",
     "@types/node-fetch": "^2.5.12",
-    "@types/react": "^17.0.37",
+    "@types/react": "^17.0.38",
     "@types/react-dom": "^17.0.11",
     "@types/swagger-ui-dist": "3.30.1",
     "argparse": "^2.0.1",
-    "body-parser": "^1.19.0",
+    "body-parser": "^1.19.1",
     "compression": "^1.7.4",
     "cors": "^2.8.5",
-    "express": "^4.17.1",
+    "express": "^4.17.2",
     "h264-mp4-encoder": "^1.0.12",
-    "immer": "^9.0.7",
+    "immer": "^9.0.12",
     "immutable": "^3.8.2",
     "node-fetch": "^2.6.2",
-    "rxjs": "^7.4.0",
-    "swagger-ui-dist": "^4.1.1",
+    "rxjs": "^7.5.2",
+    "swagger-ui-dist": "^4.1.3",
     "tslib": "^2.3.1",
     "util.promisify": "^1.1.1",
     "xhr2": "^0.2.1"
@@ -158,6 +158,6 @@
     "react-dom": "^17.0.2"
   },
   "optionalDependencies": {
-    "gl": "^4.9.2"
+    "gl": "^5.0.0"
   }
 }

+ 3 - 3
src/extensions/rcsb/graphql/types.ts

@@ -4,7 +4,7 @@ export type InputMaybe<T> = Maybe<T>;
 export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
 export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
 export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
-// Generated on 2021-11-25T14:34:23-08:00
+// Generated on 2022-01-15T19:52:34-08:00
 
 /** All built-in and custom scalars, mapped to their actual values */
 export type Scalars = {
@@ -11113,11 +11113,11 @@ export type RcsbUniprotAlignments = {
 
 export type RcsbUniprotAlignmentsCoreEntityAlignments = {
   /** Aligned region */
-  readonly aligned_regions?: Maybe<ReadonlyArray<Maybe<CoreEntityAlignmentsAlignedRegions>>>;
+  readonly aligned_regions: ReadonlyArray<Maybe<CoreEntityAlignmentsAlignedRegions>>;
   /** core_entity identifiers */
   readonly core_entity_identifiers?: Maybe<CoreEntityAlignmentsCoreEntityIdentifiers>;
   /** Alignment scores */
-  readonly scores?: Maybe<CoreEntityAlignmentsScores>;
+  readonly scores: CoreEntityAlignmentsScores;
 };
 
 export type RcsbUniprotAnnotation = {

+ 1 - 1
src/mol-io/reader/cif/schema/bird.ts

@@ -1,7 +1,7 @@
 /**
  * Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
- * Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.352, IHM 1.17, CARB draft.
+ * Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.354, IHM 1.17, MA 1.3.3.
  *
  * @author molstar/ciftools package
  */

+ 1 - 1
src/mol-io/reader/cif/schema/ccd.ts

@@ -1,7 +1,7 @@
 /**
  * Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
- * Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.352, IHM 1.17, CARB draft.
+ * Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.354, IHM 1.17, MA 1.3.3.
  *
  * @author molstar/ciftools package
  */

+ 2 - 2
src/mol-io/reader/cif/schema/mmcif.ts

@@ -1,7 +1,7 @@
 /**
  * Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
- * Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.353, IHM 1.17, MA 1.3.3.
+ * Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.354, IHM 1.17, MA 1.3.3.
  *
  * @author molstar/ciftools package
  */
@@ -682,7 +682,7 @@ export const mmCIF_Schema = {
         /**
          * An abbreviation that identifies the database.
          */
-        database_id: Aliased<'CAS' | 'CSD' | 'EMDB' | 'ICSD' | 'MDF' | 'NDB' | 'NBS' | 'PDB' | 'PDF' | 'RCSB' | 'EBI' | 'PDBE' | 'BMRB' | 'WWPDB' | 'PDB_ACC'>(str),
+        database_id: Aliased<'AFDB' | 'CAS' | 'CSD' | 'EMDB' | 'ICSD' | 'MA' | 'MDF' | 'MODBASE' | 'NDB' | 'NBS' | 'PDB' | 'PDF' | 'RCSB' | 'SMR' | 'EBI' | 'PDBE' | 'BMRB' | 'WWPDB' | 'PDB_ACC'>(str),
         /**
          * The code assigned by the database identified in
          * _database_2.database_id.

+ 73 - 2
src/mol-plugin-state/builder/structure/representation-preset.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -24,6 +24,8 @@ import { IndexPairBonds } from '../../../mol-model-formats/structure/property/bo
 import { StructConn } from '../../../mol-model-formats/structure/property/bonds/struct_conn';
 import { StructureRepresentationRegistry } from '../../../mol-repr/structure/registry';
 import { assertUnreachable } from '../../../mol-util/type-helpers';
+import { Color } from '../../../mol-util/color';
+import { PostprocessingParams } from '../../../mol-canvas3d/passes/postprocessing';
 
 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; }
@@ -98,6 +100,15 @@ type CommonParams = StructureRepresentationPresetProvider.CommonParams
 const reprBuilder = StructureRepresentationPresetProvider.reprBuilder;
 const updateFocusRepr = StructureRepresentationPresetProvider.updateFocusRepr;
 
+function resetPostprocessingProps(plugin: PluginContext) {
+    if (plugin.canvas3d) {
+        const p = PD.getDefaultValues(PostprocessingParams);
+        plugin.canvas3d.setProps({
+            postprocessing: { outline: p.outline, occlusion: p.occlusion }
+        });
+    }
+}
+
 const auto = StructureRepresentationPresetProvider({
     id: 'preset-structure-representation-auto',
     display: {
@@ -137,6 +148,7 @@ const empty = StructureRepresentationPresetProvider({
     id: 'preset-structure-representation-empty',
     display: { name: 'Empty', description: 'Removes all existing representations.' },
     async apply(ref, params, plugin) {
+        resetPostprocessingProps(plugin);
         return { };
     }
 });
@@ -191,6 +203,8 @@ const polymerAndLigand = StructureRepresentationPresetProvider({
         await update.commit({ revertOnError: false });
         await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
 
+        resetPostprocessingProps(plugin);
+
         return { components, representations };
     }
 });
@@ -230,6 +244,8 @@ const proteinAndNucleic = StructureRepresentationPresetProvider({
         await update.commit({ revertOnError: true });
         await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
 
+        resetPostprocessingProps(plugin);
+
         return { components, representations };
     }
 });
@@ -282,6 +298,8 @@ const coarseSurface = StructureRepresentationPresetProvider({
         await update.commit({ revertOnError: true });
         await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
 
+        resetPostprocessingProps(plugin);
+
         return { components, representations };
     }
 });
@@ -315,6 +333,8 @@ const polymerCartoon = StructureRepresentationPresetProvider({
         await update.commit({ revertOnError: true });
         await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
 
+        resetPostprocessingProps(plugin);
+
         return { components, representations };
     }
 });
@@ -381,6 +401,56 @@ const atomicDetail = StructureRepresentationPresetProvider({
         await update.commit({ revertOnError: true });
         await updateFocusRepr(plugin, structure, params.theme?.focus?.name ?? color, params.theme?.focus?.params ?? colorParams);
 
+        resetPostprocessingProps(plugin);
+
+        return { components, representations };
+    }
+});
+
+const illustrative = StructureRepresentationPresetProvider({
+    id: 'preset-structure-representation-illustrative',
+    display: {
+        name: 'Illustrative', group: 'Miscellaneous',
+        description: '...'
+    },
+    params: () => ({
+        ...CommonParams,
+        showCarbohydrateSymbol: PD.Boolean(false)
+    }),
+    async apply(ref, params, plugin) {
+        const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
+        if (!structureCell) return {};
+
+        const components = {
+            all: await presetStaticComponent(plugin, structureCell, 'all'),
+            branched: undefined
+        };
+
+        const structure = structureCell.obj!.data;
+
+        const { update, builder, typeParams, color } = reprBuilder(plugin, params, structure);
+
+        const representations = {
+            all: builder.buildRepresentation(update, components.all, { type: 'spacefill', typeParams: { ...typeParams, ignoreLight: true }, color: 'illustrative' }, { tag: 'all' }),
+        };
+        await update.commit({ revertOnError: true });
+        await updateFocusRepr(plugin, structure, params.theme?.focus?.name ?? color, params.theme?.focus?.params);
+
+        if (plugin.canvas3d) {
+            plugin.canvas3d.setProps({
+                postprocessing: {
+                    outline: {
+                        name: 'on',
+                        params: { scale: 1, color: Color(0x000000), threshold: 0.25 }
+                    },
+                    occlusion: {
+                        name: 'on',
+                        params: { bias: 0.9, blurKernelSize: 15, radius: 5, samples: 32 }
+                    },
+                }
+            });
+        }
+
         return { components, representations };
     }
 });
@@ -400,6 +470,7 @@ export const PresetStructureRepresentations = {
     'polymer-cartoon': polymerCartoon,
     'polymer-and-ligand': polymerAndLigand,
     'protein-and-nucleic': proteinAndNucleic,
-    'coarse-surface': coarseSurface
+    'coarse-surface': coarseSurface,
+    'illustrative': illustrative,
 };
 export type PresetStructureRepresentations = typeof PresetStructureRepresentations;

+ 21 - 6
src/mol-theme/color/illustrative.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -12,24 +12,39 @@ import { ColorTheme } from '../color';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { ThemeDataContext } from '../theme';
 import { ChainIdColorTheme, ChainIdColorThemeParams } from './chain-id';
+import { UniformColorTheme, UniformColorThemeParams } from './uniform';
+import { assertUnreachable } from '../../mol-util/type-helpers';
+import { EntityIdColorTheme, EntityIdColorThemeParams } from './entity-id';
+import { MoleculeTypeColorTheme, MoleculeTypeColorThemeParams } from './molecule-type';
 
 const DefaultIllustrativeColor = Color(0xEEEEEE);
-const Description = `Assigns an illustrative color that gives every chain a unique color with lighter carbons (inspired by David Goodsell's Molecule of the Month style).`;
+const Description = `Assigns an illustrative color that gives every chain a color based on the choosen style but with lighter carbons (inspired by David Goodsell's Molecule of the Month style).`;
 
 export const IllustrativeColorThemeParams = {
-    ...ChainIdColorThemeParams,
+    style: PD.MappedStatic('entity-id', {
+        uniform: PD.Group(UniformColorThemeParams),
+        'chain-id': PD.Group(ChainIdColorThemeParams),
+        'entity-id': PD.Group(EntityIdColorThemeParams),
+        'molecule-type': PD.Group(MoleculeTypeColorThemeParams),
+    }),
     carbonLightness: PD.Numeric(0.8, { min: -6, max: 6, step: 0.1 })
 };
 export type IllustrativeColorThemeParams = typeof IllustrativeColorThemeParams
 export function getIllustrativeColorThemeParams(ctx: ThemeDataContext) {
-    return IllustrativeColorThemeParams; // TODO return copy
+    const params = PD.clone(IllustrativeColorThemeParams);
+    return params;
 }
 
 export function IllustrativeColorTheme(ctx: ThemeDataContext, props: PD.Values<IllustrativeColorThemeParams>): ColorTheme<IllustrativeColorThemeParams> {
-    const { color: chainIdColor, legend } = ChainIdColorTheme(ctx, props);
+    const { color: styleColor, legend } =
+        props.style.name === 'uniform' ? UniformColorTheme(ctx, props.style.params) :
+            props.style.name === 'chain-id' ? ChainIdColorTheme(ctx, props.style.params) :
+                props.style.name === 'entity-id' ? EntityIdColorTheme(ctx, props.style.params) :
+                    props.style.name === 'molecule-type' ? MoleculeTypeColorTheme(ctx, props.style.params) :
+                        assertUnreachable(props.style);
 
     function illustrativeColor(location: Location, typeSymbol: ElementSymbol) {
-        const baseColor = chainIdColor(location, false);
+        const baseColor = styleColor(location, false);
         return typeSymbol === 'C' ? Color.lighten(baseColor, props.carbonLightness) : baseColor;
     }
 

+ 31 - 29
src/mol-theme/color/molecule-type.ts

@@ -1,10 +1,10 @@
 /**
- * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Color, ColorMap } from '../../mol-util/color';
+import { Color } from '../../mol-util/color';
 import { StructureElement, Unit, Bond, ElementIndex } from '../../mol-model/structure';
 import { Location } from '../../mol-model/location';
 import { ColorTheme } from '../color';
@@ -13,53 +13,55 @@ import { getElementMoleculeType } from '../../mol-model/structure/util';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { ThemeDataContext } from '../theme';
 import { TableLegend } from '../../mol-util/legend';
-import { getAdjustedColorMap } from '../../mol-util/color/color';
-
-export const MoleculeTypeColors = ColorMap({
-    water: 0x386cb0,
-    ion: 0xf0027f,
-    protein: 0xbeaed4,
-    RNA: 0xfdc086,
-    DNA: 0xbf5b17,
-    PNA: 0x42A49A,
-    saccharide: 0x7fc97f,
-});
-export type MoleculeTypeColors = typeof MoleculeTypeColors
 
 const DefaultMoleculeTypeColor = Color(0xffff99);
 const Description = 'Assigns a color based on the molecule type of a residue.';
 
 export const MoleculeTypeColorThemeParams = {
     saturation: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }),
-    lightness: PD.Numeric(0, { min: -6, max: 6, step: 0.1 })
+    lightness: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }),
+    colors: PD.Group({
+        water: PD.Color(Color(0x386cb0)),
+        ion: PD.Color(Color(0xf0027f)),
+        protein: PD.Color(Color(0xbeaed4)),
+        rna: PD.Color(Color(0xfdc086)),
+        dna: PD.Color(Color(0xbf5b17)),
+        pna: PD.Color(Color(0x42A49A)),
+        saccharide: PD.Color(Color(0x7fc97f)),
+        lipid: PD.Color(Color(0xcccccc)),
+    })
 };
 export type MoleculeTypeColorThemeParams = typeof MoleculeTypeColorThemeParams
 export function getMoleculeTypeColorThemeParams(ctx: ThemeDataContext) {
     return MoleculeTypeColorThemeParams; // TODO return copy
 }
 
-export function moleculeTypeColor(colorMap: MoleculeTypeColors, unit: Unit, element: ElementIndex): Color {
+type MoleculeTypeColorThemeProps = PD.Values<MoleculeTypeColorThemeParams>;
+export function moleculeTypeColor(props: MoleculeTypeColorThemeProps, unit: Unit, element: ElementIndex): Color {
+    let c = DefaultMoleculeTypeColor;
     const moleculeType = getElementMoleculeType(unit, element);
     switch (moleculeType) {
-        case MoleculeType.Water: return colorMap.water;
-        case MoleculeType.Ion: return colorMap.ion;
-        case MoleculeType.Protein: return colorMap.protein;
-        case MoleculeType.RNA: return colorMap.RNA;
-        case MoleculeType.DNA: return colorMap.DNA;
-        case MoleculeType.PNA: return colorMap.PNA;
-        case MoleculeType.Saccharide: return colorMap.saccharide;
+        case MoleculeType.Water: c = props.colors.water; break;
+        case MoleculeType.Ion: c = props.colors.ion; break;
+        case MoleculeType.Protein: c = props.colors.protein; break;
+        case MoleculeType.RNA: c = props.colors.rna; break;
+        case MoleculeType.DNA: c = props.colors.dna; break;
+        case MoleculeType.PNA: c = props.colors.pna; break;
+        case MoleculeType.Saccharide: c = props.colors.saccharide; break;
+        case MoleculeType.Lipid: c = props.colors.lipid; break;
     }
-    return DefaultMoleculeTypeColor;
+    c = Color.saturate(c, props.saturation);
+    c = Color.darken(c, -props.lightness);
+    return c;
 }
 
 export function MoleculeTypeColorTheme(ctx: ThemeDataContext, props: PD.Values<MoleculeTypeColorThemeParams>): ColorTheme<MoleculeTypeColorThemeParams> {
-    const colorMap = getAdjustedColorMap(MoleculeTypeColors, props.saturation, props.lightness);
 
     function color(location: Location): Color {
         if (StructureElement.Location.is(location)) {
-            return moleculeTypeColor(colorMap, location.unit, location.element);
+            return moleculeTypeColor(props, location.unit, location.element);
         } else if (Bond.isLocation(location)) {
-            return moleculeTypeColor(colorMap, location.aUnit, location.aUnit.elements[location.aIndex]);
+            return moleculeTypeColor(props, location.aUnit, location.aUnit.elements[location.aIndex]);
         }
         return DefaultMoleculeTypeColor;
     }
@@ -70,8 +72,8 @@ export function MoleculeTypeColorTheme(ctx: ThemeDataContext, props: PD.Values<M
         color,
         props,
         description: Description,
-        legend: TableLegend(Object.keys(MoleculeTypeColors).map(name => {
-            return [name, (MoleculeTypeColors as any)[name] as Color] as [string, Color];
+        legend: TableLegend(Object.keys(props.colors).map(name => {
+            return [name, (props.colors as any)[name] as Color] as [string, Color];
         }).concat([['Other/unknown', DefaultMoleculeTypeColor]]))
     };
 }

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff