jsvine / spectra

Easy color scales and color conversion for Python.
http://nbviewer.ipython.org/github/jsvine/spectra/blob/master/docs/walkthrough.ipynb
MIT License
257 stars 12 forks source link

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

Closed gfairchild closed 9 years ago

gfairchild commented 9 years ago

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.

gfairchild commented 9 years ago

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).
jsvine commented 9 years ago

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 https://github.com/jsvine/spectra/issues/4#issuecomment-121365299.

gfairchild commented 9 years ago

Glad I could help!

jsvine commented 9 years ago

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

emlyn commented 7 years ago

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]).