diff --git a/src/facet.js b/src/facet.js new file mode 100644 index 0000000000..cb2ff6cb71 --- /dev/null +++ b/src/facet.js @@ -0,0 +1,55 @@ +import {slice} from "./options.js"; + +export function facetReindex(facets, n) { + // Count the number of overlapping indexes across facets. + const overlap = new Uint8Array(n); + let count = 0; + for (const facet of facets) { + for (const i of facet) { + if (overlap[i]) ++count; + overlap[i] = 1; + } + } + + // For each overlapping index (duplicate number), assign a new unique index at + // the end of the existing array. For example, [[0, 1, 2], [2, 1, 3]] would + // become [[0, 1, 2], [4, 5, 3]]. Attach a plan to the facets array, to be + // able to read the values associated with the old index in unaffected + // channels. + if (count > 0) { + facets = facets.map((facet) => slice(facet, Uint32Array)); + const plan = (facets.plan = new Uint32Array(n + count)); + let j = 0; + for (; j < n; ++j) plan[j] = j; + overlap.fill(0); + for (const facet of facets) { + for (let k = 0; k < facet.length; ++k) { + const i = facet[k]; + if (overlap[i]) { + plan[j] = i; + facet[k] = j; + j++; + } + overlap[i] = 1; + } + } + } + return facets; +} + +// returns a function that reads X with the facets’ reindexing plan +export function getter({plan}, X) { + return !X ? X : !plan || X.length === plan.length ? (i) => X[i] : (i) => X[plan[i]]; +} + +// returns an array of X expanded along the facets’ reindexing plan +export function expander({plan}, X) { + if (!plan || !X || X.length === plan.length) return X; + const V = new X.constructor(plan.length); + for (let i = 0; i < plan.length; ++i) V[i] = X[plan[i]]; + return V; +} + +export function originals({plan}, I) { + return plan ? I.map((i) => plan[i]) : I; +} diff --git a/src/plot.js b/src/plot.js index 0e53efdce0..0f3c0f88fb 100644 --- a/src/plot.js +++ b/src/plot.js @@ -609,8 +609,24 @@ export function plot(options = {}) { .attr("transform", facetTranslate(fx, fy)) .each(function (key) { const j = indexByFacet.get(key); - for (const [mark, {channels, values, facets}] of stateByMark) { - const facet = facets ? mark.filter(facets[j] ?? facets[0], channels, values) : null; + for (const [mark, {channels, values: original, facets}] of stateByMark) { + // this facet is possibly reindexed + let values = original; + let F = facets?.[j]; + if (F && j > 0 && facets.plan) { + const {plan} = facets; + const long = Object.keys(values).filter((key) => values[key].length === plan.length); + const V = Object.fromEntries(long.map((key) => [key, []])); + F = []; + for (const i of facets[j]) { + const k = plan[i]; + F.push(k); + for (const key of long) V[key][k] = original[key][i]; + values = {...original, ...V}; + } + } + + const facet = facets ? mark.filter(F ?? facets[0], channels, values) : null; const node = mark.render(facet, scales, values, subdimensions, context); if (node != null) this.appendChild(node); } diff --git a/src/transforms/bin.js b/src/transforms/bin.js index 91ab1666d5..71a926e001 100644 --- a/src/transforms/bin.js +++ b/src/transforms/bin.js @@ -1,7 +1,14 @@ -import {bin as binner, extent, thresholdFreedmanDiaconis, thresholdScott, thresholdSturges, utcTickInterval} from "d3"; +import { + bin as binner, + extent, + sum, + thresholdFreedmanDiaconis, + thresholdScott, + thresholdSturges, + utcTickInterval +} from "d3"; import { valueof, - range, identity, maybeColumn, maybeTuple, @@ -29,6 +36,7 @@ import { } from "./group.js"; import {maybeInsetX, maybeInsetY} from "./inset.js"; import {maybeInterval} from "./interval.js"; +import {expander, getter, originals} from "../facet.js"; /** * ```js @@ -172,12 +180,19 @@ function binn( const GZ = Z && setGZ([]); const GF = F && setGF([]); const GS = S && setGS([]); - const BX = bx ? bx(data) : [[, , (I) => I]]; - const BY = by ? by(data) : [[, , (I) => I]]; + const BX = bx ? bx(data, facets) : [[, , (I) => I]]; + const BY = by ? by(data, facets) : [[, , (I) => I]]; const BX1 = bx && setBX1([]); const BX2 = bx && setBX2([]); const BY1 = by && setBY1([]); const BY2 = by && setBY2([]); + + const eG = getter(facets, G); + const eK = getter(facets, K); + const gZ = getter(facets, Z); + const gF = getter(facets, F); + const gS = getter(facets, S); + let i = 0; for (const o of outputs) o.initialize(data); if (sort) sort.initialize(data); @@ -187,8 +202,8 @@ function binn( for (const o of outputs) o.scope("facet", facet); if (sort) sort.scope("facet", facet); if (filter) filter.scope("facet", facet); - for (const [f, I] of maybeGroup(facet, G)) { - for (const [k, g] of maybeGroup(I, K)) { + for (const [f, I] of maybeGroup(facet, eG)) { + for (const [k, g] of maybeGroup(I, eK)) { for (const [x1, x2, fx] of BX) { const bb = fx(g); for (const [y1, y2, fy] of BY) { @@ -196,11 +211,11 @@ function binn( const b = fy(bb); if (filter && !filter.reduce(b, extent)) continue; groupFacet.push(i++); - groupData.push(reduceData.reduce(b, data, extent)); + groupData.push(reduceData.reduce(originals(facets, b), data, extent)); if (K) GK.push(k); - if (Z) GZ.push(G === Z ? f : Z[b[0]]); - if (F) GF.push(G === F ? f : F[b[0]]); - if (S) GS.push(G === S ? f : S[b[0]]); + if (Z) GZ.push(G === Z ? f : gZ(b[0])); + if (F) GF.push(G === F ? f : gF(b[0])); + if (S) GS.push(G === S ? f : gS(b[0])); if (BX1) BX1.push(x1), BX2.push(x2); if (BY1) BY1.push(y1), BY2.push(y2); for (const o of outputs) o.reduce(b, extent); @@ -248,8 +263,8 @@ function maybeBinValueTuple(options) { function maybeBin(options) { if (options == null) return; const {value, cumulative, domain = extent, thresholds} = options; - const bin = (data) => { - let V = valueof(data, value, Array); // d3.bin prefers Array input + const bin = (data, facets) => { + let V = expander(facets, valueof(data, value, Array)); // d3.bin prefers Array input const bin = binner().value((i) => V[i]); if (isTemporal(V) || isTimeThresholds(thresholds)) { V = V.map(coerceDate); @@ -279,7 +294,7 @@ function maybeBin(options) { } bin.thresholds(t).domain(d); } - let bins = bin(range(data)).map(binset); + let bins = bin(union(facets)).map(binset); if (cumulative) bins = (cumulative < 0 ? bins.reverse() : bins).map(bincumset); return bins.map(binfilter); }; @@ -365,3 +380,10 @@ function binfilter([{x0, x1}, set]) { function binempty() { return new Uint32Array(0); } + +function union(facets) { + const U = new Uint32Array(sum(facets, (d) => d.length)); + let c = 0; + for (const facet of facets) for (const i of facet) U[c++] = i; + return U; +} diff --git a/src/transforms/dodge.js b/src/transforms/dodge.js index 513a7b1efa..a74fbd755e 100644 --- a/src/transforms/dodge.js +++ b/src/transforms/dodge.js @@ -3,6 +3,7 @@ import {finite, positive} from "../defined.js"; import {identity, maybeNamed, number, valueof} from "../options.js"; import {coerceNumbers} from "../scales.js"; import {initializer} from "./basic.js"; +import {facetReindex, getter} from "../facet.js"; const anchorXLeft = ({marginLeft}) => [1, marginLeft]; const anchorXRight = ({width, marginRight}) => [-1, width - marginRight]; @@ -90,21 +91,26 @@ function dodge(y, x, anchor, padding, options) { return initializer(options, function (data, facets, {[x]: X, r: R}, scales, dimensions) { if (!X) throw new Error(`missing channel: ${x}`); X = coerceNumbers(valueof(X.value, scales[X.scale] || identity)); + + // make facets exclusive + facets = facetReindex(facets, data.length); + const r = R ? undefined : this.r !== undefined ? this.r : options.r !== undefined ? number(options.r) : 3; if (R) R = coerceNumbers(valueof(R.value, scales[R.scale] || identity)); let [ky, ty] = anchor(dimensions); const compare = ky ? compareAscending : compareSymmetric; - const Y = new Float64Array(X.length); - const radius = R ? (i) => R[i] : () => r; + const Y = new Float64Array((facets.plan || X).length); + const radius = R ? getter(facets, R) : () => r; + const getX = getter(facets, X); for (let I of facets) { const tree = IntervalTree(); - I = I.filter(R ? (i) => finite(X[i]) && positive(R[i]) : (i) => finite(X[i])); + I = I.filter(R ? (i) => finite(getX(i)) && positive(radius(i)) : (i) => finite(getX(i))); const intervals = new Float64Array(2 * I.length + 2); for (const i of I) { const ri = radius(i); const y0 = ky ? ri + padding : 0; // offset baseline for varying radius - const l = X[i] - ri; - const h = X[i] + ri; + const l = getX(i) - ri; + const h = getX(i) + ri; // The first two positions are 0 to test placing the dot on the baseline. let k = 2; @@ -114,8 +120,8 @@ function dodge(y, x, anchor, padding, options) { // https://observablehq.com/@mbostock/circle-offset-along-line tree.queryInterval(l - padding, h + padding, ([, , j]) => { const yj = Y[j] - y0; - const dx = X[i] - X[j]; - const dr = padding + (R ? R[i] + R[j] : 2 * r); + const dx = getX(i) - getX(j); + const dr = padding + (R ? radius(i) + radius(j) : 2 * r); const dy = Math.sqrt(dr * dr - dx * dx); intervals[k++] = yj - dy; intervals[k++] = yj + dy; diff --git a/src/transforms/group.js b/src/transforms/group.js index 5aa82be38a..cd3b320455 100644 --- a/src/transforms/group.js +++ b/src/transforms/group.js @@ -31,6 +31,7 @@ import { percentile } from "../options.js"; import {basic} from "./basic.js"; +import {getter, originals} from "../facet.js"; /** * ```js @@ -158,6 +159,14 @@ function groupn( const GZ = Z && setGZ([]); const GF = F && setGF([]); const GS = S && setGS([]); + + const eG = getter(facets, G); + const eX = getter(facets, X); + const eY = getter(facets, Y); + const gZ = getter(facets, Z); + const gF = getter(facets, F); + const gS = getter(facets, S); + let i = 0; for (const o of outputs) o.initialize(data); if (sort) sort.initialize(data); @@ -167,17 +176,17 @@ function groupn( for (const o of outputs) o.scope("facet", facet); if (sort) sort.scope("facet", facet); if (filter) filter.scope("facet", facet); - for (const [f, I] of maybeGroup(facet, G)) { - for (const [y, gg] of maybeGroup(I, Y)) { - for (const [x, g] of maybeGroup(gg, X)) { + for (const [f, I] of maybeGroup(facet, eG)) { + for (const [y, gg] of maybeGroup(I, eY)) { + for (const [x, g] of maybeGroup(gg, eX)) { if (filter && !filter.reduce(g)) continue; groupFacet.push(i++); - groupData.push(reduceData.reduce(g, data)); + groupData.push(reduceData.reduce(originals(facets, g), data)); if (X) GX.push(x); if (Y) GY.push(y); - if (Z) GZ.push(G === Z ? f : Z[g[0]]); - if (F) GF.push(G === F ? f : F[g[0]]); - if (S) GS.push(G === S ? f : S[g[0]]); + if (Z) GZ.push(G === Z ? f : gZ(g[0])); + if (F) GF.push(G === F ? f : gF(g[0])); + if (S) GS.push(G === S ? f : gS(g[0])); for (const o of outputs) o.reduce(g); if (sort) sort.reduce(g); } @@ -256,10 +265,10 @@ export function maybeEvaluator(name, reduce, inputs) { }; } -export function maybeGroup(I, X) { - return X +export function maybeGroup(I, x) { + return x ? sort( - grouper(I, (i) => X[i]), + grouper(I, (i) => x(i)), first ) : [[, I]]; diff --git a/src/transforms/hexbin.js b/src/transforms/hexbin.js index ebd0e50dc8..14fd0b5cc0 100644 --- a/src/transforms/hexbin.js +++ b/src/transforms/hexbin.js @@ -3,6 +3,7 @@ import {sqrt3} from "../symbols.js"; import {identity, isNoneish, number, valueof} from "../options.js"; import {initializer} from "./basic.js"; import {hasOutput, maybeGroup, maybeOutputs, maybeSubgroup} from "./group.js"; +import {getter} from "../facet.js"; // We don’t want the hexagons to align with the edges of the plot frame, as that // would cause extreme x-values (the upper bound of the default x-scale domain) @@ -100,19 +101,28 @@ export function hexbin(outputs = {fill: "count"}, options = {}) { const BX = []; const BY = []; let i = -1; + + // Mind reindexed facets + const eG = getter(facets, G); + const gX = getter(facets, X); + const gY = getter(facets, Y); + const gZ = getter(facets, Z); + const gF = getter(facets, F); + const gS = getter(facets, S); + const gQ = getter(facets, Q); for (const o of outputs) o.initialize(data); for (const facet of facets) { const binFacet = []; for (const o of outputs) o.scope("facet", facet); - for (const [f, I] of maybeGroup(facet, G)) { - for (const bin of hbin(I, X, Y, binWidth)) { + for (const [f, I] of maybeGroup(facet, eG)) { + for (const bin of hbin(I, gX, gY, binWidth)) { binFacet.push(++i); BX.push(bin.x); BY.push(bin.y); - if (Z) GZ.push(G === Z ? f : Z[bin[0]]); - if (F) GF.push(G === F ? f : F[bin[0]]); - if (S) GS.push(G === S ? f : S[bin[0]]); - if (Q) GQ.push(G === Q ? f : Q[bin[0]]); + if (Z) GZ.push(G === Z ? f : gZ(bin[0])); + if (F) GF.push(G === F ? f : gF(bin[0])); + if (S) GS.push(G === S ? f : gS(bin[0])); + if (Q) GQ.push(G === Q ? f : gQ(bin[0])); for (const o of outputs) o.reduce(bin); } } @@ -139,12 +149,12 @@ export function hexbin(outputs = {fill: "count"}, options = {}) { }); } -function hbin(I, X, Y, dx) { +function hbin(I, x, y, dx) { const dy = dx * (1.5 / sqrt3); const bins = new Map(); for (const i of I) { - let px = X[i], - py = Y[i]; + let px = x(i), + py = y(i); if (isNaN(px) || isNaN(py)) continue; let pj = Math.round((py = (py - oy) / dy)), pi = Math.round((px = (px - ox) / dx - (pj & 1) / 2)), diff --git a/src/transforms/map.js b/src/transforms/map.js index b62ea564c0..6016cebc68 100644 --- a/src/transforms/map.js +++ b/src/transforms/map.js @@ -1,6 +1,7 @@ import {count, group, rank} from "d3"; import {maybeZ, take, valueof, maybeInput, column} from "../options.js"; import {basic} from "./basic.js"; +import {facetReindex, getter, expander} from "../facet.js"; /** * ```js @@ -58,11 +59,13 @@ export function map(outputs = {}, options = {}) { }); return { ...basic(options, (data, facets) => { + // make facets exclusive + facets = facetReindex(facets, data.length); const Z = valueof(data, z); - const X = channels.map(({input}) => valueof(data, input)); - const MX = channels.map(({setOutput}) => setOutput(new Array(data.length))); + const X = channels.map(({input}) => expander(facets, valueof(data, input))); + const MX = channels.map(({setOutput}) => setOutput(new Array((facets.plan || data).length))); for (const facet of facets) { - for (const I of Z ? group(facet, (i) => Z[i]).values() : [facet]) { + for (const I of Z ? group(facet, getter(facets, Z)).values() : [facet]) { channels.forEach(({map}, i) => map.map(I, X[i], MX[i])); } } diff --git a/src/transforms/select.js b/src/transforms/select.js index 5f972851d3..7e6f5e6c6b 100644 --- a/src/transforms/select.js +++ b/src/transforms/select.js @@ -1,6 +1,7 @@ import {greatest, group, least} from "d3"; import {maybeZ, valueof} from "../options.js"; import {basic} from "./basic.js"; +import {expander, getter} from "../facet.js"; /** * Selects the points of each series selected by the *selector*, which can be @@ -143,12 +144,13 @@ function selectChannel(v, selector, options) { } const z = maybeZ(options); return basic(options, (data, facets) => { - const Z = valueof(data, z); - const V = valueof(data, v); + const gz = getter(facets, valueof(data, z)); + const V = expander(facets, valueof(data, v)); const selectFacets = []; + if ("plan" in facets) selectFacets.plan = facets.plan; for (const facet of facets) { const selectFacet = []; - for (const I of Z ? group(facet, (i) => Z[i]).values() : [facet]) { + for (const I of gz ? group(facet, gz).values() : [facet]) { for (const i of selector(I, V)) { selectFacet.push(i); } diff --git a/src/transforms/stack.js b/src/transforms/stack.js index 7018ff5ce9..b9f158a4e1 100644 --- a/src/transforms/stack.js +++ b/src/transforms/stack.js @@ -1,5 +1,6 @@ import {InternMap, cumsum, group, groupSort, greatest, max, min, rollup, sum} from "d3"; import {ascendingDefined} from "../defined.js"; +import {facetReindex, getter, expander} from "../facet.js"; import {field, column, maybeColumn, maybeZ, mid, range, valueof, maybeZero, one} from "../options.js"; import {basic} from "./basic.js"; @@ -146,24 +147,28 @@ function stack(x, y = one, ky, {offset, order, reverse}, options) { offset = maybeOffset(offset); order = maybeOrder(order, offset, ky); return [ - basic(options, (data, facets) => { + basic(options, function (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)); + + // make facets exclusive + facets = facetReindex(facets, data.length); + const Y1 = setY1(new Float64Array((facets.plan || data).length)); + const Y2 = setY2(new Float64Array((facets.plan || data).length)); + const facetstacks = []; for (const facet of facets) { - const stacks = X ? Array.from(group(facet, (i) => X[i]).values()) : [facet]; - if (O) applyOrder(stacks, O); + const stacks = X ? Array.from(group(facet, getter(facets, X)).values()) : [facet]; + const getY = getter(facets, Y); + if (O) applyOrder(stacks, getter(facets, O)); for (const stack of stacks) { let yn = 0, yp = 0; if (reverse) stack.reverse(); for (const i of stack) { - const y = Y[i]; + const y = getY(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 @@ -171,7 +176,7 @@ function stack(x, y = one, ky, {offset, order, reverse}, options) { } facetstacks.push(stacks); } - if (offset) offset(facetstacks, Y1, Y2, Z); + if (offset) offset(facetstacks, Y1, Y2, expander(facets, Z)); return {data, facets}; }), X, @@ -396,8 +401,8 @@ function orderZDomain(Z, domain) { return Z.map((z) => domain.get(z)); } -function applyOrder(stacks, O) { +function applyOrder(stacks, o) { for (const stack of stacks) { - stack.sort((i, j) => ascendingDefined(O[i], O[j])); + stack.sort((i, j) => ascendingDefined(o(i), o(j))); } } diff --git a/src/transforms/tree.js b/src/transforms/tree.js index 830d6a5c6c..da2e99ac51 100644 --- a/src/transforms/tree.js +++ b/src/transforms/tree.js @@ -2,6 +2,7 @@ import {stratify, tree} from "d3"; import {ascendingDefined} from "../defined.js"; import {column, identity, isObject, one, valueof} from "../options.js"; import {basic} from "./basic.js"; +import {getter} from "../facet.js"; /** * Based on the tree options described above, populates the **x** and **y** @@ -50,20 +51,20 @@ export function treeNode(options = {}) { y: Y, frameAnchor, ...basic(remainingOptions, (data, facets) => { - const P = normalize(valueof(data, path)); + const gP = getter(facets, normalize(valueof(data, path))); const X = setX([]); const Y = setY([]); let treeIndex = -1; const treeData = []; const treeFacets = []; - const rootof = stratify().path((i) => P[i]); + const rootof = stratify().path(gP); const layout = treeLayout(); if (layout.nodeSize) layout.nodeSize([1, 1]); if (layout.separation && treeSeparation !== undefined) layout.separation(treeSeparation ?? one); for (const o of outputs) o[output_values] = o[output_setValues]([]); for (const facet of facets) { const treeFacet = []; - const root = rootof(facet.filter((i) => P[i] != null)).each((node) => (node.data = data[node.data])); + const root = rootof(facet.filter((i) => gP(i) != null)).each((node) => (node.data = data[node.data])); if (treeSort != null) root.sort(treeSort); layout(root); for (const node of root.descendants()) { diff --git a/test/output/generativeRoses.svg b/test/output/generativeRoses.svg new file mode 100644 index 0000000000..e4a7205c79 --- /dev/null +++ b/test/output/generativeRoses.svg @@ -0,0 +1,296 @@ + + + + + + + + + First + + + + + Last + + + + + MaxX + + + + + MinX + + + + + MaxY + + + + + MinY + + + + + + + + + + First + + + + + Last + + + + + MaxX + + + + + MinX + + + + + MaxY + + + + + MinY + + + + + + + + + + First + + + + + Last + + + + + MaxX + + + + + MinX + + + + + MaxY + + + + + MinY + + + + + + + + + + First + + + + + Last + + + + + MaxX + + + + + MinX + + + + + MaxY + + + + + MinY + + + + + + + + + + First + + + + + Last + + + + + MaxX + + + + + MinX + + + + + MaxY + + + + + MinY + + + + + + + + + + First + + + + + Last + + + + + MaxX + + + + + MinX + + + + + MaxY + + + + + MinY + + + + + + + + + + First + + + + + Last + + + + + MaxX + + + + + MinX + + + + + MaxY + + + + + MinY + + + + + + + + + + First + + + + + Last + + + + + MaxX + + + + + MinX + + + + + MaxY + + + + + MinY + + + + \ No newline at end of file diff --git a/test/output/hexbinExclude.svg b/test/output/hexbinExclude.svg new file mode 100644 index 0000000000..ca4edb5e0f --- /dev/null +++ b/test/output/hexbinExclude.svg @@ -0,0 +1,401 @@ + + + + + 35 + + + 40 + + + 45 + + + 50 + + + 55 + ↑ culmen_length_mm + + + + Adelie + + + Chinstrap + + + Gentoo + species + + + + 14 + + + 16 + + + 18 + + + 20 + + + + + 14 + + + 16 + + + 18 + + + 20 + + + + + 14 + + + 16 + + + 18 + + + 20 + culmen_depth_mm → + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/musicRevenueBars.svg b/test/output/musicRevenueBars.svg new file mode 100644 index 0000000000..67d0421b08 --- /dev/null +++ b/test/output/musicRevenueBars.svg @@ -0,0 +1,9986 @@ + + + + + Disc + + + Download + + + Other + + + Streaming + + + Tape + + + Vinyl + group + + + + 1975 + + + 1980 + + + 1985 + + + 1990 + + + 1995 + + + 2000 + + + 2005 + + + 2010 + + + 2015 + + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + ↑ Annual revenue (billions, adj.) + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + CD Single + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + SACD + Disc (1) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Album + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Music Video + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Download Single + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Other Digital + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + Ringtones & Ringbacks + Download (1) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + DVD Audio + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Kiosk + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Music Video (Physical) + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + Synchronization + Other (1) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + Limited Tier Paid Subscription + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + On-Demand Streaming (Ad-Supported) + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Other Ad-Supported Streaming + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + Paid Subscription + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + SoundExchange Distributions + Streaming (1) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + 8 - Track + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Cassette Single + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + Other Tapes + Tape (1) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + LP/EP + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + Vinyl Single + Vinyl (1) + + + + + + + \ No newline at end of file diff --git a/test/output/musicRevenueBin.svg b/test/output/musicRevenueBin.svg new file mode 100644 index 0000000000..a55a967481 --- /dev/null +++ b/test/output/musicRevenueBin.svg @@ -0,0 +1,2318 @@ + + + + + Disc + + + Download + + + Other + + + Streaming + + + Tape + + + Vinyl + group + + + + 1970 + + + 1980 + + + 1990 + + + 2000 + + + 2010 + + + 2020 + + + + + + −100 + + + + −50 + + + + 0 + + + + 50 + + + + 100 + ↑ Annual revenue (billions, adj.) + + + + + −100 + + + + −50 + + + + 0 + + + + 50 + + + + 100 + + + + + + −100 + + + + −50 + + + + 0 + + + + 50 + + + + 100 + + + + + + −100 + + + + −50 + + + + 0 + + + + 50 + + + + 100 + + + + + + −100 + + + + −50 + + + + 0 + + + + 50 + + + + 100 + + + + + + −100 + + + + −50 + + + + 0 + + + + 50 + + + + 100 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CD + Disc (2) + + + CD + Disc (5) + + + CD + Disc (5) + + + CD + Disc (5) + + + CD + Disc (5) + + + CD + Disc (5) + + + CD + Disc (5) + + + CD + Disc (5) + + + CD + Disc (5) + + + CD + Disc (5) + + + CD Single + Disc (2) + + + CD Single + Disc (5) + + + CD Single + Disc (5) + + + CD Single + Disc (5) + + + CD Single + Disc (5) + + + CD Single + Disc (5) + + + CD Single + Disc (5) + + + CD Single + Disc (5) + + + CD Single + Disc (5) + + + CD Single + Disc (5) + + + SACD + Disc (2) + + + SACD + Disc (5) + + + SACD + Disc (5) + + + SACD + Disc (5) + + + SACD + Disc (5) + + + SACD + Disc (5) + + + SACD + Disc (5) + + + SACD + Disc (5) + + + SACD + Disc (5) + + + SACD + Disc (5) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Download Album + Download (2) + + + Download Album + Download (5) + + + Download Album + Download (5) + + + Download Album + Download (5) + + + Download Album + Download (5) + + + Download Album + Download (5) + + + Download Album + Download (5) + + + Download Album + Download (5) + + + Download Album + Download (5) + + + Download Album + Download (5) + + + Download Music Video + Download (2) + + + Download Music Video + Download (5) + + + Download Music Video + Download (5) + + + Download Music Video + Download (5) + + + Download Music Video + Download (5) + + + Download Music Video + Download (5) + + + Download Music Video + Download (5) + + + Download Music Video + Download (5) + + + Download Music Video + Download (5) + + + Download Music Video + Download (5) + + + Download Single + Download (2) + + + Download Single + Download (5) + + + Download Single + Download (5) + + + Download Single + Download (5) + + + Download Single + Download (5) + + + Download Single + Download (5) + + + Download Single + Download (5) + + + Download Single + Download (5) + + + Download Single + Download (5) + + + Download Single + Download (5) + + + Other Digital + Download (2) + + + Other Digital + Download (5) + + + Other Digital + Download (5) + + + Other Digital + Download (5) + + + Other Digital + Download (5) + + + Other Digital + Download (5) + + + Other Digital + Download (5) + + + Other Digital + Download (5) + + + Other Digital + Download (5) + + + Other Digital + Download (5) + + + Ringtones & Ringbacks + Download (2) + + + Ringtones & Ringbacks + Download (5) + + + Ringtones & Ringbacks + Download (5) + + + Ringtones & Ringbacks + Download (5) + + + Ringtones & Ringbacks + Download (5) + + + Ringtones & Ringbacks + Download (5) + + + Ringtones & Ringbacks + Download (5) + + + Ringtones & Ringbacks + Download (5) + + + Ringtones & Ringbacks + Download (5) + + + Ringtones & Ringbacks + Download (5) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DVD Audio + Other (2) + + + DVD Audio + Other (5) + + + DVD Audio + Other (5) + + + DVD Audio + Other (5) + + + DVD Audio + Other (5) + + + DVD Audio + Other (5) + + + DVD Audio + Other (5) + + + DVD Audio + Other (5) + + + DVD Audio + Other (5) + + + DVD Audio + Other (5) + + + Kiosk + Other (2) + + + Kiosk + Other (5) + + + Kiosk + Other (5) + + + Kiosk + Other (5) + + + Kiosk + Other (5) + + + Kiosk + Other (5) + + + Kiosk + Other (5) + + + Kiosk + Other (5) + + + Kiosk + Other (5) + + + Kiosk + Other (5) + + + Music Video (Physical) + Other (2) + + + Music Video (Physical) + Other (5) + + + Music Video (Physical) + Other (5) + + + Music Video (Physical) + Other (5) + + + Music Video (Physical) + Other (5) + + + Music Video (Physical) + Other (5) + + + Music Video (Physical) + Other (5) + + + Music Video (Physical) + Other (5) + + + Music Video (Physical) + Other (5) + + + Music Video (Physical) + Other (5) + + + Synchronization + Other (2) + + + Synchronization + Other (5) + + + Synchronization + Other (5) + + + Synchronization + Other (5) + + + Synchronization + Other (5) + + + Synchronization + Other (5) + + + Synchronization + Other (5) + + + Synchronization + Other (5) + + + Synchronization + Other (5) + + + Synchronization + Other (5) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Limited Tier Paid Subscription + Streaming (2) + + + Limited Tier Paid Subscription + Streaming (5) + + + Limited Tier Paid Subscription + Streaming (5) + + + Limited Tier Paid Subscription + Streaming (5) + + + Limited Tier Paid Subscription + Streaming (5) + + + Limited Tier Paid Subscription + Streaming (5) + + + Limited Tier Paid Subscription + Streaming (5) + + + Limited Tier Paid Subscription + Streaming (5) + + + Limited Tier Paid Subscription + Streaming (5) + + + Limited Tier Paid Subscription + Streaming (5) + + + On-Demand Streaming (Ad-Supported) + Streaming (2) + + + On-Demand Streaming (Ad-Supported) + Streaming (5) + + + On-Demand Streaming (Ad-Supported) + Streaming (5) + + + On-Demand Streaming (Ad-Supported) + Streaming (5) + + + On-Demand Streaming (Ad-Supported) + Streaming (5) + + + On-Demand Streaming (Ad-Supported) + Streaming (5) + + + On-Demand Streaming (Ad-Supported) + Streaming (5) + + + On-Demand Streaming (Ad-Supported) + Streaming (5) + + + On-Demand Streaming (Ad-Supported) + Streaming (5) + + + On-Demand Streaming (Ad-Supported) + Streaming (5) + + + Other Ad-Supported Streaming + Streaming (2) + + + Other Ad-Supported Streaming + Streaming (5) + + + Other Ad-Supported Streaming + Streaming (5) + + + Other Ad-Supported Streaming + Streaming (5) + + + Other Ad-Supported Streaming + Streaming (5) + + + Other Ad-Supported Streaming + Streaming (5) + + + Other Ad-Supported Streaming + Streaming (5) + + + Other Ad-Supported Streaming + Streaming (5) + + + Other Ad-Supported Streaming + Streaming (5) + + + Other Ad-Supported Streaming + Streaming (5) + + + Paid Subscription + Streaming (2) + + + Paid Subscription + Streaming (5) + + + Paid Subscription + Streaming (5) + + + Paid Subscription + Streaming (5) + + + Paid Subscription + Streaming (5) + + + Paid Subscription + Streaming (5) + + + Paid Subscription + Streaming (5) + + + Paid Subscription + Streaming (5) + + + Paid Subscription + Streaming (5) + + + Paid Subscription + Streaming (5) + + + SoundExchange Distributions + Streaming (2) + + + SoundExchange Distributions + Streaming (5) + + + SoundExchange Distributions + Streaming (5) + + + SoundExchange Distributions + Streaming (5) + + + SoundExchange Distributions + Streaming (5) + + + SoundExchange Distributions + Streaming (5) + + + SoundExchange Distributions + Streaming (5) + + + SoundExchange Distributions + Streaming (5) + + + SoundExchange Distributions + Streaming (5) + + + SoundExchange Distributions + Streaming (5) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Track + Tape (2) + + + 8 - Track + Tape (5) + + + 8 - Track + Tape (5) + + + 8 - Track + Tape (5) + + + 8 - Track + Tape (5) + + + 8 - Track + Tape (5) + + + 8 - Track + Tape (5) + + + 8 - Track + Tape (5) + + + 8 - Track + Tape (5) + + + 8 - Track + Tape (5) + + + Cassette + Tape (2) + + + Cassette + Tape (5) + + + Cassette + Tape (5) + + + Cassette + Tape (5) + + + Cassette + Tape (5) + + + Cassette + Tape (5) + + + Cassette + Tape (5) + + + Cassette + Tape (5) + + + Cassette + Tape (5) + + + Cassette + Tape (5) + + + Cassette Single + Tape (2) + + + Cassette Single + Tape (5) + + + Cassette Single + Tape (5) + + + Cassette Single + Tape (5) + + + Cassette Single + Tape (5) + + + Cassette Single + Tape (5) + + + Cassette Single + Tape (5) + + + Cassette Single + Tape (5) + + + Cassette Single + Tape (5) + + + Cassette Single + Tape (5) + + + Other Tapes + Tape (2) + + + Other Tapes + Tape (5) + + + Other Tapes + Tape (5) + + + Other Tapes + Tape (5) + + + Other Tapes + Tape (5) + + + Other Tapes + Tape (5) + + + Other Tapes + Tape (5) + + + Other Tapes + Tape (5) + + + Other Tapes + Tape (5) + + + Other Tapes + Tape (5) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LP/EP + Vinyl (2) + + + LP/EP + Vinyl (5) + + + LP/EP + Vinyl (5) + + + LP/EP + Vinyl (5) + + + LP/EP + Vinyl (5) + + + LP/EP + Vinyl (5) + + + LP/EP + Vinyl (5) + + + LP/EP + Vinyl (5) + + + LP/EP + Vinyl (5) + + + LP/EP + Vinyl (5) + + + Vinyl Single + Vinyl (2) + + + Vinyl Single + Vinyl (5) + + + Vinyl Single + Vinyl (5) + + + Vinyl Single + Vinyl (5) + + + Vinyl Single + Vinyl (5) + + + Vinyl Single + Vinyl (5) + + + Vinyl Single + Vinyl (5) + + + Vinyl Single + Vinyl (5) + + + Vinyl Single + Vinyl (5) + + + Vinyl Single + Vinyl (5) + + + + + + + \ No newline at end of file diff --git a/test/output/musicRevenueGroup.svg b/test/output/musicRevenueGroup.svg new file mode 100644 index 0000000000..6f2f3eadba --- /dev/null +++ b/test/output/musicRevenueGroup.svg @@ -0,0 +1,484 @@ + + + + + Disc + + + Download + + + Other + + + Streaming + + + Tape + + + Vinyl + group + + + + 1980 + + + 1990 + + + 2000 + + + 2010 + + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + ↑ Annual revenue (billions, adj.) + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + + + + + + −20 + + + + −10 + + + + 0 + + + + 10 + + + + 20 + + + + + + CD + Disc + + + CD Single + Disc + + + SACD + Disc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Download Album + Download + + + Download Music Video + Download + + + Download Single + Download + + + Other Digital + Download + + + Ringtones & Ringbacks + Download + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DVD Audio + Other + + + Kiosk + Other + + + Music Video (Physical) + Other + + + Synchronization + Other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Limited Tier Paid Subscription + Streaming + + + On-Demand Streaming (Ad-Supported) + Streaming + + + Other Ad-Supported Streaming + Streaming + + + Paid Subscription + Streaming + + + SoundExchange Distributions + Streaming + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Track + Tape + + + Cassette + Tape + + + Cassette Single + Tape + + + Other Tapes + Tape + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LP/EP + Vinyl + + + Vinyl Single + Vinyl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/musicRevenueWiggle.svg b/test/output/musicRevenueWiggle.svg new file mode 100644 index 0000000000..f446964356 --- /dev/null +++ b/test/output/musicRevenueWiggle.svg @@ -0,0 +1,412 @@ + + + + + Disc + + + Download + + + Other + + + Streaming + + + Tape + + + Vinyl + group + + + + 1980 + + + 1990 + + + 2000 + + + 2010 + + + + + + 0 + + + + 10 + ↑ Annual revenue (billions, adj.) + + + + + 0 + + + + 10 + + + + + + 0 + + + + 10 + + + + + + 0 + + + + 10 + + + + + + 0 + + + + 10 + + + + + + 0 + + + + 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + CD + Disc + + + CD Single + Disc + + + SACD + Disc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Download Album + Download + + + Download Music Video + Download + + + Download Single + Download + + + Other Digital + Download + + + Ringtones & Ringbacks + Download + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DVD Audio + Other + + + Kiosk + Other + + + Music Video (Physical) + Other + + + Synchronization + Other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Limited Tier Paid Subscription + Streaming + + + On-Demand Streaming (Ad-Supported) + Streaming + + + Other Ad-Supported Streaming + Streaming + + + Paid Subscription + Streaming + + + SoundExchange Distributions + Streaming + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Track + Tape + + + Cassette + Tape + + + Cassette Single + Tape + + + Other Tapes + Tape + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LP/EP + Vinyl + + + Vinyl Single + Vinyl + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/penguinCumsumExclude.svg b/test/output/penguinCumsumExclude.svg new file mode 100644 index 0000000000..3e0fb57005 --- /dev/null +++ b/test/output/penguinCumsumExclude.svg @@ -0,0 +1,806 @@ + + + + + −300 + + + −200 + + + −100 + + + 0 + + + 100 + + + 200 + + + + + Biscoe + + + Dream + + + Torgersen + island + + + + 3,000 + + + 4,000 + + + 5,000 + + + 6,000 + + + + + 3,000 + + + 4,000 + + + 5,000 + + + 6,000 + + + + + 3,000 + + + 4,000 + + + 5,000 + + + 6,000 + body_mass_g → + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/penguinDodgeReindexed.svg b/test/output/penguinDodgeReindexed.svg new file mode 100644 index 0000000000..c6a90c6451 --- /dev/null +++ b/test/output/penguinDodgeReindexed.svg @@ -0,0 +1,746 @@ + + + + + Biscoe + + + Dream + + + Torgersen + island + + + + 3,000 + + + 3,500 + + + 4,000 + + + 4,500 + + + 5,000 + + + 5,500 + + + 6,000 + body_mass_g → + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/stackExclude.svg b/test/output/stackExclude.svg new file mode 100644 index 0000000000..1631981e99 --- /dev/null +++ b/test/output/stackExclude.svg @@ -0,0 +1,68 @@ + + + + + 0 + + + 1 + + + 2 + + + 3 + + + 4 + + + 5 + + + + + a + + + b + + + c + + + + + + + + 12 + + + + + + + 02 + + + + + + + 01 + + \ No newline at end of file diff --git a/test/plots/generative-roses.js b/test/plots/generative-roses.js new file mode 100644 index 0000000000..cb9d2df848 --- /dev/null +++ b/test/plots/generative-roses.js @@ -0,0 +1,40 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; + +// Generate roses from a cumulative sum of vectors with various angles. The +// twist is that each facet selects a subset of these angles to ignore (with +// facet: "exclude"). +export default async function () { + const data = d3.range(0, 48, 0.7); + const mapped = Plot.mapY( + "cumsum", + Plot.mapX("cumsum", { + facet: "exclude", + x: Math.sin, + y: Math.cos + }) + ); + return Plot.plot({ + facet: { + data, + x: (d, i) => (i % 8) % 3, + y: (d, i) => Math.floor((i % 8) / 3), + marginRight: 80 + }, + axis: null, + marks: [ + Plot.line(data, {...mapped, curve: "natural"}), + ["First", "Last", "MaxX", "MinX", "MaxY", "MinY"].map((p) => + Plot.dot( + data, + Plot[`select${p}`]({ + ...mapped, + fill: () => p, + title: () => p, + r: 6 + }) + ) + ) + ] + }); +} diff --git a/test/plots/hexbin-exclude.js b/test/plots/hexbin-exclude.js new file mode 100644 index 0000000000..c862a43cf0 --- /dev/null +++ b/test/plots/hexbin-exclude.js @@ -0,0 +1,45 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; + +export default async function () { + const penguins = await d3.csv("data/penguins.csv", d3.autoType); + const noise = d3.randomNormal.source(d3.randomLcg(42))(0, 0.1); + return Plot.plot({ + width: 960, + height: 320, + inset: 14, + facet: { + data: penguins, + x: "species", + marginRight: 80 + }, + marks: [ + Plot.frame(), + Plot.dot( + penguins, + Plot.hexbin( + {fillOpacity: "count"}, + Plot.map( + { + x: (X) => X.map((d) => d + noise()), + y: (Y) => Y.map((d) => d + noise()) + }, + { + x: "culmen_depth_mm", + y: "culmen_length_mm", + fill: "species", + facet: "exclude" + } + ) + ) + ), + Plot.dot( + penguins, + Plot.hexbin( + {fillOpacity: "count"}, + {x: "culmen_depth_mm", y: "culmen_length_mm", fill: "species", stroke: "species"} + ) + ) + ] + }); +} diff --git a/test/plots/index.js b/test/plots/index.js index 9a94cecfee..dbd041ec4c 100644 --- a/test/plots/index.js +++ b/test/plots/index.js @@ -75,6 +75,7 @@ export {default as footballCoverage} from "./football-coverage.js"; export {default as frameCorners} from "./frame-corners.js"; export {default as fruitSales} from "./fruit-sales.js"; export {default as fruitSalesDate} from "./fruit-sales-date.js"; +export {default as generativeRoses} from "./generative-roses.js"; export {default as gistempAnomaly} from "./gistemp-anomaly.js"; export {default as gistempAnomalyMoving} from "./gistemp-anomaly-moving.js"; export {default as gistempAnomalyTransform} from "./gistemp-anomaly-transform.js"; @@ -85,6 +86,7 @@ export {default as gridChoroplethDx} from "./grid-choropleth-dx.js"; export {default as groupedRects} from "./grouped-rects.js"; export {default as hadcrutWarmingStripes} from "./hadcrut-warming-stripes.js"; export {default as hexbin} from "./hexbin.js"; +export {default as hexbinExclude} from "./hexbin-exclude.js"; export {default as hexbinOranges} from "./hexbin-oranges.js"; export {default as hexbinR} from "./hexbin-r.js"; export {default as hexbinSymbol} from "./hexbin-symbol.js"; @@ -134,6 +136,10 @@ export {default as mobyDickLetterRelativeFrequency} from "./moby-dick-letter-rel export {default as morleyBoxplot} from "./morley-boxplot.js"; export {default as moviesProfitByGenre} from "./movies-profit-by-genre.js"; export {default as musicRevenue} from "./music-revenue.js"; +export {default as musicRevenueBars} from "./music-revenue-bars.js"; +export {default as musicRevenueBin} from "./music-revenue-bin.js"; +export {default as musicRevenueGroup} from "./music-revenue-group.js"; +export {default as musicRevenueWiggle} from "./music-revenue-wiggle.js"; export {default as ordinalBar} from "./ordinal-bar.js"; export {default as penguinAnnotated} from "./penguin-annotated.js"; export {default as penguinCulmen} from "./penguin-culmen.js"; @@ -142,12 +148,13 @@ export {default as penguinCulmenDelaunay} from "./penguin-culmen-delaunay.js"; export {default as penguinCulmenDelaunayMesh} from "./penguin-culmen-delaunay-mesh.js"; export {default as penguinCulmenDelaunaySpecies} from "./penguin-culmen-delaunay-species.js"; export {default as penguinCulmenVoronoi} from "./penguin-culmen-voronoi.js"; -export {default as penguinVoronoi1D} from "./penguin-voronoi-1d.js"; +export {default as penguinCumsumExclude} from "./penguin-cumsum-exclude.js"; export {default as penguinDensity} from "./penguin-density.js"; export {default as penguinDensityFill} from "./penguin-density-fill.js"; export {default as penguinDensityZ} from "./penguin-density-z.js"; export {default as penguinDodge} from "./penguin-dodge.js"; export {default as penguinDodgeHexbin} from "./penguin-dodge-hexbin.js"; +export {default as penguinDodgeReindexed} from "./penguin-dodge-reindexed.js"; export {default as penguinDodgeVoronoi} from "./penguin-dodge-voronoi.js"; export {default as penguinFacetDodge} from "./penguin-facet-dodge.js"; export {default as penguinFacetDodgeIdentity} from "./penguin-facet-dodge-identity.js"; @@ -167,6 +174,7 @@ export {default as penguinSpeciesGroup} from "./penguin-species-group.js"; export {default as penguinSpeciesIsland} from "./penguin-species-island.js"; export {default as penguinSpeciesIslandRelative} from "./penguin-species-island-relative.js"; export {default as penguinSpeciesIslandSex} from "./penguin-species-island-sex.js"; +export {default as penguinVoronoi1D} from "./penguin-voronoi-1d.js"; export {default as polylinear} from "./polylinear.js"; export {default as randomBins} from "./random-bins.js"; export {default as randomBinsXY} from "./random-bins-xy.js"; @@ -207,6 +215,7 @@ export {default as singleValueBar} from "./single-value-bar.js"; export {default as singleValueBin} from "./single-value-bin.js"; export {default as softwareVersions} from "./software-versions.js"; export {default as sparseCell} from "./sparse-cell.js"; +export {default as stackExclude} from "./stack-exclude.js"; export {default as stackedBar} from "./stacked-bar.js"; export {default as stackedRect} from "./stacked-rect.js"; export {default as stargazers} from "./stargazers.js"; diff --git a/test/plots/music-revenue-bars.js b/test/plots/music-revenue-bars.js new file mode 100644 index 0000000000..e29eda1572 --- /dev/null +++ b/test/plots/music-revenue-bars.js @@ -0,0 +1,49 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; + +export default async function () { + const data = await d3.csv("data/riaa-us-revenue.csv", d3.autoType); + const stack = {x: (d) => d["year"].getFullYear(), y: "revenue", z: "format", order: "value", reverse: true}; + return Plot.plot({ + marginRight: 90, + marginBottom: 35, + facet: {data, y: "group", marginRight: 90}, + x: {ticks: d3.range(1975, 2020, 5), tickFormat: ""}, + y: { + grid: true, + label: "↑ Annual revenue (billions, adj.)", + transform: (d) => d / 1000, + nice: true + }, + marks: [ + Plot.frame(), + Plot.barY( + data, + Plot.groupX( + {y: "sum"}, + Plot.windowY({ + ...stack, + k: 3, + y: (d) => -d.revenue, + fill: "group", + facet: "exclude", + order: "sum" + }) + ) + ), + Plot.barY( + data, + Plot.groupX( + {y: "sum"}, + Plot.windowY({ + ...stack, + k: 3, + fill: "group", + title: (d) => `${d.format}\n${d.group}` + }) + ) + ), + Plot.ruleY([0]) + ] + }); +} diff --git a/test/plots/music-revenue-bin.js b/test/plots/music-revenue-bin.js new file mode 100644 index 0000000000..adfa085c44 --- /dev/null +++ b/test/plots/music-revenue-bin.js @@ -0,0 +1,48 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; + +export default async function () { + const data = await d3.csv("data/riaa-us-revenue.csv", d3.autoType); + const stack = {x: "year", y: "revenue", z: "format", order: "value", reverse: true}; + return Plot.plot({ + marginRight: 90, + facet: {data, y: "group", marginRight: 90}, + y: { + grid: true, + label: "↑ Annual revenue (billions, adj.)", + transform: (d) => d / 1000, + nice: true + }, + marks: [ + Plot.frame(), + Plot.rectY( + data, + Plot.binX( + {y: "sum"}, + Plot.windowY({ + ...stack, + k: 7, + interval: d3.utcYear.every(5), + y: (d) => -d.revenue, + fill: "#eee", + facet: "exclude" + }) + ) + ), + Plot.rectY( + data, + Plot.binX( + {y: "sum"}, + Plot.windowY({ + ...stack, + k: 7, + interval: d3.utcYear.every(5), + fill: "group", + title: (d) => `${d.format}\n${d.group}` + }) + ) + ), + Plot.ruleY([0]) + ] + }); +} diff --git a/test/plots/music-revenue-group.js b/test/plots/music-revenue-group.js new file mode 100644 index 0000000000..e5a3662eda --- /dev/null +++ b/test/plots/music-revenue-group.js @@ -0,0 +1,32 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; + +export default async function () { + const data = await d3.csv("data/riaa-us-revenue.csv", d3.autoType); + const stack = {x: "year", y: "revenue", z: "format", order: "appearance", reverse: true}; + return Plot.plot({ + marginRight: 90, + facet: {data, y: "group", marginRight: 90}, + y: { + grid: true, + label: "↑ Annual revenue (billions, adj.)", + transform: (d) => d / 1000 + }, + marks: [ + Plot.areaY(data, Plot.stackY({...stack, fill: "group", title: (d) => `${d.format}\n${d.group}`})), + Plot.areaY( + data, + Plot.stackY({ + ...stack, + y: (d) => -1 - d.revenue, + fill: "#eee", + stroke: "#fff", + facet: "exclude" + }) + ), + Plot.lineY(data, Plot.stackY2({...stack, stroke: "white", strokeWidth: 1})), + Plot.ruleY([0]), + Plot.frame() + ] + }); +} diff --git a/test/plots/music-revenue-wiggle.js b/test/plots/music-revenue-wiggle.js new file mode 100644 index 0000000000..0bee1b535c --- /dev/null +++ b/test/plots/music-revenue-wiggle.js @@ -0,0 +1,40 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; + +export default async function () { + const data = await d3.csv("data/riaa-us-revenue.csv", d3.autoType); + const stack = { + x: "year", + y: "revenue", + z: "format", + // order and offset are used to test that these options follow facet reindexation + order: ["Cassette", "Paid Subscription"], + offset: "wiggle", + reverse: true + }; + return Plot.plot({ + marginRight: 90, + facet: {data, y: "group", marginRight: 90}, + y: { + grid: true, + label: "↑ Annual revenue (billions, adj.)", + transform: (d) => d / 1000 + }, + marks: [ + Plot.areaY( + data, + Plot.stackY({ + ...stack, + y: (d) => -1 - d.revenue, + fill: "#eee", + stroke: "#fff", + facet: "exclude" + }) + ), + Plot.areaY(data, Plot.stackY({...stack, fill: "group", title: (d) => `${d.format}\n${d.group}`})), + Plot.lineY(data, Plot.stackY2({...stack, stroke: "white", strokeWidth: 1})), + Plot.ruleY([0]), + Plot.frame() + ] + }); +} diff --git a/test/plots/penguin-cumsum-exclude.js b/test/plots/penguin-cumsum-exclude.js new file mode 100644 index 0000000000..d3f665a6be --- /dev/null +++ b/test/plots/penguin-cumsum-exclude.js @@ -0,0 +1,37 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; + +export default async function () { + const penguins = await d3.csv("data/penguins.csv", d3.autoType); + return Plot.plot({ + facet: {data: penguins, x: "island"}, + width: 860, + height: 300, + y: {nice: true}, + marks: [ + Plot.frame(), + Plot.ruleY([0]), + Plot.dot( + penguins, + Plot.mapY( + "cumsum", + Plot.sort("body_mass_g", {x: "body_mass_g", y: -1, fill: "island", facet: "exclude", z: null, r: 1}) + ) + ), + Plot.lineY( + penguins, + Plot.mapY( + "cumsum", + Plot.sort("body_mass_g", { + x: "body_mass_g", + y: 1, + strokeWidth: 2, + stroke: "island", + facet: "include", + z: null + }) + ) + ) + ] + }); +} diff --git a/test/plots/penguin-dodge-reindexed.js b/test/plots/penguin-dodge-reindexed.js new file mode 100644 index 0000000000..e4d7b76480 --- /dev/null +++ b/test/plots/penguin-dodge-reindexed.js @@ -0,0 +1,11 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; + +export default async function () { + const penguins = await d3.csv("data/penguins.csv", d3.autoType); + return Plot.plot({ + facet: {data: penguins, y: "island"}, + height: 400, + marks: [Plot.dot(penguins, Plot.dodgeY({x: "body_mass_g", facet: "exclude", fill: "island"}))] + }); +} diff --git a/test/plots/stack-exclude.js b/test/plots/stack-exclude.js new file mode 100644 index 0000000000..e2f2afdc81 --- /dev/null +++ b/test/plots/stack-exclude.js @@ -0,0 +1,26 @@ +import * as Plot from "@observablehq/plot"; + +export default async function () { + const data = Float64Array.of(1, 2, 3); + const facets = ["a", "b", "c"]; + return Plot.plot({ + height: 180, + facet: {data, x: facets}, + marks: [ + Plot.barY(data, { + stroke: (d) => d, // channel as accessor + fill: data, // channel as array + fillOpacity: 0.5, + facet: "exclude" + }), + Plot.textY( + data, + Plot.stackY({ + y: data, + text: (d, i) => i, // the original index + facet: "exclude" + }) + ) + ] + }); +}