jsvine/spectra

domain doesn't seem to work properly when the scale list contains more than 2 elements

Closed this issue · 5 comments

This is best demonstrated with an example:

>>> import spectra
>>> color_scale = spectra.scale(['yellow', 'red', 'black'])
>>> r = color_scale.range(5)
>>> print([ c.hexcode for c in r ])
['#ffff00', '#ff8000', '#ff0000', '#800000', '#000000']

Everything works as expected. Now, if I do the same thing and try to change the domain, it doesn't work properly:

>>> color_scale = spectra.scale(['yellow', 'red', 'black']).domain([0, 100])
>>> r = color_scale.range(5)
>>> print([ c.hexcode for c in r ])
['#ffff00', '#ffbf00', '#ff8000', '#ff4000', '#ff0000']

Note how it provides five colors starting at yellow and ending at red instead of black.

Ah! After digging around in the code, I figured out what I was doing wrong. Here's how I get it to work:

>>> color_scale = spectra.scale(['yellow', 'red', 'black']).domain([0, 50, 100])
>>> r = color_scale.range(5)
>>> print([ c.hexcode for c in r ])
['#ffff00', '#ff8000', '#ff0000', '#800000', '#000000']

Basically, I didn't realize that I needed to specify each segment of the domain. This of course makes sense in retrospect, but it's not clear from the docs. I think that two things should probably happen to make this more obvious for others in the future:

  1. The documentation should be updated to show an example with more than 2 colors (feel free to use this example).
  2. An error should be raised if len(domain) != len(colors).

Thanks, Geoffrey. You're absolutely right: This fact isn't sufficiently
covered in the docs. I'll aim to clarify this and add that error in the
next day or two. Much appreciation for the opening the issue, and for the
crystal-clear example.

On Tue, Jul 14, 2015 at 4:02 PM, Geoffrey Fairchild <
notifications@github.com> wrote:

Ah! After digging around in the code, I figured out what I was doing
wrong. Here's how I get it to work:

color_scale = spectra.scale(['yellow', 'red', 'black']).domain([0, 50, 100])
r = color_scale.range(5)
print([ c.hexcode for c in r ])
['#ffff00', '#ff8000', '#ff0000', '#800000', '#000000']

Basically, I didn't realize that I needed to specify each segment of the
domain. This of course makes sense in retrospect, but it's not clear from
the docs. I think that two things should probably happen to make this more
obvious for others in the future:

  1. The documentation should be updated to show an example with more
    than 2 colors (feel free to use this example).
  2. An error should be raised if len(domain) != len(colors).


Reply to this email directly or view it on GitHub
#4 (comment).

Glad I could help!

Thanks again, Geoff. Fixed/updated in dcb890a, and now published as part of v0.0.7.

emlyn commented

Would it make sense to allow domain to take either one value per value in the scale (as at present), or just two values (for minimum and maximum, with any extra values spread evenly between)? This is effectively what happens already for the default domain of [0, 1].
So, e.g. color_scale = spectra.scale(['yellow', 'red', 'black']).domain([0, 100]) would be equivalent to color_scale = spectra.scale(['yellow', 'red', 'black']).domain([0, 50, 100]).