1import colorsys 2from itertools import cycle 3 4import numpy as np 5import matplotlib as mpl 6 7from .external import husl 8 9from .utils import desaturate, get_color_cycle 10from .colors import xkcd_rgb, crayons 11 12 13__all__ = ["color_palette", "hls_palette", "husl_palette", "mpl_palette", 14 "dark_palette", "light_palette", "diverging_palette", 15 "blend_palette", "xkcd_palette", "crayon_palette", 16 "cubehelix_palette", "set_color_codes"] 17 18 19SEABORN_PALETTES = dict( 20 deep=["#4C72B0", "#DD8452", "#55A868", "#C44E52", "#8172B3", 21 "#937860", "#DA8BC3", "#8C8C8C", "#CCB974", "#64B5CD"], 22 deep6=["#4C72B0", "#55A868", "#C44E52", 23 "#8172B3", "#CCB974", "#64B5CD"], 24 muted=["#4878D0", "#EE854A", "#6ACC64", "#D65F5F", "#956CB4", 25 "#8C613C", "#DC7EC0", "#797979", "#D5BB67", "#82C6E2"], 26 muted6=["#4878D0", "#6ACC64", "#D65F5F", 27 "#956CB4", "#D5BB67", "#82C6E2"], 28 pastel=["#A1C9F4", "#FFB482", "#8DE5A1", "#FF9F9B", "#D0BBFF", 29 "#DEBB9B", "#FAB0E4", "#CFCFCF", "#FFFEA3", "#B9F2F0"], 30 pastel6=["#A1C9F4", "#8DE5A1", "#FF9F9B", 31 "#D0BBFF", "#FFFEA3", "#B9F2F0"], 32 bright=["#023EFF", "#FF7C00", "#1AC938", "#E8000B", "#8B2BE2", 33 "#9F4800", "#F14CC1", "#A3A3A3", "#FFC400", "#00D7FF"], 34 bright6=["#023EFF", "#1AC938", "#E8000B", 35 "#8B2BE2", "#FFC400", "#00D7FF"], 36 dark=["#001C7F", "#B1400D", "#12711C", "#8C0800", "#591E71", 37 "#592F0D", "#A23582", "#3C3C3C", "#B8850A", "#006374"], 38 dark6=["#001C7F", "#12711C", "#8C0800", 39 "#591E71", "#B8850A", "#006374"], 40 colorblind=["#0173B2", "#DE8F05", "#029E73", "#D55E00", "#CC78BC", 41 "#CA9161", "#FBAFE4", "#949494", "#ECE133", "#56B4E9"], 42 colorblind6=["#0173B2", "#029E73", "#D55E00", 43 "#CC78BC", "#ECE133", "#56B4E9"] 44) 45 46 47MPL_QUAL_PALS = { 48 "tab10": 10, "tab20": 20, "tab20b": 20, "tab20c": 20, 49 "Set1": 9, "Set2": 8, "Set3": 12, 50 "Accent": 8, "Paired": 12, 51 "Pastel1": 9, "Pastel2": 8, "Dark2": 8, 52} 53 54 55QUAL_PALETTE_SIZES = MPL_QUAL_PALS.copy() 56QUAL_PALETTE_SIZES.update({k: len(v) for k, v in SEABORN_PALETTES.items()}) 57QUAL_PALETTES = list(QUAL_PALETTE_SIZES.keys()) 58 59 60class _ColorPalette(list): 61 """Set the color palette in a with statement, otherwise be a list.""" 62 def __enter__(self): 63 """Open the context.""" 64 from .rcmod import set_palette 65 self._orig_palette = color_palette() 66 set_palette(self) 67 return self 68 69 def __exit__(self, *args): 70 """Close the context.""" 71 from .rcmod import set_palette 72 set_palette(self._orig_palette) 73 74 def as_hex(self): 75 """Return a color palette with hex codes instead of RGB values.""" 76 hex = [mpl.colors.rgb2hex(rgb) for rgb in self] 77 return _ColorPalette(hex) 78 79 def _repr_html_(self): 80 """Rich display of the color palette in an HTML frontend.""" 81 s = 55 82 n = len(self) 83 html = f'<svg width="{n * s}" height="{s}">' 84 for i, c in enumerate(self.as_hex()): 85 html += ( 86 f'<rect x="{i * s}" y="0" width="{s}" height="{s}" style="fill:{c};' 87 'stroke-width:2;stroke:rgb(255,255,255)"/>' 88 ) 89 html += '</svg>' 90 return html 91 92 93def color_palette(palette=None, n_colors=None, desat=None, as_cmap=False): 94 """Return a list of colors or continuous colormap defining a palette. 95 96 Possible ``palette`` values include: 97 - Name of a seaborn palette (deep, muted, bright, pastel, dark, colorblind) 98 - Name of matplotlib colormap 99 - 'husl' or 'hsl' 100 - 'ch:<cubehelix arguments>' 101 - 'light:<color>', 'dark:<color>', 'blend:<color>,<color>', 102 - A sequence of colors in any format matplotlib accepts 103 104 Calling this function with ``palette=None`` will return the current 105 matplotlib color cycle. 106 107 This function can also be used in a ``with`` statement to temporarily 108 set the color cycle for a plot or set of plots. 109 110 See the :ref:`tutorial <palette_tutorial>` for more information. 111 112 Parameters 113 ---------- 114 palette: None, string, or sequence, optional 115 Name of palette or None to return current palette. If a sequence, input 116 colors are used but possibly cycled and desaturated. 117 n_colors : int, optional 118 Number of colors in the palette. If ``None``, the default will depend 119 on how ``palette`` is specified. Named palettes default to 6 colors, 120 but grabbing the current palette or passing in a list of colors will 121 not change the number of colors unless this is specified. Asking for 122 more colors than exist in the palette will cause it to cycle. Ignored 123 when ``as_cmap`` is True. 124 desat : float, optional 125 Proportion to desaturate each color by. 126 as_cmap : bool 127 If True, return a :class:`matplotlib.colors.Colormap`. 128 129 Returns 130 ------- 131 list of RGB tuples or :class:`matplotlib.colors.Colormap` 132 133 See Also 134 -------- 135 set_palette : Set the default color cycle for all plots. 136 set_color_codes : Reassign color codes like ``"b"``, ``"g"``, etc. to 137 colors from one of the seaborn palettes. 138 139 Examples 140 -------- 141 142 .. include:: ../docstrings/color_palette.rst 143 144 """ 145 if palette is None: 146 palette = get_color_cycle() 147 if n_colors is None: 148 n_colors = len(palette) 149 150 elif not isinstance(palette, str): 151 palette = palette 152 if n_colors is None: 153 n_colors = len(palette) 154 else: 155 156 if n_colors is None: 157 # Use all colors in a qualitative palette or 6 of another kind 158 n_colors = QUAL_PALETTE_SIZES.get(palette, 6) 159 160 if palette in SEABORN_PALETTES: 161 # Named "seaborn variant" of matplotlib default color cycle 162 palette = SEABORN_PALETTES[palette] 163 164 elif palette == "hls": 165 # Evenly spaced colors in cylindrical RGB space 166 palette = hls_palette(n_colors, as_cmap=as_cmap) 167 168 elif palette == "husl": 169 # Evenly spaced colors in cylindrical Lab space 170 palette = husl_palette(n_colors, as_cmap=as_cmap) 171 172 elif palette.lower() == "jet": 173 # Paternalism 174 raise ValueError("No.") 175 176 elif palette.startswith("ch:"): 177 # Cubehelix palette with params specified in string 178 args, kwargs = _parse_cubehelix_args(palette) 179 palette = cubehelix_palette(n_colors, *args, **kwargs, as_cmap=as_cmap) 180 181 elif palette.startswith("light:"): 182 # light palette to color specified in string 183 _, color = palette.split(":") 184 reverse = color.endswith("_r") 185 if reverse: 186 color = color[:-2] 187 palette = light_palette(color, n_colors, reverse=reverse, as_cmap=as_cmap) 188 189 elif palette.startswith("dark:"): 190 # light palette to color specified in string 191 _, color = palette.split(":") 192 reverse = color.endswith("_r") 193 if reverse: 194 color = color[:-2] 195 palette = dark_palette(color, n_colors, reverse=reverse, as_cmap=as_cmap) 196 197 elif palette.startswith("blend:"): 198 # blend palette between colors specified in string 199 _, colors = palette.split(":") 200 colors = colors.split(",") 201 palette = blend_palette(colors, n_colors, as_cmap=as_cmap) 202 203 else: 204 try: 205 # Perhaps a named matplotlib colormap? 206 palette = mpl_palette(palette, n_colors, as_cmap=as_cmap) 207 except ValueError: 208 raise ValueError("%s is not a valid palette name" % palette) 209 210 if desat is not None: 211 palette = [desaturate(c, desat) for c in palette] 212 213 if not as_cmap: 214 215 # Always return as many colors as we asked for 216 pal_cycle = cycle(palette) 217 palette = [next(pal_cycle) for _ in range(n_colors)] 218 219 # Always return in r, g, b tuple format 220 try: 221 palette = map(mpl.colors.colorConverter.to_rgb, palette) 222 palette = _ColorPalette(palette) 223 except ValueError: 224 raise ValueError(f"Could not generate a palette for {palette}") 225 226 return palette 227 228 229def hls_palette(n_colors=6, h=.01, l=.6, s=.65, as_cmap=False): # noqa 230 """Get a set of evenly spaced colors in HLS hue space. 231 232 h, l, and s should be between 0 and 1 233 234 Parameters 235 ---------- 236 237 n_colors : int 238 number of colors in the palette 239 h : float 240 first hue 241 l : float 242 lightness 243 s : float 244 saturation 245 246 Returns 247 ------- 248 list of RGB tuples or :class:`matplotlib.colors.Colormap` 249 250 See Also 251 -------- 252 husl_palette : Make a palette using evenly spaced hues in the HUSL system. 253 254 Examples 255 -------- 256 257 Create a palette of 10 colors with the default parameters: 258 259 .. plot:: 260 :context: close-figs 261 262 >>> import seaborn as sns; sns.set_theme() 263 >>> sns.palplot(sns.hls_palette(10)) 264 265 Create a palette of 10 colors that begins at a different hue value: 266 267 .. plot:: 268 :context: close-figs 269 270 >>> sns.palplot(sns.hls_palette(10, h=.5)) 271 272 Create a palette of 10 colors that are darker than the default: 273 274 .. plot:: 275 :context: close-figs 276 277 >>> sns.palplot(sns.hls_palette(10, l=.4)) 278 279 Create a palette of 10 colors that are less saturated than the default: 280 281 .. plot:: 282 :context: close-figs 283 284 >>> sns.palplot(sns.hls_palette(10, s=.4)) 285 286 """ 287 if as_cmap: 288 n_colors = 256 289 hues = np.linspace(0, 1, int(n_colors) + 1)[:-1] 290 hues += h 291 hues %= 1 292 hues -= hues.astype(int) 293 palette = [colorsys.hls_to_rgb(h_i, l, s) for h_i in hues] 294 if as_cmap: 295 return mpl.colors.ListedColormap(palette, "hls") 296 else: 297 return _ColorPalette(palette) 298 299 300def husl_palette(n_colors=6, h=.01, s=.9, l=.65, as_cmap=False): # noqa 301 """Get a set of evenly spaced colors in HUSL hue space. 302 303 h, s, and l should be between 0 and 1 304 305 Parameters 306 ---------- 307 308 n_colors : int 309 number of colors in the palette 310 h : float 311 first hue 312 s : float 313 saturation 314 l : float 315 lightness 316 317 Returns 318 ------- 319 list of RGB tuples or :class:`matplotlib.colors.Colormap` 320 321 See Also 322 -------- 323 hls_palette : Make a palette using evently spaced circular hues in the 324 HSL system. 325 326 Examples 327 -------- 328 329 Create a palette of 10 colors with the default parameters: 330 331 .. plot:: 332 :context: close-figs 333 334 >>> import seaborn as sns; sns.set_theme() 335 >>> sns.palplot(sns.husl_palette(10)) 336 337 Create a palette of 10 colors that begins at a different hue value: 338 339 .. plot:: 340 :context: close-figs 341 342 >>> sns.palplot(sns.husl_palette(10, h=.5)) 343 344 Create a palette of 10 colors that are darker than the default: 345 346 .. plot:: 347 :context: close-figs 348 349 >>> sns.palplot(sns.husl_palette(10, l=.4)) 350 351 Create a palette of 10 colors that are less saturated than the default: 352 353 .. plot:: 354 :context: close-figs 355 356 >>> sns.palplot(sns.husl_palette(10, s=.4)) 357 358 """ 359 if as_cmap: 360 n_colors = 256 361 hues = np.linspace(0, 1, int(n_colors) + 1)[:-1] 362 hues += h 363 hues %= 1 364 hues *= 359 365 s *= 99 366 l *= 99 # noqa 367 palette = [_color_to_rgb((h_i, s, l), input="husl") for h_i in hues] 368 if as_cmap: 369 return mpl.colors.ListedColormap(palette, "hsl") 370 else: 371 return _ColorPalette(palette) 372 373 374def mpl_palette(name, n_colors=6, as_cmap=False): 375 """Return discrete colors from a matplotlib palette. 376 377 Note that this handles the qualitative colorbrewer palettes 378 properly, although if you ask for more colors than a particular 379 qualitative palette can provide you will get fewer than you are 380 expecting. In contrast, asking for qualitative color brewer palettes 381 using :func:`color_palette` will return the expected number of colors, 382 but they will cycle. 383 384 If you are using the IPython notebook, you can also use the function 385 :func:`choose_colorbrewer_palette` to interactively select palettes. 386 387 Parameters 388 ---------- 389 name : string 390 Name of the palette. This should be a named matplotlib colormap. 391 n_colors : int 392 Number of discrete colors in the palette. 393 394 Returns 395 ------- 396 list of RGB tuples or :class:`matplotlib.colors.Colormap` 397 398 Examples 399 -------- 400 401 Create a qualitative colorbrewer palette with 8 colors: 402 403 .. plot:: 404 :context: close-figs 405 406 >>> import seaborn as sns; sns.set_theme() 407 >>> sns.palplot(sns.mpl_palette("Set2", 8)) 408 409 Create a sequential colorbrewer palette: 410 411 .. plot:: 412 :context: close-figs 413 414 >>> sns.palplot(sns.mpl_palette("Blues")) 415 416 Create a diverging palette: 417 418 .. plot:: 419 :context: close-figs 420 421 >>> sns.palplot(sns.mpl_palette("seismic", 8)) 422 423 Create a "dark" sequential palette: 424 425 .. plot:: 426 :context: close-figs 427 428 >>> sns.palplot(sns.mpl_palette("GnBu_d")) 429 430 """ 431 if name.endswith("_d"): 432 sub_name = name[:-2] 433 if sub_name.endswith("_r"): 434 reverse = True 435 sub_name = sub_name[:-2] 436 else: 437 reverse = False 438 pal = color_palette(sub_name, 2) + ["#333333"] 439 if reverse: 440 pal = pal[::-1] 441 cmap = blend_palette(pal, n_colors, as_cmap=True) 442 else: 443 cmap = mpl.cm.get_cmap(name) 444 445 if name in MPL_QUAL_PALS: 446 bins = np.linspace(0, 1, MPL_QUAL_PALS[name])[:n_colors] 447 else: 448 bins = np.linspace(0, 1, int(n_colors) + 2)[1:-1] 449 palette = list(map(tuple, cmap(bins)[:, :3])) 450 451 if as_cmap: 452 return cmap 453 else: 454 return _ColorPalette(palette) 455 456 457def _color_to_rgb(color, input): 458 """Add some more flexibility to color choices.""" 459 if input == "hls": 460 color = colorsys.hls_to_rgb(*color) 461 elif input == "husl": 462 color = husl.husl_to_rgb(*color) 463 color = tuple(np.clip(color, 0, 1)) 464 elif input == "xkcd": 465 color = xkcd_rgb[color] 466 467 return mpl.colors.to_rgb(color) 468 469 470def dark_palette(color, n_colors=6, reverse=False, as_cmap=False, input="rgb"): 471 """Make a sequential palette that blends from dark to ``color``. 472 473 This kind of palette is good for data that range between relatively 474 uninteresting low values and interesting high values. 475 476 The ``color`` parameter can be specified in a number of ways, including 477 all options for defining a color in matplotlib and several additional 478 color spaces that are handled by seaborn. You can also use the database 479 of named colors from the XKCD color survey. 480 481 If you are using the IPython notebook, you can also choose this palette 482 interactively with the :func:`choose_dark_palette` function. 483 484 Parameters 485 ---------- 486 color : base color for high values 487 hex, rgb-tuple, or html color name 488 n_colors : int, optional 489 number of colors in the palette 490 reverse : bool, optional 491 if True, reverse the direction of the blend 492 as_cmap : bool, optional 493 If True, return a :class:`matplotlib.colors.Colormap`. 494 input : {'rgb', 'hls', 'husl', xkcd'} 495 Color space to interpret the input color. The first three options 496 apply to tuple inputs and the latter applies to string inputs. 497 498 Returns 499 ------- 500 list of RGB tuples or :class:`matplotlib.colors.Colormap` 501 502 See Also 503 -------- 504 light_palette : Create a sequential palette with bright low values. 505 diverging_palette : Create a diverging palette with two colors. 506 507 Examples 508 -------- 509 510 Generate a palette from an HTML color: 511 512 .. plot:: 513 :context: close-figs 514 515 >>> import seaborn as sns; sns.set_theme() 516 >>> sns.palplot(sns.dark_palette("purple")) 517 518 Generate a palette that decreases in lightness: 519 520 .. plot:: 521 :context: close-figs 522 523 >>> sns.palplot(sns.dark_palette("seagreen", reverse=True)) 524 525 Generate a palette from an HUSL-space seed: 526 527 .. plot:: 528 :context: close-figs 529 530 >>> sns.palplot(sns.dark_palette((260, 75, 60), input="husl")) 531 532 Generate a colormap object: 533 534 .. plot:: 535 :context: close-figs 536 537 >>> from numpy import arange 538 >>> x = arange(25).reshape(5, 5) 539 >>> cmap = sns.dark_palette("#2ecc71", as_cmap=True) 540 >>> ax = sns.heatmap(x, cmap=cmap) 541 542 """ 543 rgb = _color_to_rgb(color, input) 544 h, s, l = husl.rgb_to_husl(*rgb) 545 gray_s, gray_l = .15 * s, 15 546 gray = _color_to_rgb((h, gray_s, gray_l), input="husl") 547 colors = [rgb, gray] if reverse else [gray, rgb] 548 return blend_palette(colors, n_colors, as_cmap) 549 550 551def light_palette(color, n_colors=6, reverse=False, as_cmap=False, input="rgb"): 552 """Make a sequential palette that blends from light to ``color``. 553 554 This kind of palette is good for data that range between relatively 555 uninteresting low values and interesting high values. 556 557 The ``color`` parameter can be specified in a number of ways, including 558 all options for defining a color in matplotlib and several additional 559 color spaces that are handled by seaborn. You can also use the database 560 of named colors from the XKCD color survey. 561 562 If you are using the IPython notebook, you can also choose this palette 563 interactively with the :func:`choose_light_palette` function. 564 565 Parameters 566 ---------- 567 color : base color for high values 568 hex code, html color name, or tuple in ``input`` space. 569 n_colors : int, optional 570 number of colors in the palette 571 reverse : bool, optional 572 if True, reverse the direction of the blend 573 as_cmap : bool, optional 574 If True, return a :class:`matplotlib.colors.Colormap`. 575 input : {'rgb', 'hls', 'husl', xkcd'} 576 Color space to interpret the input color. The first three options 577 apply to tuple inputs and the latter applies to string inputs. 578 579 Returns 580 ------- 581 list of RGB tuples or :class:`matplotlib.colors.Colormap` 582 583 See Also 584 -------- 585 dark_palette : Create a sequential palette with dark low values. 586 diverging_palette : Create a diverging palette with two colors. 587 588 Examples 589 -------- 590 591 Generate a palette from an HTML color: 592 593 .. plot:: 594 :context: close-figs 595 596 >>> import seaborn as sns; sns.set_theme() 597 >>> sns.palplot(sns.light_palette("purple")) 598 599 Generate a palette that increases in lightness: 600 601 .. plot:: 602 :context: close-figs 603 604 >>> sns.palplot(sns.light_palette("seagreen", reverse=True)) 605 606 Generate a palette from an HUSL-space seed: 607 608 .. plot:: 609 :context: close-figs 610 611 >>> sns.palplot(sns.light_palette((260, 75, 60), input="husl")) 612 613 Generate a colormap object: 614 615 .. plot:: 616 :context: close-figs 617 618 >>> from numpy import arange 619 >>> x = arange(25).reshape(5, 5) 620 >>> cmap = sns.light_palette("#2ecc71", as_cmap=True) 621 >>> ax = sns.heatmap(x, cmap=cmap) 622 623 """ 624 rgb = _color_to_rgb(color, input) 625 h, s, l = husl.rgb_to_husl(*rgb) 626 gray_s, gray_l = .15 * s, 95 627 gray = _color_to_rgb((h, gray_s, gray_l), input="husl") 628 colors = [rgb, gray] if reverse else [gray, rgb] 629 return blend_palette(colors, n_colors, as_cmap) 630 631 632def diverging_palette(h_neg, h_pos, s=75, l=50, sep=1, n=6, # noqa 633 center="light", as_cmap=False): 634 """Make a diverging palette between two HUSL colors. 635 636 If you are using the IPython notebook, you can also choose this palette 637 interactively with the :func:`choose_diverging_palette` function. 638 639 Parameters 640 ---------- 641 h_neg, h_pos : float in [0, 359] 642 Anchor hues for negative and positive extents of the map. 643 s : float in [0, 100], optional 644 Anchor saturation for both extents of the map. 645 l : float in [0, 100], optional 646 Anchor lightness for both extents of the map. 647 sep : int, optional 648 Size of the intermediate region. 649 n : int, optional 650 Number of colors in the palette (if not returning a cmap) 651 center : {"light", "dark"}, optional 652 Whether the center of the palette is light or dark 653 as_cmap : bool, optional 654 If True, return a :class:`matplotlib.colors.Colormap`. 655 656 Returns 657 ------- 658 list of RGB tuples or :class:`matplotlib.colors.Colormap` 659 660 See Also 661 -------- 662 dark_palette : Create a sequential palette with dark values. 663 light_palette : Create a sequential palette with light values. 664 665 Examples 666 -------- 667 668 Generate a blue-white-red palette: 669 670 .. plot:: 671 :context: close-figs 672 673 >>> import seaborn as sns; sns.set_theme() 674 >>> sns.palplot(sns.diverging_palette(240, 10, n=9)) 675 676 Generate a brighter green-white-purple palette: 677 678 .. plot:: 679 :context: close-figs 680 681 >>> sns.palplot(sns.diverging_palette(150, 275, s=80, l=55, n=9)) 682 683 Generate a blue-black-red palette: 684 685 .. plot:: 686 :context: close-figs 687 688 >>> sns.palplot(sns.diverging_palette(250, 15, s=75, l=40, 689 ... n=9, center="dark")) 690 691 Generate a colormap object: 692 693 .. plot:: 694 :context: close-figs 695 696 >>> from numpy import arange 697 >>> x = arange(25).reshape(5, 5) 698 >>> cmap = sns.diverging_palette(220, 20, as_cmap=True) 699 >>> ax = sns.heatmap(x, cmap=cmap) 700 701 """ 702 palfunc = dict(dark=dark_palette, light=light_palette)[center] 703 n_half = int(128 - (sep // 2)) 704 neg = palfunc((h_neg, s, l), n_half, reverse=True, input="husl") 705 pos = palfunc((h_pos, s, l), n_half, input="husl") 706 midpoint = dict(light=[(.95, .95, .95)], dark=[(.133, .133, .133)])[center] 707 mid = midpoint * sep 708 pal = blend_palette(np.concatenate([neg, mid, pos]), n, as_cmap=as_cmap) 709 return pal 710 711 712def blend_palette(colors, n_colors=6, as_cmap=False, input="rgb"): 713 """Make a palette that blends between a list of colors. 714 715 Parameters 716 ---------- 717 colors : sequence of colors in various formats interpreted by ``input`` 718 hex code, html color name, or tuple in ``input`` space. 719 n_colors : int, optional 720 Number of colors in the palette. 721 as_cmap : bool, optional 722 If True, return a :class:`matplotlib.colors.Colormap`. 723 724 Returns 725 ------- 726 list of RGB tuples or :class:`matplotlib.colors.Colormap` 727 728 """ 729 colors = [_color_to_rgb(color, input) for color in colors] 730 name = "blend" 731 pal = mpl.colors.LinearSegmentedColormap.from_list(name, colors) 732 if not as_cmap: 733 rgb_array = pal(np.linspace(0, 1, int(n_colors)))[:, :3] # no alpha 734 pal = _ColorPalette(map(tuple, rgb_array)) 735 return pal 736 737 738def xkcd_palette(colors): 739 """Make a palette with color names from the xkcd color survey. 740 741 See xkcd for the full list of colors: https://xkcd.com/color/rgb/ 742 743 This is just a simple wrapper around the ``seaborn.xkcd_rgb`` dictionary. 744 745 Parameters 746 ---------- 747 colors : list of strings 748 List of keys in the ``seaborn.xkcd_rgb`` dictionary. 749 750 Returns 751 ------- 752 palette : seaborn color palette 753 Returns the list of colors as RGB tuples in an object that behaves like 754 other seaborn color palettes. 755 756 See Also 757 -------- 758 crayon_palette : Make a palette with Crayola crayon colors. 759 760 """ 761 palette = [xkcd_rgb[name] for name in colors] 762 return color_palette(palette, len(palette)) 763 764 765def crayon_palette(colors): 766 """Make a palette with color names from Crayola crayons. 767 768 Colors are taken from here: 769 https://en.wikipedia.org/wiki/List_of_Crayola_crayon_colors 770 771 This is just a simple wrapper around the ``seaborn.crayons`` dictionary. 772 773 Parameters 774 ---------- 775 colors : list of strings 776 List of keys in the ``seaborn.crayons`` dictionary. 777 778 Returns 779 ------- 780 palette : seaborn color palette 781 Returns the list of colors as rgb tuples in an object that behaves like 782 other seaborn color palettes. 783 784 See Also 785 -------- 786 xkcd_palette : Make a palette with named colors from the XKCD color survey. 787 788 """ 789 palette = [crayons[name] for name in colors] 790 return color_palette(palette, len(palette)) 791 792 793def cubehelix_palette(n_colors=6, start=0, rot=.4, gamma=1.0, hue=0.8, 794 light=.85, dark=.15, reverse=False, as_cmap=False): 795 """Make a sequential palette from the cubehelix system. 796 797 This produces a colormap with linearly-decreasing (or increasing) 798 brightness. That means that information will be preserved if printed to 799 black and white or viewed by someone who is colorblind. "cubehelix" is 800 also available as a matplotlib-based palette, but this function gives the 801 user more control over the look of the palette and has a different set of 802 defaults. 803 804 In addition to using this function, it is also possible to generate a 805 cubehelix palette generally in seaborn using a string-shorthand; see the 806 example below. 807 808 Parameters 809 ---------- 810 n_colors : int 811 Number of colors in the palette. 812 start : float, 0 <= start <= 3 813 The hue at the start of the helix. 814 rot : float 815 Rotations around the hue wheel over the range of the palette. 816 gamma : float 0 <= gamma 817 Gamma factor to emphasize darker (gamma < 1) or lighter (gamma > 1) 818 colors. 819 hue : float, 0 <= hue <= 1 820 Saturation of the colors. 821 dark : float 0 <= dark <= 1 822 Intensity of the darkest color in the palette. 823 light : float 0 <= light <= 1 824 Intensity of the lightest color in the palette. 825 reverse : bool 826 If True, the palette will go from dark to light. 827 as_cmap : bool 828 If True, return a :class:`matplotlib.colors.Colormap`. 829 830 Returns 831 ------- 832 list of RGB tuples or :class:`matplotlib.colors.Colormap` 833 834 See Also 835 -------- 836 choose_cubehelix_palette : Launch an interactive widget to select cubehelix 837 palette parameters. 838 dark_palette : Create a sequential palette with dark low values. 839 light_palette : Create a sequential palette with bright low values. 840 841 References 842 ---------- 843 Green, D. A. (2011). "A colour scheme for the display of astronomical 844 intensity images". Bulletin of the Astromical Society of India, Vol. 39, 845 p. 289-295. 846 847 Examples 848 -------- 849 850 Generate the default palette: 851 852 .. plot:: 853 :context: close-figs 854 855 >>> import seaborn as sns; sns.set_theme() 856 >>> sns.palplot(sns.cubehelix_palette()) 857 858 Rotate backwards from the same starting location: 859 860 .. plot:: 861 :context: close-figs 862 863 >>> sns.palplot(sns.cubehelix_palette(rot=-.4)) 864 865 Use a different starting point and shorter rotation: 866 867 .. plot:: 868 :context: close-figs 869 870 >>> sns.palplot(sns.cubehelix_palette(start=2.8, rot=.1)) 871 872 Reverse the direction of the lightness ramp: 873 874 .. plot:: 875 :context: close-figs 876 877 >>> sns.palplot(sns.cubehelix_palette(reverse=True)) 878 879 Generate a colormap object: 880 881 .. plot:: 882 :context: close-figs 883 884 >>> from numpy import arange 885 >>> x = arange(25).reshape(5, 5) 886 >>> cmap = sns.cubehelix_palette(as_cmap=True) 887 >>> ax = sns.heatmap(x, cmap=cmap) 888 889 Use the full lightness range: 890 891 .. plot:: 892 :context: close-figs 893 894 >>> cmap = sns.cubehelix_palette(dark=0, light=1, as_cmap=True) 895 >>> ax = sns.heatmap(x, cmap=cmap) 896 897 Use through the :func:`color_palette` interface: 898 899 .. plot:: 900 :context: close-figs 901 902 >>> sns.palplot(sns.color_palette("ch:2,r=.2,l=.6")) 903 904 """ 905 def get_color_function(p0, p1): 906 # Copied from matplotlib because it lives in private module 907 def color(x): 908 # Apply gamma factor to emphasise low or high intensity values 909 xg = x ** gamma 910 911 # Calculate amplitude and angle of deviation from the black 912 # to white diagonal in the plane of constant 913 # perceived intensity. 914 a = hue * xg * (1 - xg) / 2 915 916 phi = 2 * np.pi * (start / 3 + rot * x) 917 918 return xg + a * (p0 * np.cos(phi) + p1 * np.sin(phi)) 919 return color 920 921 cdict = { 922 "red": get_color_function(-0.14861, 1.78277), 923 "green": get_color_function(-0.29227, -0.90649), 924 "blue": get_color_function(1.97294, 0.0), 925 } 926 927 cmap = mpl.colors.LinearSegmentedColormap("cubehelix", cdict) 928 929 x = np.linspace(light, dark, int(n_colors)) 930 pal = cmap(x)[:, :3].tolist() 931 if reverse: 932 pal = pal[::-1] 933 934 if as_cmap: 935 x_256 = np.linspace(light, dark, 256) 936 if reverse: 937 x_256 = x_256[::-1] 938 pal_256 = cmap(x_256) 939 cmap = mpl.colors.ListedColormap(pal_256, "seaborn_cubehelix") 940 return cmap 941 else: 942 return _ColorPalette(pal) 943 944 945def _parse_cubehelix_args(argstr): 946 """Turn stringified cubehelix params into args/kwargs.""" 947 948 if argstr.startswith("ch:"): 949 argstr = argstr[3:] 950 951 if argstr.endswith("_r"): 952 reverse = True 953 argstr = argstr[:-2] 954 else: 955 reverse = False 956 957 if not argstr: 958 return [], {"reverse": reverse} 959 960 all_args = argstr.split(",") 961 962 args = [float(a.strip(" ")) for a in all_args if "=" not in a] 963 964 kwargs = [a.split("=") for a in all_args if "=" in a] 965 kwargs = {k.strip(" "): float(v.strip(" ")) for k, v in kwargs} 966 967 kwarg_map = dict( 968 s="start", r="rot", g="gamma", 969 h="hue", l="light", d="dark", # noqa: E741 970 ) 971 972 kwargs = {kwarg_map.get(k, k): v for k, v in kwargs.items()} 973 974 if reverse: 975 kwargs["reverse"] = True 976 977 return args, kwargs 978 979 980def set_color_codes(palette="deep"): 981 """Change how matplotlib color shorthands are interpreted. 982 983 Calling this will change how shorthand codes like "b" or "g" 984 are interpreted by matplotlib in subsequent plots. 985 986 Parameters 987 ---------- 988 palette : {deep, muted, pastel, dark, bright, colorblind} 989 Named seaborn palette to use as the source of colors. 990 991 See Also 992 -------- 993 set : Color codes can be set through the high-level seaborn style 994 manager. 995 set_palette : Color codes can also be set through the function that 996 sets the matplotlib color cycle. 997 998 Examples 999 -------- 1000 1001 Map matplotlib color codes to the default seaborn palette. 1002 1003 .. plot:: 1004 :context: close-figs 1005 1006 >>> import matplotlib.pyplot as plt 1007 >>> import seaborn as sns; sns.set_theme() 1008 >>> sns.set_color_codes() 1009 >>> _ = plt.plot([0, 1], color="r") 1010 1011 Use a different seaborn palette. 1012 1013 .. plot:: 1014 :context: close-figs 1015 1016 >>> sns.set_color_codes("dark") 1017 >>> _ = plt.plot([0, 1], color="g") 1018 >>> _ = plt.plot([0, 2], color="m") 1019 1020 """ 1021 if palette == "reset": 1022 colors = [(0., 0., 1.), (0., .5, 0.), (1., 0., 0.), (.75, 0., .75), 1023 (.75, .75, 0.), (0., .75, .75), (0., 0., 0.)] 1024 elif not isinstance(palette, str): 1025 err = "set_color_codes requires a named seaborn palette" 1026 raise TypeError(err) 1027 elif palette in SEABORN_PALETTES: 1028 if not palette.endswith("6"): 1029 palette = palette + "6" 1030 colors = SEABORN_PALETTES[palette] + [(.1, .1, .1)] 1031 else: 1032 err = "Cannot set colors with palette '{}'".format(palette) 1033 raise ValueError(err) 1034 1035 for code, color in zip("bgrmyck", colors): 1036 rgb = mpl.colors.colorConverter.to_rgb(color) 1037 mpl.colors.colorConverter.colors[code] = rgb 1038 mpl.colors.colorConverter.cache[code] = rgb 1039