Skip to content

Shorthand syntax for d3.piecewise #1636

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Fil opened this issue May 25, 2023 · 2 comments · Fixed by #1715
Closed

Shorthand syntax for d3.piecewise #1636

Fil opened this issue May 25, 2023 · 2 comments · Fixed by #1715
Assignees
Labels
enhancement New feature or request

Comments

@Fil
Copy link
Contributor

Fil commented May 25, 2023

as discussed in #1633 it would be nice to provide a shorthand syntax for piecewise/polylinear scales with a simple domain [min, max].

Instead of

  type: "log",
   domain: [1, 5, 21, 100],
   range: ["#d3e7fa", "#5784c5", "#fc004b", "#ffec44"],

or

    type: "log",
    domain: [1, 100],
    interpolate: d3.piecewise(["#d3e7fa", "#5784c5", "#fc004b", "#ffec44"]),

you would then just say

    type: "log",
    domain: [1, 100],
    range: ["#d3e7fa", "#5784c5", "#fc004b", "#ffec44"],
    something: something

something could be interpolate: "piecewise", maybe?

@Fil Fil self-assigned this May 25, 2023
@Fil Fil added the enhancement New feature or request label May 25, 2023
@mbostock
Copy link
Member

mbostock commented May 25, 2023

From that discussion:

What if the domain contains three elements [d1, d2, d3] and the range contains four elements [r1, r2, r3, r4]? Do we ignore the extra range element r4 in that case? Or do we ignore the domain element d3 and partition [d1, d3] uniformly into three intervals [r1, r2], [r2, r3], and [r3, r4]? Do we partition [d1, d2] using [r1, r2, r3], and partition [d2, d3] using [r3, r4]?

I realized we already have the answer, though, because we already support this by way of the interpolate option using d3.piecewise:

Screenshot 2023-05-25 at 9 51 49 AM
Plot.plot({
  color: {
    legend: true,
    type: "linear",
    domain: [0, 10, 40],
    interpolate: d3.piecewise(["red", "yellow", "green", "blue", "violet"])
  },
  marks: [
    Plot.cellX(d3.ticks(0, 40, 40), {x: Plot.identity, fill: Plot.identity})
  ]
})

What this does is construct a piecewise interpolator through the given colors, and then partitions that interpolator in equal parts, assigning each part to a sequential interval from the domain. So, [d1, d2] gets the first half of the interpolator, and [d2, d3] gets the second half of the interpolator. If the number of elements in the domain and the piecewise interpolator (range) align, then d2 is mapped to r2, d3 is mapped to r3, etc. so it all works out.

I think we don’t want to use the interpolate option for this because we may want to set an interpolator (a color space) such as lab or hcl in addition to indicating that you want to fit the range to the domain rather than ignoring the extra elements. E.g.,

Screenshot 2023-05-25 at 9 58 05 AM
Plot.plot({
  color: {
    legend: true,
    type: "linear",
    domain: [0, 10, 40],
    interpolate: d3.piecewise(d3.interpolateHcl, ["red", "yellow", "green", "blue", "violet"])
  },
  marks: [
    Plot.cellX(d3.ticks(0, 40, 40), {x: Plot.identity, fill: Plot.identity})
  ]
})

Maybe fit: true? 🤔

Plot.plot({
  color: {
    legend: true,
    type: "linear",
    domain: [0, 10, 40],
    range: ["red", "yellow", "green", "blue", "violet"],
    interpolate: "hcl",
    fit: true
  },
  marks: [
    Plot.cellX(d3.ticks(0, 40, 40), {x: Plot.identity, fill: Plot.identity})
  ]
})

@mbostock mbostock changed the title provide shorthand syntax for d3.piecewise Shorthand syntax for d3.piecewise May 25, 2023
@mbostock
Copy link
Member

mbostock commented May 27, 2023

I feel like maybe I’ve changed my mind. Given that there is a clear way to handle domains and ranges of different lengths, maybe we should just allow it instead of dropping the extra elements and warning. It does change the behavior of existing plots, but respecting the extra elements is probably what the author intended; otherwise, why specify them? And seeing the change in behavior is more obvious than a warning. So… yeah. Maybe we just always do this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants