Browse Source

improved StructureViewer creation and loading

Alexander Rose 5 years ago
parent
commit
6a3115c26e
2 changed files with 45 additions and 22 deletions
  1. 6 12
      src/structure-viewer/index.html
  2. 39 10
      src/structure-viewer/index.ts

+ 6 - 12
src/structure-viewer/index.html

@@ -44,23 +44,17 @@
                 return m ? decodeURIComponent(m[1]) : undefined
             }
 
-            function getLoadParams(pdbId) {
-                return {
-                    assemblyId: getQueryParam('assemblyId') || 'deposited',
-                    url: 'https://files.rcsb.org/download/' + pdbId + '.cif',
-                    format: 'cif'
-                }
-            }
-
             // create an instance of the plugin
-            var viewer = new app.StructureViewer();
-            viewer.init('app', { });
+            var viewer = new app.StructureViewer('app');
+
+            // load pdbId
             const pdbId = getQueryParam('pdbId');
-            if (pdbId) viewer.load(getLoadParams(pdbId));
+            const assemblyId = getQueryParam('assemblyId') || 'deposited';
+            if (pdbId) viewer.loadPdbId(pdbId, assemblyId);
         </script>
         <div id="menu">
             Examples
-            <select id="examples" onchange="viewer.load(getLoadParams(this.value))">
+            <select id="examples" onchange="viewer.loadPdbId(this.value)">
                 <option value=''></option>
             </select>
         </div>

+ 39 - 10
src/structure-viewer/index.ts

@@ -17,7 +17,7 @@ import { LoadParams, SupportedFormats, StateElements } from './helpers';
 import { ControlsWrapper, ViewportWrapper } from './ui/controls';
 import { Scheduler } from 'molstar/lib/mol-task';
 import { InitVolumeStreaming, CreateVolumeStreamingInfo } from 'molstar/lib/mol-plugin/behavior/dynamic/volume-streaming/transformers';
-import { ParamDefinition } from 'molstar/lib/mol-util/param-definition';
+import { ParamDefinition as PD } from 'molstar/lib/mol-util/param-definition';
 import { PluginSpec } from 'molstar/lib/mol-plugin/spec';
 import { StructureRepresentationInteraction } from 'molstar/lib/mol-plugin/behavior/dynamic/selection/structure-representation-interaction';
 import { Model } from 'molstar/lib/mol-model/structure';
@@ -25,11 +25,28 @@ import { ColorNames } from 'molstar/lib/mol-util/color/names';
 import { StructureControlsHelper } from './ui/structure';
 require('./skin/rcsb.scss')
 
+export const DefaultStructureViewerProps = {
+    // volumeServerUrl: '//128.6.244.39/',
+    volumeServerUrl: 'https://ds.litemol.org/',
+    modelUrlProvider: (pdbId: string) => {
+        const id = pdbId.toLowerCase()
+        return {
+            // url: `https://files.rcsb.org/download/${id}.cif`,
+            // format: 'cif' as SupportedFormats
+            url: `https://alpha-models.rcsb.org/${id}.bcif`,
+            // url: `https://alpha-models.rcsb.org/models/${id.substr(1, 2)}/${id}.bcif`,
+            format: 'bcif' as SupportedFormats
+        }
+    },
+}
+export type StructureViewerProps = typeof DefaultStructureViewerProps
+
 export class StructureViewer {
-    plugin: PluginContext;
-    structureControlsHelper: StructureControlsHelper;
+    private readonly plugin: PluginContext;
+    private readonly structureControlsHelper: StructureControlsHelper;
+    private readonly props: Readonly<StructureViewerProps>
 
-    init(target: string | HTMLElement) {
+    constructor(target: string | HTMLElement, props: Partial<StructureViewerProps> = {}) {
         target = typeof target === 'string' ? document.getElementById(target)! : target
         this.plugin = createPlugin(target, {
             ...DefaultPluginSpec,
@@ -37,7 +54,7 @@ export class StructureViewer {
                 PluginSpec.Behavior(PluginBehaviors.Representation.HighlightLoci),
                 PluginSpec.Behavior(PluginBehaviors.Representation.SelectLoci),
                 PluginSpec.Behavior(PluginBehaviors.Representation.DefaultLociLabelProvider),
-                PluginSpec.Behavior(PluginBehaviors.Camera.FocusLociOnSelect, {
+                PluginSpec.Behavior(PluginBehaviors.Camera.FocusLoci, {
                     minRadius: 8,
                     extraRadius: 4
                 }),
@@ -64,6 +81,8 @@ export class StructureViewer {
             }
         });
 
+        this.props = { ...DefaultStructureViewerProps, ...props }
+
         const renderer = this.plugin.canvas3d.props.renderer;
         PluginCommands.Canvas3D.SetSettings.dispatch(this.plugin, { settings: { renderer: { ...renderer, backgroundColor: ColorNames.white } } });
         this.structureControlsHelper = new StructureControlsHelper(this.plugin)
@@ -73,12 +92,13 @@ export class StructureViewer {
         return this.plugin.state.dataState;
     }
 
-    private download(b: StateBuilder.To<PSO.Root>, url: string) {
-        return b.apply(StateTransforms.Data.Download, { url, isBinary: false })
+    private download(b: StateBuilder.To<PSO.Root>, url: string, isBinary: boolean) {
+        return b.apply(StateTransforms.Data.Download, { url, isBinary })
     }
 
     private model(b: StateBuilder.To<PSO.Data.Binary | PSO.Data.String>, format: SupportedFormats) {
-        const parsed = format === 'cif'
+        const isMmcif = format === 'cif' || format === 'bcif'
+        const parsed = isMmcif
             ? b.apply(StateTransforms.Data.ParseCif).apply(StateTransforms.Model.TrajectoryFromMmCif, {}, { ref: StateElements.Trajectory })
             : b.apply(StateTransforms.Model.TrajectoryFromPDB, {}, { ref: StateElements.Trajectory });
 
@@ -96,7 +116,8 @@ export class StructureViewer {
         const state = this.plugin.state.dataState;
         await PluginCommands.State.RemoveObject.dispatch(this.plugin, { state, ref: state.tree.root.ref });
 
-        const modelTree = this.model(this.download(state.build().toRoot(), url), format);
+        const isBinary = format === 'bcif'
+        const modelTree = this.model(this.download(state.build().toRoot(), url, isBinary), format);
         await this.applyState(modelTree);
 
         await this.structureControlsHelper.setAssembly(assemblyId)
@@ -106,6 +127,13 @@ export class StructureViewer {
         this.experimentalData.init()
     }
 
+    async loadPdbId(pdbId: string, assemblyId = 'deposited') {
+        return this.load({
+            assemblyId,
+            ...this.props.modelUrlProvider(pdbId),
+        })
+    }
+
     experimentalData = {
         init: async () => {
             const model = this.state.select(StateElements.Model)[0].obj;
@@ -124,9 +152,10 @@ export class StructureViewer {
             }
 
             if (hasXrayMap || hasEmMap) {
-                const params = ParamDefinition.getDefaultValues(InitVolumeStreaming.definition.params!(asm, this.plugin));
+                const params = PD.getDefaultValues(InitVolumeStreaming.definition.params!(asm, this.plugin));
                 params.behaviorRef = StateElements.VolumeStreaming;
                 params.defaultView = 'selection-box';
+                params.serverUrl = this.props.volumeServerUrl
                 await this.plugin.runTask(this.state.applyAction(InitVolumeStreaming, params, StateElements.Assembly));
             }
         },