diff --git a/src/mol-math/linear-algebra/3d/vec2.ts b/src/mol-math/linear-algebra/3d/vec2.ts
index a87e6fcef566a42891a9c6a3cea63644e1f50cb6..b19586a1475fec82ce41b5ff200126e286221b3d 100644
--- a/src/mol-math/linear-algebra/3d/vec2.ts
+++ b/src/mol-math/linear-algebra/3d/vec2.ts
@@ -152,6 +152,10 @@ namespace Vec2 {
         out[1] = 1.0 / a[1];
         return out;
     }
+
+    export function areEqual(a: Vec2, b: Vec2) {
+        return a[0] === b[0] && a[1] === b[1];
+    }
 }
 
 export default Vec2
\ No newline at end of file
diff --git a/src/mol-plugin/ui/controls/parameters.tsx b/src/mol-plugin/ui/controls/parameters.tsx
index 632532e786fc3870c61cffb24bc8d5d33a63f46c..b95fa7aabd0a0ce0ec0a490ed0d759d91951fc1a 100644
--- a/src/mol-plugin/ui/controls/parameters.tsx
+++ b/src/mol-plugin/ui/controls/parameters.tsx
@@ -189,7 +189,7 @@ export class ConvertedControl extends React.PureComponent<ValueControlProps<PD.C
     render() {
         const Control: ValueControl = controlFor(this.props.param.param as PD.Any);
 
-        return <Control value={this.props.param.fromValue(this.props.value)} param={this.props.param} onChange={this.onChange} onEnter={this.props.onEnter} isEnabled={this.props.isEnabled} />
+        return <Control value={this.props.param.fromValue(this.props.value)} param={this.props.param.param} onChange={this.onChange} onEnter={this.props.onEnter} isEnabled={this.props.isEnabled} />
     }
 }
 
diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts
index e9f336caf41612b3f7bcd0fdbcde1526468d51f7..6f3b2e4a9e4b6b82d0ac3cbea0deed20b403a22f 100644
--- a/src/mol-util/param-definition.ts
+++ b/src/mol-util/param-definition.ts
@@ -6,7 +6,7 @@
  */
 
 import { Color as ColorData } from './color';
-import { shallowClone } from 'mol-util';
+import { shallowClone, shallowEqual } from 'mol-util';
 import { Vec2 } from 'mol-math/linear-algebra';
 
 export namespace ParamDefinition {
@@ -103,7 +103,8 @@ export namespace ParamDefinition {
         return { type: 'group', defaultValue: getDefaultValues(params) as any, params, ...info };
     }
 
-    export interface Mapped<T> extends Base<{ name: string, params: T }> {
+    export interface NamedParams<T = any> { name: string, params: T }
+    export interface Mapped<T> extends Base<NamedParams<T>> {
         type: 'mapped',
         select: Select<string>,
         map(name: string): Any
@@ -154,4 +155,47 @@ export namespace ParamDefinition {
         // TODO
         return void 0;
     }
+
+    export function areEqual(params: Params, a: any, b: any): boolean {
+        if (a === b) return true;
+        if (!a) return !b;
+        if (!b) return !a;
+
+        if (typeof a !== 'object' || typeof b !== 'object') return false;
+        for (const k of Object.keys(params)) {
+            if (!isParamEqual(params[k], a[k], b[k])) return false;
+        }
+        return true;
+    }
+
+    function isParamEqual(p: Any, a: any, b: any): boolean {
+        if (a === b) return true;
+        if (!a) return !b;
+        if (!b) return !a;
+
+        if (p.type === 'group') {
+            return areEqual(p.params, a, b);
+        } else if (p.type === 'mapped') {
+            const u = a as NamedParams, v = b as NamedParams;
+            if (!u) return !v;
+            if (!u || !v) return false;
+            if (u.name !== v.name) return false;
+            const map = p.map(u.name);
+            return isParamEqual(map, u.params, v.params);
+        } else if (p.type === 'interval') {
+            return a[0] === b[0] && a[1] === b[1];
+        } else if (p.type === 'line-graph') {
+            const u = a as LineGraph['defaultValue'], v = b as LineGraph['defaultValue'];
+            if (u.length !== v.length) return false;
+            for (let i = 0, _i = u.length; i < _i; i++) {
+                if (!Vec2.areEqual(u[i], v[i])) return false;
+            }
+            return true;
+        } else if (typeof a === 'object' && typeof b === 'object') {
+            return shallowEqual(a, b);
+        }
+
+        // a === b was checked at the top.
+        return false;
+    }
 }
\ No newline at end of file