vedo.colors

Colors definitions and printing methods.

   1#!/usr/bin/env python3
   2# -*- coding: utf-8 -*-
   3import os
   4import sys
   5import time
   6
   7import numpy as np
   8import vedo.vtkclasses as vtk
   9import vedo
  10
  11__docformat__ = "google"
  12
  13__doc__ = """
  14Colors definitions and printing methods.
  15
  16![](https://vedo.embl.es/images/basic/colorcubes.png)
  17"""
  18
  19__all__ = [
  20    "printc",
  21    "printd",
  22    "get_color",
  23    "get_color_name",
  24    "color_map",
  25    "build_palette",
  26    "build_lut",
  27]
  28
  29
  30try:
  31    import matplotlib
  32    _has_matplotlib = True
  33    cmaps = {}
  34except ModuleNotFoundError:
  35    from vedo.cmaps import cmaps
  36    _has_matplotlib = False
  37    # see below, this is dealt with in color_map()
  38
  39#########################################################
  40# handy global shortcuts for terminal printing
  41# Ex.: print(colors.red + "hello" + colors.reset)
  42#########################################################
  43red = "\x1b[1m\x1b[31;1m"
  44green = "\x1b[1m\x1b[32;1m"
  45yellow = "\x1b[1m\x1b[33;1m"
  46blue = "\x1b[1m\x1b[34;1m"
  47reset = "\x1b[0m"
  48
  49
  50#########################################################
  51# basic color schemes
  52#########################################################
  53colors = {
  54    # order kind of matters because of pyplot.plot()
  55    "blue9": "#a8cbfe",  # bootstrap5 colors
  56    "blue8": "#81b4fe",
  57    "blue7": "#5a9cfe",
  58    "blue6": "#3485fd",
  59    "blue5": "#0d6efd",
  60    "blue4": "#0b5cd5",
  61    "blue3": "#094bac",
  62    "blue2": "#073984",
  63    "blue1": "#05285b",
  64    "indigo9": "#c8a9fa",
  65    "indigo8": "#af83f8",
  66    "indigo7": "#975cf6",
  67    "indigo6": "#7e36f4",
  68    "indigo5": "#6610f2",
  69    "indigo4": "#560dcb",
  70    "indigo3": "#450ba5",
  71    "indigo2": "#35087e",
  72    "indigo1": "#250657",
  73    "purple9": "#cbbbe9",
  74    "purple8": "#b49ddf",
  75    "purple7": "#9d7ed5",
  76    "purple6": "#8660cb",
  77    "purple5": "#6f42c1",
  78    "purple4": "#5d37a2",
  79    "purple3": "#4b2d83",
  80    "purple2": "#3a2264",
  81    "purple1": "#281845",
  82    "pink9": "#f0b6d3",
  83    "pink8": "#ea95bf",
  84    "pink7": "#e374ab",
  85    "pink6": "#dd5498",
  86    "pink5": "#d63384",
  87    "pink4": "#b42b6f",
  88    "pink3": "#92235a",
  89    "pink2": "#6f1b45",
  90    "pink1": "#4d1230",
  91    "red9": "#f2b6bc",
  92    "red8": "#ed969e",
  93    "red7": "#e77681",
  94    "red6": "#e25563",
  95    "red5": "#dc3545",
  96    "red4": "#b92d3a",
  97    "red3": "#96242f",
  98    "red2": "#721c24",
  99    "red1": "#4f1319",
 100    "orange9": "#fed1aa",
 101    "orange8": "#febc85",
 102    "orange7": "#fea75f",
 103    "orange6": "#fd933a",
 104    "orange5": "#fd7e14",
 105    "orange4": "#d56a11",
 106    "orange3": "#ac560e",
 107    "orange2": "#84420a",
 108    "orange1": "#5b2d07",
 109    "yellow9": "#ffe9a6",
 110    "yellow8": "#ffdf7e",
 111    "yellow7": "#ffd556",
 112    "yellow6": "#ffcb2f",
 113    "yellow5": "#ffc107",
 114    "yellow4": "#d6a206",
 115    "yellow3": "#ad8305",
 116    "yellow2": "#856404",
 117    "yellow1": "#5c4503",
 118    "green9": "#b2dfbc",
 119    "green8": "#8fd19e",
 120    "green7": "#6dc381",
 121    "green6": "#4ab563",
 122    "green5": "#28a745",
 123    "green4": "#228c3a",
 124    "green3": "#1b722f",
 125    "green2": "#155724",
 126    "green1": "#0e3c19",
 127    "teal9": "#afecda",
 128    "teal8": "#8be3c9",
 129    "teal7": "#67dab8",
 130    "teal6": "#44d2a8",
 131    "teal5": "#20c997",
 132    "teal4": "#1ba97f",
 133    "teal3": "#168967",
 134    "teal2": "#11694f",
 135    "teal1": "#0c4836",
 136    "cyan9": "#abdee5",
 137    "cyan8": "#86cfda",
 138    "cyan7": "#61c0cf",
 139    "cyan6": "#3cb1c3",
 140    "cyan5": "#17a2b8",
 141    "cyan4": "#13889b",
 142    "cyan3": "#106e7d",
 143    "cyan2": "#0c5460",
 144    "cyan1": "#083a42",
 145    "gray9": "#f8f9fa",
 146    "gray8": "#e9edef",
 147    "gray7": "#dee2e6",
 148    "gray6": "#ced4da",
 149    "gray5": "#adb5bd",
 150    "gray4": "#6c757d",
 151    "gray3": "#495057",
 152    "gray2": "#343a40",
 153    "gray1": "#212529",
 154    "aliceblue": "#F0F8FF",  # matplotlib scheme
 155    "antiquewhite": "#FAEBD7",
 156    "aqua": "#00FFFF",
 157    "aquamarine": "#7FFFD4",
 158    "azure": "#F0FFFF",
 159    "beige": "#F5F5DC",
 160    "bisque": "#FFE4C4",
 161    "black": "#000000",
 162    "blanchedalmond": "#FFEBCD",
 163    "blue": "#0f00fb",  # "0000FF",
 164    "blueviolet": "#8A2BE2",
 165    "brown": "#A52A2A",
 166    "burlywood": "#DEB887",
 167    "cadetblue": "#5F9EA0",
 168    "chartreuse": "#7FFF00",
 169    "chocolate": "#D2691E",
 170    "coral": "#FF7F50",
 171    "cornflowerblue": "#6495ED",
 172    "cornsilk": "#FFF8DC",
 173    "crimson": "#DC143C",
 174    "cyan": "#00FFFF",
 175    "darkblue": "#00008B",
 176    "darkcyan": "#008B8B",
 177    "darkgoldenrod": "#B8860B",
 178    "darkgray": "#A9A9A9",
 179    "darkgreen": "#006400",
 180    "darkkhaki": "#BDB76B",
 181    "darkmagenta": "#8B008B",
 182    "darkolivegreen": "#556B2F",
 183    "darkorange": "#FF8C00",
 184    "darkorchid": "#9932CC",
 185    "darkred": "#8B0000",
 186    "darksalmon": "#E9967A",
 187    "darkseagreen": "#8FBC8F",
 188    "darkslateblue": "#483D8B",
 189    "darkslategray": "#2F4F4F",
 190    "darkturquoise": "#00CED1",
 191    "darkviolet": "#9400D3",
 192    "deeppink": "#FF1493",
 193    "deepskyblue": "#00BFFF",
 194    "dimgray": "#696969",
 195    "dodgerblue": "#1E90FF",
 196    "firebrick": "#B22222",
 197    "floralwhite": "#FFFAF0",
 198    "forestgreen": "#228B22",
 199    "fuchsia": "#FF00FF",
 200    "gainsboro": "#DCDCDC",
 201    "ghostwhite": "#F8F8FF",
 202    "gold": "#FFD700",
 203    "goldenrod": "#DAA520",
 204    "gray": "#808080",
 205    "green": "#047f10",  # "#008000",
 206    "greenyellow": "#ADFF2F",
 207    "honeydew": "#F0FFF0",
 208    "hotpink": "#FF69B4",
 209    "indianred": "#CD5C5C",
 210    "indigo": "#4B0082",
 211    "ivory": "#FFFFF0",
 212    "khaki": "#F0E68C",
 213    "lavender": "#E6E6FA",
 214    "lavenderblush": "#FFF0F5",
 215    "lawngreen": "#7CFC00",
 216    "lemonchiffon": "#FFFACD",
 217    "lightblue": "#ADD8E6",
 218    "lightcoral": "#F08080",
 219    "lightcyan": "#E0FFFF",
 220    "lightgray": "#D3D3D3",
 221    "lightgreen": "#90EE90",
 222    "lightpink": "#FFB6C1",
 223    "lightsalmon": "#FFA07A",
 224    "lightseagreen": "#20B2AA",
 225    "lightskyblue": "#87CEFA",
 226    "lightsteelblue": "#B0C4DE",
 227    "lightyellow": "#FFFFE0",
 228    "lime": "#00FF00",
 229    "limegreen": "#32CD32",
 230    "linen": "#FAF0E6",
 231    "magenta": "#FF00FF",
 232    "maroon": "#800000",
 233    "mediumaquamarine": "#66CDAA",
 234    "mediumblue": "#0000CD",
 235    "mediumorchid": "#BA55D3",
 236    "mediumpurple": "#9370DB",
 237    "mediumseagreen": "#3CB371",
 238    "mediumslateblue": "#7B68EE",
 239    "mediumspringgreen": "#00FA9A",
 240    "mediumturquoise": "#48D1CC",
 241    "mediumvioletred": "#C71585",
 242    "midnightblue": "#191970",
 243    "mintcream": "#F5FFFA",
 244    "mistyrose": "#FFE4E1",
 245    "moccasin": "#FFE4B5",
 246    "navajowhite": "#FFDEAD",
 247    "navy": "#000080",
 248    "oldlace": "#FDF5E6",
 249    "olive": "#808000",
 250    "olivedrab": "#6B8E23",
 251    "orange": "#FFA500",
 252    "orangered": "#FF4500",
 253    "orchid": "#DA70D6",
 254    "palegoldenrod": "#EEE8AA",
 255    "palegreen": "#98FB98",
 256    "paleturquoise": "#AFEEEE",
 257    "palevioletred": "#DB7093",
 258    "papayawhip": "#FFEFD5",
 259    "peachpuff": "#FFDAB9",
 260    "peru": "#CD853F",
 261    "pink": "#FFC0CB",
 262    "plum": "#DDA0DD",
 263    "powderblue": "#B0E0E6",
 264    "purple": "#800080",
 265    "rebeccapurple": "#663399",
 266    "red": "#fe1e1f",  # "#FF0000",
 267    "rosybrown": "#BC8F8F",
 268    "royalblue": "#4169E1",
 269    "saddlebrown": "#8B4513",
 270    "salmon": "#FA8072",
 271    "sandybrown": "#F4A460",
 272    "seagreen": "#2E8B57",
 273    "seashell": "#FFF5EE",
 274    "sienna": "#A0522D",
 275    "silver": "#C0C0C0",
 276    "skyblue": "#87CEEB",
 277    "slateblue": "#6A5ACD",
 278    "slategray": "#708090",
 279    "snow": "#FFFAFA",
 280    "blackboard": "#393939",
 281    "springgreen": "#00FF7F",
 282    "steelblue": "#4682B4",
 283    "tan": "#D2B48C",
 284    "teal": "#008080",
 285    "thistle": "#D8BFD8",
 286    "tomato": "#FF6347",
 287    "turquoise": "#40E0D0",
 288    "violet": "#EE82EE",
 289    "wheat": "#F5DEB3",
 290    "white": "#FFFFFF",
 291    "whitesmoke": "#F5F5F5",
 292    "yellow": "#ffff36",  # "#FFFF00",
 293    "yellowgreen": "#9ACD32",
 294}
 295
 296
 297color_nicks = {  # color nicknames
 298    "bb": "blackboard",
 299    "lb": "lightblue",  # light
 300    "lg": "lightgreen",
 301    "lr": "orangered",
 302    "lc": "lightcyan",
 303    "ls": "lightsalmon",
 304    "ly": "lightyellow",
 305    "dr": "darkred",  # dark
 306    "db": "darkblue",
 307    "dg": "darkgreen",
 308    "dm": "darkmagenta",
 309    "dc": "darkcyan",
 310    "ds": "darksalmon",
 311    "dv": "darkviolet",
 312    "b1": "blue1",  # bootstrap5 colors
 313    "b2": "blue2",
 314    "b3": "blue3",
 315    "b4": "blue4",
 316    "b5": "blue5",
 317    "b6": "blue6",
 318    "b7": "blue7",
 319    "b8": "blue8",
 320    "b9": "blue9",
 321    "i1": "indigo1",
 322    "i2": "indigo2",
 323    "i3": "indigo3",
 324    "i4": "indigo4",
 325    "i5": "indigo5",
 326    "i6": "indigo6",
 327    "i7": "indigo7",
 328    "i8": "indigo8",
 329    "i9": "indigo9",
 330    "p1": "purple1",
 331    "p2": "purple2",
 332    "p3": "purple3",
 333    "p4": "purple4",
 334    "p5": "purple5",
 335    "p6": "purple6",
 336    "p7": "purple7",
 337    "p8": "purple8",
 338    "p9": "purple9",
 339    "r1": "red1",
 340    "r2": "red2",
 341    "r3": "red3",
 342    "r4": "red4",
 343    "r5": "red5",
 344    "r6": "red6",
 345    "r7": "red7",
 346    "r8": "red8",
 347    "r9": "red9",
 348    "o1": "orange1",
 349    "o2": "orange2",
 350    "o3": "orange3",
 351    "o4": "orange4",
 352    "o5": "orange5",
 353    "o6": "orange6",
 354    "o7": "orange7",
 355    "o8": "orange8",
 356    "o9": "orange9",
 357    "y1": "yellow1",
 358    "y2": "yellow2",
 359    "y3": "yellow3",
 360    "y4": "yellow4",
 361    "y5": "yellow5",
 362    "y6": "yellow6",
 363    "y7": "yellow7",
 364    "y8": "yellow8",
 365    "y9": "yellow9",
 366    "g1": "green1",
 367    "g2": "green2",
 368    "g3": "green3",
 369    "g4": "green4",
 370    "g5": "green5",
 371    "g6": "green6",
 372    "g7": "green7",
 373    "g8": "green8",
 374    "g9": "green9",
 375    "k1": "gray1",
 376    "k2": "gray2",
 377    "k3": "gray3",
 378    "k4": "gray4",
 379    "k5": "gray5",
 380    "k6": "gray6",
 381    "k7": "gray7",
 382    "k8": "gray8",
 383    "k9": "gray9",
 384    "a": "aqua",
 385    "b": "blue",
 386    "c": "cyan",
 387    "d": "gold",
 388    "f": "fuchsia",
 389    "g": "green",
 390    "i": "indigo",
 391    "k": "black",
 392    "m": "magenta",
 393    "n": "navy",
 394    "l": "lavender",
 395    "o": "orange",
 396    "p": "purple",
 397    "r": "red",
 398    "s": "salmon",
 399    "t": "tomato",
 400    "v": "violet",
 401    "y": "yellow",
 402    "w": "white",
 403}
 404
 405
 406# available colormap names:
 407cmaps_names = (
 408    "Accent",
 409    "Accent_r",
 410    "Blues",
 411    "Blues_r",
 412    "BrBG",
 413    "BrBG_r",
 414    "BuGn",
 415    "BuGn_r",
 416    "BuPu",
 417    "BuPu_r",
 418    "CMRmap",
 419    "CMRmap_r",
 420    "Dark2",
 421    "Dark2_r",
 422    "GnBu",
 423    "GnBu_r",
 424    "Greens",
 425    "Greens_r",
 426    "Greys",
 427    "Greys_r",
 428    "OrRd",
 429    "OrRd_r",
 430    "Oranges",
 431    "Oranges_r",
 432    "PRGn",
 433    "PRGn_r",
 434    "Paired",
 435    "Paired_r",
 436    "Pastel1",
 437    "Pastel1_r",
 438    "Pastel2",
 439    "Pastel2_r",
 440    "PiYG",
 441    "PiYG_r",
 442    "PuBu",
 443    "PuBuGn",
 444    "PuBuGn_r",
 445    "PuBu_r",
 446    "PuOr",
 447    "PuOr_r",
 448    "PuRd",
 449    "PuRd_r",
 450    "Purples",
 451    "Purples_r",
 452    "RdBu",
 453    "RdBu_r",
 454    "RdGy",
 455    "RdGy_r",
 456    "RdPu",
 457    "RdPu_r",
 458    "RdYlBu",
 459    "RdYlBu_r",
 460    "RdYlGn",
 461    "RdYlGn_r",
 462    "Reds",
 463    "Reds_r",
 464    "Set1",
 465    "Set1_r",
 466    "Set2",
 467    "Set2_r",
 468    "Set3",
 469    "Set3_r",
 470    "Spectral",
 471    "Spectral_r",
 472    "Wistia",
 473    "Wistia_r",
 474    "YlGn",
 475    "YlGnBu",
 476    "YlGnBu_r",
 477    "YlGn_r",
 478    "YlOrBr",
 479    "YlOrBr_r",
 480    "YlOrRd",
 481    "YlOrRd_r",
 482    "afmhot",
 483    "afmhot_r",
 484    "autumn",
 485    "autumn_r",
 486    "binary",
 487    "binary_r",
 488    "bone",
 489    "bone_r",
 490    "brg",
 491    "brg_r",
 492    "bwr",
 493    "bwr_r",
 494    "cividis",
 495    "cividis_r",
 496    "cool",
 497    "cool_r",
 498    "coolwarm",
 499    "coolwarm_r",
 500    "copper",
 501    "copper_r",
 502    "cubehelix",
 503    "cubehelix_r",
 504    "flag",
 505    "flag_r",
 506    "gist_earth",
 507    "gist_earth_r",
 508    "gist_gray",
 509    "gist_gray_r",
 510    "gist_heat",
 511    "gist_heat_r",
 512    "gist_ncar",
 513    "gist_ncar_r",
 514    "gist_rainbow",
 515    "gist_rainbow_r",
 516    "gist_stern",
 517    "gist_stern_r",
 518    "gist_yarg",
 519    "gist_yarg_r",
 520    "gnuplot",
 521    "gnuplot2",
 522    "gnuplot2_r",
 523    "gnuplot_r",
 524    "gray_r",
 525    "hot",
 526    "hot_r",
 527    "hsv",
 528    "hsv_r",
 529    "inferno",
 530    "inferno_r",
 531    "jet",
 532    "jet_r",
 533    "magma",
 534    "magma_r",
 535    "nipy_spectral",
 536    "nipy_spectral_r",
 537    "ocean",
 538    "ocean_r",
 539    "pink_r",
 540    "plasma",
 541    "plasma_r",
 542    "prism",
 543    "prism_r",
 544    "rainbow",
 545    "rainbow_r",
 546    "seismic",
 547    "seismic_r",
 548    "spring",
 549    "spring_r",
 550    "summer",
 551    "summer_r",
 552    "tab10",
 553    "tab10_r",
 554    "tab20",
 555    "tab20_r",
 556    "tab20b",
 557    "tab20b_r",
 558    "tab20c",
 559    "tab20c_r",
 560    "terrain",
 561    "terrain_r",
 562    "twilight",
 563    "twilight_r",
 564    "twilight_shifted",
 565    "twilight_shifted_r",
 566    "viridis",
 567    "viridis_r",
 568    "winter",
 569    "winter_r",
 570)
 571
 572
 573# default color palettes when using an index
 574palettes = (
 575    (
 576       [1.        , 0.75686275, 0.02745098], # yellow5
 577       [0.99215686, 0.49411765, 0.07843137], # orange5
 578       [0.8627451 , 0.20784314, 0.27058824], # red5
 579       [0.83921569, 0.2       , 0.51764706], # pink5
 580       [0.1254902 , 0.78823529, 0.59215686], # teal5
 581       [0.15686275, 0.65490196, 0.27058824], # green5
 582       [0.09019608, 0.63529412, 0.72156863], # cyan5
 583       [0.05098039, 0.43137255, 0.99215686], # blue5
 584       [0.4       , 0.0627451 , 0.94901961], # indigo5
 585       [0.67843137, 0.70980392, 0.74117647], # gray5
 586    ),
 587    (
 588        (1.0, 0.832, 0.000),  # gold
 589        (0.960, 0.509, 0.188),
 590        (0.901, 0.098, 0.194),
 591        (0.235, 0.85, 0.294),
 592        (0.46, 0.48, 0.000),
 593        (0.274, 0.941, 0.941),
 594        (0.0, 0.509, 0.784),
 595        (0.1, 0.1, 0.900),
 596        (0.902, 0.7, 1.000),
 597        (0.941, 0.196, 0.901),
 598    ),
 599    (
 600        (1.0, 0.832, 0),    # gold
 601        (0.59, 0.0, 0.09),  # dark red
 602        (0.5, 0.5, 0),      # yellow-green
 603        (0.0, 0.66, 0.42),  # green blue
 604        (0.5, 1.0, 0.0),    # green
 605        (0.0, 0.18, 0.65),  # blue
 606        (0.4, 0.0, 0.4),    # plum
 607        (0.4, 0.0, 0.6),
 608        (0.2, 0.4, 0.6),
 609        (0.1, 0.3, 0.2),
 610    ),
 611    (
 612        (0.010, 0.0706, 0.098),  #  -> black
 613        (0.0196, 0.369, 0.447),
 614        (0.0745, 0.573, 0.584),
 615        (0.584, 0.820, 0.741),
 616        (0.914, 0.847, 0.663),
 617        (0.929, 0.616, 0.149),
 618        (0.788, 0.412, 0.110),
 619        (0.729, 0.259, 0.0902),
 620        (0.678, 0.153, 0.110),
 621        (0.604, 0.153, 0.165),  #  -> red3
 622    ),
 623    (
 624        (0.345, 0.188, 0.071),  #  -> orange1
 625        (0.498, 0.314, 0.161),
 626        (0.573, 0.404, 0.239),
 627        (0.651, 0.545, 0.400),
 628        (0.714, 0.678, 0.569),
 629        (0.761, 0.773, 0.671),
 630        (0.643, 0.675, 0.533),
 631        (0.396, 0.427, 0.298),
 632        (0.255, 0.282, 0.204),
 633        (0.200, 0.239, 0.165),  #  -> blackboard
 634    ),
 635    (
 636        (0.937, 0.969, 0.820),  #  -> beige
 637        (0.729, 0.851, 0.714),
 638        (0.671, 0.639, 0.396),
 639        (0.447, 0.180, 0.180),
 640        (0.259, 0.055, 0.082),  #  -> red1
 641        (0.937, 0.969, 0.820),  #  -> beige
 642        (0.729, 0.851, 0.714),
 643        (0.671, 0.639, 0.396),
 644        (0.447, 0.180, 0.180),
 645        (0.259, 0.055, 0.082),  #  -> red1
 646    ),
 647    (
 648        (0.933, 0.298, 0.443),  #  -> red6
 649        (0.996, 0.824, 0.431),
 650        (0.082, 0.835, 0.631),
 651        (0.094, 0.537, 0.690),
 652        (0.035, 0.231, 0.294),  #  -> cyan1
 653        (0.933, 0.298, 0.443),  #  -> red6
 654        (0.996, 0.824, 0.431),
 655        (0.082, 0.835, 0.631),
 656        (0.094, 0.537, 0.690),
 657        (0.035, 0.231, 0.294),  #  -> cyan1
 658    ),
 659)
 660
 661
 662emoji = {
 663    ":bomb:": "\U0001F4A5",
 664    ":sparks:": "\U00002728",
 665    ":thumbup:": "\U0001F44D",
 666    ":target:": "\U0001F3AF",
 667    ":save:": "\U0001F4BE",
 668    ":noentry:": "\U000026D4",
 669    ":video:": "\U0001F4FD",
 670    ":lightning:": "\U000026A1",
 671    ":camera:": "\U0001F4F8",
 672    ":times:": "\U0000274C",
 673    ":world:": "\U0001F30D",
 674    ":rainbow:": "\U0001F308",
 675    ":idea:": "\U0001F4A1",
 676    ":pin:": "\U0001F4CC",
 677    ":construction:": "\U0001F6A7",
 678    ":rocket:": "\U0001F680",
 679    ":hourglass:": "\U000023F3",
 680    ":prohibited:": "\U0001F6AB",
 681    ":checked:": "\U00002705",
 682    ":smile:": "\U0001F642",
 683    ":sad:": "\U0001F612",
 684    ":star:": "\U00002B50",
 685    ":zzz:": "\U0001F4A4",
 686    ":mu:": "\U000003BC",
 687    ":pi:": "\U000003C0",
 688    ":sigma:": "\U000003C3",
 689    ":rightarrow:": "\U000027A1",
 690}
 691
 692
 693# terminal or notebook can do color print
 694def _has_colors(stream):
 695    try:
 696        import IPython
 697        return True
 698    except:
 699        pass
 700
 701    if not hasattr(stream, "isatty"):
 702        return False
 703    if not stream.isatty():
 704        return False
 705    return True
 706_terminal_has_colors = _has_colors(sys.stdout)
 707
 708
 709def _is_sequence(arg):
 710    # Check if input is iterable.
 711    if hasattr(arg, "strip"):
 712        return False
 713    if hasattr(arg, "__getslice__"):
 714        return True
 715    if hasattr(arg, "__iter__"):
 716        return True
 717    return False
 718
 719
 720def get_color(rgb=None, hsv=None):
 721    """
 722    Convert a color or list of colors to (r,g,b) format from many different input formats.
 723
 724    Set `hsv` to input as (hue, saturation, value).
 725
 726    Example:
 727         - `RGB    = (255, 255, 255)` corresponds to white
 728         - `rgb    = (1,1,1)` is again white
 729         - `hex    = #FFFF00` is yellow
 730         - `string = 'white'`
 731         - `string = 'w'` is white nickname
 732         - `string = 'dr'` is darkred
 733         - `string = 'red4'` is a shade of red
 734         - `int    =  7` picks color nr. 7 in a predefined color list
 735         - `int    = -7` picks color nr. 7 in a different predefined list
 736
 737
 738    Examples:
 739        - [colorcubes.py](https://github.com/marcomusy/vedo/tree/master/examples/basic/colorcubes.py)
 740
 741            ![](https://vedo.embl.es/images/basic/colorcubes.png)
 742    """
 743    # recursion, return a list if input is list of colors:
 744    if _is_sequence(rgb) and (len(rgb) > 3 or _is_sequence(rgb[0])):
 745        seqcol = []
 746        for sc in rgb:
 747            seqcol.append(get_color(sc))
 748        return seqcol
 749
 750    # because they are most common:
 751    if isinstance(rgb, str):
 752        if rgb == "r":
 753            return (0.9960784313725, 0.11764705882352, 0.121568627450980)
 754        elif rgb == "g":
 755            return (0.0156862745098, 0.49803921568627, 0.062745098039215)
 756        elif rgb == "b":
 757            return (0.0588235294117, 0.0, 0.984313725490196)
 758
 759    if str(rgb).isdigit():
 760        rgb = int(rgb)
 761
 762    if hsv:
 763        c = hsv2rgb(hsv)
 764    else:
 765        c = rgb
 766
 767    if _is_sequence(c):
 768        if c[0] <= 1 and c[1] <= 1 and c[2] <= 1:
 769            return c  # already rgb
 770        if len(c) == 3:
 771            return list(np.array(c) / 255.0)  # RGB
 772        return (c[0] / 255.0, c[1] / 255.0, c[2] / 255.0, c[3])  # RGBA
 773
 774    elif isinstance(c, str):  # is string
 775        c = c.replace("grey", "gray").replace(" ", "")
 776        if 0 < len(c) < 3:  # single/double letter color
 777            if c.lower() in color_nicks:
 778                c = color_nicks[c.lower()]
 779            else:
 780                vedo.logger.warning(
 781                    f"Unknown color nickname {c}\nAvailable abbreviations: {color_nicks}"
 782                )
 783                return (0.5, 0.5, 0.5)
 784
 785        if c.lower() in colors:  # matplotlib name color
 786            c = colors[c.lower()]
 787            # from now format is hex!
 788
 789        if c.startswith("#"):  # hex to rgb
 790            h = c.lstrip("#")
 791            rgb255 = list(int(h[i : i + 2], 16) for i in (0, 2, 4))
 792            rgbh = np.array(rgb255) / 255.0
 793            if np.sum(rgbh) > 3:
 794                vedo.logger.error(f"in get_color(): Wrong hex color {c}")
 795                return (0.5, 0.5, 0.5)
 796            return tuple(rgbh)
 797
 798        else:  # vtk name color
 799            namedColors = vtk.new("NamedColors")
 800            rgba = [0, 0, 0, 0]
 801            namedColors.GetColor(c, rgba)
 802            return (rgba[0] / 255.0, rgba[1] / 255.0, rgba[2] / 255.0)
 803
 804    elif isinstance(c, (int, float)):  # color number
 805        return palettes[vedo.settings.palette % len(palettes)][abs(int(c)) % 10]
 806
 807    return (0.5, 0.5, 0.5)
 808
 809
 810def get_color_name(c):
 811    """Find the name of the closest color."""
 812    c = np.array(get_color(c))  # reformat to rgb
 813    mdist = 99.0
 814    kclosest = ""
 815    for key in colors:
 816        ci = np.array(get_color(key))
 817        d = np.linalg.norm(c - ci)
 818        if d < mdist:
 819            mdist = d
 820            kclosest = str(key)
 821    return kclosest
 822
 823
 824def hsv2rgb(hsv):
 825    """Convert HSV to RGB color."""
 826    ma = vtk.new("Math")
 827    rgb = [0, 0, 0]
 828    ma.HSVToRGB(hsv, rgb)
 829    return rgb
 830
 831
 832def rgb2hsv(rgb):
 833    """Convert RGB to HSV color."""
 834    ma = vtk.new("Math")
 835    hsv = [0, 0, 0]
 836    ma.RGBToHSV(get_color(rgb), hsv)
 837    return hsv
 838
 839
 840def rgb2hex(rgb):
 841    """Convert RGB to Hex color."""
 842    h = "#%02x%02x%02x" % (int(rgb[0] * 255), int(rgb[1] * 255), int(rgb[2] * 255))
 843    return h
 844
 845
 846def hex2rgb(hx):
 847    """Convert Hex to rgb color."""
 848    h = hx.lstrip("#")
 849    rgb255 = [int(h[i : i + 2], 16) for i in (0, 2, 4)]
 850    return (rgb255[0] / 255.0, rgb255[1] / 255.0, rgb255[2] / 255.0)
 851
 852
 853def color_map(value, name="jet", vmin=None, vmax=None):
 854    """
 855    Map a real value in range [vmin, vmax] to a (r,g,b) color scale.
 856
 857    Return the (r,g,b) color, or a list of (r,g,b) colors.
 858
 859    Arguments:
 860        value : (float, list)
 861            scalar value to transform into a color
 862        name : (str, matplotlib.colors.LinearSegmentedColormap)
 863            color map name
 864
 865    Very frequently used color maps are:
 866
 867        ![](https://user-images.githubusercontent.com/32848391/50738804-577e1680-11d8-11e9-929e-fca17a8ac6f3.jpg)
 868
 869    A more complete color maps list:
 870
 871        ![](https://matplotlib.org/1.2.1/_images/show_colormaps.png)
 872
 873    .. note:: Can also directly use and customize a matplotlib color map
 874
 875    Example:
 876        ```python
 877        import matplotlib
 878        from vedo import color_map
 879        rgb = color_map(0.2, matplotlib.colormaps["jet"], 0, 1)
 880        print("rgb =", rgb)  # [0.0, 0.3, 1.0]
 881        ```
 882
 883    Examples:
 884        - [plot_bars.py](https://github.com/marcomusy/vedo/tree/master/examples/pyplot/plot_bars.py)
 885
 886            <img src="https://vedo.embl.es/images/pyplot/plot_bars.png" width="400"/>
 887
 888    """
 889    cut = _is_sequence(value)  # to speed up later
 890
 891    if cut:
 892        values = np.asarray(value)
 893        if vmin is None:
 894            vmin = np.min(values)
 895        if vmax is None:
 896            vmax = np.max(values)
 897        values = np.clip(values, vmin, vmax)
 898        values = (values - vmin) / (vmax - vmin)
 899    else:
 900        if vmin is None:
 901            vedo.logger.warning("in color_map() you must specify vmin! Assume 0.")
 902            vmin = 0
 903        if vmax is None:
 904            vedo.logger.warning("in color_map() you must specify vmax! Assume 1.")
 905            vmax = 1
 906        values = [(value - vmin) / (vmax - vmin)]
 907
 908    if _has_matplotlib:
 909        # matplotlib is available, use it! ###########################
 910        if isinstance(name, str):
 911            mp = matplotlib.colormaps[name]
 912        else:
 913            mp = name  # assume matplotlib.colors.LinearSegmentedColormap
 914        result = mp(values)[:, [0, 1, 2]]
 915
 916    else:
 917        # matplotlib not available ###################################
 918        invert = False
 919        if name.endswith("_r"):
 920            invert = True
 921            name = name.replace("_r", "")
 922        try:
 923            cmap = cmaps[name]
 924        except KeyError:
 925            vedo.logger.error(f"in color_map(), no color map with name {name} or {name}_r")
 926            vedo.logger.error(f"Available color maps are:\n{cmaps.keys()}")
 927            return np.array([0.5, 0.5, 0.5])
 928
 929        result = []
 930        n = len(cmap) - 1
 931        for v in values:
 932            iv = int(v * n)
 933            if invert:
 934                iv = n - iv
 935            rgb = hex2rgb(cmap[iv])
 936            result.append(rgb)
 937        result = np.array(result)
 938
 939    if cut:
 940        return result
 941    return result[0]
 942
 943
 944def build_palette(color1, color2, n, hsv=True):
 945    """
 946    Generate N colors starting from `color1` to `color2`
 947    by linear interpolation in HSV or RGB spaces.
 948
 949    Arguments:
 950        N : (int)
 951            number of output colors.
 952        color1 : (color)
 953            first color.
 954        color2 : (color)
 955            second color.
 956        hsv : (bool)
 957            if `False`, interpolation is calculated in RGB space.
 958
 959    Examples:
 960        - [mesh_custom.py](https://github.com/marcomusy/vedo/tree/master/examples/basic/mesh_custom.py)
 961
 962            ![](https://vedo.embl.es/images/basic/mesh_custom.png)
 963    """
 964    if hsv:
 965        color1 = rgb2hsv(color1)
 966        color2 = rgb2hsv(color2)
 967    c1 = np.array(get_color(color1))
 968    c2 = np.array(get_color(color2))
 969    cols = []
 970    for f in np.linspace(0, 1, n, endpoint=True):
 971        c = c1 * (1 - f) + c2 * f
 972        if hsv:
 973            c = np.array(hsv2rgb(c))
 974        cols.append(c)
 975    return np.array(cols)
 976
 977
 978def build_lut(
 979    colorlist,
 980    vmin=None,
 981    vmax=None,
 982    below_color=None,
 983    above_color=None,
 984    nan_color=None,
 985    below_alpha=1,
 986    above_alpha=1,
 987    nan_alpha=1,
 988    interpolate=False,
 989):
 990    """
 991    Generate colors in a lookup table (LUT).
 992
 993    Return the `vtkLookupTable` object. This can be fed into `cmap()` method.
 994
 995    Arguments:
 996        colorlist : (list)
 997            a list in the form `[(scalar1, [r,g,b]), (scalar2, 'blue'), ...]`.
 998        vmin : (float)
 999            specify minimum value of scalar range
1000        vmax : (float)
1001            specify maximum value of scalar range
1002        below_color : (color)
1003            color for scalars below the minimum in range
1004        below_alpha : (float)
1005            opacity for scalars below the minimum in range
1006        above_color : (color)
1007            color for scalars above the maximum in range
1008        above_alpha : (float)
1009            alpha for scalars above the maximum in range
1010        nan_color : (color)
1011            color for invalid (nan) scalars
1012        nan_alpha : (float)
1013            alpha for invalid (nan) scalars
1014        interpolate : (bool)
1015            interpolate or not intermediate scalars
1016
1017    Examples:
1018        - [mesh_lut.py](https://github.com/marcomusy/vedo/tree/master/examples/basic/mesh_lut.py)
1019
1020            ![](https://vedo.embl.es/images/basic/mesh_lut.png)
1021    """
1022    ctf = vtk.new("ColorTransferFunction")
1023    ctf.SetColorSpaceToRGB()
1024    ctf.SetScaleToLinear()
1025    alpha_x, alpha_vals = [], []
1026    for sc in colorlist:
1027        if len(sc) >= 3:
1028            scalar, col, alf = sc[:3]
1029        else:
1030            alf = 1
1031            scalar, col = sc
1032        r, g, b = get_color(col)
1033        ctf.AddRGBPoint(scalar, r, g, b)
1034        alpha_x.append(scalar)
1035        alpha_vals.append(alf)
1036
1037    lut = vtk.new("LookupTable")
1038    lut.SetNumberOfTableValues(256)
1039
1040    x0, x1 = ctf.GetRange()  # range of the introduced values
1041    if vmin is not None:
1042        x0 = vmin
1043    if vmax is not None:
1044        x1 = vmax
1045    ctf.SetRange(x0, x1)
1046    lut.SetRange(x0, x1)
1047
1048    if below_color is not None:
1049        lut.SetBelowRangeColor(list(get_color(below_color)) + [below_alpha])
1050        lut.SetUseBelowRangeColor(True)
1051    if above_color is not None:
1052        lut.SetAboveRangeColor(list(get_color(above_color)) + [above_alpha])
1053        lut.SetUseAboveRangeColor(True)
1054    if nan_color is not None:
1055        lut.SetNanColor(list(get_color(nan_color)) + [nan_alpha])
1056
1057    rgba = (1, 1, 1, 1)
1058    for i in range(256):
1059        p = i / 255
1060        x = (1 - p) * x0 + p * x1
1061        if interpolate:
1062            alf = np.interp(x, alpha_x, alpha_vals)
1063            rgba = list(ctf.GetColor(x)) + [alf]
1064        else:
1065            for c in colorlist:
1066                if x <= c[0]:
1067                    if len(c) == 3:
1068                        alf = c[2]
1069                    else:
1070                        alf = 1
1071                    rgba = list(get_color(c[1])) + [alf]
1072                    break
1073        lut.SetTableValue(i, rgba)
1074
1075    lut.Build()
1076    return lut
1077
1078
1079#########################################################################
1080def printc(
1081    *strings,
1082    c=None,
1083    bc=None,
1084    bold=True,
1085    italic=False,
1086    blink=False,
1087    underline=False,
1088    strike=False,
1089    dim=False,
1090    invert=False,
1091    box="",
1092    link="",
1093    end="\n",
1094    flush=True,
1095    return_string=False,
1096):
1097    """
1098    Print to terminal in color (any color!).
1099
1100    Arguments:
1101        c : (color)
1102            foreground color name or (r,g,b)
1103        bc : (color)
1104            background color name or (r,g,b)
1105        bold : (bool)
1106            boldface [True]
1107        italic : (bool)
1108            italic [False]
1109        blink : (bool)
1110            blinking text [False]
1111        underline : (bool)
1112            underline text [False]
1113        strike : (bool)
1114            strike through text [False]
1115        dim : (bool)
1116            make text look dimmer [False]
1117        invert : (bool)
1118            invert background and forward colors [False]
1119        box : (bool)
1120            print a box with specified text character ['']
1121        link : (str)
1122            print a clickable url link (works on Linux)
1123            (must press Ctrl+click to open the link)
1124        flush : (bool)
1125            flush buffer after printing [True]
1126        return_string : (bool)
1127            return the string without printing it [False]
1128        end : (str)
1129            the end character to be printed [newline]
1130
1131    Example:
1132        ```python
1133        from vedo.colors import printc
1134        printc('anything', c='tomato', bold=False, end=' ')
1135        printc('anything', 455.5, c='lightblue')
1136        printc(299792.48, c=4)
1137        ```
1138
1139    Examples:
1140        - [printc.py](https://github.com/marcomusy/vedo/tree/master/examples/other/printc.py)
1141
1142        ![](https://user-images.githubusercontent.com/32848391/50739010-2bfc2b80-11da-11e9-94de-011e50a86e61.jpg)
1143    """
1144
1145    if not vedo.settings.enable_print_color or not _terminal_has_colors:
1146        if return_string:
1147            return ''.join(strings)
1148        else:
1149            print(*strings, end=end, flush=flush)
1150            return
1151
1152    try:  # -------------------------------------------------------------
1153
1154        txt = str()
1155        ns = len(strings) - 1
1156        separator = " "
1157        offset = 0
1158        for i, s in enumerate(strings):
1159            if i == ns:
1160                separator = ""
1161            if ":" in repr(s):
1162                for k in emoji:
1163                    if k in str(s):
1164                        s = s.replace(k, emoji[k])
1165                        offset += 1
1166                for k, rp in vedo.shapes._reps:  # check symbols in shapes._reps
1167                    if k in str(s):
1168                        s = s.replace(k, rp)
1169                        offset += 1
1170
1171            txt += str(s) + separator
1172
1173        special, cseq = "", ""
1174        oneletter_colors = {
1175            "k": "\u001b[30m",  # because these are supported by most terminals
1176            "r": "\u001b[31m",
1177            "g": "\u001b[32m",
1178            "y": "\u001b[33m",
1179            "b": "\u001b[34m",
1180            "m": "\u001b[35m",
1181            "c": "\u001b[36m",
1182            "w": "\u001b[37m",
1183        }
1184
1185        if c is not None:
1186            if c is True:
1187                c = "g"
1188            elif c is False:
1189                c = "r"
1190
1191            if isinstance(c, str) and c in oneletter_colors:
1192                cseq += oneletter_colors[c]
1193            else:
1194                r, g, b = get_color(c)  # not all terms support this syntax
1195                cseq += f"\x1b[38;2;{int(r*255)};{int(g*255)};{int(b*255)}m"
1196
1197        if bc:
1198            if bc in oneletter_colors:
1199                cseq += oneletter_colors[bc]
1200            else:
1201                r, g, b = get_color(bc)
1202                cseq += f"\x1b[48;2;{int(r*255)};{int(g*255)};{int(b*255)}m"
1203
1204        if box is True:
1205            box = "-"
1206        if underline and not box:
1207            special += "\x1b[4m"
1208        if strike and not box:
1209            special += "\x1b[9m"
1210        if dim:
1211            special += "\x1b[2m"
1212        if invert:
1213            special += "\x1b[7m"
1214        if bold:
1215            special += "\x1b[1m"
1216        if italic:
1217            special += "\x1b[3m"
1218        if blink:
1219            special += "\x1b[5m"
1220
1221        if box and "\n" not in txt:
1222            box = box[0]
1223            boxv = box
1224            if box in ["_", "=", "-", "+", "~"]:
1225                boxv = "|"
1226
1227            if box in ("_", "."):
1228                outtxt = special + cseq + " " + box * (len(txt) + offset + 2) + " \n"
1229                outtxt += boxv + " " * (len(txt) + 2) + boxv + "\n"
1230            else:
1231                outtxt = special + cseq + box * (len(txt) + offset + 4) + "\n"
1232
1233            outtxt += boxv + " " + txt + " " + boxv + "\n"
1234
1235            if box == "_":
1236                outtxt += "|" + box * (len(txt) + offset + 2) + "|" + reset + end
1237            else:
1238                outtxt += box * (len(txt) + offset + 4) + reset + end
1239
1240            sys.stdout.write(outtxt)
1241
1242        else:
1243
1244            out = special + cseq + txt + reset
1245
1246            if link:
1247                # embed a link in the terminal
1248                out = f"\x1b]8;;{link}\x1b\\{out}\x1b]8;;\x1b\\"
1249
1250            if return_string:
1251                return out + end
1252            else:
1253                sys.stdout.write(out + end)
1254
1255    except:  # --------------------------------------------------- fallback
1256
1257        if return_string:
1258            return ''.join(strings)
1259
1260        try:
1261            print(*strings, end=end)
1262        except UnicodeEncodeError as e:
1263            print(e, end=end)
1264            pass
1265
1266    if flush:
1267        sys.stdout.flush()
1268
1269
1270def printd(*strings, q=False):
1271    """
1272    Print debug information about the environment where the printd() is called.
1273    Local variables are printed out with their current values.
1274
1275    Use `q` to quit (exit) the python session after the printd call.
1276    """
1277    from inspect import currentframe, getframeinfo
1278
1279    cf = currentframe().f_back
1280    cfi = getframeinfo(cf)
1281
1282    fname = os.path.basename(getframeinfo(cf).filename)
1283    print("\x1b[7m\x1b[3m\x1b[37m" + fname + " line:\x1b[1m" + str(cfi.lineno) + reset, end="")
1284    print("\x1b[3m\x1b[37m\x1b[2m", "\U00002501" * 30, time.ctime(), reset)
1285    if strings:
1286        print("    \x1b[37m\x1b[1mMessage : ", *strings)
1287    print("    \x1b[37m\x1b[1mFunction:\x1b[0m\x1b[37m " + str(cfi.function))
1288    print("    \x1b[1mLocals  :" + reset)
1289    for loc in cf.f_locals.keys():
1290        obj = cf.f_locals[loc]
1291        var = repr(obj)
1292        if 'module ' in var: continue
1293        if 'function ' in var: continue
1294        if 'class ' in var: continue
1295        if loc.startswith('_'): continue
1296        if hasattr(obj, 'name'):
1297            if not obj.name:
1298                oname = str(type(obj))
1299            else:
1300                oname = obj.name
1301            var = oname + ", at " + vedo.utils.precision(obj.GetPosition(), 3)
1302
1303        var = var.replace("vtkmodules.", "")
1304        print("      \x1b[37m", loc, "\t\t=", var[:60].replace("\n", ""), reset)
1305        if vedo.utils.is_sequence(obj) and len(obj) > 4:
1306            print('           \x1b[37m\x1b[2m\x1b[3m len:', len(obj),
1307                  ' min:', vedo.utils.precision(min(obj), 4),
1308                  ' max:', vedo.utils.precision(max(obj), 4),
1309                  reset)
1310
1311    if q:
1312        print(f"    \x1b[1m\x1b[37mExiting python now (q={bool(q)}).\x1b[0m\x1b[37m")
1313        sys.exit(0)
1314    sys.stdout.flush()
def printc( *strings, c=None, bc=None, bold=True, italic=False, blink=False, underline=False, strike=False, dim=False, invert=False, box='', link='', end='\n', flush=True, return_string=False):
1081def printc(
1082    *strings,
1083    c=None,
1084    bc=None,
1085    bold=True,
1086    italic=False,
1087    blink=False,
1088    underline=False,
1089    strike=False,
1090    dim=False,
1091    invert=False,
1092    box="",
1093    link="",
1094    end="\n",
1095    flush=True,
1096    return_string=False,
1097):
1098    """
1099    Print to terminal in color (any color!).
1100
1101    Arguments:
1102        c : (color)
1103            foreground color name or (r,g,b)
1104        bc : (color)
1105            background color name or (r,g,b)
1106        bold : (bool)
1107            boldface [True]
1108        italic : (bool)
1109            italic [False]
1110        blink : (bool)
1111            blinking text [False]
1112        underline : (bool)
1113            underline text [False]
1114        strike : (bool)
1115            strike through text [False]
1116        dim : (bool)
1117            make text look dimmer [False]
1118        invert : (bool)
1119            invert background and forward colors [False]
1120        box : (bool)
1121            print a box with specified text character ['']
1122        link : (str)
1123            print a clickable url link (works on Linux)
1124            (must press Ctrl+click to open the link)
1125        flush : (bool)
1126            flush buffer after printing [True]
1127        return_string : (bool)
1128            return the string without printing it [False]
1129        end : (str)
1130            the end character to be printed [newline]
1131
1132    Example:
1133        ```python
1134        from vedo.colors import printc
1135        printc('anything', c='tomato', bold=False, end=' ')
1136        printc('anything', 455.5, c='lightblue')
1137        printc(299792.48, c=4)
1138        ```
1139
1140    Examples:
1141        - [printc.py](https://github.com/marcomusy/vedo/tree/master/examples/other/printc.py)
1142
1143        ![](https://user-images.githubusercontent.com/32848391/50739010-2bfc2b80-11da-11e9-94de-011e50a86e61.jpg)
1144    """
1145
1146    if not vedo.settings.enable_print_color or not _terminal_has_colors:
1147        if return_string:
1148            return ''.join(strings)
1149        else:
1150            print(*strings, end=end, flush=flush)
1151            return
1152
1153    try:  # -------------------------------------------------------------
1154
1155        txt = str()
1156        ns = len(strings) - 1
1157        separator = " "
1158        offset = 0
1159        for i, s in enumerate(strings):
1160            if i == ns:
1161                separator = ""
1162            if ":" in repr(s):
1163                for k in emoji:
1164                    if k in str(s):
1165                        s = s.replace(k, emoji[k])
1166                        offset += 1
1167                for k, rp in vedo.shapes._reps:  # check symbols in shapes._reps
1168                    if k in str(s):
1169                        s = s.replace(k, rp)
1170                        offset += 1
1171
1172            txt += str(s) + separator
1173
1174        special, cseq = "", ""
1175        oneletter_colors = {
1176            "k": "\u001b[30m",  # because these are supported by most terminals
1177            "r": "\u001b[31m",
1178            "g": "\u001b[32m",
1179            "y": "\u001b[33m",
1180            "b": "\u001b[34m",
1181            "m": "\u001b[35m",
1182            "c": "\u001b[36m",
1183            "w": "\u001b[37m",
1184        }
1185
1186        if c is not None:
1187            if c is True:
1188                c = "g"
1189            elif c is False:
1190                c = "r"
1191
1192            if isinstance(c, str) and c in oneletter_colors:
1193                cseq += oneletter_colors[c]
1194            else:
1195                r, g, b = get_color(c)  # not all terms support this syntax
1196                cseq += f"\x1b[38;2;{int(r*255)};{int(g*255)};{int(b*255)}m"
1197
1198        if bc:
1199            if bc in oneletter_colors:
1200                cseq += oneletter_colors[bc]
1201            else:
1202                r, g, b = get_color(bc)
1203                cseq += f"\x1b[48;2;{int(r*255)};{int(g*255)};{int(b*255)}m"
1204
1205        if box is True:
1206            box = "-"
1207        if underline and not box:
1208            special += "\x1b[4m"
1209        if strike and not box:
1210            special += "\x1b[9m"
1211        if dim:
1212            special += "\x1b[2m"
1213        if invert:
1214            special += "\x1b[7m"
1215        if bold:
1216            special += "\x1b[1m"
1217        if italic:
1218            special += "\x1b[3m"
1219        if blink:
1220            special += "\x1b[5m"
1221
1222        if box and "\n" not in txt:
1223            box = box[0]
1224            boxv = box
1225            if box in ["_", "=", "-", "+", "~"]:
1226                boxv = "|"
1227
1228            if box in ("_", "."):
1229                outtxt = special + cseq + " " + box * (len(txt) + offset + 2) + " \n"
1230                outtxt += boxv + " " * (len(txt) + 2) + boxv + "\n"
1231            else:
1232                outtxt = special + cseq + box * (len(txt) + offset + 4) + "\n"
1233
1234            outtxt += boxv + " " + txt + " " + boxv + "\n"
1235
1236            if box == "_":
1237                outtxt += "|" + box * (len(txt) + offset + 2) + "|" + reset + end
1238            else:
1239                outtxt += box * (len(txt) + offset + 4) + reset + end
1240
1241            sys.stdout.write(outtxt)
1242
1243        else:
1244
1245            out = special + cseq + txt + reset
1246
1247            if link:
1248                # embed a link in the terminal
1249                out = f"\x1b]8;;{link}\x1b\\{out}\x1b]8;;\x1b\\"
1250
1251            if return_string:
1252                return out + end
1253            else:
1254                sys.stdout.write(out + end)
1255
1256    except:  # --------------------------------------------------- fallback
1257
1258        if return_string:
1259            return ''.join(strings)
1260
1261        try:
1262            print(*strings, end=end)
1263        except UnicodeEncodeError as e:
1264            print(e, end=end)
1265            pass
1266
1267    if flush:
1268        sys.stdout.flush()

Print to terminal in color (any color!).

Arguments:
  • c : (color) foreground color name or (r,g,b)
  • bc : (color) background color name or (r,g,b)
  • bold : (bool) boldface [True]
  • italic : (bool) italic [False]
  • blink : (bool) blinking text [False]
  • underline : (bool) underline text [False]
  • strike : (bool) strike through text [False]
  • dim : (bool) make text look dimmer [False]
  • invert : (bool) invert background and forward colors [False]
  • box : (bool) print a box with specified text character ['']
  • link : (str) print a clickable url link (works on Linux) (must press Ctrl+click to open the link)
  • flush : (bool) flush buffer after printing [True]
  • return_string : (bool) return the string without printing it [False]
  • end : (str) the end character to be printed [newline]
Example:
from vedo.colors import printc
printc('anything', c='tomato', bold=False, end=' ')
printc('anything', 455.5, c='lightblue')
printc(299792.48, c=4)
Examples:

def printd(*strings, q=False):
1271def printd(*strings, q=False):
1272    """
1273    Print debug information about the environment where the printd() is called.
1274    Local variables are printed out with their current values.
1275
1276    Use `q` to quit (exit) the python session after the printd call.
1277    """
1278    from inspect import currentframe, getframeinfo
1279
1280    cf = currentframe().f_back
1281    cfi = getframeinfo(cf)
1282
1283    fname = os.path.basename(getframeinfo(cf).filename)
1284    print("\x1b[7m\x1b[3m\x1b[37m" + fname + " line:\x1b[1m" + str(cfi.lineno) + reset, end="")
1285    print("\x1b[3m\x1b[37m\x1b[2m", "\U00002501" * 30, time.ctime(), reset)
1286    if strings:
1287        print("    \x1b[37m\x1b[1mMessage : ", *strings)
1288    print("    \x1b[37m\x1b[1mFunction:\x1b[0m\x1b[37m " + str(cfi.function))
1289    print("    \x1b[1mLocals  :" + reset)
1290    for loc in cf.f_locals.keys():
1291        obj = cf.f_locals[loc]
1292        var = repr(obj)
1293        if 'module ' in var: continue
1294        if 'function ' in var: continue
1295        if 'class ' in var: continue
1296        if loc.startswith('_'): continue
1297        if hasattr(obj, 'name'):
1298            if not obj.name:
1299                oname = str(type(obj))
1300            else:
1301                oname = obj.name
1302            var = oname + ", at " + vedo.utils.precision(obj.GetPosition(), 3)
1303
1304        var = var.replace("vtkmodules.", "")
1305        print("      \x1b[37m", loc, "\t\t=", var[:60].replace("\n", ""), reset)
1306        if vedo.utils.is_sequence(obj) and len(obj) > 4:
1307            print('           \x1b[37m\x1b[2m\x1b[3m len:', len(obj),
1308                  ' min:', vedo.utils.precision(min(obj), 4),
1309                  ' max:', vedo.utils.precision(max(obj), 4),
1310                  reset)
1311
1312    if q:
1313        print(f"    \x1b[1m\x1b[37mExiting python now (q={bool(q)}).\x1b[0m\x1b[37m")
1314        sys.exit(0)
1315    sys.stdout.flush()

Print debug information about the environment where the printd() is called. Local variables are printed out with their current values.

Use q to quit (exit) the python session after the printd call.

def get_color(rgb=None, hsv=None):
721def get_color(rgb=None, hsv=None):
722    """
723    Convert a color or list of colors to (r,g,b) format from many different input formats.
724
725    Set `hsv` to input as (hue, saturation, value).
726
727    Example:
728         - `RGB    = (255, 255, 255)` corresponds to white
729         - `rgb    = (1,1,1)` is again white
730         - `hex    = #FFFF00` is yellow
731         - `string = 'white'`
732         - `string = 'w'` is white nickname
733         - `string = 'dr'` is darkred
734         - `string = 'red4'` is a shade of red
735         - `int    =  7` picks color nr. 7 in a predefined color list
736         - `int    = -7` picks color nr. 7 in a different predefined list
737
738
739    Examples:
740        - [colorcubes.py](https://github.com/marcomusy/vedo/tree/master/examples/basic/colorcubes.py)
741
742            ![](https://vedo.embl.es/images/basic/colorcubes.png)
743    """
744    # recursion, return a list if input is list of colors:
745    if _is_sequence(rgb) and (len(rgb) > 3 or _is_sequence(rgb[0])):
746        seqcol = []
747        for sc in rgb:
748            seqcol.append(get_color(sc))
749        return seqcol
750
751    # because they are most common:
752    if isinstance(rgb, str):
753        if rgb == "r":
754            return (0.9960784313725, 0.11764705882352, 0.121568627450980)
755        elif rgb == "g":
756            return (0.0156862745098, 0.49803921568627, 0.062745098039215)
757        elif rgb == "b":
758            return (0.0588235294117, 0.0, 0.984313725490196)
759
760    if str(rgb).isdigit():
761        rgb = int(rgb)
762
763    if hsv:
764        c = hsv2rgb(hsv)
765    else:
766        c = rgb
767
768    if _is_sequence(c):
769        if c[0] <= 1 and c[1] <= 1 and c[2] <= 1:
770            return c  # already rgb
771        if len(c) == 3:
772            return list(np.array(c) / 255.0)  # RGB
773        return (c[0] / 255.0, c[1] / 255.0, c[2] / 255.0, c[3])  # RGBA
774
775    elif isinstance(c, str):  # is string
776        c = c.replace("grey", "gray").replace(" ", "")
777        if 0 < len(c) < 3:  # single/double letter color
778            if c.lower() in color_nicks:
779                c = color_nicks[c.lower()]
780            else:
781                vedo.logger.warning(
782                    f"Unknown color nickname {c}\nAvailable abbreviations: {color_nicks}"
783                )
784                return (0.5, 0.5, 0.5)
785
786        if c.lower() in colors:  # matplotlib name color
787            c = colors[c.lower()]
788            # from now format is hex!
789
790        if c.startswith("#"):  # hex to rgb
791            h = c.lstrip("#")
792            rgb255 = list(int(h[i : i + 2], 16) for i in (0, 2, 4))
793            rgbh = np.array(rgb255) / 255.0
794            if np.sum(rgbh) > 3:
795                vedo.logger.error(f"in get_color(): Wrong hex color {c}")
796                return (0.5, 0.5, 0.5)
797            return tuple(rgbh)
798
799        else:  # vtk name color
800            namedColors = vtk.new("NamedColors")
801            rgba = [0, 0, 0, 0]
802            namedColors.GetColor(c, rgba)
803            return (rgba[0] / 255.0, rgba[1] / 255.0, rgba[2] / 255.0)
804
805    elif isinstance(c, (int, float)):  # color number
806        return palettes[vedo.settings.palette % len(palettes)][abs(int(c)) % 10]
807
808    return (0.5, 0.5, 0.5)

Convert a color or list of colors to (r,g,b) format from many different input formats.

Set hsv to input as (hue, saturation, value).

Example:
  • RGB = (255, 255, 255) corresponds to white
  • rgb = (1,1,1) is again white
  • hex = #FFFF00 is yellow
  • string = 'white'
  • string = 'w' is white nickname
  • string = 'dr' is darkred
  • string = 'red4' is a shade of red
  • int = 7 picks color nr. 7 in a predefined color list
  • int = -7 picks color nr. 7 in a different predefined list
Examples:
def get_color_name(c):
811def get_color_name(c):
812    """Find the name of the closest color."""
813    c = np.array(get_color(c))  # reformat to rgb
814    mdist = 99.0
815    kclosest = ""
816    for key in colors:
817        ci = np.array(get_color(key))
818        d = np.linalg.norm(c - ci)
819        if d < mdist:
820            mdist = d
821            kclosest = str(key)
822    return kclosest

Find the name of the closest color.

def color_map(value, name='jet', vmin=None, vmax=None):
854def color_map(value, name="jet", vmin=None, vmax=None):
855    """
856    Map a real value in range [vmin, vmax] to a (r,g,b) color scale.
857
858    Return the (r,g,b) color, or a list of (r,g,b) colors.
859
860    Arguments:
861        value : (float, list)
862            scalar value to transform into a color
863        name : (str, matplotlib.colors.LinearSegmentedColormap)
864            color map name
865
866    Very frequently used color maps are:
867
868        ![](https://user-images.githubusercontent.com/32848391/50738804-577e1680-11d8-11e9-929e-fca17a8ac6f3.jpg)
869
870    A more complete color maps list:
871
872        ![](https://matplotlib.org/1.2.1/_images/show_colormaps.png)
873
874    .. note:: Can also directly use and customize a matplotlib color map
875
876    Example:
877        ```python
878        import matplotlib
879        from vedo import color_map
880        rgb = color_map(0.2, matplotlib.colormaps["jet"], 0, 1)
881        print("rgb =", rgb)  # [0.0, 0.3, 1.0]
882        ```
883
884    Examples:
885        - [plot_bars.py](https://github.com/marcomusy/vedo/tree/master/examples/pyplot/plot_bars.py)
886
887            <img src="https://vedo.embl.es/images/pyplot/plot_bars.png" width="400"/>
888
889    """
890    cut = _is_sequence(value)  # to speed up later
891
892    if cut:
893        values = np.asarray(value)
894        if vmin is None:
895            vmin = np.min(values)
896        if vmax is None:
897            vmax = np.max(values)
898        values = np.clip(values, vmin, vmax)
899        values = (values - vmin) / (vmax - vmin)
900    else:
901        if vmin is None:
902            vedo.logger.warning("in color_map() you must specify vmin! Assume 0.")
903            vmin = 0
904        if vmax is None:
905            vedo.logger.warning("in color_map() you must specify vmax! Assume 1.")
906            vmax = 1
907        values = [(value - vmin) / (vmax - vmin)]
908
909    if _has_matplotlib:
910        # matplotlib is available, use it! ###########################
911        if isinstance(name, str):
912            mp = matplotlib.colormaps[name]
913        else:
914            mp = name  # assume matplotlib.colors.LinearSegmentedColormap
915        result = mp(values)[:, [0, 1, 2]]
916
917    else:
918        # matplotlib not available ###################################
919        invert = False
920        if name.endswith("_r"):
921            invert = True
922            name = name.replace("_r", "")
923        try:
924            cmap = cmaps[name]
925        except KeyError:
926            vedo.logger.error(f"in color_map(), no color map with name {name} or {name}_r")
927            vedo.logger.error(f"Available color maps are:\n{cmaps.keys()}")
928            return np.array([0.5, 0.5, 0.5])
929
930        result = []
931        n = len(cmap) - 1
932        for v in values:
933            iv = int(v * n)
934            if invert:
935                iv = n - iv
936            rgb = hex2rgb(cmap[iv])
937            result.append(rgb)
938        result = np.array(result)
939
940    if cut:
941        return result
942    return result[0]

Map a real value in range [vmin, vmax] to a (r,g,b) color scale.

Return the (r,g,b) color, or a list of (r,g,b) colors.

Arguments:
  • value : (float, list) scalar value to transform into a color
  • name : (str, matplotlib.colors.LinearSegmentedColormap) color map name
Very frequently used color maps are:

A more complete color maps list:

Can also directly use and customize a matplotlib color map
Example:
import matplotlib
from vedo import color_map
rgb = color_map(0.2, matplotlib.colormaps["jet"], 0, 1)
print("rgb =", rgb)  # [0.0, 0.3, 1.0]
Examples:
def build_palette(color1, color2, n, hsv=True):
945def build_palette(color1, color2, n, hsv=True):
946    """
947    Generate N colors starting from `color1` to `color2`
948    by linear interpolation in HSV or RGB spaces.
949
950    Arguments:
951        N : (int)
952            number of output colors.
953        color1 : (color)
954            first color.
955        color2 : (color)
956            second color.
957        hsv : (bool)
958            if `False`, interpolation is calculated in RGB space.
959
960    Examples:
961        - [mesh_custom.py](https://github.com/marcomusy/vedo/tree/master/examples/basic/mesh_custom.py)
962
963            ![](https://vedo.embl.es/images/basic/mesh_custom.png)
964    """
965    if hsv:
966        color1 = rgb2hsv(color1)
967        color2 = rgb2hsv(color2)
968    c1 = np.array(get_color(color1))
969    c2 = np.array(get_color(color2))
970    cols = []
971    for f in np.linspace(0, 1, n, endpoint=True):
972        c = c1 * (1 - f) + c2 * f
973        if hsv:
974            c = np.array(hsv2rgb(c))
975        cols.append(c)
976    return np.array(cols)

Generate N colors starting from color1 to color2 by linear interpolation in HSV or RGB spaces.

Arguments:
  • N : (int) number of output colors.
  • color1 : (color) first color.
  • color2 : (color) second color.
  • hsv : (bool) if False, interpolation is calculated in RGB space.
Examples:
def build_lut( colorlist, vmin=None, vmax=None, below_color=None, above_color=None, nan_color=None, below_alpha=1, above_alpha=1, nan_alpha=1, interpolate=False):
 979def build_lut(
 980    colorlist,
 981    vmin=None,
 982    vmax=None,
 983    below_color=None,
 984    above_color=None,
 985    nan_color=None,
 986    below_alpha=1,
 987    above_alpha=1,
 988    nan_alpha=1,
 989    interpolate=False,
 990):
 991    """
 992    Generate colors in a lookup table (LUT).
 993
 994    Return the `vtkLookupTable` object. This can be fed into `cmap()` method.
 995
 996    Arguments:
 997        colorlist : (list)
 998            a list in the form `[(scalar1, [r,g,b]), (scalar2, 'blue'), ...]`.
 999        vmin : (float)
1000            specify minimum value of scalar range
1001        vmax : (float)
1002            specify maximum value of scalar range
1003        below_color : (color)
1004            color for scalars below the minimum in range
1005        below_alpha : (float)
1006            opacity for scalars below the minimum in range
1007        above_color : (color)
1008            color for scalars above the maximum in range
1009        above_alpha : (float)
1010            alpha for scalars above the maximum in range
1011        nan_color : (color)
1012            color for invalid (nan) scalars
1013        nan_alpha : (float)
1014            alpha for invalid (nan) scalars
1015        interpolate : (bool)
1016            interpolate or not intermediate scalars
1017
1018    Examples:
1019        - [mesh_lut.py](https://github.com/marcomusy/vedo/tree/master/examples/basic/mesh_lut.py)
1020
1021            ![](https://vedo.embl.es/images/basic/mesh_lut.png)
1022    """
1023    ctf = vtk.new("ColorTransferFunction")
1024    ctf.SetColorSpaceToRGB()
1025    ctf.SetScaleToLinear()
1026    alpha_x, alpha_vals = [], []
1027    for sc in colorlist:
1028        if len(sc) >= 3:
1029            scalar, col, alf = sc[:3]
1030        else:
1031            alf = 1
1032            scalar, col = sc
1033        r, g, b = get_color(col)
1034        ctf.AddRGBPoint(scalar, r, g, b)
1035        alpha_x.append(scalar)
1036        alpha_vals.append(alf)
1037
1038    lut = vtk.new("LookupTable")
1039    lut.SetNumberOfTableValues(256)
1040
1041    x0, x1 = ctf.GetRange()  # range of the introduced values
1042    if vmin is not None:
1043        x0 = vmin
1044    if vmax is not None:
1045        x1 = vmax
1046    ctf.SetRange(x0, x1)
1047    lut.SetRange(x0, x1)
1048
1049    if below_color is not None:
1050        lut.SetBelowRangeColor(list(get_color(below_color)) + [below_alpha])
1051        lut.SetUseBelowRangeColor(True)
1052    if above_color is not None:
1053        lut.SetAboveRangeColor(list(get_color(above_color)) + [above_alpha])
1054        lut.SetUseAboveRangeColor(True)
1055    if nan_color is not None:
1056        lut.SetNanColor(list(get_color(nan_color)) + [nan_alpha])
1057
1058    rgba = (1, 1, 1, 1)
1059    for i in range(256):
1060        p = i / 255
1061        x = (1 - p) * x0 + p * x1
1062        if interpolate:
1063            alf = np.interp(x, alpha_x, alpha_vals)
1064            rgba = list(ctf.GetColor(x)) + [alf]
1065        else:
1066            for c in colorlist:
1067                if x <= c[0]:
1068                    if len(c) == 3:
1069                        alf = c[2]
1070                    else:
1071                        alf = 1
1072                    rgba = list(get_color(c[1])) + [alf]
1073                    break
1074        lut.SetTableValue(i, rgba)
1075
1076    lut.Build()
1077    return lut

Generate colors in a lookup table (LUT).

Return the vtkLookupTable object. This can be fed into cmap() method.

Arguments:
  • colorlist : (list) a list in the form [(scalar1, [r,g,b]), (scalar2, 'blue'), ...].
  • vmin : (float) specify minimum value of scalar range
  • vmax : (float) specify maximum value of scalar range
  • below_color : (color) color for scalars below the minimum in range
  • below_alpha : (float) opacity for scalars below the minimum in range
  • above_color : (color) color for scalars above the maximum in range
  • above_alpha : (float) alpha for scalars above the maximum in range
  • nan_color : (color) color for invalid (nan) scalars
  • nan_alpha : (float) alpha for invalid (nan) scalars
  • interpolate : (bool) interpolate or not intermediate scalars
Examples: