From 023b65572ea26a8579544ab1cd595698a9b93ad2 Mon Sep 17 00:00:00 2001
From: Alexander Rose <alex.rose@rcsb.org>
Date: Tue, 30 Jul 2019 16:22:34 -0700
Subject: [PATCH] viewer, option to load files without adding visuals

---
 src/mol-plugin/state/actions/data-format.ts | 10 ++++---
 src/mol-plugin/state/actions/shape.ts       | 10 ++++---
 src/mol-plugin/state/actions/structure.ts   | 14 +++++-----
 src/mol-plugin/state/actions/volume.ts      | 30 +++++++++++++--------
 4 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/src/mol-plugin/state/actions/data-format.ts b/src/mol-plugin/state/actions/data-format.ts
index b5fbf0cb9..dacd03fd7 100644
--- a/src/mol-plugin/state/actions/data-format.ts
+++ b/src/mol-plugin/state/actions/data-format.ts
@@ -103,25 +103,28 @@ export class DataFormatRegistry<D extends PluginStateObject.Data.Binary | Plugin
     }
 }
 
+export type DataFormatBuilderOptions = { visuals: boolean }
+
 export interface DataFormatProvider<D extends PluginStateObject.Data.Binary | PluginStateObject.Data.String> {
     label: string
     description: string
     stringExtensions: string[]
     binaryExtensions: string[]
     isApplicable(info: FileInfo, data: string | Uint8Array): boolean
-    getDefaultBuilder(ctx: PluginContext, data: StateBuilder.To<D>, state?: State): Task<void>
+    getDefaultBuilder(ctx: PluginContext, data: StateBuilder.To<D>, options: DataFormatBuilderOptions, state?: State): Task<void>
 }
 
 //
 
 export const OpenFile = StateAction.build({
-    display: { name: 'Open File', description: 'Load a file and create its default visual' },
+    display: { name: 'Open File', description: 'Load a file and optionally create its default visuals' },
     from: PluginStateObject.Root,
     params: (a, ctx: PluginContext) => {
         const { extensions, options } = ctx.dataFormat.registry
         return {
             file: PD.File({ accept: Array.from(extensions).map(e => `.${e}`).join(',')}),
             format: PD.Select('auto', options),
+            visuals: PD.Boolean(true, { description: 'Add default visuals' }),
         }
     }
 })(({ params, state }, ctx: PluginContext) => Task.create('Open File', async taskCtx => {
@@ -140,8 +143,9 @@ export const OpenFile = StateAction.build({
 
     const provider = params.format === 'auto' ? ctx.dataFormat.registry.auto(info, dataStateObject) : ctx.dataFormat.registry.get(params.format)
     const b = state.build().to(data.ref);
+    const options = { visuals: params.visuals }
     // need to await the 2nd update the so that the enclosing Task finishes after the update is done.
-    await provider.getDefaultBuilder(ctx, b, state).runInContext(taskCtx)
+    await provider.getDefaultBuilder(ctx, b, options, state).runInContext(taskCtx)
 }));
 
 //
diff --git a/src/mol-plugin/state/actions/shape.ts b/src/mol-plugin/state/actions/shape.ts
index 0257c8857..799b27176 100644
--- a/src/mol-plugin/state/actions/shape.ts
+++ b/src/mol-plugin/state/actions/shape.ts
@@ -10,7 +10,7 @@ import { Task } from '../../../mol-task';
 import { FileInfo } from '../../../mol-util/file-info';
 import { PluginStateObject } from '../objects';
 import { StateTransforms } from '../transforms';
-import { DataFormatProvider } from './data-format';
+import { DataFormatProvider, DataFormatBuilderOptions } from './data-format';
 
 export const PlyProvider: DataFormatProvider<any> = {
     label: 'PLY',
@@ -20,11 +20,13 @@ export const PlyProvider: DataFormatProvider<any> = {
     isApplicable: (info: FileInfo, data: string) => {
         return info.ext === 'ply'
     },
-    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.String>, state: State) => {
+    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.String>, options: DataFormatBuilderOptions, state: State) => {
         return Task.create('PLY default builder', async taskCtx => {
-            const tree = data.apply(StateTransforms.Data.ParsePly)
+            let tree: StateBuilder.To<any> = data.apply(StateTransforms.Data.ParsePly)
                 .apply(StateTransforms.Model.ShapeFromPly)
-                .apply(StateTransforms.Representation.ShapeRepresentation3D)
+            if (options.visuals) {
+                tree = tree.apply(StateTransforms.Representation.ShapeRepresentation3D)
+            }
             await state.updateTree(tree).runInContext(taskCtx)
         })
     }
diff --git a/src/mol-plugin/state/actions/structure.ts b/src/mol-plugin/state/actions/structure.ts
index f287e64fa..3ecad410b 100644
--- a/src/mol-plugin/state/actions/structure.ts
+++ b/src/mol-plugin/state/actions/structure.ts
@@ -13,7 +13,7 @@ import { StateTransforms } from '../transforms';
 import { Download } from '../transforms/data';
 import { StructureRepresentation3DHelpers } from '../transforms/representation';
 import { CustomModelProperties, StructureSelection, CustomStructureProperties } from '../transforms/model';
-import { DataFormatProvider, guessCifVariant } from './data-format';
+import { DataFormatProvider, guessCifVariant, DataFormatBuilderOptions } from './data-format';
 import { FileInfo } from '../../../mol-util/file-info';
 import { Task } from '../../../mol-task';
 import { StructureElement } from '../../../mol-model/structure';
@@ -29,10 +29,10 @@ export const MmcifProvider: DataFormatProvider<any> = {
         if (info.ext === 'cif' || info.ext === 'bcif') return guessCifVariant(info, data) !== 'dscif'
         return false
     },
-    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, state: State) => {
+    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, options: DataFormatBuilderOptions, state: State) => {
         return Task.create('mmCIF default builder', async taskCtx => {
             const traj = createModelTree(data, 'cif');
-            await state.updateTree(createStructureTree(ctx, traj, false)).runInContext(taskCtx)
+            await state.updateTree(options.visuals ? createStructureTree(ctx, traj, false) : traj).runInContext(taskCtx)
         })
     }
 }
@@ -45,10 +45,10 @@ export const PdbProvider: DataFormatProvider<any> = {
     isApplicable: (info: FileInfo, data: string) => {
         return info.ext === 'pdb' || info.ext === 'ent'
     },
-    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.String>, state: State) => {
+    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.String>, options: DataFormatBuilderOptions, state: State) => {
         return Task.create('PDB default builder', async taskCtx => {
             const traj = createModelTree(data, 'pdb');
-            await state.updateTree(createStructureTree(ctx, traj, false)).runInContext(taskCtx)
+            await state.updateTree(options.visuals ? createStructureTree(ctx, traj, false) : traj).runInContext(taskCtx)
         })
     }
 }
@@ -61,10 +61,10 @@ export const GroProvider: DataFormatProvider<any> = {
     isApplicable: (info: FileInfo, data: string) => {
         return info.ext === 'gro'
     },
-    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.String>, state: State) => {
+    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.String>, options: DataFormatBuilderOptions, state: State) => {
         return Task.create('GRO default builder', async taskCtx => {
             const traj = createModelTree(data, 'gro');
-            await state.updateTree(createStructureTree(ctx, traj, false)).runInContext(taskCtx)
+            await state.updateTree(options.visuals ? createStructureTree(ctx, traj, false) : traj).runInContext(taskCtx)
         })
     }
 }
diff --git a/src/mol-plugin/state/actions/volume.ts b/src/mol-plugin/state/actions/volume.ts
index 6f9f6a8a6..70951e9fe 100644
--- a/src/mol-plugin/state/actions/volume.ts
+++ b/src/mol-plugin/state/actions/volume.ts
@@ -16,7 +16,7 @@ import { PluginStateObject } from '../objects';
 import { StateTransforms } from '../transforms';
 import { Download } from '../transforms/data';
 import { VolumeRepresentation3DHelpers } from '../transforms/representation';
-import { DataFormatProvider, guessCifVariant } from './data-format';
+import { DataFormatProvider, guessCifVariant, DataFormatBuilderOptions } from './data-format';
 
 export const Ccp4Provider: DataFormatProvider<any> = {
     label: 'CCP4/MRC/BRIX',
@@ -26,11 +26,13 @@ export const Ccp4Provider: DataFormatProvider<any> = {
     isApplicable: (info: FileInfo, data: Uint8Array) => {
         return info.ext === 'ccp4' || info.ext === 'mrc' || info.ext === 'map'
     },
-    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary>, state: State) => {
+    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary>, options: DataFormatBuilderOptions, state: State) => {
         return Task.create('CCP4/MRC/BRIX default builder', async taskCtx => {
-            const tree = data.apply(StateTransforms.Data.ParseCcp4)
+            let tree: StateBuilder.To<any> = data.apply(StateTransforms.Data.ParseCcp4)
                 .apply(StateTransforms.Volume.VolumeFromCcp4)
-                .apply(StateTransforms.Representation.VolumeRepresentation3D)
+            if (options.visuals) {
+                tree = tree.apply(StateTransforms.Representation.VolumeRepresentation3D)
+            }
             await state.updateTree(tree).runInContext(taskCtx)
         })
     }
@@ -44,11 +46,13 @@ export const Dsn6Provider: DataFormatProvider<any> = {
     isApplicable: (info: FileInfo, data: Uint8Array) => {
         return info.ext === 'dsn6' || info.ext === 'brix'
     },
-    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary>, state: State) => {
+    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary>, options: DataFormatBuilderOptions, state: State) => {
         return Task.create('DSN6/BRIX default builder', async taskCtx => {
-            const tree = data.apply(StateTransforms.Data.ParseDsn6)
+            let tree: StateBuilder.To<any> = data.apply(StateTransforms.Data.ParseDsn6)
                 .apply(StateTransforms.Volume.VolumeFromDsn6)
-                .apply(StateTransforms.Representation.VolumeRepresentation3D)
+            if (options.visuals) {
+                tree = tree.apply(StateTransforms.Representation.VolumeRepresentation3D)
+            }
             await state.updateTree(tree).runInContext(taskCtx)
         })
     }
@@ -62,7 +66,7 @@ export const DscifProvider: DataFormatProvider<any> = {
     isApplicable: (info: FileInfo, data: Uint8Array | string) => {
         return guessCifVariant(info, data) === 'dscif' ? true : false
     },
-    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, state: State) => {
+    getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, options: DataFormatBuilderOptions, 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)
@@ -72,11 +76,15 @@ export const DscifProvider: DataFormatProvider<any> = {
             if (blocks.length === 1) {
                 tree = b
                     .apply(StateTransforms.Volume.VolumeFromDensityServerCif, { blockHeader: blocks[0].header })
-                    .apply(StateTransforms.Representation.VolumeRepresentation3D, VolumeRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'isosurface', { isoValue: VolumeIsoValue.relative(1.5), alpha: 0.3 }, 'uniform', { value: ColorNames.teal }))
+                if (options.visuals) {
+                    tree = tree.apply(StateTransforms.Representation.VolumeRepresentation3D, VolumeRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'isosurface', { isoValue: VolumeIsoValue.relative(1.5), alpha: 0.3 }, 'uniform', { value: ColorNames.teal }))
+                }
             } else if (blocks.length === 2) {
                 tree = b
                     .apply(StateTransforms.Volume.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 }))
+                if (options.visuals) {
+                    tree = tree.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.Volume.VolumeFromDensityServerCif, { blockHeader: blocks[1].header })
                 const posParams = VolumeRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'isosurface', { isoValue: VolumeIsoValue.relative(3), alpha: 0.3 }, 'uniform', { value: ColorNames.green })
@@ -199,5 +207,5 @@ const DownloadDensity = StateAction.build({
     }
 
     const b = state.build().to(data.ref);
-    await provider.getDefaultBuilder(ctx, b, state).runInContext(taskCtx)
+    await provider.getDefaultBuilder(ctx, b, { visuals: true }, state).runInContext(taskCtx)
 }));
\ No newline at end of file
-- 
GitLab