plotjs 0.0.3__tar.gz → 0.0.4__tar.gz

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.
Files changed (91) hide show
  1. {plotjs-0.0.3 → plotjs-0.0.4}/.coverage +0 -0
  2. {plotjs-0.0.3 → plotjs-0.0.4}/.github/workflows/tests.yaml +5 -2
  3. {plotjs-0.0.3 → plotjs-0.0.4}/.gitignore +2 -0
  4. {plotjs-0.0.3 → plotjs-0.0.4}/Makefile +3 -2
  5. {plotjs-0.0.3/plotjs.egg-info → plotjs-0.0.4}/PKG-INFO +1 -1
  6. {plotjs-0.0.3 → plotjs-0.0.4}/coverage-badge.svg +1 -1
  7. {plotjs-0.0.3 → plotjs-0.0.4}/docs/gallery/index.md +17 -5
  8. plotjs-0.0.4/docs/guides/advanced/advanced.py +213 -0
  9. plotjs-0.0.4/docs/guides/advanced/index.md +201 -0
  10. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/CSS-2.html +407 -347
  11. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/CSS.html +407 -347
  12. plotjs-0.0.4/docs/iframes/area-natural-disasters.html +3878 -0
  13. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/javascript.html +407 -347
  14. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/javascript2.html +265 -205
  15. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/quickstart.html +407 -347
  16. plotjs-0.0.4/docs/iframes/quickstart10.html +989 -0
  17. plotjs-0.0.4/docs/iframes/quickstart11.html +2407 -0
  18. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/quickstart2.html +407 -347
  19. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/quickstart3.html +407 -347
  20. plotjs-0.0.4/docs/iframes/quickstart4.html +1253 -0
  21. plotjs-0.0.4/docs/iframes/quickstart5.html +1507 -0
  22. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/quickstart6.html +108 -48
  23. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/quickstart7.html +265 -205
  24. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/quickstart8.html +106 -46
  25. {plotjs-0.0.3 → plotjs-0.0.4}/docs/iframes/quickstart9.html +722 -662
  26. {plotjs-0.0.3 → plotjs-0.0.4}/docs/index.md +129 -1
  27. {plotjs-0.0.3 → plotjs-0.0.4}/docs/index.qmd +113 -1
  28. plotjs-0.0.4/package-lock.json +6317 -0
  29. plotjs-0.0.4/package.json +11 -0
  30. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/__init__.py +1 -1
  31. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/main.py +28 -8
  32. plotjs-0.0.4/plotjs/static/main.js +87 -0
  33. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/static/template.html +84 -24
  34. {plotjs-0.0.3 → plotjs-0.0.4/plotjs.egg-info}/PKG-INFO +1 -1
  35. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs.egg-info/SOURCES.txt +14 -8
  36. {plotjs-0.0.3 → plotjs-0.0.4}/pyproject.toml +3 -4
  37. plotjs-0.0.4/tests/PlotSVGParser.test.js +83 -0
  38. {plotjs-0.0.3/tests → plotjs-0.0.4/tests/test-python}/test_css_and_js_utils.py +3 -3
  39. {plotjs-0.0.3/tests → plotjs-0.0.4/tests/test-python}/test_main.py +1 -1
  40. plotjs-0.0.4/vitest.config.js +9 -0
  41. plotjs-0.0.3/docs/guides/advanced/advanced.py +0 -2
  42. plotjs-0.0.3/docs/guides/advanced/index.md +0 -1
  43. plotjs-0.0.3/docs/iframes/quickstart4.html +0 -1193
  44. plotjs-0.0.3/docs/iframes/quickstart5.html +0 -1419
  45. plotjs-0.0.3/plotjs/static/d3.min.js +0 -2
  46. plotjs-0.0.3/plotjs/static/main.js +0 -143
  47. {plotjs-0.0.3 → plotjs-0.0.4}/.gitattributes +0 -0
  48. {plotjs-0.0.3 → plotjs-0.0.4}/.github/workflows/doc.yaml +0 -0
  49. {plotjs-0.0.3 → plotjs-0.0.4}/.github/workflows/lint.yaml +0 -0
  50. {plotjs-0.0.3 → plotjs-0.0.4}/.github/workflows/pypi.yaml +0 -0
  51. {plotjs-0.0.3 → plotjs-0.0.4}/.github/workflows/type.yaml +0 -0
  52. {plotjs-0.0.3 → plotjs-0.0.4}/.pre-commit-config.yaml +0 -0
  53. {plotjs-0.0.3 → plotjs-0.0.4}/LICENSE +0 -0
  54. {plotjs-0.0.3 → plotjs-0.0.4}/README.md +0 -0
  55. {plotjs-0.0.3 → plotjs-0.0.4}/docs/developers/contributing.md +0 -0
  56. {plotjs-0.0.3 → plotjs-0.0.4}/docs/developers/how-it-works.md +0 -0
  57. {plotjs-0.0.3 → plotjs-0.0.4}/docs/gallery/index.qmd +0 -0
  58. {plotjs-0.0.3 → plotjs-0.0.4}/docs/guides/css/CSS.py +0 -0
  59. {plotjs-0.0.3 → plotjs-0.0.4}/docs/guides/css/index.md +0 -0
  60. {plotjs-0.0.3 → plotjs-0.0.4}/docs/guides/javascript/index.md +0 -0
  61. {plotjs-0.0.3 → plotjs-0.0.4}/docs/guides/javascript/javascript.py +0 -0
  62. {plotjs-0.0.3 → plotjs-0.0.4}/docs/guides/troubleshooting/index.md +0 -0
  63. {plotjs-0.0.3 → plotjs-0.0.4}/docs/img/how-it-works-1.png +0 -0
  64. {plotjs-0.0.3 → plotjs-0.0.4}/docs/img/how-it-works-2.png +0 -0
  65. {plotjs-0.0.3 → plotjs-0.0.4}/docs/index_files/figure-commonmark/cell-3-output-1.png +0 -0
  66. {plotjs-0.0.3 → plotjs-0.0.4}/docs/reference/css.md +0 -0
  67. {plotjs-0.0.3 → plotjs-0.0.4}/docs/reference/datasets.md +0 -0
  68. {plotjs-0.0.3 → plotjs-0.0.4}/docs/reference/javascript.md +0 -0
  69. {plotjs-0.0.3 → plotjs-0.0.4}/docs/reference/magic-plot.md +0 -0
  70. {plotjs-0.0.3 → plotjs-0.0.4}/docs/static/style.css +0 -0
  71. {plotjs-0.0.3 → plotjs-0.0.4}/docs/stylesheets/style.css +0 -0
  72. {plotjs-0.0.3 → plotjs-0.0.4}/mkdocs.yaml +0 -0
  73. {plotjs-0.0.3 → plotjs-0.0.4}/overrides/partials/footer.html +0 -0
  74. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/css.py +0 -0
  75. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/data/__init__.py +0 -0
  76. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/data/datasets.py +0 -0
  77. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/data/iris.csv +0 -0
  78. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/data/mtcars.csv +0 -0
  79. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/data/titanic.csv +0 -0
  80. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/javascript.py +0 -0
  81. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/static/default.css +0 -0
  82. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs/utils.py +0 -0
  83. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs.egg-info/dependency_links.txt +0 -0
  84. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs.egg-info/requires.txt +0 -0
  85. {plotjs-0.0.3 → plotjs-0.0.4}/plotjs.egg-info/top_level.txt +0 -0
  86. {plotjs-0.0.3 → plotjs-0.0.4}/setup.cfg +0 -0
  87. {plotjs-0.0.3/tests → plotjs-0.0.4/tests/test-python}/__init__.py +0 -0
  88. {plotjs-0.0.3/tests → plotjs-0.0.4/tests/test-python}/static/script.js +0 -0
  89. {plotjs-0.0.3/tests → plotjs-0.0.4/tests/test-python}/static/style.css +0 -0
  90. {plotjs-0.0.3/tests → plotjs-0.0.4/tests/test-python}/test_data.py +0 -0
  91. {plotjs-0.0.3/tests → plotjs-0.0.4/tests/test-python}/test_magic_plot.py +0 -0
Binary file
@@ -1,4 +1,4 @@
1
- name: Unit tests
1
+ name: Tests (Python + JS)
2
2
 
3
3
  on:
4
4
  pull_request:
@@ -24,5 +24,8 @@ jobs:
24
24
  - name: Install the project
25
25
  run: uv sync --all-groups
26
26
 
27
+ - name: Install npm dependencies
28
+ run: npm install
29
+
27
30
  - name: Run tests
28
- run: uv run pytest
31
+ run: make test
@@ -32,3 +32,5 @@ sandbox/
32
32
  scripts/release.sh
33
33
 
34
34
  /.quarto/
35
+
36
+ node_modules
@@ -1,4 +1,4 @@
1
- .PHONY: all examples coverage
1
+ .PHONY: all examples gallery
2
2
 
3
3
  examples:
4
4
  quarto render docs/index.qmd
@@ -17,4 +17,5 @@ coverage:
17
17
  rm coverage.xml
18
18
 
19
19
  test:
20
- uv run pytest
20
+ uv run pytest # run python tests
21
+ npm test # run javascript tests
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotjs
3
- Version: 0.0.3
3
+ Version: 0.0.4
4
4
  Summary: Turn static matplotlib charts into interactive web visualizations
5
5
  Author-email: Joseph Barbier <joseph.barbierdarnal@mail.com>
6
6
  License-Expression: MIT
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="114" height="20" role="img" aria-label="coverage: 92.19%"><title>coverage: 92.19%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="114" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="53" height="20" fill="#4c1"/><rect width="114" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">coverage</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text><text aria-hidden="true" x="865" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">92.19%</text><text x="865" y="140" transform="scale(.1)" fill="#fff" textLength="430">92.19%</text></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="114" height="20" role="img" aria-label="coverage: 93.02%"><title>coverage: 93.02%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="114" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="53" height="20" fill="#4c1"/><rect width="114" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">coverage</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text><text aria-hidden="true" x="865" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">93.02%</text><text x="865" y="140" transform="scale(.1)" fill="#fff" textLength="430">93.02%</text></g></svg>
@@ -18,11 +18,11 @@ This page contains all the `plotjs` examples from this website.
18
18
 
19
19
  <div style="display: flex;">
20
20
 
21
- <iframe width="100%" height="300" src="../iframes/quickstart4.html" style="flex: 1; border: none;">
21
+ <iframe width="100%" height="300" src="../iframes/area-natural-disasters.html" style="flex: 1; border: none;">
22
22
 
23
23
  </iframe>
24
24
 
25
- <iframe width="100%" height="300" src="../iframes/quickstart5.html" style="flex: 1; border: none;">
25
+ <iframe width="100%" height="300" src="../iframes/quickstart4.html" style="flex: 1; border: none;">
26
26
 
27
27
  </iframe>
28
28
 
@@ -30,11 +30,11 @@ This page contains all the `plotjs` examples from this website.
30
30
 
31
31
  <div style="display: flex;">
32
32
 
33
- <iframe width="100%" height="300" src="../iframes/quickstart9.html" style="flex: 1; border: none;">
33
+ <iframe width="100%" height="300" src="../iframes/quickstart5.html" style="flex: 1; border: none;">
34
34
 
35
35
  </iframe>
36
36
 
37
- <iframe width="100%" height="300" src="../iframes/CSS.html" style="flex: 1; border: none;">
37
+ <iframe width="100%" height="300" src="../iframes/quickstart9.html" style="flex: 1; border: none;">
38
38
 
39
39
  </iframe>
40
40
 
@@ -42,19 +42,31 @@ This page contains all the `plotjs` examples from this website.
42
42
 
43
43
  <div style="display: flex;">
44
44
 
45
+ <iframe width="100%" height="300" src="../iframes/CSS.html" style="flex: 1; border: none;">
46
+
47
+ </iframe>
48
+
45
49
  <iframe width="100%" height="300" src="../iframes/quickstart2.html" style="flex: 1; border: none;">
46
50
 
47
51
  </iframe>
48
52
 
53
+ </div>
54
+
55
+ <div style="display: flex;">
56
+
49
57
  <iframe width="100%" height="300" src="../iframes/javascript.html" style="flex: 1; border: none;">
50
58
 
51
59
  </iframe>
52
60
 
61
+ <iframe width="100%" height="300" src="../iframes/quickstart3.html" style="flex: 1; border: none;">
62
+
63
+ </iframe>
64
+
53
65
  </div>
54
66
 
55
67
  <div style="display: flex;">
56
68
 
57
- <iframe width="100%" height="300" src="../iframes/quickstart3.html" style="flex: 1; border: none;">
69
+ <iframe width="100%" height="300" src="../iframes/quickstart10.html" style="flex: 1; border: none;">
58
70
 
59
71
  </iframe>
60
72
 
@@ -0,0 +1,213 @@
1
+ from plotjs import MagicPlot, css
2
+ import pandas as pd
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+ from pypalettes import load_cmap
6
+ from highlight_text import fig_text, ax_text
7
+ from pyfonts import load_google_font
8
+ from drawarrow import ax_arrow
9
+
10
+ url = "https://raw.githubusercontent.com/holtzy/The-Python-Graph-Gallery/master/static/data/disaster-events.csv"
11
+ df = pd.read_csv(url)
12
+
13
+
14
+ def remove_agg_rows(entity: str):
15
+ if entity.lower().startswith("all disasters"):
16
+ return False
17
+ else:
18
+ return True
19
+
20
+
21
+ df = df.replace("Dry mass movement", "Drought")
22
+ df = df[df["Entity"].apply(remove_agg_rows)]
23
+ df = df[~df["Entity"].isin(["Fog", "Glacial lake outburst flood"])]
24
+ df = df.pivot_table(index="Entity", columns="Year", values="Disasters").T
25
+ df.loc[1900, :] = df.loc[1900, :].fillna(0)
26
+ df = df[df.index >= 1960]
27
+ df = df[df.index <= 2023]
28
+ df = df.interpolate(axis=1)
29
+ df.head()
30
+
31
+ # set up the font properties
32
+ font = load_google_font("Bebas Neue")
33
+ other_font = load_google_font("Fira Sans", weight="light")
34
+ other_bold_font = load_google_font("Fira Sans", weight="medium")
35
+
36
+ # initialize the figure
37
+ fig, ax = plt.subplots(figsize=(14, 7), dpi=300)
38
+ ax.set_axis_off()
39
+
40
+ # define the x-axis variable and order the columns
41
+ columns = df.sum().sort_values().index.to_list()
42
+ x = df.index
43
+
44
+ # defines color map and mapping with columns
45
+ colors = load_cmap("Dali").colors
46
+ color_mapping = {
47
+ "Flood": colors[4],
48
+ "Volcanic activity": colors[0],
49
+ "Wildfire": colors[6],
50
+ "Drought": colors[7],
51
+ "Extreme temperature": colors[5],
52
+ "Wet mass movement": colors[3],
53
+ "Earthquake": colors[2],
54
+ "Extreme weather": colors[1],
55
+ }
56
+ colors = [color_mapping[col] for col in columns]
57
+
58
+ # create the stacked area plot
59
+ areas = np.stack(df[columns].values, axis=-1)
60
+ ax.stackplot(x, areas, colors=colors)
61
+
62
+ # add label for the x-axis
63
+ for year in range(1960, 2030, 10):
64
+ ax_text(
65
+ x=year,
66
+ y=-10,
67
+ s=f"{year}",
68
+ va="top",
69
+ ha="left",
70
+ fontsize=13,
71
+ font=font,
72
+ color="grey",
73
+ )
74
+
75
+ # add label for the y-axis
76
+ for value in range(100, 400, 100):
77
+ ax_text(
78
+ x=1960,
79
+ y=value,
80
+ s=f"{value}",
81
+ va="center",
82
+ ha="left",
83
+ fontsize=13,
84
+ font=font,
85
+ color="grey",
86
+ )
87
+ ax.plot([1963, 2023], [value, value], color="grey", lw=0.1)
88
+
89
+ # add title
90
+ fig_text(
91
+ s="More than 1 natural disaster occurs\n<every day> since the 21st century",
92
+ x=0.16,
93
+ y=0.83,
94
+ fontsize=24,
95
+ ha="left",
96
+ va="top",
97
+ color="black",
98
+ font=other_font,
99
+ fig=fig,
100
+ highlight_textprops=[{"font": other_bold_font}],
101
+ )
102
+
103
+ # source and credit
104
+ text = """
105
+ <Design>: barbierjoseph.com
106
+ <Data>: EM-DAT, CRED / UCLouvain (2024)
107
+ """
108
+ fig_text(
109
+ s=text,
110
+ x=0.16,
111
+ y=0.05,
112
+ fontsize=10,
113
+ ha="left",
114
+ va="top",
115
+ color="black",
116
+ fontproperties=other_font,
117
+ highlight_textprops=[{"font": other_bold_font}, {"font": other_bold_font}],
118
+ )
119
+
120
+ # add inline labels
121
+ y_pos = [330, 220, 180, 100, 70, 30, -10, -30]
122
+ for i in range(len(y_pos)):
123
+ country = columns[::-1][i]
124
+ val_2023 = int(df.loc[2023, country])
125
+ ax_text(
126
+ x=2030,
127
+ y=y_pos[i],
128
+ s=f"{country.upper()} - {val_2023} disasters in 2023",
129
+ va="center",
130
+ ha="left",
131
+ font=other_bold_font,
132
+ fontsize=12,
133
+ color=colors[7 - i],
134
+ )
135
+
136
+ # add inflexion arrows
137
+ x_axis_start = 2023
138
+ x_axis_end = 2030
139
+ radius = 10
140
+ arrow_props = {"clip_on": False, "color": "black", "fill_head": False}
141
+ ax_arrow(
142
+ tail_position=(x_axis_start, 330), head_position=(x_axis_end, 330), **arrow_props
143
+ )
144
+ ax_arrow(
145
+ tail_position=(x_axis_start, 220), head_position=(x_axis_end, 220), **arrow_props
146
+ )
147
+ ax_arrow(
148
+ tail_position=(x_axis_start, 90),
149
+ head_position=(x_axis_end, 180),
150
+ inflection_position=(2040, 180),
151
+ **arrow_props,
152
+ )
153
+ ax_arrow(
154
+ tail_position=(x_axis_start, 60),
155
+ head_position=(x_axis_end, 100),
156
+ inflection_position=(2040, 100),
157
+ **arrow_props,
158
+ )
159
+ ax_arrow(
160
+ tail_position=(x_axis_start, 45),
161
+ head_position=(x_axis_end, 70),
162
+ inflection_position=(2040, 70),
163
+ **arrow_props,
164
+ )
165
+ ax_arrow(
166
+ tail_position=(x_axis_start, 30), head_position=(x_axis_end, 30), **arrow_props
167
+ )
168
+ ax_arrow(
169
+ tail_position=(x_axis_start, 20),
170
+ head_position=(x_axis_end, -10),
171
+ inflection_position=(2040, -10),
172
+ **arrow_props,
173
+ )
174
+ ax_arrow(
175
+ tail_position=(x_axis_start, 4),
176
+ head_position=(x_axis_end, -30),
177
+ inflection_position=(2040, -30),
178
+ **arrow_props,
179
+ )
180
+ plt.savefig("debug.svg")
181
+
182
+ MagicPlot(fig, bbox_inches="tight").add_css(
183
+ css.from_dict(
184
+ {
185
+ ".tooltip": {
186
+ "width": "180px",
187
+ "text-align": "center",
188
+ "font-size": "1.2em",
189
+ "background": "#000814",
190
+ }
191
+ }
192
+ )
193
+ ).add_tooltip(labels=columns).save("docs/iframes/area-natural-disasters.html")
194
+
195
+ #####################################################
196
+
197
+
198
+ (
199
+ MagicPlot(fig)
200
+ .add_css(
201
+ css.from_dict(
202
+ {
203
+ ".tooltip": {
204
+ "width": "180px",
205
+ "text-align": "center",
206
+ "font-size": "1.2em",
207
+ "background": "#000814",
208
+ }
209
+ }
210
+ )
211
+ )
212
+ .add_tooltip(labels=columns)
213
+ )
@@ -0,0 +1,201 @@
1
+ # TODO: find cool examples to showcase here
2
+
3
+ ## Natural disasters
4
+
5
+ ```py
6
+ from plotjs import MagicPlot, css
7
+ import pandas as pd
8
+ import numpy as np
9
+ import matplotlib.pyplot as plt
10
+ from pypalettes import load_cmap
11
+ from highlight_text import fig_text, ax_text
12
+ from pyfonts import load_google_font
13
+ from drawarrow import ax_arrow
14
+
15
+ url = "https://raw.githubusercontent.com/holtzy/The-Python-Graph-Gallery/master/static/data/disaster-events.csv"
16
+ df = pd.read_csv(url)
17
+
18
+
19
+ def remove_agg_rows(entity: str):
20
+ if entity.lower().startswith("all disasters"):
21
+ return False
22
+ else:
23
+ return True
24
+
25
+
26
+ df = df.replace("Dry mass movement", "Drought")
27
+ df = df[df["Entity"].apply(remove_agg_rows)]
28
+ df = df[~df["Entity"].isin(["Fog", "Glacial lake outburst flood"])]
29
+ df = df.pivot_table(index="Entity", columns="Year", values="Disasters").T
30
+ df.loc[1900, :] = df.loc[1900, :].fillna(0)
31
+ df = df[df.index >= 1960]
32
+ df = df[df.index <= 2023]
33
+ df = df.interpolate(axis=1)
34
+ df.head()
35
+
36
+ # set up the font properties
37
+ font = load_google_font("Bebas Neue")
38
+ other_font = load_google_font("Fira Sans", weight="light")
39
+ other_bold_font = load_google_font("Fira Sans", weight="medium")
40
+
41
+ # initialize the figure
42
+ fig, ax = plt.subplots(figsize=(14, 7), dpi=300)
43
+ ax.set_axis_off()
44
+
45
+ # define the x-axis variable and order the columns
46
+ columns = df.sum().sort_values().index.to_list()
47
+ x = df.index
48
+
49
+ # defines color map and mapping with columns
50
+ colors = load_cmap("Dali").colors
51
+ color_mapping = {
52
+ "Flood": colors[4],
53
+ "Volcanic activity": colors[0],
54
+ "Wildfire": colors[6],
55
+ "Drought": colors[7],
56
+ "Extreme temperature": colors[5],
57
+ "Wet mass movement": colors[3],
58
+ "Earthquake": colors[2],
59
+ "Extreme weather": colors[1],
60
+ }
61
+ colors = [color_mapping[col] for col in columns]
62
+
63
+ # create the stacked area plot
64
+ areas = np.stack(df[columns].values, axis=-1)
65
+ ax.stackplot(x, areas, colors=colors)
66
+
67
+ # add label for the x-axis
68
+ for year in range(1960, 2030, 10):
69
+ ax_text(
70
+ x=year,
71
+ y=-10,
72
+ s=f"{year}",
73
+ va="top",
74
+ ha="left",
75
+ fontsize=13,
76
+ font=font,
77
+ color="grey",
78
+ )
79
+
80
+ # add label for the y-axis
81
+ for value in range(100, 400, 100):
82
+ ax_text(
83
+ x=1960,
84
+ y=value,
85
+ s=f"{value}",
86
+ va="center",
87
+ ha="left",
88
+ fontsize=13,
89
+ font=font,
90
+ color="grey",
91
+ )
92
+ ax.plot([1963, 2023], [value, value], color="grey", lw=0.1)
93
+
94
+ # add title
95
+ fig_text(
96
+ s="More than 1 natural disaster occurs\n<every day> since the 21st century",
97
+ x=0.16,
98
+ y=0.83,
99
+ fontsize=24,
100
+ ha="left",
101
+ va="top",
102
+ color="black",
103
+ font=other_font,
104
+ fig=fig,
105
+ highlight_textprops=[{"font": other_bold_font}],
106
+ )
107
+
108
+ # source and credit
109
+ text = """
110
+ <Design>: barbierjoseph.com
111
+ <Data>: EM-DAT, CRED / UCLouvain (2024)
112
+ """
113
+ fig_text(
114
+ s=text,
115
+ x=0.16,
116
+ y=0.05,
117
+ fontsize=10,
118
+ ha="left",
119
+ va="top",
120
+ color="black",
121
+ fontproperties=other_font,
122
+ highlight_textprops=[{"font": other_bold_font}, {"font": other_bold_font}],
123
+ )
124
+
125
+ # add inline labels
126
+ y_pos = [330, 220, 180, 100, 70, 30, -10, -30]
127
+ for i in range(len(y_pos)):
128
+ country = columns[::-1][i]
129
+ val_2023 = int(df.loc[2023, country])
130
+ ax_text(
131
+ x=2030,
132
+ y=y_pos[i],
133
+ s=f"{country.upper()} - {val_2023} disasters in 2023",
134
+ va="center",
135
+ ha="left",
136
+ font=other_bold_font,
137
+ fontsize=12,
138
+ color=colors[7 - i],
139
+ )
140
+
141
+ # add inflexion arrows
142
+ x_axis_start = 2023
143
+ x_axis_end = 2030
144
+ radius = 10
145
+ arrow_props = {"clip_on": False, "color": "black", "fill_head": False}
146
+ ax_arrow(
147
+ tail_position=(x_axis_start, 330), head_position=(x_axis_end, 330), **arrow_props
148
+ )
149
+ ax_arrow(
150
+ tail_position=(x_axis_start, 220), head_position=(x_axis_end, 220), **arrow_props
151
+ )
152
+ ax_arrow(
153
+ tail_position=(x_axis_start, 90),
154
+ head_position=(x_axis_end, 180),
155
+ inflection_position=(2040, 180),
156
+ **arrow_props,
157
+ )
158
+ ax_arrow(
159
+ tail_position=(x_axis_start, 60),
160
+ head_position=(x_axis_end, 100),
161
+ inflection_position=(2040, 100),
162
+ **arrow_props,
163
+ )
164
+ ax_arrow(
165
+ tail_position=(x_axis_start, 45),
166
+ head_position=(x_axis_end, 70),
167
+ inflection_position=(2040, 70),
168
+ **arrow_props,
169
+ )
170
+ ax_arrow(
171
+ tail_position=(x_axis_start, 30), head_position=(x_axis_end, 30), **arrow_props
172
+ )
173
+ ax_arrow(
174
+ tail_position=(x_axis_start, 20),
175
+ head_position=(x_axis_end, -10),
176
+ inflection_position=(2040, -10),
177
+ **arrow_props,
178
+ )
179
+ ax_arrow(
180
+ tail_position=(x_axis_start, 4),
181
+ head_position=(x_axis_end, -30),
182
+ inflection_position=(2040, -30),
183
+ **arrow_props,
184
+ )
185
+ plt.savefig("debug.svg")
186
+
187
+ MagicPlot(fig, bbox_inches="tight").add_css(
188
+ css.from_dict(
189
+ {
190
+ ".tooltip": {
191
+ "width": "180px",
192
+ "text-align": "center",
193
+ "font-size": "1.2em",
194
+ "background": "#000814",
195
+ }
196
+ }
197
+ )
198
+ ).add_tooltip(labels=columns).save("docs/iframes/area-natural-disasters.html")
199
+ ```
200
+
201
+ <iframe width="1000" height="400" src="../../iframes/area-natural-disasters.html" style="border:none;"></iframe>