From ed5f5819ad51999a520b2a17e4db6288174a2ae1 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Sat, 23 Feb 2019 19:08:43 +0100
Subject: [PATCH] mol-plugin: volume streaming

---
 src/mol-model/volume/data.ts                  |  4 ++--
 src/mol-plugin/behavior/dynamic/volume.ts     | 21 ++++++++++++++++---
 .../state/transforms/representation.ts        |  6 +++---
 src/mol-plugin/state/transforms/volume.ts     |  3 ++-
 src/mol-repr/volume/isosurface.ts             |  6 +++---
 src/mol-state/transform.ts                    |  4 ++++
 src/mol-state/tree/transient.ts               | 10 +++++++++
 7 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/src/mol-model/volume/data.ts b/src/mol-model/volume/data.ts
index fce0581ed..97572d0ef 100644
--- a/src/mol-model/volume/data.ts
+++ b/src/mol-model/volume/data.ts
@@ -21,10 +21,10 @@ interface VolumeData {
 }
 
 namespace VolumeData {
-    export const Empty: VolumeData = {
+    export const One: VolumeData = {
         cell: SpacegroupCell.Zero,
         fractionalBox: Box3D.empty(),
-        data: Tensor.create(Tensor.Space([0, 0, 0], [0, 1, 2]), Tensor.Data1([])),
+        data: Tensor.create(Tensor.Space([1, 1, 1], [0, 1, 2]), Tensor.Data1([0])),
         dataStats: { min: 0, max: 0, mean: 0, sigma: 0 }
     }
 
diff --git a/src/mol-plugin/behavior/dynamic/volume.ts b/src/mol-plugin/behavior/dynamic/volume.ts
index 7afbba36a..856f239f4 100644
--- a/src/mol-plugin/behavior/dynamic/volume.ts
+++ b/src/mol-plugin/behavior/dynamic/volume.ts
@@ -41,7 +41,7 @@ export namespace VolumeStreaming {
                 topRight: PD.Vec3(Vec3.create(-7.1, -10, -0.9))
             }, { description: 'Static box defined by cartesian coords.' }),
             // 'around-selection': PD.Group({ radius: PD.Numeric(5, { min: 0, max: 10 }) }),
-            // 'whole-structure': PD.Group({  }),
+            'cell': PD.Group({  }),
             // 'auto': PD.Group({  }), // based on camera distance/active selection/whatever, show whole structure or slice.
         }),
         detailLevel: PD.Numeric(3, { min: 0, max: 7 }),
@@ -55,6 +55,7 @@ export namespace VolumeStreaming {
     export class Behavior implements PluginBehavior<Params> {
         // TODO: have special value for "cell"?
         private cache = LRUCache.create<ChannelData>(25);
+        // private ref: string = '';
 
         currentData: ChannelData = { }
 
@@ -109,14 +110,28 @@ export namespace VolumeStreaming {
         }
 
         register(ref: string): void {
-            // TODO: registr camera movement/loci so that "around selection box works"
+            // TODO: register camera movement/loci so that "around selection box works"
+            // alternatively, and maybe a better solution, write a global behavior that modifies this node from the outside
+            // this.ref = ref;
             this.update(this.params);
         }
 
         async update(params: Params): Promise<boolean> {
             this.params = params;
 
-            const box: Box3D = Box3D.create(params.box.params.bottomLeft, params.box.params.topRight);
+            let box: Box3D | undefined = void 0;
+
+            switch (params.box.name) {
+                case 'static-box':
+                    box = Box3D.create(params.box.params.bottomLeft, params.box.params.topRight);
+                    break;
+                case 'cell':
+                    box = this.params.levels.name === 'x-ray'
+                        ? void 0 // TODO get bounding box of the model (how to solve assemblies)
+                        : void 0;
+                    break;
+            }
+
             const data = await this.queryData(box);
             this.currentData = data || { };
 
diff --git a/src/mol-plugin/state/transforms/representation.ts b/src/mol-plugin/state/transforms/representation.ts
index 9bf811edd..25af4e857 100644
--- a/src/mol-plugin/state/transforms/representation.ts
+++ b/src/mol-plugin/state/transforms/representation.ts
@@ -195,16 +195,16 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({
                 type: PD.Mapped<any>(
                     registry.default.name,
                     registry.types,
-                    name => PD.Group<any>(registry.get(name).getParams(themeCtx, VolumeData.Empty ))),
+                    name => PD.Group<any>(registry.get(name).getParams(themeCtx, VolumeData.One ))),
                 colorTheme: PD.Mapped<any>(
                     type.defaultColorTheme,
                     themeCtx.colorThemeRegistry.types,
-                    name => PD.Group<any>(themeCtx.colorThemeRegistry.get(name).getParams({ volume: VolumeData.Empty }))
+                    name => PD.Group<any>(themeCtx.colorThemeRegistry.get(name).getParams({ volume: VolumeData.One }))
                 ),
                 sizeTheme: PD.Mapped<any>(
                     type.defaultSizeTheme,
                     themeCtx.sizeThemeRegistry.types,
-                    name => PD.Group<any>(themeCtx.sizeThemeRegistry.get(name).getParams({ volume: VolumeData.Empty }))
+                    name => PD.Group<any>(themeCtx.sizeThemeRegistry.get(name).getParams({ volume: VolumeData.One }))
                 )
             }
         }
diff --git a/src/mol-plugin/state/transforms/volume.ts b/src/mol-plugin/state/transforms/volume.ts
index 7568a9ab8..a0516c70e 100644
--- a/src/mol-plugin/state/transforms/volume.ts
+++ b/src/mol-plugin/state/transforms/volume.ts
@@ -111,6 +111,7 @@ const VolumeStreamingBehavior = PluginStateTransform.BuiltIn({
     apply: ({ params }, plugin: PluginContext) => Task.create('Volume Streaming', async ctx => {
         const behavior = new VolumeStreaming.Behavior(plugin, params);
         // get the initial data now so that the child projections dont get empty volumes.
+        // TODO: this is a temporary fix
         await behavior.update(behavior.params);
         return new VolumeStreaming.Obj(behavior, { label: 'Volume Streaming' });
     }),
@@ -174,7 +175,7 @@ const VolumeStreamingVisual = PluginStateTransform.BuiltIn({
 });
 
 function createVolumeProps(streaming: VolumeStreaming.Behavior, channel: keyof VolumeStreaming.ChannelData, level: VolumeStreaming.LevelType) {
-    const data = streaming.currentData[channel] || VolumeData.Empty;
+    const data = streaming.currentData[channel] || VolumeData.One;
     // TODO: createTheme fails when VolumeData.Empty is used for some reason.
 
     let isoValue: VolumeIsoValue, color: Color;
diff --git a/src/mol-repr/volume/isosurface.ts b/src/mol-repr/volume/isosurface.ts
index 0082bf2d5..7ebfe7df4 100644
--- a/src/mol-repr/volume/isosurface.ts
+++ b/src/mol-repr/volume/isosurface.ts
@@ -24,18 +24,18 @@ export function createIsoValueParam(defaultValue: VolumeIsoValue) {
         defaultValue,
         {
             'absolute': PD.Converted(
-                (v: VolumeIsoValue) => VolumeIsoValue.toAbsolute(v, VolumeData.Empty.dataStats).absoluteValue,
+                (v: VolumeIsoValue) => VolumeIsoValue.toAbsolute(v, VolumeData.One.dataStats).absoluteValue,
                 (v: number) => VolumeIsoValue.absolute(v),
                 PD.Numeric(0.5, { min: -1, max: 1, step: 0.01 })
             ),
             'relative': PD.Converted(
-                (v: VolumeIsoValue) => VolumeIsoValue.toRelative(v, VolumeData.Empty.dataStats).relativeValue,
+                (v: VolumeIsoValue) => VolumeIsoValue.toRelative(v, VolumeData.One.dataStats).relativeValue,
                 (v: number) => VolumeIsoValue.relative(v),
                 PD.Numeric(2, { min: -10, max: 10, step: 0.01 })
             )
         },
         (v: VolumeIsoValue) => v.kind === 'absolute' ? 'absolute' : 'relative',
-        (v: VolumeIsoValue, c: 'absolute' | 'relative') => c === 'absolute' ? VolumeIsoValue.toAbsolute(v, VolumeData.Empty.dataStats) : VolumeIsoValue.toRelative(v, VolumeData.Empty.dataStats)
+        (v: VolumeIsoValue, c: 'absolute' | 'relative') => c === 'absolute' ? VolumeIsoValue.toAbsolute(v, VolumeData.One.dataStats) : VolumeIsoValue.toRelative(v, VolumeData.One.dataStats)
     )
 }
 
diff --git a/src/mol-state/transform.ts b/src/mol-state/transform.ts
index 57e104f3b..12de75d1c 100644
--- a/src/mol-state/transform.ts
+++ b/src/mol-state/transform.ts
@@ -56,6 +56,10 @@ namespace Transform {
         return { ...t, parent, version: UUID.create22() };
     }
 
+    export function withNewVersion(t: Transform): Transform {
+        return { ...t, version: UUID.create22() };
+    }
+
     export function createRoot(props?: Props): Transform {
         return create(RootRef, StateTransformer.ROOT, {}, { ref: RootRef, props });
     }
diff --git a/src/mol-state/tree/transient.ts b/src/mol-state/tree/transient.ts
index cb75faae3..571d914c3 100644
--- a/src/mol-state/tree/transient.ts
+++ b/src/mol-state/tree/transient.ts
@@ -96,6 +96,16 @@ class TransientTree implements StateTree {
         const old = this.transforms.get(ref);
         this.removeChild(old.parent, ref);
         this.addChild(newParent, ref);
+        this.changeNodes();
+        this.transforms.set(ref, StateTransform.withParent(old, newParent));
+    }
+
+    updateVersion(ref: StateTransform.Ref) {
+        ensurePresent(this.transforms, ref);
+
+        const t = this.transforms.get(ref);
+        this.changeNodes();
+        this.transforms.set(ref, StateTransform.withNewVersion(t));
     }
 
     add(transform: StateTransform, initialState?: Partial<StateObjectCell.State>) {
-- 
GitLab