8
8
9
9
import pkg_resources
10
10
import functools
11
+ import warnings
11
12
12
13
import numpy as np
13
14
import pandas as pd
@@ -287,21 +288,40 @@ def _determine_extend(calc_data, vmin, vmax):
287
288
288
289
def _color_palette (cmap , n_colors ):
289
290
import matplotlib .pyplot as plt
290
- try :
291
- from seaborn .apionly import color_palette
292
- pal = color_palette (cmap , n_colors = n_colors )
293
- except (TypeError , ImportError , ValueError ):
294
- # TypeError is raised when LinearSegmentedColormap (viridis) is used
295
- # ImportError is raised when seaborn is not installed
296
- # ValueError is raised when seaborn doesn't like a colormap (e.g. jet)
297
- # Use homegrown solution if you don't have seaborn or are using viridis
298
- if isinstance (cmap , basestring ):
299
- cmap = plt .get_cmap (cmap )
300
-
301
- colors_i = np .linspace (0 , 1. , n_colors )
291
+ from matplotlib .colors import ListedColormap
292
+ colors_i = np .linspace (0 , 1. , n_colors )
293
+ if isinstance (cmap , (list , tuple )):
294
+ # we have a list of colors
295
+ try :
296
+ # first try to turn it into a palette with seaborn
297
+ from seaborn .apionly import color_palette
298
+ pal = color_palette (cmap , n_colors = n_colors )
299
+ except ImportError :
300
+ # if that fails, use matplotlib
301
+ # in this case, is there any difference between mpl and seaborn?
302
+ cmap = ListedColormap (cmap , N = n_colors )
303
+ pal = cmap (colors_i )
304
+ elif isinstance (cmap , basestring ):
305
+ # we have some sort of named palette
306
+ try :
307
+ # first try to turn it into a palette with seaborn
308
+ from seaborn .apionly import color_palette
309
+ pal = color_palette (cmap , n_colors = n_colors )
310
+ except (ImportError , ValueError ):
311
+ # ValueError is raised when seaborn doesn't like a colormap (e.g. jet)
312
+ # if that fails, use matplotlib
313
+ try :
314
+ # is this a matplotlib cmap?
315
+ cmap = plt .get_cmap (cmap )
316
+ except ValueError :
317
+ # or maybe we just got a single color as a string
318
+ cmap = ListedColormap ([cmap ], N = n_colors )
319
+ pal = cmap (colors_i )
320
+ else :
321
+ # cmap better be a LinearSegmentedColormap (e.g. viridis)
302
322
pal = cmap (colors_i )
303
- return pal
304
323
324
+ return pal
305
325
306
326
def _build_discrete_cmap (cmap , levels , extend , filled ):
307
327
"""
@@ -386,8 +406,12 @@ def _plot2d(plotfunc):
386
406
The mapping from data values to color space. If not provided, this
387
407
will be either be ``viridis`` (if the function infers a sequential
388
408
dataset) or ``RdBu_r`` (if the function infers a diverging dataset).
389
- When ``levels`` is provided and when `Seaborn` is installed, ``cmap``
390
- may also be a `seaborn` color palette or a list of colors.
409
+ When when `Seaborn` is installed, ``cmap`` may also be a `seaborn`
410
+ color palette. If ``cmap`` is seaborn color palette and the plot type
411
+ is not ``contour`` or ``contourf``, ``levels`` must also be specified.
412
+ colors : discrete colors to plot, optional
413
+ A single color or a list of colors. If the plot type is not ``contour``
414
+ or ``contourf``, the ``levels`` argument is required.
391
415
center : float, optional
392
416
The value at which to center the colormap. Passing this value implies
393
417
use of a diverging colormap.
@@ -415,13 +439,27 @@ def _plot2d(plotfunc):
415
439
@functools .wraps (plotfunc )
416
440
def newplotfunc (darray , ax = None , xincrease = None , yincrease = None ,
417
441
add_colorbar = True , add_labels = True , vmin = None , vmax = None , cmap = None ,
418
- center = None , robust = False , extend = None , levels = None ,
442
+ center = None , robust = False , extend = None , levels = None , colors = None ,
419
443
** kwargs ):
420
444
# All 2d plots in xray share this function signature.
421
445
# Method signature below should be consistent.
422
446
423
447
import matplotlib .pyplot as plt
424
448
449
+ # colors is mutually exclusive with cmap
450
+ if cmap and colors :
451
+ raise ValueError ("Can't specify both cmap and colors." )
452
+ # colors is only valid when levels is supplied or the plot is of type
453
+ # contour or contourf
454
+ if colors and (('contour' not in plotfunc .__name__ ) and (not levels )):
455
+ raise ValueError ("Can only specify colors with contour or levels" )
456
+ # we should not be getting a list of colors in cmap anymore
457
+ # is there a better way to do this test?
458
+ if isinstance (cmap , (list , tuple )):
459
+ warnings .warn ("Specifying a list of colors in cmap is deprecated. "
460
+ "Use colors keyword instead." ,
461
+ DeprecationWarning , stacklevel = 3 )
462
+
425
463
if ax is None :
426
464
ax = plt .gca ()
427
465
@@ -444,9 +482,9 @@ def newplotfunc(darray, ax=None, xincrease=None, yincrease=None,
444
482
levels = 7 # this is the matplotlib default
445
483
filled = plotfunc .__name__ != 'contour'
446
484
485
+ cmap = colors if colors else cmap
447
486
cmap_params = _determine_cmap_params (z .data , vmin , vmax , cmap , center ,
448
487
robust , extend , levels , filled )
449
-
450
488
if 'contour' in plotfunc .__name__ :
451
489
# extend is a keyword argument only for contour and contourf, but
452
490
# passing it to the colorbar is sufficient for imshow and
@@ -482,7 +520,7 @@ def newplotfunc(darray, ax=None, xincrease=None, yincrease=None,
482
520
@functools .wraps (newplotfunc )
483
521
def plotmethod (_PlotMethods_obj , ax = None , xincrease = None , yincrease = None ,
484
522
add_colorbar = True , add_labels = True , vmin = None , vmax = None , cmap = None ,
485
- center = None , robust = False , extend = None , levels = None ,
523
+ colors = None , center = None , robust = False , extend = None , levels = None ,
486
524
** kwargs ):
487
525
'''
488
526
The method should have the same signature as the function.
0 commit comments