{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Ribbon box\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\n\nfrom matplotlib import cbook\nfrom matplotlib import colors as mcolors\nfrom matplotlib.image import AxesImage\nfrom matplotlib.transforms import Bbox, BboxTransformTo, TransformedBbox\n\n\nclass RibbonBox:\n\n original_image = plt.imread(\n cbook.get_sample_data(\"Minduka_Present_Blue_Pack.png\"))\n cut_location = 70\n b_and_h = original_image[:, :, 2:3]\n color = original_image[:, :, 2:3] - original_image[:, :, 0:1]\n alpha = original_image[:, :, 3:4]\n nx = original_image.shape[1]\n\n def __init__(self, color):\n rgb = mcolors.to_rgb(color)\n self.im = np.dstack(\n [self.b_and_h - self.color * (1 - np.array(rgb)), self.alpha])\n\n def get_stretched_image(self, stretch_factor):\n stretch_factor = max(stretch_factor, 1)\n ny, nx, nch = self.im.shape\n ny2 = int(ny*stretch_factor)\n return np.vstack(\n [self.im[:self.cut_location],\n np.broadcast_to(\n self.im[self.cut_location], (ny2 - ny, nx, nch)),\n self.im[self.cut_location:]])\n\n\nclass RibbonBoxImage(AxesImage):\n zorder = 1\n\n def __init__(self, ax, bbox, color, *, extent=(0, 1, 0, 1), **kwargs):\n super().__init__(ax, extent=extent, **kwargs)\n self._bbox = bbox\n self._ribbonbox = RibbonBox(color)\n self.set_transform(BboxTransformTo(bbox))\n\n def draw(self, renderer):\n stretch_factor = self._bbox.height / self._bbox.width\n\n ny = int(stretch_factor*self._ribbonbox.nx)\n if self.get_array() is None or self.get_array().shape[0] != ny:\n arr = self._ribbonbox.get_stretched_image(stretch_factor)\n self.set_array(arr)\n\n super().draw(renderer)\n\n\ndef main():\n fig, ax = plt.subplots()\n\n years = np.arange(2004, 2009)\n heights = [7900, 8100, 7900, 6900, 2800]\n box_colors = [\n (0.8, 0.2, 0.2),\n (0.2, 0.8, 0.2),\n (0.2, 0.2, 0.8),\n (0.7, 0.5, 0.8),\n (0.3, 0.8, 0.7),\n ]\n\n for year, h, bc in zip(years, heights, box_colors):\n bbox0 = Bbox.from_extents(year - 0.4, 0., year + 0.4, h)\n bbox = TransformedBbox(bbox0, ax.transData)\n ax.add_artist(RibbonBoxImage(ax, bbox, bc, interpolation=\"bicubic\"))\n ax.annotate(str(h), (year, h), va=\"bottom\", ha=\"center\")\n\n ax.set_xlim(years[0] - 0.5, years[-1] + 0.5)\n ax.set_ylim(0, 10000)\n\n background_gradient = np.zeros((2, 2, 4))\n background_gradient[:, :, :3] = [1, 1, 0]\n background_gradient[:, :, 3] = [[0.1, 0.3], [0.3, 0.5]] # alpha channel\n ax.imshow(background_gradient, interpolation=\"bicubic\", zorder=0.1,\n extent=(0, 1, 0, 1), transform=ax.transAxes)\n\n plt.show()\n\n\nmain()" ] } ], "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.13.2" } }, "nbformat": 4, "nbformat_minor": 0 }