|
1 | 1 | ''' |
| 2 | +========================== |
| 3 | +Lightness of the colormaps |
| 4 | +========================== |
| 5 | +
|
2 | 6 | For each colormap, plot the lightness parameter L* from CIELAB colorspace |
3 | 7 | along the y axis vs index through the colormap. Colormaps are examined in |
4 | 8 | categories as in the original matplotlib gallery of colormaps. |
5 | 9 | ''' |
6 | 10 |
|
7 | | -from colormaps import cmaps |
8 | 11 | import numpy as np |
| 12 | +import matplotlib as mpl |
9 | 13 | import matplotlib.pyplot as plt |
10 | 14 | from matplotlib import cm |
11 | | -import matplotlib as mpl |
12 | 15 | from colorspacious import cspace_converter |
| 16 | +from colormaps import cmaps # the colormaps, grouped by category |
13 | 17 |
|
14 | 18 | mpl.rcParams.update({'font.size': 12}) |
15 | 19 |
|
16 | | -# indices to step through colormap |
| 20 | +# Number of colormap per subplot for particular cmap categories |
| 21 | +_DSUBS = {'Perceptually Uniform Sequential': 4, 'Sequential': 6, |
| 22 | + 'Sequential (2)': 6, 'Diverging': 6, 'Qualitative': 4, |
| 23 | + 'Miscellaneous': 6} |
| 24 | + |
| 25 | +# Spacing between the colormaps of a subplot |
| 26 | +_DC = {'Perceptually Uniform Sequential': 1.4, 'Sequential': 0.7, |
| 27 | + 'Sequential (2)': 1.4, 'Diverging': 1.4, 'Qualitative': 1.4, |
| 28 | + 'Miscellaneous': 1.4} |
| 29 | + |
| 30 | +# Indices to step through colormap |
17 | 31 | x = np.linspace(0.0, 1.0, 100) |
18 | 32 |
|
19 | 33 | # Do plot |
20 | 34 | for cmap_category, cmap_list in cmaps: |
21 | 35 |
|
22 | | - # Do subplots so that colormaps have enough space. 5 per subplot? |
23 | | - dsub = 5 # number of colormaps per subplot |
24 | | - if cmap_category == 'Diverging': # because has 12 colormaps |
25 | | - dsub = 6 |
26 | | - elif cmap_category == 'Sequential (2)': |
27 | | - dsub = 6 |
28 | | - elif cmap_category == 'Sequential': |
29 | | - dsub = 7 |
30 | | - nsubplots = int(np.ceil(len(cmap_list)/float(dsub))) |
31 | | - |
32 | | - fig = plt.figure(figsize=(7,2.6*nsubplots)) |
| 36 | + # Do subplots so that colormaps have enough space. |
| 37 | + # Default is 6 colormaps per subplot. |
| 38 | + dsub = _DSUBS.get(cmap_category, 6) |
| 39 | + nsubplots = int(np.ceil(len(cmap_list) / float(dsub))) |
33 | 40 |
|
34 | | - for i, subplot in enumerate(range(nsubplots)): |
| 41 | + # squeeze=False to handle similarly the case of a single subplot |
| 42 | + fig, axes = plt.subplots(nrows=nsubplots, squeeze=False, |
| 43 | + figsize=(7, 2.6*nsubplots)) |
35 | 44 |
|
36 | | - locs = [] # locations for text labels |
| 45 | + for i, ax in enumerate(axes.flat): |
37 | 46 |
|
38 | | - ax = fig.add_subplot(nsubplots, 1, i+1) |
| 47 | + locs = [] # locations for text labels |
39 | 48 |
|
40 | 49 | for j, cmap in enumerate(cmap_list[i*dsub:(i+1)*dsub]): |
41 | 50 |
|
42 | | - # Get rgb values for colormap |
43 | | - rgb = cm.get_cmap(cmap)(x)[np.newaxis,:,:3] |
44 | | - |
45 | | - # Get colormap in CAM02-UCS colorspace. We want the lightness. |
| 51 | + # Get RGB values for colormap and convert the colormap in |
| 52 | + # CAM02-UCS colorspace. lab[0, :, 0] is the lightness. |
| 53 | + rgb = cm.get_cmap(cmap)(x)[np.newaxis, :, :3] |
46 | 54 | lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb) |
47 | 55 |
|
48 | | - # Plot colormap L values |
49 | | - # Do separately for each category so each plot can be pretty |
50 | | - # to make scatter markers change color along plot: |
| 56 | + # Plot colormap L values. Do separately for each category |
| 57 | + # so each plot can be pretty. To make scatter markers change |
| 58 | + # color along plot: |
51 | 59 | # http://stackoverflow.com/questions/8202605/matplotlib-scatterplot-colour-as-a-function-of-a-third-variable |
52 | | - if cmap_category=='Perceptually Uniform Sequential': |
53 | | - dc = 1.15 # spacing between colormaps |
54 | | - ax.scatter(x+j*dc, lab[0,:,0], c=x, cmap=cmap, |
55 | | - s=300, linewidths=0.) |
56 | | - if i==2: |
57 | | - ax.axis([-0.1,4.1,0,100]) |
58 | | - else: |
59 | | - ax.axis([-0.1,4.7,0,100]) |
60 | | - locs.append(x[-1]+j*dc) # store locations for colormap labels |
61 | | - |
62 | | - elif cmap_category=='Sequential': |
63 | | - dc = 0.6 # spacing between colormaps |
| 60 | + |
| 61 | + if cmap_category == 'Sequential': |
64 | 62 | # These colormaps all start at high lightness but we want them |
65 | 63 | # reversed to look nice in the plot, so reverse the order. |
66 | | - ax.scatter(x+j*dc, lab[0,::-1,0], c=x[::-1], cmap=cmap, |
67 | | - s=300, linewidths=0.) |
68 | | - if i==2: |
69 | | - ax.axis([-0.1,4.1,0,100]) |
70 | | - else: |
71 | | - ax.axis([-0.1,4.7,0,100]) |
72 | | - locs.append(x[-1]+j*dc) # store locations for colormap labels |
73 | | - |
74 | | - elif cmap_category=='Sequential (2)': |
75 | | - dc = 1.15 |
76 | | - ax.scatter(x+j*dc, lab[0,:,0], c=x, cmap=cmap, |
77 | | - s=300, linewidths=0.) |
78 | | - ax.axis([-0.1,7.0,0,100]) |
79 | | - # store locations for colormap labels |
80 | | - locs.append(x[-1]+j*dc) |
81 | | - |
82 | | - elif cmap_category=='Diverging': |
83 | | - dc = 1.2 |
84 | | - ax.scatter(x+j*dc, lab[0,:,0], c=x, cmap=cmap, |
85 | | - s=300, linewidths=0.) |
86 | | - ax.axis([-0.1,7.1,0,100]) |
87 | | - # store locations for colormap labels |
88 | | - locs.append(x[int(x.size/2.)]+j*dc) |
89 | | - elif cmap_category=='Qualitative': |
90 | | - dc = 1.3 |
91 | | - ax.scatter(x+j*dc, lab[0,:,0], c=x, cmap=cmap, |
92 | | - s=300, linewidths=0.) |
93 | | - ax.axis([-0.1,6.3,0,100]) |
94 | | - # store locations for colormap labels |
95 | | - locs.append(x[int(x.size/2.)]+j*dc) |
96 | | - |
97 | | - elif cmap_category=='Miscellaneous': |
98 | | - dc = 1.25 |
99 | | - ax.scatter(x+j*dc, lab[0,:,0], c=x, cmap=cmap, |
100 | | - s=300, linewidths=0.) |
101 | | - ax.axis([-0.1,6.1,0,100]) |
102 | | - # store locations for colormap labels |
103 | | - locs.append(x[int(x.size/2.)]+j*dc) |
104 | | - |
105 | | - # Set up labels for colormaps |
106 | | - ax.xaxis.set_ticks_position('top') |
107 | | - ticker = mpl.ticker.FixedLocator(locs) |
108 | | - ax.xaxis.set_major_locator(ticker) |
109 | | - formatter = mpl.ticker.FixedFormatter(cmap_list[i*dsub:(i+1)*dsub]) |
110 | | - ax.xaxis.set_major_formatter(formatter) |
111 | | - labels = ax.get_xticklabels() |
112 | | - for label in labels: |
113 | | - label.set_rotation(60) |
| 64 | + y_ = lab[0, ::-1, 0] |
| 65 | + c_ = x[::-1] |
| 66 | + else: |
| 67 | + y_ = lab[0, :, 0] |
| 68 | + c_ = x |
| 69 | + |
| 70 | + dc = _DC.get(cmap_category, 1.4) # cmaps horizontal spacing |
| 71 | + ax.scatter(x + j*dc, y_, c=c_, cmap=cmap, s=300, linewidths=0.0) |
| 72 | + |
| 73 | + # Store locations for colormap labels |
| 74 | + if cmap_category in ('Perceptually Uniform Sequential', |
| 75 | + 'Sequential'): |
| 76 | + locs.append(x[-1] + j*dc) |
| 77 | + elif cmap_category in ('Diverging', 'Qualitative', |
| 78 | + 'Miscellaneous', 'Sequential (2)'): |
| 79 | + locs.append(x[int(x.size/2.)] + j*dc) |
| 80 | + |
| 81 | + # Set up the axis limits: |
| 82 | + # * the 1st subplot is used as a reference for the x-axis limits |
| 83 | + # * lightness values goes from 0 to 100 (y-axis limits) |
| 84 | + ax.set_xlim(axes[0, 0].get_xlim()) |
| 85 | + ax.set_ylim(0.0, 100.0) |
| 86 | + |
| 87 | + # Set up labels for colormaps |
| 88 | + ax.xaxis.set_ticks_position('top') |
| 89 | + ticker = mpl.ticker.FixedLocator(locs) |
| 90 | + ax.xaxis.set_major_locator(ticker) |
| 91 | + formatter = mpl.ticker.FixedFormatter(cmap_list[i*dsub:(i+1)*dsub]) |
| 92 | + ax.xaxis.set_major_formatter(formatter) |
| 93 | + ax.xaxis.set_tick_params(rotation=50) |
114 | 94 |
|
115 | 95 | ax.set_xlabel(cmap_category + ' colormaps', fontsize=14) |
116 | 96 | fig.text(0.0, 0.55, 'Lightness $L^*$', fontsize=12, |
117 | 97 | transform=fig.transFigure, rotation=90) |
118 | 98 |
|
119 | | - fig.tight_layout(h_pad=0.05, pad=1.5) |
| 99 | + fig.tight_layout(h_pad=0.0, pad=1.5) |
120 | 100 | plt.show() |
0 commit comments