Browse Source

added number precision helpers, improved isovalue step calculation

Alexander Rose 5 years ago
parent
commit
2c88ace91c
3 changed files with 23 additions and 5 deletions
  1. 3 2
      src/mol-plugin/ui/custom/volume.tsx
  2. 3 2
      src/mol-repr/volume/isosurface.ts
  3. 17 1
      src/mol-util/number.ts

+ 3 - 2
src/mol-plugin/ui/custom/volume.tsx

@@ -15,6 +15,7 @@ import { Slider } from '../controls/slider';
 import { VolumeIsoValue, VolumeData } from '../../../mol-model/volume';
 import { Vec3 } from '../../../mol-math/linear-algebra';
 import { ColorNames } from '../../../mol-util/color/names';
+import { toPrecision } from '../../../mol-util/number';
 
 const ChannelParams = {
     color: PD.Color(ColorNames.black, { description: 'Display color of the volume.' }),
@@ -40,12 +41,12 @@ function Channel(props: {
     const value = channel.isoValue.kind === 'relative' ? channel.isoValue.relativeValue : channel.isoValue.absoluteValue;
     const relMin = (min - mean) / sigma;
     const relMax = (max - mean) / sigma;
+    const step = toPrecision(isRelative ? Math.round(((max - min) / sigma)) / 100 : sigma / 100, 2)
 
     return <ExpandableGroup
         label={props.label + (props.isRelative ? ' \u03C3' : '')}
         colorStripe={channel.color}
-        pivot={<Slider value={value} min={isRelative ? relMin : min} max={isRelative ? relMax : max}
-            step={isRelative ? sigma / 100 : Math.round(((max - min) / sigma)) / 100}
+        pivot={<Slider value={value} min={isRelative ? relMin : min} max={isRelative ? relMax : max} step={step}
             onChange={v => props.changeIso(props.name, v, isRelative)} disabled={props.params.isDisabled} onEnter={props.params.events.onEnter} />}
         controls={<ParameterControls onChange={({ name, value }) => props.changeParams(props.name, name, value)} params={ChannelParams} values={channel} onEnter={props.params.events.onEnter} />}
     />;

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

@@ -18,6 +18,7 @@ import { EmptyLoci } from '../../mol-model/loci';
 import { VisualUpdateState } from '../util';
 import { Lines } from '../../mol-geo/geometry/lines/lines';
 import { RepresentationContext, RepresentationParamsGetter, Representation } from '../representation';
+import { toPrecision } from '../../mol-util/number';
 
 const defaultStats: VolumeData['dataStats'] = { min: -1, max: 1, mean: 0, sigma: 0.1  };
 export function createIsoValueParam(defaultValue: VolumeIsoValue, stats?: VolumeData['dataStats']) {
@@ -43,12 +44,12 @@ export function createIsoValueParam(defaultValue: VolumeIsoValue, stats?: Volume
             'absolute': PD.Converted(
                 (v: VolumeIsoValue) => VolumeIsoValue.toAbsolute(v, VolumeData.One.dataStats).absoluteValue,
                 (v: number) => VolumeIsoValue.absolute(v),
-                PD.Numeric(mean, { min, max, step: sigma / 100 })
+                PD.Numeric(mean, { min, max, step: toPrecision(sigma / 100, 2) })
             ),
             'relative': PD.Converted(
                 (v: VolumeIsoValue) => VolumeIsoValue.toRelative(v, VolumeData.One.dataStats).relativeValue,
                 (v: number) => VolumeIsoValue.relative(v),
-                PD.Numeric(Math.min(1, relMax), { min: relMin, max: relMax, step: Math.round(((max - min) / sigma)) / 100 })
+                PD.Numeric(Math.min(1, relMax), { min: relMin, max: relMax, step: toPrecision(Math.round(((max - min) / sigma)) / 100, 2) })
             )
         },
         (v: VolumeIsoValue) => v.kind === 'absolute' ? 'absolute' : 'relative',

+ 17 - 1
src/mol-util/number.ts

@@ -1,7 +1,8 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
 /**
@@ -52,4 +53,19 @@ export function isInteger(s: string) {
     s = s.trim()
     const n = parseInt(s, 10)
     return isNaN(n) ? false : n.toString() === s
+}
+
+export function getPrecision(v: number) {
+    if (!isFinite(v)) return 0
+    let e = 1
+    let p = 0
+    while (Math.round(v * e) / e !== v) {
+        e *= 10
+        ++p
+    }
+    return p
+}
+
+export function toPrecision(v: number, precision: number) {
+    return parseFloat(v.toPrecision(precision))
 }