Repository: microsoft/SandDance (language: python)

Issue:
Add sort to scatterplot for z-order



Discussion / hints:

Fix patch:
diff --git a/packages/sanddance-explorer/src/dialogs/chart.tsx b/packages/sanddance-explorer/src/dialogs/chart.tsx
index b8d76c39e..ce4fa5e40 100644
--- a/packages/sanddance-explorer/src/dialogs/chart.tsx
+++ b/packages/sanddance-explorer/src/dialogs/chart.tsx
@@ -271,7 +271,7 @@ function _Chart(_props: Props) {
                                     }
                                 }
                                 const disabled = props.disabled
-                                    || (props.view === '2d' && specRole.role === 'z')
+                                    || specRole.disabled
                                     || (specRole.role === 'size' && !(!specCapabilities.countsAndSums || totalStyle.indexOf('sum-') === 0))
                                     || (specRole.role === 'sort' && specCapabilities.countsAndSums && totalStyle === 'sum-treemap');
                                 return (
diff --git a/packages/sanddance-specs/package-lock.json b/packages/sanddance-specs/package-lock.json
index 6b6c1b9fd..b193e28ee 100644
--- a/packages/sanddance-specs/package-lock.json
+++ b/packages/sanddance-specs/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "@msrvida/sanddance-specs",
-  "version": "1.5.1",
+  "version": "1.6.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "@msrvida/sanddance-specs",
-      "version": "1.5.1",
+      "version": "1.6.0",
       "license": "MIT",
       "dependencies": {
         "d3-color": "^1.4.0",
diff --git a/packages/sanddance-specs/package.json b/packages/sanddance-specs/package.json
index b8601de5e..a666736ba 100644
--- a/packages/sanddance-specs/package.json
+++ b/packages/sanddance-specs/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@msrvida/sanddance-specs",
-  "version": "1.5.1",
+  "version": "1.6.0",
   "description": "SandDance Vega specification generator.",
   "main": "dist/es6/index.js",
   "repository": {
diff --git a/packages/sanddance-specs/src/charts/barchartH.ts b/packages/sanddance-specs/src/charts/barchartH.ts
index e56cb4736..48ba4ad47 100644
--- a/packages/sanddance-specs/src/charts/barchartH.ts
+++ b/packages/sanddance-specs/src/charts/barchartH.ts
@@ -42,7 +42,8 @@ export default function (specContext: SpecContext): SpecBuilderProps {
         layoutType: 'Band',
         props: bandProps,
     }];
-    if (insight.totalStyle === 'sum-strip-percent') {
+    const { totalStyle, view } = insight;
+    if (totalStyle === 'sum-strip-percent') {
         x.aggregate = 'percent';
         x.title = language.percent;
         const stripProps: StripProps = {
@@ -53,6 +54,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
             sort: specColumns.sort,
             z: specColumns.z,
             showAxes,
+            view,
         };
         layouts.push({
             layoutType: 'Strip',
@@ -71,7 +73,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
             layoutType: 'AggregateContainer',
             props: aggProps,
         });
-        switch (insight.totalStyle) {
+        switch (totalStyle) {
             case 'sum-treemap': {
                 x.aggregate = 'sum';
                 x.title = language.sum;
@@ -81,6 +83,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     treeMapMethod: specViewOptions.language.treeMapMethod,
                     z: specColumns.z,
                     showAxes,
+                    view,
                 };
                 layouts.push({
                     layoutType: 'Treemap',
@@ -98,6 +101,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     sort: specColumns.sort,
                     z: specColumns.z,
                     showAxes,
+                    view,
                 };
                 layouts.push({
                     layoutType: 'Strip',
@@ -115,6 +119,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     sort: specColumns.sort,
                     z: specColumns.z,
                     showAxes,
+                    view,
                 };
                 layouts.push({
                     layoutType: 'Strip',
@@ -132,6 +137,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     maxGroupedUnits: aggProps.globalAggregateMaxExtentSignal,
                     maxGroupedFillSize: aggProps.globalAggregateMaxExtentScaledSignal,
                     showAxes,
+                    view,
                 };
                 layouts.push({
                     layoutType: 'Square',
@@ -159,6 +165,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     role: 'z',
                     axisSelection: specColumns.z?.quantitative ? 'range' : 'exact',
                     allowNone: true,
+                    disabled: view === '2d',
                 },
                 {
                     role: 'color',
diff --git a/packages/sanddance-specs/src/charts/barchartV.ts b/packages/sanddance-specs/src/charts/barchartV.ts
index 8d56abc91..e301be11a 100644
--- a/packages/sanddance-specs/src/charts/barchartV.ts
+++ b/packages/sanddance-specs/src/charts/barchartV.ts
@@ -42,7 +42,8 @@ export default function (specContext: SpecContext): SpecBuilderProps {
         layoutType: 'Band',
         props: bandProps,
     }];
-    if (insight.totalStyle === 'sum-strip-percent') {
+    const { totalStyle, view } = insight;
+    if (totalStyle === 'sum-strip-percent') {
         y.aggregate = 'percent';
         y.title = language.percent;
         const stripProps: StripProps = {
@@ -53,6 +54,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
             sort: specColumns.sort,
             z: specColumns.z,
             showAxes,
+            view,
         };
         layouts.push({
             layoutType: 'Strip',
@@ -71,7 +73,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
             layoutType: 'AggregateContainer',
             props: aggProps,
         });
-        switch (insight.totalStyle) {
+        switch (totalStyle) {
             case 'sum-treemap': {
                 y.aggregate = 'sum';
                 y.title = language.sum;
@@ -81,6 +83,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     treeMapMethod: specViewOptions.language.treeMapMethod,
                     z: specColumns.z,
                     showAxes,
+                    view,
                 };
                 layouts.push({
                     layoutType: 'Treemap',
@@ -98,6 +101,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     sort: specColumns.sort,
                     z: specColumns.z,
                     showAxes,
+                    view,
                 };
                 layouts.push({
                     layoutType: 'Strip',
@@ -114,6 +118,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     sort: specColumns.sort,
                     z: specColumns.z,
                     showAxes,
+                    view,
                 };
                 layouts.push({
                     layoutType: 'Strip',
@@ -131,6 +136,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     maxGroupedUnits: aggProps.globalAggregateMaxExtentSignal,
                     maxGroupedFillSize: aggProps.globalAggregateMaxExtentScaledSignal,
                     showAxes,
+                    view,
                 };
                 layouts.push({
                     layoutType: 'Square',
@@ -158,6 +164,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     role: 'z',
                     axisSelection: specColumns.z?.quantitative ? 'range' : 'exact',
                     allowNone: true,
+                    disabled: view === '2d',
                 },
                 {
                     role: 'color',
diff --git a/packages/sanddance-specs/src/charts/density.ts b/packages/sanddance-specs/src/charts/density.ts
index 10ac2523e..0a8e8074f 100644
--- a/packages/sanddance-specs/src/charts/density.ts
+++ b/packages/sanddance-specs/src/charts/density.ts
@@ -72,7 +72,8 @@ export default function (specContext: SpecContext): SpecBuilderProps {
             props: aggProps,
         },
     ];
-    switch (insight.totalStyle) {
+    const { totalStyle, view } = insight;
+    switch (totalStyle) {
         case 'sum-treemap': {
             aggProps.aggregation = 'sum';
             const treemapProps: TreemapProps = {
@@ -81,6 +82,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                 treeMapMethod: specViewOptions.language.treeMapMethod,
                 z: specColumns.z,
                 showAxes,
+                view,
             };
             layouts.push({
                 layoutType: 'Treemap',
@@ -97,6 +99,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                 sort: specColumns.sort,
                 z: specColumns.z,
                 showAxes,
+                view,
             };
             layouts.push({
                 layoutType: 'Strip',
@@ -112,6 +115,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                 sort: specColumns.sort,
                 z: specColumns.z,
                 showAxes,
+                view,
             };
             layouts.push({
                 layoutType: 'Strip',
@@ -128,6 +132,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                 maxGroupedUnits: null,
                 maxGroupedFillSize: null,
                 showAxes,
+                view,
             };
             aggProps.onBuild = (aggMaxExtent, aggMaxExtentScaled) => {
                 squareProps.maxGroupedUnits = aggMaxExtent;
@@ -165,6 +170,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     role: 'z',
                     axisSelection: specColumns.z?.quantitative ? 'range' : 'exact',
                     allowNone: true,
+                    disabled: view === '2d',
                 },
                 {
                     role: 'color',
diff --git a/packages/sanddance-specs/src/charts/grid.ts b/packages/sanddance-specs/src/charts/grid.ts
index f377e00c5..7fecf16a9 100644
--- a/packages/sanddance-specs/src/charts/grid.ts
+++ b/packages/sanddance-specs/src/charts/grid.ts
@@ -11,12 +11,14 @@ import { SquareProps } from '../layouts/square';
 
 export default function (specContext: SpecContext): SpecBuilderProps {
     const { insight, specColumns } = specContext;
+    const { view } = insight;
     const squareProps: SquareProps = {
         sortBy: specColumns.sort,
         fillDirection: 'right-down',
         z: specColumns.z,
         collapseYHeight: true,
         showAxes: !insight.hideAxes,
+        view,
     };
     const axisScales: AxisScales = {
         z: { title: specColumns.z && specColumns.z.name },
@@ -36,6 +38,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     role: 'z',
                     axisSelection: specColumns.z?.quantitative ? 'range' : 'exact',
                     allowNone: true,
+                    disabled: view === '2d',
                 },
                 {
                     role: 'color',
diff --git a/packages/sanddance-specs/src/charts/scatterplot.ts b/packages/sanddance-specs/src/charts/scatterplot.ts
index ca2afbea8..e49ff2974 100644
--- a/packages/sanddance-specs/src/charts/scatterplot.ts
+++ b/packages/sanddance-specs/src/charts/scatterplot.ts
@@ -21,6 +21,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
         zGrounded: specViewOptions.language.zGrounded,
         backgroundImageExtents,
         showAxes: !(backgroundImageExtents || insight.hideAxes),
+        view: insight.view,
     };
     const axisScales: AxisScales = {
         x: { title: specColumns.x?.name },
@@ -51,6 +52,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     role: 'z',
                     axisSelection: specColumns.z?.quantitative ? 'range' : 'exact',
                     allowNone: true,
+                    disabled: false,
                 },
                 {
                     role: 'color',
diff --git a/packages/sanddance-specs/src/charts/strips.ts b/packages/sanddance-specs/src/charts/strips.ts
index b83dbb0d2..f0747d817 100644
--- a/packages/sanddance-specs/src/charts/strips.ts
+++ b/packages/sanddance-specs/src/charts/strips.ts
@@ -13,6 +13,7 @@ import { StripProps } from '../layouts/strip';
 
 export default function (specContext: SpecContext): SpecBuilderProps {
     const { insight, specColumns } = specContext;
+    const { view } = insight;
     const stripProps: StripProps = {
         sortOrder: 'ascending',
         orientation: 'vertical',
@@ -20,6 +21,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
         sort: specColumns.sort,
         z: specColumns.z,
         showAxes: !insight.hideAxes,
+        view,
     };
     const axisScales: AxisScales = {
         z: { title: specColumns.z && specColumns.z.name },
@@ -64,6 +66,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     role: 'z',
                     axisSelection: specColumns.z?.quantitative ? 'range' : 'exact',
                     allowNone: true,
+                    disabled: view === '2d',
                 },
                 {
                     role: 'color',
diff --git a/packages/sanddance-specs/src/charts/treemap.ts b/packages/sanddance-specs/src/charts/treemap.ts
index c60d3f1ab..b17c79688 100644
--- a/packages/sanddance-specs/src/charts/treemap.ts
+++ b/packages/sanddance-specs/src/charts/treemap.ts
@@ -13,6 +13,7 @@ import { AggregateContainerProps } from '../layouts/aggregateContainer';
 
 export default function (specContext: SpecContext): SpecBuilderProps {
     const { insight, specColumns, specViewOptions } = specContext;
+    const { view } = insight;
     const treemapProps: TreemapProps = {
         corner: 'top-left',
         group: specColumns.group,
@@ -20,6 +21,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
         treeMapMethod: specViewOptions.language.treeMapMethod,
         z: specColumns.z,
         showAxes: !insight.hideAxes,
+        view,
     };
     const axisScales: AxisScales = {
         z: { title: specColumns.z && specColumns.z.name },
@@ -67,6 +69,7 @@ export default function (specContext: SpecContext): SpecBuilderProps {
                     role: 'z',
                     axisSelection: specColumns.z?.quantitative ? 'range' : 'exact',
                     allowNone: true,
+                    disabled: view === '2d',
                 },
                 {
                     role: 'color',
diff --git a/packages/sanddance-specs/src/layouts/scatter.ts b/packages/sanddance-specs/src/layouts/scatter.ts
index ff860eb7e..cdba48892 100644
--- a/packages/sanddance-specs/src/layouts/scatter.ts
+++ b/packages/sanddance-specs/src/layouts/scatter.ts
@@ -18,7 +18,7 @@ import {
     addTransforms,
 } from '../scope';
 import { testForCollapseSelection } from '../selection';
-import { Column } from '@msrvida/chart-types';
+import { Column, View } from '@msrvida/chart-types';
 import {
     RectEncodeEntry,
     RectMark,
@@ -40,6 +40,7 @@ export interface ScatterProps extends LayoutProps {
     zGrounded: string;
     showAxes: boolean;
     backgroundImageExtents: Extents;
+    view: View;
 }
 
 export class Scatter extends Layout {
@@ -55,7 +56,7 @@ export class Scatter extends Layout {
         sizeScale: string,
         xScale: string,
         yScale: string,
-        zScale: string
+        zScale: string,
     };
 
     constructor(public props: ScatterProps & LayoutBuildProps) {
@@ -79,7 +80,7 @@ export class Scatter extends Layout {
 
     public build(): InnerScope {
         const { names, prefix, props } = this;
-        const { backgroundImageExtents, globalScope, parentScope, scatterPointScaleDisplay, showAxes, size, x, y, z, zGrounded } = props;
+        const { backgroundImageExtents, globalScope, parentScope, scatterPointScaleDisplay, showAxes, size, view, x, y, z, zGrounded } = props;
         const qsize = size && size.quantitative && size;
 
         addSignals(globalScope.scope,
@@ -182,13 +183,20 @@ export class Scatter extends Layout {
                         signal: `${SignalNames.ZGrounded} ? 0 : ${zValue}`,
                     },
                 ],
+                zindex: [
+                    {
+                        signal: `${SignalNames.ZGrounded} ? 0 : ${zValue}`,
+                    },
+                ],
                 depth: [
                     {
                         test: testForCollapseSelection(),
                         value: 0,
                     },
                     {
-                        signal: `${SignalNames.ZGrounded} ? ${zValue} : ${sizeValueSignal}`,
+                        signal: view === '3d'
+                            ? `${SignalNames.ZGrounded} ? ${zValue} : ${sizeValueSignal}`
+                            : '0',
                     },
                 ],
             },
@@ -202,50 +210,52 @@ export class Scatter extends Layout {
             reverse: boolean,
             signal: string
         }[] = [
-            {
-                column: x,
-                xyz: 'x',
-                scaleName: names.xScale,
-                domain: backgroundImageExtents ?
-                    {
-                        signal: names.xExtent,
-                    }
-                    :
-                    {
-                        data: globalScope.data.name,
-                        field: safeFieldName(x.name),
-                    },
-                reverse: false,
-                signal: parentScope.sizeSignals.layoutWidth,
-            },
-            {
-                column: y,
-                xyz: 'y',
-                scaleName: names.yScale,
-                domain: backgroundImageExtents ?
-                    {
-                        signal: names.yExtent,
-                    }
-                    :
-                    {
+                {
+                    column: x,
+                    xyz: 'x',
+                    scaleName: names.xScale,
+                    domain: backgroundImageExtents ?
+                        {
+                            signal: names.xExtent,
+                        }
+                        :
+                        {
+                            data: globalScope.data.name,
+                            field: safeFieldName(x.name),
+                        },
+                    reverse: false,
+                    signal: parentScope.sizeSignals.layoutWidth,
+                },
+                {
+                    column: y,
+                    xyz: 'y',
+                    scaleName: names.yScale,
+                    domain: backgroundImageExtents ?
+                        {
+                            signal: names.yExtent,
+                        }
+                        :
+                        {
+                            data: globalScope.data.name,
+                            field: safeFieldName(y.name),
+                        },
+                    reverse: true,
+                    signal: parentScope.sizeSignals.layoutHeight,
+                },
+                {
+                    column: z,
+                    xyz: 'z',
+                    scaleName: names.zScale,
+                    domain: {
                         data: globalScope.data.name,
-                        field: safeFieldName(y.name),
+                        field: z ? safeFieldName(z.name) : null,
                     },
-                reverse: true,
-                signal: parentScope.sizeSignals.layoutHeight,
-            },
-            {
-                column: z,
-                xyz: 'z',
-                scaleName: names.zScale,
-                domain: {
-                    data: globalScope.data.name,
-                    field: z ? safeFieldName(z.name) : null,
+                    reverse: false,
+                    signal: view === '3d'
+                        ? `(${globalScope.zSize}) * ${SignalNames.ZProportion}`
+                        : `10 * ${SignalNames.ZProportion}`,
                 },
-                reverse: false,
-                signal: `(${globalScope.zSize}) * ${SignalNames.ZProportion}`,
-            },
-        ];
+            ];
         columnSignals.forEach(cs => {
             const { column, domain, reverse, scaleName, signal, xyz } = cs;
             if (!column) return;
diff --git a/packages/sanddance-specs/src/layouts/square.ts b/packages/sanddance-specs/src/layouts/square.ts
index 9f192ea3c..66586da71 100644
--- a/packages/sanddance-specs/src/layouts/square.ts
+++ b/packages/sanddance-specs/src/layouts/square.ts
@@ -15,7 +15,7 @@ import {
 } from '../scope';
 import { testForCollapseSelection } from '../selection';
 import { addZScale } from '../zBase';
-import { Column } from '@msrvida/chart-types';
+import { Column, View } from '@msrvida/chart-types';
 import { FormulaTransform, RectMark } from 'vega-typings';
 
 export interface SquareProps extends LayoutProps {
@@ -26,6 +26,7 @@ export interface SquareProps extends LayoutProps {
     maxGroupedFillSize?: string;
     collapseYHeight?: boolean;
     showAxes: boolean;
+    view: View;
 }
 
 export class Square extends Layout {
@@ -35,7 +36,7 @@ export class Square extends Layout {
         maxGroupSignal: string,
         stack0: string,
         stack1: string,
-        zScale: string
+        zScale: string,
     };
 
     constructor(public props: SquareProps & LayoutBuildProps) {
@@ -53,7 +54,7 @@ export class Square extends Layout {
 
     public build(): InnerScope {
         const { names, prefix, props } = this;
-        const { fillDirection, globalScope, groupings, parentScope, collapseYHeight, showAxes, sortBy, z } = props;
+        const { fillDirection, globalScope, groupings, parentScope, collapseYHeight, showAxes, sortBy, view, z } = props;
         const zScale = addZScale(z, globalScope.zSize, globalScope.data.name, names.zScale);
 
         addTransforms(globalScope.data, {
@@ -102,10 +103,16 @@ export class Square extends Layout {
                                 test: testForCollapseSelection(),
                                 value: 0,
                             },
-                            {
-                                scale: names.zScale,
-                                field: safeFieldName(z.name),
-                            },
+                            view === '3d'
+                                ?
+                                {
+                                    scale: names.zScale,
+                                    field: safeFieldName(z.name),
+                                }
+                                :
+                                {
+                                    value: 0
+                                },
                         ],
                     },
                 },
diff --git a/packages/sanddance-specs/src/layouts/strip.ts b/packages/sanddance-specs/src/layouts/strip.ts
index e173c6108..58f3ba0aa 100644
--- a/packages/sanddance-specs/src/layouts/strip.ts
+++ b/packages/sanddance-specs/src/layouts/strip.ts
@@ -15,7 +15,7 @@ import {
 } from '../scope';
 import { testForCollapseSelection } from '../selection';
 import { addZScale } from '../zBase';
-import { Column } from '@msrvida/chart-types';
+import { Column, View } from '@msrvida/chart-types';
 import {
     LinearScale,
     RectMark,
@@ -32,6 +32,7 @@ export interface StripProps extends LayoutProps {
     sort: Column;
     z: Column;
     showAxes: boolean;
+    view: View;
 }
 
 export class Strip extends Layout {
@@ -57,7 +58,7 @@ export class Strip extends Layout {
 
     public build(): InnerScope {
         const { names, prefix, props } = this;
-        const { addPercentageScale, globalScope, groupings, orientation, showAxes, size, sort, sortOrder, parentScope, z } = props;
+        const { addPercentageScale, globalScope, groupings, orientation, showAxes, size, sort, sortOrder, parentScope, view, z } = props;
 
         const zScale = addZScale(z, globalScope.zSize, globalScope.data.name, names.zScale);
 
@@ -146,10 +147,16 @@ export class Strip extends Layout {
                                 test: testForCollapseSelection(),
                                 value: 0,
                             },
-                            {
-                                scale: names.zScale,
-                                field: safeFieldName(z.name),
-                            },
+                            view === '3d'
+                                ?
+                                {
+                                    scale: names.zScale,
+                                    field: safeFieldName(z.name),
+                                }
+                                :
+                                {
+                                    value: 0
+                                },
                         ],
                     },
                 },
diff --git a/packages/sanddance-specs/src/layouts/treemap.ts b/packages/sanddance-specs/src/layouts/treemap.ts
index f5b8356d8..ec403d2b9 100644
--- a/packages/sanddance-specs/src/layouts/treemap.ts
+++ b/packages/sanddance-specs/src/layouts/treemap.ts
@@ -17,7 +17,7 @@ import {
 } from '../scope';
 import { testForCollapseSelection } from '../selection';
 import { addZScale } from '../zBase';
-import { Column } from '@msrvida/chart-types';
+import { Column, View } from '@msrvida/chart-types';
 import {
     Data,
     GroupMark,
@@ -32,6 +32,7 @@ export interface TreemapProps extends LayoutProps {
     treeMapMethod: string;
     z: Column;
     showAxes: boolean;
+    view: View;
 }
 
 export class Treemap extends Layout {
@@ -200,7 +201,7 @@ export class Treemap extends Layout {
 
     private addMark(offsets: LayoutOffsets, markParent: Scope, markDataName: string) {
         const { names, prefix, props } = this;
-        const { z } = props;
+        const { view, z } = props;
         const mark: RectMark = {
             name: prefix,
             type: 'rect',
@@ -220,10 +221,16 @@ export class Treemap extends Layout {
                                 test: testForCollapseSelection(),
                                 value: 0,
                             },
-                            {
-                                scale: names.zScale,
-                                field: safeFieldName(z.name),
-                            },
+                            view === '3d'
+                                ?
+                                {
+                                    scale: names.zScale,
+                                    field: safeFieldName(z.name),
+                                }
+                                :
+                                {
+                                    value: 0
+                                },
                         ],
                     },
                 },
diff --git a/packages/sanddance-specs/src/types.ts b/packages/sanddance-specs/src/types.ts
index b25ac4dbd..b195f0577 100644
--- a/packages/sanddance-specs/src/types.ts
+++ b/packages/sanddance-specs/src/types.ts
@@ -134,6 +134,7 @@ export interface SpecRoleCapabilities {
     binnable?: boolean;
     axisSelection?: AxisSelectionType;
     axisSelectionBetweenTicks?: boolean;
+    disabled?: boolean;
 
     /**
      * Signals associated with this spec role.
diff --git a/packages/vega-morphcharts/package-lock.json b/packages/vega-morphcharts/package-lock.json
index 776d6e108..e4c785182 100644
--- a/packages/vega-morphcharts/package-lock.json
+++ b/packages/vega-morphcharts/package-lock.json
@@ -1,12 +1,12 @@
 {
 	"name": "@msrvida/vega-morphcharts",
-	"version": "1.0.0",
+	"version": "1.0.1",
 	"lockfileVersion": 2,
 	"requires": true,
 	"packages": {
 		"": {
 			"name": "@msrvida/vega-morphcharts",
-			"version": "1.0.0",
+			"version": "1.0.1",
 			"license": "MIT",
 			"dependencies": {
 				"d3-color": "^1.4.0",
diff --git a/packages/vega-morphcharts/package.json b/packages/vega-morphcharts/package.json
index 14983fc77..5a48fd1d4 100644
--- a/packages/vega-morphcharts/package.json
+++ b/packages/vega-morphcharts/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@msrvida/vega-morphcharts",
-	"version": "1.0.0",
+	"version": "1.0.1",
 	"description": "MorphCharts renderer for Vega",
 	"main": "dist/es6/index.js",
 	"files": [
diff --git a/packages/vega-morphcharts/src/marks/rect.ts b/packages/vega-morphcharts/src/marks/rect.ts
index 8b6a9792c..cf365e429 100644
--- a/packages/vega-morphcharts/src/marks/rect.ts
+++ b/packages/vega-morphcharts/src/marks/rect.ts
@@ -21,8 +21,9 @@ const markStager: MarkStager = (options: MarkStagerOptions, stage: Stage, scene:
 
     base.vega.sceneVisit(scene, function (item: SceneCube) {
 
-        const z = stage.view === '2d' ? 0 : (item.z || 0) + minZ;
-        const depth = (stage.view === '2d' ? 0 : (item.depth || 0)) + min3dDepth;
+        const noZ = item.z === undefined;
+        const z = noZ ? 0 : (item.z || 0) + minZ;
+        const depth = (noZ ? 0 : (item.depth || 0)) + min3dDepth;
 
         //change direction of y from SVG to GL
         const ty = -1;


Test patch:
diff --git a/docs/tests/sanddance-specs/v1/js/sanddance-specs.js b/docs/tests/sanddance-specs/v1/js/sanddance-specs.js
index 1dc8c3e5b..01b4b05b2 100644
--- a/docs/tests/sanddance-specs/v1/js/sanddance-specs.js
+++ b/docs/tests/sanddance-specs/v1/js/sanddance-specs.js
@@ -411,7 +411,8 @@ exports.default = function(specContext) {
             props: bandProps
         }
     ];
-    if (insight.totalStyle === "sum-strip-percent") {
+    const { totalStyle , view  } = insight;
+    if (totalStyle === "sum-strip-percent") {
         x.aggregate = "percent";
         x.title = language.percent;
         const stripProps = {
@@ -421,7 +422,8 @@ exports.default = function(specContext) {
             size: specColumns.size,
             sort: specColumns.sort,
             z: specColumns.z,
-            showAxes
+            showAxes,
+            view
         };
         layouts.push({
             layoutType: "Strip",
@@ -440,7 +442,7 @@ exports.default = function(specContext) {
             layoutType: "AggregateContainer",
             props: aggProps
         });
-        switch(insight.totalStyle){
+        switch(totalStyle){
             case "sum-treemap":
                 {
                     x.aggregate = "sum";
@@ -450,7 +452,8 @@ exports.default = function(specContext) {
                         size: specColumns.size,
                         treeMapMethod: specViewOptions.language.treeMapMethod,
                         z: specColumns.z,
-                        showAxes
+                        showAxes,
+                        view
                     };
                     layouts.push({
                         layoutType: "Treemap",
@@ -468,7 +471,8 @@ exports.default = function(specContext) {
                         size: specColumns.size,
                         sort: specColumns.sort,
                         z: specColumns.z,
-                        showAxes
+                        showAxes,
+                        view
                     };
                     layouts.push({
                         layoutType: "Strip",
@@ -486,7 +490,8 @@ exports.default = function(specContext) {
                         size: specColumns.size,
                         sort: specColumns.sort,
                         z: specColumns.z,
-                        showAxes
+                        showAxes,
+                        view
                     };
                     layouts.push({
                         layoutType: "Strip",
@@ -504,7 +509,8 @@ exports.default = function(specContext) {
                         z: specColumns.z,
                         maxGroupedUnits: aggProps.globalAggregateMaxExtentSignal,
                         maxGroupedFillSize: aggProps.globalAggregateMaxExtentScaledSignal,
-                        showAxes
+                        showAxes,
+                        view
                     };
                     layouts.push({
                         layoutType: "Square",
@@ -533,7 +539,8 @@ exports.default = function(specContext) {
                 {
                     role: "z",
                     axisSelection: ((_d = specColumns.z) === null || _d === void 0 ? void 0 : _d.quantitative) ? "range" : "exact",
-                    allowNone: true
+                    allowNone: true,
+                    disabled: view === "2d"
                 },
                 {
                     role: "color",
@@ -786,7 +793,8 @@ exports.default = function(specContext) {
             props: bandProps
         }
     ];
-    if (insight.totalStyle === "sum-strip-percent") {
+    const { totalStyle , view  } = insight;
+    if (totalStyle === "sum-strip-percent") {
         y.aggregate = "percent";
         y.title = language.percent;
         const stripProps = {
@@ -796,7 +804,8 @@ exports.default = function(specContext) {
             size: specColumns.size,
             sort: specColumns.sort,
             z: specColumns.z,
-            showAxes
+            showAxes,
+            view
         };
         layouts.push({
             layoutType: "Strip",
@@ -815,7 +824,7 @@ exports.default = function(specContext) {
             layoutType: "AggregateContainer",
             props: aggProps
         });
-        switch(insight.totalStyle){
+        switch(totalStyle){
             case "sum-treemap":
                 {
                     y.aggregate = "sum";
@@ -825,7 +834,8 @@ exports.default = function(specContext) {
                         size: specColumns.size,
                         treeMapMethod: specViewOptions.language.treeMapMethod,
                         z: specColumns.z,
-                        showAxes
+                        showAxes,
+                        view
                     };
                     layouts.push({
                         layoutType: "Treemap",
@@ -843,7 +853,8 @@ exports.default = function(specContext) {
                         size: specColumns.size,
                         sort: specColumns.sort,
                         z: specColumns.z,
-                        showAxes
+                        showAxes,
+                        view
                     };
                     layouts.push({
                         layoutType: "Strip",
@@ -860,7 +871,8 @@ exports.default = function(specContext) {
                         orientation: "vertical",
                         sort: specColumns.sort,
                         z: specColumns.z,
-                        showAxes
+                        showAxes,
+                        view
                     };
                     layouts.push({
                         layoutType: "Strip",
@@ -878,7 +890,8 @@ exports.default = function(specContext) {
                         z: specColumns.z,
                         maxGroupedUnits: aggProps.globalAggregateMaxExtentSignal,
                         maxGroupedFillSize: aggProps.globalAggregateMaxExtentScaledSignal,
-                        showAxes
+                        showAxes,
+                        view
                     };
                     layouts.push({
                         layoutType: "Square",
@@ -907,7 +920,8 @@ exports.default = function(specContext) {
                 {
                     role: "z",
                     axisSelection: ((_b = specColumns.z) === null || _b === void 0 ? void 0 : _b.quantitative) ? "range" : "exact",
-                    allowNone: true
+                    allowNone: true,
+                    disabled: view === "2d"
                 },
                 {
                     role: "color",
@@ -1022,7 +1036,8 @@ exports.default = function(specContext) {
             props: aggProps
         }, 
     ];
-    switch(insight.totalStyle){
+    const { totalStyle , view  } = insight;
+    switch(totalStyle){
         case "sum-treemap":
             {
                 aggProps.aggregation = "sum";
@@ -1031,7 +1046,8 @@ exports.default = function(specContext) {
                     size: specColumns.size,
                     treeMapMethod: specViewOptions.language.treeMapMethod,
                     z: specColumns.z,
-                    showAxes
+                    showAxes,
+                    view
                 };
                 layouts.push({
                     layoutType: "Treemap",
@@ -1048,7 +1064,8 @@ exports.default = function(specContext) {
                     size: specColumns.size,
                     sort: specColumns.sort,
                     z: specColumns.z,
-                    showAxes
+                    showAxes,
+                    view
                 };
                 layouts.push({
                     layoutType: "Strip",
@@ -1064,7 +1081,8 @@ exports.default = function(specContext) {
                     orientation: "vertical",
                     sort: specColumns.sort,
                     z: specColumns.z,
-                    showAxes
+                    showAxes,
+                    view
                 };
                 layouts.push({
                     layoutType: "Strip",
@@ -1081,7 +1099,8 @@ exports.default = function(specContext) {
                     z: specColumns.z,
                     maxGroupedUnits: null,
                     maxGroupedFillSize: null,
-                    showAxes
+                    showAxes,
+                    view
                 };
                 aggProps.onBuild = (aggMaxExtent, aggMaxExtentScaled)=>{
                     squareProps.maxGroupedUnits = aggMaxExtent;
@@ -1122,7 +1141,8 @@ exports.default = function(specContext) {
                 {
                     role: "z",
                     axisSelection: ((_j = specColumns.z) === null || _j === void 0 ? void 0 : _j.quantitative) ? "range" : "exact",
-                    allowNone: true
+                    allowNone: true,
+                    disabled: view === "2d"
                 },
                 {
                     role: "color",
@@ -1169,12 +1189,14 @@ parcelHelpers.defineInteropFlag(exports);
 exports.default = function(specContext) {
     var _a;
     const { insight , specColumns  } = specContext;
+    const { view  } = insight;
     const squareProps = {
         sortBy: specColumns.sort,
         fillDirection: "right-down",
         z: specColumns.z,
         collapseYHeight: true,
-        showAxes: !insight.hideAxes
+        showAxes: !insight.hideAxes,
+        view
     };
     const axisScales = {
         z: {
@@ -1195,7 +1217,8 @@ exports.default = function(specContext) {
                 {
                     role: "z",
                     axisSelection: ((_a = specColumns.z) === null || _a === void 0 ? void 0 : _a.quantitative) ? "range" : "exact",
-                    allowNone: true
+                    allowNone: true,
+                    disabled: view === "2d"
                 },
                 {
                     role: "color",
@@ -1243,7 +1266,8 @@ exports.default = function(specContext) {
         scatterPointScaleDisplay: specViewOptions.language.scatterPointScale,
         zGrounded: specViewOptions.language.zGrounded,
         backgroundImageExtents,
-        showAxes: !(backgroundImageExtents || insight.hideAxes)
+        showAxes: !(backgroundImageExtents || insight.hideAxes),
+        view: insight.view
     };
     const axisScales = {
         x: {
@@ -1279,7 +1303,8 @@ exports.default = function(specContext) {
                 {
                     role: "z",
                     axisSelection: ((_j = specColumns.z) === null || _j === void 0 ? void 0 : _j.quantitative) ? "range" : "exact",
-                    allowNone: true
+                    allowNone: true,
+                    disabled: false
                 },
                 {
                     role: "color",
@@ -1451,13 +1476,15 @@ parcelHelpers.defineInteropFlag(exports);
 exports.default = function(specContext) {
     var _a;
     const { insight , specColumns  } = specContext;
+    const { view  } = insight;
     const stripProps = {
         sortOrder: "ascending",
         orientation: "vertical",
         size: specColumns.size,
         sort: specColumns.sort,
         z: specColumns.z,
-        showAxes: !insight.hideAxes
+        showAxes: !insight.hideAxes,
+        view
     };
     const axisScales = {
         z: {
@@ -1503,7 +1530,8 @@ exports.default = function(specContext) {
                 {
                     role: "z",
                     axisSelection: ((_a = specColumns.z) === null || _a === void 0 ? void 0 : _a.quantitative) ? "range" : "exact",
-                    allowNone: true
+                    allowNone: true,
+                    disabled: view === "2d"
                 },
                 {
                     role: "color",
@@ -1542,13 +1570,15 @@ parcelHelpers.defineInteropFlag(exports);
 exports.default = function(specContext) {
     var _a;
     const { insight , specColumns , specViewOptions  } = specContext;
+    const { view  } = insight;
     const treemapProps = {
         corner: "top-left",
         group: specColumns.group,
         size: specColumns.size,
         treeMapMethod: specViewOptions.language.treeMapMethod,
         z: specColumns.z,
-        showAxes: !insight.hideAxes
+        showAxes: !insight.hideAxes,
+        view
     };
     const axisScales = {
         z: {
@@ -1597,7 +1627,8 @@ exports.default = function(specContext) {
                 {
                     role: "z",
                     axisSelection: ((_a = specColumns.z) === null || _a === void 0 ? void 0 : _a.quantitative) ? "range" : "exact",
-                    allowNone: true
+                    allowNone: true,
+                    disabled: view === "2d"
                 },
                 {
                     role: "color",
@@ -4523,7 +4554,7 @@ class Scatter extends (0, _layout.Layout) {
     }
     build() {
         const { names , prefix , props  } = this;
-        const { backgroundImageExtents , globalScope , parentScope , scatterPointScaleDisplay , showAxes , size , x , y , z , zGrounded  } = props;
+        const { backgroundImageExtents , globalScope , parentScope , scatterPointScaleDisplay , showAxes , size , view , x , y , z , zGrounded  } = props;
         const qsize = size && size.quantitative && size;
         (0, _scope.addSignals)(globalScope.scope, {
             name: (0, _constants.SignalNames).PointScale,
@@ -4623,13 +4654,18 @@ class Scatter extends (0, _layout.Layout) {
                     signal: `${(0, _constants.SignalNames).ZGrounded} ? 0 : ${zValue}`
                 }, 
             ],
+            zindex: [
+                {
+                    signal: `${(0, _constants.SignalNames).ZGrounded} ? 0 : ${zValue}`
+                }, 
+            ],
             depth: [
                 {
                     test: (0, _selection.testForCollapseSelection)(),
                     value: 0
                 },
                 {
-                    signal: `${(0, _constants.SignalNames).ZGrounded} ? ${zValue} : ${sizeValueSignal}`
+                    signal: view === "3d" ? `${(0, _constants.SignalNames).ZGrounded} ? ${zValue} : ${sizeValueSignal}` : "0"
                 }, 
             ]
         });
@@ -4669,7 +4705,7 @@ class Scatter extends (0, _layout.Layout) {
                     field: z ? (0, _expr.safeFieldName)(z.name) : null
                 },
                 reverse: false,
-                signal: `(${globalScope.zSize}) * ${(0, _constants.SignalNames).ZProportion}`
+                signal: view === "3d" ? `(${globalScope.zSize}) * ${(0, _constants.SignalNames).ZProportion}` : `10 * ${(0, _constants.SignalNames).ZProportion}`
             }, 
         ];
         columnSignals.forEach((cs)=>{
@@ -4757,7 +4793,7 @@ class Square extends (0, _layout.Layout) {
     }
     build() {
         const { names , prefix , props  } = this;
-        const { fillDirection , globalScope , groupings , parentScope , collapseYHeight , showAxes , sortBy , z  } = props;
+        const { fillDirection , globalScope , groupings , parentScope , collapseYHeight , showAxes , sortBy , view , z  } = props;
         const zScale = (0, _zBase.addZScale)(z, globalScope.zSize, globalScope.data.name, names.zScale);
         (0, _scope.addTransforms)(globalScope.data, Object.assign({
             type: "stack",
@@ -4803,9 +4839,11 @@ class Square extends (0, _layout.Layout) {
                             test: (0, _selection.testForCollapseSelection)(),
                             value: 0
                         },
-                        {
+                        view === "3d" ? {
                             scale: names.zScale,
                             field: (0, _expr.safeFieldName)(z.name)
+                        } : {
+                            value: 0
                         }, 
                     ]
                 })
@@ -5215,7 +5253,7 @@ class Strip extends (0, _layout.Layout) {
     }
     build() {
         const { names , prefix , props  } = this;
-        const { addPercentageScale , globalScope , groupings , orientation , showAxes , size , sort , sortOrder , parentScope , z  } = props;
+        const { addPercentageScale , globalScope , groupings , orientation , showAxes , size , sort , sortOrder , parentScope , view , z  } = props;
         const zScale = (0, _zBase.addZScale)(z, globalScope.zSize, globalScope.data.name, names.zScale);
         const horizontal = orientation === "horizontal";
         const transform = [];
@@ -5286,9 +5324,11 @@ class Strip extends (0, _layout.Layout) {
                             test: (0, _selection.testForCollapseSelection)(),
                             value: 0
                         },
-                        {
+                        view === "3d" ? {
                             scale: names.zScale,
                             field: (0, _expr.safeFieldName)(z.name)
+                        } : {
+                            value: 0
                         }, 
                     ]
                 })
@@ -5483,7 +5523,7 @@ class Treemap extends (0, _layout.Layout) {
     }
     addMark(offsets, markParent, markDataName) {
         const { names , prefix , props  } = this;
-        const { z  } = props;
+        const { view , z  } = props;
         const mark = {
             name: prefix,
             type: "rect",
@@ -5507,9 +5547,11 @@ class Treemap extends (0, _layout.Layout) {
                             test: (0, _selection.testForCollapseSelection)(),
                             value: 0
                         },
-                        {
+                        view === "3d" ? {
                             scale: names.zScale,
                             field: (0, _expr.safeFieldName)(z.name)
+                        } : {
+                            value: 0
                         }, 
                     ]
                 })
diff --git a/docs/tests/sanddance-specs/v1/specs/scatter.json b/docs/tests/sanddance-specs/v1/specs/scatter.json
index 8dd073541..539fce9a3 100644
--- a/docs/tests/sanddance-specs/v1/specs/scatter.json
+++ b/docs/tests/sanddance-specs/v1/specs/scatter.json
@@ -2,14 +2,14 @@
     "columns": {
         "x": "Longitude",
         "y": "Latitude",
-        "color": "Obama",
-        "z": "Education"
+        "color": "Income",
+        "z": "Income"
     },
-    "scheme": "redblue",
+    "scheme": "redyellowgreen",
     "size": {
         "height": 600,
         "width": 800
     },
     "chart": "scatterplot",
-    "view": "3d"
+    "view": "2d"
 }
\ No newline at end of file