{ "cells": [ { "cell_type": "markdown", "id": "2904a870", "metadata": {}, "source": [ "# Make a dynamic DYNAMAX logo" ] }, { "cell_type": "code", "execution_count": 72, "id": "3c651a00", "metadata": {}, "outputs": [], "source": [ "from fastprogress.fastprogress import progress_bar\n", "import jax.numpy as jnp\n", "import jax.random as jr\n", "from jax.nn import one_hot, softmax, sigmoid\n", "from jax import vmap\n", "from tensorflow_probability.substrates import jax as tfp\n", "import matplotlib.pyplot as plt\n", "from matplotlib.patches import Rectangle \n", "\n", "tfd = tfp.distributions" ] }, { "cell_type": "code", "execution_count": 2, "id": "ae440066", "metadata": {}, "outputs": [], "source": [ "# Make a JAX-y color palette\n", "COLORS = [\"#6B90CA\", # blues\n", " \"#4367B1\",\n", " \"#3C5BA9\",\n", " \"#29A69A\", # greens\n", " \"#1B796C\",\n", " \"#186A5C\",\n", " \"#C489BC\", # purples\n", " \"#903F98\",\n", " \"#6A2C91\"]" ] }, { "cell_type": "code", "execution_count": 4, "id": "6a89cc4d", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "FIGSIZE_PX = jnp.array([2080, 320])\n", "DPI = 1000\n", "\n", "# Test that the mask works\n", "fig = plt.figure(figsize=FIGSIZE_PX / DPI)\n", "mask = plt.imread(\"mask.png\")\n", "ax = fig.add_axes((0, 0, 1, 1))\n", "ax.patch.set_color('r')\n", "ax.imshow(mask, aspect=\"auto\")\n", "ax.xaxis.set_visible(False)\n", "ax.yaxis.set_visible(False)\n", "for sp in ax.spines.values():\n", " sp.set_visible(False)\n", "\n", "plt.savefig(\"test.png\", dpi=1000)" ] }, { "cell_type": "markdown", "id": "d5dd82f0", "metadata": {}, "source": [ "# Break the image down into squares of various sizes" ] }, { "cell_type": "code", "execution_count": 110, "id": "33dd7121", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created 1433 rectangles\n" ] } ], "source": [ "RECT_PX = 80\n", "FIGSIZE_RECT = (FIGSIZE_PX / RECT_PX).astype(int)\n", "\n", "patches = []\n", "for i in range(FIGSIZE_RECT[1]):\n", " for j in range(FIGSIZE_RECT[0]):\n", " # make a rectangle patch; we'll color it later.\n", " patches.append(Rectangle((j * RECT_PX, i * RECT_PX), RECT_PX, RECT_PX))\n", " \n", "def split_patch(rect):\n", " # Split a rectangle into four quadrants\n", " x, y = rect.xy\n", " sz = rect.get_width() / 2\n", " r1 = Rectangle((x, y), sz, sz)\n", " r2 = Rectangle((x + sz, y), sz, sz)\n", " r3 = Rectangle((x, y + sz), sz, sz)\n", " r4 = Rectangle((x + sz, y + sz), sz, sz)\n", " return [r1, r2, r3, r4]\n", "\n", "# Split in 3 phases\n", "seed = jr.PRNGKey(0)\n", "for r in range(3): \n", " # split depending on how far to the right the rectangle is located\n", " # with the threshold increasing each round.\n", "# split_prob = lambda x: sigmoid(( x - (r + 1) * 6) / 2)\n", " split_prob = lambda x: 0.5\n", " \n", " # Go through and split the patches\n", " new_patches = []\n", " for rect in patches:\n", " key, seed = jr.split(seed)\n", " if jr.bernoulli(key, split_prob(rect.xy[0] // RECT_PX)) == 1:\n", " new_patches.extend(split_patch(rect))\n", " else:\n", " new_patches.append(rect)\n", " \n", " patches = new_patches\n", "\n", "num_patches = len(patches)\n", "print(\"Created \", num_patches, \"rectangles\")" ] }, { "cell_type": "code", "execution_count": 111, "id": "810da12e-3abd-418a-9be1-1425ef439aa1", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "ddc9f81f9d784c47b15ff92b21a655f5", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/199 [00:00" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Plot the mask on top of rectanges\n", "fig = plt.figure(figsize=FIGSIZE_PX / DPI)\n", "ax = fig.add_axes((0, 0, 1, 1))\n", "ax.patch.set_color('w')\n", "\n", "for rect in patches:\n", " ax.add_patch(rect)\n", "\n", "# overlay the mask\n", "mask = plt.imread(\"mask.png\")\n", "ax.imshow(mask, aspect=\"auto\", zorder=1000)\n", "\n", "# remove the axes and spines\n", "ax.xaxis.set_visible(False)\n", "ax.yaxis.set_visible(False)\n", "for sp in ax.spines.values():\n", " sp.set_visible(False)\n", "\n", "ax.set_xlim(0, FIGSIZE_PX[0])\n", "ax.set_ylim(FIGSIZE_PX[1], 0)\n", "\n", "plt.savefig(\"logo-000.png\", dpi=250)\n", "\n", "for t in progress_bar(range(1, num_timesteps)):\n", " for rect, color in zip(patches, colors[t]):\n", " rect.set_facecolor(COLORS[color])\n", " plt.savefig(\"logo-{:03d}.png\".format(t), dpi=250)\n", " \n", "# Save a high resolution static logo\n", "plt.savefig(\"logo.png\".format(t), dpi=1000)" ] }, { "cell_type": "code", "execution_count": 114, "id": "96a13b24-b442-4a93-b654-b7ffba13d5ba", "metadata": {}, "outputs": [], "source": [ "!convert -delay 50 -loop 0 `ls -v logo-*.png` logo.gif" ] }, { "cell_type": "code", "execution_count": null, "id": "a81f78f9-789e-4662-899e-dbb0217890e8", "metadata": {}, "outputs": [], "source": [ "!rm logo-*.png" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.6" } }, "nbformat": 4, "nbformat_minor": 5 }