Browse Source

wip, DscifProvider

Alexander Rose 6 years ago
parent
commit
c23651c054

+ 57 - 28
src/mol-plugin/state/actions/basic.ts

@@ -6,7 +6,7 @@
  */
 
 import { PluginContext } from 'mol-plugin/context';
-import { StateTree, Transformer, StateObject } from 'mol-state';
+import { StateTree, Transformer, StateObject, State } from 'mol-state';
 import { StateAction } from 'mol-state/action';
 import { StateSelection } from 'mol-state/state/selection';
 import { StateTreeBuilder } from 'mol-state/tree/builder';
@@ -14,9 +14,11 @@ import { ParamDefinition as PD } from 'mol-util/param-definition';
 import { PluginStateObject } from '../objects';
 import { StateTransforms } from '../transforms';
 import { Download } from '../transforms/data';
-import { StructureRepresentation3DHelpers } from '../transforms/representation';
+import { StructureRepresentation3DHelpers, VolumeRepresentation3DHelpers } from '../transforms/representation';
 import { getFileInfo, FileInfo } from 'mol-util/file-info';
 import { Task } from 'mol-task';
+import { ColorNames } from 'mol-util/color/tables';
+import { VolumeIsoValue } from 'mol-model/volume';
 
 // TODO: "structure/volume parser provider"
 
@@ -171,8 +173,8 @@ export const UpdateTrajectory = StateAction.build({
 //
 
 export class DataFormatRegistry<D extends PluginStateObject.Data.Binary | PluginStateObject.Data.String, M extends StateObject> {
-    private _list: { name: string, provider: DataFormatProvider<D, M> }[] = []
-    private _map = new Map<string, DataFormatProvider<D, M>>()
+    private _list: { name: string, provider: DataFormatProvider<D> }[] = []
+    private _map = new Map<string, DataFormatProvider<D>>()
 
     get default() { return this._list[0]; }
     get types(): [string, string][] {
@@ -185,7 +187,7 @@ export class DataFormatRegistry<D extends PluginStateObject.Data.Binary | Plugin
         this.add('dscif', DscifProvider)
     };
 
-    add(name: string, provider: DataFormatProvider<D, M>) {
+    add(name: string, provider: DataFormatProvider<D>) {
         this._list.push({ name, provider })
         this._map.set(name, provider)
     }
@@ -203,7 +205,7 @@ export class DataFormatRegistry<D extends PluginStateObject.Data.Binary | Plugin
         throw new Error('no compatible data format provider available')
     }
 
-    get(name: string): DataFormatProvider<D, M> {
+    get(name: string): DataFormatProvider<D> {
         if (this._map.has(name)) {
             return this._map.get(name)!
         } else {
@@ -216,53 +218,82 @@ export class DataFormatRegistry<D extends PluginStateObject.Data.Binary | Plugin
     }
 }
 
-interface DataFormatProvider<D extends PluginStateObject.Data.Binary | PluginStateObject.Data.String, M extends StateObject> {
+interface DataFormatProvider<D extends PluginStateObject.Data.Binary | PluginStateObject.Data.String> {
     label: string
     description: string
     fileExtensions: string[]
     isApplicable(info: FileInfo, data: string | Uint8Array): boolean
-    getDefaultBuilder(b: StateTreeBuilder.To<D>): StateTreeBuilder.To<M>
+    getDefaultBuilder(ctx: PluginContext, data: StateTreeBuilder.To<D>, state?: State): Task<void>
 }
 
-const Ccp4Provider: DataFormatProvider<any, any> = {
+const Ccp4Provider: DataFormatProvider<any> = {
     label: 'CCP4/MRC/BRIX',
     description: 'CCP4/MRC/BRIX',
     fileExtensions: ['ccp4', 'mrc', 'map'],
     isApplicable: (info: FileInfo, data: Uint8Array) => {
         return info.ext === 'ccp4' || info.ext === 'mrc' || info.ext === 'map'
     },
-    getDefaultBuilder: (b: StateTreeBuilder.To<PluginStateObject.Data.Binary>) => {
-        return b.apply(StateTransforms.Data.ParseCcp4)
-            .apply(StateTransforms.Model.VolumeFromCcp4)
-            .apply(StateTransforms.Representation.VolumeRepresentation3D)
+    getDefaultBuilder: (ctx: PluginContext, data: StateTreeBuilder.To<PluginStateObject.Data.Binary>, state: State) => {
+        return Task.create('CCP4/MRC/BRIX default builder', async taskCtx => {
+            const tree = data.apply(StateTransforms.Data.ParseCcp4)
+                .apply(StateTransforms.Model.VolumeFromCcp4)
+                .apply(StateTransforms.Representation.VolumeRepresentation3D)
+            await state.updateTree(tree).runInContext(taskCtx)
+        })
     }
 }
 
-const Dsn6Provider: DataFormatProvider<any, any> = {
+const Dsn6Provider: DataFormatProvider<any> = {
     label: 'DSN6/BRIX',
     description: 'DSN6/BRIX',
     fileExtensions: ['dsn6', 'brix'],
     isApplicable: (info: FileInfo, data: Uint8Array) => {
         return info.ext === 'dsn6' || info.ext === 'brix'
     },
-    getDefaultBuilder: (b: StateTreeBuilder.To<PluginStateObject.Data.Binary>) => {
-        return b.apply(StateTransforms.Data.ParseDsn6)
-            .apply(StateTransforms.Model.VolumeFromDsn6)
-            .apply(StateTransforms.Representation.VolumeRepresentation3D)
+    getDefaultBuilder: (ctx: PluginContext, data: StateTreeBuilder.To<PluginStateObject.Data.Binary>, state: State) => {
+        return Task.create('DSN6/BRIX default builder', async taskCtx => {
+            const tree = data.apply(StateTransforms.Data.ParseDsn6)
+                .apply(StateTransforms.Model.VolumeFromDsn6)
+                .apply(StateTransforms.Representation.VolumeRepresentation3D)
+            await state.updateTree(tree).runInContext(taskCtx)
+        })
     }
 }
 
-const DscifProvider: DataFormatProvider<any, any> = {
+const DscifProvider: DataFormatProvider<any> = {
     label: 'DensityServer CIF',
     description: 'DensityServer CIF',
     fileExtensions: ['cif'],
     isApplicable: (info: FileInfo, data: Uint8Array) => {
         return info.ext === 'cif'
     },
-    getDefaultBuilder: (b: StateTreeBuilder.To<PluginStateObject.Data.Binary>) => {
-        return b.apply(StateTransforms.Data.ParseCif, {  })
-            .apply(StateTransforms.Model.VolumeFromDensityServerCif)
-            .apply(StateTransforms.Representation.VolumeRepresentation3D)
+    getDefaultBuilder: (ctx: PluginContext, data: StateTreeBuilder.To<PluginStateObject.Data.Binary>, state: State) => {
+        return Task.create('DensityServer CIF default builder', async taskCtx => {
+            const cifBuilder = data.apply(StateTransforms.Data.ParseCif)
+            const cifStateObject = await state.updateTree(cifBuilder).runInContext(taskCtx)
+            const b = state.build().to(cifBuilder.ref);
+            const blocks = cifStateObject.data.blocks.slice(1); // zero block contains query meta-data
+            let tree: StateTreeBuilder.To<any>
+            if (blocks.length === 1) {
+                tree = b
+                    .apply(StateTransforms.Model.VolumeFromDensityServerCif, { blockHeader: blocks[0].header })
+                    .apply(StateTransforms.Representation.VolumeRepresentation3D, VolumeRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'isosurface', { isoValue: VolumeIsoValue.relative(1.5), alpha: 0.3 }))
+            } else if (blocks.length === 2) {
+                tree = b
+                    .apply(StateTransforms.Model.VolumeFromDensityServerCif, { blockHeader: blocks[0].header })
+                    .apply(StateTransforms.Representation.VolumeRepresentation3D, VolumeRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'isosurface', { isoValue: VolumeIsoValue.relative(1.5), alpha: 0.3 }, 'uniform', { value: ColorNames.blue }))
+                const vol = tree.to(cifBuilder.ref)
+                    .apply(StateTransforms.Model.VolumeFromDensityServerCif, { blockHeader: blocks[1].header })
+                const posParams = VolumeRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'isosurface', { isoValue: VolumeIsoValue.relative(3), alpha: 0.3 }, 'uniform', { value: ColorNames.green })
+                tree = vol.apply(StateTransforms.Representation.VolumeRepresentation3D, posParams)
+                const negParams = VolumeRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'isosurface', { isoValue: VolumeIsoValue.relative(-3), alpha: 0.3 }, 'uniform', { value: ColorNames.red })
+                tree = tree.to(vol.ref).apply(StateTransforms.Representation.VolumeRepresentation3D, negParams)
+            } else {
+                throw new Error('unknown number of blocks')
+            }
+
+            await state.updateTree(tree).runInContext(taskCtx);
+        })
     }
 }
 
@@ -302,9 +333,8 @@ export const OpenVolume = StateAction.build({
 
     const provider = params.format === 'auto' ? ctx.dataFormat.registry.auto(getFileInfo(params.file), dataStateObject) : ctx.dataFormat.registry.get(params.format)
     const b = state.build().to(data.ref);
-    const tree = provider.getDefaultBuilder(b).getTree()
     // need to await the 2nd update the so that the enclosing Task finishes after the update is done.
-    await state.updateTree(tree).runInContext(taskCtx);
+    await provider.getDefaultBuilder(ctx, b, state).runInContext(taskCtx)
 }));
 
 export { DownloadDensity };
@@ -341,7 +371,7 @@ const DownloadDensity = StateAction.build({
 })(({ params, state }, ctx: PluginContext) => Task.create('Download Density', async taskCtx => {
     const src = params.source;
     let downloadParams: Transformer.Params<Download>;
-    let provider: DataFormatProvider<any, any>
+    let provider: DataFormatProvider<any>
 
     switch (src.name) {
         case 'url':
@@ -386,6 +416,5 @@ const DownloadDensity = StateAction.build({
     }
 
     const b = state.build().to(data.ref);
-    const tree = provider.getDefaultBuilder(b).getTree()
-    await state.updateTree(tree).runInContext(taskCtx);
+    await provider.getDefaultBuilder(ctx, b, state).runInContext(taskCtx)
 }));

+ 7 - 6
src/mol-plugin/state/transforms/representation.ts

@@ -19,6 +19,8 @@ import { ExplodeRepresentation3D } from 'mol-plugin/behavior/dynamic/representat
 import { VolumeData } from 'mol-model/volume';
 import { BuiltInVolumeRepresentationsName } from 'mol-repr/volume/registry';
 import { VolumeParams } from 'mol-repr/volume/representation';
+import { BuiltInColorThemeName, ColorTheme } from 'mol-theme/color';
+import { BuiltInSizeThemeName, SizeTheme } from 'mol-theme/size';
 
 export namespace StructureRepresentation3DHelpers {
     export function getDefaultParams(ctx: PluginContext, name: BuiltInStructureRepresentationsName, structure: Structure, structureParams?: Partial<PD.Values<StructureParams>>): Transformer.Params<StructureRepresentation3D> {
@@ -162,14 +164,14 @@ export namespace VolumeRepresentation3DHelpers {
         })
     }
 
-    export function getDefaultParamsStatic(ctx: PluginContext, name: BuiltInVolumeRepresentationsName, volumeParams?: Partial<PD.Values<VolumeParams>>): Transformer.Params<VolumeRepresentation3D> {
+    export function getDefaultParamsStatic(ctx: PluginContext, name: BuiltInVolumeRepresentationsName, volumeParams?: Partial<PD.Values<PD.Params>>, colorName?: BuiltInColorThemeName, colorParams?: Partial<ColorTheme.Props>, sizeName?: BuiltInSizeThemeName, sizeParams?: Partial<SizeTheme.Props>): Transformer.Params<VolumeRepresentation3D> {
         const type = ctx.volumeRepresentation.registry.get(name);
-        const colorParams = ctx.volumeRepresentation.themeCtx.colorThemeRegistry.get(type.defaultColorTheme).defaultValues;
-        const sizeParams = ctx.volumeRepresentation.themeCtx.sizeThemeRegistry.get(type.defaultSizeTheme).defaultValues
+        const colorType = ctx.volumeRepresentation.themeCtx.colorThemeRegistry.get(colorName || type.defaultColorTheme);
+        const sizeType = ctx.volumeRepresentation.themeCtx.sizeThemeRegistry.get(sizeName || type.defaultSizeTheme);
         return ({
             type: { name, params: volumeParams ? { ...type.defaultValues, ...volumeParams } : type.defaultValues },
-            colorTheme: { name: type.defaultColorTheme, params: colorParams },
-            sizeTheme: { name: type.defaultSizeTheme, params: sizeParams }
+            colorTheme: { name: type.defaultColorTheme, params: colorParams ? { ...colorType.defaultValues, ...colorParams } : colorType.defaultValues },
+            sizeTheme: { name: type.defaultSizeTheme, params: sizeParams ? { ...sizeType.defaultValues, ...sizeParams } : sizeType.defaultValues }
         })
     }
 }
@@ -234,7 +236,6 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({
             repr.setTheme(createTheme(plugin.volumeRepresentation.themeCtx, { volume: a.data }, params))
             // TODO set initial state, repr.setState({})
             // TODO include isoValue in the label where available
-            console.log(params.type.params);
             await repr.createOrUpdate(props, a.data).runInContext(ctx);
             return new SO.Volume.Representation3D(repr, { label: provider.label });
         });