Skip to content

Commit 373364e

Browse files
author
Martin Journois
committed
Modify LinearColormap.to_scale
1 parent aafec58 commit 373364e

1 file changed

Lines changed: 83 additions & 6 deletions

File tree

folium/colormap.py

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
Utility module for dealing with colormaps.
77
88
"""
9+
import math
910
from jinja2 import Template
1011
from folium.six import text_type, binary_type
1112
from folium.element import MacroElement, Figure, JavascriptLink
@@ -243,6 +244,15 @@ def _parse_color(x):
243244
color_tuple = tuple(u/255. for u in color_tuple)
244245
return tuple(map(float,(color_tuple+(1.,))[:4]))
245246

247+
_round = round
248+
249+
def _base(x):
250+
if x > 0:
251+
base = pow(10, math.floor(math.log10(x)))
252+
return round(x/base)*base
253+
else:
254+
return 0
255+
246256
class ColorMap(MacroElement):
247257
"""A generic class for creating colormaps."""
248258

@@ -384,7 +394,8 @@ def _rgba_floats_tuple(self, x):
384394

385395
return tuple((1.-p) * self.colors[i-1][j] + p*self.colors[i][j] for j in range(4))
386396

387-
def to_step(self, n=None, index=None):
397+
def to_step(self, n=None, index=None, data=None, method=None, quantiles=None,
398+
round=False, base_round=False):
388399
"""Splits the LinearColormap into a StepColormap.
389400
390401
Parameters
@@ -396,21 +407,87 @@ def to_step(self, n=None, index=None):
396407
The values corresponding to each color bounds.
397408
It has to be sorted.
398409
If None, a regular grid between `min` and `max` is created.
410+
data : list of floats, default None
411+
A sample of data to adapt the color map to.
412+
method : str, default 'linear'
413+
The method used to create data-based colormap.
414+
It can be 'linear' for linear scale, 'log' for logarithmic,
415+
or 'quant' for data's quantile-based scale.
416+
quantiles : list of floats, default None
417+
Alternatively, you can provide explicitely the quantiles you
418+
want to use in the scale.
419+
round : bool, default False
420+
If True, all values will be rounded.
421+
base_round : bool, default False
422+
If True, all values will be rounded to the nearest order-of-magnitude
423+
integer. For example, 2100 is rounded to 2000, 2790 to 3000.
399424
400425
Return
401426
------
402427
A StepColormap with `n=len(index)-1` colors.
428+
429+
Examples:
430+
>> lc.to_step(n=12)
431+
>> lc.to_step(index=[0,2,4,6,8,10])
432+
>> lc.to_step(data=some_list, n=12)
433+
>> lc.to_step(data=some_list, n=12, method='linear')
434+
>> lc.to_step(data=some_list, n=12, method='log')
435+
>> lc.to_step(data=some_list, n=12, method='quantiles')
436+
>> lc.to_step(data=some_list, quantiles=[0,0.3,0.7,1])
437+
>> lc.to_step(data=some_list, quantiles=[0,0.3,0.7,1], base_round=True)
403438
"""
404439
if index is None:
405-
if n is None:
406-
raise ValueError('You must specify either `index` or `n`')
407-
index = [self.min + (self.max-self.min)*i*1./n for i in range(1+n)]
440+
if data is None:
441+
if n is None:
442+
raise ValueError('You must specify either `index`,`data` or `n`')
443+
else:
444+
index = [self.min + (self.max-self.min)*i*1./n for i in range(1+n)]
445+
scaled_cm = self
446+
else:
447+
max_ = max(data)
448+
min_ = min(data)
449+
scaled_cm = self.scale(min=min_, max=max_)
450+
method = ('quantiles' if quantiles is not None
451+
else method if method is not None
452+
else 'linear'
453+
)
454+
if method.lower().startswith('lin'):
455+
if n is None:
456+
raise ValueError('You must specify either `index` or `n`')
457+
index = [min_ + i*(max_-min_)*1./n for i in range(1+n)]
458+
elif method.lower().startswith('log'):
459+
if n is None:
460+
raise ValueError('You must specify either `index` or `n`')
461+
if min_<=0:
462+
raise ValueError('Log-scale works only with strictly positive values.')
463+
index = [math.exp(
464+
math.log(min_) + i*(math.log(max_)-math.log(min_))*1./n
465+
) for i in range(1+n)]
466+
elif method.lower().startswith('quant'):
467+
if quantiles is None:
468+
if n is None:
469+
raise ValueError('You must specify either `index`, `n` or `quantiles`.')
470+
else:
471+
quantiles = [i*1./n for i in range(1+n)]
472+
p = len(data)-1
473+
s = sorted(data)
474+
index = [s[int(q*p)]*(1.-(q*p)%1)+s[min(int(q*p)+1, p)]*((q*p)%1) for q in quantiles]
475+
else:
476+
raise ValueError('Unknown method {}'.format(method))
477+
else:
478+
scaled_cm = self.scale(min=min(index), max=max(index))
408479

409480
n = len(index)-1
410481

411-
colors = [self._rgba_floats_tuple(index[i]*(1.-i/(n-1.))+index[i+1]*i/(n-1.)) for i in range(n)]
482+
if round:
483+
index = [_round(x) for x in index]
484+
485+
if base_round:
486+
index = [_base(x) for x in index]
487+
488+
colors = [scaled_cm._rgba_floats_tuple(index[i]*(1.-i/(n-1.))+index[i+1]*i/(n-1.)) for i in range(n)]
412489

413-
return StepColormap(colors, index=index, min=self.min, max=self.max)
490+
return StepColormap(colors, index=index, min=index[0], max=index[-1])
414491

415492
def scale(self, min=0., max=1.):
416493
"""Transforms the colorscale so that the minimal and maximal values

0 commit comments

Comments
 (0)