66Utility module for dealing with colormaps.
77
88"""
9+ import math
910from jinja2 import Template
1011from folium .six import text_type , binary_type
1112from 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+
246256class 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