diff --git a/src/mark.js b/src/mark.js
index 6f1bdcdf9f..2e7635f54f 100644
--- a/src/mark.js
+++ b/src/mark.js
@@ -9,7 +9,8 @@ export class Mark {
constructor(data, channels = [], options = {}) {
const names = new Set();
this.data = data;
- this.transform = maybeTransform(options);
+ const {transform} = maybeTransform(options);
+ this.transform = transform;
this.channels = channels.filter(channel => {
const {name, value, optional} = channel;
if (value == null) {
@@ -220,13 +221,19 @@ export function maybeLazyChannel(source) {
// If both t1 and t2 are defined, returns a composite transform that first
// applies t1 and then applies t2.
-export function maybeTransform({filter: f1, sort: s1, reverse: r1, transform: t1} = {}, t2) {
+export function maybeTransform({
+ filter: f1,
+ sort: s1,
+ reverse: r1,
+ transform: t1,
+ ...options
+} = {}, t2) {
if (t1 === undefined) {
if (f1 != null) t1 = filter(f1);
if (s1 != null) t1 = compose(t1, sort(s1));
if (r1) t1 = compose(t1, reverse);
}
- return compose(t1, t2);
+ return {...options, transform: compose(t1, t2)};
}
// Assuming that both x1 and x2 and lazy channels (per above), this derives a
diff --git a/src/marks/bar.js b/src/marks/bar.js
index 30319dbe77..25a963e1a6 100644
--- a/src/marks/bar.js
+++ b/src/marks/bar.js
@@ -1,4 +1,3 @@
-import {ascending} from "d3";
import {create} from "d3";
import {filter} from "../defined.js";
import {Mark, number, maybeColor, maybeZero, title, maybeNumber} from "../mark.js";
@@ -9,7 +8,6 @@ export class AbstractBar extends Mark {
data,
channels,
{
- z,
title,
fill,
fillOpacity,
@@ -33,7 +31,6 @@ export class AbstractBar extends Mark {
data,
[
...channels,
- {name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "fill", value: vfill, scale: "color", optional: true},
{name: "fillOpacity", value: vfillOpacity, scale: "opacity", optional: true},
@@ -58,9 +55,8 @@ export class AbstractBar extends Mark {
}
render(I, scales, channels, dimensions) {
const {rx, ry} = this;
- const {z: Z, title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO} = channels;
+ const {title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO} = channels;
const index = filter(I, ...this._positions(channels), F, FO, S, SO);
- if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(this._transform, scales)
diff --git a/src/marks/dot.js b/src/marks/dot.js
index a672e0e93a..b1bfa83553 100644
--- a/src/marks/dot.js
+++ b/src/marks/dot.js
@@ -1,4 +1,3 @@
-import {ascending} from "d3";
import {create} from "d3";
import {filter, positive} from "../defined.js";
import {Mark, identity, maybeColor, maybeNumber, maybeTuple, title} from "../mark.js";
@@ -10,7 +9,6 @@ export class Dot extends Mark {
{
x,
y,
- z,
r,
title,
fill,
@@ -30,7 +28,6 @@ export class Dot extends Mark {
[
{name: "x", value: x, scale: "x", optional: true},
{name: "y", value: y, scale: "y", optional: true},
- {name: "z", value: z, optional: true},
{name: "r", value: vr, scale: "r", optional: true},
{name: "title", value: title, optional: true},
{name: "fill", value: vfill, scale: "color", optional: true},
@@ -53,12 +50,11 @@ export class Dot extends Mark {
render(
I,
{x, y},
- {x: X, y: Y, z: Z, r: R, title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO},
+ {x: X, y: Y, r: R, title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO},
{width, height, marginTop, marginRight, marginBottom, marginLeft}
) {
let index = filter(I, X, Y, F, FO, S, SO);
if (R) index = index.filter(i => positive(R[i]));
- if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(applyTransform, x, y, 0.5, 0.5)
diff --git a/src/marks/link.js b/src/marks/link.js
index e9409893c8..780c43d204 100644
--- a/src/marks/link.js
+++ b/src/marks/link.js
@@ -1,4 +1,3 @@
-import {ascending} from "d3";
import {create} from "d3";
import {filter} from "../defined.js";
import {Mark, maybeColor, maybeNumber, title} from "../mark.js";
@@ -12,7 +11,6 @@ export class Link extends Mark {
y1,
x2,
y2,
- z,
title,
stroke,
strokeOpacity,
@@ -28,7 +26,6 @@ export class Link extends Mark {
{name: "y1", value: y1, scale: "y"},
{name: "x2", value: x2, scale: "x"},
{name: "y2", value: y2, scale: "y"},
- {name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "stroke", value: vstroke, scale: "color", optional: true},
{name: "strokeOpacity", value: vstrokeOpacity, scale: "opacity", optional: true}
@@ -44,10 +41,9 @@ export class Link extends Mark {
render(
I,
{x, y},
- {x1: X1, y1: Y1, x2: X2, y2: Y2, z: Z, title: L, stroke: S, strokeOpacity: SO}
+ {x1: X1, y1: Y1, x2: X2, y2: Y2, title: L, stroke: S, strokeOpacity: SO}
) {
const index = filter(I, X1, Y1, X2, Y2, S, SO);
- if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(applyTransform, x, y, 0.5, 0.5)
diff --git a/src/marks/rect.js b/src/marks/rect.js
index 26891b3f3e..e809540f23 100644
--- a/src/marks/rect.js
+++ b/src/marks/rect.js
@@ -1,4 +1,3 @@
-import {ascending} from "d3";
import {create} from "d3";
import {filter} from "../defined.js";
import {Mark, number, maybeColor, maybeZero, title, maybeNumber} from "../mark.js";
@@ -12,7 +11,6 @@ export class Rect extends Mark {
y1,
x2,
y2,
- z,
title,
fill,
fillOpacity,
@@ -39,7 +37,6 @@ export class Rect extends Mark {
{name: "y1", value: y1, scale: "y"},
{name: "x2", value: x2, scale: "x"},
{name: "y2", value: y2, scale: "y"},
- {name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "fill", value: vfill, scale: "color", optional: true},
{name: "fillOpacity", value: vfillOpacity, scale: "opacity", optional: true},
@@ -65,11 +62,10 @@ export class Rect extends Mark {
render(
I,
{x, y},
- {x1: X1, y1: Y1, x2: X2, y2: Y2, z: Z, title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO}
+ {x1: X1, y1: Y1, x2: X2, y2: Y2, title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO}
) {
const {rx, ry} = this;
const index = filter(I, X1, Y2, X2, Y2, F, FO, S, SO);
- if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(applyTransform, x, y)
diff --git a/src/marks/rule.js b/src/marks/rule.js
index 1ae189d568..5a79bc771f 100644
--- a/src/marks/rule.js
+++ b/src/marks/rule.js
@@ -1,4 +1,3 @@
-import {ascending} from "d3";
import {create} from "d3";
import {filter} from "../defined.js";
import {Mark, identity, maybeColor, zero, title, number} from "../mark.js";
@@ -11,7 +10,6 @@ export class RuleX extends Mark {
x,
y1,
y2,
- z,
title,
stroke,
inset = 0,
@@ -27,7 +25,6 @@ export class RuleX extends Mark {
{name: "x", value: x, scale: "x", optional: true},
{name: "y1", value: y1, scale: "y", optional: true},
{name: "y2", value: y2, scale: "y", optional: true},
- {name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "stroke", value: vstroke, scale: "color", optional: true}
],
@@ -40,11 +37,10 @@ export class RuleX extends Mark {
render(
I,
{x, y},
- {x: X, y1: Y1, y2: Y2, z: Z, title: L, stroke: S},
+ {x: X, y1: Y1, y2: Y2, title: L, stroke: S},
{width, height, marginTop, marginRight, marginLeft, marginBottom}
) {
const index = filter(I, X, Y1, Y2, S);
- if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(applyTransform, X && x, null, 0.5, 0)
@@ -69,7 +65,6 @@ export class RuleY extends Mark {
x1,
x2,
y,
- z,
title,
stroke,
inset = 0,
@@ -85,7 +80,6 @@ export class RuleY extends Mark {
{name: "y", value: y, scale: "y", optional: true},
{name: "x1", value: x1, scale: "x", optional: true},
{name: "x2", value: x2, scale: "x", optional: true},
- {name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "stroke", value: vstroke, scale: "color", optional: true}
],
@@ -98,11 +92,10 @@ export class RuleY extends Mark {
render(
I,
{x, y},
- {y: Y, x1: X1, x2: X2, z: Z, title: L, stroke: S},
+ {y: Y, x1: X1, x2: X2, title: L, stroke: S},
{width, height, marginTop, marginRight, marginLeft, marginBottom}
) {
const index = filter(I, Y, X1, X2);
- if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(applyTransform, null, Y && y, 0, 0.5)
diff --git a/src/marks/text.js b/src/marks/text.js
index 4c0175c22b..77dd6f0086 100644
--- a/src/marks/text.js
+++ b/src/marks/text.js
@@ -1,4 +1,3 @@
-import {ascending} from "d3";
import {create} from "d3";
import {filter, nonempty} from "../defined.js";
import {Mark, indexOf, identity, string, title, maybeColor, maybeNumber, maybeTuple, numberChannel} from "../mark.js";
@@ -10,7 +9,6 @@ export class Text extends Mark {
{
x,
y,
- z,
text = indexOf,
title,
fill,
@@ -36,7 +34,6 @@ export class Text extends Mark {
[
{name: "x", value: x, scale: "x", optional: true},
{name: "y", value: y, scale: "y", optional: true},
- {name: "z", value: z, optional: true},
{name: "fontSize", value: numberChannel(vfontSize), optional: true},
{name: "rotate", value: numberChannel(vrotate), optional: true},
{name: "text", value: text},
@@ -60,12 +57,11 @@ export class Text extends Mark {
render(
I,
{x, y},
- {x: X, y: Y, z: Z, rotate: R, text: T, title: L, fill: F, fillOpacity: FO, fontSize: FS},
+ {x: X, y: Y, rotate: R, text: T, title: L, fill: F, fillOpacity: FO, fontSize: FS},
{width, height, marginTop, marginRight, marginBottom, marginLeft}
) {
const {rotate} = this;
const index = filter(I, X, Y, F, FO, R).filter(i => nonempty(T[i]));
- if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
const cx = (marginLeft + width - marginRight) / 2;
const cy = (marginTop + height - marginBottom) / 2;
return create("svg:g")
diff --git a/src/marks/tick.js b/src/marks/tick.js
index 5ad82c32a0..b5deadc4e1 100644
--- a/src/marks/tick.js
+++ b/src/marks/tick.js
@@ -1,4 +1,3 @@
-import {ascending} from "d3";
import {create} from "d3";
import {filter} from "../defined.js";
import {Mark, identity, maybeColor, title} from "../mark.js";
@@ -9,7 +8,6 @@ class AbstractTick extends Mark {
data,
channels,
{
- z,
title,
stroke,
...options
@@ -20,7 +18,6 @@ class AbstractTick extends Mark {
data,
[
...channels,
- {name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "stroke", value: vstroke, scale: "color", optional: true}
],
@@ -29,9 +26,8 @@ class AbstractTick extends Mark {
Style(this, {stroke: cstroke, ...options});
}
render(I, scales, channels, dimensions) {
- const {x: X, y: Y, z: Z, title: L, stroke: S} = channels;
+ const {x: X, y: Y, title: L, stroke: S} = channels;
const index = filter(I, X, Y, S);
- if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(this._transform, scales)
diff --git a/src/transforms/bin.js b/src/transforms/bin.js
index 0e77cb9005..0467fd2c3a 100644
--- a/src/transforms/bin.js
+++ b/src/transforms/bin.js
@@ -69,12 +69,7 @@ function binn(
z: GZ,
fill: GF,
stroke: GS,
- ...options,
- ...BX1 ? {x1: BX1, x2: BX2, x: mid(BX1, BX2)} : {x},
- ...BY1 ? {y1: BY1, y2: BY2, y: mid(BY1, BY2)} : {y},
- ...GK && {[gk]: GK},
- ...Object.fromEntries(outputs.map(({name, output}) => [name, output])),
- transform: maybeTransform(options, (data, facets) => {
+ ...maybeTransform(options, (data, facets) => {
const K = valueof(data, k);
const Z = valueof(data, z);
const F = valueof(data, vfill);
@@ -121,7 +116,11 @@ function binn(
groupFacets.push(groupFacet);
}
return {data: groupData, facets: groupFacets};
- })
+ }),
+ ...BX1 ? {x1: BX1, x2: BX2, x: mid(BX1, BX2)} : {x},
+ ...BY1 ? {y1: BY1, y2: BY2, y: mid(BY1, BY2)} : {y},
+ ...GK && {[gk]: GK},
+ ...Object.fromEntries(outputs.map(({name, output}) => [name, output]))
};
}
diff --git a/src/transforms/group.js b/src/transforms/group.js
index fa245b73d5..932c1f9a3c 100644
--- a/src/transforms/group.js
+++ b/src/transforms/group.js
@@ -57,11 +57,7 @@ function groupn(
z: GZ,
fill: GF,
stroke: GS,
- ...options,
- ...GX && {x: GX},
- ...GY && {y: GY},
- ...Object.fromEntries(outputs.map(({name, output}) => [name, output])),
- transform: maybeTransform(options, (data, facets) => {
+ ...maybeTransform(options, (data, facets) => {
const X = valueof(data, x);
const Y = valueof(data, y);
const Z = valueof(data, z);
@@ -97,7 +93,10 @@ function groupn(
groupFacets.push(groupFacet);
}
return {data: groupData, facets: groupFacets};
- })
+ }),
+ ...GX && {x: GX},
+ ...GY && {y: GY},
+ ...Object.fromEntries(outputs.map(({name, output}) => [name, output]))
};
}
diff --git a/src/transforms/map.js b/src/transforms/map.js
index 02826513e2..416b51712a 100644
--- a/src/transforms/map.js
+++ b/src/transforms/map.js
@@ -22,9 +22,7 @@ export function map(outputs = {}, options = {}) {
return {key, input, output, setOutput, map: maybeMap(map)};
});
return {
- ...options,
- ...Object.fromEntries(channels.map(({key, output}) => [key, output])),
- transform: maybeTransform(options, (data, facets) => {
+ ...maybeTransform(options, (data, facets) => {
const Z = valueof(data, z);
const X = channels.map(({input}) => valueof(data, input));
const MX = channels.map(({setOutput}) => setOutput(new Array(data.length)));
@@ -34,7 +32,8 @@ export function map(outputs = {}, options = {}) {
}
}
return {data, facets};
- })
+ }),
+ ...Object.fromEntries(channels.map(({key, output}) => [key, output]))
};
}
diff --git a/src/transforms/select.js b/src/transforms/select.js
index 54237d7c6f..3fdf822dfd 100644
--- a/src/transforms/select.js
+++ b/src/transforms/select.js
@@ -2,27 +2,27 @@ import {greatest, group, least} from "d3";
import {maybeTransform, maybeZ, valueof} from "../mark.js";
export function selectFirst(options) {
- return {...options, transform: select(first, undefined, options)};
+ return select(first, undefined, options);
}
export function selectLast(options) {
- return {...options, transform: select(last, undefined, options)};
+ return select(last, undefined, options);
}
-export function selectMinX({x, ...options} = {}) {
- return {...options, x, transform: select(min, x, options)};
+export function selectMinX(options = {}) {
+ return select(min, options.x, options);
}
-export function selectMinY({y, ...options} = {}) {
- return {...options, y, transform: select(min, y, options)};
+export function selectMinY(options = {}) {
+ return select(min, options.y, options);
}
-export function selectMaxX({x, ...options} = {}) {
- return {...options, x, transform: select(max, x, options)};
+export function selectMaxX(options = {}) {
+ return select(max, options.x, options);
}
-export function selectMaxY({y, ...options} = {}) {
- return {...options, y, transform: select(max, y, options)};
+export function selectMaxY(options = {}) {
+ return select(max, options.y, options);
}
// TODO If the value (for some required channel) is undefined, scan forward?
diff --git a/src/transforms/stack.js b/src/transforms/stack.js
index c817578325..b291a915bb 100644
--- a/src/transforms/stack.js
+++ b/src/transforms/stack.js
@@ -40,34 +40,31 @@ function stack(x, y = () => 1, ky, {offset, order, reverse, ...options} = {}) {
offset = maybeOffset(offset);
order = maybeOrder(order, offset, ky);
return [
- {
- ...options,
- transform: maybeTransform(options, (data, facets) => {
- const X = x == null ? undefined : setX(valueof(data, x));
- const Y = valueof(data, y, Float64Array);
- const Z = valueof(data, z);
- const O = order && order(data, X, Y, Z);
- const n = data.length;
- const Y1 = setY1(new Float64Array(n));
- const Y2 = setY2(new Float64Array(n));
- for (const facet of facets) {
- const stacks = X ? Array.from(group(facet, i => X[i]).values()) : [facet];
- if (O) applyOrder(stacks, O);
- for (const stack of stacks) {
- let yn = 0, yp = 0;
- if (reverse) stack.reverse();
- for (const i of stack) {
- const y = Y[i];
- if (y < 0) yn = Y2[i] = (Y1[i] = yn) + y;
- else if (y > 0) yp = Y2[i] = (Y1[i] = yp) + y;
- else Y2[i] = Y1[i] = yp; // NaN or zero
- }
+ maybeTransform(options, (data, facets) => {
+ const X = x == null ? undefined : setX(valueof(data, x));
+ const Y = valueof(data, y, Float64Array);
+ const Z = valueof(data, z);
+ const O = order && order(data, X, Y, Z);
+ const n = data.length;
+ const Y1 = setY1(new Float64Array(n));
+ const Y2 = setY2(new Float64Array(n));
+ for (const facet of facets) {
+ const stacks = X ? Array.from(group(facet, i => X[i]).values()) : [facet];
+ if (O) applyOrder(stacks, O);
+ for (const stack of stacks) {
+ let yn = 0, yp = 0;
+ if (reverse) stack.reverse();
+ for (const i of stack) {
+ const y = Y[i];
+ if (y < 0) yn = Y2[i] = (Y1[i] = yn) + y;
+ else if (y > 0) yp = Y2[i] = (Y1[i] = yp) + y;
+ else Y2[i] = Y1[i] = yp; // NaN or zero
}
- if (offset) offset(stacks, Y1, Y2, Z);
}
- return {data, facets};
- })
- },
+ if (offset) offset(stacks, Y1, Y2, Z);
+ }
+ return {data, facets};
+ }),
X,
Y1,
Y2
diff --git a/test/marks/bar-test.js b/test/marks/bar-test.js
index 9574e796e6..dcb09fa8df 100644
--- a/test/marks/bar-test.js
+++ b/test/marks/bar-test.js
@@ -32,13 +32,6 @@ tape("barX(data, {y}) uses a band scale", test => {
test.strictEqual(bar.channels.find(c => c.name === "y").value.label, "x");
});
-tape("barX(data, {z}) specifies an optional z channel", test => {
- const bar = Plot.barX(undefined, {z: "x"});
- const z = bar.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "x");
- test.strictEqual(z.scale, undefined);
-});
-
tape("barX(data, {title}) specifies an optional title channel", test => {
const bar = Plot.barX(undefined, {title: "x"});
const title = bar.channels.find(c => c.name === "title");
@@ -126,13 +119,6 @@ tape("barY(data, {x}) uses a band scale", test => {
test.strictEqual(bar.channels.find(c => c.name === "x").value.label, "y");
});
-tape("barY(data, {z}) specifies an optional z channel", test => {
- const bar = Plot.barY(undefined, {z: "x"});
- const z = bar.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "x");
- test.strictEqual(z.scale, undefined);
-});
-
tape("barY(data, {title}) specifies an optional title channel", test => {
const bar = Plot.barY(undefined, {title: "x"});
const title = bar.channels.find(c => c.name === "title");
diff --git a/test/marks/cell-test.js b/test/marks/cell-test.js
index 5ab37425b3..c742ea3eca 100644
--- a/test/marks/cell-test.js
+++ b/test/marks/cell-test.js
@@ -26,13 +26,6 @@ tape("cell() has the expected defaults", test => {
test.strictEqual(cell.insetLeft, 0);
});
-tape("cell(data, {z}) specifies an optional z channel", test => {
- const cell = Plot.cell(undefined, {z: "x"});
- const z = cell.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "x");
- test.strictEqual(z.scale, undefined);
-});
-
tape("cell(data, {title}) specifies an optional title channel", test => {
const cell = Plot.cell(undefined, {title: "x"});
const title = cell.channels.find(c => c.name === "title");
diff --git a/test/marks/dot-test.js b/test/marks/dot-test.js
index 74e7591485..b2f69eb24f 100644
--- a/test/marks/dot-test.js
+++ b/test/marks/dot-test.js
@@ -21,13 +21,6 @@ tape("dot() has the expected defaults", test => {
test.strictEqual(dot.mixBlendMode, undefined);
});
-tape("dot(data, {z}) specifies an optional z channel", test => {
- const dot = Plot.dot(undefined, {z: "x"});
- const z = dot.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "x");
- test.strictEqual(z.scale, undefined);
-});
-
tape("dot(data, {r}) allows r to be a constant radius", test => {
const dot = Plot.dot(undefined, {r: 42});
test.strictEqual(dot.r, 42);
diff --git a/test/marks/link-test.js b/test/marks/link-test.js
index 0431092467..3f41021404 100644
--- a/test/marks/link-test.js
+++ b/test/marks/link-test.js
@@ -20,13 +20,6 @@ tape("link(data, options) has the expected defaults", test => {
test.strictEqual(link.mixBlendMode, undefined);
});
-tape("link(data, {z}) specifies an optional z channel", test => {
- const link = Plot.link(undefined, {x1: "0", y1: "1", x2: "2", y2: "3", z: "4"});
- const z = link.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "4");
- test.strictEqual(z.scale, undefined);
-});
-
tape("link(data, {title}) specifies an optional title channel", test => {
const link = Plot.link(undefined, {x1: "0", y1: "1", x2: "2", y2: "3", title: "4"});
const title = link.channels.find(c => c.name === "title");
diff --git a/test/marks/rect-test.js b/test/marks/rect-test.js
index 9bbb5be4ce..7b2e287480 100644
--- a/test/marks/rect-test.js
+++ b/test/marks/rect-test.js
@@ -24,13 +24,6 @@ tape("rect(data, options) has the expected defaults", test => {
test.strictEqual(rect.insetLeft, 0);
});
-tape("rect(data, {z}) specifies an optional z channel", test => {
- const rect = Plot.rect(undefined, {x1: "0", y1: "1", x2: "2", y2: "3", z: "4"});
- const z = rect.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "4");
- test.strictEqual(z.scale, undefined);
-});
-
tape("rect(data, {title}) specifies an optional title channel", test => {
const rect = Plot.rect(undefined, {x1: "0", y1: "1", x2: "2", y2: "3", title: "4"});
const title = rect.channels.find(c => c.name === "title");
diff --git a/test/marks/rule-test.js b/test/marks/rule-test.js
index 64e5ec8af4..4730cb2624 100644
--- a/test/marks/rule-test.js
+++ b/test/marks/rule-test.js
@@ -20,13 +20,6 @@ tape("ruleX() has the expected defaults", test => {
test.strictEqual(rule.mixBlendMode, undefined);
});
-tape("ruleX(data, {z}) specifies an optional z channel", test => {
- const rule = Plot.ruleX(undefined, {z: "x"});
- const z = rule.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "x");
- test.strictEqual(z.scale, undefined);
-});
-
tape("ruleX(data, {title}) specifies an optional title channel", test => {
const rule = Plot.ruleX(undefined, {title: "x"});
const title = rule.channels.find(c => c.name === "title");
@@ -114,13 +107,6 @@ tape("ruleY() has the expected defaults", test => {
test.strictEqual(rule.mixBlendMode, undefined);
});
-tape("ruleY(data, {z}) specifies an optional z channel", test => {
- const rule = Plot.ruleY(undefined, {z: "x"});
- const z = rule.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "x");
- test.strictEqual(z.scale, undefined);
-});
-
tape("ruleY(data, {title}) specifies an optional title channel", test => {
const rule = Plot.ruleY(undefined, {title: "x"});
const title = rule.channels.find(c => c.name === "title");
diff --git a/test/marks/text-test.js b/test/marks/text-test.js
index 0f661a93a2..41392988e3 100644
--- a/test/marks/text-test.js
+++ b/test/marks/text-test.js
@@ -24,13 +24,6 @@ tape("text() has the expected defaults", test => {
test.strictEqual(text.rotate, 0);
});
-tape("text(data, {z}) specifies an optional z channel", test => {
- const text = Plot.text(undefined, {z: "x"});
- const z = text.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "x");
- test.strictEqual(z.scale, undefined);
-});
-
tape("text(data, {title}) specifies an optional title channel", test => {
const text = Plot.text(undefined, {title: "x"});
const title = text.channels.find(c => c.name === "title");
diff --git a/test/marks/tick-test.js b/test/marks/tick-test.js
index ffec65d807..e8f6d54ddf 100644
--- a/test/marks/tick-test.js
+++ b/test/marks/tick-test.js
@@ -28,13 +28,6 @@ tape("tickX(data, {y}) uses a band scale", test => {
test.strictEqual(tick.channels.find(c => c.name === "y").value.label, "x");
});
-tape("tickX(data, {z}) specifies an optional z channel", test => {
- const tick = Plot.tickX(undefined, {z: "x"});
- const z = tick.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "x");
- test.strictEqual(z.scale, undefined);
-});
-
tape("tickX(data, {title}) specifies an optional title channel", test => {
const tick = Plot.tickX(undefined, {title: "x"});
const title = tick.channels.find(c => c.name === "title");
@@ -87,13 +80,6 @@ tape("tickY(data, {x}) uses a band scale", test => {
test.strictEqual(tick.channels.find(c => c.name === "x").value.label, "y");
});
-tape("tickY(data, {z}) specifies an optional z channel", test => {
- const tick = Plot.tickY(undefined, {z: "x"});
- const z = tick.channels.find(c => c.name === "z");
- test.strictEqual(z.value.label, "x");
- test.strictEqual(z.scale, undefined);
-});
-
tape("tickY(data, {title}) specifies an optional title channel", test => {
const tick = Plot.tickY(undefined, {title: "x"});
const title = tick.channels.find(c => c.name === "title");
diff --git a/test/output/carsParcoords.svg b/test/output/carsParcoords.svg
index 74ee8ad9a4..314f0e4b7b 100644
--- a/test/output/carsParcoords.svg
+++ b/test/output/carsParcoords.svg
@@ -436,6 +436,6 @@
- 8101214161820222434567810015020025030035040045010152025303540456080100120140160180200220200025003000350040004500500070727476788082
- 8101214161820222434567810015020025030035040045010152025303540456080100120140160180200220200025003000350040004500500070727476788082
+ 1015202530354045345678100150200250300350400450608010012014016018020022020002500300035004000450050008101214161820222470727476788082
+ 1015202530354045345678100150200250300350400450608010012014016018020022020002500300035004000450050008101214161820222470727476788082
\ No newline at end of file
diff --git a/test/output/policeDeaths.svg b/test/output/policeDeaths.svg
index e9e6a6fdfe..34b1724b0e 100644
--- a/test/output/policeDeaths.svg
+++ b/test/output/policeDeaths.svg
@@ -13,6 +13,6 @@
- All other races 6%Black 44%Hispanic 32%White 18%
- All other races 15%Black 13%Hispanic 12%White 60%
+ Black 44%Hispanic 32%White 18%All other races 6%
+ Black 13%Hispanic 12%White 60%All other races 15%
\ No newline at end of file
diff --git a/test/output/usPopulationStateAge.svg b/test/output/usPopulationStateAge.svg
index 4b971e74dd..f7ff09ebf7 100644
--- a/test/output/usPopulationStateAge.svg
+++ b/test/output/usPopulationStateAge.svg
@@ -87,473 +87,473 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
\ No newline at end of file
diff --git a/test/output/usPopulationStateAgeDots.svg b/test/output/usPopulationStateAgeDots.svg
index b90092bd3b..82d2445af2 100644
--- a/test/output/usPopulationStateAgeDots.svg
+++ b/test/output/usPopulationStateAgeDots.svg
@@ -103,474 +103,474 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
- AKALARAZCACOCTDCDEFLGAHIIAIDILINKSKYLAMAMDMEMIMNMOMSMTNCNDNENHNJNMNVNYOHOKORPAPRRISCSDTNTXUTVAVTWAWIWVWY
+ ALAKAZARCACOCTDEDCFLGAHIIDILINIAKSKYLAMEMDMAMIMNMSMOMTNENVNHNJNMNYNCNDOHOKORPARISCSDTNTXUTVTVAWAWVWIWYPR
\ No newline at end of file
diff --git a/test/plots/crimean-war-overlapped.js b/test/plots/crimean-war-overlapped.js
index d93b4de8e8..f40da4630c 100644
--- a/test/plots/crimean-war-overlapped.js
+++ b/test/plots/crimean-war-overlapped.js
@@ -11,7 +11,7 @@ export default async function() {
label: null
},
marks: [
- Plot.barY(data, {x: "date", y: "deaths", z: d => -d.deaths, fill: "cause"}),
+ Plot.barY(data, {x: "date", y: "deaths", sort: d => -d.deaths, fill: "cause"}),
Plot.ruleY([0])
]
});