1"""
2=========================
3Violin plot customization
4=========================
5
6This example demonstrates how to fully customize violin plots.
7The first plot shows the default style by providing only
8the data. The second plot first limits what matplotlib draws
9with additional kwargs. Then a simplified representation of
10a box plot is drawn on top. Lastly, the styles of the artists
11of the violins are modified.
12
13For more information on violin plots, the scikit-learn docs have a great
14section: https://scikit-learn.org/stable/modules/density.html
15"""
16
17import matplotlib.pyplot as plt
18import numpy as np
19
20
21def adjacent_values(vals, q1, q3):
22    upper_adjacent_value = q3 + (q3 - q1) * 1.5
23    upper_adjacent_value = np.clip(upper_adjacent_value, q3, vals[-1])
24
25    lower_adjacent_value = q1 - (q3 - q1) * 1.5
26    lower_adjacent_value = np.clip(lower_adjacent_value, vals[0], q1)
27    return lower_adjacent_value, upper_adjacent_value
28
29
30def set_axis_style(ax, labels):
31    ax.xaxis.set_tick_params(direction='out')
32    ax.xaxis.set_ticks_position('bottom')
33    ax.set_xticks(np.arange(1, len(labels) + 1))
34    ax.set_xticklabels(labels)
35    ax.set_xlim(0.25, len(labels) + 0.75)
36    ax.set_xlabel('Sample name')
37
38
39# create test data
40np.random.seed(19680801)
41data = [sorted(np.random.normal(0, std, 100)) for std in range(1, 5)]
42
43fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(9, 4), sharey=True)
44
45ax1.set_title('Default violin plot')
46ax1.set_ylabel('Observed values')
47ax1.violinplot(data)
48
49ax2.set_title('Customized violin plot')
50parts = ax2.violinplot(
51        data, showmeans=False, showmedians=False,
52        showextrema=False)
53
54for pc in parts['bodies']:
55    pc.set_facecolor('#D43F3A')
56    pc.set_edgecolor('black')
57    pc.set_alpha(1)
58
59quartile1, medians, quartile3 = np.percentile(data, [25, 50, 75], axis=1)
60whiskers = np.array([
61    adjacent_values(sorted_array, q1, q3)
62    for sorted_array, q1, q3 in zip(data, quartile1, quartile3)])
63whiskers_min, whiskers_max = whiskers[:, 0], whiskers[:, 1]
64
65inds = np.arange(1, len(medians) + 1)
66ax2.scatter(inds, medians, marker='o', color='white', s=30, zorder=3)
67ax2.vlines(inds, quartile1, quartile3, color='k', linestyle='-', lw=5)
68ax2.vlines(inds, whiskers_min, whiskers_max, color='k', linestyle='-', lw=1)
69
70# set style for the axes
71labels = ['A', 'B', 'C', 'D']
72for ax in [ax1, ax2]:
73    set_axis_style(ax, labels)
74
75plt.subplots_adjust(bottom=0.15, wspace=0.05)
76plt.show()
77
78#############################################################################
79#
80# .. admonition:: References
81#
82#    The use of the following functions, methods, classes and modules is shown
83#    in this example:
84#
85#    - `matplotlib.axes.Axes.violinplot` / `matplotlib.pyplot.violinplot`
86#    - `matplotlib.axes.Axes.vlines` / `matplotlib.pyplot.vlines`
87