├── .gitignore
├── LICENSE
├── README.md
├── Tutorial1-Fig-Ax.py
├── Tutorial2_lineplot_color_legend.py
├── examples
├── cmap.ipynb
├── extend_ax.ipynb
├── gridspec.ipynb
├── legend.ipynb
├── markersize.ipynb
├── stacked_legends.ipynb
└── yaxis_tick_on_right.ipynb
├── plotly
├── index.html
├── network.html
└── plotly.py
├── rcParams.txt
├── sankey
├── Sankey_tutorial.py
├── sankey_tutorial.pptx
└── sankey_tutorial_bezier.ai
├── tutorial3_boxplot_etc.py
├── tutorial5_seaborn.py
└── tutorial_4_violin_dendrogram.py
/.gitignore:
--------------------------------------------------------------------------------
1 | <<<<<<< HEAD
2 |
3 | =======
4 | **/.DS_Store
5 | .ipynb_checkpoints/**
6 | >>>>>>> 7164dfc56abe05217dab383c27613f404711b903
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Guangyuan(Frank) Li
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # python_visualization_tutorial
2 | A comprehensive guide of how to make publication-ready figures in python
3 |
4 | I am planning to share how to make publication-quality figures in python, I will publish all the tutorial in TowardDatascience Medium platform. In the meantime, I will share some sporadic tricks as separate jupyter nodebook at the bottom of the page.
5 |
6 | ## Phase I: Static Figure (basic matplotlib and seaborn)
7 | 1. [Tutorial I (Understanding Fig and Ax object)](https://towardsdatascience.com/making-publication-quality-figures-in-python-part-i-fig-and-axes-d86c3903ad9b)
8 | 2. [Turorial II (Line plot, colors and legends)](https://frankligy.medium.com/making-publication-quality-figures-in-python-part-ii-line-plot-legends-colors-4430a5891706)
9 | 3. [Tutorial III (boxplot, scatter plot, heatmap, colormap, barplot, histogram)](https://frankligy.medium.com/making-publication-quality-figures-in-python-part-iii-box-plot-bar-plot-scatter-plot-407fa457449)
10 | 4. [Tutorial IV (Violin plot, dendrogram)](https://towardsdatascience.com/making-publication-quality-figures-in-python-part-iv-violin-plot-and-dendrogram-ed0bb8b23ddd)
11 | 5. [Tutorial V (Seaborn)](https://frankligy.medium.com/all-you-need-to-know-about-seaborn-6678a02f31ff)
12 |
13 | ## Phase II: Advanced tutorials
14 | 1. [Plotly, interactive network](https://frankligy.medium.com/plotly-meets-scientific-visualization-8c2074f032cb)
15 | 2. [Sankey plot strategies (Matplotlib Path and Patch)](https://frankligy.medium.com/the-essence-of-drawing-sankey-plot-491fb2cb234)
16 |
17 |
18 | ## Do you want to know some tricks?
19 | 1. [gridspec](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/gridspec.ipynb)
20 | 2. [how to move yaxis ticks to the right spines](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/yaxis_tick_on_right.ipynb)
21 | 3. [how to extract certain number of colors?](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/cmap.ipynb)
22 | 4. [legend,flexibly adjust it](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/legend.ipynb)
23 | 5. [transformation, bbox](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/extend_ax.ipynb)
24 | 6. [stacked legend](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/stacked_legends.ipynb)
25 | 7. [Markersize](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/markersize.ipynb)
26 | 8. stay tuned
27 |
--------------------------------------------------------------------------------
/Tutorial1-Fig-Ax.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | import matplotlib.pyplot as plt
3 | from matplotlib.ticker import MultipleLocator,FormatStrFormatter,MaxNLocator
4 |
5 | a = pd.Series(list(mpl.rcParams.keys()))
6 |
7 |
8 | mpl.rcParams['pdf.fonttype'] = 42
9 | mpl.rcParams['ps.fonttype'] = 42
10 | mpl.rcParams['font.family'] = 'Arial'
11 |
12 | fig = plt.figure()
13 | mpl.rcParams['figure.figsize'] # [6.4,4.8] 6.4 is the width, 4.8 is the height
14 | fig = plt.figure(figsize=(10,6))
15 | ax = plt.axes((0.1,0.1,0.5,0.8))
16 | ax.spines['right'].set_visible(False)
17 | ax.spines['left'].set_visible(False)
18 | ax.spines['bottom'].set_visible(False)
19 | ax.spines['top'].set_visible(False)
20 | ax.tick_params(axis='x',which='major',direction='out',length=10,width=5,color='red',pad=15,labelsize=15,labelcolor='green',
21 | labelrotation=15)
22 | ax.set_xticks([0.2,1])
23 | ax.set_xticklabels(['pos1','pos2'])
24 |
25 | ax.yaxis.set_major_locator(MultipleLocator(0.5))
26 | ax.yaxis.set_minor_locator(MultipleLocator(0.1))
27 |
28 | a=ax.yaxis.get_major_locator()
29 | b=ax.yaxis.get_major_formatter()
30 |
31 | ax.grid(True,which='major',axis='both',alpha=0.3)
32 |
33 | c = ax.get_xticks()
34 | d = ax.get_xticklabels()
35 |
36 | fig,axes = plt.subplots(nrows=4,ncols=4,figsize=(10,6))
37 | fig,axes = plt.subplots(nrows=4,ncols=4,figsize=(10,6),gridspec_kw={'wspace':0.5,'hspace':0.5})
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Tutorial2_lineplot_color_legend.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | import matplotlib.pyplot as plt
3 | from matplotlib.ticker import MultipleLocator,FormatStrFormatter,MaxNLocator
4 | import numpy as np
5 | import pandas as pd
6 |
7 | mpl.rcParams['pdf.fonttype'] = 42
8 | mpl.rcParams['ps.fonttype'] = 42
9 | mpl.rcParams['font.family'] = 'Arial'
10 |
11 | np.random.seed(42)
12 |
13 |
14 | x = np.arange(1,11,1)
15 | y1 = np.linspace(300,400,10)
16 | y2 = np.random.randint(low=300,high=400,size=10)
17 |
18 | mpl.rcParams['lines.marker'] #None
19 | mpl.rcParams['lines.markersize'] #6.0
20 | mpl.rcParams['lines.linewidth'] # 1.5
21 | mpl.rcParams['axes.prop_cycle']
22 |
23 | mpl.colors.to_rgb('#1f77b4')
24 |
25 | fig = plt.figure(figsize=(10,6))
26 | ax = fig.add_axes([0.1,0.1,0.5,0.8])
27 | p1 = ax.plot(x,y1,marker='o',markersize=8,markerfacecolor='red',markeredgecolor='black',markeredgewidth=2,
28 | linestyle='--',linewidth=3,zorder=3)
29 | p2 = ax.plot(x,y2,marker='o')
30 | ax.legend(handles=[p1[0],p2[0]],labels=['blue line','orange line'],loc='upper left',bbox_to_anchor=(1,1),
31 | title='legend',frameon=False)
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/examples/cmap.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 4,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "%matplotlib inline\n",
10 | "import matplotlib\n",
11 | "from matplotlib import cm\n",
12 | "import matplotlib.pyplot as plt\n",
13 | "import numpy as np\n",
14 | "from matplotlib import colors"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 10,
20 | "metadata": {},
21 | "outputs": [],
22 | "source": [
23 | "# get discrete value from built in colormap\n",
24 | "# Method1: < 10 colors, go to this approach\n",
25 | "a = matplotlib.rcParams['axes.prop_cycle']"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": 17,
31 | "metadata": {},
32 | "outputs": [
33 | {
34 | "data": {
35 | "text/html": [
36 | "
'color' | '#1f77b4' |
'#ff7f0e' |
'#2ca02c' |
'#d62728' |
'#9467bd' |
'#8c564b' |
'#e377c2' |
'#7f7f7f' |
'#bcbd22' |
'#17becf' |
"
37 | ],
38 | "text/plain": [
39 | "cycler('color', ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'])"
40 | ]
41 | },
42 | "execution_count": 17,
43 | "metadata": {},
44 | "output_type": "execute_result"
45 | }
46 | ],
47 | "source": [
48 | "a"
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": 16,
54 | "metadata": {},
55 | "outputs": [
56 | {
57 | "data": {
58 | "text/plain": [
59 | "'#1f77b4'"
60 | ]
61 | },
62 | "execution_count": 16,
63 | "metadata": {},
64 | "output_type": "execute_result"
65 | }
66 | ],
67 | "source": [
68 | "list(list(a)[0].values())[0]"
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "execution_count": 20,
74 | "metadata": {},
75 | "outputs": [],
76 | "source": [
77 | "# Method2: < 12 colors\n",
78 | "a1 = cm.get_cmap('Set3').colors[:12]"
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": 21,
84 | "metadata": {},
85 | "outputs": [
86 | {
87 | "data": {
88 | "text/plain": [
89 | "((0.5529411764705883, 0.8274509803921568, 0.7803921568627451),\n",
90 | " (1.0, 1.0, 0.7019607843137254),\n",
91 | " (0.7450980392156863, 0.7294117647058823, 0.8549019607843137),\n",
92 | " (0.984313725490196, 0.5019607843137255, 0.4470588235294118),\n",
93 | " (0.5019607843137255, 0.6941176470588235, 0.8274509803921568),\n",
94 | " (0.9921568627450981, 0.7058823529411765, 0.3843137254901961),\n",
95 | " (0.7019607843137254, 0.8705882352941177, 0.4117647058823529),\n",
96 | " (0.9882352941176471, 0.803921568627451, 0.8980392156862745),\n",
97 | " (0.8509803921568627, 0.8509803921568627, 0.8509803921568627),\n",
98 | " (0.7372549019607844, 0.5019607843137255, 0.7411764705882353),\n",
99 | " (0.8, 0.9215686274509803, 0.7725490196078432),\n",
100 | " (1.0, 0.9294117647058824, 0.43529411764705883))"
101 | ]
102 | },
103 | "execution_count": 21,
104 | "metadata": {},
105 | "output_type": "execute_result"
106 | }
107 | ],
108 | "source": [
109 | "a1"
110 | ]
111 | },
112 | {
113 | "cell_type": "code",
114 | "execution_count": 23,
115 | "metadata": {},
116 | "outputs": [],
117 | "source": [
118 | "# Method3: < 20 colors\n",
119 | "a2 = cm.get_cmap('tab20').colors[:20]"
120 | ]
121 | },
122 | {
123 | "cell_type": "code",
124 | "execution_count": 24,
125 | "metadata": {},
126 | "outputs": [
127 | {
128 | "data": {
129 | "text/plain": [
130 | "((0.12156862745098039, 0.4666666666666667, 0.7058823529411765),\n",
131 | " (0.6823529411764706, 0.7803921568627451, 0.9098039215686274),\n",
132 | " (1.0, 0.4980392156862745, 0.054901960784313725),\n",
133 | " (1.0, 0.7333333333333333, 0.47058823529411764),\n",
134 | " (0.17254901960784313, 0.6274509803921569, 0.17254901960784313),\n",
135 | " (0.596078431372549, 0.8745098039215686, 0.5411764705882353),\n",
136 | " (0.8392156862745098, 0.15294117647058825, 0.1568627450980392),\n",
137 | " (1.0, 0.596078431372549, 0.5882352941176471),\n",
138 | " (0.5803921568627451, 0.403921568627451, 0.7411764705882353),\n",
139 | " (0.7725490196078432, 0.6901960784313725, 0.8352941176470589),\n",
140 | " (0.5490196078431373, 0.33725490196078434, 0.29411764705882354),\n",
141 | " (0.7686274509803922, 0.611764705882353, 0.5803921568627451),\n",
142 | " (0.8901960784313725, 0.4666666666666667, 0.7607843137254902),\n",
143 | " (0.9686274509803922, 0.7137254901960784, 0.8235294117647058),\n",
144 | " (0.4980392156862745, 0.4980392156862745, 0.4980392156862745),\n",
145 | " (0.7803921568627451, 0.7803921568627451, 0.7803921568627451),\n",
146 | " (0.7372549019607844, 0.7411764705882353, 0.13333333333333333),\n",
147 | " (0.8588235294117647, 0.8588235294117647, 0.5529411764705883),\n",
148 | " (0.09019607843137255, 0.7450980392156863, 0.8117647058823529),\n",
149 | " (0.6196078431372549, 0.8549019607843137, 0.8980392156862745))"
150 | ]
151 | },
152 | "execution_count": 24,
153 | "metadata": {},
154 | "output_type": "execute_result"
155 | }
156 | ],
157 | "source": [
158 | "a2"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": 2,
164 | "metadata": {},
165 | "outputs": [],
166 | "source": [
167 | "# Method4: > 20 colors, pick colors from continuous colormap\n",
168 | "cmap = [cm.jet(round(i)) for i in np.linspace(0,255,27)]"
169 | ]
170 | },
171 | {
172 | "cell_type": "code",
173 | "execution_count": 3,
174 | "metadata": {},
175 | "outputs": [
176 | {
177 | "data": {
178 | "text/plain": [
179 | "[(0.0, 0.0, 0.5, 1.0),\n",
180 | " (0.0, 0.0, 0.67825311942959, 1.0),\n",
181 | " (0.0, 0.0, 0.85650623885918, 1.0),\n",
182 | " (0.0, 0.0, 1.0, 1.0),\n",
183 | " (0.0, 0.11176470588235295, 1.0, 1.0),\n",
184 | " (0.0, 0.26862745098039204, 1.0, 1.0),\n",
185 | " (0.0, 0.42549019607843136, 1.0, 1.0),\n",
186 | " (0.0, 0.5823529411764706, 1.0, 1.0),\n",
187 | " (0.0, 0.7235294117647059, 1.0, 1.0),\n",
188 | " (0.0, 0.8803921568627451, 0.9835547122074637, 1.0),\n",
189 | " (0.11068943706514844, 1.0, 0.8570524984187226, 1.0),\n",
190 | " (0.2371916508538899, 1.0, 0.7305502846299811, 1.0),\n",
191 | " (0.3636938646426312, 1.0, 0.6040480708412397, 1.0),\n",
192 | " (0.4901960784313725, 1.0, 0.4775458570524984, 1.0),\n",
193 | " (0.6040480708412397, 1.0, 0.3636938646426312, 1.0),\n",
194 | " (0.730550284629981, 1.0, 0.23719165085388993, 1.0),\n",
195 | " (0.8570524984187222, 1.0, 0.11068943706514867, 1.0),\n",
196 | " (0.9835547122074635, 0.9448075526506902, 0.0, 1.0),\n",
197 | " (1.0, 0.7995642701525056, 0.0, 1.0),\n",
198 | " (1.0, 0.6688453159041396, 0.0, 1.0),\n",
199 | " (1.0, 0.5236020334059556, 0.0, 1.0),\n",
200 | " (1.0, 0.3783587509077707, 0.0, 1.0),\n",
201 | " (1.0, 0.2331154684095862, 0.0, 1.0),\n",
202 | " (1.0, 0.08787218591140178, 0.0, 1.0),\n",
203 | " (0.8565062388591802, 0.0, 0.0, 1.0),\n",
204 | " (0.6782531194295901, 0.0, 0.0, 1.0),\n",
205 | " (0.5, 0.0, 0.0, 1.0)]"
206 | ]
207 | },
208 | "execution_count": 3,
209 | "metadata": {},
210 | "output_type": "execute_result"
211 | }
212 | ],
213 | "source": [
214 | "cmap"
215 | ]
216 | },
217 | {
218 | "cell_type": "code",
219 | "execution_count": 6,
220 | "metadata": {},
221 | "outputs": [
222 | {
223 | "name": "stdout",
224 | "output_type": "stream",
225 | "text": [
226 | "#000080\n",
227 | "#0000ad\n",
228 | "#0000da\n",
229 | "#0000ff\n",
230 | "#001cff\n",
231 | "#0044ff\n",
232 | "#006cff\n",
233 | "#0094ff\n",
234 | "#00b8ff\n",
235 | "#00e0fb\n",
236 | "#1cffdb\n",
237 | "#3cffba\n",
238 | "#5dff9a\n",
239 | "#7dff7a\n",
240 | "#9aff5d\n",
241 | "#baff3c\n",
242 | "#dbff1c\n",
243 | "#fbf100\n",
244 | "#ffcc00\n",
245 | "#ffab00\n",
246 | "#ff8600\n",
247 | "#ff6000\n",
248 | "#ff3b00\n",
249 | "#ff1600\n",
250 | "#da0000\n",
251 | "#ad0000\n",
252 | "#800000\n"
253 | ]
254 | }
255 | ],
256 | "source": [
257 | "# convert to hexadecimal\n",
258 | "for c in cmap:\n",
259 | " print(colors.to_hex(c))\n",
260 | "# if you want to convert back, colors.to_rgb() or to_rgba()"
261 | ]
262 | },
263 | {
264 | "cell_type": "markdown",
265 | "metadata": {},
266 | "source": [
267 | "## construct custom colormap, first extract gradient using adobe online color, understand the dynamic changes of R G B channels, then specify cdict"
268 | ]
269 | },
270 | {
271 | "cell_type": "code",
272 | "execution_count": 26,
273 | "metadata": {},
274 | "outputs": [],
275 | "source": [
276 | "# Nathan's Yellow-blue schema\n",
277 | "# yellow-blue colormap\n",
278 | "cdict = {\n",
279 | " 'red':((0.0,0.0,0.0),\n",
280 | " (0.5,0.0,0.0),\n",
281 | " (1.0,1.0,1.0)),\n",
282 | " 'green':((0.0,0.8,0.8),\n",
283 | " (0.5,0.0,0.0),\n",
284 | " (1.0,1.0,1.0)),\n",
285 | " 'blue':((0.0,1.0,1.0),\n",
286 | " (0.5,0.0,0.0),\n",
287 | " (1.0,0.0,0.0))\n",
288 | "}\n",
289 | "from matplotlib.colors import LinearSegmentedColormap\n",
290 | "newcmp = LinearSegmentedColormap('yellow_blue',segmentdata=cdict)"
291 | ]
292 | },
293 | {
294 | "cell_type": "code",
295 | "execution_count": 27,
296 | "metadata": {},
297 | "outputs": [],
298 | "source": [
299 | "# SHAP pink-blue schema\n",
300 | "cdict = {'red':((0.0,0.0,0.0),\n",
301 | " (1.0,1.0,1.0)),\n",
302 | " 'green':((0.0,0.5,0.5),\n",
303 | " (0.73,0.0,0.0),\n",
304 | " (1.0,0.0,0.0)),\n",
305 | " 'blue':((0.0,1.0,1.0),\n",
306 | " (1.0,0.0,0.0))}\n",
307 | "newcmp = LinearSegmentedColormap('testCmap', segmentdata=cdict)"
308 | ]
309 | },
310 | {
311 | "cell_type": "code",
312 | "execution_count": null,
313 | "metadata": {},
314 | "outputs": [],
315 | "source": []
316 | }
317 | ],
318 | "metadata": {
319 | "kernelspec": {
320 | "display_name": "Python 3",
321 | "language": "python",
322 | "name": "python3"
323 | },
324 | "language_info": {
325 | "codemirror_mode": {
326 | "name": "ipython",
327 | "version": 3
328 | },
329 | "file_extension": ".py",
330 | "mimetype": "text/x-python",
331 | "name": "python",
332 | "nbconvert_exporter": "python",
333 | "pygments_lexer": "ipython3",
334 | "version": "3.6.12"
335 | }
336 | },
337 | "nbformat": 4,
338 | "nbformat_minor": 4
339 | }
340 |
--------------------------------------------------------------------------------
/examples/extend_ax.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "88b60d95-9ee5-44be-9063-ef831451dd6b",
6 | "metadata": {},
7 | "source": [
8 | "## How to extend the ax if the text protrudes out?\n",
9 | "## It is also about Transformation and Bbox"
10 | ]
11 | },
12 | {
13 | "cell_type": "code",
14 | "execution_count": 11,
15 | "id": "30f54a5b-4866-47f3-aefd-231ee2a82528",
16 | "metadata": {},
17 | "outputs": [],
18 | "source": [
19 | "import matplotlib.pyplot as plt\n",
20 | "import matplotlib as mpl\n",
21 | "from matplotlib.transforms import Bbox\n",
22 | "import pandas as pd\n",
23 | "import numpy as np"
24 | ]
25 | },
26 | {
27 | "cell_type": "code",
28 | "execution_count": 12,
29 | "id": "51c9620b-c5e2-4007-af0e-add01939e78e",
30 | "metadata": {},
31 | "outputs": [
32 | {
33 | "data": {
34 | "text/plain": [
35 | "Text(0.9, 0.9, 'hhhhhhh')"
36 | ]
37 | },
38 | "execution_count": 12,
39 | "metadata": {},
40 | "output_type": "execute_result"
41 | },
42 | {
43 | "data": {
44 | "image/png": "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\n",
45 | "text/plain": [
46 | ""
47 | ]
48 | },
49 | "metadata": {
50 | "needs_background": "light"
51 | },
52 | "output_type": "display_data"
53 | }
54 | ],
55 | "source": [
56 | "# problem, as you can see, the text protrudes out the ax\n",
57 | "fig,ax = plt.subplots()\n",
58 | "ax.set_xlim([0,1])\n",
59 | "ax.set_ylim([0,1])\n",
60 | "data_text_coords = (0.9,0.9)\n",
61 | "ax.text(x=data_text_coords[0],y=data_text_coords[1],s='hhhhhhh') # default transform is ax.transData"
62 | ]
63 | },
64 | {
65 | "cell_type": "markdown",
66 | "id": "82d240b2-8a65-47d6-b2e7-66d5d463fb9f",
67 | "metadata": {},
68 | "source": [
69 | "## Easy fix:\n",
70 | "1. first save text as an object\n",
71 | "2. get text coordinate (display), inversely transform to coordinate (Ax), then adjust the x_lim"
72 | ]
73 | },
74 | {
75 | "cell_type": "code",
76 | "execution_count": 13,
77 | "id": "523394ae-1535-44e8-bdef-fb3eb830e952",
78 | "metadata": {},
79 | "outputs": [
80 | {
81 | "data": {
82 | "image/png": "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\n",
83 | "text/plain": [
84 | ""
85 | ]
86 | },
87 | "metadata": {
88 | "needs_background": "light"
89 | },
90 | "output_type": "display_data"
91 | },
92 | {
93 | "data": {
94 | "image/png": "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\n",
95 | "text/plain": [
96 | ""
97 | ]
98 | },
99 | "metadata": {
100 | "needs_background": "light"
101 | },
102 | "output_type": "display_data"
103 | }
104 | ],
105 | "source": [
106 | "# easy fix, first save to texts object (Text)\n",
107 | "fig,ax = plt.subplots()\n",
108 | "ax.set_xlim([0,1])\n",
109 | "ax.set_ylim([0,1])\n",
110 | "data_text_coords = (0.9,0.9)\n",
111 | "texts = ax.text(x=data_text_coords[0],y=data_text_coords[1],s='hhhhhhh') # default transform is ax.transData\n",
112 | "plt.pause(0.01)\n",
113 | "ax_text_coords = ax.transAxes.inverted().transform(texts.get_window_extent().get_points())\n",
114 | "# get_window_extent() will return a Bbox object, get_points() for Bbox will return ndarray\n",
115 | "ymax = ax_text_coords[1,1]\n",
116 | "fig,ax = plt.subplots()\n",
117 | "ax.set_xlim([0,ymax+0.3])\n",
118 | "data_text_coords = (0.9,0.9)\n",
119 | "texts = ax.text(x=data_text_coords[0],y=data_text_coords[1],s='hhhhhhh') # default transform is ax.transData"
120 | ]
121 | },
122 | {
123 | "cell_type": "markdown",
124 | "id": "8c2ba27f-d970-4191-ba6e-50304d9391d8",
125 | "metadata": {},
126 | "source": [
127 | "## More complex fix\n",
128 | "1. make sure the text are drawn based on fig coords\n",
129 | "2. then update the ax based on fig coords"
130 | ]
131 | },
132 | {
133 | "cell_type": "code",
134 | "execution_count": 16,
135 | "id": "00c728c4-a3af-41e4-a5e2-59fe00697463",
136 | "metadata": {},
137 | "outputs": [
138 | {
139 | "data": {
140 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAdIAAAE2CAYAAADVtROiAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAQ8ElEQVR4nO3df6zd9X3f8dfbgIMWUphqV6owFKKZUQcWQq48L5VSJrLIoMhEaVaBEnVUCEssVNMaNWJiShv6V9esQ43YUkeLWCs1/IpUWakrJrUgElQSTAgkdkLjuSQYUIA0RcpP6uy9P+4tulyufY/9Odc+13s8pCOd7/d8zvd8+OjaT3/POfdLdXcAgOOz7mRPAADWMiEFgAFCCgADhBQABggpAAwQUgAYsGJIq+rTVfVCVX3tCI9XVf1hVR2oqier6vLpTxMAZtMkZ6R3Jtl+lMevSrJ54bYzyf8YnxYArA0rhrS7H0ryd0cZck2SP+55jyQ5p6p+floTBIBZNo3PSM9N8syi7UML+wDglHf6iXyxqtqZ+bd/88Y3vvHtF1988Yl8eQBY1mOPPfZSd288nudOI6TPJjlv0famhX2v0927kuxKkrm5ud67d+8UXh4AxlTVt473udN4a3d3kl9b+PbutiQvd/fzUzguAMy8Fc9Iq+ozSa5IsqGqDiX57SRnJEl3fzLJniRXJzmQ5IdJfn21JgsAs2bFkHb3dSs83kk+NLUZAcAa4spGADBASAFggJACwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAZMFNKq2l5VT1XVgaq6ZZnHz6+qB6rq8ap6sqqunv5UAWD2rBjSqjotyR1JrkqyJcl1VbVlybD/nOSe7n5bkmuT/PdpTxQAZtEkZ6Rbkxzo7oPd/UqSu5Jcs2RMJ/mZhftnJ3luelMEgNl1+gRjzk3yzKLtQ0n+5ZIxv5Pkf1fVbyR5Y5J3TWV2ADDjpvVlo+uS3Nndm5JcneRPqup1x66qnVW1t6r2vvjii1N6aQA4eSYJ6bNJzlu0vWlh32I3JLknSbr7r5OcmWTD0gN1967unuvuuY0bNx7fjAFghkwS0keTbK6qC6tqfea/TLR7yZhvJ7kySarqFzMfUqecAJzyVgxpdx9OcnOS+5N8PfPfzt1XVbdV1Y6FYR9OcmNVPZHkM0mu7+5erUkDwKyY5MtG6e49SfYs2ffRRff3J/ml6U4NAGafKxsBwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAYIKcCEnn766VxyySWv23/FFVdk7969r9t/55135uabb172WGeddday+6+//vrcd999r9v/4IMP5j3vec+yz7ngggvy0ksvHW3qrCIhBYABQgpwDH7605/mxhtvzFve8pa8+93vzo9+9KMkyb333putW7fmoosuyuc///lXxz/33HPZvn17Nm/enI985COvOdatt96at771rdm2bVu+853vvLr/oYceyjve8Y68+c1vfs3Z6fe///28//3vz8UXX5wPfOADWfy/ff7EJz6Ryy+/PJdeemm+8Y1vrNZ/PssQUoBj8M1vfjMf+tCHsm/fvpxzzjn57Gc/myQ5fPhwvvSlL+X222/Pxz72sVfHf+UrX8ndd9+dr371q7n77rvzzDPPJEl+8IMfZNu2bXniiSfyzne+M5/61Kdefc7zzz+fL3zhC/nc5z6XW2655dX9jz/+eG6//fbs378/Bw8ezMMPP/zqYxs2bMiXv/zl3HTTTfn4xz++2svAIkIKcAwuvPDCXHbZZUmSt7/97Xn66aeTJO973/tety9Jrrzyypx99tk588wzs2XLlnzrW99Kkqxfv/7VzzyXPue9731v1q1bly1btrzmTHXr1q3ZtGlT1q1bl8suu+w1zznS67P6hBTgGLzhDW949f5pp52Ww4cPv2b/4n1HG3/GGWekqlZ8zuK3b490rKO9PqtPSAFggJACwIBa/LbBiTQ3N9fL/d4VAJxoVfVYd88dz3OdkQLAACEFgAFCCgADhBQABggpAAwQUgAYIKQAMEBIAWCAkALAACEFgAFCCgADhBQABggpAAwQUgAYIKQAMEBIAWCAkALAACEFgAFCCgADhBQABggpAAwQUgAYIKQAMEBIAWCAkALAgIlCWlXbq+qpqjpQVbccYcyvVtX+qtpX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\n",
141 | "text/plain": [
142 | ""
143 | ]
144 | },
145 | "metadata": {
146 | "needs_background": "light"
147 | },
148 | "output_type": "display_data"
149 | }
150 | ],
151 | "source": [
152 | "fig,ax = plt.subplots()\n",
153 | "ax.set_xlim([0,1])\n",
154 | "ax.set_ylim([0,1])\n",
155 | "data_text_coords = (0.9,0.9)\n",
156 | "display_text_coords = ax.transData.transform(data_text_coords)\n",
157 | "fig_text_coords = fig.transFigure.inverted().transform(display_text_coords)\n",
158 | "texts = ax.text(x=fig_text_coords[0],y=fig_text_coords[1],s='hhhhhhh',transform=fig.transFigure)\n",
159 | "fig_ax_coords = ax.get_position().get_points()\n",
160 | "## build Bbox from the construct, not extents nor bounds\n",
161 | "new_bbox = Bbox([[fig_ax_coords[0,0],fig_ax_coords[0,1]],[fig_ax_coords[1,0]+0.2,fig_ax_coords[1,1]+0.2]])\n",
162 | "ax.set_position(new_bbox)"
163 | ]
164 | },
165 | {
166 | "cell_type": "markdown",
167 | "id": "92ffc797-e7fc-4e40-bd29-26e61decb970",
168 | "metadata": {},
169 | "source": [
170 | "# talks a bit about bbox"
171 | ]
172 | },
173 | {
174 | "cell_type": "code",
175 | "execution_count": 5,
176 | "id": "087abffa-1ecc-4b05-b7d2-730bd40a9a57",
177 | "metadata": {},
178 | "outputs": [
179 | {
180 | "data": {
181 | "text/plain": [
182 | "Bbox([[0.0, 0.0], [1.0, 1.0]])"
183 | ]
184 | },
185 | "execution_count": 5,
186 | "metadata": {},
187 | "output_type": "execute_result"
188 | }
189 | ],
190 | "source": [
191 | "# method1: constructor, [[x0,y0],[x1,y1]], first is the lower left, second is the upper right\n",
192 | "Bbox([[0,0],[1,1]])"
193 | ]
194 | },
195 | {
196 | "cell_type": "code",
197 | "execution_count": 8,
198 | "id": "aeb6e99d-5155-47e1-b22e-ec6a5652fb65",
199 | "metadata": {},
200 | "outputs": [
201 | {
202 | "data": {
203 | "text/plain": [
204 | "Bbox([[0.0, 0.0], [1.0, 1.0]])"
205 | ]
206 | },
207 | "execution_count": 8,
208 | "metadata": {},
209 | "output_type": "execute_result"
210 | }
211 | ],
212 | "source": [
213 | "# method2: from_bounds(x0,y0,width,height)\n",
214 | "Bbox.from_bounds(0,0,1,1)"
215 | ]
216 | },
217 | {
218 | "cell_type": "code",
219 | "execution_count": 10,
220 | "id": "514ed90e-31c5-49b3-b0b1-75dd12d2a225",
221 | "metadata": {},
222 | "outputs": [
223 | {
224 | "data": {
225 | "text/plain": [
226 | "Bbox([[0.0, 0.0], [1.0, 1.0]])"
227 | ]
228 | },
229 | "execution_count": 10,
230 | "metadata": {},
231 | "output_type": "execute_result"
232 | }
233 | ],
234 | "source": [
235 | "# method3: from_extent (x0,y0,y0,y1)\n",
236 | "Bbox.from_extents(0,0,1,1)"
237 | ]
238 | },
239 | {
240 | "cell_type": "code",
241 | "execution_count": null,
242 | "id": "8fcf1778-c43f-4ee1-a3ab-c6d091cfc51f",
243 | "metadata": {},
244 | "outputs": [],
245 | "source": []
246 | }
247 | ],
248 | "metadata": {
249 | "kernelspec": {
250 | "display_name": "Python 3",
251 | "language": "python",
252 | "name": "python3"
253 | },
254 | "language_info": {
255 | "codemirror_mode": {
256 | "name": "ipython",
257 | "version": 3
258 | },
259 | "file_extension": ".py",
260 | "mimetype": "text/x-python",
261 | "name": "python",
262 | "nbconvert_exporter": "python",
263 | "pygments_lexer": "ipython3",
264 | "version": "3.6.13"
265 | }
266 | },
267 | "nbformat": 4,
268 | "nbformat_minor": 5
269 | }
270 |
--------------------------------------------------------------------------------
/examples/gridspec.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "%matplotlib inline\n",
10 | "import matplotlib\n",
11 | "import matplotlib.pyplot as plt"
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": 4,
17 | "metadata": {},
18 | "outputs": [
19 | {
20 | "data": {
21 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXwAAAD8CAYAAAB0IB+mAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAV3klEQVR4nO3db6hc9Z3H8ffHpKk0jVqaCCWJRtnEeLEL2sFaCtWiW2IeJA8skkBoLcFQu8pSpeDi0kp85EpdKGRXb6mkFfwTfSAXjARqIwHxurkhNTUR5RqtXpVN/NM8Ef+k/e6Dc5Tb23szv8ycOefO+X1ecOGcmd/MfL/M5JMzvzPzG0UEZmbWfmc0XYCZmdXDgW9mlgkHvplZJhz4ZmaZcOCbmWXCgW9mlgkHfh8kPSDpmKQXm67FzKwbB35/dgLrmi7CzCyFA78PEbEPeL/pOszMUixsuoC2k7QN2AawePHib6xdu7bhisxsmB04cODdiFjWy20d+AMWEaPAKECn04mJiYmGKzKzYSbpz73e1lM6ZmaZcOCbmWXCgd8HSQ8DzwEXSZqStLXpmszM5uI5/D5ExOamazAzS+UjfDOzTDjwzcwy4cA3M8uEA9/MLBMOfDOzTDjwzcwy4cA3M8uEA9/MLBMO/D5IWifpZUmTkm5vuh4zs1Nx4PdI0gJgB3AtMAJsljTSbFVmZnNz4PfucmAyIo5GxCfAI8DGhmsyM5uT19Lp3XLgzWn7U8A3Zw6a/gMowMct/v3bpcC7TRcxIG3tra19Qbt7u6jXGzrwB2z6D6BImoiITsMlDYR7Gz5t7Qva31uvt/WUTu/eAlZO219RXmZmNi858Hu3H1gt6QJJi4BNwFjDNZmZzclTOj2KiJOSbgb2AAuAByLicJebjQ6+ssa4t+HT1r7Avc1KEVFlIWZmNk95SsfMLBMOfDOzTDjwB6DbkguSvijp0fL65yWtaqDM05bQ162Sjkg6JOlpSec3UWcvUpfJkHSdpJA0NB/5S+lN0vXlc3dY0kN119irhNfkeZL2SjpYvi7XN1Hn6ZL0gKRjc31vR4VflX0fknRZ0h1HhP8q/KM4gfsqcCGwCHgBGJkx5ifAfeX2JuDRpuuuqK/vAl8qt28ahr5SeyvHLQH2AeNAp+m6K3zeVgMHga+U++c2XXeFvY0CN5XbI8DrTded2Nt3gMuAF+e4fj3wFCDgCuD5lPv1EX71UpZc2Aj8ttx+HLhakmqssRdd+4qIvRHxYbk7TvHdhGGQukzGXcDdwEd1FtenlN5uBHZExAcAEXGs5hp7ldJbAGeV22cDb9dYX88iYh/w/imGbAR+F4Vx4BxJX+t2vw786s225MLyucZExEngBPDVWqrrXUpf022lOAIZBl17K98yr4yIJ+ssrAIpz9saYI2kZyWNS1pXW3X9SentTmCLpClgN3BLPaUN3On+ewT8OXwbAElbgA5wZdO1VEHSGcC9wA0NlzIoCymmda6ieFe2T9LXI+IvTRZVkc3Azoj4paRvAQ9KuiQi/tZ0YU3wEX71UpZc+HyMpIUUbzXfq6W63iUtJSHpGuAOYENEfFxTbf3q1tsS4BLgGUmvU8yZjg3JiduU520KGIuITyPiNeAViv8A5ruU3rYCuwAi4jngTIqF1YZdT0u7OPCrl7Lkwhjww3L7+8AfojwTM4917UvSpcD9FGE/LPPA0KW3iDgREUsjYlVErKI4P7EhInpexKpGKa/HJyiO7pG0lGKK52iNNfYqpbc3gKsBJF1MEfjHa61yMMaAH5Sf1rkCOBER73S7kad0KhZzLLkgaTswERFjwG8o3lpOUpyY2dRcxWkS+7oH+DLwWHkO+o2I2NBY0YkSextKib3tAb4n6QjwV+BnETHf33Gm9nYb8GtJP6U4gXvDEBxcIelhiv+El5bnH34BfAEgIu6jOB+xHpgEPgR+lHS/Q9C7mZlVwFM6ZmaZcOCbmWXCgW9mlgkHvplZJhz4ZmaZcOCbmWXCgW9mlgkHfh+6rVltZjafOPD7sxMYlpUFzSxzDvw+JKxZbWY2b3gtnQGTtA3YBrB48eJvrF27tuGKzGyYHThw4N2IWNbLbR34AxYRoxQ/s0an04mJiWFYYNHM5itJf+71tp7SMTPLhAPfzCwTDvw+lGtWPwdcJGlK0tamazIzm4vn8PsQEZubrsHMLJWP8M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDvw+SFon6WVJk5Jub7oeM7NTceD3SNICYAdwLTACbJY00mxVZmZzc+D37nJgMiKORsQnwCPAxoZrMjOb08KmCxhiy4E3p+1PAd+cOUjSNmBbufuxpBdrqK0JS4F3my5iQNraW1v7gnb3dlGvN3TgD1hEjAKjAJImIqLTcEkD4d6GT1v7gvb31uttPaXTu7eAldP2V5SXmZnNSw783u0HVku6QNIiYBMw1nBNZmZz8pROjyLipKSbgT3AAuCBiDjc5Wajg6+sMe5t+LS1L3Bvs1JEVFmImZnNU57SMTPLhAPfzCwTDvwB6LbkgqQvSnq0vP55SasaKPO0JfR1q6Qjkg5JelrS+U3U2YvUZTIkXScpJA3NR/5SepN0ffncHZb0UN019irhNXmepL2SDpavy/VN1Hm6JD0g6dhc39tR4Vdl34ckXZZ0xxHhvwr/KE7gvgpcCCwCXgBGZoz5CXBfub0JeLTpuivq67vAl8rtm4ahr9TeynFLgH3AONBpuu4Kn7fVwEHgK+X+uU3XXWFvo8BN5fYI8HrTdSf29h3gMuDFOa5fDzwFCLgCeD7lfn2EX72UJRc2Ar8ttx8HrpakGmvsRde+ImJvRHxY7o5TfDdhGKQuk3EXcDfwUZ3F9SmltxuBHRHxAUBEHKu5xl6l9BbAWeX22cDbNdbXs4jYB7x/iiEbgd9FYRw4R9LXut2vA796sy25sHyuMRFxEjgBfLWW6nqX0td0WymOQIZB197Kt8wrI+LJOgurQMrztgZYI+lZSeOS1tVWXX9SersT2CJpCtgN3FJPaQN3uv8eAX8O3wZA0hagA1zZdC1VkHQGcC9wQ8OlDMpCimmdqyjele2T9PWI+EuTRVVkM7AzIn4p6VvAg5IuiYi/NV1YE3yEX72UJRc+HyNpIcVbzfdqqa53SUtJSLoGuAPYEBEf11Rbv7r1tgS4BHhG0usUc6ZjQ3LiNuV5mwLGIuLTiHgNeIXiP4D5LqW3rcAugIh4DjiTYmG1YdfT0i4O/OqlLLkwBvyw3P4+8Icoz8TMY137knQpcD9F2A/LPDB06S0iTkTE0ohYFRGrKM5PbIiInhexqlHK6/EJiqN7JC2lmOI5WmONvUrp7Q3gagBJF1ME/vFaqxyMMeAH5ad1rgBORMQ73W7kKZ2KxRxLLkjaDkxExBjwG4q3lpMUJ2Y2NVdxmsS+7gG+DDxWnoN+IyI2NFZ0osTehlJib3uA70k6AvwV+FlEzPd3nKm93Qb8WtJPKU7g3jAEB1dIepjiP+Gl5fmHXwBfAIiI+yjOR6wHJoEPgR8l3e8Q9G5mZhXwlI6ZWSYc+GZmmXDgm5llwoFvZpYJB76ZWSYc+GZmmXDgm5llomvgD2xd5nksx57NrP1SjvB3AqdaPe9ainU3VgPbgP/pv6zG7SS/ns2s5boG/qDWZZ7PcuzZzNqvijn8ntZlHnI59mxmQ67WxdMkbaOYAmHx4sXfWLt2bZ0P/7kDBw68GxHL6nis+dKzmbVDP/lVReAnr8scEaMUvzFJp9OJiYlmVpeV9Oc+72Loejazdugnv6qY0ulpXeYhl2PPZjbkuh7hD2pd5vksx57NrP26Bn5EbO5yfQD/WllF80COPZtZ+/mbtmZmmXDgm5llwoFvZpYJB76ZWSYc+GZmmXDgm5llwoFvZpYJB76ZWSYc+GZmmXDgm5llwoFvZpYJB76ZWSYc+GZmmXDgm5llIinwJa2T9LKkSUm3z3L9eZL2Sjoo6ZCk9dWXWq8cezazdusa+JIWADuAa4ERYLOkkRnD/gPYFRGXApuA/6660Drl2LOZtV/KEf7lwGREHI2IT4BHgI0zxgRwVrl9NvB2dSU2IseezazlUgJ/OfDmtP2p8rLp7gS2lD8HuBu4ZbY7krRN0oSkiePHj/dQbm1y7NnMWq6qk7abgZ0RsYLit14flPQP9x0RoxHRiYjOsmXLKnroxuTYs5kNsZTAfwtYOW1/RXnZdFuBXQAR8RxwJrC0igIbkmPPZtZyKYG/H1gt6QJJiyhOUI7NGPMGcDWApIspwm+Y5y9y7NnMWq5r4EfESeBmYA/wEsUnUw5L2i5pQznsNuBGSS8ADwM3REQMquhBy7FnM2u/hSmDImI3xYnJ6Zf9fNr2EeDb1ZbWrBx7NrN28zdtzcwy4cA3M8uEA9/MLBMOfDOzTDjwzcwy4cA3M8uEA9/MLBMOfDOzTDjwzcwy4cA3M8uEA9/MLBMOfDOzTDjwzcwy4cA3M8tEUuBLWifpZUmTkm6fY8z1ko5IOizpoWrLrF+OPZtZu3VdD1/SAmAH8C8UP+a9X9JYuR78Z2NWA/8OfDsiPpB07qAKrkOOPZtZ+6Uc4V8OTEbE0Yj4BHgE2DhjzI3Ajoj4ACAijlVbZu1y7NnMWi4l8JcDb07bnyovm24NsEbSs5LGJa2b7Y4kbZM0IWni+PF5/fOvOfZsZi1X1UnbhcBq4CpgM/BrSefMHBQRoxHRiYjOsmXLKnroxuTYs5kNsZTAfwtYOW1/RXnZdFPAWER8GhGvAa9QhOGwyrFnM2u5lMDfD6yWdIGkRcAmYGzGmCcojnSRtJRiuuNodWXWLseezazlugZ+RJwEbgb2AC8BuyLisKTtkjaUw/YA70k6AuwFfhYR7w2q6EHLsWczaz9FRCMP3Ol0YmJiopHHlnQgIjp1P26TPZtZO/STX/6mrZlZJhz4ZmaZcOCbmWXCgW9mlgkHvplZJhz4ZmaZcOCbmWXCgW9mlgkHvplZJhz4ZmaZcOCbmWXCgW9mlgkHvplZJhz4ZmaZSAp8SeskvSxpUtLtpxh3naSQVPvSw1XLsWcza7eugS9pAbADuBYYATZLGpll3BLg34Dnqy6ybjn2bGbtl3KEfzkwGRFHI+IT4BFg4yzj7gLuBj6qsL6m5NizmbVcSuAvB96ctj9VXvY5SZcBKyPiyVPdkaRtkiYkTRw/fvy0i61Rjj2bWcv1fdJW0hnAvcBt3cZGxGhEdCKis2zZsn4fujE59mxmwy8l8N8CVk7bX1Fe9pklwCXAM5JeB64Axob8JGaOPZtZy6UE/n5gtaQLJC0CNgFjn10ZESciYmlErIqIVcA4sCEihvnXunPs2cxarmvgR8RJ4GZgD/ASsCsiDkvaLmnDoAtsQo49m1n7LUwZFBG7gd0zLvv5HGOv6r+s5uXYs5m1m79pa2aWCQe+mVkmHPhmZplw4JuZZcKBb2aWCQe+mVkmHPhmZplw4JuZZcKBb2aWCQe+mVkmHPhmZplw4JuZZcKBb2aWCQe+mVkmkgJf0jpJL0ualHT7LNffKumIpEOSnpZ0fvWl1ivHns2s3boGvqQFwA7gWmAE2CxpZMawg0AnIv4ZeBz4z6oLrVOOPZtZ+6Uc4V8OTEbE0Yj4BHgE2Dh9QETsjYgPy91xit+AHWY59mxmLZcS+MuBN6ftT5WXzWUr8NRsV0jaJmlC0sTx48fTq6xfjj2bWctVetJW0hagA9wz2/URMRoRnYjoLFu2rMqHbkyOPZvZcEr5Tdu3gJXT9leUl/0dSdcAdwBXRsTH1ZTXmBx7NrOWSznC3w+slnSBpEXAJmBs+gBJlwL3Axsi4lj1ZdYux57NrOW6Bn5EnARuBvYALwG7IuKwpO2SNpTD7gG+DDwm6Y+Sxua4u6GQY89m1n4pUzpExG5g94zLfj5t+5qK62pcjj2bWbv5m7ZmZplw4JuZZcKBb2aWCQe+mVkmHPhmZplw4JuZZcKBb2aWCQe+mVkmHPhmZplw4JuZZcKBb2aWCQe+mVkmHPhmZplw4JuZZSIp8CWtk/SypElJt89y/RclPVpe/7ykVZVXWrMcezazdusa+JIWADuAa4ERYLOkkRnDtgIfRMQ/Af8F3F11oXXKsWcza7+UI/zLgcmIOBoRnwCPABtnjNkI/Lbcfhy4WpKqK7N2OfZsZi2X8otXy4E3p+1PAd+ca0xEnJR0Avgq8O70QZK2AdvK3Y8lvdhL0RW4qMv1bex50JYyo/cWaWtvbe0L2t1bt/yaU9JPHFYlIkaBUQBJExHRqfPxPyNpoq7Hmi89D5p7Gz5t7Qva31uvt02Z0nkLWDltf0V52axjJC0Ezgbe67WoeSDHns2s5VICfz+wWtIFkhYBm4CxGWPGgB+W298H/hARUV2ZtcuxZzNrua5TOuX89M3AHmAB8EBEHJa0HZiIiDHgN8CDkiaB9ykCspvRPuru1ykfu6U9D5p7Gz5t7Qvc26zkg1Izszz4m7ZmZplw4JuZZaKRwO+2bMGAHvMBScfq+Bx8W5dlSOjrVklHJB2S9LSk85uosxepr0lJ10kKSUPzkb+U3iRdXz53hyU9VHeNvUp4TZ4naa+kg+Xrcn0TdZ6ubnmlwq/Kvg9JuizpjiOi1j+Kk6CvAhcCi4AXgJEaHvc7wGXAi033B/wEuK/c3gQ8WvfzMKC+vgt8qdy+aRj6Su2tHLcE2AeMA52m667weVsNHAS+Uu6f23TdFfY2CtxUbo8Arzddd2Jvp8wrYD3wFCDgCuD5lPtt4gg/ZdmCykXEPopP0wxaW5dl6NpXROyNiA/L3XGK7y8Mg9TX5F0UayZ9VGdxfUrp7UZgR0R8ABARx2qusVcpvQVwVrl9NvB2jfX1LCGvNgK/i8I4cI6kr3W73yYCf7ZlC5Y3UMegpPT3d8syAJ8tyzCfne7ztpXiCGQYdO2tfMu8MiKerLOwCqQ8b2uANZKelTQuaV1t1fUnpbc7gS2SpoDdwC31lDZwPeVorUsrWB4kbQE6wJVN11IFSWcA9wI3NFzKoCykmNa5iuJd2T5JX4+IvzRZVEU2Azsj4peSvkXx3ZlLIuJvTRfWhCaO8FOWLRhmbV2WIel5k3QNcAewISI+rqm2fnXrbQlwCfCMpNcp5kzHhuTEbcrzNgWMRcSnEfEa8ArFfwDzXUpvW4FdABHxHHAmxcJqw66nHG0i8FOWLRhmbV2WoWtfki4F7qcI+2GZB4YuvUXEiYhYGhGrImIVxfmJDRFR2yJ8fUh5PT5BcXSPpKUUUzxHa6yxVym9vQFcDSDpYorAP15rlYMxBvyg/LTOFcCJiHin660aOgO9nuIo4lXgjpoe82HgHeBTiiOarXX2B2ynCAkoXnSPAZPA/wIXNvE8DKCv3wP/B/yx/Btruuaqepsx9hmG5FM6ic+bKKasjgB/AjY1XXOFvY0Az1J8guePwPearjmxr3/IK+DHwI+nPWc7yr7/lPp69NIKZmaZ8Ddtzcwy4cA3M8uEA9/MLBMOfDOzTDjwzcwy4cA3M8uEA9/MLBP/DxsH83EJwYckAAAAAElFTkSuQmCC\n",
22 | "text/plain": [
23 | ""
24 | ]
25 | },
26 | "metadata": {
27 | "needs_background": "light"
28 | },
29 | "output_type": "display_data"
30 | }
31 | ],
32 | "source": [
33 | "fig = plt.figure()\n",
34 | "gs = matplotlib.gridspec.GridSpec(nrows=3,ncols=2,width_ratios=(0.1,0.9),height_ratios=(0.1,0.2,0.7),hspace=0.5)\n",
35 | "ax1 = fig.add_subplot(gs[0,1])\n",
36 | "ax2 = fig.add_subplot(gs[1,1])\n",
37 | "ax3 = fig.add_subplot(gs[2,1])\n",
38 | "ax4 = fig.add_subplot(gs[2,0])"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 10,
44 | "metadata": {},
45 | "outputs": [
46 | {
47 | "data": {
48 | "image/png": "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\n",
49 | "text/plain": [
50 | ""
51 | ]
52 | },
53 | "metadata": {
54 | "needs_background": "light"
55 | },
56 | "output_type": "display_data"
57 | }
58 | ],
59 | "source": [
60 | "fig = plt.figure()\n",
61 | "gs = matplotlib.gridspec.GridSpec(nrows=3,ncols=2,width_ratios=(0.1,0.9),height_ratios=(0.1,0.2,0.7),hspace=0.7)\n",
62 | "ax1 = fig.add_subplot(gs[0,1])\n",
63 | "ax2 = fig.add_subplot(gs[1,1])\n",
64 | "ax3 = fig.add_subplot(gs[2,1])\n",
65 | "ax4 = fig.add_subplot(gs[2,0])\n",
66 | "gs.update(bottom=0.5)\n",
67 | "gs2 = matplotlib.gridspec.GridSpec(nrows=1,ncols=1,top=0.3)\n",
68 | "ax5 = fig.add_subplot(gs2[0,0])"
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "execution_count": null,
74 | "metadata": {},
75 | "outputs": [],
76 | "source": []
77 | }
78 | ],
79 | "metadata": {
80 | "kernelspec": {
81 | "display_name": "Python 3",
82 | "language": "python",
83 | "name": "python3"
84 | },
85 | "language_info": {
86 | "codemirror_mode": {
87 | "name": "ipython",
88 | "version": 3
89 | },
90 | "file_extension": ".py",
91 | "mimetype": "text/x-python",
92 | "name": "python",
93 | "nbconvert_exporter": "python",
94 | "pygments_lexer": "ipython3",
95 | "version": "3.6.12"
96 | }
97 | },
98 | "nbformat": 4,
99 | "nbformat_minor": 4
100 | }
101 |
--------------------------------------------------------------------------------
/examples/legend.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "%matplotlib inline\n",
10 | "import matplotlib\n",
11 | "import matplotlib.pyplot as plt\n",
12 | "import matplotlib.patches as mpatches\n",
13 | "import matplotlib.lines as mlines"
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": 4,
19 | "metadata": {},
20 | "outputs": [
21 | {
22 | "data": {
23 | "text/plain": [
24 | ""
25 | ]
26 | },
27 | "execution_count": 4,
28 | "metadata": {},
29 | "output_type": "execute_result"
30 | },
31 | {
32 | "data": {
33 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXwAAAD8CAYAAAB0IB+mAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAATAElEQVR4nO3de4yddZ3H8feXS53QUtjQ0ja0QDdbSkttoUwRhEA3CgLRqQYUGgli0BpQY0RdMWyEQEy8r8HUrSU2qIhcaoSCGIiKIVyKHSIQ2lqp2IWpIGNlKbN1oLXf/eMc22FsO6czz5wz7e/9Sk7yXH7neb7zy8znPOe5/CYyE0nS/u+AVhcgSWoOA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRADBn5ELIuIlyPimd2sj4i4MSLWR8TTETG3+jIlSUPVyBH+zcC5e1h/HjCt/loE/PfQy5IkVW3AwM/Mh4C/7qHJAuAHWbMSODwiJlVVoCSpGgdVsI2jgBf6zHfVl73Yv2FELKL2LYDRo0effPzxx1ewe0kqxxNPPPGXzBw/mPdWEfgNy8ylwFKA9vb27OzsbObuJWmfFxH/M9j3VnGXzkZgSp/5yfVlkqQRpIrAXwFcWr9b51Tg1cz8p9M5kqTWGvCUTkT8GJgPjIuILuBa4GCAzFwC3AecD6wHtgAfHq5iJUmDN2DgZ+bCAdYn8PHKKpIkYOvWrXR1ddHb29vqUlqira2NyZMnc/DBB1e2zaZetJWkRnV1dXHooYdy7LHHEhGtLqepMpNNmzbR1dXF1KlTK9uuQytIGpF6e3s54ogjigt7gIjgiCOOqPzbjYEvacQqMez/YTh+dgNfkgph4EvaN0ycCBHVvSZOHJYyr7vuOr7+9a8Py7aHysCXtG/4859bur3MZPv27dXW0GQGviTtxoYNG5g+fTqXXnops2bN4oYbbmDevHnMnj2ba6+9dke7L33pSxx33HGcccYZrFu3roUV75m3ZUrSHjz77LN8//vfZ/PmzSxfvpzf/OY3ZCYdHR089NBDjB49mttuu40nn3ySbdu2MXfuXE4++eRWl71LBr4k7cExxxzDqaeeymc/+1keeOABTjrpJAB6enp49tlnee2113jf+97HIYccAkBHR0cry90jA1+S9mD06NFA7Rz+F77wBT72sY+9af23vvWtFlQ1OJ7Dl6QGvOtd72LZsmX09PQAsHHjRl5++WXOPPNM7rrrLv72t7/x2muvcc8997S40t3zCF/SvmHChGrv1JkwYa+an3POOaxdu5bTTjsNgDFjxnDLLbcwd+5cLrroIubMmcORRx7JvHnzqquxYlEb+6z5/AcokvZk7dq1zJgxo9VltNSu+iAinsjM9sFsz1M6klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRDehy9pnzDx6xP58/9Vdx/+hNETeOmzL1W2vX2BR/iS9glVhn2V29u2bVsl22kGj/AlaQ9uuOEGbrnlFsaPH8+UKVM4+eSTuffeeznxxBN5+OGHWbhwIfPnz+eqq66ip6eHcePGcfPNNzNp0iT+8Ic/8PGPf5zu7m4OOeQQbrrpJo4//nguu+wyxo4dS2dnJy+99BJf/epXufDCC4f9ZzHwJWk3Vq1axU9+8hOeeuoptm7d+qahj9944w06OzvZunUrZ511FnfffTfjx4/n9ttv55prrmHZsmUsWrSIJUuWMG3aNB5//HGuvPJKfvWrXwHw4osv8vDDD/O73/2Ojo4OA1+SWumRRx5hwYIFtLW10dbWxnve854d6y666CIA1q1bxzPPPMPZZ58NwN///ncmTZpET08Pjz76KO9///t3vOf111/fMf3e976XAw44gJkzZ/Lnqv+b124Y+JI0CH2HTT7hhBN47LHH3rR+8+bNHH744Tz55JO7fP9b3vKWHdPNGtPMi7aStBunn34699xzD729vfT09HDvvff+U5vp06fT3d29I/C3bt3K6tWrGTt2LFOnTuXOO+8EaqH+1FNPNbX+/gx8SfuECaP3bjjjKrY3b948Ojo6mD17Nueddx5vfetbOeyww97UZtSoUSxfvpzPf/7zzJkzhxNPPJFHH30UgB/96Ed873vfY86cOZxwwgncfffdlf4Me8vhkSWNSCNleOSenh7GjBnDli1bOPPMM1m6dClz585tyr6rHh7Zc/iStAeLFi1izZo19Pb28qEPfahpYT8cDHxJ2oNbb7211SVUxnP4klQIA1+SCmHgS1IhDHxJKoSBL2mfMHEiRFT3mjhx4H1u2LCBWbNm/dPy+fPnsy/eVt5Q4EfEuRGxLiLWR8TVu1h/dEQ8GBG/jYinI+L86kuVVLKqh5tp0vA1I8qAgR8RBwKLgfOAmcDCiJjZr9l/Andk5knAxcB3qi5Uklph27ZtfPCDH2TGjBlceOGFbNmy5U3rx4wZs2N6+fLlXHbZZQB0d3dzwQUXMG/ePObNm8cjjzzSzLJ3qZEj/FOA9Zn5XGa+AdwGLOjXJoGx9enDgD9VV6Iktc66deu48sorWbt2LWPHjuU732nsePZTn/oUn/70p3cMsfyRj3xkmCsdWCMPXh0FvNBnvgt4W7821wEPRMQngdHAO3e1oYhYBCwCOProo/e2VklquilTpnD66acDcMkll3DjjTc29L5f/OIXrFmzZsf85s2bdwzT0CpVPWm7ELg5M78REacBP4yIWZm5vW+jzFwKLIXaWDoV7VuShk1ENDzf29u7Y3r79u2sXLmStra24S1wLzRySmcjMKXP/OT6sr4uB+4AyMzHgDZgXBUFSlIrPf/88zuGPr711ls544wz3rR+woQJrF27lu3bt/PTn/50x/JzzjmHb3/72zvmdzcufjM1EvirgGkRMTUiRlG7KLuiX5vngXcARMQMaoHfXWWhkso2odrRkRve3vTp01m8eDEzZszglVde4YorrnjT+i9/+cu8+93v5u1vfzuTJk3asfzGG2+ks7OT2bNnM3PmTJYsWVJl+YPS0PDI9dssvwUcCCzLzC9FxPVAZ2auqN+1cxMwhtoF3P/IzAf2tE2HR5a0JyNleORWasnwyJl5H3Bfv2Vf7DO9Bjh9MAVIkprDJ20lqRAGvqQRq1X/kW8kGI6f3cCXNCK1tbWxadOmIkM/M9m0aVPlt3T6H68kjUiTJ0+mq6uL7u4yb/hra2tj8uTJlW7TwJc0Ih188MFMnTq11WXsVzylI0mFMPAlqRAGviQVwsCXpEIY+JJUCANfkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAgDX5IKYeBLUiEMfEkqhIEvSYUw8CWpEAa+JBXCwJekQhj4klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRAGviQVwsCXpEIY+JJUiIYCPyLOjYh1EbE+Iq7eTZsPRMSaiFgdEbdWW6YkaagOGqhBRBwILAbOBrqAVRGxIjPX9GkzDfgCcHpmvhIRRw5XwZKkwWnkCP8UYH1mPpeZbwC3AQv6tfkosDgzXwHIzJerLVOSNFSNBP5RwAt95rvqy/o6DjguIh6JiJURce6uNhQRiyKiMyI6u7u7B1exJGlQqrpoexAwDZgPLARuiojD+zfKzKWZ2Z6Z7ePHj69o15KkRjQS+BuBKX3mJ9eX9dUFrMjMrZn5R+D31D4AJEkjRCOBvwqYFhFTI2IUcDGwol+bu6gd3RMR46id4nmuujIlSUM1YOBn5jbgE8D9wFrgjsxcHRHXR0RHvdn9wKaIWAM8CHwuMzcNV9GSpL0XmdmSHbe3t2dnZ2dL9i1J+6qIeCIz2wfzXp+0laRCGPiSVAgDX5IKYeBLUiEMfEkqhIEvSYUw8CWpEAa+JBXCwJekQhj4klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRAGviQVwsCXpEIY+JJUCANfkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAgDX5IKYeBLUiEMfEkqhIEvSYUw8CWpEAa+JBXCwJekQhj4klQIA1+SCtFQ4EfEuRGxLiLWR8TVe2h3QURkRLRXV6IkqQoDBn5EHAgsBs4DZgILI2LmLtodCnwKeLzqIiVJQ9fIEf4pwPrMfC4z3wBuAxbsot0NwFeA3grrkyRVpJHAPwp4oc98V33ZDhExF5iSmT/b04YiYlFEdEZEZ3d3914XK0kavCFftI2IA4BvAp8ZqG1mLs3M9sxsHz9+/FB3LUnaC40E/kZgSp/5yfVl/3AoMAv4dURsAE4FVnjhVpJGlkYCfxUwLSKmRsQo4GJgxT9WZuarmTkuM4/NzGOBlUBHZnYOS8WSpEEZMPAzcxvwCeB+YC1wR2aujojrI6JjuAuUJFXjoEYaZeZ9wH39ln1xN23nD70sSVLVfNJWkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAgDX5IKYeBLUiEMfEkqhIEvSYUw8CWpEAa+JBXCwJekQhj4klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRAGviQVwsCXpEIY+JJUCANfkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAgDX5IKYeBLUiEaCvyIODci1kXE+oi4ehfrr4qINRHxdET8MiKOqb5USdJQDBj4EXEgsBg4D5gJLIyImf2a/RZoz8zZwHLgq1UXKkkamkaO8E8B1mfmc5n5BnAbsKBvg8x8MDO31GdXApOrLVOSNFSNBP5RwAt95rvqy3bncuDnu1oREYsiojMiOru7uxuvUpI0ZJVetI2IS4B24Gu7Wp+ZSzOzPTPbx48fX+WuJUkDOKiBNhuBKX3mJ9eXvUlEvBO4BjgrM1+vpjxJUlUaOcJfBUyLiKkRMQq4GFjRt0FEnAR8F+jIzJerL1OSNFQDBn5mbgM+AdwPrAXuyMzVEXF9RHTUm30NGAPcGRFPRsSK3WxOktQijZzSITPvA+7rt+yLfabfWXFdkqSK+aStJBXCwJekQhj4klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRAGviQVwsCXpEIY+JJUCANfkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAgDX5IKYeBLUiEMfEkqhIEvSYUw8CWpEAa+JBXCwJekQhj4klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRAGviQVwsCXpEIY+JJUiIYCPyLOjYh1EbE+Iq7exfq3RMTt9fWPR8SxlVcqSRqSAQM/Ig4EFgPnATOBhRExs1+zy4FXMvPfgP8CvlJ1oZKkoWnkCP8UYH1mPpeZbwC3AQv6tVkAfL8+vRx4R0REdWVKkobqoAbaHAW80Ge+C3jb7tpk5raIeBU4AvhL30YRsQhYVJ99PSKeGUzR+6Fx9OurgtkXO9kXO9kXO00f7BsbCfzKZOZSYClARHRmZnsz9z9S2Rc72Rc72Rc72Rc7RUTnYN/byCmdjcCUPvOT68t22SYiDgIOAzYNtihJUvUaCfxVwLSImBoRo4CLgRX92qwAPlSfvhD4VWZmdWVKkoZqwFM69XPynwDuBw4ElmXm6oi4HujMzBXA94AfRsR64K/UPhQGsnQIde9v7Iud7Iud7Iud7IudBt0X4YG4JJXBJ20lqRAGviQVYtgD32EZdmqgL66KiDUR8XRE/DIijmlFnc0wUF/0aXdBRGRE7Le35DXSFxHxgfrvxuqIuLXZNTZLA38jR0fEgxHx2/rfyfmtqHO4RcSyiHh5d88qRc2N9X56OiLmNrThzBy2F7WLvH8A/hUYBTwFzOzX5kpgSX36YuD24aypVa8G++LfgUPq01eU3Bf1docCDwErgfZW193C34tpwG+Bf6nPH9nqulvYF0uBK+rTM4ENra57mPriTGAu8Mxu1p8P/BwI4FTg8Ua2O9xH+A7LsNOAfZGZD2bmlvrsSmrPPOyPGvm9ALiB2rhMvc0srska6YuPAosz8xWAzHy5yTU2SyN9kcDY+vRhwJ+aWF/TZOZD1O543J0FwA+yZiVweERMGmi7wx34uxqW4ajdtcnMbcA/hmXY3zTSF31dTu0TfH80YF/Uv6JOycyfNbOwFmjk9+I44LiIeCQiVkbEuU2rrrka6YvrgEsiogu4D/hkc0obcfY2T4AmD62gxkTEJUA7cFara2mFiDgA+CZwWYtLGSkOonZaZz61b30PRcRbM/N/W1lUiywEbs7Mb0TEadSe/5mVmdtbXdi+YLiP8B2WYadG+oKIeCdwDdCRma83qbZmG6gvDgVmAb+OiA3UzlGu2E8v3Dbye9EFrMjMrZn5R+D31D4A9jeN9MXlwB0AmfkY0EZtYLXSNJQn/Q134Dssw04D9kVEnAR8l1rY76/naWGAvsjMVzNzXGYem5nHUrue0ZGZgx40agRr5G/kLmpH90TEOGqneJ5rYo3N0khfPA+8AyAiZlAL/O6mVjkyrAAurd+tcyrwama+ONCbhvWUTg7fsAz7nAb74mvAGODO+nXr5zOzo2VFD5MG+6IIDfbF/cA5EbEG+Dvwuczc774FN9gXnwFuiohPU7uAe9n+eIAYET+m9iE/rn694lrgYIDMXELt+sX5wHpgC/Dhhra7H/aVJGkXfNJWkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RC/D8YimMKOgV+UwAAAABJRU5ErkJggg==\n",
34 | "text/plain": [
35 | ""
36 | ]
37 | },
38 | "metadata": {
39 | "needs_background": "light"
40 | },
41 | "output_type": "display_data"
42 | }
43 | ],
44 | "source": [
45 | "# a patch of color\n",
46 | "fig,ax = plt.subplots()\n",
47 | "ax.legend(handles=[mpatches.Patch(color=i) for i in 'rgb'],labels=['red','green','blue'])"
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": 5,
53 | "metadata": {},
54 | "outputs": [
55 | {
56 | "data": {
57 | "text/plain": [
58 | ""
59 | ]
60 | },
61 | "execution_count": 5,
62 | "metadata": {},
63 | "output_type": "execute_result"
64 | },
65 | {
66 | "data": {
67 | "image/png": "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\n",
68 | "text/plain": [
69 | ""
70 | ]
71 | },
72 | "metadata": {
73 | "needs_background": "light"
74 | },
75 | "output_type": "display_data"
76 | }
77 | ],
78 | "source": [
79 | "# Line2D\n",
80 | "fig,ax = plt.subplots()\n",
81 | "ax.legend(handles=[mlines.Line2D([],[],marker='v',linestyle='--',color=i) for i in 'rgb'],labels=['red','green','blue'])"
82 | ]
83 | },
84 | {
85 | "cell_type": "markdown",
86 | "metadata": {},
87 | "source": [
88 | "# further explanation of loc and bbox_to_anchors argument.\n",
89 | "\n",
90 | "1. there's a bounding box and a legend box \n",
91 | "2. when bbox_to_anchor is a tuple of length 4 (x0,y0,width,height), the x0,y0 always means the lower left of the bounding box. Then the loc determine how the legend box will align with the bounding box. for instance, upper left means the upper left of the bounding box and the upper left of the legend box are overlapping with each other.\n",
92 | "3. when bbox_to_anchor is a tuple of length 2 (x0,y0), the bounding box is by default a dot (width and height = 0), so it seems like the loc means the \"loc\" of the legend box itself to the (x0,y0) we just specified"
93 | ]
94 | },
95 | {
96 | "cell_type": "code",
97 | "execution_count": 9,
98 | "metadata": {},
99 | "outputs": [
100 | {
101 | "data": {
102 | "image/png": "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\n",
103 | "text/plain": [
104 | ""
105 | ]
106 | },
107 | "metadata": {
108 | "needs_background": "light"
109 | },
110 | "output_type": "display_data"
111 | },
112 | {
113 | "data": {
114 | "text/plain": [
115 | "array([[0.94347372, 0.70198675],\n",
116 | " [1.07004182, 0.92273731]])"
117 | ]
118 | },
119 | "execution_count": 9,
120 | "metadata": {},
121 | "output_type": "execute_result"
122 | }
123 | ],
124 | "source": [
125 | "# How to retrieve the width and height of the legend box\n",
126 | "fig,ax = plt.subplots()\n",
127 | "leg1 = ax.legend(handles=[mpatches.Patch(color=i) for i in 'rgb'],labels=['r','g','b'],loc='upper left',bbox_to_anchor=(1,1))\n",
128 | "plt.pause(0.01) # most importantly!!!!!! doesn't matter which matplotlib backend you are using\n",
129 | "frame = leg1.get_frame() # rectangle, actually fancyboxpath\n",
130 | "x0 = frame.get_x()\n",
131 | "y0 = frame.get_y()\n",
132 | "x1 = x0 + frame.get_width()\n",
133 | "y1 = y0 + frame.get_height()\n",
134 | "ax.transAxes.inverted().transform([[x0,y0],[x1,y1]])"
135 | ]
136 | },
137 | {
138 | "cell_type": "code",
139 | "execution_count": 5,
140 | "metadata": {},
141 | "outputs": [
142 | {
143 | "data": {
144 | "text/plain": [
145 | "array([[0.94347372, 0.70198675],\n",
146 | " [1.07004182, 0.92273731]])"
147 | ]
148 | },
149 | "execution_count": 5,
150 | "metadata": {},
151 | "output_type": "execute_result"
152 | }
153 | ],
154 | "source": [
155 | "# alternatively\n",
156 | "frame = leg1.get_frame()\n",
157 | "ax.transAxes.inverted().transform(frame.get_bbox().get_points())"
158 | ]
159 | },
160 | {
161 | "cell_type": "code",
162 | "execution_count": null,
163 | "metadata": {},
164 | "outputs": [],
165 | "source": []
166 | }
167 | ],
168 | "metadata": {
169 | "kernelspec": {
170 | "display_name": "Python 3",
171 | "language": "python",
172 | "name": "python3"
173 | },
174 | "language_info": {
175 | "codemirror_mode": {
176 | "name": "ipython",
177 | "version": 3
178 | },
179 | "file_extension": ".py",
180 | "mimetype": "text/x-python",
181 | "name": "python",
182 | "nbconvert_exporter": "python",
183 | "pygments_lexer": "ipython3",
184 | "version": "3.6.13"
185 | }
186 | },
187 | "nbformat": 4,
188 | "nbformat_minor": 4
189 | }
190 |
--------------------------------------------------------------------------------
/examples/markersize.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "markersize.ipynb",
7 | "provenance": []
8 | },
9 | "kernelspec": {
10 | "name": "python3",
11 | "display_name": "Python 3"
12 | },
13 | "language_info": {
14 | "name": "python"
15 | }
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "code",
20 | "execution_count": 1,
21 | "metadata": {
22 | "id": "ZRx1oozi3WaS"
23 | },
24 | "outputs": [],
25 | "source": [
26 | "import matplotlib as mpl\n",
27 | "import matplotlib.pyplot as plt\n",
28 | "import numpy as np\n",
29 | "import pandas as pd\n",
30 | "import os,sys"
31 | ]
32 | },
33 | {
34 | "cell_type": "markdown",
35 | "source": [
36 | "When plotting using `ax.scatter`, the `s` parameter is different from `markersize` parameter when using `ax.plot`, the former should be `markersize**2`, detailed explanation can be found at (https://stackoverflow.com/questions/14827650/pyplot-scatter-plot-marker-size#:~:text=So%20far%20the%20answer%20to,is%20hence%201%2F72%20inches.).\n",
37 | "\n",
38 | "But a more confusing thing is, the unit of the `s` or `markersize` is not the data unit shouwn in the axes or data, instead of, it represents the number of `points`. This notebook aims to illustrate what it is and how to specify `s` based on how many data units I want it to occupy (like, I want a dot occupy 2 data units)."
39 | ],
40 | "metadata": {
41 | "id": "nnJyM5oy4G4f"
42 | }
43 | },
44 | {
45 | "cell_type": "code",
46 | "source": [
47 | "def to_point_unit(s,fig,ax,xlim,ylim,scatter=True):\n",
48 | " # s means how many data units you want the marker to occupy\n",
49 | " ppi = 72 # matplotlib default point per inch is 72\n",
50 | " dpi = fig.dpi # matplotlib default dot/pixel per inch is 100\n",
51 | " ax.set_xlim(xlim)\n",
52 | " ax.set_ylim(ylim)\n",
53 | " fig.canvas.draw() # or using plt.pause(0.01)\n",
54 | " one_data_unit_to_one_display_unit = ax.get_window_extent().width/ (xlim[1]-xlim[0]) # display unit = pixel\n",
55 | " one_display_unit_to_one_point_unit = ppi / dpi\n",
56 | " one_data_unit_to_one_point_unit = one_data_unit_to_one_display_unit * one_display_unit_to_one_point_unit\n",
57 | " s_point_unit = one_data_unit_to_one_point_unit * s\n",
58 | " if scatter:\n",
59 | " s_point_unit = s_point_unit ** 2\n",
60 | " return s_point_unit"
61 | ],
62 | "metadata": {
63 | "id": "QtOLm9Ck5E1q"
64 | },
65 | "execution_count": 2,
66 | "outputs": []
67 | },
68 | {
69 | "cell_type": "code",
70 | "source": [
71 | "fig, ax = plt.subplots()\n",
72 | "s = 1\n",
73 | "sp = to_point_unit(s,fig,ax,(0,10),(0,10),True)\n",
74 | "ax.scatter([4],[4],s=sp)"
75 | ],
76 | "metadata": {
77 | "colab": {
78 | "base_uri": "https://localhost:8080/",
79 | "height": 287
80 | },
81 | "id": "LByB3AEQ5zLY",
82 | "outputId": "af297ff2-2571-4822-8f34-7284cfacd281"
83 | },
84 | "execution_count": 3,
85 | "outputs": [
86 | {
87 | "output_type": "execute_result",
88 | "data": {
89 | "text/plain": [
90 | ""
91 | ]
92 | },
93 | "metadata": {},
94 | "execution_count": 3
95 | },
96 | {
97 | "output_type": "display_data",
98 | "data": {
99 | "text/plain": [
100 | ""
101 | ],
102 | "image/png": "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\n"
103 | },
104 | "metadata": {
105 | "needs_background": "light"
106 | }
107 | }
108 | ]
109 | }
110 | ]
111 | }
--------------------------------------------------------------------------------
/examples/stacked_legends.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 18,
6 | "id": "94d19fcb-254d-42fa-ac2e-2ed38cf1b5c7",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "%matplotlib inline\n",
11 | "import numpy as np\n",
12 | "import pandas as pd\n",
13 | "import matplotlib.pyplot as plt\n",
14 | "import matplotlib as mpl\n",
15 | "import matplotlib.patches as mpatches"
16 | ]
17 | },
18 | {
19 | "cell_type": "code",
20 | "execution_count": 19,
21 | "id": "f7a50d61-a10e-4f4c-9a59-bbb2418964c3",
22 | "metadata": {},
23 | "outputs": [
24 | {
25 | "data": {
26 | "text/plain": [
27 | "'module://ipykernel.pylab.backend_inline'"
28 | ]
29 | },
30 | "execution_count": 19,
31 | "metadata": {},
32 | "output_type": "execute_result"
33 | }
34 | ],
35 | "source": [
36 | "mpl.get_backend()"
37 | ]
38 | },
39 | {
40 | "cell_type": "code",
41 | "execution_count": 20,
42 | "id": "892f8086-457e-4d41-b21c-24f969d64ca0",
43 | "metadata": {},
44 | "outputs": [],
45 | "source": [
46 | "mpl.use('MacOSX')"
47 | ]
48 | },
49 | {
50 | "cell_type": "code",
51 | "execution_count": 21,
52 | "id": "0d51fd25-2f23-4b87-acd6-e8d27c0dc96d",
53 | "metadata": {},
54 | "outputs": [],
55 | "source": [
56 | "def get_location_of_legend_box(leg_artist):\n",
57 | " frame = leg_artist.get_frame()\n",
58 | " x0 = frame.get_x()\n",
59 | " y0 = frame.get_y()\n",
60 | " x1 = x0 + frame.get_width()\n",
61 | " y1 = y0 + frame.get_height()\n",
62 | " ax_box_coord = ax.transAxes.inverted().transform([[x0, y0], [x1, y1]])\n",
63 | " width = ax_box_coord[1, 0] - ax_box_coord[0, 0]\n",
64 | " height = ax_box_coord[1, 1] - ax_box_coord[0, 1]\n",
65 | " lowest_point = ax_box_coord[0, 1]\n",
66 | " farthest_point = ax_box_coord[1, 0]\n",
67 | " return width,height,lowest_point,farthest_point\n",
68 | "\n",
69 | "def arrange_legend_boxs(legs_hl_list,ax):\n",
70 | " current_lowest_point = 1\n",
71 | " current_farthest_point = 1\n",
72 | " last_farthest_point = None\n",
73 | " have_legend_in_the_column = False\n",
74 | " ready_legend_artist = []\n",
75 | " for item in legs_hl_list:\n",
76 | " leg_artist = ax.legend(handles=item[0],labels=item[1],loc='upper left',bbox_to_anchor=(current_farthest_point,current_lowest_point))\n",
77 | " plt.pause(0.01)\n",
78 | " width,height,lowest_point,farthest_point = get_location_of_legend_box(leg_artist)\n",
79 | " if have_legend_in_the_column:\n",
80 | " if lowest_point < 0:\n",
81 | " current_farthest_point = max([last_farthest_point,farthest_point])\n",
82 | " leg_artist = ax.legend(handles=item[0],labels=item[1],loc='upper left',bbox_to_anchor=(current_farthest_point,1))\n",
83 | " plt.pause(0.01)\n",
84 | " width, height, lowest_point, farthest_point = get_location_of_legend_box(leg_artist)\n",
85 | " current_lowest_point = lowest_point\n",
86 | " last_farthest_point = farthest_point\n",
87 | " ready_legend_artist.append(leg_artist)\n",
88 | " have_legend_in_the_column = True\n",
89 | "\n",
90 | " for artist in ready_legend_artist:\n",
91 | " ax.add_artist(artist)"
92 | ]
93 | },
94 | {
95 | "cell_type": "code",
96 | "execution_count": 22,
97 | "id": "a1d2f956-7f70-4883-b758-11cee07ed0c4",
98 | "metadata": {},
99 | "outputs": [
100 | {
101 | "data": {
102 | "image/png": "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+a5rJNi5c2d00aJFBcXFxYUFBQWFV1xxReHGjRvz0/mahFIAAAAAWePAgQOja2pqqlpaWvLuvPPOI4sXLz62e/fusbfddtuM559/frzv+oazAwcOWE1NzeiWlha74447EosXL3b/8R//oT/5kz/Jf/7559MWTAmlAAAAALJGQ0NDbOnSpZ83NDTse+655z7duHHj/vr6+r1m5h588MELjx49SoZJk4aGBi1dujTR0NDQ/pOf/OTUxo0bO+rr60+bmR588MH85uYBzV87aPxAAQAAAGSNWCwWrF69+lDPdQsWLGivra092traGq2rq2O0NE1isZhWr159que6BQsWBLW1ta61tVX//M//PCodr0soBQAAAJA1Zs+e3T5+/PhE7/U1NTWtkrRz586cuH9oLpo9e7bGjz8789fU1ASStHPnzrTkR0IpAAAAgKxRVlbWea71U6ZM6ZSkEydORDNb0cgxceJEd671F1xwgZOkEydO9Hlrz6EglAIAAADIGkeOHDnnhDqHDh3Kl6Rx48YFma1o5Pj888/PGTo/++wzk6Rx48adM7QOFaEUAAAAQNbYvXt34bFjx87KKdu3by+SpMsvv7w981WNDLt379axY8fOWr99+/aoJF1++eVnnVYdBkIpAAAAgKzR1tYWfeihh6b0XPfmm28Wbt68uTQWiwV33HHH2akJoWhra9NDDz00pue6N998M7p582aLxWL60z/90zPpeN28dHQKAAAAAOdjzpw5bevXr58Yj8fHzp07t62xsTF/y5Ytpc45e+qppz4uLS1Ny2gdpDlz5mj9+vWReDxe+O1vfzvR1NRkW7ZsMeecnnrqqc4JEyak5XUZKQUAAACQNaZNm3Z627Zte4uLi7vWrVtX9sorr4yfNWtW+4svvvjB8uXLGSVNo2nTprlt27adLi4udj//+c8jW7ZssUsuuUT/8i//0rl8+fJzTkAVBkZKAQAAAHg3c+bMM865ePe/X3/99Q991jOSVFVVJZxzX1yr+/rrr3dk8vUJpQAAAECWck7x/p+FdHBOTKiUIZy+CwAAAADwhlAKAAAAAPCGUAoAAAAA8IZQCgAAAADwhlAKAAAAAPCGUAoAAABgWHDO+S5hxEokEue9LaEUAAAA8KdTkguCgM/lIUgkEhFJTtKZgTxdkrq6utJa00jRI5QGg92Wgx8AAADw56NEItHR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\n",
103 | "text/plain": [
104 | ""
105 | ]
106 | },
107 | "metadata": {
108 | "needs_background": "light"
109 | },
110 | "output_type": "display_data"
111 | }
112 | ],
113 | "source": [
114 | "## test\n",
115 | "leg1_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n",
116 | "leg2_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n",
117 | "leg3_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n",
118 | "leg4_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n",
119 | "leg5_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n",
120 | "leg6_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n",
121 | "fig,ax = plt.subplots()\n",
122 | "arrange_legend_boxs([leg1_hl,leg2_hl,leg3_hl,leg4_hl,leg5_hl,leg6_hl],ax)"
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "execution_count": null,
128 | "id": "1c7822df-c047-47de-bf94-0eb8ebf7ffb7",
129 | "metadata": {},
130 | "outputs": [],
131 | "source": []
132 | },
133 | {
134 | "cell_type": "code",
135 | "execution_count": null,
136 | "id": "012ae3fb-11ef-44ab-82c0-853716c5174a",
137 | "metadata": {},
138 | "outputs": [],
139 | "source": []
140 | }
141 | ],
142 | "metadata": {
143 | "kernelspec": {
144 | "display_name": "Python 3",
145 | "language": "python",
146 | "name": "python3"
147 | },
148 | "language_info": {
149 | "codemirror_mode": {
150 | "name": "ipython",
151 | "version": 3
152 | },
153 | "file_extension": ".py",
154 | "mimetype": "text/x-python",
155 | "name": "python",
156 | "nbconvert_exporter": "python",
157 | "pygments_lexer": "ipython3",
158 | "version": "3.6.13"
159 | }
160 | },
161 | "nbformat": 4,
162 | "nbformat_minor": 5
163 | }
164 |
--------------------------------------------------------------------------------
/examples/yaxis_tick_on_right.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 4,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "%matplotlib inline\n",
10 | "import matplotlib\n",
11 | "import matplotlib.pyplot as plt\n",
12 | "import numpy as np"
13 | ]
14 | },
15 | {
16 | "cell_type": "code",
17 | "execution_count": 5,
18 | "metadata": {},
19 | "outputs": [
20 | {
21 | "data": {
22 | "image/png": "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\n",
23 | "text/plain": [
24 | ""
25 | ]
26 | },
27 | "metadata": {
28 | "needs_background": "light"
29 | },
30 | "output_type": "display_data"
31 | }
32 | ],
33 | "source": [
34 | "fig,ax = plt.subplots()\n",
35 | "ax.set_yticks(np.arange(10))\n",
36 | "ax.set_yticklabels(np.arange(10))\n",
37 | "ax.yaxis.set_label_position('right')\n",
38 | "ax.yaxis.tick_right()"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 7,
44 | "metadata": {},
45 | "outputs": [
46 | {
47 | "data": {
48 | "image/png": "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\n",
49 | "text/plain": [
50 | ""
51 | ]
52 | },
53 | "metadata": {
54 | "needs_background": "light"
55 | },
56 | "output_type": "display_data"
57 | }
58 | ],
59 | "source": [
60 | "fig,ax = plt.subplots()\n",
61 | "ax1 = ax.twinx()"
62 | ]
63 | },
64 | {
65 | "cell_type": "code",
66 | "execution_count": null,
67 | "metadata": {},
68 | "outputs": [],
69 | "source": []
70 | }
71 | ],
72 | "metadata": {
73 | "kernelspec": {
74 | "display_name": "Python 3",
75 | "language": "python",
76 | "name": "python3"
77 | },
78 | "language_info": {
79 | "codemirror_mode": {
80 | "name": "ipython",
81 | "version": 3
82 | },
83 | "file_extension": ".py",
84 | "mimetype": "text/x-python",
85 | "name": "python",
86 | "nbconvert_exporter": "python",
87 | "pygments_lexer": "ipython3",
88 | "version": "3.6.12"
89 | }
90 | },
91 | "nbformat": 4,
92 | "nbformat_minor": 4
93 | }
94 |
--------------------------------------------------------------------------------
/plotly/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | public_html
5 |
6 |
7 |
8 |
9 |
10 |
11 | Hello world!
12 |
13 |
--------------------------------------------------------------------------------
/plotly/network.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/plotly/plotly.py:
--------------------------------------------------------------------------------
1 | import networkx as nx
2 | import pandas as pd
3 |
4 | # convert pandas edgelist or adjancencym matrix to network graph object
5 | df1 = pd.DataFrame({'source':['node1','node1','node2'],'target':['node2','node3','node3'],'weight':[4.5,4.5,4.5],
6 | 'color':['blue','green','blue']}). # edge list
7 | df2 = pd.DataFrame(data=[[0,4.5,4.5],[0,0,4.5],[0,0,0]],index=['node1','node2','node3'],columns=['node1','node2','node3']) # adjacency
8 | G1 = nx.from_pandas_edgelist(df1,source='source',target='target',edge_attr='weight',create_using=nx.Graph)
9 | G2 = nx.from_pandas_adjacency(df2,create_using=nx.Graph)
10 |
11 | # nodes anatomy
12 | type(G1.nodes())
13 | # networkx.classes.reportviews.NodeView
14 | list(G1.nodes())
15 | # ['node1', 'node2', 'node3']
16 | type(G1.nodes(data=True))
17 | # networkx.classes.reportviews.NodeDataView
18 | list(G1.nodes(data=True))
19 | # [('node1', {}), ('node2', {}), ('node3', {})]
20 | G1.nodes['node1']
21 | # {}
22 |
23 |
24 | # edges anatomy
25 | type(G1.edges())
26 | # networkx.classes.reportviews.EdgeView
27 | list(G1.edges())
28 | # [('node1', 'node2'), ('node1', 'node3'), ('node2', 'node3')]
29 | type(G1.edges(data=True))
30 | # networkx.classes.reportviews.EdgeDataView
31 | list(G1.edges(data=True))
32 | # [('node1', 'node2', {'weight': 4.5}),
33 | # ('node1', 'node3', {'weight': 4.5}),
34 | # ('node2', 'node3', {'weight': 4.5})]
35 | G1.edges[('node1','node2')]
36 | # {'weight': 4.5}
37 |
38 |
39 | # set and get attributes
40 | ## node
41 | node_color_dict = {'node1':'green','node2':'blue','node3':'red'}
42 | nx.set_node_attributes(G1,node_color_dict,'color')
43 | list(G1.nodes(data=True))
44 | # [('node1', {'color': 'green'}),
45 | # ('node2', {'color': 'blue'}),
46 | # ('node3', {'color': 'red'})]
47 | ## edge
48 | nx.get_edge_attributes(G1,'weight')
49 | # {('node1', 'node2'): 4.5, ('node1', 'node3'): 4.5, ('node2', 'node3'): 4.5}
50 |
51 |
52 | import plotly.graph_objects as go
53 | ## step1: compute the graph layout (coordinates of nodes in 2D)
54 | coords_dict = nx.spring_layout(G1,seed=42)
55 | # {'node1': array([-0.33486468, 0.96136632]),
56 | # 'node2': array([ 1. , -0.19068184]),
57 | # 'node3': array([-0.66513532, -0.77068448])}
58 | ## step2: set the dictionary as the attribute of the node
59 | nx.set_node_attributes(G1,coords_dict,'coord')
60 | ## step3: validate
61 | G1.nodes['node1']
62 | #{'color': 'green', 'coord': array([-0.33486468, 0.96136632])}
63 |
64 |
65 | node_x = [] # store x coordinates
66 | node_y = [] # store y coordinates
67 | node_text = [] # store text when mouse hovers over the node
68 | for node,node_attr_dict in G1.nodes(data=True): # recall anatomy
69 | x,y = node_attr_dict['coord']
70 | node_x.append(x)
71 | node_y.append(y)
72 | node_text.append(node)
73 | node_trace = go.Scatter(name='nodes',x=node_x,y=node_y,mode='markers',hoverinfo='text',text=node_text,marker={'color':'green','size':5})
74 |
75 | edge_x = []
76 | edge_y = []
77 | for edge_end1,edge_end2,edge_attr_dict in G1.edges(data=True):
78 | x0,y0 = G1.nodes[edge_end1]['coord']
79 | x1,y1 = G1.nodes[edge_end2]['coord']
80 | x2,y2 = None,None
81 | for x,y in zip([x0,x1,x2],[y0,y1,y2]):
82 | edge_x.append(x)
83 | edge_y.append(y)
84 | edge_trace = go.Scatter(name='lines',x=edge_x,y=edge_y,mode='lines',line=go.scatter.Line(color='black',width=2))
85 |
86 |
87 | fig_layout = go.Layout(showlegend=True,title='network',xaxis=dict(title_text='coordinate x'))
88 | fig = go.Figure(data=[node_trace,edge_trace],layout=fig_layout)
89 | fig.write_html('./network.html',include_plotlyjs='cdn')
90 |
91 |
92 |
--------------------------------------------------------------------------------
/rcParams.txt:
--------------------------------------------------------------------------------
1 | _internal.classic_mode
2 | agg.path.chunksize
3 | animation.avconv_args
4 | animation.avconv_path
5 | animation.bitrate
6 | animation.codec
7 | animation.convert_args
8 | animation.convert_path
9 | animation.embed_limit
10 | animation.ffmpeg_args
11 | animation.ffmpeg_path
12 | animation.frame_format
13 | animation.html
14 | animation.html_args
15 | animation.writer
16 | axes.autolimit_mode
17 | axes.axisbelow
18 | axes.edgecolor
19 | axes.facecolor
20 | axes.formatter.limits
21 | axes.formatter.min_exponent
22 | axes.formatter.offset_threshold
23 | axes.formatter.use_locale
24 | axes.formatter.use_mathtext
25 | axes.formatter.useoffset
26 | axes.grid
27 | axes.grid.axis
28 | axes.grid.which
29 | axes.labelcolor
30 | axes.labelpad
31 | axes.labelsize
32 | axes.labelweight
33 | axes.linewidth
34 | axes.prop_cycle
35 | axes.spines.bottom
36 | axes.spines.left
37 | axes.spines.right
38 | axes.spines.top
39 | axes.titlecolor
40 | axes.titlelocation
41 | axes.titlepad
42 | axes.titlesize
43 | axes.titleweight
44 | axes.titley
45 | axes.unicode_minus
46 | axes.xmargin
47 | axes.ymargin
48 | axes3d.grid
49 | backend
50 | backend_fallback
51 | boxplot.bootstrap
52 | boxplot.boxprops.color
53 | boxplot.boxprops.linestyle
54 | boxplot.boxprops.linewidth
55 | boxplot.capprops.color
56 | boxplot.capprops.linestyle
57 | boxplot.capprops.linewidth
58 | boxplot.flierprops.color
59 | boxplot.flierprops.linestyle
60 | boxplot.flierprops.linewidth
61 | boxplot.flierprops.marker
62 | boxplot.flierprops.markeredgecolor
63 | boxplot.flierprops.markeredgewidth
64 | boxplot.flierprops.markerfacecolor
65 | boxplot.flierprops.markersize
66 | boxplot.meanline
67 | boxplot.meanprops.color
68 | boxplot.meanprops.linestyle
69 | boxplot.meanprops.linewidth
70 | boxplot.meanprops.marker
71 | boxplot.meanprops.markeredgecolor
72 | boxplot.meanprops.markerfacecolor
73 | boxplot.meanprops.markersize
74 | boxplot.medianprops.color
75 | boxplot.medianprops.linestyle
76 | boxplot.medianprops.linewidth
77 | boxplot.notch
78 | boxplot.patchartist
79 | boxplot.showbox
80 | boxplot.showcaps
81 | boxplot.showfliers
82 | boxplot.showmeans
83 | boxplot.vertical
84 | boxplot.whiskerprops.color
85 | boxplot.whiskerprops.linestyle
86 | boxplot.whiskerprops.linewidth
87 | boxplot.whiskers
88 | contour.corner_mask
89 | contour.linewidth
90 | contour.negative_linestyle
91 | date.autoformatter.day
92 | date.autoformatter.hour
93 | date.autoformatter.microsecond
94 | date.autoformatter.minute
95 | date.autoformatter.month
96 | date.autoformatter.second
97 | date.autoformatter.year
98 | date.epoch
99 | docstring.hardcopy
100 | errorbar.capsize
101 | figure.autolayout
102 | figure.constrained_layout.h_pad
103 | figure.constrained_layout.hspace
104 | figure.constrained_layout.use
105 | figure.constrained_layout.w_pad
106 | figure.constrained_layout.wspace
107 | figure.dpi
108 | figure.edgecolor
109 | figure.facecolor
110 | figure.figsize
111 | figure.frameon
112 | figure.max_open_warning
113 | figure.raise_window
114 | figure.subplot.bottom
115 | figure.subplot.hspace
116 | figure.subplot.left
117 | figure.subplot.right
118 | figure.subplot.top
119 | figure.subplot.wspace
120 | figure.titlesize
121 | figure.titleweight
122 | font.cursive
123 | font.family
124 | font.fantasy
125 | font.monospace
126 | font.sans-serif
127 | font.serif
128 | font.size
129 | font.stretch
130 | font.style
131 | font.variant
132 | font.weight
133 | grid.alpha
134 | grid.color
135 | grid.linestyle
136 | grid.linewidth
137 | hatch.color
138 | hatch.linewidth
139 | hist.bins
140 | image.aspect
141 | image.cmap
142 | image.composite_image
143 | image.interpolation
144 | image.lut
145 | image.origin
146 | image.resample
147 | interactive
148 | keymap.all_axes
149 | keymap.back
150 | keymap.copy
151 | keymap.forward
152 | keymap.fullscreen
153 | keymap.grid
154 | keymap.grid_minor
155 | keymap.help
156 | keymap.home
157 | keymap.pan
158 | keymap.quit
159 | keymap.quit_all
160 | keymap.save
161 | keymap.xscale
162 | keymap.yscale
163 | keymap.zoom
164 | legend.borderaxespad
165 | legend.borderpad
166 | legend.columnspacing
167 | legend.edgecolor
168 | legend.facecolor
169 | legend.fancybox
170 | legend.fontsize
171 | legend.framealpha
172 | legend.frameon
173 | legend.handleheight
174 | legend.handlelength
175 | legend.handletextpad
176 | legend.labelspacing
177 | legend.loc
178 | legend.markerscale
179 | legend.numpoints
180 | legend.scatterpoints
181 | legend.shadow
182 | legend.title_fontsize
183 | lines.antialiased
184 | lines.color
185 | lines.dash_capstyle
186 | lines.dash_joinstyle
187 | lines.dashdot_pattern
188 | lines.dashed_pattern
189 | lines.dotted_pattern
190 | lines.linestyle
191 | lines.linewidth
192 | lines.marker
193 | lines.markeredgecolor
194 | lines.markeredgewidth
195 | lines.markerfacecolor
196 | lines.markersize
197 | lines.scale_dashes
198 | lines.solid_capstyle
199 | lines.solid_joinstyle
200 | markers.fillstyle
201 | mathtext.bf
202 | mathtext.cal
203 | mathtext.default
204 | mathtext.fallback
205 | mathtext.fallback_to_cm
206 | mathtext.fontset
207 | mathtext.it
208 | mathtext.rm
209 | mathtext.sf
210 | mathtext.tt
211 | mpl_toolkits.legacy_colorbar
212 | patch.antialiased
213 | patch.edgecolor
214 | patch.facecolor
215 | patch.force_edgecolor
216 | patch.linewidth
217 | path.effects
218 | path.simplify
219 | path.simplify_threshold
220 | path.sketch
221 | path.snap
222 | pcolor.shading
223 | pdf.compression
224 | pdf.fonttype
225 | pdf.inheritcolor
226 | pdf.use14corefonts
227 | pgf.preamble
228 | pgf.rcfonts
229 | pgf.texsystem
230 | polaraxes.grid
231 | ps.distiller.res
232 | ps.fonttype
233 | ps.papersize
234 | ps.useafm
235 | ps.usedistiller
236 | savefig.bbox
237 | savefig.directory
238 | savefig.dpi
239 | savefig.edgecolor
240 | savefig.facecolor
241 | savefig.format
242 | savefig.jpeg_quality
243 | savefig.orientation
244 | savefig.pad_inches
245 | savefig.transparent
246 | scatter.edgecolors
247 | scatter.marker
248 | svg.fonttype
249 | svg.hashsalt
250 | svg.image_inline
251 | text.antialiased
252 | text.color
253 | text.hinting
254 | text.hinting_factor
255 | text.kerning_factor
256 | text.latex.preamble
257 | text.latex.preview
258 | text.usetex
259 | timezone
260 | tk.window_focus
261 | toolbar
262 | webagg.address
263 | webagg.open_in_browser
264 | webagg.port
265 | webagg.port_retries
266 | xaxis.labellocation
267 | xtick.alignment
268 | xtick.bottom
269 | xtick.color
270 | xtick.direction
271 | xtick.labelbottom
272 | xtick.labelsize
273 | xtick.labeltop
274 | xtick.major.bottom
275 | xtick.major.pad
276 | xtick.major.size
277 | xtick.major.top
278 | xtick.major.width
279 | xtick.minor.bottom
280 | xtick.minor.pad
281 | xtick.minor.size
282 | xtick.minor.top
283 | xtick.minor.visible
284 | xtick.minor.width
285 | xtick.top
286 | yaxis.labellocation
287 | ytick.alignment
288 | ytick.color
289 | ytick.direction
290 | ytick.labelleft
291 | ytick.labelright
292 | ytick.labelsize
293 | ytick.left
294 | ytick.major.left
295 | ytick.major.pad
296 | ytick.major.right
297 | ytick.major.size
298 | ytick.major.width
299 | ytick.minor.left
300 | ytick.minor.pad
301 | ytick.minor.right
302 | ytick.minor.size
303 | ytick.minor.visible
304 | ytick.minor.width
305 | ytick.right
306 |
--------------------------------------------------------------------------------
/sankey/Sankey_tutorial.py:
--------------------------------------------------------------------------------
1 |
2 | import pandas as pd
3 | import matplotlib.pyplot as plt
4 | import numpy as np
5 | from matplotlib.path import Path
6 | from matplotlib.patches import PathPatch, Rectangle
7 |
8 | # draw the canvas and ax
9 | fig,ax = plt.subplots()
10 | ax.set_xlim([0,1])
11 | ax.set_ylim([0,1])
12 | ax.grid()
13 |
14 | # draw the recs
15 | rec_left = Rectangle(xy=(0.1,0.6),width=0.2,height=0.2,facecolor='orange',edgecolor='k')
16 | ax.add_patch(rec_left)
17 | rec_right = Rectangle(xy=(0.7,0.2),width=0.2,height=0.2,facecolor='green',edgecolor='k')
18 | ax.add_patch(rec_right)
19 |
20 | # demo the path object logics
21 | verts = [(0.3,0.8),(0.5,0.8),(0.7,0.4),(0.3,0.6),(0.3,0.8)]
22 | codes = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY]
23 | p = Path(verts,codes)
24 | ax.add_patch(PathPatch(p,fc='none'))
25 |
26 | # method1, Path, demo the curve4 logics
27 | verts = [(0.3,0.8), (0.5,0.8), (0.5,0.4), (0.7,0.4)]
28 | codes = [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4]
29 | p = Path(verts,codes)
30 | ax.add_patch(PathPatch(p,fc='none',alpha=0.6))
31 |
32 | # method1, path
33 | verts = [(0.3,0.8), (0.5,0.8), (0.5,0.4), (0.7,0.4), (0.7,0.2), (0.5,0.2), (0.5,0.6), (0.3,0.6), (0.3,0.8)]
34 | codes = [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4, Path.LINETO, Path.CURVE4, Path.CURVE4, Path.CURVE4, Path.CLOSEPOLY]
35 | p = Path(verts,codes)
36 | ax.add_patch(PathPatch(p,fc='red',alpha=0.6))
37 |
38 | # method2, convolve
39 | yu = np.array(50*[0.8] + 50*[0.4])
40 | yu_c = np.convolve(yu, 0.05*np.ones(20),mode='valid')
41 | yu_cc = np.convolve(yu_c, 0.05*np.ones(20),mode='valid')
42 | yd = np.array(50*[0.6] + 50*[0.2])
43 | yd_c = np.convolve(yd, 0.05*np.ones(20),mode='valid')
44 | yd_cc = np.convolve(yd_c, 0.05*np.ones(20),mode='valid')
45 | ax.fill_between(np.linspace(0.3,0.7,62),yd_cc,yu_cc,color='blue',alpha=0.6)
--------------------------------------------------------------------------------
/sankey/sankey_tutorial.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frankligy/python_visualization_tutorial/1ac56c55a7e7f317296cffc98dc43014df57a77f/sankey/sankey_tutorial.pptx
--------------------------------------------------------------------------------
/sankey/sankey_tutorial_bezier.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frankligy/python_visualization_tutorial/1ac56c55a7e7f317296cffc98dc43014df57a77f/sankey/sankey_tutorial_bezier.ai
--------------------------------------------------------------------------------
/tutorial3_boxplot_etc.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | import matplotlib.pyplot as plt
3 | from matplotlib.colors import ListedColormap
4 |
5 | mpl.rcParams['pdf.fonttype'] = 42
6 | mpl.rcParams['ps.fonttype'] = 42
7 | mpl.rcParams['font.family'] = 'Arial'
8 |
9 | import numpy as np
10 |
11 | np.random.seed(42)
12 | data1 = np.random.randn(100)
13 | data2 = np.random.randn(100)
14 | data3 = np.random.randn(100)
15 |
16 | fig,ax = plt.subplots()
17 | bp = ax.boxplot(x=[data1,data2,data3],positions=[1,5,7],patch_artist=True)
18 | for flier in bp['fliers']:
19 | flier.set_markersize(9)
20 | flier.set_marker('v')
21 | for box in bp['boxes']:
22 | box.set_facecolor('green')
23 | box.set_edgecolor('black')
24 | box.set_linewidth(2)
25 | for whisker in bp['whiskers']:
26 | whisker.set_linewidth(5)
27 | for cap in bp['caps']:
28 | cap.set_color('red')
29 | cap.set_linewidth(10)
30 | for median in bp['medians']:
31 | median.set_linewidth(15)
32 |
33 |
34 | fig,ax = plt.subplots()
35 | ax.bar(x=[1,4,9],height=(data1.max(),data2.max(),data3.max()),width=0.5,edgecolor='black',color=['green','red','orange'],
36 | yerr=np.array([[0.1,0.1,0.1],[0.15,0.15,0.15]]),ecolor='red',capsize=5)
37 |
38 |
39 | fig,ax = plt.subplots()
40 | ax.hist(x=[data1,data2],bins=20,edgecolor='black')
41 |
42 | fig,ax = plt.subplots()
43 | ax.scatter(x=np.arange(10),y=np.arange(10)+5,s=np.arange(10)*10,c=np.random.rand(10),cmap='spring')
44 | ax.scatter(x=[1,2,3],y=[1,2,3],s=[100,200,300],c=['r','g','b'])
45 |
46 |
47 |
48 | fig,ax = plt.subplots()
49 | ax.imshow(np.random.randn(5,5),cmap='Set1')
50 | ax.set_xticks(np.linspace(0.5,3.5,4))
51 | ax.set_yticks(np.linspace(0.5,3.5,4))
52 | ax.tick_params(axis='both',length=0,labelsize=0)
53 | ax.grid(b=True,which='major',axis='both',color='black')
54 | ax.text(-0.2,3,'hey')
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/tutorial5_seaborn.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | import matplotlib.pyplot as plt
3 | from matplotlib.colors import ListedColormap
4 |
5 | mpl.rcParams['pdf.fonttype'] = 42
6 | mpl.rcParams['ps.fonttype'] = 42
7 | mpl.rcParams['font.family'] = 'Arial'
8 |
9 | import numpy as np
10 |
11 | np.random.seed(42)
12 | data1 = np.random.randn(100)
13 | data2 = np.random.randn(100)
14 | data3 = np.random.randn(100)
15 |
16 | import seaborn as sns
17 | import pandas as pd
18 |
19 | # prepare datasets
20 |
21 | penguin = sns.load_dataset('penguins') # long form
22 | synthesis = pd.DataFrame({'var1':data1,'var2':data2,'var3':data3}) # wideform
23 | a = synthesis.stack().reset_index(-1)
24 |
25 | # distribution plot
26 |
27 | fig,ax = plt.subplots()
28 | sns.histplot(data=penguin,kde=True,stat='frequency',x='bill_length_mm',hue='species',multiple='layer',
29 | kde_kws={'bw_adjust':5},line_kws={'linewidth':7},palette='Set2',ax=ax)
30 | sns.rugplot(data=penguin,x='bill_length_mm',hue='species',ax=ax)
31 | sns.histplot(data=synthesis,kde=True,stat='density',common_norm=False,hue_order=['var2','var1','var3'],
32 | multiple='layer')
33 |
34 |
35 | sns.kdeplot(data=penguin,x='bill_length_mm',hue='species',clip=(35,100))
36 | sns.rugplot(data=penguin,x='bill_length_mm',hue='species')
37 |
38 |
39 |
40 | # categorical plot
41 | sns.violinplot(data=penguin,x='species',y='bill_length_mm',hue='sex',split=True,bw=0.2,inner='quartile',scale_hue=True,
42 | scale='count')
43 |
44 |
45 |
46 | sns.swarmplot(data=penguin,x='species',y='bill_length_mm',hue='sex',dodge=True)
47 |
48 | sns.pointplot(data=penguin,x='species',y='bill_length_mm',hue='sex')
49 |
50 | # regression plot
51 | sns.regplot(data=penguin,x='bill_length_mm',y='bill_depth_mm')
52 |
53 | # matrix plot
54 | sns.heatmap(data=synthesis.iloc[0:5,:],annot=True,linewidths=0.5,square=True,yticklabels=False)
55 | mask = np.array([[0,0,0],
56 | [0,0,0],
57 | [0,1,0],
58 | [0,0,0],
59 | [0,0,0]])
60 | sns.heatmap(data=synthesis.iloc[0:5,:],annot=True,linewidths=0.5,square=True,yticklabels=False,mask=mask)
61 |
62 |
63 | row_cb = pd.DataFrame(data=np.random.choice(['r','g','b','m'],(100,2)),index=np.arange(100),columns=['hey','ha'])
64 | sns.clustermap(data=synthesis,row_colors=row_cb)
65 |
66 |
67 | # pair plot and joint plot
68 | sns.pairplot(data=penguin.iloc[:,[2,3,4,5]],dropna=True)
69 | sns.jointplot(data=penguin,x='bill_length_mm',y='bill_depth_mm',kind='reg')
70 |
71 |
72 |
--------------------------------------------------------------------------------
/tutorial_4_violin_dendrogram.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | import matplotlib.pyplot as plt
3 | from matplotlib.colors import ListedColormap
4 |
5 | mpl.rcParams['pdf.fonttype'] = 42
6 | mpl.rcParams['ps.fonttype'] = 42
7 | mpl.rcParams['font.family'] = 'Arial'
8 |
9 | import numpy as np
10 |
11 | np.random.seed(42)
12 | data1 = np.random.randn(100)
13 | data2 = np.random.randn(100)
14 | data3 = np.random.randn(100)
15 |
16 | dataset = [data1,data2,data3]
17 | positions = [1,5,7]
18 | fig,ax = plt.subplots()
19 | vp = ax.violinplot(dataset=dataset,positions=[1,5,7])
20 |
21 | for body in vp['bodies']:
22 | body.set_facecolor('red')
23 | body.set_edgecolor('black')
24 | body.set_alpha(1)
25 | vp['cmaxes'].set_color('black')
26 | vp['cmins'].set_color('black')
27 | vp['cbars'].set_color('black')
28 |
29 | tmp = [np.percentile(data,[25,50,75]) for data in dataset]
30 |
31 | def get_whisker(tmp,dataset):
32 | whisker = []
33 | for quantile,data in zip(tmp,dataset):
34 | data = np.array(data)
35 | q1 = quantile[0]
36 | median = quantile[1]
37 | q3 = quantile[2]
38 | iqr = q3 - q1
39 | upper = q3 + 1.5 * iqr
40 | upper = np.clip(upper,q3,data.max())
41 | lower = q1 - 1.5 * iqr
42 | lower = np.clip(lower,data.min(),q1)
43 | whisker.append((upper,lower))
44 | return whisker
45 |
46 | whisker = get_whisker(tmp,dataset)
47 | ax.scatter(positions,[quantile[1] for quantile in tmp],marker='o',color='white',s=30,zorder=3)
48 | ax.vlines(positions,[quantile[0] for quantile in tmp],[quantile[2] for quantile in tmp],color='black',linestyle='-',lw=5)
49 | ax.vlines(positions,[bound[0] for bound in whisker],[bound[1] for bound in whisker],color='black',linestyle='-',lw=4)
50 |
51 |
52 | sample1 = np.random.randn(100)
53 | sample2 = np.random.randn(100)
54 | sample3 = np.random.randn(100)
55 | sample4 = np.random.randn(100)
56 | sample5 = np.random.randn(100)
57 | sample6 = np.random.randn(100)
58 |
59 | mat = np.row_stack([sample1,sample2,sample3,sample4,sample5,sample6])
60 |
61 | from scipy.spatial.distance import pdist,squareform
62 | dense_distance = pdist(mat,'euclidean')
63 | square_distance = squareform(dense_distance)
64 |
65 | from scipy.cluster.hierarchy import linkage,dendrogram
66 | linkage_matrix = linkage(dense_distance,method='ward',metric='euclidean')
67 | fig,ax = plt.subplots()
68 | dendrogram(linkage_matrix,ax=ax)
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------