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

Find the name of the closest color.

def color_map(value, name='jet', vmin=None, vmax=None):
859def color_map(value, name="jet", vmin=None, vmax=None):
860    """
861    Map a real value in range [vmin, vmax] to a (r,g,b) color scale.
862
863    Return the (r,g,b) color, or a list of (r,g,b) colors.
864
865    Arguments:
866        value : (float, list)
867            scalar value to transform into a color
868        name : (str, matplotlib.colors.LinearSegmentedColormap)
869            color map name
870
871    Very frequently used color maps are:
872
873        ![](https://user-images.githubusercontent.com/32848391/50738804-577e1680-11d8-11e9-929e-fca17a8ac6f3.jpg)
874
875    A more complete color maps list:
876
877        ![](https://matplotlib.org/1.2.1/_images/show_colormaps.png)
878
879    .. note:: Can also directly use and customize a matplotlib color map
880
881    Example:
882        ```python
883        import matplotlib
884        from vedo import color_map
885        rgb = color_map(0.2, matplotlib.colormaps["jet"], 0, 1)
886        print("rgb =", rgb)  # [0.0, 0.3, 1.0]
887        ```
888
889    Examples:
890        - [plot_bars.py](https://github.com/marcomusy/vedo/tree/master/examples/pyplot/plot_bars.py)
891
892            <img src="https://vedo.embl.es/images/pyplot/plot_bars.png" width="400"/>
893
894    """
895    cut = _is_sequence(value)  # to speed up later
896
897    if cut:
898        values = np.asarray(value)
899        if vmin is None:
900            vmin = np.min(values)
901        if vmax is None:
902            vmax = np.max(values)
903        values = np.clip(values, vmin, vmax)
904        values = (values - vmin) / (vmax - vmin)
905    else:
906        if vmin is None:
907            vedo.logger.warning("in color_map() you must specify vmin! Assume 0.")
908            vmin = 0
909        if vmax is None:
910            vedo.logger.warning("in color_map() you must specify vmax! Assume 1.")
911            vmax = 1
912        if vmax == vmin:
913            values = [value - vmin]
914        else:
915            values = [(value - vmin) / (vmax - vmin)]
916
917    if _has_matplotlib:
918        # matplotlib is available, use it! ###########################
919        if isinstance(name, str):
920            mp = matplotlib.colormaps[name]
921        else:
922            mp = name  # assume matplotlib.colors.LinearSegmentedColormap
923        result = mp(values)[:, [0, 1, 2]]
924
925    else:
926        # matplotlib not available ###################################
927        invert = False
928        if name.endswith("_r"):
929            invert = True
930            name = name.replace("_r", "")
931        try:
932            cmap = cmaps[name]
933        except KeyError:
934            vedo.logger.error(f"in color_map(), no color map with name {name} or {name}_r")
935            vedo.logger.error(f"Available color maps are:\n{cmaps.keys()}")
936            return np.array([0.5, 0.5, 0.5])
937
938        result = []
939        n = len(cmap) - 1
940        for v in values:
941            iv = int(v * n)
942            if invert:
943                iv = n - iv
944            rgb = hex2rgb(cmap[iv])
945            result.append(rgb)
946        result = np.array(result)
947
948    if cut:
949        return result
950    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) -> numpy.ndarray:
953def build_palette(color1, color2, n, hsv=True) -> np.ndarray:
954    """
955    Generate N colors starting from `color1` to `color2`
956    by linear interpolation in HSV or RGB spaces.
957
958    Arguments:
959        N : (int)
960            number of output colors.
961        color1 : (color)
962            first color.
963        color2 : (color)
964            second color.
965        hsv : (bool)
966            if `False`, interpolation is calculated in RGB space.
967
968    Examples:
969        - [mesh_custom.py](https://github.com/marcomusy/vedo/tree/master/examples/basic/mesh_custom.py)
970
971            ![](https://vedo.embl.es/images/basic/mesh_custom.png)
972    """
973    if hsv:
974        color1 = rgb2hsv(color1)
975        color2 = rgb2hsv(color2)
976    c1 = np.array(get_color(color1))
977    c2 = np.array(get_color(color2))
978    cols = []
979    for f in np.linspace(0, 1, n, endpoint=True):
980        c = c1 * (1 - f) + c2 * f
981        if hsv:
982            c = np.array(hsv2rgb(c))
983        cols.append(c)
984    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) -> vtkmodules.vtkCommonCore.vtkLookupTable:
 987def build_lut(
 988    colorlist,
 989    vmin=None,
 990    vmax=None,
 991    below_color=None,
 992    above_color=None,
 993    nan_color=None,
 994    below_alpha=1,
 995    above_alpha=1,
 996    nan_alpha=1,
 997    interpolate=False,
 998) -> vtki.vtkLookupTable:
 999    """
1000    Generate colors in a lookup table (LUT).
1001
1002    Return the `vtkLookupTable` object. This can be fed into `cmap()` method.
1003
1004    Arguments:
1005        colorlist : (list)
1006            a list in the form `[(scalar1, [r,g,b]), (scalar2, 'blue'), ...]`.
1007        vmin : (float)
1008            specify minimum value of scalar range
1009        vmax : (float)
1010            specify maximum value of scalar range
1011        below_color : (color)
1012            color for scalars below the minimum in range
1013        below_alpha : (float)
1014            opacity for scalars below the minimum in range
1015        above_color : (color)
1016            color for scalars above the maximum in range
1017        above_alpha : (float)
1018            alpha for scalars above the maximum in range
1019        nan_color : (color)
1020            color for invalid (nan) scalars
1021        nan_alpha : (float)
1022            alpha for invalid (nan) scalars
1023        interpolate : (bool)
1024            interpolate or not intermediate scalars
1025
1026    Examples:
1027        - [mesh_lut.py](https://github.com/marcomusy/vedo/tree/master/examples/basic/mesh_lut.py)
1028
1029            ![](https://vedo.embl.es/images/basic/mesh_lut.png)
1030    """
1031    ctf = vtki.new("ColorTransferFunction")
1032    ctf.SetColorSpaceToRGB()
1033    ctf.SetScaleToLinear()
1034
1035    alpha_x, alpha_vals = [], []
1036    for sc in colorlist:
1037        if len(sc) >= 3:
1038            scalar, col, alf = sc[:3]
1039        else:
1040            alf = 1
1041            scalar, col = sc
1042        r, g, b = get_color(col)
1043        ctf.AddRGBPoint(scalar, r, g, b)
1044        alpha_x.append(scalar)
1045        alpha_vals.append(alf)
1046
1047    ncols = 8 * len(colorlist)
1048    if not interpolate:
1049        ncols = len(colorlist)
1050
1051    lut = vtki.new("LookupTable")
1052    lut.SetNumberOfTableValues(ncols)
1053
1054    x0, x1 = ctf.GetRange()  # range of the introduced values
1055    if vmin is not None:
1056        x0 = vmin
1057    if vmax is not None:
1058        x1 = vmax
1059    ctf.SetRange(x0, x1)
1060    lut.SetRange(x0, x1)
1061
1062    if below_color is not None:
1063        lut.SetBelowRangeColor(list(get_color(below_color)) + [below_alpha])
1064        lut.SetUseBelowRangeColor(True)
1065    if above_color is not None:
1066        lut.SetAboveRangeColor(list(get_color(above_color)) + [above_alpha])
1067        lut.SetUseAboveRangeColor(True)
1068    if nan_color is not None:
1069        lut.SetNanColor(list(get_color(nan_color)) + [nan_alpha])
1070
1071    if interpolate:
1072        for i in range(ncols):
1073            p = i / (ncols-1)
1074            x = (1 - p) * x0 + p * x1
1075            alf = np.interp(x, alpha_x, alpha_vals)
1076            rgba = list(ctf.GetColor(x)) + [alf]
1077            lut.SetTableValue(i, rgba)
1078    else:
1079        for i in range(ncols):
1080            if len(colorlist[i]) > 2: 
1081                alpha = colorlist[i][2]
1082            else:
1083                alpha = 1.0
1084            # print("colorlist entry:", colorlist[i])
1085            rgba = list(get_color(colorlist[i][1])) + [alpha]
1086            lut.SetTableValue(i, rgba)
1087
1088    lut.Build()
1089    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: