python-colourlovers
python-colourlovers copied to clipboard
Pb with cl.interp on colors scale
In [294]: import colorlover as cl
In [295]: cl
Out[295]: <module 'colorlover' from '/home/latty/.virtualenvs/screenpulse-unittest/local/lib/python2.7/site-packages/colorlover/__init__.pyc'>
In [296]: colormaps = cl.scales['7']['qual']['Dark2']
In [297]: colormaps
Out[297]:
['rgb(27,158,119)',
'rgb(217,95,2)',
'rgb(117,112,179)',
'rgb(231,41,138)',
'rgb(102,166,30)',
'rgb(230,171,2)',
'rgb(166,118,29)']
In [298]: cl.interp(colormaps, 11)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-298-946770f2b787> in <module>()
----> 1 cl.interp(colormaps, 11)
/home/latty/.virtualenvs/screenpulse-unittest/local/lib/python2.7/site-packages/colorlover/__init__.pyc in interp(scl, r)
1821 c_i = int(i*math.floor(SCL_FI)/round(r[-1])) # start color index
1822 hsl_o = rgb_to_hsl( scl[c_i] ) # convert rgb to hls
-> 1823 hsl_f = rgb_to_hsl( scl[c_i+1] )
1824 section_min = c_i*r[-1]/SCL_FI
1825 section_max = (c_i+1)*(r[-1]/SCL_FI)
IndexError: list index out of range
this bug is not stable, here for example:
In [310]: cl.interp(colormaps, 10)
Out[310]:
['hsl(162.0, 70.0%, 36.0%)',
'hsl(70.6666666667, 88.6666666667%, 40.0%)',
'hsl(72.3333333333, 75.3333333333%, 47.0%)',
'hsl(167.0, 30.0%, 57.0%)',
'hsl(275.0, 62.6666666667%, 54.3333333333%)',
'hsl(248.666666667, 75.6666666667%, 48.0%)',
'hsl(88.0, 69.0%, 38.0%)',
'hsl(58.6666666667, 88.3333333333%, 42.6666666667%)',
'hsl(29.3333333333, 107.666666667%, 47.3333333333%)',
'hsl(38.0, 70.0%, 38.0%)']
In [311]: cl.interp(colormaps, 11)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-311-946770f2b787> in <module>()
----> 1 cl.interp(colormaps, 11)
/home/latty/.virtualenvs/screenpulse-unittest/local/lib/python2.7/site-packages/colorlover/__init__.pyc in interp(scl, r)
1821 c_i = int(i*math.floor(SCL_FI)/round(r[-1])) # start color index
1822 hsl_o = rgb_to_hsl( scl[c_i] ) # convert rgb to hls
-> 1823 hsl_f = rgb_to_hsl( scl[c_i+1] )
1824 section_min = c_i*r[-1]/SCL_FI
1825 section_max = (c_i+1)*(r[-1]/SCL_FI)
IndexError: list index out of range
In [312]: cl.interp(colormaps, 15)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-312-e3b4fde92ac0> in <module>()
----> 1 cl.interp(colormaps, 15)
/home/latty/.virtualenvs/screenpulse-unittest/local/lib/python2.7/site-packages/colorlover/__init__.pyc in interp(scl, r)
1821 c_i = int(i*math.floor(SCL_FI)/round(r[-1])) # start color index
1822 hsl_o = rgb_to_hsl( scl[c_i] ) # convert rgb to hls
-> 1823 hsl_f = rgb_to_hsl( scl[c_i+1] )
1824 section_min = c_i*r[-1]/SCL_FI
1825 section_max = (c_i+1)*(r[-1]/SCL_FI)
IndexError: list index out of range
In [313]: cl.interp(colormaps, 16)
Out[313]:
['hsl(162.0, 70.0%, 36.0%)',
'hsl(107.2, 81.2%, 38.4%)',
'hsl(52.4, 92.4%, 40.8%)',
'hsl(-2.4, 103.6%, 43.2%)',
'hsl(110.2, 57.2%, 51.0%)',
'hsl(167.0, 30.0%, 57.0%)',
'hsl(223.8, 2.8%, 63.0%)',
'hsl(296.6, 69.2%, 53.8%)',
'hsl(361.4, 88.8%, 52.2%)',
'hsl(426.2, 108.4%, 50.6%)',
'hsl(88.0, 69.0%, 38.0%)',
'hsl(-8.4, 65.0%, 32.0%)',
'hsl(-104.8, 61.0%, 26.0%)',
'hsl(-201.2, 57.0%, 20.0%)',
'hsl(17.6, 115.4%, 49.2%)',
'hsl(0.0, 127.0%, 52.0%)']
I propose a (new) implementation with scipy/numpy implementation for interp:
def interp(scl, r):
''' Interpolate a color scale "scl" to a new one with length "r"
Fun usage in IPython notebook:
HTML( to_html( to_hsl( interp( cl.scales['11']['qual']['Paired'], 5000 ) ) ) ) '''
def rgb_to_hsl(rgb):
''' Adapted from M Bostock's RGB to HSL converter in d3.js
https://github.com/mbostock/d3/blob/master/src/color/rgb.js '''
r, g, b = float(rgb[0]) / 255.0, \
float(rgb[1]) / 255.0, \
float(rgb[2]) / 255.0
mx = max(r, g, b)
mn = min(r, g, b)
h = s = l = (mx + mn) / 2
if mx == mn: # achromatic
h = 0
s = 0 if 0 < l < 1 else h
else:
d = mx - mn
s = d / (mx + mn) if l < 0.5 else d / (2 - mx - mn)
if mx == r:
h = (g - b) / d + (6 if g < b else 0)
elif mx == g:
h = (b - r) / d + 2
else:
h = r - g / d + 4
return int(round(h * 60, 4)), int(round(s * 100, 4)), int(round(l * 100, 4))
# convert str RGB to numeric list of tuples
scl = cl.to_numeric(scl)
# convert RGB to HSL colormap (allow to interpolate linearly after)
shsl = map(rgb_to_hsl, scl)
nb_composants = len(scl[0])
assert nb_composants == 3
range_shsl = np.arange(len(shsl))
interp_range_shsl = np.linspace(0, len(shsl)-1, num=r, endpoint=True)
scl_interps = [
interpolate.interp1d(range_shsl, map(itemgetter(composant), shsl))(interp_range_shsl)
for composant in range(nb_composants)
]
interp_c = map(
lambda hsl: 'hsl' + str(hsl),
zip(*scl_interps)
)
return cl.to_hsl(interp_c)
I think it's more simple and seems to be more stable (not buggy :p).