diff --git a/src/apps/rednatco/controls.tsx b/src/apps/rednatco/controls.tsx
index 11ee3a5b36b3c31cc7a9caf2db2d73d154a639e5..2c3c53896964c687c7ec6e10969c31fb2351dbda 100644
--- a/src/apps/rednatco/controls.tsx
+++ b/src/apps/rednatco/controls.tsx
@@ -56,6 +56,34 @@ export class ToggleButton extends React.Component<{ text: string, enabled: boole
     }
 }
 
+export class RangeSlider extends React.Component<RangeSlider.Props> {
+    render() {
+        return (
+            <input
+                className='rmsp-range-slider'
+                type='range'
+                value={this.props.value ? this.props.value : 0}
+                min={this.props.min}
+                max={this.props.max}
+                step={this.props.step}
+                onChange={evt => {
+                    const n = parseFloat(evt.currentTarget.value);
+                    this.props.onChange(isNaN(n) ? null : n);
+                }}
+            />
+        );
+    }
+}
+export namespace RangeSlider {
+    export interface Props {
+        min: number;
+        max: number;
+        step: number;
+        value: number|null;
+        onChange: (n: number|null) => void;
+    }
+}
+
 export class SpinBox extends React.Component<SpinBox.Props> {
     private clsDisabled() {
         return this.props.classNameDisabled ?? 'rmsp-spinbox-input-disabled';
@@ -88,7 +116,14 @@ export class SpinBox extends React.Component<SpinBox.Props> {
                     type='text'
                     className={this.props.disabled ? this.clsDisabled() : this.clsEnabled()}
                     value={this.props.formatter ? this.props.formatter(this.props.value) : this.props.value?.toString() ?? ''}
-                    onChange={evt => this.props.onChange(evt.currentTarget.value)}
+                    onChange={evt =>{
+                        const v = evt.currentTarget.value;
+                        const n = parseFloat(v);
+                        if (!isNaN(n) && (n < this.props.min || n > this.props.max))
+                            return;
+
+                        this.props.onChange(evt.currentTarget.value);
+                    }}
                     onWheel={evt => {
                         evt.stopPropagation();
                         if (this.props.value === null)
diff --git a/src/apps/rednatco/density-map-controls.tsx b/src/apps/rednatco/density-map-controls.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b922006a04cc4f67f5bbbd9dae4cfe27e4d7315e
--- /dev/null
+++ b/src/apps/rednatco/density-map-controls.tsx
@@ -0,0 +1,108 @@
+import React from 'react';
+import { CollapsibleVertical, RangeSlider, SpinBox, ToggleButton } from './controls';
+import { isoToFixed } from './util';
+
+export class DensityMapControls extends React.Component<DensityMapControls.Props> {
+    render() {
+        return (
+            <CollapsibleVertical caption='Density map'>
+                <div className='rmsp-controls'>
+                    <div className='rmsp-controls-section-caption'>
+                        Representations:
+                    </div>
+                    <div className='rmsp-controls-line'>
+                        <div className='rmsp-control-item'>
+                            <ToggleButton
+                                text='Wireframe'
+                                switchedOn={this.props.wireframe}
+                                onClick={() => this.props.toggleWireframe()}
+                                enabled={true}
+                            />
+                        </div>
+                        <div className='rmsp-control-item'>
+                            <ToggleButton
+                                text='Solid'
+                                switchedOn={this.props.solid}
+                                onClick={() => this.props.toggleSolid()}
+                                enabled={true}
+                            />
+                        </div>
+                    </div>
+
+                    <div className='rmsp-controls-section-caption'>
+                        Iso:
+                    </div>
+                    <div className='rmsp-controls-line'>
+                        <div className='rmsp-control-item'>
+                            <RangeSlider
+                                min={this.props.isoMin}
+                                max={this.props.isoMax}
+                                step={this.props.isoStep}
+                                value={isoToFixed(this.props.iso, this.props.isoStep)}
+                                onChange={(v) => this.props.changeIso(v!)}
+                            />
+                        </div>
+                        <div className='rmsp-control-item'>
+                            <div style={{ display: 'grid', gridTemplateColumns: '4em 1fr' }}>
+                                <SpinBox
+                                    min={this.props.isoMin}
+                                    max={this.props.isoMax}
+                                    step={this.props.isoStep}
+                                    value={isoToFixed(this.props.iso, this.props.isoStep)}
+                                    onChange={(v) => this.props.changeIso(parseFloat(v))}
+                                    pathPrefix=''
+                                />
+                                <div />
+                            </div>
+                        </div>
+                    </div>
+
+                    <div className='rmsp-controls-section-caption'>
+                        Transparency:
+                    </div>
+                    <div className='rmsp-controls-line'>
+                        <div className='rmsp-control-item'>
+                            <RangeSlider
+                                min={0}
+                                max={1}
+                                step={0.1}
+                                value={(1.0 - this.props.alpha)}
+                                onChange={(v) => this.props.changeAlpha(1.0 - v!)}
+                            />
+                        </div>
+                        <div className='rmsp-control-item'>
+                            <div style={{ display: 'grid', gridTemplateColumns: '4em 1fr' }}>
+                                <SpinBox
+                                    min={0}
+                                    max={1}
+                                    step={0.1}
+                                    value={parseFloat((1.0 - this.props.alpha).toFixed(1))}
+                                    onChange={(v) => this.props.changeAlpha(1.0 - parseFloat(v))}
+                                    pathPrefix=''
+                                />
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </CollapsibleVertical>
+        );
+    }
+}
+
+export namespace DensityMapControls {
+    export interface Props {
+        wireframe: boolean;
+        solid: boolean;
+        toggleWireframe: () => void;
+        toggleSolid: () => void;
+
+        isoMin: number;
+        isoMax: number;
+        isoStep: number;
+        iso: number;
+        changeIso: (iso: number) => void;
+
+        alpha: number;
+        changeAlpha: (alpha: number) => void;
+    }
+}
diff --git a/src/apps/rednatco/index.tsx b/src/apps/rednatco/index.tsx
index e5a86b0aec8797fff1391b05bc594f2ba5b9d0a7..de537d688e735662f2cd77ceed309d7515c5202e 100644
--- a/src/apps/rednatco/index.tsx
+++ b/src/apps/rednatco/index.tsx
@@ -2,12 +2,13 @@ import React from 'react';
 import ReactDOM from 'react-dom';
 import { ReDNATCOMspApi as Api } from './api';
 import { ReDNATCOMspApiImpl } from './api-impl';
+import { DensityMapControls } from './density-map-controls';
 import { Filters } from './filters';
 import { ReDNATCOMspViewer } from './viewer';
 import { NtCColors } from './colors';
 import { ColorPicker } from './color-picker';
 import { CollapsibleVertical, PushButton, ToggleButton } from './controls';
-import { luminance } from './util';
+import { isoBounds, luminance, toggleArray } from './util';
 import { Color } from '../../mol-util/color';
 import { assertUnreachable } from '../../mol-util/type-helpers';
 import './index.html';
@@ -26,27 +27,39 @@ const ConformersByClass = {
 type ConformersByClass = typeof ConformersByClass;
 
 const DefaultChainColor = Color(0xD9D9D9);
+const DefaultDensityMapAlpha = 0.5;
 const DefaultWaterColor = Color(0x0BB2FF);
 export type VisualRepresentations = 'ball-and-stick'|'cartoon';
+export type DensityMapRepresentation = 'wireframe'|'solid';
+
 const Display = {
-    representation: 'cartoon' as VisualRepresentations,
+    structures: {
+        representation: 'cartoon' as VisualRepresentations,
+
+        showNucleic: true,
+        showProtein: false,
+        showWater: false,
 
-    showNucleic: true,
-    showProtein: false,
-    showWater: false,
+        showPyramids: true,
+        pyramidsTransparent: false,
 
-    showPyramids: true,
-    pyramidsTransparent: false,
+        showBalls: false,
+        ballsTransparent: false,
 
-    showBalls: false,
-    ballsTransparent: false,
+        modelNumber: 1,
 
-    modelNumber: 1,
+        classColors: { ...NtCColors.Classes },
+        conformerColors: { ...NtCColors.Conformers },
+        chainColor: DefaultChainColor,
+        waterColor: DefaultWaterColor,
+    },
+    densityMap: {
+        representations: ['wireframe'] as DensityMapRepresentation[],
+        isoValue: 0,
 
-    classColors: { ...NtCColors.Classes },
-    conformerColors: { ...NtCColors.Conformers },
-    chainColor: DefaultChainColor,
-    waterColor: DefaultWaterColor,
+        alpha: DefaultDensityMapAlpha,
+        color: 0x000000
+    },
 };
 export type Display = typeof Display;
 
@@ -99,7 +112,10 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
     private updateChainColor(color: number) {
         const display: Display = {
             ...this.state.display,
-            chainColor: Color(color),
+            structures: {
+                ...this.state.display.structures,
+                chainColor: Color(color),
+            },
         };
 
         this.viewer!.changeChainColor(display);
@@ -107,7 +123,7 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
     }
 
     private updateClassColor(changes: { cls: keyof NtCColors.Classes, color: number }|{ cls: keyof NtCColors.Classes, color: number }[]) {
-        const classColors = { ...this.state.display.classColors };
+        const classColors = { ...this.state.display.structures.classColors };
 
         const isArray = Array.isArray(changes);
         if (isArray) {
@@ -116,7 +132,7 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
             classColors[changes.cls] = Color(changes.color);
 
         const conformerColors: NtCColors.Conformers = {
-            ...this.state.display.conformerColors,
+            ...this.state.display.structures.conformerColors,
             ...(isArray
                 ? changes.map(item => this.classColorToConformers(item.cls, Color(item.color)))
                 : this.classColorToConformers(changes.cls, Color(changes.color)))
@@ -128,7 +144,7 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
     }
 
     private updateConformerColor(changes: { conformer: keyof NtCColors.Conformers, color: number }|{ conformer: keyof NtCColors.Conformers, color: number }[]) {
-        const conformerColors = { ...this.state.display.conformerColors };
+        const conformerColors = { ...this.state.display.structures.conformerColors };
         if (Array.isArray(changes))
             changes.forEach(item => conformerColors[item.conformer] = Color(item.color));
         else
@@ -142,7 +158,10 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
     private updateWaterColor(color: number) {
         const display: Display = {
             ...this.state.display,
-            waterColor: Color(color),
+            structures: {
+                ...this.state.display.structures,
+                waterColor: Color(color),
+            },
         };
 
         this.viewer!.changeWaterColor(display);
@@ -196,10 +215,13 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
 
             const display: Display = {
                 ...this.state.display,
-                modelNumber: cmd.model,
+                structures: {
+                    ...this.state.display.structures,
+                    modelNumber: cmd.model,
+                },
             };
 
-            this.viewer.switchModel(display);
+            this.viewer.switchModel(display.structures.modelNumber);
             this.setState({ ...this.state, display });
         }
     }
@@ -244,6 +266,9 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
         const hasProtein = this.viewer?.has('structure', 'protein') ?? false;
         const hasWater = this.viewer?.has('structure', 'water') ?? false;
 
+        const isoRange = this.viewer?.densityMapIsoRange();
+        const _isoBounds = isoRange ? isoBounds(isoRange.min, isoRange.max) : { min: 0, max: 0, step: 0 };
+
         return (
             <div className='rmsp-app'>
                 <div id={this.props.elemId + '-viewer'} className='rmsp-viewer'></div>
@@ -253,12 +278,16 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                         <div className='rmsp-controls-line'>
                             <div className='rmsp-control-item'>
                                 <PushButton
-                                    text={capitalize(this.state.display.representation)}
+                                    text={capitalize(this.state.display.structures.representation)}
                                     enabled={ready}
                                     onClick={() => {
                                         const display: Display = {
                                             ...this.state.display,
-                                            representation: this.state.display.representation === 'cartoon' ? 'ball-and-stick' : 'cartoon',
+                                            structures: {
+                                                ...this.state.display.structures,
+                                                representation: this.state.display.structures.representation === 'cartoon'
+                                                    ? 'ball-and-stick' : 'cartoon',
+                                            },
                                         };
                                         this.viewer!.changeRepresentation(display);
                                         this.setState({ ...this.state, display });
@@ -273,11 +302,14 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                                 <ToggleButton
                                     text='Nucleic'
                                     enabled={hasNucleic}
-                                    switchedOn={this.state.display.showNucleic}
+                                    switchedOn={this.state.display.structures.showNucleic}
                                     onClick={() => {
                                         const display: Display = {
                                             ...this.state.display,
-                                            showNucleic: !this.state.display.showNucleic,
+                                            structures: {
+                                                ...this.state.display.structures,
+                                                showNucleic: !this.state.display.structures.showNucleic,
+                                            }
                                         };
                                         this.viewer!.toggleSubstructure('nucleic', display);
                                         this.setState({ ...this.state, display });
@@ -288,11 +320,14 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                                 <ToggleButton
                                     text='Protein'
                                     enabled={hasProtein}
-                                    switchedOn={this.state.display.showProtein}
+                                    switchedOn={this.state.display.structures.showProtein}
                                     onClick={() => {
                                         const display: Display = {
                                             ...this.state.display,
-                                            showProtein: !this.state.display.showProtein,
+                                            structures: {
+                                                ...this.state.display.structures,
+                                                showProtein: !this.state.display.structures.showProtein,
+                                            },
                                         };
                                         this.viewer!.toggleSubstructure('protein', display);
                                         this.setState({ ...this.state, display });
@@ -303,11 +338,14 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                                 <ToggleButton
                                     text='Water'
                                     enabled={hasWater}
-                                    switchedOn={this.state.display.showWater}
+                                    switchedOn={this.state.display.structures.showWater}
                                     onClick={() => {
                                         const display: Display = {
                                             ...this.state.display,
-                                            showWater: !this.state.display.showWater,
+                                            structures: {
+                                                ...this.state.display.structures,
+                                                showWater: !this.state.display.structures.showWater,
+                                            },
                                         };
                                         this.viewer!.toggleSubstructure('water', display);
                                         this.setState({ ...this.state, display });
@@ -323,11 +361,14 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                                     <ToggleButton
                                         text='Pyramids'
                                         enabled={ready}
-                                        switchedOn={this.state.display.showPyramids}
+                                        switchedOn={this.state.display.structures.showPyramids}
                                         onClick={() => {
                                             const display: Display = {
                                                 ...this.state.display,
-                                                showPyramids: !this.state.display.showPyramids,
+                                                structures: {
+                                                    ...this.state.display.structures,
+                                                    showPyramids: !this.state.display.structures.showPyramids,
+                                                }
                                             };
                                             this.viewer!.changePyramids(display);
                                             this.setState({ ...this.state, display });
@@ -336,12 +377,15 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                                 </div>
                                 <div className='rmsp-control-item'>
                                     <PushButton
-                                        text={this.state.display.pyramidsTransparent ? 'Transparent' : 'Solid'}
-                                        enabled={this.state.display.showPyramids}
+                                        text={this.state.display.structures.pyramidsTransparent ? 'Transparent' : 'Solid'}
+                                        enabled={this.state.display.structures.showPyramids}
                                         onClick={() => {
                                             const display: Display = {
                                                 ...this.state.display,
-                                                pyramidsTransparent: !this.state.display.pyramidsTransparent,
+                                                structures: {
+                                                    ...this.state.display.structures,
+                                                    pyramidsTransparent: !this.state.display.structures.pyramidsTransparent,
+                                                }
                                             };
                                             this.viewer!.changePyramids(display);
                                             this.setState({ ...this.state, display });
@@ -360,12 +404,15 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                                 </div>
                                 <div className='rmsp-control-item'>
                                     <PushButton
-                                        text={this.state.display.ballsTransparent ? 'Transparent' : 'Solid'}
-                                        enabled={this.state.display.showBalls}
+                                        text={this.state.display.structures.ballsTransparent ? 'Transparent' : 'Solid'}
+                                        enabled={this.state.display.structures.showBalls}
                                         onClick={() => {
                                             const display: Display = {
                                                 ...this.state.display,
-                                                ballsTransparent: !this.state.display.ballsTransparent,
+                                                structures: {
+                                                    ...this.state.display.structures,
+                                                    ballsTransparent: !this.state.display.structures.ballsTransparent,
+                                                },
                                             };
                                             /* No balls today... */
                                             this.setState({ ...this.state, display });
@@ -383,11 +430,11 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                                         className='rmsp-control-item'
                                         onClick={evt => ColorPicker.create(
                                             evt,
-                                            this.state.display.classColors[k],
+                                            this.state.display.structures.classColors[k],
                                             color => this.updateClassColor({ cls: k, color })
                                         )}
                                     >
-                                        <ColorBox caption={k} color={this.state.display.classColors[k]} />
+                                        <ColorBox caption={k} color={this.state.display.structures.classColors[k]} />
                                     </div>
                                     <PushButton
                                         text='R'
@@ -411,21 +458,21 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                                                 className='rmsp-control-item'
                                                 onClick={evt => ColorPicker.create(
                                                     evt,
-                                                    this.state.display.conformerColors[uprKey],
+                                                    this.state.display.structures.conformerColors[uprKey],
                                                     color => this.updateConformerColor({ conformer: uprKey, color })
                                                 )}
                                             >
-                                                <ColorBox caption={`${ntc.slice(0, 2)}`} color={this.state.display.conformerColors[uprKey]} />
+                                                <ColorBox caption={`${ntc.slice(0, 2)}`} color={this.state.display.structures.conformerColors[uprKey]} />
                                             </div>
                                             <div
                                                 className='rmsp-control-item'
                                                 onClick={evt => ColorPicker.create(
                                                     evt,
-                                                    this.state.display.conformerColors[lwrKey],
+                                                    this.state.display.structures.conformerColors[lwrKey],
                                                     color => this.updateConformerColor({ conformer: lwrKey, color })
                                                 )}
                                             >
-                                                <ColorBox caption={`${ntc.slice(2)}`} color={this.state.display.conformerColors[lwrKey]} />
+                                                <ColorBox caption={`${ntc.slice(2)}`} color={this.state.display.structures.conformerColors[lwrKey]} />
                                             </div>
                                             <PushButton
                                                 text='R'
@@ -450,11 +497,11 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                                     className='rmsp-control-item'
                                     onClick={evt => ColorPicker.create(
                                         evt,
-                                        this.state.display.chainColor,
+                                        this.state.display.structures.chainColor,
                                         color => this.updateChainColor(color)
                                     )}
                                 >
-                                    <ColorBox caption='Chains' color={this.state.display.chainColor} />
+                                    <ColorBox caption='Chains' color={this.state.display.structures.chainColor} />
                                 </div>
                                 <PushButton
                                     text='R'
@@ -467,11 +514,11 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                                     className='rmsp-control-item'
                                     onClick={evt => ColorPicker.create(
                                         evt,
-                                        this.state.display.waterColor,
+                                        this.state.display.structures.waterColor,
                                         color => this.updateWaterColor(color)
                                     )}
                                 >
-                                    <ColorBox caption='Waters' color={this.state.display.waterColor} />
+                                    <ColorBox caption='Waters' color={this.state.display.structures.waterColor} />
                                 </div>
                                 <PushButton
                                     text='R'
@@ -483,6 +530,49 @@ export class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
                         </div>
                     </div>
                 </CollapsibleVertical>
+                {this.viewer?.hasDensityMap()
+                    ? <DensityMapControls
+                        wireframe={this.state.display.densityMap.representations.includes('wireframe')}
+                        toggleWireframe={() => {
+                            const display = { ...this.state.display };
+                            display.densityMap.representations = toggleArray(display.densityMap.representations, 'wireframe');
+
+                            this.viewer!.changeDensityMap(display);
+                            this.setState({ ...this.state, display });
+                        }}
+
+                        solid={this.state.display.densityMap.representations.includes('solid')}
+                        toggleSolid={() => {
+                            const display = { ...this.state.display };
+                            display.densityMap.representations = toggleArray(display.densityMap.representations, 'solid');
+
+                            this.viewer!.changeDensityMap(display);
+                            this.setState({ ...this.state, display });
+                        }}
+
+                        isoMin={_isoBounds.min}
+                        isoMax={_isoBounds.max}
+                        isoStep={_isoBounds.step}
+                        iso={this.state.display.densityMap.isoValue}
+                        changeIso={(v) => {
+                            const display = { ...this.state.display };
+                            display.densityMap.isoValue = v;
+
+                            this.viewer!.changeDensityMap(display);
+                            this.setState({ ...this.state, display });
+                        }}
+
+                        alpha={this.state.display.densityMap.alpha}
+                        changeAlpha={(alpha) => {
+                            const display = { ...this.state.display };
+                            display.densityMap.alpha = alpha;
+
+                            this.viewer!.changeDensityMap(display);
+                            this.setState({ ...this.state, display });
+                        }}
+                    />
+                    : undefined
+                }
             </div>
         );
     }
diff --git a/src/apps/rednatco/rednatco-molstar.css b/src/apps/rednatco/rednatco-molstar.css
index c048b92c09079c3f5555a9629c0f83e1000a2832..fddb76fdec5905731c5c7e0360845e52e3139919 100644
--- a/src/apps/rednatco/rednatco-molstar.css
+++ b/src/apps/rednatco/rednatco-molstar.css
@@ -122,6 +122,44 @@
     margin: 0.15em;
 }
 
+.rmsp-range-slider {
+    -moz-appearance: none;
+    -webkit-appearance: none;
+    appearance: none;
+
+    background: #ccc;
+    height: 0.15em;
+    margin: auto 0 auto 0;
+    width: 100%;
+}
+.rmsp-range-slider::-moz-range-thumb {
+    background: white;
+    border-radius: 0;
+    border: 0.15em solid #aaa;
+    cursor: pointer;
+    height: 0.8em;
+    transition: background-color 222ms;
+    width: 0.8em;
+}
+.rmsp-range-slider::-moz-range-thumb:hover {
+    background-color: #ccc;
+}
+.rmsp-range-slider::-webkit-slider-thumb {
+    -webkit-appearance: none;
+    appearance: none;
+
+    background: white;
+    border-radius: 0;
+    border: 0.15em solid #aaa;
+    cursor: pointer;
+    height: 1em;
+    transition: background-color 222ms;
+    width: 1em;
+}
+.rmsp-range-slider::-webkit-slider-thumb:hover {
+    background-color: #ccc;
+}
+
 .rmsp-spinbox-container {
     background-color: white;
     border: 0.15em solid #ccc;
diff --git a/src/apps/rednatco/util.ts b/src/apps/rednatco/util.ts
index 75a79ad263d76aba80f03fd7e9b69e86fb828cbe..165709e39b5f8bb96f1018ca2146b8c5f0ef4215 100644
--- a/src/apps/rednatco/util.ts
+++ b/src/apps/rednatco/util.ts
@@ -1,5 +1,27 @@
 import { Color } from '../../mol-util/color';
 
+export function isoBounds(min: number, max: number): { min: number, max: number, step: number } {
+    let diff = max - min;
+    if (diff <= 0.0)
+        return { min, max, step: 0.01 }; // This should never happen
+
+    diff /= 25;
+    const l = Math.floor(Math.log10(diff));
+    const step = Math.pow(10.0, l);
+
+    min = Math.floor((min - step) / step) * step;
+    max = Math.floor((max + step) / step) * step;
+
+    return { min, max, step };
+}
+
+export function isoToFixed(iso: number, step: number) {
+    const d = Math.log10(step);
+    if (d >= 0)
+        return parseFloat(iso.toFixed(0));
+    return parseFloat(iso.toFixed(-d));
+}
+
 /* https://alienryderflex.com/hsp.html */
 export function luminance(color: Color) {
     let [r, g, b] = Color.toRgb(color);
@@ -8,3 +30,16 @@ export function luminance(color: Color) {
     b /= 255.0;
     return Math.sqrt(0.299 * r * r + 0.587 * g * g + 0.114 * b * b);
 }
+
+export function prettyIso(iso: number, step: number) {
+    return Math.floor((iso - step) / step) * step + step;
+}
+
+export function toggleArray<T>(array: T[], elem: T) {
+    if (array.includes(elem))
+        return array.filter((x) => x !== elem);
+    else {
+        array.push(elem);
+        return array;
+    }
+}
diff --git a/src/apps/rednatco/viewer.ts b/src/apps/rednatco/viewer.ts
index 8c609374fee3ae872e6fbffe55983d5f0b12afa3..209e78ddc96ed9e767850fe0ddac9e93d5d7e45e 100644
--- a/src/apps/rednatco/viewer.ts
+++ b/src/apps/rednatco/viewer.ts
@@ -9,6 +9,7 @@ import { ReferenceConformersPdbs } from './reference-conformers-pdbs';
 import { Step } from './step';
 import { Superpose } from './superpose';
 import { Traverse } from './traverse';
+import { isoBounds, prettyIso } from './util';
 import { DnatcoConfalPyramids } from '../../extensions/dnatco';
 import { ConfalPyramidsParams } from '../../extensions/dnatco/confal-pyramids/representation';
 import { OrderedSet } from '../../mol-data/int/ordered-set';
@@ -16,7 +17,7 @@ import { BoundaryHelper } from '../../mol-math/geometry/boundary-helper';
 import { Vec3 } from '../../mol-math/linear-algebra/3d';
 import { EmptyLoci, Loci } from '../../mol-model/loci';
 import { ElementIndex, Model, StructureElement, StructureProperties, StructureSelection, Trajectory } from '../../mol-model/structure';
-// import { Volume } from '../../mol-model/volume';
+import { Volume } from '../../mol-model/volume';
 import { structureUnion, structureSubtract } from '../../mol-model/structure/query/utils/structure-set';
 import { Location } from '../../mol-model/structure/structure/element/location';
 import { MmcifFormat } from '../../mol-model-formats/structure/mmcif';
@@ -243,6 +244,24 @@ export class ReDNATCOMspViewer {
         this.app = app;
     }
 
+    private densityMapVisuals(vis: Display['densityMap']) {
+        return {
+            type: {
+                name: 'isosurface',
+                params: {
+                    alpha: vis.alpha,
+                    isoValue: Volume.IsoValue.absolute(vis.isoValue),
+                    visuals: vis.representations,
+                    sizeFactor: 0.75,
+                }
+            },
+            colorTheme: {
+                name: 'uniform',
+                params: { value: Color(vis.color) },
+            },
+        };
+    }
+
     private focusOnLoci(loci: StructureElement.Loci) {
         if (!this.plugin.canvas3d)
             return;
@@ -489,7 +508,7 @@ export class ReDNATCOMspViewer {
     }
 
     async changeChainColor(display: Display) {
-        const color = Color(display.chainColor);
+        const color = Color(display.structures.chainColor);
 
         const b = this.plugin.state.data.build();
         for (const sub of ['nucleic', 'protein'] as IDs.Substructure[]) {
@@ -499,7 +518,7 @@ export class ReDNATCOMspViewer {
                         StateTransforms.Representation.StructureRepresentation3D,
                         old => ({
                             ...old,
-                            ...this.substructureVisuals(display.representation, color),
+                            ...this.substructureVisuals(display.structures.representation, color),
                         })
                     );
             }
@@ -521,7 +540,7 @@ export class ReDNATCOMspViewer {
                     StateTransforms.Representation.StructureRepresentation3D,
                     old => ({
                         ...old,
-                        ...this.substructureVisuals(display.representation, color),
+                        ...this.substructureVisuals(display.structures.representation, color),
                     })
                 );
         }
@@ -543,7 +562,7 @@ export class ReDNATCOMspViewer {
                     params: {
                         colors: {
                             name: 'custom',
-                            params: display.conformerColors ?? NtCColors.Conformers,
+                            params: display.structures.conformerColors ?? NtCColors.Conformers,
                         },
                     },
                 },
@@ -554,13 +573,13 @@ export class ReDNATCOMspViewer {
     }
 
     async changePyramids(display: Display) {
-        if (display.showPyramids) {
+        if (display.structures.showPyramids) {
             if (!this.has('pyramids', 'nucleic')) {
                 const b = this.getBuilder('structure', 'nucleic');
                 if (b) {
                     b.apply(
                         StateTransforms.Representation.StructureRepresentation3D,
-                        this.pyramidsParams(display.conformerColors ?? NtCColors.Conformers, new Map(), display.pyramidsTransparent ?? false),
+                        this.pyramidsParams(display.structures.conformerColors ?? NtCColors.Conformers, new Map(), display.structures.pyramidsTransparent ?? false),
                         { ref: IDs.ID('pyramids', 'nucleic', BaseRef) }
                     );
                     await b.commit();
@@ -571,7 +590,7 @@ export class ReDNATCOMspViewer {
                     StateTransforms.Representation.StructureRepresentation3D,
                     old => ({
                         ...old,
-                        ...this.pyramidsParams(display.conformerColors ?? NtCColors.Conformers, new Map(), display.pyramidsTransparent ?? false),
+                        ...this.pyramidsParams(display.structures.conformerColors ?? NtCColors.Conformers, new Map(), display.structures.pyramidsTransparent ?? false),
                     })
                 );
                 await b.commit();
@@ -581,7 +600,7 @@ export class ReDNATCOMspViewer {
     }
 
     async changeWaterColor(display: Display) {
-        const color = Color(display.waterColor);
+        const color = Color(display.structures.waterColor);
 
         const b = this.plugin.state.data.build();
         if (this.has('visual', 'water', BaseRef)) {
@@ -600,8 +619,8 @@ export class ReDNATCOMspViewer {
 
     async changeRepresentation(display: Display) {
         const b = this.plugin.state.data.build();
-        const repr = display.representation;
-        const color = Color(display.chainColor);
+        const repr = display.structures.representation;
+        const color = Color(display.structures.chainColor);
 
         for (const sub of ['nucleic', 'protein'] as IDs.Substructure[]) {
             if (this.has('visual', sub)) {
@@ -630,6 +649,24 @@ export class ReDNATCOMspViewer {
         await b.commit();
     }
 
+    async changeDensityMap(display: Display) {
+        if (!this.hasDensityMap())
+            return;
+
+        const b = this.plugin.state.data.build().to(IDs.DensityID('visual', BaseRef));
+        const vis = display.densityMap;
+
+        b.update(
+            StateTransforms.Representation.VolumeRepresentation3D,
+            old => ({
+                ...old,
+                ...this.densityMapVisuals(vis),
+            })
+        );
+
+        await b.commit();
+    }
+
     currentModelNumber() {
         const model = this.plugin.state.data.cells.get(IDs.ID('model', '', BaseRef))?.obj;
         if (!model)
@@ -637,6 +674,15 @@ export class ReDNATCOMspViewer {
         return (model as StateObject<Model>).data.modelNum;
     }
 
+    densityMapIsoRange(ref = BaseRef): { min: number, max: number }|undefined {
+        const cell = this.plugin.state.data.cells.get(IDs.DensityID('volume', ref));
+        if (!cell || !cell.obj)
+            return void 0;
+
+        const grid = (cell.obj.data as Volume).grid;
+        return { min: grid.stats.min, max: grid.stats.max };
+    }
+
     focusOnSelectedStep() {
         const sel = this.plugin.state.data.cells.get(IDs.ID('superposition', '', NtCSupSel));
         const prev = this.plugin.state.data.cells.get(IDs.ID('superposition', '', NtCSupPrev));
@@ -796,6 +842,10 @@ export class ReDNATCOMspViewer {
         return !!this.plugin.state.data.cells.get(IDs.ID(id, sub, ref))?.obj?.data;
     }
 
+    hasDensityMap(ref = BaseRef) {
+        return !!this.plugin.state.data.cells.get(IDs.DensityID('volume', ref))?.obj?.data;
+    }
+
     isReady() {
         return this.has('structure', '', BaseRef);
     }
@@ -807,14 +857,14 @@ export class ReDNATCOMspViewer {
     ) {
         // TODO: Remove the currently loaded structure
 
-        const chainColor = Color(display.chainColor);
-        const waterColor = Color(display.waterColor);
+        const chainColor = Color(display.structures.chainColor);
+        const waterColor = Color(display.structures.waterColor);
 
         const b = (t => coords.type === 'pdb'
             ? t.apply(StateTransforms.Model.TrajectoryFromPDB, {}, { ref: IDs.ID('trajectory', '', BaseRef) })
             : t.apply(StateTransforms.Data.ParseCif).apply(StateTransforms.Model.TrajectoryFromMmCif, {}, { ref: IDs.ID('trajectory', '', BaseRef) })
         )(this.plugin.state.data.build().toRoot().apply(RawData, { data: coords.data }, { ref: IDs.ID('data', '', BaseRef) }))
-            .apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: display.modelNumber ? display.modelNumber - 1 : 0 }, { ref: IDs.ID('model', '', BaseRef) })
+            .apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: display.structures.modelNumber ? display.structures.modelNumber - 1 : 0 }, { ref: IDs.ID('model', '', BaseRef) })
             .apply(StateTransforms.Model.StructureFromModel, {}, { ref: IDs.ID('entire-structure', '', BaseRef) })
             // Extract substructures
             .apply(StateTransforms.Model.StructureComplexElement, { type: 'nucleic' }, { ref: IDs.ID('entire-structure', 'nucleic', BaseRef) })
@@ -855,23 +905,23 @@ export class ReDNATCOMspViewer {
 
         // Create default visuals
         const b3 = this.plugin.state.data.build();
-        if (display.showNucleic && this.has('structure', 'nucleic')) {
+        if (display.structures.showNucleic && this.has('structure', 'nucleic')) {
             b3.to(IDs.ID('structure', 'nucleic', BaseRef))
                 .apply(
                     StateTransforms.Representation.StructureRepresentation3D,
                     this.substructureVisuals('cartoon', chainColor),
                     { ref: IDs.ID('visual', 'nucleic', BaseRef) }
                 );
-            if (display.showPyramids) {
+            if (display.structures.showPyramids) {
                 b3.to(IDs.ID('structure', 'nucleic', BaseRef))
                     .apply(
                         StateTransforms.Representation.StructureRepresentation3D,
-                        this.pyramidsParams(display.conformerColors ?? NtCColors.Conformers, new Map(), false),
+                        this.pyramidsParams(display.structures.conformerColors ?? NtCColors.Conformers, new Map(), false),
                         { ref: IDs.ID('pyramids', 'nucleic', BaseRef) }
                     );
             }
         }
-        if (display.showProtein && this.has('structure', 'protein')) {
+        if (display.structures.showProtein && this.has('structure', 'protein')) {
             b3.to(IDs.ID('structure', 'protein', BaseRef))
                 .apply(
                     StateTransforms.Representation.StructureRepresentation3D,
@@ -879,7 +929,7 @@ export class ReDNATCOMspViewer {
                     { ref: IDs.ID('visual', 'protein', BaseRef) }
                 );
         }
-        if (display.showWater && this.has('structure', 'water')) {
+        if (display.structures.showWater && this.has('structure', 'water')) {
             b3.to(IDs.ID('structure', 'water', BaseRef))
                 .apply(
                     StateTransforms.Representation.StructureRepresentation3D,
@@ -899,27 +949,24 @@ export class ReDNATCOMspViewer {
             b4.toRoot()
                 .apply(RawData, { data: densityMap.data }, { ref: IDs.DensityID('data', BaseRef) })
                 .apply(ParseTransform)
-                .apply(VolumeTransform, {}, { ref: IDs.DensityID('volume', BaseRef) })
+                .apply(VolumeTransform, {}, { ref: IDs.DensityID('volume', BaseRef) });
+
+            await b4.commit(); // Load the density map now so we can probe the stats;
+            const isoRange = this.densityMapIsoRange()!;
+            const bounds = isoBounds(isoRange.min, isoRange.max);
+            const iso = prettyIso(((isoRange.max - isoRange.min) / 2) + isoRange.min, bounds.step);
+
+            const b5 = this.plugin.state.data.build().to(IDs.DensityID('volume', BaseRef))
                 .apply(
                     StateTransforms.Representation.VolumeRepresentation3D,
-                    {
-                        type: {
-                            name: 'isosurface',
-                            params: {
-                                alpha: 0.5,
-                                visuals: ['wireframe'],
-                                sizeFactor: 0.75,
-                            }
-                        },
-                        colorTheme: {
-                            name: 'uniform',
-                            params: { value: Color(0x000000) },
-                        },
-                    },
+                    this.densityMapVisuals(display.densityMap),
                     { ref: IDs.DensityID('visual', BaseRef) }
                 );
 
-            await b4.commit();
+            await b5.commit();
+
+            display.densityMap.representations = ['wireframe'];
+            display.densityMap.isoValue = iso;
         }
 
         this.haveMultipleModels = this.getModelCount() > 1;
@@ -1034,7 +1081,7 @@ export class ReDNATCOMspViewer {
         // Switch to a different model if the selected step is from a different model
         // This is the first thing we need to do
         if (step.model !== this.currentModelNumber())
-            await this.switchModel({ modelNumber: step.model });
+            await this.switchModel(step.model);
 
         const entireStruCell = this.plugin.state.data.cells.get(IDs.ID('structure', 'nucleic', BaseRef));
         if (!entireStruCell)
@@ -1066,7 +1113,7 @@ export class ReDNATCOMspViewer {
         const subtracted = structureSubtract(stru, slice);
         const remainderBundle = StructureElement.Bundle.fromSubStructure(stru, subtracted);
 
-        const chainColor = Color(display.chainColor);
+        const chainColor = Color(display.structures.chainColor);
         const b = this.plugin.state.data.build();
         b.to(entireStruCell)
             .apply(
@@ -1087,11 +1134,11 @@ export class ReDNATCOMspViewer {
             );
 
         // Only show the remainder if the nucleic substructure is shown
-        if (display.showNucleic) {
+        if (display.structures.showNucleic) {
             b.to(IDs.ID('structure', 'remainder-slice', BaseRef))
                 .apply(
                     StateTransforms.Representation.StructureRepresentation3D,
-                    this.substructureVisuals(display.representation, chainColor),
+                    this.substructureVisuals(display.structures.representation, chainColor),
                     { ref: IDs.ID('visual', 'remainder-slice', BaseRef) }
                 )
                 .delete(IDs.ID('visual', 'nucleic', BaseRef));
@@ -1108,8 +1155,8 @@ export class ReDNATCOMspViewer {
         return true;
     }
 
-    async switchModel(display: Partial<Display>) {
-        if (display.modelNumber && display.modelNumber === this.currentModelNumber())
+    async switchModel(modelNumber?: number) {
+        if (modelNumber && modelNumber === this.currentModelNumber())
             return;
 
         const b = this.plugin.state.data.build()
@@ -1121,7 +1168,7 @@ export class ReDNATCOMspViewer {
                 StateTransforms.Model.ModelFromTrajectory,
                 old => ({
                     ...old,
-                    modelIndex: display.modelNumber ? display.modelNumber - 1 : 0
+                    modelIndex: modelNumber ? modelNumber - 1 : 0
                 })
             );
 
@@ -1181,16 +1228,16 @@ export class ReDNATCOMspViewer {
     }
 
     async toggleSubstructure(sub: IDs.Substructure, display: Display) {
-        const show = sub === 'nucleic' ? !!display.showNucleic :
-            sub === 'protein' ? !!display.showProtein : !!display.showWater;
-        const repr = display.representation;
+        const show = sub === 'nucleic' ? !!display.structures.showNucleic :
+            sub === 'protein' ? !!display.structures.showProtein : !!display.structures.showWater;
+        const repr = display.structures.representation;
 
         if (sub === 'nucleic')
-            this.toggleNucleicSubstructure(show, repr, Color(display.chainColor));
+            this.toggleNucleicSubstructure(show, repr, Color(display.structures.chainColor));
         else {
             if (show) {
                 const b = this.getBuilder('structure', sub);
-                const visuals = sub === 'water' ? this.waterVisuals(Color(display.waterColor)) : this.substructureVisuals(repr, Color(display.chainColor));
+                const visuals = sub === 'water' ? this.waterVisuals(Color(display.structures.waterColor)) : this.substructureVisuals(repr, Color(display.structures.chainColor));
                 if (b) {
                     b.apply(
                         StateTransforms.Representation.StructureRepresentation3D,