py2ls 0.1.7.9__py3-none-any.whl → 0.1.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
py2ls/plot.py
CHANGED
@@ -4,8 +4,9 @@ from matplotlib.colors import to_rgba
|
|
4
4
|
from scipy.stats import gaussian_kde
|
5
5
|
|
6
6
|
import logging
|
7
|
+
|
7
8
|
# Suppress INFO messages from fontTools
|
8
|
-
logging.getLogger(
|
9
|
+
logging.getLogger("fontTools").setLevel(logging.WARNING)
|
9
10
|
|
10
11
|
|
11
12
|
def catplot(data, *args, **kwargs):
|
@@ -15,220 +16,291 @@ def catplot(data, *args, **kwargs):
|
|
15
16
|
Args:
|
16
17
|
data (array): data matrix
|
17
18
|
"""
|
19
|
+
|
18
20
|
def plot_bars(data_m, opt_b, xloc, ax):
|
19
|
-
bar_positions = get_positions(
|
20
|
-
|
21
|
+
bar_positions = get_positions(
|
22
|
+
xloc, opt_b["loc"], opt_b["x_width"], data.shape[0]
|
23
|
+
)
|
24
|
+
bar_positions = np.nanmean(bar_positions, axis=0)
|
21
25
|
for i, (x, y) in enumerate(zip(bar_positions, data_m)):
|
22
|
-
color = to_rgba(opt_b[
|
23
|
-
ax.bar(
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
color = to_rgba(opt_b["FaceColor"][i % len(opt_b["FaceColor"])])
|
27
|
+
ax.bar(
|
28
|
+
x,
|
29
|
+
y,
|
30
|
+
width=opt_b["x_width"],
|
31
|
+
color=color,
|
32
|
+
edgecolor=opt_b["EdgeColor"],
|
33
|
+
alpha=opt_b["FaceAlpha"],
|
34
|
+
linewidth=opt_b["LineWidth"],
|
35
|
+
hatch=opt_b["hatch"],
|
36
|
+
)
|
31
37
|
|
32
38
|
def plot_errors(data, data_m, opt_e, xloc, ax):
|
33
|
-
error_positions = get_positions(
|
34
|
-
|
39
|
+
error_positions = get_positions(
|
40
|
+
xloc, opt_e["loc"], opt_e["x_width"], data.shape[0]
|
41
|
+
)
|
42
|
+
error_positions = np.nanmean(error_positions, axis=0)
|
35
43
|
errors = np.nanstd(data, axis=0)
|
36
|
-
if opt_e[
|
37
|
-
errors /= np.sqrt(np.sum(~np.isnan(data),axis=0))
|
44
|
+
if opt_e["error"] == "sem":
|
45
|
+
errors /= np.sqrt(np.sum(~np.isnan(data), axis=0))
|
38
46
|
|
39
|
-
if not isinstance(opt_e[
|
40
|
-
opt_e[
|
41
|
-
if not isinstance(opt_e[
|
42
|
-
opt_e[
|
47
|
+
if not isinstance(opt_e["FaceColor"], list):
|
48
|
+
opt_e["FaceColor"] = [opt_e["FaceColor"]]
|
49
|
+
if not isinstance(opt_e["MarkerEdgeColor"], list):
|
50
|
+
opt_e["MarkerEdgeColor"] = [opt_e["MarkerEdgeColor"]]
|
43
51
|
for i, (x, y, err) in enumerate(zip(error_positions, data_m, errors)):
|
44
|
-
if opt_e[
|
45
|
-
ax.errorbar(
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
if opt_e["MarkerSize"] == "auto":
|
53
|
+
ax.errorbar(
|
54
|
+
x,
|
55
|
+
y,
|
56
|
+
yerr=err,
|
57
|
+
fmt=opt_e["Marker"],
|
58
|
+
ecolor=opt_e["LineColor"],
|
59
|
+
elinewidth=opt_e["LineWidth"],
|
60
|
+
lw=opt_e["LineWidth"],
|
61
|
+
ls=opt_e["LineStyle"],
|
62
|
+
capsize=opt_e["CapSize"],
|
63
|
+
capthick=opt_e["CapLineWidth"],
|
64
|
+
mec=opt_e["MarkerEdgeColor"][i % len(opt_e["MarkerEdgeColor"])],
|
65
|
+
mfc=opt_e["FaceColor"][i % len(opt_e["FaceColor"])],
|
66
|
+
visible=opt_e["Visible"],
|
67
|
+
)
|
57
68
|
else:
|
58
|
-
ax.errorbar(
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
ax.errorbar(
|
70
|
+
x,
|
71
|
+
y,
|
72
|
+
yerr=err,
|
73
|
+
fmt=opt_e["Marker"],
|
74
|
+
ecolor=opt_e["LineColor"],
|
75
|
+
elinewidth=opt_e["LineWidth"],
|
76
|
+
lw=opt_e["LineWidth"],
|
77
|
+
ls=opt_e["LineStyle"],
|
78
|
+
capsize=opt_e["CapSize"],
|
79
|
+
capthick=opt_e["CapLineWidth"],
|
80
|
+
markersize=opt_e["MarkerSize"],
|
81
|
+
mec=opt_e["MarkerEdgeColor"][i % len(opt_e["MarkerEdgeColor"])],
|
82
|
+
mfc=opt_e["FaceColor"][i % len(opt_e["FaceColor"])],
|
83
|
+
visible=opt_e["Visible"],
|
84
|
+
)
|
72
85
|
|
73
86
|
def plot_scatter(data, opt_s, xloc, ax):
|
74
|
-
scatter_positions = get_positions(
|
87
|
+
scatter_positions = get_positions(
|
88
|
+
xloc, opt_s["loc"], opt_s["x_width"], data.shape[0]
|
89
|
+
)
|
75
90
|
for i, (x, y) in enumerate(zip(scatter_positions.T, data.T)):
|
76
|
-
color = to_rgba(opt_s[
|
77
|
-
ax.scatter(
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
X_bx = xloc
|
92
|
-
elif
|
91
|
+
color = to_rgba(opt_s["FaceColor"][i % len(opt_s["FaceColor"])])
|
92
|
+
ax.scatter(
|
93
|
+
x,
|
94
|
+
y,
|
95
|
+
color=color,
|
96
|
+
alpha=opt_s["FaceAlpha"],
|
97
|
+
edgecolor=opt_s["MarkerEdgeColor"],
|
98
|
+
s=opt_s["MarkerSize"],
|
99
|
+
marker=opt_s["Marker"],
|
100
|
+
linewidths=opt_s["LineWidth"],
|
101
|
+
cmap=opt_s["cmap"],
|
102
|
+
)
|
103
|
+
|
104
|
+
def plot_boxplot(data, bx_opt, xloc, ax):
|
105
|
+
if "l" in bx_opt["loc"]:
|
106
|
+
X_bx = xloc - bx_opt["x_width"]
|
107
|
+
elif "r" in bx_opt["loc"]:
|
108
|
+
X_bx = xloc + bx_opt["x_width"]
|
109
|
+
elif "i" in bx_opt["loc"]:
|
93
110
|
X_bx = xloc
|
94
|
-
X_bx[:, 0] += bx_opt[
|
95
|
-
X_bx[:, -1] -= bx_opt[
|
96
|
-
elif
|
111
|
+
X_bx[:, 0] += bx_opt["x_width"]
|
112
|
+
X_bx[:, -1] -= bx_opt["x_width"]
|
113
|
+
elif "o" in bx_opt["loc"]:
|
97
114
|
X_bx = xloc
|
98
|
-
X_bx[:, 0] -= bx_opt[
|
99
|
-
X_bx[:, -1] += bx_opt[
|
100
|
-
elif
|
115
|
+
X_bx[:, 0] -= bx_opt["x_width"]
|
116
|
+
X_bx[:, -1] += bx_opt["x_width"]
|
117
|
+
elif "c" in bx_opt["loc"] or "m" in bx_opt["loc"]:
|
101
118
|
X_bx = xloc
|
102
119
|
else:
|
103
120
|
X_bx = xloc
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
whiskerprops = dict(
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
bx_opt[
|
121
|
+
|
122
|
+
boxprops = dict(color=bx_opt["EdgeColor"], linewidth=bx_opt["BoxLineWidth"])
|
123
|
+
flierprops = dict(
|
124
|
+
marker=bx_opt["OutlierMarker"],
|
125
|
+
markerfacecolor=bx_opt["OutlierColor"],
|
126
|
+
markersize=bx_opt["OutlierSize"],
|
127
|
+
)
|
128
|
+
whiskerprops = dict(
|
129
|
+
linestyle=bx_opt["WhiskerLineStyle"],
|
130
|
+
color=bx_opt["WhiskerLineColor"],
|
131
|
+
linewidth=bx_opt["WhiskerLineWidth"],
|
132
|
+
)
|
133
|
+
capprops = dict(
|
134
|
+
color=bx_opt["CapLineColor"],
|
135
|
+
linewidth=bx_opt["CapLineWidth"],
|
136
|
+
)
|
137
|
+
medianprops = dict(
|
138
|
+
linestyle=bx_opt["MedianLineStyle"],
|
139
|
+
color=bx_opt["MedianLineColor"],
|
140
|
+
linewidth=bx_opt["MedianLineWidth"],
|
141
|
+
)
|
142
|
+
meanprops = dict(
|
143
|
+
linestyle=bx_opt["MeanLineStyle"],
|
144
|
+
color=bx_opt["MeanLineColor"],
|
145
|
+
linewidth=bx_opt["MeanLineWidth"],
|
146
|
+
)
|
147
|
+
bxp = ax.boxplot(
|
148
|
+
data,
|
149
|
+
positions=X_bx,
|
150
|
+
notch=bx_opt["Notch"],
|
151
|
+
patch_artist=True,
|
152
|
+
boxprops=boxprops,
|
153
|
+
flierprops=flierprops,
|
154
|
+
whiskerprops=whiskerprops,
|
155
|
+
capwidths=bx_opt["CapSize"],
|
156
|
+
showfliers=bx_opt["Outliers"],
|
157
|
+
showcaps=bx_opt["Caps"],
|
158
|
+
capprops=capprops,
|
159
|
+
medianprops=medianprops,
|
160
|
+
meanline=bx_opt["MeanLine"],
|
161
|
+
showmeans=bx_opt["MeanLine"],
|
162
|
+
meanprops=meanprops,
|
163
|
+
widths=bx_opt["x_width"],
|
164
|
+
)
|
165
|
+
|
166
|
+
if bx_opt["BoxLineWidth"] < 0.1:
|
167
|
+
bx_opt["EdgeColor"] = "none"
|
141
168
|
else:
|
142
|
-
bx_opt[
|
169
|
+
bx_opt["EdgeColor"] = bx_opt["EdgeColor"]
|
143
170
|
|
144
|
-
for patch, color in zip(bxp[
|
145
|
-
patch.set_facecolor(to_rgba(color, bx_opt[
|
171
|
+
for patch, color in zip(bxp["boxes"], bx_opt["FaceColor"]):
|
172
|
+
patch.set_facecolor(to_rgba(color, bx_opt["FaceAlpha"]))
|
146
173
|
|
147
|
-
if bx_opt[
|
174
|
+
if bx_opt["MedianLineTop"]:
|
148
175
|
ax.set_children(ax.get_children()[::-1]) # move median line forward
|
149
176
|
|
150
177
|
def plot_violin(data, opt_v, xloc, ax):
|
151
|
-
violin_positions = get_positions(
|
178
|
+
violin_positions = get_positions(
|
179
|
+
xloc, opt_v["loc"], opt_v["x_width"], data.shape[0]
|
180
|
+
)
|
152
181
|
violin_positions = np.nanmean(violin_positions, axis=0)
|
153
182
|
for i, (x, ys) in enumerate(zip(violin_positions, data.T)):
|
154
183
|
ys = ys[~np.isnan(ys)]
|
155
184
|
if len(ys) > 1:
|
156
|
-
kde = gaussian_kde(ys, bw_method=opt_v[
|
185
|
+
kde = gaussian_kde(ys, bw_method=opt_v["BandWidth"])
|
157
186
|
min_val, max_val = ys.min(), ys.max()
|
158
|
-
y_vals = np.linspace(min_val, max_val, opt_v[
|
187
|
+
y_vals = np.linspace(min_val, max_val, opt_v["NumPoints"])
|
159
188
|
kde_vals = kde(y_vals)
|
160
|
-
kde_vals = kde_vals / kde_vals.max() * opt_v[
|
161
|
-
if
|
162
|
-
ax.fill_betweenx(
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
189
|
+
kde_vals = kde_vals / kde_vals.max() * opt_v["x_width"]
|
190
|
+
if "r" in opt_v["loc"].lower():
|
191
|
+
ax.fill_betweenx(
|
192
|
+
y_vals,
|
193
|
+
x,
|
194
|
+
x + kde_vals,
|
195
|
+
color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
|
196
|
+
alpha=opt_v["FaceAlpha"],
|
197
|
+
edgecolor=opt_v["EdgeColor"],
|
198
|
+
)
|
199
|
+
elif "l" in opt_v["loc"].lower() and not "f" in opt_v["loc"].lower():
|
200
|
+
ax.fill_betweenx(
|
201
|
+
y_vals,
|
202
|
+
x - kde_vals,
|
203
|
+
x,
|
204
|
+
color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
|
205
|
+
alpha=opt_v["FaceAlpha"],
|
206
|
+
edgecolor=opt_v["EdgeColor"],
|
207
|
+
)
|
208
|
+
elif "o" in opt_v["loc"].lower() or "both" in opt_v["loc"].lower():
|
209
|
+
ax.fill_betweenx(
|
210
|
+
y_vals,
|
211
|
+
x - kde_vals,
|
212
|
+
x + kde_vals,
|
213
|
+
color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
|
214
|
+
alpha=opt_v["FaceAlpha"],
|
215
|
+
edgecolor=opt_v["EdgeColor"],
|
216
|
+
)
|
217
|
+
elif "i" in opt_v["loc"].lower():
|
177
218
|
if i % 2 == 1: # odd number
|
178
|
-
ax.fill_betweenx(
|
179
|
-
|
180
|
-
|
181
|
-
|
219
|
+
ax.fill_betweenx(
|
220
|
+
y_vals,
|
221
|
+
x - kde_vals,
|
222
|
+
x,
|
223
|
+
color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
|
224
|
+
alpha=opt_v["FaceAlpha"],
|
225
|
+
edgecolor=opt_v["EdgeColor"],
|
226
|
+
)
|
182
227
|
else:
|
183
|
-
ax.fill_betweenx(
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
228
|
+
ax.fill_betweenx(
|
229
|
+
y_vals,
|
230
|
+
x,
|
231
|
+
x + kde_vals,
|
232
|
+
color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
|
233
|
+
alpha=opt_v["FaceAlpha"],
|
234
|
+
edgecolor=opt_v["EdgeColor"],
|
235
|
+
)
|
236
|
+
elif "f" in opt_v["loc"].lower():
|
237
|
+
ax.fill_betweenx(
|
238
|
+
y_vals,
|
239
|
+
x - kde_vals,
|
240
|
+
x + kde_vals,
|
241
|
+
color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
|
242
|
+
alpha=opt_v["FaceAlpha"],
|
243
|
+
edgecolor=opt_v["EdgeColor"],
|
244
|
+
)
|
245
|
+
|
246
|
+
def plot_lines(data, opt_l, opt_s, ax):
|
247
|
+
scatter_positions = get_positions(
|
248
|
+
xloc, opt_s["loc"], opt_s["x_width"], data.shape[0]
|
249
|
+
)
|
250
|
+
for incol in range(data.shape[1] - 1):
|
196
251
|
for irow in range(data.shape[0]):
|
197
252
|
if not np.isnan(data[irow, incol]):
|
198
|
-
if
|
199
|
-
|
253
|
+
if (
|
254
|
+
opt_l["LineStyle"] is not None
|
255
|
+
and not opt_l["LineStyle"] == "none"
|
256
|
+
):
|
257
|
+
x_data = [
|
258
|
+
scatter_positions[irow, incol],
|
259
|
+
scatter_positions[irow, incol + 1],
|
260
|
+
]
|
200
261
|
y_data = [data[irow, incol], data[irow, incol + 1]]
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
262
|
+
|
263
|
+
ax.plot(
|
264
|
+
x_data,
|
265
|
+
y_data,
|
266
|
+
color=opt_l["LineColor"],
|
267
|
+
linestyle=opt_l["LineStyle"],
|
268
|
+
linewidth=opt_l["LineWidth"],
|
269
|
+
alpha=opt_l["LineAlpha"],
|
270
|
+
)
|
271
|
+
|
209
272
|
def get_positions(xloc, loc_type, x_width, n_row=None):
|
210
|
-
if
|
273
|
+
if "rand" in loc_type:
|
211
274
|
scatter_positions = np.zeros((n_row, len(xloc)))
|
212
275
|
np.random.seed(111)
|
213
276
|
for i, x in enumerate(xloc):
|
214
|
-
scatter_positions[:, i] = np.random.uniform(
|
277
|
+
scatter_positions[:, i] = np.random.uniform(
|
278
|
+
x - x_width, x + x_width, n_row
|
279
|
+
)
|
215
280
|
return scatter_positions
|
216
|
-
elif
|
217
|
-
return np.tile(xloc - x_width,(n_row,1))
|
218
|
-
elif
|
219
|
-
return np.tile(xloc + x_width,(n_row,1))
|
220
|
-
elif
|
221
|
-
return np.tile(
|
222
|
-
|
223
|
-
|
281
|
+
elif "l" in loc_type:
|
282
|
+
return np.tile(xloc - x_width, (n_row, 1))
|
283
|
+
elif "r" in loc_type and not "d" in loc_type:
|
284
|
+
return np.tile(xloc + x_width, (n_row, 1))
|
285
|
+
elif "i" in loc_type:
|
286
|
+
return np.tile(
|
287
|
+
np.concatenate([xloc[:1] + x_width, xloc[1:-1], xloc[-1:] - x_width]),
|
288
|
+
(n_row, 1),
|
289
|
+
)
|
290
|
+
elif "o" in loc_type:
|
291
|
+
return np.tile(
|
292
|
+
np.concatenate([xloc[:1] - x_width, xloc[1:-1], xloc[-1:] + x_width]),
|
293
|
+
(n_row, 1),
|
294
|
+
)
|
224
295
|
else:
|
225
|
-
return np.tile(xloc,(n_row,1))
|
226
|
-
|
296
|
+
return np.tile(xloc, (n_row, 1))
|
297
|
+
|
298
|
+
def sort_catplot_layers(custom_order, full_order=["b", "bx", "e", "v", "s", "l"]):
|
227
299
|
"""
|
228
300
|
sort layers
|
229
301
|
"""
|
230
302
|
# Ensure custom_order is a list of strings
|
231
|
-
custom_order = [str(layer) for layer in custom_order]
|
303
|
+
custom_order = [str(layer) for layer in custom_order]
|
232
304
|
j = 1
|
233
305
|
layers = list(range(len(full_order)))
|
234
306
|
for i in range(len(full_order)):
|
@@ -245,181 +317,190 @@ def catplot(data, *args, **kwargs):
|
|
245
317
|
# # Example usage:
|
246
318
|
# custom_order = ['s', 'bx', 'e']
|
247
319
|
# full_order = sort_catplot_layers(custom_order)
|
248
|
-
|
320
|
+
|
249
321
|
# full_order
|
250
|
-
opt = kwargs.get(
|
251
|
-
ax = kwargs.get(
|
252
|
-
if
|
253
|
-
ax=plt.gca()
|
254
|
-
|
255
|
-
default_colors =
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
opt.setdefault(
|
270
|
-
opt[
|
271
|
-
|
322
|
+
opt = kwargs.get("opt", {})
|
323
|
+
ax = kwargs.get("ax", None)
|
324
|
+
if "ax" not in locals() or ax is None:
|
325
|
+
ax = plt.gca()
|
326
|
+
|
327
|
+
default_colors = (
|
328
|
+
np.array(
|
329
|
+
[
|
330
|
+
[0, 0, 0],
|
331
|
+
[234, 37, 46],
|
332
|
+
[0, 154, 222],
|
333
|
+
[175, 89, 186],
|
334
|
+
[255, 198, 37],
|
335
|
+
[242, 133, 34],
|
336
|
+
]
|
337
|
+
)
|
338
|
+
/ 255.0
|
339
|
+
)
|
340
|
+
|
341
|
+
opt.setdefault("c", default_colors)
|
342
|
+
if len(opt["c"]) < data.shape[1]:
|
343
|
+
additional_colors = plt.cm.winter(
|
344
|
+
np.linspace(0, 1, data.shape[1] - len(opt["c"]))
|
345
|
+
)
|
346
|
+
opt["c"] = np.vstack([opt["c"], additional_colors[:, :3]])
|
347
|
+
if isinstance(opt["c"], dict):
|
348
|
+
opt["c"] = opt["c"]["c"]
|
349
|
+
|
350
|
+
opt.setdefault("loc", {})
|
351
|
+
opt["loc"].setdefault("go", 0)
|
352
|
+
opt["loc"].setdefault("xloc", np.arange(1, data.shape[1] + 1))
|
272
353
|
|
273
354
|
# export setting
|
274
|
-
opt.setdefault(
|
275
|
-
opt[
|
276
|
-
print(opt[
|
355
|
+
opt.setdefault("export", {})
|
356
|
+
opt["export"].setdefault("path", None)
|
357
|
+
print(opt["export"])
|
277
358
|
|
278
359
|
# opt.setdefault('layer', {})
|
279
|
-
opt.setdefault(
|
280
|
-
|
281
|
-
opt.setdefault(
|
282
|
-
opt[
|
283
|
-
opt[
|
284
|
-
opt[
|
285
|
-
opt[
|
286
|
-
opt[
|
287
|
-
opt[
|
288
|
-
opt[
|
289
|
-
opt[
|
290
|
-
opt[
|
291
|
-
opt[
|
292
|
-
opt[
|
293
|
-
|
294
|
-
opt.setdefault(
|
295
|
-
opt[
|
296
|
-
opt[
|
297
|
-
opt[
|
298
|
-
opt[
|
299
|
-
opt[
|
300
|
-
opt[
|
301
|
-
opt[
|
302
|
-
opt[
|
303
|
-
opt[
|
304
|
-
opt[
|
305
|
-
opt[
|
306
|
-
opt[
|
307
|
-
opt[
|
308
|
-
opt[
|
309
|
-
opt[
|
310
|
-
opt[
|
311
|
-
opt[
|
312
|
-
|
313
|
-
opt.setdefault(
|
314
|
-
opt[
|
315
|
-
opt[
|
316
|
-
opt[
|
317
|
-
opt[
|
318
|
-
opt[
|
319
|
-
opt[
|
320
|
-
opt[
|
321
|
-
opt[
|
322
|
-
opt[
|
323
|
-
opt[
|
324
|
-
|
325
|
-
opt.setdefault(
|
326
|
-
opt[
|
327
|
-
opt[
|
328
|
-
opt[
|
329
|
-
opt[
|
330
|
-
opt[
|
331
|
-
|
332
|
-
opt.setdefault(
|
333
|
-
opt[
|
334
|
-
opt[
|
335
|
-
opt[
|
336
|
-
opt[
|
337
|
-
opt[
|
338
|
-
opt[
|
339
|
-
opt[
|
340
|
-
opt[
|
341
|
-
opt[
|
342
|
-
opt[
|
343
|
-
opt[
|
344
|
-
opt[
|
345
|
-
opt[
|
346
|
-
opt[
|
360
|
+
opt.setdefault("layer", ["b", "bx", "e", "v", "s", "l"])
|
361
|
+
|
362
|
+
opt.setdefault("b", {})
|
363
|
+
opt["b"].setdefault("go", 1)
|
364
|
+
opt["b"].setdefault("loc", "c")
|
365
|
+
opt["b"].setdefault("FaceColor", opt["c"])
|
366
|
+
opt["b"].setdefault("FaceAlpha", 0.65)
|
367
|
+
opt["b"].setdefault("EdgeColor", "k")
|
368
|
+
opt["b"].setdefault("EdgeAlpha", 1)
|
369
|
+
opt["b"].setdefault("LineStyle", "-")
|
370
|
+
opt["b"].setdefault("LineWidth", 0.8)
|
371
|
+
opt["b"].setdefault("x_width", 0.5)
|
372
|
+
opt["b"].setdefault("ShowBaseLine", "off")
|
373
|
+
opt["b"].setdefault("hatch", None)
|
374
|
+
|
375
|
+
opt.setdefault("e", {})
|
376
|
+
opt["e"].setdefault("go", 1)
|
377
|
+
opt["e"].setdefault("loc", "l")
|
378
|
+
opt["e"].setdefault("LineWidth", 1)
|
379
|
+
opt["e"].setdefault("CapLineWidth", 1)
|
380
|
+
opt["e"].setdefault("CapSize", 2)
|
381
|
+
opt["e"].setdefault("Marker", "none")
|
382
|
+
opt["e"].setdefault("LineStyle", "none")
|
383
|
+
opt["e"].setdefault("LineColor", "k")
|
384
|
+
opt["e"].setdefault("LineJoin", "round")
|
385
|
+
opt["e"].setdefault("MarkerSize", "auto")
|
386
|
+
opt["e"].setdefault("FaceColor", opt["c"])
|
387
|
+
opt["e"].setdefault("MarkerEdgeColor", "none")
|
388
|
+
opt["e"].setdefault("Visible", True)
|
389
|
+
opt["e"].setdefault("Orientation", "vertical")
|
390
|
+
opt["e"].setdefault("error", "sem")
|
391
|
+
opt["e"].setdefault("x_width", opt["b"]["x_width"] / 5)
|
392
|
+
opt["e"].setdefault("cap_dir", "b")
|
393
|
+
|
394
|
+
opt.setdefault("s", {})
|
395
|
+
opt["s"].setdefault("go", 1)
|
396
|
+
opt["s"].setdefault("loc", "r")
|
397
|
+
opt["s"].setdefault("FaceColor", opt["c"])
|
398
|
+
opt["s"].setdefault("cmap", None)
|
399
|
+
opt["s"].setdefault("FaceAlpha", 1)
|
400
|
+
opt["s"].setdefault("x_width", opt["b"]["x_width"] / 5)
|
401
|
+
opt["s"].setdefault("Marker", "o")
|
402
|
+
opt["s"].setdefault("MarkerSize", 10)
|
403
|
+
opt["s"].setdefault("LineWidth", 0.5)
|
404
|
+
opt["s"].setdefault("MarkerEdgeColor", "k")
|
405
|
+
|
406
|
+
opt.setdefault("l", {})
|
407
|
+
opt["l"].setdefault("go", 1)
|
408
|
+
opt["l"].setdefault("LineStyle", "-")
|
409
|
+
opt["l"].setdefault("LineColor", "k")
|
410
|
+
opt["l"].setdefault("LineWidth", 0.5)
|
411
|
+
opt["l"].setdefault("LineAlpha", 0.5)
|
412
|
+
|
413
|
+
opt.setdefault("bx", {})
|
414
|
+
opt["bx"].setdefault("go", 0)
|
415
|
+
opt["bx"].setdefault("loc", "r")
|
416
|
+
opt["bx"].setdefault("FaceColor", opt["c"])
|
417
|
+
opt["bx"].setdefault("EdgeColor", "k")
|
418
|
+
opt["bx"].setdefault("FaceAlpha", 0.7)
|
419
|
+
opt["bx"].setdefault("EdgeAlpha", 1)
|
420
|
+
opt["bx"].setdefault("LineStyle", "-")
|
421
|
+
opt["bx"].setdefault("x_width", 0.2)
|
422
|
+
opt["bx"].setdefault("ShowBaseLine", "off")
|
423
|
+
opt["bx"].setdefault("Notch", False)
|
424
|
+
opt["bx"].setdefault("Outliers", "on")
|
425
|
+
opt["bx"].setdefault("OutlierMarker", "+")
|
426
|
+
opt["bx"].setdefault("OutlierColor", "r")
|
427
|
+
opt["bx"].setdefault("OutlierSize", 6)
|
347
428
|
# opt['bx'].setdefault('PlotStyle', 'traditional')
|
348
429
|
# opt['bx'].setdefault('FactorDirection', 'auto')
|
349
|
-
opt[
|
350
|
-
opt[
|
351
|
-
opt[
|
352
|
-
opt[
|
353
|
-
opt[
|
354
|
-
opt[
|
355
|
-
opt[
|
356
|
-
opt[
|
357
|
-
opt[
|
358
|
-
opt[
|
359
|
-
opt[
|
360
|
-
opt[
|
361
|
-
opt[
|
362
|
-
opt[
|
363
|
-
opt[
|
364
|
-
opt[
|
365
|
-
opt[
|
366
|
-
opt[
|
367
|
-
opt[
|
368
|
-
opt[
|
369
|
-
opt[
|
370
|
-
|
430
|
+
opt["bx"].setdefault("Whisker", 0.5)
|
431
|
+
opt["bx"].setdefault("Orientation", "vertical")
|
432
|
+
opt["bx"].setdefault("BoxLineWidth", 0.5)
|
433
|
+
opt["bx"].setdefault("FaceColor", "k")
|
434
|
+
opt["bx"].setdefault("WhiskerLineStyle", "-")
|
435
|
+
opt["bx"].setdefault("WhiskerLineColor", "k")
|
436
|
+
opt["bx"].setdefault("WhiskerLineWidth", 0.5)
|
437
|
+
opt["bx"].setdefault("Caps", True)
|
438
|
+
opt["bx"].setdefault("CapLineColor", "k")
|
439
|
+
opt["bx"].setdefault("CapLineWidth", 0.5)
|
440
|
+
opt["bx"].setdefault("CapSize", 0.2)
|
441
|
+
opt["bx"].setdefault("MedianLineStyle", "-")
|
442
|
+
opt["bx"].setdefault("MedianStyle", "line")
|
443
|
+
opt["bx"].setdefault("MedianLineColor", "k")
|
444
|
+
opt["bx"].setdefault("MedianLineWidth", 2)
|
445
|
+
opt["bx"].setdefault("MedianLineTop", False)
|
446
|
+
opt["bx"].setdefault("MeanLine", False)
|
447
|
+
opt["bx"].setdefault("showmeans", opt["bx"]["MeanLine"])
|
448
|
+
opt["bx"].setdefault("MeanLineStyle", "-")
|
449
|
+
opt["bx"].setdefault("MeanLineColor", "w")
|
450
|
+
opt["bx"].setdefault("MeanLineWidth", 2)
|
451
|
+
|
371
452
|
# Violin plot options
|
372
|
-
opt.setdefault(
|
373
|
-
opt[
|
374
|
-
opt[
|
375
|
-
opt[
|
376
|
-
opt[
|
377
|
-
opt[
|
378
|
-
opt[
|
379
|
-
opt[
|
380
|
-
opt[
|
381
|
-
opt[
|
382
|
-
opt[
|
383
|
-
opt[
|
384
|
-
|
453
|
+
opt.setdefault("v", {})
|
454
|
+
opt["v"].setdefault("go", 0)
|
455
|
+
opt["v"].setdefault("x_width", 0.3)
|
456
|
+
opt["v"].setdefault("loc", "r")
|
457
|
+
opt["v"].setdefault("EdgeColor", "none")
|
458
|
+
opt["v"].setdefault("FaceColor", opt["c"])
|
459
|
+
opt["v"].setdefault("FaceAlpha", 0.3)
|
460
|
+
opt["v"].setdefault("BandWidth", "scott")
|
461
|
+
opt["v"].setdefault("Function", "pdf")
|
462
|
+
opt["v"].setdefault("Kernel", "gau")
|
463
|
+
opt["v"].setdefault("NumPoints", 500)
|
464
|
+
opt["v"].setdefault("BoundaryCorrection", "reflection")
|
385
465
|
|
386
466
|
data_m = np.nanmean(data, axis=0)
|
387
467
|
nr, nc = data.shape
|
388
|
-
|
468
|
+
|
389
469
|
for key in kwargs.keys():
|
390
470
|
if key in opt:
|
391
471
|
if isinstance(kwargs[key], dict):
|
392
472
|
opt[key].update(kwargs[key])
|
393
473
|
else:
|
394
474
|
opt[key] = kwargs[key]
|
395
|
-
xloc = opt[
|
396
|
-
layers = sort_catplot_layers(opt[
|
397
|
-
for layer in layers:
|
398
|
-
if layer==
|
399
|
-
plot_bars(data_m, opt[
|
400
|
-
elif layer==
|
401
|
-
plot_errors(data, data_m, opt[
|
402
|
-
elif layer==
|
403
|
-
plot_scatter(data, opt[
|
404
|
-
elif layer==
|
405
|
-
plot_boxplot(data, opt[
|
406
|
-
elif layer==
|
407
|
-
plot_violin(data, opt[
|
408
|
-
elif all([layer==
|
409
|
-
plot_lines(data, opt[
|
475
|
+
xloc = opt["loc"]["xloc"]
|
476
|
+
layers = sort_catplot_layers(opt["layer"])
|
477
|
+
for layer in layers:
|
478
|
+
if layer == "b" and opt["b"]["go"]:
|
479
|
+
plot_bars(data_m, opt["b"], xloc, ax)
|
480
|
+
elif layer == "e" and opt["e"]["go"]:
|
481
|
+
plot_errors(data, data_m, opt["e"], xloc, ax)
|
482
|
+
elif layer == "s" and opt["s"]["go"]:
|
483
|
+
plot_scatter(data, opt["s"], xloc, ax)
|
484
|
+
elif layer == "bx" and opt["bx"]["go"]:
|
485
|
+
plot_boxplot(data, opt["bx"], xloc, ax)
|
486
|
+
elif layer == "v" and opt["v"]["go"]:
|
487
|
+
plot_violin(data, opt["v"], xloc, ax)
|
488
|
+
elif all([layer == "l", opt["l"]["go"], opt["s"]["go"]]):
|
489
|
+
plot_lines(data, opt["l"], opt["s"], ax)
|
410
490
|
# figsets
|
411
|
-
kw_figsets=kwargs.get(
|
491
|
+
kw_figsets = kwargs.get("figsets", None)
|
412
492
|
if kw_figsets is not None:
|
413
|
-
figsets(ax=ax
|
493
|
+
figsets(ax=ax, **kw_figsets)
|
414
494
|
return ax
|
415
495
|
|
496
|
+
|
416
497
|
# from py2ls.ips import get_color,figsets
|
417
498
|
# opt={}
|
418
499
|
# opt = {
|
419
500
|
# 'export':{'path':get_cwd()},
|
420
501
|
# 'c': get_color(5,cmap='jet',by='linspace'), # Custom colors for 3 categories
|
421
502
|
# 'b': {
|
422
|
-
# 'go': 0,
|
503
|
+
# 'go': 0,
|
423
504
|
# 'x_width': 0.85,
|
424
505
|
# 'FaceAlpha': 0.7,
|
425
506
|
# 'EdgeColor':'none'
|
@@ -448,7 +529,7 @@ def catplot(data, *args, **kwargs):
|
|
448
529
|
# 'FaceAlpha': 1,
|
449
530
|
# 'FaceColor':'k',
|
450
531
|
# 'LineWidth':1
|
451
|
-
|
532
|
+
|
452
533
|
# },
|
453
534
|
# 'bx':{
|
454
535
|
# 'go':1,
|
@@ -500,7 +581,7 @@ def catplot(data, *args, **kwargs):
|
|
500
581
|
import numpy as np
|
501
582
|
import matplotlib
|
502
583
|
import matplotlib.pyplot as plt
|
503
|
-
import matplotlib.ticker as tck
|
584
|
+
import matplotlib.ticker as tck
|
504
585
|
import seaborn as sns
|
505
586
|
from cycler import cycler
|
506
587
|
|
@@ -508,6 +589,7 @@ from cycler import cycler
|
|
508
589
|
def get_cmap():
|
509
590
|
return plt.colormaps()
|
510
591
|
|
592
|
+
|
511
593
|
def read_mplstyle(style_file):
|
512
594
|
# Load the style file
|
513
595
|
plt.style.use(style_file)
|
@@ -521,11 +603,14 @@ def read_mplstyle(style_file):
|
|
521
603
|
for i, j in style_dict.items():
|
522
604
|
print(f"\n{i}::::{j}")
|
523
605
|
return style_dict
|
606
|
+
|
607
|
+
|
524
608
|
# #example usage:
|
525
609
|
# style_file = "/ std-colors.mplstyle"
|
526
610
|
# style_dict = read_mplstyle(style_file)
|
527
611
|
|
528
|
-
|
612
|
+
|
613
|
+
def figsets(*args, **kwargs):
|
529
614
|
"""
|
530
615
|
usage:
|
531
616
|
figsets(ax=axs[1],
|
@@ -575,13 +660,31 @@ def figsets(*args,**kwargs):
|
|
575
660
|
fontname = "Arial"
|
576
661
|
sns_themes = ["white", "whitegrid", "dark", "darkgrid", "ticks"]
|
577
662
|
sns_contexts = ["notebook", "talk", "poster"] # now available "paper"
|
578
|
-
scienceplots_styles = [
|
579
|
-
"
|
580
|
-
"
|
663
|
+
scienceplots_styles = [
|
664
|
+
"science",
|
665
|
+
"nature",
|
666
|
+
"scatter",
|
667
|
+
"ieee",
|
668
|
+
"no-latex",
|
669
|
+
"std-colors",
|
670
|
+
"high-vis",
|
671
|
+
"bright",
|
672
|
+
"dark_background",
|
673
|
+
"science",
|
674
|
+
"high-vis",
|
675
|
+
"vibrant",
|
676
|
+
"muted",
|
677
|
+
"retro",
|
678
|
+
"grid",
|
679
|
+
"high-contrast",
|
680
|
+
"light",
|
681
|
+
"cjk-tc-font",
|
682
|
+
"cjk-kr-font",
|
581
683
|
]
|
582
|
-
|
684
|
+
|
685
|
+
def set_step_1(ax, key, value):
|
583
686
|
if ("fo" in key) and (("size" in key) or ("sz" in key)):
|
584
|
-
fontsize=value
|
687
|
+
fontsize = value
|
585
688
|
plt.rcParams.update({"font.size": value})
|
586
689
|
# style
|
587
690
|
if "st" in key.lower() or "th" in key.lower():
|
@@ -611,13 +714,13 @@ def figsets(*args,**kwargs):
|
|
611
714
|
if "la" in key.lower():
|
612
715
|
if "loc" in key.lower() or "po" in key.lower():
|
613
716
|
for i in value:
|
614
|
-
if "l" in i.lower() and not
|
615
|
-
ax.yaxis.set_label_position("left")
|
616
|
-
if "r" in i.lower() and not
|
717
|
+
if "l" in i.lower() and not "g" in i.lower():
|
718
|
+
ax.yaxis.set_label_position("left")
|
719
|
+
if "r" in i.lower() and not "o" in i.lower():
|
617
720
|
ax.yaxis.set_label_position("right")
|
618
|
-
if "t" in i.lower() and not
|
721
|
+
if "t" in i.lower() and not "l" in i.lower():
|
619
722
|
ax.xaxis.set_label_position("top")
|
620
|
-
if "b" in i.lower()and not
|
723
|
+
if "b" in i.lower() and not "o" in i.lower():
|
621
724
|
ax.xaxis.set_label_position("bottom")
|
622
725
|
if ("x" in key.lower()) and (
|
623
726
|
"tic" not in key.lower() and "tk" not in key.lower()
|
@@ -631,15 +734,15 @@ def figsets(*args,**kwargs):
|
|
631
734
|
"tic" not in key.lower() and "tk" not in key.lower()
|
632
735
|
):
|
633
736
|
ax.set_zlabel(value, fontname=fontname)
|
634
|
-
if key==
|
737
|
+
if key == "xlabel" and isinstance(value, dict):
|
635
738
|
ax.set_xlabel(**value)
|
636
|
-
if key==
|
739
|
+
if key == "ylabel" and isinstance(value, dict):
|
637
740
|
ax.set_ylabel(**value)
|
638
741
|
# tick location
|
639
742
|
if "tic" in key.lower() or "tk" in key.lower():
|
640
743
|
if ("loc" in key.lower()) or ("po" in key.lower()):
|
641
|
-
if isinstance(value,str):
|
642
|
-
value=[value]
|
744
|
+
if isinstance(value, str):
|
745
|
+
value = [value]
|
643
746
|
if isinstance(value, list):
|
644
747
|
loc = []
|
645
748
|
for i in value:
|
@@ -654,28 +757,28 @@ def figsets(*args,**kwargs):
|
|
654
757
|
if i.lower() in ["a", "both", "all", "al", ":"]:
|
655
758
|
ax.xaxis.set_ticks_position("both")
|
656
759
|
ax.yaxis.set_ticks_position("both")
|
657
|
-
if i.lower() in ["xnone",
|
760
|
+
if i.lower() in ["xnone", "xoff", "none"]:
|
658
761
|
ax.xaxis.set_ticks_position("none")
|
659
|
-
if i.lower() in ["ynone",
|
762
|
+
if i.lower() in ["ynone", "yoff", "none"]:
|
660
763
|
ax.yaxis.set_ticks_position("none")
|
661
764
|
# ticks / labels
|
662
765
|
elif "x" in key.lower():
|
663
766
|
if value is None:
|
664
|
-
value=[]
|
767
|
+
value = []
|
665
768
|
if "la" not in key.lower():
|
666
769
|
ax.set_xticks(value)
|
667
770
|
if "la" in key.lower():
|
668
771
|
ax.set_xticklabels(value)
|
669
772
|
elif "y" in key.lower():
|
670
773
|
if value is None:
|
671
|
-
value=[]
|
774
|
+
value = []
|
672
775
|
if "la" not in key.lower():
|
673
776
|
ax.set_yticks(value)
|
674
777
|
if "la" in key.lower():
|
675
778
|
ax.set_yticklabels(value)
|
676
779
|
elif "z" in key.lower():
|
677
780
|
if value is None:
|
678
|
-
value=[]
|
781
|
+
value = []
|
679
782
|
if "la" not in key.lower():
|
680
783
|
ax.set_zticks(value)
|
681
784
|
if "la" in key.lower():
|
@@ -683,34 +786,31 @@ def figsets(*args,**kwargs):
|
|
683
786
|
# rotation
|
684
787
|
if "angle" in key.lower() or ("rot" in key.lower()):
|
685
788
|
if "x" in key.lower():
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
tick.set_horizontalalignment(
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
ax.tick_params(axis='x', rotation=value)
|
696
|
-
for tick in ax.get_xticklabels():
|
697
|
-
tick.set_horizontalalignment('left')
|
789
|
+
ax.tick_params(axis="x", rotation=value)
|
790
|
+
for tick in ax.get_xticklabels():
|
791
|
+
if value in [0, 90, 180, 270]:
|
792
|
+
tick.set_horizontalalignment("center")
|
793
|
+
else:
|
794
|
+
if value > 0:
|
795
|
+
tick.set_horizontalalignment("right")
|
796
|
+
elif value < 0:
|
797
|
+
tick.set_horizontalalignment("left")
|
698
798
|
if "y" in key.lower():
|
699
799
|
ax.tick_params(axis="y", rotation=value)
|
700
800
|
for tick in ax.get_yticklabels():
|
701
|
-
tick.set_horizontalalignment(
|
801
|
+
tick.set_horizontalalignment("right")
|
702
802
|
|
703
803
|
if "bo" in key in key: # box setting, and ("p" in key or "l" in key):
|
704
804
|
if isinstance(value, (str, list)):
|
705
805
|
locations = []
|
706
806
|
for i in value:
|
707
|
-
if "l" in i.lower() and not
|
807
|
+
if "l" in i.lower() and not "t" in i.lower():
|
708
808
|
locations.append("left")
|
709
|
-
if "r" in i.lower()and not
|
809
|
+
if "r" in i.lower() and not "o" in i.lower(): # right
|
710
810
|
locations.append("right")
|
711
|
-
if "t" in i.lower() and not
|
811
|
+
if "t" in i.lower() and not "r" in i.lower(): # top
|
712
812
|
locations.append("top")
|
713
|
-
if "b" in i.lower() and not
|
813
|
+
if "b" in i.lower() and not "t" in i.lower():
|
714
814
|
locations.append("bottom")
|
715
815
|
if i.lower() in ["a", "both", "all", "al", ":"]:
|
716
816
|
[
|
@@ -726,7 +826,7 @@ def figsets(*args,**kwargs):
|
|
726
826
|
spi.set_position(("outward", 0))
|
727
827
|
else:
|
728
828
|
spi.set_color("none") # no spine
|
729
|
-
if
|
829
|
+
if "tick" in key.lower(): # tick ticks tick_para ={}
|
730
830
|
if isinstance(value, dict):
|
731
831
|
for k, val in value.items():
|
732
832
|
if "wh" in k.lower():
|
@@ -735,28 +835,28 @@ def figsets(*args,**kwargs):
|
|
735
835
|
) # {'major', 'minor', 'both'}, default: 'major'
|
736
836
|
elif "dir" in k.lower():
|
737
837
|
ax.tick_params(direction=val) # {'in', 'out', 'inout'}
|
738
|
-
elif "len" in k.lower()
|
838
|
+
elif "len" in k.lower(): # length
|
739
839
|
ax.tick_params(length=val)
|
740
|
-
elif ("wid" in k.lower()) or ("wd" in k.lower()):
|
840
|
+
elif ("wid" in k.lower()) or ("wd" in k.lower()): # width
|
741
841
|
ax.tick_params(width=val)
|
742
|
-
elif "ax" in k.lower():
|
842
|
+
elif "ax" in k.lower(): # ax
|
743
843
|
ax.tick_params(axis=val) # {'x', 'y', 'both'}, default: 'both'
|
744
844
|
elif ("c" in k.lower()) and ("ect" not in k.lower()):
|
745
845
|
ax.tick_params(colors=val) # Tick color.
|
746
|
-
elif "pad" in k.lower() or
|
846
|
+
elif "pad" in k.lower() or "space" in k.lower():
|
747
847
|
ax.tick_params(
|
748
848
|
pad=val
|
749
849
|
) # float, distance in points between tick and label
|
750
850
|
elif (
|
751
|
-
("lab" in k.lower() or
|
851
|
+
("lab" in k.lower() or "text" in k.lower())
|
752
852
|
and ("s" in k.lower())
|
753
853
|
and ("z" in k.lower())
|
754
|
-
):
|
854
|
+
): # label_size
|
755
855
|
ax.tick_params(
|
756
856
|
labelsize=val
|
757
857
|
) # float, distance in points between tick and label
|
758
858
|
|
759
|
-
if "mi" in key.lower() and "tic" in key.lower()
|
859
|
+
if "mi" in key.lower() and "tic" in key.lower(): # minor_ticks
|
760
860
|
if "x" in value.lower() or "x" in key.lower():
|
761
861
|
ax.xaxis.set_minor_locator(tck.AutoMinorLocator()) # ax.minorticks_on()
|
762
862
|
if "y" in value.lower() or "y" in key.lower():
|
@@ -767,7 +867,8 @@ def figsets(*args,**kwargs):
|
|
767
867
|
ax.minorticks_on()
|
768
868
|
if key == "colormap" or key == "cmap":
|
769
869
|
plt.set_cmap(value)
|
770
|
-
|
870
|
+
|
871
|
+
def set_step_2(ax, key, value):
|
771
872
|
if key == "figsize":
|
772
873
|
pass
|
773
874
|
if "xlim" in key.lower():
|
@@ -776,7 +877,7 @@ def figsets(*args,**kwargs):
|
|
776
877
|
ax.set_ylim(value)
|
777
878
|
if "zlim" in key.lower():
|
778
879
|
ax.set_zlim(value)
|
779
|
-
if "sc" in key.lower():
|
880
|
+
if "sc" in key.lower(): # scale
|
780
881
|
if "x" in key.lower():
|
781
882
|
ax.set_xscale(value)
|
782
883
|
if "y" in key.lower():
|
@@ -786,19 +887,19 @@ def figsets(*args,**kwargs):
|
|
786
887
|
if key == "grid":
|
787
888
|
if isinstance(value, dict):
|
788
889
|
for k, val in value.items():
|
789
|
-
if "wh" in k.lower():
|
890
|
+
if "wh" in k.lower(): # which
|
790
891
|
ax.grid(
|
791
892
|
which=val
|
792
893
|
) # {'major', 'minor', 'both'}, default: 'major'
|
793
|
-
elif "ax" in k.lower():
|
894
|
+
elif "ax" in k.lower(): # ax
|
794
895
|
ax.grid(axis=val) # {'x', 'y', 'both'}, default: 'both'
|
795
|
-
elif ("c" in k.lower()) and ("ect" not in k.lower()):
|
896
|
+
elif ("c" in k.lower()) and ("ect" not in k.lower()): # c: color
|
796
897
|
ax.grid(color=val) # Tick color.
|
797
|
-
elif "l" in k.lower() and ("s" in k.lower())
|
898
|
+
elif "l" in k.lower() and ("s" in k.lower()): # ls:line stype
|
798
899
|
ax.grid(linestyle=val)
|
799
|
-
elif "l" in k.lower() and ("w" in k.lower()):
|
900
|
+
elif "l" in k.lower() and ("w" in k.lower()): # lw: line width
|
800
901
|
ax.grid(linewidth=val)
|
801
|
-
elif "al" in k.lower()
|
902
|
+
elif "al" in k.lower(): # alpha:
|
802
903
|
ax.grid(alpha=val)
|
803
904
|
else:
|
804
905
|
if value == "on" or value is True:
|
@@ -810,37 +911,39 @@ def figsets(*args,**kwargs):
|
|
810
911
|
plt.suptitle(value)
|
811
912
|
else:
|
812
913
|
ax.set_title(value)
|
813
|
-
if key.lower() in ["spine", "adjust", "ad", "sp", "spi", "adj","spines"]:
|
914
|
+
if key.lower() in ["spine", "adjust", "ad", "sp", "spi", "adj", "spines"]:
|
814
915
|
if isinstance(value, bool) or (value in ["go", "do", "ja", "yes"]):
|
815
916
|
if value:
|
816
917
|
adjust_spines(ax) # dafault distance=2
|
817
918
|
if isinstance(value, (float, int)):
|
818
919
|
adjust_spines(ax=ax, distance=value)
|
819
|
-
if "c" in key.lower() and (
|
920
|
+
if "c" in key.lower() and (
|
921
|
+
"sp" in key.lower() or "ax" in key.lower()
|
922
|
+
): # spine color
|
820
923
|
for loc, spi in ax.spines.items():
|
821
924
|
spi.set_color(value)
|
822
|
-
if
|
823
|
-
legend_kws = kwargs.get(
|
925
|
+
if "leg" in key.lower(): # legend
|
926
|
+
legend_kws = kwargs.get("legend", None)
|
824
927
|
if legend_kws:
|
825
928
|
# https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html
|
826
|
-
ax.legend(**legend_kws)
|
827
|
-
|
929
|
+
ax.legend(**legend_kws)
|
930
|
+
|
828
931
|
for arg in args:
|
829
|
-
if isinstance(arg,matplotlib.axes._axes.Axes):
|
830
|
-
ax=arg
|
831
|
-
args=args[1:]
|
832
|
-
ax = kwargs.get(
|
833
|
-
if
|
834
|
-
ax=plt.gca()
|
932
|
+
if isinstance(arg, matplotlib.axes._axes.Axes):
|
933
|
+
ax = arg
|
934
|
+
args = args[1:]
|
935
|
+
ax = kwargs.get("ax", plt.gca())
|
936
|
+
if "ax" not in locals() or ax is None:
|
937
|
+
ax = plt.gca()
|
835
938
|
for key, value in kwargs.items():
|
836
939
|
set_step_1(ax, key, value)
|
837
940
|
set_step_2(ax, key, value)
|
838
941
|
for arg in args:
|
839
942
|
if isinstance(arg, dict):
|
840
943
|
for k, val in arg.items():
|
841
|
-
set_step_1(ax,k, val)
|
944
|
+
set_step_1(ax, k, val)
|
842
945
|
for k, val in arg.items():
|
843
|
-
set_step_2(ax,k, val)
|
946
|
+
set_step_2(ax, k, val)
|
844
947
|
else:
|
845
948
|
Nargin = len(args) // 2
|
846
949
|
ax.labelFontSizeMultiplier = 1
|
@@ -850,11 +953,11 @@ def figsets(*args,**kwargs):
|
|
850
953
|
for ip in range(Nargin):
|
851
954
|
key = args[ip * 2].lower()
|
852
955
|
value = args[ip * 2 + 1]
|
853
|
-
set_step_1(ax,key, value)
|
956
|
+
set_step_1(ax, key, value)
|
854
957
|
for ip in range(Nargin):
|
855
958
|
key = args[ip * 2].lower()
|
856
959
|
value = args[ip * 2 + 1]
|
857
|
-
set_step_2(ax,key, value)
|
960
|
+
set_step_2(ax, key, value)
|
858
961
|
colors = [
|
859
962
|
"#474747",
|
860
963
|
"#FF2C00",
|
@@ -870,8 +973,8 @@ def figsets(*args,**kwargs):
|
|
870
973
|
plt.gcf().align_labels()
|
871
974
|
|
872
975
|
|
976
|
+
from cycler import cycler
|
873
977
|
|
874
|
-
from cycler import cycler
|
875
978
|
|
876
979
|
# set up the colorlist, give the number, or the colormap's name
|
877
980
|
def get_color(n=1, cmap="auto", by="start"):
|
@@ -881,6 +984,7 @@ def get_color(n=1, cmap="auto", by="start"):
|
|
881
984
|
colors = [cmap_(i) for i in range(cmap_.N)]
|
882
985
|
return [matplotlib.colors.rgb2hex(color) for color in colors]
|
883
986
|
# usage: clist = cmap2hex("viridis")
|
987
|
+
|
884
988
|
# cycle times, total number is n (defaultn=10)
|
885
989
|
def cycle2list(colorlist, n=10):
|
886
990
|
cycler_ = cycler(tmp=colorlist)
|
@@ -890,18 +994,21 @@ def get_color(n=1, cmap="auto", by="start"):
|
|
890
994
|
if i > n:
|
891
995
|
break
|
892
996
|
return clist
|
997
|
+
|
893
998
|
def hue2rgb(hex_colors):
|
894
999
|
def hex_to_rgb(hex_color):
|
895
1000
|
"""Converts a hexadecimal color code to RGB values."""
|
896
1001
|
if hex_colors.startswith("#"):
|
897
1002
|
hex_color = hex_color.lstrip("#")
|
898
1003
|
return tuple(int(hex_color[i : i + 2], 16) / 255.0 for i in (0, 2, 4))
|
1004
|
+
|
899
1005
|
if isinstance(hex_colors, str):
|
900
1006
|
return hex_to_rgb(hex_colors)
|
901
1007
|
elif isinstance(hex_colors, (list)):
|
902
1008
|
"""Converts a list of hexadecimal color codes to a list of RGB values."""
|
903
1009
|
rgb_values = [hex_to_rgb(hex_color) for hex_color in hex_colors]
|
904
1010
|
return rgb_values
|
1011
|
+
|
905
1012
|
if "aut" in cmap:
|
906
1013
|
colorlist = [
|
907
1014
|
"#474747",
|
@@ -914,7 +1021,7 @@ def get_color(n=1, cmap="auto", by="start"):
|
|
914
1021
|
]
|
915
1022
|
else:
|
916
1023
|
colorlist = cmap2hex(cmap)
|
917
|
-
if "st" in by.lower() or "be" in by.lower():
|
1024
|
+
if "st" in by.lower() or "be" in by.lower():
|
918
1025
|
# cycle it
|
919
1026
|
clist = cycle2list(colorlist, n=n)
|
920
1027
|
if "l" in by.lower() or "p" in by.lower():
|
@@ -927,6 +1034,7 @@ def get_color(n=1, cmap="auto", by="start"):
|
|
927
1034
|
return clist # a color list
|
928
1035
|
# example usage: clist = get_color(4,cmap="auto", by="start") # get_color(4, cmap="hot", by="linspace")
|
929
1036
|
|
1037
|
+
|
930
1038
|
"""
|
931
1039
|
# n = 7
|
932
1040
|
# clist = get_color(n, cmap="auto", by="linspace") # get_color(100)
|
@@ -940,35 +1048,39 @@ def get_color(n=1, cmap="auto", by="start"):
|
|
940
1048
|
# figsets(plt.gca(), {"style": "whitegrid"}) """
|
941
1049
|
|
942
1050
|
|
943
|
-
|
944
1051
|
from scipy.signal import savgol_filter
|
945
|
-
import numpy as np
|
946
|
-
import matplotlib.pyplot as plt
|
1052
|
+
import numpy as np
|
1053
|
+
import matplotlib.pyplot as plt
|
1054
|
+
|
947
1055
|
|
948
|
-
def stdshade(ax=None
|
1056
|
+
def stdshade(ax=None, *args, **kwargs):
|
949
1057
|
# Separate kws_line and kws_fill if necessary
|
950
|
-
kws_line = kwargs.pop(
|
951
|
-
kws_fill = kwargs.pop(
|
1058
|
+
kws_line = kwargs.pop("kws_line", {})
|
1059
|
+
kws_fill = kwargs.pop("kws_fill", {})
|
952
1060
|
|
953
1061
|
# Merge kws_line and kws_fill into kwargs
|
954
1062
|
kwargs.update(kws_line)
|
955
1063
|
kwargs.update(kws_fill)
|
1064
|
+
|
956
1065
|
def str2list(str_):
|
957
1066
|
l = []
|
958
1067
|
[l.append(x) for x in str_]
|
959
1068
|
return l
|
1069
|
+
|
960
1070
|
def hue2rgb(hex_colors):
|
961
1071
|
def hex_to_rgb(hex_color):
|
962
1072
|
"""Converts a hexadecimal color code to RGB values."""
|
963
1073
|
if hex_colors.startswith("#"):
|
964
1074
|
hex_color = hex_color.lstrip("#")
|
965
1075
|
return tuple(int(hex_color[i : i + 2], 16) / 255.0 for i in (0, 2, 4))
|
1076
|
+
|
966
1077
|
if isinstance(hex_colors, str):
|
967
1078
|
return hex_to_rgb(hex_colors)
|
968
1079
|
elif isinstance(hex_colors, (list)):
|
969
1080
|
"""Converts a list of hexadecimal color codes to a list of RGB values."""
|
970
1081
|
rgb_values = [hex_to_rgb(hex_color) for hex_color in hex_colors]
|
971
1082
|
return rgb_values
|
1083
|
+
|
972
1084
|
if (
|
973
1085
|
isinstance(ax, np.ndarray)
|
974
1086
|
and ax.ndim == 2
|
@@ -1024,35 +1136,35 @@ def stdshade(ax=None,*args, **kwargs):
|
|
1024
1136
|
if args[iarg] in ["sem", "std"]:
|
1025
1137
|
paraStdSem = args[iarg]
|
1026
1138
|
if args[iarg].startswith("#"):
|
1027
|
-
acolor=hue2rgb(args[iarg])
|
1139
|
+
acolor = hue2rgb(args[iarg])
|
1028
1140
|
if str2list(args[iarg])[0] in l_c_one:
|
1029
1141
|
if len(args[iarg]) == 3:
|
1030
1142
|
k = [i for i in str2list(args[iarg]) if i in l_c_one]
|
1031
1143
|
if k != []:
|
1032
|
-
acolor = k[0]
|
1144
|
+
acolor = k[0]
|
1033
1145
|
st = [i for i in l_style2 if i in args[iarg]]
|
1034
1146
|
if st != []:
|
1035
|
-
plotStyle = st[0]
|
1147
|
+
plotStyle = st[0]
|
1036
1148
|
elif len(args[iarg]) == 2:
|
1037
1149
|
k = [i for i in str2list(args[iarg]) if i in l_c_one]
|
1038
1150
|
if k != []:
|
1039
|
-
acolor = k[0]
|
1151
|
+
acolor = k[0]
|
1040
1152
|
mk = [i for i in str2list(args[iarg]) if i in l_mark]
|
1041
1153
|
if mk != []:
|
1042
|
-
plotMarker = mk[0]
|
1154
|
+
plotMarker = mk[0]
|
1043
1155
|
st = [i for i in l_style1 if i in args[iarg]]
|
1044
1156
|
if st != []:
|
1045
|
-
plotStyle = st[0]
|
1157
|
+
plotStyle = st[0]
|
1046
1158
|
if len(args[iarg]) == 1:
|
1047
1159
|
k = [i for i in str2list(args[iarg]) if i in l_c_one]
|
1048
1160
|
if k != []:
|
1049
|
-
acolor = k[0]
|
1161
|
+
acolor = k[0]
|
1050
1162
|
mk = [i for i in str2list(args[iarg]) if i in l_mark]
|
1051
1163
|
if mk != []:
|
1052
|
-
plotMarker = mk[0]
|
1164
|
+
plotMarker = mk[0]
|
1053
1165
|
st = [i for i in l_style1 if i in args[iarg]]
|
1054
1166
|
if st != []:
|
1055
|
-
plotStyle = st[0]
|
1167
|
+
plotStyle = st[0]
|
1056
1168
|
if len(args[iarg]) == 2:
|
1057
1169
|
st = [i for i in l_style2 if i in args[iarg]]
|
1058
1170
|
if st != []:
|
@@ -1064,7 +1176,7 @@ def stdshade(ax=None,*args, **kwargs):
|
|
1064
1176
|
and args[iarg] >= 1
|
1065
1177
|
):
|
1066
1178
|
smth = args[iarg]
|
1067
|
-
smth = kwargs.get(
|
1179
|
+
smth = kwargs.get("smth", smth)
|
1068
1180
|
if "x" not in locals() or x is None:
|
1069
1181
|
x = np.arange(1, y.shape[1] + 1)
|
1070
1182
|
elif len(x) < y.shape[1]:
|
@@ -1097,50 +1209,50 @@ def stdshade(ax=None,*args, **kwargs):
|
|
1097
1209
|
# line_kws = kwargs.get('line_kws', {})
|
1098
1210
|
|
1099
1211
|
# setting form kwargs
|
1100
|
-
lw = kwargs.get(
|
1101
|
-
ls= kwargs.get(
|
1102
|
-
marker=kwargs.get("marker",plotMarker)
|
1103
|
-
label=kwargs.get("label",None)
|
1104
|
-
label_line = kwargs.get("label_line",None)
|
1105
|
-
label_fill = kwargs.get(
|
1106
|
-
alpha=kwargs.get(
|
1107
|
-
color=kwargs.get(
|
1212
|
+
lw = kwargs.get("lw", 0.5)
|
1213
|
+
ls = kwargs.get("ls", plotStyle)
|
1214
|
+
marker = kwargs.get("marker", plotMarker)
|
1215
|
+
label = kwargs.get("label", None)
|
1216
|
+
label_line = kwargs.get("label_line", None)
|
1217
|
+
label_fill = kwargs.get("label_fill", None)
|
1218
|
+
alpha = kwargs.get("alpha", alpha)
|
1219
|
+
color = kwargs.get("color", acolor)
|
1108
1220
|
if not label_line and label:
|
1109
1221
|
label_line = label
|
1110
|
-
kwargs[
|
1111
|
-
kwargs[
|
1112
|
-
kwargs[
|
1113
|
-
kwargs[
|
1222
|
+
kwargs["lw"] = lw
|
1223
|
+
kwargs["ls"] = ls
|
1224
|
+
kwargs["label_line"] = label_line
|
1225
|
+
kwargs["label_fill"] = label_fill
|
1114
1226
|
|
1115
1227
|
# set kws_line
|
1116
|
-
if
|
1117
|
-
kws_line[
|
1118
|
-
if
|
1119
|
-
kws_line[
|
1120
|
-
if
|
1121
|
-
kws_line[
|
1122
|
-
if
|
1123
|
-
kws_line[
|
1124
|
-
if
|
1125
|
-
kws_line[
|
1228
|
+
if "color" not in kws_line:
|
1229
|
+
kws_line["color"] = color
|
1230
|
+
if "lw" not in kws_line:
|
1231
|
+
kws_line["lw"] = lw
|
1232
|
+
if "ls" not in kws_line:
|
1233
|
+
kws_line["ls"] = ls
|
1234
|
+
if "marker" not in kws_line:
|
1235
|
+
kws_line["marker"] = marker
|
1236
|
+
if "label" not in kws_line:
|
1237
|
+
kws_line["label"] = label_line
|
1126
1238
|
|
1127
1239
|
# set kws_line
|
1128
|
-
if
|
1129
|
-
kws_fill[
|
1130
|
-
if
|
1131
|
-
kws_fill[
|
1132
|
-
if
|
1133
|
-
kws_fill[
|
1134
|
-
if
|
1135
|
-
kws_fill[
|
1240
|
+
if "color" not in kws_fill:
|
1241
|
+
kws_fill["color"] = color
|
1242
|
+
if "alpha" not in kws_fill:
|
1243
|
+
kws_fill["alpha"] = alpha
|
1244
|
+
if "lw" not in kws_fill:
|
1245
|
+
kws_fill["lw"] = 0
|
1246
|
+
if "label" not in kws_fill:
|
1247
|
+
kws_fill["label"] = label_fill
|
1136
1248
|
|
1137
1249
|
fill = ax.fill_between(x, yMean + wings, yMean - wings, **kws_fill)
|
1138
1250
|
line = ax.plot(x, yMean, **kws_line)
|
1139
1251
|
|
1140
1252
|
# figsets
|
1141
|
-
kw_figsets=kwargs.get(
|
1253
|
+
kw_figsets = kwargs.get("figsets", None)
|
1142
1254
|
if kw_figsets is not None:
|
1143
|
-
figsets(ax=ax
|
1255
|
+
figsets(ax=ax, **kw_figsets)
|
1144
1256
|
|
1145
1257
|
return line[0], fill
|
1146
1258
|
|
@@ -1175,27 +1287,30 @@ plt.legend()
|
|
1175
1287
|
"""
|
1176
1288
|
|
1177
1289
|
|
1178
|
-
def adjust_spines(ax=None, spines=[
|
1290
|
+
def adjust_spines(ax=None, spines=["left", "bottom"], distance=2):
|
1179
1291
|
if ax is None:
|
1180
1292
|
ax = plt.gca()
|
1181
1293
|
for loc, spine in ax.spines.items():
|
1182
1294
|
if loc in spines:
|
1183
|
-
spine.set_position((
|
1295
|
+
spine.set_position(("outward", distance)) # outward by 2 points
|
1184
1296
|
# spine.set_smart_bounds(True)
|
1185
1297
|
else:
|
1186
|
-
spine.set_color(
|
1298
|
+
spine.set_color("none") # don't draw spine
|
1187
1299
|
# turn off ticks where there is no spine
|
1188
|
-
if
|
1189
|
-
ax.yaxis.set_ticks_position(
|
1300
|
+
if "left" in spines:
|
1301
|
+
ax.yaxis.set_ticks_position("left")
|
1190
1302
|
else:
|
1191
1303
|
ax.yaxis.set_ticks([])
|
1192
|
-
if
|
1193
|
-
ax.xaxis.set_ticks_position(
|
1304
|
+
if "bottom" in spines:
|
1305
|
+
ax.xaxis.set_ticks_position("bottom")
|
1194
1306
|
else:
|
1195
1307
|
# no xaxis ticks
|
1196
1308
|
ax.xaxis.set_ticks([])
|
1309
|
+
|
1310
|
+
|
1197
1311
|
# And then plot the data:
|
1198
1312
|
|
1313
|
+
|
1199
1314
|
def add_colorbar(im, width=None, pad=None, **kwargs):
|
1200
1315
|
# usage: add_colorbar(im, width=0.01, pad=0.005, label="PSD (dB)", shrink=0.8)
|
1201
1316
|
l, b, w, h = im.axes.get_position().bounds # get boundaries
|
@@ -1205,6 +1320,7 @@ def add_colorbar(im, width=None, pad=None, **kwargs):
|
|
1205
1320
|
cax = fig.add_axes([l + w + pad, b, width, h]) # define cbar Axes
|
1206
1321
|
return fig.colorbar(im, cax=cax, **kwargs) # draw cbar
|
1207
1322
|
|
1323
|
+
|
1208
1324
|
def padcat(*args, fill_value=np.nan, axis=1):
|
1209
1325
|
"""
|
1210
1326
|
Concatenate vectors with padding.
|
@@ -1226,14 +1342,14 @@ def padcat(*args, fill_value=np.nan, axis=1):
|
|
1226
1342
|
max_len = max(len(lst) for lst in args)
|
1227
1343
|
result = np.full((len(args), max_len), fill_value)
|
1228
1344
|
for i, lst in enumerate(args):
|
1229
|
-
result[i, :len(lst)] = lst
|
1345
|
+
result[i, : len(lst)] = lst
|
1230
1346
|
elif axis == 1:
|
1231
1347
|
# Concatenate along columns
|
1232
1348
|
max_len = max(len(lst) for lst in args)
|
1233
1349
|
result = np.full((max_len, len(args)), fill_value)
|
1234
1350
|
for i, lst in enumerate(args):
|
1235
|
-
result[:len(lst), i] = lst
|
1351
|
+
result[: len(lst), i] = lst
|
1236
1352
|
else:
|
1237
1353
|
raise ValueError("axis must be 0 or 1")
|
1238
|
-
|
1239
|
-
return result
|
1354
|
+
|
1355
|
+
return result
|