Browse Source

support for loading structures with initial 3d transform applied

Alexander Rose 4 years ago
parent
commit
c570844843

+ 20 - 9
src/structure-viewer/helpers/model.ts

@@ -9,6 +9,8 @@ import { PluginCommands } from 'molstar/lib/mol-plugin/commands';
 import { PluginContext } from 'molstar/lib/mol-plugin/context';
 import { PresetProps, RcsbPreset } from './preset';
 import { Asset } from 'molstar/lib/mol-util/assets';
+import { Mat4 } from 'molstar/lib/mol-math/linear-algebra';
+import { StateTransforms } from 'molstar/lib/mol-plugin-state/transforms';
 
 export class ModelLoader {
     get customState() {
@@ -20,21 +22,30 @@ export class ModelLoader {
         await PluginCommands.State.RemoveObject(this.plugin, { state, ref: state.tree.root.ref })
     }
 
-    async load(load: LoadParams, props?: PresetProps) {
-        await this.clear()
-
+    async load(load: LoadParams, props?: PresetProps, matrix?: Mat4) {
         const { fileOrUrl, format } = load
         const isBinary = format === 'bcif'
 
         const data = fileOrUrl instanceof File
             ? (await this.plugin.builders.data.readFile({ file: Asset.File(fileOrUrl), isBinary })).data
             : await this.plugin.builders.data.download({ url: fileOrUrl, isBinary })
-        await this.plugin.builders.structure.parseTrajectory(data, 'mmcif')
-
-        const mng = this.plugin.managers.structure.hierarchy
-        await mng.applyPreset(mng.current.trajectories, RcsbPreset, {
-            preset: props || { kind: 'standard', assemblyId: 'deposited' }
-        })
+        const trajectory = await this.plugin.builders.structure.parseTrajectory(data, 'mmcif')
+
+        const selector = await this.plugin.builders.structure.hierarchy.applyPreset(trajectory, RcsbPreset, {
+            preset: props || { kind: 'standard', assemblyId: '' }
+        });
+
+        if (matrix && selector) {
+            const params = {
+                transform: {
+                    name: 'matrix' as const,
+                    params: { data: matrix, transpose: false }
+                }
+            };
+            const b = this.plugin.state.data.build().to(selector.structureProperties)
+                .insert(StateTransforms.Model.TransformStructureConformation, params);
+            await this.plugin.runTask(this.plugin.state.data.updateTree(b));
+        }
     }
 
     constructor(private plugin: PluginContext) {

+ 30 - 0
src/structure-viewer/index.html

@@ -63,6 +63,16 @@
             <select id="examples" onchange="loadExample(parseInt(this.value))">
                 <option value=''></option>
             </select>
+
+            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+            Clear
+            <button style="padding: 3px;" onclick="viewer.clear()">all</button>
+
+            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+            Superposed
+            <button style="padding: 3px;" onclick="superposed()">3PQR | 1U19</button>
         </div>
         <script>
             function loadExample(index) {
@@ -258,6 +268,26 @@
                 Object.assign(option, { text: '[' + e.id + '] ' + e.info, value: i })
                 examplesSelect.appendChild(option)
             }
+
+            //
+
+            function superposed() {
+                viewer.clear()
+                    .then(function() {
+                        return viewer.loadPdbId('3pqr', { kind: 'standard', assemblyId: '1' })
+                    })
+                    .then(function() {
+                        return viewer.loadPdbId('1u19', { kind: 'standard', assemblyId: '1' }, [
+                            -0.67160917400372, 0.28222298510688404, 0.6850488398834855, 0,
+                            0.13262098666685063, 0.9554691407700946, -0.26361033961856695, 0,
+                            -0.7289399153866256, -0.08619120567473626, -0.6791305379047228, 0,
+                            -7.602670654900173, -30.317901981509067, 24.605855585357773, 1
+                        ])
+                    })
+                    .then(function() {
+                        viewer.resetCamera(0)
+                    });
+            }
         </script>
     </body>
 </html>

+ 13 - 4
src/structure-viewer/index.ts

@@ -24,6 +24,7 @@ import { ControlsWrapper, ViewportWrapper } from './ui/controls';
 import { PluginConfig } from 'molstar/lib/mol-plugin/config';
 import { RCSBAssemblySymmetry } from 'molstar/lib/extensions/rcsb/assembly-symmetry/behavior';
 import { RCSBValidationReport } from 'molstar/lib/extensions/rcsb/validation-report/behavior';
+import { Mat4 } from 'molstar/lib/mol-math/linear-algebra';
 require('./skin/rcsb.scss')
 
 /** package version, filled in at bundle build time */
@@ -130,11 +131,19 @@ export class StructureViewer {
 
     //
 
-    async loadPdbId(pdbId: string, props?: PresetProps) {
+    resetCamera(durationMs?: number) {
+        this.plugin.managers.camera.reset(undefined, durationMs);
+    }
+
+    async clear() {
+        await this.customState.modelLoader.clear();
+    }
+
+    async loadPdbId(pdbId: string, props?: PresetProps, matrix?: Mat4) {
         for (const provider of this.props.modelUrlProviders) {
             try {
                 const p = provider(pdbId)
-                await this.customState.modelLoader.load({ fileOrUrl: p.url, format: p.format }, props)
+                await this.customState.modelLoader.load({ fileOrUrl: p.url, format: p.format }, props, matrix)
                 break
             } catch (e) {
                 console.warn(`loading '${pdbId}' failed with '${e}', trying next model-loader-provider`)
@@ -142,7 +151,7 @@ export class StructureViewer {
         }
     }
 
-    async loadUrl(url: string, props?: PresetProps) {
-        await this.customState.modelLoader.load({ fileOrUrl: url, format: 'cif', }, props)
+    async loadUrl(url: string, props?: PresetProps, matrix?: Mat4) {
+        await this.customState.modelLoader.load({ fileOrUrl: url, format: 'cif', }, props, matrix)
     }
 }