|
a |
|
b/src/scpanel/palettes.py |
|
|
1 |
"""Color palettes in addition to matplotlib's palettes.""" |
|
|
2 |
|
|
|
3 |
from typing import Mapping, Sequence |
|
|
4 |
|
|
|
5 |
from matplotlib import cm, colors |
|
|
6 |
|
|
|
7 |
tab10 = [ |
|
|
8 |
"#1f77b4", |
|
|
9 |
"#ff7f0e", |
|
|
10 |
"#2ca02c", |
|
|
11 |
"#d62728", |
|
|
12 |
"#9467bd", |
|
|
13 |
"#8c564b", |
|
|
14 |
"#e377c2", |
|
|
15 |
"#7f7f7f", |
|
|
16 |
"#bcbd22", |
|
|
17 |
"#17becf", |
|
|
18 |
] |
|
|
19 |
# Colorblindness adjusted vega_10 |
|
|
20 |
# See https://github.com/scverse/scanpy/issues/387 |
|
|
21 |
vega_10 = list(map(colors.to_hex, cm.tab10.colors)) |
|
|
22 |
vega_10_scanpy = vega_10.copy() |
|
|
23 |
vega_10_scanpy[2] = "#279e68" # green |
|
|
24 |
vega_10_scanpy[4] = "#aa40fc" # purple |
|
|
25 |
vega_10_scanpy[8] = "#b5bd61" # kakhi |
|
|
26 |
|
|
|
27 |
# default matplotlib 2.0 palette |
|
|
28 |
# see 'category20' on https://github.com/vega/vega/wiki/Scales#scale-range-literals |
|
|
29 |
vega_20 = list(map(colors.to_hex, cm.tab20.colors)) |
|
|
30 |
|
|
|
31 |
# reorderd, some removed, some added |
|
|
32 |
vega_20_scanpy = [ |
|
|
33 |
# dark without grey: |
|
|
34 |
*vega_20[0:14:2], |
|
|
35 |
*vega_20[16::2], |
|
|
36 |
# light without grey: |
|
|
37 |
*vega_20[1:15:2], |
|
|
38 |
*vega_20[17::2], |
|
|
39 |
# manual additions: |
|
|
40 |
"#ad494a", |
|
|
41 |
"#8c6d31", |
|
|
42 |
] |
|
|
43 |
vega_20_scanpy[2] = vega_10_scanpy[2] |
|
|
44 |
vega_20_scanpy[4] = vega_10_scanpy[4] |
|
|
45 |
vega_20_scanpy[7] = vega_10_scanpy[8] # kakhi shifted by missing grey |
|
|
46 |
## ['#1f77b4','#aec7e8','#ff7f0e','#ffbb78','#2ca02c','#98df8a', |
|
|
47 |
## '#d62728','#ff9896','#9467bd','#c5b0d5','#8c564b','#c49c94', |
|
|
48 |
## '#e377c2','#f7b6d2','#7f7f7f','#c7c7c7','#bcbd22','#dbdb8d','#17becf','#9edae5'] |
|
|
49 |
# TODO: also replace pale colors if necessary |
|
|
50 |
|
|
|
51 |
default_20 = vega_20_scanpy |
|
|
52 |
|
|
|
53 |
# https://graphicdesign.stackexchange.com/questions/3682/where-can-i-find-a-large-palette-set-of-contrasting-colors-for-coloring-many-d |
|
|
54 |
# update 1 |
|
|
55 |
# orig reference https://research.wu.ac.at/en/publications/escaping-rgbland-selecting-colors-for-statistical-graphics-26 |
|
|
56 |
zeileis_28 = [ |
|
|
57 |
"#023fa5", |
|
|
58 |
"#7d87b9", |
|
|
59 |
"#bec1d4", |
|
|
60 |
"#d6bcc0", |
|
|
61 |
"#bb7784", |
|
|
62 |
"#8e063b", |
|
|
63 |
"#4a6fe3", |
|
|
64 |
"#8595e1", |
|
|
65 |
"#b5bbe3", |
|
|
66 |
"#e6afb9", |
|
|
67 |
"#e07b91", |
|
|
68 |
"#d33f6a", |
|
|
69 |
"#11c638", |
|
|
70 |
"#8dd593", |
|
|
71 |
"#c6dec7", |
|
|
72 |
"#ead3c6", |
|
|
73 |
"#f0b98d", |
|
|
74 |
"#ef9708", |
|
|
75 |
"#0fcfc0", |
|
|
76 |
"#9cded6", |
|
|
77 |
"#d5eae7", |
|
|
78 |
"#f3e1eb", |
|
|
79 |
"#f6c4e1", |
|
|
80 |
"#f79cd4", |
|
|
81 |
# these last ones were added: |
|
|
82 |
"#7f7f7f", |
|
|
83 |
"#c7c7c7", |
|
|
84 |
"#1CE6FF", |
|
|
85 |
"#336600", |
|
|
86 |
] |
|
|
87 |
|
|
|
88 |
default_28 = zeileis_28 |
|
|
89 |
|
|
|
90 |
# from https://godsnotwheregodsnot.blogspot.com/2012/09/color-distribution-methodology.html |
|
|
91 |
godsnot_102 = [ |
|
|
92 |
# "#000000", # remove the black, as often, we have black colored annotation |
|
|
93 |
"#FFFF00", |
|
|
94 |
"#1CE6FF", |
|
|
95 |
"#FF34FF", |
|
|
96 |
"#FF4A46", |
|
|
97 |
"#008941", |
|
|
98 |
"#006FA6", |
|
|
99 |
"#A30059", |
|
|
100 |
"#FFDBE5", |
|
|
101 |
"#7A4900", |
|
|
102 |
"#0000A6", |
|
|
103 |
"#63FFAC", |
|
|
104 |
"#B79762", |
|
|
105 |
"#004D43", |
|
|
106 |
"#8FB0FF", |
|
|
107 |
"#997D87", |
|
|
108 |
"#5A0007", |
|
|
109 |
"#809693", |
|
|
110 |
"#6A3A4C", |
|
|
111 |
"#1B4400", |
|
|
112 |
"#4FC601", |
|
|
113 |
"#3B5DFF", |
|
|
114 |
"#4A3B53", |
|
|
115 |
"#FF2F80", |
|
|
116 |
"#61615A", |
|
|
117 |
"#BA0900", |
|
|
118 |
"#6B7900", |
|
|
119 |
"#00C2A0", |
|
|
120 |
"#FFAA92", |
|
|
121 |
"#FF90C9", |
|
|
122 |
"#B903AA", |
|
|
123 |
"#D16100", |
|
|
124 |
"#DDEFFF", |
|
|
125 |
"#000035", |
|
|
126 |
"#7B4F4B", |
|
|
127 |
"#A1C299", |
|
|
128 |
"#300018", |
|
|
129 |
"#0AA6D8", |
|
|
130 |
"#013349", |
|
|
131 |
"#00846F", |
|
|
132 |
"#372101", |
|
|
133 |
"#FFB500", |
|
|
134 |
"#C2FFED", |
|
|
135 |
"#A079BF", |
|
|
136 |
"#CC0744", |
|
|
137 |
"#C0B9B2", |
|
|
138 |
"#C2FF99", |
|
|
139 |
"#001E09", |
|
|
140 |
"#00489C", |
|
|
141 |
"#6F0062", |
|
|
142 |
"#0CBD66", |
|
|
143 |
"#EEC3FF", |
|
|
144 |
"#456D75", |
|
|
145 |
"#B77B68", |
|
|
146 |
"#7A87A1", |
|
|
147 |
"#788D66", |
|
|
148 |
"#885578", |
|
|
149 |
"#FAD09F", |
|
|
150 |
"#FF8A9A", |
|
|
151 |
"#D157A0", |
|
|
152 |
"#BEC459", |
|
|
153 |
"#456648", |
|
|
154 |
"#0086ED", |
|
|
155 |
"#886F4C", |
|
|
156 |
"#34362D", |
|
|
157 |
"#B4A8BD", |
|
|
158 |
"#00A6AA", |
|
|
159 |
"#452C2C", |
|
|
160 |
"#636375", |
|
|
161 |
"#A3C8C9", |
|
|
162 |
"#FF913F", |
|
|
163 |
"#938A81", |
|
|
164 |
"#575329", |
|
|
165 |
"#00FECF", |
|
|
166 |
"#B05B6F", |
|
|
167 |
"#8CD0FF", |
|
|
168 |
"#3B9700", |
|
|
169 |
"#04F757", |
|
|
170 |
"#C8A1A1", |
|
|
171 |
"#1E6E00", |
|
|
172 |
"#7900D7", |
|
|
173 |
"#A77500", |
|
|
174 |
"#6367A9", |
|
|
175 |
"#A05837", |
|
|
176 |
"#6B002C", |
|
|
177 |
"#772600", |
|
|
178 |
"#D790FF", |
|
|
179 |
"#9B9700", |
|
|
180 |
"#549E79", |
|
|
181 |
"#FFF69F", |
|
|
182 |
"#201625", |
|
|
183 |
"#72418F", |
|
|
184 |
"#BC23FF", |
|
|
185 |
"#99ADC0", |
|
|
186 |
"#3A2465", |
|
|
187 |
"#922329", |
|
|
188 |
"#5B4534", |
|
|
189 |
"#FDE8DC", |
|
|
190 |
"#404E55", |
|
|
191 |
"#0089A3", |
|
|
192 |
"#CB7E98", |
|
|
193 |
"#A4E804", |
|
|
194 |
"#324E72", |
|
|
195 |
] |
|
|
196 |
|
|
|
197 |
default_102 = godsnot_102 |
|
|
198 |
|
|
|
199 |
|
|
|
200 |
def _plot_color_cycle(clists: Mapping[str, Sequence[str]]): |
|
|
201 |
import matplotlib.pyplot as plt |
|
|
202 |
import numpy as np |
|
|
203 |
from matplotlib.colors import BoundaryNorm, ListedColormap |
|
|
204 |
|
|
|
205 |
fig, axes = plt.subplots(nrows=len(clists)) # type: plt.Figure, plt.Axes |
|
|
206 |
fig.subplots_adjust(top=0.95, bottom=0.01, left=0.3, right=0.99) |
|
|
207 |
axes[0].set_title("Color Maps/Cycles", fontsize=14) |
|
|
208 |
|
|
|
209 |
for ax, (name, clist) in zip(axes, clists.items()): |
|
|
210 |
n = len(clist) |
|
|
211 |
ax.imshow( |
|
|
212 |
np.arange(n)[None, :].repeat(2, 0), |
|
|
213 |
aspect="auto", |
|
|
214 |
cmap=ListedColormap(clist), |
|
|
215 |
norm=BoundaryNorm(np.arange(n + 1) - 0.5, n), |
|
|
216 |
) |
|
|
217 |
pos = list(ax.get_position().bounds) |
|
|
218 |
x_text = pos[0] - 0.01 |
|
|
219 |
y_text = pos[1] + pos[3] / 2.0 |
|
|
220 |
fig.text(x_text, y_text, name, va="center", ha="right", fontsize=10) |
|
|
221 |
|
|
|
222 |
# Turn off all ticks & spines |
|
|
223 |
for ax in axes: |
|
|
224 |
ax.set_axis_off() |
|
|
225 |
fig.show() |
|
|
226 |
|
|
|
227 |
|
|
|
228 |
if __name__ == "__main__": |
|
|
229 |
_plot_color_cycle( |
|
|
230 |
{name: colors for name, colors in globals().items() if isinstance(colors, list)} |
|
|
231 |
) |