11---
2- kernelspec :
3- name : python3
4- display_name : python3
52jupytext :
63 text_representation :
74 extension : .md
85 format_name : myst
9- format_version : ' 0.13'
10- jupytext_version : 1.13.8
6+ format_version : 0.13
7+ jupytext_version : 1.14.1
8+ kernelspec :
9+ display_name : Python 3 (ipykernel)
10+ language : python
11+ name : python3
1112---
1213
1314``` {code-cell} ipython3
1415:tags: [remove-input]
1516
1617import os
18+ import functools
19+ import subprocess
20+ import tempfile
21+ from pathlib import Path
1722
1823import matplotlib.tri as mtri
1924import numpy as np
@@ -26,7 +31,8 @@ from tqdm.auto import tqdm
2631import adaptive
2732
2833
29- def add_rounded_corners(size, rad):
34+ @functools.lru_cache
35+ def make_cut(size, rad):
3036 # Make new images
3137 circle = Image.new("L", (rad * 2, rad * 2), color=1)
3238 draw = ImageDraw.Draw(circle)
@@ -41,7 +47,12 @@ def add_rounded_corners(size, rad):
4147 alpha.paste(circle.crop((rad, rad, rad * 2, rad * 2)), (w - rad, h - rad))
4248
4349 # To array
44- cut = np.array(alpha)
50+ return np.array(alpha)
51+
52+
53+ @functools.lru_cache
54+ def add_rounded_corners(size=(1000, 1000), rad=300):
55+ cut = make_cut(size, rad)
4556 cut = cut.reshape((*cut.shape, 1)).repeat(4, axis=2)
4657
4758 # Set the corners to (252, 252, 252, 255) to match the RTD background #FCFCFC
@@ -50,6 +61,16 @@ def add_rounded_corners(size, rad):
5061 return cut
5162
5263
64+ def remove_rounded_corners(fname):
65+ im = Image.open(fname)
66+ ar = np.array(im)
67+ cut = make_cut(size=ar.shape[:-1], rad=round(ar.shape[0] * 0.3)).astype(bool)
68+ ar[:, :, -1] = np.where(~cut, ar[:, :, -1], 0)
69+ im_new = Image.fromarray(ar)
70+ im_new.save(fname)
71+ return im_new
72+
73+
5374def learner_till(till, learner, data):
5475 new_learner = adaptive.Learner2D(None, bounds=learner.bounds)
5576 new_learner.data = {k: v for k, v in data[:till]}
@@ -61,7 +82,7 @@ def learner_till(till, learner, data):
6182
6283def plot_tri(learner, ax):
6384 tri = learner.ip().tri
64- triang = mtri.Triangulation(*tri.points.T, triangles=tri.vertices )
85+ triang = mtri.Triangulation(*tri.points.T, triangles=tri.simplices )
6586 return ax.triplot(triang, c="k", lw=0.8, alpha=0.8)
6687
6788
@@ -70,10 +91,14 @@ def get_new_artists(npoints, learner, data, rounded_corners, ax):
7091 line1, line2 = plot_tri(new_learner, ax)
7192 data = np.rot90(new_learner.interpolated_on_grid()[-1])
7293 im = ax.imshow(data, extent=(-0.5, 0.5, -0.5, 0.5), cmap="viridis")
73- im2 = ax.imshow(rounded_corners, extent=(-0.5, 0.5, -0.5, 0.5), zorder=10)
74- return im, line1, line2, im2
94+ if rounded_corners is None:
95+ return im, line1, line2
96+ else:
97+ im2 = ax.imshow(rounded_corners, extent=(-0.5, 0.5, -0.5, 0.5), zorder=10)
98+ return im, line1, line2, im2
7599
76100
101+ @functools.lru_cache
77102def create_and_run_learner():
78103 def ring(xy):
79104 import numpy as np
@@ -87,11 +112,7 @@ def create_and_run_learner():
87112 return learner
88113
89114
90- def main(fname="source/_static/logo_docs.mp4"):
91- learner = create_and_run_learner()
92-
93- data = list(learner.data.items())
94-
115+ def get_figure():
95116 fig, ax = plt.subplots(figsize=(5, 5))
96117 fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=None, hspace=None)
97118 ax.set_xticks([])
@@ -100,29 +121,99 @@ def main(fname="source/_static/logo_docs.mp4"):
100121 ax.spines["right"].set_visible(False)
101122 ax.spines["bottom"].set_visible(False)
102123 ax.spines["left"].set_visible(False)
124+ return fig, ax
125+
126+
127+ def setup(nseconds=15):
128+ learner = create_and_run_learner()
129+
130+ data = list(learner.data.items())
131+
132+ fig, ax = get_figure()
103133
104- nseconds = 15
105134 npoints = (len(data) * np.linspace(0, 1, 24 * nseconds) ** 2).astype(int)
106135 rounded_corners = add_rounded_corners(size=(1000, 1000), rad=300)
136+ return npoints, learner, data, rounded_corners, fig, ax
137+
138+
139+ def animate_mp4(fname="source/_static/logo_docs.mp4", nseconds=15):
140+ npoints, learner, data, rounded_corners, fig, ax = setup()
107141 artists = [
108142 get_new_artists(n, learner, data, rounded_corners, ax) for n in tqdm(npoints)
109143 ]
110-
111144 ani = animation.ArtistAnimation(fig, artists, blit=True)
112145 ani.save(fname, writer=FFMpegWriter(fps=24))
113146
114147
148+ def animate_png(folder=None, nseconds=15):
149+ npoints, learner, data, rounded_corners, fig, ax = setup(nseconds)
150+ if folder is None:
151+ folder = Path(tempfile.gettempdir()) / next(tempfile._get_candidate_names())
152+ folder = Path(folder)
153+ folder.mkdir(parents=True, exist_ok=True)
154+ fnames = []
155+ ims = []
156+ for i, n in tqdm(enumerate(npoints), total=len(npoints)):
157+ fname = folder / f"logo_docs_{i:07d}.png"
158+ fnames.append(fname)
159+ npoints, learner, data, _, fig, ax = setup(nseconds)
160+ get_new_artists(n, learner, data, None, ax)
161+ fig.savefig(fname, transparent=True)
162+ ax.cla()
163+ plt.close(fig)
164+ im = remove_rounded_corners(fname)
165+ ims.append(im)
166+ return fnames, ims
167+
168+
169+ def save_webp(fname_webp, ims):
170+ (im, *_ims) = ims
171+ im.save(
172+ fname_webp,
173+ save_all=True,
174+ append_images=_ims,
175+ opimize=False,
176+ durarion=2,
177+ quality=70,
178+ )
179+
180+
181+ def save_webm(fname, fnames):
182+ args = [
183+ "ffmpeg",
184+ "-framerate",
185+ "24",
186+ "-f",
187+ "image2",
188+ "-i",
189+ str(fnames[0]).replace("0000000", "%07d"),
190+ "-c:v",
191+ "libvpx-vp9",
192+ "-pix_fmt",
193+ "yuva420p",
194+ "-crf",
195+ "23", # 0 is lossless 51 is worst
196+ "-y",
197+ fname,
198+ ]
199+ return subprocess.run(args, capture_output=True)
200+
201+
115202if __name__ == "__main__":
116- fname = "_static/logo_docs.mp4"
117- if not os.path.exists(fname):
118- main(fname)
203+ fname_mp4 = Path("_static/logo_docs.mp4")
204+ # if not fname_mp4.exists():
205+ # animate_mp4(fname_mp4)
206+ fname_webm = fname_mp4.with_suffix(".webm")
207+ if not fname_webm.exists():
208+ fnames, ims = animate_png()
209+ save_webm(fname_webm, fnames)
119210```
120211
121212``` {eval-rst}
122213.. raw:: html
123214
124215 <video autoplay loop muted playsinline webkit-playsinline
125216 style="width: 400px; max-width: 100%; margin: 0 auto; display:block;">
126- <source src="_static/logo_docs.mp4 " type="video/mp4">
217+ <source src="_static/logo_docs.webm " type="video/mp4">
127218 </video><br>
128219```
0 commit comments