chroma.js icon indicating copy to clipboard operation
chroma.js copied to clipboard

add scale.invert

Open johnfrancisgit opened this issue 8 years ago • 8 comments

The option to get the domain value for a given color seems to be missing.

johnfrancisgit avatar Jul 05 '16 10:07 johnfrancisgit

This is exactly what I'm looking for. Has anyone done any work on this or looked into the code to see where I can pull this out of? Should be pretty easy...

ahalota avatar Nov 10 '16 00:11 ahalota

so this would be something like

scale = chroma.scale(['blue', 'red']);
scale(0.5); // #800080
scale.invert("#800080"); // 0.5

gka avatar Apr 06 '17 15:04 gka

I am not sure "invert" is a name people would intuitively associate with this operation. Perhaps something like scale.lookup, scale.find or scale.locate would be clearer? Just my 2 cents.

waldyrious avatar Apr 07 '17 00:04 waldyrious

well, invert is the terminology used in D3.js so I thought it would be nice to use a consistent wording

https://github.com/d3/d3-scale#continuous_invert

gka avatar Apr 07 '17 00:04 gka

Ah, I see. In that case, I suppose using alternative terms in the documentation would be enough to improve the discoverability of this feature.

waldyrious avatar Apr 07 '17 09:04 waldyrious

actually, I feel this is not as easy to implement as I thought. there are some cases where this would not be possible, like if you pass a color that's not part of the scale, or maybe it's part of the scale more than once.

in short, there is no guarantee a color scale function is continuous and thereby it might not be differentiable using linear approximation.

I could easily construct a scale that would be impossible to find the invert using approximation:

chroma.scale(['red','red','white','red','red']).domain([0,0.6,0.61,0.62,1])

starting from a random point, or the center, it would be almost impossible to find out in which direction to look to find the position of white.

of course, it's easier to do in a simple two color gradient, but I am leaning toward not implementing it unless it produces meaningful results for all use cases.

gka avatar May 29 '17 18:05 gka

I am looking for doing this to ensure readability. any concise way to do it with chroma.js?

malarinv avatar Jun 29 '18 19:06 malarinv

This issue looks like solving y = f(x) for x given y. It only has unique solution for monotonic strictly increasing (or strictly decreasing) continuous functions.

Few cases to consider with application to this issue:

Case 1: When using scale.colors or scale.classes instead of continuous scale, a single color will represent an interval of input values. Can think of it as a ladder function. Reverse task can be defined in two incompatible ways:

  • any color from the list can be associated with an interval of domain values, any color not from the list can't be associated with any value, even if it is a combination of adjacent colors;
  • domain value(s) searched for a color as if it were a continuous scale.

Case 2: For a weakly increasing/decreasing function, one value of y may be associated with a single value or an interval of values on x.

Case 3: Non-monotonic function can have multiple values or value intervals on x for a single y.

Assuming there is an efficient way to solve for x (find all values or value intervals) - it might make sense to return a list of all possible solutions and let the consumer to deal with ambiguities, if there are any.

Another question is how to deal with colors that are far from the scale. The color scale is a curve in 3D space with some quantization effects.

  • Strictly sticking to a limited set of colors might make it inconvenient depending on how colors are drawn (see case 1);
  • Being promiscuous about input color will make it to produce something even for nonsense input. (Imagine a red-green scale and try to find a domain value of black color).

Is there a clear notion of sigma to draw a line between these extremes?

KillyMXI avatar May 15 '19 16:05 KillyMXI