py2ls 0.1.9.4__py3-none-any.whl → 0.1.9.6__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
@@ -9,7 +9,8 @@ import matplotlib.ticker as tck
9
9
  from cycler import cycler
10
10
  import logging
11
11
  import os
12
- from .ips import fsave, fload, mkdir
12
+
13
+ from .ips import fsave, fload, mkdir, listdir, figsave
13
14
  from .stats import *
14
15
 
15
16
  # Suppress INFO messages from fontTools
@@ -28,8 +29,25 @@ def catplot(data, *args, **kwargs):
28
29
  """
29
30
 
30
31
  def plot_bars(data, data_m, opt_b, xloc, ax, label=None):
32
+ if "l" in opt_b["loc"]:
33
+ xloc_s = xloc - opt_b["x_dist"]
34
+ elif "r" in opt_b["loc"]:
35
+ xloc_s = xloc + opt_b["x_dist"]
36
+ elif "i" in opt_b["loc"]:
37
+ xloc_s = xloc
38
+ xloc_s[:, 0] += opt_b["x_dist"]
39
+ xloc_s[:, -1] -= opt_b["x_dist"]
40
+ elif "o" in opt_b["loc"]:
41
+ xloc_s = xloc
42
+ xloc_s[:, 0] -= opt_b["x_dist"]
43
+ xloc_s[:, -1] += opt_b["x_dist"]
44
+ elif "c" in opt_b["loc"] or "m" in opt_b["loc"]:
45
+ xloc_s = xloc
46
+ else:
47
+ xloc_s = xloc
48
+
31
49
  bar_positions = get_positions(
32
- xloc, opt_b["loc"], opt_b["x_width"], data.shape[0]
50
+ xloc_s, opt_b["loc"], opt_b["x_width"], data.shape[0]
33
51
  )
34
52
  bar_positions = np.nanmean(bar_positions, axis=0)
35
53
  for i, (x, y) in enumerate(zip(bar_positions, data_m)):
@@ -60,12 +78,22 @@ def catplot(data, *args, **kwargs):
60
78
 
61
79
  def plot_errors(data, data_m, opt_e, xloc, ax, label=None):
62
80
  error_positions = get_positions(
63
- xloc, opt_e["loc"], opt_e["x_width"], data.shape[0]
81
+ xloc, opt_e["loc"], opt_e["x_dist"], data.shape[0]
64
82
  )
65
83
  error_positions = np.nanmean(error_positions, axis=0)
66
84
  errors = np.nanstd(data, axis=0, ddof=1)
67
85
  if opt_e["error"] == "sem":
68
86
  errors /= np.sqrt(np.sum(~np.isnan(data), axis=0))
87
+ if opt_e["LineStyle"] != "none":
88
+ # draw lines
89
+ ax.plot(
90
+ error_positions,
91
+ data_m,
92
+ color=opt_e["LineColor"],
93
+ linestyle=opt_e["LineStyle"],
94
+ linewidth=opt_e["LineWidth"],
95
+ alpha=opt_e["LineAlpha"],
96
+ )
69
97
 
70
98
  if not isinstance(opt_e["FaceColor"], list):
71
99
  opt_e["FaceColor"] = [opt_e["FaceColor"]]
@@ -144,8 +172,25 @@ def catplot(data, *args, **kwargs):
144
172
  )
145
173
 
146
174
  def plot_scatter(data, opt_s, xloc, ax, label=None):
175
+ if "l" in opt_s["loc"]:
176
+ xloc_s = xloc - opt_s["x_dist"]
177
+ elif "r" in opt_s["loc"]:
178
+ xloc_s = xloc + opt_s["x_dist"]
179
+ elif "i" in opt_s["loc"]:
180
+ xloc_s = xloc
181
+ xloc_s[:, 0] += opt_s["x_dist"]
182
+ xloc_s[:, -1] -= opt_s["x_dist"]
183
+ elif "o" in opt_s["loc"]:
184
+ xloc_s = xloc
185
+ xloc_s[:, 0] -= opt_s["x_dist"]
186
+ xloc_s[:, -1] += opt_s["x_dist"]
187
+ elif "c" in opt_s["loc"] or "m" in opt_s["loc"]:
188
+ xloc_s = xloc
189
+ else:
190
+ xloc_s = xloc
191
+
147
192
  scatter_positions = get_positions(
148
- xloc, opt_s["loc"], opt_s["x_width"], data.shape[0]
193
+ xloc_s, opt_s["loc"], opt_s["x_width"], data.shape[0]
149
194
  )
150
195
  for i, (x, y) in enumerate(zip(scatter_positions.T, data.T)):
151
196
  color = to_rgba(opt_s["FaceColor"][i % len(opt_s["FaceColor"])])
@@ -177,17 +222,17 @@ def catplot(data, *args, **kwargs):
177
222
 
178
223
  def plot_boxplot(data, bx_opt, xloc, ax, label=None):
179
224
  if "l" in bx_opt["loc"]:
180
- X_bx = xloc - bx_opt["x_width"]
225
+ X_bx = xloc - bx_opt["x_dist"]
181
226
  elif "r" in bx_opt["loc"]:
182
- X_bx = xloc + bx_opt["x_width"]
227
+ X_bx = xloc + bx_opt["x_dist"]
183
228
  elif "i" in bx_opt["loc"]:
184
229
  X_bx = xloc
185
- X_bx[:, 0] += bx_opt["x_width"]
186
- X_bx[:, -1] -= bx_opt["x_width"]
230
+ X_bx[:, 0] += bx_opt["x_dist"]
231
+ X_bx[:, -1] -= bx_opt["x_dist"]
187
232
  elif "o" in bx_opt["loc"]:
188
233
  X_bx = xloc
189
- X_bx[:, 0] -= bx_opt["x_width"]
190
- X_bx[:, -1] += bx_opt["x_width"]
234
+ X_bx[:, 0] -= bx_opt["x_dist"]
235
+ X_bx[:, -1] += bx_opt["x_dist"]
191
236
  elif "c" in bx_opt["loc"] or "m" in bx_opt["loc"]:
192
237
  X_bx = xloc
193
238
  else:
@@ -196,7 +241,8 @@ def catplot(data, *args, **kwargs):
196
241
  boxprops = dict(color=bx_opt["EdgeColor"], linewidth=bx_opt["BoxLineWidth"])
197
242
  flierprops = dict(
198
243
  marker=bx_opt["OutlierMarker"],
199
- markerfacecolor=bx_opt["OutlierColor"],
244
+ markerfacecolor=bx_opt["OutlierFaceColor"],
245
+ markeredgecolor=bx_opt["OutlierEdgeColor"],
200
246
  markersize=bx_opt["OutlierSize"],
201
247
  )
202
248
  whiskerprops = dict(
@@ -258,20 +304,125 @@ def catplot(data, *args, **kwargs):
258
304
  if bx_opt["MedianLineTop"]:
259
305
  ax.set_children(ax.get_children()[::-1]) # move median line forward
260
306
 
261
- def plot_violin(data, opt_v, xloc, ax, label=None):
307
+ def plot_violin(data, opt_v, xloc, ax, label=None, vertical=True):
262
308
  violin_positions = get_positions(
263
- xloc, opt_v["loc"], opt_v["x_width"], data.shape[0]
309
+ xloc, opt_v["loc"], opt_v["x_dist"], data.shape[0]
264
310
  )
265
311
  violin_positions = np.nanmean(violin_positions, axis=0)
266
312
  for i, (x, ys) in enumerate(zip(violin_positions, data.T)):
267
313
  ys = ys[~np.isnan(ys)]
268
- kde = gaussian_kde(ys, bw_method=opt_v["BandWidth"])
269
- min_val, max_val = ys.min(), ys.max()
270
- y_vals = np.linspace(min_val, max_val, opt_v["NumPoints"])
271
- kde_vals = kde(y_vals)
272
- kde_vals = kde_vals / kde_vals.max() * opt_v["x_width"]
273
- if label is not None and i < len(label):
274
- if len(ys) > 1:
314
+ if np.all(ys == ys[0]): # Check if data is constant
315
+ print(
316
+ "Data is constant; KDE cannot be applied. Plotting a flat line instead."
317
+ )
318
+ if vertical:
319
+ ax.plot(
320
+ [x - opt_v["x_width"] / 2, x + opt_v["x_width"] / 2],
321
+ [ys[0], ys[0]],
322
+ color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
323
+ lw=2,
324
+ label=label[i] if label else None,
325
+ )
326
+ else:
327
+ ax.plot(
328
+ [ys[0], ys[0]],
329
+ [x - opt_v["x_width"] / 2, x + opt_v["x_width"] / 2],
330
+ color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
331
+ lw=2,
332
+ label=label[i] if label else None,
333
+ )
334
+ else:
335
+ kde = gaussian_kde(ys, bw_method=opt_v["BandWidth"])
336
+ min_val, max_val = ys.min(), ys.max()
337
+ y_vals = np.linspace(min_val, max_val, opt_v["NumPoints"])
338
+ kde_vals = kde(y_vals)
339
+ kde_vals = kde_vals / kde_vals.max() * opt_v["x_width"]
340
+ if label is not None and i < len(label):
341
+ if len(ys) > 1:
342
+ if "r" in opt_v["loc"].lower():
343
+ ax.fill_betweenx(
344
+ y_vals,
345
+ x,
346
+ x + kde_vals,
347
+ color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
348
+ alpha=opt_v["FaceAlpha"],
349
+ edgecolor=opt_v["EdgeColor"],
350
+ label=label[i],
351
+ lw=opt_v["LineWidth"],
352
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
353
+ )
354
+ elif (
355
+ "l" in opt_v["loc"].lower()
356
+ and not "f" in opt_v["loc"].lower()
357
+ ):
358
+ ax.fill_betweenx(
359
+ y_vals,
360
+ x - kde_vals,
361
+ x,
362
+ color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
363
+ alpha=opt_v["FaceAlpha"],
364
+ edgecolor=opt_v["EdgeColor"],
365
+ label=label[i],
366
+ lw=opt_v["LineWidth"],
367
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
368
+ )
369
+ elif (
370
+ "o" in opt_v["loc"].lower()
371
+ or "both" in opt_v["loc"].lower()
372
+ ):
373
+ ax.fill_betweenx(
374
+ y_vals,
375
+ x - kde_vals,
376
+ x + kde_vals,
377
+ color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
378
+ alpha=opt_v["FaceAlpha"],
379
+ edgecolor=opt_v["EdgeColor"],
380
+ label=label[i],
381
+ lw=opt_v["LineWidth"],
382
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
383
+ )
384
+ elif "i" in opt_v["loc"].lower():
385
+ if i % 2 == 1: # odd number
386
+ ax.fill_betweenx(
387
+ y_vals,
388
+ x - kde_vals,
389
+ x,
390
+ color=opt_v["FaceColor"][
391
+ i % len(opt_v["FaceColor"])
392
+ ],
393
+ alpha=opt_v["FaceAlpha"],
394
+ edgecolor=opt_v["EdgeColor"],
395
+ label=label[i],
396
+ lw=opt_v["LineWidth"],
397
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
398
+ )
399
+ else:
400
+ ax.fill_betweenx(
401
+ y_vals,
402
+ x,
403
+ x + kde_vals,
404
+ color=opt_v["FaceColor"][
405
+ i % len(opt_v["FaceColor"])
406
+ ],
407
+ alpha=opt_v["FaceAlpha"],
408
+ edgecolor=opt_v["EdgeColor"],
409
+ label=label[i],
410
+ lw=opt_v["LineWidth"],
411
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
412
+ )
413
+ elif "f" in opt_v["loc"].lower():
414
+ ax.fill_betweenx(
415
+ y_vals,
416
+ x - kde_vals,
417
+ x + kde_vals,
418
+ color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
419
+ alpha=opt_v["FaceAlpha"],
420
+ edgecolor=opt_v["EdgeColor"],
421
+ label=label[i],
422
+ lw=opt_v["LineWidth"],
423
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
424
+ )
425
+ else:
275
426
  if "r" in opt_v["loc"].lower():
276
427
  ax.fill_betweenx(
277
428
  y_vals,
@@ -280,7 +431,8 @@ def catplot(data, *args, **kwargs):
280
431
  color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
281
432
  alpha=opt_v["FaceAlpha"],
282
433
  edgecolor=opt_v["EdgeColor"],
283
- label=label[i],
434
+ lw=opt_v["LineWidth"],
435
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
284
436
  )
285
437
  elif (
286
438
  "l" in opt_v["loc"].lower() and not "f" in opt_v["loc"].lower()
@@ -292,7 +444,8 @@ def catplot(data, *args, **kwargs):
292
444
  color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
293
445
  alpha=opt_v["FaceAlpha"],
294
446
  edgecolor=opt_v["EdgeColor"],
295
- label=label[i],
447
+ lw=opt_v["LineWidth"],
448
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
296
449
  )
297
450
  elif "o" in opt_v["loc"].lower() or "both" in opt_v["loc"].lower():
298
451
  ax.fill_betweenx(
@@ -302,7 +455,8 @@ def catplot(data, *args, **kwargs):
302
455
  color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
303
456
  alpha=opt_v["FaceAlpha"],
304
457
  edgecolor=opt_v["EdgeColor"],
305
- label=label[i],
458
+ lw=opt_v["LineWidth"],
459
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
306
460
  )
307
461
  elif "i" in opt_v["loc"].lower():
308
462
  if i % 2 == 1: # odd number
@@ -313,7 +467,8 @@ def catplot(data, *args, **kwargs):
313
467
  color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
314
468
  alpha=opt_v["FaceAlpha"],
315
469
  edgecolor=opt_v["EdgeColor"],
316
- label=label[i],
470
+ lw=opt_v["LineWidth"],
471
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
317
472
  )
318
473
  else:
319
474
  ax.fill_betweenx(
@@ -323,7 +478,8 @@ def catplot(data, *args, **kwargs):
323
478
  color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
324
479
  alpha=opt_v["FaceAlpha"],
325
480
  edgecolor=opt_v["EdgeColor"],
326
- label=label[i],
481
+ lw=opt_v["LineWidth"],
482
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
327
483
  )
328
484
  elif "f" in opt_v["loc"].lower():
329
485
  ax.fill_betweenx(
@@ -333,68 +489,162 @@ def catplot(data, *args, **kwargs):
333
489
  color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
334
490
  alpha=opt_v["FaceAlpha"],
335
491
  edgecolor=opt_v["EdgeColor"],
336
- label=label[i],
492
+ lw=opt_v["LineWidth"],
493
+ hatch=opt_v["hatch"][i % len(opt_v["FaceColor"])],
337
494
  )
338
- else:
339
- if "r" in opt_v["loc"].lower():
340
- ax.fill_betweenx(
341
- y_vals,
342
- x,
343
- x + kde_vals,
344
- color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
345
- alpha=opt_v["FaceAlpha"],
346
- edgecolor=opt_v["EdgeColor"],
347
- )
348
- elif "l" in opt_v["loc"].lower() and not "f" in opt_v["loc"].lower():
349
- ax.fill_betweenx(
350
- y_vals,
351
- x - kde_vals,
352
- x,
353
- color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
354
- alpha=opt_v["FaceAlpha"],
355
- edgecolor=opt_v["EdgeColor"],
356
- )
357
- elif "o" in opt_v["loc"].lower() or "both" in opt_v["loc"].lower():
358
- ax.fill_betweenx(
359
- y_vals,
360
- x - kde_vals,
361
- x + kde_vals,
362
- color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
363
- alpha=opt_v["FaceAlpha"],
364
- edgecolor=opt_v["EdgeColor"],
365
- )
366
- elif "i" in opt_v["loc"].lower():
367
- if i % 2 == 1: # odd number
368
- ax.fill_betweenx(
369
- y_vals,
370
- x - kde_vals,
371
- x,
372
- color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
373
- alpha=opt_v["FaceAlpha"],
374
- edgecolor=opt_v["EdgeColor"],
375
- )
376
- else:
377
- ax.fill_betweenx(
378
- y_vals,
379
- x,
380
- x + kde_vals,
381
- color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
382
- alpha=opt_v["FaceAlpha"],
383
- edgecolor=opt_v["EdgeColor"],
384
- )
385
- elif "f" in opt_v["loc"].lower():
386
- ax.fill_betweenx(
387
- y_vals,
388
- x - kde_vals,
389
- x + kde_vals,
390
- color=opt_v["FaceColor"][i % len(opt_v["FaceColor"])],
391
- alpha=opt_v["FaceAlpha"],
392
- edgecolor=opt_v["EdgeColor"],
393
- )
495
+
496
+ def plot_ridgeplot(data, x, y, opt_r, **kwargs_figsets):
497
+ # in the sns.FacetGrid class, the 'hue' argument is the one that is the one that will be represented by colors with 'palette'
498
+ if opt_r["column4color"] is None:
499
+ column4color = x
500
+ else:
501
+ column4color = opt_r["column4color"]
502
+
503
+ if opt_r["row_labels"] is None:
504
+ opt_r["row_labels"] = data[x].unique().tolist()
505
+
506
+ if isinstance(opt_r["FaceColor"], str):
507
+ opt_r["FaceColor"] = [opt_r["FaceColor"]]
508
+ if len(opt_r["FaceColor"]) == 1:
509
+ opt_r["FaceColor"] = np.tile(
510
+ opt_r["FaceColor"], [1, len(opt_r["row_labels"])]
511
+ )[0]
512
+ if len(opt_r["FaceColor"]) > len(opt_r["row_labels"]):
513
+ opt_r["FaceColor"] = opt_r["FaceColor"][: len(opt_r["row_labels"])]
514
+
515
+ g = sns.FacetGrid(
516
+ data=data,
517
+ row=x,
518
+ hue=column4color,
519
+ aspect=opt_r["aspect"],
520
+ height=opt_r["subplot_height"],
521
+ palette=opt_r["FaceColor"],
522
+ )
523
+
524
+ # kdeplot
525
+ g.map(
526
+ sns.kdeplot,
527
+ y,
528
+ bw_adjust=opt_r["bw_adjust"],
529
+ clip_on=opt_r["clip"],
530
+ fill=opt_r["fill"],
531
+ alpha=opt_r["FaceAlpha"],
532
+ linewidth=opt_r["EdgeLineWidth"],
533
+ )
534
+
535
+ # edge / line of kdeplot
536
+ if opt_r["EdgeColor"] is not None:
537
+ g.map(
538
+ sns.kdeplot,
539
+ y,
540
+ bw_adjust=opt_r["bw_adjust"],
541
+ clip_on=opt_r["clip"],
542
+ color=opt_r["EdgeColor"],
543
+ lw=opt_r["EdgeLineWidth"],
544
+ )
545
+ else:
546
+ g.map(
547
+ sns.kdeplot,
548
+ y,
549
+ bw_adjust=opt_r["bw_adjust"],
550
+ clip_on=opt_r["clip"],
551
+ color=opt_r["EdgeColor"],
552
+ lw=opt_r["EdgeLineWidth"],
553
+ )
554
+
555
+ # add a horizontal line
556
+ if opt_r["xLineColor"] is not None:
557
+ g.map(
558
+ plt.axhline,
559
+ y=0,
560
+ lw=opt_r["xLineWidth"],
561
+ clip_on=opt_r["clip"],
562
+ color=opt_r["xLineColor"],
563
+ )
564
+ else:
565
+ g.map(
566
+ plt.axhline,
567
+ y=0,
568
+ lw=opt_r["xLineWidth"],
569
+ clip_on=opt_r["clip"],
570
+ )
571
+
572
+ if isinstance(opt_r["color_row_label"], str):
573
+ opt_r["color_row_label"] = [opt_r["color_row_label"]]
574
+ if len(opt_r["color_row_label"]) == 1:
575
+ opt_r["color_row_label"] = np.tile(
576
+ opt_r["color_row_label"], [1, len(opt_r["row_labels"])]
577
+ )[0]
578
+
579
+ # loop over the FacetGrid figure axes (g.axes.flat)
580
+ for i, ax in enumerate(g.axes.flat):
581
+ if kwargs_figsets.get("xlim", False):
582
+ ax.set_xlim(kwargs_figsets.get("xlim", False))
583
+ if kwargs_figsets.get("xlim", False):
584
+ ax.set_ylim(kwargs_figsets.get("ylim", False))
585
+ if i == 0:
586
+ row_x = opt_r["row_label_loc_xscale"] * np.abs(
587
+ np.diff(ax.get_xlim())
588
+ ) + np.min(ax.get_xlim())
589
+ row_y = opt_r["row_label_loc_yscale"] * np.abs(
590
+ np.diff(ax.get_ylim())
591
+ ) + np.min(ax.get_ylim())
592
+ ax.set_title(kwargs_figsets.get("title", ""))
593
+ ax.text(
594
+ row_x,
595
+ row_y,
596
+ opt_r["row_labels"][i],
597
+ fontweight=opt_r["fontweight"],
598
+ fontsize=opt_r["fontsize"],
599
+ color=opt_r["color_row_label"][i],
600
+ )
601
+ figsets(**kwargs_figsets)
602
+
603
+ # we use matplotlib.Figure.subplots_adjust() function to get the subplots to overlap
604
+ g.fig.subplots_adjust(hspace=opt_r["subplot_hspace"])
605
+
606
+ # eventually we remove axes titles, yticks and spines
607
+ g.set_titles("")
608
+ g.set(yticks=[])
609
+ g.set(ylabel=opt_r["subplot_ylabel"])
610
+ # if kwargs_figsets:
611
+ # g.set(**kwargs_figsets)
612
+ if kwargs_figsets.get("xlim", False):
613
+ g.set(xlim=kwargs_figsets.get("xlim", False))
614
+ g.despine(bottom=True, left=True)
615
+
616
+ plt.setp(
617
+ ax.get_xticklabels(),
618
+ fontsize=opt_r["fontsize"],
619
+ fontweight=opt_r["fontweight"],
620
+ )
621
+ # if opt_r["ylabel"] is None:
622
+ # opt_r["ylabel"] = y
623
+ # plt.xlabel(
624
+ # opt_r["ylabel"], fontweight=opt_r["fontweight"], fontsize=opt_r["fontsize"]
625
+ # )
626
+ return g, opt_r
394
627
 
395
628
  def plot_lines(data, opt_l, opt_s, ax):
629
+ if "l" in opt_s["loc"]:
630
+ xloc_s = xloc - opt_s["x_dist"]
631
+ elif "r" in opt_s["loc"]:
632
+ xloc_s = xloc + opt_s["x_dist"]
633
+ elif "i" in opt_s["loc"]:
634
+ xloc_s = xloc
635
+ xloc_s[:, 0] += opt_s["x_dist"]
636
+ xloc_s[:, -1] -= opt_s["x_dist"]
637
+ elif "o" in opt_s["loc"]:
638
+ xloc_s = xloc
639
+ xloc_s[:, 0] -= opt_s["x_dist"]
640
+ xloc_s[:, -1] += opt_s["x_dist"]
641
+ elif "c" in opt_s["loc"] or "m" in opt_s["loc"]:
642
+ xloc_s = xloc
643
+ else:
644
+ xloc_s = xloc
645
+
396
646
  scatter_positions = get_positions(
397
- xloc, opt_s["loc"], opt_s["x_width"], data.shape[0]
647
+ xloc_s, opt_s["loc"], opt_s["x_width"], data.shape[0]
398
648
  )
399
649
  for incol in range(data.shape[1] - 1):
400
650
  for irow in range(data.shape[0]):
@@ -448,6 +698,8 @@ def catplot(data, *args, **kwargs):
448
698
  """
449
699
  sort layers
450
700
  """
701
+ if "r" in full_order:
702
+ return ["r"]
451
703
  # Ensure custom_order is a list of strings
452
704
  custom_order = [str(layer) for layer in custom_order]
453
705
  j = 1
@@ -469,10 +721,9 @@ def catplot(data, *args, **kwargs):
469
721
 
470
722
  ax = kwargs.get("ax", None)
471
723
  col = kwargs.get("col", None)
724
+ report = kwargs.get("report", True)
725
+ vertical = kwargs.get("vertical", True)
472
726
  if not col:
473
- if "ax" not in locals() or ax is None:
474
- ax = plt.gca()
475
-
476
727
  kw_figsets = kwargs.get("figsets", None)
477
728
  # check the data type
478
729
  if isinstance(data, pd.DataFrame):
@@ -608,15 +859,20 @@ def catplot(data, *args, **kwargs):
608
859
  if "style" in k and "exp" not in k:
609
860
  style_use = v
610
861
  break
611
- if style_use:
862
+ if style_use is not None:
612
863
  try:
613
864
  dir_curr_script = os.path.dirname(os.path.abspath(__file__))
614
865
  dir_style = dir_curr_script + "/data/styles/"
615
- style_load = fload(dir_style + style_use + ".json")
866
+ if isinstance(style_use, str):
867
+ style_load = fload(dir_style + style_use + ".json")
868
+ else:
869
+ style_load = fload(
870
+ listdir(dir_style, "json").path.tolist()[style_use]
871
+ )
616
872
  style_load = remove_colors_in_dict(style_load)
617
873
  opt.update(style_load)
618
874
  except:
619
- print(f"cannot find the style'{style_name}'")
875
+ print(f"cannot find the style'{style_use}'")
620
876
 
621
877
  color_custom = kwargs.get("c", default_colors)
622
878
  if not isinstance(color_custom, list):
@@ -631,7 +887,6 @@ def catplot(data, *args, **kwargs):
631
887
 
632
888
  # export setting
633
889
  opt.setdefault("style", {})
634
- opt["style"].setdefault("export", None)
635
890
  opt.setdefault("layer", ["b", "bx", "e", "v", "s", "l"])
636
891
 
637
892
  opt.setdefault("b", {})
@@ -644,18 +899,20 @@ def catplot(data, *args, **kwargs):
644
899
  opt["b"].setdefault("LineStyle", "-")
645
900
  opt["b"].setdefault("LineWidth", 0.8)
646
901
  opt["b"].setdefault("x_width", default_x_width)
902
+ opt["b"].setdefault("x_dist", opt["b"]["x_width"])
647
903
  opt["b"].setdefault("ShowBaseLine", "off")
648
904
  opt["b"].setdefault("hatch", None)
649
905
 
650
906
  opt.setdefault("e", {})
651
907
  opt["e"].setdefault("go", 1)
652
908
  opt["e"].setdefault("loc", "l")
653
- opt["e"].setdefault("LineWidth", 1)
909
+ opt["e"].setdefault("LineWidth", 2)
654
910
  opt["e"].setdefault("CapLineWidth", 1)
655
911
  opt["e"].setdefault("CapSize", 2)
656
912
  opt["e"].setdefault("Marker", "none")
657
913
  opt["e"].setdefault("LineStyle", "none")
658
914
  opt["e"].setdefault("LineColor", "k")
915
+ opt["e"].setdefault("LineAlpha", 0.5)
659
916
  opt["e"].setdefault("LineJoin", "round")
660
917
  opt["e"].setdefault("MarkerSize", "auto")
661
918
  opt["e"].setdefault("FaceColor", color_custom)
@@ -664,22 +921,24 @@ def catplot(data, *args, **kwargs):
664
921
  opt["e"].setdefault("Orientation", "vertical")
665
922
  opt["e"].setdefault("error", "sem")
666
923
  opt["e"].setdefault("x_width", default_x_width / 5)
924
+ opt["e"].setdefault("x_dist", opt["e"]["x_width"])
667
925
  opt["e"].setdefault("cap_dir", "b")
668
926
 
669
927
  opt.setdefault("s", {})
670
928
  opt["s"].setdefault("go", 1)
671
929
  opt["s"].setdefault("loc", "r")
672
- opt["s"].setdefault("FaceColor", "w")
930
+ opt["s"].setdefault("FaceColor", color_custom)
673
931
  opt["s"].setdefault("cmap", None)
674
932
  opt["s"].setdefault("FaceAlpha", 1)
675
- opt["s"].setdefault("x_width", default_x_width / 5)
933
+ opt["s"].setdefault("x_width", default_x_width / 5 * 0.5)
934
+ opt["s"].setdefault("x_dist", opt["s"]["x_width"])
676
935
  opt["s"].setdefault("Marker", "o")
677
936
  opt["s"].setdefault("MarkerSize", 15)
678
937
  opt["s"].setdefault("LineWidth", 0.8)
679
938
  opt["s"].setdefault("MarkerEdgeColor", "k")
680
939
 
681
940
  opt.setdefault("l", {})
682
- opt["l"].setdefault("go", 1)
941
+ opt["l"].setdefault("go", 0)
683
942
  opt["l"].setdefault("LineStyle", "-")
684
943
  opt["l"].setdefault("LineColor", "k")
685
944
  opt["l"].setdefault("LineWidth", 0.5)
@@ -694,11 +953,13 @@ def catplot(data, *args, **kwargs):
694
953
  opt["bx"].setdefault("EdgeAlpha", 1)
695
954
  opt["bx"].setdefault("LineStyle", "-")
696
955
  opt["bx"].setdefault("x_width", default_x_width / 5)
956
+ opt["bx"].setdefault("x_dist", opt["bx"]["x_width"])
697
957
  opt["bx"].setdefault("ShowBaseLine", "off")
698
958
  opt["bx"].setdefault("Notch", False)
699
959
  opt["bx"].setdefault("Outliers", "on")
700
960
  opt["bx"].setdefault("OutlierMarker", "+")
701
- opt["bx"].setdefault("OutlierColor", "r")
961
+ opt["bx"].setdefault("OutlierFaceColor", "r")
962
+ opt["bx"].setdefault("OutlierEdgeColor", "k")
702
963
  opt["bx"].setdefault("OutlierSize", 6)
703
964
  # opt['bx'].setdefault('PlotStyle', 'traditional')
704
965
  # opt['bx'].setdefault('FactorDirection', 'auto')
@@ -730,16 +991,44 @@ def catplot(data, *args, **kwargs):
730
991
  opt.setdefault("v", {})
731
992
  opt["v"].setdefault("go", 0)
732
993
  opt["v"].setdefault("x_width", 0.3)
994
+ opt["v"].setdefault("x_dist", opt["v"]["x_width"])
733
995
  opt["v"].setdefault("loc", "r")
734
996
  opt["v"].setdefault("EdgeColor", "none")
997
+ opt["v"].setdefault("LineWidth", 0.5)
735
998
  opt["v"].setdefault("FaceColor", color_custom)
736
- opt["v"].setdefault("FaceAlpha", 0.3)
999
+ opt["v"].setdefault("FaceAlpha", 1)
737
1000
  opt["v"].setdefault("BandWidth", "scott")
738
1001
  opt["v"].setdefault("Function", "pdf")
739
1002
  opt["v"].setdefault("Kernel", "gau")
1003
+ opt["v"].setdefault("hatch", None)
740
1004
  opt["v"].setdefault("NumPoints", 500)
741
1005
  opt["v"].setdefault("BoundaryCorrection", "reflection")
742
1006
 
1007
+ # ridgeplot
1008
+ opt.setdefault("r", {})
1009
+ opt["r"].setdefault("go", 0)
1010
+ opt["r"].setdefault("bw_adjust", 1)
1011
+ opt["r"].setdefault("clip", False)
1012
+ opt["r"].setdefault("FaceColor", get_color(20))
1013
+ opt["r"].setdefault("FaceAlpha", 1)
1014
+ opt["r"].setdefault("EdgeLineWidth", 1.5)
1015
+ opt["r"].setdefault("fill", True)
1016
+ opt["r"].setdefault("EdgeColor", "none")
1017
+ opt["r"].setdefault("xLineWidth", opt["r"]["EdgeLineWidth"] + 0.5)
1018
+ opt["r"].setdefault("xLineColor", "none")
1019
+ opt["r"].setdefault("aspect", 8)
1020
+ opt["r"].setdefault("subplot_hspace", -0.3) # overlap subplots
1021
+ opt["r"].setdefault("subplot_height", 0.75)
1022
+ opt["r"].setdefault("subplot_ylabel", "")
1023
+ opt["r"].setdefault("column4color", None)
1024
+ opt["r"].setdefault("row_labels", None)
1025
+ opt["r"].setdefault("row_label_loc_xscale", 0.01)
1026
+ opt["r"].setdefault("row_label_loc_yscale", 0.05)
1027
+ opt["r"].setdefault("fontweight", plt.rcParams["font.weight"])
1028
+ opt["r"].setdefault("fontsize", plt.rcParams["font.size"])
1029
+ opt["r"].setdefault("color_row_label", "k")
1030
+ opt["r"].setdefault("ylabel", None)
1031
+
743
1032
  data_m = np.nanmean(data, axis=0)
744
1033
  nr, nc = data.shape
745
1034
 
@@ -753,8 +1042,13 @@ def catplot(data, *args, **kwargs):
753
1042
  xloc = np.array(opt["loc"]["xloc"])
754
1043
  else:
755
1044
  xloc = opt["loc"]["xloc"]
756
- layers = sort_catplot_layers(opt["layer"])
1045
+ if opt["r"]["go"]:
1046
+ layers = sort_catplot_layers(opt["layer"], "r")
1047
+ else:
1048
+ layers = sort_catplot_layers(opt["layer"])
757
1049
 
1050
+ if ("ax" not in locals() or ax is None) and not opt["r"]["go"]:
1051
+ ax = plt.gca()
758
1052
  label = kwargs.get("label", "bar")
759
1053
  if label:
760
1054
  if "b" in label:
@@ -792,23 +1086,37 @@ def catplot(data, *args, **kwargs):
792
1086
  plot_boxplot(data, opt["bx"], xloc, ax, label=None)
793
1087
  elif layer == "v" and opt["v"]["go"]:
794
1088
  if legend_which == "v":
795
- plot_violin(data, opt["v"], xloc, ax, label=legend_hue)
1089
+ plot_violin(
1090
+ data, opt["v"], xloc, ax, label=legend_hue, vertical=vertical
1091
+ )
796
1092
  else:
797
- plot_violin(data, opt["v"], xloc, ax, label=None)
1093
+ plot_violin(data, opt["v"], xloc, ax, vertical=vertical, label=None)
1094
+ elif layer == "r" and opt["r"]["go"]:
1095
+ kwargs_figsets = kwargs.get("figsets", None)
1096
+ if x and y:
1097
+ if kwargs_figsets:
1098
+ plot_ridgeplot(df, x, y, opt["r"], **kwargs_figsets)
1099
+ else:
1100
+ plot_ridgeplot(df, x, y, opt["r"])
798
1101
  elif all([layer == "l", opt["l"]["go"], opt["s"]["go"]]):
799
1102
  plot_lines(data, opt["l"], opt["s"], ax)
800
1103
 
801
- if kw_figsets is not None:
1104
+ if kw_figsets is not None and not opt["r"]["go"]:
802
1105
  figsets(ax=ax, **kw_figsets)
803
1106
  show_legend = kwargs.get("show_legend", True)
804
- if show_legend:
1107
+ if show_legend and not opt["r"]["go"]:
805
1108
  ax.legend()
806
1109
  # ! add asterisks in the plot
807
1110
  if stats_param:
808
1111
  if len(xticklabels) >= 1:
809
1112
  if hue is None:
810
1113
  add_asterisks(
811
- ax, res, xticks_x_loc, xticklabels, y_loc=np.max(data)
1114
+ ax,
1115
+ res,
1116
+ xticks_x_loc,
1117
+ xticklabels,
1118
+ y_loc=np.max(data),
1119
+ report_go=report,
812
1120
  )
813
1121
  else: # hue is not None
814
1122
  ihue = 1
@@ -840,6 +1148,7 @@ def catplot(data, *args, **kwargs):
840
1148
  xticks[xloc_curr : xloc_curr + hue_len],
841
1149
  legend_hue,
842
1150
  y_loc=np.max(data),
1151
+ report_go=report,
843
1152
  )
844
1153
  ihue += 1
845
1154
  else: # 240814: still has some bugs
@@ -850,7 +1159,12 @@ def catplot(data, *args, **kwargs):
850
1159
  tab_res[f"{xticklabels[0]}(mean±sem)"] = [str_mean_sem(x1)]
851
1160
  tab_res[f"{xticklabels[1]}(mean±sem)"] = [str_mean_sem(x2)]
852
1161
  add_asterisks(
853
- ax, res[1], xticks_x_loc, xticklabels, y_loc=np.max([x1, x2])
1162
+ ax,
1163
+ res[1],
1164
+ xticks_x_loc,
1165
+ xticklabels,
1166
+ y_loc=np.max([x1, x2]),
1167
+ report_go=report,
854
1168
  )
855
1169
  elif isinstance(res, pd.DataFrame):
856
1170
  display(res)
@@ -858,7 +1172,12 @@ def catplot(data, *args, **kwargs):
858
1172
  x1 = df.loc[df[x] == xticklabels[0], y].tolist()
859
1173
  x2 = df.loc[df[x] == xticklabels[1], y].tolist()
860
1174
  add_asterisks(
861
- ax, res, xticks_x_loc, xticklabels, y_loc=np.max([x1, x2])
1175
+ ax,
1176
+ res,
1177
+ xticks_x_loc,
1178
+ xticklabels,
1179
+ y_loc=np.max([x1, x2]),
1180
+ report_go=report,
862
1181
  )
863
1182
 
864
1183
  style_export = kwargs.get("style_export", None)
@@ -1294,6 +1613,8 @@ def get_color(
1294
1613
  by: str = "start",
1295
1614
  alpha: float = 1.0,
1296
1615
  output: str = "hue",
1616
+ *args,
1617
+ **kwargs,
1297
1618
  ):
1298
1619
  def cmap2hex(cmap_name):
1299
1620
  cmap_ = matplotlib.pyplot.get_cmap(cmap_name)
@@ -1343,6 +1664,8 @@ def get_color(
1343
1664
  else:
1344
1665
  return "#{:02X}{:02X}{:02X}".format(r, g, b)
1345
1666
 
1667
+ if cmap == "gray":
1668
+ cmap = "grey"
1346
1669
  # Determine color list based on cmap parameter
1347
1670
  if "aut" in cmap:
1348
1671
  colorlist = [
@@ -1354,7 +1677,38 @@ def get_color(
1354
1677
  "#FF9500",
1355
1678
  "#D57DBE",
1356
1679
  ]
1680
+ by = "start"
1681
+ elif any(["cub" in cmap.lower(), "sns" in cmap.lower()]):
1682
+ if kwargs:
1683
+ colorlist = sns.cubehelix_palette(n, **kwargs)
1684
+ else:
1685
+ colorlist = sns.cubehelix_palette(
1686
+ n, start=0.5, rot=-0.75, light=0.85, dark=0.15, as_cmap=False
1687
+ )
1688
+ colorlist = [matplotlib.colors.rgb2hex(color) for color in colorlist]
1689
+ elif any(["hls" in cmap.lower(), "hsl" in cmap.lower()]):
1690
+ if kwargs:
1691
+ colorlist = sns.hls_palette(n, **kwargs)
1692
+ else:
1693
+ colorlist = sns.hls_palette(n)
1694
+ colorlist = [matplotlib.colors.rgb2hex(color) for color in colorlist]
1695
+ elif any(["col" in cmap.lower(), "pal" in cmap.lower()]):
1696
+ palette, desat, as_cmap = None, None, False
1697
+ if kwargs:
1698
+ for k, v in kwargs.items():
1699
+ if "p" in k:
1700
+ palette = v
1701
+ elif "d" in k:
1702
+ desat = v
1703
+ elif "a" in k:
1704
+ as_cmap = v
1705
+ colorlist = sns.color_palette(
1706
+ palette=palette, n_colors=n, desat=desat, as_cmap=as_cmap
1707
+ )
1708
+ colorlist = [matplotlib.colors.rgb2hex(color) for color in colorlist]
1357
1709
  else:
1710
+ if by == "start":
1711
+ by = "linspace"
1358
1712
  colorlist = cmap2hex(cmap)
1359
1713
 
1360
1714
  # Determine method for generating color list
@@ -1721,6 +2075,7 @@ def add_asterisks(ax, res, xticks_x_loc, xticklabels, **kwargs_funcstars):
1721
2075
  pval_groups = res["res_tab"]["p-unc"].tolist()[0]
1722
2076
  else:
1723
2077
  pval_groups = res["res_tab"]["PR(>F)"].tolist()[0]
2078
+ report_go = kwargs_funcstars.get("report_go", False)
1724
2079
  if pval_groups <= 0.05:
1725
2080
  A_list = res["res_posthoc"]["A"].tolist()
1726
2081
  B_list = res["res_posthoc"]["B"].tolist()
@@ -1743,6 +2098,32 @@ def add_asterisks(ax, res, xticks_x_loc, xticklabels, **kwargs_funcstars):
1743
2098
  )
1744
2099
  if P <= 0.05:
1745
2100
  yscal_ -= 0.075
2101
+ if report_go:
2102
+ try:
2103
+ if isinstance(res["APA"], list):
2104
+ APA_str = res["APA"][0]
2105
+ else:
2106
+ APA_str = res["APA"]
2107
+ except:
2108
+ pass
2109
+
2110
+ FuncStars(
2111
+ ax=ax,
2112
+ x1=(
2113
+ xticks_x_loc[0] - (xticks_x_loc[-1] - xticks_x_loc[0]) / 3
2114
+ if xticks_x_loc[0] > 1
2115
+ else xticks_x_loc[0]
2116
+ ),
2117
+ x2=(
2118
+ xticks_x_loc[0] - (xticks_x_loc[-1] - xticks_x_loc[0]) / 3
2119
+ if xticks_x_loc[0] > 1
2120
+ else xticks_x_loc[0]
2121
+ ),
2122
+ pval=None,
2123
+ report_scale=np.random.uniform(0.7, 0.99),
2124
+ report=APA_str,
2125
+ fontsize_note=8,
2126
+ )
1746
2127
  else:
1747
2128
  if isinstance(res, tuple):
1748
2129
  res = res[1]
@@ -1763,3 +2144,38 @@ def add_asterisks(ax, res, xticks_x_loc, xticklabels, **kwargs_funcstars):
1763
2144
  pval=pval_groups,
1764
2145
  **kwargs_funcstars,
1765
2146
  )
2147
+
2148
+
2149
+ def style_examples(
2150
+ dir_save="/Users/macjianfeng/Dropbox/github/python/py2ls/.venv/lib/python3.12/site-packages/py2ls/data/styles/example",
2151
+ ):
2152
+ f = listdir(
2153
+ "/Users/macjianfeng/Dropbox/github/python/py2ls/.venv/lib/python3.12/site-packages/py2ls/data/styles/",
2154
+ kind=".json",
2155
+ )
2156
+ display(f.sample(2))
2157
+ # def style_example(dir_save,)
2158
+ # Sample data creation
2159
+ np.random.seed(42)
2160
+ categories = ["A", "B", "C", "D", "E"]
2161
+ data = pd.DataFrame(
2162
+ {
2163
+ "value": np.concatenate(
2164
+ [np.random.normal(loc, 0.4, 100) for loc in range(5)]
2165
+ ),
2166
+ "category": np.repeat(categories, 100),
2167
+ }
2168
+ )
2169
+ for i in range(f.num[0]):
2170
+ plt.figure()
2171
+ _, _ = catplot(
2172
+ data=data,
2173
+ x="category",
2174
+ y="value",
2175
+ style=i,
2176
+ figsets=dict(title=f"style{i+1} or style idx={i}"),
2177
+ )
2178
+ figsave(
2179
+ dir_save,
2180
+ f"{f.name[i]}.pdf",
2181
+ )