{ "cells": [ { "cell_type": "markdown", "id": "bc7840ba-518b-4fba-8a6d-16d368d94e59", "metadata": {}, "source": [ "(schematic)=\n", "# `schematic` - manual drawing\n", "\n", "This example demonstrates the basic functionality of the `schematic` module.\n", "The schematic module is a simple wrapper around `matplotlib` that allows\n", "programatically drawing diagrams, e.g. for tensor networks, in 2D and also\n", "pseudo-3D. It is used as the backend for automatic drawing in\n", "[TensorNetwork.draw](quimb.tensor.drawing.draw_tn), but it also useful for\n", "making manual diagrams not associated with a tensor network. The main object\n", "is the [`Drawing`](quimb.schematic.Drawing) class.\n", "\n", "\n", "## Illustrative full examples\n", "\n", "The following examples are intended to be illustrative of a full drawing.\n", "If you supply a dict of `presets` to `Drawing`, then you can provide default\n", "styling for various elements simply by name.\n", "\n", "### 2D example" ] }, { "cell_type": "code", "execution_count": 1, "id": "67d6b0f1-1943-48a6-8b2a-b6676f371080", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%config InlineBackend.figure_formats = ['svg']\n", "from quimb import schematic\n", "\n", "presets = {\n", " 'bond': {'linewidth': 3},\n", " 'phys': {'linewidth': 1.5},\n", " 'center': {\n", " # `get_color` uses more colorblind friendly colors\n", " 'color': schematic.get_color('orange'),\n", " 'hatch': '/////',\n", " },\n", " 'left': {\n", " 'color': schematic.get_color('bluedark'),\n", " },\n", " 'right': {\n", " 'color': schematic.get_color('blue'),\n", " },\n", "}\n", "\n", "d = schematic.Drawing(presets=presets)\n", "\n", "L = 10\n", "center = 5\n", "\n", "for i in range(10):\n", " # draw tensor\n", " d.circle((i, 0), preset=(\n", " \"center\" if i == center else\n", " \"left\" if i < center else\n", " \"right\"\n", " ))\n", "\n", " # draw physical index\n", " d.line((i, 0), (i, -2/3), preset='phys')\n", "\n", " # draw virtual bond\n", " if i + 1 < L:\n", " d.line((i, 0), (i + 1, 0), preset='bond')\n", "\n", " # draw isometric conditions\n", " if i != center:\n", " d.arrowhead((i, -2/3), (i, 0), preset='phys')\n", " if i < center - 1:\n", " d.arrowhead((i, 0), (i + 1, 0), preset='bond')\n", " if i > center + 1:\n", " d.arrowhead((i, 0), (i - 1, 0), preset='bond')\n", "\n", "# label the left\n", "if center > 0:\n", " d.text((center - 1, 0.8), 'LEFT')\n", " d.patch_around([(i, 0) for i in range(center)], radius=0.5)\n", "\n", "# label pair\n", "if center + 1 < L:\n", " d.patch_around_circles(\n", " (center, 0), 0.3,\n", " (center + 1, 0), 0.3,\n", " facecolor=(.2, .8, .5, .4),\n", " )\n", "\n", "# label the right\n", "if center + 2 < L:\n", " d.text((center + 2, 0.8), 'RIGHT')\n", " d.patch_around([(i, 0) for i in range(center + 2, L)], radius=0.5)" ] }, { "cell_type": "markdown", "id": "2da67ed9-a3d4-4622-9dac-cb8b44f6e2cc", "metadata": {}, "source": [ "### Pseudo-3D example\n", "\n", "If you supply 3D coordinates to `Drawing` methods then the objects will be\n", "mapped by the axonometric projection to 2D and given appropriate z-ordering.\n", "The projection and orientation can be controlled in the `Drawing` constructor." ] }, { "cell_type": "code", "execution_count": 2, "id": "3f190069-28f8-4ca8-845f-9422d00dcb9f", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing(presets=presets, figsize=(10, 10))\n", "\n", "L = 10\n", "\n", "radius = 0.15\n", "\n", "for center in range(L):\n", " # map the stage into a 3D x-coordinate\n", " x = 2 * center\n", "\n", " for i in range(10):\n", " # draw tensor, can now use cube rather than circle\n", " d.cube((x, i, 0), radius=radius, preset=(\n", " \"center\" if i == center else\n", " \"left\" if i < center else\n", " \"right\"\n", " ))\n", "\n", " # draw physical index\n", " d.line((x, i, 0), (x, i, -2/3), preset='phys')\n", "\n", " # draw virtual bond\n", " if i + 1 < L:\n", " d.line((x, i + radius, 0), (x, i + 1 - radius, 0), preset='bond')\n", "\n", " # draw isometric conditions\n", " if i != center:\n", " d.arrowhead((x, i, -2/3), (x, i, 0), preset='phys')\n", " if i < center - 1:\n", " d.arrowhead((x, i, 0), (x, i + 1, 0), preset='bond')\n", " if i > center + 1:\n", " d.arrowhead((x, i, 0), (x, i - 1, 0), preset='bond')\n", "\n", " # label the left\n", " if center > 0:\n", " d.patch_around([(x, i, 0) for i in range(center)], radius=3 * radius, smoothing=0.0)\n", "\n", " # label pair\n", " if center + 1 < L:\n", " d.patch_around_circles(\n", " (x, center, 0), 2.5 * radius,\n", " (x, center + 1, 0), 2.5 * radius,\n", " facecolor=(.2, .7, .3, .3),\n", " )\n", "\n", " # label the right\n", " if center + 2 < L:\n", " d.patch_around([(x, i, 0) for i in range(center + 2, L)], radius=3 * radius, smoothing=0.0)\n", "\n", "d.text((0, 0, 1), '$T^i_{e_i}$', color=schematic.get_color('orange'))" ] }, { "cell_type": "markdown", "id": "71a8e368-fcbe-46ad-b20a-00ad0afce088", "metadata": {}, "source": [ "## Individual elements:\n", "\n", "Here we demonstrate the different types of individual element that can be placed.\n", "The `hash_to_color` function is useful way to deterministically generate colors\n", "from hashable objects." ] }, { "cell_type": "code", "execution_count": 3, "id": "3af5ff64-f4a7-4101-ac35-bbb27ff55ed0", "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "id": "2d07bfcb-7413-47a3-8fae-14217c2951f9", "metadata": {}, "source": [ "### Circles\n", "\n", "[Drawing.circle](quimb.schematic.Drawing.circle) draws a circle with a given\n", "radius and center coordinates." ] }, { "cell_type": "code", "execution_count": 4, "id": "54b39d1a-1dc7-487c-be3b-3ebf38e3cae3", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "coos = [\n", " (i, j, 0)\n", " for i in range(4)\n", " for j in range(4)\n", "]\n", "\n", "for coo in coos:\n", " d.circle(\n", " coo,\n", " radius=np.random.uniform(0.2, 0.3),\n", " color=schematic.hash_to_color(str(coo))\n", " )\n", "\n", "# dot is a simple alias circle\n", "d.dot((1.5, 1.5, 0))" ] }, { "cell_type": "markdown", "id": "d9b74efd-0b3a-495f-99b8-1a445ccde49e", "metadata": {}, "source": [ "### Cubes\n", "\n", "[Drawing.cube](quimb.schematic.Drawing.cube) draws a cube with a given\n", "'radius' and center coordinates, only for 3D coordinates." ] }, { "cell_type": "code", "execution_count": 5, "id": "d62fc612-369d-47e5-9894-d4f0aed9fcd9", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "coos = [\n", " (i, j, 0)\n", " for i in range(4)\n", " for j in range(4)\n", "]\n", "\n", "for coo in coos:\n", " d.cube(\n", " coo,\n", " radius=np.random.uniform(0.2, 0.3),\n", " color=schematic.hash_to_color(str(coo))\n", " )" ] }, { "cell_type": "markdown", "id": "4a4ca822-5598-4569-8819-1cc57ae0c113", "metadata": {}, "source": [ "### Text\n", "\n", "[Drawing.text](quimb.schematic.Drawing.cube) places text in data coordinates\n", "(including 3D). [Drawing.label_ax](quimb.schematic.Drawing.label_ax) and\n", "[Drawing.label_fig](quimb.schematic.Drawing.label_fig) are the same but default\n", "to axis and figure coordinates respectively." ] }, { "cell_type": "code", "execution_count": 6, "id": "19a89817-c735-401a-9385-d5c7c5dc3706", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "coos = [\n", " (i, j, 0)\n", " for i in range(4)\n", " for j in range(4)\n", "]\n", "\n", "for coo in coos:\n", " d.text(\n", " coo, str(coo),\n", " color=schematic.hash_to_color(str(coo))\n", " )\n", "\n", "# labels are the same but use the axes or figure coordinates\n", "d.label_ax(0.1, 0.9, '$\\\\mathbf{B}$', fontsize=20)\n", "d.label_fig(0.5, 0.0, '$\\\\sum_e \\\\prod_i ~ T^i_{e_i}$', fontsize=16)" ] }, { "cell_type": "markdown", "id": "03be6728-fcd4-4587-b1ff-7fd7a2f86dea", "metadata": {}, "source": [ "### General shapes\n", "\n", "[Drawing.shape](quimb.schematic.Drawing.shape) draws a general filled shape\n", "given a sequence of 2D or 3D coordinates." ] }, { "cell_type": "code", "execution_count": 7, "id": "798ab62f-8365-4a12-89e9-a7d766ba0ace", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "rng = np.random.default_rng(1)\n", "pts = rng.normal(size=(8, 3, 3))\n", "\n", "for coos in pts:\n", " d.shape(\n", " coos,\n", " alpha=0.8,\n", " hatch=\"XXX\",\n", " edgecolor=schematic.hash_to_color(str(coos)),\n", " )" ] }, { "cell_type": "markdown", "id": "ba219abd-b53b-416d-b87f-aca9ba217c38", "metadata": {}, "source": [ "### Markers\n", "\n", "[Drawing.marker](quimb.schematic.Drawing.marker) is a convenience method for\n", "specifying the shape of a patch using a single string or integer, to yield\n", "a regular polygon." ] }, { "cell_type": "code", "execution_count": 8, "id": "bbd07d21-a3b1-40c5-b5c1-978abdd626d8", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "for p in range(3, 10):\n", " d.marker((p, 0), marker=p)\n", " d.text((p, 0.5), f\"{p}-gon\")" ] }, { "cell_type": "markdown", "id": "6e245c56-b078-4fae-9005-ad9cdbd41428", "metadata": {}, "source": [ "It is a wrapper around [Drawing.regular_polygon](quimb.schematic.Drawing.regular_polygon) with which you can also change the rotation with the `orientation` argument." ] }, { "cell_type": "markdown", "id": "49d1cc78-7143-4a15-9af6-41e86d623201", "metadata": {}, "source": [ "## Lines and curves\n", "\n", "### Lines\n", "\n", "The basic method for drawing lines between a pair of 2D or 3d points is\n", "[Drawing.line](quimb.schematic.Drawing.line)." ] }, { "cell_type": "code", "execution_count": 9, "id": "3ce43edd-aefb-4fc9-b684-083bd1606e80", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "d.line((0, 0, 0), (0, 0, 1))\n", "d.line((0, 1, 0), (0, 1, 1), arrowhead=True)\n", "d.line((1, 0, 0), (1, 0, 1), linewidth=4)\n", "d.line((1, 1, 0), (1, 1, 1), linestyle=':')" ] }, { "cell_type": "markdown", "id": "c1651f7e-3798-49ce-b07b-9c680741fd3b", "metadata": {}, "source": [ "When drawing lattice bonds it can be used fule to shorten the lines somewhat for visual effect.\n", "\n", "1. The `stretch` kwarg applies an overall relative stretch to the whole line.\n", "2. The `shorten` kwarg makes the line stop an absolute amount shorter, a tuple can be used to control start and end separately.\n", "\n", "By setting `shorten` to the `radius` of circles drawn, the lines connect exactly to the circle edge:" ] }, { "cell_type": "code", "execution_count": 10, "id": "40d3c112-c37a-45ba-953c-a26d0b8edf86", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "r = 0.15\n", "\n", "edges = [\n", " ((i, j), (i, j + 1)) for i in range(5) for j in range(3)\n", "] + [\n", " ((i, j), (i + 1, j)) for i in range(4) for j in range(4)\n", "]\n", "sites = {site for edge in edges for site in edge}\n", "\n", "for site in sites:\n", " d.circle((0, *site), radius=2.0 * r, color=schematic.get_color(\"green\"), linewidth=3)\n", " d.circle((3, *site), radius=0.7 * r, color=schematic.get_color(\"pink\"), linewidth=2)\n", "for sitea, siteb in edges:\n", " d.line((0, *sitea), (0, *siteb,), shorten=2.0 * r, linewidth=3)\n", " d.line((3, *sitea), (3, *siteb,), shorten=0.7 * r, linewidth=1)" ] }, { "cell_type": "markdown", "id": "22b6a127-1635-4eff-b5c7-d2f1a93ca6de", "metadata": {}, "source": [ "### Arrows and labels\n", "\n", "You can easily add text and arrows along lines:" ] }, { "cell_type": "code", "execution_count": 11, "id": "a0e0f65e-d0f8-4c54-98d5-069aaecab394", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "pa, pb, pc = (0, 0), (1, 1), (2, 0.5)\n", "\n", "d.line(pa, pb, text=\"hello\\n\")\n", "d.line(pb, pc, text=dict(text=\"world\\n\", color='red'), arrowhead=dict(center=1))\n", "\n", "# calling `line` with `text=` is a shortcut for `text_between`\n", "d.text_between(pa, pc, \"Could this be a shortcut?\", color=\"green\")" ] }, { "cell_type": "markdown", "id": "7473baf2-f781-4757-b056-dbc5493e4f24", "metadata": {}, "source": [ "### Curves\n", "\n", "If you want a line to pass through multiple points, you can use\n", "[Drawing.curve](quimb.schematic.Drawing.curve) to draw a smooth curve." ] }, { "cell_type": "code", "execution_count": 12, "id": "f15004d2-4bc5-46d3-911f-09babf81b58f", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "d.curve(\n", " [(0, 0), (1, 1), (2.5, 0.5), (3.5, 1.5)],\n", " linestyle='-.', linewidth=5,\n", ")\n", "\n", "# you can draw just the arrowhead separatel\n", "d.arrowhead((1, 1), (2.5, 0.5), linewidth=5, width=0.15)" ] }, { "cell_type": "markdown", "id": "e58f6f42-9581-4235-aed9-43b8b31c1917", "metadata": {}, "source": [ "Curves pass *exactly* through all points given, with the `smoothing` kwarg controlling... how smoothly they do this." ] }, { "cell_type": "code", "execution_count": 13, "id": "b3bec64b-a8ae-47f9-bce9-6091ca36bd9c", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import matplotlib as mpl\n", "\n", "d = schematic.Drawing()\n", "\n", "rng = np.random.default_rng(1)\n", "pts = rng.normal(size=(20, 3))\n", "cm = mpl.colormaps.get_cmap('RdPu')\n", "\n", "for pt in pts:\n", " d.dot(pt, color='black', radius=0.05)\n", "\n", "for smoothing in np.linspace(0.0, 2.0, 11):\n", " d.curve(pts, smoothing=smoothing, color=cm(smoothing / 2))\n", "\n", "d.label_ax(1.0, 0.60, \"smoothing=0.0\", color=cm(0.0))\n", "d.label_ax(1.0, 0.65, \"smoothing=1.0\", color=cm(0.5))\n", "d.label_ax(1.0, 0.70, \"smoothing=2.0\", color=cm(1.0))" ] }, { "cell_type": "markdown", "id": "6144e149-ae13-4a7a-b504-455b5f43d207", "metadata": {}, "source": [ "[Drawing.curve](quimb.schematic.Drawing.curve) also takes the `shorten` kwarg which shortens the final segments by the specified absolute amount:" ] }, { "cell_type": "code", "execution_count": 19, "id": "3eec3724-a36f-4a3c-b4e2-4209288c6783", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "r1 = 0.2\n", "r2 = 0.3\n", "\n", "d.circle((0, 1), radius=r1, linewidth=3)\n", "d.curve([(0, 1), (0, 0), (1, 1), (1, 0)], shorten=(r1, r2), linewidth=3)\n", "# also add an arrow on the middle segment\n", "d.arrowhead((0, 0), (1, 1), linewidth=3)\n", "d.circle((1, 0), radius=r2, linewidth=3)" ] }, { "cell_type": "markdown", "id": "7c6e999b-baa8-4244-aa65-7809887bfad4", "metadata": {}, "source": [ "### Multi-edges\n", "\n", "If you want to programmatically draw multiple lines from one place to the other ('multi-edges') you can use `line_offset`:" ] }, { "cell_type": "code", "execution_count": 13, "id": "61ca4569-9207-42ea-987b-5b837e6fe025", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "pa, pb = (0, 0, 0), (0, 1, 1)\n", "\n", "green = schematic.get_color(\"green\")\n", "red = schematic.get_color(\"red\")\n", "blue = schematic.get_color(\"blue\")\n", "\n", "d.circle(pa, color=green)\n", "d.circle(pb, color=red)\n", "\n", "# you can still use arrowheads and text labels\n", "d.line_offset(pa, pb, 0.2, arrowhead=dict(center=0.9), text='forwards\\n', color=blue)\n", "d.line_offset(pa, pb, 0.0, arrowhead=dict(center=0.9, reverse=True), text='backwards\\n', color=blue)\n", "d.line_offset(pa, pb, -0.2, arrowhead=dict(center=0.9, reverse=\"both\"), text='both ways!\\n', color=blue, midlength=0.4)" ] }, { "cell_type": "markdown", "id": "33e480be-92d0-4cb8-964c-b362544eab26", "metadata": {}, "source": [ "## Highlighting areas and groups of objects\n", "\n", "### Patches around general areas\n", "\n", "In technical drawings it is often useful to highlight areas. The\n", "[Drawing.patch](quimb.schematic.Drawing.patch) method does this by filling in\n", "a curve, given by a sequence of 2D or 3D coordinates." ] }, { "cell_type": "code", "execution_count": 14, "id": "8a50481f-104c-449c-a9dc-794d69d7fc4e", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing(figsize=(4, 4))\n", "\n", "d.marker((0, 0), marker='s', color=schematic.get_color('yellow'))\n", "d.marker((0, 1), marker='s', color=schematic.get_color('bluedark'))\n", "d.patch([\n", " (-.3, -.3),\n", " (+.3, -.3),\n", " (+.3, +1.3),\n", " (-.3, +1.3),\n", "], smoothing=0.3)" ] }, { "cell_type": "markdown", "id": "7a2cc6f7-56e3-46f5-bec2-e56faf82e708", "metadata": {}, "source": [ "### Patches around two circles\n", "\n", "If you want to specifically highlight two circles, you can use\n", "[Drawing.patch_around_circles](quimb.schematic.Drawing.patch_around_circles),\n", "and simply specify the two circles by their center coordinates and radii." ] }, { "cell_type": "code", "execution_count": 15, "id": "5aea70e8-1439-4497-8598-fef721849f11", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing(figsize=(4, 4))\n", "\n", "d.circle((0, 0), radius=3, color=schematic.get_color('pink'))\n", "d.circle((10, 1), radius=2, color=schematic.get_color('blue'))\n", "\n", "d.patch_around_circles(\n", " (0, 0), 3,\n", " (10, 1), 2,\n", " padding=0.5,\n", ")" ] }, { "cell_type": "markdown", "id": "29a7f01e-b567-4787-8ef5-91ce04f2699d", "metadata": {}, "source": [ "### Patches around arbitrary collections of objects\n", "\n", "If you want to highlight an arbitrary collection of objects, you can call\n", "[Drawing.patch_around](quimb.schematic.Drawing.patch_around), this computes\n", "the convex hull of the objects and draws a patch around it." ] }, { "cell_type": "code", "execution_count": 16, "id": "17869202-003e-47d5-bd67-4c8ed94dcebb", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "for pt in pts[:7]:\n", " d.dot(pt, color='orange', radius=0.05)\n", "for pt in pts[7:]:\n", " d.dot(pt, color='black', radius=0.05)\n", "\n", "d.patch_around(pts[:7], edgecolor='orange')" ] }, { "cell_type": "markdown", "id": "22c4cf81-f527-4899-89a4-f0aa888c9b9e", "metadata": {}, "source": [ "You can control how much padding is added around the perimeter of the objects\n", "using the `radius` kwarg." ] }, { "cell_type": "code", "execution_count": 17, "id": "17441c35-9218-4ea1-abe6-181d70ccfd48", "metadata": { "tags": [] }, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "d = schematic.Drawing()\n", "\n", "for k, pt in enumerate(pts):\n", " d.dot(pt, color=schematic.hash_to_color(str(k)), radius=0.05)\n", "\n", "for k in range(1, len(pts)):\n", " d.patch_around(\n", " pts[:k],\n", " radius=0.05 * k,\n", " facecolor=schematic.hash_to_color(str(k - 1)),\n", " linestyle=\"-\",\n", " zorder=-k,\n", " alpha=0.5,\n", " )" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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" } }, "nbformat": 4, "nbformat_minor": 4 }