Переглянути джерело

Merge branch 'master' into dev-sb-motifvis

# Conflicts:
#	package-lock.json
#	package.json
#	src/viewer/helpers/preset.ts
JonStargaryen 3 роки тому
батько
коміт
e98e115730
4 змінених файлів з 106 додано та 8 видалено
  1. 12 0
      CHANGELOG.md
  2. 2 2
      package.json
  3. 89 5
      src/viewer/helpers/preset.ts
  4. 3 1
      src/viewer/index.html

+ 12 - 0
CHANGELOG.md

@@ -2,6 +2,18 @@
 
 [Semantic Versioning](https://semver.org/)
 
+## [1.6.9] - 2021-06-23
+### Added
+- Mol* 2.0.7 & some internal cleanup
+
+## [1.6.8] - 2021-06-11
+### Added
+- Hide all but 2Fo-Fc map (RO-2751)
+
+## [1.6.6] - 2021-06-08
+### Added
+- Special density preset with 0(-ish) radius for ligands (RO-2751)
+
 ## [1.6.5] - 2021-06-03
 ### Bug fixes
 - Access to maps.rcsb.org via HTTPS

+ 2 - 2
package.json

@@ -1,6 +1,6 @@
 {
     "name": "@rcsb/rcsb-molstar",
-    "version": "1.7.0-dev.1",
+    "version": "1.6.9",
     "description": "RCSB PDB apps and props based on Mol*.",
     "homepage": "https://github.com/rcsb/rcsb-molstar#readme",
     "repository": {
@@ -49,7 +49,7 @@
         "file-loader": "^6.2.0",
         "fs-extra": "^9.0.1",
         "mini-css-extract-plugin": "^1.3.2",
-        "molstar": "^2.0.6",
+        "molstar": "^2.0.7",
         "node-sass": "^5.0.0",
         "raw-loader": "^4.0.2",
         "react": "^17.0.1",

+ 89 - 5
src/viewer/helpers/preset.ts

@@ -14,6 +14,13 @@ import { RootStructureDefinition } from 'molstar/lib/mol-plugin-state/helpers/ro
 import { StructureRepresentationPresetProvider } from 'molstar/lib/mol-plugin-state/builder/structure/representation-preset';
 import { StructureElement } from 'molstar/lib/mol-model/structure';
 import { InitVolumeStreaming } from 'molstar/lib/mol-plugin/behavior/dynamic/volume-streaming/transformers';
+import {
+    Structure,
+    StructureSelection,
+    QueryContext,
+    StructureElement
+} from 'molstar/lib/mol-model/structure';
+import { compile } from 'molstar/lib/mol-script/runtime/query/compiler';
 import { ViewerState } from '../types';
 import {
     StateSelection,
@@ -21,13 +28,68 @@ import {
     StateObject,
     StateTransformer
 } from 'molstar/lib/mol-state';
-import { VolumeStreaming } from 'molstar/lib/mol-plugin/behavior/dynamic/volume-streaming/behavior';
 import { Mat4 } from 'molstar/lib/mol-math/linear-algebra';
 import { CustomStructureProperties } from 'molstar/lib/mol-plugin-state/transforms/model';
 import { FlexibleStructureFromModel } from './superpose/flexible-structure';
 import { PluginCommands } from 'molstar/lib/mol-plugin/commands';
 import { InteractivityManager } from 'molstar/lib/mol-plugin-state/manager/interactivity';
 import { MembraneOrientationPreset } from 'molstar/lib/extensions/anvil/behavior';
+import { setSubtreeVisibility } from 'molstar/lib/mol-plugin/behavior/static/state';
+import { VolumeStreaming } from 'molstar/lib/mol-plugin/behavior/dynamic/volume-streaming/behavior';
+import {
+    InitVolumeStreaming,
+    VolumeStreamingVisual
+} from 'molstar/lib/mol-plugin/behavior/dynamic/volume-streaming/transformers';
+
+type Target = {
+    readonly auth_seq_id?: number
+    readonly label_seq_id?: number
+    readonly label_comp_id?: string
+    readonly label_asym_id?: string
+}
+
+function targetToExpression(target: Target): Expression {
+    const residueTests: Expression[] = [];
+    const tests = Object.create(null);
+
+    if (target.auth_seq_id) {
+        residueTests.push(MS.core.rel.eq([target.auth_seq_id, MS.ammp('auth_seq_id')]));
+    } else if (target.label_seq_id) {
+        residueTests.push(MS.core.rel.eq([target.label_seq_id, MS.ammp('label_seq_id')]));
+    }
+    if (target.label_comp_id) {
+        residueTests.push(MS.core.rel.eq([target.label_comp_id, MS.ammp('label_comp_id')]));
+    }
+    if (residueTests.length === 1) {
+        tests['residue-test'] = residueTests[0];
+    } else if (residueTests.length > 1) {
+        tests['residue-test'] = MS.core.logic.and(residueTests);
+    }
+
+    if (target.label_asym_id) {
+        tests['chain-test'] = MS.core.rel.eq([target.label_asym_id, MS.ammp('label_asym_id')]);
+    }
+
+    if (Object.keys(tests).length > 0) {
+        return MS.struct.modifier.union([
+            MS.struct.generator.atomGroups(tests)
+        ]);
+    } else {
+        return MS.struct.generator.empty;
+    }
+}
+
+function targetToLoci(target: Target, structure: Structure): StructureElement.Loci {
+    const expression = targetToExpression(target);
+    const query = compile<StructureSelection>(expression);
+    const selection = query(new QueryContext(structure));
+    return StructureSelection.toLociWithSourceUnits(selection);
+}
+
+type Range = {
+    label_asym_id: string
+    label_seq_id?: { beg: number, end?: number }
+}
 import {
     normalizeTargets,
     createSelectionExpressions,
@@ -92,7 +154,9 @@ type MembraneProps = {
 
 type FeatureDensityProps = {
     kind: 'feature-density',
-    target: Target
+    target: Target,
+    radius?: number,
+    hiddenChannels?: string[]
 } & BaseProps
 
 export type MotifProps = {
@@ -251,7 +315,7 @@ export const RcsbPreset = TrajectoryHierarchyPresetProvider({
             const target = chainMode ? loci : StructureElement.Loci.firstResidue(loci);
 
             if (p.kind === 'feature-density') {
-                await initVolumeStreaming(plugin, structure);
+                await initVolumeStreaming(plugin, structure, { overrideRadius: p.radius || 0, hiddenChannels: p.hiddenChannels || ['fo-fc(+ve)', 'fo-fc(-ve)'] });
             }
 
             plugin.managers.structure.focus.setFromLoci(target);
@@ -286,13 +350,33 @@ export const RcsbPreset = TrajectoryHierarchyPresetProvider({
     }
 });
 
-async function initVolumeStreaming(plugin: PluginContext, structure: StructureObject) {
+async function initVolumeStreaming(plugin: PluginContext, structure: StructureObject, props?: { overrideRadius?: number, hiddenChannels: string[] }) {
     if (!structure?.cell?.parent) return;
 
     const volumeRoot = StateSelection.findTagInSubtree(structure.cell.parent.tree, structure.cell.transform.ref, VolumeStreaming.RootTag);
     if (!volumeRoot) {
+        const state = plugin.state.data;
         const params = PD.getDefaultValues(InitVolumeStreaming.definition.params!(structure.obj!, plugin));
-        await plugin.runTask(plugin.state.data.applyAction(InitVolumeStreaming, params, structure.ref));
+        await plugin.runTask(state.applyAction(InitVolumeStreaming, params, structure.ref));
+
+        // RO-2751: allow to specify radius of shown density
+        if (props?.overrideRadius !== void 0) {
+            const { params, transform } = state.select(StateSelection.Generators.ofType(VolumeStreaming))[0];
+
+            const p = params?.values;
+            (p.entry.params.view.params as any).radius = props.overrideRadius;
+
+            await state.build().to(transform.ref).update(p).commit();
+        }
+        // RO-2751: hide all but 2Fo-Fc map
+        if (props?.hiddenChannels?.length) {
+            const cells = state.select(StateSelection.Generators.ofTransformer(VolumeStreamingVisual));
+            for (const cell of cells) {
+                if (props.hiddenChannels.indexOf(cell.obj!.tags![0]) !== -1) {
+                    setSubtreeVisibility(state, cell.transform.ref, true);
+                }
+            }
+        }
     }
 
     ViewerState(plugin).collapsed.next({

+ 3 - 1
src/viewer/index.html

@@ -321,7 +321,9 @@
                         target: {
                             label_asym_id: 'D',
                             auth_seq_id: 502
-                        }
+                        },
+                        // radius: 0,
+                        // hiddenChannels: ['fo-fc(+ve)', 'fo-fc(-ve)']
                     }
                 },
                 {