From a65bba0969f466866f24225eac800c17efb5af59 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Tue, 18 Jun 2019 13:39:23 +0200
Subject: [PATCH] proteopedia-wrapper: better HET group focusing

---
 src/examples/proteopedia-wrapper/changelog.md |  5 ++
 src/examples/proteopedia-wrapper/helpers.ts   |  3 +-
 src/examples/proteopedia-wrapper/index.html   |  2 +-
 src/examples/proteopedia-wrapper/index.ts     | 54 ++++++++++++-------
 4 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/src/examples/proteopedia-wrapper/changelog.md b/src/examples/proteopedia-wrapper/changelog.md
index 9680f701e..b9d8bd109 100644
--- a/src/examples/proteopedia-wrapper/changelog.md
+++ b/src/examples/proteopedia-wrapper/changelog.md
@@ -1,3 +1,8 @@
+== v3.2 ==
+
+* Fixed assembly loading.
+* Better HET group focus.
+
 == v3.0 ==
 
 * Fixed initial camera zoom.
diff --git a/src/examples/proteopedia-wrapper/helpers.ts b/src/examples/proteopedia-wrapper/helpers.ts
index 7d1360c3e..d8d4f2610 100644
--- a/src/examples/proteopedia-wrapper/helpers.ts
+++ b/src/examples/proteopedia-wrapper/helpers.ts
@@ -115,5 +115,6 @@ export enum StateElements {
     Water = 'water',
     WaterVisual = 'water-visual',
 
-    HetGroupFocus = 'het-group-focus'
+    HetGroupFocus = 'het-group-focus',
+    HetGroupFocusGroup = 'het-group-focus-group'
 }
\ No newline at end of file
diff --git a/src/examples/proteopedia-wrapper/index.html b/src/examples/proteopedia-wrapper/index.html
index 5fd7d7bbc..2a72e4b51 100644
--- a/src/examples/proteopedia-wrapper/index.html
+++ b/src/examples/proteopedia-wrapper/index.html
@@ -212,7 +212,7 @@
                     var l = document.createElement('button');
                     l.innerText = r.name;
                     l.onclick = function () {
-                        PluginWrapper.hetGroups.focusFirst(r.name);
+                        PluginWrapper.hetGroups.focusFirst(r.name, r.indices[0]);
                     };
                     div.appendChild(l);
                 });
diff --git a/src/examples/proteopedia-wrapper/index.ts b/src/examples/proteopedia-wrapper/index.ts
index 0a5bf878b..248b96029 100644
--- a/src/examples/proteopedia-wrapper/index.ts
+++ b/src/examples/proteopedia-wrapper/index.ts
@@ -29,6 +29,7 @@ import { BuiltInSizeThemes } from '../../mol-theme/size';
 import { ColorNames } from '../../mol-util/color/tables';
 import { InitVolumeStreaming, CreateVolumeStreamingInfo } from '../../mol-plugin/behavior/dynamic/volume-streaming/transformers';
 import { ParamDefinition } from '../../mol-util/param-definition';
+import { ResidueIndex } from '../../mol-model/structure';
 // import { Vec3 } from 'mol-math/linear-algebra';
 // import { ParamDefinition } from 'mol-util/param-definition';
 // import { Text } from 'mol-geo/geometry/text/text';
@@ -36,7 +37,7 @@ require('../../mol-plugin/skin/light.scss')
 
 class MolStarProteopediaWrapper {
     static VERSION_MAJOR = 3;
-    static VERSION_MINOR = 1;
+    static VERSION_MINOR = 2;
 
     private _ev = RxEventHelper.create();
 
@@ -298,30 +299,34 @@ class MolStarProteopediaWrapper {
             PluginCommands.State.Update.dispatch(this.plugin, { state: this.state, tree: update });
             PluginCommands.Camera.Reset.dispatch(this.plugin, { });
         },
-        focusFirst: async (resn: string) => {
+        focusFirst: async (resn: string, resIdx: ResidueIndex) => {
             if (!this.state.transforms.has(StateElements.Assembly)) return;
+            await PluginCommands.Camera.Reset.dispatch(this.plugin, { });
 
             // const asm = (this.state.select(StateElements.Assembly)[0].obj as PluginStateObject.Molecule.Structure).data;
 
             const update = this.state.build();
 
-            update.delete(StateElements.HetGroupFocus);
-
-            const surroundings = MS.struct.modifier.includeSurroundings({
-                0: MS.struct.filter.first([
-                    MS.struct.generator.atomGroups({
-                        'residue-test': MS.core.rel.eq([MS.struct.atomProperty.macromolecular.label_comp_id(), resn]),
-                        'group-by': MS.struct.atomProperty.macromolecular.residueKey()
-                    })
-                ]),
-                radius: 5,
-                'as-whole-residues': true
-            });
-
-            const sel = update.to(StateElements.Assembly)
-                .apply(StateTransforms.Model.StructureSelection, { label: resn, query: surroundings }, { ref: StateElements.HetGroupFocus });
-
-            sel.apply(StateTransforms.Representation.StructureRepresentation3D, this.createSurVisualParams());
+            update.delete(StateElements.HetGroupFocusGroup);
+
+            const core = MS.struct.filter.first([
+                MS.struct.generator.atomGroups({
+                    'residue-test': MS.core.logic.and([
+                        MS.core.rel.eq([MS.struct.atomProperty.macromolecular.label_comp_id(), resn]),
+                        // the resIdx isn't very clear solution and is based on current implementation of residueKey()
+                        MS.core.rel.eq([MS.struct.atomProperty.macromolecular.residueKey(), resIdx])
+                    ]),
+                    'group-by': MS.core.str.concat([MS.struct.atomProperty.core.operatorName(), MS.struct.atomProperty.macromolecular.residueKey()])
+                })
+            ]);
+            const surroundings = MS.struct.modifier.includeSurroundings({ 0: core, radius: 5, 'as-whole-residues': true });
+
+            const group = update.to(StateElements.Assembly).group(StateTransforms.Misc.CreateGroup, { label: resn }, { ref: StateElements.HetGroupFocusGroup });
+
+            group.apply(StateTransforms.Model.StructureSelection, { label: 'Core', query: core }, { ref: StateElements.HetGroupFocus })
+                .apply(StateTransforms.Representation.StructureRepresentation3D, this.createCoreVisualParams());
+            group.apply(StateTransforms.Model.StructureSelection, { label: 'Surroundings', query: surroundings })
+                .apply(StateTransforms.Representation.StructureRepresentation3D, this.createSurVisualParams());
             // sel.apply(StateTransforms.Representation.StructureLabels3D, {
             //     target: { name: 'residues', params: { } },
             //     options: {
@@ -341,7 +346,7 @@ class MolStarProteopediaWrapper {
             // const position = Vec3.sub(Vec3.zero(), sphere.center, asmCenter);
             // Vec3.normalize(position, position);
             // Vec3.scaleAndAdd(position, sphere.center, position, sphere.radius);
-            const snapshot = this.plugin.canvas3d.camera.getFocus(sphere.center, 0.75 * sphere.radius);
+            const snapshot = this.plugin.canvas3d.camera.getFocus(sphere.center, Math.max(sphere.radius, 5));
             PluginCommands.Camera.SetSnapshot.dispatch(this.plugin, { snapshot, durationMs: 250 });
         }
     }
@@ -355,6 +360,15 @@ class MolStarProteopediaWrapper {
         });
     }
 
+    private createCoreVisualParams() {
+        const asm = this.state.select(StateElements.Assembly)[0].obj as PluginStateObject.Molecule.Structure;
+        return StructureRepresentation3DHelpers.createParams(this.plugin, asm.data, {
+            repr: BuiltInStructureRepresentations['ball-and-stick'],
+            // color: [BuiltInColorThemes.uniform, () => ({ value: ColorNames.gray })],
+            // size: [BuiltInSizeThemes.uniform, () => ({ value: 0.33 } )]
+        });
+    }
+
     snapshot = {
         get: () => {
             return this.plugin.state.getSnapshot();
-- 
GitLab