Преглед на файлове

factored out/moved common volume helpers

- createIsoValueParam
- eachVolumeLoci
Alexander Rose преди 4 години
родител
ревизия
e73227519b

+ 43 - 0
src/mol-model/volume/volume.ts

@@ -13,6 +13,8 @@ import { CubeFormat } from '../../mol-model-formats/volume/cube';
 import { equalEps } from '../../mol-math/linear-algebra/3d/common';
 import { ModelFormat } from '../../mol-model-formats/format';
 import { CustomProperties } from '../custom-property';
+import { ParamDefinition as PD } from '../../mol-util/param-definition';
+import { toPrecision } from '../../mol-util/number';
 
 export interface Volume {
     readonly label?: string
@@ -72,6 +74,47 @@ export namespace Volume {
         }
     }
 
+    const defaultStats: Grid['stats'] = { min: -1, max: 1, mean: 0, sigma: 0.1  };
+    export function createIsoValueParam(defaultValue: Volume.IsoValue, stats?: Grid['stats']) {
+        const sts = stats || defaultStats;
+        const { min, max, mean, sigma } = sts;
+
+        // using ceil/floor could lead to "ouf of bounds" when converting
+        const relMin = (min - mean) / sigma;
+        const relMax = (max - mean) / sigma;
+
+        let def = defaultValue;
+        if (defaultValue.kind === 'absolute') {
+            if (defaultValue.absoluteValue < min) def = Volume.IsoValue.absolute(min);
+            else if (defaultValue.absoluteValue > max) def = Volume.IsoValue.absolute(max);
+        } else {
+            if (defaultValue.relativeValue < relMin) def = Volume.IsoValue.relative(relMin);
+            else if (defaultValue.relativeValue > relMax) def = Volume.IsoValue.relative(relMax);
+        }
+
+        return PD.Conditioned(
+            def,
+            {
+                'absolute': PD.Converted(
+                    (v: Volume.IsoValue) => Volume.IsoValue.toAbsolute(v, Grid.One.stats).absoluteValue,
+                    (v: number) => Volume.IsoValue.absolute(v),
+                    PD.Numeric(mean, { min, max, step: toPrecision(sigma / 100, 2) })
+                ),
+                'relative': PD.Converted(
+                    (v: Volume.IsoValue) => Volume.IsoValue.toRelative(v, Grid.One.stats).relativeValue,
+                    (v: number) => Volume.IsoValue.relative(v),
+                    PD.Numeric(Math.min(1, relMax), { min: relMin, max: relMax, step: toPrecision(Math.round(((max - min) / sigma)) / 100, 2) })
+                )
+            },
+            (v: Volume.IsoValue) => v.kind === 'absolute' ? 'absolute' : 'relative',
+            (v: Volume.IsoValue, c: 'absolute' | 'relative') => c === 'absolute' ? Volume.IsoValue.toAbsolute(v, sts) : Volume.IsoValue.toRelative(v, sts),
+            { isEssential: true }
+        );
+    }
+
+    export const IsoValueParam = createIsoValueParam(Volume.IsoValue.relative(2));
+    export type IsoValueParam = typeof IsoValueParam
+
     export const One: Volume = {
         label: '',
         grid: Grid.One,

+ 4 - 5
src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts

@@ -8,7 +8,6 @@
 import { ParamDefinition as PD } from '../../../../mol-util/param-definition';
 import { PluginStateObject } from '../../../../mol-plugin-state/objects';
 import { Volume, Grid } from '../../../../mol-model/volume';
-import { createIsoValueParam } from '../../../../mol-repr/volume/isosurface';
 import { VolumeServerHeader, VolumeServerInfo } from './model';
 import { Box3D } from '../../../../mol-math/geometry';
 import { Vec3 } from '../../../../mol-math/linear-algebra';
@@ -39,10 +38,10 @@ export namespace VolumeStreaming {
 
     function channelParam(label: string, color: Color, defaultValue: Volume.IsoValue, stats: Grid['stats'], defaults: Partial<ChannelParams> = {}) {
         return PD.Group<ChannelParams>({
-            isoValue: createIsoValueParam(typeof defaults.isoValue !== 'undefined' ? defaults.isoValue : defaultValue, stats),
-            color: PD.Color(typeof defaults.color !== 'undefined' ? defaults.color : color),
-            wireframe: PD.Boolean(typeof defaults.wireframe !== 'undefined' ? defaults.wireframe : false),
-            opacity: PD.Numeric(typeof defaults.opacity !== 'undefined' ? defaults.opacity : 0.3, { min: 0, max: 1, step: 0.01 })
+            isoValue: Volume.createIsoValueParam(defaults.isoValue ?? defaultValue, stats),
+            color: PD.Color(defaults.color ?? color),
+            wireframe: PD.Boolean(defaults.wireframe ?? false),
+            opacity: PD.Numeric(defaults.opacity ?? 0.3, { min: 0, max: 1, step: 0.01 })
         }, { label, isExpanded: true });
     }
 

+ 1 - 2
src/mol-plugin/behavior/dynamic/volume-streaming/transformers.ts

@@ -11,7 +11,6 @@ import { ParamDefinition as PD } from '../../../../mol-util/param-definition';
 import { Task } from '../../../../mol-task';
 import { PluginContext } from '../../../../mol-plugin/context';
 import { urlCombine } from '../../../../mol-util/url';
-import { createIsoValueParam } from '../../../../mol-repr/volume/isosurface';
 import { Volume } from '../../../../mol-model/volume';
 import { StateAction, StateObject, StateTransformer } from '../../../../mol-state';
 import { getStreamingMethod, getIds, getContourLevel, getEmdbIds } from './util';
@@ -157,7 +156,7 @@ const InfoEntryParams = {
     dataId: PD.Text(''),
     source: PD.MappedStatic('x-ray', {
         'em': PD.Group({
-            isoValue: createIsoValueParam(Volume.IsoValue.relative(1))
+            isoValue: Volume.createIsoValueParam(Volume.IsoValue.relative(1))
         }),
         'x-ray': PD.Group({ })
     })

+ 6 - 65
src/mol-repr/volume/isosurface.ts

@@ -17,56 +17,15 @@ import { NullLocation } from '../../mol-model/location';
 import { VisualUpdateState } from '../util';
 import { Lines } from '../../mol-geo/geometry/lines/lines';
 import { RepresentationContext, RepresentationParamsGetter, Representation } from '../representation';
-import { toPrecision } from '../../mol-util/number';
 import { PickingId } from '../../mol-geo/geometry/picking';
 import { EmptyLoci, Loci } from '../../mol-model/loci';
-import { Interval, OrderedSet } from '../../mol-data/int';
+import { Interval } from '../../mol-data/int';
 import { Tensor } from '../../mol-math/linear-algebra';
 import { fillSerial } from '../../mol-util/array';
-
-const defaultStats: Grid['stats'] = { min: -1, max: 1, mean: 0, sigma: 0.1  };
-export function createIsoValueParam(defaultValue: Volume.IsoValue, stats?: Grid['stats']) {
-    const sts = stats || defaultStats;
-    const { min, max, mean, sigma } = sts;
-
-    // using ceil/floor could lead to "ouf of bounds" when converting
-    const relMin = (min - mean) / sigma;
-    const relMax = (max - mean) / sigma;
-
-    let def = defaultValue;
-    if (defaultValue.kind === 'absolute') {
-        if (defaultValue.absoluteValue < min) def = Volume.IsoValue.absolute(min);
-        else if (defaultValue.absoluteValue > max) def = Volume.IsoValue.absolute(max);
-    } else {
-        if (defaultValue.relativeValue < relMin) def = Volume.IsoValue.relative(relMin);
-        else if (defaultValue.relativeValue > relMax) def = Volume.IsoValue.relative(relMax);
-    }
-
-    return PD.Conditioned(
-        def,
-        {
-            'absolute': PD.Converted(
-                (v: Volume.IsoValue) => Volume.IsoValue.toAbsolute(v, Grid.One.stats).absoluteValue,
-                (v: number) => Volume.IsoValue.absolute(v),
-                PD.Numeric(mean, { min, max, step: toPrecision(sigma / 100, 2) })
-            ),
-            'relative': PD.Converted(
-                (v: Volume.IsoValue) => Volume.IsoValue.toRelative(v, Grid.One.stats).relativeValue,
-                (v: number) => Volume.IsoValue.relative(v),
-                PD.Numeric(Math.min(1, relMax), { min: relMin, max: relMax, step: toPrecision(Math.round(((max - min) / sigma)) / 100, 2) })
-            )
-        },
-        (v: Volume.IsoValue) => v.kind === 'absolute' ? 'absolute' : 'relative',
-        (v: Volume.IsoValue, c: 'absolute' | 'relative') => c === 'absolute' ? Volume.IsoValue.toAbsolute(v, sts) : Volume.IsoValue.toRelative(v, sts),
-        { isEssential: true }
-    );
-}
-
-export const IsoValueParam = createIsoValueParam(Volume.IsoValue.relative(2));
-type IsoValueParam = typeof IsoValueParam
+import { eachVolumeLoci } from './util';
 
 export const VolumeIsosurfaceParams = {
-    isoValue: IsoValueParam
+    isoValue: Volume.IsoValueParam
 };
 export type VolumeIsosurfaceParams = typeof VolumeIsosurfaceParams
 export type VolumeIsosurfaceProps = PD.Values<VolumeIsosurfaceParams>
@@ -83,26 +42,8 @@ function getIsosurfaceLoci(pickingId: PickingId, volume: Volume, props: VolumeIs
     return EmptyLoci;
 }
 
-function eachIsosurface(loci: Loci, volume: Volume, props: VolumeIsosurfaceProps, apply: (interval: Interval) => boolean) {
-    let changed = false;
-    if (Volume.isLoci(loci)) {
-        if (!Volume.areEquivalent(loci.volume, volume)) return false;
-        if (apply(Interval.ofLength(volume.grid.cells.data.length))) changed = true;
-    } else if (Volume.Isosurface.isLoci(loci)) {
-        if (!Volume.areEquivalent(loci.volume, volume)) return false;
-        if (!Volume.IsoValue.areSame(loci.isoValue, props.isoValue, volume.grid.stats)) return false;
-        if (apply(Interval.ofLength(volume.grid.cells.data.length))) changed = true;
-    } else if (Volume.Cell.isLoci(loci)) {
-        if (!Volume.areEquivalent(loci.volume, volume)) return false;
-        if (Interval.is(loci.indices)) {
-            if (apply(loci.indices)) changed = true;
-        } else {
-            OrderedSet.forEach(loci.indices, v => {
-                if (apply(Interval.ofSingleton(v))) changed = true;
-            });
-        }
-    }
-    return changed;
+export function eachIsosurface(loci: Loci, volume: Volume, props: VolumeIsosurfaceProps, apply: (interval: Interval) => boolean) {
+    return eachVolumeLoci(loci, volume, props.isoValue, apply);
 }
 
 //
@@ -205,7 +146,7 @@ export const IsosurfaceParams = {
 export type IsosurfaceParams = typeof IsosurfaceParams
 export function getIsosurfaceParams(ctx: ThemeRegistryContext, volume: Volume) {
     const p = PD.clone(IsosurfaceParams);
-    p.isoValue = createIsoValueParam(Volume.IsoValue.relative(2), volume.grid.stats);
+    p.isoValue = Volume.createIsoValueParam(Volume.IsoValue.relative(2), volume.grid.stats);
     return p;
 }
 

+ 2 - 3
src/mol-repr/volume/slice.ts

@@ -20,7 +20,6 @@ import { Interval, OrderedSet, SortedArray } from '../../mol-data/int';
 import { transformPositionArray } from '../../mol-geo/util';
 import { equalEps } from '../../mol-math/linear-algebra/3d/common';
 import { RenderableState } from '../../mol-gl/renderable';
-import { createIsoValueParam, IsoValueParam } from './isosurface';
 import { Color } from '../../mol-util/color';
 import { ColorTheme } from '../../mol-theme/color';
 
@@ -177,7 +176,7 @@ export const SliceParams = {
         y: PD.Numeric(0, { min: 0, max: 0, step: 1 }),
         z: PD.Numeric(0, { min: 0, max: 0, step: 1 }),
     }, { isEssential: true }),
-    isoValue: IsoValueParam,
+    isoValue: Volume.IsoValueParam,
 };
 export type SliceParams = typeof SliceParams
 export function getSliceParams(ctx: ThemeRegistryContext, volume: Volume) {
@@ -188,7 +187,7 @@ export function getSliceParams(ctx: ThemeRegistryContext, volume: Volume) {
         y: PD.Numeric(0, { min: 0, max: dim[1] - 1, step: 1 }),
         z: PD.Numeric(0, { min: 0, max: dim[2] - 1, step: 1 }),
     }, { isEssential: true });
-    p.isoValue = createIsoValueParam(Volume.IsoValue.absolute(volume.grid.stats.min), volume.grid.stats);
+    p.isoValue = Volume.createIsoValueParam(Volume.IsoValue.absolute(volume.grid.stats.min), volume.grid.stats);
     return p;
 }
 

+ 31 - 0
src/mol-repr/volume/util.ts

@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Volume } from '../../mol-model/volume';
+import { Loci } from '../../mol-model/loci';
+import { Interval, OrderedSet } from '../../mol-data/int';
+
+export function eachVolumeLoci(loci: Loci, volume: Volume, isoValue: Volume.IsoValue, apply: (interval: Interval) => boolean) {
+    let changed = false;
+    if (Volume.isLoci(loci)) {
+        if (!Volume.areEquivalent(loci.volume, volume)) return false;
+        if (apply(Interval.ofLength(volume.grid.cells.data.length))) changed = true;
+    } else if (Volume.Isosurface.isLoci(loci)) {
+        if (!Volume.areEquivalent(loci.volume, volume)) return false;
+        if (!Volume.IsoValue.areSame(loci.isoValue, isoValue, volume.grid.stats)) return false;
+        if (apply(Interval.ofLength(volume.grid.cells.data.length))) changed = true;
+    } else if (Volume.Cell.isLoci(loci)) {
+        if (!Volume.areEquivalent(loci.volume, volume)) return false;
+        if (Interval.is(loci.indices)) {
+            if (apply(loci.indices)) changed = true;
+        } else {
+            OrderedSet.forEach(loci.indices, v => {
+                if (apply(Interval.ofSingleton(v))) changed = true;
+            });
+        }
+    }
+    return changed;
+}