Coverage for /home/deng/Projects/metatree_drawer/treeprofiler_algo/pastml/pastml/visualisation/colour_generator.py: 23%

39 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-03-21 09:19 +0100

1import colorsys 

2import os 

3import re 

4 

5import pandas as pd 

6 

7NUM2COLOURS = { 

8 1: ['#1b9e77'], 

9 2: ['#d95f02', '#1b9e77'], 

10 3: ['#a6cee3', '#1f78b4', '#b2df8a'], 

11 4: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3'], 

12 5: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00'], 

13 6: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f'], 

14 7: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f'], 

15 8: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00'], 

16 9: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6'], 

17 10: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a'], 

18 11: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', 

19 '#ffff99'], 

20 12: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', 

21 '#ffff99', '#b15928'], 

22 13: ['#cc9566', '#ccc466', '#a4cc66', '#75cc66', '#66cc85', '#66ccb4', '#66b4cc', 

23 '#6685cc', '#7566cc', '#a466cc', '#cc66c4', '#cc6695', '#cc6666'] 

24} 

25 

26WHITE = '#ffffff' 

27 

28 

29def get_enough_colours(num_unique_values): 

30 """ 

31 Generates and returns an array of `num_unique_values` HEX colours. 

32 :param num_unique_values: int, number of colours to be generated. 

33 :return: array of str, containing colours in HEX format. 

34 """ 

35 if num_unique_values in NUM2COLOURS: 

36 return NUM2COLOURS[num_unique_values] 

37 vs = ['#%02x%02x%02x' % tuple(rgb) for rgb in 

38 (map(lambda x: int(x * 255), colorsys.hsv_to_rgb(*hsv)) for hsv in 

39 ((_ / num_unique_values, 0.25 * (1 + (_ % 3)), .8) for _ in range(1, num_unique_values + 1)))] 

40 if num_unique_values < 20: 

41 return vs[::5] + vs[1::5] + vs[2::5] + vs[3::5] + vs[4::5] 

42 return vs[::10] + vs[1::10] + vs[2::10] + vs[3::10] + vs[4::10] \ 

43 + vs[5::10] + vs[6::10] + vs[7::10] + vs[8::10] + vs[9::10] 

44 

45 

46def hex_to_rgb(value): 

47 value = value.lstrip('#') 

48 return tuple(int(value[i:i + 2], 16) for i in (0, 2, 4)) 

49 

50 

51def parse_colours(colours, states): 

52 if not isinstance(colours, str) and not isinstance(colours, dict): 

53 raise ValueError('Colours must be specified either as a dict or as a path to a csv file, not as {}!' 

54 .format(type(colours))) 

55 if isinstance(colours, str): 

56 if not os.path.exists(colours): 

57 raise ValueError('The specified colour file ({}) does not exist.' 

58 .format(colours)) 

59 try: 

60 colour_dict = pd.read_csv(colours, header=0, index_col=0, sep='\t') 

61 if 'colour' not in colour_dict.columns: 

62 raise ValueError('Could not find the "colour" column in the parameter file {}. ' 

63 'It should be a tab-delimited file with two columns, ' 

64 'the first one containing character states, ' 

65 'and the second, named "colour", containing colours if HEX format, e.g. #7566cc.') 

66 colour_dict = colour_dict.to_dict()['colour'] 

67 colours = colour_dict 

68 except: 

69 raise ValueError('The specified colour file {} is malformatted, ' 

70 'should be a tab-delimited file with two columns, ' 

71 'the first one containing character states, ' 

72 'and the second, named "colour", containing colours if HEX format, e.g. #7566cc.' 

73 .format(colours)) 

74 colours = {str(k.encode('ASCII', 'replace').decode()).strip(): v for (k, v) in colours.items()} 

75 colours_specified = set(states) & set(colours.keys()) 

76 if len(colours_specified) < len(states): 

77 raise ValueError('Some colour parameters are specified, but missing the following states: {}' 

78 .format(', '.join(set(states) - colours_specified))) 

79 else: 

80 for state in colours_specified: 

81 colour = colours[state] 

82 if not re.findall('^[#]([a-zA-Z0-9]{6}|[a-zA-Z0-9]{8})$', colour): 

83 raise ValueError('The colour {} specified for {} is not in HEX format (e.g. #7566cc).'.format(colour, state)) 

84 return [colours[s] for s in states] 

85