Coverage for /home/deng/Projects/ete4/hackathon/ete4/ete4/utils.py: 14%
124 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-03-21 09:19 +0100
« prev ^ index » next coverage.py v7.2.7, created at 2024-03-21 09:19 +0100
1import os
2import re
3import time
4import random
5import colorsys
7try:
8 import numpy
9except ImportError:
10 mean = lambda v: sum(v)/len(v)
11else:
12 mean = numpy.mean
15# CONVERT shell colors to the same curses palette
16SHELL_COLORS = {
17 "wr": '\033[1;37;41m', # white on red
18 "wo": '\033[1;37;43m', # white on orange
19 "wm": '\033[1;37;45m', # white on magenta
20 "wb": '\033[1;37;46m', # white on blue
21 "bw": '\033[1;37;40m', # black on white
22 "lblue": '\033[1;34m', # light blue
23 "lred": '\033[1;31m', # light red
24 "lgreen": '\033[1;32m', # light green
25 "yellow": '\033[1;33m', # yellow
26 "cyan": '\033[36m', # cyan
27 "blue": '\033[34m', # blue
28 "green": '\033[32m', # green
29 "orange": '\033[33m', # orange
30 "red": '\033[31m', # red
31 "magenta": "\033[35m", # magenta
32 "white": "\033[0m", # white
33 None: "\033[0m", # end
34}
37def color(string, color):
38 return "%s%s%s" % (SHELL_COLORS[color], string, SHELL_COLORS[None])
41def clear_color(string):
42 return re.sub("\\033\[[^m]+m", "", string)
45def print_table(items, header=None, wrap=True, max_col_width=20,
46 wrap_style="wrap", row_line=False, fix_col_width=False, title=None):
47 """Print a matrix of data as a human readable table.
49 :param items: List of lists containing any type of values that can
50 be converted into text strings.
51 :param wrap: If False, column widths are set to fit all values in
52 each column.
53 :param wrap_style: Column adjustment method. It can be "wrap" to
54 wrap values to fit `max_col_width` (by extending cell height),
55 or "cut": to strip values to `max_col_width`.
57 Example::
59 print_table([[3, 2, {"whatever": 1, "bla": [1,2]}],
60 [5,"this is a test\n of wrapping text\n"
61 "with the new function", 777], [1, 1, 1]],
62 header=["This is column number 1", "Column number 2", "col3"],
63 wrap=True, max_col_width=15, wrap_style='wrap',
64 row_line=True, fix_col_width=True)
66 # This is column | Column number 2 | col3
67 # number 1 | |
68 # =============== | =============== | ===============
69 # 3 | 2 | {'bla': [1, 2],
70 # | | 'whatever': 1}
71 # --------------- | --------------- | ---------------
72 # 5 | this is a test | 777
73 # | of |
74 # | wrapping text |
75 # | with the new |
76 # | function |
77 # --------------- | --------------- | ---------------
78 # 1 | 1 | 1
79 # =============== | =============== | ===============
81 """
82 # See https://gist.github.com/jhcepas/5884168
83 def safelen(string):
84 return len(clear_color(string))
86 if isinstance(fix_col_width, list):
87 c2maxw = {i: fix_col_width[i] for i in range(len(items[0]))}
88 wrap = True
89 elif fix_col_width == True:
90 c2maxw = {i: max_col_width for i in range(len(items[0]))}
91 wrap = True
92 elif not wrap:
93 c2maxw = {i: max([safelen(str(e[i])) for e in items]) for i in range(len(items[0]))}
94 else:
95 c2maxw = {i: min(max_col_width, max([safelen(str(e[i])) for e in items]))
96 for i in range(len(items[0]))}
98 if header:
99 current_item = -1
100 row = header
101 if wrap and not fix_col_width:
102 for col, maxw in c2maxw.items():
103 c2maxw[col] = max(maxw, safelen(header[col]))
104 if wrap:
105 c2maxw[col] = min(c2maxw[col], max_col_width)
106 else:
107 current_item = 0
108 row = items[current_item]
110 if title:
111 table_width = sum(c2maxw.values()) + (3*(len(c2maxw)-1))
112 print("-" *table_width)
113 print(title.center(table_width))
114 print("-" *table_width)
116 while row:
117 is_extra = False
118 values = []
119 extra_line = [""]*len(row)
120 for col, val in enumerate(row):
121 cwidth = c2maxw[col]
122 wrap_width = cwidth
123 val = clear_color(str(val))
124 try:
125 newline_i = val.index("\n")
126 except ValueError:
127 pass
128 else:
129 wrap_width = min(newline_i+1, wrap_width)
130 val = val.replace("\n", " ", 1)
131 if wrap and safelen(val) > wrap_width:
132 if wrap_style == "cut":
133 val = val[:wrap_width-1]+"+"
134 elif wrap_style == "wrap":
135 extra_line[col] = val[wrap_width:]
136 val = val[:wrap_width]
137 val = val.ljust(cwidth)
138 values.append(val)
139 print(' | '.join(values))
140 if not set(extra_line) - set(['']):
141 if header and current_item == -1:
142 print(' | '.join(['='*c2maxw[col] for col in range(len(row)) ]))
143 current_item += 1
144 try:
145 row = items[current_item]
146 except IndexError:
147 row = None
148 else:
149 row = extra_line
150 is_extra = True
152 if row_line and not is_extra and not (header and current_item == 0):
153 if row:
154 print(' | '.join(['-'*c2maxw[col] for col in range(len(row)) ]))
155 else:
156 print(' | '.join(['='*c2maxw[col] for col in range(len(extra_line)) ]))
160def ask(string, valid_values, default=-1, case_sensitive=False):
161 """Keep asking until we get a valid answer and return it."""
162 while True:
163 answer = input('%s [%s] ' % (string, ','.join(valid_values)))
165 if not answer and default >= 0:
166 return valid_values[default]
168 if case_sensitive and answer in valid_values:
169 return answer
170 elif (not case_sensitive and
171 answer.lower() in [v.lower() for v in valid_values]):
172 return answer.lower()
175def timeit(f):
176 def a_wrapper_accepting_arguments(*args, **kargs):
177 t1 = time.time()
178 r = f(*args, **kargs)
179 print(" ", f.__name__, time.time() - t1, "seconds")
180 return r
181 return a_wrapper_accepting_arguments
184SVG_COLORS = {
185 "indianred", # CD5C5C 2059292
186 "lightcoral", # F08080 240128128
187 "salmon", # FA8072 250128114
188 "darksalmon", # E9967A 233150122
189 "lightsalmon", # FFA07A 255160122
190 "crimson", # DC143C 2202060
191 "red", # FF0000 25500
192 "firebrick", # B22222 1783434
193 "darkred", # 8B0000 13900
194 "pink", # FFC0CB 255192203
195 "lightpink", # FFB6C1 255182193
196 "hotpink", # FF69B4 255105180
197 "deeppink", # FF1493 25520147
198 "mediumvioletred", # C71585 19921133
199 "palevioletred", # DB7093 219112147
200 "lightsalmon", # FFA07A 255160122
201 "coral", # FF7F50 25512780
202 "tomato", # FF6347 2559971
203 "orangered", # FF4500 255690
204 "darkorange", # FF8C00 2551400
205 "orange", # FFA500 2551650
206 "gold", # FFD700 2552150
207 "yellow", # FFFF00 2552550
208 "lightyellow", # FFFFE0 255255224
209 "lemonchiffon", # FFFACD 255250205
210 "lightgoldenrodyellow", # FAFAD2 250250210
211 "papayawhip", # FFEFD5 255239213
212 "moccasin", # FFE4B5 255228181
213 "peachpuff", # FFDAB9 255218185
214 "palegoldenrod", # EEE8AA 238232170
215 "khaki", # F0E68C 240230140
216 "darkkhaki", # BDB76B 189183107
217 "lavender", # E6E6FA 230230250
218 "thistle", # D8BFD8 216191216
219 "plum", # DDA0DD 221160221
220 "violet", # EE82EE 238130238
221 "orchid", # DA70D6 218112214
222 "fuchsia", # FF00FF 2550255
223 "magenta", # FF00FF 2550255
224 "mediumorchid", # BA55D3 18685211
225 "mediumpurple", # 9370DB 147112219
226 "amethyst", # 9966CC 153102204
227 "blueviolet", # 8A2BE2 13843226
228 "darkviolet", # 9400D3 1480211
229 "darkorchid", # 9932CC 15350204
230 "darkmagenta", # 8B008B 1390139
231 "purple", # 800080 1280128
232 "indigo", # 4B0082 750130
233 "slateblue", # 6A5ACD 10690205
234 "darkslateblue", # 483D8B 7261139
235 "mediumslateblue", # 7B68EE 123104238
236 "greenyellow", # ADFF2F 17325547
237 "chartreuse", # 7FFF00 1272550
238 "lawngreen", # 7CFC00 1242520
239 "lime", # 00FF00 02550
240 "limegreen", # 32CD32 5020550
241 "palegreen", # 98FB98 152251152
242 "lightgreen", # 90EE90 144238144
243 "mediumspringgreen", # 00FA9A 0250154
244 "springgreen", # 00FF7F 0255127
245 "mediumseagreen", # 3CB371 60179113
246 "seagreen", # 2E8B57 4613987
247 "forestgreen", # 228B22 3413934
248 "green", # 008000 01280
249 "darkgreen", # 006400 01000
250 "yellowgreen", # 9ACD32 15420550
251 "olivedrab", # 6B8E23 10714235
252 "olive", # 808000 1281280
253 "darkolivegreen", # 556B2F 8510747
254 "mediumaquamarine", # 66CDAA 102205170
255 "darkseagreen", # 8FBC8F 143188143
256 "lightseagreen" # 20B2AA 32178170
257 "darkcyan", # 008B8B 0139139
258 "teal", # 008080 0128128
259 "aqua", # 00FFFF 0255255
260 "cyan", # 00FFFF 0255255
261 "lightcyan", # E0FFFF 224255255
262 "paleturquoise", # AFEEEE 175238238
263 "aquamarine", # 7FFFD4 127255212
264 "turquoise", # 40E0D0 64224208
265 "mediumturquoise", # 48D1CC 72209204
266 "darkturquoise", # 00CED1 0206209
267 "cadetblue", # 5F9EA0 95158160
268 "steelblue", # 4682B4 70130180
269 "lightsteelblue", # B0C4DE 176196222
270 "powderblue", # B0E0E6 176224230
271 "lightblue", # ADD8E6 173216230
272 "skyblue", # 87CEEB 135206235
273 "lightskyblue", # 87CEFA 135206250
274 "deepskyblue", # 00BFFF 0191255
275 "dodgerblue", # 1E90FF 30144255
276 "cornflowerblue", # 6495ED 100149237
277 "mediumslateblue", # 7B68EE 123104238
278 "royalblue", # 4169E1 65105225
279 "blue", # 0000FF 00255
280 "mediumblue", # 0000CD 00205
281 "darkblue", # 00008B 00139
282 "navy", # 000080 00128
283 "midnightblue", # 191970 2525112
284 "cornsilk", # FFF8DC 255248220
285 "blanchedalmond", # FFEBCD 255235205
286 "bisque", # FFE4C4 255228196
287 "navajowhite", # FFDEAD 255222173
288 "wheat", # F5DEB3 245222179
289 "burlywood", # DEB887 222184135
290 "tan", # D2B48C 210180140
291 "rosybrown", # BC8F8F 188143143
292 "sandybrown", # F4A460 24416496
293 "goldenrod", # DAA520 21816532
294 "darkgoldenrod", # B8860B 18413411
295 "peru", # CD853F 20513363
296 "chocolate", # D2691E 21010530
297 "saddlebrown", # 8B4513 1396919
298 "sienna", # A0522D 1608245
299 "brown", # A52A2A 1654242
300 "maroon", # 800000 12800
301 "white", # FFFFFF 255255255
302 "snow", # FFFAFA 255250250
303 "honeydew", # F0FFF0 240255240
304 "mintcream", # F5FFFA 245255250
305 "azure", # F0FFFF 240255255
306 "aliceblue", # F0F8FF 240248255
307 "ghostwhite", # F8F8FF 248248255
308 "whitesmoke", # F5F5F5 245245245
309 "seashell", # FFF5EE 255245238
310 "beige", # F5F5DC 245245220
311 "oldlace", # FDF5E6 253245230
312 "floralwhite", # FFFAF0 255250240
313 "ivory", # FFFFF0 255255240
314 "antiquewhite", # FAEBD7 250235215
315 "linen", # FAF0E6 250240230
316 "lavenderblush", # FFF0F5 255240245
317 "mistyrose", # FFE4E1 255228225
318 "gainsboro", # DCDCDC 220220220
319 "lightgrey", # D3D3D3 211211211
320 "silver", # C0C0C0 192192192
321 "darkgray", # A9A9A9 169169169
322 "gray", # 808080 128128128
323 "dimgray", # 696969 105105105
324 "lightslategray", # 778899 119136153
325 "slategray", # 708090 112128144
326 "darkslategray", # 2F4F4F 477979
327 "black"} # 000000 000
330COLOR_SCHEMES = {
331 'accent': [
332 '#7fc97f',
333 '#beaed4',
334 '#fdc086',
335 '#ffff99',
336 '#386cb0',
337 '#f0027f',
338 '#bf5b17',
339 '#666666'],
340 'blues': [
341 '#f7fbff',
342 '#deebf7',
343 '#c6dbef',
344 '#9ecae1',
345 '#6baed6',
346 '#4292c6',
347 '#2171b5',
348 '#08519c',
349 '#08306b'],
350 'brbg': [
351 '#543005',
352 '#8c510a',
353 '#bf812d',
354 '#dfc27d',
355 '#f6e8c3',
356 '#f5f5f5',
357 '#c7eae5',
358 '#80cdc1',
359 '#35978f',
360 '#01665e',
361 '#003c30'],
362 'bugn': [
363 '#f7fcfd',
364 '#e5f5f9',
365 '#ccece6',
366 '#99d8c9',
367 '#66c2a4',
368 '#41ae76',
369 '#238b45',
370 '#006d2c',
371 '#00441b'],
372 'bupu': [
373 '#f7fcfd',
374 '#e0ecf4',
375 '#bfd3e6',
376 '#9ebcda',
377 '#8c96c6',
378 '#8c6bb1',
379 '#88419d',
380 '#810f7c',
381 '#4d004b'],
382 'dark2': [
383 '#1b9e77',
384 '#d95f02',
385 '#7570b3',
386 '#e7298a',
387 '#66a61e',
388 '#e6ab02',
389 '#a6761d',
390 '#666666'],
391 'gnbu': [
392 '#f7fcf0',
393 '#e0f3db',
394 '#ccebc5',
395 '#a8ddb5',
396 '#7bccc4',
397 '#4eb3d3',
398 '#2b8cbe',
399 '#0868ac',
400 '#084081'],
401 'greens': [
402 '#f7fcf5',
403 '#e5f5e0',
404 '#c7e9c0',
405 '#a1d99b',
406 '#74c476',
407 '#41ab5d',
408 '#238b45',
409 '#006d2c',
410 '#00441b'],
411 'greys': [
412 '#ffffff',
413 '#f0f0f0',
414 '#d9d9d9',
415 '#bdbdbd',
416 '#969696',
417 '#737373',
418 '#525252',
419 '#252525',
420 '#000000'],
421 'orrd': [
422 '#fff7ec',
423 '#fee8c8',
424 '#fdd49e',
425 '#fdbb84',
426 '#fc8d59',
427 '#ef6548',
428 '#d7301f',
429 '#b30000',
430 '#7f0000'],
431 'oranges': [
432 '#fff5eb',
433 '#fee6ce',
434 '#fdd0a2',
435 '#fdae6b',
436 '#fd8d3c',
437 '#f16913',
438 '#d94801',
439 '#a63603',
440 '#7f2704'],
441 'prgn': [
442 '#40004b',
443 '#762a83',
444 '#9970ab',
445 '#c2a5cf',
446 '#e7d4e8',
447 '#f7f7f7',
448 '#d9f0d3',
449 '#a6dba0',
450 '#5aae61',
451 '#1b7837',
452 '#00441b'],
453 'paired': [
454 '#a6cee3',
455 '#1f78b4',
456 '#b2df8a',
457 '#33a02c',
458 '#fb9a99',
459 '#e31a1c',
460 '#fdbf6f',
461 '#ff7f00',
462 '#cab2d6',
463 '#6a3d9a',
464 '#ffff99',
465 '#b15928'],
466 'pastel1': [
467 '#fbb4ae',
468 '#b3cde3',
469 '#ccebc5',
470 '#decbe4',
471 '#fed9a6',
472 '#ffffcc',
473 '#e5d8bd',
474 '#fddaec',
475 '#f2f2f2'],
476 'pastel2': [
477 '#b3e2cd',
478 '#fdcdac',
479 '#cbd5e8',
480 '#f4cae4',
481 '#e6f5c9',
482 '#fff2ae',
483 '#f1e2cc',
484 '#cccccc'],
485 'piyg': [
486 '#8e0152',
487 '#c51b7d',
488 '#de77ae',
489 '#f1b6da',
490 '#fde0ef',
491 '#f7f7f7',
492 '#e6f5d0',
493 '#b8e186',
494 '#7fbc41',
495 '#4d9221',
496 '#276419'],
497 'pubu': [
498 '#fff7fb',
499 '#ece7f2',
500 '#d0d1e6',
501 '#a6bddb',
502 '#74a9cf',
503 '#3690c0',
504 '#0570b0',
505 '#045a8d',
506 '#023858'],
507 'pubugn': [
508 '#fff7fb',
509 '#ece2f0',
510 '#d0d1e6',
511 '#a6bddb',
512 '#67a9cf',
513 '#3690c0',
514 '#02818a',
515 '#016c59',
516 '#014636'],
517 'puor': [
518 '#7f3b08',
519 '#b35806',
520 '#e08214',
521 '#fdb863',
522 '#fee0b6',
523 '#f7f7f7',
524 '#d8daeb',
525 '#b2abd2',
526 '#8073ac',
527 '#542788',
528 '#2d004b'],
529 'purd': [
530 '#f7f4f9',
531 '#e7e1ef',
532 '#d4b9da',
533 '#c994c7',
534 '#df65b0',
535 '#e7298a',
536 '#ce1256',
537 '#980043',
538 '#67001f'],
539 'purples': [
540 '#fcfbfd',
541 '#efedf5',
542 '#dadaeb',
543 '#bcbddc',
544 '#9e9ac8',
545 '#807dba',
546 '#6a51a3',
547 '#54278f',
548 '#3f007d'],
549 'rdbu': [
550 '#67001f',
551 '#b2182b',
552 '#d6604d',
553 '#f4a582',
554 '#fddbc7',
555 '#f7f7f7',
556 '#d1e5f0',
557 '#92c5de',
558 '#4393c3',
559 '#2166ac',
560 '#053061'],
561 'rdgy': [
562 '#67001f',
563 '#b2182b',
564 '#d6604d',
565 '#f4a582',
566 '#fddbc7',
567 '#ffffff',
568 '#e0e0e0',
569 '#bababa',
570 '#878787',
571 '#4d4d4d',
572 '#1a1a1a'],
573 'rdpu': [
574 '#fff7f3',
575 '#fde0dd',
576 '#fcc5c0',
577 '#fa9fb5',
578 '#f768a1',
579 '#dd3497',
580 '#ae017e',
581 '#7a0177',
582 '#49006a'],
583 'rdylbu': [
584 '#a50026',
585 '#d73027',
586 '#f46d43',
587 '#fdae61',
588 '#fee090',
589 '#ffffbf',
590 '#e0f3f8',
591 '#abd9e9',
592 '#74add1',
593 '#4575b4',
594 '#313695'],
595 'rdylgn': [
596 '#a50026',
597 '#d73027',
598 '#f46d43',
599 '#fdae61',
600 '#fee08b',
601 '#ffffbf',
602 '#d9ef8b',
603 '#a6d96a',
604 '#66bd63',
605 '#1a9850',
606 '#006837'],
607 'reds': [
608 '#fff5f0',
609 '#fee0d2',
610 '#fcbba1',
611 '#fc9272',
612 '#fb6a4a',
613 '#ef3b2c',
614 '#cb181d',
615 '#a50f15',
616 '#67000d'],
617 'set1': [
618 '#e41a1c',
619 '#377eb8',
620 '#4daf4a',
621 '#984ea3',
622 '#ff7f00',
623 '#ffff33',
624 '#a65628',
625 '#f781bf',
626 '#999999'],
627 'set2': [
628 '#66c2a5',
629 '#fc8d62',
630 '#8da0cb',
631 '#e78ac3',
632 '#a6d854',
633 '#ffd92f',
634 '#e5c494',
635 '#b3b3b3'],
636 'set3': [
637 '#8dd3c7',
638 '#ffffb3',
639 '#bebada',
640 '#fb8072',
641 '#80b1d3',
642 '#fdb462',
643 '#b3de69',
644 '#fccde5',
645 '#d9d9d9',
646 '#bc80bd',
647 '#ccebc5',
648 '#ffed6f'],
649 'spectral': [
650 '#9e0142',
651 '#d53e4f',
652 '#f46d43',
653 '#fdae61',
654 '#fee08b',
655 '#ffffbf',
656 '#e6f598',
657 '#abdda4',
658 '#66c2a5',
659 '#3288bd',
660 '#5e4fa2'],
661 'ylgn': [
662 '#ffffe5',
663 '#f7fcb9',
664 '#d9f0a3',
665 '#addd8e',
666 '#78c679',
667 '#41ab5d',
668 '#238443',
669 '#006837',
670 '#004529'],
671 'ylgnbu': [
672 '#ffffd9',
673 '#edf8b1',
674 '#c7e9b4',
675 '#7fcdbb',
676 '#41b6c4',
677 '#1d91c0',
678 '#225ea8',
679 '#253494',
680 '#081d58'],
681 'ylorbr': [
682 '#ffffe5',
683 '#fff7bc',
684 '#fee391',
685 '#fec44f',
686 '#fe9929',
687 '#ec7014',
688 '#cc4c02',
689 '#993404',
690 '#662506'],
691 'ylorrd': [
692 '#ffffcc',
693 '#ffeda0',
694 '#fed976',
695 '#feb24c',
696 '#fd8d3c',
697 '#fc4e2a',
698 '#e31a1c',
699 '#bd0026',
700 '#800026']}
703def random_color(h=None, l=None, s=None, num=None, sep=None, seed=None):
704 """Return the RGB code of a random color.
706 Hue (h), Lightness (l) and Saturation (s) of the generated color
707 can be specified as arguments.
708 """
709 def rgb2hex(rgb):
710 return '#%02x%02x%02x' % rgb
712 def hls2hex(h, l, s):
713 return rgb2hex( tuple([int(x*255) for x in colorsys.hls_to_rgb(h, l, s)]))
715 if not h:
716 if seed:
717 random.seed(seed)
718 color = 1.0 / random.randint(1, 360)
719 else:
720 color = h
722 if not num:
723 n = 1
724 sep = 1
725 else:
726 n = num
728 if not sep:
729 n = num
730 sep = (1.0/n)
732 evenly_separated_colors = [color + (sep*n) for n in range(n)]
734 rcolors = []
735 for h in evenly_separated_colors:
736 if not s:
737 s = 0.5
738 if not l:
739 l = 0.5
740 rcolors.append(hls2hex(h, l, s))
742 if num:
743 return rcolors
744 else:
745 return rcolors[0]