Diff of /src/scpanel/palettes.py [000000] .. [d90ecf]

Switch to unified view

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
    )